Reputation: 243
I get a new Windows 10 Notebook, while I ran a MBP for long time. On MacOs I use an US Intl kezmap and I really like the shortcuts to write the german umlauts.
On MacOS I use {RAlt} + {u} followed by {a},{o},{u} or {s} to write the corresponding german Umlaut. To write a upper case umlaut I have to press {Shift} + {a},{o} or {u}.
I try to write an AHK script to reproduce this behavior, but unfortunately I have no success.
What I currently have created is this.
;Umlaut
#Persistent
RAlt & a::
GetKeyState, state, Shift
if state = U
SendInput {ASC 0228} ;RAlt+a = lower case a-umlaut
else Send, {ASC 0196} ;RAlt+Shift+a = UPPER CASE A-umlaut
return
RAlt & o::
GetKeyState, state, Shift
if state = U
SendInput {ASC 0246} ;RAlt+o = lower case o-umlaut
else Send, {ASC 0214} ;RAlt+Shift+o = UPPER CASE O-umlaut
return
RAlt & u::
GetKeyState, state, Shift
if state = U
SendInput {ASC 0252} ;RAlt+u = lower case u-umlaut
else Send, {ASC 0220} ;RAlt+Shift+u = UPPER CASE U-umlaut
return
RAlt & s:: Send, {ASC 0223} ;RAlt+s = RAlt+s, Eszett
return
It works, but I really want the key combos described above. How can I reach this goal?
Upvotes: 1
Views: 331
Reputation: 1521
I'd rather suggest slightly different input approach: type in the letter and then use a script that substitutes the last character to the left of cursor.
I have done so when I worked a lot with german texts and turned out to be more effective compared to the method you describe. Also can replace the characters that are already in the text just by placing cursor by them and pressing same hotkey.
Here it is
dict := ComObjCreate("Scripting.Dictionary")
dict.Add("a", "ä")
dict.Add("A", "Ä")
dict.Add("o", "ö")
dict.Add("O", "Ö")
dict.Add("u", "ü")
dict.Add("U", "Ü")
>!u::
temp := clipboard ; backup clipboard
send +{left}
send ^{insert}
sleep 100
c := clipboard
found := false
for key in dict {
if (key==c) {
v := dict.item[key]
found := true
send %v%
}
}
if (found=false) {
send {right}
; tooltip key not found
}
clipboard = %temp%
return
Upvotes: 0
Reputation: 6489
First to fix the code seen in the original post, it's quite legacy and uses a lot of weird approaches. To list and fix all of them:
#Persistent
is doing nothing for us. It's useless here.
The RAlt & key::
type hotkeys labels should use modifiers, and look like this >!key::
.
The >!
modifier means right alt.
Usage of the legacy GetKeyState
command should be replaced by the GetKeyState()
function.
Though, this isn't actually needed at all. The shift hotkey modifier +
should just be used like so:
>!a::SendInput, ä
>!+a::SendInput, Ä
>!o::SendInput, ö
>!+o::SendInput, Ö
>!u::SendInput, ü
>!+u::SendInput, Ü
>!s::SendInput, ß
I also ditched the using the ASC codes, since I see no reason to use them.
I guess it would make the script file more flexible to be saved under a more primitive encoding, but eh.
So this was the code in your post done right.
And now to implement what you were actually looking to do:
Pressing RAlt + u
enters a umlaut typing mode.
Easiest way of doing this, that I can think of, is just using creating context sensitive hotkeys with #If
.
Normally I wouldn't recommend the usage of #If
in AHK v1, due to its downsides (as documented in the documentation), but it'll be more than fine for a little script like this. And it makes this a lot easier and neater.
So first lets create a RAlt + u
hotkey, that sets the state of some variable to true
:
>!u::UmlautTypingMode := true
Then we can create context sensitive hotkeys by always first checking the value of that variable:
>!u::UmlautTypingMode := true
#If, UmlautTypingMode ;start context sensitive hotkeys (if the variable value evaluates to true)
a::
SendInput, ä
UmlautTypingMode := false
return
+a::
SendInput, Ä
UmlautTypingMode := false
return
o::
SendInput, ö
UmlautTypingMode := false
return
+o::
SendInput, Ö
UmlautTypingMode := false
return
<!u::return
u::
SendInput, ü
UmlautTypingMode := false
return
+u::
SendInput, Ü
UmlautTypingMode := false
return
s::
SendInput, ß
UmlautTypingMode := false
return
#If ;end context sensitive hotkeys
As you can see, we unfortunately had to get rid of those sweet clean one-liner hotkeys, since false
every time, and end code execution with a return
.
Of course this could be compacted with some more advanced AHK, but I'll keep it simple.
And the small little <!u::return
line inside the there is to make the initial RAlt + u
press not produce a ü
.
So that should be it. Works fine on my end at least.
Though, I've just now realized that with "{RAlt} + {u} followed by {a},{o},{u} or {s}" you may have meant that you'd keep typing umlauts for as long as RAlt is held down. If this was the case, the code needs some adjusting.
Right now you press and release RAlt + u
to enter the umlaut typing mode.
Finally, as a bonus, here's the the code compacted down to a one-liner.
I know, it's stupid, I just couldn't resist, I love making these haha.
>!u::UmlautTypingMode := true
#If, UmlautTypingMode
a::
+a::
o::
+o::
u::
+u::
s::SendInput, % ((A_ThisHotkey = "s"), UmlautTypingMode := false) ? "ß" : ("¨" ((A_ThisHotkey ~= "\+") ? Format("{:U}", SubStr(A_ThisHotkey, 0)) : SubStr(A_ThisHotkey, 0)))
>!u::return
#If
Also, no idea if this will work on different keyboard layouts.
Works for me at least.
EDIT:
A timeout requested was the comments. They're very easy and convenient to do with a timer.
So, we change our >!u::UmlautTypingMode := true
hotkey to this:
>!u::
UmlautTypingMode := true
SetTimer, Timeout, -2000
return
Negative number in the timer's period means it runs just once after 2000ms.
And now we of course have to also create the label (or function, I'll use a label here to keep it more simple) called Timeout
(it's not a built in thing, we could've used any name here).
Timeout:
UmlautTypingMode := false
return
This label can be placed for example at the bottom of the script.
Upvotes: 1