Help with objects and error message Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
berz
Posts: 18
Joined: 16 Apr 2021, 16:40

Help with objects and error message

16 Apr 2021, 17:10

Sorry for the generic title. I have the following hotkey:

Code: Select all

MacronKeys := {Space: ¯, a: ā} ; this is declared at the top of the script

; ...

; Alt Gr + Shift + -
<^>!+-:: 
Input, Char, L1
Send % (MacronKeys.HasKey(%Char%)? MacronKeys[%Char%] : ¯%Char%)
return

; ...
The intended semantics are: when the user presses alt gr + shift + -, record one input Char. If MacronKeys contains that char, output the corresponding letter (for Space, ¯, for a, ā). If it doesn't, simply send ¯ and append the input char to it.

What actually happens:
If I press the hotkey and then "a", nothing is sent.
If I press space, I get an error:

Code: Select all

The following variable name contains an illegal character: " "
and then the line of Send above.
If I press anything that isn't in MacronKeys, nothing is sent.

This is my first time making a complex script, so I'm probably messing up something basic (and I tried various combinations of % signs around variables and whatnot), but I couldn't figure out why even searching through the documentation. Help?
gregster
Posts: 8921
Joined: 30 Sep 2013, 06:48

Re: Help with objects and error message

16 Apr 2021, 17:20

Try

Code: Select all

MacronKeys := {" ": "¯", a: "ā"} ; this is declared at the top of the script

; Alt Gr + Shift + -
<^>!+-:: 
Input, Char, L1
Send % (MacronKeys.HasKey(Char)? MacronKeys[Char] : "¯" Char)
return
object values need to be quoted, if they are strings - literal object keys can be quoted (in the special case of a space character, it is probably necessary)
Generally, in expression mode (that you forced here by using % followed by space), you don't use %s around variables (exceptions exist, such as "double-derefs"). But literal strings require quotes...

You could also do this:

Code: Select all

MacronKeys := {(a_space) : "¯", a: "ā"}
https://www.autohotkey.com/docs/Objects.htm#Usage_Associative_Arrays wrote:Any expression can be used as a key, but to use a variable as a key, it must be enclosed in parentheses. For example, {(KeyVar): Value} and {GetKey(): Value} are both valid.
a_space is a built-in variable in AutoHotkey that contains a standard space character. Your code above would look for a literal string "Space" instead in Char (which can never happen in your hotkey subroutine which limits input to a single character).
berz
Posts: 18
Joined: 16 Apr 2021, 16:40

Re: Help with objects and error message

17 Apr 2021, 02:48

Ohh, everything makes sense now (and it works). Thank you so much.
berz
Posts: 18
Joined: 16 Apr 2021, 16:40

Re: Help with objects and error message

17 Apr 2021, 03:08

I've been trying to make the code more general, but it stopped working. I'm probably doing something stupid again.

Here's the new code:

Code: Select all

; By the way, must this declaration be in one line or can I put newlines in it to make it nicer?
DeadKeys := {"¯": {a: "ā"}}

DeadKey(sym)
{
    Input, Char, L1
    if (Char = " ")
        Send, %sym%
        return

    Send % (DeadKeys[sym].HasKey(Char)? DeadKeys[sym][Char] : sym Char)
}

; ...

<^>!+-::
DeadKey("¯")
return
What happens here is that if I press the hotkey and then space, it acts as expected and simply outputs ¯, but anything else causes no output at all.
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: Help with objects and error message

17 Apr 2021, 05:11

Code: Select all

 if (Char = " ")
        Send, %sym%
        return
missing braces. this isnt python
berz
Posts: 18
Joined: 16 Apr 2021, 16:40

Re: Help with objects and error message

17 Apr 2021, 05:47

swagfag wrote:
17 Apr 2021, 05:11

Code: Select all

 if (Char = " ")
        Send, %sym%
        return
missing braces. this isnt python
Oh. I was sure I saw some example without braces but evidently I was mistaken.

However, the code now looks like this:

Code: Select all

DeadKeys := {"¯": {a: "ā"}}

DeadKey(sym)
{
    Input, Char, L1
    if (Char = " ") {
        Send, %sym%
        return
    }

    Send % (DeadKeys[sym].HasKey(Char)? DeadKeys[sym][Char] : sym Char)
}

; ...

<^>!+-::
DeadKey("¯")
return
but if I input the hotkey and then a, the output is ¯a instead of ā, in other words it looks like HasKey is failing, even though the Char is present in the key of the inner object. I tried both with and without quoting the key "a".
swagfag
Posts: 6222
Joined: 11 Jan 2017, 17:59

Re: Help with objects and error message

17 Apr 2021, 06:59

functions have scope. DeadKeys in ur function is a reference to an undefined(blank) variable, not the object u had created earlier. check the ahk tutorials
User avatar
boiler
Posts: 16768
Joined: 21 Dec 2014, 02:44

Re: Help with objects and error message

17 Apr 2021, 09:05

Among the ways to address the scope issue, this probably makes the most sense for your function:

Code: Select all

DeadKey(sym)
{
	static DeadKeys := {"¯": {a: "ā"}}

    Input, Char, L1
    if (Char = " ") {
        Send, %sym%
        return
    }

    Send % (DeadKeys[sym].HasKey(Char)? DeadKeys[sym][Char] : sym Char)
}

; ...
<^>!+-::
DeadKey("¯")
return
berz
Posts: 18
Joined: 16 Apr 2021, 16:40

Re: Help with objects and error message

17 Apr 2021, 10:19

boiler wrote:
17 Apr 2021, 09:05
Among the ways to address the scope issue, this probably makes the most sense for your function:

Code: Select all

DeadKey(sym)
{
	static DeadKeys := {"¯": {a: "ā"}}

    Input, Char, L1
    if (Char = " ") {
        Send, %sym%
        return
    }

    Send % (DeadKeys[sym].HasKey(Char)? DeadKeys[sym][Char] : sym Char)
}

; ...
<^>!+-::
DeadKey("¯")
return
Oh I see, I thought declaring them at the top would make them global, my mistake.

Now for the (hopefully) last problem: I now have multiple options for output like so:

Code: Select all

DeadKey(sym)
{
    static DeadKeys := {"¯": {a: "ā", A: "Ā", e: "ē", E: "Ē", I: "Ī", i: "ī", O: "Ō", o: "ō", Æ: "Ǣ", æ: "ǣ", Y: "Ȳ", y: "ȳ", G: "Ḡ", g: "ḡ"}}

    Input, Char, L1
    if (Char = " ") {
        Send, %sym%
        return
    }

    Send % (DeadKeys[sym].HasKey(Char)? DeadKeys[sym][Char] : sym Char)
}
But whenever I input one of the letters, only the last-declared variant is considered. That means that for example, whether I input a or A, the result will always be Ā, and whether I input i or I, the result is always ī. Quoting the keys doesn't solve it. I reread the docs about objects and the notes on key names but couldn't find anything relating to case-sensitiveness. How can I solve this?
User avatar
boiler
Posts: 16768
Joined: 21 Dec 2014, 02:44

Re: Help with objects and error message  Topic is solved

17 Apr 2021, 10:30

Here's a workaround. The added "x" is only used internal to the function. The user just presses the hotkey and the capital letter as intended.

Code: Select all

DeadKey(sym)
{
    static DeadKeys := {"¯": {a: "ā", Ax: "Ā", e: "ē", Ex: "Ē", Ix: "Ī", i: "ī", Ox: "Ō", o: "ō", Æ: "Ǣ", æ: "ǣ", Yx: "Ȳ", y: "ȳ", Gx: "Ḡ", g: "ḡ"}}

    Input, Char, L1
    if (Char = " ") {
        Send, %sym%
        return
    }
	Char .= (RegExMatch(Char, "[A-Z]") && DeadKeys[sym].HasKey(Char "x")) ? "x" : ""
    Send % (DeadKeys[sym].HasKey(Char)? DeadKeys[sym][Char] : sym Char)
}
berz
Posts: 18
Joined: 16 Apr 2021, 16:40

Re: Help with objects and error message

17 Apr 2021, 11:40

boiler wrote:
17 Apr 2021, 10:30
Here's a workaround. The added "x" is only used internal to the function. The user just presses the hotkey and the capital letter as intended.

Code: Select all

DeadKey(sym)
{
    static DeadKeys := {"¯": {a: "ā", Ax: "Ā", e: "ē", Ex: "Ē", Ix: "Ī", i: "ī", Ox: "Ō", o: "ō", Æ: "Ǣ", æ: "ǣ", Yx: "Ȳ", y: "ȳ", Gx: "Ḡ", g: "ḡ"}}

    Input, Char, L1
    if (Char = " ") {
        Send, %sym%
        return
    }
	Char .= (RegExMatch(Char, "[A-Z]") && DeadKeys[sym].HasKey(Char "x")) ? "x" : ""
    Send % (DeadKeys[sym].HasKey(Char)? DeadKeys[sym][Char] : sym Char)
}
It's unfortunate that such a workaround is necessary, but thank you very much, that's rather clever.
Now everything works as expected, thank you everybody for helping. ^^
berz
Posts: 18
Joined: 16 Apr 2021, 16:40

Re: Help with objects and error message

17 Apr 2021, 16:22

Aaand once again, I spoke too soon.

The code so far works, but it was acting on regular keys. Now I need to also apply it to existing dead keys (I use the US international layout), and those are giving me trouble.
Here's the current code:

Code: Select all

DeadKey(sym)
{
    static MacronKeys := {a: "ā", Ax: "Ā", e: "ē", Ex: "Ē", Ix: "Ī", i: "ī", Ox: "Ō", o: "ō", Æ: "Ǣ", æ: "ǣ", Yx: "Ȳ", y: "ȳ", Gx: "Ḡ", g: "ḡ"}
    static CircumflexKeys := {a: "â", g: "ĝ"}
    static DeadKeys := {"¯": MacronKeys}

    Input, Char, L1
    if (Char = " ") {
        Send, %sym%
        return
    }

    Char .= (RegExMatch(Char, "[A-Z]") && DeadKeys[sym].HasKey(Char "x")) ? "x" : ""
    SendRaw % (DeadKeys[sym].HasKey(Char)? DeadKeys[sym][Char] : sym Char)
}

; ...

+6::
DeadKey("^")
return
Shift + 6 = ^ which on US Intl. is a deadkey already, but it doesn't support some characters that would make sense on it, like ĝ and others, so my intent is to expand existing deadkeys like it. I wouldn't mind reimplementing even those letters that are supported, if need be.

The problem:
- Hotkey + "a" results in a regular a. Note that this wouldn't happen even without the script, since the original deadkey supports "a" already.
- Hotkey + space results in nothing.
- Hotkey + a character that isn't supported by the original nor my dead key causes the character to be printed normally, but then one character is eaten by the script.
- Hotkey + "g", a character which is not supported by the original deadkey, results in the same as above.

Unfortunately the key history isn't helpful either, because it simply detects shift, then 6, then the key I press, with no difference between doing it with a deadkey or a regular symbol.

How can I solve this?
User avatar
boiler
Posts: 16768
Joined: 21 Dec 2014, 02:44

Re: Help with objects and error message

17 Apr 2021, 17:58

I don't know what you mean by saying it's already a deadkey. How could it work unless you changed the following line to add CircumflexKeys? It works as expected for me with this change, and I expect it would for you too. Perhaps something else isn't working the way you expected, but I would start by changing to the line below, then describe what is or isn't working from there.

Code: Select all

   static DeadKeys := {"¯": MacronKeys, "^": CircumflexKeys}
berz
Posts: 18
Joined: 16 Apr 2021, 16:40

Re: Help with objects and error message

18 Apr 2021, 03:27

boiler wrote:
17 Apr 2021, 17:58
I don't know what you mean by saying it's already a deadkey. How could it work unless you changed the following line to add CircumflexKeys? It works as expected for me with this change, and I expect it would for you too. Perhaps something else isn't working the way you expected, but I would start by changing to the line below, then describe what is or isn't working from there.

Code: Select all

   static DeadKeys := {"¯": MacronKeys, "^": CircumflexKeys}
It's already a deadkey because the US International layout already has some deadkeys even without any AHK script running. ^ is a deadkey that can produce â, ê, î, û, ô, but it can't produce ĝ and a few others, and what I want to do is extend it to add these missing combinations.

And yeah, that line you mention was an embarrassing oversight... It fixed most of the issues. ^^"

Remaining issue number 1: if I press ^ + space, a single ^ should appear but instead nothing happens.

Remaining issue number 2: after pressing the hotkey and then a character that is not included in my deadkeys, some keypresses get ignored. For example if I press ^ + e, I expect "ê" (because of the existing deadkey) or at least "^e" to appear, but what happens is only "e" appears. If I then press backspace immediately it works, but if I wait a short bit before pressing it, it doesn't do anything and I have to wait several seconds for my keys to start working again. It's a bit baffling and I hope it doesn't have to do with performance, since I think what I'm doing is not too complex overall.

The two issues are probably caused by the same thing, but I don't know what. I tried adding an EndKey parameter to Input with keys like Backspace, Space etc but it didn't help.
User avatar
boiler
Posts: 16768
Joined: 21 Dec 2014, 02:44

Re: Help with objects and error message

18 Apr 2021, 07:39

Issue number 1: That's because Send sees the ^ as a modifier key (Ctrl), so change it to:

Code: Select all

        Send, {Raw}%sym%

Issue number 2: Add a $ in front of your hotkey to keep it from triggering itself:

Code: Select all

$+6::
berz
Posts: 18
Joined: 16 Apr 2021, 16:40

Re: Help with objects and error message

18 Apr 2021, 10:40

boiler wrote:
18 Apr 2021, 07:39
Issue number 1: That's because Send sees the ^ as a modifier key (Ctrl), so change it to:

Code: Select all

        Send, {Raw}%sym%

Issue number 2: Add a $ in front of your hotkey to keep it from triggering itself:

Code: Select all

$+6::
Issue 2 is solved. For issue 1, I tried both your way and with SendRaw (which should be equivalent as far as I know), but if I want just a ^ to appear I have to press space twice instead of once, contrary to what happens for the other hotkey, ¯. Any clue?
berz
Posts: 18
Joined: 16 Apr 2021, 16:40

Re: Help with objects and error message

18 Apr 2021, 10:51

One more thing: the "original" deadkeys, when you press, for example ^ and then ^ again (or simply keep the keys pressed) output the symbol continuously (^ twice makes ^^, if you keep it pressed you get ^^^^^^^^^^...). My custom deadkeys don't currently do that, but I would like them to. In other words, the symbol for the deadkey itself should behave like any other letter or symbol for which there is no set combination. How can I implement that?
User avatar
boiler
Posts: 16768
Joined: 21 Dec 2014, 02:44

Re: Help with objects and error message

18 Apr 2021, 12:15

berz wrote: For issue 1, I tried both your way and with SendRaw (which should be equivalent as far as I know), but if I want just a ^ to appear I have to press space twice instead of once, contrary to what happens for the other hotkey, ¯. Any clue?
It works as you want it to on my standard US keyboard, so I am guessing the issue is that you are using the same key as a hotkey that Windows uses as a deadkey for the US Intl keyboard. That's why I think it doesn't happen with your other hotkey. Perhaps if you added something else to the hotkey, such as Ctrl or AltGr, then it wouldn't conflict and cause those types of issues.

berz wrote: One more thing: the "original" deadkeys, when you press, for example ^ and then ^ again (or simply keep the keys pressed) output the symbol continuously (^ twice makes ^^, if you keep it pressed you get ^^^^^^^^^^...). My custom deadkeys don't currently do that, but I would like them to. In other words, the symbol for the deadkey itself should behave like any other letter or symbol for which there is no set combination. How can I implement that?
The problem is that pressing ^ is your hotkey, so it's not being picked up by the Input command. I would think this could also be solved if you used a different hotkey than the one that actually produces the character.
berz
Posts: 18
Joined: 16 Apr 2021, 16:40

Re: Help with objects and error message

18 Apr 2021, 15:59

I think I'll have to reimplement my deadkeys (and any other difference) on top of a regular US layout without deadkeys...

Thank you for your help so far.
User avatar
boiler
Posts: 16768
Joined: 21 Dec 2014, 02:44

Re: Help with objects and error message

18 Apr 2021, 16:23

berz wrote: I think I'll have to reimplement my deadkeys (and any other difference) on top of a regular US layout without deadkeys...
I don’t think that alone is going to solve your problems because I have a regular US layout and am still subject to the same problem because you’re trying to have the same character captured by the Input command that you’re also using as a hotkey.

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: peter_ahk, ShatterCoder and 150 guests