https://github.com/eshrh/nyaatouch
an ergonomic modal editing scheme for emacs optimized for dvorak built on meow
https://github.com/eshrh/nyaatouch
Last synced: 4 months ago
JSON representation
an ergonomic modal editing scheme for emacs optimized for dvorak built on meow
- Host: GitHub
- URL: https://github.com/eshrh/nyaatouch
- Owner: eshrh
- License: gpl-3.0
- Created: 2022-03-21T21:34:51.000Z (over 4 years ago)
- Default Branch: master
- Last Pushed: 2025-04-07T08:17:50.000Z (over 1 year ago)
- Last Synced: 2025-04-07T09:27:31.941Z (over 1 year ago)
- Language: Emacs Lisp
- Size: 83 KB
- Stars: 18
- Watchers: 2
- Forks: 1
- Open Issues: 1
-
Metadata Files:
- Readme: README.org
- License: LICENSE
Awesome Lists containing this project
README
* Nyaatouch
Nyaatouch is a highly ergonomic [[https://en.wikipedia.org/wiki/Dvorak_keyboard_layout][dvorak]] modal editing scheme for [[https://www.gnu.org/software/emacs/][emacs]].
It is built on the [[https://github.com/meow-edit/meow][meow]] modal framework (hence the name), which I also help maintain. Lots of code has been upstreamed into meow to make this system possible. If you're stumbling onto this repository and you either don't use dvorak or would like something a little more traditional but still efficient, I'd suggest checking that project out first.
Meow is a fantastic platform to build a custom editing scheme on for
several reasons
- minimal configuration (no keybindings by default!!)
- self contained, with no dependencies
- allows truly arbitrary keybindings by key macros, which gives a lot
of freedom
- makes it very easy to create custom modal states
If you're interested in more about why vanilla meow is neat,
especially in contrast to something more traditional like vim or
kakoune you might like [[https://www.esrh.me/posts/2021-12-18-switching-to-meow.html][this]] blog post I wrote.
This package pulls in some other packages I find absolutely necessary
for editing programs:
+ [[https://github.com/abo-abo/avy][avy]] - jumping to places
+ [[https://github.com/abo-abo/swiper][swiper]] - extremely neat incremental searcher
+ [[https://github.com/Fuco1/smartparens][smartparens]] - generic bracket manipulation
+ [[https://github.com/skissue/meow-tree-sitter][meow-tree-sitter]] - tree sitter thing selection
Nyaatouch is essentially my personal config, except when I realized that
just my editing related config had grown to nearly 300 lines and
resembled nothing else I know of, I decided to create a package for
it.
* Documentation/Rationale
Nyaatouch is exclusively and strongly focused on ergonomics. This
means that ideas like mnemonic commands and the like totally go out
the window -- keys are assigned to commands based on position,
comfort, and frequency.
Spatially assigned keys take strong influence from dvorak, which
emphasizes alternating hands by spatially separating the vowels and
consonants. In nyaatouch, this is achieved by spatially separating
selections and actions on selections. This means that a wide variety
of useful things can be done by a near instant hand alternation, often
without even moving your hands from the home row.
For instance, deleting a word in nyaatouch is =es=, which is far more
comfortable than say, =diw= in either qwerty or dvorak vim. There's also
a lot more abstraction and consistency in the notion of formalized
"things" and the alternation pattern.
Selecting inside a matched pair of parens, copying the contents,
moving a line below and then pasting is =idhD=. Compare this to
=vi(yp=. Unusable on dvorak!
Another key change that nyaatouch makes is to swap C-x to C-u. This is
stolen from the emacswiki, and is a genius idea. C-u is not used
nearly as often, and putting it under the pointer is super neat, for
example saving file is basically free with holding control and
pressing the hand alternating sequence =us=. This is why I didn't remap
it into the leader like I did with many other uncomfortable C-x
bindings that are still bad with this modification.
** Notes on the movement keys
For some time, i experimented with putting the movement keys on
fgcr. I think this definitely has some merits, especially with regards
to consistency, but it also has two practical problems.
1. Loss of alternation. With insert on j and the movement keys on top
row, you lose some alternation action. After all, insert is rarely
pressed with a selection active. The only reason to select
something is to act on it directly.
2. gc are important. in magit for instance, g is refresh and c is
commit. These are nice keybindings, and I don't want to change
them.
The compromise that I use here is to put up/down back on the home row,
but leave left and right, which are less used, on the top row. Now
that c is free though, we can shift right to be on c, where it is
slightly more comfortable.
The other compromise made for this is to move open new line up
to g. Change/replace on a selection is far too essential to leave the
home row in an alternation focused layout, and is therefore on n.
* Reference
#+BEGIN_SRC
Meow Cheatsheet
┏━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━┯━━━━━━━━━━━━━┓
┃ ~ │ ! │ @ │ # │ $ │ % │ ^ │ & │ * │ ( │ ) │ { │ } │ BKSP ┃
┃ | | | | | | | | case| | | | | ┃
┠─┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┤ ┃
┃ ` │ 1 │ 2 │ 3 │ 4 │ 5 │ 6 │ 7 │ 8 │ 9 │ 0 │ [ │ ] │ ┃
┃ | ex →1| ex →2 ex →3 ex →4 ex →5 ex →6 ex →7 ex →8 ex →9 ex →0 | | ┃
┠─────────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────┴───┬─────────┨
┃ TAB │ " │ < │ > │ P │ Y │ F │ G │ C │ R │ L │ ? │ + │ | ┃
┃ | ←find| ←thing thing→ ex ← open ↑ ex → undo-sel nt-dupli… +num ├┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┨
┃ │ ' │ , │ . │ p │ y │ f │ g │ c │ r │ l │ / │ = │ ┃
┃ | find|←thing→| [thing] join ← open ↓ → del undo nt-dupli… \ ───────────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─┬───────┴─────────┨
┃ │ A │ O │ E │ U │ I │ D │ H │ T │ N │ S │ _ │ ┃
┃ | | [str]| ←sym→| insert block-ex… yank ex ↓ ex ↑ rep -1 ┃
┃ ├┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┤ ┃
┃ │ a │ o │ e │ u │ i │ d │ h │ t │ n │ s │ - │ ┃
┃ | line| ←str→| ←word→ ins. block save ↓ ↑ chg kill swiper ┃
┠───────────────┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────┬───┴─────────────────┨
┃ │ : │ Q │ J │ K │ X │ B │ M │ W │ V │ Z │ ┃
┃ | | | | ←sym| sym→ ┃
┃ ├┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┼┄┄┄┄┄┄┄┄┄┤ ┃
┃ │ ; │ q │ j │ k │ x │ b │ m │ w │ v │ z │ ┃
┃ | reverse| quit| grab| ←word| word→ paren-mo… avy-goto… quit sel repeat pop-sel ┃
┗━━━━━━━━━━━━━━━━━━━━━┷━━━━━━━━━┷━━━━━━━━━┷━━━━━━━━━╅─────────┴─────────┴─────────┴─────────╆━━━━━━━━━┷━━━━━━━━━┷━━━━━━━━━┷━━━━━━━━━━━━━━━━━━━━━┛
┃ SPC ┃
┃ ┃
┃ ┃
┗━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┛
NOTE:
ex means this command will expand current region.
←thing→ (inner), [thing] (bounds), ←thing (begin) and thing→ (end) require a THING as input:
latex -> x round -> r square -> s curly -> c string -> g
symbol -> e window -> w buffer -> b paragraph -> p line -> l
defun -> d sentence -> .
#+END_SRC
** Top row
- 1..9 :: expansion hints
- * :: toggle case with intelligent behavior. see source for details.
** Upper row
- ' :: prompt for char and find forward
- " :: prompt for char and find backward
- , :: meow's inner of thing, selects some object without the delimiters
- . :: meow's bounds of thing, selects some object with the delimiters
- < :: beginning of thing
- > :: end of thing
- p :: meow-join, selects from the last char of the previous line to
the first char of the current line
- f :: move left
- g :: open down
- G :: open up
- c :: move right
- r :: delete one char
- FCHT :: expand selection in corresponding direction
- l :: undo
- / :: Duplicate
- ? :: Duplicate and comment the duplicated thing
- + :: add one to number under point. accepts numeric prefix arg.
** Home row
*** Left hand
- a :: select line
- o :: select inside string *
- O :: select whole string
- e :: select word
- E :: select symbol (according to symbol table)
- u :: insert AT CURSOR. This is different from meow-insert.
- U :: standard meow-insert
- i :: select block (matching parens)
*** Right hand
- d :: yank, copy.
- D :: paste
- h :: move down
- t :: move up
- n :: change
- N :: replace
- S :: kill.
- - :: swiper (better incremental search)
- _ :: subtract one from the number under point. Accepts prefix arg.
** Bottom row
- ; :: exchange point and mark, reverse hint direction
- q :: quit
- j :: enter meow's standard beacon state
- k :: back word
- x :: forward word
- K, X :: back and forward symbols
- b :: enter paren state
- m :: cancel selection
- w :: repeat command
- z :: pop selection marker
** Paren state bindings
The parenthesis state is a custom nyaatouch state to facilitate
dealing with pairs of characters. It uses smartparens as a backend for
most commands.
- fgcr :: movement
- o + {s, r, c, g} :: wrap with square, round, curly, string
- O :: unwrap
- b :: slurp
- x :: barf
- k :: back barf
- j :: back slurp
- s,S :: splice forward and back
- e :: end of sexp
- a :: beginning of sexp
- G :: goto top level paren
- y, Y :: transpose, forward and back
- l :: undo
** Leader bindings
- a :: M-x (extended command)
- e :: C-x b (switch buffer)
- o :: C-h (help prefix)
- u :: C-x C-f (find file)
- h :: C-x o (other window) on my setup this is actually ace-window.
- t :: C-x 0 (close window)
- T :: C-x 1 (close every other window but this one)
- n :: C-x 3 (vert split)
- N :: C-x 2 (horiz split)
- , :: maps to g in programs that need g like magit
- . :: maps to c in programs that need it
- l :: toggle meow using the system clipboard
** Extra thing
- x :: selects latex objects. These can be begin/end envs, parens or
dollar signs.
* Usage
In the off chance you're crazy enough to give this a shot, you can
either download the file and add it to your load-path, or use this
MELPA-flavor recipe:
#+BEGIN_SRC emacs-lisp
'(nyaatouch :repo "https://github.com/eshrh/nyaatouch" :fetcher github)
#+END_SRC
You can give that list to straight-use-package or whatever other
program you may use. Then, usage is just:
#+BEGIN_SRC emacs-lisp
(require 'nyaatouch)
(turn-on-nyaatouch)
#+END_SRC
=turn-off-nyaatouch= also exists and may be of interest.