From acb2fc6a291829d33bf78dfdd344ec9357d1e86a Mon Sep 17 00:00:00 2001 From: UndeadKernel <6165006+UndeadKernel@users.noreply.github.com> Date: Tue, 8 Aug 2023 15:28:12 +0200 Subject: [PATCH] tweak(default): transient bindings for mc and er Better default (transient) bindings for multiple-cursors (mc) and expand-region (er) in vanilla emacs. A transient map takes care of repeating useful commands without having to input entire shortcut sequences. Added the binding "C-+" to create a new cursor like what is selected (following the recommendation of the package's author). --- modules/config/default/+emacs-bindings.el | 14 ++++++---- modules/config/default/+emacs.el | 15 +++++++++- .../multiple-cursors/autoload/vanilla-mc.el | 28 +++++++++++++++++++ modules/editor/multiple-cursors/config.el | 20 ++++++++++++- 4 files changed, 70 insertions(+), 7 deletions(-) create mode 100644 modules/editor/multiple-cursors/autoload/vanilla-mc.el diff --git a/modules/config/default/+emacs-bindings.el b/modules/config/default/+emacs-bindings.el index 7c63e68e280..348549f3b86 100644 --- a/modules/config/default/+emacs-bindings.el +++ b/modules/config/default/+emacs-bindings.el @@ -439,10 +439,10 @@ (:when (modulep! :editor multiple-cursors) (:prefix-map ("m" . "multiple-cursors") :desc "Edit lines" "l" #'mc/edit-lines - :desc "Mark next" "n" #'mc/mark-next-like-this - :desc "Unmark next" "N" #'mc/unmark-next-like-this - :desc "Mark previous" "p" #'mc/mark-previous-like-this - :desc "Unmark previous" "P" #'mc/unmark-previous-like-this + :desc "Mark next" "n" #'+mc/transient-mark-next-like-this + :desc "Unmark next" "N" #'+mc/transient-unmark-next-like-this + :desc "Mark previous" "p" #'+mc/transient-mark-previous-like-this + :desc "Unmark previous" "P" #'+mc/transient-unmark-previous-like-this :desc "Mark all" "t" #'mc/mark-all-like-this :desc "Mark all DWIM" "m" #'mc/mark-all-like-this-dwim :desc "Edit line endings" "e" #'mc/edit-ends-of-lines @@ -543,7 +543,11 @@ "C-c h" #'+ein/hydra/body) ;;; expand-region - "C-=" #'er/expand-region + "C-=" (cmd! (call-interactively #'er/expand-region) + (set-transient-map +er-transient-map t)) + + ;; multiple-cursors + "C-+" #'mc/mark-next-like-this ;;; flycheck (:after flycheck diff --git a/modules/config/default/+emacs.el b/modules/config/default/+emacs.el index a68711bb2b1..b2e5d0c6a31 100644 --- a/modules/config/default/+emacs.el +++ b/modules/config/default/+emacs.el @@ -10,8 +10,21 @@ (delete-selection-mode +1) (use-package! expand-region - :commands (er/contract-region er/mark-symbol er/mark-word) + :commands (er/expand-region er/contract-region er/mark-symbol er/mark-word) + :init + (setq expand-region-fast-keys-enabled nil) :config + ;; Configure the transient map called when expanding a region + (setq +er-transient-map + (let ((t-map (make-sparse-keymap))) + (define-key t-map (kbd "C-=") #'er/expand-region) + (define-key t-map (kbd "=") #'er/expand-region) + (define-key t-map (kbd "C--") #'er/contract-region) + (define-key t-map (kbd "-") #'er/contract-region) + (define-key t-map (kbd "C-0") (cmd! (er/expand-region 0))) + (define-key t-map (kbd "0") (cmd! (er/expand-region 0))) + t-map)) + ;; Custom expansion quitting (defadvice! doom--quit-expand-region-a (&rest _) "Properly abort an expand-region region." :before '(evil-escape doom/escape) diff --git a/modules/editor/multiple-cursors/autoload/vanilla-mc.el b/modules/editor/multiple-cursors/autoload/vanilla-mc.el new file mode 100644 index 00000000000..550a0fdd936 --- /dev/null +++ b/modules/editor/multiple-cursors/autoload/vanilla-mc.el @@ -0,0 +1,28 @@ +;;; editor/multiple-cursors/autoload/vanilla-mc.el -*- lexical-binding: t; -*- +;;;###if (not (modulep! :editor evil)) + +;;;###autoload +(defun +mc/transient-call (func) + (require 'multiple-cursors) + (set-transient-map +mc-transient-map t) + (call-interactively func)) + +;;;###autoload +(defun +mc/transient-mark-next-like-this () + (interactive) + (+mc/transient-call #'mc/mark-next-like-this)) + +;;;###autoload +(defun +mc/transient-unmark-next-like-this () + (interactive) + (+mc/transient-call #'mc/unmark-next-like-this)) + +;;;###autoload +(defun +mc/transient-mark-previous-like-this () + (interactive) + (+mc/transient-call #'mc/mark-previous-like-this)) + +;;;###autoload +(defun +mc/transient-unmark-previous-like-this () + (interactive) + (+mc/transient-call #'mc/unmark-previous-like-this)) diff --git a/modules/editor/multiple-cursors/config.el b/modules/editor/multiple-cursors/config.el index cbc4e0d0f7c..219b34c4f56 100644 --- a/modules/editor/multiple-cursors/config.el +++ b/modules/editor/multiple-cursors/config.el @@ -166,7 +166,25 @@ ;; Can't use `mc/cmds-to-run-once' because mc-lists.el overwrites it (add-to-list 'mc--default-cmds-to-run-once 'swiper-mc) - ;; TODO multiple-cursors config for Emacs users? + ;; Use transient commands with vanilla Emacs. + (when (not (modulep! :editor evil)) + ;; Transient map used to better control multiple-cursors in vanilla Emacs. + ;; This map is disabled if a key not in the map is pressed (e.g., "q"). + (setq +mc-transient-map + (let ((t-map (make-sparse-keymap))) + (define-key t-map (kbd "n") #'mc/mark-next-like-this) + (define-key t-map (kbd "N") #'mc/unmark-next-like-this) + (define-key t-map (kbd "p") #'mc/mark-previous-like-this) + (define-key t-map (kbd "P") #'mc/unmark-previous-like-this) + t-map)) + ;; All functions called from the transient map need to be named (i.e., not + ;; be lambdas). These functions need to be further added to the "run once" + ;; category to avoid duplicating calls. + (mapc (lambda (func) (add-to-list 'mc--default-cmds-to-run-once func)) + '(+mc/transient-mark-next-like-this + +mc/transient-mark-previous-like-this + +mc/transient-unmark-next-like-this + +mc/transient-unmark-previous-like-this))) ;; mc doesn't play well with evil, this attempts to assuage some of its ;; problems so that any plugins that depend on multiple-cursors (which I have