spacemacs/layers/+completion/helm/funcs.el

661 lines
25 KiB
EmacsLisp
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

;;; funcs.el --- Helm Layer functions File for Spacemacs
;;
;; Copyright (c) 2012-2022 Sylvain Benner & Contributors
;;
;; Author: Sylvain Benner <sylvain.benner@gmail.com>
;; URL: https://github.com/syl20bnr/spacemacs
;;
;; This file is not part of GNU Emacs.
;;
;; This program 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 of the License, 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.
;;
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
(defvar spacemacs--helm-popwin-mode nil
"Temp variable to store `popwin-mode''s value.")
(defun spacemacs//helm-cleanup ()
"Cleanup some helm related states when quitting."
;; deactivate helm transient state if active when closing the helm buffer
(ignore-errors
(spacemacs/helm-navigation-transient-state/nil)))
(defun spacemacs//helm-prepare-display ()
"Prepare necessary settings to make Helm display properly."
(setq spacemacs-display-buffer-alist display-buffer-alist)
;; the only buffer to display is Helm, nothing else we must set this
;; otherwise Helm cannot reuse its own windows for copyinng/deleting
;; etc... because of existing popwin buffers in the alist
(setq display-buffer-alist nil)
(setq spacemacs--helm-popwin-mode popwin-mode)
(when popwin-mode
(popwin-mode -1)))
(defun spacemacs//helm-restore-display ()
;; we must enable popwin-mode first then restore `display-buffer-alist'
;; Otherwise, popwin keeps adding up its own buffers to
;; `display-buffer-alist' and could slow down Emacs as the list grows
(when spacemacs--helm-popwin-mode
(popwin-mode))
(setq display-buffer-alist spacemacs-display-buffer-alist))
;; REPLs integration
(defun helm-available-repls ()
"Show all the repls available."
(interactive)
(let ((helm-available-repls
`((name . "HELM available REPLs")
(candidates . ,(mapcar #'car spacemacs-repl-list))
(action . (lambda (candidate)
(let ((repl (cdr (assoc candidate spacemacs-repl-list))))
(require (car repl))
(call-interactively (cdr repl))))))))
(helm :sources '(helm-available-repls)
:buffer "*helm repls*")))
;; Search tools integration
(defun spacemacs//helm-do-ag-region-or-symbol (func &optional dir)
"Search with `ag' with a default input."
(require 'helm-ag)
(cl-letf* (((symbol-value 'helm-ag-insert-at-point) 'symbol)
;; make thing-at-point choosing the active region first
((symbol-function 'this-fn) (symbol-function 'thing-at-point))
((symbol-function 'thing-at-point)
(lambda (thing)
(let ((res (if (region-active-p)
(buffer-substring-no-properties
(region-beginning) (region-end))
(this-fn thing))))
(when res (rxt-quote-pcre res))))))
(funcall func dir)))
(defun spacemacs//helm-do-search-find-tool (base tools default-inputp)
"Create a cond form given a TOOLS string list and evaluate it."
(eval
`(cond
,@(mapcar
(lambda (x)
`((executable-find ,x)
',(let ((func
(intern
(format (if default-inputp
"spacemacs/%s-%s-region-or-symbol"
"spacemacs/%s-%s")
base x))))
(if (fboundp func)
func
(intern (format "%s-%s" base x))))))
tools)
(t 'helm-do-grep))))
;; Search in current file ----------------------------------------------
(defun spacemacs/helm-file-do-ag (&optional _)
"Wrapper to execute `helm-ag-this-file.'"
(interactive)
(helm-do-ag-this-file))
(defun spacemacs/helm-file-do-ag-region-or-symbol ()
"Search in current file with `ag' using a default input."
(interactive)
(spacemacs//helm-do-ag-region-or-symbol 'spacemacs/helm-file-do-ag))
(defun spacemacs/helm-file-smart-do-search (&optional default-inputp)
"Search in current file using `dotspacemacs-search-tools'.
Search for a search tool in the order provided by `dotspacemacs-search-tools'
If DEFAULT-INPUTP is non nil then the current region or symbol at point
are used as default input."
(interactive)
(call-interactively
(spacemacs//helm-do-search-find-tool "helm-file-do"
dotspacemacs-search-tools
default-inputp)))
(defun spacemacs/helm-file-smart-do-search-region-or-symbol ()
"Search in current file using `dotspacemacs-search-tools' with
default input.
Search for a search tool in the order provided by `dotspacemacs-search-tools'."
(interactive)
(spacemacs/helm-file-smart-do-search t))
;; Search in files -----------------------------------------------------
(defun spacemacs/helm-files-do-ag (&optional dir)
"Search in files with `ag' using a default input."
(interactive)
(helm-do-ag dir))
(defun spacemacs/helm-files-do-ag-region-or-symbol ()
"Search in files with `ag' using a default input."
(interactive)
(spacemacs//helm-do-ag-region-or-symbol 'spacemacs/helm-files-do-ag))
(defun spacemacs/helm-files-do-ack (&optional dir)
"Search in files with `ack'."
(interactive)
(let ((helm-ag-base-command "ack --nocolor --nogroup"))
(helm-do-ag dir)))
(defun spacemacs/helm-files-do-ack-region-or-symbol ()
"Search in files with `ack' using a default input."
(interactive)
(spacemacs//helm-do-ag-region-or-symbol 'spacemacs/helm-files-do-ack))
(defun spacemacs/helm-files-do-pt (&optional dir)
"Search in files with `pt'."
(interactive)
(let ((helm-ag-base-command "pt -e --nocolor --nogroup"))
(helm-do-ag dir)))
(defun spacemacs/helm-files-do-pt-region-or-symbol ()
"Search in files with `pt' using a default input."
(interactive)
(spacemacs//helm-do-ag-region-or-symbol 'spacemacs/helm-files-do-pt))
(defun spacemacs/helm-files-do-rg (&optional dir)
"Search in files with `rg'."
(interactive)
;; --line-number forces line numbers (disabled by default on windows)
;; no --vimgrep because it adds column numbers that wgrep can't handle
;; see https://github.com/syl20bnr/spacemacs/pull/8065
(let* ((root-helm-ag-base-command "rg --smart-case --no-heading --color=never --line-number")
(helm-ag-base-command (if spacemacs-helm-rg-max-column-number
(concat root-helm-ag-base-command " --max-columns=" (number-to-string spacemacs-helm-rg-max-column-number))
root-helm-ag-base-command)))
(helm-do-ag dir)))
(defun spacemacs/helm-files-do-rg-region-or-symbol ()
"Search in files with `rg' using a default input."
(interactive)
(spacemacs//helm-do-ag-region-or-symbol 'spacemacs/helm-files-do-rg))
(defun spacemacs/helm-files-smart-do-search (&optional default-inputp)
"Search in files using `dotspacemacs-search-tools'.
Search for a search tool in the order provided by `dotspacemacs-search-tools'
If DEFAULT-INPUTP is non nil then the current region or symbol at point
are used as default input."
(interactive)
(call-interactively
(spacemacs//helm-do-search-find-tool "helm-files-do"
dotspacemacs-search-tools
default-inputp)))
(defun spacemacs/helm-files-smart-do-search-region-or-symbol ()
"Search in files using `dotspacemacs-search-tools' with default input.
Search for a search tool in the order provided by `dotspacemacs-search-tools'."
(interactive)
(spacemacs/helm-files-smart-do-search t))
;; Search in current dir -----------------------------------------------
(defun spacemacs/helm-dir-do-ag ()
"Search in current directory with `ag'."
(interactive)
(spacemacs/helm-files-do-ag default-directory))
(defun spacemacs/helm-dir-do-ag-region-or-symbol ()
"Search in current directory with `ag' with a default input."
(interactive)
(spacemacs//helm-do-ag-region-or-symbol 'spacemacs/helm-files-do-ag default-directory))
(defun spacemacs/helm-dir-do-ack ()
"Search in current directory with `ack'."
(interactive)
(spacemacs/helm-files-do-ack default-directory))
(defun spacemacs/helm-dir-do-grep ()
"Search in current directory with `grep'."
(interactive)
(spacemacs//helm-do-grep-region-or-symbol (list default-directory) nil))
(defun spacemacs/helm-dir-do-ack-region-or-symbol ()
"Search in current directory with `ack' with a default input."
(interactive)
(spacemacs//helm-do-ag-region-or-symbol 'spacemacs/helm-files-do-ack default-directory))
(defun spacemacs/helm-dir-do-pt ()
"Search in current directory with `pt'."
(interactive)
(spacemacs/helm-files-do-pt default-directory))
(defun spacemacs/helm-dir-do-pt-region-or-symbol ()
"Search in current directory with `pt' with a default input."
(interactive)
(spacemacs//helm-do-ag-region-or-symbol 'spacemacs/helm-files-do-pt default-directory))
(defun spacemacs/helm-dir-do-rg ()
"Search in current directory with `rg'."
(interactive)
(spacemacs/helm-files-do-rg default-directory))
(defun spacemacs/helm-dir-do-rg-region-or-symbol ()
"Search in current directory with `rg' with a default input."
(interactive)
(spacemacs//helm-do-ag-region-or-symbol 'spacemacs/helm-files-do-rg default-directory))
(defun spacemacs/helm-dir-smart-do-search (&optional default-inputp)
"Search in current directory using `dotspacemacs-search-tools'.
Search for a search tool in the order provided by `dotspacemacs-search-tools'
If DEFAULT-INPUTP is non nil then the current region or symbol at point
are used as default input."
(interactive)
(call-interactively
(spacemacs//helm-do-search-find-tool "helm-dir-do"
dotspacemacs-search-tools
default-inputp)))
(defun spacemacs/helm-dir-smart-do-search-region-or-symbol ()
"Search in current directory using `dotspacemacs-search-tools'.
with default input.
Search for a search tool in the order provided by `dotspacemacs-search-tools'."
(interactive)
(spacemacs/helm-dir-smart-do-search t))
;; Search in buffers ---------------------------------------------------
(defun spacemacs/helm-buffers-do-ag (&optional _)
"Wrapper to execute `helm-ag-buffers.'"
(interactive)
(helm-do-ag-buffers))
(defun spacemacs/helm-buffers-do-ag-region-or-symbol ()
"Search in opened buffers with `ag' with a default input."
(interactive)
(spacemacs//helm-do-ag-region-or-symbol 'spacemacs/helm-buffers-do-ag))
(defun spacemacs/helm-buffers-do-ack (&optional _)
"Search in opened buffers with `ack'."
(interactive)
(let ((helm-ag-base-command "ack --nocolor --nogroup"))
(helm-do-ag-buffers)))
(defun spacemacs/helm-buffers-do-ack-region-or-symbol ()
"Search in opened buffers with `ack' with a default input."
(interactive)
(spacemacs//helm-do-ag-region-or-symbol 'spacemacs/helm-buffers-do-ack))
(defun spacemacs/helm-buffers-do-pt (&optional _)
"Search in opened buffers with `pt'."
(interactive)
(let ((helm-ag-base-command "pt -e --nocolor --nogroup"))
(helm-do-ag-buffers)))
(defun spacemacs/helm-buffers-do-pt-region-or-symbol ()
"Search in opened buffers with `pt' using a default input."
(interactive)
(spacemacs//helm-do-ag-region-or-symbol 'spacemacs/helm-buffers-do-pt))
(defun spacemacs/helm-buffers-do-rg (&optional _)
"Search in opened buffers with `rg'."
(interactive)
;; --line-number forces line numbers (disabled by default on windows)
;; no --vimgrep because it adds column numbers that wgrep can't handle
;; see https://github.com/syl20bnr/spacemacs/pull/8065
(let ((helm-ag-base-command "rg --smart-case --no-heading --color=never --line-number --max-columns=150")
(helm-ag-success-exit-status '(0 2)))
(helm-do-ag-buffers)))
(defun spacemacs/helm-buffers-do-rg-region-or-symbol ()
"Search in opened buffers with `rg' using a default input."
(interactive)
(spacemacs//helm-do-ag-region-or-symbol 'spacemacs/helm-buffers-do-rg))
(defun spacemacs/helm-buffers-smart-do-search (&optional default-inputp)
"Search in opened buffers using `dotspacemacs-search-tools'.
Search for a search tool in the order provided by `dotspacemacs-search-tools'
If DEFAULT-INPUTP is non nil then the current region or symbol at point
are used as default input."
(interactive)
(call-interactively
(spacemacs//helm-do-search-find-tool "helm-buffers-do"
dotspacemacs-search-tools
default-inputp)))
(defun spacemacs/helm-buffers-smart-do-search-region-or-symbol ()
"Search in opened buffers using `dotspacemacs-search-tools' with
default input.
Search for a search tool in the order provided by `dotspacemacs-search-tools'."
(interactive)
(spacemacs/helm-buffers-smart-do-search t))
;; Search in project ---------------------------------------------------
(defun spacemacs/helm-project-smart-do-search-in-dir (dir)
(interactive)
(let ((default-directory dir))
(spacemacs/helm-project-smart-do-search)))
(defun spacemacs/helm-projectile-grep ()
"Replace `helm-projectile-grep' to actually use `ag', `pt' etc.."
(interactive)
(helm-exit-and-execute-action
'spacemacs/helm-project-smart-do-search-in-dir))
(defun spacemacs/helm-project-do-ag ()
"Search in current project with `ag'."
(interactive)
(let ((dir (projectile-project-root)))
(if dir
(helm-do-ag dir)
(message "error: Not in a project."))))
(defun spacemacs/helm-project-do-ag-region-or-symbol ()
"Search in current project with `ag' using a default input."
(interactive)
(let ((dir (projectile-project-root)))
(if dir
(spacemacs//helm-do-ag-region-or-symbol 'helm-do-ag dir)
(message "error: Not in a project."))))
(defun spacemacs/helm-project-do-ack ()
"Search in current project with `ack'."
(interactive)
(let ((dir (projectile-project-root)))
(if dir
(spacemacs/helm-files-do-ack dir)
(message "error: Not in a project."))))
(defun spacemacs/helm-project-do-ack-region-or-symbol ()
"Search in current project with `ack' using a default input."
(interactive)
(let ((dir (projectile-project-root)))
(if dir
(spacemacs//helm-do-ag-region-or-symbol
'spacemacs/helm-files-do-ack dir)
(message "error: Not in a project."))))
(defun spacemacs/helm-project-do-pt ()
"Search in current project with `pt'."
(interactive)
(let ((dir (projectile-project-root)))
(if dir
(spacemacs/helm-files-do-pt dir)
(message "error: Not in a project."))))
(defun spacemacs/helm-project-do-pt-region-or-symbol ()
"Search in current project with `pt' using a default input."
(interactive)
(let ((dir (projectile-project-root)))
(if dir
(spacemacs//helm-do-ag-region-or-symbol
'spacemacs/helm-files-do-pt dir)
(message "error: Not in a project."))))
(defun spacemacs/helm-project-do-rg ()
"Search in current project with `rg'."
(interactive)
(let ((dir (projectile-project-root)))
(if dir
(spacemacs/helm-files-do-rg dir)
(message "error: Not in a project."))))
(defun spacemacs/helm-project-do-rg-region-or-symbol ()
"Search in current project with `rg' using a default input."
(interactive)
(let ((dir (projectile-project-root)))
(if dir
(spacemacs//helm-do-ag-region-or-symbol
'spacemacs/helm-files-do-rg dir)
(message "error: Not in a project."))))
(defun spacemacs/helm-project-smart-do-search (&optional default-inputp)
"Search in current project using `dotspacemacs-search-tools'.
Search for a search tool in the order provided by `dotspacemacs-search-tools'
If DEFAULT-INPUTP is non nil then the current region or symbol at point
are used as default input."
(interactive)
(let ((projectile-require-project-root nil))
(call-interactively
(spacemacs//helm-do-search-find-tool "helm-project-do"
dotspacemacs-search-tools
default-inputp))))
(defun spacemacs/helm-project-smart-do-search-region-or-symbol ()
"Search in current project using `dotspacemacs-search-tools' with
default input.
Search for a search tool in the order provided by `dotspacemacs-search-tools'."
(interactive)
(spacemacs/helm-project-smart-do-search t))
;; grep
(defun spacemacs//helm-do-grep-region-or-symbol
(&optional targs use-region-or-symbol-p)
"Version of `helm-do-grep' with a default input."
(interactive)
(require 'helm)
(cl-letf*
(((symbol-function 'this-fn) (symbol-function 'helm-do-grep-1))
((symbol-function 'helm-do-grep-1)
(lambda (targets &optional recurse zgrep exts
default-input region-or-symbol-p)
(let* ((new-input (when region-or-symbol-p
(if (region-active-p)
(buffer-substring-no-properties
(region-beginning) (region-end))
(thing-at-point 'symbol t))))
(quoted-input (when new-input
(rxt-quote-pcre new-input))))
(this-fn targets recurse zgrep exts
default-input quoted-input))))
(preselection (or (dired-get-filename nil t)
(buffer-file-name (current-buffer))))
(targets (if targs
targs
(helm-read-file-name
"Search in file(s): "
:marked-candidates t
:preselect (when preselection
(if helm-ff-transformer-show-only-basename
(helm-basename preselection)
preselection))))))
(helm-do-grep-1 targets nil nil nil nil use-region-or-symbol-p)))
(defun spacemacs/helm-file-do-grep ()
"Search in current file with `grep' using a default input."
(interactive)
(spacemacs//helm-do-grep-region-or-symbol
(list (buffer-file-name (current-buffer))) nil))
(defun spacemacs/helm-file-do-grep-region-or-symbol ()
"Search in current file with `grep' using a default input."
(interactive)
(spacemacs//helm-do-grep-region-or-symbol
(list (buffer-file-name (current-buffer))) t))
(defun spacemacs/helm-files-do-grep ()
"Search in files with `grep'."
(interactive)
(spacemacs//helm-do-grep-region-or-symbol nil nil))
(defun spacemacs/helm-files-do-grep-region-or-symbol ()
"Search in files with `grep' using a default input."
(interactive)
(spacemacs//helm-do-grep-region-or-symbol nil t))
(defun spacemacs/helm-buffers-do-grep ()
"Search in opened buffers with `grep'."
(interactive)
(let ((buffers (cl-loop for buffer in (buffer-list)
when (buffer-file-name buffer)
collect (buffer-file-name buffer))))
(spacemacs//helm-do-grep-region-or-symbol buffers nil)))
(defun spacemacs/helm-buffers-do-grep-region-or-symbol ()
"Search in opened buffers with `grep' with a default input."
(interactive)
(let ((buffers (cl-loop for buffer in (buffer-list)
when (buffer-file-name buffer)
collect (buffer-file-name buffer))))
(spacemacs//helm-do-grep-region-or-symbol buffers t)))
(defun spacemacs/resume-last-search-buffer ()
"open last helm-ag or hgrep buffer."
(interactive)
(cond ((get-buffer "*helm ag results*")
(switch-to-buffer-other-window "*helm ag results*"))
((get-buffer "*helm-ag*")
(helm-resume "*helm-ag*"))
((get-buffer "*hgrep*")
(switch-to-buffer-other-window "*hgrep*"))
(t
(message "No previous search buffer found"))))
(defun spacemacs/helm-find-files (arg)
"Custom spacemacs implementation for calling helm-find-files-1.
Removes the automatic guessing of the initial value based on thing at point. "
(interactive "P")
;; fixes #10882 and #11270
(require 'helm-files)
(let* ((hist (and arg helm-ff-history (helm-find-files-history nil)))
(default-input hist)
(input (cond ((and (eq major-mode 'dired-mode) default-input)
(file-name-directory default-input))
((and (not (string= default-input ""))
default-input))
(t (expand-file-name (helm-current-directory))))))
(set-text-properties 0 (length input) nil input)
(helm-find-files-1 input)))
;; Key bindings
(defmacro spacemacs||set-helm-key (keys func)
"Define a key bindings for FUNC using KEYS.
Ensure that helm is required before calling FUNC."
(let ((func-name (intern (format "lazy-helm/%s" (symbol-name func)))))
`(progn
(defun ,func-name ()
,(format "Wrapper to ensure that `helm' is loaded before calling %s."
(symbol-name func))
(interactive)
(require 'helm)
(call-interactively ',func))
(spacemacs/set-leader-keys ,keys ',func-name))))
;; Find files tweaks
(defun spacemacs//helm-find-files-edit (candidate)
"Opens a dired buffer and immediately switches to editable mode."
(dired (file-name-directory candidate))
(dired-goto-file candidate)
(dired-toggle-read-only))
(defun spacemacs/helm-find-files-edit ()
"Exits helm, opens a dired buffer and immediately switches to editable mode."
(interactive)
(helm-exit-and-execute-action 'spacemacs//helm-find-files-edit))
(defun spacemacs/helm-jump-in-buffer ()
"Jump in buffer using `imenu' facilities and helm."
(interactive)
(call-interactively
(cond
((eq major-mode 'org-mode) 'helm-org-in-buffer-headings)
(t 'helm-semantic-or-imenu))))
(defun spacemacs//helm-open-buffers-in-windows (buffers)
"This function allows a different default action, on marking multiple
candidate buffers/files for helm. By default, helm either opens all
files/buffers in the same window, or creates splits. This function instead
opens the buffers (or files) across different already-open windows. The first
selected buffer is opened in the current window, the next is opened in the
window with higher number, etc. This will make a loop around, so with 4
windows, and window 2 active, opening 4 buffers will open them in windows
2 3 4 1. If more buffers are opened than windows available, the remainder are
not set to any window (but in the case of files, they are still opened
to buffers)."
(let ((num-buffers (length buffers))
(num-windows (length (winum--window-list)))
(cur-win (or (winum-get-number) (winum-get-number (other-window 1))))
(num-buffers-placed 0))
(cl-loop for buffer in buffers do
(when (>= num-buffers-placed num-windows) (cl-return))
(set-window-buffer (winum-get-window-by-number cur-win) buffer)
(setq cur-win (+ 1 (mod cur-win num-windows)))
(cl-incf num-buffers-placed))))
(defun spacemacs/helm-find-buffers-windows ()
(interactive)
(helm-exit-and-execute-action
(lambda (candidate)
(spacemacs//helm-open-buffers-in-windows (helm-marked-candidates)))))
(defun spacemacs/helm-find-files-windows ()
(interactive)
(helm-exit-and-execute-action
(lambda (candidate)
(let* ((files (helm-marked-candidates))
(buffers (mapcar 'find-file-noselect files)))
(spacemacs//helm-open-buffers-in-windows buffers)))))
;; Generalized next-error interface
(defun spacemacs//gne-init-helm-ag (&rest args)
(with-current-buffer "*helm ag results*"
(setq spacemacs--gne-min-line 5
spacemacs--gne-max-line (save-excursion
(goto-char (point-max))
(previous-line)
(line-number-at-pos))
spacemacs--gne-line-func
(lambda (c)
(helm-ag--find-file-action
c 'find-file helm-ag--search-this-file-p))
next-error-function 'spacemacs/gne-next)))
(defun spacemacs//gne-init-helm-grep (&rest args)
(with-current-buffer "*hgrep*"
(setq spacemacs--gne-min-line 5
spacemacs--gne-max-line
(save-excursion
(goto-char (point-max))
(previous-line)
(line-number-at-pos))
spacemacs--gne-line-func 'helm-grep-action
next-error-function 'spacemacs/gne-next)))
;; theme
(defun spacemacs/helm-themes ()
"Remove limit on number of candidates on `helm-themes'"
(interactive)
(let (helm-candidate-number-limit)
(helm-themes)))
;; Buffers ---------------------------------------------------------------------
(defun spacemacs/helm-buffers-list-unfiltered ()
"Helm buffers without filtering."
(interactive)
(let ((helm-boring-buffer-regexp-list nil))
(call-interactively #'helm-buffers-list)))
;; Command search ---------------------------------------------------------------------
(defun spacemacs/helm-M-x-fuzzy-matching ()
"Helm M-x with fuzzy matching enabled"
(interactive)
(let ((completion-styles completion-styles))
(add-to-list 'completion-styles 'flex t)
(call-interactively 'helm-M-x)))