-
Notifications
You must be signed in to change notification settings - Fork 1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Better aliases for modifiers #2
Comments
Personally, I think the ideal aliases for me would be to just use the unicode modifier/key symbols directly, ⌘, ⌥, ⌃, ⇧, ⎋, ⇥ and so on. I also personally use ☆ for Hyper. I use the actual symbols all the time in a bunch of different contexts and I have Typinator snippets that make them very quick to insert. This was requested and discussed in an issue for GokuRakuJoudo and implemented in a fork by eugenesvk. I also like how left and right options were implemented just using the I definitely prefer your implementation of a config using YAML over EDN, I'd likely switch over if you added this type of symbol aliases or I might fork it and work on that myself when I have a little more free time. |
Thanks for the link to that PR! I really like that system of modifiers, I should have done more research before I implemented the current one. I lazily defaulted to using vim-like syntax because it was familiar.
/base/:
<⌘⇧-e>: shnotify(==HELLO==) This translates to "from": { "key_code": "e", "modifiers": { "mandatory": [ "command", "shift" ] } },
"to": [ { "shell_command": "osascript -e 'display notification \"==HELLO==\"'" } ], I used the 'side-neutral' modifiers rather than 'left_' or 'right_'. I already pushed this but I don't expect this to meet the standards for your request. I'd like to consider doing an overhaul of the modifier-syntax if you're willing to answer a few questions to guide me. I'm typing this up real quick before I have to leave the house but I'll do more research in the goku repo and the fork you linked later. Thanks again for the comment! |
Yeah, absolutely, however I can help! |
I was going to write a whole discourse on my thought process, but no one should be asked to read that. So, here's some off the cuff ideas. I'm pretty sure I could implement this in one day (other than updating guides and README and updating tests) and have all these as valid options. I might work on this in a dev branch just to see if I can get some foresight for some issues that might come up in a bigger overhaul. /base/:
<cosm-s>: string(git status) # Current syntax
cosm-s: string(git status)
cOSm-s: string(git status ) # Still got the case-sensitivity to indicate sides
rahg-s: string(git status ) # and the bad side-neutral aliases
⌃⌥⇧⌘-s: string(git status)
‹⌃⌥›⇧⌘›-s: string(git status)
⌃ ⌥ ⇧ ⌘ | s: string(git status) # This would help some of the visual clutter
# We would lose the pipe alias '|' but we can add 'pipe'
‹⌃ ⌥› ⇧ ⌘› | s: string(git status)
‹⌃ ⌥› ⇧ ⌘› | s + t + a: string(git status) # For simultaneous 'from' events I need to do a little more work to figure out how to get aliases for a multi-modifier like hyper as a modifier (I should list this in the list of limitations/bugs, but the current alias Also, I eventually want to have some defaults (the four unicode symbols + some predefined 'alphabet soup' to quote @eugenesvk) and then let the user add a dictionary in their YAML config to set their own aliases, unicode or otherwise. Not just for modifiers but for any key. Something like this, anywhere in the .yaml file: aliases:
⨁: left_control + right_option
☀︎: brightness_up
# etc. But I'm not attached to any of this, I'm mainly just thinking out loud and trying to create a roadmap. Would you mind sharing if you have a certain syntax in mind and any criticism you have of the above examples? This is just a playground plan |
This commit lets the user choose between a left, right, or side-ambivalent modifier using the following unicode syntax: ⌘ - command ‹⌘ - left_command ⌘› - right_command etc. for other mods, ⌘, ⌥, ⌃, ⇧. Also added is an alias that's valid for hyper, ☆. e.g. ☆ | 8 would map to 'command+option+control+shift + 8' This syntax was discussed in this issue in the GokuRakuJoudo repo: yqrashawn/GokuRakuJoudo#205 so credit to the participants of that issue. Addresses #2
This commit lets the user choose between a left, right, or side-ambivalent modifier using the following unicode syntax: ⌘ - command ‹⌘ - left_command ⌘› - right_command etc. for other mods, ⌘, ⌥, ⌃, ⇧. Also added is an alias that's valid for hyper, ☆. e.g. ☆ | 8 would map to 'command+option+control+shift + 8' This syntax was discussed in this issue in the GokuRakuJoudo repo: yqrashawn/GokuRakuJoudo#205 so credit to the participants of that issue. Addresses #2
As of 1c359f7, the syntax I mentioned above should work, but there's a good chance I missed something. Also, ☆ works as a hyper alias - you can use it as a modifier or map other keys to it. The syntax that I don't love is requiring Didn't lose the pipe alias for I'm open to radical changes and innovations and reverting this commit if we settle on something cleaner. TODO: update README, guides, and sample configs, and add some more tests. Priority: add functions to catch user error. e.g. right now, adding an invalid char that's not in the UNICODE_MODS dict in the 'from' part of the mapping raises a KeyError. Sleep first! |
As of 28f26af, user-defined aliases are available, but not for modifiers. So, you can define an alias to remap a key to a modifier combo, e.g. aliases:
⨁:
- right_option
- [left_control]
super_tab:
- tab
- [left_option, left_control, left_shift]
force_push: shell(git push --force origin master) But you can only use the alias in the primary-key 'field', not the modifier field. /base/:
insert: ⨁ # This is valid
⨁ | g: string(git init) + CR # This is not (for now) With the example above, you could have a mapping like: /base/:
⨁ + g: string(git init) + CR But that's strictly a simultaneous from event, so you'd be forced to execute it within the simultaneous threshold. With the latest commit, if an
I'm not sure about multi-char modifiers aliases, e.g. if you wanted |
Okay, sorry for the slow replies, it's been a bit of nightmare week for me. I really like being able to implement custom aliases but the syntax for multiple modifiers isn't ideal. aliases:
★:
- fn
- [right_control, right_option, right_shift, right_command] I wish I could just do In general, I would love to be able to define a list of items and have it infer the final item as the field string if a field string isn't explicitly set ( That said, the pipe syntax is excellent. I'm finding it really clean to use and it makes it pretty obvious what a line does. It's significantly easier to read than using angle brackets. It might be nice if modifier aliases could be used to the left of a pipe but I don't think it's a big deal.
That's a tough call. If you could get it working it might be useful, not essential. It is still a bit confusing knowing where you can use aliases and where you can't. It took me a couple of tries before I got this bit working: # Brackets
⇧› | left_shift: ["(", left_shift]
‹⇧ | right_shift: [")", right_shift]
⇧› ⌘ | left_shift: ["[", ⌘-left_shift]
‹⇧ ⌘ | right_shift: ["]", ⌘-right_shift]
⇧› ⌥ | left_shift: ["{", ⌥-left_shift]
‹⇧ ⌥ | right_shift: ["}", ⌥-right_shift]
⇧› ⌃ | left_shift: ["<", ⌃-left_shift]
‹⇧ ⌃ | right_shift: [">", ⌃-right_shift] Great work on the documentation, it's excellent! I am so excited about Karaml, I found Goku to be a bit tedious to work with, though dramatically better than JSON, and I was experimenting with skhd as a possible replacement to Karabiner because it's configs were easier to write. It unfortunately didn't support layering however, just key chords so I switched back. If I'd found Karaml sooner I wouldn't have even looked for alternatives. |
Thanks for the detailed reply. As a precursory note, I know I'm probably conflating terminology and being inconsistent, so feel free to point that out if I'm being confusing in my comments. I'll try to be more thoughtful.
I like that idea, and it would be easy to implement since it's easy to distinguish between the string and the nested list.
If I'm understanding correctly, would you want a syntax where we just get rid of an explicit delimiter between modifiers and and just use the final whitespace as the delimiter? Also a great idea, and I don't think it would be an issue so long as
I can work on that, shouldn't take too long, just need a few days to catch up on other things.
That was sort of an oversight on my part. I could have made the Unicode aliases available for the 'primary' key code (this is one of those terms in my own mental model so lmk if it's wrong) by just inserting them in the ALIAS dict (the dict of Alias tuples for 'primary' keys, separate from the MODIFIERS and UNICODE_MODS dicts of strings). This modifier keys qua modifier vs. modifier keys qua primary key distinction is why I unconsciously didn't add aliases for the modifiers in these recent updates, because I wanted to make explicit when a modifier key code needed to be primary. That may be what was unclear about where and when you could use those modifier aliases. Sorry about that. Also, when modifier key codes are 'primary', they need to have a So, I'll update the ALIAS dict and push it. After this commit, you should be able to have this in your config: # Brackets
⇧› | ‹⇧: ["(", ⇧›]
⇧› ⌥ | ‹⇧: ["{", ⌥ | ‹⇧] # The pipe-as-delimiter works in the rhs as well if you prefer it over the dash
# Or, equivalent:
# Here, the non-explicit ⇧ defaults to the left side when it's an alias for a 'primary' key code
⇧› ⌥ | ⇧: ["{", ⌥ | ⇧] And btw, since the Is this what you were expecting when you were trying to use the aliases in different places? Let me know if I interpreted 'final whitespace as delimiter' correctly and I'll work on it. Sorry the code is such a mess. |
I believe so, basically I want it to behave just like the previous suggestions for # Like this
⌥ ⌘› o: Do a simple stand-alone action
# While keeping
⌥ ⌘ | 1: Do
⌃ | 1: some
⇧ ⌃ | 1: complex or related
⇧ | 1: things The more I think about this the less necessary I think it is but it's still an idea that might be worth considering.
Sound reasoning, might be better to spell it out explicitly.
Love it, thanks!
I like this idea a lot! So I did find someplace where the aliases shouldn't expanded and should be treated simply as the unicode character: # # Modifiers Layer
#
# Because text expansion is just too slow.
#
/modifiers/:
c: string(⌃) # Outputs nothing
o: string(\⌥) # Outputs `\`
s: string('⇧') # Outputs `''`
n: string(⌘) # Outputs nothing
h: string(☆) # Outputs nothing
l: string(‹) # Throws a fatal error
r: string(\›) # Throws a fatal error. As does `string('›')` I really can't express how fantastic Karaml is! Keep up the great work! |
Thanks for the kind words! I appreciate your help in making this a cleaner interface.
Nice bug find. This is a mix of issues. Primarily, the string() 'pseudo-function' (another one of my imprecise terms) works by reading the string's arg character by character and adding the corresponding key code to a list of 'to' events. There are no Unicode key_codes, so generally those are the ones throwing those errors. Those aliases that we have added already (⌘ ⌃ etc.) in your examples above are being read as valid key codes, but they're being added to the list of 'to' events as the key they're the alias of. So, It would make sense to ignore Unicode aliases in the pqrs-org/KE-complex_modifications#697 This issue might provide some insight. I'll do more research. Thanks for finding that bug. I'm going to push this to the top of the todo-list so you can add that /modifiers/ layer asap. |
Try this one I'm using to insert various symbols with karabiner/goku, the only downside of Applescript is that it's not immediate unlike the more complicated solutions that require editing your layout with Ukelele (or adding some Hex code layout that you'll never use anywhere else) and using a simple key combo, so would be nice to have a less hacky instant solution that is just as convenient as |
Thanks for the suggestion! Yes, AppleScript does seem to be kinda sluggish. I used to use it for some minor mouse movements and it felt like an eternity. I like the idea of using a shell script instead of appending a series of events to the 'to' list, mostly because then you wouldn't end up with a monstrous JSON file full of giant 'to' lists (even though we're trying to abstract from it here). I'll mess around with that. |
I wouldn't push this as the top priority on my account, I can pretty easily send a osascript command to a Typinator expander, Keyboard Maestro macro or possibly an Alfred expander or snippet if Alfred exposes those commands in its AppleScript dictionary to achieve this functionality.
Which is pretty how Goku does it. |
I made an attempt at solving the symbols issue with the Otherwise, if all characters in the string can be handled by Karabiner, then string() works the way it has been, by adding a series of One issue with the delay of the AppleScript. Say you have a karaml map like this: /base/:
⌥ | m: string(⌘ ⌃ ⌥ ⇧) + ESC + return + string(hello!)
⌥ | n: string(g r a h) + ESC + return + string(hello!) The first string in the first map is now a shell command. The subsequent events aren't going to wait for the shell command to execute, they'll just go when the shell command leaves the stack (? or however tekezo does it). See #3 for more on this, but this behavior is more or less intentional. In the second map, everything executes fast enough that it's not an issue. Anyway. I'm having some weird issue with my shell, but this feature was working for me for a minute. It stopped working while I was spam testing some of those commands. @ChristinWhite If you want to check it out /modifiers/:
c: string(⌃)
o: string(⌥)
s: string('⇧')
n: string(⌘)
h: string(☆)
l: string(‹)
# r: string(\›) # non-working case that I'm too lazy to fix rn
# (a backslash followed by a unicode escape sequence)
w: string(hello ⇧⌘☆ \n\tworld ☆⌃) # yaml escape characters (new line, tab etc.) also work
a: string(👍) # and emojis! |
Regarding the issues with consistency I mentioned above, after those commands stop working (for whatever reason I haven't figured out yet),the Karbiner-Elements GUI log shows this error when I try to execute it again:
After restarting the console with this command though, they work again, and I can't reproduce my earlier issue
|
I merged 13f9a60 for the new string() feature to print any character. Also, as of 2798bb1, the 'final whitespace as delimiter' syntax is supported, per #2 (comment) Any amount of whitespace is valid, except that the first character has to be properly indented per YAML syntax. ⌥ ⌘› o: string(I can print ⌘⌥⇧⌃ now!) # either opt + right command + o prints that string
⌘› o: string(bye) # this isn't valid
' ⌘› o': string(bye) # but this is (per standard YAML) if you're shooting for alignment of symbols Also, with all the progress made, I want to make it a goal to change all the examples in the docs to use the pipe syntax, and maybe even the symbol aliases for the modifiers. But first I want to try to learn more about what caused those console crashes (? or whatever they were) earlier. I think the only major feature that was mentioned that's left to address (EDIT: I'm happy to address new ones!) is multi-char aliases in the modifier 'field', e.g. lcmd rcmd | o: app(Obsidian)
kitty_mod | g: # some fancy command that needs the kitty modifier (e.g. ctrl + shift) |
Whoops,also gotta fix up the |
All of the strings are now working perfectly! |
@ChristinWhite good news / breaking changes 4094671 (plus a fix in 2de7cff, whoops) I updated the syntax for the Also, if an alias is composed entirely of modifiers, it will also be added to the (now renamed) So, as of this commit, this is possible: aliases:
⁙: o c | s # With a delimiter, this aliases to `left opt` + `left ctrl + `s`
⁙: o c s # With no (explicit) delim, this aliases to `left opt` + `left ctrl` + `left shift`
⁙: ⌥ ⌃ ⇧ # When it's all modifier symbols, syntax doesn't matter.
# Both of the two above will be added to both the general ALIASES and MODIFIER_ALIASES dict
⏎: return_or_enter
screen_saver: shell(open -b com.apple.ScreenSaver.Engine) # Start Screen Saver
/base/:
tab: [tab, ⁙] # tab to left opt, ctrl, and shift when held
j+k: ⁙ | e # simul j+k to left opt, ctrl, shift, and e
⁙ | ⏎: screen_saver # left opt, ctrl, shift, and enter starts screen saver
⁙ e: ⁙ | ⏎ # etc. Hopefully I didn't miss any bugs (EDIT: lol @ my audacity. See ca6eff5 and 5013c6e for fixes in the user defined aliases map) |
This is fantastic! |
Since this is somewhat alias related, I'll mention here that I added a user-defined templates feature a while back that imitates Goku's (but Goku's is more flexible b/c I think it's actual Clojure and not just regex parsing) https://github.com/al-ce/karaml#user-defined-shell-command-templates |
g
forcommand
(gui) anda
foroption
(alt) are ok, buth
forshift
andr
forcontrol
look bad in the configuration.l
forcaps_lock
isn't great either. I don't likem
/m
forleft/right_command
mainly because in VimM
is used forMeta
as a modifier, and on Mac that's equivalent to the option keys.The lower/upper-case system for left/right modifiers seemed like a good solution for keeping modifiers down to a single letter but it can be hard to distinguish them, especially
o
andO
, and I've found myself wondering why some mapping wasn't triggering because I didn't notice this.Needs improvement.
The text was updated successfully, but these errors were encountered: