Add support for bépo layout in a dedicated module

Evil is loaded too early to be able to wait for the
config.el file of a user to set the CR-rotation style variable.
This commit is contained in:
Gerry Agbobada 2020-08-14 21:41:25 +02:00 committed by Gerry Agbobada
parent 58af4aef56
commit 911d7cb82c
No known key found for this signature in database
GPG Key ID: BE26DBAFD866BE34
5 changed files with 475 additions and 1 deletions

View File

@ -179,4 +179,8 @@
:config
;;literate
(default +bindings +smartparens))
(default +bindings +smartparens)
:input
;;layout ; auie,ctsrnm is the superior home row
)

View File

@ -0,0 +1,103 @@
;;; 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)
(setq avy-keys '(?a ?u ?i ?e ?c ?, ?t ?s ?r ?n))
;; :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-ts-bare-keymap +default-minibuffer-maps))
(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-bare-keymap
'(magit-mode-map
magit-diff-section-base-map
magit-staged-section-map
magit-unstaged-section-map
magit-untracked-section-map) doom-bepo-cr-rotation-style)
;; 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))

View File

@ -0,0 +1,70 @@
#+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]]
- [[#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=
- 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
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.

View File

@ -0,0 +1,278 @@
;;; input/keymaps/autoload/bepo.el -*- lexical-binding: t; -*-
;;;###autoload
(defun doom-bepo-highlight-hard-spaces ()
"Highlight hard (non-breaking) space characters (`?\u00a0').
\(This is also ?\240.)
This also sets `nobreak-char-display' to nil, to turn off its
low-level, vanilla highlighting."
(interactive)
(when (boundp 'nobreak-char-display) (setq nobreak-char-display nil))
(font-lock-add-keywords nil `(("[\u00a0]+" (0 'doom-bepo-hard-space 'prepend))) 'APPEND))
;;;###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))

View File

@ -0,0 +1,19 @@
;;; input/keymaps/config.el -*- lexical-binding: t; -*-
(defface doom-bepo-hard-space '((t (:background "Aquamarine")))
"*Face for highlighting non-breaking spaces (`?\u00a0')in Font-Lock mode.
\(This is also ?\240.)"
:group 'doom-bepo :group 'faces)
(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"))