Merge pull request #3754 from gagbo/feature/input-layout
Add support for bépo layout in a dedicated module
This commit is contained in:
commit
ed264dcdb2
5 changed files with 485 additions and 0 deletions
112
modules/input/layout/+bepo.el
Normal file
112
modules/input/layout/+bepo.el
Normal file
|
@ -0,0 +1,112 @@
|
|||
;;; input/layout/+bepo.el -*- lexical-binding: t; -*-
|
||||
|
||||
;; NOTE: the evaluation loads the whole autoload/bepo.el file but it doesn't really matter as other
|
||||
;; functions are eagerly called in this block
|
||||
;; NOTE: since this file is loaded before $DOOMDIR/config.el, the cr-rotation-style variable
|
||||
;; if not default needs to be set up in $DOOMDIR/init.el
|
||||
(fset 'doom-bepo--evil-collection-hook
|
||||
(doom-bepo-rotate-collection-keymaps-h-builder doom-bepo-cr-rotation-style))
|
||||
(add-hook 'evil-collection-setup-hook #'doom-bepo--evil-collection-hook)
|
||||
|
||||
;; Highlight non breaking spaces as error in prog modes only
|
||||
;; TODO: this variable is defined in a file called xdisp.c Will that work in non-X builds ?
|
||||
(setq nobreak-char-display t)
|
||||
(set-face-attribute 'nobreak-space nil :underline t)
|
||||
|
||||
(add-transient-hook! 'doom-init-modules-hook
|
||||
;; "ts" would be a little too common for an evil escape sequence
|
||||
(setq evil-escape-key-sequence "gq")
|
||||
(setq avy-keys '(?a ?u ?i ?e ?, ?c ?t ?s ?r ?n)
|
||||
lispy-avy-keys '(?a ?u ?i ?e ?, ?c ?t ?s ?r ?n ?m ?b ?é ?p ?o ?è ?v ?d ?l ?j ?z))
|
||||
;; :ui window-select settings, ignoring +numbers flag for now
|
||||
(after! ace-window
|
||||
(setq aw-keys '(?a ?u ?i ?e ?, ?c ?t ?s ?r ?n)))
|
||||
(after! switch-window
|
||||
(setq switch-window-shortcut-style 'qwerty
|
||||
switch-window-qwerty-shortcuts '("a" "u" "i" "e" "," "c" "t" "s" "r")))
|
||||
|
||||
(doom-bepo-rotate-ts-bare-keymap '(read-expression-map))
|
||||
(doom-bepo-rotate-bare-keymap '(evil-window-map) doom-bepo-cr-rotation-style)
|
||||
|
||||
(map! :i "C-t" #'+default-newline
|
||||
(:when (featurep! :editor multiple-cursors)
|
||||
:prefix "gz"
|
||||
:nv "t" #'evil-mc-make-cursor-move-next-line
|
||||
:nv "s" #'evil-mc-make-cursor-move-prev-line
|
||||
;; the old toggle mapping (t) is made available both on "T" for mnemonics and
|
||||
;; "j" as a "classic" rotation
|
||||
:nv "T" #'+multiple-cursors/evil-mc-toggle-cursors
|
||||
:nv "j" #'+multiple-cursors/evil-mc-toggle-cursors)
|
||||
(:when (featurep! :ui popup)
|
||||
:n "C-$" #'+popup/toggle
|
||||
:n "C-#" #'+popup/raise))
|
||||
(map!
|
||||
:leader
|
||||
:desc "Window" "é" 'evil-window-map
|
||||
(:when (featurep! :ui popup)
|
||||
:desc "Toggle last popup" "#" #'+popup/toggle)
|
||||
(:when (featurep! :ui workspaces)
|
||||
:desc "Switch buffer" "«" #'switch-to-buffer)
|
||||
:desc "Switch to last buffer" "$" #'evil-switch-to-windows-last-buffer
|
||||
(:when (featurep! :ui workspaces)
|
||||
(:prefix-map ("TAB" . "workspace")
|
||||
:desc "Switch to last workspace" "$" #'+workspace/other
|
||||
:desc "Next workspace" ")" #'+workspace/switch-right
|
||||
:desc "Previous workspace" "(" #'+workspace/switch-left))
|
||||
(:prefix-map ("b" . "buffer")
|
||||
:desc "Previous buffer" "(" #'previous-buffer
|
||||
:desc "Next buffer" ")" #'next-buffer)
|
||||
(:prefix-map ("c" . "code")
|
||||
:desc "Jump to documentation" "S" #'+lookup/documentation)
|
||||
(:prefix-map ("g" . "git")
|
||||
(:when (featurep! :ui vc-gutter)
|
||||
:desc "Jump to next hunk" ")" #'git-gutter:next-hunk
|
||||
:desc "Jump to previous hunk" "(" #'git-gutter:previous-hunk))
|
||||
(:prefix-map ("p" . "project")
|
||||
:desc "Browse other project" "»" #'doom/browse-in-other-project))
|
||||
(after! treemacs
|
||||
(doom-bepo-rotate-ts-bare-keymap '(evil-treemacs-state-map)))
|
||||
(after! (:or helm ivy)
|
||||
(doom-bepo-rotate-bare-keymap +default-minibuffer-maps doom-bepo-cr-rotation-style))
|
||||
(after! company
|
||||
(doom-bepo-rotate-bare-keymap '(company-active-map company-search-map) doom-bepo-cr-rotation-style))
|
||||
(after! helm
|
||||
(doom-bepo-rotate-bare-keymap '(helm-map) doom-bepo-cr-rotation-style))
|
||||
(after! general
|
||||
(doom-bepo-rotate-evil-keymap doom-bepo-cr-rotation-style))
|
||||
(after! evil-snipe
|
||||
(doom-bepo--evil-collection-hook
|
||||
nil
|
||||
'(evil-snipe-local-mode-map evil-snipe-override-local-mode-map)))
|
||||
(after! lispyville
|
||||
;; <> en direct
|
||||
(general-translate-key '(normal motion) 'lispyville-mode-map
|
||||
"«" "<"
|
||||
"»" ">"))
|
||||
(after! (evil magit evil-magit)
|
||||
(doom-bepo-rotate-ts-bare-keymap
|
||||
'(magit-mode-map
|
||||
magit-diff-section-base-map
|
||||
magit-staged-section-map
|
||||
magit-unstaged-section-map
|
||||
magit-untracked-section-map))
|
||||
;; Without this, "s" is mapped to 'magit-delete-thing (the old "k" for "kill") and
|
||||
;; takes precedence over the evil command to go up one line
|
||||
(map! :map magit-mode-map "s" nil)
|
||||
(doom-bepo--evil-collection-hook
|
||||
nil
|
||||
'(magit-mode-map
|
||||
magit-cherry-mode-map
|
||||
magit-mode-map
|
||||
magit-blob-mode-map
|
||||
magit-diff-mode-map
|
||||
magit-log-mode-map
|
||||
magit-log-select-mode-map
|
||||
magit-reflog-mode-map
|
||||
magit-status-mode-map
|
||||
magit-file-mode-map
|
||||
magit-log-read-revs-map
|
||||
magit-process-mode-map
|
||||
magit-refs-mode-map)))
|
||||
(after! evil-easymotion
|
||||
(doom-bepo-rotate-bare-keymap '(evilem-map) doom-bepo-cr-rotation-style)))
|
90
modules/input/layout/README.org
Normal file
90
modules/input/layout/README.org
Normal file
|
@ -0,0 +1,90 @@
|
|||
#+TITLE: input/layout
|
||||
#+DATE: Jun 29, 2020
|
||||
#+SINCE: v3.0
|
||||
#+STARTUP: inlineimages nofold
|
||||
|
||||
* Table of Contents :TOC_3:noexport:
|
||||
- [[#description][Description]]
|
||||
- [[#maintainers][Maintainers]]
|
||||
- [[#module-flags][Module Flags]]
|
||||
- [[#plugins][Plugins]]
|
||||
- [[#prerequisites][Prerequisites]]
|
||||
- [[#features][Features]]
|
||||
- [[#bépo][Bépo]]
|
||||
- [[#leaving-mnemonics-alone-when-possible][Leaving mnemonics alone when possible]]
|
||||
- [[#possible-contributions][Possible contributions]]
|
||||
- [[#configuration][Configuration]]
|
||||
- [[#bépo-1][Bépo]]
|
||||
- [[#troubleshooting][Troubleshooting]]
|
||||
- [[#how-to-deactivate-the-new-bindings-and-go-back-to-the-old-ones-][How to deactivate the new bindings and go back to the old ones ?]]
|
||||
|
||||
* Description
|
||||
This module provides barebones support for using Doom with evil-mode with non-qwerty layouts.
|
||||
|
||||
** Maintainers
|
||||
+ @gagbo (Author)
|
||||
|
||||
** Module Flags
|
||||
+ =+bepo= Enables modifications for the BÉPO layout (customized with version 1.1 in mind)
|
||||
|
||||
** Plugins
|
||||
None
|
||||
|
||||
* Prerequisites
|
||||
This module should only be active if evil is enabled. It uses a general.el utility function, and
|
||||
the hooks provided by evil-collection to make the necessary changes.
|
||||
|
||||
* Features
|
||||
# An in-depth list of features, how to use them, and their dependencies.
|
||||
** Bépo
|
||||
Support for the bépo layout includes:
|
||||
- Setting Avy keys to the correct home row keys
|
||||
- Changing navigation keys to =ctsr=
|
||||
+ old =t= is mapped to =j=
|
||||
+ old =s= is mapped to =k= (i.e. staging in the magit status buffer is done with =k=)
|
||||
+ See [[*Configuration][Configuration]] to see where old =c= and =r= functions
|
||||
are remapped
|
||||
- Bind =<>= functions to =«»= keys when possible
|
||||
- Bind =[]= functions to =()= keys when possible
|
||||
- Bind =é= key to =w= functions when possible
|
||||
- Bind =è= key to useful functions when possible
|
||||
- Bind =`~= functions to =$#= keys when possible
|
||||
|
||||
*** Leaving mnemonics alone when possible
|
||||
Exchanging =hjkl= to =ctsr= has the effect of destroying a few mnemonics: the
|
||||
change operator becomes =l= for example, or the window split becomes =SPC é k=.
|
||||
|
||||
The module tries to limit those changes to the minimum, especially in special
|
||||
buffers. A concrete example is magit.
|
||||
|
||||
As the =magit: project= buffer (obtained with =magit-status=) does not need
|
||||
left-right navigation, keys =c=, =r=, =h=, and =l= keep their "expected" bindings,
|
||||
while =t=, =s=, =j=, and =k= are flipped:
|
||||
- checking the log from a magit buffer is still on =l=
|
||||
- staging a file/region has been moved to =k=
|
||||
|
||||
*** Possible contributions
|
||||
A nice addition in the future might be to have all the normal mode bindings that
|
||||
start with =g= start with =,= instead to avoid the curl on these common
|
||||
bindings. This is *not* implemented for the time being.
|
||||
|
||||
* Configuration
|
||||
** Bépo
|
||||
=doom-bepo-cr-rotation-style= controls whether:
|
||||
- =qwerty-c= functions are mapped on =bépo-l= key, and =qwerty-r= functions on
|
||||
=bépo-h= key (='ergodis=), or
|
||||
- =qwerty-c= functions are mapped on =bépo-h= key, and =qwerty-r= functions on
|
||||
=bépo-l= key (='strict=)
|
||||
='strict= would be the logical choice but the =c= functions are used more often
|
||||
than the =r= ones so [[https://bepo.fr/wiki/Vim#Principe][Ergodis]] advises to
|
||||
actually put all the =c= functions on the key that does not need a curl.
|
||||
|
||||
* Troubleshooting
|
||||
# Common issues and their solution, or places to look for help.
|
||||
** How to deactivate the new bindings and go back to the old ones ?
|
||||
If you are learning a new layout you might want to go back to tho old one to
|
||||
"get work done". Sadly the only way is to comment out the module, run =doom
|
||||
sync= and restart emacs.
|
||||
|
||||
Restoring the session =SPC q l= by default helps to lower the impact of the
|
||||
restart.
|
268
modules/input/layout/autoload/bepo.el
Normal file
268
modules/input/layout/autoload/bepo.el
Normal file
|
@ -0,0 +1,268 @@
|
|||
;;; input/keymaps/autoload/bepo.el -*- lexical-binding: t; -*-
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-bepo-rotate-ts-bare-keymap (keymaps)
|
||||
"Rotate [jk] with [ts] in KEYMAP."
|
||||
(dolist (keymap keymaps)
|
||||
(general-translate-key nil keymap
|
||||
"t" "j"
|
||||
"T" "J"
|
||||
"s" "k"
|
||||
"S" "K"
|
||||
"j" "t"
|
||||
"J" "T"
|
||||
"k" "s"
|
||||
"K" "S"
|
||||
"C-t" "C-j"
|
||||
"C-s" "C-k"
|
||||
"C-j" "C-t"
|
||||
"C-k" "C-s"
|
||||
"M-t" "M-j"
|
||||
"M-s" "M-k"
|
||||
"M-j" "M-t"
|
||||
"M-k" "M-s"
|
||||
"C-S-t" "C-S-j"
|
||||
"C-S-s" "C-S-k"
|
||||
"C-S-j" "C-S-t"
|
||||
"C-S-k" "C-S-s"
|
||||
"M-S-t" "M-S-j"
|
||||
"M-S-s" "M-S-k"
|
||||
"M-S-j" "M-S-t"
|
||||
"M-S-k" "M-S-s")))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-bepo-rotate-é-quotes-bare-keymap (keymaps)
|
||||
"Rotate [w<>] with [é«»] in KEYMAP."
|
||||
(dolist (keymap keymaps)
|
||||
(general-translate-key nil keymap
|
||||
"é" "w"
|
||||
"É" "W"
|
||||
"«" "<"
|
||||
"»" ">"
|
||||
"C-é" "C-w"
|
||||
"C-«" "C-<"
|
||||
"C-»" "C->"
|
||||
"M-é" "M-w"
|
||||
"M-«" "M-<"
|
||||
"M-»" "M->"
|
||||
"C-S-é" "C-S-w"
|
||||
"C-S-«" "C-S-<"
|
||||
"C-S-»" "C-S->"
|
||||
"M-S-é" "M-S-w"
|
||||
"M-S-«" "M-S-<"
|
||||
"M-S-»" "M-S->")))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-bepo-rotate-cr-bare-keymap (keymaps &optional style)
|
||||
"Rotate [hl] with [cr] in KEYMAP.
|
||||
|
||||
If STYLE is nil or 'ergodis, the old 'c' bindings will be mapped on 'l' and the old 'r' on 'h'.
|
||||
Otherwise if STYLE is 'strict, the old 'c' bindings will be mapped on 'h' and the old 'r' on 'l'.
|
||||
Undefined behaviour in other cases, for forward compatibility."
|
||||
(let ((style (or style 'ergodis)))
|
||||
(dolist (keymap keymaps)
|
||||
(progn
|
||||
(general-translate-key nil keymap
|
||||
"c" "h"
|
||||
"C" "H"
|
||||
"r" "l"
|
||||
"R" "L"
|
||||
"C-c" "C-h"
|
||||
"C-r" "C-l"
|
||||
"M-c" "M-h"
|
||||
"M-r" "M-l"
|
||||
"C-S-c" "C-S-h"
|
||||
"C-S-r" "C-S-l"
|
||||
"M-S-c" "M-S-h"
|
||||
"M-S-r" "M-S-l")
|
||||
(cond ((eq style 'ergodis)
|
||||
(general-translate-key nil keymap
|
||||
"h" "r"
|
||||
"H" "R"
|
||||
"l" "c"
|
||||
"L" "C"
|
||||
"C-h" "C-r"
|
||||
"C-l" "C-c"
|
||||
"M-h" "M-r"
|
||||
"M-l" "M-c"
|
||||
"C-S-h" "C-S-r"
|
||||
"C-S-l" "C-S-c"
|
||||
"M-S-h" "M-S-r"
|
||||
"M-S-l" "M-S-c"))
|
||||
(t
|
||||
(general-translate-key nil keymap
|
||||
"h" "c"
|
||||
"H" "C"
|
||||
"l" "r"
|
||||
"L" "R"
|
||||
"C-h" "C-c"
|
||||
"C-l" "C-r"
|
||||
"M-h" "M-c"
|
||||
"M-l" "M-r"
|
||||
"C-S-h" "C-S-c"
|
||||
"C-S-l" "C-S-r"
|
||||
"M-S-h" "M-S-c"
|
||||
"M-S-l" "M-S-r")))))))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-bepo-rotate-bare-keymap (keymaps &optional cr-style)
|
||||
"Rotate [hjklw<>] with [ctsré«»] in KEYMAP.
|
||||
See `doom-bepo-cr-rotation-style' for the meaning of CR-STYLE"
|
||||
(doom-bepo-rotate-cr-bare-keymap keymaps cr-style)
|
||||
(doom-bepo-rotate-ts-bare-keymap keymaps)
|
||||
(doom-bepo-rotate-é-quotes-bare-keymap keymaps))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-bepo-rotate-evil-keymap (&optional cr-style)
|
||||
"Remap evil-{normal,operator,motion,...}-state-map
|
||||
to be more natural with Bépo keyboard layout.
|
||||
See `doom-bepo-cr-rotation-style' for the meaning of CR-STYLE."
|
||||
(general-translate-key nil '(normal motion visual)
|
||||
"c" "h"
|
||||
"C" "H"
|
||||
"t" "j"
|
||||
"T" "J"
|
||||
"s" "k"
|
||||
"S" "K"
|
||||
"r" "l"
|
||||
"R" "L"
|
||||
"j" "t"
|
||||
"J" "T"
|
||||
"k" "s"
|
||||
"K" "S")
|
||||
(cond ((eq cr-style 'ergodis)
|
||||
(general-translate-key nil '(normal motion visual)
|
||||
"h" "r"
|
||||
"H" "R"
|
||||
"l" "c"
|
||||
"L" "C"))
|
||||
(t
|
||||
(general-translate-key nil '(normal motion visual)
|
||||
"h" "c"
|
||||
"H" "C"
|
||||
"l" "r"
|
||||
"L" "R")))
|
||||
|
||||
(general-translate-key nil '(insert)
|
||||
"C-c" "C-h"
|
||||
"C-C" "C-H"
|
||||
"C-t" "C-j"
|
||||
"C-T" "C-J"
|
||||
"C-s" "C-k"
|
||||
"C-S" "C-K"
|
||||
"C-r" "C-l"
|
||||
"C-R" "C-L"
|
||||
"C-j" "C-t"
|
||||
"C-J" "C-T"
|
||||
"C-k" "C-s"
|
||||
"C-K" "C-S")
|
||||
(cond ((eq cr-style 'ergodis)
|
||||
(general-translate-key nil '(insert)
|
||||
"C-h" "C-r"
|
||||
"C-H" "C-R"
|
||||
"C-l" "C-c"
|
||||
"C-L" "C-C"))
|
||||
(t
|
||||
(general-translate-key nil '(insert)
|
||||
"C-h" "C-c"
|
||||
"C-H" "C-C"
|
||||
"C-l" "C-r"
|
||||
"C-L" "C-R")))
|
||||
|
||||
|
||||
;; <> as direct access
|
||||
(general-translate-key nil '(normal motion)
|
||||
"«" "<"
|
||||
"»" ">")
|
||||
|
||||
;; " è replaces ^0 to go at BOL
|
||||
(general-translate-key nil '(normal motion)
|
||||
"è" "^"
|
||||
"È" "0")
|
||||
|
||||
;; [W] -> [É]
|
||||
;; [C-W] -> [W]
|
||||
(general-translate-key nil '(normal motion operator)
|
||||
"é" "w"
|
||||
"É" "W"
|
||||
"w" "C-w"
|
||||
"W" "C-w C-w"))
|
||||
|
||||
;;;###autoload
|
||||
(defun doom-bepo-rotate-collection-keymaps-h-builder (cr-style)
|
||||
"Build a hook that remaps evil-collection customizations to be more natural
|
||||
with Bépo keyboard layout, according to CR-STYLE (see `doom-bepo-cr-rotation-style')."
|
||||
(let* ((cr-style (or cr-style 'ergodis))
|
||||
(doom-bepo-hook (lambda (_mode mode-keymaps &rest _rest)
|
||||
(dolist (keymap mode-keymaps)
|
||||
(general-translate-key '(normal motion visual) keymap
|
||||
"c" "h"
|
||||
"C" "H"
|
||||
"t" "j"
|
||||
"T" "J"
|
||||
"s" "k"
|
||||
"S" "K"
|
||||
"r" "l"
|
||||
"R" "L"
|
||||
"j" "t"
|
||||
"J" "T"
|
||||
"k" "s"
|
||||
"K" "S")
|
||||
(cond ((eq cr-style 'ergodis)
|
||||
(general-translate-key '(normal motion visual) keymap
|
||||
"h" "r"
|
||||
"H" "R"
|
||||
"l" "c"
|
||||
"L" "C"))
|
||||
(t
|
||||
(general-translate-key '(normal motion visual) keymap
|
||||
"h" "c"
|
||||
"H" "C"
|
||||
"l" "r"
|
||||
"L" "R")))
|
||||
|
||||
|
||||
(general-translate-key '(insert) keymap
|
||||
"C-c" "C-h"
|
||||
"C-C" "C-H"
|
||||
"C-t" "C-j"
|
||||
"C-T" "C-J"
|
||||
"C-s" "C-k"
|
||||
"C-S" "C-K"
|
||||
"C-r" "C-l"
|
||||
"C-R" "C-L"
|
||||
"C-j" "C-t"
|
||||
"C-J" "C-T"
|
||||
"C-k" "C-s"
|
||||
"C-K" "C-S")
|
||||
(cond ((eq cr-style 'ergodis)
|
||||
(general-translate-key '(insert) keymap
|
||||
"C-h" "C-r"
|
||||
"C-H" "C-R"
|
||||
"C-l" "C-c"
|
||||
"C-L" "C-C"))
|
||||
(t
|
||||
(general-translate-key '(insert) keymap
|
||||
"C-h" "C-c"
|
||||
"C-H" "C-C"
|
||||
"C-l" "C-r"
|
||||
"C-L" "C-R")))
|
||||
|
||||
;; <> en direct
|
||||
(general-translate-key '(normal motion visual) keymap
|
||||
"«" "<"
|
||||
"»" ">")
|
||||
|
||||
;; è pour aller au début de ligne
|
||||
(general-translate-key '(normal motion visual) keymap
|
||||
"è" "^"
|
||||
"È" "0")
|
||||
|
||||
;; [W] -> [É]
|
||||
;; [C-W] -> [W]
|
||||
(general-translate-key '(normal motion operator visual) keymap
|
||||
"é" "w"
|
||||
"É" "W"
|
||||
"w" "C-w"
|
||||
"W" "C-w C-w")))))
|
||||
doom-bepo-hook))
|
14
modules/input/layout/config.el
Normal file
14
modules/input/layout/config.el
Normal file
|
@ -0,0 +1,14 @@
|
|||
;;; input/keymaps/config.el -*- lexical-binding: t; -*-
|
||||
|
||||
(defvar doom-bepo-cr-rotation-style 'ergodis
|
||||
"Modify this variable in your $DOOMDIR/init.el
|
||||
Style of binding rotation for the cr keys.
|
||||
If 'ergodis, then the module maps the old 'c' bindings to 'l' and the old 'r' to 'h', as
|
||||
the 'change' function is used more often and 'l' is easier to reach than 'h' in bépo.
|
||||
|
||||
If 'strict, the module does a normal swap and 'c' bindings go to 'h', 'r' bindings go to 'l'.
|
||||
|
||||
In all cases, 'h' functions go to 'c' and 'l' ones go to 'r' so the navigation keys still feel vim-like.")
|
||||
|
||||
(when (featurep! +bepo)
|
||||
(load! "+bepo"))
|
Loading…
Add table
Add a link
Reference in a new issue