summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSean Whitton <spwhitton@spwhitton.name>2016-10-17 07:53:26 -0700
committerSean Whitton <spwhitton@spwhitton.name>2016-10-17 07:53:26 -0700
commitd126ead6f2fd24ef0ca1b631b5fdd1af870878ab (patch)
tree04c18f6b9494391c4e2fb6d225c08aac00ebd0c6
parent0828483d516497c90660d851b732206fcf5e1337 (diff)
parent378ceb9b8b8c63cd550d57248e07631de354439f (diff)
Merge tag 'v2.3.0'
Version 2.3.0 * Add support for ripgrep. * Allow showing action buffer beside helm buffer.
-rw-r--r--helm-core-pkg.el2
-rw-r--r--helm-grep.el72
-rw-r--r--helm-pkg.el4
-rw-r--r--helm-sys.el5
-rw-r--r--helm-utils.el2
-rw-r--r--helm.el239
6 files changed, 201 insertions, 123 deletions
diff --git a/helm-core-pkg.el b/helm-core-pkg.el
index a9d6fd01..91690563 100644
--- a/helm-core-pkg.el
+++ b/helm-core-pkg.el
@@ -1,6 +1,6 @@
;;; helm-core-pkg.el --- define helm-core for package.el
-(define-package "helm-core" "2.2.1"
+(define-package "helm-core" "2.3.0"
"Development files for Helm"
'((emacs "24.4")
(async "1.9"))
diff --git a/helm-grep.el b/helm-grep.el
index 1bba7523..bdebca34 100644
--- a/helm-grep.el
+++ b/helm-grep.el
@@ -417,21 +417,28 @@ It is intended to use as a let-bound variable, DON'T set this globaly.")
;; we need to pass an empty string
;; to types to avoid error.
(or include "")))
- (smartcase (if (helm-grep-use-ack-p) ""
- (unless (let ((case-fold-search nil))
- (string-match-p
- "[[:upper:]]" helm-pattern)) "i")))
+ (smartcase (if (helm-grep-use-ack-p)
+ ""
+ (unless (let ((case-fold-search nil))
+ (string-match-p
+ "[[:upper:]]" helm-pattern))
+ "i")))
(helm-grep-default-command
(concat helm-grep-default-command " %m")) ; `%m' like multi.
(patterns (split-string helm-pattern))
(pipes
(helm-aif (cdr patterns)
(cl-loop with pipcom = (pcase (helm-grep-command)
+ ;; Use grep for GNU regexp based tools.
((or "grep" "zgrep" "git-grep")
- "grep --color=always")
+ (replace-regexp-in-string
+ "\\s-\\'" ""
+ (format "grep --color=always %s"
+ (if smartcase "-i" ""))))
+ ;; Use ack-grep for PCRE based tools.
;; Sometimes ack-grep cmd is ack only.
((and (pred (string-match-p "ack")) ack)
- (format "%s --color" ack)))
+ (format "%s --smart-case --color" ack)))
for p in it concat
(format " | %s %s" pipcom (shell-quote-argument p)))
"")))
@@ -1256,49 +1263,76 @@ If a prefix arg is given run grep on all buffers ignoring non--file-buffers."
(format-spec helm-pdfgrep-default-read-command
(list (cons ?f fname) (cons ?p pageno))))))
-;;; AG - PT
+;;; AG - PT - RG
;;
;; https://github.com/ggreer/the_silver_searcher
;; https://github.com/monochromegane/the_platinum_searcher
+;; https://github.com/BurntSushi/ripgrep
(defcustom helm-grep-ag-command
"ag --line-numbers -S --hidden --color --nogroup %s %s %s"
- "The default command for AG or PT.
+ "The default command for AG, PT or RG.
+
Takes three format specs, the first for type(s), the second for pattern
and the third for directory.
+Here the command line to use with ripgrep:
+
+ rg --smart-case --no-heading --line-number %s %s %s
+
+If you want native color output with ripgrep (--color=always)
+you have to use a workaround as ripgrep is not supporting emacs
+dumb terminal, here it is:
+
+ TERM=eterm-color rg --color=always --smart-case --no-heading --line-number %s %s %s
+
You must use an output format that fit with helm grep, that is:
\"filename:line-number:string\"
The option \"--nogroup\" allow this.
The option \"--line-numbers\" is also mandatory except with PT (not supported).
+For RG the options \"--no-heading\" and \"--line-number\" are the ones to use.
-You can use safely \"--color\" (default)."
+You can use safely \"--color\" (used by default) with AG and PT."
:group 'helm-grep
:type 'string)
(defun helm-grep--ag-command ()
- (car (split-string helm-grep-ag-command)))
+ (car (helm-remove-if-match
+ "\\`[A-Z]*=" (split-string helm-grep-ag-command))))
(defun helm-grep-ag-get-types ()
"Returns a list of AG types if available with AG version.
-See AG option \"--list-file-types\"."
+See AG option \"--list-file-types\"
+Ripgrep (rg) types are also supported if this backend is used."
(with-temp-buffer
- (when (equal (call-process (helm-grep--ag-command)
- nil t nil "--list-file-types") 0)
- (goto-char (point-min))
- (cl-loop while (re-search-forward "^ *\\(--[a-z]*\\)" nil t)
- collect (match-string 1)))))
+ (let* ((com (helm-grep--ag-command))
+ (ripgrep (string= com "rg"))
+ (regex (if ripgrep "^\\(.*\\):" "^ *\\(--[a-z]*\\)"))
+ (prefix (if ripgrep "-t" "")))
+ (when (equal (call-process com
+ nil t nil
+ (if ripgrep
+ "--type-list" "--list-file-types")) 0)
+ (goto-char (point-min))
+ (cl-loop while (re-search-forward regex nil t)
+ for type = (match-string 1)
+ collect (cons type (concat prefix type)))))))
(defun helm-grep-ag-prepare-cmd-line (pattern directory &optional type)
"Prepare AG command line to search PATTERN in DIRECTORY.
When TYPE is specified it is one of what returns `helm-grep-ag-get-types'
if available with current AG version."
(let* ((patterns (split-string pattern))
- (pipe-cmd (cond ((executable-find "ack") "ack --color")
- ((executable-find "ack-grep") "ack-grep --color")
- (t "grep --perl-regexp --color=always")))
+ (smartcase (let ((case-fold-search nil))
+ (string-match-p
+ "[[:upper:]]" helm-pattern)))
+ (pipe-cmd (cond ((executable-find "ack") "ack --smart-case --color")
+ ((executable-find "ack-grep") "ack-grep --smart-case --color")
+ (t (replace-regexp-in-string
+ "\\s-\\'" "" (format "grep --perl-regexp --color=always %s"
+ (if smartcase "-i" ""))))))
(cmd (format helm-grep-ag-command
(mapconcat 'identity type " ")
(shell-quote-argument (car patterns))
diff --git a/helm-pkg.el b/helm-pkg.el
index 0253ca55..e4f231a9 100644
--- a/helm-pkg.el
+++ b/helm-pkg.el
@@ -1,11 +1,11 @@
;;; helm-pkg.el --- define helm for package.el
-(define-package "helm" "2.2.1"
+(define-package "helm" "2.3.0"
"Helm is an Emacs incremental and narrowing framework"
'((emacs "24.4")
(async "1.9")
(popup "0.5.3")
- (helm-core "2.2.1"))
+ (helm-core "2.3.0"))
:url "https://emacs-helm.github.io/helm/")
;; Local Variables:
diff --git a/helm-sys.el b/helm-sys.el
index 3230a0ca..7a13bab2 100644
--- a/helm-sys.el
+++ b/helm-sys.el
@@ -113,7 +113,7 @@ This affect also sorting functions in the same way."
(cancel-timer helm-top--poll-timer))
(condition-case nil
(progn
- (when (and (helm-alive-p) (null no-update))
+ (when (and (helm-alive-p) (not (helm-action-window)) (null no-update))
;; Fix quitting while process is running
;; by binding `with-local-quit' in init function
;; Issue #1521.
@@ -421,7 +421,8 @@ Show actions only on line starting by a PID."
(helm :sources 'helm-source-top
:buffer "*helm top*" :full-frame t
:candidate-number-limit 9999
- :preselect "^\\s-*[0-9]+")
+ :preselect "^\\s-*[0-9]+"
+ :truncate-lines helm-show-action-window-other-window)
(remove-hook 'helm-after-update-hook 'helm-top--skip-top-line))))
;;;###autoload
diff --git a/helm-utils.el b/helm-utils.el
index 63bcdb8f..bb91bc6e 100644
--- a/helm-utils.el
+++ b/helm-utils.el
@@ -648,7 +648,7 @@ If STRING is non--nil return instead a space separated string."
(set-window-text-height (helm-window) helm-resize-on-pa-text-height)))
(defun helm-match-line-cleanup-pulse ()
- (run-with-idle-timer 0.3 nil #'helm-match-line-cleanup))
+ (run-with-timer 0.3 nil #'helm-match-line-cleanup))
(add-hook 'helm-after-persistent-action-hook 'helm-persistent-autoresize-hook)
(add-hook 'helm-cleanup-hook 'helm-match-line-cleanup)
diff --git a/helm.el b/helm.el
index e78d8a3d..f0978804 100644
--- a/helm.el
+++ b/helm.el
@@ -605,6 +605,12 @@ See `helm-log-save-maybe' for more info."
:type 'string
:group 'helm)
+(defcustom helm-show-action-window-other-window nil
+ "Show action buffer beside `helm-buffer' when non-nil.
+Note that this may not fit well with some helm window configurations,
+so it have only effect when `helm-always-two-windows' is non-nil."
+ :group 'helm
+ :type 'boolean)
;;; Faces
;;
@@ -1023,6 +1029,7 @@ You should not modify this yourself unless you know what you are doing.")
"Flag to prevent helm popping up errors in candidates functions.
Should be set in candidates functions if needed, will be restored
at end of session.")
+(defvar helm--action-prompt "Select action: ")
;; Utility: logging
(defun helm-log (format-string &rest args)
@@ -2382,7 +2389,7 @@ For ANY-PRESELECT ANY-RESUME ANY-KEYMAP ANY-DEFAULT ANY-HISTORY, See `helm'."
(helm-get-current-source))
(helm-mark-current-line t)
(helm-update any-preselect))
- (with-current-buffer (helm-buffer-get)
+ (with-helm-buffer
(let* ((src (helm-get-current-source))
(src-keymap (assoc-default 'keymap src))
(hist (or (and any-history (symbolp any-history) any-history)
@@ -3555,36 +3562,56 @@ If action buffer is selected, back to the helm buffer."
(setq helm-saved-selection (helm-get-selection nil nil src))
(with-selected-frame (with-helm-window (selected-frame))
(prog1
- (cond ((get-buffer-window helm-action-buffer 'visible)
- (set-window-buffer (get-buffer-window helm-action-buffer)
- helm-buffer)
- (kill-buffer helm-action-buffer)
- (setq helm-saved-selection nil)
- (helm-set-pattern helm-input 'noupdate))
- (helm-saved-selection
- (setq helm-saved-current-source src)
- (let ((actions (helm-get-actions-from-current-source src)))
- (if (functionp actions)
- (message "Sole action: %s"
- (if (or (consp actions)
- (byte-code-function-p actions))
- "Anonymous" actions))
- (helm-show-action-buffer actions)
- ;; Be sure the minibuffer is entirely deleted (#907).
- (helm--delete-minibuffer-contents-from "")
- ;; Make `helm-pattern' differs from the previous value.
- (setq helm-pattern 'dummy)
- (helm-check-minibuffer-input))))
- (t (message "No Actions available")))
+ (helm-acond ((get-buffer-window helm-action-buffer 'visible)
+ (set-window-buffer (get-buffer-window helm-action-buffer)
+ helm-buffer)
+ (helm--set-action-prompt 'restore)
+ (when (and helm-show-action-window-other-window
+ helm-always-two-windows)
+ (delete-window it))
+ (kill-buffer helm-action-buffer)
+ (setq helm-saved-selection nil)
+ (helm-set-pattern helm-input 'noupdate))
+ (helm-saved-selection
+ (setq helm-saved-current-source src)
+ (let ((actions (helm-get-actions-from-current-source src))
+ helm-onewindow-p)
+ (if (functionp actions)
+ (message "Sole action: %s"
+ (if (or (consp actions)
+ (byte-code-function-p actions))
+ "Anonymous" actions))
+ (helm-show-action-buffer actions)
+ ;; Be sure the minibuffer is entirely deleted (#907).
+ (helm--delete-minibuffer-contents-from "")
+ (helm--set-action-prompt)
+ (helm-check-minibuffer-input))))
+ (t (message "No Actions available")))
(helm-display-mode-line (helm-get-current-source))
(run-hooks 'helm-window-configuration-hook))))))
(put 'helm-select-action 'helm-only t)
+(defun helm--set-action-prompt (&optional restore)
+ (with-selected-window (minibuffer-window)
+ (let ((inhibit-read-only t)
+ (props '(face minibuffer-prompt
+ field t
+ read-only t
+ rear-nonsticky t
+ front-sticky t))
+ (prt (if restore helm--prompt helm--action-prompt)))
+ (erase-buffer)
+ (insert (apply #'propertize prt props)))))
+
(defun helm-show-action-buffer (actions)
(with-current-buffer (get-buffer-create helm-action-buffer)
(erase-buffer)
(buffer-disable-undo)
- (set-window-buffer (get-buffer-window helm-buffer) helm-action-buffer)
+ (set-window-buffer (if (and helm-show-action-window-other-window
+ helm-always-two-windows)
+ (split-window (get-buffer-window helm-buffer) nil 'right)
+ (get-buffer-window helm-buffer))
+ helm-action-buffer)
(set (make-local-variable 'helm-sources)
(list
(helm-build-sync-source "Actions"
@@ -3592,7 +3619,7 @@ If action buffer is selected, back to the helm buffer."
:nomark t
:keymap 'helm-map
:candidates actions
- :mode-line '("Action(s)" "TAB:BackToCands RET/f1/f2/fn:NthAct")
+ :mode-line '("Action(s)" "\\<helm-map>\\[helm-select-action]:BackToCands RET/f1/f2/fn:NthAct")
:candidate-transformer
(lambda (candidates)
(cl-loop for (i . j) in candidates
@@ -3684,8 +3711,9 @@ mode and header lines."
(propertize (format " [prefarg:%s]" arg)
'face 'helm-prefarg)))))
" "
- (:eval (helm-show-candidate-number
- (car-safe helm-mode-line-string)))
+ (:eval (with-helm-buffer
+ (helm-show-candidate-number
+ (car-safe helm-mode-line-string))))
" " helm--mode-line-string-real " "
(:eval (make-string (window-width) ? )))
keymap (keymap (mode-line keymap
@@ -3709,9 +3737,9 @@ mode and header lines."
(helm--set-header-line))
(helm-display-header-line
(let ((hlstr (helm-interpret-value
- (and (listp source)
- (assoc-default 'header-line source))
- source))
+ (and (listp source)
+ (assoc-default 'header-line source))
+ source))
(endstr (make-string (window-width) ? )))
(setq header-line-format
(propertize (concat " " hlstr endstr)
@@ -3726,7 +3754,9 @@ mode and header lines."
(cont (buffer-substring beg end))
(pref (propertize
" "
- 'display (if (string-match-p (regexp-quote helm--prompt) cont)
+ 'display (if (string-match-p (regexp-opt `(,helm--prompt
+ ,helm--action-prompt))
+ cont)
'(space :width left-fringe)
(propertize
"->"
@@ -4674,37 +4704,51 @@ Returns the resulting buffer."
"Toggle resplit helm window, vertically or horizontally."
(interactive)
(with-helm-alive-p
- (when helm-prevent-escaping-from-minibuffer
- (helm-prevent-switching-other-window :enabled nil))
- (unwind-protect
- (with-helm-window
- (if (or helm-full-frame (one-window-p t))
- (message "Error: Attempt to resplit a single window")
- (let ((before-height (window-height)))
- (delete-window)
- (set-window-buffer
- (select-window
- (if (= (window-height) before-height) ; initial split was horizontal.
- ;; Split window vertically with `helm-buffer' placed
- ;; on the good side according to actual value of
- ;; `helm-split-window-default-side'.
- (prog1
- (cond ((or (eq helm-split-window-default-side 'above)
- (eq helm-split-window-default-side 'left))
- (split-window
- (selected-window) nil 'above))
- (t (split-window-vertically)))
- (setq helm-split-window-state 'vertical))
- ;; Split window vertically, same comment as above.
- (setq helm-split-window-state 'horizontal)
- (cond ((or (eq helm-split-window-default-side 'left)
- (eq helm-split-window-default-side 'above))
- (split-window (selected-window) nil 'left))
- (t (split-window-horizontally)))))
- helm-buffer)))
- (setq helm--window-side-state (helm--get-window-side-state)))
- (when helm-prevent-escaping-from-minibuffer
- (helm-prevent-switching-other-window :enabled t)))))
+ (if(= (length (window-list nil 1)) 2)
+ (progn
+ (when helm-prevent-escaping-from-minibuffer
+ (helm-prevent-switching-other-window :enabled nil))
+ (unwind-protect
+ (with-helm-window
+ (cond ((or helm-full-frame (one-window-p t))
+ (user-error "Attempt to resplit a single window"))
+ ((helm-action-window)
+ (user-error "Can't resplit while selecting actions"))
+ (t
+ (let* ((before-height (window-height))
+ (ow (or (and (window-live-p helm-persistent-action-display-window)
+ helm-persistent-action-display-window)
+ (get-buffer-window helm-current-buffer)))
+ (ow-buf (window-buffer ow)))
+ (delete-window ow)
+ (set-window-buffer
+ (if (= (window-height) before-height) ; initial split was horizontal.
+ ;; Split window vertically with `helm-buffer' placed
+ ;; on the good side according to actual value of
+ ;; `helm-split-window-default-side'.
+ (prog1
+ (cond ((or (eq helm-split-window-default-side 'above)
+ (eq helm-split-window-default-side 'left))
+ (split-window (helm-window) nil 'below))
+ ((or (eq helm-split-window-default-side 'below)
+ (eq helm-split-window-default-side 'right))
+ (split-window (helm-window) nil 'above))
+ (t (split-window-vertically)))
+ (setq helm-split-window-state 'vertical))
+ ;; Split window vertically, same comment as above.
+ (setq helm-split-window-state 'horizontal)
+ (cond ((or (eq helm-split-window-default-side 'left)
+ (eq helm-split-window-default-side 'above))
+ (split-window (helm-window) nil 'right))
+ ((or (eq helm-split-window-default-side 'right)
+ (eq helm-split-window-default-side 'below))
+ (split-window (helm-window) nil 'left))
+ (t (split-window-horizontally))))
+ ow-buf))))
+ (setq helm--window-side-state (helm--get-window-side-state))))
+ (when helm-prevent-escaping-from-minibuffer
+ (helm-prevent-switching-other-window :enabled t)))
+ (error "current window configuration not suitable for splitting"))))
(put 'helm-toggle-resplit-window 'helm-only t)
;; Utility: Resize helm window.
@@ -4734,43 +4778,42 @@ If N is positive enlarge, if negative narrow."
"Swap window holding `helm-buffer' with other window."
(interactive)
(with-helm-alive-p
- (if (and helm-full-frame (one-window-p t))
- (error "Error: Can't swap windows in a single window")
- (let* ((w1 (helm-window))
- (split-state (eq helm-split-window-state 'horizontal))
- (w1size (window-total-size w1 split-state))
- (b1 (window-buffer w1)) ; helm-buffer
- (s1 (window-start w1))
- (cur-frame (window-frame w1))
- (w2 (with-selected-window (helm-window)
- ;; Don't try to display helm-buffer
- ;; in a dedicated window.
- (get-window-with-predicate
- (lambda (w) (not (window-dedicated-p w)))
- 1 cur-frame)))
- (w2size (window-total-size w2 split-state))
- (b2 (window-buffer w2)) ; probably helm-current-buffer
- (s2 (window-start w2))
- resize)
- (with-selected-frame (window-frame w1)
- (helm-replace-buffer-in-window w1 b1 b2)
- (helm-replace-buffer-in-window w2 b2 b1)
- (setq resize
- (cond ( ;; helm-window is smaller than other window.
- (< w1size w2size)
- (- (- (max w2size w1size)
- (min w2size w1size))))
- ( ;; helm-window is larger than other window.
- (> w1size w2size)
- (- (max w2size w1size)
- (min w2size w1size)))
- ( ;; windows have probably same size.
- t nil)))
- ;; Maybe resize the window holding helm-buffer.
- (and resize (window-resize w2 resize split-state))
- (set-window-start w1 s2 t)
- (set-window-start w2 s1 t))
- (setq helm--window-side-state (helm--get-window-side-state))))))
+ (if (= (length (window-list nil 1)) 2)
+ (cond ((and helm-full-frame (one-window-p t))
+ (user-error "Can't swap windows in a single window"))
+ ((helm-action-window)
+ (user-error "Can't resplit while selecting actions"))
+ (t
+ (let* ((w1 (helm-window))
+ (split-state (eq helm-split-window-state 'horizontal))
+ (w1size (window-total-size w1 split-state))
+ (s1 (window-start w1))
+ (w2 (or (and (window-live-p helm-persistent-action-display-window)
+ helm-persistent-action-display-window)
+ (get-buffer-window helm-current-buffer)))
+ (w2size (window-total-size w2 split-state))
+ (b2 (window-buffer w2)) ; probably helm-current-buffer
+ (s2 (window-start w2))
+ (resize (cond ( ;; helm-window is smaller than other window.
+ (< w1size w2size)
+ (- (- (max w2size w1size)
+ (min w2size w1size))))
+ ( ;; helm-window is larger than other window.
+ (> w1size w2size)
+ (- (max w2size w1size)
+ (min w2size w1size)))
+ ( ;; windows have probably same size.
+ t nil))))
+ (with-selected-frame (window-frame w1)
+ (delete-window w2)
+ (set-window-buffer
+ (setq w2 (split-window w1 nil helm--window-side-state)) b2)
+ ;; Maybe resize the window holding helm-buffer.
+ (and resize (window-resize w2 resize split-state))
+ (set-window-start w1 s2 t)
+ (set-window-start w2 s1 t))
+ (setq helm--window-side-state (helm--get-window-side-state)))))
+ (error "current window configuration not suitable for splitting"))))
(put 'helm-swap-windows 'helm-only t)
(defun helm--get-window-side-state ()