diff options
Diffstat (limited to 'elpa/swiper-20200503.1102')
-rw-r--r-- | elpa/swiper-20200503.1102/swiper-autoloads.el | 64 | ||||
-rw-r--r-- | elpa/swiper-20200503.1102/swiper-pkg.el | 2 | ||||
-rw-r--r-- | elpa/swiper-20200503.1102/swiper.el | 1719 |
3 files changed, 0 insertions, 1785 deletions
diff --git a/elpa/swiper-20200503.1102/swiper-autoloads.el b/elpa/swiper-20200503.1102/swiper-autoloads.el deleted file mode 100644 index 64a4221..0000000 --- a/elpa/swiper-20200503.1102/swiper-autoloads.el +++ /dev/null @@ -1,64 +0,0 @@ -;;; swiper-autoloads.el --- automatically extracted autoloads -;; -;;; Code: - -(add-to-list 'load-path (directory-file-name - (or (file-name-directory #$) (car load-path)))) - - -;;;### (autoloads nil "swiper" "swiper.el" (0 0 0 0)) -;;; Generated autoloads from swiper.el - -(autoload 'swiper-avy "swiper" "\ -Jump to one of the current swiper candidates. - -\(fn)" t nil) - -(autoload 'swiper-backward "swiper" "\ -`isearch-backward' with an overview. -When non-nil, INITIAL-INPUT is the initial search pattern. - -\(fn &optional INITIAL-INPUT)" t nil) - -(autoload 'swiper-thing-at-point "swiper" "\ -`swiper' with `ivy-thing-at-point'. - -\(fn)" t nil) - -(autoload 'swiper-all-thing-at-point "swiper" "\ -`swiper-all' with `ivy-thing-at-point'. - -\(fn)" t nil) - -(autoload 'swiper "swiper" "\ -`isearch-forward' with an overview. -When non-nil, INITIAL-INPUT is the initial search pattern. - -\(fn &optional INITIAL-INPUT)" t nil) - -(autoload 'swiper-all "swiper" "\ -Run `swiper' for all open buffers. - -\(fn &optional INITIAL-INPUT)" t nil) - -(autoload 'swiper-isearch "swiper" "\ -A `swiper' that's not line-based. - -\(fn &optional INITIAL-INPUT)" t nil) - -(autoload 'swiper-isearch-backward "swiper" "\ -Like `swiper-isearch' but the first result is before the point. - -\(fn &optional INITIAL-INPUT)" t nil) - -(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "swiper" '("swiper-"))) - -;;;*** - -;; Local Variables: -;; version-control: never -;; no-byte-compile: t -;; no-update-autoloads: t -;; coding: utf-8 -;; End: -;;; swiper-autoloads.el ends here diff --git a/elpa/swiper-20200503.1102/swiper-pkg.el b/elpa/swiper-20200503.1102/swiper-pkg.el deleted file mode 100644 index 18a4f3a..0000000 --- a/elpa/swiper-20200503.1102/swiper-pkg.el +++ /dev/null @@ -1,2 +0,0 @@ -;;; -*- no-byte-compile: t -*- -(define-package "swiper" "20200503.1102" "Isearch with an overview. Oh, man!" '((emacs "24.5") (ivy "0.13.0")) :commit "c6b60d34ac37bf4d91a25f16d22e528f85e06938" :keywords '("matching") :authors '(("Oleh Krehel" . "ohwoeowho@gmail.com")) :maintainer '("Oleh Krehel" . "ohwoeowho@gmail.com") :url "https://github.com/abo-abo/swiper") diff --git a/elpa/swiper-20200503.1102/swiper.el b/elpa/swiper-20200503.1102/swiper.el deleted file mode 100644 index f49a414..0000000 --- a/elpa/swiper-20200503.1102/swiper.el +++ /dev/null @@ -1,1719 +0,0 @@ -;;; swiper.el --- Isearch with an overview. Oh, man! -*- lexical-binding: t -*- - -;; Copyright (C) 2015-2019 Free Software Foundation, Inc. - -;; Author: Oleh Krehel <ohwoeowho@gmail.com> -;; URL: https://github.com/abo-abo/swiper -;; Package-Version: 20200503.1102 -;; Package-Commit: c6b60d34ac37bf4d91a25f16d22e528f85e06938 -;; Version: 0.13.0 -;; Package-Requires: ((emacs "24.5") (ivy "0.13.0")) -;; Keywords: matching - -;; This file is part of GNU Emacs. - -;; This file is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 3, or (at your option) -;; any later version. - -;; This program is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; For a full copy of the GNU General Public License -;; see <https://www.gnu.org/licenses/>. - -;;; Commentary: - -;; This package gives an overview of the current regex search -;; candidates. The search regex can be split into groups with a -;; space. Each group is highlighted with a different face. -;; -;; It can double as a quick `regex-builder', although only single -;; lines will be matched. - -;;; Code: - -(require 'ivy) - -(defgroup swiper nil - "`isearch' with an overview." - :group 'matching - :prefix "swiper-") - -(defface swiper-match-face-1 - '((t (:inherit lazy-highlight))) - "The background face for `swiper' matches." - :group 'ivy-faces) - -(defface swiper-match-face-2 - '((t (:inherit isearch))) - "Face for `swiper' matches modulo 1." - :group 'ivy-faces) - -(defface swiper-match-face-3 - '((t (:inherit match))) - "Face for `swiper' matches modulo 2." - :group 'ivy-faces) - -(defface swiper-match-face-4 - '((t (:inherit isearch-fail))) - "Face for `swiper' matches modulo 3." - :group 'ivy-faces) - -(defface swiper-background-match-face-1 - '((t (:inherit swiper-match-face-1))) - "The background face for non-current `swiper' matches." - :group 'ivy-faces) - -(defface swiper-background-match-face-2 - '((t (:inherit swiper-match-face-2))) - "Face for non-current `swiper' matches modulo 1." - :group 'ivy-faces) - -(defface swiper-background-match-face-3 - '((t (:inherit swiper-match-face-3))) - "Face for non-current `swiper' matches modulo 2." - :group 'ivy-faces) - -(defface swiper-background-match-face-4 - '((t (:inherit swiper-match-face-4))) - "Face for non-current `swiper' matches modulo 3." - :group 'ivy-faces) - -(defface swiper-line-face - '((t (:inherit highlight))) - "Face for current `swiper' line." - :group 'ivy-faces) - -(defcustom swiper-faces '(swiper-match-face-1 - swiper-match-face-2 - swiper-match-face-3 - swiper-match-face-4) - "List of `swiper' faces for group matches." - :group 'ivy-faces - :type '(repeat face)) - -(defvar swiper-background-faces - '(swiper-background-match-face-1 - swiper-background-match-face-2 - swiper-background-match-face-3 - swiper-background-match-face-4) - "Like `swiper-faces', but used for all matches except the current one.") - -(defun swiper--recompute-background-faces () - (let ((faces '(swiper-background-match-face-1 - swiper-background-match-face-2 - swiper-background-match-face-3 - swiper-background-match-face-4)) - (colir-compose-method #'colir-compose-soft-light)) - (cl-mapc (lambda (f1 f2) - (let ((bg (face-background f1))) - (when bg - (set-face-background - f2 - (colir-blend - (colir-color-parse bg) - (colir-color-parse "#ffffff")))))) - swiper-faces - faces))) -(swiper--recompute-background-faces) - -(defcustom swiper-min-highlight 2 - "Only highlight matches for regexps at least this long." - :type 'integer) - -(defcustom swiper-include-line-number-in-search nil - "Include line number in text of search candidates." - :type 'boolean - :group 'swiper) - -(defcustom swiper-goto-start-of-match nil - "When non-nil, go to the start of the match, not its end. -Treated as non-nil when searching backwards." - :type 'boolean - :group 'swiper) - -(defun swiper-C-s (&optional arg) - "Move cursor vertically down ARG candidates. -If the input is empty, select the previous history element instead." - (interactive "p") - (if (string= ivy-text "") - (ivy-previous-history-element 1) - (ivy-next-line arg))) - -(defvar swiper-map - (let ((map (make-sparse-keymap))) - (define-key map (kbd "C-s") 'swiper-C-s) - (define-key map (kbd "M-q") 'swiper-query-replace) - (define-key map (kbd "C-l") 'swiper-recenter-top-bottom) - (define-key map (kbd "C-'") 'swiper-avy) - (define-key map (kbd "C-7") 'swiper-mc) - (define-key map (kbd "C-c C-f") 'swiper-toggle-face-matching) - map) - "Keymap for swiper.") - -(defvar swiper--query-replace-overlays nil) - -(defun swiper--query-replace-updatefn () - (let ((lisp (ignore-errors (nth 2 (query-replace-compile-replacement ivy-text t))))) - (dolist (ov swiper--query-replace-overlays) - (overlay-put - ov 'after-string - (propertize - (condition-case nil - (with-current-buffer (overlay-buffer ov) - (set-match-data (overlay-get ov 'md)) - (if (consp lisp) - (eval lisp) - (match-substitute-replacement ivy-text))) - (error ivy-text)) - 'face 'error))))) - -(defun swiper--query-replace-cleanup () - (while swiper--query-replace-overlays - (delete-overlay (pop swiper--query-replace-overlays)))) - -(defun swiper--query-replace-setup () - (with-ivy-window - (let ((end (window-end (selected-window) t)) - (re (ivy-re-to-str ivy-regex))) - (save-excursion - (beginning-of-line) - (while (re-search-forward re end t) - (let ((ov (make-overlay (1- (match-end 0)) (match-end 0))) - (md (match-data t))) - (overlay-put - ov 'matches - (mapcar - (lambda (x) - (list `(match-string ,x) (match-string x))) - (number-sequence 0 (1- (/ (length md) 2))))) - (overlay-put ov 'md md) - (push ov swiper--query-replace-overlays)) - (unless (> (match-end 0) (match-beginning 0)) - (forward-char))))))) - -(defun swiper-query-replace () - "Start `query-replace' with string to replace from last search string." - (interactive) - (cond ((null (window-minibuffer-p)) - (user-error "Should only be called in the minibuffer through `swiper-map'")) - ((string= "" ivy-text) - (user-error "Empty input")) - (t - (swiper--query-replace-setup) - (unwind-protect - (let* ((enable-recursive-minibuffers t) - (from (ivy-re-to-str ivy-regex)) - (groups (number-sequence 1 ivy--subexps)) - (default - (list - (mapconcat (lambda (i) (format "\\%d" i)) groups " ") - (format "\\,(concat %s)" - (if (<= ivy--subexps 1) - "\\&" - (mapconcat - (lambda (i) (format "\\%d" i)) - groups - " \" \" "))))) - (to - (query-replace-compile-replacement - (ivy-read - (format "Query replace %s with: " from) nil - :def default - :caller 'swiper-query-replace) - t))) - (swiper--cleanup) - (ivy-exit-with-action - (lambda (_) - (with-ivy-window - (move-beginning-of-line 1) - (let ((inhibit-read-only t)) - (perform-replace from to - t t nil)))))) - (swiper--query-replace-cleanup))))) - -(ivy-configure 'swiper-query-replace - :update-fn #'swiper--query-replace-updatefn) -(put 'swiper-query-replace 'no-counsel-M-x t) - -(defvar inhibit-message) - -(defun swiper-all-query-replace () - "Start `query-replace' with string to replace from last search string." - (interactive) - (if (null (window-minibuffer-p)) - (user-error - "Should only be called in the minibuffer through `swiper-all-map'") - (let* ((enable-recursive-minibuffers t) - (from (ivy--regex ivy-text)) - (to (query-replace-read-to from "Query replace" t))) - (swiper--cleanup) - (ivy-exit-with-action - (lambda (_) - (let ((wnd-conf (current-window-configuration)) - (inhibit-message t)) - (unwind-protect - (dolist (cand ivy--old-cands) - (let ((buffer (get-text-property 0 'buffer cand))) - (switch-to-buffer buffer) - (goto-char (point-min)) - (perform-replace from to t t nil))) - (set-window-configuration wnd-conf)))))))) -(put 'swiper-all-query-replace 'no-counsel-M-x t) - -(defvar avy-all-windows) -(defvar avy-style) -(defvar avy-keys) -(declare-function avy--overlay-post "ext:avy") -(declare-function avy-action-goto "ext:avy") -(declare-function avy-candidate-beg "ext:avy") -(declare-function avy--done "ext:avy") -(declare-function avy--make-backgrounds "ext:avy") -(declare-function avy-window-list "ext:avy") -(declare-function avy-read "ext:avy") -(declare-function avy-read-de-bruijn "ext:avy") -(declare-function avy-tree "ext:avy") -(declare-function avy-push-mark "ext:avy") -(declare-function avy--remove-leading-chars "ext:avy") - -(defun swiper--avy-candidates () - (let* ( - ;; We'll have overlapping overlays, so we sort all the - ;; overlays in the visible region by their start, and then - ;; throw out non-Swiper overlays or overlapping Swiper - ;; overlays. - (visible-overlays (cl-sort (with-ivy-window - (overlays-in (window-start) - (window-end))) - #'< :key #'overlay-start)) - (min-overlay-start 0) - (overlays-for-avy - (cl-remove-if-not - (lambda (ov) - (when (and (>= (overlay-start ov) - min-overlay-start) - (memq (overlay-get ov 'face) - (append swiper-faces swiper-background-faces))) - (setq min-overlay-start (overlay-start ov)))) - visible-overlays)) - (offset (if (eq (ivy-state-caller ivy-last) 'swiper) 1 0))) - (nconc - (mapcar (lambda (ov) - (cons (overlay-start ov) - (overlay-get ov 'window))) - overlays-for-avy) - (save-excursion - (save-restriction - (narrow-to-region (window-start) (window-end)) - (goto-char (point-min)) - (forward-line) - (let ((win (selected-window)) - cands) - (while (not (eobp)) - (push (cons (+ (point) offset) win) - cands) - (forward-line)) - cands)))))) - -(defun swiper--avy-candidate () - (let ((candidates (swiper--avy-candidates)) - (avy-all-windows nil)) - (unwind-protect - (prog2 - (avy--make-backgrounds - (append (avy-window-list) - (list (ivy-state-window ivy-last)))) - (if (eq avy-style 'de-bruijn) - (avy-read-de-bruijn candidates avy-keys) - (avy-read (avy-tree candidates avy-keys) - #'avy--overlay-post - #'avy--remove-leading-chars)) - (avy-push-mark)) - (avy--done)))) - -(defun swiper--avy-goto (candidate) - (cond ((let ((win (cdr-safe candidate))) - (and win (window-minibuffer-p win))) - (let ((nlines (count-lines (point-min) (point-max)))) - (ivy-set-index - (+ (car (ivy--minibuffer-index-bounds - ivy--index ivy--length ivy-height)) - (line-number-at-pos (car candidate)) - (if (or (= nlines (1+ ivy-height)) - (< ivy--length ivy-height)) - 0 - (- ivy-height nlines)) - -2))) - (ivy--exhibit) - (ivy-done) - (ivy-call)) - ((or (consp candidate) - (number-or-marker-p candidate)) - (ivy-quit-and-run - (avy-action-goto (avy-candidate-beg candidate)))))) - -;;;###autoload -(defun swiper-avy () - "Jump to one of the current swiper candidates." - (interactive) - (unless (require 'avy nil 'noerror) - (error "Package avy isn't installed")) - (cl-case (length ivy-text) - (0 - (user-error "Need at least one char of input")) - (1 - (let ((swiper-min-highlight 1)) - (swiper--update-input-ivy)))) - (swiper--avy-goto (swiper--avy-candidate))) - -(declare-function mc/create-fake-cursor-at-point "ext:multiple-cursors-core") -(declare-function multiple-cursors-mode "ext:multiple-cursors-core") - -(defun swiper-mc () - "Create a fake cursor for each `swiper' candidate. -Make sure `swiper-mc' is on `mc/cmds-to-run-once' list." - (interactive) - (unless (require 'multiple-cursors nil t) - (error "Multiple-cursors isn't installed")) - (unless (window-minibuffer-p) - (error "Call me only from `swiper'")) - (let ((cands (nreverse ivy--old-cands)) - (action (ivy--get-action ivy-last))) - (unless (string= ivy-text "") - (ivy-exit-with-action - (lambda (_) - (let (cand) - (while (setq cand (pop cands)) - (funcall action cand) - (when cands - (mc/create-fake-cursor-at-point)))) - (multiple-cursors-mode 1)))))) - -(defvar swiper--current-window-start nil - "Store `window-start' to restore it later. -This prevents a \"jumping\" behavior which occurs when variables -such as `scroll-conservatively' are set to a high value.") - -(defun swiper-recenter-top-bottom (&optional arg) - "Call (`recenter-top-bottom' ARG)." - (interactive "P") - (with-ivy-window - (recenter-top-bottom arg) - (setq swiper--current-window-start (window-start)))) - -(defvar swiper-font-lock-exclude - '(Man-mode - adoc-mode - bbdb-mode - bongo-library-mode - bongo-mode - bongo-playlist-mode - bookmark-bmenu-mode - circe-channel-mode - circe-query-mode - circe-server-mode - deadgrep-mode - debbugs-gnu-mode - dired-mode - elfeed-search-mode - elfeed-show-mode - emms-playlist-mode - emms-stream-mode - erc-mode - eshell-mode - eww-mode - forth-block-mode - forth-mode - fundamental-mode - gnus-article-mode - gnus-group-mode - gnus-summary-mode - help-mode - helpful-mode - jabber-chat-mode - magit-popup-mode - matrix-client-mode - matrix-client-room-list-mode - mu4e-headers-mode - mu4e-view-mode - nix-mode - notmuch-search-mode - notmuch-tree-mode - occur-edit-mode - occur-mode - org-agenda-mode - package-menu-mode - rcirc-mode - sauron-mode - sieve-mode - treemacs-mode - twittering-mode - vc-dir-mode - w3m-mode - woman-mode - xref--xref-buffer-mode) - "List of major-modes that are incompatible with `font-lock-ensure'.") - -(defun swiper-font-lock-ensure-p () - "Return non-nil if we should `font-lock-ensure'." - (or (derived-mode-p 'magit-mode) - (bound-and-true-p magit-blame-mode) - (memq major-mode swiper-font-lock-exclude) - (not (derived-mode-p 'prog-mode)))) - -(defun swiper-font-lock-ensure () - "Ensure the entire buffer is highlighted." - (unless (swiper-font-lock-ensure-p) - (unless (or (> (buffer-size) 100000) (null font-lock-mode)) - (if (fboundp 'font-lock-ensure) - ;; Added in Emacs 25.1. - (font-lock-ensure) - (with-no-warnings (font-lock-fontify-buffer)))))) - -(defvar swiper--format-spec "" - "Store the current candidates format spec.") - -(defvar swiper--width nil - "Store the number of digits needed for the longest line number.") - -(defvar swiper-use-visual-line nil - "When non-nil, use `line-move' instead of `forward-line'.") - -(defvar dired-isearch-filenames) -(declare-function dired-move-to-filename "dired") - -(defun swiper--line () - (let* ((beg (cond ((and (eq major-mode 'dired-mode) - (bound-and-true-p dired-isearch-filenames)) - (dired-move-to-filename) - (point)) - (swiper-use-visual-line - (save-excursion - (beginning-of-visual-line) - (point))) - (t - (point)))) - (end (if swiper-use-visual-line - (save-excursion - (end-of-visual-line) - (point)) - (line-end-position)))) - - (concat - " " - (buffer-substring beg end)))) - -(defvar swiper-use-visual-line-p - (lambda (n-lines) - (and visual-line-mode - ;; super-slow otherwise - (< (buffer-size) 20000) - (< n-lines 400))) - "A predicate that decides whether `line-move' or `forward-line' is used. -Note that `line-move' can be very slow.") - -(defun swiper--candidates (&optional numbers-width) - "Return a list of this buffer lines. - -NUMBERS-WIDTH, when specified, is used for width spec of line -numbers; replaces calculating the width from buffer line count." - (let* ((inhibit-field-text-motion t) - (n-lines (count-lines (point-min) (point-max)))) - (if (funcall swiper-use-visual-line-p n-lines) - (progn - (when (eq major-mode 'org-mode) - (require 'outline) - (if (fboundp 'outline-show-all) - ;; Added in Emacs 25.1. - (outline-show-all) - (with-no-warnings - (show-all)))) - (setq swiper-use-visual-line t)) - (setq swiper-use-visual-line nil)) - (unless (zerop n-lines) - (setq swiper--width (or numbers-width - (1+ (floor (log n-lines 10))))) - (setq swiper--format-spec - (format "%%-%dd " swiper--width)) - (let ((line-number 1) - (advancer (if swiper-use-visual-line - (lambda (arg) (line-move arg t)) - #'forward-line)) - candidates) - (save-excursion - (goto-char (point-min)) - (swiper-font-lock-ensure) - (while (< (point) (point-max)) - (when (swiper-match-usable-p) - (let ((str (swiper--line))) - (setq str (ivy-cleanup-string str)) - (let ((line-number-str - (format swiper--format-spec line-number))) - (if swiper-include-line-number-in-search - (setq str (concat line-number-str str)) - (put-text-property - 0 1 'display line-number-str str)) - (put-text-property - 0 1 'swiper-line-number line-number str)) - (push str candidates))) - (funcall advancer 1) - (cl-incf line-number)) - (nreverse candidates)))))) - -(defvar swiper--opoint 1 - "The point when `swiper' starts.") - -;;;###autoload -(defun swiper-backward (&optional initial-input) - "`isearch-backward' with an overview. -When non-nil, INITIAL-INPUT is the initial search pattern." - (interactive) - (let ((ivy-index-functions-alist - '((swiper . ivy-recompute-index-swiper-backward)))) - (swiper initial-input))) - -;;;###autoload -(defun swiper-thing-at-point () - "`swiper' with `ivy-thing-at-point'." - (interactive) - (let ((thing (ivy-thing-at-point))) - (when (use-region-p) - (deactivate-mark)) - (swiper (regexp-quote thing)))) - -;;;###autoload -(defun swiper-all-thing-at-point () - "`swiper-all' with `ivy-thing-at-point'." - (interactive) - (let ((thing (ivy-thing-at-point))) - (when (use-region-p) - (deactivate-mark)) - (swiper-all (regexp-quote thing)))) - -(defun swiper--extract-matches (regex cands) - "Extract captured REGEX groups from CANDS." - (let (res) - (dolist (cand cands) - (setq cand (substring cand 1)) - (when (string-match regex cand) - (push (mapconcat (lambda (n) (match-string-no-properties n cand)) - (number-sequence - 1 - (/ (- (length (match-data)) 2) 2)) - " ") - res))) - (nreverse res))) - -(defun swiper--occur-cands (fname cands) - (when cands - (with-current-buffer (ivy-state-buffer ivy-last) - (when (eq (ivy-state-caller ivy-last) 'swiper-isearch) - (setq cands (mapcar #'swiper--line-at-point cands))) - (let* ((pt-min (point-min)) - (line-delta - (save-restriction - (widen) - (1- (line-number-at-pos pt-min)))) - (lines - (if (eq (ivy-state-caller ivy-last) 'swiper-isearch) - (swiper--isearch-occur-cands cands) - (mapcar (lambda (s) - (let ((n (swiper--line-number s))) - (setq s (substring s 1)) - (add-text-properties 0 1 (list 'swiper-line-number n) s) - (cons n s))) - cands))) - (offset (+ (length fname) 2))) - (mapcar (lambda (x) - (let ((nn (number-to-string - (+ (car x) line-delta)))) - (remove-text-properties 0 1 '(display) (cdr x)) - (put-text-property 0 (length nn) 'face 'ivy-grep-line-number nn) - (put-text-property 0 1 'offset (+ offset (length nn)) fname) - (format "%s:%s:%s" fname nn (cdr x)))) - lines))))) - -(defun swiper--isearch-occur-cands (cands) - (let* ((last-pt (get-text-property 0 'point (car cands))) - (line (1+ (line-number-at-pos last-pt))) - res pt) - (dolist (cand cands) - (setq pt (get-text-property 0 'point cand)) - (cl-incf line (1- (count-lines last-pt pt))) - (push (cons line cand) res) - (setq last-pt pt)) - (nreverse res))) - -(defun swiper--occur-insert-lines (cands) - (let ((inhibit-read-only t)) - ;; Need precise number of header lines for `wgrep' to work. - (insert (format "-*- mode:grep; default-directory: %S -*-\n\n\n" - default-directory)) - (insert (format "%d candidates:\n" (length cands))) - (ivy--occur-insert-lines cands) - (goto-char (point-min)) - (forward-line 4))) - -(defun swiper--occur-buffer () - (let ((buffer (ivy-state-buffer ivy-last))) - (unless (buffer-live-p buffer) - (setq buffer - (setf (ivy-state-buffer ivy-last) - (find-file-noselect - (plist-get (ivy-state-extra-props ivy-last) :fname)))) - (save-selected-window - (pop-to-buffer buffer)) - (setf (ivy-state-window ivy-last) (selected-window))) - buffer)) - -(defun swiper-occur (&optional cands) - "Generate a custom occur buffer for `swiper'. -When capture groups are present in the input, print them instead of lines." - (setq cands (or ivy-marked-candidates cands)) - (let* ((buffer (swiper--occur-buffer)) - (fname (propertize - (with-ivy-window - (if (buffer-file-name buffer) - (file-name-nondirectory - (buffer-file-name buffer)) - (buffer-name buffer))) - 'face - 'ivy-grep-info)) - (re - (progn - (string-match "\"\\(.*\\)\"" (buffer-name)) - (ivy-set-text (match-string 1 (buffer-name))) - (mapconcat #'identity (ivy--split ivy-text) ".*?"))) - (cands - (swiper--occur-cands - fname - (or cands - (save-window-excursion - (switch-to-buffer buffer) - (if (eq (ivy-state-caller ivy-last) 'swiper) - (let ((ivy--regex-function 'swiper--re-builder)) - (setq ivy--old-re nil) - (ivy--filter re (swiper--candidates))) - (swiper-isearch-function ivy-text))))))) - (if (string-match-p "\\\\(" re) - (insert - (mapconcat #'identity - (swiper--extract-matches - re (with-current-buffer buffer - (swiper--candidates))) - "\n")) - (unless (eq major-mode 'ivy-occur-grep-mode) - (ivy-occur-grep-mode) - (font-lock-mode -1)) - (swiper--occur-insert-lines - (mapcar (lambda (cand) (concat "./" cand)) cands))))) - -(declare-function evil-set-jump "ext:evil-jumps") - -(defvar swiper--current-line nil) -(defvar swiper--current-match-start nil) -(defvar swiper--point-min nil) -(defvar swiper--point-max nil) -(defvar swiper--reveal-mode nil) - -(defun swiper--init () - "Perform initialization common to both completion methods." - (setq swiper--current-line nil) - (setq swiper--current-match-start nil) - (setq swiper--current-window-start nil) - (setq swiper--opoint (point)) - (setq swiper--point-min (point-min)) - (setq swiper--point-max (point-max)) - (when (setq swiper--reveal-mode - (bound-and-true-p reveal-mode)) - (reveal-mode -1)) - (lazy-highlight-cleanup t) - (setq isearch-opened-overlays nil) - (when (bound-and-true-p evil-mode) - (evil-set-jump))) - -(defun swiper--normalize-regex (re) - "Normalize the swiper regex RE. -Add a space after a leading `^' if needed and apply -`search-default-mode' if bound." - (replace-regexp-in-string - "^\\(?:\\\\(\\)?\\^" - (concat "\\&" (if (eq 'swiper (ivy-state-caller ivy-last)) " " "")) - (if (functionp (bound-and-true-p search-default-mode)) - (mapconcat - (lambda (x) - (if (string-match-p "\\`[^$\\^]+\\'" x) - (funcall search-default-mode x) - x)) - (split-string re "\\b") "") - re) - t)) - -(defun swiper--re-builder (str) - "Transform STR into a swiper regex. -This is the regex used in the minibuffer where candidates have -line numbers. For the buffer, use `ivy--regex' instead." - (let* ((re-builder (ivy-alist-setting ivy-re-builders-alist)) - (str (replace-regexp-in-string "\\\\n" "\n" str)) - (re (funcall re-builder str))) - (if (consp re) - (mapcar - (lambda (x) - (cons (swiper--normalize-regex (car x)) - (cdr x))) - re) - (swiper--normalize-regex re)))) - -(defvar swiper-history nil - "History for `swiper'.") - -(defvar swiper-invocation-face nil - "The face at the point of invocation of `swiper'.") - -(defcustom swiper-stay-on-quit nil - "When non-nil don't go back to search start on abort." - :type 'boolean) - -;;;###autoload -(defun swiper (&optional initial-input) - "`isearch-forward' with an overview. -When non-nil, INITIAL-INPUT is the initial search pattern." - (interactive) - (let ((candidates (swiper--candidates))) - (swiper--init) - (setq swiper-invocation-face - (plist-get (text-properties-at (point)) 'face)) - (let ((preselect - (if (or swiper-use-visual-line (null search-invisible)) - (count-screen-lines - (point-min) - (save-excursion (beginning-of-visual-line) (point))) - (1- (line-number-at-pos)))) - (minibuffer-allow-text-properties t) - res) - (unwind-protect - (and - (setq res - (ivy-read - "Swiper: " - candidates - :initial-input initial-input - :keymap swiper-map - :preselect - (if initial-input - (cl-position-if - (lambda (x) - (= (1+ preselect) (swiper--line-number x))) - (progn - (setq ivy--old-re nil) - (ivy--filter initial-input candidates))) - preselect) - :require-match t - :action #'swiper--action - :re-builder #'swiper--re-builder - :history 'swiper-history - :extra-props (list :fname (buffer-file-name)) - :caller 'swiper)) - (point)) - (unless (or res swiper-stay-on-quit) - (goto-char swiper--opoint)) - (isearch-clean-overlays) - (unless (or res (string= ivy-text "")) - (cl-pushnew ivy-text swiper-history)) - (setq swiper--current-window-start nil) - (when swiper--reveal-mode - (reveal-mode 1)))))) - -(ivy-configure 'swiper - :occur #'swiper-occur - :update-fn #'swiper--update-input-ivy - :unwind-fn #'swiper--cleanup - :index-fn #'ivy-recompute-index-swiper) - -(defun swiper-toggle-face-matching () - "Toggle matching only the candidates with `swiper-invocation-face'." - (interactive) - (setf (ivy-state-matcher ivy-last) - (if (ivy-state-matcher ivy-last) - nil - #'swiper--face-matcher)) - (setq ivy--old-re nil)) - -(defun swiper--face-matcher (regexp candidates) - "Return REGEXP matching CANDIDATES. -Matched candidates should have `swiper-invocation-face'." - (cl-remove-if-not - (lambda (x) - (and (string-match regexp x) - (let* ((s (match-string 0 x)) - (n (length s)) - (i 0)) - (while (and (< i n) - (text-property-any - i (1+ i) - 'face swiper-invocation-face - s)) - (cl-incf i)) - (= i n)))) - candidates)) - -(defun swiper--ensure-visible () - "Remove overlays hiding point." - (let ((overlays (overlays-at (1- (point)))) - ov expose) - (while (setq ov (pop overlays)) - (if (and (invisible-p (overlay-get ov 'invisible)) - (setq expose (overlay-get ov 'isearch-open-invisible))) - (funcall expose ov))))) - -(defvar swiper--overlays nil - "Store overlays.") - -(defvar swiper--isearch-highlight-timer nil - "This timer used by `swiper--delayed-add-overlays'.") - -(defun swiper--cleanup () - "Clean up the overlays." - (while swiper--overlays - (delete-overlay (pop swiper--overlays))) - ;; force cleanup unless it's :unwind - (lazy-highlight-cleanup - (if (eq ivy-exit 'done) lazy-highlight-cleanup t)) - (when (timerp swiper--isearch-highlight-timer) - (cancel-timer swiper--isearch-highlight-timer) - (setq swiper--isearch-highlight-timer nil))) - -(defun swiper--add-cursor-overlay (wnd) - (let* ((special (or (eolp) (looking-at "\t"))) - (ov (make-overlay (point) (if special (point) (1+ (point)))))) - (if special - (overlay-put ov 'after-string (propertize " " 'face 'ivy-cursor)) - (overlay-put ov 'face 'ivy-cursor)) - (overlay-put ov 'window wnd) - (overlay-put ov 'priority 2) - (push ov swiper--overlays))) - -(defun swiper--add-line-overlay (wnd) - (let ((beg (if visual-line-mode - (save-excursion - (beginning-of-visual-line) - (point)) - (line-beginning-position))) - (end (if visual-line-mode - (save-excursion - (end-of-visual-line) - (point)) - (1+ (line-end-position))))) - (push (swiper--make-overlay beg end 'swiper-line-face wnd 0) - swiper--overlays))) - -(defun swiper--make-overlay (beg end face wnd priority) - "Create an overlay bound by BEG and END. -FACE, WND and PRIORITY are properties corresponding to -the face, window and priority of the overlay." - (let ((overlay (make-overlay beg end))) - (overlay-put overlay 'face face) - (overlay-put overlay 'window wnd) - (overlay-put overlay 'priority priority) - overlay)) - -(defun swiper--recenter-p () - (or (display-graphic-p) - (not recenter-redisplay))) - -(defun swiper--positive-regexps () - (if (listp ivy-regex) - (mapcar #'car (cl-remove-if-not #'cdr ivy-regex)) - (list ivy-regex))) - -(defun swiper--update-input-ivy () - "Called when `ivy' input is updated." - (with-ivy-window - (swiper--cleanup) - (when (> (length (ivy-state-current ivy-last)) 0) - (let ((regexps (swiper--positive-regexps)) - (re-idx -1) - (case-fold-search (ivy--case-fold-p ivy-text))) - (dolist (re regexps) - (setq re-idx (1+ re-idx)) - (let* ((re (replace-regexp-in-string - " " "\t" - re)) - (num (swiper--line-number (ivy-state-current ivy-last)))) - (unless (memq this-command '(ivy-yank-word - ivy-yank-symbol - ivy-yank-char - scroll-other-window)) - (when (cl-plusp num) - (unless (if swiper--current-line - (eq swiper--current-line num) - (eq (line-number-at-pos) num)) - (goto-char swiper--point-min) - (if swiper-use-visual-line - (line-move (1- num)) - (forward-line (1- num)))) - (if (and (equal ivy-text "") - (>= swiper--opoint (line-beginning-position)) - (<= swiper--opoint (line-end-position))) - (goto-char swiper--opoint) - (if (eq swiper--current-line num) - (when swiper--current-match-start - (goto-char swiper--current-match-start)) - (setq swiper--current-line num)) - (when (re-search-forward re (line-end-position) t) - (setq swiper--current-match-start (match-beginning 0)))) - (isearch-range-invisible (line-beginning-position) - (line-end-position)) - (swiper--maybe-recenter))) - (swiper--add-overlays - re - (max - (if (swiper--recenter-p) - (window-start) - (line-beginning-position (- (window-height)))) - swiper--point-min) - (min - (if (swiper--recenter-p) - (window-end (selected-window) t) - (line-end-position (window-height))) - swiper--point-max) - nil - re-idx))))))) - -(defun swiper--add-overlays (re &optional beg end wnd re-idx) - "Add overlays for RE regexp in visible part of the current buffer. -BEG and END, when specified, are the point bounds. -WND, when specified is the window." - (setq wnd (or wnd (ivy-state-window ivy-last))) - (swiper--add-line-overlay wnd) - (let* ((pt (point)) - (wh (window-height)) - (beg (or beg (save-excursion - (forward-line (- wh)) - (point)))) - (end (or end (save-excursion - (forward-line wh) - (point)))) - (case-fold-search (ivy--case-fold-p re))) - (when (>= (length re) swiper-min-highlight) - (save-excursion - (goto-char beg) - ;; RE can become an invalid regexp - (while (progn - (when (eolp) - (unless (eobp) - (forward-char))) - (and (ignore-errors (re-search-forward re end t)) - (> (- (match-end 0) (match-beginning 0)) 0))) - ;; Don't highlight a match if it spans multiple - ;; lines. `count-lines' returns 1 if the match is within a - ;; single line, even if it includes the newline, and 2 or - ;; greater otherwise. We hope that the inclusion of the - ;; newline will not ever be a problem in practice. - (when (< (count-lines (match-beginning 0) (match-end 0)) 2) - (let* ((faces (if (= (match-end 0) pt) - swiper-faces - swiper-background-faces)) - (adder-fn (lambda (beg end face priority) - (push (swiper--make-overlay beg end face wnd priority) - isearch-lazy-highlight-overlays)))) - (unless (and (consp ivy--old-re) - (null - (save-match-data - (ivy--re-filter ivy--old-re - (list - (buffer-substring-no-properties - (line-beginning-position) - (line-end-position))))))) - (swiper--add-properties faces adder-fn re-idx))))))))) - -(defun swiper--add-properties (faces adder-fn &optional re-idx) - (let ((mb (match-beginning 0)) - (me (match-end 0))) - (unless (> (- me mb) 2017) - (funcall adder-fn - mb me - (if (and ivy-use-group-face-if-no-groups (zerop ivy--subexps)) - (nth (1+ (mod (or re-idx 0) (1- (length faces)))) faces) - (car faces)) - 0))) - (let ((i 1) - (j 0)) - (while (<= (cl-incf j) ivy--subexps) - (let ((bm (match-beginning j)) - (em (match-end j))) - (when (and (integerp em) - (integerp bm)) - (when (eq (ivy-alist-setting ivy-re-builders-alist t) #'ivy--regex-fuzzy) - (while (and (< j ivy--subexps) - (integerp (match-beginning (+ j 1))) - (= em (match-beginning (+ j 1)))) - (setq em (match-end (cl-incf j))))) - (funcall adder-fn - bm em - (nth (1+ (mod (+ i 2) (1- (length faces)))) - faces) - i) - (cl-incf i)))))) - -(defcustom swiper-action-recenter nil - "When non-nil, recenter after exiting `swiper'." - :type 'boolean) -(defvar evil-search-module) -(defvar evil-ex-search-pattern) -(defvar evil-ex-search-persistent-highlight) -(defvar evil-ex-search-direction) -(declare-function evil-ex-search-activate-highlight "evil-ex") - -(defun swiper--maybe-recenter () - (cond (swiper-action-recenter - (recenter)) - ((swiper--recenter-p) - (when swiper--current-window-start - (set-window-start (selected-window) swiper--current-window-start)) - (when (or - (< (point) (window-start)) - (> (point) (window-end (ivy-state-window ivy-last) t))) - (recenter)))) - (setq swiper--current-window-start (window-start))) - -(defun swiper--line-number (x) - (or (get-text-property 0 'swiper-line-number x) - (get-text-property 1 'swiper-line-number x))) - -(defcustom swiper-verbose t - "When non-nil, print more informational messages." - :type 'boolean) - -(defun swiper--push-mark () - (when (/= (point) swiper--opoint) - (unless (and transient-mark-mode mark-active) - (when (eq ivy-exit 'done) - (push-mark swiper--opoint t) - (when swiper-verbose - (message "Mark saved where search started")))))) - -(defun swiper--action (x) - "Goto line X." - (let ((ln (1- (swiper--line-number x))) - (re (ivy--regex ivy-text)) - (case-fold-search (ivy--case-fold-p ivy-text))) - (if (null x) - (user-error "No candidates") - (with-ivy-window - (unless (equal (current-buffer) - (ivy-state-buffer ivy-last)) - (switch-to-buffer (ivy-state-buffer ivy-last))) - (goto-char - (if (buffer-narrowed-p) - swiper--point-min - (point-min))) - (funcall (if swiper-use-visual-line - #'line-move - #'forward-line) - ln) - (when (and (re-search-forward re (line-end-position) t) swiper-goto-start-of-match) - (goto-char (match-beginning 0))) - (swiper--ensure-visible) - (swiper--maybe-recenter) - (swiper--push-mark) - (swiper--remember-search-history re))))) - -(defun swiper--remember-search-history (re) - "Add the search pattern RE to the search history ring." - (add-to-history - 'regexp-search-ring - re - regexp-search-ring-max) - ;; integration with evil-mode's search - (when (bound-and-true-p evil-mode) - (when (eq evil-search-module 'isearch) - (setq isearch-string ivy-text)) - (when (eq evil-search-module 'evil-search) - (add-to-history 'evil-ex-search-history re) - (setq evil-ex-search-pattern (list re t t)) - (setq evil-ex-search-direction 'forward) - (when evil-ex-search-persistent-highlight - (evil-ex-search-activate-highlight evil-ex-search-pattern))))) - -(defun swiper-from-isearch () - "Invoke `swiper' from isearch." - (interactive) - (let ((query (if isearch-regexp - isearch-string - (regexp-quote isearch-string)))) - (isearch-exit) - (swiper query))) - -(defvar swiper-multi-buffers nil - "Store the current list of buffers.") - -(defvar swiper-multi-candidates nil - "Store the list of candidates for `swiper-multi'.") - -(defun swiper-multi-prompt () - "Return prompt for `swiper-multi'." - (format "Buffers (%s): " - (mapconcat #'identity swiper-multi-buffers ", "))) - -(defvar swiper-window-width 80) - -(defun swiper-multi () - "Select one or more buffers. -Run `swiper' for those buffers." - (interactive) - (setq swiper-multi-buffers nil) - (let ((ivy-use-virtual-buffers nil)) - (ivy-read (swiper-multi-prompt) - #'internal-complete-buffer - :action #'swiper-multi-action-1)) - (let ((swiper-window-width (- (- (frame-width) (if (display-graphic-p) 0 1)) 4))) - (ivy-read "Swiper: " swiper-multi-candidates - :action #'swiper-multi-action-2 - :caller 'swiper-multi))) - -(ivy-configure 'swiper-multi - :unwind-fn #'swiper--cleanup - :index-fn #'ivy-recompute-index-swiper - :format-fn #'swiper--all-format-function) - -(defun swiper-multi-action-1 (x) - "Add X to list of selected buffers `swiper-multi-buffers'. -If X is already part of the list, remove it instead. Quit the selection if -X is selected by either `ivy-done', `ivy-alt-done' or `ivy-immediate-done', -otherwise continue prompting for buffers." - (if (member x swiper-multi-buffers) - (progn - (setq swiper-multi-buffers (delete x swiper-multi-buffers))) - (unless (equal x "") - (setq swiper-multi-buffers (append swiper-multi-buffers (list x))))) - (let ((prompt (swiper-multi-prompt))) - (setf (ivy-state-prompt ivy-last) prompt) - (setq ivy--prompt (concat "%-4d " prompt))) - (cond ((memq this-command '(ivy-done - ivy-alt-done - ivy-immediate-done)) - (setq swiper-multi-candidates - (swiper--multi-candidates - (mapcar #'get-buffer swiper-multi-buffers)))) - ((eq this-command 'ivy-call) - (with-selected-window (active-minibuffer-window) - (delete-minibuffer-contents))))) - -(defun swiper-multi-action-2 (x) - "Move to candidate X from `swiper-multi'." - (when (> (length x) 0) - (let ((buffer-name (get-text-property 0 'buffer x))) - (when buffer-name - (with-ivy-window - (switch-to-buffer buffer-name) - (goto-char (point-min)) - (forward-line (1- (swiper--line-number x))) - (re-search-forward - (ivy--regex ivy-text) - (line-end-position) t) - (isearch-range-invisible (line-beginning-position) - (line-end-position)) - (unless (eq ivy-exit 'done) - (swiper--cleanup) - (swiper--add-overlays (ivy--regex ivy-text)))))))) - -(defun swiper-all-buffer-p (buffer) - "Return non-nil if BUFFER should be considered by `swiper-all'." - (let ((mode (buffer-local-value 'major-mode (get-buffer buffer)))) - (cond - ;; Ignore TAGS buffers, they tend to add duplicate results. - ((eq mode #'tags-table-mode) nil) - ;; Always consider dired buffers, even though they're not backed - ;; by a file. - ((eq mode #'dired-mode) t) - ;; Always consider stash buffers too, as they may have - ;; interesting content not present in any buffers. We don't #' - ;; quote to satisfy the byte-compiler. - ((eq mode 'magit-stash-mode) t) - ;; Email buffers have no file, but are useful to search - ((eq mode 'gnus-article-mode) t) - ;; Otherwise, only consider the file if it's backed by a file. - (t (buffer-file-name buffer))))) - -;;* `swiper-all' -(defun swiper-all-function (str) - "Search in all open buffers for STR." - (or - (ivy-more-chars) - (let* ((buffers (cl-remove-if-not #'swiper-all-buffer-p (buffer-list))) - (re-full ivy-regex) - re re-tail - cands match - (case-fold-search (ivy--case-fold-p str))) - (setq re (ivy-re-to-str re-full)) - (when (consp re-full) - (setq re-tail (cdr re-full))) - (dolist (buffer buffers) - (with-current-buffer buffer - (save-excursion - (goto-char (point-min)) - (while (re-search-forward re nil t) - (setq match (if (memq major-mode '(org-mode dired-mode)) - (buffer-substring-no-properties - (line-beginning-position) - (line-end-position)) - (buffer-substring - (line-beginning-position) - (line-end-position)))) - (put-text-property - 0 1 'buffer - (buffer-name) - match) - (put-text-property 0 1 'point (point) match) - (when (or (null re-tail) (ivy-re-match re-tail match)) - (push match cands)))))) - (setq ivy--old-re re-full) - (if (null cands) - (list "") - (setq ivy--old-cands (nreverse cands)))))) - -(defun swiper--all-format-function (cands) - "Format CANDS for `swiper-all'. -See `ivy-format-functions-alist' for further information." - (let* ((ww swiper-window-width) - (col2 1) - (cands-with-buffer - (mapcar (lambda (s) - (let ((buffer (get-text-property 0 'buffer s))) - (setq col2 (max col2 (length buffer))) - (cons s buffer))) cands)) - (col1 (- ww 4 col2))) - (setq cands - (mapcar (lambda (x) - (if (cdr x) - (let ((s (ivy--truncate-string (car x) col1))) - (concat - s - (make-string - (max 0 - (- ww (string-width s) (length (cdr x)))) - ?\ ) - (cdr x))) - (car x))) - cands-with-buffer)) - (ivy--format-function-generic - (lambda (str) - (ivy--add-face str 'ivy-current-match)) - (lambda (str) - str) - cands - "\n"))) - -(defvar swiper-all-map - (let ((map (make-sparse-keymap))) - (define-key map (kbd "M-q") 'swiper-all-query-replace) - map) - "Keymap for `swiper-all'.") - -;;;###autoload -(defun swiper-all (&optional initial-input) - "Run `swiper' for all open buffers." - (interactive) - (let ((swiper-window-width (- (frame-width) (if (display-graphic-p) 0 1)))) - (ivy-read "swiper-all: " 'swiper-all-function - :action #'swiper-all-action - :dynamic-collection t - :keymap swiper-all-map - :initial-input initial-input - :caller 'swiper-all))) - -(ivy-configure 'swiper-all - :update-fn 'auto - :unwind-fn #'swiper--cleanup - :format-fn #'swiper--all-format-function) - -(defun swiper-all-action (x) - "Move to candidate X from `swiper-all'." - (when (> (length x) 0) - (let ((buffer-name (get-text-property 0 'buffer x))) - (when buffer-name - (with-ivy-window - (switch-to-buffer buffer-name) - (goto-char (get-text-property 0 'point x)) - (isearch-range-invisible (line-beginning-position) - (line-end-position)) - (unless (eq ivy-exit 'done) - (swiper--cleanup) - (swiper--add-overlays (ivy--regex ivy-text)))))))) - -(defun swiper--multi-candidates (buffers) - "Extract candidates from BUFFERS." - (let ((res nil)) - (dolist (buf buffers) - (with-current-buffer buf - (setq res - (nconc - (mapcar - (lambda (s) (put-text-property 0 1 'buffer (buffer-name) s) s) - (swiper--candidates 4)) - res)))) - res)) - -;;* `swiper-isearch' -(defun swiper-isearch-function (str) - "Collect STR matches in the current buffer for `swiper-isearch'." - (with-ivy-window - (swiper--isearch-function str))) - -(defun swiper-match-usable-p () - (or search-invisible - (not (cl-find-if - (lambda (ov) - (invisible-p (overlay-get ov 'invisible))) - (overlays-at (point)))))) - -(defvar swiper--isearch-backward nil) -(defvar swiper--isearch-start-point nil) - -(defun swiper--isearch-function-1 (re backward) - (unless (string= re ".") - (let (cands) - (save-excursion - (goto-char (if backward (point-max) (point-min))) - (while (and (funcall (if backward #'re-search-backward #'re-search-forward) re nil t) - (not (and - (= (match-beginning 0) (match-end 0)) - (if backward (bobp) (eobp))))) - (when (swiper-match-usable-p) - (let ((pos (if (or backward swiper-goto-start-of-match) - (match-beginning 0) - (point)))) - (push pos cands))) - (when (= (match-beginning 0) (match-end 0)) - (if backward - (backward-char) - (forward-char))))) - (if backward - cands - (nreverse cands))))) - -(defun swiper--isearch-next-item (re cands) - (if swiper--isearch-backward - (or - (cl-position-if - (lambda (x) - (and - (< x swiper--isearch-start-point) - (eq 0 (string-match-p - re - (buffer-substring-no-properties - x swiper--isearch-start-point))))) - cands - :from-end t) - 0) - (or - (cl-position-if - (lambda (x) (> x swiper--isearch-start-point)) - cands) - 0))) - -(defun swiper--isearch-filter-ignore-order (re-full cands) - (let (filtered-cands) - (dolist (re-cons re-full cands) - (save-excursion - (dolist (cand cands) - (goto-char cand) - (beginning-of-line) - (unless (if (re-search-forward (car re-cons) (line-end-position) t) - (not (cdr re-cons)) - (cdr re-cons)) - (push cand filtered-cands)))) - (setq cands (nreverse filtered-cands)) - (setq filtered-cands nil)))) - -(defun swiper--isearch-function (str) - (let ((re-full ivy-regex)) - (unless (equal re-full "") - (let* ((case-fold-search (ivy--case-fold-p str)) - (re - (if (stringp re-full) - re-full - (mapconcat - #'ivy--regex-or-literal - (delq nil (mapcar (lambda (x) (and (cdr x) (car x))) re-full)) - "\\|"))) - (cands (swiper--isearch-function-1 re swiper--isearch-backward))) - (when (consp re-full) - (setq cands (swiper--isearch-filter-ignore-order re-full cands))) - (setq ivy--old-re re) - (ivy-set-index (swiper--isearch-next-item re cands)) - (setq ivy--old-cands cands))))) - -(defcustom swiper-isearch-highlight-delay '(2 0.2) - "When `ivy-text' is too short, delay showing the overlay. - -The default value will delay showing the overlay by 0.2 seconds -if `ivy-text' is shorter than 2 characters. - -The aim is to reduce the visual clutter, since it's very rare -that we search only for one character." - :type '(list - (integer :tag "Text length") - (float :tag "Delay in seconds"))) - -(defun swiper--delayed-add-overlays () - (if (and swiper-isearch-highlight-delay - (< (length ivy-text) (car swiper-isearch-highlight-delay))) - (setq swiper--isearch-highlight-timer - (run-with-idle-timer - (cadr swiper-isearch-highlight-delay) nil - (lambda () - (with-ivy-window - (swiper--add-overlays (ivy--regex ivy-text)))))) - (dolist (re (swiper--positive-regexps)) - (swiper--add-overlays re)))) - -(defun swiper-isearch-action (x) - "Move to X for `swiper-isearch'." - (if (or (numberp x) - (and (> (length x) 0) - (setq x (get-text-property 0 'point x)))) - (with-ivy-window - (goto-char x) - (when (and (or (eq this-command 'ivy-previous-line-or-history) - (and (eq this-command 'ivy-done) - (eq last-command 'ivy-previous-line-or-history))) - (looking-back ivy-regex (line-beginning-position))) - (goto-char (match-beginning 0))) - (isearch-range-invisible (point) (1+ (point))) - (swiper--maybe-recenter) - (if (eq ivy-exit 'done) - (progn - (swiper--push-mark) - (swiper--remember-search-history (ivy--regex ivy-text))) - (swiper--cleanup) - (swiper--delayed-add-overlays) - (swiper--add-cursor-overlay - (ivy-state-window ivy-last)))) - (swiper--cleanup))) - -(defun swiper-action-copy (_x) - "Copy line at point and go back." - (kill-new - (buffer-substring-no-properties - (line-beginning-position) (line-end-position))) - (goto-char swiper--opoint)) - -(ivy-add-actions 'swiper-isearch '(("w" swiper-action-copy "copy"))) -(ivy-add-actions 'swiper '(("w" swiper-action-copy "copy"))) - -(defun swiper-isearch-thing-at-point () - "Insert `symbol-at-point' into the minibuffer of `swiper-isearch'. -When not running `swiper-isearch' already, start it." - (interactive) - (if (window-minibuffer-p) - (let (bnd str regionp) - (with-ivy-window - (setq bnd - (if (setq regionp (region-active-p)) - (prog1 (cons (region-beginning) (region-end)) - (deactivate-mark)) - (bounds-of-thing-at-point 'symbol))) - (setq str (buffer-substring-no-properties (car bnd) (cdr bnd)))) - (insert str) - (unless regionp - (ivy--insert-symbol-boundaries))) - (let (thing) - (if (use-region-p) - (progn - (setq thing (buffer-substring-no-properties - (region-beginning) (region-end))) - (goto-char (region-beginning)) - (deactivate-mark)) - (let ((bnd (bounds-of-thing-at-point 'symbol))) - (when bnd - (goto-char (car bnd))) - (setq thing (ivy-thing-at-point)))) - (swiper-isearch thing)))) - -(defvar swiper-isearch-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map swiper-map) - (define-key map (kbd "M-n") 'swiper-isearch-thing-at-point) - map) - "Keymap for `swiper-isearch'.") - -(defun swiper--isearch-same-line-p (s1 s2) - "Check if S1 and S2 are equal and on the same line." - (and (equal s1 s2) - (<= (count-lines - (get-text-property 0 'point s2) - (get-text-property 0 'point s1)) - 1))) - -(defun swiper-isearch-format-function (cands) - (if (numberp (car-safe cands)) - (let ((re (ivy-re-to-str ivy-regex))) - (if (string= re "^$") - "" - (mapconcat - #'identity - (swiper--isearch-format - ivy--index ivy--length (or ivy--old-cands ivy--all-candidates) - re - (ivy-state-current ivy-last) - (ivy-state-buffer ivy-last)) - "\n"))) - (funcall - (ivy-alist-setting ivy-format-functions-alist t) - cands))) - -(defun swiper--line-at-point (pt) - (save-excursion - (goto-char pt) - (let ((s (buffer-substring - (line-beginning-position) - (line-end-position)))) - (if (string= s "") - s - (put-text-property 0 1 'point pt s) - (ivy-cleanup-string s))))) - -(defun swiper--isearch-highlight (str &optional current) - (let ((start 0) - (i 0) - (re (ivy-re-to-str ivy-regex))) - (catch 'done - (while (string-match re str start) - (if (= (match-beginning 0) (match-end 0)) - (throw 'done t) - (setq start (match-end 0))) - (swiper--add-properties - (if (eq current i) - swiper-faces - swiper-background-faces) - (lambda (beg end face _priority) - (add-face-text-property beg end face nil str))) - (cl-incf i))) - str)) - -(defun swiper--isearch-format (index length cands regex current buffer) - (let* ((half-height (/ ivy-height 2)) - (i (1- index)) - (j 0) - (len 0) - res s) - (with-current-buffer buffer - (while (and (>= i 0) - (swiper--isearch-same-line-p - (swiper--line-at-point (nth i cands)) - (swiper--line-at-point current))) - (cl-decf i) - (cl-incf j)) - (while (and (>= i 0) - (< len half-height)) - (setq s (swiper--line-at-point (nth i cands))) - (unless (swiper--isearch-same-line-p s (car res)) - (push (swiper--isearch-highlight s) res) - (cl-incf len)) - (cl-decf i)) - (setq res (nreverse res)) - (let ((current-str - (swiper--line-at-point current)) - (start 0)) - (dotimes (_ (1+ j)) - (string-match regex current-str start) - (setq start (match-end 0))) - (font-lock-prepend-text-property - 0 (length current-str) - 'face 'swiper-line-face current-str) - (swiper--isearch-highlight current-str j) - (push current-str res)) - (cl-incf len) - (setq i (1+ index)) - (while (and (< i length) - (swiper--isearch-same-line-p - (swiper--line-at-point (nth i cands)) - (swiper--line-at-point current))) - (cl-incf i)) - (while (and (< i length) - (< len ivy-height)) - (setq s (swiper--line-at-point (nth i cands))) - (unless (swiper--isearch-same-line-p s (car res)) - (push (swiper--isearch-highlight s) res) - (cl-incf len)) - (cl-incf i)) - (nreverse res)))) - -(defun swiper--isearch-init () - "Initialize `swiper-isearch'." - (swiper--init) - (setq swiper--isearch-start-point (point)) - (swiper-font-lock-ensure)) - -(defun swiper--isearch-unwind () - (swiper--cleanup) - (unless (or (eq ivy-exit 'done) swiper-stay-on-quit) - (goto-char swiper--opoint)) - (isearch-clean-overlays) - (swiper--ensure-visible) - (unless (or (eq ivy-exit 'done) (string= ivy-text "")) - (cl-pushnew ivy-text swiper-history))) - -;;;###autoload -(defun swiper-isearch (&optional initial-input) - "A `swiper' that's not line-based." - (interactive) - (let ((ivy-fixed-height-minibuffer t) - (cursor-in-non-selected-windows nil) - (swiper-min-highlight 1)) - (ivy-read - "Swiper: " - #'swiper-isearch-function - :initial-input initial-input - :keymap swiper-isearch-map - :dynamic-collection t - :require-match t - :action #'swiper-isearch-action - :re-builder #'swiper--re-builder - :history 'swiper-history - :extra-props (list :fname (buffer-file-name)) - :caller 'swiper-isearch))) - -(ivy-configure 'swiper-isearch - :occur #'swiper-occur - :init-fn #'swiper--isearch-init - :update-fn 'auto - :unwind-fn #'swiper--isearch-unwind - :format-fn #'swiper-isearch-format-function) - -;;;###autoload -(defun swiper-isearch-backward (&optional initial-input) - "Like `swiper-isearch' but the first result is before the point." - (interactive) - (let ((swiper--isearch-backward t)) - (swiper-isearch initial-input))) - -(defun swiper-isearch-toggle () - "Two-way toggle between `swiper-isearch' and isearch. -Intended to be bound in `isearch-mode-map' and `swiper-map'." - (interactive) - (if isearch-mode - (let ((query (if isearch-regexp - isearch-string - (regexp-quote isearch-string)))) - (isearch-exit) - (goto-char (or (and isearch-forward isearch-other-end) - (point))) - (swiper-isearch query)) - (ivy-exit-with-action - (lambda (_) - (when (looking-back (ivy-re-to-str ivy-regex) (line-beginning-position)) - (goto-char (match-beginning 0))) - (isearch-mode t) - (unless (string= ivy-text "") - (isearch-yank-string ivy-text)))))) - -(provide 'swiper) - -;;; swiper.el ends here |