Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 4 additions & 20 deletions install/mac/karabiner/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,12 @@ Engram layouts for Karabiner.
```


# Using Karabiner with Engram
## Using Karabiner with Engram

To use the vanilla Engram layout on MacOS, simply

1. Install Karabiner `brew install karabiner-elements` (you'll have to grant necessary permissions in `System Settings`, detailed on the [Karabiner website](https://karabiner-elements.pqrs.org)).
2. Click this link to open the Engram layout [directly in Karabiner](https://smote.io/install_engram.html)
2. Click this link to open the Engram layout [directly in Karabiner](https://esm.sh/gh/binarybottle/engram/install/mac/karabiner/install_engram.html)

Or you can view the JSON [here](https://raw.githubusercontent.com/binarybottle/engram/master/install/mac/karabiner/engram.json) (you'll need to place the json file in `~/.config/karabiner/assets/complex_modifications/` and maybe restart Karabiner if you want to customize/ install manually).

Expand All @@ -26,26 +26,10 @@ Or you can view the JSON [here](https://raw.githubusercontent.com/binarybottle/e

This directory also includes [Karabiner.ts](https://github.com/evan-liu/karabiner.ts) config, as well as a [Goku](https://github.com/yqrashawn/GokuRakuJoudo) config.

Home Row Mods are working better in the Karabiner.ts config than the Goku one. (They're configured as simlayers in the Karabiner.ts version.) Karabiner.ts also 🏃🏻‍♂️s 53 times faster--73.6ms vs. 3.947s.

The command keys are set to work more like they do on a mech ergo board.
## Home Row Mods

Currently, Home Row Mods work only one at a time, but hoping to get that sorted shortly. 🤓

Karabiner still has some shortcomings. It seems like no matter how it's configured, typing rhythm isn't as natural with Karabiner as it is with [timeless Home Row Mods](https://github.com/urob/zmk-config#timeless-homerow-mods) in zmk using below config.

```dtsi
hrml: home_row_mod_left {
compatible = "zmk,behavior-hold-tap";
label = "HOME_ROW_MOD_LEFT";
#binding-cells = <2>;
flavor = "balanced";
tapping-term-ms = <HM_TAPPING_TERM>;
hold-trigger-key-positions = < KEYS_R THUMBS >;
hold-trigger-on-release;
bindings = <&kp>, <&kp>;
};
```
Home row mods don't work very well in Karabiner. If you are interested in using home row mods on MacOS, you'll probably be happier installing KMonad, also documented in the `engram/install/mac` directory.


## Installing
Expand Down
4 changes: 3 additions & 1 deletion install/mac/karabiner/deno.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@
"tasks": {
"build": "deno run -A index.ts"
},
"importMap": "import_map.json",
"imports": {
"karabinerts": "https://deno.land/x/karabinerts/deno.ts"
},
"fmt": {
"semiColons": false,
"singleQuote": true
Expand Down
5 changes: 0 additions & 5 deletions install/mac/karabiner/import_map.json

This file was deleted.

104 changes: 31 additions & 73 deletions install/mac/karabiner/index.ts
Original file line number Diff line number Diff line change
@@ -1,85 +1,43 @@
import {
layer,
FromKeyParam,
// layer,
LayerKeyParam,
map,
ModifierParam,
rule,
simlayer,
// toKey,
// ToKeyParam,
withMapper,
withModifier,
writeToProfile,
} from 'karabinerts'
import { engram, engram_left, engram_right } from './engram.ts'

// writeToProfile("--dry-run", [
writeToProfile('karabiner.ts', [
layer('⇪', 'nav').manipulators([
withModifier('optionalAny')([
map('u').to('↖︎'),
map('i').to('⇟'),
map('o').to('⇞'),
map('p').to('↘︎'),
map('j').to('←'),
map('k').to('↓'),
map('l').to('↑'),
map(';').to('→'),
map('m').to('z', '<⌘'),
map(',').to('x', '<⌘'),
map('.').to('c', '<⌘'),
map('/').to('v', '<⌘'),
]),
]),
simlayer('f', '<⇧').manipulators([
// Reminder to experiment with .toDelayedAction() method
// map('<⌘').toIfAlone('⌫').to('<⌘').toDelayedAction(toKey('m'), toKey('t')),
// withMapper(engram_right)((k) => map(k.from, k.fromMod).to(k.to, "⌘⇧").condition(ifVar("<⌘", 1))),
// withMapper(engram_right)((k) => map(k.from, k.fromMod).to(k.to, "⇧⌥").condition(ifVar("<⌥", 1))),
// withMapper(engram_right)((k) => map(k.from, k.fromMod).to(k.to, "⌃⇧").condition(ifVar("<⌃", 1))),
withMapper(engram_right)((k) => map(k.from, k.fromMod).to(k.to, '⇧')),
]),
simlayer('j', '>⇧').manipulators([
// withMapper(engram_left)((k) => map(k.from, k.fromMod).to(k.to, "⌘⇧").condition(ifVar(">⌘", 1))),
// withMapper(engram_left)((k) => map(k.from, k.fromMod).to(k.to, "⇧⌥").condition(ifVar(">⌥", 1))),
// withMapper(engram_left)((k) => map(k.from, k.fromMod).to(k.to, "⌃⇧").condition(ifVar(">⌃", 1))),
withMapper(engram_left)((k) => map(k.from, k.fromMod).to(k.to, '⇧')),
]),
simlayer('d', '<⌘').manipulators([
// withMapper(engram_right)((k) => map(k.from, k.fromMod).to(k.to, "⌘⌥").condition(ifVar("<⌥", 1))),
withMapper(engram_right)((k) => map(k.from, k.fromMod).to(k.to, '⌘')),
]),
simlayer('k', '>⌘').manipulators([
// withMapper(engram_left)((k) => map(k.from, k.fromMod).to(k.to, "⌘⌥").condition(ifVar(">⌥", 1))),
withMapper(engram_left)((k) => map(k.from, k.fromMod).to(k.to, '⌘')),
]),
simlayer('s', '<⌥').manipulators([
withMapper(engram_right)((k) => map(k.from, k.fromMod).to(k.to, '⌥')),
]),
simlayer('l', '>⌥').manipulators([
withMapper(engram_left)((k) => map(k.from, k.fromMod).to(k.to, '⌥')),
]),
simlayer('a', '<⌃').manipulators([
withMapper(engram_right)((k) => map(k.from, k.fromMod).to(k.to, '⌃')),
]),
simlayer(';', '>⌃').manipulators([
withMapper(engram_left)((k) => map(k.from, k.fromMod).to(k.to, '⌃')),
]),
const qhr: FromKeyParam[] = ['a', 's', 'd', 'f', 'j', 'k', 'l', ';']
const mods = ['‹⌃', '‹⌥', '‹⌘', '‹⇧', '›⇧', '›⌘', '›⌥', '›⌃']

rule('short pinkies').manipulators([
withModifier('optionalAny')([
map('<⌘').toIfAlone('⌫').to('<⌘'),
map('>⌘').toIfAlone('⏎').to('<⌘'),
map('=').to('⌫'),
map('>⇧', '<⇧').to('\\'),
map('>⇧').to('/'),
]),
]),
rule('engram').manipulators([
withModifier('optionalAny')([
withMapper(engram)((k) => map(k.from, k.fromMod).to(k.to, k.toMod)),
writeToProfile('karabiner.ts', [

// Uncomment for home row mods. This is an incomplete implementation! Use KMonad for the full experience.

// ...(qhr.map((key, i) =>
// simlayer(key as LayerKeyParam, mods[i])
// .manipulators([
// withMapper(i < 4 ? engram_right : engram_left)((k) =>
// map(k.from).to(k.to, mods[i] as ModifierParam)
// ),
// ])
// )),

// Engram base layer
rule('engram').manipulators([
withModifier('optionalAny')([
withMapper(engram)((k) => map(k.from).to(k.to)),
]),
]),
]),
], {
'simlayer.threshold_milliseconds': 300,
'basic.to_delayed_action_delay_milliseconds': 251,
'basic.to_if_alone_timeout_milliseconds': 250,
'basic.to_if_held_down_threshold_milliseconds': 251,
})
], {
'simlayer.threshold_milliseconds': 500,
'basic.to_if_alone_timeout_milliseconds': 199,
'basic.to_delayed_action_delay_milliseconds': 200,
'basic.to_if_held_down_threshold_milliseconds': 200,
})
14 changes: 14 additions & 0 deletions install/mac/karabiner/install_engram.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<!-- This file lets Karabiner directly import the Engram layout. It's served by esm.sh in the docs so that headers are set appropriately. -->
<!DOCTYPE html>
<html>

<head>
<meta http-equiv="refresh"
content="1; url='karabiner://karabiner/assets/complex_modifications/import?url=https://raw.githubusercontent.com/binarybottle/engram/master/install/mac/karabiner/engram.json'" />
</head>

<body>
<p>Opening Engram layout in Karabiner momentarily...</p>
</body>

</html>
42 changes: 42 additions & 0 deletions install/mac/kmonad/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# KMonad and Engram

[KMonad](https://github.com/kmonad/kmonad), **the onion of keyboard management**, is a cross platform keyboard management tool. It's `.kbd` config files are concise and easy to read and alter.

The example configs in this directory are laid out for a MacBook/Air/Pro keyboard, but could easily be adapted or used as a starting point to configure Engram on Linx or Windows as well. KMonad makes trivial work of home row mods. It is fast and easy to work with and may become your preferred way of changing layouts.

Some changes to KMonad for MacOS compatability have only recently been pulled in to the main branch of the project and the install docs are still not fully updated. Follow [this gist](https://gist.github.com/amiorin/4c74f63fe599a1dcbd0933628df1aac9) by @amiorin to build KMonad.

You may be able to replace

```
git clone --recursive https://github.com/vosaica/kmonad.git
cd kmonad
git checkout Upgrade-DriverKit-VirtualHIDDevice
git submodule update --init
stack build --flag kmonad:dext --extra-include-dirs=c_src/mac/Karabiner-DriverKit-VirtualHIDDevice/include/pqrs/karabiner/driverkit:c_src/mac/Karabiner-DriverKit-VirtualHIDDevice/src/Client/vendor/include
```

with

```
git clone --recursive https://github.com/kmonad/kmonad.git
cd kmonad/
stack build --flag kmonad:dext --extra-include-dirs=c_src/mac/Karabiner-DriverKit-VirtualHIDDevice/include/pqrs/karabiner/driverkit:c_src/mac/Karabiner-DriverKit-VirtualHIDDevice/src/Client/vendor/include
```

You can replace the `stack build` command with `stack install` and it should place the compiled binaries appropriately on your system. If you don't happen to have haskell installed on your system already, try running `brew install haskell-stack` before proceeding with the above insturctions.



To have the layout load on startup, place your preferred `.kbd` file in something like `~/.local/config/`, and install the `kmonad.plist` file found in this directory, either via launchctl or, should you prefer to use the GUI, with something like [LaunchControl](https://www.soma-zone.com/LaunchControl/). depending on which config file you choose to use, you may also need to adjust the appropriate fields in your launchctl service.

## Tap Macro

Switching to home row mods leaves quite a few spare keys on your keyboard. You can remap these to frequently typed phrases with KMonad's __tap macro__ system:

```kmonad
(tap-macro K M o n a d)
#(K M o n a d)
```

There are a few examples included in the sample configuration files in this directory. `engram.kbd` is the vanilla variant that adheres strictly to the official engram layout. `engram-hrm.kbd` also adheres to the vanilla layout, but includes home row mods. An `engrammer.kbd` example is included as well, both for breadth, and to demonstrate KMonad's macro system in practice. See the [KMonad Configuration Guide](https://github.com/kmonad/kmonad/blob/1b2ec006259ddbe6cda30db8eb783e8177a9f12b/keymap/tutorial.kbd#L481C1-L481C2) for more detailed instructions.
60 changes: 60 additions & 0 deletions install/mac/kmonad/engram-hrm.kbd
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
;; See kmonad's keymap/tutorial.kbd for a more complete tutorial

;; Engram, for reference
;; [{ 1| 2= 3~ 4+ 5< 6> 7^ 8& 9% 0* ]} /\
;; bB yY oO uU '( ") lL dD wW vV zZ #$ @`
;; cC iI eE aA ,; .: hH tT sS nN qQ
;; gG xX jJ kK -_ ?! rR mM fF pP

(defcfg
input (iokit-name "Apple Internal Keyboard / Trackpad")
output (kext)
fallthrough true
allow-cmd false
)

(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 up
fn lctl lalt lmet spc rmet ralt left down rght
)

(defalias
up (layer-toggle engram_shifted_homerow_mods)

cc (tap-hold-next-release 200 c lctl)
ai (tap-hold-next-release 200 i lalt)
me (tap-hold-next-release 200 e lmet)
sa (tap-hold-next-release 200 a @up)
sh (tap-hold-next-release 200 h @up)
mt (tap-hold-next-release 200 t rmet)
as (tap-hold-next-release 200 s lalt)
cn (tap-hold-next-release 200 n rctl)

csc (tap-hold-next-release 200 C S-lctl)
asi (tap-hold-next-release 200 I S-lalt)
mse (tap-hold-next-release 200 E S-lmet)
ssa (tap-hold-next-release 200 A lsft)
ssh (tap-hold-next-release 200 H rsft)
mst (tap-hold-next-release 200 T S-rmet)
ass (tap-hold-next-release 200 S S-lalt)
csn (tap-hold-next-release 200 N S-rctl)
)

(deflayer engram_homerow_mods
[ 1 2 3 4 5 6 7 8 9 0 ] / bspc
tab b y o u ' " l d w v z # @
caps @cc @ai @me @sa , . @sh @mt @as @cn q ret
@up g x j k - ? r m f p @up up
fn lctl lalt lmet spc rmet ralt left down rght
)

(deflayer engram_shifted_homerow_mods
{ | = ~ + < > ^ & % * } \ S-bspc
tab B Y O U \( \) L D W V Z $ `
caps @csc @asi @mse @ssa ; : @ssh @mst @ass @csn Q S-ret
@up G X J K _ ! R M F P @up S-up
S-fn S-lctl S-lalt S-lmet S-spc S-rmet S-ralt S-left S-down S-rght
)
42 changes: 42 additions & 0 deletions install/mac/kmonad/engram.kbd
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
;; See kmonad's keymap/tutorial.kbd for a more complete tutorial

;; Engram, for reference
;; [{ 1| 2= 3~ 4+ 5< 6> 7^ 8& 9% 0* ]} /\
;; bB yY oO uU '( ") lL dD wW vV zZ #$ @`
;; cC iI eE aA ,; .: hH tT sS nN qQ
;; gG xX jJ kK -_ ?! rR mM fF pP

(defcfg
input (iokit-name "Apple Internal Keyboard / Trackpad")
output (kext)
fallthrough true
allow-cmd false
)

(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 up
fn lctl lalt lmet spc rmet ralt left down rght
)

(defalias
up (layer-toggle engram_shifted)
)

(deflayer engram
[ 1 2 3 4 5 6 7 8 9 0 ] / bspc
tab b y o u ' " l d w v z # @
caps c i e a , . h t s n q ret
@up g x j k - ? r m f p @up up
fn lctl lalt lmet spc rmet ralt left down rght
)

(deflayer engram_shifted
{ | = ~ + < > ^ & % * } \ S-bspc
tab B Y O U \( \) L D W V Z $ `
caps C I E A ; : H T S N Q S-ret
@up G X J K _ ! R M F P @up S-up
S-fn S-lctl S-lalt S-lmet S-spc S-rmet S-ralt S-left S-down S-rght
)
56 changes: 56 additions & 0 deletions install/mac/kmonad/engrammer.kbd
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
;; See keymap/tutorial.kbd for a more complete tutorial

(defcfg
input (iokit-name "Apple Internal Keyboard / Trackpad")
output (kext)
fallthrough true
allow-cmd false
)

(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 up
fn lctl lalt lmet spc rmet ralt left down rght
)

(defalias
cc (tap-hold-next-release 200 c lctl)
ai (tap-hold-next-release 200 i lalt)
me (tap-hold-next-release 200 e lmet)
sa (tap-hold-next-release 200 a lsft)
sh (tap-hold-next-release 200 h rsft)
mt (tap-hold-next-release 200 t rmet)
as (tap-hold-next-release 200 s lalt)
cn (tap-hold-next-release 200 n rctl)
nav (tap-hold 180 caps (layer-toggle navigation))
af #(spc \( \) spc = > spc )
ht #(h t t p s : / /)
moi #(Y o u r spc N a m e)

)

(deflayer engram_homerow_mods
grv 1 2 3 4 5 6 7 8 9 0 [ ] bspc
tab b y o u ' ; l d w v z = \
@nav @cc @ai @me @sa , . @sh @mt @as @cn q ret
g x j k - @af / r m f p @ht up
fn M-spc esc bspc spc ret @moi left down rght
)

(deflayer navigation
_ _ _ _ _ _ _ _ _ _ _ _ _ _
_ _ _ _ _ _ _ home pgdn pgup end _ _ _
_ _ _ _ _ _ _ left down up rght _ _
_ _ _ _ _ _ M-S-z M-z M-x M-c M-v _ _
_ _ _ _ _ _ _ _ _ _
)

;; (deflayer blank
;; _ _ _ _ _ _ _ _ _ _ _ _ _ _
;; _ _ _ _ _ _ _ _ _ _ _ _ _ _
;; _ _ _ _ _ _ _ _ _ _ _ _ _
;; _ _ _ _ _ _ _ _ _ _ _ _ _
;; _ _ _ _ _ _ _ _ _ _
;; )
Loading