├── README.org ├── autoload ├── bindings-colemak.el ├── bindings-dvorak.el ├── bindings-dvp.el ├── bindings-qwerty.el ├── bindings-qwertz.el ├── meow-cursor.el └── meow-escape.el ├── config.el └── packages.el /README.org: -------------------------------------------------------------------------------- 1 | #+title: :editor meow 2 | #+subtitle: lightweight, modern modal editing 3 | #+created: May 19, 2024 4 | #+since: whenever v3 happens 5 | 6 | * Description :unfold: 7 | 8 | This module integrates [[https://github.com/meow-edit/meow][Meow]] with Doom Emacs. 9 | 10 | The integration consists of: 11 | 12 | - A 'port' of Doom's (emacs) leader and localleader bindings to Meow's Keypad state; 13 | 14 | - A cursor configuration that uses the 'bar' cursor shape to indicate the way 15 | Emacs' cursor positioning differs from other modal editors, with 16 | ~cursor-blink-mode~ rather than a shape change to indicate a switch to Insert 17 | state; 18 | 19 | - A custom =emacs= Meow state with minimal bindings, intended for modes that use 20 | the keys bound in Motion state, and as a means of demonstrating the process of 21 | defining a custom state; 22 | 23 | - Numerous other tweaks, including to the suggested bindings, to integrate with 24 | Doom better. 25 | 26 | It is recommended to read [[https://github.com/meow-edit/meow/blob/master/README.org][Meow's README]] prior to trying this module. 27 | 28 | #+begin_quote 29 | Meow is designed as a minimal, dependency-free modal 'layer' on top of Emacs, 30 | preferring to leverage built-in functionality rather than reinventing the wheel. 31 | If it seems to be 'missing' a feature present in another modal system, it may be 32 | because the equivalent Emacs functionality is considered usable enough not to 33 | warrant a Meow-flavored reimplementation. Accordingly, it is suggested to become 34 | familiar with Emacs' basic concepts and features, at least up to the level 35 | taught in the Tutorial (=M-x help-with-tutorial=). 36 | #+end_quote 37 | 38 | ** Module flags 39 | - +qwerty, +qwertz, +dvorak, +dvp, +colemak :: Set up Meow's suggested bindings 40 | for the respective layouts. If you don't use any of these flags, you will need 41 | to set up bindings yourself; see [[https://github.com/meow-edit/meow/blob/master/GET_STARTED.org#set-up-command-layout][the relevant docs]]. 42 | 43 | You will probably want to look at the files responsible for defining the 44 | bindings (in this module's =autoload/= directory) in order to be aware of any 45 | tweaks applied by this module. If the reason for a tweak is not documented in 46 | its respective file, it probably is in =+qwerty=. 47 | 48 | ** Packages 49 | - [[doom-package:meow]] 50 | 51 | ** Hacks 52 | - The localleader bindings are accomplished via a hack. 53 | 54 | ** TODO Changelog 55 | # This section will be machine generated. Don't edit it by hand. 56 | /This module does not have a changelog yet./ 57 | 58 | * Installation 59 | 60 | #+begin_src sh 61 | mkdir -p ~/.config/doom/modules/editor # or ~/.doom.d/modules/editor, if your Doom config is in ~/.doom.d 62 | cd $_ # change working directory to the one above 63 | git clone https://github.com/meow-edit/doom-meow meow 64 | #+end_src 65 | 66 | [[id:01cffea4-3329-45e2-a892-95a384ab2338][Enable this module in your ~doom!~ block.]] 67 | (add =(meow +your-desired-flags...)= after the =:editor= section in =init.el=) 68 | 69 | After you ~doom sync~ and restart Emacs, Meow will start in Normal state, so 70 | make sure that bindings have been set up; see [[*Module flags][Module flags]]. 71 | 72 | The leader and localleader bindings are defined in [[doom-module::config default 73 | +bindings]], so that module is required for them to work. 74 | 75 | This module will not work smoothly with [[doom-module::editor evil]], 76 | [[doom-module::editor god]], or [[doom-module::editor objed]]. You must disable those 77 | modules in your ~doom!~ block to use this one. 78 | 79 | * TODO Usage 80 | #+begin_quote 81 | 󱌣 /This module's usage documentation is incomplete./ [[doom-contrib-module:][Complete it?]] 82 | #+end_quote 83 | 84 | Please refer to [[https://github.com/meow-edit/meow/blob/master/README.org][Meow's docs]] for any information not related to Doom or this 85 | module. 86 | 87 | ** Leader and localleader integration 88 | 89 | This module configures Meow's Keypad state such that it can be used to access 90 | Doom's leader/localleader bindings, as set up by [[doom-module::config default 91 | +bindings]]. Note that since this module cannot be used with Evil, you'll be using 92 | Doom's Emacs leader/localleader bindings 93 | ([[emacsdir:modules/config/default/+emacs-bindings.el]]), which are not the same as 94 | its Evil ones. 95 | 96 | As described [[https://github.com/meow-edit/meow/blob/master/TUTORIAL.org#keypad][in Meow's documentation]], when a key other than =x= / =h= / =c= / 97 | =m= / =g= is pressed in Keypad state, it is directly looked up in the leader 98 | keymap. This module sets =doom-leader-map= (bound to =C-c= by default) as the 99 | leader keymap. So, for example, =SPC s p= produces =C-c s p=. 100 | 101 | Some tweaks were necessary in order to accomodate the differences of Keypad state - 102 | 103 | - ~doom-leader-code-map~ is bound to =k=, as =c= is taken by Keypad. 104 | 105 | - Localleader is bound to =l=, as =m= is taken. 106 | 107 | * Configuration 108 | 109 | ** Cursor 110 | 111 | In Emacs, the cursor is always considered to be located /between/ two 112 | characters. In Vim, the cursor is always considered to be /on top of/ a 113 | character. Evil manages to accomplish the latter behavior, but Meow [[https://github.com/meow-edit/meow/discussions/87#discussion-3721642][does not 114 | attempt]] to do so. In order to help Evil/Vim users adjust, this module includes a 115 | custom cursor configuration - 116 | 117 | - The 'bar' cursor shape is used in most cases, as it sits between two 118 | characters. 119 | You can change this by setting any of the ~meow-cursor-type-*~ variables. 120 | 121 | - Since we don't use the block cursor shape to indicate Normal state, we instead 122 | blink the cursor to indicate when we're in Insert state. 123 | You can disable this by setting ~+meow-want-blink-cursor-in-insert~ to ~nil~. 124 | 125 | ** Disabling bindings for certain modes 126 | 127 | In modes that bind unmodified keys, Meow starts in 'Motion' state. The default 128 | bindings for Motion state (with =+qwerty=) bind =j= and =k= to ~next-line~ and 129 | ~previous-line~, respectively; and =SPC= triggers Keypad state. This is only 130 | useful in modes where moving over lines is a meaningful concept, and =SPC= 131 | doesn't have an important binding. 132 | 133 | For modes that don't fit the above description, this module defines a custom 134 | 'Emacs' state. This state has only two bindings - =M-SPC= to trigger Keypad 135 | (this binding is also added in Insert state), and =C-]= to switch to Motion 136 | state. Once in Motion state, you can use =C-]= to switch to Meow's 'temp Normal' 137 | state if you need more of Meow's bindings. 138 | 139 | For example, to make ~pdf-view-mode~ start in Emacs state: 140 | #+begin_src emacs-lisp 141 | ;; in $DOOMDIR/config.el 142 | (add-to-list 'meow-mode-state-list '(pdf-view-mode . emacs)) 143 | #+end_src 144 | 145 | ** Disabling expansion hints for some modes 146 | 147 | The expansion hints are known to work poorly with variable-width fonts (see [[https://github.com/meow-edit/meow/issues/110][this 148 | issue]]). If you encounter this problem, you should disable them for the modes in 149 | which you use those fonts - 150 | #+begin_src emacs-lisp 151 | ;; in $DOOMDIR/config.el 152 | ;; For example, to disable expansion hints in org-mode - 153 | (add-to-list 'meow-expand-exclude-mode-list 'org-mode) 154 | #+end_src 155 | 156 | 157 | ** ~map!~ vs ~meow-define-keys~ 158 | 159 | Doom's ~map!~ and Meow's ~meow-define-keys~ are largely equivalent in terms of 160 | functionality. ~(map! :map meow-normal-state-keymap ...)~ and ~(meow-define-keys 161 | 'normal ...)~ (and ~(meow-normal-define-keys ...)~) will do the same thing, as 162 | far as this author is aware. 163 | 164 | There is one exception - when binding a key to another key, ~meow-define-keys~ 165 | generates a command to execute that key, and binds to that. ~map!~ doesn't 166 | explicitly support binding a key to another key, and when you try it, it binds 167 | the key directly without a command wrapping it. This binding seems to get 168 | overridden by any command bound to the same key. 169 | 170 | * Troubleshooting 171 | [[doom-report:][Report an issue?]] 172 | 173 | ** Prefix key descriptions in =which-key= popup 174 | These do not show up properly when Keypad state is used. It is unclear where to 175 | look for the source of the problem. The previous module also had [[https://github.com/meow-edit/doom-meow-archive/issues/5][this issue]]. 176 | 177 | ** Undo and [[doom-package:undo-fu]] 178 | Meow's ~meow-undo~ expects the command bound to ~meow--kbd-undo~ (default =C-/=) 179 | to behave like Emacs' built-in ~undo~ command. Undo-Fu remaps this command to 180 | ~undo-fu-only-undo~, which behaves differently, so ~meow-undo~ doesn't work 181 | properly. Currently, the only workaround is to stop using Undo-Fu and learn 182 | Emacs' default undo mechanism: 183 | #+begin_src emacs-lisp 184 | ;; In $DOOMDIR/packages.el 185 | (package! undo-fu :disable t) 186 | #+end_src 187 | 188 | * Frequently asked questions 189 | 190 | ** Mode-specific/state-specific Meow bindings 191 | Unlike Evil, Meow does not directly support keybindings specific to a particular 192 | mode or state. For example, there is no (direct) way to make =TAB= do one thing 193 | in =org-mode= and another in =emacs-lisp-mode=. This is an intentional 194 | limitation; see [[https://github.com/meow-edit/meow/pull/126#issuecomment-992004368][this issue comment]] for a discussion, and the recommended way of 195 | achieving this kind of functionality. 196 | 197 | 198 | * TODO Appendix 199 | #+begin_quote 200 | 󱌣 This module has no appendix yet. [[doom-contrib-module:][Write one?]] 201 | #+end_quote 202 | -------------------------------------------------------------------------------- /autoload/bindings-colemak.el: -------------------------------------------------------------------------------- 1 | ;;; editor/meow/autoload/bindings-colemak.el -*- lexical-binding: t; -*- 2 | 3 | ;;;###autoload 4 | (defun +meow--setup-colemak () 5 | (setq meow-cheatsheet-layout meow-cheatsheet-layout-colemak) 6 | (meow-motion-overwrite-define-key 7 | ;; Use e to move up, n to move down. 8 | ;; Since special modes usually use n to move down, we only overwrite e here. 9 | '("e" . previous-line) 10 | '("" . ignore)) 11 | (meow-leader-define-key 12 | '("?" . meow-cheatsheet) 13 | ;; To execute the originally e in MOTION state, use SPC e. 14 | '("e" . "C-e") 15 | '("1" . meow-digit-argument) 16 | '("2" . meow-digit-argument) 17 | '("3" . meow-digit-argument) 18 | '("4" . meow-digit-argument) 19 | '("5" . meow-digit-argument) 20 | '("6" . meow-digit-argument) 21 | '("7" . meow-digit-argument) 22 | '("8" . meow-digit-argument) 23 | '("9" . meow-digit-argument) 24 | '("0" . meow-digit-argument)) 25 | (meow-normal-define-key 26 | '("0" . meow-expand-0) 27 | '("1" . meow-expand-1) 28 | '("2" . meow-expand-2) 29 | '("3" . meow-expand-3) 30 | '("4" . meow-expand-4) 31 | '("5" . meow-expand-5) 32 | '("6" . meow-expand-6) 33 | '("7" . meow-expand-7) 34 | '("8" . meow-expand-8) 35 | '("9" . meow-expand-9) 36 | '("-" . negative-argument) 37 | '(";" . meow-reverse) 38 | '("," . meow-inner-of-thing) 39 | '("." . meow-bounds-of-thing) 40 | '("[" . meow-beginning-of-thing) 41 | '("]" . meow-end-of-thing) 42 | '("/" . meow-visit) 43 | '("a" . meow-append) 44 | '("A" . meow-open-below) 45 | '("b" . meow-back-word) 46 | '("B" . meow-back-symbol) 47 | '("c" . meow-change) 48 | '("d" . meow-delete) 49 | '("e" . meow-prev) 50 | '("E" . meow-prev-expand) 51 | '("f" . meow-find) 52 | '("g" . meow-cancel-selection) 53 | '("G" . meow-grab) 54 | '("h" . meow-left) 55 | '("H" . meow-left-expand) 56 | '("i" . meow-right) 57 | '("I" . meow-right-expand) 58 | '("j" . meow-join) 59 | '("k" . meow-kill) 60 | '("l" . meow-line) 61 | '("L" . meow-goto-line) 62 | '("m" . meow-mark-word) 63 | '("M" . meow-mark-symbol) 64 | '("n" . meow-next) 65 | '("N" . meow-next-expand) 66 | '("o" . meow-block) 67 | '("O" . meow-to-block) 68 | '("p" . meow-yank) 69 | '("P" . meow-yank-pop) 70 | '("q" . nil) 71 | '("r" . meow-replace) 72 | '("s" . meow-insert) 73 | '("S" . meow-open-above) 74 | '("t" . meow-till) 75 | '("u" . meow-undo) 76 | '("U" . meow-undo-in-selection) 77 | '("v" . meow-search) 78 | '("w" . meow-next-word) 79 | '("W" . meow-next-symbol) 80 | '("x" . meow-delete) 81 | '("X" . meow-backward-delete) 82 | '("y" . meow-save) 83 | '("z" . meow-pop-selection) 84 | '("'" . repeat) 85 | '("" . ignore))) 86 | -------------------------------------------------------------------------------- /autoload/bindings-dvorak.el: -------------------------------------------------------------------------------- 1 | ;;; editor/meow/autoload/bindings-dvorak.el -*- lexical-binding: t; -*- 2 | 3 | ;;;###autoload 4 | (defun +meow--setup-dvorak () 5 | (setq meow-cheatsheet-layout meow-cheatsheet-layout-dvorak) 6 | (meow-leader-define-key 7 | '("1" . meow-digit-argument) 8 | '("2" . meow-digit-argument) 9 | '("3" . meow-digit-argument) 10 | '("4" . meow-digit-argument) 11 | '("5" . meow-digit-argument) 12 | '("6" . meow-digit-argument) 13 | '("7" . meow-digit-argument) 14 | '("8" . meow-digit-argument) 15 | '("9" . meow-digit-argument) 16 | '("0" . meow-digit-argument) 17 | '("/" . meow-keypad-describe-key) 18 | '("?" . meow-cheatsheet)) 19 | (meow-motion-overwrite-define-key 20 | ;; custom keybinding for motion state 21 | '("" . ignore)) 22 | (meow-normal-define-key 23 | '("0" . meow-expand-0) 24 | '("9" . meow-expand-9) 25 | '("8" . meow-expand-8) 26 | '("7" . meow-expand-7) 27 | '("6" . meow-expand-6) 28 | '("5" . meow-expand-5) 29 | '("4" . meow-expand-4) 30 | '("3" . meow-expand-3) 31 | '("2" . meow-expand-2) 32 | '("1" . meow-expand-1) 33 | '("-" . negative-argument) 34 | '(";" . meow-reverse) 35 | '("," . meow-inner-of-thing) 36 | '("." . meow-bounds-of-thing) 37 | '("<" . meow-beginning-of-thing) 38 | '(">" . meow-end-of-thing) 39 | '("a" . meow-append) 40 | '("A" . meow-open-below) 41 | '("b" . meow-back-word) 42 | '("B" . meow-back-symbol) 43 | '("c" . meow-change) 44 | '("d" . meow-delete) 45 | '("D" . meow-backward-delete) 46 | '("e" . meow-line) 47 | '("E" . meow-goto-line) 48 | '("f" . meow-find) 49 | '("g" . meow-cancel-selection) 50 | '("G" . meow-grab) 51 | '("h" . meow-left) 52 | '("H" . meow-left-expand) 53 | '("i" . meow-insert) 54 | '("I" . meow-open-above) 55 | '("j" . meow-join) 56 | '("k" . meow-kill) 57 | '("l" . meow-till) 58 | '("m" . meow-mark-word) 59 | '("M" . meow-mark-symbol) 60 | '("n" . meow-next) 61 | '("N" . meow-next-expand) 62 | '("o" . meow-block) 63 | '("O" . meow-to-block) 64 | '("p" . meow-prev) 65 | '("P" . meow-prev-expand) 66 | '("q" . nil) 67 | '("Q" . meow-goto-line) 68 | '("r" . meow-replace) 69 | '("R" . meow-swap-grab) 70 | '("s" . meow-search) 71 | '("t" . meow-right) 72 | '("T" . meow-right-expand) 73 | '("u" . meow-undo) 74 | '("U" . meow-undo-in-selection) 75 | '("v" . meow-visit) 76 | '("w" . meow-next-word) 77 | '("W" . meow-next-symbol) 78 | '("x" . meow-save) 79 | '("X" . meow-sync-grab) 80 | '("y" . meow-yank) 81 | '("z" . meow-pop-selection) 82 | '("'" . repeat) 83 | '("" . ignore))) 84 | -------------------------------------------------------------------------------- /autoload/bindings-dvp.el: -------------------------------------------------------------------------------- 1 | ;;; editor/meow/autoload/bindings-dvp.el -*- lexical-binding: t; -*- 2 | 3 | ;;;###autoload 4 | (defun +meow--setup-dvp () 5 | (setq meow-cheatsheet-layout meow-cheatsheet-layout-dvp) 6 | (meow-leader-define-key 7 | '("?" . meow-cheatsheet)) 8 | (meow-motion-overwrite-define-key 9 | ;; custom keybinding for motion state 10 | '("" . ignore)) 11 | (meow-normal-define-key 12 | '("?" . meow-cheatsheet) 13 | '("*" . meow-expand-0) 14 | '("=" . meow-expand-9) 15 | '("!" . meow-expand-8) 16 | '("[" . meow-expand-7) 17 | '("]" . meow-expand-6) 18 | '("{" . meow-expand-5) 19 | '("+" . meow-expand-4) 20 | '("}" . meow-expand-3) 21 | '(")" . meow-expand-2) 22 | '("(" . meow-expand-1) 23 | '("1" . digit-argument) 24 | '("2" . digit-argument) 25 | '("3" . digit-argument) 26 | '("4" . digit-argument) 27 | '("5" . digit-argument) 28 | '("6" . digit-argument) 29 | '("7" . digit-argument) 30 | '("8" . digit-argument) 31 | '("9" . digit-argument) 32 | '("0" . digit-argument) 33 | '("-" . negative-argument) 34 | '(";" . meow-reverse) 35 | '("," . meow-inner-of-thing) 36 | '("." . meow-bounds-of-thing) 37 | '("<" . meow-beginning-of-thing) 38 | '(">" . meow-end-of-thing) 39 | '("a" . meow-append) 40 | '("A" . meow-open-below) 41 | '("b" . meow-back-word) 42 | '("B" . meow-back-symbol) 43 | '("c" . meow-change) 44 | '("d" . meow-delete) 45 | '("D" . meow-backward-delete) 46 | '("e" . meow-line) 47 | '("E" . meow-goto-line) 48 | '("f" . meow-find) 49 | '("g" . meow-cancel-selection) 50 | '("G" . meow-grab) 51 | '("h" . meow-left) 52 | '("H" . meow-left-expand) 53 | '("i" . meow-insert) 54 | '("I" . meow-open-above) 55 | '("j" . meow-join) 56 | '("k" . meow-kill) 57 | '("l" . meow-till) 58 | '("m" . meow-mark-word) 59 | '("M" . meow-mark-symbol) 60 | '("n" . meow-next) 61 | '("N" . meow-next-expand) 62 | '("o" . meow-block) 63 | '("O" . meow-to-block) 64 | '("p" . meow-prev) 65 | '("P" . meow-prev-expand) 66 | '("q" . nil) 67 | '("r" . meow-replace) 68 | '("R" . meow-swap-grab) 69 | '("s" . meow-search) 70 | '("t" . meow-right) 71 | '("T" . meow-right-expand) 72 | '("u" . meow-undo) 73 | '("U" . meow-undo-in-selection) 74 | '("v" . meow-visit) 75 | '("w" . meow-next-word) 76 | '("W" . meow-next-symbol) 77 | '("x" . meow-save) 78 | '("X" . meow-sync-grab) 79 | '("y" . meow-yank) 80 | '("z" . meow-pop-selection) 81 | '("'" . repeat) 82 | '("" . ignore))) 83 | -------------------------------------------------------------------------------- /autoload/bindings-qwerty.el: -------------------------------------------------------------------------------- 1 | ;;; editor/meow/autoload/bindings-qwerty.el -*- lexical-binding: t; -*- 2 | 3 | ;;;###autoload 4 | (defun +meow--setup-qwerty () 5 | (setq meow-cheatsheet-layout meow-cheatsheet-layout-qwerty) 6 | (meow-motion-overwrite-define-key 7 | ;; 'j' and 'k' are suggested to be bound to `meow-next' and `meow-prev', but 8 | ;; these deactivate the region, which is not helpful unless we're in normal 9 | ;; state. 10 | ;; TODO PR in suggested bindings 11 | '("j" . next-line) 12 | '("k" . previous-line) 13 | '("" . ignore)) 14 | (meow-leader-define-key 15 | ;; ;; The suggested bindings would have allowed us to use 'SPC j' and 'SPC k' 16 | ;; ;; to run whatever commands were originally mapped to 'j' and 'k' while in 17 | ;; ;; Motion state. But our bindings make SPC k the prefix for 18 | ;; ;; `doom-leader-code-map', so that won't work. Nevertheless, we leave 19 | ;; ;; those bindings here anyway. 20 | ;; SPC j/k will run the original command in MOTION state 21 | ;; (because we set `meow-motion-remap-prefix' to "C-") 22 | '("j" . "C-j") 23 | '("k" . "C-k") 24 | ;; Use SPC (0-9) for digit arguments. 25 | '("1" . meow-digit-argument) 26 | '("2" . meow-digit-argument) 27 | '("3" . meow-digit-argument) 28 | '("4" . meow-digit-argument) 29 | '("5" . meow-digit-argument) 30 | '("6" . meow-digit-argument) 31 | '("7" . meow-digit-argument) 32 | '("8" . meow-digit-argument) 33 | '("9" . meow-digit-argument) 34 | '("0" . meow-digit-argument) 35 | '("/" . meow-keypad-describe-key) 36 | '("?" . meow-cheatsheet)) 37 | (meow-normal-define-key 38 | '("0" . meow-expand-0) 39 | '("9" . meow-expand-9) 40 | '("8" . meow-expand-8) 41 | '("7" . meow-expand-7) 42 | '("6" . meow-expand-6) 43 | '("5" . meow-expand-5) 44 | '("4" . meow-expand-4) 45 | '("3" . meow-expand-3) 46 | '("2" . meow-expand-2) 47 | '("1" . meow-expand-1) 48 | '("-" . negative-argument) 49 | '(";" . meow-reverse) 50 | '("," . meow-inner-of-thing) 51 | '("." . meow-bounds-of-thing) 52 | '("[" . meow-beginning-of-thing) 53 | '("]" . meow-end-of-thing) 54 | '("a" . meow-append) 55 | '("A" . meow-open-below) 56 | '("b" . meow-back-word) 57 | '("B" . meow-back-symbol) 58 | '("c" . meow-change) 59 | '("d" . meow-delete) 60 | '("D" . meow-backward-delete) 61 | '("e" . meow-next-word) 62 | '("E" . meow-next-symbol) 63 | '("f" . meow-find) 64 | '("g" . meow-cancel-selection) 65 | '("G" . meow-grab) 66 | '("h" . meow-left) 67 | '("H" . meow-left-expand) 68 | '("i" . meow-insert) 69 | '("I" . meow-open-above) 70 | '("j" . meow-next) 71 | '("J" . meow-next-expand) 72 | '("k" . meow-prev) 73 | '("K" . meow-prev-expand) 74 | '("l" . meow-right) 75 | '("L" . meow-right-expand) 76 | '("m" . meow-join) 77 | '("n" . meow-search) 78 | '("o" . meow-block) 79 | '("O" . meow-to-block) 80 | '("p" . meow-yank) 81 | ;; `yank-pop' is pretty essential, and 'P' is convenient and not used. 82 | ;; TODO PR in suggested bindings 83 | '("P" . meow-yank-pop) 84 | ;; Integrate with Doom's popup system instead of calling `meow-quit'. 85 | '("q" . nil) 86 | '("Q" . meow-goto-line) 87 | '("r" . meow-replace) 88 | '("R" . meow-swap-grab) 89 | '("s" . meow-kill) 90 | '("t" . meow-till) 91 | '("u" . meow-undo) 92 | '("U" . meow-undo-in-selection) 93 | '("v" . meow-visit) 94 | '("w" . meow-mark-word) 95 | '("W" . meow-mark-symbol) 96 | '("x" . meow-line) 97 | '("X" . meow-goto-line) 98 | '("y" . meow-save) 99 | '("Y" . meow-sync-grab) 100 | '("z" . meow-pop-selection) 101 | '("'" . repeat) 102 | '("" . ignore))) 103 | -------------------------------------------------------------------------------- /autoload/bindings-qwertz.el: -------------------------------------------------------------------------------- 1 | ;;; editor/meow/autoload/bindings-qwertz.el -*- lexical-binding: t; -*- 2 | 3 | ;;;###autoload 4 | (defun +meow--setup-qwertz () 5 | (setq meow-cheatsheet-physical-layout meow-cheatsheet-physical-layout-iso) 6 | (setq meow-cheatsheet-layout meow-cheatsheet-layout-qwertz) 7 | 8 | (meow-thing-register 'angle 9 | '(pair (";") (":")) 10 | '(pair (";") (":"))) 11 | 12 | (setq meow-char-thing-table 13 | '((?f . round) 14 | (?d . square) 15 | (?s . curly) 16 | (?a . angle) 17 | (?r . string) 18 | (?v . paragraph) 19 | (?c . line) 20 | (?x . buffer))) 21 | 22 | (meow-leader-define-key 23 | ;; Use SPC (0-9) for digit arguments. 24 | '("1" . meow-digit-argument) 25 | '("2" . meow-digit-argument) 26 | '("3" . meow-digit-argument) 27 | '("4" . meow-digit-argument) 28 | '("5" . meow-digit-argument) 29 | '("6" . meow-digit-argument) 30 | '("7" . meow-digit-argument) 31 | '("8" . meow-digit-argument) 32 | '("9" . meow-digit-argument) 33 | '("0" . meow-digit-argument) 34 | '("-" . meow-keypad-describe-key) 35 | '("_" . meow-cheatsheet)) 36 | 37 | (meow-normal-define-key 38 | ;; expansion 39 | '("0" . meow-expand-0) 40 | '("1" . meow-expand-1) 41 | '("2" . meow-expand-2) 42 | '("3" . meow-expand-3) 43 | '("4" . meow-expand-4) 44 | '("5" . meow-expand-5) 45 | '("6" . meow-expand-6) 46 | '("7" . meow-expand-7) 47 | '("8" . meow-expand-8) 48 | '("9" . meow-expand-9) 49 | '("ä" . meow-reverse) 50 | 51 | ;; movement 52 | '("i" . meow-prev) 53 | '("k" . meow-next) 54 | '("j" . meow-left) 55 | '("l" . meow-right) 56 | 57 | '("z" . meow-search) 58 | '("-" . meow-visit) 59 | 60 | ;; expansion 61 | '("I" . meow-prev-expand) 62 | '("K" . meow-next-expand) 63 | '("J" . meow-left-expand) 64 | '("L" . meow-right-expand) 65 | 66 | '("u" . meow-back-word) 67 | '("U" . meow-back-symbol) 68 | '("o" . meow-next-word) 69 | '("O" . meow-next-symbol) 70 | 71 | '("a" . meow-mark-word) 72 | '("A" . meow-mark-symbol) 73 | '("s" . meow-line) 74 | '("S" . meow-goto-line) 75 | '("w" . meow-block) 76 | '("q" . meow-join) 77 | '("g" . meow-grab) 78 | '("G" . meow-pop-grab) 79 | '("m" . meow-swap-grab) 80 | '("M" . meow-sync-grab) 81 | '("p" . meow-cancel-selection) 82 | '("P" . meow-pop-selection) 83 | 84 | '("x" . meow-till) 85 | '("y" . meow-find) 86 | 87 | '("," . meow-beginning-of-thing) 88 | '("." . meow-end-of-thing) 89 | '(";" . meow-inner-of-thing) 90 | '(":" . meow-bounds-of-thing) 91 | 92 | ;; editing 93 | '("d" . meow-kill) 94 | '("f" . meow-change) 95 | '("t" . meow-delete) 96 | '("c" . meow-save) 97 | '("v" . meow-yank) 98 | '("V" . meow-yank-pop) 99 | 100 | '("e" . meow-insert) 101 | '("E" . meow-open-above) 102 | '("r" . meow-append) 103 | '("R" . meow-open-below) 104 | 105 | '("h" . undo-only) 106 | '("H" . undo-redo) 107 | 108 | '("b" . open-line) 109 | '("B" . split-line) 110 | 111 | '("ü" . indent-rigidly-left-to-tab-stop) 112 | '("+" . indent-rigidly-right-to-tab-stop) 113 | 114 | ;; ignore escape 115 | '("" . ignore))) 116 | -------------------------------------------------------------------------------- /autoload/meow-cursor.el: -------------------------------------------------------------------------------- 1 | ;;; editor/meow/autoload/meow-cursor.el -*- lexical-binding: t; -*- 2 | 3 | ;;;###autoload 4 | (defun +meow-maybe-toggle-cursor-blink (&rest _) 5 | "Turn cursor blink on if in insert state, off otherwise." 6 | (when +meow-want-blink-cursor-in-insert 7 | (if (meow-insert-mode-p) 8 | (blink-cursor-mode +1) 9 | (blink-cursor-mode -1)))) 10 | -------------------------------------------------------------------------------- /autoload/meow-escape.el: -------------------------------------------------------------------------------- 1 | ;;; editor/meow/autoload/meow-escape.el -*- lexical-binding: t; -*- 2 | 3 | ;;;###autoload 4 | (defun +meow-escape () 5 | "Call `meow-cancel-selection', else fallback to `doom/escape'." 6 | (interactive) 7 | (if (region-active-p) 8 | (meow-cancel-selection) 9 | (call-interactively #'doom/escape))) 10 | -------------------------------------------------------------------------------- /config.el: -------------------------------------------------------------------------------- 1 | ;;; editor/meow/config.el -*- lexical-binding: t; -*- 2 | 3 | (use-package! meow 4 | 5 | ;;; Loading 6 | 7 | ;; Eager-load Meow, so that if there are errors later in our config, at least 8 | ;; we have Meow set up to fix them. 9 | :demand t 10 | 11 | ;; Enable after modules have loaded. 12 | :hook (doom-after-modules-config . meow-global-mode) 13 | 14 | :init 15 | 16 | ;;; `meow-motion-remap-prefix' 17 | 18 | ;; Rebind all keys shadowed by Meow's Motion state to 'C-'. 19 | ;; Different from the Meow default 'H-', because how many users actually 20 | ;; have that key on their keyboard? 21 | ;; 'C-j' and 'C-k' are unlikely to be rebound by any modes as they're basic 22 | ;; editing keys. 'C-]' can't be remapped under the 'C-' prefix, but it's 23 | ;; unlikely that any mode will shadow `abort-recursive-edit'. 24 | (setq meow-motion-remap-prefix "C-") 25 | 26 | :config 27 | 28 | ;;; Cursor configuration 29 | 30 | ;; In Emacs, unlike Evil, the cursor is /between/ two characters, not on top 31 | ;; of a character. Since this module will likely attract a lot of Evil users, 32 | ;; use the 'bar' cursor shape instead of the default 'block' to reflect this 33 | ;; fact. 34 | ;; In addition, blink the cursor in insert state. 35 | 36 | (defvar +meow-want-blink-cursor-in-insert t 37 | "Whether `blink-cursor-mode' should be enabled in INSERT state.") 38 | 39 | (setq meow-cursor-type-normal 'bar 40 | meow-cursor-type-insert 'bar 41 | meow-cursor-type-beacon 'bar 42 | meow-cursor-type-default 'box 43 | blink-cursor-delay 0 ; start blinking immediately 44 | blink-cursor-blinks 0 ; blink forever 45 | blink-cursor-interval 0.15) ; blink time period 46 | 47 | ;; Toggle blink on entering/exiting insert mode 48 | (add-hook 'meow-insert-mode-hook #'+meow-maybe-toggle-cursor-blink) 49 | 50 | ;; When we switch windows, the window we switch to may be in a different state 51 | ;; than the previous one 52 | (advice-add #'meow--on-window-state-change 53 | :after #'+meow-maybe-toggle-cursor-blink) 54 | 55 | ;;; Continuing commented lines 56 | 57 | ;; Since `meow-open-below' just runs `newline-and-indent', it will perform 58 | ;; Doom's behavior of continuing commented lines (if 59 | ;; `+default-want-RET-continue-comments' is non-nil). Prevent this. 60 | (defvar +meow-want-meow-open-below-continue-comments nil 61 | "If non-nil `meow-open-below' will continue commented lines.") 62 | 63 | (defadvice! +meow--newline-indent-and-continue-comments-a (&rest _) 64 | "Support `+meow-want-meow-open-below-continue-comments'. 65 | Doom uses `+default--newline-indent-and-continue-comments-a' to continue 66 | comments. Prevent that from running if necessary." 67 | :before-while #'+default--newline-indent-and-continue-comments-a 68 | (interactive "*") 69 | (if (eq real-this-command #'meow-open-below) 70 | +meow-want-meow-open-below-continue-comments 71 | t)) 72 | 73 | 74 | ;;; Expansion hints 75 | ;; These should not be disabled anywhere by default; if users find that they 76 | ;; cause problems due to variable-width fonts etc., they can configure this 77 | ;; variable themselves. 78 | (setq meow-expand-exclude-mode-list nil) 79 | 80 | 81 | ;;; Alternate states 82 | 83 | ;; Use a consistent key for exiting EMACS state and `meow-temp-normal'. 84 | ;; We use 'C-]' as our binding to toggle this state, both in Motion and Emacs 85 | ;; states. This binding was chosen based on the notion that it is rare to use 86 | ;; its default binding `abort-recursive-edit'. It is rare to encounter 87 | ;; recursive editing levels outside the minibuffer, and that specific case is 88 | ;; handled by `doom/escape'. 89 | ;; If it is really needed, `abort-recursive-edit' is also bound to `C-x X a'. 90 | 91 | (defvar +meow-alternate-state-key "C-]" 92 | "Key to switch to an alternate state in Meow. 93 | - Invoke `meow-temp-normal' in Motion state 94 | - In EMACS state, return to previous/Motion state.") 95 | 96 | (meow-motion-overwrite-define-key 97 | (cons +meow-alternate-state-key #'meow-temp-normal)) 98 | 99 | ;;; Emacs state 100 | ;; Meow's Motion state, as configured by the suggested bindings, is mainly 101 | ;; useful in modes where moving the cursor between lines is meaningful, and 102 | ;; the mode doesn't bind SPC. For anything else, it tends to get in the way. 103 | ;; In such cases, it's best to configure our own bindings for the mode rather 104 | ;; than relying on Motion state. 105 | ;; In Meow, every mode starts in a particular state, defaulting to Motion. So, 106 | ;; if we want a mode to not have any Meow bindings, it needs to start in a 107 | ;; state without any bindings. 108 | ;; To this end, we define a custom EMACS state to switch to. This state will 109 | ;; have no bindings except one to switch back to the previous state (or to 110 | ;; Motion state if the buffer started in Emacs state), and a binding to invoke 111 | ;; Keypad state (we use M-SPC as it's unlikely to be bound by other modes, and 112 | ;; the default binding of `cycle-spacing' probably won't be relevant in the 113 | ;; special modes we're using this state for). 114 | 115 | (defvar +meow-emacs-state--previous nil 116 | "Meow state before switching to EMACS state.") 117 | 118 | (defface meow-emacs-cursor 119 | `((t (:inherit unspecified 120 | :background ,(face-foreground 'warning)))) 121 | "BEACON cursor face." 122 | :group 'meow) 123 | 124 | (defvar meow-emacs-state-keymap 125 | (let ((map (make-sparse-keymap))) 126 | (define-key map (kbd +meow-alternate-state-key) #'+meow-toggle-emacs-state) 127 | (define-key map (kbd "M-SPC") #'meow-keypad) 128 | map) 129 | "Keymap for EMACS state. 130 | Should only contain `+meow-toggle-emacs-state'.") 131 | 132 | (meow-define-state emacs 133 | "Meow EMACS state minor mode. 134 | This is a custom state having no bindings except `+meow-toggle-emacs-state' and 135 | `meow-keypad'." 136 | :lighter " [E]" 137 | :keymap meow-emacs-state-keymap 138 | :face meow-emacs-cursor) 139 | 140 | (defun +meow-toggle-emacs-state () 141 | "Toggle EMACS state. 142 | If EMACS state was manually switched to via this command, switch back to the 143 | previous state. Otherwise, assume that the buffer started in EMACS state, and 144 | switch to MOTION state." 145 | (interactive) 146 | (if (meow-emacs-mode-p) 147 | (progn 148 | (meow--switch-state 149 | (or +meow-emacs-state--previous 'motion)) 150 | (setq +meow-emacs-state--previous nil)) 151 | (setq +meow-emacs-state--previous meow--current-state) 152 | (meow--switch-state 'emacs))) 153 | 154 | ;;; misc. settings 155 | 156 | ;; Wait for longer before removing the expansion hints. One second is too 157 | ;; short, especially for people using them for the first time. 158 | (setq meow-expand-hint-remove-delay 4.0) 159 | 160 | ;; Don't self-insert keypad-mode keys if they're undefined, in order to be 161 | ;; consistent with Emacs' standard behavior with undefined keys. 162 | (setq meow-keypad-self-insert-undefined nil) 163 | 164 | ;;; Bindings 165 | 166 | ;;;; Suggested bindings 167 | 168 | (cond ((modulep! +qwerty) (+meow--setup-qwerty)) 169 | ((modulep! +qwertz) (+meow--setup-qwertz)) 170 | ((modulep! +dvorak) (+meow--setup-dvorak)) 171 | ((modulep! +dvp) (+meow--setup-dvp)) 172 | ((modulep! +colemak) (+meow--setup-colemak)) 173 | (t nil)) 174 | 175 | ;;;; Doom leader/localleader 176 | 177 | ;; FIXME: When these are invoked via Keypad, the descriptions of prefixes are 178 | ;; not shown. This could be a Doom problem, a general.el problem, or a 179 | ;; `meow--which-key-describe-keymap' problem. 180 | (when (modulep! :config default +bindings) 181 | 182 | ;; Doom uses a complicated system involving `general-override-mode' to set 183 | ;; up its leader and localleader keys. I don't pretend to understand how it 184 | ;; works. But as far as I can tell, we can rely on it to work in the 185 | ;; following way - 186 | ;; `doom-leader-alt-key' (default 'C-c') is treated as the leader key when 187 | ;; Doom's emacs bindings are in use, and all leader keybindings should be 188 | ;; accessible under this key. 189 | ;; So we can simply tell Meow to prefix the Keypad key sequence with 'C-c', 190 | ;; and all leader key bindings should be accessible when Keypad is invoked. 191 | ;; With `meow-keypad' bound to 'SPC' as expected, this parallels the 192 | ;; behavior in :editor evil. 193 | (setq meow-keypad-leader-dispatch "C-c") 194 | 195 | ;; A minor tweak - 'SPC c' will translate to 'C-c' rather than invoking 196 | ;; `doom-leader-code-map'. So we must use another prefix key. 'k' was chosen 197 | ;; because it wasn't already in use, and because it makes 198 | ;; `+lookup/documentation', a very handy command, easy to invoke 199 | ;; ('SPC k k'). 200 | ;; (We need a hook since this module is loaded before the bindings are, due to ':demand') 201 | (add-hook! 'doom-after-modules-config-hook 202 | (defun +meow-leader-move-code-map-h () 203 | (when (boundp 'doom-leader-code-map) 204 | (define-key doom-leader-map "k" (cons "code" doom-leader-code-map)) 205 | ;; Unbind the 'c' prefix; we'll use it in our localleader hack. 206 | (define-key doom-leader-map "c" nil)))) 207 | 208 | ;; Also note that the Git commands are now under 'SPC v', unlike in 209 | ;; :editor evil. 210 | 211 | ;; Next, the localleader. For non-Evil users, this is invoked by 'C-c l'. 212 | ;; Since 'l' isn't used as a prefix in `doom-leader-map', we can use it as 213 | ;; the prefix for localleader. ('SPC m' would translate to 'M-' in Keypad 214 | ;; state, so we can't use it.) 215 | ;; I do not understand how Doom accomplishes the localleader bindings and do 216 | ;; not want to tangle with general.el, so we'll accomplish this with a HACK. 217 | ;; 218 | ;; Doom binds `doom-leader-map' under 'C-c' (the default value of 219 | ;; `doom-leader-alt-key'. Ideally we want to bind locallleader under this 220 | ;; prefix as well. Since we just freed up the 'c' prefix in 221 | ;; `doom-leader-map', we use that - 222 | (add-hook! 'doom-after-modules-config-hook 223 | (defun +meow-set-localleader-alt-key-h () 224 | (setq doom-localleader-alt-key "C-c c"))) 225 | ;; 226 | ;; Then, we define a command that calls 'C-c c', and bind it to 'l': 227 | (define-key doom-leader-map "l" 228 | (cons "+localleader" (cmd! (meow--execute-kbd-macro "C-c c")))) 229 | ;; ...and now the localleader bindings are accessible with 'SPC l' (or with 230 | ;; 'SPC c SPC c', for that matter). 231 | ) 232 | 233 | ;;;; Layout-independent Rebindings 234 | 235 | ;;;;; Keypad 236 | 237 | ;;;;;; SPC u -> C-u 238 | ;; Like in Doom's evil config. 239 | (define-key doom-leader-map "u" #'meow-universal-argument) 240 | 241 | ;;;;; 'M-SPC' 242 | 243 | ;; As in our EMACS state, make 'M-SPC' trigger the leader-key bindings in 244 | ;; Insert state. 245 | (meow-define-keys 'insert '("M-SPC" . meow-keypad)) 246 | 247 | ;;;;; `+meow-escape' 248 | 249 | ;; By default, ESC does nothing in Meow normal state (bound to `ignore'). But 250 | ;; we need to run `doom-escape-hook' for things like :ui popup to function as 251 | ;; expected. In addition, it makes sense to extend `doom/escape's incremental 252 | ;; behavior to Meow. 253 | ;; Hence, `+meow-escape' - a command that cancels the selection if it's 254 | ;; active, otherwise falling back to `doom/escape'. 255 | ;; This also has the nice effect of requiring one less normal-state 256 | ;; keybinding - `meow-cancel-selection' is no longer needed as this command 257 | ;; invokes it when necessary, so the user can rebind 'g' if they want. 258 | (meow-normal-define-key '("" . +meow-escape)) 259 | 260 | ;;;;; Esc in Motion state 261 | 262 | ;; Popups will be in Motion state, and Doom's popup management relies on 263 | ;; `doom-escape-hook'. So we can't have bound to `ignore'. 264 | (meow-motion-overwrite-define-key '("" . doom/escape)) 265 | 266 | ;;;; Emacs tutorial 267 | ;; It teaches the default bindings, so make it start in our Emacs state. 268 | (defadvice! +meow-emacs-tutorial-a (&rest _) 269 | :after #'help-with-tutorial 270 | (+meow-toggle-emacs-state) 271 | (insert 272 | (propertize 273 | "Meow: this Tutorial buffer has been started in Emacs state. Meow 274 | bindings are not active.\n\n" 275 | 'face 'warning)))) 276 | -------------------------------------------------------------------------------- /packages.el: -------------------------------------------------------------------------------- 1 | ;; -*- no-byte-compile: t; -*- 2 | ;;; completion/company/packages.el 3 | 4 | (package! meow) 5 | --------------------------------------------------------------------------------