diff --git a/.gitignore b/.gitignore index 9d6b97a..8dc9e4e 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ test/.packages +*.elc diff --git a/evil-snipe.el b/evil-snipe.el index fa8174a..9048e81 100755 --- a/evil-snipe.el +++ b/evil-snipe.el @@ -1,4 +1,4 @@ -;;; evil-snipe.el --- emulate vim-sneak & vim-seek +;;; evil-snipe.el --- Emulate vim-sneak & vim-seek -*- lexical-binding: t; -*- ;; ;; Copyright (C) 2014-20 Henrik Lissner ;; @@ -7,9 +7,9 @@ ;; Created: December 5, 2014 ;; Modified: August 21, 2023 ;; Version: 2.1.3 -;; Keywords: emulation, vim, evil, sneak, seek +;; Keywords: convenience, emulations, vim, evil, sneak, seek ;; Homepage: https://github.com/hlissner/evil-snipe -;; Package-Requires: ((emacs "24.4") (evil "1.2.12") (cl-lib "0.5")) +;; Package-Requires: ((emacs "25.1") (evil "1.2.12") (cl-lib "0.5")) ;; ;; This file is not part of GNU Emacs. @@ -72,19 +72,19 @@ for repeating snipes." (defcustom evil-snipe-scope 'line "Dictates the scope of searches, which can be one of: -'line +\='line Search line after the cursor (this is vim-seek behavior) (default) -'buffer +\='buffer Search rest of the buffer after the cursor (vim-sneak behavior) -'visible - Search rest of visible buffer (Is more performant than 'buffer, but will not +\='visible + Search rest of visible buffer (Is more performant than \='buffer, but will not highlight/jump past the visible buffer) -'whole-line - Same as 'line, but highlight matches on either side of cursor -'whole-buffer - Same as 'buffer, but highlight *all* matches in buffer -'whole-visible - Same as 'visible, but highlight *all* visible matches in buffer +\='whole-line + Same as \='line, but highlight matches on either side of cursor +\='whole-buffer + Same as \='buffer, but highlight *all* matches in buffer +\='whole-visible + Same as \='visible, but highlight *all* visible matches in buffer See `evil-snipe-repeat-scope' to change scope only when repeating snipes. @@ -121,7 +121,7 @@ If `evil-snipe-override-evil' is non-nil, this applies to f/F/t/T as well." :type 'boolean) (defcustom evil-snipe-show-prompt t - "If non-nil, show 'N>' prompt while sniping." + "If non-nil, show N> prompt while sniping." :group 'evil-snipe :type 'boolean) @@ -137,19 +137,20 @@ search contains capital letters." :group 'evil-snipe :type 'boolean) +(define-obsolete-variable-alias 'evil-snipe-symbol-groups 'evil-snipe-aliases "v2.0.0") + (defcustom evil-snipe-aliases '() - "A list of characters mapped to regexps '(CHAR REGEX). + "A list of characters mapped to regexps \='(CHAR REGEX). If CHAR is used in a snipe, it will be replaced with REGEX. These aliases apply globally. To set an alias for a specific mode use: - (add-hook 'c++-mode-hook + (add-hook \='c++-mode-hook (lambda () - (make-local-variable 'evil-snipe-aliases) - (push '(?\[ \"[[{(]\") evil-snipe-aliases)))" + (make-local-variable \='evil-snipe-aliases) + (push \='(?\[ \"[[{(]\") evil-snipe-aliases)))" :group 'evil-snipe :type '(repeat (cons (character :tag "Key") (regexp :tag "Pattern")))) -(define-obsolete-variable-alias 'evil-snipe-symbol-groups 'evil-snipe-aliases "v2.0.0") (defcustom evil-snipe-disabled-modes '(org-agenda-mode magit-mode git-rebase-mode elfeed-show-mode @@ -173,27 +174,28 @@ evil-exchange or anything else. MUST BE SET BEFORE EVIL-SNIPE IS LOADED.") (defcustom evil-snipe-skip-leading-whitespace t - "If non-nil, single char sniping (f/F/t/T) will skip over leading whitespaces -in a line (when you snipe for whitespace, e.g. f or f)." + "If non-nil, single char sniping (f/F/t/T) will skip over leading whitespaces. +It skips leading whitespaces when you snipe for whitespace, +e.g. f or f." :group 'evil-snipe :type 'boolean) (defcustom evil-snipe-tab-increment nil - "If non-nil, pressing TAB while sniping will add another character to your -current search. For example, typing sab will search for 'ab'. In order to search -for 'abcd', you do sabcd. + "If non-nil, pressing TAB while sniping adds another character to the search. +For example, typing sab will search for \='ab\='. In order to search +for \='abcd\=', you do sabcd. If nil, TAB will search for literal tab characters." :group 'evil-snipe :type 'boolean) (defcustom evil-snipe-char-fold nil - "If non-nil, uses `char-fold-to-regexp' to include other ascii variants of a -search string. CURRENTLY EXPERIMENTAL. + "Non-nil to use `char-fold-to-regexp' to include ASCII variants search string. +CURRENTLY EXPERIMENTAL. -e.g. The letter 'a' will match all of its accented cousins, even those composed -of multiple characters, as well as many other symbols like U+249C (PARENTHESIZED -LATIN SMALL LETTER A). +e.g. The letter \='a\=' will match all of its accented cousins, even those +composed of multiple characters, as well as many other symbols like +U+249C (PARENTHESIZED LATIN SMALL LETTER A). Only works in Emacs 25.1+." :group 'evil-snipe @@ -210,7 +212,14 @@ Can be let-bound to create motions that search for N characters. Do not set directly, unless you want to change the default number of characters to search.") (defvar evil-snipe--transient-map-func nil) +(defvar evil-snipe-keymap nil + "Keymap for transient state.") +(defvar evil-snipe-parent-transient-map + (let ((map (make-sparse-keymap))) + (define-key map ";" #'evil-snipe-repeat) + (define-key map "," #'evil-snipe-repeat-reverse) + map)) ;; ;;; Faces @@ -234,6 +243,7 @@ search.") (not (string-match-p "[A-Z]" (mapconcat #'cdr data "")))))) (defun evil-snipe--process-key (key) + "Process KEY to return a cons cell of keystr and its regexp." (let ((keystr (char-to-string key))) (cons keystr (cond ((car (cdr (assoc key evil-snipe-aliases)))) (evil-snipe-char-fold (char-fold-to-regexp keystr)) @@ -333,8 +343,8 @@ If FIRST-P is t, then use `evil-snipe-first-p-match-face'" 'evil-snipe-matches-face)) overlay)) -(defun evil-snipe--highlight-all (count forward-p data) - "Highlight instances of keys in DATA at COUNT intervals. +(defun evil-snipe--highlight-all (_count forward-p data) + "Highlight instances of keys in DATA intervals. Goes backward if FORWARD-P is nil." (let ((case-fold-search (evil-snipe--case-p data)) (match (mapconcat #'cdr data "")) @@ -363,6 +373,9 @@ Goes backward if FORWARD-P is nil." overlays))))))) overlays)) +(defvar evil-snipe-local-mode) +(defvar evil-snipe-override-local-mode) + (defun evil-snipe--cleanup () "Disable overlays and clean up after evil-snipe." (when (or evil-snipe-local-mode evil-snipe-override-local-mode) @@ -376,6 +389,7 @@ Goes backward if FORWARD-P is nil." (setq evil-snipe--transient-map-func nil))) (defun evil-snipe--transient-map (forward-key backward-key) + "Return a transient map with FORWARD-KEY and BACKWARD-KEY." (let ((map (make-sparse-keymap))) (set-keymap-parent map evil-snipe-parent-transient-map) (when evil-snipe-repeat-keys @@ -386,8 +400,8 @@ Goes backward if FORWARD-P is nil." (defun evil-snipe-seek (count keys &optional keymap) "Perform a snipe with KEYS at COUNT intervals. -KEYS is a list of characters provided by <-c> and <+c> interactive codes. KEYMAP -is the transient map to activate afterwards." +KEYS is a list of characters provided by <-c> and <+c> interactive codes. +KEYMAP is the transient map to activate afterwards." (pcase keys (`abort (setq evil-inhibit-operator t)) ;; if , repeat last search @@ -401,15 +415,16 @@ is the transient map to activate afterwards." (let ((data (mapcar #'evil-snipe--process-key keys))) (let ((case-fold-search (evil-snipe--case-p data)) (count (or count (if evil-snipe--last-direction 1 -1))) - (keymap (if (keymapp keymap) keymap))) + (evil-snipe-keymap (if (keymapp keymap) keymap))) (unless evil-snipe--last-repeat - (setq evil-snipe--last (list count keys keymap + (setq evil-snipe--last (list count keys evil-snipe-keymap evil-snipe--consume-match evil-snipe--match-count))) (evil-snipe--seek count data) (point)))))) (defun evil-snipe--seek-re (data scope count) + "Search for DATA regex within SCOPE and COUNT." (let ((regex (mapconcat #'cdr data "")) result) (when (and evil-snipe-skip-leading-whitespace @@ -423,10 +438,10 @@ is the transient map to activate afterwards." result)))) (defun evil-snipe--seek (count data &optional internal-p) - "Perform a snipe and adjust cursor position depending on mode." + "Perform a snipe using COUNT and DATA, adjusting cursor position. +INTERNAL-P is non-nil if this is an internal call." (let ((orig-point (point)) - (forward-p (> count 0)) - (match (mapconcat #'cdr data ""))) + (forward-p (> count 0))) ;; Adjust search starting point (if forward-p (forward-char)) (unless evil-snipe--consume-match @@ -471,10 +486,10 @@ is the transient map to activate afterwards." (when evil-snipe-enable-highlight (evil-snipe--highlight beg end t))) ;; Activate the repeat keymap - (when (and (boundp 'keymap) keymap) + (when (and (boundp 'evil-snipe-keymap) evil-snipe-keymap) (evil-snipe--disable-transient-map) (setq evil-snipe--transient-map-func - (set-transient-map keymap)))))) + (set-transient-map evil-snipe-keymap)))))) ;; Try to "spill over" into new scope on failed search (evil-snipe-spillover-scope @@ -486,10 +501,10 @@ is the transient map to activate afterwards." ;; If, at last, it fails... (t (goto-char orig-point) - (when (and evil-snipe--last-repeat (boundp 'keymap) keymap) + (when (and evil-snipe--last-repeat (boundp 'evil-snipe-keymap) evil-snipe-keymap) (evil-snipe--disable-transient-map) (setq evil-snipe--transient-map-func - (set-transient-map keymap))) + (set-transient-map evil-snipe-keymap))) (user-error "Can't find %s" ; show invisible keys (replace-regexp-in-string "\t" "" @@ -520,7 +535,7 @@ is the transient map to activate afterwards." last-keys last-keymap)))) (evil-define-motion evil-snipe-repeat-reverse (count) - "Repeat the inverse of the last evil-snipe `count' times" + "Repeat the inverse of the last evil-snipe `count' times." (interactive "") (evil-snipe-repeat (or (and (integerp count) (- count)) -1))) @@ -537,7 +552,8 @@ explicitly choose the function names." `(progn (evil-define-motion ,forward-fn (count keys) ,(concat "Jumps to the next " (int-to-string n) - "-char match COUNT matches away. Including KEYS is a list of character codes.") + "-char match COUNT matches away. +Including KEYS is a list of character codes.") :jump t (interactive (let ((count (if current-prefix-arg (prefix-numeric-value current-prefix-arg)))) @@ -579,6 +595,7 @@ explicitly choose the function names." ;;;###autoload (autoload 'evil-snipe-T "evil-snipe" nil t) (evil-snipe-def 1 'exclusive "t" "T") +(define-obsolete-variable-alias 'evil-snipe-mode-map 'evil-snipe-local-mode-map "2.0.8") (defvar evil-snipe-local-mode-map (let ((map (make-sparse-keymap))) @@ -596,6 +613,8 @@ explicitly choose the function names." "X" #'evil-snipe-X)) map)) +(define-obsolete-variable-alias 'evil-snipe-override-mode-map 'evil-snipe-override-local-mode-map "2.0.8") + (defvar evil-snipe-override-local-mode-map (let ((map (make-sparse-keymap))) (evil-define-key* 'motion map @@ -609,40 +628,36 @@ explicitly choose the function names." "," #'evil-snipe-repeat-reverse)) map)) -(defvar evil-snipe-parent-transient-map - (let ((map (make-sparse-keymap))) - (define-key map ";" #'evil-snipe-repeat) - (define-key map "," #'evil-snipe-repeat-reverse) - map)) - ;;;###autoload -(defun turn-on-evil-snipe-mode () - "Enable evil-snipe-mode in the current buffer." +(defun evil-snipe-turn-on-mode () + "Enable `evil-snipe-mode' in the current buffer." (unless (apply #'derived-mode-p evil-snipe-disabled-modes) (evil-snipe-local-mode +1))) ;;;###autoload -(defun turn-on-evil-snipe-override-mode () - "Enable evil-snipe-mode in the current buffer." +(defun evil-snipe-turn-on-override-mode () + "Enable `evil-snipe-override-mode' in the current buffer." (unless (apply #'derived-mode-p evil-snipe-disabled-modes) (evil-snipe-override-local-mode +1))) ;;;###autoload -(defun turn-off-evil-snipe-mode () +(defun evil-snipe-turn-off-mode () "Disable `evil-snipe-local-mode' in the current buffer." (evil-snipe-local-mode -1)) ;;;###autoload -(defun turn-off-evil-snipe-override-mode () - "Disable evil-snipe-override-mode in the current buffer." +(defun evil-snipe-turn-off-override-mode () + "Disable `evil-snipe-override-local-mode' in the current buffer." (evil-snipe-override-local-mode -1)) (when (fboundp 'advice-add) (advice-add #'evil-force-normal-state :before #'evil-snipe--cleanup)) (add-hook 'evil-insert-state-entry-hook #'evil-snipe--disable-transient-map) -(defvar evil-snipe--keymaps-init nil) +(defvar evil-snipe--keymaps-init nil + "Non-nil if keymaps are initialized.") (defun evil-snipe--normalize-keymaps () + "Normalize keymaps." (unless evil-snipe--keymaps-init (set (make-local-variable 'evil-snipe--keymaps-init) (and (evil-normalize-keymaps) t)))) @@ -662,14 +677,11 @@ explicitly choose the function names." ;;;###autoload (define-globalized-minor-mode evil-snipe-mode - evil-snipe-local-mode turn-on-evil-snipe-mode) + evil-snipe-local-mode evil-snipe-turn-on-mode) ;;;###autoload (define-globalized-minor-mode evil-snipe-override-mode - evil-snipe-override-local-mode turn-on-evil-snipe-override-mode) - -(define-obsolete-variable-alias 'evil-snipe-mode-map 'evil-snipe-local-mode-map "2.0.8") -(define-obsolete-variable-alias 'evil-snipe-override-mode-map 'evil-snipe-override-local-mode-map "2.0.8") + evil-snipe-override-local-mode evil-snipe-turn-on-override-mode) (provide 'evil-snipe) ;;; evil-snipe.el ends here diff --git a/test/.nosearch b/test/.nosearch new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/test/.nosearch @@ -0,0 +1 @@ +