yeet
This commit is contained in:
@@ -0,0 +1,131 @@
|
||||
;;; editor/multiple-cursors/autoload/evil-mc.el -*- lexical-binding: t; -*-
|
||||
;;;###if (featurep! :editor evil)
|
||||
|
||||
;;;###autoload
|
||||
(defun +multiple-cursors/evil-mc-toggle-cursors ()
|
||||
"Toggle frozen state of evil-mc cursors."
|
||||
(interactive)
|
||||
(unless (evil-mc-has-cursors-p)
|
||||
(user-error "No cursors exist to be toggled"))
|
||||
(setq evil-mc-frozen (not (and (evil-mc-has-cursors-p)
|
||||
evil-mc-frozen)))
|
||||
(if evil-mc-frozen
|
||||
(message "evil-mc paused")
|
||||
(message "evil-mc resumed")))
|
||||
|
||||
;;;###autoload (autoload '+multiple-cursors/evil-mc-toggle-cursor-here "editor/multiple-cursors/autoload/evil-mc" nil t)
|
||||
(evil-define-command +multiple-cursors/evil-mc-toggle-cursor-here ()
|
||||
"Create a cursor at point. If in visual block or line mode, then create
|
||||
cursors on each line of the selection, on the column of the cursor. Otherwise
|
||||
pauses cursors."
|
||||
:repeat nil
|
||||
:keep-visual nil
|
||||
:evil-mc t
|
||||
(interactive)
|
||||
(cond ((and (evil-mc-has-cursors-p)
|
||||
(evil-normal-state-p)
|
||||
(let* ((pos (point))
|
||||
(cursor (cl-find-if (lambda (cursor)
|
||||
(eq pos (evil-mc-get-cursor-start cursor)))
|
||||
evil-mc-cursor-list)))
|
||||
(when cursor
|
||||
(evil-mc-delete-cursor cursor)
|
||||
(setq evil-mc-cursor-list (delq cursor evil-mc-cursor-list))
|
||||
t))))
|
||||
|
||||
((memq evil-this-type '(block line))
|
||||
(let ((col (evil-column))
|
||||
(line-at-pt (line-number-at-pos)))
|
||||
;; Fix off-by-one error
|
||||
(when (= evil-visual-direction 1)
|
||||
(cl-decf col)
|
||||
(backward-char))
|
||||
(save-excursion
|
||||
(evil-apply-on-block
|
||||
(lambda (ibeg _)
|
||||
(unless (or (= line-at-pt (line-number-at-pos ibeg))
|
||||
(invisible-p ibeg))
|
||||
(goto-char ibeg)
|
||||
(move-to-column col)
|
||||
(when (= (current-column) col)
|
||||
(evil-mc-make-cursor-here))))
|
||||
evil-visual-beginning
|
||||
(if (eq evil-this-type 'line) (1- evil-visual-end) evil-visual-end)
|
||||
nil)
|
||||
(evil-exit-visual-state))))
|
||||
(t
|
||||
(evil-mc-pause-cursors)
|
||||
;; I assume I don't want the cursors to move yet
|
||||
(evil-mc-make-cursor-here))))
|
||||
|
||||
;;;###autoload (autoload '+multiple-cursors:evil-mc "editor/multiple-cursors/autoload/evil-mc" nil t)
|
||||
(evil-define-command +multiple-cursors:evil-mc (beg end type pattern &optional flags bang)
|
||||
"Create mc cursors at each match of PATTERN within BEG and END.
|
||||
|
||||
This leaves the cursor where the final cursor would be. If BANG, then treat
|
||||
PATTERN as literal. PATTERN is a delimited regexp (the same that :g or :s uses).
|
||||
FLAGS can be g and/or i; which mean the same thing they do in
|
||||
`evil-ex-substitute'."
|
||||
:evil-mc t
|
||||
:keep-visual t
|
||||
(interactive "<R><//!><!>")
|
||||
(unless (and (stringp pattern)
|
||||
(not (string-empty-p pattern)))
|
||||
(user-error "A regexp pattern is required"))
|
||||
(require 'evil-mc)
|
||||
(let ((m (evil-ex-make-pattern
|
||||
(if bang (regexp-quote pattern) pattern)
|
||||
(cond ((memq ?i flags) 'insensitive)
|
||||
((memq ?I flags) 'sensitive)
|
||||
((not +multiple-cursors-evil-mc-ex-case)
|
||||
evil-ex-search-case)
|
||||
(t +multiple-cursors-evil-mc-ex-case))
|
||||
(or (and +multiple-cursors-evil-mc-ex-global
|
||||
(not (memq ?g flags)))
|
||||
(and (not +multiple-cursors-evil-mc-ex-global)
|
||||
(memq ?g flags))))))
|
||||
(evil-mc-run-cursors-before)
|
||||
(setq evil-mc-pattern (cons m (list beg end type)))
|
||||
(evil-with-restriction beg end
|
||||
(goto-char beg)
|
||||
(while (eq (evil-ex-find-next m 'forward t) t)
|
||||
(evil-mc-make-cursor-at-pos (1- (point)))
|
||||
(unless (evil-ex-pattern-whole-line m)
|
||||
(goto-char (line-beginning-position 2)))))
|
||||
(evil-mc-goto-cursor
|
||||
(if (= (evil-visual-direction) 1)
|
||||
(evil-mc-find-last-cursor)
|
||||
(evil-mc-find-first-cursor))
|
||||
nil)
|
||||
(evil-mc-undo-cursor-at-pos (1- (point)))
|
||||
(if (evil-mc-has-cursors-p)
|
||||
(evil-mc-print-cursors-info "Created")
|
||||
(evil-mc-message "No cursors were created"))))
|
||||
|
||||
;;;###autoload (autoload '+multiple-cursors/evil-mc-undo-cursor "editor/multiple-cursors/autoload/evil-mc" nil t)
|
||||
(evil-define-command +multiple-cursors/evil-mc-undo-cursor ()
|
||||
"Undos last cursor, or all cursors in visual region."
|
||||
:repeat nil
|
||||
:evil-mc t
|
||||
(interactive)
|
||||
(if (evil-visual-state-p)
|
||||
(or (mapc (lambda (c)
|
||||
(evil-mc-delete-cursor c)
|
||||
(setq evil-mc-cursor-list (delq c evil-mc-cursor-list)))
|
||||
(cl-remove-if-not
|
||||
(lambda (pos)
|
||||
(and (>= pos evil-visual-beginning)
|
||||
(< pos evil-visual-end)))
|
||||
evil-mc-cursor-list
|
||||
:key #'evil-mc-get-cursor-start))
|
||||
(message "No cursors to undo in region"))
|
||||
(evil-mc-undo-last-added-cursor)))
|
||||
|
||||
|
||||
;;;###autoload (autoload '+multiple-cursors-execute-default-operator-fn "editor/multiple-cursors/autoload/evil-mc" nil t)
|
||||
|
||||
(after! evil-mc
|
||||
(evil-mc-define-handler +multiple-cursors-execute-default-operator-fn ()
|
||||
:cursor-clear region
|
||||
(evil-mc-with-region-or-execute-macro region t
|
||||
(funcall (evil-mc-get-command-name) region-start region-end))))
|
||||
206
.config/emacs/modules/editor/multiple-cursors/config.el
Normal file
206
.config/emacs/modules/editor/multiple-cursors/config.el
Normal file
@@ -0,0 +1,206 @@
|
||||
;;; editor/multiple-cursors/config.el -*- lexical-binding: t; -*-
|
||||
|
||||
(defvar +multiple-cursors-evil-mc-ex-global t
|
||||
"TODO")
|
||||
|
||||
(defvar +multiple-cursors-evil-mc-ex-case nil
|
||||
"TODO")
|
||||
|
||||
|
||||
;;
|
||||
;;; Packages
|
||||
|
||||
(use-package! evil-multiedit
|
||||
:when (featurep! :editor evil)
|
||||
:defer t)
|
||||
|
||||
|
||||
(use-package! iedit
|
||||
:when (featurep! :completion vertico)
|
||||
:defer t
|
||||
:init
|
||||
;; Fix conflict with embark.
|
||||
(setq iedit-toggle-key-default nil))
|
||||
|
||||
|
||||
(use-package! evil-mc
|
||||
:when (featurep! :editor evil)
|
||||
:commands (evil-mc-make-cursor-here
|
||||
evil-mc-make-all-cursors
|
||||
evil-mc-undo-all-cursors
|
||||
evil-mc-pause-cursors
|
||||
evil-mc-resume-cursors
|
||||
evil-mc-make-and-goto-first-cursor
|
||||
evil-mc-make-and-goto-last-cursor
|
||||
evil-mc-make-cursor-in-visual-selection-beg
|
||||
evil-mc-make-cursor-in-visual-selection-end
|
||||
evil-mc-make-cursor-move-next-line
|
||||
evil-mc-make-cursor-move-prev-line
|
||||
evil-mc-make-cursor-at-pos
|
||||
evil-mc-has-cursors-p
|
||||
evil-mc-make-and-goto-next-cursor
|
||||
evil-mc-skip-and-goto-next-cursor
|
||||
evil-mc-make-and-goto-prev-cursor
|
||||
evil-mc-skip-and-goto-prev-cursor
|
||||
evil-mc-make-and-goto-next-match
|
||||
evil-mc-skip-and-goto-next-match
|
||||
evil-mc-skip-and-goto-next-match
|
||||
evil-mc-make-and-goto-prev-match
|
||||
evil-mc-skip-and-goto-prev-match)
|
||||
:init
|
||||
;; The included keybindings are too imposing and are likely to cause
|
||||
;; conflicts, so we'll set them ourselves.
|
||||
(defvar evil-mc-key-map (make-sparse-keymap))
|
||||
|
||||
:config
|
||||
(global-evil-mc-mode +1)
|
||||
|
||||
;; REVIEW This is tremendously slow on macos and windows for some reason.
|
||||
(setq evil-mc-enable-bar-cursor (not (or IS-MAC IS-WINDOWS)))
|
||||
|
||||
(after! smartparens
|
||||
;; Make evil-mc cooperate with smartparens better
|
||||
(let ((vars (cdr (assq :default evil-mc-cursor-variables))))
|
||||
(unless (memq (car sp--mc/cursor-specific-vars) vars)
|
||||
(setcdr (assq :default evil-mc-cursor-variables)
|
||||
(append vars sp--mc/cursor-specific-vars)))))
|
||||
|
||||
;; Whitelist more commands
|
||||
(dolist (fn '((backward-kill-word)
|
||||
(company-complete-common . evil-mc-execute-default-complete)
|
||||
(doom/backward-to-bol-or-indent . evil-mc-execute-default-call)
|
||||
(doom/forward-to-last-non-comment-or-eol . evil-mc-execute-default-call)
|
||||
;; :emacs undo
|
||||
(undo-fu-only-undo . evil-mc-execute-default-undo)
|
||||
(undo-fu-only-redo . evil-mc-execute-default-redo)
|
||||
;; :editor evil
|
||||
(evil-delete-back-to-indentation . evil-mc-execute-default-call)
|
||||
(evil-escape . evil-mc-execute-default-evil-normal-state) ; C-g
|
||||
(evil-numbers/inc-at-pt-incremental)
|
||||
(evil-numbers/dec-at-pt-incremental)
|
||||
(evil-digit-argument-or-evil-beginning-of-visual-line
|
||||
(:default . evil-mc-execute-default-call)
|
||||
(visual . evil-mc-execute-visual-call))
|
||||
;; :tools eval
|
||||
(+eval:replace-region . +multiple-cursors-execute-default-operator-fn)
|
||||
;; :lang ess
|
||||
(ess-smart-comma . evil-mc-execute-call)
|
||||
;; :lang org
|
||||
(evil-org-delete . evil-mc-execute-default-evil-delete)))
|
||||
(setf (alist-get (car fn) evil-mc-custom-known-commands)
|
||||
(if (and (cdr fn) (listp (cdr fn)))
|
||||
(cdr fn)
|
||||
(list (cons :default
|
||||
(or (cdr fn)
|
||||
#'evil-mc-execute-default-call-with-count))))))
|
||||
|
||||
;; HACK Allow these commands to be repeated by prefixing them with a numerical
|
||||
;; argument. See gabesoft/evil-mc#110
|
||||
(defadvice! +multiple-cursors--make-repeatable-a (fn)
|
||||
:around '(evil-mc-make-and-goto-first-cursor
|
||||
evil-mc-make-and-goto-last-cursor
|
||||
evil-mc-make-and-goto-prev-cursor
|
||||
evil-mc-make-and-goto-next-cursor
|
||||
evil-mc-skip-and-goto-prev-cursor
|
||||
evil-mc-skip-and-goto-next-cursor
|
||||
evil-mc-make-and-goto-prev-match
|
||||
evil-mc-make-and-goto-next-match
|
||||
evil-mc-skip-and-goto-prev-match
|
||||
evil-mc-skip-and-goto-next-match)
|
||||
(dotimes (i (if (integerp current-prefix-arg) current-prefix-arg 1))
|
||||
(funcall fn)))
|
||||
|
||||
;; If we're entering insert mode, it's a good bet that we want to start using
|
||||
;; our multiple cursors
|
||||
(add-hook 'evil-insert-state-entry-hook #'evil-mc-resume-cursors)
|
||||
|
||||
(pushnew! evil-mc-incompatible-minor-modes
|
||||
;; evil-escape's escape key leaves behind extraneous characters
|
||||
'evil-escape-mode
|
||||
;; Lispy commands don't register on more than 1 cursor. Lispyville
|
||||
;; is fine though.
|
||||
'lispy-mode)
|
||||
|
||||
(add-hook! 'doom-escape-hook
|
||||
(defun +multiple-cursors-escape-multiple-cursors-h ()
|
||||
"Clear evil-mc cursors and restore state."
|
||||
(when (evil-mc-has-cursors-p)
|
||||
(evil-mc-undo-all-cursors)
|
||||
(evil-mc-resume-cursors)
|
||||
t)))
|
||||
|
||||
;; Forward declare these so that ex completion and evil-mc support is
|
||||
;; recognized before the autoloaded functions are loaded.
|
||||
(evil-add-command-properties '+evil:align :evil-mc t)
|
||||
(evil-add-command-properties '+multiple-cursors:evil-mc :evil-mc t)
|
||||
|
||||
(map! :map evil-mc-key-map
|
||||
:nv "g." nil
|
||||
:nv "C-n" #'evil-mc-make-and-goto-next-cursor
|
||||
:nv "C-N" #'evil-mc-make-and-goto-last-cursor
|
||||
:nv "C-p" #'evil-mc-make-and-goto-prev-cursor
|
||||
:nv "C-P" #'evil-mc-make-and-goto-first-cursor))
|
||||
|
||||
|
||||
(after! multiple-cursors-core
|
||||
(setq mc/list-file (concat doom-etc-dir "mc-lists.el"))
|
||||
|
||||
;; 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?
|
||||
|
||||
;; 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
|
||||
;; no control over) can still use it in relative safety.
|
||||
(when (featurep! :editor evil)
|
||||
(evil-define-key* '(normal emacs) mc/keymap [escape] #'mc/keyboard-quit)
|
||||
|
||||
(defvar +mc--compat-evil-prev-state nil)
|
||||
(defvar +mc--compat-mark-was-active nil)
|
||||
|
||||
(add-hook! 'multiple-cursors-mode-enabled-hook
|
||||
(defun +multiple-cursors-compat-switch-to-emacs-state-h ()
|
||||
(when (and (bound-and-true-p evil-mode)
|
||||
(not (memq evil-state '(insert emacs))))
|
||||
(setq +mc--compat-evil-prev-state evil-state)
|
||||
(when (region-active-p)
|
||||
(setq +mc--compat-mark-was-active t))
|
||||
(let ((mark-before (mark))
|
||||
(point-before (point)))
|
||||
(evil-emacs-state 1)
|
||||
(when (or +mc--compat-mark-was-active (region-active-p))
|
||||
(goto-char point-before)
|
||||
(set-mark mark-before))))))
|
||||
|
||||
(add-hook! 'multiple-cursors-mode-disabled-hook
|
||||
(defun +multiple-cursors-compat-back-to-previous-state-h ()
|
||||
(when +mc--compat-evil-prev-state
|
||||
(unwind-protect
|
||||
(cl-case +mc--compat-evil-prev-state
|
||||
;; For `evil-multiedit', marked occurrences aren't saved after
|
||||
;; exiting mc, so we should return to normal state anyway
|
||||
((normal visual multiedit multiedit-insert)
|
||||
(evil-force-normal-state))
|
||||
(t (message "Don't know how to handle previous state: %S"
|
||||
+mc--compat-evil-prev-state)))
|
||||
(setq +mc--compat-evil-prev-state nil)
|
||||
(setq +mc--compat-mark-was-active nil)))))
|
||||
|
||||
;; When running edit-lines, point will return (position + 1) as a result of
|
||||
;; how evil deals with regions
|
||||
(defadvice! +multiple--cursors-adjust-mark-for-evil-a (&rest _)
|
||||
:before #'mc/edit-lines
|
||||
(when (and (bound-and-true-p evil-mode)
|
||||
(not (memq evil-state '(insert emacs))))
|
||||
(if (> (point) (mark))
|
||||
(goto-char (1- (point)))
|
||||
(push-mark (1- (mark))))))
|
||||
|
||||
(add-hook! 'rectangular-region-mode-hook
|
||||
(defun +multiple-cursors-evil-compat-rect-switch-state-h ()
|
||||
(if rectangular-region-mode
|
||||
(+multiple-cursors-compat-switch-to-emacs-state-h)
|
||||
(setq +mc--compat-evil-prev-state nil))))
|
||||
|
||||
(defvar mc--default-cmds-to-run-once nil)))
|
||||
@@ -0,0 +1,9 @@
|
||||
;; -*- no-byte-compile: t; -*-
|
||||
;;; editor/multiple-cursors/packages.el
|
||||
|
||||
(cond
|
||||
((featurep! :editor evil)
|
||||
(package! evil-multiedit :pin "23b53bc8743fb82a8854ba907b1d277374c93a79")
|
||||
(package! evil-mc :pin "246aecc17481dd23c172a9b845f02a9d9e322c7f"))
|
||||
|
||||
((package! multiple-cursors :pin "8a60fc7ef0ae6e5ca089a7c95264cd0ae83e7274")))
|
||||
Reference in New Issue
Block a user