From: Oleh Krehel Date: Tue, 29 Sep 2015 14:09:53 +0000 (+0200) Subject: Merge commit 'ba49407c5b4c719dd5dcc298c260513abf0c70df' from swiper X-Git-Url: https://code.delx.au/gnu-emacs-elpa/commitdiff_plain/8b734977727d8c96e3f716bcda3e0e20ccf70fa1?hp=-c Merge commit 'ba49407c5b4c719dd5dcc298c260513abf0c70df' from swiper --- 8b734977727d8c96e3f716bcda3e0e20ccf70fa1 diff --combined packages/swiper/counsel.el index 63c9552f8,ac04e6775..ac04e6775 --- a/packages/swiper/counsel.el +++ b/packages/swiper/counsel.el @@@ -33,6 -33,7 +33,7 @@@ ;;; Code: (require 'swiper) + (require 'etags) (defvar counsel-completion-beg nil "Completion bounds start.") @@@ -81,18 -82,73 +82,73 @@@ :initial-input str :action #'counsel--el-action))) + (declare-function slime-symbol-start-pos "ext:slime") + (declare-function slime-symbol-end-pos "ext:slime") + (declare-function slime-contextual-completions "ext:slime-c-p-c") + + ;;;###autoload + (defun counsel-cl () + "Common Lisp completion at point." + (interactive) + (setq counsel-completion-beg (slime-symbol-start-pos)) + (setq counsel-completion-end (slime-symbol-end-pos)) + (ivy-read "Symbol name: " + (car (slime-contextual-completions + counsel-completion-beg + counsel-completion-end)) + :action #'counsel--el-action)) + (defun counsel--el-action (symbol) "Insert SYMBOL, erasing the previous one." (when (stringp symbol) - (when counsel-completion-beg - (delete-region - counsel-completion-beg - counsel-completion-end)) - (setq counsel-completion-beg - (move-marker (make-marker) (point))) - (insert symbol) - (setq counsel-completion-end - (move-marker (make-marker) (point))))) + (with-ivy-window + (when counsel-completion-beg + (delete-region + counsel-completion-beg + counsel-completion-end)) + (setq counsel-completion-beg + (move-marker (make-marker) (point))) + (insert symbol) + (setq counsel-completion-end + (move-marker (make-marker) (point)))))) + + (declare-function deferred:sync! "ext:deferred") + (declare-function jedi:complete-request "ext:jedi-core") + (declare-function jedi:ac-direct-matches "ext:jedi") + + (defun counsel-jedi () + "Python completion at point." + (interactive) + (let ((bnd (bounds-of-thing-at-point 'symbol))) + (if bnd + (progn + (setq counsel-completion-beg (car bnd)) + (setq counsel-completion-end (cdr bnd))) + (setq counsel-completion-beg nil) + (setq counsel-completion-end nil))) + (deferred:sync! + (jedi:complete-request)) + (ivy-read "Symbol name: " (jedi:ac-direct-matches) + :action #'counsel--py-action)) + + (defun counsel--py-action (symbol) + "Insert SYMBOL, erasing the previous one." + (when (stringp symbol) + (with-ivy-window + (when counsel-completion-beg + (delete-region + counsel-completion-beg + counsel-completion-end)) + (setq counsel-completion-beg + (move-marker (make-marker) (point))) + (insert symbol) + (setq counsel-completion-end + (move-marker (make-marker) (point))) + (when (equal (get-text-property 0 'symbol symbol) "f") + (insert "()") + (setq counsel-completion-end + (move-marker (make-marker) (point))) + (backward-char 1))))) (defvar counsel-describe-map (let ((map (make-sparse-keymap))) @@@ -114,6 -170,7 +170,7 @@@ (defun counsel--find-symbol (x) "Find symbol definition that corresponds to string X." + (ring-insert find-tag-marker-ring (point-marker)) (let ((full-name (get-text-property 0 'full-name x))) (if full-name (find-library full-name) @@@ -138,7 -195,7 +195,7 @@@ "Return current symbol at point as a string." (let ((s (thing-at-point 'symbol))) (and (stringp s) - (if (string-match "\\`[`']?\\(.*\\)'?\\'" s) + (if (string-match "\\`[`']?\\(.*?\\)'?\\'" s) (match-string 1 s) s)))) @@@ -230,11 -287,16 +287,16 @@@ (require 'info-look) (info-lookup 'symbol symbol mode)) + (defvar counsel-unicode-char-history nil + "History for `counsel-unicode-char'.") + ;;;###autoload (defun counsel-unicode-char () "Insert a Unicode character at point." (interactive) (let ((minibuffer-allow-text-properties t)) + (setq counsel-completion-beg (point)) + (setq counsel-completion-end (point)) (ivy-read "Unicode name: " (mapcar (lambda (x) (propertize @@@ -242,7 -304,12 +304,12 @@@ 'result (cdr x))) (ucs-names)) :action (lambda (char) - (insert-char (get-text-property 0 'result char)))))) + (with-ivy-window + (delete-region counsel-completion-beg counsel-completion-end) + (setq counsel-completion-beg (point)) + (insert-char (get-text-property 0 'result char)) + (setq counsel-completion-end (point)))) + :history 'counsel-unicode-char-history))) (declare-function cider-sync-request:complete "ext:cider-client") ;;;###autoload @@@ -288,7 -355,7 +355,7 @@@ (counsel-more-chars 3) (let* ((default-directory counsel--git-grep-dir) (cmd (format "git --no-pager grep --full-name -n --no-color -i -e %S" - (ivy--regex string t)))) + (setq ivy--old-re (ivy--regex string t))))) (if (<= counsel--git-grep-count 20000) (split-string (shell-command-to-string cmd) "\n" t) (counsel--gg-candidates (ivy--regex string)) @@@ -430,7 -497,9 +497,9 @@@ Skip some dotfiles unless `ivy-text' re (if (string= event "finished\n") (progn (with-current-buffer (process-buffer process) - (setq ivy--all-candidates (split-string (buffer-string) "\n" t)) + (setq ivy--all-candidates + (ivy--sort-maybe + (split-string (buffer-string) "\n" t))) (setq ivy--old-cands ivy--all-candidates)) (ivy--exhibit)) (if (string= event "exited abnormally with code 1\n") @@@ -444,7 -513,11 +513,11 @@@ (call-process shell-file-name nil nil nil shell-command-switch - (format "xdg-open %s" (shell-quote-argument x)))) + (format "%s %s" + (if (eq system-type 'darwin) + "open" + "xdg-open") + (shell-quote-argument x)))) (declare-function dired-jump "dired-x") (defun counsel-locate-action-dired (x) @@@ -454,16 -527,33 +527,33 @@@ (defvar counsel-locate-history nil "History for `counsel-locate'.") + (defcustom counsel-locate-options (if (eq system-type 'darwin) + '("-i") + '("-i" "--regex")) + "Command line options for `locate`." + :group 'ivy + :type '(repeat string)) + (ivy-set-actions 'counsel-locate '(("x" counsel-locate-action-extern "xdg-open") ("d" counsel-locate-action-dired "dired"))) + (defun counsel-unquote-regex-parens (str) + (replace-regexp-in-string + "\\\\)" ")" + (replace-regexp-in-string + "\\\\(" "(" + str))) + (defun counsel-locate-function (str &rest _u) (if (< (length str) 3) (counsel-more-chars 3) (counsel--async-command - (concat "locate -i --regex " (ivy--regex str))) + (format "locate %s '%s'" + (mapconcat #'identity counsel-locate-options " ") + (counsel-unquote-regex-parens + (ivy--regex str)))) '("" "working..."))) ;;;###autoload @@@ -783,22 -873,50 +873,50 @@@ Usable with `ivy-resume', `ivy-next-lin (t (error "Tags alignment failed"))) (org-move-to-column col))) + (defun counsel-org--set-tags () + (counsel-org-change-tags + (if counsel-org-tags + (format ":%s:" + (mapconcat #'identity counsel-org-tags ":")) + ""))) + + (defvar org-agenda-bulk-marked-entries) + + (declare-function org-get-at-bol "org") + (declare-function org-agenda-error "org-agenda") + (defun counsel-org-tag-action (x) (if (member x counsel-org-tags) (progn (setq counsel-org-tags (delete x counsel-org-tags))) - (setq counsel-org-tags (append counsel-org-tags (list x))) - (unless (member x ivy--all-candidates) - (setq ivy--all-candidates (append ivy--all-candidates (list x))))) + (unless (equal x "") + (setq counsel-org-tags (append counsel-org-tags (list x))) + (unless (member x ivy--all-candidates) + (setq ivy--all-candidates (append ivy--all-candidates (list x)))))) (let ((prompt (counsel-org-tag-prompt))) (setf (ivy-state-prompt ivy-last) prompt) (setq ivy--prompt (concat "%-4d " prompt))) - (cond ((memq this-command '(ivy-done ivy-alt-done)) - (counsel-org-change-tags - (if counsel-org-tags - (format ":%s:" - (mapconcat #'identity counsel-org-tags ":")) - ""))) + (cond ((memq this-command '(ivy-done + ivy-alt-done + ivy-immediate-done)) + (if (eq major-mode 'org-agenda-mode) + (if (null org-agenda-bulk-marked-entries) + (let ((hdmarker (or (org-get-at-bol 'org-hd-marker) + (org-agenda-error)))) + (with-current-buffer (marker-buffer hdmarker) + (goto-char hdmarker) + (counsel-org--set-tags))) + (let ((add-tags (copy-sequence counsel-org-tags))) + (dolist (m org-agenda-bulk-marked-entries) + (with-current-buffer (marker-buffer m) + (save-excursion + (goto-char m) + (setq counsel-org-tags + (delete-dups + (append (split-string (org-get-tags-string) ":" t) + add-tags))) + (counsel-org--set-tags)))))) + (counsel-org--set-tags))) ((eq this-command 'ivy-call) (delete-minibuffer-contents)))) @@@ -824,15 -942,25 +942,25 @@@ "Add or remove tags in org-mode." (interactive) (save-excursion - (unless (org-at-heading-p) - (org-back-to-heading t)) - (setq counsel-org-tags (split-string (org-get-tags-string) ":" t)) + (if (eq major-mode 'org-agenda-mode) + (if org-agenda-bulk-marked-entries + (setq counsel-org-tags nil) + (let ((hdmarker (or (org-get-at-bol 'org-hd-marker) + (org-agenda-error)))) + (with-current-buffer (marker-buffer hdmarker) + (goto-char hdmarker) + (setq counsel-org-tags + (split-string (org-get-tags-string) ":" t))))) + (unless (org-at-heading-p) + (org-back-to-heading t)) + (setq counsel-org-tags (split-string (org-get-tags-string) ":" t))) (let ((org-setting-tags t) (org-last-tags-completion-table (append org-tag-persistent-alist (or org-tag-alist (org-get-buffer-tags)) (and - org-complete-tags-always-offer-all-agenda-tags + (or org-complete-tags-always-offer-all-agenda-tags + (eq major-mode 'org-agenda-mode)) (org-global-tags-completion-table (org-agenda-files)))))) (ivy-read (counsel-org-tag-prompt) @@@ -858,11 -986,9 +986,9 @@@ "Grep in the current directory for STRING." (if (< (length string) 3) (counsel-more-chars 3) - (let ((regex (replace-regexp-in-string - "\\\\)" ")" - (replace-regexp-in-string - "\\\\(" "(" - (ivy--regex string))))) + (let ((regex (counsel-unquote-regex-parens + (setq ivy--old-re + (ivy--regex string))))) (counsel--async-command (format "ag --noheading --nocolor %S" regex)) nil))) @@@ -912,6 -1038,54 +1038,54 @@@ INITIAL-INPUT can be given as the initi (unless (string-match "pdf$" x) (swiper ivy-text))))))) + (defcustom counsel-yank-pop-truncate nil + "When non-nil, truncate the display of long strings." + :group 'ivy) + + ;;;###autoload + (defun counsel-yank-pop () + "Ivy replacement for `yank-pop'." + (interactive) + (if (eq last-command 'yank) + (progn + (setq counsel-completion-end (point)) + (setq counsel-completion-beg + (save-excursion + (search-backward (car kill-ring)) + (point)))) + (setq counsel-completion-beg (point)) + (setq counsel-completion-end (point))) + (let ((candidates (cl-remove-if + (lambda (s) + (or (< (length s) 3) + (string-match "\\`[\n[:blank:]]+\\'" s))) + (delete-dups kill-ring)))) + (when counsel-yank-pop-truncate + (setq candidates + (mapcar (lambda (s) + (if (string-match "\\`\\(.*\n.*\n.*\n.*\\)\n" s) + (progn + (let ((s (copy-sequence s))) + (put-text-property + (match-end 1) + (length s) + 'display + " [...]" + s) + s)) + s)) + candidates))) + (ivy-read "kill-ring: " candidates + :action 'counsel-yank-pop-action))) + + (defun counsel-yank-pop-action (s) + "Insert S into the buffer, overwriting the previous yank." + (with-ivy-window + (delete-region counsel-completion-beg + counsel-completion-end) + (insert (substring-no-properties s)) + (setq counsel-completion-end (point)))) + (provide 'counsel) ;;; counsel.el ends here diff --combined packages/swiper/ivy.el index 21197c3e3,04c254e8e..04c254e8e --- a/packages/swiper/ivy.el +++ b/packages/swiper/ivy.el @@@ -44,7 -44,10 +44,10 @@@ :group 'convenience) (defface ivy-current-match - '((t (:inherit highlight))) + '((((class color) (background light)) + :background "#1a4b77" :foreground "white") + (((class color) (background dark)) + :background "#65a7e2" :foreground "black")) "Face used by Ivy for highlighting first match.") (defface ivy-confirm-face @@@ -78,6 -81,17 +81,17 @@@ and the candidate count. "Whether to wrap around after the first and last candidate." :type 'boolean) + (defcustom ivy-display-style nil + "The style for formatting the minibuffer. + + By default, the matched strings will be copied as they are. + + With the fancy method, the matching parts of the regexp will be + additionally highlighted, just like `swiper' does it." + :type '(choice + (const :tag "Plain" nil) + (const :tag "Fancy" fancy))) + (defcustom ivy-on-del-error-function 'minibuffer-keyboard-quit "The handler for when `ivy-backward-delete-char' throws. This is usually meant as a quick exit out of the minibuffer." @@@ -123,8 -137,6 +137,6 @@@ Only \"./\" and \"../\" apply here. The (define-key map (kbd "M-d") 'ivy-kill-word) (define-key map (kbd "M-<") 'ivy-beginning-of-buffer) (define-key map (kbd "M->") 'ivy-end-of-buffer) - (define-key map (kbd "") 'ivy-beginning-of-buffer) - (define-key map (kbd "") '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) @@@ -139,6 -151,7 +151,7 @@@ (define-key map (kbd "M-o") 'ivy-dispatching-done) (define-key map (kbd "C-k") 'ivy-kill-line) (define-key map (kbd "S-SPC") 'ivy-restrict-to-matches) + (define-key map (kbd "M-w") 'ivy-kill-ring-save) map) "Keymap used in the minibuffer.") (autoload 'hydra-ivy/body "ivy-hydra" "" t) @@@ -428,6 -441,7 +441,7 @@@ If the text hasn't changed as a result (setq ivy-exit 'done) (exit-minibuffer)) + ;;;###autoload (defun ivy-resume () "Resume the last completion session." (interactive) @@@ -481,6 -495,7 +495,7 @@@ (interactive) (ivy-set-index (max (- ivy--index ivy-height) 0))) + (defun ivy-minibuffer-grow () "Grow the minibuffer window by 1 line." (interactive) @@@ -875,6 -890,10 +890,10 @@@ candidates with each input. (let* ((hist (or history 'ivy-history)) (minibuffer-completion-table collection) (minibuffer-completion-predicate predicate) + (resize-mini-windows (cond + ((display-graphic-p) nil) + ((null resize-mini-windows) 'grow-only) + (t resize-mini-windows))) (res (read-from-minibuffer prompt (ivy-state-initial-input ivy-last) @@@ -954,6 -973,7 +973,7 @@@ This is useful for recursive `ivy-read' ((eq collection 'internal-complete-buffer) (setq coll (ivy--buffer-list "" ivy-use-virtual-buffers))) ((or (functionp collection) + (byte-code-function-p collection) (vectorp collection) (listp (car collection))) (setq coll (all-completions "" collection predicate))) @@@ -1014,6 -1034,7 +1034,7 @@@ nil))) (setf (ivy-state-initial-input ivy-last) initial-input))) + ;;;###autoload (defun ivy-completing-read (prompt collection &optional predicate require-match initial-input history def _inherit-input-method) @@@ -1038,7 -1059,11 +1059,11 @@@ The history, defaults and input-method :require-match require-match :initial-input (if (consp initial-input) (car initial-input) - initial-input) + (if (and (stringp initial-input) + (string-match "\\+" initial-input)) + (replace-regexp-in-string + "\\+" "\\\\+" initial-input) + initial-input)) :preselect (if (listp def) (car def) def) :history history :keymap nil @@@ -1209,6 -1234,8 +1234,8 @@@ Insert .* between each char. (set (make-local-variable 'minibuffer-default-add-function) (lambda () (list ivy--default))) + (when (display-graphic-p) + (setq truncate-lines t)) (setq-local max-mini-window-height ivy-height) (add-hook 'post-command-hook #'ivy--exhibit nil t) ;; show completions with empty input @@@ -1267,6 -1294,10 +1294,10 @@@ (save-excursion (goto-char (point-min)) (delete-region (point-min) (minibuffer-prompt-end)) + (when (> (length n-str) (window-width)) + (setq n-str (concat (substring n-str 0 + (max (- (window-width) 30) + 10)) "... "))) (set-text-properties 0 (length n-str) `(face minibuffer-prompt ,@std-props) n-str) @@@ -1289,6 -1320,23 +1320,23 @@@ (defvar inhibit-message) + (defun ivy--sort-maybe (collection) + "Sort COLLECTION if needed." + (let ((sort (ivy-state-sort ivy-last)) + entry) + (if (null sort) + collection + (let ((sort-fn (cond ((functionp sort) + sort) + ((setq entry (assoc (ivy-state-collection ivy-last) + ivy-sort-functions-alist)) + (cdr entry)) + (t + (cdr (assoc t ivy-sort-functions-alist)))))) + (if (functionp sort-fn) + (cl-sort (copy-sequence collection) sort-fn) + collection))))) + (defun ivy--exhibit () "Insert Ivy completions display. Should be run via minibuffer `post-command-hook'." @@@ -1301,7 -1349,8 +1349,8 @@@ (unless (equal ivy--old-text ivy-text) (while-no-input (setq ivy--all-candidates - (funcall (ivy-state-collection ivy-last) ivy-text)) + (ivy--sort-maybe + (funcall (ivy-state-collection ivy-last) ivy-text))) (setq ivy--old-text ivy-text))) (when ivy--all-candidates (ivy--insert-minibuffer @@@ -1352,7 -1401,23 +1401,23 @@@ (let ((buffer-undo-list t)) (save-excursion (forward-line 1) - (insert text)))))) + (insert text)))) + (when (display-graphic-p) + (ivy--resize-minibuffer-to-fit)))) + + (defun ivy--resize-minibuffer-to-fit () + "Resize the minibuffer window so it has enough space to display + all of the text contained in the minibuffer." + (with-selected-window (minibuffer-window) + (if (fboundp 'window-text-pixel-size) + (let ((text-height (cdr (window-text-pixel-size))) + (body-height (window-body-height nil t))) + (when (> text-height body-height) + (window-resize nil (- text-height body-height) nil t t))) + (let ((text-height (count-screen-lines)) + (body-height (window-body-height))) + (when (> text-height body-height) + (window-resize nil (- text-height body-height) nil t)))))) (declare-function colir-blend-face-background "ext:colir") @@@ -1362,7 -1427,15 +1427,15 @@@ `propertize' or `add-face-text-property' in this case." (require 'colir) (condition-case nil - (colir-blend-face-background 0 (length str) face str) + (progn + (colir-blend-face-background 0 (length str) face str) + (let ((foreground (face-foreground face))) + (when foreground + (add-face-text-property + 0 (length str) + `(:foreground ,foreground) + nil + str)))) (error (ignore-errors (font-lock-append-text-property 0 (length str) 'face face str)))) @@@ -1372,6 -1445,7 +1445,7 @@@ "Return all items that match NAME in CANDIDATES. CANDIDATES are assumed to be static." (let* ((re (funcall ivy--regex-function name)) + (re-str (if (listp re) (caar re) re)) (matcher (ivy-state-matcher ivy-last)) (case-fold-search (string= name (downcase name))) (cands (cond @@@ -1412,17 -1486,17 +1486,17 @@@ (tail (nthcdr ivy--index ivy--old-cands)) idx) (when (and tail ivy--old-cands (not (equal "^" ivy--old-re))) - (unless (and (not (equal re ivy--old-re)) + (unless (and (not (equal re-str ivy--old-re)) (or (setq ivy--index (or - (cl-position (if (and (> (length re) 0) - (eq ?^ (aref re 0))) - (substring re 1) - re) cands + (cl-position (if (and (> (length re-str) 0) + (eq ?^ (aref re-str 0))) + (substring re-str 1) + re-str) cands :test #'equal) (and ivy--directory (cl-position - (concat re "/") cands + (concat re-str "/") cands :test #'equal)))))) (while (and tail (null idx)) ;; Compare with eq to handle equal duplicates in cands @@@ -1433,7 -1507,7 +1507,7 @@@ (or (cl-position (ivy-state-preselect ivy-last) cands :test #'equal) ivy--index))) - (setq ivy--old-re (if cands re "")) + (setq ivy--old-re (if cands re-str "")) (setq ivy--old-cands cands))) (defvar ivy-format-function 'ivy-format-function-default @@@ -1442,13 -1516,16 +1516,16 @@@ This string will be inserted into the m (defun ivy-format-function-default (cands) "Transform CANDS into a string for minibuffer." - (let ((ww (window-width))) - (mapconcat - (lambda (s) - (if (> (length s) ww) - (concat (substring s 0 (- ww 3)) "...") - s)) - cands "\n"))) + (if (bound-and-true-p truncate-lines) + (mapconcat #'identity cands "\n") + (let ((ww (- (window-width) + (if (and (boundp 'fringe-mode) (eq fringe-mode 0)) 1 0)))) + (mapconcat + (lambda (s) + (if (> (length s) ww) + (concat (substring s 0 (- ww 3)) "...") + s)) + cands "\n")))) (defun ivy-format-function-arrow (cands) "Transform CANDS into a string for minibuffer." @@@ -1461,6 -1538,48 +1538,48 @@@ s)) cands "\n"))) + (defcustom swiper-minibuffer-faces + '(swiper-minibuffer-match-face-1 + swiper-minibuffer-match-face-2 + swiper-minibuffer-match-face-3 + swiper-minibuffer-match-face-4) + "List of `swiper' faces for minibuffer group matches.") + + (defun ivy--format-minibuffer-line (str) + (let ((start 0) + (str (copy-sequence str))) + (when (eq ivy-display-style 'fancy) + (unless ivy--old-re + (setq ivy--old-re (funcall ivy--regex-function ivy-text))) + (while (and (string-match ivy--old-re str start) + (> (- (match-end 0) (match-beginning 0)) 0)) + (setq start (match-end 0)) + (let ((i 0)) + (while (<= i ivy--subexps) + (let ((face + (cond ((zerop ivy--subexps) + (cadr swiper-minibuffer-faces)) + ((zerop i) + (car swiper-minibuffer-faces)) + (t + (nth (1+ (mod (+ i 2) (1- (length swiper-minibuffer-faces)))) + swiper-minibuffer-faces))))) + (if (fboundp 'add-face-text-property) + (add-face-text-property + (match-beginning i) + (match-end i) + face + nil + str) + (font-lock-append-text-property + (match-beginning i) + (match-end i) + 'face + face + str))) + (cl-incf i))))) + str)) + (defun ivy--format (cands) "Return a string for CANDS suitable for display in the minibuffer. CANDS is a list of strings." @@@ -1482,18 -1601,11 +1601,11 @@@ x)) cands))) (setq ivy--current (copy-sequence (nth index cands))) - (setf (nth index cands) - (ivy--add-face ivy--current 'ivy-current-match)) (setq cands (mapcar - (lambda (s) - (let ((s (copy-sequence s))) - (when (fboundp 'add-face-text-property) - (add-face-text-property - 0 (length s) - `(:height ,(face-attribute 'default :height) - :overline nil) nil s)) - s)) + #'ivy--format-minibuffer-line cands)) + (setf (nth index cands) + (ivy--add-face (nth index cands) 'ivy-current-match)) (let* ((ivy--index index) (res (concat "\n" (funcall ivy-format-function cands)))) (put-text-property 0 (length res) 'read-only nil res) @@@ -1556,15 -1668,16 +1668,16 @@@ When VIRTUAL is non-nil, add virtual bu (defun ivy--switch-buffer-action (buffer) "Switch to BUFFER. BUFFER may be a string or nil." - (if (zerop (length buffer)) - (switch-to-buffer - ivy-text nil 'force-same-window) - (let ((virtual (assoc buffer ivy--virtual-buffers))) - (if (and virtual - (not (get-buffer buffer))) - (find-file (cdr virtual)) + (with-ivy-window + (if (zerop (length buffer)) (switch-to-buffer - buffer nil 'force-same-window))))) + ivy-text nil 'force-same-window) + (let ((virtual (assoc buffer ivy--virtual-buffers))) + (if (and virtual + (not (get-buffer buffer))) + (find-file (cdr virtual)) + (switch-to-buffer + buffer nil 'force-same-window)))))) (defun ivy--switch-buffer-other-window-action (buffer) "Switch to BUFFER in other window. @@@ -1577,6 -1690,12 +1690,12 @@@ BUFFER may be a string or nil. (find-file-other-window (cdr virtual)) (switch-to-buffer-other-window buffer))))) + (defun ivy--rename-buffer-action (buffer) + "Rename BUFFER." + (let ((new-name (read-string "Rename buffer (to new name): "))) + (with-current-buffer buffer + (rename-buffer new-name)))) + (defvar ivy-switch-buffer-map (make-sparse-keymap)) (ivy-set-actions @@@ -1588,8 -1707,12 +1707,12 @@@ "kill") ("j" ivy--switch-buffer-other-window-action - "other"))) + "other") + ("r" + ivy--rename-buffer-action + "rename"))) + ;;;###autoload (defun ivy-switch-buffer () "Switch to another buffer." (interactive) @@@ -1601,11 -1724,15 +1724,15 @@@ :action #'ivy--switch-buffer-action :keymap ivy-switch-buffer-map)))) + ;;;###autoload (defun ivy-recentf () "Find a file on `recentf-list'." (interactive) (ivy-read "Recentf: " recentf-list - :action #'find-file)) + :action + (lambda (f) + (with-ivy-window + (find-file f))))) (defun ivy-yank-word () "Pull next word from buffer into search string." @@@ -1621,6 -1748,18 +1748,18 @@@ (when amend (insert amend)))) + (defun ivy-kill-ring-save () + "Store the current candidates into the kill ring. + If the region is active, forward to `kill-ring-save' instead." + (interactive) + (if (region-active-p) + (call-interactively 'kill-ring-save) + (kill-new + (mapconcat + #'identity + ivy--old-cands + "\n")))) + (defun ivy-insert-current () "Make the current candidate into current input. Don't finish completion." diff --combined packages/swiper/swiper.el index 1032f0486,1b2d9067a..1b2d9067a --- a/packages/swiper/swiper.el +++ b/packages/swiper/swiper.el @@@ -61,6 -61,35 +61,35 @@@ '((t (:inherit isearch-fail))) "Face for `swiper' matches modulo 3.") + (defface swiper-minibuffer-match-face-1 + '((((class color) (background light)) + :background "#d3d3d3") + (((class color) (background dark)) + :background "#555555")) + "The background face for `swiper' minibuffer matches." + :group 'function-args-faces) + + (defface swiper-minibuffer-match-face-2 + '((((class color) (background light)) + :background "#e99ce8" :weight bold) + (((class color) (background dark)) + :background "#777777" :weight bold)) + "Face for `swiper' minibuffer matches modulo 1.") + + (defface swiper-minibuffer-match-face-3 + '((((class color) (background light)) + :background "#bbbbff" :weight bold) + (((class color) (background dark)) + :background "#7777ff" :weight bold)) + "Face for `swiper' minibuffer matches modulo 2.") + + (defface swiper-minibuffer-match-face-4 + '((((class color) (background light)) + :background "#ffbbff" :weight bold) + (((class color) (background dark)) + :background "#8a498a" :weight bold)) + "Face for `swiper' minibuffer matches modulo 3.") + (defface swiper-line-face '((t (:inherit highlight))) "Face for current `swiper' line.") @@@ -144,7 -173,9 +173,9 @@@ elfeed-search-mode fundamental-mode Man-mode - woman-mode))) + woman-mode + mu4e-view-mode + mu4e-headers-mode))) (unless (> (buffer-size) 100000) (if (fboundp 'font-lock-ensure) (font-lock-ensure) @@@ -162,19 -193,21 +193,21 @@@ (unless (zerop n-lines) (setq swiper--width (1+ (floor (log n-lines 10)))) (setq swiper--format-spec - (format "%%-%dd %%s" swiper--width)) + (format "%%-%dd " swiper--width)) (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) + (let ((str (concat " " (buffer-substring + (line-beginning-position) + (line-end-position))))) + (put-text-property 0 1 'display + (format swiper--format-spec + (cl-incf line-number)) + str) + (push str candidates)) (forward-line 1)) (nreverse candidates)))))) @@@ -228,17 -261,12 +261,12 @@@ there have line numbers. In the buffer "`isearch' with an overview using `ivy'. When non-nil, INITIAL-INPUT is the initial search pattern." (interactive) - (unless (eq (length (help-function-arglist 'ivy-read)) 4) - (warn "You seem to be using the outdated stand-alone \"ivy\" package. - Please remove it and update the \"swiper\" package.")) (swiper--init) (let ((candidates (swiper--candidates)) - (preselect (format - swiper--format-spec - (line-number-at-pos) - (buffer-substring-no-properties - (line-beginning-position) - (line-end-position)))) + (preselect (buffer-substring-no-properties + (line-beginning-position) + (line-end-position))) + (minibuffer-allow-text-properties t) res) (unwind-protect (setq res (ivy-read @@@ -280,26 -308,28 +308,28 @@@ "Called when `ivy' input is updated." (with-ivy-window (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))) - (goto-char (point-min)) - (when (cl-plusp num) + (when (> (length ivy--current) 0) + (let* ((re (funcall ivy--regex-function ivy-text)) + (re (if (stringp re) re (caar re))) + (str (get-text-property 0 'display ivy--current)) + (num (if (string-match "^[0-9]+" str) + (string-to-number (match-string 0 str)) + 0))) (goto-char (point-min)) - (forward-line (1- num)) - (if (and (equal ivy-text "") - (>= swiper--opoint (line-beginning-position)) - (<= swiper--opoint (line-end-position))) - (goto-char swiper--opoint) - (re-search-forward re (line-end-position) t)) - (isearch-range-invisible (line-beginning-position) - (line-end-position)) - (unless (and (>= (point) (window-start)) - (<= (point) (window-end (ivy-state-window ivy-last) t))) - (recenter))) - (swiper--add-overlays re)))) + (when (cl-plusp num) + (goto-char (point-min)) + (forward-line (1- num)) + (if (and (equal ivy-text "") + (>= swiper--opoint (line-beginning-position)) + (<= swiper--opoint (line-end-position))) + (goto-char swiper--opoint) + (re-search-forward re (line-end-position) t)) + (isearch-range-invisible (line-beginning-position) + (line-end-position)) + (unless (and (>= (point) (window-start)) + (<= (point) (window-end (ivy-state-window ivy-last) t))) + (recenter))) + (swiper--add-overlays re))))) (defun swiper--add-overlays (re &optional beg end) "Add overlays for RE regexp in visible part of the current buffer. @@@ -347,7 -377,7 +377,7 @@@ BEG and END, when specified, are the po (if (null x) (user-error "No candidates") (goto-char (point-min)) - (forward-line (1- (read x))) + (forward-line (1- (read (get-text-property 0 'display x)))) (re-search-forward (ivy--regex input) (line-end-position) t) (swiper--ensure-visible) @@@ -366,6 -396,83 +396,83 @@@ (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 () + (format "Buffers (%s): " + (mapconcat #'identity swiper-multi-buffers ", "))) + + (defun swiper-multi () + "Select one or more buffers. + Run `swiper' for those buffers." + (interactive) + (setq swiper-multi-buffers nil) + (setq swiper-multi-candidates nil) + (ivy-read (swiper-multi-prompt) + 'internal-complete-buffer + :action 'swiper-multi-action-1) + (ivy-read "Swiper: " swiper-multi-candidates + :action 'swiper-multi-action-2 + :unwind #'swiper--cleanup)) + + (defun swiper-multi-action-1 (x) + (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)) + (let ((ww (window-width))) + (dolist (buf swiper-multi-buffers) + (with-current-buffer buf + (setq swiper-multi-candidates + (append + (mapcar + (lambda (s) + (setq s (concat s " ")) + (let ((len (length s))) + (put-text-property + (1- len) len 'display + (concat + (make-string + (max + (- ww + (string-width s) + (length (buffer-name)) + 1) + 0) + ?\ ) + (buffer-name)) + s) + s)) + (swiper--candidates)) + swiper-multi-candidates)))))) + ((eq this-command 'ivy-call) + (delete-minibuffer-contents)))) + + (defun swiper-multi-action-2 (x) + (let ((buf-space (get-text-property (1- (length x)) 'display x))) + (with-ivy-window + (when (string-match "\\` *\\([^ ]+\\)\\'" buf-space) + (switch-to-buffer (match-string 1 buf-space)) + (goto-char (point-min)) + (forward-line (1- (read x))) + (re-search-forward + (ivy--regex ivy-text) + (line-end-position) t) + (unless (eq ivy-exit 'done) + (swiper--cleanup) + (swiper--add-overlays (ivy--regex ivy-text))))))) + (provide 'swiper) ;;; swiper.el ends here