[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[elpa] master 302a16a 67/67: Add 'packages/swiper/' from commit '55414c3
From: |
Oleh Krehel |
Subject: |
[elpa] master 302a16a 67/67: Add 'packages/swiper/' from commit '55414c321ca07bd86f0f1efaf8f6130617e6fad6' |
Date: |
Sun, 22 Mar 2015 17:34:14 +0000 |
branch: master
commit 302a16a15bbaf3842246293a27c77ba2fd9a56e1
Merge: 5aa7896 55414c3
Author: Oleh Krehel <address@hidden>
Commit: Oleh Krehel <address@hidden>
Add 'packages/swiper/' from commit
'55414c321ca07bd86f0f1efaf8f6130617e6fad6'
git-subtree-dir: packages/swiper
git-subtree-mainline: 5aa78963734dc6975cad8df1c8853b65a4f1b826
git-subtree-split: 55414c321ca07bd86f0f1efaf8f6130617e6fad6
---
packages/swiper/.travis.yml | 12 ++
packages/swiper/Makefile | 16 ++
packages/swiper/README.md | 16 ++
packages/swiper/counsel.el | 77 ++++++++
packages/swiper/ivy-test.el | 67 +++++++
packages/swiper/ivy.el | 413 +++++++++++++++++++++++++++++++++++++++++++
packages/swiper/swiper.el | 255 ++++++++++++++++++++++++++
7 files changed, 856 insertions(+), 0 deletions(-)
diff --git a/packages/swiper/.travis.yml b/packages/swiper/.travis.yml
new file mode 100644
index 0000000..1f5dbc7
--- /dev/null
+++ b/packages/swiper/.travis.yml
@@ -0,0 +1,12 @@
+language: emacs-lisp
+env:
+ matrix:
+ - EMACS=emacs24
+
+before_install:
+ - sudo add-apt-repository -y ppa:cassou/emacs
+ - sudo apt-get update -qq
+ - sudo apt-get install -qq $EMACS
+
+script:
+ - make test
diff --git a/packages/swiper/Makefile b/packages/swiper/Makefile
new file mode 100644
index 0000000..453f709
--- /dev/null
+++ b/packages/swiper/Makefile
@@ -0,0 +1,16 @@
+emacs ?= emacs
+
+LOAD = -l ivy.el -l swiper.el
+
+.PHONY: all compile clean
+
+all: test
+
+test:
+ $(emacs) -batch $(LOAD) -l ivy-test.el -f ert-run-tests-batch-and-exit
+
+compile:
+ $(emacs) -batch $(LOAD) --eval "(mapc #'byte-compile-file '(\"ivy.el\"
\"swiper.el\"))"
+
+clean:
+ rm -f *.elc
diff --git a/packages/swiper/README.md b/packages/swiper/README.md
new file mode 100644
index 0000000..6482463
--- /dev/null
+++ b/packages/swiper/README.md
@@ -0,0 +1,16 @@
+[](https://travis-ci.org/abo-abo/swiper)
+
+## Swiper
+
+Package for GNU Emacs that gives you an overview as you search for a regex
+
+
+
+The package uses the `ivy` back end for the overview, see also
+[swiper-helm](https://github.com/abo-abo/swiper-helm).
+
+## Screenshots
+
+
+
+There's also a one minute [video
demo](https://www.youtube.com/watch?v=s3qwiAtKjuA).
diff --git a/packages/swiper/counsel.el b/packages/swiper/counsel.el
new file mode 100644
index 0000000..07d9a66
--- /dev/null
+++ b/packages/swiper/counsel.el
@@ -0,0 +1,77 @@
+;;; consel.el --- Elisp completion at point -*- lexical-binding: t -*-
+
+;; Copyright (C) 2015 Free Software Foundation, Inc.
+
+;; Author: Oleh Krehel <address@hidden>
+
+;; 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 <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; Just call `counsel' to start completing the `obarray'.
+;; The initial (optional) input is thing-at-point.
+
+;;; Code:
+
+(require 'ivy)
+
+(defun counsel ()
+ "Elisp completion at point."
+ (interactive)
+ (counsel--generic
+ (lambda (str) (all-completions str obarray))))
+
+(defun couns-clj ()
+ "Clojure completion at point."
+ (interactive)
+ (counsel--generic
+ (lambda (str)
+ (mapcar
+ #'cl-caddr
+ (cider-sync-request:complete str ":same")))))
+
+(defun couns-git ()
+ "Find file in the current Git repository."
+ (interactive)
+ (let* ((default-directory (locate-dominating-file
+ default-directory ".git"))
+ (cands (split-string
+ (shell-command-to-string
+ "git ls-files --full-name --")
+ "\n"))
+ (file (ivy-read "Find file: " cands)))
+ (when file
+ (find-file file))))
+
+(defun counsel--generic (completion-fn)
+ "Complete thing at point with COMPLETION-FN."
+ (let* ((bnd (bounds-of-thing-at-point 'symbol))
+ (str (if bnd
+ (buffer-substring-no-properties
+ (car bnd) (cdr bnd))
+ ""))
+ (candidates (funcall completion-fn str))
+ (ivy-height 7)
+ (res (ivy-read (format "pattern (%s): " str)
+ candidates)))
+ (when (stringp res)
+ (when bnd
+ (delete-region (car bnd) (cdr bnd)))
+ (insert res))))
+
+(provide 'counsel)
+
+;;; counsel.el ends here
diff --git a/packages/swiper/ivy-test.el b/packages/swiper/ivy-test.el
new file mode 100644
index 0000000..a33f886
--- /dev/null
+++ b/packages/swiper/ivy-test.el
@@ -0,0 +1,67 @@
+;;; ivy-test.el --- tests for ivy
+
+;; Copyright (C) 2015 Free Software Foundation, Inc.
+
+;; Author: Oleh Krehel
+
+;; 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 <http://www.gnu.org/licenses/>.
+
+(require 'ert)
+
+(defvar ivy-expr nil
+ "Holds a test expression to evaluate with `ivy-eval'.")
+
+(defvar ivy-result nil
+ "Holds the eval result of `ivy-expr' by `ivy-eval'.")
+
+(defun ivy-eval ()
+ "Evaluate `ivy-expr'."
+ (interactive)
+ (setq ivy-result (eval ivy-expr)))
+
+(global-set-key (kbd "C-c e") 'ivy-eval)
+
+(defun ivy-with (expr keys)
+ "Evaluate EXPR followed by KEYS."
+ (let ((ivy-expr expr))
+ (execute-kbd-macro
+ (vconcat (kbd "C-c e")
+ (kbd keys)))
+ ivy-result))
+
+(ert-deftest ivy-read ()
+ (should (equal
+ (ivy-read "pattern: " nil)
+ nil))
+ (should (equal
+ (ivy-read "pattern: " '("42"))
+ "42"))
+ (should (equal
+ (ivy-with '(ivy-read "pattern: " '("blue" "yellow"))
+ "C-m")
+ "blue"))
+ (should (equal
+ (ivy-with '(ivy-read "pattern: " '("blue" "yellow"))
+ "y C-m")
+ "yellow"))
+ (should (equal
+ (ivy-with '(ivy-read "pattern: " '("blue" "yellow"))
+ "y DEL b C-m")
+ "blue"))
+ (should (equal
+ (ivy-with '(ivy-read "pattern: " '("blue" "yellow"))
+ "z C-m")
+ nil)))
diff --git a/packages/swiper/ivy.el b/packages/swiper/ivy.el
new file mode 100644
index 0000000..4d307f3
--- /dev/null
+++ b/packages/swiper/ivy.el
@@ -0,0 +1,413 @@
+;;; ivy.el --- Incremental Vertical completYon -*- lexical-binding: t -*-
+
+;; Copyright (C) 2015 Free Software Foundation, Inc.
+
+;; Author: Oleh Krehel <address@hidden>
+;; URL: https://github.com/abo-abo/swiper
+;; Version: 0.1.0
+;; Package-Requires: ((emacs "24.1"))
+;; 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 <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+;;
+;; This package provides `ivy-read' as an alternative to
+;; `completing-read' and similar functions.
+;;
+;; There's no intricate code to determine the best candidate.
+;; Instead, the user can navigate to it with `ivy-next-line' and
+;; `ivy-previous-line'.
+;;
+;; The matching is done by splitting the input text by spaces and
+;; re-building it into a regex.
+;; So "for example" is transformed into "\\(for\\).*\\(example\\)".
+
+;;; Code:
+;;* Customization
+(defgroup ivy nil
+ "Incremental vertical completion."
+ :group 'convenience)
+
+(defface ivy-current-match
+ '((t (:inherit highlight)))
+ "Face used by Ivy for highlighting first match.")
+
+(defcustom ivy-height 10
+ "Number of lines for the minibuffer window."
+ :type 'integer)
+
+(defcustom ivy-count-format "%-4d "
+ "The style of showing the current candidate count for `ivy-read'.
+Set this to nil if you don't want the count."
+ :type 'string)
+
+(defcustom ivy-wrap nil
+ "Whether to wrap around after the first and last candidate."
+ :type 'boolean)
+
+;;* User Visible
+;;** Keymap
+(require 'delsel)
+(defvar ivy-minibuffer-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map (kbd "C-m") 'ivy-done)
+ (define-key map (kbd "C-n") 'ivy-next-line)
+ (define-key map (kbd "C-p") 'ivy-previous-line)
+ (define-key map (kbd "C-s") 'ivy-next-line-or-history)
+ (define-key map (kbd "C-r") 'ivy-previous-line-or-history)
+ (define-key map (kbd "SPC") 'self-insert-command)
+ (define-key map (kbd "DEL") 'ivy-backward-delete-char)
+ (define-key map (kbd "M-<") 'ivy-beginning-of-buffer)
+ (define-key map (kbd "M->") 'ivy-end-of-buffer)
+ (define-key map (kbd "M-n") 'ivy-next-history-element)
+ (define-key map (kbd "M-p") 'ivy-previous-history-element)
+ (define-key map (kbd "C-g") 'minibuffer-keyboard-quit)
+ map)
+ "Keymap used in the minibuffer.")
+
+(defvar ivy-history nil
+ "History list of candidates entered in the minibuffer.
+
+Maximum length of the history list is determined by the value
+of `history-length', which see.")
+
+;;** Commands
+(defun ivy-done ()
+ "Exit the minibuffer with the selected candidate."
+ (interactive)
+ (delete-minibuffer-contents)
+ (unless (zerop ivy--length)
+ (insert ivy--current)
+ (setq ivy-exit 'done))
+ (exit-minibuffer))
+
+(defun ivy-beginning-of-buffer ()
+ "Select the first completion candidate."
+ (interactive)
+ (setq ivy--index 0))
+
+(defun ivy-end-of-buffer ()
+ "Select the last completion candidate."
+ (interactive)
+ (setq ivy--index (1- ivy--length)))
+
+(defun ivy-next-line ()
+ "Select the next completion candidate."
+ (interactive)
+ (if (>= ivy--index (1- ivy--length))
+ (when ivy-wrap
+ (ivy-beginning-of-buffer))
+ (cl-incf ivy--index)))
+
+(defun ivy-next-line-or-history ()
+ "Select the next completion candidate.
+If the input is empty, select the previous history element instead."
+ (interactive)
+ (when (string= ivy-text "")
+ (ivy-previous-history-element 1))
+ (if (>= ivy--index (1- ivy--length))
+ (when ivy-wrap
+ (ivy-beginning-of-buffer))
+ (cl-incf ivy--index)))
+
+(defun ivy-previous-line ()
+ "Select the previous completion candidate."
+ (interactive)
+ (if (zerop ivy--index)
+ (when ivy-wrap
+ (ivy-end-of-buffer))
+ (cl-decf ivy--index)))
+
+(defun ivy-previous-line-or-history ()
+ "Select the previous completion candidate.
+If the input is empty, select the previous history element instead."
+ (interactive)
+ (when (string= ivy-text "")
+ (ivy-previous-history-element 1))
+ (if (zerop ivy--index)
+ (when ivy-wrap
+ (ivy-end-of-buffer))
+ (cl-decf ivy--index)))
+
+(defun ivy-previous-history-element (arg)
+ "Forward to `previous-history-element' with ARG."
+ (interactive "p")
+ (previous-history-element arg)
+ (move-end-of-line 1))
+
+(defun ivy-next-history-element (arg)
+ "Forward to `next-history-element' with ARG."
+ (interactive "p")
+ (next-history-element arg)
+ (move-end-of-line 1))
+
+(defun ivy-backward-delete-char ()
+ "Forward to `backward-delete-char'.
+On error (read-only), quit without selecting."
+ (interactive)
+ (condition-case nil
+ (backward-delete-char 1)
+ (error
+ (minibuffer-keyboard-quit))))
+
+;;** Entry Point
+(defun ivy-read (prompt collection &optional initial-input update-fn preselect)
+ "Read a string in the minibuffer, with completion.
+
+PROMPT is a string to prompt with; normally it ends in a colon
+and a space. When PROMPT contains %d, it will be updated with
+the current number of matching candidates.
+
+COLLECTION is a list of strings.
+
+If INITIAL-INPUT is non-nil, insert it in the minibuffer initially.
+
+UPDATE-FN is called each time the current candidate(s) is changed.
+
+If PRESELECT is non-nil select the corresponding candidate out of
+the ones that match INITIAL-INPUT."
+ (cl-case (length collection)
+ (0 nil)
+ (1 (car collection))
+ (t
+ (setq ivy--index (or
+ (and preselect
+ (ivy--preselect-index
+ collection initial-input preselect))
+ 0))
+ (setq ivy--old-re nil)
+ (setq ivy--old-cands nil)
+ (setq ivy-text "")
+ (setq ivy--all-candidates collection)
+ (setq ivy--update-fn update-fn)
+ (setq ivy-exit nil)
+ (setq ivy--default (or (thing-at-point 'symbol) ""))
+ (setq ivy--prompt
+ (cond ((string-match "%.*d" prompt)
+ prompt)
+ ((string-match "%.*d" ivy-count-format)
+ (concat ivy-count-format prompt))
+ (t
+ nil)))
+ (unwind-protect
+ (minibuffer-with-setup-hook
+ #'ivy--minibuffer-setup
+ (let ((res (read-from-minibuffer
+ prompt
+ initial-input
+ ivy-minibuffer-map
+ nil
+ 'ivy-history)))
+ (when (eq ivy-exit 'done)
+ (pop ivy-history)
+ (setq ivy-history
+ (cons ivy-text (delete ivy-text ivy-history)))
+ res)))
+ (remove-hook 'post-command-hook #'ivy--exhibit)))))
+
+(defun ivy--preselect-index (candidates initial-input preselect)
+ "Return the index in CANDIDATES filtered by INITIAL-INPUT for PRESELECT."
+ (when initial-input
+ (setq candidates
+ (cl-remove-if-not
+ (lambda (x)
+ (string-match initial-input x))
+ candidates)))
+ (cl-position-if
+ (lambda (x)
+ (string-match preselect x))
+ candidates))
+
+(defvar ivy-text ""
+ "Stores the user's string as it is typed in.")
+
+(defvar ivy-exit nil
+ "Store 'done if the completion was successfully selected.
+Otherwise, store nil.")
+
+;;* Implementation
+;;** Regex
+(defvar ivy--subexps 0
+ "Number of groups in the current `ivy--regex'.")
+
+(defvar ivy--regex-hash
+ (make-hash-table :test 'equal)
+ "Store pre-computed regex.")
+
+(defun ivy--regex (str)
+ "Re-build regex from STR in case it has a space."
+ (let ((hashed (gethash str ivy--regex-hash)))
+ (if hashed
+ (prog1 (cdr hashed)
+ (setq ivy--subexps (car hashed)))
+ (cdr (puthash str
+ (let ((subs (split-string str " +" t)))
+ (if (= (length subs) 1)
+ (cons
+ (setq ivy--subexps 0)
+ (car subs))
+ (cons
+ (setq ivy--subexps (length subs))
+ (mapconcat
+ (lambda (x) (format "\\(%s\\)" x))
+ subs
+ ".*"))))
+ ivy--regex-hash)))))
+
+;;** Rest
+(defun ivy--minibuffer-setup ()
+ "Setup ivy completion in the minibuffer."
+ (set (make-local-variable 'completion-show-inline-help) nil)
+ (set (make-local-variable 'minibuffer-default-add-function)
+ (lambda ()
+ (list ivy--default)))
+ (use-local-map (make-composed-keymap ivy-minibuffer-map
+ (current-local-map)))
+ (setq-local max-mini-window-height ivy-height)
+ (add-hook 'post-command-hook #'ivy--exhibit nil t)
+ ;; show completions with empty input
+ (ivy--exhibit))
+
+(defvar ivy--all-candidates nil
+ "Store the candidates passed to `ivy-read'.")
+
+(defvar ivy--index 0
+ "Store the index of the current candidate.")
+
+(defvar ivy--length 0
+ "Store the amount of viable candidates.")
+
+(defvar ivy--current ""
+ "Current candidate.")
+
+(defvar ivy--default nil
+ "Default initial input.")
+
+(defvar ivy--update-fn nil
+ "Current function to call when current candidate(s) update.")
+
+(defun ivy--input ()
+ "Return the current minibuffer input."
+ ;; assume one-line minibuffer input
+ (buffer-substring-no-properties
+ (minibuffer-prompt-end)
+ (line-end-position)))
+
+(defun ivy--cleanup ()
+ "Delete the displayed completion candidates."
+ (save-excursion
+ (goto-char (minibuffer-prompt-end))
+ (delete-region (line-end-position) (point-max))))
+
+(defvar ivy--prompt nil
+ "Store the format-style prompt.
+When non-nil, it should contain one %d.")
+
+(defun ivy--insert-prompt ()
+ "Update the prompt according to `ivy--prompt'."
+ (when ivy--prompt
+ (let ((inhibit-read-only t)
+ (n-str (format ivy--prompt ivy--length)))
+ (save-excursion
+ (goto-char (point-min))
+ (delete-region (point-min) (minibuffer-prompt-end))
+ (set-text-properties
+ 0 (length n-str)
+ '(front-sticky t rear-nonsticky t field t read-only t face
minibuffer-prompt)
+ n-str)
+ (insert n-str))
+ ;; get out of the prompt area
+ (constrain-to-field nil (point-max)))))
+
+(defun ivy--exhibit ()
+ "Insert Ivy completions display.
+Should be run via minibuffer `post-command-hook'."
+ (setq ivy-text (ivy--input))
+ (ivy--cleanup)
+ (let ((text (ivy-completions
+ ivy-text
+ ivy--all-candidates))
+ (buffer-undo-list t)
+ deactivate-mark)
+ (when ivy--update-fn
+ (funcall ivy--update-fn))
+ (ivy--insert-prompt)
+ ;; Do nothing if while-no-input was aborted.
+ (when (stringp text)
+ (save-excursion
+ (forward-line 1)
+ (insert text)))))
+
+(defvar ivy--old-re nil
+ "Store the old regexp.")
+
+(defvar ivy--old-cands nil
+ "Store the candidates matched by `ivy--old-re'.")
+
+(defun ivy--add-face (str face)
+ "Propertize STR with FACE.
+`font-lock-append-text-property' is used, since it's better than
+`propertize' or `add-face-text-property' in this case."
+ (font-lock-append-text-property 0 (length str) 'face face str)
+ str)
+
+(defun ivy-completions (name candidates)
+ "Return as text the current completions.
+NAME is a string of words separated by spaces that is used to
+build a regex.
+CANDIDATES is a list of strings."
+ (let* ((re (ivy--regex name))
+ (cands (if (and (equal re ivy--old-re)
+ ivy--old-cands)
+ ivy--old-cands
+ (setq ivy--old-re re)
+ (ignore-errors
+ (cl-remove-if-not
+ (lambda (x) (string-match re x))
+ candidates))))
+ (tail (nthcdr ivy--index ivy--old-cands))
+ (ww (window-width))
+ idx)
+ (setq ivy--length (length cands))
+ (when (and tail ivy--old-cands)
+ (while (and tail
+ (null (setq idx (cl-position (pop tail) cands
+ :test #'equal)))))
+ (setq ivy--index (or idx 0)))
+ (setq ivy--old-cands cands)
+ (when (>= ivy--index ivy--length)
+ (setq ivy--index (max (1- ivy--length) 0)))
+ (if (null cands)
+ ""
+ (let* ((half-height (/ ivy-height 2))
+ (start (max 0 (- ivy--index half-height)))
+ (end (min (+ start (1- ivy-height)) ivy--length))
+ (cands (cl-subseq cands start end))
+ (index (min ivy--index half-height (1- (length cands)))))
+ (setq ivy--current (copy-sequence (nth index cands)))
+ (setf (nth index cands)
+ (ivy--add-face ivy--current 'ivy-current-match))
+ (concat "\n" (mapconcat
+ (lambda (s)
+ (if (> (length s) ww)
+ (concat (substring s 0 (- ww 3)) "...")
+ s))
+ cands "\n"))))))
+
+(provide 'ivy)
+
+;;; ivy.el ends here
diff --git a/packages/swiper/swiper.el b/packages/swiper/swiper.el
new file mode 100644
index 0000000..1be8676
--- /dev/null
+++ b/packages/swiper/swiper.el
@@ -0,0 +1,255 @@
+;;; swiper.el --- Isearch with an overview. Oh, man! -*- lexical-binding: t -*-
+
+;; Copyright (C) 2015 Free Software Foundation, Inc.
+
+;; Author: Oleh Krehel <address@hidden>
+;; URL: https://github.com/abo-abo/swiper
+;; Version: 0.1.0
+;; Package-Requires: ((emacs "24.1") (ivy "0.1.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 <http://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.
+;;
+;; The overview back end is `ivy'.
+;;
+;; 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 isearch-lazy-highlight-face)))
+ "Face for `swiper' matches.")
+
+(defface swiper-match-face-2
+ '((t (:inherit isearch)))
+ "Face for `swiper' matches.")
+
+(defface swiper-match-face-3
+ '((t (:inherit match)))
+ "Face for `swiper' matches.")
+
+(defface swiper-match-face-4
+ '((t (:inherit isearch)))
+ "Face for `swiper' matches.")
+
+(defface swiper-line-face
+ '((t (:inherit highlight)))
+ "Face for current `swiper' line.")
+
+(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.")
+
+(defcustom swiper-min-highlight 2
+ "Only highlight matches for regexps at least this long."
+ :type 'integer)
+
+(defvar swiper--window nil
+ "Store the current window.")
+
+(defun swiper-font-lock-ensure ()
+ "Ensure the entired buffer is highlighted."
+ (unless (or (derived-mode-p 'magit-mode)
+ (memq major-mode '(package-menu-mode emms-playlist-mode)))
+ (if (fboundp 'font-lock-ensure)
+ (font-lock-ensure)
+ (font-lock-fontify-buffer))))
+
+(defvar swiper--format-spec ""
+ "Store the current candidates format spec.")
+
+(defun swiper--candidates ()
+ "Return a list of this buffer lines."
+ (let ((n-lines (count-lines (point-min) (point-max))))
+ (unless (zerop n-lines)
+ (setq swiper--format-spec
+ (format "%%-%dd %%s" (1+ (floor (log n-lines 10)))))
+ (let ((line-number 0)
+ candidates)
+ (save-excursion
+ (goto-char (point-min))
+ (swiper-font-lock-ensure)
+ (while (< (point) (point-max))
+ (push (format swiper--format-spec
+ (cl-incf line-number)
+ (buffer-substring
+ (line-beginning-position)
+ (line-end-position)))
+ candidates)
+ (zerop (forward-line 1)))
+ (nreverse candidates))))))
+
+(defvar swiper--opoint 1
+ "The point when `swiper' starts.")
+
+;;;###autoload
+(defun swiper (&optional initial-input)
+ "`isearch' with an overview.
+When non-nil, INITIAL-INPUT is the initial search pattern."
+ (interactive)
+ (swiper--ivy initial-input))
+
+(defun swiper--init ()
+ "Perform initialization common to both completion methods."
+ (deactivate-mark)
+ (setq swiper--opoint (point))
+ (setq swiper--len 0)
+ (setq swiper--anchor (line-number-at-pos))
+ (setq swiper--window (selected-window)))
+
+(defun swiper--ivy (&optional initial-input)
+ "`isearch' with an overview using `ivy'.
+When non-nil, INITIAL-INPUT is the initial search pattern."
+ (interactive)
+ (ido-mode -1)
+ (swiper--init)
+ (let ((candidates (swiper--candidates))
+ (preselect (format
+ swiper--format-spec
+ (line-number-at-pos)
+ (regexp-quote
+ (buffer-substring-no-properties
+ (line-beginning-position)
+ (line-end-position)))))
+ res)
+ (unwind-protect
+ (setq res (ivy-read
+ (replace-regexp-in-string
+ "%s" "pattern: " swiper--format-spec)
+ candidates
+ initial-input
+ #'swiper--update-input-ivy
+ preselect))
+ (ido-mode 1)
+ (swiper--cleanup)
+ (if (null ivy-exit)
+ (goto-char swiper--opoint)
+ (swiper--action res ivy-text)))))
+
+(defun swiper--ensure-visible ()
+ "Remove overlays hiding point."
+ (let ((overlays (overlays-at (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)))))
+
+(defun swiper--cleanup ()
+ "Clean up the overlays."
+ (while swiper--overlays
+ (delete-overlay (pop swiper--overlays)))
+ (save-excursion
+ (goto-char (point-min))
+ (isearch-clean-overlays)))
+
+(defvar swiper--overlays nil
+ "Store overlays.")
+
+(defvar swiper--anchor nil
+ "A line number to which the search should be anchored.")
+
+(defvar swiper--len 0
+ "The last length of input for which an anchoring was made.")
+
+(defun swiper--update-input-ivy ()
+ "Called when `ivy' input is updated."
+ (swiper--cleanup)
+ (let* ((re (ivy--regex ivy-text))
+ (str ivy--current)
+ (num (if (string-match "^[0-9]+" str)
+ (string-to-number (match-string 0 str))
+ 0)))
+ (with-selected-window swiper--window
+ (goto-char (point-min))
+ (when (cl-plusp num)
+ (goto-char (point-min))
+ (forward-line (1- num))
+ (isearch-range-invisible (line-beginning-position)
+ (line-end-position))
+ (unless (and (> (point) (window-start))
+ (< (point) (window-end swiper--window t)))
+ (recenter)))
+ (let ((ov (make-overlay
+ (line-beginning-position)
+ (1+ (line-end-position)))))
+ (overlay-put ov 'face 'swiper-line-face)
+ (overlay-put ov 'window swiper--window)
+ (push ov swiper--overlays))
+ (swiper--add-overlays
+ re
+ (window-start swiper--window)
+ (window-end swiper--window t)))))
+
+(defun swiper--add-overlays (re beg end)
+ "Add overlays for RE regexp in current buffer between BEG and END."
+ (when (>= (length re) swiper-min-highlight)
+ (save-excursion
+ (goto-char beg)
+ ;; RE can become an invalid regexp
+ (while (and (ignore-errors (re-search-forward re end t))
+ (> (- (match-end 0) (match-beginning 0)) 0))
+ (let ((i 0))
+ (while (<= i ivy--subexps)
+ (when (match-beginning i)
+ (let ((overlay (make-overlay (match-beginning i)
+ (match-end i)))
+ (face
+ (cond ((zerop ivy--subexps)
+ (cl-caddr swiper-faces))
+ ((zerop i)
+ (car swiper-faces))
+ (t
+ (nth (1+ (mod (1- i) (1- (length swiper-faces))))
+ swiper-faces)))))
+ (push overlay swiper--overlays)
+ (overlay-put overlay 'face face)
+ (overlay-put overlay 'window swiper--window)
+ (overlay-put overlay 'priority i)))
+ (cl-incf i)))))))
+
+(defun swiper--action (x input)
+ "Goto line X and search for INPUT."
+ (if (null x)
+ (user-error "No candidates")
+ (goto-char (point-min))
+ (forward-line (1- (read x)))
+ (re-search-forward
+ (ivy--regex input) (line-end-position) t)
+ (swiper--ensure-visible)
+ (when (/= (point) swiper--opoint)
+ (unless (and transient-mark-mode mark-active)
+ (push-mark swiper--opoint t)
+ (message "Mark saved where search started")))))
+
+(provide 'swiper)
+
+;;; swiper.el ends here
- [elpa] master c4acef9 56/67: swiper.el: Remove the helm bits, (continued)
- [elpa] master c4acef9 56/67: swiper.el: Remove the helm bits, Oleh Krehel, 2015/03/22
- [elpa] master 0c85d9a 58/67: Add a custom `ivy-count-format', Oleh Krehel, 2015/03/22
- [elpa] master c2e58e9 59/67: Fix invalid package header line, Oleh Krehel, 2015/03/22
- [elpa] master a275a2a 60/67: Use `font-lock-append-text-property' to non-destructively modify a, Oleh Krehel, 2015/03/22
- [elpa] master 7876619 61/67: Update "C-n" and "C-p" bindings, Oleh Krehel, 2015/03/22
- [elpa] master f20b287 62/67: swiper.el (swiper--init): Set `swiper--opoint', Oleh Krehel, 2015/03/22
- [elpa] master bb6c40c 63/67: swiper.el (swiper-min-highlight): New defcustom, Oleh Krehel, 2015/03/22
- [elpa] master cf71b09 64/67: ivy.el (ivy-wrap): New defcustom, Oleh Krehel, 2015/03/22
- [elpa] master 55414c3 66/67: Update Copyright, Oleh Krehel, 2015/03/22
- [elpa] master 4358c03 65/67: Move swiper-helm to another repo, Oleh Krehel, 2015/03/22
- [elpa] master 302a16a 67/67: Add 'packages/swiper/' from commit '55414c321ca07bd86f0f1efaf8f6130617e6fad6',
Oleh Krehel <=