diff options
author | Preston Pan <preston@nullring.xyz> | 2023-06-11 17:43:34 -0700 |
---|---|---|
committer | Preston Pan <preston@nullring.xyz> | 2023-06-11 17:43:34 -0700 |
commit | 846b48b0b179fcaa49c494d0da0e23db71b989dd (patch) | |
tree | ad76990055afed803a8de5ed08b89a73e8a32967 /config/kmonad.org |
first commit
Diffstat (limited to 'config/kmonad.org')
-rw-r--r-- | config/kmonad.org | 720 |
1 files changed, 720 insertions, 0 deletions
diff --git a/config/kmonad.org b/config/kmonad.org new file mode 100644 index 0000000..4f38a86 --- /dev/null +++ b/config/kmonad.org @@ -0,0 +1,720 @@ +#+title: KMonad Configuration +#+author: Preston Pan +#+description: My Literate KMonad Configuration +#+html_head: <link rel="stylesheet" type="text/css" href="../style.css" /> + +* Goals +** It should be the most efficient keyboard layout possible. +*** Ergonomic key positions and more frequent keys closer to home row. +*** Optimize the layers in such a way where we do not need to change layer frequently +however, layers are still needed because it is sometimes more economical to switch layers rather than to reach. + +* Configuration +** Initial Values +We must set our initial values for the configuration: +#+begin_src kbd :tangle config.kbd +(defcfg + input (device-file "/dev/input/by-path/platform-i8042-serio-0-event-kbd") + output (uinput-sink "My KMonad output" + "/usr/bin/sleep 1 && /usr/bin/setxkbmap -option compose:ralt") + cmp-seq ralt ;; Set the compose key to `RightAlt' + cmp-seq-delay 5 ;; 5ms delay between each compose-key sequence press + fallthrough true + allow-cmd true +) +#+end_src +you need to set your input device according to your hardware. +** defsrc +The defsrc block specifies the default layout that our keyboard uses. Note that when you are, +for example, using a 40% keyboard, some of these keys will not be present. +However, it is still syntactically valid and you will be able to use this +configuration. +#+begin_src kbd :tangle config.kbd +(defsrc + grv 1 2 3 4 5 6 7 8 9 0 - = bspc + tab q w e r t y u i o p [ ] \ + caps a s d f g h j k l ; ' ret + lsft z x c v b n m , . / rsft + lctl lmet lalt spc ralt rmet cmp rctl +) +#+end_src +Also note that the defsrc block is not used for custom key configuration. It +is used only to describe the shape of the current keyboard. +** defalias +defalias defines aliases for buttons. Buttons are used in deflayer blocks +in order to remap the keys. +#+begin_src kbd :tangle config.kbd +(defalias + num (layer-toggle numbers) + kil C-A-del +) +#+end_src +** deflayer +#+begin_src kbd :tangle config.kbd +#| -------------------------------------------------------------------------- + Necessary: at least 1 `deflayer` block + + It is also important to mention that the 'keymap' in KMonad is modelled as a + stack of layers (just like in QMK). When an event is registered we look in the + top-most layer for a handler. If we don't find one we try the next layer, and + then the next. + + Exactly what 'evaluates-to-a-button' will be expanded on in more detail below. + There are very many different specialist buttons in KMonad that we will touch + upon. However, for now, these 4 are a good place to begin: + + 1. Any keycode evaluates to a button that, on press, emits the press of that + keycode, and on release, emits the release of that keycode. Just a 'normal' + button. The exception is '\', which gets used as an escape character. Use + '\\' instead. Other characters that need to be escaped to match the literal + character are '(', ')', and '_'. + + 2. An @-prefixed name evaluates to an alias lookup. We named two buttons in + the `defalias` block above, we could now refer to these buttons using + `@num` and `@kil`. This is also why we only use alias-names no longer than + 3 characters in this tutorial. Also, note that we are already referencing + some aliases that have not yet been defined, this is not an issue. + + 3. The '_' character evaluates to transparent. I.e. no handler for that + key-event in this layer, causing this event to be handed down the layer + stack to perhaps be handled by the next layer. + + 4. The 'XX' character evaluates to blocked. I.e. no action bound to that + key-event in this layer, but do actually catch event, preventing any + underlying layer from handling it. + + Finally, it is important to note that the *first* `deflayer` statement in a + KMonad config will be the layer that is active when KMonad starts up. + + -------------------------------------------------------------------------- |# + + +(deflayer qwerty + grv 1 2 3 4 5 6 7 8 9 0 - = bspc + tab q w e r t y u i o p [ ] \ + esc a s d f g h j k l ; ' ret + lsft z x c v b n m , . / rsft + lctl lmet lalt spc @num rmet @sym rctl +) + +(deflayer numbers + _ _ _ _ _ _ _ _ _ _ _ _ _ _ + _ _ _ _ _ XX / 7 8 9 - _ _ _ + _ _ _ _ _ XX * 4 5 6 + _ _ + _ _ \( \) . XX 0 1 2 3 _ _ + _ _ _ _ _ _ _ _ +) + +#+end_src + +#+begin_src kbd :tangle config.kbd +#| -------------------------------------------------------------------------- + Optional: modded buttons + + Let's start by exploring the various special buttons that are supported by + KMonad by looking at 'modded' buttons, that is to say, buttons that activate + some kind of 'mod', then perform some button, and finally release that 'mod' + again. + + We have already seen an example of this style of button, our `kil` button is + one such button. Let's look at it in more detail: + C-A-del + + This looks like a simple declarative statement, but it's helpful to realize + that is simply syntactic sugar around 2 function calls. This statement is + equivalent to: + (around ctl (around alt del)) + + This highlights a core design principle in KMonad: we try to provide very + simple buttons, and then we provide rules and functions for combining them + into new buttons. Although note: still very much a work in progress. + + So, looking at this statement: + (around foo bar) + + Here, `around` is a function that takes two buttons and creates a new button. + This new button will, on a press, first press foo, then press bar, and on a + release first release bar, and then foo. Once created, this new button can be + passed to anything in KMonad that expects a button. + + We have already seen other examples of modded buttons, \(, \), *, and +. There + are no Keycodes for these buttons in KMonad, but they are buttons. They simply + evaluate to `(around lsft x)`. All shifted numbers have their corresponding + characters, the same is true for all capitals, and < > : ~ " | { } \_ + and ?. + + To wrap up 'modded-buttons', let's look back at C-A-del. We have 8 variants: + C- : (around lctl X) + A- : (around lalt X) + M- : (around lmet X) + S- : (around lsft X) + + Then RC-, RA-, RM-, and RS- behave exactly the same, except using the + right-modifier. + + These can be combined however you please: + C-A-M-S-x ;; Perfectly valid + C-% ;; Perfectly valid: same as C-S-5 + C-RC-RA-A-M-S-RS-m ;; Sure, but why would you? + + Also, note that although we provide special syntax for certain modifiers, + these buttons are in no way 'special' in KMonad. There is no concept of 'modifier'. + (around a (around b c)) ;; Perfectly valid + + -------------------------------------------------------------------------- |# + +(defalias + + ;; Something useful + cpy C-c + pst C-v + cut C-x + + ;; Something silly + md1 (around a (around b c)) ;; abc + md2 (around a (around lsft b)) ;; aB + md3 C-A-M-S-l + md4 (around % b) ;; BEWARE: %B, not %b, do you see why? +) + +#| -------------------------------------------------------------------------- + Optional: sticky keys + + KMonad also support so called "sticky keys". These are keys that will + behave as if they were pressed after just tapping them. This behaviour + wears off after the next button is pressed, which makes them ideal for + things like a quick control or shift. For example, tapping a sticky and + then pressing `abc' will result in `Abc'. + + You can create these keys with the `sticky-key' keyword: + + (defalias + slc (sticky-key 500 lctl)) + + The number after `sticky-key' is the timeout you want, in milliseconds. If + a key is tapped and that time has passed, it won't act like it's pressed + down when we receive the next keypress. + + It is also possible to combine sticky keys. For example, to + get a sticky shift+control you can do + + (defalias + ssc (around + (sticky-key 500 lsft) + (sticky-key 500 lctl))) + + -------------------------------------------------------------------------- |# + +;; Let's make both shift keys sticky +(defalias + sl (sticky-key 300 lsft) + sr (sticky-key 300 rsft)) + + +;; Now we define the 'tst' button as opening and closing a bunch of layers at +;; the same time. If you understand why this works, you're starting to grok +;; KMonad. +;; +;; Explanation: we define a bunch of testing-layers with buttons to illustrate +;; the various options in KMonad. Each of these layers makes sure to have its +;; buttons not overlap with the buttons from the other layers, and specifies all +;; its other buttons as transparent. When we use the nested `around` statement, +;; whenever we push the button linked to '@tst' (check `qwerty` layer, we bind +;; it to `rctl`), any button we press when holding `rctl` will be pressed in the +;; context of those 4 layers overlayed on the stack. When we release `rctl`, all +;; these layers will be popped again. +(defalias tst (around (layer-toggle macro-test) + (around (layer-toggle layer-test) + (around (layer-toggle around-next-test) + (around (layer-toggle command-test) + (layer-toggle modded-test)))))) + +(deflayer modded-test + _ _ _ _ _ _ _ _ _ _ _ _ _ _ + _ _ @md4 _ _ _ _ _ _ _ _ _ _ _ + _ _ @md1 @md2 @md3 _ _ _ _ _ _ _ _ + _ _ @cut @cpy @pst _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _ +) + +#| -------------------------------------------------------------------------- + Optional: tap-macros + + Let's look at a button we haven't seen yet, tap-macros. + + `tap-macro` is a function that takes an arbitrary number of buttons and + returns a new button. When this new button is pressed it rapidly taps all its + stored buttons in quick succesion except for its last button, which it only + presses. This last button gets released when the `tap-macro` gets released. + + There are two ways to define a `tap-macro`, using the `tap-macro` function + directly, or through the #() syntactic sugar. Both evaluate to exactly the + same button. + + (tap-macro K M o n a d) + #(K M o n a d) + + If you are going to use a `tap-macro` to perform a sequence of actions inside + some program you probably want to include short pauses between inputs to give + the program time to register all the key-presses. Therefore we also provide + the 'pause' function, which simply pauses processing for a certain amount of + milliseconds. Pauses can be created like this: + + (pause 20) + P20 + + You can also pause between each key stroke by specifying the `:delay' keyword, + as well as a time in ms, at the end of a `tap-macro': + + (tap-macro K M o n a d :delay 5) + #(K M o n a d :delay 5) + + The above would be equivalent to e.g. + + (tap-macro K P5 M P5 o P5 n P5 a P5 d) + + The `tap-macro-release` is like `tap-macro`, except that it + waits to press the last button when the `tap-macro-release` + gets released. It might be useful when combined with a + footswitch that sends keyboard scan codes. + + (tap-macro-release i K M o n a d esc) + + WARNING: DO NOT STORE YOUR PASSWORDS IN PLAIN TEXT OR IN YOUR KEYBOARD + + I know it might be tempting to store your password as a macro, but there are 2 + huge risks: + 1. You accidentally leak your config and expose your password + 2. Anyone who knows about the button can get clear-text representation of your + password with any text editor, shell, or text-input field. + + Support for triggering shell commands directly from KMonad is described in the + command buttons section below. + + This concludes this public service announcement. + + -------------------------------------------------------------------------- |# + +(defalias + mc1 #(K M o n a d) + mc2 #(C-c P50 A-tab P50 C-v) ;; Careful, this might do something + mc3 #(P200 h P150 4 P100 > < P50 > < P20 0 r z 1 ! 1 ! !) + mc4 (tap-macro a (pause 50) @md2 (pause 50) c) + mc5 (tap-macro-release esc esc esc) + mc6 #(@mc3 spc @mc3 spc @mc3) +) + +(deflayer macro-test + _ @mc1 @mc2 @mc3 @mc4 @mc5 @mc6 _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _ +) + + +#| -------------------------------------------------------------------------- + Optional: layer manipulation + + You have already seen the basics of layer-manipulation. The `layer-toggle` + button. This button adds a layer to the top of KMonad's layer stack when + pressed, and removes it again when released. There are a number of other ways + to manipulate the layer stack, some safer than others. Let's go through all of + them from safest to least safe: + + `layer-toggle` works as described before, 2 things to note: + 1. If you are confused or worried about pressing a key, changing layers, and + then releasing a key and this causing issues: don't be. KMonad handles + presses and releases in very different ways. Presses get passed directly to + the stacked keymap as previously described. When a KMonad button has its + press-action triggered, it then registers a callback that will catch its + own release before we ever touch the keymap. This guarantees that the + button triggered by the press of X *will be* the button whose release is + triggered by the release of X (the release of X might trigger other things + as well, but that is besides the point.) + 2. If `layer-toggle` can only ever add and then necessarily remove 1 layer + from the stack, then it will never cause a permanent change, and is + perfectly safe. + + `layer-delay`, once pressed, temporarily switches to some layer for some + milliseconds. Just like `layer-toggle` this will never permanently mess-up the + layer stack. This button was initially implemented to provide some + 'leader-key' style behavior. Although I think in the future better solutions + will be available. For now this will temporarily add a layer to the top of the + stack: + (layer-delay 500 my-layer) + + `layer-next`, once pressed, primes KMonad to handle the next press from some + arbitrary layer. This aims to fill the same usecase as `layer-delay`: the + beginnings of 'leader-key' style behavior. I think this whole button will get + deleted soon, because the more general `around-next` now exists (see below) + and this is nothing more than: + (around-next (layer-toggle layer-name)) + Until then though, use `layer-next` like this: + (layer-next layer-name) + + `layer-switch`: change the base-layer of KMonad. As described at the top of + this document, the first `deflayer` statement is the layer that is active when + KMonad starts. Since `layer-toggle` can only ever add on and remove from the + top of that, it can never change the base-layer. The following button will + unregister the bottom-most layer of the keymap, and replace it with another + layer. + (layer-switch my-layer) + + This is where things start getting potentially dangerous (i.e. get KMonad into + an unusuable state until a restart has occured). It is perfectly possible to + switch into a layer that you can never get out of. Or worse, you could + theoretically have a layer full of only `XX`s and switch into that, rendering + your keyboard unuseable until you somehow manage to kill KMonad (without using + your keyboard). + + However, when handled well, `layer-switch` is very useful, letting you switch + between 'modes' for your keyboard. I have a tiny keyboard with a weird keymap, + but I switch into a simple 'qwerty' keymap shifted 1 button to the right for + gaming. Just make sure that any 'mode' you switch into has a button that + allows you to switch back out of the 'mode' (or content yourself restarting + KMonad somehow). + + `layer-add` and `layer-rem`. This is where you can very quickly cause yourself + a big headache. Originally I didn't expose these operations, but someone + wanted to use them, and I am not one to deny someone else a chainsaw. As the + names might give away: + (layer-add name) ;; Add a layer to the top of the stack + (layer-rem name) ;; Remove a layer by name (noop if no such layer) + + To use `layer-add` and `layer-rem` well, you should take a moment to think + about how to create a layout that will prevent you from getting into + situations where you enter a key-configuration you cannot get out of again. + These two operations together, however, are very useful for activating a + permanent overlay for a while. This technique is illustrated in the tap-hold + overlay a bit further down. + + + -------------------------------------------------------------------------- |# + +(defalias + + yah (layer-toggle asking-for-trouble) ;; Completely safe + nah (layer-add asking-for-trouble) ;; Completely unsafe + + ld1 (layer-delay 500 numbers) ;; One way to get a leader-key + ld2 (layer-next numbers) ;; Another way to get a leader key + + ;; NOTE, this is safe because both `qwerty` and `colemak` contain the `@tst` + ;; button which will get us to the `layer-test` layer, which itself contains + ;; both `@qwe` and `@col`. + qwe (layer-switch qwerty) ;; Set qwerty as the base layer + col (layer-switch colemak) ;; Set colemak as the base layer +) +(deflayer layer-test + @qwe _ _ _ _ _ _ _ _ _ _ @add _ @nah + @col _ _ _ _ _ _ _ _ _ _ _ _ @yah + _ _ _ _ _ _ _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _ _ @ld1 @ld2 _ + _ _ _ _ _ _ _ _ +) + +;; Exactly like qwerty, but with the letters switched around +(deflayer colemak + grv 1 2 3 4 5 6 7 8 9 0 - = bspc + tab q w f p g j l u y ; [ ] \ + @xcp a r s t d h n e i o ' ret + @sl z x c v b k m , . / @sr + lctl @num lalt spc ralt rmet @sym @tst +) + +(defalias lol #(: - D)) + +;; Contrived example +(deflayer asking-for-trouble + @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol + @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol + @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol + @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol @lol + @lol @lol @lol @lol @lol @lol @lol @lol +) + +;; One way to safely use layer-add and layer-rem: the button bound to layer-add +;; is the same button bound to layer-rem in the layer that `add` adds to the +;; stack. I.e., it becomes impossible to add or remove multiple copies of a +;; layer. +(defalias + add (layer-add multi-overlay) ;; multi-overlay is defined in the next + rem (layer-rem multi-overlay) ;; section below this + ) + +#| -------------------------------------------------------------------------- + Optional: Multi-use buttons + + Perhaps one of the most useful features of KMonad, where a lot of work has + gone into, but also an area with many buttons that are ever so slightly + different. The naming and structuring of these buttons might change sometime + soon, but for now, this is what there is. + + For the next section being able to talk about examples is going to be handy, + so consider the following scenario and mini-language that will be the same + between scenarios. + - We have some button `foo` that will be different between scenarios + - `foo` is bound to 'Esc' on the input keyboard + - the letters a s d f are bound to themselves + - Px signifies the press of button x on the keyboard + - Rx signifies the release of said button + - Tx signifies the sequential and near instantaneous press and release of x + - 100 signifies 100ms pass + + So for example: + Tesc Ta: + tap of 'Esc' (triggering `foo`), tap of 'a' triggering `a` + Pesc 100 Ta Tb Resc: + press of 'Esc', 100ms pause, tap of 'a', tap of 'b', release of 'Esc' + + The `tap-next` button takes 2 buttons, one for tapping, one for holding, and + combines them into a single button. When pressed, if the next event is its own + release, we tap the 'tapping' button. In all other cases we first press the + 'holding' button then we handle the event. Then when the `tap-next` gets + released, we release the 'holding' button. + + So, using our mini-language, we set foo to: + (tap-next x lsft) + Then: + Tesc -> x + Tesc Ta -> xa + Pesc Ta Resc -> A + Pesc Ta Tr Resc -> AR + + The `tap-hold` button is very similar to `tap-next` (a theme, trust me). The + difference lies in how the decision is made whether to tap or hold. A + `tap-hold` waits for a particular timeout, if the `tap-hold` is released + anywhere before that moment we execute a tap immediately. If the timeout + occurs and the `tap-hold` is still held, we switch to holding mode. + + The additional feature of a `tap-hold` is that it pauses event-processing + until it makes its decision and then rolls back processing when the decision + has been made. + + So, again with the mini-language, we set foo to: + (tap-hold 200 x lsft) ;; Like tap-next, but with a 200ms timeout + Then: + Tesc -> x + Tesc Ta -> xa + Pesc 300 a -> A (the moment you press a) + Pesc a 300 -> A (after 200 ms) + Pesc a 100 Resc -> xa (both happening immediately on Resc) + + The `tap-hold-next` button is a combination of the previous 2. Essentially, + think of it as a `tap-next` button, but it also switches to held after a + period of time. This is useful, because if you have a (tap-next ret ctl) for + example, and you press it thinking you want to press C-v, but then you change + your mind, you now cannot release the button without triggering a 'ret', that + you then have to backspace. With the `tap-hold-next` button, you simply + outwait the delay, and you're good. I see no benefit of `tap-next` over + `tap-hold-next` with a decent timeout value. + + You can use the `:timeout-button` keyword to specify a button other than the + hold button which should be held when the timeout expires. For example, we + can construct a button which types one x when tapped, multiple x's when held, + and yet still acts as shift when another button is pressed before the timeout + expires. So, using the minilanguage and foo as: + (tap-hold-next 200 x lsft :timeout-button x) + Then: + Tesc -> Tx + Pesc 100 a -> A (the moment you press a) + Pesc 5000 Resc -> xxxxxxx (some number of auto-repeated x's) + + Note that KMonad does not itself auto-repeat the key. In this last example, + KMonad emits 200 Px 4800 Rx, and the operating system's auto-repeat feature, + if any, emits multiple x's because it sees that the x key is held for 4800 ms. + + The `tap-next-release` is like `tap-next`, except it decides whether to tap or + hold based on the next release of a key that was *not* pressed before us. This + also performs rollback like `tap-hold`. So, using the minilanguage and foo as: + (tap-next-release x lsft) + Then: + Tesc Ta -> xa + Pa Pesc Ra Resc -> ax (because 'a' was already pressed when we started, so + foo decides it is tapping) + Pesc Pa Resc Ra -> xa (because the first release we encounter is of esc) + Pesc Ta Resc -> A (because a was pressed *and* released after we started, + so foo decides it is holding) + + `tap-next-press` is also a lot like `tap-next`, but decides whether to tap or + hold based on whether another key is pressed before this one is released. + Using the minilanguage: + (tap-next-press x lsft) + Then: + Tesc Ta -> xa + Pa Pesc Ra Resc -> ax (because esc is released before another key is pressed) + Pesc Pa Resc Ra -> A (because a is pressed before esc is released) + Pesc Ta Resc -> A (a is pressed before esc is released here as well) + + These increasingly stranger buttons are, I think, coming from the stubborn + drive of some of my more eccentric (and I mean that in the most positive way) + users to make typing with modifiers on the home-row more comfortable. + Especially layouts that encourage a lot of rolling motions are nicer to use + with the `release` style buttons. + + The `tap-hold-next-release` (notice a trend?) is just like `tap-next-release`, + but it comes with an additional timeout that, just like `tap-hold-next` will + jump into holding-mode after a timeout. + + I honestly think that `tap-hold-next-release`, although it seems the most + complicated, probably is the most comfortable to use. But I've put all of them + in a testing layer down below, so give them a go and see what is nice. + + -------------------------------------------------------------------------- |# + + +(defalias + xtn (tap-next x lsft) ;; Shift that does 'x' on tap + xth (tap-hold 400 x lsft) ;; Long delay for easier testing + thn (tap-hold-next 400 x lsft) + tnr (tap-next-release x lsft) + tnp (tap-next-press x lsft) + tnh (tap-hold-next-release 2000 x lsft) + + ;; Used it the colemak layer + xcp (tap-hold-next 400 esc ctl) +) + +;; Some of the buttons used here are defined in the next section +(deflayer multi-overlay + @mt _ _ _ _ _ _ _ _ _ _ _ @rem _ + _ _ _ _ _ _ _ _ _ _ _ _ _ _ + @thn _ _ _ _ _ _ _ _ _ _ _ _ + @xtn _ _ _ _ _ _ _ _ _ _ @xth + @tnr @tnp _ _ _ _ _ @tnh +) + + +#| -------------------------------------------------------------------------- + Optional: Multi-tap + + Besides the tap-hold style buttons there is another multi-use button (with. + only 1 variant, at the moment). The `multi-tap`. + + A `multi-tap` codes for different buttons depending on how often it is tapped. + It is defined by a series of delays and buttons, followed by a last button + without delay. As long as you tap the `multi-tap` within the delay specified, + it will jump to the next button. Once the delay is exceeded the selected + button is pressed. If the last button in the list is reached, it is + immediately pressed. When another key is pressed down while we're tapping, + `multi-tap' also immediately exits and taps the current button. + + Note that you can actually hold the button, so in the below example, going: + tap-tap-hold (wait 300ms) will get you a pressed c, until you release again. + + -------------------------------------------------------------------------- |# + +(defalias + mt (multi-tap 300 a 300 b 300 c 300 d e)) + + +#| -------------------------------------------------------------------------- + Optional: Around-next + + The `around-next` function creates a button that primes KMonad to perform the + next button-press inside some context. This could be the context of 'having + Shift pressed' or 'being inside some layer' or, less usefully, 'having d + pressed'. It is a more general and powerful version of `layer-next`. + + There is also an `around-next-timeout` button that does the same thing as + `around-next`, except that if some other button press is not detected within + some timeout, some other button is tapped. This can be used to create a + leader-key that simply times out (by passing a non-button), or a key that can + still function as a normal key, but also as a leader key when used slowly. + + I think expansion of this button-style is probably the future of leader-key, + hydra-style functionality support in KMonad. + + -------------------------------------------------------------------------- |# + +(defalias + ns (around-next sft) ;; Shift the next press + nnm (around-next @num) ;; Perform next press in numbers layer + ntm (around-next-timeout 500 sft XX) + + +) + +(deflayer around-next-test + _ _ _ _ _ _ _ _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _ _ _ _ _ _ _ + @ns _ _ _ _ _ _ _ _ _ _ _ _ + @nnm _ _ _ _ _ _ _ _ _ _ _ + @ntm _ _ _ _ _ _ _ +) + +#| -------------------------------------------------------------------------- + Optional: Compose-key sequences + + Compose-key sequences are series of button-presses that your operating system + will interpret as the insertion of a special character, like accented + characters, or various special-languages. In that sense, they are just + syntactic sugar for keyboard macros. + + To get this to work on Linux you will need to set your compose-key with a tool + like `setxkbmap', as well as tell kmonad that information. See the `defcfg' + block at the top of this file for a working example. Note that you need to + wait ever so slightly for the keyboard to register with linux before the + command gets executed, that's why the `sleep 1`. Also, note that all the + `/run/current-system' stuff is because the author uses NixOS. Just find a + shell-command that will: + + 1. Sleep a moment + 2. Set the compose-key to your desired key + + Please be aware that what `setxkbmap' calls the `menu' key is not actually the + `menu' key! If you want to use the often suggested + + setxkbmap -option compose:menu + + you will have to set your compose key within kmonad to `compose' and not + `menu'. + + After this, this should work out of the box under Linux. Windows does not + recognize the same compose-key sequences, but WinCompose will make most of the + sequences line up with KMonad: http://wincompose.info/ + This has not in any way been tested on Mac. + + In addition to hard-coded symbols, we also provide 'uncompleted' macros. Since + a compose-key sequence is literally just a series of keystrokes, we can omit + the last one, and enter the sequence for 'add an umlaut' and let the user then + press some letter to add this umlaut to. These are created using the `+"` + syntax. + + -------------------------------------------------------------------------- |# + +(defalias + sym (layer-toggle symbols) + +) + +(deflayer symbols + _ _ _ _ _ _ _ _ _ _ _ _ _ _ + _ ä é © _ _ _ _ _ _ _ _ _ _ + _ +' +~ +` +^ _ _ _ _ _ _ _ _ + _ +" +, _ _ _ _ _ _ _ _ _ + _ _ _ _ _ _ _ _) + + +#| -------------------------------------------------------------------------- + Optional: Command buttons + + Currently we also provide the ability to launch arbitrary shell-commands from + inside kmonad. These commands are simply handed off to the command-shell + without any further checking or waiting. + + NOTE: currently only tested on Linux, but should work on any platform, as long + as the command is valid for that platform. + + The `cmd-button' function takes two arguments, the second one of which is + optional. These represent the commands to be executed on pressing and + releasing the button respectively. + + BEWARE: never run anyone's configuration without looking at it. You wouldn't + want to push: + + (cmd-button "rm -rf ~/*") ;; Delete all this user's data + + + -------------------------------------------------------------------------- |# +#+end_src |