(progn
(add-to-list 'load-path "~/.emacs.d/elpa/ggtags-20151214.1344" t)
(require 'ggtags)
- (add-to-list 'load-path "~/.emacs.d/elpa/helm-gtags-20160202.503" t)
+ (add-to-list 'load-path "~/.emacs.d/elpa/helm-gtags-20170116.529" t)
(require 'helm-gtags)
(add-hook 'puppet-mode-hook
(lambda()
(if (>= emacs-major-version 24)
(progn
(add-to-list 'load-path
- "~/.emacs.d/elpa/helm-20160530.424")
+ "~/.emacs.d/elpa/helm-20181029.623")
(require 'helm)
(helm-mode 1)
(global-set-key (kbd "M-y") 'helm-show-kill-ring)
#+BEGIN_SRC emacs-lisp :tangle yes
(if (>= emacs-major-version 24)
(progn
- (add-to-list 'load-path "~/.emacs.d/elpa/helm-descbinds-20160108.1947")
+ (add-to-list 'load-path "~/.emacs.d/elpa/helm-descbinds-20180429.1456")
(require 'helm-descbinds)
(define-key global-map (kbd "C-h b") 'helm-descbinds)
)
+++ /dev/null
-;;; ac-helm-autoloads.el --- automatically extracted autoloads
-;;
-;;; Code:
-
-\f
-;;;### (autoloads (ac-complete-with-helm) "ac-helm" "ac-helm.el"
-;;;;;; (21793 7937 0 0))
-;;; Generated autoloads from ac-helm.el
-
-(autoload 'ac-complete-with-helm "ac-helm" "\
-Select `auto-complete' candidates by `helm'.
-It is useful to narrow candidates.
-
-\(fn)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil nil ("ac-helm-pkg.el") (21793 7937 70647 0))
-
-;;;***
-\f
-(provide 'ac-helm-autoloads)
-;; Local Variables:
-;; version-control: never
-;; no-byte-compile: t
-;; no-update-autoloads: t
-;; coding: utf-8
-;; End:
-;;; ac-helm-autoloads.el ends here
+++ /dev/null
-(define-package "ac-helm" "20140919.917" "Helm interface for auto-complete" (quote ((helm "1.6.3") (auto-complete "1.4.0") (popup "0.5.0") (cl-lib "0.5"))))
+++ /dev/null
-;;; ac-helm.el --- Helm interface for auto-complete
-
-;; Copyright (C) 2009 rubikitch
-;; Copyright (C) 2013 Yasuyuki Oka <yasuykNOSPAMgmail.com>
-
-;; Author: rubikitch <rubikitchNOSPAMruby-lang.org>
-;; Yasuyuki Oka <yasuykNOSPAMgmail.com>
-;; Maintainer: Yasuyuki Oka <yasuykNOSPAMgmail.com>
-;; Version: 2.2
-;; Package-Version: 20140919.917
-;; Package-Requires: ((helm "1.6.3")(auto-complete "1.4.0")(popup "0.5.0") (cl-lib "0.5"))
-;; Keywords: completion, convenience, helm
-
-;; 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 2, or (at your option)
-;; any later version.
-
-;; This file 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 GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
-
-;;; Commentary:
-
-;; Auto Complete with Helm. It enables us to narrow candidates
-;; with helm interface. If you have helm-match-plugin.el,
-;; candidates can be narrowed many times.
-
-;; Commands:
-;;
-;; Below are complete command list:
-;;
-;; `ac-complete-with-helm'
-;; Select auto-complete candidates by `helm'.
-;;
-;; Customizable Options:
-;;
-;; Below are customizable option list:
-;;
-
-;; Installation:
-
-;; Add the following to your emacs init file:
-;;
-;; (require 'ac-helm) ;; Not necessary if using ELPA package
-;; (global-set-key (kbd "C-:") 'ac-complete-with-helm)
-;; (define-key ac-complete-mode-map (kbd "C-:") 'ac-complete-with-helm)
-
-;; That's all.
-
-;;; Code:
-
-(require 'helm)
-(require 'helm-match-plugin nil t)
-(require 'helm-elisp)
-(require 'auto-complete)
-(require 'cl-lib)
-(require 'popup)
-
-;;;###autoload
-(defun ac-complete-with-helm ()
- "Select `auto-complete' candidates by `helm'.
-It is useful to narrow candidates."
- (interactive)
- (unless ac-completing
- (call-interactively 'auto-complete))
- (with-helm-show-completion ac-point (point)
- (helm :sources 'helm-source-auto-complete-candidates
- :buffer "*helm auto-complete*")))
-
-(defun helm-auto-complete-init ()
- (helm-attrset 'ac-candidates ac-candidates)
- (helm-attrset 'menu-width
- (popup-preferred-width ac-candidates))
- (helm-attrset 'ac-prefix ac-prefix)
- (when (<= (length ac-candidates) 1)
- (helm-exit-minibuffer))
- (ac-abort))
-
-(defun helm-auto-complete-action (string)
- (delete-char (- (length (helm-attr 'ac-prefix))))
- (insert string)
- (prog1 (let ((action (get-text-property 0 'action string)))
- (if action (funcall action)))
- ;; for GC
- (helm-attrset 'ac-candidates nil)))
-
-(defun helm-auto-complete-candidates ()
- (cl-loop for x in (helm-attr 'ac-candidates) collect
- (cons
- (helm-aif (get-text-property 0 'action x)
- (format "%s%s <%s>"
- x
- ;; padding
- (make-string (- (helm-attr 'menu-width) (length x)) ? )
- ;; action function name
- it)
- x)
- x)))
-
-(defvar helm-source-auto-complete-candidates
- '((name . "Auto Complete")
- (init . helm-auto-complete-init)
- (candidates . helm-auto-complete-candidates)
- (action . helm-auto-complete-action)
- (persistent-action . popup-item-show-help)
- (ac-candidates)
- (menu-width)))
-
-(provide 'ac-helm)
-
-;;; ac-helm.el ends here
--- /dev/null
+;;; ac-helm-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+
+(add-to-list 'load-path (directory-file-name
+ (or (file-name-directory #$) (car load-path))))
+
+\f
+;;;### (autoloads nil "ac-helm" "ac-helm.el" (0 0 0 0))
+;;; Generated autoloads from ac-helm.el
+
+(autoload 'ac-complete-with-helm "ac-helm" "\
+Select `auto-complete' candidates by `helm'.
+It is useful to narrow candidates.
+
+\(fn)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ac-helm" '("helm-")))
+
+;;;***
+\f
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; coding: utf-8
+;; End:
+;;; ac-helm-autoloads.el ends here
--- /dev/null
+;;; -*- no-byte-compile: t -*-
+(define-package "ac-helm" "20160319.233" "Helm interface for auto-complete" '((helm "1.6.3") (auto-complete "1.4.0") (popup "0.5.0") (cl-lib "0.5")) :commit "baf2b1e04bcffa835084389c0fab415f26efbf32" :keywords '("completion" "convenience" "helm") :authors '(("rubikitch" . "rubikitchNOSPAMruby-lang.org") ("Yasuyuki Oka" . "yasuykNOSPAMgmail.com")) :maintainer '("Yasuyuki Oka" . "yasuykNOSPAMgmail.com"))
--- /dev/null
+;;; ac-helm.el --- Helm interface for auto-complete
+
+;; Copyright (C) 2009 rubikitch
+;; Copyright (C) 2013 Yasuyuki Oka <yasuykNOSPAMgmail.com>
+
+;; Author: rubikitch <rubikitchNOSPAMruby-lang.org>
+;; Yasuyuki Oka <yasuykNOSPAMgmail.com>
+;; Maintainer: Yasuyuki Oka <yasuykNOSPAMgmail.com>
+;; Version: 2.2
+;; Package-Version: 20160319.233
+;; Package-Requires: ((helm "1.6.3")(auto-complete "1.4.0")(popup "0.5.0") (cl-lib "0.5"))
+;; Keywords: completion, convenience, helm
+
+;; 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 2, or (at your option)
+;; any later version.
+
+;; This file 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 GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; Auto Complete with Helm. It enables us to narrow candidates
+;; with helm interface. If you have helm-match-plugin.el,
+;; candidates can be narrowed many times.
+
+;; Commands:
+;;
+;; Below are complete command list:
+;;
+;; `ac-complete-with-helm'
+;; Select auto-complete candidates by `helm'.
+;;
+;; Customizable Options:
+;;
+;; Below are customizable option list:
+;;
+
+;; Installation:
+
+;; Add the following to your emacs init file:
+;;
+;; (require 'ac-helm) ;; Not necessary if using ELPA package
+;; (global-set-key (kbd "C-:") 'ac-complete-with-helm)
+;; (define-key ac-complete-mode-map (kbd "C-:") 'ac-complete-with-helm)
+
+;; That's all.
+
+;;; Code:
+
+(require 'helm)
+(require 'helm-multi-match nil t)
+(require 'helm-elisp)
+(require 'auto-complete)
+(require 'cl-lib)
+(require 'popup)
+
+;;;###autoload
+(defun ac-complete-with-helm ()
+ "Select `auto-complete' candidates by `helm'.
+It is useful to narrow candidates."
+ (interactive)
+ (unless ac-completing
+ (call-interactively 'auto-complete))
+ (with-helm-show-completion ac-point (point)
+ (helm :sources 'helm-source-auto-complete-candidates
+ :buffer "*helm auto-complete*")))
+
+(defun helm-auto-complete-init ()
+ (helm-attrset 'ac-candidates ac-candidates)
+ (helm-attrset 'menu-width
+ (popup-preferred-width ac-candidates))
+ (helm-attrset 'ac-prefix ac-prefix)
+ (when (<= (length ac-candidates) 1)
+ (helm-exit-minibuffer))
+ (ac-abort))
+
+(defun helm-auto-complete-action (string)
+ (delete-char (- (length (helm-attr 'ac-prefix))))
+ (insert string)
+ (prog1 (let ((action (get-text-property 0 'action string)))
+ (if action (funcall action)))
+ ;; for GC
+ (helm-attrset 'ac-candidates nil)))
+
+(defun helm-auto-complete-candidates ()
+ (cl-loop for x in (helm-attr 'ac-candidates) collect
+ (cons
+ (helm-aif (get-text-property 0 'action x)
+ (format "%s%s <%s>"
+ x
+ ;; padding
+ (make-string (- (helm-attr 'menu-width) (length x)) ? )
+ ;; action function name
+ it)
+ x)
+ x)))
+
+(defvar helm-source-auto-complete-candidates
+ '((name . "Auto Complete")
+ (init . helm-auto-complete-init)
+ (candidates . helm-auto-complete-candidates)
+ (action . helm-auto-complete-action)
+ (persistent-action . popup-item-show-help)
+ (ac-candidates)
+ (menu-width)))
+
+(provide 'ac-helm)
+
+;;; ac-helm.el ends here
+++ /dev/null
-Auto Complete with Helm. It enables us to narrow candidates
-with helm interface. If you have helm-match-plugin.el,
-candidates can be narrowed many times.
-
-Commands:
-
-Below are complete command list:
-
- `ac-complete-with-helm'
- Select auto-complete candidates by `helm'.
-
-Customizable Options:
-
-Below are customizable option list:
-
-
-Installation:
-
-Add the following to your emacs init file:
-
-(require 'ac-helm) ;; Not necessary if using ELPA package
-(global-set-key (kbd "C-:") 'ac-complete-with-helm)
-(define-key ac-complete-mode-map (kbd "C-:") 'ac-complete-with-helm)
-
-That's all.
+++ /dev/null
-#!/usr/bin/env bash
-
-
-## Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-##
-## 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/>.
-
-## Commentary:
-
-# Preconfigured Emacs with a basic helm configuration.
-# Useful to start quickly an emacs -Q with helm.
-# Run it from this directory or symlink it somewhere in your PATH.
-
-# If TEMP env var exists use it otherwise declare it.
-[ -z $TEMP ] && declare TEMP="/tmp"
-
-CONF_FILE="$TEMP/helm-cfg.el"
-EMACS=emacs
-
-case $1 in
- -P)
- shift 1
- declare EMACS=$1
- shift 1
- ;;
- -h)
- echo "Usage: ${0##*/} [-P} Emacs path [-h} help [--] EMACS ARGS"
- exit 2
- ;;
-esac
-
-cd $(dirname "$0")
-
-# Check if autoload file exists.
-# It is maybe in a different directory if
-# emacs-helm.sh is a symlink.
-LS=$(ls -l $0 | awk '{print $11}')
-if [ ! -z $LS ]; then
- AUTO_FILE="$(dirname $LS)/helm-autoloads.el"
-else
- AUTO_FILE="helm-autoloads.el"
-fi
-if [ ! -e "$AUTO_FILE" ]; then
- echo No autoloads found, please run make first to generate autoload file
- exit 2
-fi
-
-
-cat > $CONF_FILE <<EOF
-(setq initial-scratch-message (concat initial-scratch-message
-";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\
-;; This Emacs is Powered by \`HELM' using\n\
-;; emacs program \"$EMACS\".\n\
-;; This is a minimal \`helm' configuration to discover \`helm' or debug it.\n\
-;; You can retrieve this minimal configuration in \"$CONF_FILE\" \n\
-;; Some originals emacs commands have been replaced by own \`helm' commands:\n\n\
-;; - \`find-file'(C-x C-f) =>\`helm-find-files'\n\
-;; - \`occur'(M-s o) =>\`helm-occur'\n\
-;; - \`list-buffers'(C-x C-b) =>\`helm-buffers-list'\n\
-;; - \`completion-at-point'(M-tab) =>\`helm-lisp-completion-at-point'[1]\n\
-;; - \`dabbrev-expand'(M-/) =>\`helm-dabbrev'\n\n\
-;; - \`execute-extended-command'(M-x) =>\`helm-M-x'\n\n
-;; Some others native emacs commands are \"helmized\" by \`helm-mode'.\n\
-;; [1] Coming with emacs-24.4 \`completion-at-point' is \"helmized\" by \`helm-mode'\n\
-;; which provide helm completion in many other places like \`shell-mode'.\n\
-;; You will find embeded help for most helm commands with \`C-h m'.\n\
-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\n\n"))
-
-(setq package-user-dir (directory-file-name
- (file-name-directory
- (directory-file-name default-directory))))
-(unless (member "helm.el" (directory-files default-directory))
- (setq package-load-list '((helm-core t) (helm t) (async t) (popup t)))
- (package-initialize))
-(add-to-list 'load-path (file-name-directory (file-truename "$0")))
-(setq default-frame-alist '((vertical-scroll-bars . nil)
- (tool-bar-lines . 0)
- (menu-bar-lines . 0)
- (fullscreen . nil)))
-(blink-cursor-mode -1)
-(require 'helm-config)
-(helm-mode 1)
-(define-key global-map [remap find-file] 'helm-find-files)
-(define-key global-map [remap occur] 'helm-occur)
-(define-key global-map [remap list-buffers] 'helm-buffers-list)
-(define-key global-map [remap dabbrev-expand] 'helm-dabbrev)
-(global-set-key (kbd "M-x") 'helm-M-x)
-(unless (boundp 'completion-in-region-function)
- (define-key lisp-interaction-mode-map [remap completion-at-point] 'helm-lisp-completion-at-point)
- (define-key emacs-lisp-mode-map [remap completion-at-point] 'helm-lisp-completion-at-point))
-(add-hook 'kill-emacs-hook #'(lambda () (and (file-exists-p "$CONF_FILE") (delete-file "$CONF_FILE"))))
-EOF
-
-$EMACS -Q -l $CONF_FILE $@
-
+++ /dev/null
-;;; helm-adaptive.el --- Adaptive Sorting of Candidates. -*- lexical-binding: t -*-
-
-;; Original Author: Tamas Patrovics
-
-;; Copyright (C) 2007 Tamas Patrovics
-;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'helm)
-
-\f
-(defgroup helm-adapt nil
- "Adaptative sorting of candidates for Helm."
- :group 'helm)
-
-(defcustom helm-adaptive-history-file
- "~/.emacs.d/helm-adaptive-history"
- "Path of file where history information is stored."
- :type 'string
- :group 'helm-adapt)
-
-(defcustom helm-adaptive-history-length 50
- "Maximum number of candidates stored for a source."
- :type 'number
- :group 'helm-adapt)
-
-\f
-;; Internal
-(defvar helm-adaptive-done nil
- "nil if history information is not yet stored for the current
-selection.")
-
-(defvar helm-adaptive-history nil
- "Contains the stored history information.
-Format: ((SOURCE-NAME (SELECTED-CANDIDATE (PATTERN . NUMBER-OF-USE) ...) ...) ...)")
-
-(defun helm-adaptive-done-reset ()
- (setq helm-adaptive-done nil))
-
-;;;###autoload
-(define-minor-mode helm-adaptive-mode
- "Toggle adaptive sorting in all sources."
- :group 'helm-adapt
- :require 'helm-adaptive
- :global t
- (if helm-adaptive-mode
- (progn
- (unless helm-adaptive-history
- (helm-adaptive-maybe-load-history))
- (add-hook 'kill-emacs-hook 'helm-adaptive-save-history)
- ;; Should run at beginning of `helm-initial-setup'.
- (add-hook 'helm-before-initialize-hook 'helm-adaptive-done-reset)
- ;; Should run at beginning of `helm-exit-minibuffer'.
- (add-hook 'helm-before-action-hook 'helm-adaptive-store-selection)
- ;; Should run at beginning of `helm-select-action'.
- (add-hook 'helm-select-action-hook 'helm-adaptive-store-selection))
- (helm-adaptive-save-history)
- (setq helm-adaptive-history nil)
- (remove-hook 'kill-emacs-hook 'helm-adaptive-save-history)
- (remove-hook 'helm-before-initialize-hook 'helm-adaptive-done-reset)
- (remove-hook 'helm-before-action-hook 'helm-adaptive-store-selection)
- (remove-hook 'helm-select-action-hook 'helm-adaptive-store-selection)))
-
-(defun helm-adapt-use-adaptive-p (&optional source-name)
- "Return current source only if it use adaptive history, nil otherwise."
- (when helm-adaptive-mode
- (let* ((source (or source-name (helm-get-current-source)))
- (adapt-source (or (assoc-default 'filtered-candidate-transformer
- (assoc (assoc-default 'type source)
- helm-type-attributes))
- (assoc-default 'candidate-transformer
- (assoc (assoc-default 'type source)
- helm-type-attributes))
- (assoc-default 'filtered-candidate-transformer source)
- (assoc-default 'candidate-transformer source))))
- (if (listp adapt-source)
- (and (member 'helm-adaptive-sort adapt-source) source)
- (and (eq adapt-source 'helm-adaptive-sort) source)))))
-
-(defun helm-adaptive-store-selection ()
- "Store history information for the selected candidate."
- (unless helm-adaptive-done
- (setq helm-adaptive-done t)
- (let ((source (helm-adapt-use-adaptive-p)))
- (when source
- (let* ((source-name (or (assoc-default 'type source)
- (assoc-default 'name source)))
- (source-info (or (assoc source-name helm-adaptive-history)
- (progn
- (push (list source-name) helm-adaptive-history)
- (car helm-adaptive-history))))
- (selection (helm-get-selection))
- (selection-info (progn
- (setcdr source-info
- (cons
- (let ((found (assoc selection (cdr source-info))))
- (if (not found)
- ;; new entry
- (list selection)
- ;; move entry to the beginning of the
- ;; list, so that it doesn't get
- ;; trimmed when the history is
- ;; truncated
- (setcdr source-info
- (delete found (cdr source-info)))
- found))
- (cdr source-info)))
- (cadr source-info)))
- (pattern-info (progn
- (setcdr selection-info
- (cons
- (let ((found (assoc helm-pattern (cdr selection-info))))
- (if (not found)
- ;; new entry
- (cons helm-pattern 0)
-
- ;; move entry to the beginning of the
- ;; list, so if two patterns used the
- ;; same number of times then the one
- ;; used last appears first in the list
- (setcdr selection-info
- (delete found (cdr selection-info)))
- found))
- (cdr selection-info)))
- (cadr selection-info))))
-
- ;; increase usage count
- (setcdr pattern-info (1+ (cdr pattern-info)))
-
- ;; truncate history if needed
- (if (> (length (cdr selection-info)) helm-adaptive-history-length)
- (setcdr selection-info
- (cl-subseq (cdr selection-info) 0 helm-adaptive-history-length))))))))
-
-(defun helm-adaptive-maybe-load-history ()
- "Load `helm-adaptive-history-file' which contain `helm-adaptive-history'.
-Returns nil if `helm-adaptive-history-file' doesn't exist."
- (when (file-readable-p helm-adaptive-history-file)
- (load-file helm-adaptive-history-file)))
-
-(defun helm-adaptive-save-history (&optional arg)
- "Save history information to file given by `helm-adaptive-history-file'."
- (interactive "p")
- (with-temp-buffer
- (insert
- ";; -*- mode: emacs-lisp -*-\n"
- ";; History entries used for helm adaptive display.\n")
- (prin1 `(setq helm-adaptive-history ',helm-adaptive-history)
- (current-buffer))
- (insert ?\n)
- (write-region (point-min) (point-max) helm-adaptive-history-file nil
- (unless arg 'quiet))))
-
-(defun helm-adaptive-sort (candidates source)
- "Sort the CANDIDATES for SOURCE by usage frequency.
-This is a filtered candidate transformer you can use with the
-`filtered-candidate-transformer' attribute."
- (let* ((source-name (or (assoc-default 'type source)
- (assoc-default 'name source)))
- (source-info (assoc source-name helm-adaptive-history)))
- (if source-info
- (let ((usage
- ;; ... assemble a list containing the (CANIDATE . USAGE-COUNT)
- ;; pairs
- (mapcar (lambda (candidate-info)
- (let ((count 0))
- (cl-dolist (pattern-info (cdr candidate-info))
- (if (not (equal (car pattern-info)
- helm-pattern))
- (cl-incf count (cdr pattern-info))
-
- ;; if current pattern is equal to the previously
- ;; used one then this candidate has priority
- ;; (that's why its count is boosted by 10000) and
- ;; it only has to compete with other candidates
- ;; which were also selected with the same pattern
- (setq count (+ 10000 (cdr pattern-info)))
- (cl-return)))
- (cons (car candidate-info) count)))
- (cdr source-info))))
- (if (and usage (consp usage))
- ;; sort the list in descending order, so candidates with highest
- ;; priorty come first
- (progn
- (setq usage (sort usage (lambda (first second)
- (> (cdr first) (cdr second)))))
-
- ;; put those candidates first which have the highest usage count
- (cl-loop for (info . _freq) in usage
- for member = (cl-member info candidates
- :test 'helm-adaptive-compare)
- when member collect (car member) into sorted
- and do
- (setq candidates (cl-remove info candidates
- :test 'helm-adaptive-compare))
- finally return (append sorted candidates)))
- (message "Your `%s' is maybe corrupted or too old, \
-you should reinitialize it with `helm-reset-adaptive-history'"
- helm-adaptive-history-file)
- (sit-for 1)
- candidates))
- ;; if there is no information stored for this source then do nothing
- candidates)))
-
-;;;###autoload
-(defun helm-reset-adaptive-history ()
- "Delete all `helm-adaptive-history' and his file.
-Useful when you have a old or corrupted `helm-adaptive-history-file'."
- (interactive)
- (when (y-or-n-p "Really delete all your `helm-adaptive-history'? ")
- (setq helm-adaptive-history nil)
- (delete-file helm-adaptive-history-file)))
-
-(defun helm-adaptive-compare (x y)
- "Compare candidates X and Y taking into account that the
-candidate can be in (DISPLAY . REAL) format."
- (equal (if (listp x) (cdr x) x)
- (if (listp y) (cdr y) y)))
-
-
-(provide 'helm-adaptive)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-adaptive.el ends here
+++ /dev/null
-;;; helm-apt.el --- Helm interface for Debian/Ubuntu packages (apt-*) -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'helm)
-(require 'helm-utils)
-(require 'helm-external)
-(require 'helm-help)
-
-(declare-function term-line-mode "term")
-(declare-function term-char-mode "term")
-(declare-function term-send-input "term")
-(declare-function term-send-eof "term")
-
-\f
-(defgroup helm-apt nil
- "Apt related Applications and libraries for Helm."
- :group 'helm)
-
-(defcustom helm-apt-cache-show-function 'helm-apt-cache-show-1
- "Function of one argument used to show apt package.
-Default is `helm-apt-cache-show-1' but you can use `apt-utils-show-package-1'
-from `apt-utils.el' to have something more enhanced.
-If nil default `helm-apt-cache-show-1' will be used."
- :type 'function
- :group 'helm-apt)
-
-(defcustom helm-apt-actions
- '(("Show package description" . helm-apt-cache-show)
- ("Install package(s)" . helm-apt-install)
- ("Reinstall package(s)" . helm-apt-reinstall)
- ("Remove package(s)" . helm-apt-uninstall)
- ("Purge package(s)" . helm-apt-purge))
- "Actions for helm apt."
- :group 'helm-apt
- :type '(alist :key-type string :value-type function))
-
-(defface helm-apt-installed
- '((t (:foreground "green")))
- "Face used for apt installed candidates."
- :group 'helm-apt)
-
-(defface helm-apt-deinstalled
- '((t (:foreground "DimGray")))
- "Face used for apt deinstalled candidates."
- :group 'helm-apt)
-
-\f
-(defvar helm-apt-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map helm-map)
- (define-key map (kbd "M-I") 'helm-apt-show-only-installed)
- (define-key map (kbd "M-U") 'helm-apt-show-only-not-installed)
- (define-key map (kbd "M-D") 'helm-apt-show-only-deinstalled)
- (define-key map (kbd "M-A") 'helm-apt-show-all)
- map))
-
-\f
-(defvar helm-source-apt
- (helm-build-in-buffer-source "APT"
- :init #'helm-apt-init
- :candidate-transformer #'helm-apt-candidate-transformer
- :display-to-real #'helm-apt-display-to-real
- :update #'helm-apt-refresh
- :keymap helm-apt-map
- :help-message 'helm-apt-help-message
- :action 'helm-apt-actions
- :persistent-action #'helm-apt-persistent-action
- :persistent-help "Show package description"))
-
-;;; Internals vars
-(defvar helm-apt-search-command "apt-cache search '%s'")
-(defvar helm-apt-show-command "apt-cache show '%s'")
-(defvar helm-apt-installed-packages nil)
-(defvar helm-apt-all-packages nil)
-(defvar helm-apt-input-history nil)
-(defvar helm-apt-show-only 'all)
-(defvar helm-apt-term-buffer nil)
-(defvar helm-apt-default-archs nil)
-
-(defun helm-apt-refresh ()
- "Refresh installed candidates list."
- (setq helm-apt-installed-packages nil)
- (setq helm-apt-all-packages nil))
-
-(defun helm-apt-persistent-action (candidate)
- "Persistent action for APT source."
- (helm-apt-cache-show candidate))
-
-(defun helm-apt--installed-package-name (name)
- (cl-loop for arch in helm-apt-default-archs
- thereis (or (assoc-default
- name helm-apt-installed-packages)
- (assoc-default
- (format "%s:%s" name arch)
- helm-apt-installed-packages))))
-
-(defun helm-apt-candidate-transformer (candidates)
- "Show installed CANDIDATES and the ones to deinstall in a different color."
- (cl-loop for cand in candidates
- for name = (helm-apt-display-to-real cand)
- for deinstall = (string=
- (helm-apt--installed-package-name name)
- "deinstall")
- for install = (string=
- (helm-apt--installed-package-name name)
- "install")
- for show = (cond ((and deinstall
- (memq helm-apt-show-only '(all deinstalled)))
- (propertize cand 'face 'helm-apt-deinstalled))
- ((and install
- (memq helm-apt-show-only '(all installed)))
- (propertize cand 'face 'helm-apt-installed))
- ((and (eq helm-apt-show-only 'noinstalled)
- (not install)) cand)
- ((eq helm-apt-show-only 'all) cand))
- when show collect show))
-
-(defun helm-apt-show-only-installed ()
- (interactive)
- (with-helm-alive-p
- (setq helm-apt-show-only 'installed)
- (helm-update)))
-(put 'helm-apt-show-only-installed 'helm-only t)
-
-(defun helm-apt-show-only-not-installed ()
- (interactive)
- (with-helm-alive-p
- (setq helm-apt-show-only 'noinstalled)
- (helm-update)))
-(put 'helm-apt-show-only-not-installed 'helm-only t)
-
-(defun helm-apt-show-only-deinstalled ()
- (interactive)
- (with-helm-alive-p
- (setq helm-apt-show-only 'deinstalled)
- (helm-update)))
-(put 'helm-apt-show-only-deinstalled 'helm-only t)
-
-(defun helm-apt-show-all ()
- (interactive)
- (with-helm-alive-p
- (setq helm-apt-show-only 'all)
- (helm-update)))
-(put 'helm-apt-show-all 'helm-only t)
-
-(defun helm-apt-init ()
- "Initialize list of debian packages."
- (let ((query ""))
- (unless (and helm-apt-installed-packages
- helm-apt-all-packages)
- (message "Loading package list...")
- (setq helm-apt-installed-packages
- (with-temp-buffer
- (call-process-shell-command "dpkg --get-selections"
- nil (current-buffer))
- (cl-loop for i in (split-string (buffer-string) "\n" t)
- for p = (split-string i)
- collect (cons (car p) (cadr p)))))
- (helm-init-candidates-in-buffer
- 'global
- (setq helm-apt-all-packages
- (with-temp-buffer
- (call-process-shell-command
- (format helm-apt-search-command query)
- nil (current-buffer))
- (buffer-string))))
- (message "Loading package list done")
- (sit-for 0.5))))
-
-(defun helm-apt-display-to-real (line)
- "Return only name of a debian package.
-LINE is displayed like:
-package name - description."
- (car (split-string line " - ")))
-
-(defvar helm-apt-show-current-package nil)
-(define-derived-mode helm-apt-show-mode
- special-mode "helm-apt-show"
- "Mode to display infos on apt packages.")
-
-(defun helm-apt-cache-show (package)
- "Show information on apt package PACKAGE."
- (if (and (functionp helm-apt-cache-show-function)
- (not (eq helm-apt-cache-show-function
- 'helm-apt-cache-show)))
- ;; A function, call it.
- (funcall helm-apt-cache-show-function package)
- ;; nil or whatever use default.
- (helm-apt-cache-show-1 package)))
-
-(defun helm-apt-cache-show-1 (package)
- (let* ((command (format helm-apt-show-command package))
- (buf (get-buffer-create "*helm apt show*")))
- (switch-to-buffer buf)
- (unless (string= package helm-apt-show-current-package)
- (let ((inhibit-read-only t))
- (erase-buffer)
- (save-excursion
- (call-process-shell-command
- command nil (current-buffer) t))))
- (helm-apt-show-mode)
- (set (make-local-variable 'helm-apt-show-current-package)
- package)))
-
-(defun helm-apt-install (_package)
- "Run 'apt-get install' shell command on PACKAGE."
- (helm-apt-generic-action :action 'install))
-
-(defun helm-apt-reinstall (_package)
- "Run 'apt-get install --reinstall' shell command on PACKAGE."
- (helm-apt-generic-action :action 'reinstall))
-
-(defun helm-apt-uninstall (_package)
- "Run 'apt-get remove' shell command on PACKAGE."
- (helm-apt-generic-action :action 'uninstall))
-
-(defun helm-apt-purge (_package)
- "Run 'apt-get purge' shell command on PACKAGE."
- (helm-apt-generic-action :action 'purge))
-
-(cl-defun helm-apt-generic-action (&key action)
- "Run 'apt-get ACTION'.
-Support install, remove and purge actions."
- (if (and helm-apt-term-buffer
- (buffer-live-p (get-buffer helm-apt-term-buffer)))
- (switch-to-buffer helm-apt-term-buffer)
- (ansi-term (getenv "SHELL") "term apt")
- (setq helm-apt-term-buffer (buffer-name)))
- (term-line-mode)
- (let ((command (cl-case action
- (install "sudo apt-get install ")
- (reinstall "sudo apt-get install --reinstall ")
- (uninstall "sudo apt-get remove ")
- (purge "sudo apt-get purge ")
- (t (error "Unknown action"))))
- (beg (point))
- end
- (cand-list (mapconcat (lambda (x) (format "'%s'" x))
- (helm-marked-candidates) " ")))
- (goto-char (point-max))
- (insert (concat command cand-list))
- (setq end (point))
- (if (y-or-n-p (format "%s package(s)" (symbol-name action)))
- (progn
- (setq helm-external-commands-list nil)
- (setq helm-apt-installed-packages nil)
- (term-char-mode) (term-send-input))
- (delete-region beg end))))
-
-;;;###autoload
-(defun helm-apt (arg)
- "Preconfigured `helm' : frontend of APT package manager.
-With a prefix arg reload cache."
- (interactive "P")
- (setq helm-apt-show-only 'all)
- (unless helm-apt-default-archs
- (setq helm-apt-default-archs
- (append (split-string
- (shell-command-to-string
- "dpkg --print-architecture")
- "\n" t)
- (split-string
- (shell-command-to-string
- "dpkg --print-foreign-architectures")
- "\n" t))))
- (let ((query (read-string "Search Package: " nil 'helm-apt-input-history)))
- (when arg (helm-apt-refresh))
- (helm :sources 'helm-source-apt
- :prompt "Search Package: "
- :input query
- :buffer "*helm apt*"
- :history 'helm-apt-input-history)))
-
-
-(provide 'helm-apt)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-apt.el ends here
+++ /dev/null
-;;; helm-autoloads.el --- automatically extracted autoloads
-;;
-;;; Code:
-(add-to-list 'load-path (or (file-name-directory #$) (car load-path)))
-\f
-;;;### (autoloads nil "helm-adaptive" "helm-adaptive.el" (22348 36311
-;;;;;; 0 0))
-;;; Generated autoloads from helm-adaptive.el
-
-(defvar helm-adaptive-mode nil "\
-Non-nil if Helm-Adaptive mode is enabled.
-See the command `helm-adaptive-mode' for a description of this minor mode.
-Setting this variable directly does not take effect;
-either customize it (see the info node `Easy Customization')
-or call the function `helm-adaptive-mode'.")
-
-(custom-autoload 'helm-adaptive-mode "helm-adaptive" nil)
-
-(autoload 'helm-adaptive-mode "helm-adaptive" "\
-Toggle adaptive sorting in all sources.
-
-\(fn &optional ARG)" t nil)
-
-(autoload 'helm-reset-adaptive-history "helm-adaptive" "\
-Delete all `helm-adaptive-history' and his file.
-Useful when you have a old or corrupted `helm-adaptive-history-file'.
-
-\(fn)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "helm-apt" "helm-apt.el" (22348 36311 0 0))
-;;; Generated autoloads from helm-apt.el
-
-(autoload 'helm-apt "helm-apt" "\
-Preconfigured `helm' : frontend of APT package manager.
-With a prefix arg reload cache.
-
-\(fn ARG)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "helm-bookmark" "helm-bookmark.el" (22348 36311
-;;;;;; 0 0))
-;;; Generated autoloads from helm-bookmark.el
-
-(autoload 'helm-bookmarks "helm-bookmark" "\
-Preconfigured `helm' for bookmarks.
-
-\(fn)" t nil)
-
-(autoload 'helm-filtered-bookmarks "helm-bookmark" "\
-Preconfigured helm for bookmarks (filtered by category).
-Optional source `helm-source-bookmark-addressbook' is loaded
-only if external library addressbook-bookmark.el is available.
-
-\(fn)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "helm-buffers" "helm-buffers.el" (22348 36311
-;;;;;; 0 0))
-;;; Generated autoloads from helm-buffers.el
-
-(autoload 'helm-buffers-list "helm-buffers" "\
-Preconfigured `helm' to list buffers.
-
-\(fn)" t nil)
-
-(autoload 'helm-mini "helm-buffers" "\
-Preconfigured `helm' lightweight version (buffer -> recentf).
-
-\(fn)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "helm-color" "helm-color.el" (22348 36311 0
-;;;;;; 0))
-;;; Generated autoloads from helm-color.el
-
-(autoload 'helm-colors "helm-color" "\
-Preconfigured `helm' for color.
-
-\(fn)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "helm-command" "helm-command.el" (22348 36311
-;;;;;; 0 0))
-;;; Generated autoloads from helm-command.el
-
-(autoload 'helm-M-x "helm-command" "\
-Preconfigured `helm' for Emacs commands.
-It is `helm' replacement of regular `M-x' `execute-extended-command'.
-
-Unlike regular `M-x' emacs vanilla `execute-extended-command' command,
-the prefix args if needed, are passed AFTER starting `helm-M-x'.
-
-You can get help on each command by persistent action.
-
-\(fn ARG &optional COMMAND-NAME)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "helm-config" "helm-config.el" (22348 36311
-;;;;;; 0 0))
-;;; Generated autoloads from helm-config.el
-
-(autoload 'helm-configuration "helm-config" "\
-Customize `helm'.
-
-\(fn)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "helm-dabbrev" "helm-dabbrev.el" (22348 36311
-;;;;;; 0 0))
-;;; Generated autoloads from helm-dabbrev.el
-
-(autoload 'helm-dabbrev "helm-dabbrev" "\
-Preconfigured helm for dynamic abbreviations.
-
-\(fn)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "helm-elisp" "helm-elisp.el" (22348 36311 0
-;;;;;; 0))
-;;; Generated autoloads from helm-elisp.el
-
-(autoload 'helm-lisp-completion-at-point "helm-elisp" "\
-Preconfigured helm for lisp symbol completion at point.
-
-\(fn)" t nil)
-
-(autoload 'helm-complete-file-name-at-point "helm-elisp" "\
-Preconfigured helm to complete file name at point.
-
-\(fn &optional FORCE)" t nil)
-
-(autoload 'helm-lisp-indent "helm-elisp" "\
-
-
-\(fn)" t nil)
-
-(autoload 'helm-lisp-completion-or-file-name-at-point "helm-elisp" "\
-Preconfigured helm to complete lisp symbol or filename at point.
-Filename completion happen if string start after or between a double quote.
-
-\(fn)" t nil)
-
-(autoload 'helm-apropos "helm-elisp" "\
-Preconfigured helm to describe commands, functions, variables and faces.
-In non interactives calls DEFAULT argument should be provided as a string,
-i.e the `symbol-name' of any existing symbol.
-
-\(fn DEFAULT)" t nil)
-
-(autoload 'helm-manage-advice "helm-elisp" "\
-Preconfigured `helm' to disable/enable function advices.
-
-\(fn)" t nil)
-
-(autoload 'helm-locate-library "helm-elisp" "\
-Preconfigured helm to locate elisp libraries.
-
-\(fn)" t nil)
-
-(autoload 'helm-timers "helm-elisp" "\
-Preconfigured `helm' for timers.
-
-\(fn)" t nil)
-
-(autoload 'helm-complex-command-history "helm-elisp" "\
-Preconfigured helm for complex command history.
-
-\(fn)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "helm-elisp-package" "helm-elisp-package.el"
-;;;;;; (22348 36311 0 0))
-;;; Generated autoloads from helm-elisp-package.el
-
-(autoload 'helm-list-elisp-packages "helm-elisp-package" "\
-Preconfigured helm for listing and handling emacs packages.
-
-\(fn ARG)" t nil)
-
-(autoload 'helm-list-elisp-packages-no-fetch "helm-elisp-package" "\
-Preconfigured helm for emacs packages.
-Same as `helm-list-elisp-packages' but don't fetch packages on remote.
-
-\(fn)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "helm-elscreen" "helm-elscreen.el" (22348 36311
-;;;;;; 0 0))
-;;; Generated autoloads from helm-elscreen.el
-
-(autoload 'helm-elscreen "helm-elscreen" "\
-Preconfigured helm to list elscreen.
-
-\(fn)" t nil)
-
-(autoload 'helm-elscreen-history "helm-elscreen" "\
-Preconfigured helm to list elscreen in history order.
-
-\(fn)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "helm-eshell" "helm-eshell.el" (22348 36311
-;;;;;; 0 0))
-;;; Generated autoloads from helm-eshell.el
-
-(autoload 'helm-esh-pcomplete "helm-eshell" "\
-Preconfigured helm to provide helm completion in eshell.
-
-\(fn)" t nil)
-
-(autoload 'helm-eshell-history "helm-eshell" "\
-Preconfigured helm for eshell history.
-
-\(fn)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "helm-eval" "helm-eval.el" (22348 36311 0 0))
-;;; Generated autoloads from helm-eval.el
-
-(autoload 'helm-eval-expression "helm-eval" "\
-Preconfigured helm for `helm-source-evaluation-result'.
-
-\(fn ARG)" t nil)
-
-(autoload 'helm-eval-expression-with-eldoc "helm-eval" "\
-Preconfigured helm for `helm-source-evaluation-result' with `eldoc' support.
-
-\(fn)" t nil)
-
-(autoload 'helm-calcul-expression "helm-eval" "\
-Preconfigured helm for `helm-source-calculation-result'.
-
-\(fn)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "helm-external" "helm-external.el" (22348 36311
-;;;;;; 0 0))
-;;; Generated autoloads from helm-external.el
-
-(autoload 'helm-run-external-command "helm-external" "\
-Preconfigured `helm' to run External PROGRAM asyncronously from Emacs.
-If program is already running exit with error.
-You can set your own list of commands with
-`helm-external-commands-list'.
-
-\(fn PROGRAM)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "helm-files" "helm-files.el" (22348 36311 0
-;;;;;; 0))
-;;; Generated autoloads from helm-files.el
-
-(autoload 'helm-browse-project "helm-files" "\
-Preconfigured helm to browse projects.
-Browse files and see status of project with its vcs.
-Only HG and GIT are supported for now.
-Fall back to `helm-browse-project-find-files'
-if current directory is not under control of one of those vcs.
-With a prefix ARG browse files recursively, with two prefix ARG
-rebuild the cache.
-If the current directory is found in the cache, start
-`helm-browse-project-find-files' even with no prefix ARG.
-NOTE: The prefix ARG have no effect on the VCS controlled directories.
-
-Needed dependencies for VCS:
-<https://github.com/emacs-helm/helm-ls-git>
-and
-<https://github.com/emacs-helm/helm-ls-hg>
-and
-<http://melpa.org/#/helm-ls-svn>.
-
-\(fn ARG)" t nil)
-
-(autoload 'helm-find "helm-files" "\
-Preconfigured `helm' for the find shell command.
-
-Recursively find files whose names are matched by all specified
-globbing PATTERNs under the current directory using the external
-program specified in `find-program' (usually \"find\"). Every
-input PATTERN is silently wrapped into two stars: *PATTERN*.
-
-With prefix argument, prompt for a directory to search.
-
-When user option `helm-findutils-search-full-path' is non-nil,
-match against complete paths, otherwise, against file names
-without directory part.
-
-The (possibly empty) list of globbing PATTERNs can be followed by
-the separator \"*\" plus any number of additional arguments that
-are passed to \"find\" literally.
-
-\(fn ARG)" t nil)
-
-(autoload 'helm-find-files "helm-files" "\
-Preconfigured `helm' for helm implementation of `find-file'.
-Called with a prefix arg show history if some.
-Don't call it from programs, use `helm-find-files-1' instead.
-This is the starting point for nearly all actions you can do on files.
-
-\(fn ARG)" t nil)
-
-(autoload 'helm-for-files "helm-files" "\
-Preconfigured `helm' for opening files.
-Run all sources defined in `helm-for-files-preferred-list'.
-
-\(fn)" t nil)
-
-(autoload 'helm-multi-files "helm-files" "\
-Preconfigured helm similar to `helm-for-files' but that don't run locate.
-Allow toggling from locate to others sources.
-This allow seeing first if what you search is in other sources before launching
-locate.
-
-\(fn)" t nil)
-
-(autoload 'helm-recentf "helm-files" "\
-Preconfigured `helm' for `recentf'.
-
-\(fn)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "helm-font" "helm-font.el" (22348 36311 0 0))
-;;; Generated autoloads from helm-font.el
-
-(autoload 'helm-select-xfont "helm-font" "\
-Preconfigured `helm' to select Xfont.
-
-\(fn)" t nil)
-
-(autoload 'helm-ucs "helm-font" "\
-Preconfigured helm for `ucs-names' math symbols.
-
-\(fn)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "helm-grep" "helm-grep.el" (22348 36311 0 0))
-;;; Generated autoloads from helm-grep.el
-
-(autoload 'helm-goto-precedent-file "helm-grep" "\
-Go to precedent file in helm grep/etags buffers.
-
-\(fn)" t nil)
-
-(autoload 'helm-goto-next-file "helm-grep" "\
-Go to precedent file in helm grep/etags buffers.
-
-\(fn)" t nil)
-
-(autoload 'helm-do-grep-ag "helm-grep" "\
-Preconfigured helm for grepping with AG in `default-directory'.
-With prefix-arg prompt for type if available with your AG version.
-
-\(fn ARG)" t nil)
-
-(autoload 'helm-grep-do-git-grep "helm-grep" "\
-Preconfigured helm for git-grepping `default-directory'.
-With a prefix arg ARG git-grep the whole repository.
-
-\(fn ARG)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "helm-help" "helm-help.el" (22348 36311 0 0))
-;;; Generated autoloads from helm-help.el
-
-(autoload 'helm-documentation "helm-help" "\
-Preconfigured helm for helm documentation.
-With a prefix arg refresh the documentation.
-
-Find here the documentation of all sources actually documented.
-
-\(fn ARG)" t nil)
-
-(defvar helm-comp-read-mode-line "\\<helm-comp-read-map>C/\\[helm-cr-empty-string]:Empty \\<helm-map>\\[helm-help]:Help \\[helm-select-action]:Act \\[helm-maybe-exit-minibuffer]/f1/f2/f-n:NthAct \\[helm-toggle-suspend-update]:Tog.suspend")
-
-(defvar helm-read-file-name-mode-line-string "\\<helm-read-file-map>\\[helm-help]:Help C/\\[helm-cr-empty-string]:Empty \\<helm-map>\\[helm-select-action]:Act \\[helm-maybe-exit-minibuffer]/f1/f2/f-n:NthAct \\[helm-toggle-suspend-update]:Tog.suspend" "\
-String displayed in mode-line in `helm-source-find-files'.")
-
-(defvar helm-top-mode-line "\\<helm-top-map>\\[helm-help]:Help \\<helm-map>\\[helm-select-action]:Act \\[helm-maybe-exit-minibuffer]/f1/f2/f-n:NthAct \\[helm-toggle-suspend-update]:Tog.suspend")
-
-(autoload 'helm-describe-helm-attribute "helm-help" "\
-Display the full documentation of HELM-ATTRIBUTE.
-HELM-ATTRIBUTE should be a symbol.
-
-\(fn HELM-ATTRIBUTE)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "helm-id-utils" "helm-id-utils.el" (22348 36311
-;;;;;; 0 0))
-;;; Generated autoloads from helm-id-utils.el
-
-(autoload 'helm-gid "helm-id-utils" "\
-Preconfigured helm for `gid' command line of `ID-Utils'.
-Need A database created with the command `mkid'
-above `default-directory'.
-Need id-utils as dependency which provide `mkid', `gid' etc...
-See <https://www.gnu.org/software/idutils/>.
-
-\(fn)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "helm-imenu" "helm-imenu.el" (22348 36311 0
-;;;;;; 0))
-;;; Generated autoloads from helm-imenu.el
-
-(autoload 'helm-imenu "helm-imenu" "\
-Preconfigured `helm' for `imenu'.
-
-\(fn)" t nil)
-
-(autoload 'helm-imenu-in-all-buffers "helm-imenu" "\
-Preconfigured helm for fetching imenu entries in all buffers with similar mode as current.
-A mode is similar as current if it is the same, it is derived i.e `derived-mode-p'
-or it have an association in `helm-imenu-all-buffer-assoc'.
-
-\(fn)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "helm-info" "helm-info.el" (22348 36311 0 0))
-;;; Generated autoloads from helm-info.el
-
-(autoload 'helm-info "helm-info" "\
-Preconfigured `helm' for searching Info files' indices.
-
-\(fn)" t nil)
-
-(autoload 'helm-info-at-point "helm-info" "\
-Preconfigured `helm' for searching info at point.
-With a prefix-arg insert symbol at point.
-
-\(fn)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "helm-locate" "helm-locate.el" (22348 36311
-;;;;;; 0 0))
-;;; Generated autoloads from helm-locate.el
-
-(autoload 'helm-projects-find-files "helm-locate" "\
-Find files with locate in `helm-locate-project-list'.
-With a prefix arg refresh the database in each project.
-
-\(fn UPDATE)" t nil)
-
-(autoload 'helm-locate "helm-locate" "\
-Preconfigured `helm' for Locate.
-Note: you can add locate options after entering pattern.
-See 'man locate' for valid options and also `helm-locate-command'.
-
-You can specify a local database with prefix argument ARG.
-With two prefix arg, refresh the current local db or create it
-if it doesn't exists.
-
-To create a user specific db, use
-\"updatedb -l 0 -o db_path -U directory\".
-Where db_path is a filename matched by
-`helm-locate-db-file-regexp'.
-
-\(fn ARG)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "helm-man" "helm-man.el" (22348 36311 0 0))
-;;; Generated autoloads from helm-man.el
-
-(autoload 'helm-man-woman "helm-man" "\
-Preconfigured `helm' for Man and Woman pages.
-With a prefix arg reinitialize the cache.
-
-\(fn ARG)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "helm-misc" "helm-misc.el" (22348 36311 0 0))
-;;; Generated autoloads from helm-misc.el
-
-(autoload 'helm-browse-menubar "helm-misc" "\
-Preconfigured helm to the menubar using lacarte.el.
-
-\(fn)" t nil)
-
-(autoload 'helm-world-time "helm-misc" "\
-Preconfigured `helm' to show world time.
-Default action change TZ environment variable locally to emacs.
-
-\(fn)" t nil)
-
-(autoload 'helm-insert-latex-math "helm-misc" "\
-Preconfigured helm for latex math symbols completion.
-
-\(fn)" t nil)
-
-(autoload 'helm-ratpoison-commands "helm-misc" "\
-Preconfigured `helm' to execute ratpoison commands.
-
-\(fn)" t nil)
-
-(autoload 'helm-stumpwm-commands "helm-misc" "\
-Preconfigured helm for stumpwm commands.
-
-\(fn)" t nil)
-
-(autoload 'helm-minibuffer-history "helm-misc" "\
-Preconfigured `helm' for `minibuffer-history'.
-
-\(fn)" t nil)
-
-(autoload 'helm-comint-input-ring "helm-misc" "\
-Preconfigured `helm' that provide completion of `comint' history.
-
-\(fn)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "helm-mode" "helm-mode.el" (22348 36311 0 0))
-;;; Generated autoloads from helm-mode.el
-
-(autoload 'helm-comp-read "helm-mode" "\
-Read a string in the minibuffer, with helm completion.
-
-It is helm `completing-read' equivalent.
-
-- PROMPT is the prompt name to use.
-
-- COLLECTION can be a list, vector, obarray or hash-table.
- It can be also a function that receives three arguments:
- the values string, predicate and t. See `all-completions' for more details.
-
-Keys description:
-
-- TEST: A predicate called with one arg i.e candidate.
-
-- INITIAL-INPUT: Same as input arg in `helm'.
-
-- PRESELECT: See preselect arg of `helm'.
-
-- DEFAULT: This option is used only for compatibility with regular
- Emacs `completing-read' (Same as DEFAULT arg of `completing-read').
-
-- BUFFER: Name of helm-buffer.
-
-- MUST-MATCH: Candidate selected must be one of COLLECTION.
-
-- FUZZY: Enable fuzzy matching.
-
-- REVERSE-HISTORY: When non--nil display history source after current
- source completion.
-
-- REQUIRES-PATTERN: Same as helm attribute, default is 0.
-
-- HISTORY: A list containing specific history, default is nil.
- When it is non--nil, all elements of HISTORY are displayed in
- a special source before COLLECTION.
-
-- INPUT-HISTORY: A symbol. the minibuffer input history will be
- stored there, if nil or not provided, `minibuffer-history'
- will be used instead.
-
-- CASE-FOLD: Same as `helm-case-fold-search'.
-
-- DEL-INPUT: Boolean, when non--nil (default) remove the partial
- minibuffer input from HISTORY is present.
-
-- PERSISTENT-ACTION: A function called with one arg i.e candidate.
-
-- PERSISTENT-HELP: A string to document PERSISTENT-ACTION.
-
-- MODE-LINE: A string or list to display in mode line.
- Default is `helm-comp-read-mode-line'.
-
-- KEYMAP: A keymap to use in this `helm-comp-read'.
- (the keymap will be shared with history source)
-
-- NAME: The name related to this local source.
-
-- EXEC-WHEN-ONLY-ONE: Bound `helm-execute-action-at-once-if-one'
- to non--nil. (possibles values are t or nil).
-
-- VOLATILE: Use volatile attribute.
-
-- SORT: A predicate to give to `sort' e.g `string-lessp'
- Use this only on small data as it is ineficient.
- If you want to sort faster add a sort function to
- FC-TRANSFORMER.
- Note that FUZZY when enabled is already providing a sort function.
-
-- FC-TRANSFORMER: A `filtered-candidate-transformer' function
- or a list of functions.
-
-- HIST-FC-TRANSFORMER: A `filtered-candidate-transformer'
- function for the history source.
-
-- MARKED-CANDIDATES: If non--nil return candidate or marked candidates as a list.
-
-- NOMARK: When non--nil don't allow marking candidates.
-
-- ALISTP: (default is non--nil) See `helm-comp-read-get-candidates'.
-
-- CANDIDATES-IN-BUFFER: when non--nil use a source build with
- `helm-source-in-buffer' which is much faster.
- Argument VOLATILE have no effect when CANDIDATES-IN-BUFFER is non--nil.
-
-Any prefix args passed during `helm-comp-read' invocation will be recorded
-in `helm-current-prefix-arg', otherwise if prefix args were given before
-`helm-comp-read' invocation, the value of `current-prefix-arg' will be used.
-That's mean you can pass prefix args before or after calling a command
-that use `helm-comp-read' See `helm-M-x' for example.
-
-\(fn PROMPT COLLECTION &key TEST INITIAL-INPUT DEFAULT PRESELECT (buffer \"*Helm Completions*\") MUST-MATCH FUZZY REVERSE-HISTORY (requires-pattern 0) HISTORY INPUT-HISTORY (case-fold helm-comp-read-case-fold-search) (del-input t) (persistent-action nil) (persistent-help \"DoNothing\") (mode-line helm-comp-read-mode-line) HELP-MESSAGE (keymap helm-comp-read-map) (name \"Helm Completions\") CANDIDATES-IN-BUFFER EXEC-WHEN-ONLY-ONE QUIT-WHEN-NO-CAND (volatile t) SORT (fc-transformer (quote helm-cr-default-transformer)) HIST-FC-TRANSFORMER MARKED-CANDIDATES NOMARK (alistp t) (candidate-number-limit helm-candidate-number-limit))" nil nil)
-
-(autoload 'helm-read-file-name "helm-mode" "\
-Read a file name with helm completion.
-It is helm `read-file-name' emulation.
-
-Argument PROMPT is the default prompt to use.
-
-Keys description:
-
-- NAME: Source name, default to \"Read File Name\".
-
-- INITIAL-INPUT: Where to start read file name, default to `default-directory'.
-
-- BUFFER: `helm-buffer' name default to \"*Helm Completions*\".
-
-- TEST: A predicate called with one arg 'candidate'.
-
-- CASE-FOLD: Same as `helm-case-fold-search'.
-
-- PRESELECT: helm preselection.
-
-- HISTORY: Display HISTORY in a special source.
-
-- MUST-MATCH: Can be 'confirm, nil, or t.
-
-- MARKED-CANDIDATES: When non--nil return a list of marked candidates.
-
-- NOMARK: When non--nil don't allow marking candidates.
-
-- ALISTP: Don't use `all-completions' in history (take effect only on history).
-
-- PERSISTENT-ACTION: a persistent action function.
-
-- PERSISTENT-HELP: persistent help message.
-
-- MODE-LINE: A mode line message, default is `helm-read-file-name-mode-line-string'.
-
-\(fn PROMPT &key (name \"Read File Name\") (initial-input default-directory) (buffer \"*Helm file completions*\") TEST (case-fold helm-file-name-case-fold-search) PRESELECT HISTORY MUST-MATCH DEFAULT MARKED-CANDIDATES (candidate-number-limit helm-ff-candidate-number-limit) NOMARK (alistp t) (persistent-action (quote helm-find-files-persistent-action)) (persistent-help \"Hit1 Expand Candidate, Hit2 or (C-u) Find file\") (mode-line helm-read-file-name-mode-line-string))" nil nil)
-
-(defvar helm-mode nil "\
-Non-nil if Helm mode is enabled.
-See the command `helm-mode' for a description of this minor mode.
-Setting this variable directly does not take effect;
-either customize it (see the info node `Easy Customization')
-or call the function `helm-mode'.")
-
-(custom-autoload 'helm-mode "helm-mode" nil)
-
-(autoload 'helm-mode "helm-mode" "\
-Toggle generic helm completion.
-
-All functions in Emacs that use `completing-read'
-or `read-file-name' and friends will use helm interface
-when this mode is turned on.
-However you can modify this behavior for functions of your choice
-with `helm-completing-read-handlers-alist'.
-
-Called with a positive arg, turn on unconditionally, with a
-negative arg turn off.
-You can turn it on with `helm-mode'.
-
-Some crap emacs functions may not be supported,
-e.g `ffap-alternate-file' and maybe others
-You can add such functions to `helm-completing-read-handlers-alist'
-with a nil value.
-
-Note: This mode is incompatible with Emacs23.
-
-\(fn &optional ARG)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "helm-net" "helm-net.el" (22348 36311 0 0))
-;;; Generated autoloads from helm-net.el
-
-(autoload 'helm-surfraw "helm-net" "\
-Preconfigured `helm' to search PATTERN with search ENGINE.
-
-\(fn PATTERN ENGINE)" t nil)
-
-(autoload 'helm-google-suggest "helm-net" "\
-Preconfigured `helm' for google search with google suggest.
-
-\(fn)" t nil)
-
-(autoload 'helm-wikipedia-suggest "helm-net" "\
-Preconfigured `helm' for Wikipedia lookup with Wikipedia suggest.
-
-\(fn)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "helm-org" "helm-org.el" (22348 36311 0 0))
-;;; Generated autoloads from helm-org.el
-
-(autoload 'helm-org-agenda-files-headings "helm-org" "\
-Preconfigured helm for org files headings.
-
-\(fn)" t nil)
-
-(autoload 'helm-org-in-buffer-headings "helm-org" "\
-Preconfigured helm for org buffer headings.
-
-\(fn)" t nil)
-
-(autoload 'helm-org-parent-headings "helm-org" "\
-Preconfigured helm for org headings that are parents of the
-current heading.
-
-\(fn)" t nil)
-
-(autoload 'helm-org-capture-templates "helm-org" "\
-Preconfigured helm for org templates.
-
-\(fn)" t nil)
-
-(autoload 'helm-org-completing-read-tags "helm-org" "\
-
-
-\(fn PROMPT COLLECTION PRED REQ INITIAL HIST DEF INHERIT-INPUT-METHOD NAME BUFFER)" nil nil)
-
-;;;***
-\f
-;;;### (autoloads nil "helm-regexp" "helm-regexp.el" (22348 36311
-;;;;;; 0 0))
-;;; Generated autoloads from helm-regexp.el
-
-(autoload 'helm-moccur-mode "helm-regexp" "\
-Major mode to provide actions in helm moccur saved buffer.
-
-Special commands:
-\\{helm-moccur-mode-map}
-
-\(fn)" t nil)
-
-(autoload 'helm-regexp "helm-regexp" "\
-Preconfigured helm to build regexps.
-`query-replace-regexp' can be run from there against found regexp.
-
-\(fn)" t nil)
-
-(autoload 'helm-occur "helm-regexp" "\
-Preconfigured helm for Occur.
-
-\(fn)" t nil)
-
-(autoload 'helm-occur-from-isearch "helm-regexp" "\
-Invoke `helm-occur' from isearch.
-
-\(fn)" t nil)
-
-(autoload 'helm-multi-occur-from-isearch "helm-regexp" "\
-Invoke `helm-multi-occur' from isearch.
-
-With a prefix arg, reverse the behavior of
-`helm-moccur-always-search-in-current'.
-The prefix arg can be set before calling
-`helm-multi-occur-from-isearch' or during the buffer selection.
-
-\(fn &optional ARG)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "helm-ring" "helm-ring.el" (22348 36311 0 0))
-;;; Generated autoloads from helm-ring.el
-
-(defvar helm-push-mark-mode nil "\
-Non-nil if Helm-Push-Mark mode is enabled.
-See the command `helm-push-mark-mode' for a description of this minor mode.
-Setting this variable directly does not take effect;
-either customize it (see the info node `Easy Customization')
-or call the function `helm-push-mark-mode'.")
-
-(custom-autoload 'helm-push-mark-mode "helm-ring" nil)
-
-(autoload 'helm-push-mark-mode "helm-ring" "\
-Provide an improved version of `push-mark'.
-Modify the behavior of `push-mark' to update
-the `global-mark-ring' after each new visit.
-
-\(fn &optional ARG)" t nil)
-
-(autoload 'helm-mark-ring "helm-ring" "\
-Preconfigured `helm' for `helm-source-mark-ring'.
-
-\(fn)" t nil)
-
-(autoload 'helm-global-mark-ring "helm-ring" "\
-Preconfigured `helm' for `helm-source-global-mark-ring'.
-
-\(fn)" t nil)
-
-(autoload 'helm-all-mark-rings "helm-ring" "\
-Preconfigured `helm' for `helm-source-global-mark-ring' and `helm-source-mark-ring'.
-
-\(fn)" t nil)
-
-(autoload 'helm-register "helm-ring" "\
-Preconfigured `helm' for Emacs registers.
-
-\(fn)" t nil)
-
-(autoload 'helm-show-kill-ring "helm-ring" "\
-Preconfigured `helm' for `kill-ring'.
-It is drop-in replacement of `yank-pop'.
-
-First call open the kill-ring browser, next calls move to next line.
-
-\(fn)" t nil)
-
-(autoload 'helm-execute-kmacro "helm-ring" "\
-Preconfigured helm for keyboard macros.
-Define your macros with `f3' and `f4'.
-See (info \"(emacs) Keyboard Macros\") for detailed infos.
-This command is useful when used with persistent action.
-
-\(fn)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "helm-semantic" "helm-semantic.el" (22348 36311
-;;;;;; 0 0))
-;;; Generated autoloads from helm-semantic.el
-
-(autoload 'helm-semantic "helm-semantic" "\
-Preconfigured `helm' for `semantic'.
-If ARG is supplied, pre-select symbol at point instead of current
-
-\(fn ARG)" t nil)
-
-(autoload 'helm-semantic-or-imenu "helm-semantic" "\
-Preconfigured helm for `semantic' or `imenu'.
-If ARG is supplied, pre-select symbol at point instead of current
-semantic tag in scope.
-
-If `semantic-mode' is active in the current buffer, then use
-semantic for generating tags, otherwise fall back to `imenu'.
-Fill in the symbol at point by default.
-
-\(fn ARG)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "helm-sys" "helm-sys.el" (22348 36311 0 0))
-;;; Generated autoloads from helm-sys.el
-
-(defvar helm-top-poll-mode nil "\
-Non-nil if Helm-Top-Poll mode is enabled.
-See the command `helm-top-poll-mode' for a description of this minor mode.
-Setting this variable directly does not take effect;
-either customize it (see the info node `Easy Customization')
-or call the function `helm-top-poll-mode'.")
-
-(custom-autoload 'helm-top-poll-mode "helm-sys" nil)
-
-(autoload 'helm-top-poll-mode "helm-sys" "\
-Refresh automatically helm top buffer once enabled.
-
-\(fn &optional ARG)" t nil)
-
-(autoload 'helm-top "helm-sys" "\
-Preconfigured `helm' for top command.
-
-\(fn)" t nil)
-
-(autoload 'helm-list-emacs-process "helm-sys" "\
-Preconfigured `helm' for emacs process.
-
-\(fn)" t nil)
-
-(autoload 'helm-xrandr-set "helm-sys" "\
-Preconfigured helm for xrandr.
-
-\(fn)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "helm-tags" "helm-tags.el" (22348 36311 0 0))
-;;; Generated autoloads from helm-tags.el
-
-(autoload 'helm-etags-select "helm-tags" "\
-Preconfigured helm for etags.
-If called with a prefix argument REINIT
-or if any of the tag files have been modified, reinitialize cache.
-
-This function aggregates three sources of tag files:
-
- 1) An automatically located file in the parent directories,
- by `helm-etags-get-tag-file'.
- 2) `tags-file-name', which is commonly set by `find-tag' command.
- 3) `tags-table-list' which is commonly set by `visit-tags-table' command.
-
-\(fn REINIT)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil "helm-utils" "helm-utils.el" (22348 36311 0
-;;;;;; 0))
-;;; Generated autoloads from helm-utils.el
-
-(defvar helm-popup-tip-mode nil "\
-Non-nil if Helm-Popup-Tip mode is enabled.
-See the command `helm-popup-tip-mode' for a description of this minor mode.
-Setting this variable directly does not take effect;
-either customize it (see the info node `Easy Customization')
-or call the function `helm-popup-tip-mode'.")
-
-(custom-autoload 'helm-popup-tip-mode "helm-utils" nil)
-
-(autoload 'helm-popup-tip-mode "helm-utils" "\
-Show help-echo informations in a popup tip at end of line.
-
-\(fn &optional ARG)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil nil ("helm-easymenu.el" "helm-multi-match.el"
-;;;;;; "helm-pkg.el" "helm-plugin.el" "helm-types.el") (22348 36311
-;;;;;; 363287 0))
-
-;;;***
-\f
-;; Local Variables:
-;; version-control: never
-;; no-byte-compile: t
-;; no-update-autoloads: t
-;; End:
-;;; helm-autoloads.el ends here
+++ /dev/null
-;;; helm-bookmark.el --- Helm for Emacs regular Bookmarks. -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Code:
-(require 'cl-lib)
-(require 'bookmark)
-(require 'helm)
-(require 'helm-help)
-(require 'helm-types)
-(require 'helm-utils)
-(require 'helm-info)
-(require 'helm-adaptive)
-(require 'helm-net)
-
-(declare-function addressbook-bookmark-edit "ext:addressbook-bookmark.el" (bookmark))
-(declare-function message-buffers "message.el")
-(declare-function addressbook-set-mail-buffer-1 "ext:addressbook-bookmark.el"
- (&optional bookmark-name append cc))
-
-\f
-(defgroup helm-bookmark nil
- "Predefined configurations for `helm.el'."
- :group 'helm)
-
-(defcustom helm-bookmark-show-location nil
- "Show location of bookmark on display."
- :group 'helm-bookmark
- :type 'boolean)
-
-(defcustom helm-bookmark-default-filtered-sources
- (append '(helm-source-bookmark-files&dirs
- helm-source-bookmark-helm-find-files
- helm-source-bookmark-info
- helm-source-bookmark-gnus
- helm-source-bookmark-man
- helm-source-bookmark-images
- helm-source-bookmark-w3m)
- (and (locate-library "addressbook-bookmark")
- (list 'helm-source-bookmark-addressbook))
- (list 'helm-source-bookmark-uncategorized
- 'helm-source-bookmark-set))
- "List of sources to use in `helm-filtered-bookmarks'."
- :group 'helm-bookmark
- :type '(repeat (choice symbol)))
-
-(defcustom helm-bookmark-addressbook-actions
- '(("Show Contact(s)"
- . (lambda (candidate)
- (let* ((contacts (helm-marked-candidates))
- (current-prefix-arg helm-current-prefix-arg))
- (bookmark-jump
- (helm-bookmark-get-bookmark-from-name (car contacts)))
- (helm-aif (cdr contacts)
- (let ((current-prefix-arg '(4)))
- (cl-loop for bmk in it do
- (bookmark-jump
- (helm-bookmark-get-bookmark-from-name bmk))))))))
- ("Mail To" . helm-bookmark-addressbook-send-mail-1)
- ("Mail Cc" . (lambda (_candidate)
- (helm-bookmark-addressbook-send-mail-1 nil 'cc)))
- ("Mail Bcc" . (lambda (_candidate)
- (helm-bookmark-addressbook-send-mail-1 nil 'bcc)))
- ("Edit Bookmark"
- . (lambda (candidate)
- (let ((bmk (helm-bookmark-get-bookmark-from-name
- candidate)))
- (addressbook-bookmark-edit
- (assoc bmk bookmark-alist)))))
- ("Delete bookmark(s)" . helm-delete-marked-bookmarks)
- ("Insert Email at point"
- . (lambda (candidate)
- (let* ((bmk (helm-bookmark-get-bookmark-from-name
- candidate))
- (mlist (split-string
- (assoc-default
- 'email (assoc bmk bookmark-alist))
- ", ")))
- (insert
- (if (> (length mlist) 1)
- (helm-comp-read
- "Insert Mail Address: " mlist :must-match t)
- (car mlist))))))
- ("Show annotation"
- . (lambda (candidate)
- (let ((bmk (helm-bookmark-get-bookmark-from-name
- candidate)))
- (bookmark-show-annotation bmk))))
- ("Edit annotation"
- . (lambda (candidate)
- (let ((bmk (helm-bookmark-get-bookmark-from-name
- candidate)))
- (bookmark-edit-annotation bmk))))
- ("Show Google map"
- . (lambda (candidate)
- (let* ((bmk (helm-bookmark-get-bookmark-from-name
- candidate))
- (full-bmk (assoc bmk bookmark-alist)))
- (addressbook-google-map full-bmk)))))
- "Actions for addressbook bookmarks."
- :group 'helm-bookmark
- :type '(alist :key-type string :value-type function))
-
-\f
-(defface helm-bookmark-info
- '((t (:foreground "green")))
- "Face used for W3m Emacs bookmarks (not w3m bookmarks)."
- :group 'helm-bookmark)
-
-(defface helm-bookmark-w3m
- '((t (:foreground "yellow")))
- "Face used for W3m Emacs bookmarks (not w3m bookmarks)."
- :group 'helm-bookmark)
-
-(defface helm-bookmark-gnus
- '((t (:foreground "magenta")))
- "Face used for Gnus bookmarks."
- :group 'helm-bookmark)
-
-(defface helm-bookmark-man
- '((t (:foreground "Orange4")))
- "Face used for Woman/man bookmarks."
- :group 'helm-bookmark)
-
-(defface helm-bookmark-file
- '((t (:foreground "Deepskyblue2")))
- "Face used for file bookmarks."
- :group 'helm-bookmark)
-
-(defface helm-bookmark-directory
- '((t (:inherit helm-ff-directory)))
- "Face used for file bookmarks."
- :group 'helm-bookmark)
-
-(defface helm-bookmark-addressbook
- '((t (:foreground "tomato")))
- "Face used for addressbook bookmarks."
- :group 'helm-bookmark)
-
-\f
-(defvar helm-bookmark-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map helm-map)
- (define-key map (kbd "C-c o") 'helm-bookmark-run-jump-other-window)
- (define-key map (kbd "C-d") 'helm-bookmark-run-delete)
- (define-key map (kbd "C-]") 'helm-bookmark-toggle-filename)
- (define-key map (kbd "M-e") 'helm-bookmark-run-edit)
- map)
- "Generic Keymap for emacs bookmark sources.")
-
-(defclass helm-source-basic-bookmarks (helm-source-in-buffer helm-type-bookmark)
- ((init :initform (lambda ()
- (bookmark-maybe-load-default-file)
- (helm-init-candidates-in-buffer
- 'global
- (bookmark-all-names))))
- (filtered-candidate-transformer :initform 'helm-bookmark-transformer)))
-
-(defvar helm-source-bookmarks
- (helm-make-source "Bookmarks" 'helm-source-basic-bookmarks)
- "See (info \"(emacs)Bookmarks\").")
-
-(defun helm-bookmark-transformer (candidates _source)
- (cl-loop for i in candidates
- for loc = (bookmark-location i)
- for len = (string-width i)
- for trunc = (if (> len bookmark-bmenu-file-column)
- (helm-substring i bookmark-bmenu-file-column)
- i)
- for sep = (make-string (- (+ bookmark-bmenu-file-column 2)
- (length trunc))
- ? )
- if helm-bookmark-show-location
- collect (cons (concat trunc sep (if (listp loc) (car loc) loc)) i)
- else collect i))
-
-(defun helm-bookmark-toggle-filename-1 (_candidate)
- (let* ((real (helm-get-selection helm-buffer))
- (trunc (if (> (string-width real) bookmark-bmenu-file-column)
- (helm-substring real bookmark-bmenu-file-column)
- real))
- (loc (bookmark-location real)))
- (setq helm-bookmark-show-location (not helm-bookmark-show-location))
- (helm-update (if helm-bookmark-show-location
- (concat (regexp-quote trunc)
- " +"
- (regexp-quote
- (if (listp loc) (car loc) loc)))
- (regexp-quote real)))))
-
-(defun helm-bookmark-toggle-filename ()
- "Toggle bookmark location visibility."
- (interactive)
- (with-helm-alive-p
- (helm-attrset 'toggle-filename
- '(helm-bookmark-toggle-filename-1 . never-split))
- (helm-execute-persistent-action 'toggle-filename)))
-(put 'helm-bookmark-toggle-filename 'helm-only t)
-
-(defun helm-bookmark-jump (candidate)
- "Jump to bookmark from keyboard."
- (let ((current-prefix-arg helm-current-prefix-arg)
- non-essential)
- (bookmark-jump candidate)))
-
-(defun helm-bookmark-jump-other-window (candidate)
- (let (non-essential)
- (bookmark-jump-other-window candidate)))
-
-\f
-;;; bookmark-set
-;;
-(defvar helm-source-bookmark-set
- (helm-build-dummy-source "Set Bookmark"
- :filtered-candidate-transformer
- (lambda (_candidates _source)
- (list (or (and (not (string= helm-pattern ""))
- helm-pattern)
- "Enter a bookmark name to record")))
- :action '(("Set bookmark" . (lambda (candidate)
- (if (string= helm-pattern "")
- (message "No bookmark name given for record")
- (bookmark-set candidate))))))
- "See (info \"(emacs)Bookmarks\").")
-
-\f
-;;; Predicates
-;;
-(defconst helm-bookmark--non-file-filename " - no file -"
- "Name to use for `filename' entry, for non-file bookmarks.")
-
-(defun helm-bookmark-gnus-bookmark-p (bookmark)
- "Return non-nil if BOOKMARK is a Gnus bookmark.
-BOOKMARK is a bookmark name or a bookmark record."
- (or (eq (bookmark-get-handler bookmark) 'bmkext-jump-gnus)
- (eq (bookmark-get-handler bookmark) 'gnus-summary-bookmark-jump)
- (eq (bookmark-get-handler bookmark) 'bookmarkp-jump-gnus)))
-
-(defun helm-bookmark-w3m-bookmark-p (bookmark)
- "Return non-nil if BOOKMARK is a W3m bookmark.
-BOOKMARK is a bookmark name or a bookmark record."
- (or (eq (bookmark-get-handler bookmark) 'bmkext-jump-w3m)
- (eq (bookmark-get-handler bookmark) 'bookmark-w3m-bookmark-jump)
- (eq (bookmark-get-handler bookmark) 'bookmarkp-jump-w3m)))
-
-(defun helm-bookmark-woman-bookmark-p (bookmark)
- "Return non-nil if BOOKMARK is a Woman bookmark.
-BOOKMARK is a bookmark name or a bookmark record."
- (or (eq (bookmark-get-handler bookmark) 'bmkext-jump-woman)
- (eq (bookmark-get-handler bookmark) 'woman-bookmark-jump)
- (eq (bookmark-get-handler bookmark) 'bookmarkp-jump-woman)))
-
-(defun helm-bookmark-man-bookmark-p (bookmark)
- "Return non-nil if BOOKMARK is a Man bookmark.
-BOOKMARK is a bookmark name or a bookmark record."
- (or (eq (bookmark-get-handler bookmark) 'bmkext-jump-man)
- (eq (bookmark-get-handler bookmark) 'Man-bookmark-jump)
- (eq (bookmark-get-handler bookmark) 'bookmarkp-jump-man)))
-
-(defun helm-bookmark-woman-man-bookmark-p (bookmark)
- "Return non-nil if BOOKMARK is a Man or Woman bookmark.
-BOOKMARK is a bookmark name or a bookmark record."
- (or (helm-bookmark-man-bookmark-p bookmark)
- (helm-bookmark-woman-bookmark-p bookmark)))
-
-(defun helm-bookmark-info-bookmark-p (bookmark)
- "Return non-nil if BOOKMARK is an Info bookmark.
-BOOKMARK is a bookmark name or a bookmark record."
- (eq (bookmark-get-handler bookmark) 'Info-bookmark-jump))
-
-(defun helm-bookmark-image-bookmark-p (bookmark)
- "Return non-nil if BOOKMARK bookmarks an image file."
- (if (stringp bookmark)
- (assoc 'image-type (assoc bookmark bookmark-alist))
- (assoc 'image-type bookmark)))
-
-(defun helm-bookmark-file-p (bookmark)
- "Return non-nil if BOOKMARK bookmarks a file or directory.
-BOOKMARK is a bookmark name or a bookmark record.
-This excludes bookmarks of a more specific kind (Info, Gnus, and W3m)."
- (let* ((filename (bookmark-get-filename bookmark))
- (isnonfile (equal filename helm-bookmark--non-file-filename)))
- (and filename (not isnonfile) (not (bookmark-get-handler bookmark)))))
-
-(defun helm-bookmark-helm-find-files-p (bookmark)
- "Return non-nil if BOOKMARK bookmarks a `helm-find-files' session.
-BOOKMARK is a bookmark name or a bookmark record."
- (eq (bookmark-get-handler bookmark) 'helm-ff-bookmark-jump))
-
-(defun helm-bookmark-addressbook-p (bookmark)
- "Return non--nil if BOOKMARK is a contact recorded with addressbook-bookmark.
-BOOKMARK is a bookmark name or a bookmark record."
- (if (listp bookmark)
- (string= (assoc-default 'type bookmark) "addressbook")
- (string= (assoc-default
- 'type (assoc bookmark bookmark-alist)) "addressbook")))
-
-(defun helm-bookmark-uncategorized-bookmark-p (bookmark)
- "Return non--nil if BOOKMARK match no known category."
- (cl-loop for pred in '(helm-bookmark-addressbook-p
- helm-bookmark-gnus-bookmark-p
- helm-bookmark-w3m-bookmark-p
- helm-bookmark-woman-man-bookmark-p
- helm-bookmark-info-bookmark-p
- helm-bookmark-image-bookmark-p
- helm-bookmark-file-p
- helm-bookmark-helm-find-files-p
- helm-bookmark-addressbook-p)
- never (funcall pred bookmark)))
-
-(defun helm-bookmark-filter-setup-alist (fn)
- "Return a filtered `bookmark-alist' sorted alphabetically."
- (cl-loop for b in bookmark-alist
- for name = (car b)
- when (funcall fn b) collect
- (propertize name 'location (bookmark-location name))))
-\f
-;;; Bookmark handlers
-;;
-(defvar w3m-async-exec)
-(defun helm-bookmark-jump-w3m (bookmark)
- "Jump to W3m bookmark BOOKMARK, setting a new tab.
-If `browse-url-browser-function' is set to something else
-than `w3m-browse-url' use it."
- (require 'helm-net)
- (let ((file (or (bookmark-prop-get bookmark 'filename)
- (bookmark-prop-get bookmark 'url)))
- (buf (generate-new-buffer-name "*w3m*"))
- (w3m-async-exec nil)
- (really-use-w3m (equal browse-url-browser-function 'w3m-browse-url)))
- (helm-browse-url file really-use-w3m)
- (when really-use-w3m
- (bookmark-default-handler
- `("" (buffer . ,buf) . ,(bookmark-get-bookmark-record bookmark))))))
-
-;; All bookmarks recorded with the handler provided with w3m
-;; (`bookmark-w3m-bookmark-jump') will use our handler which open
-;; the bookmark in a new tab or in an external browser depending
-;; on `browse-url-browser-function'.
-(defalias 'bookmark-w3m-bookmark-jump 'helm-bookmark-jump-w3m)
-
-;; Provide compatibility with old handlers provided in external
-;; packages bookmark-extensions.el and bookmark+.
-(defalias 'bmkext-jump-woman 'woman-bookmark-jump)
-(defalias 'bmkext-jump-man 'Man-bookmark-jump)
-(defalias 'bmkext-jump-w3m 'helm-bookmark-jump-w3m)
-(defalias 'bmkext-jump-gnus 'gnus-summary-bookmark-jump)
-(defalias 'bookmarkp-jump-gnus 'gnus-summary-bookmark-jump)
-(defalias 'bookmarkp-jump-w3m 'helm-bookmark-jump-w3m)
-(defalias 'bookmarkp-jump-woman 'woman-bookmark-jump)
-(defalias 'bookmarkp-jump-man 'Man-bookmark-jump)
-
-\f
-;;;; Filtered bookmark sources
-;;
-;;
-(defclass helm-source-filtered-bookmarks (helm-source-in-buffer helm-type-bookmark)
- ((filtered-candidate-transformer
- :initform '(helm-adaptive-sort
- helm-highlight-bookmark))))
-
-;;; W3m bookmarks.
-;;
-(defun helm-bookmark-w3m-setup-alist ()
- "Specialized filter function for bookmarks w3m."
- (helm-bookmark-filter-setup-alist 'helm-bookmark-w3m-bookmark-p))
-
-(defvar helm-source-bookmark-w3m
- (helm-make-source "Bookmark W3m" 'helm-source-filtered-bookmarks
- :init (lambda ()
- (bookmark-maybe-load-default-file)
- (helm-init-candidates-in-buffer
- 'global (helm-bookmark-w3m-setup-alist)))))
-
-;;; Images
-;;
-(defun helm-bookmark-images-setup-alist ()
- "Specialized filter function for images bookmarks."
- (helm-bookmark-filter-setup-alist 'helm-bookmark-image-bookmark-p))
-
-(defvar helm-source-bookmark-images
- (helm-make-source "Bookmark Images" 'helm-source-filtered-bookmarks
- :init (lambda ()
- (bookmark-maybe-load-default-file)
- (helm-init-candidates-in-buffer
- 'global (helm-bookmark-images-setup-alist)))))
-
-;;; Woman Man
-;;
-(defun helm-bookmark-man-setup-alist ()
- "Specialized filter function for bookmarks w3m."
- (helm-bookmark-filter-setup-alist 'helm-bookmark-woman-man-bookmark-p))
-
-(defvar helm-source-bookmark-man
- (helm-make-source "Bookmark Woman&Man" 'helm-source-filtered-bookmarks
- :init (lambda ()
- (bookmark-maybe-load-default-file)
- (helm-init-candidates-in-buffer
- 'global (helm-bookmark-man-setup-alist)))))
-
-;;; Gnus
-;;
-(defun helm-bookmark-gnus-setup-alist ()
- "Specialized filter function for bookmarks gnus."
- (helm-bookmark-filter-setup-alist 'helm-bookmark-gnus-bookmark-p))
-
-(defvar helm-source-bookmark-gnus
- (helm-make-source "Bookmark Gnus" 'helm-source-filtered-bookmarks
- :init (lambda ()
- (bookmark-maybe-load-default-file)
- (helm-init-candidates-in-buffer
- 'global (helm-bookmark-gnus-setup-alist)))))
-
-;;; Info
-;;
-(defun helm-bookmark-info-setup-alist ()
- "Specialized filter function for bookmarks info."
- (helm-bookmark-filter-setup-alist 'helm-bookmark-info-bookmark-p))
-
-(defvar helm-source-bookmark-info
- (helm-make-source "Bookmark Info" 'helm-source-filtered-bookmarks
- :init (lambda ()
- (bookmark-maybe-load-default-file)
- (helm-init-candidates-in-buffer
- 'global (helm-bookmark-info-setup-alist)))))
-
-;;; Files and directories
-;;
-(defun helm-bookmark-local-files-setup-alist ()
- "Specialized filter function for bookmarks locals files."
- (helm-bookmark-filter-setup-alist 'helm-bookmark-file-p))
-
-(defvar helm-source-bookmark-files&dirs
- (helm-make-source "Bookmark Files&Directories" 'helm-source-filtered-bookmarks
- :init (lambda ()
- (bookmark-maybe-load-default-file)
- (helm-init-candidates-in-buffer
- 'global (helm-bookmark-local-files-setup-alist)))))
-
-;;; Helm find files sessions.
-;;
-(defun helm-bookmark-helm-find-files-setup-alist ()
- "Specialized filter function for `helm-find-files' bookmarks."
- (helm-bookmark-filter-setup-alist 'helm-bookmark-helm-find-files-p))
-
-(defvar helm-source-bookmark-helm-find-files
- (helm-make-source "Bookmark helm-find-files sessions" 'helm-source-filtered-bookmarks
- :init (lambda ()
- (bookmark-maybe-load-default-file)
- (helm-init-candidates-in-buffer
- 'global (helm-bookmark-helm-find-files-setup-alist)))
- :persistent-action (lambda (_candidate) (ignore))
- :persistent-help "Do nothing"))
-
-;;; Uncategorized bookmarks
-;;
-(defun helm-bookmark-uncategorized-setup-alist ()
- "Specialized filter function for uncategorized bookmarks."
- (helm-bookmark-filter-setup-alist 'helm-bookmark-uncategorized-bookmark-p))
-
-(defvar helm-source-bookmark-uncategorized
- (helm-make-source "Bookmark uncategorized" 'helm-source-filtered-bookmarks
- :init (lambda ()
- (bookmark-maybe-load-default-file)
- (helm-init-candidates-in-buffer
- 'global (helm-bookmark-uncategorized-setup-alist)))))
-
-;;; Addressbook.
-;;
-;;
-(defclass helm-bookmark-addressbook-class (helm-source-in-buffer)
- ((init :initform (lambda ()
- (require 'addressbook-bookmark nil t)
- (bookmark-maybe-load-default-file)
- (helm-init-candidates-in-buffer
- 'global
- (helm-bookmark-addressbook-setup-alist))))
- (persistent-action :initform
- (lambda (candidate)
- (let ((bmk (helm-bookmark-get-bookmark-from-name
- candidate)))
- (bookmark--jump-via bmk 'switch-to-buffer))))
- (persistent-help :initform "Show contact - Prefix with C-u to append")
- (mode-line :initform (list "Contact(s)" helm-mode-line-string))
- (filtered-candidate-transformer :initform
- '(helm-adaptive-sort
- helm-highlight-bookmark))
- (action :initform 'helm-bookmark-addressbook-actions)))
-
-(defun helm-bookmark-addressbook-send-mail-1 (_candidate &optional cc)
- (let* ((contacts (helm-marked-candidates))
- (bookmark (helm-bookmark-get-bookmark-from-name
- (car contacts)))
- (append (message-buffers)))
- (addressbook-set-mail-buffer-1 bookmark append)
- (helm-aif (cdr contacts)
- (progn
- (when cc (addressbook-set-mail-buffer-1 (car it) nil cc))
- (cl-loop for bmk in (cdr it) do
- (addressbook-set-mail-buffer-1
- (helm-bookmark-get-bookmark-from-name bmk) 'append cc))))))
-
-(defun helm-bookmark-addressbook-setup-alist ()
- "Specialized filter function for addressbook bookmarks."
- (helm-bookmark-filter-setup-alist 'helm-bookmark-addressbook-p))
-
-(defvar helm-source-bookmark-addressbook
- (helm-make-source "Bookmark Addressbook" 'helm-bookmark-addressbook-class))
-
-;;; Transformer
-;;
-\f
-(defun helm-highlight-bookmark (bookmarks _source)
- "Used as `filtered-candidate-transformer' to colorize bookmarks."
- (let ((non-essential t))
- (cl-loop for i in bookmarks
- for isfile = (bookmark-get-filename i)
- for hff = (helm-bookmark-helm-find-files-p i)
- for handlerp = (and (fboundp 'bookmark-get-handler)
- (bookmark-get-handler i))
- for isw3m = (and (fboundp 'helm-bookmark-w3m-bookmark-p)
- (helm-bookmark-w3m-bookmark-p i))
- for isgnus = (and (fboundp 'helm-bookmark-gnus-bookmark-p)
- (helm-bookmark-gnus-bookmark-p i))
- for isman = (and (fboundp 'helm-bookmark-man-bookmark-p) ; Man
- (helm-bookmark-man-bookmark-p i))
- for iswoman = (and (fboundp 'helm-bookmark-woman-bookmark-p) ; Woman
- (helm-bookmark-woman-bookmark-p i))
- for isannotation = (bookmark-get-annotation i)
- for isabook = (string= (bookmark-prop-get i 'type)
- "addressbook")
- for isinfo = (eq handlerp 'Info-bookmark-jump)
- for loc = (bookmark-location i)
- for len = (string-width i)
- for trunc = (if (and helm-bookmark-show-location
- (> len bookmark-bmenu-file-column))
- (helm-substring
- i bookmark-bmenu-file-column)
- i)
- ;; Add a * if bookmark have annotation
- if (and isannotation (not (string-equal isannotation "")))
- do (setq trunc (concat "*" (if helm-bookmark-show-location trunc i)))
- for sep = (and helm-bookmark-show-location
- (make-string (- (+ bookmark-bmenu-file-column 2)
- (string-width trunc))
- ? ))
- for bmk = (cond ( ;; info buffers
- isinfo
- (propertize trunc 'face 'helm-bookmark-info
- 'help-echo isfile))
- ( ;; w3m buffers
- isw3m
- (propertize trunc 'face 'helm-bookmark-w3m
- 'help-echo isfile))
- ( ;; gnus buffers
- isgnus
- (propertize trunc 'face 'helm-bookmark-gnus
- 'help-echo isfile))
- ( ;; Man Woman
- (or iswoman isman)
- (propertize trunc 'face 'helm-bookmark-man
- 'help-echo isfile))
- ( ;; Addressbook
- isabook
- (propertize trunc 'face 'helm-bookmark-addressbook))
- ( ;; directories
- (and isfile
- (or hff
- ;; This is needed because `non-essential'
- ;; is not working on Emacs-24.2 and the behavior
- ;; of tramp seems to have changed since previous
- ;; versions (Need to reenter password even if a
- ;; first connection have been established,
- ;; probably when host is named differently
- ;; i.e machine/localhost)
- (and (not (file-remote-p isfile))
- (file-directory-p isfile))))
- (propertize trunc 'face 'helm-bookmark-directory
- 'help-echo isfile))
- ( ;; regular files
- t
- (propertize trunc 'face 'helm-bookmark-file
- 'help-echo isfile)))
- collect (if helm-bookmark-show-location
- (cons (concat bmk sep (if (listp loc) (car loc) loc))
- i)
- (cons bmk i)))))
-
-\f
-;;; Edit/rename/save bookmarks.
-;;
-;;
-(defun helm-bookmark-edit-bookmark (bookmark-name)
- "Edit bookmark's name and file name, and maybe save them.
-BOOKMARK-NAME is the current (old) name of the bookmark to be renamed."
- (let ((bmk (helm-bookmark-get-bookmark-from-name bookmark-name))
- (handler (bookmark-prop-get bookmark-name 'handler)))
- (if (eq handler 'addressbook-bookmark-jump)
- (addressbook-bookmark-edit
- (assoc bmk bookmark-alist))
- (helm-bookmark-edit-bookmark-1 bookmark-name handler))))
-
-(defun helm-bookmark-edit-bookmark-1 (bookmark-name handler)
- (let* ((helm--reading-passwd-or-string t)
- (bookmark-fname (bookmark-get-filename bookmark-name))
- (bookmark-loc (bookmark-prop-get bookmark-name 'location))
- (new-name (read-from-minibuffer "Name: " bookmark-name))
- (new-loc (read-from-minibuffer "FileName or Location: "
- (or bookmark-fname
- (if (consp bookmark-loc)
- (car bookmark-loc)
- bookmark-loc))))
- (docid (and (eq handler 'mu4e-bookmark-jump)
- (read-number "Docid: " (cdr bookmark-loc)))))
- (when docid
- (setq new-loc (cons new-loc docid)))
- (when (and (not (equal new-name "")) (not (equal new-loc ""))
- (y-or-n-p "Save changes? "))
- (if bookmark-fname
- (progn
- (helm-bookmark-rename bookmark-name new-name 'batch)
- (bookmark-set-filename new-name new-loc))
- (bookmark-prop-set
- (bookmark-get-bookmark bookmark-name) 'location new-loc)
- (helm-bookmark-rename bookmark-name new-name 'batch))
- (helm-bookmark-maybe-save-bookmark)
- (list new-name new-loc))))
-
-(defun helm-bookmark-maybe-save-bookmark ()
- "Increment save counter and maybe save `bookmark-alist'."
- (setq bookmark-alist-modification-count (1+ bookmark-alist-modification-count))
- (when (bookmark-time-to-save-p) (bookmark-save)))
-
-(defun helm-bookmark-rename (old &optional new batch)
- "Change bookmark's name from OLD to NEW.
-Interactively:
- If called from the keyboard, then prompt for OLD.
- If called from the menubar, select OLD from a menu.
-If NEW is nil, then prompt for its string value.
-
-If BATCH is non-nil, then do not rebuild the menu list.
-
-While the user enters the new name, repeated `C-w' inserts consecutive
-words from the buffer into the new bookmark name."
- (interactive (list (bookmark-completing-read "Old bookmark name")))
- (bookmark-maybe-historicize-string old)
- (bookmark-maybe-load-default-file)
- (save-excursion (skip-chars-forward " ") (setq bookmark-yank-point (point)))
- (setq bookmark-current-buffer (current-buffer))
- (let ((newname (or new (read-from-minibuffer
- "New name: " nil
- (let ((now-map (copy-keymap minibuffer-local-map)))
- (define-key now-map "\C-w" 'bookmark-yank-word)
- now-map)
- nil 'bookmark-history))))
- (bookmark-set-name old newname)
- (setq bookmark-current-bookmark newname)
- (unless batch (bookmark-bmenu-surreptitiously-rebuild-list))
- (helm-bookmark-maybe-save-bookmark) newname))
-
-(defun helm-bookmark-run-edit ()
- "Run `helm-bookmark-edit-bookmark' from keyboard."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-bookmark-edit-bookmark)))
-(put 'helm-bookmark-run-edit 'helm-only t)
-
-\f
-(defun helm-bookmark-run-jump-other-window ()
- "Jump to bookmark from keyboard."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'bookmark-jump-other-window)))
-(put 'helm-bookmark-run-jump-other-window 'helm-only t)
-
-(defun helm-bookmark-run-delete ()
- "Delete bookmark from keyboard."
- (interactive)
- (with-helm-alive-p
- (when (y-or-n-p "Delete bookmark(s)?")
- (helm-exit-and-execute-action 'helm-delete-marked-bookmarks))))
-(put 'helm-bookmark-run-delete 'helm-only t)
-
-(defun helm-bookmark-get-bookmark-from-name (bmk)
- "Return bookmark name even if it is a bookmark with annotation.
-e.g prepended with *."
- (let ((bookmark (replace-regexp-in-string "\\`\\*" "" bmk)))
- (if (assoc bookmark bookmark-alist) bookmark bmk)))
-
-(defun helm-delete-marked-bookmarks (_ignore)
- "Delete this bookmark or all marked bookmarks."
- (cl-dolist (i (helm-marked-candidates))
- (bookmark-delete (helm-bookmark-get-bookmark-from-name i)
- 'batch)))
-
-
-;;;###autoload
-(defun helm-bookmarks ()
- "Preconfigured `helm' for bookmarks."
- (interactive)
- (helm :sources '(helm-source-bookmarks
- helm-source-bookmark-set)
- :buffer "*helm bookmarks*"
- :default (buffer-name helm-current-buffer)))
-
-;;;###autoload
-(defun helm-filtered-bookmarks ()
- "Preconfigured helm for bookmarks (filtered by category).
-Optional source `helm-source-bookmark-addressbook' is loaded
-only if external library addressbook-bookmark.el is available."
- (interactive)
- (helm :sources helm-bookmark-default-filtered-sources
- :prompt "Search Bookmark: "
- :buffer "*helm filtered bookmarks*"
- :default (list (thing-at-point 'symbol)
- (buffer-name helm-current-buffer))))
-
-(provide 'helm-bookmark)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-bookmark.el ends here
+++ /dev/null
-;;; helm-buffers.el --- helm support for buffers. -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Code:
-\f
-(require 'cl-lib)
-(require 'helm)
-(require 'helm-types)
-(require 'helm-utils)
-(require 'helm-elscreen)
-(require 'helm-grep)
-(require 'helm-plugin)
-(require 'helm-regexp)
-(require 'helm-help)
-
-(declare-function ido-make-buffer-list "ido" (default))
-(declare-function ido-add-virtual-buffers-to-list "ido")
-(declare-function helm-comp-read "helm-mode")
-(declare-function helm-browse-project "helm-files")
-
-\f
-(defgroup helm-buffers nil
- "Buffers related Applications and libraries for Helm."
- :group 'helm)
-
-(defcustom helm-boring-buffer-regexp-list
- '("\\` " "\\*helm" "\\*helm-mode" "\\*Echo Area" "\\*Minibuf")
- "The regexp list that match boring buffers.
-Buffer candidates matching these regular expression will be
-filtered from the list of candidates if the
-`helm-skip-boring-buffers' candidate transformer is used."
- :type '(repeat (choice regexp))
- :group 'helm-buffers)
-
-(defcustom helm-white-buffer-regexp-list nil
- "The regexp list of not boring buffers.
-These buffers will be displayed even if they match one of
-`helm-boring-buffer-regexp-list'."
- :type '(repeat (choice regexp))
- :group 'helm-buffers)
-
-(defcustom helm-buffers-favorite-modes '(lisp-interaction-mode
- emacs-lisp-mode
- text-mode
- org-mode)
- "List of preferred mode to open new buffers with."
- :type '(repeat (choice function))
- :group 'helm-buffers)
-
-(defcustom helm-buffer-max-length 20
- "Max length of buffer names before truncate.
-When disabled (nil) use the longest buffer-name length found."
- :group 'helm-buffers
- :type '(choice (const :tag "Disabled" nil)
- (integer :tag "Length before truncate")))
-
-(defcustom helm-buffer-details-flag t
- "Always show details in buffer list when non--nil."
- :group 'helm-buffers
- :type 'boolean)
-
-(defcustom helm-buffers-fuzzy-matching nil
- "Fuzzy matching buffer names when non--nil.
-Only buffer names are fuzzy matched when this is enabled,
-`major-mode' matching is not affected by this."
- :group 'helm-buffers
- :type 'boolean)
-
-(defcustom helm-buffer-skip-remote-checking nil
- "Ignore checking for `file-exists-p' on remote files."
- :group 'helm-buffers
- :type 'boolean)
-
-(defcustom helm-buffers-truncate-lines t
- "Truncate lines in `helm-buffers-list' when non--nil."
- :group 'helm-buffers
- :type 'boolean)
-
-(defcustom helm-mini-default-sources '(helm-source-buffers-list
- helm-source-recentf
- helm-source-buffer-not-found)
- "Default sources list used in `helm-mini'."
- :group 'helm-buffers
- :type '(repeat (choice symbol)))
-
-(defcustom helm-buffers-end-truncated-string "..."
- "The string to display at end of truncated buffer names."
- :type 'string
- :group 'helm-buffers)
-
-\f
-;;; Faces
-;;
-;;
-(defgroup helm-buffers-faces nil
- "Customize the appearance of helm-buffers."
- :prefix "helm-"
- :group 'helm-buffers
- :group 'helm-faces)
-
-(defface helm-buffer-saved-out
- '((t (:foreground "red" :background "black")))
- "Face used for buffer files modified outside of emacs."
- :group 'helm-buffers-faces)
-
-(defface helm-buffer-not-saved
- '((t (:foreground "Indianred2")))
- "Face used for buffer files not already saved on disk."
- :group 'helm-buffers-faces)
-
-(defface helm-buffer-size
- '((((background dark)) :foreground "RosyBrown")
- (((background light)) :foreground "SlateGray"))
- "Face used for buffer size."
- :group 'helm-buffers-faces)
-
-(defface helm-buffer-process
- '((t (:foreground "Sienna3")))
- "Face used for process status in buffer."
- :group 'helm-buffers-faces)
-
-(defface helm-buffer-directory
- '((t (:foreground "DarkRed" :background "LightGray")))
- "Face used for directories in `helm-buffers-list'."
- :group 'helm-buffers-faces)
-
-(defface helm-buffer-file
- '((t :inherit font-lock-builtin-face))
- "Face for buffer file names in `helm-buffers-list'."
- :group 'helm-buffers-faces)
-
-\f
-;;; Buffers keymap
-;;
-(defvar helm-buffer-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map helm-map)
- ;; No need to have separate command for grep and zgrep
- ;; as we don't use recursivity for buffers.
- ;; So use zgrep for both as it is capable to handle non--compressed files.
- (define-key map (kbd "M-g s") 'helm-buffer-run-zgrep)
- (define-key map (kbd "C-s") 'helm-buffers-run-multi-occur)
- (define-key map (kbd "C-x C-d") 'helm-buffers-run-browse-project)
- (define-key map (kbd "C-c o") 'helm-buffer-switch-other-window)
- (define-key map (kbd "C-c C-o") 'helm-buffer-switch-other-frame)
- (define-key map (kbd "C-c =") 'helm-buffer-run-ediff)
- (define-key map (kbd "M-=") 'helm-buffer-run-ediff-merge)
- (define-key map (kbd "C-=") 'helm-buffer-diff-persistent)
- (define-key map (kbd "M-U") 'helm-buffer-revert-persistent)
- (define-key map (kbd "C-c d") 'helm-buffer-run-kill-persistent)
- (define-key map (kbd "M-D") 'helm-buffer-run-kill-buffers)
- (define-key map (kbd "C-x C-s") 'helm-buffer-save-persistent)
- (define-key map (kbd "C-M-%") 'helm-buffer-run-query-replace-regexp)
- (define-key map (kbd "M-%") 'helm-buffer-run-query-replace)
- (define-key map (kbd "M-m") 'helm-toggle-all-marks)
- (define-key map (kbd "M-a") 'helm-mark-all)
- (define-key map (kbd "C-]") 'helm-toggle-buffers-details)
- (define-key map (kbd "C-c a") 'helm-buffers-toggle-show-hidden-buffers)
- (define-key map (kbd "<C-M-SPC>") 'helm-buffers-mark-similar-buffers)
- map)
- "Keymap for buffer sources in helm.")
-
-(defvar helm-buffers-ido-virtual-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map helm-map)
- (define-key map (kbd "C-c o") 'helm-ff-run-switch-other-window)
- (define-key map (kbd "C-c C-o") 'helm-ff-run-switch-other-frame)
- (define-key map (kbd "M-g s") 'helm-ff-run-grep)
- (define-key map (kbd "M-g z") 'helm-ff-run-zgrep)
- (define-key map (kbd "M-D") 'helm-ff-run-delete-file)
- (define-key map (kbd "C-c C-x") 'helm-ff-run-open-file-externally)
- map))
-
-\f
-(defvar helm-buffers-list-cache nil)
-(defvar helm-buffer-max-len-mode nil)
-(defvar helm-buffers-in-project-p nil)
-
-(defun helm-buffers-list--init ()
- ;; Issue #51 Create the list before `helm-buffer' creation.
- (setq helm-buffers-list-cache (funcall (helm-attr 'buffer-list)))
- (let ((result (cl-loop for b in helm-buffers-list-cache
- maximize (length b) into len-buf
- maximize (length (with-current-buffer b
- (format-mode-line mode-name)))
- into len-mode
- finally return (cons len-buf len-mode))))
- (unless (default-value 'helm-buffer-max-length)
- (helm-set-local-variable 'helm-buffer-max-length (car result)))
- (unless (default-value 'helm-buffer-max-len-mode)
- (helm-set-local-variable 'helm-buffer-max-len-mode (cdr result)))))
-
-(defclass helm-source-buffers (helm-source-sync helm-type-buffer)
- ((buffer-list
- :initarg :buffer-list
- :initform #'helm-buffer-list
- :custom function
- :documentation
- " A function with no arguments to create buffer list.")
- (init :initform 'helm-buffers-list--init)
- (candidates :initform helm-buffers-list-cache)
- (matchplugin :initform nil)
- (match :initform 'helm-buffers-match-function)
- (persistent-action :initform 'helm-buffers-list-persistent-action)
- (resume :initform (lambda ()
- (run-with-idle-timer
- 0.1 nil (lambda ()
- (with-helm-buffer
- (helm-force-update))))))
- (keymap :initform helm-buffer-map)
- (migemo :initform 'nomultimatch)
- (volatile :initform t)
- (help-message :initform 'helm-buffer-help-message)
- (persistent-help
- :initform
- "Show this buffer / C-u \\[helm-execute-persistent-action]: Kill this buffer")))
-
-(defvar helm-source-buffers-list nil)
-
-(defvar helm-source-buffer-not-found
- (helm-build-dummy-source
- "Create buffer"
- :action (helm-make-actions
- "Create buffer (C-u choose mode)"
- (lambda (candidate)
- (let ((mjm (or (and helm-current-prefix-arg
- (intern-soft (helm-comp-read
- "Major-mode: "
- helm-buffers-favorite-modes)))
- (cl-loop for (r . m) in auto-mode-alist
- when (string-match r candidate)
- return m)))
- (buffer (get-buffer-create candidate)))
- (if mjm
- (with-current-buffer buffer (funcall mjm))
- (set-buffer-major-mode buffer))
- (switch-to-buffer buffer))))))
-
-(defvar ido-temp-list)
-(defvar ido-ignored-list)
-(defvar ido-process-ignore-lists)
-(defvar ido-use-virtual-buffers)
-(defvar ido-virtual-buffers)
-
-(defvar helm-source-ido-virtual-buffers
- (helm-build-sync-source "Ido virtual buffers"
- :candidates (lambda ()
- (let (ido-temp-list
- ido-ignored-list
- (ido-process-ignore-lists t))
- (when ido-use-virtual-buffers
- (ido-add-virtual-buffers-to-list)
- ido-virtual-buffers)))
- :fuzzy-match helm-buffers-fuzzy-matching
- :keymap helm-buffers-ido-virtual-map
- :help-message 'helm-buffers-ido-virtual-help-message
- :action '(("Find file" . helm-find-many-files)
- ("Find file other window" . find-file-other-window)
- ("Find file other frame" . find-file-other-frame)
- ("Find file as root" . helm-find-file-as-root)
- ("Grep File(s) `C-u recurse'" . helm-find-files-grep)
- ("Zgrep File(s) `C-u Recurse'" . helm-ff-zgrep)
- ("View file" . view-file)
- ("Delete file(s)" . helm-delete-marked-files)
- ("Open file externally (C-u to choose)"
- . helm-open-file-externally))))
-
-\f
-(defvar ido-use-virtual-buffers)
-(defvar ido-ignore-buffers)
-(defun helm-buffer-list ()
- "Return the current list of buffers.
-Currently visible buffers are put at the end of the list.
-See `ido-make-buffer-list' for more infos."
- (require 'ido)
- (let ((ido-process-ignore-lists t)
- ido-ignored-list
- ido-ignore-buffers
- ido-use-virtual-buffers)
- (ido-make-buffer-list nil)))
-
-(defun helm-buffer-size (buffer)
- "Return size of BUFFER."
- (with-current-buffer buffer
- (save-restriction
- (widen)
- (helm-file-human-size
- (- (position-bytes (point-max))
- (position-bytes (point-min)))))))
-
-(defun helm-buffer--show-details (buf-name prefix help-echo
- size mode dir face1 face2
- proc details type)
- (append
- (list
- (concat prefix
- (propertize buf-name 'face face1
- 'help-echo help-echo
- 'type type)))
- (and details
- (list size mode
- (propertize
- (if proc
- (format "(%s %s in `%s')"
- (process-name proc)
- (process-status proc) dir)
- (format "(in `%s')" dir))
- 'face face2)))))
-
-(defun helm-buffer--details (buffer &optional details)
- (let* ((mode (with-current-buffer buffer (format-mode-line mode-name)))
- (buf (get-buffer buffer))
- (size (propertize (helm-buffer-size buf)
- 'face 'helm-buffer-size))
- (proc (get-buffer-process buf))
- (dir (with-current-buffer buffer (helm-aif default-directory (abbreviate-file-name it))))
- (file-name (helm-aif (buffer-file-name buf) (abbreviate-file-name it)))
- (name (buffer-name buf))
- (name-prefix (when (and dir (file-remote-p dir))
- (propertize "@ " 'face 'helm-ff-prefix))))
- ;; No fancy things on remote buffers.
- (if (and name-prefix helm-buffer-skip-remote-checking)
- (helm-buffer--show-details
- name name-prefix file-name size mode dir
- 'helm-buffer-file 'helm-buffer-process nil details 'filebuf)
- (cond
- ( ;; A dired buffer.
- (rassoc buf dired-buffers)
- (helm-buffer--show-details
- name name-prefix dir size mode dir
- 'helm-buffer-directory 'helm-buffer-process nil details 'dired))
- ;; A buffer file modified somewhere outside of emacs.=>red
- ((and file-name
- (file-exists-p file-name)
- (not (verify-visited-file-modtime buf)))
- (helm-buffer--show-details
- name name-prefix file-name size mode dir
- 'helm-buffer-saved-out 'helm-buffer-process nil details 'modout))
- ;; A new buffer file not already saved on disk (or a deleted file) .=>indianred2
- ((and file-name (not (file-exists-p file-name)))
- (helm-buffer--show-details
- name name-prefix file-name size mode dir
- 'helm-buffer-not-saved 'helm-buffer-process nil details 'notsaved))
- ;; A buffer file modified and not saved on disk.=>orange
- ((and file-name (buffer-modified-p buf))
- (helm-buffer--show-details
- name name-prefix file-name size mode dir
- 'helm-ff-symlink 'helm-buffer-process nil details 'mod))
- ;; A buffer file not modified and saved on disk.=>green
- (file-name
- (helm-buffer--show-details
- name name-prefix file-name size mode dir
- 'helm-buffer-file 'helm-buffer-process nil details 'filebuf))
- ;; Any non--file buffer.=>grey italic
- (t
- (helm-buffer--show-details
- name (and proc name-prefix) dir size mode dir
- 'italic 'helm-buffer-process proc details 'nofile))))))
-
-(defun helm-highlight-buffers (buffers _source)
- "Transformer function to highlight BUFFERS list.
-Should be called after others transformers i.e (boring buffers)."
- (cl-loop for i in buffers
- for (name size mode meta) = (if helm-buffer-details-flag
- (helm-buffer--details i 'details)
- (helm-buffer--details i))
- for truncbuf = (if (> (string-width name) helm-buffer-max-length)
- (helm-substring-by-width
- name helm-buffer-max-length
- helm-buffers-end-truncated-string)
- (concat name
- (make-string
- (- (+ helm-buffer-max-length
- (length helm-buffers-end-truncated-string))
- (string-width name)) ? )))
- for len = (length mode)
- when (> len helm-buffer-max-len-mode)
- do (setq helm-buffer-max-len-mode len)
- for fmode = (concat (make-string
- (- (max helm-buffer-max-len-mode len) len) ? )
- mode)
- ;; The max length of a number should be 1023.9X where X is the
- ;; units, this is 7 characters.
- for formatted-size = (and size (format "%7s" size))
- collect (cons (if helm-buffer-details-flag
- (concat truncbuf "\t" formatted-size
- " " fmode " " meta)
- name)
- (get-buffer i))))
-
-(defun helm-buffer--get-preselection (buffer)
- (let ((bufname (buffer-name buffer)))
- (concat "^"
- (if (and (null helm-buffer-details-flag)
- (numberp helm-buffer-max-length)
- (> (string-width bufname)
- helm-buffer-max-length))
- (regexp-quote
- (helm-substring-by-width
- bufname helm-buffer-max-length
- helm-buffers-end-truncated-string))
- (concat (regexp-quote bufname)
- (if helm-buffer-details-flag
- "$" "[[:blank:]]+"))))))
-
-(defun helm-toggle-buffers-details ()
- (interactive)
- (with-helm-alive-p
- (let ((preselect (helm-buffer--get-preselection
- (helm-get-selection))))
- (setq helm-buffer-details-flag (not helm-buffer-details-flag))
- (helm-force-update preselect))))
-(put 'helm-toggle-buffers-details 'helm-only t)
-
-(defun helm-buffers-sort-transformer (candidates _source)
- (if (string= helm-pattern "")
- candidates
- (sort candidates
- (lambda (s1 s2)
- (< (string-width s1) (string-width s2))))))
-
-(defun helm-buffers-mark-similar-buffers-1 ()
- (with-helm-window
- (let ((type (get-text-property
- 0 'type (helm-get-selection nil 'withprop))))
- (save-excursion
- (goto-char (helm-get-previous-header-pos))
- (helm-next-line)
- (let* ((next-head (helm-get-next-header-pos))
- (end (and next-head
- (save-excursion
- (goto-char next-head)
- (forward-line -1)
- (point))))
- (maxpoint (or end (point-max))))
- (while (< (point) maxpoint)
- (helm-mark-current-line)
- (let ((cand (helm-get-selection nil 'withprop)))
- (when (and (not (helm-this-visible-mark))
- (eq (get-text-property 0 'type cand) type))
- (helm-make-visible-mark)))
- (forward-line 1) (end-of-line))))
- (helm-mark-current-line)
- (helm-display-mode-line (helm-get-current-source) t)
- (message "%s candidates marked" (length helm-marked-candidates)))))
-
-(defun helm-buffers-mark-similar-buffers ()
- "Mark All buffers that have same property `type' than current.
-i.e same color."
- (interactive)
- (with-helm-alive-p
- (let ((marked (helm-marked-candidates)))
- (if (and (>= (length marked) 1)
- (with-helm-window helm-visible-mark-overlays))
- (helm-unmark-all)
- (helm-buffers-mark-similar-buffers-1)))))
-(put 'helm-buffers-mark-similar-buffers 'helm-only t)
-
-\f
-;;; match functions
-;;
-(defun helm-buffer--match-mjm (pattern mjm)
- (when (string-match "\\`\\*" pattern)
- (cl-loop with patterns = (split-string (substring pattern 1) ",")
- for pat in patterns
- if (string-match "\\`!" pat)
- collect (string-match (substring pat 1) mjm) into neg
- else collect (string-match pat mjm) into pos
- finally return
- (let ((neg-test (cl-loop for i in neg thereis (numberp i)))
- (pos-test (cl-loop for i in pos thereis (numberp i))))
- (or
- (and neg (not pos) (not neg-test))
- (and pos pos-test)
- (and neg neg-test (not neg-test)))))))
-
-(defun helm-buffer--match-pattern (pattern candidate)
- (let ((bfn (if (and helm-buffers-fuzzy-matching
- (not helm-migemo-mode)
- (not (string-match "\\`\\^" pattern)))
- #'helm--mapconcat-pattern
- #'identity))
- (mfn (if helm-migemo-mode
- #'helm-mm-migemo-string-match #'string-match)))
- (if (string-match "\\`!" pattern)
- (not (funcall mfn (funcall bfn (substring pattern 1))
- candidate))
- (funcall mfn (funcall bfn pattern) candidate))))
-
-(defun helm-buffers--match-from-mjm (candidate)
- (let* ((cand (replace-regexp-in-string "^\\s-\\{1\\}" "" candidate))
- (buf (get-buffer cand))
- (regexp (cl-loop with pattern = helm-pattern
- for p in (split-string pattern)
- when (string-match "\\`\\*" p)
- return p)))
- (if regexp
- (when buf
- (with-current-buffer buf
- (let ((mjm (format-mode-line mode-name)))
- (helm-buffer--match-mjm regexp mjm))))
- t)))
-
-(defun helm-buffers--match-from-pat (candidate)
- (let ((regexp-list (cl-loop with pattern = helm-pattern
- for p in (split-string pattern)
- unless (string-match
- "\\`\\(\\*\\|/\\|@\\)" p)
- collect p)))
- (if regexp-list
- (cl-loop for re in regexp-list
- always (helm-buffer--match-pattern re candidate))
- t)))
-
-(defun helm-buffers--match-from-inside (candidate)
- (let* ((cand (replace-regexp-in-string "^\\s-\\{1\\}" "" candidate))
- (buf (get-buffer cand))
- (regexp (cl-loop with pattern = helm-pattern
- for p in (split-string pattern)
- when (string-match "\\`@\\(.*\\)" p)
- return (match-string 1 p))))
- (if (and buf regexp)
- (with-current-buffer buf
- (save-excursion
- (goto-char (point-min))
- (if helm-migemo-mode
- (helm-mm-migemo-forward regexp nil t)
- (re-search-forward regexp nil t))))
- t)))
-
-(defun helm-buffers--match-from-directory (candidate)
- (let* ((cand (replace-regexp-in-string "^\\s-\\{1\\}" "" candidate))
- (buf (get-buffer cand))
- (buf-fname (buffer-file-name buf))
- (regexps (cl-loop with pattern = helm-pattern
- for p in (split-string pattern)
- when (string-match "\\`/" p)
- collect p)))
- (if regexps
- (cl-loop for re in regexps
- thereis
- (and buf-fname
- (string-match
- (substring re 1) (helm-basedir buf-fname))))
- t)))
-
-(defun helm-buffers-match-function (candidate)
- "Default function to match buffers."
- (and (helm-buffers--match-from-pat candidate)
- (helm-buffers--match-from-mjm candidate)
- (helm-buffers--match-from-inside candidate)
- (helm-buffers--match-from-directory candidate)))
-
-\f
-(defun helm-buffer-query-replace-1 (&optional regexp-flag buffers)
- "Query replace in marked buffers.
-If REGEXP-FLAG is given use `query-replace-regexp'."
- (let ((prompt (if regexp-flag "Query replace regexp" "Query replace"))
- (bufs (or buffers (helm-marked-candidates)))
- (helm--reading-passwd-or-string t))
- (cl-loop with args = (query-replace-read-args prompt regexp-flag t)
- for buf in bufs
- do
- (save-window-excursion
- (switch-to-buffer buf)
- (save-excursion
- (let ((case-fold-search t))
- (goto-char (point-min))
- (apply #'perform-replace
- (list (nth 0 args) (nth 1 args)
- t regexp-flag (nth 2 args) nil
- multi-query-replace-map))))))))
-
-(defun helm-buffer-query-replace-regexp (_candidate)
- (helm-buffer-query-replace-1 'regexp))
-
-(defun helm-buffer-query-replace (_candidate)
- (helm-buffer-query-replace-1))
-
-(defun helm-buffer-toggle-diff (candidate)
- "Toggle diff buffer CANDIDATE with it's file."
- (let (helm-persistent-action-use-special-display)
- (helm-aif (get-buffer-window "*Diff*")
- (progn (kill-buffer "*Diff*")
- (set-window-buffer it helm-current-buffer))
- (diff-buffer-with-file (get-buffer candidate)))))
-
-(defun helm-buffer-diff-persistent ()
- "Toggle diff buffer without quitting helm."
- (interactive)
- (with-helm-alive-p
- (helm-attrset 'diff-action 'helm-buffer-toggle-diff)
- (helm-execute-persistent-action 'diff-action)))
-(put 'helm-buffer-diff-persistent 'helm-only t)
-
-(defun helm-revert-buffer (candidate)
- (with-current-buffer candidate
- (helm-aif (buffer-file-name)
- (and (file-exists-p it) (revert-buffer t t)))))
-
-(defun helm-revert-marked-buffers (_ignore)
- (mapc 'helm-revert-buffer (helm-marked-candidates)))
-
-(defun helm-buffer-revert-and-update (_candidate)
- (let ((marked (helm-marked-candidates))
- (preselect (helm-buffers--quote-truncated-buffer
- (helm-get-selection))))
- (cl-loop for buf in marked do (helm-revert-buffer buf))
- (when (> (length marked) 1) (helm-unmark-all))
- (helm-force-update preselect)))
-
-(defun helm-buffer-revert-persistent ()
- "Revert buffer without quitting helm."
- (interactive)
- (with-helm-alive-p
- (helm-attrset 'revert-action '(helm-buffer-revert-and-update . never-split))
- (helm-execute-persistent-action 'revert-action)))
-(put 'helm-buffer-revert-persistent 'helm-only t)
-
-(defun helm-buffer-save-and-update (_candidate)
- (let ((marked (helm-marked-candidates))
- (preselect (helm-get-selection nil t))
- (enable-recursive-minibuffers t))
- (cl-loop for buf in marked do
- (with-current-buffer (get-buffer buf)
- (when (buffer-file-name) (save-buffer))))
- (when (> (length marked) 1) (helm-unmark-all))
- (helm-force-update (regexp-quote preselect))))
-
-(defun helm-buffer-save-persistent ()
- "Save buffer without quitting helm."
- (interactive)
- (with-helm-alive-p
- (helm-attrset 'save-action '(helm-buffer-save-and-update . never-split))
- (helm-execute-persistent-action 'save-action)))
-(put 'helm-buffer-save-persistent 'helm-only t)
-
-(defun helm-buffer-run-kill-persistent ()
- "Kill buffer without quitting helm."
- (interactive)
- (with-helm-alive-p
- (helm-attrset 'kill-action '(helm-buffers-persistent-kill . never-split))
- (helm-execute-persistent-action 'kill-action)))
-(put 'helm-buffer-run-kill-persistent 'helm-only t)
-
-(defun helm-kill-marked-buffers (_ignore)
- (let* ((bufs (helm-marked-candidates))
- (killed-bufs (cl-count-if 'kill-buffer bufs)))
- (with-helm-buffer
- (setq helm-marked-candidates nil
- helm-visible-mark-overlays nil))
- (message "Killed %s buffer(s)" killed-bufs)))
-
-(defun helm-buffer-run-kill-buffers ()
- "Run kill buffer action from `helm-source-buffers-list'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-kill-marked-buffers)))
-(put 'helm-buffer-run-kill-buffers 'helm-only t)
-
-(defun helm-buffer-run-grep ()
- "Run Grep action from `helm-source-buffers-list'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-grep-buffers)))
-(put 'helm-buffer-run-grep 'helm-only t)
-
-(defun helm-buffer-run-zgrep ()
- "Run Grep action from `helm-source-buffers-list'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-zgrep-buffers)))
-(put 'helm-buffer-run-zgrep 'helm-only t)
-
-(defun helm-buffer-run-query-replace-regexp ()
- "Run Query replace regexp action from `helm-source-buffers-list'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-buffer-query-replace-regexp)))
-(put 'helm-buffer-run-query-replace-regexp 'helm-only t)
-
-(defun helm-buffer-run-query-replace ()
- "Run Query replace action from `helm-source-buffers-list'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-buffer-query-replace)))
-(put 'helm-buffer-run-query-replace 'helm-only t)
-
-(defun helm-buffer-switch-other-window ()
- "Run switch to other window action from `helm-source-buffers-list'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-switch-to-buffers-other-window)))
-(put 'helm-buffer-switch-other-window 'helm-only t)
-
-(defun helm-buffer-switch-other-frame ()
- "Run switch to other frame action from `helm-source-buffers-list'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'switch-to-buffer-other-frame)))
-(put 'helm-buffer-switch-other-frame 'helm-only t)
-
-(defun helm-buffer-switch-to-elscreen ()
- "Run switch to elscreen action from `helm-source-buffers-list'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-find-buffer-on-elscreen)))
-(put 'helm-buffer-switch-to-elscreen 'helm-only t)
-
-(defun helm-buffer-run-ediff ()
- "Run ediff action from `helm-source-buffers-list'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-ediff-marked-buffers)))
-(put 'helm-buffer-run-ediff 'helm-only t)
-
-(defun helm-buffer-run-ediff-merge ()
- "Run ediff action from `helm-source-buffers-list'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-ediff-marked-buffers-merge)))
-(put 'helm-buffer-run-ediff-merge 'helm-only t)
-
-(defun helm-buffers-persistent-kill-1 (buffer)
- "Persistent action to kill buffer."
- (if (eql (get-buffer buffer) (get-buffer helm-current-buffer))
- (progn
- (message "Can't kill `helm-current-buffer' without quitting session")
- (sit-for 1))
- (with-current-buffer (get-buffer buffer)
- (kill-buffer buffer))
- (helm-delete-current-selection)
- (with-helm-temp-hook 'helm-after-persistent-action-hook
- (helm-force-update (regexp-quote (helm-get-selection nil t))))))
-
-(defun helm-buffers--quote-truncated-buffer (buffer)
- (let ((bufname (and (bufferp buffer)
- (buffer-name buffer))))
- (when bufname
- (regexp-quote
- (if helm-buffer-max-length
- (helm-substring-by-width
- bufname helm-buffer-max-length
- "")
- bufname)))))
-
-(defun helm-buffers-persistent-kill (_buffer)
- (let ((marked (helm-marked-candidates)))
- (unwind-protect
- (cl-loop for b in marked
- do (progn (helm-preselect
- (format "^%s"
- (helm-buffers--quote-truncated-buffer b)))
- (when (y-or-n-p (format "kill buffer (%s)? " b))
- (helm-buffers-persistent-kill-1 b))
- (message nil)))
- (with-helm-buffer
- (setq helm-marked-candidates nil
- helm-visible-mark-overlays nil))
- (helm-force-update (helm-buffers--quote-truncated-buffer
- (helm-get-selection))))))
-
-(defun helm-buffers-list-persistent-action (candidate)
- (let ((current (window-buffer helm-persistent-action-display-window)))
- (if (or (eql current (get-buffer helm-current-buffer))
- (not (eql current (get-buffer candidate))))
- (switch-to-buffer candidate)
- (switch-to-buffer helm-current-buffer))))
-
-(defun helm-ediff-marked-buffers (_candidate &optional merge)
- "Ediff 2 marked buffers or CANDIDATE and `helm-current-buffer'.
-With optional arg MERGE call `ediff-merge-buffers'."
- (let ((lg-lst (length (helm-marked-candidates)))
- buf1 buf2)
- (cl-case lg-lst
- (0
- (error "Error:You have to mark at least 1 buffer"))
- (1
- (setq buf1 helm-current-buffer
- buf2 (cl-first (helm-marked-candidates))))
- (2
- (setq buf1 (cl-first (helm-marked-candidates))
- buf2 (cl-second (helm-marked-candidates))))
- (t
- (error "Error:To much buffers marked!")))
- (if merge
- (ediff-merge-buffers buf1 buf2)
- (ediff-buffers buf1 buf2))))
-
-(defun helm-ediff-marked-buffers-merge (candidate)
- "Ediff merge `helm-current-buffer' with CANDIDATE.
-See `helm-ediff-marked-buffers'."
- (helm-ediff-marked-buffers candidate t))
-
-(defun helm-multi-occur-as-action (_candidate)
- "Multi occur action for `helm-source-buffers-list'.
-Can be used by any source that list buffers."
- (let ((helm-moccur-always-search-in-current
- (if helm-current-prefix-arg
- (not helm-moccur-always-search-in-current)
- helm-moccur-always-search-in-current))
- (buffers (helm-marked-candidates))
- (input (cl-loop for i in (split-string helm-pattern " " t)
- thereis (and (string-match "\\`@\\(.*\\)" i)
- (match-string 1 i)))))
- (helm-multi-occur-1 buffers input)))
-
-(defun helm-buffers-run-multi-occur ()
- "Run `helm-multi-occur-as-action' by key."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-multi-occur-as-action)))
-(put 'helm-buffers-run-multi-occur 'helm-only t)
-
-(defun helm-buffers-toggle-show-hidden-buffers ()
- (interactive)
- (with-helm-alive-p
- (let ((filter-attrs (helm-attr 'filtered-candidate-transformer
- helm-source-buffers-list)))
- (if (memq 'helm-shadow-boring-buffers filter-attrs)
- (helm-attrset 'filtered-candidate-transformer
- (cons 'helm-skip-boring-buffers
- (remove 'helm-shadow-boring-buffers
- filter-attrs))
- helm-source-buffers-list t)
- (helm-attrset 'filtered-candidate-transformer
- (cons 'helm-shadow-boring-buffers
- (remove 'helm-skip-boring-buffers
- filter-attrs))
- helm-source-buffers-list t))
- (helm-force-update))))
-(put 'helm-buffers-toggle-show-hidden-buffers 'helm-only t)
-
-(defun helm-buffers-browse-project (buf)
- "Browse project from buffer."
- (with-current-buffer buf
- (helm-browse-project helm-current-prefix-arg)))
-
-(defun helm-buffers-run-browse-project ()
- "Run `helm-buffers-browse-project' from key."
- (interactive)
- (with-helm-alive-p
- (if helm-buffers-in-project-p
- (user-error "You are already browsing this project")
- (helm-exit-and-execute-action 'helm-buffers-browse-project))))
-\f
-;;; Candidate Transformers
-;;
-;;
-(defun helm-skip-boring-buffers (buffers _source)
- (helm-skip-entries buffers
- helm-boring-buffer-regexp-list
- helm-white-buffer-regexp-list))
-
-(defun helm-shadow-boring-buffers (buffers _source)
- "Buffers matching `helm-boring-buffer-regexp' will be
-displayed with the `file-name-shadow' face if available."
- (helm-shadow-entries buffers helm-boring-buffer-regexp-list))
-
-\f
-;;;###autoload
-(defun helm-buffers-list ()
- "Preconfigured `helm' to list buffers."
- (interactive)
- (unless helm-source-buffers-list
- (setq helm-source-buffers-list
- (helm-make-source "Buffers" 'helm-source-buffers)))
- (helm :sources '(helm-source-buffers-list
- helm-source-ido-virtual-buffers
- helm-source-buffer-not-found)
- :buffer "*helm buffers*"
- :keymap helm-buffer-map
- :truncate-lines helm-buffers-truncate-lines))
-
-;;;###autoload
-(defun helm-mini ()
- "Preconfigured `helm' lightweight version \(buffer -> recentf\)."
- (interactive)
- (require 'helm-files)
- (unless helm-source-buffers-list
- (setq helm-source-buffers-list
- (helm-make-source "Buffers" 'helm-source-buffers)))
- (helm :sources helm-mini-default-sources
- :buffer "*helm mini*"
- :ff-transformer-show-only-basename nil
- :truncate-lines helm-buffers-truncate-lines))
-
-(provide 'helm-buffers)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-buffers.el ends here
+++ /dev/null
-;;; helm-color.el --- colors and faces -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Code:
-(require 'cl-lib)
-(require 'helm)
-(require 'helm-help)
-
-;;; Customize Face
-;;
-;;
-(defun helm-custom-faces-init ()
- "Initialize buffer for `helm-source-customize-face'."
- (unless (helm-candidate-buffer)
- (save-selected-window
- (list-faces-display)
- (message nil))
- (helm-init-candidates-in-buffer
- 'global
- (with-current-buffer (get-buffer "*Faces*")
- (buffer-substring
- (next-single-char-property-change (point-min) 'face)
- (point-max))))
- (kill-buffer "*Faces*")))
-
-(defvar helm-source-customize-face
- (helm-build-in-buffer-source "Customize Face"
- :init 'helm-custom-faces-init
- :get-line 'buffer-substring
- :action '(("Customize"
- . (lambda (line)
- (customize-face (intern (car (split-string line))))))
- ("Copy name"
- . (lambda (line)
- (kill-new (car (split-string line " " t)))))))
- "See (info \"(emacs)Faces\")")
-
-;;; Colors browser
-;;
-;;
-(defun helm-colors-init ()
- (unless (helm-candidate-buffer)
- (save-selected-window
- (list-colors-display)
- (message nil))
- (helm-init-candidates-in-buffer
- 'global
- (with-current-buffer (get-buffer "*Colors*")
- (buffer-string)))
- (kill-buffer "*Colors*")))
-
-(defun helm-color-insert-name (candidate)
- (with-helm-current-buffer
- (insert (helm-colors-get-name candidate))))
-
-(defun helm-color-kill-name (candidate)
- (kill-new (helm-colors-get-name candidate)))
-
-(defun helm-color-insert-rgb (candidate)
- (with-helm-current-buffer
- (insert (helm-colors-get-rgb candidate))))
-
-(defun helm-color-kill-rgb (candidate)
- (kill-new (helm-colors-get-rgb candidate)))
-
-(defun helm-color-run-insert-name ()
- "Insert name of color from `helm-source-colors'"
- (interactive)
- (with-helm-alive-p (helm-exit-and-execute-action 'helm-color-insert-name)))
-(put 'helm-color-run-insert-name 'helm-only t)
-
-(defun helm-color-run-kill-name ()
- "Kill name of color from `helm-source-colors'"
- (interactive)
- (with-helm-alive-p (helm-exit-and-execute-action 'helm-color-kill-name)))
-(put 'helm-color-run-kill-name 'helm-only t)
-
-(defun helm-color-run-insert-rgb ()
- "Insert RGB of color from `helm-source-colors'"
- (interactive)
- (with-helm-alive-p (helm-exit-and-execute-action 'helm-color-insert-rgb)))
-(put 'helm-color-run-insert-rgb 'helm-only t)
-
-(defun helm-color-run-kill-rgb ()
- "Kill RGB of color from `helm-source-colors'"
- (interactive)
- (with-helm-alive-p (helm-exit-and-execute-action 'helm-color-kill-rgb)))
-(put 'helm-color-run-kill-rgb 'helm-only t)
-
-(defvar helm-color-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map helm-map)
- (define-key map (kbd "C-c n") 'helm-color-run-insert-name)
- (define-key map (kbd "C-c N") 'helm-color-run-kill-name)
- (define-key map (kbd "C-c r") 'helm-color-run-insert-rgb)
- (define-key map (kbd "C-c R") 'helm-color-run-kill-rgb)
- map))
-
-(defvar helm-source-colors
- (helm-build-in-buffer-source "Colors"
- :init 'helm-colors-init
- :get-line 'buffer-substring
- :keymap helm-color-map
- :persistent-help "Kill entry in RGB format."
- :persistent-action 'helm-color-kill-rgb
- :help-message 'helm-colors-help-message
- :action
- '(("Copy Name (C-c N)" . helm-color-kill-name)
- ("Copy RGB (C-c R)" . helm-color-kill-rgb)
- ("Insert Name (C-c n)" . helm-color-insert-name)
- ("Insert RGB (C-c r)" . helm-color-insert-rgb))))
-
-(defun helm-colors-get-name (candidate)
- "Get color name."
- (replace-regexp-in-string
- " " ""
- (with-temp-buffer
- (insert (capitalize candidate))
- (goto-char (point-min))
- (search-forward-regexp "\\s-\\{2,\\}")
- (delete-region (point) (point-max))
- (buffer-string))))
-
-(defun helm-colors-get-rgb (candidate)
- "Get color RGB."
- (replace-regexp-in-string
- " " ""
- (with-temp-buffer
- (insert (capitalize candidate))
- (goto-char (point-max))
- (search-backward-regexp "\\s-\\{2,\\}")
- (delete-region (point) (point-min))
- (buffer-string))))
-
-;;;###autoload
-(defun helm-colors ()
- "Preconfigured `helm' for color."
- (interactive)
- (helm :sources '(helm-source-colors helm-source-customize-face)
- :buffer "*helm colors*"))
-
-(provide 'helm-color)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-color.el ends here
+++ /dev/null
-;;; helm-command.el --- Helm execute-exended-command. -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'helm)
-(require 'helm-help)
-(require 'helm-mode)
-(require 'helm-elisp)
-
-\f
-(defgroup helm-command nil
- "Emacs command related Applications and libraries for Helm."
- :group 'helm)
-
-(defcustom helm-M-x-requires-pattern 0
- "Value of requires-pattern for `helm-M-x'.
-Show all candidates on startup when 0 (default)."
- :group 'helm-command
- :type 'boolean)
-
-(defcustom helm-M-x-always-save-history nil
- "`helm-M-x' Save command in `extended-command-history' even when it fail."
- :group 'helm-command
- :type 'boolean)
-
-(defcustom helm-M-x-reverse-history nil
- "The history source of `helm-M-x' appear in second position when non--nil."
- :group 'helm-command
- :type 'boolean)
-
-(defcustom helm-M-x-fuzzy-match nil
- "Enable fuzzy matching in `helm-M-x' when non--nil."
- :group 'helm-command
- :type 'boolean)
-
-\f
-;;; Faces
-;;
-;;
-(defgroup helm-command-faces nil
- "Customize the appearance of helm-command."
- :prefix "helm-"
- :group 'helm-command
- :group 'helm-faces)
-
-(defface helm-M-x-key '((t (:foreground "orange" :underline t)))
- "Face used in helm-M-x to show keybinding."
- :group 'helm-command-faces)
-
-\f
-(defvar helm-M-x-input-history nil)
-
-\f
-(cl-defun helm-M-x-get-major-mode-command-alist (mode-map)
- "Return alist of MODE-MAP."
- (when mode-map
- (cl-loop for key being the key-seqs of mode-map using (key-bindings com)
- for str-key = (key-description key)
- for ismenu = (string-match "<menu-bar>" str-key)
- unless ismenu collect (cons str-key com))))
-
-(defun helm-get-mode-map-from-mode (mode)
- "Guess the mode-map name according to MODE.
-Some modes don't use conventional mode-map name
-so we need to guess mode-map name. e.g python-mode ==> py-mode-map.
-Return nil if no mode-map found."
- (cl-loop ;; Start with a conventional mode-map name.
- with mode-map = (intern-soft (format "%s-map" mode))
- with mode-string = (symbol-name mode)
- with mode-name = (replace-regexp-in-string "-mode" "" mode-string)
- while (not mode-map)
- for count downfrom (length mode-name)
- ;; Return when no result after parsing entire string.
- when (eq count 0) return nil
- for sub-name = (substring mode-name 0 count)
- do (setq mode-map (intern-soft (format "%s-map" (concat sub-name "-mode"))))
- finally return mode-map))
-
-(defun helm-M-x-current-mode-map-alist ()
- "Return mode-map alist of current `major-mode'."
- (let ((map-sym (helm-get-mode-map-from-mode major-mode)))
- (when (and map-sym (boundp map-sym))
- (helm-M-x-get-major-mode-command-alist (symbol-value map-sym)))))
-
-
-(defun helm-M-x-transformer-1 (candidates &optional sort)
- "Transformer function to show bindings in emacs commands.
-Show global bindings and local bindings according to current `major-mode'.
-If SORT is non nil sort list with `helm-generic-sort-fn'.
-Note that SORT should not be used when fuzzy matching because
-fuzzy matching is running its own sort function with a different algorithm."
- (with-helm-current-buffer
- (cl-loop with local-map = (helm-M-x-current-mode-map-alist)
- for cand in candidates
- for local-key = (car (rassq cand local-map))
- for key = (substitute-command-keys (format "\\[%s]" cand))
- unless (get (intern (if (consp cand) (car cand) cand)) 'helm-only)
- collect
- (cons (cond ((and (string-match "^M-x" key) local-key)
- (format "%s (%s)"
- cand (propertize
- local-key
- 'face 'helm-M-x-key)))
- ((string-match "^M-x" key) cand)
- (t (format "%s (%s)"
- cand (propertize
- key
- 'face 'helm-M-x-key))))
- cand)
- into ls
- finally return
- (if sort (sort ls #'helm-generic-sort-fn) ls))))
-
-(defun helm-M-x-transformer (candidates _source)
- "Transformer function for `helm-M-x' candidates."
- (helm-M-x-transformer-1 candidates (null helm--in-fuzzy)))
-
-(defun helm-M-x-transformer-hist (candidates _source)
- "Transformer function for `helm-M-x' candidates."
- (helm-M-x-transformer-1 candidates))
-
-(defun helm-M-x--notify-prefix-arg ()
- ;; Notify a prefix-arg set AFTER calling M-x.
- (when prefix-arg
- (with-helm-window
- (helm-display-mode-line (helm-get-current-source) 'force))))
-
-(defun helm-cmd--get-current-function-name ()
- (save-excursion
- (beginning-of-defun)
- (cadr (split-string (buffer-substring-no-properties
- (point-at-bol) (point-at-eol))))))
-
-(defun helm-cmd--get-preconfigured-commands (&optional dir)
- (let* ((helm-dir (or dir (helm-basedir (locate-library "helm"))))
- (helm-autoload-file (expand-file-name "helm-autoloads.el" helm-dir))
- results)
- (when (file-exists-p helm-autoload-file)
- (with-temp-buffer
- (insert-file-contents helm-autoload-file)
- (while (re-search-forward "Preconfigured" nil t)
- (push (substring (helm-cmd--get-current-function-name) 1) results))))
- results))
-
-(defun helm-M-x-read-extended-command (&optional collection history)
- "Read command name to invoke in `helm-M-x'.
-Helm completion is not provided when executing or defining
-kbd macros.
-Optional arg COLLECTION is to allow using another COLLECTION
-than the default which is OBARRAY."
- (if (or defining-kbd-macro executing-kbd-macro)
- (if helm-mode
- (unwind-protect
- (progn
- (helm-mode -1)
- (read-extended-command))
- (helm-mode 1))
- (read-extended-command))
- (let* ((orig-fuzzy-sort-fn helm-fuzzy-sort-fn)
- (helm-fuzzy-sort-fn (lambda (candidates source)
- (funcall orig-fuzzy-sort-fn
- candidates source 'real)))
- (helm--mode-line-display-prefarg t)
- (tm (run-at-time 1 0.1 'helm-M-x--notify-prefix-arg))
- (helm-move-selection-after-hook
- (cons (lambda () (setq current-prefix-arg nil))
- helm-move-selection-after-hook)))
- (setq extended-command-history
- (cl-loop for c in extended-command-history
- when (and c (commandp (intern c)))
- do (set-text-properties 0 (length c) nil c)
- and collect c))
- (unwind-protect
- (let ((msg "Error: Specifying a prefix arg before calling `helm-M-x'"))
- (when current-prefix-arg
- (ding)
- (message "%s" msg)
- (while (not (sit-for 1))
- (discard-input))
- (user-error msg))
- (setq current-prefix-arg nil)
- (helm-comp-read
- "M-x " (or collection obarray)
- :test 'commandp
- :requires-pattern helm-M-x-requires-pattern
- :name "Emacs Commands"
- :buffer "*helm M-x*"
- :persistent-action (lambda (candidate)
- (helm-elisp--persistent-help
- candidate 'helm-describe-function))
- :persistent-help "Describe this command"
- :history (or history extended-command-history)
- :reverse-history helm-M-x-reverse-history
- :input-history 'helm-M-x-input-history
- :del-input nil
- :help-message 'helm-M-x-help-message
- :must-match t
- :fuzzy helm-M-x-fuzzy-match
- :nomark t
- :candidates-in-buffer t
- :fc-transformer 'helm-M-x-transformer
- :hist-fc-transformer 'helm-M-x-transformer-hist))
- (cancel-timer tm)
- (setq helm--mode-line-display-prefarg nil)))))
-
-;;;###autoload
-(defun helm-M-x (arg &optional command-name)
- "Preconfigured `helm' for Emacs commands.
-It is `helm' replacement of regular `M-x' `execute-extended-command'.
-
-Unlike regular `M-x' emacs vanilla `execute-extended-command' command,
-the prefix args if needed, are passed AFTER starting `helm-M-x'.
-
-You can get help on each command by persistent action."
- (interactive (list current-prefix-arg (helm-M-x-read-extended-command)))
- (let ((sym-com (and (stringp command-name) (intern-soft command-name))))
- (when sym-com
- ;; Avoid having `this-command' set to *exit-minibuffer.
- (setq this-command sym-com
- ;; Handle C-x z (repeat) Issue #322
- real-this-command sym-com)
- ;; If helm-M-x is called with regular emacs completion (kmacro)
- ;; use the value of arg otherwise use helm-current-prefix-arg.
- (let ((prefix-arg (or helm-current-prefix-arg arg)))
- ;; This ugly construct is to save history even on error.
- (unless helm-M-x-always-save-history
- (command-execute sym-com 'record))
- (setq extended-command-history
- (cons command-name
- (delete command-name extended-command-history)))
- (when helm-M-x-always-save-history
- (command-execute sym-com 'record))))))
-
-
-(provide 'helm-command)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-command.el ends here
+++ /dev/null
-;;; helm-config.el --- Applications library for `helm.el' -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Code:
-
-\f
-;;; Require
-;;
-;;
-(declare-function async-bytecomp-package-mode "ext:async-bytecomp.el")
-(when (require 'async-bytecomp nil t)
- (and (fboundp 'async-bytecomp-package-mode)
- (async-bytecomp-package-mode 1)))
-
-\f
-(defgroup helm-config nil
- "Various configurations for Helm."
- :group 'helm)
-
-(defcustom helm-command-prefix-key "C-x c"
- "The key `helm-command-prefix' is bound to in the global map."
- :type '(choice (string :tag "Key") (const :tag "no binding"))
- :group 'helm-config
- :set
- (lambda (var key)
- (when (and (boundp var) (symbol-value var))
- (define-key (current-global-map)
- (read-kbd-macro (symbol-value var)) nil))
- (when key
- (define-key (current-global-map)
- (read-kbd-macro key) 'helm-command-prefix))
- (set var key)))
-
-(defcustom helm-minibuffer-history-key "C-r"
- "The key `helm-minibuffer-history' is bound to in minibuffer local maps."
- :type '(choice (string :tag "Key") (const :tag "no binding"))
- :group 'helm-config
- :set
- (lambda (var key)
- (cl-dolist (map '(minibuffer-local-completion-map
- minibuffer-local-filename-completion-map
- minibuffer-local-filename-must-match-map ; Emacs 23.1.+
- minibuffer-local-isearch-map
- minibuffer-local-map
- minibuffer-local-must-match-filename-map ; Older Emacsen
- minibuffer-local-must-match-map
- minibuffer-local-ns-map))
- (when (and (boundp map) (keymapp (symbol-value map)))
- (when (and (boundp var) (symbol-value var))
- (define-key (symbol-value map)
- (read-kbd-macro (symbol-value var)) nil))
- (when key
- (define-key (symbol-value map)
- (read-kbd-macro key) 'helm-minibuffer-history))))
- (set var key)))
-\f
-;;; Command Keymap
-;;
-;;
-(defvar helm-command-map
- (let ((map (make-sparse-keymap)))
- (define-key map (kbd "a") 'helm-apropos)
- (define-key map (kbd "e") 'helm-etags-select)
- (define-key map (kbd "l") 'helm-locate)
- (define-key map (kbd "s") 'helm-surfraw)
- (define-key map (kbd "r") 'helm-regexp)
- (define-key map (kbd "m") 'helm-man-woman)
- (define-key map (kbd "t") 'helm-top)
- (define-key map (kbd "/") 'helm-find)
- (define-key map (kbd "i") 'helm-semantic-or-imenu)
- (define-key map (kbd "I") 'helm-imenu-in-all-buffers)
- (define-key map (kbd "<tab>") 'helm-lisp-completion-at-point)
- (define-key map (kbd "p") 'helm-list-emacs-process)
- (define-key map (kbd "C-x r b") 'helm-filtered-bookmarks)
- (define-key map (kbd "M-y") 'helm-show-kill-ring)
- (define-key map (kbd "C-c <SPC>") 'helm-all-mark-rings)
- (define-key map (kbd "C-x C-f") 'helm-find-files)
- (define-key map (kbd "f") 'helm-multi-files)
- (define-key map (kbd "C-:") 'helm-eval-expression-with-eldoc)
- (define-key map (kbd "C-,") 'helm-calcul-expression)
- (define-key map (kbd "M-x") 'helm-M-x)
- (define-key map (kbd "M-s o") 'helm-occur)
- (define-key map (kbd "M-g a") 'helm-do-grep-ag)
- (define-key map (kbd "c") 'helm-colors)
- (define-key map (kbd "F") 'helm-select-xfont)
- (define-key map (kbd "8") 'helm-ucs)
- (define-key map (kbd "C-c f") 'helm-recentf)
- (define-key map (kbd "C-c g") 'helm-google-suggest)
- (define-key map (kbd "h i") 'helm-info-at-point)
- (define-key map (kbd "h r") 'helm-info-emacs)
- (define-key map (kbd "h g") 'helm-info-gnus)
- (define-key map (kbd "h h") 'helm-documentation)
- (define-key map (kbd "C-x C-b") 'helm-buffers-list)
- (define-key map (kbd "C-x r i") 'helm-register)
- (define-key map (kbd "C-c C-x") 'helm-run-external-command)
- (define-key map (kbd "b") 'helm-resume)
- (define-key map (kbd "M-g i") 'helm-gid)
- (define-key map (kbd "@") 'helm-list-elisp-packages)
- map))
-
-;; Don't override the keymap we just defined with an empty
-;; keymap. This also protect bindings changed by the user.
-(defvar helm-command-prefix)
-(define-prefix-command 'helm-command-prefix)
-(fset 'helm-command-prefix helm-command-map)
-(setq helm-command-prefix helm-command-map)
-
-\f
-;;; Menu
-
-(require 'helm-easymenu)
-
-\f
-;;;###autoload
-(defun helm-configuration ()
- "Customize `helm'."
- (interactive)
- (customize-group "helm"))
-
-\f
-;;; Fontlock
-(cl-dolist (mode '(emacs-lisp-mode lisp-interaction-mode))
- (font-lock-add-keywords
- mode
- '(("(\\<\\(with-helm-after-update-hook\\)\\>" 1 font-lock-keyword-face)
- ("(\\<\\(with-helm-temp-hook\\)\\>" 1 font-lock-keyword-face)
- ("(\\<\\(with-helm-window\\)\\>" 1 font-lock-keyword-face)
- ("(\\<\\(with-helm-quittable\\)\\>" 1 font-lock-keyword-face)
- ("(\\<\\(with-helm-current-buffer\\)\\>" 1 font-lock-keyword-face)
- ("(\\<\\(with-helm-buffer\\)\\>" 1 font-lock-keyword-face)
- ("(\\<\\(with-helm-show-completion\\)\\>" 1 font-lock-keyword-face)
- ("(\\<\\(with-helm-default-directory\\)\\>" 1 font-lock-keyword-face)
- ("(\\<\\(with-helm-display-same-window\\)\\>" 1 font-lock-keyword-face)
- ("(\\<\\(with-helm-restore-variables\\)\\>" 1 font-lock-keyword-face)
- ("(\\<\\(define-helm-type-attribute\\)\\>" 1 font-lock-keyword-face)
- ("(\\<\\(helm-multi-key-defun\\)\\>" 1 font-lock-keyword-face)
- ("(\\<\\(helm-while-no-input\\)\\>" 1 font-lock-keyword-face)
- ("(\\<\\(helm-aif\\)\\>" 1 font-lock-keyword-face)
- ("(\\<\\(helm-awhile\\)\\>" 1 font-lock-keyword-face)
- ("(\\<\\(helm-acond\\)\\>" 1 font-lock-keyword-face)
- ("(\\<\\(helm-with-gensyms\\)\\>" 1 font-lock-keyword-face))))
-
-\f
-;;; Load the autoload file
-;; It should have been generated either by
-;; package.el or the make file.
-
-(load "helm-autoloads" nil t)
-
-(provide 'helm-config)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-config.el ends here
+++ /dev/null
-;;; helm-dabbrev.el --- Helm implementation of dabbrev. -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Code:
-
-(require 'helm)
-(require 'helm-lib)
-(require 'helm-help)
-(require 'helm-elisp) ; For show-completion.
-\f
-(defgroup helm-dabbrev nil
- "Dabbrev related Applications and libraries for Helm."
- :group 'helm)
-
-(defcustom helm-dabbrev-always-search-all t
- "Always search in all buffers when non--nil.
-Note that even if nil, a search in all buffers
-will occur if the length of candidates is <= than
-`helm-dabbrev-max-length-result'."
- :group 'helm-dabbrev
- :type 'boolean)
-
-(defcustom helm-dabbrev-max-length-result 20
- "Max length of candidates before searching in all buffers.
-If number of candidates found in current-buffer is <= to this,
-search in all buffers.
-Have no effect when `helm-dabbrev-always-search-all' is non--nil."
- :group 'helm-dabbrev
- :type 'integer)
-
-(defcustom helm-dabbrev-ignored-buffers-regexps
- '("\\*helm" "\\*Messages" "\\*Echo Area" "\\*Buffer List")
- "List of regexps matching names of buffers that helm-dabbrev should not check."
- :group 'helm-dabbrev
- :type '(repeat regexp))
-
-(defcustom helm-dabbrev-related-buffer-fn #'helm-dabbrev--same-major-mode-p
- "A function that decide if a buffer to search in is related to `current-buffer'.
-This is actually determined by comparing `major-mode' of the buffer to search
-and the `current-buffer'.
-The function take one arg, the buffer which is current, look at
-`helm-dabbrev--same-major-mode-p' for example.
-
-When nil all buffers are considered related to `current-buffer'."
- :group 'helm-dabbrev
- :type 'function)
-
-(defcustom helm-dabbrev-major-mode-assoc nil
- "Major mode association alist.
-This allow helm-dabbrev searching in buffers with the associated `major-mode'.
-e.g \(emacs-lisp-mode . lisp-interaction-mode\)
-will allow searching in the lisp-interaction-mode buffer when `current-buffer'
-is an `emacs-lisp-mode' buffer and vice versa i.e
-no need to provide \(lisp-interaction-mode . emacs-lisp-mode\) association.
-
-When nil check is the searched buffer have same `major-mode'
-than the `current-buffer'.
-This have no effect when `helm-dabbrev-related-buffer-fn' is nil or of course
-bound to a function that doesn't handle this var."
- :type '(alist :key-type symbol :value-type symbol)
- :group 'helm-dabbrev)
-
-(defcustom helm-dabbrev-lineno-around 30
- "Search first in this number of lines before an after point."
- :group 'helm-dabbrev
- :type 'integer)
-
-(defcustom helm-dabbrev-cycle-threshold nil
- "Number of time helm-dabbrev cycle before displaying helm completion.
-When nil or 0 disable cycling."
- :group 'helm-dabbrev
- :type '(choice (const :tag "Cycling disabled" nil) integer))
-
-(defcustom helm-dabbrev-case-fold-search 'smart
- "Set `case-fold-search' in `helm-dabbrev'.
-Same as `helm-case-fold-search' but for `helm-dabbrev'.
-Note that this is not affecting searching in helm buffer,
-but the initial search for all candidates in buffer(s)."
- :group 'helm-dabbrev
- :type '(choice (const :tag "Ignore case" t)
- (const :tag "Respect case" nil)
- (other :tag "Smart" 'smart)))
-
-\f
-(defvar helm-dabbrev-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map helm-map)
- (define-key map (kbd "M-/") 'helm-next-line)
- (define-key map (kbd "M-:") 'helm-previous-line)
- map))
-
-;; Internal
-(defvar helm-dabbrev--exclude-current-buffer-flag nil)
-(defvar helm-dabbrev--cache nil)
-(defvar helm-dabbrev--data nil)
-(defvar helm-dabbrev--regexp "\\s-\\|\t\\|[(\[\{\"'`=<$;.]\\|\\s\\\\|^")
-(cl-defstruct helm-dabbrev-info dabbrev limits iterator)
-
-\f
-(defun helm-dabbrev--buffer-list ()
- (cl-loop with lst = (buffer-list)
- for buf in (if helm-dabbrev--exclude-current-buffer-flag
- (cdr lst) lst)
- unless (cl-loop for r in helm-dabbrev-ignored-buffers-regexps
- thereis (string-match r (buffer-name buf)))
- collect buf))
-
-(defun helm-dabbrev--same-major-mode-p (start-buffer)
- "Decide if current-buffer is related to START-BUFFER."
- (helm-same-major-mode-p start-buffer helm-dabbrev-major-mode-assoc))
-
-(defun helm-dabbrev--collect (str limit ignore-case all)
- (let* ((case-fold-search ignore-case)
- (buffer1 (current-buffer)) ; start buffer.
- (minibuf (minibufferp buffer1))
- result pos-before pos-after
- (search-and-store
- (lambda (pattern direction)
- (while (cl-case direction
- (1 (search-forward pattern nil t))
- (-1 (search-backward pattern nil t))
- (2 (let ((pos
- (save-excursion
- (forward-line
- helm-dabbrev-lineno-around)
- (point))))
- (setq pos-after pos)
- (search-forward pattern pos t)))
- (-2 (let ((pos
- (save-excursion
- (forward-line
- (- helm-dabbrev-lineno-around))
- (point))))
- (setq pos-before pos)
- (search-backward pattern pos t))))
- (let* ((replace-regexp (concat "\\(" helm-dabbrev--regexp "\\)\\'"))
- (match-1 (helm-aif (thing-at-point 'symbol)
- ;; `thing-at-point' returns
- ;; the quote outside of e-lisp mode,
- ;; e.g in message mode,
- ;; `foo' => foo'
- ;; but in e-lisp like modes:
- ;; `foo' => foo
- ;; so remove it [1].
- (replace-regexp-in-string
- replace-regexp
- "" (substring-no-properties it))))
- (match-2 (helm-aif (thing-at-point 'filename)
- ;; Same as in [1].
- (replace-regexp-in-string
- replace-regexp
- "" (substring-no-properties it))))
- (lst (if (string= match-1 match-2)
- (list match-1)
- (list match-1 match-2))))
- (cl-loop for match in lst
- unless (or (string= str match)
- (member match result))
- do (push match result)))))))
- (cl-loop for buf in (if all (helm-dabbrev--buffer-list)
- (list (current-buffer)))
-
- do (with-current-buffer buf
- (when (or minibuf ; check against all buffers when in minibuffer.
- (if helm-dabbrev-related-buffer-fn
- (funcall helm-dabbrev-related-buffer-fn buffer1)
- t))
- (save-excursion
- ;; Start searching before thing before point.
- (goto-char (- (point) (length str)))
- ;; Search the last 30 lines before point.
- (funcall search-and-store str -2)) ; store pos [1]
- (save-excursion
- ;; Search the next 30 lines after point.
- (funcall search-and-store str 2)) ; store pos [2]
- (save-excursion
- ;; Search all before point.
- (goto-char pos-before) ; start from [1]
- (funcall search-and-store str -1))
- (save-excursion
- ;; Search all after point.
- (goto-char pos-after) ; start from [2]
- (funcall search-and-store str 1))))
- when (> (length result) limit) return (nreverse result)
- finally return (nreverse result))))
-
-(defun helm-dabbrev--get-candidates (abbrev)
- (cl-assert abbrev nil "[No Match]")
- (with-current-buffer (current-buffer)
- (let* ((dabbrev-get (lambda (str all-bufs)
- (helm-dabbrev--collect
- str helm-candidate-number-limit
- (cl-case helm-dabbrev-case-fold-search
- (smart (helm-set-case-fold-search-1 abbrev))
- (t helm-dabbrev-case-fold-search))
- all-bufs)))
- (lst (funcall dabbrev-get abbrev helm-dabbrev-always-search-all)))
- (if (and (not helm-dabbrev-always-search-all)
- (<= (length lst) helm-dabbrev-max-length-result))
- ;; Search all but don't recompute current-buffer.
- (let ((helm-dabbrev--exclude-current-buffer-flag t))
- (append lst (funcall dabbrev-get abbrev 'all-bufs)))
- lst))))
-\f
-(defun helm-dabbrev-default-action (candidate)
- (with-helm-current-buffer
- (let* ((limits (helm-bounds-of-thing-before-point
- helm-dabbrev--regexp))
- (beg (car limits))
- (end (point)))
- (run-with-timer
- 0.01 nil
- 'helm-insert-completion-at-point
- beg end candidate))))
-
-;;;###autoload
-(defun helm-dabbrev ()
- "Preconfigured helm for dynamic abbreviations."
- (interactive)
- (let ((dabbrev (helm-thing-before-point nil helm-dabbrev--regexp))
- (limits (helm-bounds-of-thing-before-point helm-dabbrev--regexp))
- (enable-recursive-minibuffers t)
- (cycling-disabled-p (or (null helm-dabbrev-cycle-threshold)
- (zerop helm-dabbrev-cycle-threshold)))
- (helm-execute-action-at-once-if-one t)
- (helm-quit-if-no-candidate
- (lambda ()
- (message "[Helm-dabbrev: No expansion found]"))))
- (cl-assert (and (stringp dabbrev) (not (string= dabbrev "")))
- nil "[Helm-dabbrev: Nothing found before point]")
- (when (and
- ;; have been called at least once.
- (helm-dabbrev-info-p helm-dabbrev--data)
- ;; But user have moved with some other command
- ;; in the meaning time.
- (not (eq last-command 'helm-dabbrev)))
- (setq helm-dabbrev--data nil))
- (when cycling-disabled-p
- (setq helm-dabbrev--cache (helm-dabbrev--get-candidates dabbrev)))
- (unless (or cycling-disabled-p
- (helm-dabbrev-info-p helm-dabbrev--data))
- (setq helm-dabbrev--cache (helm-dabbrev--get-candidates dabbrev))
- (setq helm-dabbrev--data
- (make-helm-dabbrev-info
- :dabbrev dabbrev
- :limits limits
- :iterator
- (helm-iter-list
- (cl-loop for i in helm-dabbrev--cache when
- (and i (string-match
- (concat "^" (regexp-quote dabbrev)) i))
- collect i into selection
- when (and selection
- (= (length selection)
- helm-dabbrev-cycle-threshold))
- ;; When selection len reach
- ;; `helm-dabbrev-cycle-threshold'
- ;; return selection.
- return selection
- ;; selection len never reach
- ;; `helm-dabbrev-cycle-threshold'
- ;; return selection.
- finally return selection)))))
- (let ((iter (and (helm-dabbrev-info-p helm-dabbrev--data)
- (helm-dabbrev-info-iterator helm-dabbrev--data)))
- deactivate-mark)
- ;; Cycle until iterator is consumed.
- (helm-aif (and iter (helm-iter-next iter))
- (progn
- (helm-insert-completion-at-point
- (car (helm-dabbrev-info-limits helm-dabbrev--data))
- (cdr limits) it)
- ;; Move already tried candidates to end of list.
- (setq helm-dabbrev--cache (append (remove it helm-dabbrev--cache)
- (list it))))
- ;; If the length of candidates is only one when computed
- ;; that's mean the unique matched item have already been
- ;; inserted by the iterator, so no need to reinsert the old dabbrev,
- ;; just let helm exiting with "No expansion found".
- (let ((old-dabbrev (if (helm-dabbrev-info-p helm-dabbrev--data)
- (helm-dabbrev-info-dabbrev helm-dabbrev--data)
- dabbrev)))
- (unless (cdr (all-completions old-dabbrev helm-dabbrev--cache))
- (setq cycling-disabled-p t))
- ;; Iterator is now empty, reset dabbrev to initial value
- ;; and start helm completion.
- (unless cycling-disabled-p
- (setq dabbrev old-dabbrev
- limits (helm-dabbrev-info-limits helm-dabbrev--data))
- (setq helm-dabbrev--data nil)
- (delete-region (car limits) (point))
- (insert dabbrev))
- (with-helm-show-completion (car limits) (cdr limits)
- (helm :sources (helm-build-in-buffer-source "Dabbrev Expand"
- :data helm-dabbrev--cache
- :persistent-action 'ignore
- :persistent-help "DoNothing"
- :keymap helm-dabbrev-map
- :action 'helm-dabbrev-default-action)
- :buffer "*helm dabbrev*"
- :input (concat "^" dabbrev " ")
- :resume 'noresume
- :allow-nest t)))))))
-
-(provide 'helm-dabbrev)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-dabbrev.el ends here
+++ /dev/null
-;;; helm-easymenu.el --- Helm easymenu definitions. -*- lexical-binding: t -*-
-
-;; Copyright (C) 2015 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Code:
-
-(require 'easymenu)
-
-(easy-menu-add-item
- nil '("Tools")
- '("Helm"
- ["Find any Files/Buffers" helm-multi-files t]
- ["Helm Everywhere (Toggle)" helm-mode t]
- ["Helm resume" helm-resume t]
- "----"
- ("Files"
- ["Find files" helm-find-files t]
- ["Recent Files" helm-recentf t]
- ["Locate" helm-locate t]
- ["Search Files with find" helm-find t]
- ["Bookmarks" helm-filtered-bookmarks t])
- ("Buffers"
- ["Find buffers" helm-buffers-list t])
- ("Commands"
- ["Emacs Commands" helm-M-x t]
- ["Externals Commands" helm-run-external-command t])
- ("Help"
- ["Helm Apropos" helm-apropos t])
- ("Info"
- ["Info at point" helm-info-at-point t]
- ["Emacs Manual index" helm-info-emacs t]
- ["Gnus Manual index" helm-info-gnus t]
- ["Helm documentation" helm-documentation t])
- ("Org"
- ["Org headlines in org agenda files" helm-org-agenda-files-headings t]
- ["Org headlines in buffer" helm-org-in-buffer-headings t])
- ("Elpa"
- ["Elisp packages" helm-list-elisp-packages t]
- ["Elisp packages no fetch" helm-list-elisp-packages-no-fetch t])
- ("Tools"
- ["Occur" helm-occur t]
- ["Grep current directory with AG" helm-do-grep-ag t]
- ["Gid" helm-gid t]
- ["Etags" helm-etags-select t]
- ["Lisp complete at point" helm-lisp-completion-at-point t]
- ["Browse Kill ring" helm-show-kill-ring t]
- ["Browse register" helm-register t]
- ["Mark Ring" helm-all-mark-rings t]
- ["Regexp handler" helm-regexp t]
- ["Colors & Faces" helm-colors t]
- ["Show xfonts" helm-select-xfont t]
- ["Ucs Symbols" helm-ucs t]
- ["Imenu" helm-imenu t]
- ["Imenu all" helm-imenu-in-all-buffers t]
- ["Semantic or Imenu" helm-semantic-or-imenu t]
- ["Google Suggest" helm-google-suggest t]
- ["Eval expression" helm-eval-expression-with-eldoc t]
- ["Calcul expression" helm-calcul-expression t]
- ["Man pages" helm-man-woman t]
- ["Top externals process" helm-top t]
- ["Emacs internals process" helm-list-emacs-process t])
- "----"
- ["Preferred Options" helm-configuration t])
- "Spell Checking")
-
-(easy-menu-add-item nil '("Tools") '("----") "Spell Checking")
-
-
-(provide 'helm-easymenu)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-easymenu.el ends here
+++ /dev/null
-;;; helm-elisp-package.el --- helm interface for package.el -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Code:
-(require 'cl-lib)
-(require 'helm)
-(require 'helm-help)
-(require 'package)
-
-(defgroup helm-el-package nil
- "helm elisp packages."
- :group 'helm)
-
-(defcustom helm-el-package-initial-filter 'all
- "Show only installed, upgraded or all packages at startup."
- :group 'helm-el-package
- :type '(radio :tag "Initial filter for elisp packages"
- (const :tag "Show all packages" all)
- (const :tag "Show installed packages" installed)
- (const :tag "Show not installed packages" uninstalled)
- (const :tag "Show upgradable packages" upgrade)))
-
-;; internals vars
-(defvar helm-el-package--show-only 'all)
-(defvar helm-el-package--initialized-p nil)
-(defvar helm-el-package--tabulated-list nil)
-(defvar helm-el-package--upgrades nil)
-(defvar helm-el-package--removable-packages nil)
-
-;; Shutup bytecompiler for emacs-24*
-(defvar package-menu-async) ; Only available on emacs-25.
-
-(defun helm-el-package--init ()
- (let (package-menu-async)
- (when (null package-alist)
- (setq helm-el-package--show-only 'all))
- (when (fboundp 'package--removable-packages)
- (setq helm-el-package--removable-packages
- (package--removable-packages)))
- (save-selected-window
- (if (and helm-el-package--initialized-p
- (fboundp 'package-show-package-list))
- ;; Use this as `list-packages' doesn't work
- ;; properly (empty buffer) when called from lisp
- ;; with 'no-fetch (emacs-25 WA).
- (package-show-package-list)
- (list-packages helm-el-package--initialized-p))
- (setq helm-el-package--initialized-p t)
- (message nil))
- (helm-init-candidates-in-buffer
- 'global
- (with-current-buffer (get-buffer "*Packages*")
- (setq helm-el-package--tabulated-list tabulated-list-entries)
- (buffer-string)))
- (setq helm-el-package--upgrades (helm-el-package-menu--find-upgrades))
- (if helm-force-updating-p
- (if helm-el-package--upgrades
- (message "%d package(s) can be upgraded, Refreshing packages list done"
- (length helm-el-package--upgrades))
- (message "Refreshing packages list done, no upgrades available"))
- (setq helm-el-package--show-only (if helm-el-package--upgrades
- 'upgrade
- helm-el-package-initial-filter)))
- (kill-buffer "*Packages*")))
-
-(defun helm-el-package-describe (candidate)
- (let ((id (get-text-property 0 'tabulated-list-id candidate)))
- (describe-package (if (fboundp 'package-desc-name)
- (package-desc-name id)
- (car id)))))
-
-(defun helm-el-package-visit-homepage (candidate)
- (let* ((id (get-text-property 0 'tabulated-list-id candidate))
- (pkg (if (fboundp 'package-desc-name) (package-desc-name id)
- (car id)))
- (desc (cadr (assoc pkg package-archive-contents)))
- (extras (package-desc-extras desc))
- (url (and (listp extras) (cdr-safe (assoc :url extras)))))
- (if (stringp url)
- (browse-url url)
- (message "Package %s has no homepage"
- (propertize (symbol-name pkg)
- 'face 'font-lock-keyword-face)))))
-
-(defun helm-el-run-visit-homepage ()
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-el-package-visit-homepage)))
-(put 'helm-el-run-visit-homepage 'helm-only t)
-
-(defun helm-el-package-install-1 (pkg-list)
- (cl-loop with mkd = pkg-list
- for p in mkd
- for id = (get-text-property 0 'tabulated-list-id p)
- do (package-install
- (if (fboundp 'package-desc-name) id (car id)))
- collect (if (fboundp 'package-desc-full-name) id (car id))
- into installed-list
- finally do (progn
- (when (boundp 'package-selected-packages)
- (customize-save-variable
- 'package-selected-packages
- (append (mapcar 'package-desc-name installed-list)
- package-selected-packages)))
- (if (fboundp 'package-desc-full-name)
- (message (format "%d packages installed:\n(%s)"
- (length installed-list)
- (mapconcat #'package-desc-full-name
- installed-list ", ")))
- (message (format "%d packages installed:\n(%s)"
- (length installed-list)
- (mapconcat 'symbol-name installed-list ", ")))))))
-
-(defun helm-el-package-install (_candidate)
- (helm-el-package-install-1 (helm-marked-candidates)))
-
-(defun helm-el-run-package-install ()
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-el-package-install)))
-(put 'helm-el-run-package-install 'helm-only t)
-
-(defun helm-el-package-uninstall-1 (pkg-list)
- (cl-loop with mkd = pkg-list
- for p in mkd
- for id = (get-text-property 0 'tabulated-list-id p)
- do
- (condition-case-unless-debug err
- (with-no-warnings
- (if (fboundp 'package-desc-full-name)
- ;; emacs 24.4
- (package-delete id)
- ;; emacs 24.3
- (package-delete (symbol-name (car id))
- (package-version-join (cdr id)))))
- (error (message (cadr err))))
- unless (assoc (elt id 1) package-alist)
- collect (if (fboundp 'package-desc-full-name)
- id
- (cons (symbol-name (car id))
- (package-version-join (cdr id))))
- into delete-list
- finally do (if delete-list
- (if (fboundp 'package-desc-full-name)
- ;; emacs 24.4
- (message (format "%d packages deleted:\n(%s)"
- (length delete-list)
- (mapconcat #'package-desc-full-name
- delete-list ", ")))
- ;; emacs 24.3
- (message (format "%d packages deleted:\n(%s)"
- (length delete-list)
- (mapconcat (lambda (x)
- (concat (car x) "-" (cdr x)))
- delete-list ", ")))
- ;; emacs 24.3 doesn't update
- ;; its `package-alist' after deleting.
- (cl-loop for p in package-alist
- when (assq (symbol-name (car p)) delete-list)
- do (setq package-alist (delete p package-alist))))
- "No package deleted")))
-
-(defun helm-el-package-uninstall (_candidate)
- (helm-el-package-uninstall-1 (helm-marked-candidates)))
-
-(defun helm-el-run-package-uninstall ()
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-el-package-uninstall)))
-(put 'helm-el-run-package-uninstall 'helm-only t)
-
-(defun helm-el-package-menu--find-upgrades ()
- (cl-loop for entry in helm-el-package--tabulated-list
- for pkg-desc = (car entry)
- for status = (package-desc-status pkg-desc)
- when (member status '("installed" "unsigned" "dependency"))
- collect pkg-desc
- into installed
- when (member status '("available" "new"))
- collect (cons (package-desc-name pkg-desc) pkg-desc)
- into available
- finally return
- (cl-loop for pkg in installed
- for avail-pkg = (assq (package-desc-name pkg) available)
- when (and avail-pkg
- (version-list-< (package-desc-version pkg)
- (package-desc-version
- (cdr avail-pkg))))
- collect avail-pkg)))
-
-(defun helm-el-package-upgrade-1 (pkg-list)
- (cl-loop for p in pkg-list
- for pkg-desc = (car p)
- for upgrade = (cdr (assq (package-desc-name pkg-desc)
- helm-el-package--upgrades))
- do
- (cond ((null upgrade)
- (ignore))
- ((equal pkg-desc upgrade)
- ;;Install.
- (package-install pkg-desc))
- (t
- ;; Delete.
- (if (boundp 'package-selected-packages)
- (with-no-warnings
- (package-delete pkg-desc t t))
- (package-delete pkg-desc))))))
-
-(defun helm-el-package-upgrade (_candidate)
- (helm-el-package-upgrade-1
- (cl-loop with pkgs = (helm-marked-candidates)
- for p in helm-el-package--tabulated-list
- for pkg = (car p)
- if (member (symbol-name (package-desc-name pkg)) pkgs)
- collect p)))
-
-(defun helm-el-run-package-upgrade ()
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-el-package-upgrade)))
-(put 'helm-el-run-package-upgrade 'helm-only t)
-
-(defun helm-el-package-upgrade-all ()
- (if helm-el-package--upgrades
- (with-helm-display-marked-candidates
- helm-marked-buffer-name (mapcar (lambda (x) (symbol-name (car x)))
- helm-el-package--upgrades)
- (when (y-or-n-p "Upgrade all packages? ")
- (helm-el-package-upgrade-1 helm-el-package--tabulated-list)))
- (message "No packages to upgrade actually!")))
-
-(defun helm-el-package-upgrade-all-action (_candidate)
- (helm-el-package-upgrade-all))
-
-(defun helm-el-run-package-upgrade-all ()
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-el-package-upgrade-all-action)))
-(put 'helm-el-run-package-upgrade-all 'helm-only t)
-
-(defun helm-el-package--transformer (candidates _source)
- (cl-loop for c in candidates
- for id = (get-text-property 0 'tabulated-list-id c)
- for name = (if (fboundp 'package-desc-name)
- (and id (package-desc-name id))
- (car id))
- for installed-p = (assq name package-alist)
- for upgrade-p = (assq name helm-el-package--upgrades)
- for user-installed-p = (and (boundp 'package-selected-packages)
- (memq name package-selected-packages))
- do (when user-installed-p (put-text-property 0 2 'display "S " c))
- do (when (memq name helm-el-package--removable-packages)
- (put-text-property 0 2 'display "U " c)
- (put-text-property
- 2 (+ (length (symbol-name name)) 2)
- 'face 'font-lock-variable-name-face c))
- for cand = (cons c (car (split-string c)))
- when (or (and upgrade-p
- (eq helm-el-package--show-only 'upgrade))
- (and installed-p
- (eq helm-el-package--show-only 'installed))
- (and (not installed-p)
- (eq helm-el-package--show-only 'uninstalled))
- (eq helm-el-package--show-only 'all))
- collect cand))
-
-(defun helm-el-package-show-upgrade ()
- (interactive)
- (with-helm-alive-p
- (setq helm-el-package--show-only 'upgrade)
- (helm-update)))
-(put 'helm-el-package-show-upgrade 'helm-only t)
-
-(defun helm-el-package-show-installed ()
- (interactive)
- (with-helm-alive-p
- (setq helm-el-package--show-only 'installed)
- (helm-update)))
-(put 'helm-el-package-show-installed 'helm-only t)
-
-(defun helm-el-package-show-all ()
- (interactive)
- (with-helm-alive-p
- (setq helm-el-package--show-only 'all)
- (helm-update)))
-(put 'helm-el-package-show-all 'helm-only t)
-
-(defun helm-el-package-show-uninstalled ()
- (interactive)
- (with-helm-alive-p
- (setq helm-el-package--show-only 'uninstalled)
- (helm-update)))
-(put 'helm-el-package-show-uninstalled 'helm-only t)
-
-(defvar helm-el-package-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map helm-map)
- (define-key map (kbd "M-I") 'helm-el-package-show-installed)
- (define-key map (kbd "M-O") 'helm-el-package-show-uninstalled)
- (define-key map (kbd "M-U") 'helm-el-package-show-upgrade)
- (define-key map (kbd "M-A") 'helm-el-package-show-all)
- (define-key map (kbd "C-c i") 'helm-el-run-package-install)
- (define-key map (kbd "C-c r") 'helm-el-run-package-reinstall)
- (define-key map (kbd "C-c d") 'helm-el-run-package-uninstall)
- (define-key map (kbd "C-c u") 'helm-el-run-package-upgrade)
- (define-key map (kbd "C-c U") 'helm-el-run-package-upgrade-all)
- (define-key map (kbd "C-c @") 'helm-el-run-visit-homepage)
- map))
-
-(defvar helm-source-list-el-package nil)
-(defclass helm-list-el-package-source (helm-source-in-buffer)
- ((init :initform 'helm-el-package--init)
- (get-line :initform 'buffer-substring)
- (filtered-candidate-transformer :initform 'helm-el-package--transformer)
- (action-transformer :initform 'helm-el-package--action-transformer)
- (help-message :initform 'helm-el-package-help-message)
- (keymap :initform helm-el-package-map)
- (update :initform 'helm-el-package--update)
- (candidate-number-limit :initform 9999)
- (action :initform '(("Describe package" . helm-el-package-describe)
- ("Visit homepage" . helm-el-package-visit-homepage)))))
-
-(defun helm-el-package--action-transformer (actions candidate)
- (let* ((pkg-desc (get-text-property
- 0 'tabulated-list-id candidate))
- (pkg-name (package-desc-name pkg-desc))
- (acts (if helm-el-package--upgrades
- (append actions '(("Upgrade all packages"
- . helm-el-package-upgrade-all-action)))
- actions)))
- (cond ((and (package-installed-p pkg-name)
- (cdr (assq pkg-name helm-el-package--upgrades)))
- (append '(("Upgrade package(s)" . helm-el-package-upgrade)
- ("Uninstall package(s)" . helm-el-package-uninstall)) acts))
- ((and (package-installed-p pkg-name)
- (or (null (package-built-in-p pkg-name))
- (and (package-built-in-p pkg-name)
- (assq pkg-name package-alist))))
- (append acts '(("Reinstall package(s)" . helm-el-package-reinstall)
- ("Uninstall package(s)" . helm-el-package-uninstall))))
- (t (append acts '(("Install packages(s)" . helm-el-package-install)))))))
-
-(defun helm-el-package--update ()
- (setq helm-el-package--initialized-p nil))
-
-(defun helm-el-package-reinstall (_pkg)
- (cl-loop for p in (helm-marked-candidates)
- for pkg-desc = (get-text-property 0 'tabulated-list-id p)
- for name = (package-desc-name pkg-desc)
- do (if (boundp 'package-selected-packages)
- (with-no-warnings
- (package-delete pkg-desc 'force 'nosave)
- ;; pkg-desc contain the description
- ;; of the installed package just removed
- ;; and is BTW no more valid.
- ;; Use the entry in package-archive-content
- ;; which is the non--installed package entry.
- ;; For some reason `package-install'
- ;; need a pkg-desc (package-desc-p) for the build-in
- ;; packages already installed, the name (as symbol)
- ;; fails with such packages.
- (package-install
- (cadr (assq name package-archive-contents))))
- (package-delete pkg-desc)
- (package-install name))))
-
-(defun helm-el-run-package-reinstall ()
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-el-package-reinstall)))
-(put 'helm-el-run-package-reinstall 'helm-only t)
-
-;;;###autoload
-(defun helm-list-elisp-packages (arg)
- "Preconfigured helm for listing and handling emacs packages."
- (interactive "P")
- (when arg (setq helm-el-package--initialized-p nil))
- (unless helm-source-list-el-package
- (setq helm-source-list-el-package
- (helm-make-source "list packages" 'helm-list-el-package-source)))
- (helm :sources 'helm-source-list-el-package
- :buffer "*helm list packages*"))
-
-;;;###autoload
-(defun helm-list-elisp-packages-no-fetch ()
- "Preconfigured helm for emacs packages.
-Same as `helm-list-elisp-packages' but don't fetch packages on remote."
- (interactive)
- (let ((helm-el-package--initialized-p t))
- (helm-list-elisp-packages nil)))
-
-(provide 'helm-elisp-package)
-
-;;; helm-elisp-package.el ends here
+++ /dev/null
-;;; helm-elisp.el --- Elisp symbols completion for helm. -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Code:
-(require 'cl-lib)
-(require 'helm)
-(require 'helm-help)
-(require 'helm-types)
-(require 'helm-utils)
-(require 'helm-info)
-(require 'helm-eval)
-(require 'helm-files)
-(require 'advice)
-
-(declare-function 'helm-describe-function "helm-lib")
-(declare-function 'helm-describe-variable "helm-lib")
-(declare-function 'helm-describe-face "helm-lib")
-
-\f
-;;; Customizable values
-
-(defgroup helm-elisp nil
- "Elisp related Applications and libraries for Helm."
- :group 'helm)
-
-(defcustom helm-turn-on-show-completion t
- "Display candidate in buffer while moving selection when non--nil."
- :group 'helm-elisp
- :type 'boolean)
-
-(defcustom helm-show-completion-use-special-display t
- "A special display will be used in Lisp completion if non--nil.
-All functions that are wrapped in macro `with-helm-show-completion'
-will be affected."
- :group 'helm-elisp
- :type 'boolean)
-
-(defcustom helm-show-completion-min-window-height 7
- "Minimum completion window height used in show completion.
-This is used in macro `with-helm-show-completion'."
- :group 'helm-elisp
- :type 'integer)
-
-(defcustom helm-lisp-quoted-function-list
- '(funcall apply mapc cl-mapc mapcar cl-mapcar
- callf callf2 cl-callf cl-callf2 fset
- fboundp fmakunbound symbol-function)
- "List of function where quoted function completion happen.
-e.g give only function names after \(funcall '."
- :group 'helm-elisp
- :type '(repeat (choice symbol)))
-
-(defcustom helm-lisp-unquoted-function-list
- '(function defadvice)
- "List of function where unquoted function completion happen.
-e.g give only function names after \(function ."
- :group 'helm-elisp
- :type '(repeat (choice symbol)))
-
-(defcustom helm-apropos-fuzzy-match nil
- "Enable fuzzy matching for `helm-apropos' when non-nil."
- :group 'helm-elisp
- :type 'boolean)
-
-(defcustom helm-lisp-fuzzy-completion nil
- "Enable fuzzy matching in emacs-lisp completion when non-nil.
-NOTE: This enable fuzzy matching in helm native implementation of
-elisp completion, but not on helmized elisp completion, i.e
-fuzzy completion is not available in `completion-at-point'."
- :group 'helm-elisp
- :type 'boolean)
-
-(defcustom helm-apropos-function-list '(helm-def-source--emacs-commands
- helm-def-source--emacs-functions
- helm-def-source--eieio-classes
- helm-def-source--eieio-generic
- helm-def-source--emacs-variables
- helm-def-source--emacs-faces
- helm-def-source--helm-attributes)
- "A list of functions that build helm sources to use in `helm-apropos'."
- :group 'helm-elisp
- :type '(repeat (choice symbol)))
-
-\f
-;;; Faces
-;;
-;;
-(defgroup helm-elisp-faces nil
- "Customize the appearance of helm-elisp."
- :prefix "helm-"
- :group 'helm-elisp
- :group 'helm-faces)
-
-(defface helm-lisp-show-completion
- '((t (:background "DarkSlateGray")))
- "Face used for showing candidates in `helm-lisp-completion'."
- :group 'helm-elisp-faces)
-
-(defface helm-lisp-completion-info
- '((t (:foreground "red")))
- "Face used for showing info in `helm-lisp-completion'."
- :group 'helm-elisp-faces)
-
-(defcustom helm-elisp-help-function
- 'helm-elisp-show-help
- "Function for displaying help for Lisp symbols."
- :group 'helm-elisp
- :type '(choice (function :tag "Open help for the symbol."
- helm-elisp-show-help)
- (function :tag "Show one liner in modeline."
- helm-elisp-show-doc-modeline)))
-
-\f
-;;; Show completion.
-;;
-;; Provide show completion with macro `with-helm-show-completion'.
-
-(defvar helm-show-completion-overlay nil)
-
-;; Called each time cursor move in helm-buffer.
-(defun helm-show-completion ()
- (with-helm-current-buffer
- (overlay-put helm-show-completion-overlay
- 'display (substring-no-properties
- (helm-get-selection)))))
-
-(defun helm-show-completion-init-overlay (beg end)
- (when (and helm-turn-on-show-completion beg end)
- (setq helm-show-completion-overlay (make-overlay beg end))
- (overlay-put helm-show-completion-overlay
- 'face 'helm-lisp-show-completion)))
-
-(defun helm-show-completion-display-function (buffer &rest _args)
- "A special resized helm window is used depending on position in BUFFER."
- (with-selected-window (selected-window)
- (if (window-dedicated-p)
- (helm-default-display-buffer buffer)
- (let* ((screen-size (+ (count-screen-lines (window-start) (point) t)
- 1 ; mode-line
- (if header-line-format 1 0))) ; header-line
- (def-size (- (window-height)
- helm-show-completion-min-window-height))
- (upper-height (max window-min-height (min screen-size def-size)))
- split-window-keep-point)
- (recenter -1)
- (set-window-buffer (if (active-minibuffer-window)
- (minibuffer-selected-window)
- (split-window nil upper-height
- helm-split-window-default-side))
- buffer)))))
-
-(defmacro with-helm-show-completion (beg end &rest body)
- "Show helm candidate in an overlay at point.
-BEG and END are the beginning and end position of the current completion
-in `helm-current-buffer'.
-BODY is an helm call where we want to enable show completion.
-If `helm-turn-on-show-completion' is nil just do nothing."
- (declare (indent 2) (debug t))
- `(let ((helm-move-selection-after-hook
- (and helm-turn-on-show-completion
- (append (list 'helm-show-completion)
- helm-move-selection-after-hook)))
- (helm-always-two-windows t)
- (helm-split-window-default-side
- (if (eq helm-split-window-default-side 'same)
- 'below helm-split-window-default-side))
- helm-split-window-in-side-p
- helm-reuse-last-window-split-state)
- (helm-set-local-variable
- 'helm-display-function
- (if helm-show-completion-use-special-display
- 'helm-show-completion-display-function
- 'helm-default-display-buffer))
- (unwind-protect
- (progn
- (helm-show-completion-init-overlay ,beg ,end)
- ,@body)
- (when (and helm-turn-on-show-completion
- helm-show-completion-overlay
- (overlayp helm-show-completion-overlay))
- (delete-overlay helm-show-completion-overlay)))))
-
-\f
-;;; Lisp symbol completion.
-;;
-;;
-(defun helm-lisp-completion--predicate-at-point (beg)
- ;; Return a predicate for `all-completions'.
- (let ((fn-sym-p (lambda ()
- (or
- (and (eq (char-before) ?\ )
- (save-excursion
- (skip-syntax-backward " " (point-at-bol))
- (memq (symbol-at-point)
- helm-lisp-unquoted-function-list)))
- (and (eq (char-before) ?\')
- (save-excursion
- (forward-char -1)
- (eq (char-before) ?\#)))))))
- (save-excursion
- (goto-char beg)
- (if (or
- ;; Complete on all symbols in non--lisp modes (logs mail etc..)
- (not (memq major-mode '(emacs-lisp-mode
- lisp-interaction-mode
- inferior-emacs-lisp-mode)))
- (not (or (funcall fn-sym-p)
- (and (eq (char-before) ?\')
- (save-excursion
- (forward-char (if (funcall fn-sym-p) -2 -1))
- (skip-syntax-backward " " (point-at-bol))
- (memq (symbol-at-point)
- helm-lisp-quoted-function-list)))
- (eq (char-before) ?\())) ; no paren before str.
- ;; Looks like we are in a let statement.
- (condition-case nil
- (progn (up-list -2) (forward-char 1)
- (eq (char-after) ?\())
- (error nil)))
- (lambda (sym)
- (or (boundp sym) (fboundp sym) (symbol-plist sym)))
- #'fboundp))))
-
-(defun helm-thing-before-point (&optional limits regexp)
- "Return symbol name before point.
-If REGEXP is specified return what REGEXP find before point.
-By default match the beginning of symbol before point.
-With LIMITS arg specified return the beginning and end position
-of symbol before point."
- (save-excursion
- (let (beg
- (end (point))
- (boundary (field-beginning nil nil (point-at-bol))))
- (if (re-search-backward (or regexp "\\_<") boundary t)
- (setq beg (match-end 0))
- (setq beg boundary))
- (unless (= beg end)
- (if limits
- (cons beg end)
- (buffer-substring-no-properties beg end))))))
-
-(defun helm-bounds-of-thing-before-point (&optional regexp)
- "Get the beginning and end position of `helm-thing-before-point'.
-Return a cons \(beg . end\)."
- (helm-thing-before-point 'limits regexp))
-
-(defun helm-insert-completion-at-point (beg end str)
- ;; When there is no space after point
- ;; we are completing inside a symbol or
- ;; after a partial symbol with the next arg aside
- ;; without space, in this case mark the region.
- ;; deleting it would remove the
- ;; next arg which is unwanted.
- (delete-region beg end)
- (insert str)
- (let ((pos (cdr (or (bounds-of-thing-at-point 'symbol)
- ;; needed for helm-dabbrev.
- (bounds-of-thing-at-point 'filename)))))
- (when (and pos (< (point) pos))
- (push-mark pos t t))))
-
-(defvar helm-lisp-completion--cache nil)
-(defvar helm-lgst-len nil)
-;;;###autoload
-(defun helm-lisp-completion-at-point ()
- "Preconfigured helm for lisp symbol completion at point."
- (interactive)
- (setq helm-lgst-len 0)
- (let* ((target (helm-thing-before-point))
- (beg (car (helm-bounds-of-thing-before-point)))
- (end (point))
- (pred (and beg (helm-lisp-completion--predicate-at-point beg)))
- (loc-vars (and (fboundp 'elisp--local-variables)
- (ignore-errors
- (mapcar #'symbol-name (elisp--local-variables)))))
- (glob-syms (and target pred (all-completions target obarray pred)))
- (candidates (append loc-vars glob-syms))
- (helm-quit-if-no-candidate t)
- (helm-execute-action-at-once-if-one t)
- (enable-recursive-minibuffers t))
- (setq helm-lisp-completion--cache (cl-loop for sym in candidates
- for len = (length sym)
- when (> len helm-lgst-len)
- do (setq helm-lgst-len len)
- collect sym))
- (if candidates
- (with-helm-show-completion beg end
- ;; Overlay is initialized now in helm-current-buffer.
- (helm
- :sources (helm-build-in-buffer-source "Lisp completion"
- :data helm-lisp-completion--cache
- :persistent-action 'helm-lisp-completion-persistent-action
- :nomark t
- :fuzzy-match helm-lisp-fuzzy-completion
- :persistent-help (helm-lisp-completion-persistent-help)
- :filtered-candidate-transformer
- 'helm-lisp-completion-transformer
- :action `(lambda (candidate)
- (with-helm-current-buffer
- (run-with-timer
- 0.01 nil
- 'helm-insert-completion-at-point
- ,beg ,end candidate))))
- :input (if helm-lisp-fuzzy-completion
- target (concat target " "))
- :resume 'noresume
- :buffer "*helm lisp completion*"
- :allow-nest t))
- (message "[No Match]"))))
-
-(defun helm-lisp-completion-persistent-action (candidate &optional name)
- "Show documentation for the function.
-Documentation is shown briefly in mode-line or completely
-in other window according to the value of `helm-elisp-help-function'."
- (funcall helm-elisp-help-function candidate name))
-
-(defun helm-lisp-completion-persistent-help ()
- "Return persistent-help according to the value of `helm-elisp-help-function'"
- (cl-ecase helm-elisp-help-function
- (helm-elisp-show-doc-modeline "Show brief doc in mode-line")
- (helm-elisp-show-help "Toggle show help for the symbol")))
-
-(defun helm-elisp--show-help-1 (candidate &optional name)
- (let ((sym (intern-soft candidate)))
- (cl-typecase sym
- ((and fboundp boundp)
- (if (member name '("describe-function" "describe-variable"))
- (funcall (intern (format "helm-%s" name)) sym)
- ;; When there is no way to know what to describe
- ;; prefer describe-function.
- (helm-describe-function sym)))
- (fbound (helm-describe-function sym))
- (bound (helm-describe-variable sym))
- (face (helm-describe-face sym)))))
-
-(defun helm-elisp-show-help (candidate &optional name)
- "Show full help for the function CANDIDATE.
-Arg NAME specify the name of the top level function
-calling helm generic completion (e.g \"describe-function\")."
- (helm-elisp--persistent-help
- candidate 'helm-elisp--show-help-1 name))
-
-(defun helm-elisp-show-doc-modeline (candidate &optional name)
- "Show brief documentation for the function in modeline."
- (let ((cursor-in-echo-area t)
- mode-line-in-non-selected-windows)
- (helm-show-info-in-mode-line
- (propertize
- (helm-get-first-line-documentation
- (intern candidate) name)
- 'face 'helm-lisp-completion-info))))
-
-(defun helm-lisp-completion-transformer (candidates _source)
- "Helm candidates transformer for lisp completion."
- (cl-loop for c in candidates
- for sym = (intern c)
- for annot = (cl-typecase sym
- (command " (Com)")
- (class " (Class)")
- (generic " (Gen)")
- (fbound " (Fun)")
- (bound " (Var)")
- (face " (Face)"))
- for spaces = (make-string (- helm-lgst-len (length c)) ? )
- collect (cons (concat c spaces annot) c) into lst
- finally return (sort lst #'helm-generic-sort-fn)))
-
-(defun helm-get-first-line-documentation (sym &optional name)
- "Return first line documentation of symbol SYM.
-If SYM is not documented, return \"Not documented\"."
- (let ((doc (cl-typecase sym
- ((and fboundp boundp)
- (cond ((string= name "describe-function")
- (documentation sym t))
- ((string= name "describe-variable")
- (documentation-property sym 'variable-documentation t))
- (t (documentation sym t))))
- (fbound (documentation sym t))
- (bound (documentation-property sym 'variable-documentation t))
- (face (face-documentation sym)))))
- (if (and doc (not (string= doc ""))
- ;; `documentation' return "\n\n(args...)"
- ;; for CL-style functions.
- (not (string-match-p "^\n\n" doc)))
- (car (split-string doc "\n"))
- "Not documented")))
-
-;;; File completion.
-;;
-;; Complete file name at point.
-
-;;;###autoload
-(defun helm-complete-file-name-at-point (&optional force)
- "Preconfigured helm to complete file name at point."
- (interactive)
- (require 'helm-mode)
- (let* ((tap (thing-at-point 'filename))
- beg
- (init (and tap
- (or force
- (save-excursion
- (end-of-line)
- (search-backward tap (point-at-bol) t)
- (setq beg (point))
- (looking-back "[^'`( ]" (1- (point)))))
- (expand-file-name
- (substring-no-properties tap))))
- (end (point))
- (helm-quit-if-no-candidate t)
- (helm-execute-action-at-once-if-one t)
- completion)
- (with-helm-show-completion beg end
- (setq completion (helm-read-file-name "FileName: "
- :initial-input init)))
- (when (and completion (not (string= completion "")))
- (delete-region beg end) (insert (if (string-match "^~" tap)
- (abbreviate-file-name completion)
- completion)))))
-
-;;;###autoload
-(defun helm-lisp-indent ()
- ;; It is meant to use with `helm-define-multi-key' which
- ;; does not support args for functions yet, so use `current-prefix-arg'
- ;; for now instead of (interactive "P").
- (interactive)
- (let ((tab-always-indent (or (eq tab-always-indent 'complete)
- tab-always-indent)))
- (indent-for-tab-command current-prefix-arg)))
-
-;;;###autoload
-(defun helm-lisp-completion-or-file-name-at-point ()
- "Preconfigured helm to complete lisp symbol or filename at point.
-Filename completion happen if string start after or between a double quote."
- (interactive)
- (let* ((tap (thing-at-point 'filename)))
- (if (and tap (save-excursion
- (end-of-line)
- (search-backward tap (point-at-bol) t)
- (looking-back "[^'`( ]" (1- (point)))))
- (helm-complete-file-name-at-point)
- (helm-lisp-completion-at-point))))
-
-\f
-;;; Apropos
-;;
-;;
-(defun helm-apropos-init (test default)
- "Init candidates buffer for `helm-apropos' sources."
- (require 'helm-help)
- (helm-init-candidates-in-buffer 'global
- (let ((default-symbol (and (stringp default)
- (intern-soft default)))
- (symbols (all-completions "" obarray test)))
- (if (and default-symbol (funcall test default-symbol))
- (cons default-symbol symbols)
- symbols))))
-
-(defun helm-apropos-init-faces (default)
- "Init candidates buffer for faces for `helm-apropos'."
- (require 'helm-help)
- (with-current-buffer (helm-candidate-buffer 'global)
- (goto-char (point-min))
- (let ((default-symbol (and (stringp default)
- (intern-soft default)))
- (faces (face-list)))
- (when (and default-symbol (facep default-symbol))
- (insert (concat default "\n")))
- (insert
- (mapconcat #'prin1-to-string
- (if default
- (cl-remove-if (lambda (sym) (string= sym default)) faces)
- faces)
- "\n")))))
-
-(defun helm-apropos-default-sort-fn (candidates _source)
- (if (string= helm-pattern "")
- candidates
- (sort candidates #'helm-generic-sort-fn)))
-
-(defun helm-def-source--emacs-variables (&optional default)
- (helm-build-in-buffer-source "Variables"
- :init `(lambda ()
- (helm-apropos-init
- (lambda (x) (and (boundp x) (not (keywordp x)))) ,default))
- :fuzzy-match helm-apropos-fuzzy-match
- :filtered-candidate-transformer (and (null helm-apropos-fuzzy-match)
- 'helm-apropos-default-sort-fn)
- :nomark t
- :persistent-action (lambda (candidate)
- (helm-elisp--persistent-help
- candidate 'helm-describe-variable))
- :persistent-help "Describe variable"
- :action '(("Describe variable" . helm-describe-variable)
- ("Find variable" . helm-find-variable)
- ("Info lookup" . helm-info-lookup-symbol)
- ("Set variable" . helm-set-variable))
- :action-transformer
- (lambda (actions candidate)
- (let ((sym (helm-symbolify candidate)))
- (if (custom-variable-p sym)
- (append
- actions
- (let ((standard-value (eval (car (get sym 'standard-value)))))
- (unless (equal standard-value (symbol-value sym))
- `(("Reset Variable to default value" .
- ,(lambda (candidate)
- (let ((sym (helm-symbolify candidate)))
- (set sym standard-value)))))))
- '(("Customize variable" .
- (lambda (candidate)
- (customize-option (helm-symbolify candidate))))))
- actions)))))
-
-(defun helm-def-source--emacs-faces (&optional default)
- "Create `helm' source for faces to be displayed with
-`helm-apropos'."
- (helm-build-in-buffer-source "Faces"
- :init (lambda () (helm-apropos-init-faces default))
- :fuzzy-match helm-apropos-fuzzy-match
- :filtered-candidate-transformer
- (append (and (null helm-apropos-fuzzy-match)
- '(helm-apropos-default-sort-fn))
- (list
- (lambda (candidates _source)
- (cl-loop for c in candidates
- collect (propertize c 'face (intern c))))))
- :persistent-action (lambda (candidate)
- (helm-elisp--persistent-help
- candidate 'helm-describe-face))
- :persistent-help "Describe face"
- :nomark t
- :action '(("Describe face" . helm-describe-face)
- ("Find face" . helm-find-face-definition)
- ("Customize face" . (lambda (candidate)
- (customize-face (helm-symbolify candidate)))))))
-
-(defun helm-def-source--helm-attributes (&optional _default)
- (let ((def-act (lambda (candidate)
- (let (special-display-buffer-names
- special-display-regexps
- helm-persistent-action-use-special-display)
- (with-output-to-temp-buffer "*Help*"
- (princ (get (intern candidate) 'helm-attrdoc)))))))
- (helm-build-sync-source "Helm attributes"
- :candidates (lambda ()
- (mapcar 'symbol-name helm-attributes))
- :fuzzy-match helm-apropos-fuzzy-match
- :nomark t
- :persistent-action (lambda (candidate)
- (helm-elisp--persistent-help
- candidate def-act))
- :persistent-help "Describe helm attribute"
- :action def-act)))
-
-(defun helm-def-source--emacs-commands (&optional default)
- (helm-build-in-buffer-source "Commands"
- :init `(lambda ()
- (helm-apropos-init 'commandp ,default))
- :fuzzy-match helm-apropos-fuzzy-match
- :filtered-candidate-transformer (and (null helm-apropos-fuzzy-match)
- 'helm-apropos-default-sort-fn)
- :nomark t
- :persistent-action (lambda (candidate)
- (helm-elisp--persistent-help
- candidate 'helm-describe-function))
- :persistent-help "Describe command"
- :action '(("Describe function" . helm-describe-function)
- ("Find function" . helm-find-function)
- ("Info lookup" . helm-info-lookup-symbol))))
-
-(defun helm-def-source--emacs-functions (&optional default)
- (helm-build-in-buffer-source "Functions"
- :init `(lambda ()
- (helm-apropos-init (lambda (x)
- (and (fboundp x)
- (not (commandp x))
- (not (generic-p x))
- (not (class-p x))))
- ,default))
- :fuzzy-match helm-apropos-fuzzy-match
- :filtered-candidate-transformer (and (null helm-apropos-fuzzy-match)
- 'helm-apropos-default-sort-fn)
- :persistent-action (lambda (candidate)
- (helm-elisp--persistent-help
- candidate 'helm-describe-function))
- :persistent-help "Describe function"
- :nomark t
- :action '(("Describe function" . helm-describe-function)
- ("Find function" . helm-find-function)
- ("Info lookup" . helm-info-lookup-symbol))))
-
-(defun helm-def-source--eieio-classes (&optional default)
- (helm-build-in-buffer-source "Classes"
- :init `(lambda ()
- (helm-apropos-init (lambda (x)
- (class-p x))
- ,default))
- :fuzzy-match helm-apropos-fuzzy-match
- :filtered-candidate-transformer (and (null helm-apropos-fuzzy-match)
- 'helm-apropos-default-sort-fn)
- :nomark t
- :persistent-action (lambda (candidate)
- (helm-elisp--persistent-help
- candidate 'helm-describe-function))
- :persistent-help "Describe class"
- :action '(("Describe function" . helm-describe-function)
- ("Find function" . helm-find-function)
- ("Info lookup" . helm-info-lookup-symbol))))
-
-(defun helm-def-source--eieio-generic (&optional default)
- (helm-build-in-buffer-source "Generic functions"
- :init `(lambda ()
- (helm-apropos-init (lambda (x)
- (generic-p x))
- ,default))
- :fuzzy-match helm-apropos-fuzzy-match
- :filtered-candidate-transformer (and (null helm-apropos-fuzzy-match)
- 'helm-apropos-default-sort-fn)
- :nomark t
- :persistent-action (lambda (candidate)
- (helm-elisp--persistent-help
- candidate 'helm-describe-function))
- :persistent-help "Describe generic function"
- :action '(("Describe function" . helm-describe-function)
- ("Find function" . helm-find-function)
- ("Info lookup" . helm-info-lookup-symbol))))
-
-(defun helm-info-lookup-symbol-1 (c)
- (let ((helm-execute-action-at-once-if-one t)
- (helm-quit-if-no-candidate
- `(lambda ()
- (message "`%s' Not Documented as a symbol" ,c))))
- (helm :sources '(helm-source-info-elisp
- helm-source-info-cl
- helm-source-info-eieio)
- :resume 'noresume
- :buffer "*helm lookup*"
- :input c)))
-
-(defun helm-info-lookup-symbol (candidate)
- (run-with-timer 0.01 nil #'helm-info-lookup-symbol-1 candidate))
-
-(defun helm-elisp--persistent-help (candidate fun &optional name)
- (let ((hbuf (get-buffer (help-buffer))))
- (if (and (helm-attr 'help-running-p)
- (string= candidate (helm-attr 'help-current-symbol))
- (null helm-persistent-action-use-special-display))
- (progn
- ;; When started from a help buffer,
- ;; Don't kill this buffer as it is helm-current-buffer.
- (unless (equal hbuf helm-current-buffer)
- (kill-buffer hbuf)
- (set-window-buffer (get-buffer-window hbuf)
- helm-current-buffer))
- (helm-attrset 'help-running-p nil))
- (if name (funcall fun candidate name) (funcall fun candidate))
- (helm-attrset 'help-running-p t))
- (helm-attrset 'help-current-symbol candidate)))
-
-;;;###autoload
-(defun helm-apropos (default)
- "Preconfigured helm to describe commands, functions, variables and faces.
-In non interactives calls DEFAULT argument should be provided as a string,
-i.e the `symbol-name' of any existing symbol."
- (interactive (list (thing-at-point 'symbol)))
- (helm :sources
- (mapcar (lambda (func)
- (funcall func default))
- helm-apropos-function-list)
- :buffer "*helm apropos*"
- :preselect (and default (concat "\\_<" (regexp-quote default) "\\_>"))))
-
-\f
-;;; Advices
-;;
-;;
-(defvar helm-source-advice
- '((name . "Function Advice")
- (candidates . helm-advice-candidates)
- (action ("Toggle Enable/Disable" . helm-advice-toggle))
- (persistent-action . helm-advice-persistent-action)
- (nomark)
- (multiline)
- (persistent-help . "Describe function / C-u C-j: Toggle advice")))
-
-(defun helm-advice-candidates ()
- (cl-loop for (fname) in ad-advised-functions
- for function = (intern fname)
- append
- (cl-loop for class in ad-advice-classes append
- (cl-loop for advice in (ad-get-advice-info-field function class)
- for enabled = (ad-advice-enabled advice)
- collect
- (cons (format
- "%s %s %s"
- (if enabled "Enabled " "Disabled")
- (propertize fname 'face 'font-lock-function-name-face)
- (ad-make-single-advice-docstring advice class nil))
- (list function class advice))))))
-
-(defun helm-advice-persistent-action (func-class-advice)
- (if current-prefix-arg
- (helm-advice-toggle func-class-advice)
- (describe-function (car func-class-advice))))
-
-(defun helm-advice-toggle (func-class-advice)
- (cl-destructuring-bind (function _class advice) func-class-advice
- (cond ((ad-advice-enabled advice)
- (ad-advice-set-enabled advice nil)
- (message "Disabled"))
- (t
- (ad-advice-set-enabled advice t)
- (message "Enabled")))
- (ad-activate function)
- (and helm-in-persistent-action
- (helm-advice-update-current-display-string))))
-
-(defun helm-advice-update-current-display-string ()
- (helm-edit-current-selection
- (let ((newword (cond ((looking-at "Disabled") "Enabled")
- ((looking-at "Enabled") "Disabled"))))
- (when newword
- (delete-region (point) (progn (forward-word 1) (point)))
- (insert newword)))))
-
-;;;###autoload
-(defun helm-manage-advice ()
- "Preconfigured `helm' to disable/enable function advices."
- (interactive)
- (helm-other-buffer 'helm-source-advice "*helm advice*"))
-
-\f
-;;; Locate elisp library
-;;
-;;
-(defun helm-locate-library-scan-list ()
- (cl-loop for dir in load-path
- when (file-directory-p dir)
- append (directory-files dir t (concat (regexp-opt (get-load-suffixes))
- "\\'"))
- into lst
- finally return (helm-fast-remove-dups lst :test 'equal)))
-
-;;;###autoload
-(defun helm-locate-library ()
- "Preconfigured helm to locate elisp libraries."
- (interactive)
- (helm :sources (helm-build-in-buffer-source "Elisp libraries (Scan)"
- :data (lambda () (helm-locate-library-scan-list))
- :fuzzy-match t
- :keymap helm-generic-files-map
- :match-part (lambda (candidate)
- (if helm-ff-transformer-show-only-basename
- (helm-basename candidate) candidate))
- :filter-one-by-one (lambda (c)
- (if helm-ff-transformer-show-only-basename
- (cons (helm-basename c) c) c))
- :action (helm-actions-from-type-file))
- :buffer "*helm locate library*"))
-
-(defun helm-set-variable (var)
- "Set value to VAR interactively."
- (let* ((sym (helm-symbolify var))
- (val (default-value sym)))
- (set-default sym (eval-minibuffer (format "Set `%s': " var)
- (if (or (stringp val) (memq val '(nil t)))
- (prin1-to-string val)
- (format "'%s" (prin1-to-string val)))))))
-
-\f
-;;; Elisp Timers.
-;;
-;;
-(defclass helm-absolute-time-timers-class (helm-source-sync helm-type-timers)
- ((candidates :initform timer-list)
- (allow-dups :initform t)
- (candidate-transformer
- :initform
- (lambda (candidates)
- (cl-loop for timer in candidates
- collect (cons (helm-elisp--format-timer timer) timer))))))
-
-(defvar helm-source-absolute-time-timers
- (helm-make-source "Absolute Time Timers" 'helm-absolute-time-timers-class))
-
-(defclass helm-idle-time-timers-class (helm-source-sync helm-type-timers)
- ((candidates :initform timer-idle-list)
- (allow-dups :initform t)
- (candidate-transformer
- :initform
- (lambda (candidates)
- (cl-loop for timer in candidates
- collect (cons (helm-elisp--format-timer timer) timer))))))
-
-(defvar helm-source-idle-time-timers
- (helm-make-source "Idle Time Timers" 'helm-idle-time-timers-class))
-
-(defun helm-elisp--format-timer (timer)
- (format "%s repeat=%s %s(%s)"
- (let ((time (timer--time timer)))
- (if (timer--idle-delay timer)
- (format-time-string "idle-for=%5s" time)
- (format-time-string "%m/%d %T" time)))
- (or (timer--repeat-delay timer) "nil")
- (mapconcat 'identity (split-string
- (prin1-to-string (timer--function timer))
- "\n") " ")
- (mapconcat 'prin1-to-string (timer--args timer) " ")))
-
-;;;###autoload
-(defun helm-timers ()
- "Preconfigured `helm' for timers."
- (interactive)
- (helm :sources '(helm-source-absolute-time-timers
- helm-source-idle-time-timers)
- :buffer "*helm timers*"))
-
-\f
-;;; Complex command history
-;;
-;;
-(defun helm-btf--usable-p ()
- "Return t if current version of `backtrace-frame' accept 2 arguments."
- (condition-case nil
- (progn (backtrace-frame 1 'condition-case) t)
- (wrong-number-of-arguments nil)))
-
-(if (helm-btf--usable-p) ; Check if BTF accept more than one arg.
- ;; Emacs 24.4.
- (dont-compile
- (defvar helm-sexp--last-sexp nil)
- ;; This wont work compiled.
- (defun helm-sexp-eval-1 ()
- (interactive)
- (unwind-protect
- (progn
- ;; Trick called-interactively-p into thinking that `cand' is
- ;; an interactive call, See `repeat-complex-command'.
- (add-hook 'called-interactively-p-functions
- #'helm-complex-command-history--called-interactively-skip)
- (eval (read helm-sexp--last-sexp)))
- (remove-hook 'called-interactively-p-functions
- #'helm-complex-command-history--called-interactively-skip)))
-
- (defun helm-complex-command-history--called-interactively-skip (i _frame1 frame2)
- (and (eq 'eval (cadr frame2))
- (eq 'helm-sexp-eval-1
- (cadr (backtrace-frame (+ i 2) #'called-interactively-p)))
- 1))
-
- (defun helm-sexp-eval (_candidate)
- (call-interactively #'helm-sexp-eval-1)))
- ;; Emacs 24.3
- (defun helm-sexp-eval (cand)
- (let ((sexp (read cand)))
- (condition-case err
- (if (> (length (remove nil sexp)) 1)
- (eval sexp)
- (apply 'call-interactively sexp))
- (error (message "Evaluating gave an error: %S" err)
- nil)))))
-
-(defvar helm-source-complex-command-history
- (helm-build-sync-source "Complex Command History"
- :candidates (lambda ()
- ;; Use cdr to avoid adding
- ;; `helm-complex-command-history' here.
- (cl-loop for i in command-history
- unless (equal i '(helm-complex-command-history))
- collect (prin1-to-string i)))
- :action (helm-make-actions
- "Eval" (lambda (candidate)
- (and (boundp 'helm-sexp--last-sexp)
- (setq helm-sexp--last-sexp candidate))
- (let ((command (read candidate)))
- (unless (equal command (car command-history))
- (setq command-history (cons command command-history))))
- (run-with-timer 0.1 nil #'helm-sexp-eval candidate))
- "Edit and eval" (lambda (candidate)
- (edit-and-eval-command "Eval: " (read candidate))))
- :persistent-action #'helm-sexp-eval
- :multiline t))
-
-;;;###autoload
-(defun helm-complex-command-history ()
- "Preconfigured helm for complex command history."
- (interactive)
- (helm :sources 'helm-source-complex-command-history
- :buffer "*helm complex commands*"))
-
-(provide 'helm-elisp)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-elisp.el ends here
+++ /dev/null
-;;; helm-elscreen.el -- Elscreen support -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Code:
-(require 'cl-lib)
-(require 'helm)
-
-(declare-function elscreen-find-screen-by-buffer "ext:elscreen.el" (buffer &optional create))
-(declare-function elscreen-find-file "ext:elscreen.el" (filename))
-(declare-function elscreen-goto "ext:elscreen.el" (screen))
-(declare-function elscreen-get-conf-list "ext:elscreen.el" (type))
-
-(defun helm-find-buffer-on-elscreen (candidate)
- "Open buffer in new screen, if marked buffers open all in elscreens."
- (helm-require-or-error 'elscreen 'helm-find-buffer-on-elscreen)
- (helm-aif (helm-marked-candidates)
- (cl-dolist (i it)
- (let ((target-screen (elscreen-find-screen-by-buffer
- (get-buffer i) 'create)))
- (elscreen-goto target-screen)))
- (let ((target-screen (elscreen-find-screen-by-buffer
- (get-buffer candidate) 'create)))
- (elscreen-goto target-screen))))
-
-(defun helm-elscreen-find-file (file)
- (helm-require-or-error 'elscreen 'helm-elscreen-find-file)
- (elscreen-find-file file))
-
-(defclass helm-source-elscreen (helm-source-sync)
- ((candidates
- :initform
- (lambda ()
- (when (cdr (elscreen-get-screen-to-name-alist))
- (cl-sort (cl-loop for (screen . name) in (elscreen-get-screen-to-name-alist)
- collect (cons (format "[%d] %s" screen name) screen))
- #'< :key #'cdr))))
- (action :initform
- '(("Change Screen" .
- (lambda (candidate)
- (elscreen-goto candidate)))
- ("Kill Screen(s)" .
- (lambda (_)
- (cl-dolist (i (helm-marked-candidates))
- (elscreen-goto i)
- (elscreen-kill))))
- ("Only Screen" .
- (lambda (candidate)
- (elscreen-goto candidate)
- (elscreen-kill-others)))))
- (migemo :initform t)))
-
-(defclass helm-source-elscreen-history (helm-source-elscreen)
- ((candidates
- :initform
- (lambda ()
- (let ((sname (elscreen-get-screen-to-name-alist)))
- (when (cdr sname)
- (cl-loop for screen in (cdr (elscreen-get-conf-list 'screen-history))
- collect (cons (format "[%d] %s" screen (cdr (assq screen sname)))
- screen))))))))
-
-(defvar helm-source-elscreen-list
- (helm-make-source "ElScreen" 'helm-source-elscreen))
-
-(defvar helm-source-elscreen-history-list
- (helm-make-source "ElScreen History" 'helm-source-elscreen-history))
-
-;;;###autoload
-(defun helm-elscreen ()
- "Preconfigured helm to list elscreen."
- (interactive)
- (helm-other-buffer 'helm-source-elscreen-list "*Helm ElScreen*"))
-
-;;;###autoload
-(defun helm-elscreen-history ()
- "Preconfigured helm to list elscreen in history order."
- (interactive)
- (helm-other-buffer 'helm-source-elscreen-history-list "*Helm ElScreen*"))
-
-(provide 'helm-elscreen)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-elscreen.el ends here
+++ /dev/null
-;;; helm-eshell.el --- pcomplete and eshell completion for helm. -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Commentary:
-;;
-;; Enable like this in .emacs:
-;; (add-hook 'eshell-mode-hook
-;; (lambda ()
-;; (eshell-cmpl-initialize)
-;; (define-key eshell-mode-map [remap eshell-pcomplete] 'helm-esh-pcomplete)
-;; (define-key eshell-mode-map (kbd "M-p") 'helm-eshell-history)))
-
-
-;;; Code:
-(require 'cl-lib)
-(require 'helm)
-(require 'helm-lib)
-(require 'helm-help)
-(require 'helm-elisp)
-
-(declare-function eshell-read-aliases-list "em-alias")
-(declare-function eshell-send-input "esh-mode" (&optional use-region queue-p no-newline))
-(declare-function eshell-bol "esh-mode")
-(declare-function eshell-parse-arguments "esh-arg" (beg end))
-(declare-function eshell-backward-argument "esh-mode" (&optional arg))
-(declare-function helm-quote-whitespace "helm-lib")
-
-\f
-(defgroup helm-eshell nil
- "Helm eshell completion and history."
- :group 'helm)
-
-\f
-(defvar helm-eshell-history-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map helm-map)
- (define-key map (kbd "M-p") 'helm-next-line)
- map)
- "Keymap for `helm-eshell-history'.")
-
-(defvar helm-esh-completion-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map helm-map)
- (define-key map (kbd "TAB") 'helm-next-line)
- map)
- "Keymap for `helm-esh-pcomplete'.")
-
-\f
-(defclass helm-esh-source (helm-source-sync)
- ((init :initform (lambda ()
- (setq pcomplete-current-completions nil
- pcomplete-last-completion-raw nil)
- ;; Eshell-command add this hook in all minibuffers
- ;; Remove it for the helm one. (Fixed in Emacs24)
- (remove-hook 'minibuffer-setup-hook 'eshell-mode)))
- (candidates :initform 'helm-esh-get-candidates)
- (nomark :initform t)
- (persistent-action :initform 'ignore)
- (nohighlight :initform t)
- (filtered-candidate-transformer
- :initform
- (lambda (candidates _sources)
- (cl-loop
- for i in candidates
- collect
- (cond ((string-match "\\`~/?" helm-ec-target)
- (abbreviate-file-name i))
- ((string-match "\\`/" helm-ec-target) i)
- (t
- (file-relative-name i)))
- into lst
- finally return (sort lst 'helm-generic-sort-fn))))
- (action :initform 'helm-ec-insert))
- "Helm class to define source for Eshell completion.")
-
-;; Internal.
-(defvar helm-ec-target "")
-(defun helm-ec-insert (candidate)
- "Replace text at point with CANDIDATE.
-The function that call this should set `helm-ec-target' to thing at point."
- (let ((pt (point)))
- (when (and helm-ec-target
- (search-backward helm-ec-target nil t)
- (string= (buffer-substring (point) pt) helm-ec-target))
- (delete-region (point) pt)))
- (when (string-match "\\`\\*" helm-ec-target) (insert "*"))
- (cond ((string-match "\\`~/?" helm-ec-target)
- (insert (helm-quote-whitespace (abbreviate-file-name candidate))))
- ((string-match "\\`/" helm-ec-target)
- (insert (helm-quote-whitespace candidate)))
- (t
- (insert (concat (and (string-match "\\`[.]/" helm-ec-target) "./")
- (helm-quote-whitespace
- (file-relative-name candidate)))))))
-
-(defun helm-esh-get-candidates ()
- "Get candidates for eshell completion using `pcomplete'."
- (catch 'pcompleted
- (with-helm-current-buffer
- (let* ((pcomplete-stub)
- pcomplete-seen pcomplete-norm-func
- pcomplete-args pcomplete-last pcomplete-index
- (pcomplete-autolist pcomplete-autolist)
- (pcomplete-suffix-list pcomplete-suffix-list)
- (table (pcomplete-completions))
- (entry (or (try-completion helm-pattern
- (pcomplete-entries))
- helm-pattern)))
- (cl-loop ;; expand entry too to be able to compare it with file-cand.
- with exp-entry = (and (stringp entry)
- (not (string= entry ""))
- (file-name-as-directory
- (expand-file-name entry default-directory)))
- for i in (all-completions pcomplete-stub table)
- ;; Transform the related names to abs names.
- for file-cand = (and exp-entry
- (if (file-remote-p i) i
- (expand-file-name
- i (file-name-directory entry))))
- ;; Compare them to avoid dups.
- for file-entry-p = (and (stringp exp-entry)
- (stringp file-cand)
- ;; Fix :/tmp/foo/ $ cd foo
- (not (file-directory-p file-cand))
- (file-equal-p exp-entry file-cand))
- if (and file-cand (or (file-remote-p file-cand)
- (file-exists-p file-cand))
- (not file-entry-p))
- collect file-cand into ls
- else
- ;; Avoid adding entry here.
- unless file-entry-p collect i into ls
- finally return
- (if (and exp-entry
- (file-directory-p exp-entry)
- ;; If the car of completion list is
- ;; an executable, probably we are in
- ;; command completion, so don't add a
- ;; possible file related entry here.
- (and ls (not (executable-find (car ls))))
- ;; Don't add entry if already in prompt.
- (not (file-equal-p exp-entry pcomplete-stub)))
- (append (list exp-entry)
- ;; Entry should not be here now but double check.
- (remove entry ls))
- ls))))))
-\f
-;;; Eshell history.
-;;
-;;
-(defclass helm-eshell-history-source (helm-source-sync)
- ((init :initform
- (lambda ()
- ;; Same comment as in `helm-source-esh'.
- (remove-hook 'minibuffer-setup-hook 'eshell-mode)))
- (candidates
- :initform
- (lambda ()
- (with-helm-current-buffer
- (cl-loop for c from 0 to (ring-length eshell-history-ring)
- collect (eshell-get-history c)))))
- (nomark :initform t)
- (multiline :initform t)
- (keymap :initform helm-eshell-history-map)
- (candidate-number-limit :initform 9999)
- (action :initform (lambda (candidate)
- (eshell-kill-input)
- (insert candidate))))
- "Helm class to define source for Eshell history.")
-
-\f
-;;;###autoload
-(defun helm-esh-pcomplete ()
- "Preconfigured helm to provide helm completion in eshell."
- (interactive)
- (let* ((helm-quit-if-no-candidate t)
- (helm-execute-action-at-once-if-one t)
- (end (point-marker))
- (beg (save-excursion (eshell-bol) (point)))
- (args (catch 'eshell-incomplete
- (eshell-parse-arguments beg end)))
- (target
- (or (and (looking-back " " (1- (point))) " ")
- (buffer-substring-no-properties
- (save-excursion
- (eshell-backward-argument 1) (point))
- end)))
- (first (car args)) ; Maybe lisp delimiter "(".
- last ; Will be the last but parsed by pcomplete.
- del-space)
- (setq helm-ec-target (or target " ")
- end (point)
- ;; Reset beg for `with-helm-show-completion'.
- beg (or (and target (not (string= target " "))
- (- end (length target)))
- ;; Nothing at point.
- (progn (insert " ") (setq del-space t) (point))))
- (cond ((eq first ?\()
- (helm-lisp-completion-or-file-name-at-point))
- ;; In eshell `pcomplete-parse-arguments' is called
- ;; with `pcomplete-parse-arguments-function'
- ;; locally bound to `eshell-complete-parse-arguments'
- ;; which is calling `lisp-complete-symbol',
- ;; calling it before would popup the
- ;; *completions* buffer.
- (t (setq last (replace-regexp-in-string
- "\\`\\*" ""
- (car (last (ignore-errors
- (pcomplete-parse-arguments))))))
- (with-helm-show-completion beg end
- (or (helm :sources (helm-make-source "Eshell completions" 'helm-esh-source)
- :buffer "*helm pcomplete*"
- :keymap helm-esh-completion-map
- :resume 'noresume
- :input (and (stringp last)
- (helm-ff-set-pattern last)))
- (and del-space (looking-back "\\s-" (1- (point)))
- (delete-char -1))))))))
-
-;;;###autoload
-(defun helm-eshell-history ()
- "Preconfigured helm for eshell history."
- (interactive)
- (let* ((end (point))
- (beg (save-excursion (eshell-bol) (point)))
- (input (buffer-substring beg end))
- flag-empty)
- (when (eq beg end)
- (insert " ")
- (setq flag-empty t)
- (setq end (point)))
- (unwind-protect
- (with-helm-show-completion beg end
- (helm :sources (helm-make-source "Eshell history"
- 'helm-eshell-history-source)
- :buffer "*helm eshell history*"
- :resume 'noresume
- :input input))
- (when (and flag-empty
- (looking-back " " (1- (point))))
- (delete-char -1)))))
-
-(provide 'helm-eshell)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-eshell ends here
+++ /dev/null
-;;; helm-eval.el --- eval expressions from helm. -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Code:
-(require 'cl-lib)
-(require 'helm)
-(require 'helm-help)
-(require 'eldoc)
-(require 'edebug)
-
-\f
-(defgroup helm-eval nil
- "Eval related Applications and libraries for Helm."
- :group 'helm)
-
-(defcustom helm-eldoc-in-minibuffer-show-fn
- 'helm-show-info-in-mode-line
- "A function to display eldoc info.
-Should take one arg: the string to display."
- :group 'helm-eval
- :type 'symbol)
-
-(defcustom helm-show-info-in-mode-line-delay 12
- "Eldoc will show info in mode-line during this delay if user is idle."
- :type 'integer
- :group 'helm-eval)
-
-\f
-;;; Eldoc compatibility between emacs-24 and emacs-25
-;;
-(if (require 'elisp-mode nil t) ; emacs-25
- ;; Maybe the eldoc functions have been
- ;; already aliased by eldoc-eval.
- (cl-loop for (f . a) in '((eldoc-current-symbol .
- elisp--current-symbol)
- (eldoc-fnsym-in-current-sexp .
- elisp--fnsym-in-current-sexp)
- (eldoc-get-fnsym-args-string .
- elisp-get-fnsym-args-string)
- (eldoc-get-var-docstring .
- elisp-get-var-docstring))
- unless (fboundp f)
- do (defalias f a))
- ;; Emacs-24.
- (declare-function eldoc-current-symbol "eldoc")
- (declare-function eldoc-get-fnsym-args-string "eldoc" (sym &optional index))
- (declare-function eldoc-get-var-docstring "eldoc" (sym))
- (declare-function eldoc-fnsym-in-current-sexp "eldoc"))
-
-;;; Evaluation Result
-;;
-;;
-;; Internal
-(defvar helm-eldoc-active-minibuffers-list nil)
-
-(defvar helm-eval-expression-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map helm-map)
- (define-key map (kbd "<C-return>") 'helm-eval-new-line-and-indent)
- (define-key map (kbd "<M-tab>") 'lisp-indent-line)
- (define-key map (kbd "<C-tab>") 'helm-lisp-completion-at-point)
- (define-key map (kbd "C-p") 'previous-line)
- (define-key map (kbd "C-n") 'next-line)
- (define-key map (kbd "<up>") 'previous-line)
- (define-key map (kbd "<down>") 'next-line)
- (define-key map (kbd "<right>") 'forward-char)
- (define-key map (kbd "<left>") 'backward-char)
- map))
-
-(defun helm-build-evaluation-result-source ()
- (helm-build-dummy-source "Evaluation Result"
- :multiline t
- :mode-line "C-RET: nl-and-indent, M-tab: reindent, C-tab:complete, C-p/n: next/prec-line."
- :filtered-candidate-transformer (lambda (_candidates _source)
- (list
- (condition-case nil
- (with-helm-current-buffer
- (pp-to-string
- (if edebug-active
- (edebug-eval-expression
- (read helm-pattern))
- (eval (read helm-pattern)))))
- (error "Error"))))
- :nohighlight t
- :action '(("Copy result to kill-ring" . (lambda (candidate)
- (kill-new
- (replace-regexp-in-string
- "\n" "" candidate))
- (message "Result copied to kill-ring")))
- ("copy sexp to kill-ring" . (lambda (_candidate)
- (kill-new helm-input)
- (message "Sexp copied to kill-ring"))))))
-
-(defun helm-eval-new-line-and-indent ()
- (interactive)
- (newline) (lisp-indent-line))
-
-(defun helm-eldoc-store-minibuffer ()
- "Store minibuffer buffer name in `helm-eldoc-active-minibuffers-list'."
- (with-selected-window (minibuffer-window)
- (push (current-buffer) helm-eldoc-active-minibuffers-list)))
-
-(defun helm-eldoc-show-in-eval ()
- "Return eldoc in mode-line for current minibuffer input."
- (let ((buf (window-buffer (active-minibuffer-window))))
- (condition-case err
- (when (member buf helm-eldoc-active-minibuffers-list)
- (with-current-buffer buf
- (let* ((sym (save-excursion
- (unless (looking-back ")\\|\"" (1- (point)))
- (forward-char -1))
- (eldoc-current-symbol)))
- (info-fn (eldoc-fnsym-in-current-sexp))
- (doc (or (eldoc-get-var-docstring sym)
- (eldoc-get-fnsym-args-string
- (car info-fn) (cadr info-fn)))))
- (when doc (funcall helm-eldoc-in-minibuffer-show-fn doc)))))
- (error (message "Eldoc in minibuffer error: %S" err) nil))))
-
-(defun helm-show-info-in-mode-line (str)
- "Display string STR in mode-line."
- (save-selected-window
- (with-current-buffer helm-buffer
- (let ((mode-line-format (concat " " str)))
- (force-mode-line-update)
- (sit-for helm-show-info-in-mode-line-delay))
- (force-mode-line-update))))
-
-;;; Calculation Result
-;;
-;;
-(defvar helm-source-calculation-result
- (helm-build-dummy-source "Calculation Result"
- :filtered-candidate-transformer (lambda (_candidates _source)
- (list
- (condition-case nil
- (calc-eval helm-pattern)
- (error "error"))))
- :nohighlight t
- :action '(("Copy result to kill-ring" . (lambda (candidate)
- (kill-new candidate)
- (message "Result \"%s\" copied to kill-ring"
- candidate)))
- ("Copy operation to kill-ring" . (lambda (_candidate)
- (kill-new helm-input)
- (message "Calculation copied to kill-ring"))))))
-
-;;;###autoload
-(defun helm-eval-expression (arg)
- "Preconfigured helm for `helm-source-evaluation-result'."
- (interactive "P")
- (helm :sources (helm-build-evaluation-result-source)
- :input (when arg (thing-at-point 'sexp))
- :buffer "*helm eval*"
- :echo-input-in-header-line nil
- :history 'read-expression-history
- :keymap helm-eval-expression-map))
-
-(defvar eldoc-idle-delay)
-;;;###autoload
-(defun helm-eval-expression-with-eldoc ()
- "Preconfigured helm for `helm-source-evaluation-result' with `eldoc' support. "
- (interactive)
- (let ((timer (run-with-idle-timer
- eldoc-idle-delay 'repeat
- 'helm-eldoc-show-in-eval)))
- (unwind-protect
- (minibuffer-with-setup-hook
- 'helm-eldoc-store-minibuffer
- (call-interactively 'helm-eval-expression))
- (and timer (cancel-timer timer))
- (setq helm-eldoc-active-minibuffers-list
- (cdr helm-eldoc-active-minibuffers-list)))))
-
-;;;###autoload
-(defun helm-calcul-expression ()
- "Preconfigured helm for `helm-source-calculation-result'."
- (interactive)
- (helm :sources 'helm-source-calculation-result
- :buffer "*helm calcul*"))
-
-(provide 'helm-eval)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-eval.el ends here
+++ /dev/null
-;;; helm-external.el --- Run Externals commands within Emacs with helm completion. -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'helm)
-(require 'helm-help)
-(require 'helm-net)
-
-\f
-(defgroup helm-external nil
- "External related Applications and libraries for Helm."
- :group 'helm)
-
-(defcustom helm-raise-command nil
- "A shell command to jump to a window running specific program.
-Need external program wmctrl.
-This will be use with `format', so use something like \"wmctrl -xa %s\"."
- :type 'string
- :group 'helm-external)
-
-(defcustom helm-external-programs-associations nil
- "Alist to store externals programs associated with file extension.
-This variable overhide setting in .mailcap file.
-e.g : '\(\(\"jpg\" . \"gqview\"\) (\"pdf\" . \"xpdf\"\)\) "
- :type '(alist :key-type string :value-type string)
- :group 'helm-external)
-
-(defcustom helm-default-external-file-browser "nautilus"
- "Default external file browser for your system.
-Directories will be opened externally with it when
-opening file externally in `helm-find-files'.
-Set to nil if you do not have external file browser
-or do not want to use it.
-Windows users should set that to \"explorer.exe\"."
- :group 'helm-external
- :type 'string)
-
-\f
-;;; Internals
-(defvar helm-external-command-history nil)
-(defvar helm-external-commands-list nil
- "A list of all external commands the user can execute.
-If this variable is not set by the user, it will be calculated
-automatically.")
-
-(defun helm-external-commands-list-1 (&optional sort)
- "Returns a list of all external commands the user can execute.
-If `helm-external-commands-list' is non-nil it will
-return its contents. Else it calculates all external commands
-and sets `helm-external-commands-list'."
- (helm-aif helm-external-commands-list
- it
- (setq helm-external-commands-list
- (cl-loop
- for dir in (split-string (getenv "PATH") path-separator)
- when (and (file-exists-p dir) (file-accessible-directory-p dir))
- for lsdir = (cl-loop for i in (directory-files dir t)
- for bn = (file-name-nondirectory i)
- when (and (not (member bn completions))
- (not (file-directory-p i))
- (file-executable-p i))
- collect bn)
- append lsdir into completions
- finally return
- (if sort (sort completions 'string-lessp) completions)))))
-
-(defun helm-run-or-raise (exe &optional file)
- "Generic command that run asynchronously EXE.
-If EXE is already running just jump to his window if `helm-raise-command'
-is non--nil.
-When FILE argument is provided run EXE with FILE."
- (let* ((real-com (car (split-string exe)))
- (proc (if file (concat real-com " " file) real-com))
- process-connection-type)
- (if (get-process proc)
- (if helm-raise-command
- (shell-command (format helm-raise-command real-com))
- (error "Error: %s is already running" real-com))
- (when (member real-com helm-external-commands-list)
- (message "Starting %s..." real-com)
- (if file
- (start-process-shell-command
- proc nil (format "%s %s"
- real-com
- (shell-quote-argument
- (if (eq system-type 'windows-nt)
- (helm-w32-prepare-filename file)
- file))))
- (start-process-shell-command proc nil real-com))
- (set-process-sentinel
- (get-process proc)
- (lambda (process event)
- (when (and (string= event "finished\n")
- helm-raise-command
- (not (helm-get-pid-from-process-name real-com)))
- (shell-command (format helm-raise-command "emacs")))
- (message "%s process...Finished." process))))
- (setq helm-external-commands-list
- (cons real-com
- (delete real-com helm-external-commands-list))))))
-
-(defun helm-get-mailcap-for-file (filename)
- "Get the command to use for FILENAME from mailcap files."
- (mailcap-parse-mailcaps)
- (let* ((ext (file-name-extension filename))
- (mime (when ext (mailcap-extension-to-mime ext)))
- (result (when mime (mailcap-mime-info mime))))
- ;; If elisp file have no associations in .mailcap
- ;; `mailcap-maybe-eval' is returned, in this case just return nil.
- (when (stringp result) (helm-basename result))))
-
-(defun helm-get-default-program-for-file (filename)
- "Try to find a default program to open FILENAME.
-Try first in `helm-external-programs-associations' and then in mailcap file
-if nothing found return nil."
- (let* ((ext (file-name-extension filename))
- (def-prog (assoc-default ext helm-external-programs-associations)))
- (cond ((and def-prog (not (string= def-prog ""))) def-prog)
- ((and helm-default-external-file-browser (file-directory-p filename))
- helm-default-external-file-browser)
- (t (helm-get-mailcap-for-file filename)))))
-
-(defun helm-open-file-externally (file)
- "Open FILE with an external program.
-Try to guess which program to use with `helm-get-default-program-for-file'.
-If not found or a prefix arg is given query the user which tool to use."
- (let* ((fname (expand-file-name file))
- (collection (helm-external-commands-list-1 'sort))
- (def-prog (helm-get-default-program-for-file fname))
- (program (if (or helm-current-prefix-arg (not def-prog))
- ;; Prefix arg or no default program.
- (prog1
- (helm-comp-read
- "Program: " collection
- :must-match t
- :name "Open file Externally"
- :del-input nil
- :history helm-external-command-history)
- ;; Always prompt to set this program as default.
- (setq def-prog nil))
- ;; No prefix arg or default program exists.
- def-prog)))
- (unless (or def-prog ; Association exists, no need to record it.
- ;; Don't try to record non--filenames associations (e.g urls).
- (not (file-exists-p fname)))
- (when
- (y-or-n-p
- (format
- "Do you want to make `%s' the default program for this kind of files? "
- program))
- (helm-aif (assoc (file-name-extension fname)
- helm-external-programs-associations)
- (setq helm-external-programs-associations
- (delete it helm-external-programs-associations)))
- (push (cons (file-name-extension fname)
- (helm-read-string
- "Program (Add args maybe and confirm): " program))
- helm-external-programs-associations)
- (customize-save-variable 'helm-external-programs-associations
- helm-external-programs-associations)))
- (helm-run-or-raise program file)
- (setq helm-external-command-history
- (cons program
- (delete program
- (cl-loop for i in helm-external-command-history
- when (executable-find i) collect i))))))
-
-;;;###autoload
-(defun helm-run-external-command (program)
- "Preconfigured `helm' to run External PROGRAM asyncronously from Emacs.
-If program is already running exit with error.
-You can set your own list of commands with
-`helm-external-commands-list'."
- (interactive (list
- (helm-comp-read
- "RunProgram: "
- (helm-external-commands-list-1 'sort)
- :must-match t
- :del-input nil
- :name "External Commands"
- :history helm-external-command-history)))
- (helm-run-or-raise program)
- (setq helm-external-command-history
- (cons program (delete program
- (cl-loop for i in helm-external-command-history
- when (executable-find i) collect i)))))
-
-
-(provide 'helm-external)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-external ends here
+++ /dev/null
-;;; helm-files.el --- helm file browser and related. -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Code:
-\f
-(require 'cl-lib)
-(require 'helm)
-(require 'helm-types)
-(require 'helm-utils)
-(require 'helm-external)
-(require 'helm-grep)
-(require 'helm-help)
-(require 'helm-locate)
-(require 'helm-bookmark)
-(require 'helm-tags)
-(require 'helm-buffers)
-(require 'thingatpt)
-(require 'ffap)
-(require 'dired-aux)
-(require 'dired-x)
-(require 'tramp)
-(require 'image-dired)
-
-(declare-function find-library-name "find-func.el" (library))
-(declare-function w32-shell-execute "ext:w32fns.c" (operation document &optional parameters show-flag))
-(declare-function gnus-dired-attach "ext:gnus-dired.el" (files-to-attach))
-(declare-function image-dired-display-image "image-dired.el" (file &optional original-size))
-(declare-function image-dired-update-property "image-dired.el" (prop value))
-(declare-function eshell-read-aliases-list "em-alias")
-(declare-function eshell-send-input "esh-mode" (&optional use-region queue-p no-newline))
-(declare-function eshell-kill-input "esh-mode")
-(declare-function eshell-bol "esh-mode")
-(declare-function eshell-reset "esh-mode.el")
-(declare-function eshell/cd "em-dirs.el")
-(declare-function eshell-quote-argument "esh-arg.el")
-(declare-function helm-ls-git-ls "ext:helm-ls-git")
-(declare-function helm-hg-find-files-in-project "ext:helm-ls-hg")
-(declare-function helm-gid "helm-id-utils.el")
-(declare-function helm-ls-svn-ls "ext:helm-ls-svn")
-
-(defvar recentf-list)
-(defvar helm-mm-matching-method)
-(defvar dired-async-mode)
-
-\f
-(defgroup helm-files nil
- "Files applications and libraries for Helm."
- :group 'helm)
-
-(defcustom helm-boring-file-regexp-list
- (mapcar (lambda (f)
- (concat
- (rx-to-string
- (replace-regexp-in-string
- "/$" "" f) t) "$"))
- completion-ignored-extensions)
- "The regexp list matching boring files."
- :group 'helm-files
- :type '(repeat (choice regexp)))
-
-(defcustom helm-for-files-preferred-list
- '(helm-source-buffers-list
- helm-source-recentf
- helm-source-bookmarks
- helm-source-file-cache
- helm-source-files-in-current-dir
- helm-source-locate)
- "Your preferred sources to find files."
- :type '(repeat (choice symbol))
- :group 'helm-files)
-
-(defcustom helm-tramp-verbose 0
- "Just like `tramp-verbose' but specific to helm.
-When set to 0 don't show tramp messages in helm.
-If you want to have the default tramp messages set it to 3."
- :type 'integer
- :group 'helm-files)
-
-(defcustom helm-ff-auto-update-initial-value nil
- "Auto update when only one candidate directory is matched.
-Default value when starting `helm-find-files' is nil because
-it prevent using <backspace> to delete char backward and by the way
-confuse beginners.
-For a better experience with `helm-find-files' set this to non--nil
-and use C-<backspace> to toggle it."
- :group 'helm-files
- :type 'boolean)
-
-(defcustom helm-ff-lynx-style-map t
- "Use arrow keys to navigate with `helm-find-files'.
-You will have to restart Emacs or reeval `helm-find-files-map'
-and `helm-read-file-map' for this take effect."
- :group 'helm-files
- :type 'boolean)
-
-(defcustom helm-ff-history-max-length 100
- "Number of elements shown in `helm-find-files' history."
- :group 'helm-files
- :type 'integer)
-
-(defcustom helm-ff-fuzzy-matching t
- "Enable fuzzy matching for `helm-find-files' when non--nil.
-See `helm-ff--transform-pattern-for-completion' for more info."
- :group 'helm-files
- :type 'boolean)
-
-(defcustom helm-ff-tramp-not-fancy t
- "No colors when listing remote files when set to non--nil.
-This make listing much faster, specially on slow machines."
- :group 'helm-files
- :type 'boolean)
-
-(defcustom helm-ff-exif-data-program "exiftran"
- "Program used to extract exif data of an image file."
- :group 'helm-files
- :type 'string)
-
-(defcustom helm-ff-exif-data-program-args "-d"
- "Arguments used for `helm-ff-exif-data-program'."
- :group 'helm-files
- :type 'string)
-
-(defcustom helm-ff-newfile-prompt-p t
- "Whether Prompt or not when creating new file.
-This set `ffap-newfile-prompt'."
- :type 'boolean
- :group 'helm-files)
-
-(defcustom helm-ff-avfs-directory "~/.avfs"
- "The default avfs directory, usually '~/.avfs'.
-When this is set you will be able to expand archive filenames with `C-j'
-inside an avfs directory mounted with mountavfs.
-See <http://sourceforge.net/projects/avf/>."
- :type 'string
- :group 'helm-files)
-
-(defcustom helm-ff-file-compressed-list '("gz" "bz2" "zip" "7z")
- "Minimal list of compressed files extension."
- :type '(repeat (choice string))
- :group 'helm-files)
-
-(defcustom helm-ff-printer-list nil
- "A list of available printers on your system.
-When non--nil let you choose a printer to print file.
-Otherwise when nil the variable `printer-name' will be used.
-On Unix based systems (lpstat command needed) you don't need to set this,
-`helm-ff-find-printers' will find a list of available printers for you."
- :type '(repeat (choice string))
- :group 'helm-files)
-
-(defcustom helm-ff-transformer-show-only-basename t
- "Show only basename of candidates in `helm-find-files'.
-This can be toggled at anytime from `helm-find-files' with \
-\\<helm-find-files-map>\\[helm-ff-run-toggle-basename]."
- :type 'boolean
- :group 'helm-files)
-
-(defcustom helm-ff-signal-error-on-dot-files t
- "Signal error when file is `.' or `..' on file deletion when non--nil.
-Default is non--nil.
-WARNING: Setting this to nil is unsafe and can cause deletion of a whole tree."
- :group 'helm-files
- :type 'boolean)
-
-(defcustom helm-ff-search-library-in-sexp nil
- "Search for library in `require' and `declare-function' sexp."
- :group 'helm-files
- :type 'boolean)
-
-(defcustom helm-tooltip-hide-delay 25
- "Hide tooltips automatically after this many seconds."
- :group 'helm-files
- :type 'integer)
-
-(defcustom helm-ff-file-name-history-use-recentf nil
- "Use `recentf-list' instead of `file-name-history' in `helm-find-files'."
- :group 'helm-files
- :type 'boolean)
-
-(defcustom helm-ff-skip-boring-files nil
- "Non--nil to skip files matching regexps in `helm-boring-file-regexp-list'.
-This take effect in `helm-find-files' and file completion used by `helm-mode'
-i.e `helm-read-file-name'."
- :group 'helm-files
- :type 'boolean)
-
-(defcustom helm-ff-candidate-number-limit 5000
- "The `helm-candidate-number-limit' for `helm-find-files', `read-file-name' and friends."
- :group 'helm-files
- :type 'integer)
-
-(defcustom helm-findutils-skip-boring-files t
- "Ignore files matching regexps in `completion-ignored-extensions'."
- :group 'helm-files
- :type 'boolean)
-
-(defcustom helm-findutils-search-full-path nil
- "Search in full path with shell command find when non--nil.
-I.e use the -path/ipath arguments of find instead of -name/iname."
- :group 'helm-files
- :type 'boolean)
-
-(defcustom helm-files-save-history-extra-sources
- '("Find" "Locate" "Recentf"
- "Files from Current Directory" "File Cache")
- "Extras source that save candidate to `file-name-history'."
- :group 'helm-files
- :type '(repeat (choice string)))
-
-(defcustom helm-find-files-before-init-hook nil
- "Hook that run before initialization of `helm-find-files'."
- :group 'helm-files
- :type 'hook)
-
-(defcustom helm-find-files-after-init-hook nil
- "Hook that run after initialization of `helm-find-files'."
- :group 'helm-files
- :type 'hook)
-
-(defcustom helm-multi-files-toggle-locate-binding "C-c p"
- "Default binding to switch back and forth locate in `helm-multi-files'."
- :group 'helm-files
- :type 'string)
-
-(defcustom helm-find-files-bookmark-prefix "Helm-find-files: "
- "bookmark name prefix of `helm-find-files' sessions."
- :group 'helm-files
- :type 'string)
-
-(defcustom helm-ff-guess-ffap-filenames nil
- "Use ffap to guess local filenames at point in `helm-find-files'.
-This doesn't disable url or mail at point, see
-`helm-ff-guess-ffap-urls' for this."
- :group 'helm-files
- :type 'boolean)
-
-(defcustom helm-ff-guess-ffap-urls t
- "Use ffap to guess local urls at point in `helm-find-files'.
-This doesn't disable guessing filenames at point,
-see `helm-ff-guess-ffap-filenames' for this."
- :group 'helm-files
- :type 'boolean)
-
-(defcustom helm-ff-no-preselect nil
- "When non--nil `helm-find-files' starts at root of current directory."
- :group 'helm-files
- :type 'boolean)
-
-(defcustom helm-substitute-in-filename-stay-on-remote nil
- "Don't switch back to local filesystem when expanding pattern with / or ~/."
- :group 'helm-files
- :type 'boolean)
-
-\f
-;;; Faces
-;;
-;;
-(defgroup helm-files-faces nil
- "Customize the appearance of helm-files."
- :prefix "helm-"
- :group 'helm-files
- :group 'helm-faces)
-
-(defface helm-ff-prefix
- '((t (:background "yellow" :foreground "black")))
- "Face used to prefix new file or url paths in `helm-find-files'."
- :group 'helm-files-faces)
-
-(defface helm-ff-executable
- '((t (:foreground "green")))
- "Face used for executable files in `helm-find-files'."
- :group 'helm-files-faces)
-
-(defface helm-ff-directory
- '((t (:foreground "DarkRed" :background "LightGray")))
- "Face used for directories in `helm-find-files'."
- :group 'helm-files-faces)
-
-(defface helm-ff-dotted-directory
- '((t (:foreground "black" :background "DimGray")))
- "Face used for dotted directories in `helm-find-files'."
- :group 'helm-files-faces)
-
-(defface helm-ff-dotted-symlink-directory
- '((t (:foreground "DarkOrange" :background "DimGray")))
- "Face used for dotted symlinked directories in `helm-find-files'."
- :group 'helm-files-faces)
-
-(defface helm-ff-symlink
- '((t (:foreground "DarkOrange")))
- "Face used for symlinks in `helm-find-files'."
- :group 'helm-files-faces)
-
-(defface helm-ff-invalid-symlink
- '((t (:foreground "black" :background "red")))
- "Face used for invalid symlinks in `helm-find-files'."
- :group 'helm-files-faces)
-
-(defface helm-ff-file
- '((t (:inherit font-lock-builtin-face)))
- "Face used for file names in `helm-find-files'."
- :group 'helm-files-faces)
-
-(defface helm-history-deleted
- '((t (:inherit helm-ff-invalid-symlink)))
- "Face used for deleted files in `file-name-history'."
- :group 'helm-files-faces)
-
-(defface helm-history-remote
- '((t (:foreground "Indianred1")))
- "Face used for remote files in `file-name-history'."
- :group 'helm-files-faces)
-
-\f
-;;; Helm-find-files - The helm file browser.
-;;
-;; Keymaps
-(defvar helm-find-files-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map helm-map)
- (define-key map (kbd "C-]") 'helm-ff-run-toggle-basename)
- (define-key map (kbd "C-x C-f") 'helm-ff-run-locate)
- (define-key map (kbd "C-x C-d") 'helm-ff-run-browse-project)
- (define-key map (kbd "C-x r m") 'helm-ff-bookmark-set)
- (define-key map (kbd "C-x r b") 'helm-find-files-toggle-to-bookmark)
- (define-key map (kbd "C-s") 'helm-ff-run-grep)
- (define-key map (kbd "M-g s") 'helm-ff-run-grep)
- (define-key map (kbd "M-g p") 'helm-ff-run-pdfgrep)
- (define-key map (kbd "M-g z") 'helm-ff-run-zgrep)
- (define-key map (kbd "M-g a") 'helm-ff-run-grep-ag)
- (define-key map (kbd "M-g g") 'helm-ff-run-git-grep)
- (define-key map (kbd "M-g i") 'helm-ff-run-gid)
- (define-key map (kbd "M-.") 'helm-ff-run-etags)
- (define-key map (kbd "M-R") 'helm-ff-run-rename-file)
- (define-key map (kbd "M-C") 'helm-ff-run-copy-file)
- (define-key map (kbd "M-B") 'helm-ff-run-byte-compile-file)
- (define-key map (kbd "M-L") 'helm-ff-run-load-file)
- (define-key map (kbd "M-S") 'helm-ff-run-symlink-file)
- (define-key map (kbd "M-H") 'helm-ff-run-hardlink-file)
- (define-key map (kbd "M-D") 'helm-ff-run-delete-file)
- (define-key map (kbd "M-K") 'helm-ff-run-kill-buffer-persistent)
- (define-key map (kbd "C-c d") 'helm-ff-persistent-delete)
- (define-key map (kbd "M-e") 'helm-ff-run-switch-to-eshell)
- (define-key map (kbd "C-c i") 'helm-ff-run-complete-fn-at-point)
- (define-key map (kbd "C-c o") 'helm-ff-run-switch-other-window)
- (define-key map (kbd "C-c C-o") 'helm-ff-run-switch-other-frame)
- (define-key map (kbd "C-c C-x") 'helm-ff-run-open-file-externally)
- (define-key map (kbd "C-c X") 'helm-ff-run-open-file-with-default-tool)
- (define-key map (kbd "M-!") 'helm-ff-run-eshell-command-on-file)
- (define-key map (kbd "M-%") 'helm-ff-run-query-replace-on-marked)
- (define-key map (kbd "C-c =") 'helm-ff-run-ediff-file)
- (define-key map (kbd "M-=") 'helm-ff-run-ediff-merge-file)
- (define-key map (kbd "M-p") 'helm-ff-run-switch-to-history)
- (define-key map (kbd "C-c h") 'helm-ff-file-name-history)
- (define-key map (kbd "M-i") 'helm-ff-properties-persistent)
- (define-key map (kbd "C-}") 'helm-narrow-window)
- (define-key map (kbd "C-{") 'helm-enlarge-window)
- (define-key map (kbd "C-<backspace>") 'helm-ff-run-toggle-auto-update)
- (define-key map (kbd "C-c <DEL>") 'helm-ff-run-toggle-auto-update)
- (define-key map (kbd "C-c C-a") 'helm-ff-run-gnus-attach-files)
- (define-key map (kbd "C-c p") 'helm-ff-run-print-file)
- (define-key map (kbd "C-c /") 'helm-ff-run-find-sh-command)
- ;; Next 2 have no effect if candidate is not an image file.
- (define-key map (kbd "M-l") 'helm-ff-rotate-left-persistent)
- (define-key map (kbd "M-r") 'helm-ff-rotate-right-persistent)
- (define-key map (kbd "C-l") 'helm-find-files-up-one-level)
- (define-key map (kbd "C-r") 'helm-find-files-down-last-level)
- (define-key map (kbd "C-c r") 'helm-ff-run-find-file-as-root)
- (define-key map (kbd "C-x C-v") 'helm-ff-run-find-alternate-file)
- (define-key map (kbd "C-c @") 'helm-ff-run-insert-org-link)
- (helm-define-key-with-subkeys map (kbd "DEL") ?\d 'helm-ff-delete-char-backward
- nil nil 'helm-ff-delete-char-backward--exit-fn)
- (when helm-ff-lynx-style-map
- (define-key map (kbd "<left>") 'helm-find-files-up-one-level)
- (define-key map (kbd "<right>") 'helm-execute-persistent-action))
- (delq nil map))
- "Keymap for `helm-find-files'.")
-
-(defvar helm-read-file-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map helm-map)
- (define-key map (kbd "<C-return>") 'helm-cr-empty-string)
- (define-key map (kbd "<M-RET>") 'helm-cr-empty-string)
- (define-key map (kbd "C-]") 'helm-ff-run-toggle-basename)
- (define-key map (kbd "C-.") 'helm-find-files-up-one-level)
- (define-key map (kbd "C-l") 'helm-find-files-up-one-level)
- (define-key map (kbd "C-r") 'helm-find-files-down-last-level)
- (define-key map (kbd "C-c h") 'helm-ff-file-name-history)
- (define-key map (kbd "C-<backspace>") 'helm-ff-run-toggle-auto-update)
- (define-key map (kbd "C-c <DEL>") 'helm-ff-run-toggle-auto-update)
- (helm-define-key-with-subkeys map (kbd "DEL") ?\d 'helm-ff-delete-char-backward
- nil nil 'helm-ff-delete-char-backward--exit-fn)
- (when helm-ff-lynx-style-map
- (define-key map (kbd "<left>") 'helm-find-files-up-one-level)
- (define-key map (kbd "<right>") 'helm-execute-persistent-action)
- (define-key map (kbd "<M-left>") 'helm-previous-source)
- (define-key map (kbd "<M-right>") 'helm-next-source))
- (delq nil map))
- "Keymap for `helm-read-file-name'.")
-
-\f
-;; Internal.
-(defvar helm-find-files-doc-header " (\\<helm-find-files-map>\\[helm-find-files-up-one-level]: Go up one level)"
- "*The doc that is inserted in the Name header of a find-files or dired source.")
-(defvar helm-ff-auto-update-flag nil
- "Internal, flag to turn on/off auto-update in `helm-find-files'.
-Don't set it directly, use instead `helm-ff-auto-update-initial-value'.")
-(defvar helm-ff-last-expanded nil
- "Store last expanded directory or file.")
-(defvar helm-ff-default-directory nil)
-(defvar helm-ff-history nil)
-(defvar helm-ff-cand-to-mark nil)
-(defvar helm-ff-url-regexp
- "\\`\\(news\\(post\\)?:\\|nntp:\\|mailto:\\|file:\\|\\(ftp\\|https?\\|telnet\\|gopher\\|www\\|wais\\):/?/?\\).*"
- "Same as `ffap-url-regexp' but match earlier possible url.")
-(defvar helm-tramp-file-name-regexp "\\`/\\([^[/:]+\\|[^/]+]\\):")
-(defvar helm-marked-buffer-name "*helm marked*")
-(defvar helm-ff--auto-update-state nil)
-(defvar helm-ff--deleting-char-backward nil)
-(defvar helm-multi-files--toggle-locate nil)
-(defvar helm-ff--move-to-first-real-candidate t)
-(defvar helm-find-files--toggle-bookmark nil)
-
-\f
-;;; Helm-find-files
-;;
-;;
-(defcustom helm-find-files-actions
- (helm-make-actions
- "Find File" 'helm-find-file-or-marked
- "Find file in Dired" 'helm-point-file-in-dired
- (lambda () (and (locate-library "elscreen") "Find file in Elscreen"))
- 'helm-elscreen-find-file
- "View file" 'view-file
- "Checksum File" 'helm-ff-checksum
- "Query replace fnames on marked" 'helm-ff-query-replace-on-marked
- "Query replace contents on marked" 'helm-ff-query-replace
- "Query replace regexp contents on marked" 'helm-ff-query-replace-regexp
- "Serial rename files" 'helm-ff-serial-rename
- "Serial rename by symlinking files" 'helm-ff-serial-rename-by-symlink
- "Serial rename by copying files" 'helm-ff-serial-rename-by-copying
- "Open file with default tool" 'helm-open-file-with-default-tool
- "Find file in hex dump" 'hexl-find-file
- "Browse project" 'helm-ff-browse-project
- "Complete at point `C-c i'" 'helm-insert-file-name-completion-at-point
- "Insert as org link `C-c @'" 'helm-files-insert-as-org-link
- "Find shell command `C-c /'" 'helm-ff-find-sh-command
- "Add marked files to file-cache" 'helm-ff-cache-add-file
- "Open file externally `C-c C-x, C-u to choose'" 'helm-open-file-externally
- "Grep File(s) `C-s, C-u Recurse'" 'helm-find-files-grep
- "Grep current directory with AG" 'helm-find-files-ag
- "Git grep" 'helm-ff-git-grep
- "Zgrep File(s) `M-g z, C-u Recurse'" 'helm-ff-zgrep
- "Gid" 'helm-ff-gid
- "Switch to Eshell `M-e'" 'helm-ff-switch-to-eshell
- "Etags `M-., C-u reload tag file'" 'helm-ff-etags-select
- "Eshell command on file(s) `M-!, C-u take all marked as arguments.'"
- 'helm-find-files-eshell-command-on-file
- "Find file as root `C-c r'" 'helm-find-file-as-root
- "Find alternate file" 'find-alternate-file
- "Ediff File `C-c ='" 'helm-find-files-ediff-files
- "Ediff Merge File `M-='" 'helm-find-files-ediff-merge-files
- "Delete File(s) `M-D'" 'helm-delete-marked-files
- "Copy file(s) `M-C, C-u to follow'" 'helm-find-files-copy
- "Rename file(s) `M-R, C-u to follow'" 'helm-find-files-rename
- "Backup files" 'helm-find-files-backup
- "Symlink files(s) `M-S, C-u to follow'" 'helm-find-files-symlink
- "Relsymlink file(s) `C-u to follow'" 'helm-find-files-relsymlink
- "Hardlink file(s) `M-H, C-u to follow'" 'helm-find-files-hardlink
- "Find file other window `C-c o'" 'helm-find-files-other-window
- "Switch to history `M-p'" 'helm-find-files-switch-to-hist
- "Find file other frame `C-c C-o'" 'find-file-other-frame
- "Print File `C-c p, C-u to refresh'" 'helm-ff-print
- "Locate `C-x C-f, C-u to specify locate db'" 'helm-ff-locate)
- "Actions for `helm-find-files'."
- :group 'helm-files
- :type '(alist :key-type string :value-type function))
-
-(defvar helm-source-find-files nil
- "The main source to browse files.
-Should not be used among other sources.")
-
-(defclass helm-source-ffiles (helm-source-sync)
- ((header-name
- :initform (lambda (name)
- (concat name (substitute-command-keys
- helm-find-files-doc-header))))
- (init
- :initform (lambda ()
- (setq helm-ff-auto-update-flag
- helm-ff-auto-update-initial-value)
- (setq helm-ff--auto-update-state
- helm-ff-auto-update-flag)
- (helm-set-local-variable 'bookmark-make-record-function
- #'helm-ff-make-bookmark-record)))
- (candidates :initform 'helm-find-files-get-candidates)
- (filtered-candidate-transformer :initform 'helm-ff-sort-candidates)
- (filter-one-by-one :initform 'helm-ff-filter-candidate-one-by-one)
- (persistent-action :initform 'helm-find-files-persistent-action)
- (persistent-help :initform "Hit1 Expand Candidate, Hit2 or (C-u) Find file")
- (help-message :initform 'helm-ff-help-message)
- (mode-line :initform (list "File(s)" helm-mode-line-string))
- (volatile :initform t)
- (cleanup :initform 'helm-find-files-cleanup)
- (migemo :initform t)
- (nohighlight :initform t)
- (keymap :initform helm-find-files-map)
- (candidate-number-limit :initform 'helm-ff-candidate-number-limit)
- (action-transformer
- :initform 'helm-find-files-action-transformer)
- (action :initform 'helm-find-files-actions)
- (before-init-hook :initform 'helm-find-files-before-init-hook)
- (after-init-hook :initform 'helm-find-files-after-init-hook)))
-
-;; Bookmark handlers.
-;;
-(defun helm-ff-make-bookmark-record ()
- "The `bookmark-make-record-function' for `helm-find-files'."
- (with-helm-buffer
- `((filename . ,helm-ff-default-directory)
- (presel . ,(helm-get-selection))
- (handler . helm-ff-bookmark-jump))))
-
-(defun helm-ff-bookmark-jump (bookmark)
- "bookmark handler for `helm-find-files'."
- (let ((fname (bookmark-prop-get bookmark 'filename))
- (presel (bookmark-prop-get bookmark 'presel)))
- (helm-find-files-1 fname (if helm-ff-transformer-show-only-basename
- (helm-basename presel)
- presel))))
-
-(defun helm-ff-bookmark-set ()
- "Record `helm-find-files' session in bookmarks."
- (interactive)
- (with-helm-alive-p
- (with-helm-buffer
- (bookmark-set
- (concat helm-find-files-bookmark-prefix
- (abbreviate-file-name helm-ff-default-directory))))
- (message "Helm find files session bookmarked! ")))
-(put 'helm-ff-bookmark-set 'helm-only t)
-
-(defun helm-dwim-target-directory ()
- "Return value of `default-directory' of buffer in other window.
-If there is only one window return the value of currently visited directory
-if found in `helm-ff-history' or fallback to `default-directory'
-of current buffer."
- (with-helm-current-buffer
- (let ((num-windows (length (remove (get-buffer-window helm-marked-buffer-name)
- (window-list)))))
- (expand-file-name
- (if (> num-windows 1)
- (save-selected-window
- (other-window 1)
- default-directory)
- ;; Using the car of *ff-history allow
- ;; staying in the directory visited instead of current.
- (or (car-safe helm-ff-history) default-directory))))))
-
-(defun helm-ff--count-and-collect-dups (files)
- (cl-loop with dups = (make-hash-table :test 'equal)
- for f in files
- for file = (if (file-directory-p f)
- (concat (helm-basename f) "/")
- (helm-basename f))
- for count = (gethash file dups)
- if count do (puthash file (1+ count) dups)
- else do (puthash file 1 dups)
- finally return (cl-loop for k being the hash-keys in dups
- using (hash-value v)
- if (> v 1)
- collect (format "%s(%s)" k v)
- else
- collect k)))
-
-(defun helm-find-files-do-action (action)
- "Generic function for creating actions from `helm-source-find-files'.
-ACTION must be an action supported by `helm-dired-action'."
- (let* ((ifiles (mapcar 'expand-file-name ; Allow modify '/foo/.' -> '/foo'
- (helm-marked-candidates :with-wildcard t)))
- (cand (helm-get-selection)) ; Target
- (prompt (format "%s %s file(s) to: "
- (capitalize (symbol-name action))
- (length ifiles)))
- helm-ff--move-to-first-real-candidate
- (parg helm-current-prefix-arg)
- helm-display-source-at-screen-top ; prevent setting window-start.
- helm-ff-auto-update-initial-value
- (dest (with-helm-display-marked-candidates
- helm-marked-buffer-name
- (helm-ff--count-and-collect-dups ifiles)
- (with-helm-current-buffer
- (helm-read-file-name
- prompt
- :preselect (unless (cdr ifiles)
- (if helm-ff-transformer-show-only-basename
- (helm-basename cand) cand))
- :initial-input (helm-dwim-target-directory)
- :history (helm-find-files-history :comp-read nil))))))
- (helm-dired-action
- dest :files ifiles :action action :follow parg)))
-
-(defun helm-find-files-copy (_candidate)
- "Copy files from `helm-find-files'."
- (helm-find-files-do-action 'copy))
-
-(defun helm-find-files-backup (_candidate)
- "Backup files from `helm-find-files'.
-This reproduce the behavior of \"cp --backup=numbered from to\"."
- (cl-assert (and (fboundp 'dired-async-mode) dired-async-mode) nil
- "Backup only available when `dired-async-mode' is enabled")
- (helm-find-files-do-action 'backup))
-
-(defun helm-find-files-rename (_candidate)
- "Rename files from `helm-find-files'."
- (helm-find-files-do-action 'rename))
-
-(defun helm-find-files-symlink (_candidate)
- "Symlink files from `helm-find-files'."
- (helm-find-files-do-action 'symlink))
-
-(defun helm-find-files-relsymlink (_candidate)
- "Relsymlink files from `helm-find-files'."
- (helm-find-files-do-action 'relsymlink))
-
-(defun helm-find-files-hardlink (_candidate)
- "Hardlink files from `helm-find-files'."
- (helm-find-files-do-action 'hardlink))
-
-(defun helm-find-files-other-window (_candidate)
- "Keep current-buffer and open files in separate windows."
- (let* ((files (helm-marked-candidates))
- (buffers (mapcar 'find-file-noselect files)))
- (switch-to-buffer-other-window (car buffers))
- (helm-aif (cdr buffers)
- (save-selected-window
- (cl-loop for buffer in it
- do (progn
- (select-window (split-window))
- (switch-to-buffer buffer)))))))
-
-(defun helm-find-files-byte-compile (_candidate)
- "Byte compile elisp files from `helm-find-files'."
- (let ((files (helm-marked-candidates :with-wildcard t))
- (parg helm-current-prefix-arg))
- (cl-loop for fname in files
- do (byte-compile-file fname parg))))
-
-(defun helm-find-files-load-files (_candidate)
- "Load elisp files from `helm-find-files'."
- (let ((files (helm-marked-candidates :with-wildcard t)))
- (cl-loop for fname in files
- do (load fname))))
-
-(defun helm-find-files-ediff-files-1 (candidate &optional merge)
- "Generic function to ediff/merge files in `helm-find-files'."
- (let* ((bname (helm-basename candidate))
- (marked (helm-marked-candidates :with-wildcard t))
- (prompt (if merge "Ediff Merge `%s' With File: "
- "Ediff `%s' With File: "))
- (fun (if merge 'ediff-merge-files 'ediff-files))
- (input (helm-dwim-target-directory))
- (presel (if helm-ff-transformer-show-only-basename
- (helm-basename candidate)
- (expand-file-name
- (helm-basename candidate)
- input))))
- (if (= (length marked) 2)
- (funcall fun (car marked) (cadr marked))
- (funcall fun candidate (helm-read-file-name
- (format prompt bname)
- :initial-input input
- :preselect presel)))))
-
-(defun helm-find-files-ediff-files (candidate)
- (helm-find-files-ediff-files-1 candidate))
-
-(defun helm-find-files-ediff-merge-files (candidate)
- (helm-find-files-ediff-files-1 candidate 'merge))
-
-(defun helm-find-files-grep (_candidate)
- "Default action to grep files from `helm-find-files'."
- (helm-do-grep-1 (helm-marked-candidates :with-wildcard t)
- helm-current-prefix-arg))
-
-(defun helm-ff-git-grep (_candidate)
- "Default action to git-grep `helm-ff-default-directory'."
- (helm-grep-git-1 helm-ff-default-directory helm-current-prefix-arg))
-
-(defun helm-find-files-ag (_candidate)
- (helm-grep-ag helm-ff-default-directory
- helm-current-prefix-arg))
-
-(defun helm-ff-zgrep (_candidate)
- "Default action to zgrep files from `helm-find-files'."
- (helm-ff-zgrep-1 (helm-marked-candidates :with-wildcard t) helm-current-prefix-arg))
-
-(defun helm-ff-pdfgrep (_candidate)
- "Default action to pdfgrep files from `helm-find-files'."
- (let ((cands (cl-loop for file in (helm-marked-candidates :with-wildcard t)
- if (or (string= (file-name-extension file) "pdf")
- (string= (file-name-extension file) "PDF"))
- collect file))
- (helm-pdfgrep-default-function 'helm-pdfgrep-init))
- (when cands
- (helm-do-pdfgrep-1 cands))))
-
-(defun helm-ff-etags-select (candidate)
- "Default action to jump to etags from `helm-find-files'."
- (when (get-buffer helm-action-buffer)
- (kill-buffer helm-action-buffer))
- (let* ((source-name (assoc-default 'name (helm-get-current-source)))
- (default-directory (if (string= source-name "Find Files")
- helm-ff-default-directory
- (file-name-directory candidate))))
- (helm-etags-select helm-current-prefix-arg)))
-
-(defun helm-find-files-switch-to-hist (_candidate)
- "Switch to helm-find-files history."
- (helm-find-files t))
-
-(defvar eshell-command-aliases-list nil)
-(defvar helm-eshell-command-on-file-input-history nil)
-(defun helm-find-files-eshell-command-on-file-1 (&optional map)
- "Run `eshell-command' on CANDIDATE or marked candidates.
-This is done possibly with an eshell alias, if no alias found, you can type in
-an eshell command.
-
-Basename of CANDIDATE can be a wild-card.
-e.g you can do \"eshell-command command *.el\"
-Where \"*.el\" is the CANDIDATE.
-
-It is possible to do eshell-command command <CANDIDATE> <some more args>
-like this: \"command %s some more args\".
-
-If MAP is given run `eshell-command' on all marked files at once,
-Otherwise, run `eshell-command' on each marked files.
-In other terms, with a prefix arg do on the three marked files
-\"foo\" \"bar\" \"baz\":
-
-\"eshell-command command foo bar baz\"
-
-otherwise do
-
-\"eshell-command command foo\"
-\"eshell-command command bar\"
-\"eshell-command command baz\"
-
-Note:
-If `eshell' or `eshell-command' have not been run once,
-or if you have no eshell aliases `eshell-command-aliases-list'
-will not be loaded first time you use this."
- (when (or eshell-command-aliases-list
- (y-or-n-p "Eshell is not loaded, run eshell-command without alias anyway? "))
- (and eshell-command-aliases-list (eshell-read-aliases-list))
- (let* ((cand-list (helm-marked-candidates))
- (default-directory (or helm-ff-default-directory
- ;; If candidate is an url *-ff-default-directory is nil
- ;; so keep value of default-directory.
- default-directory))
- (command (helm-comp-read
- "Command: "
- (cl-loop for (a . c) in eshell-command-aliases-list
- when (string-match "\\(\\$1\\|\\$\\*\\)$" (car c))
- collect (propertize a 'help-echo (car c)) into ls
- finally return (sort ls 'string<))
- :buffer "*helm eshell on file*"
- :name "Eshell command"
- :mode-line
- '("Eshell alias"
- "C-h m: Help, \\[universal-argument]: Insert output at point")
- :help-message 'helm-esh-help-message
- :input-history
- 'helm-eshell-command-on-file-input-history))
- (alias-value (car (assoc-default command eshell-command-aliases-list)))
- cmd-line)
- (if (or (equal helm-current-prefix-arg '(16))
- (equal map '(16)))
- ;; Two time C-u from `helm-comp-read' mean print to current-buffer.
- ;; i.e `eshell-command' will use this value.
- (setq current-prefix-arg '(16))
- ;; Else reset the value of `current-prefix-arg'
- ;; to avoid printing in current-buffer.
- (setq current-prefix-arg nil))
- (if (and (or
- ;; One prefix-arg have been passed before `helm-comp-read'.
- ;; If map have been set with C-u C-u (value == '(16))
- ;; ignore it.
- (and map (equal map '(4)))
- ;; One C-u from `helm-comp-read'.
- (equal helm-current-prefix-arg '(4))
- ;; An alias that finish with $*
- (and alias-value
- ;; If command is an alias be sure it accept
- ;; more than one arg i.e $*.
- (string-match "\\$\\*$" alias-value)))
- (cdr cand-list))
-
- ;; Run eshell-command with ALL marked files as arguments.
- ;; This wont work on remote files, because tramp handlers depends
- ;; on `default-directory' (limitation).
- (let ((mapfiles (mapconcat 'eshell-quote-argument cand-list " ")))
- (if (string-match "'%s'\\|\"%s\"\\|%s" command)
- (setq cmd-line (format command mapfiles)) ; See [1]
- (setq cmd-line (format "%s %s" command mapfiles)))
- (helm-log "%S" cmd-line)
- (eshell-command cmd-line))
-
- ;; Run eshell-command on EACH marked files.
- ;; To work with tramp handler we have to call
- ;; COMMAND on basename of each file, using
- ;; its basedir as `default-directory'.
- (cl-loop for f in cand-list
- for dir = (and (not (string-match ffap-url-regexp f))
- (helm-basedir f))
- for file = (eshell-quote-argument
- (format "%s" (if (and dir (file-remote-p dir))
- (helm-basename f) f)))
- for com = (if (string-match "'%s'\\|\"%s\"\\|%s" command)
- ;; [1] This allow to enter other args AFTER filename
- ;; i.e <command %s some_more_args>
- (format command file)
- (format "%s %s" command file))
- do (let ((default-directory (or dir default-directory)))
- (eshell-command com)))))))
-
-(defun helm-find-files-eshell-command-on-file (_candidate)
- "Run `eshell-command' on CANDIDATE or marked candidates.
-See `helm-find-files-eshell-command-on-file-1' for more info."
- (helm-find-files-eshell-command-on-file-1 helm-current-prefix-arg))
-
-(defun helm-ff-switch-to-eshell (_candidate)
- "Switch to eshell and cd to `helm-ff-default-directory'."
- (let ((cd-eshell (lambda ()
- (eshell/cd helm-ff-default-directory)
- (eshell-reset))))
- (if (get-buffer "*eshell*")
- (switch-to-buffer "*eshell*")
- (call-interactively 'eshell))
- (unless (get-buffer-process (current-buffer))
- (funcall cd-eshell))))
-
-(defun helm-ff-serial-rename-action (method)
- "Rename all marked files in `helm-ff-default-directory' with METHOD.
-See `helm-ff-serial-rename-1'."
- (let* ((helm--reading-passwd-or-string t)
- (cands (helm-marked-candidates :with-wildcard t))
- (def-name (car cands))
- (name (helm-read-string "NewName: "
- (replace-regexp-in-string
- "[0-9]+$" ""
- (helm-basename
- def-name
- (file-name-extension def-name)))))
- (start (read-number "StartAtNumber: "))
- (extension (helm-read-string "Extension: "
- (file-name-extension (car cands))))
- (dir (expand-file-name
- (helm-read-file-name
- "Serial Rename to directory: "
- :initial-input
- (expand-file-name helm-ff-default-directory)
- :test 'file-directory-p
- :must-match t)))
- done)
- (with-helm-display-marked-candidates
- helm-marked-buffer-name (helm-ff--count-and-collect-dups cands)
- (if (y-or-n-p
- (format "Rename %s file(s) to <%s> like this ?\n%s "
- (length cands) dir (format "%s <-> %s%s.%s"
- (helm-basename (car cands))
- name start extension)))
- (progn
- (helm-ff-serial-rename-1
- dir cands name start extension :method method)
- (setq done t)
- (message nil))))
- (if done
- (with-helm-current-buffer (helm-find-files-1 dir))
- (message "Operation aborted"))))
-
-(defun helm-ff-member-directory-p (file directory)
- (let ((dir-file (expand-file-name
- (file-name-as-directory (file-name-directory file))))
- (cur-dir (expand-file-name (file-name-as-directory directory))))
- (string= dir-file cur-dir)))
-
-(cl-defun helm-ff-serial-rename-1
- (directory collection new-name start-at-num extension &key (method 'rename))
- "rename files in COLLECTION to DIRECTORY with the prefix name NEW-NAME.
-Rename start at number START-AT-NUM - ex: prefixname-01.jpg.
-EXTENSION is the file extension to use, in empty prompt,
-reuse the original extension of file.
-METHOD can be one of rename, copy or symlink.
-Files will be renamed if they are files of current directory, otherwise they
-will be treated with METHOD.
-Default METHOD is rename."
- ;; Maybe remove directories selected by error in collection.
- (setq collection (cl-remove-if 'file-directory-p collection))
- (let* ((tmp-dir (file-name-as-directory
- (concat (file-name-as-directory directory)
- (symbol-name (cl-gensym "tmp")))))
- (fn (cl-case method
- (copy 'copy-file)
- (symlink 'make-symbolic-link)
- (rename 'rename-file)
- (t (error "Error: Unknown method %s" method)))))
- (make-directory tmp-dir)
- (unwind-protect
- (progn
- ;; Rename all files to tmp-dir with new-name.
- ;; If files are not from start directory, use method
- ;; to move files to tmp-dir.
- (cl-loop for i in collection
- for count from start-at-num
- for fnum = (if (< count 10) "0%s" "%s")
- for nname = (concat tmp-dir new-name (format fnum count)
- (if (not (string= extension ""))
- (format ".%s" (replace-regexp-in-string
- "[.]" "" extension))
- (file-name-extension i 'dot)))
- do (if (helm-ff-member-directory-p i directory)
- (rename-file i nname)
- (funcall fn i nname)))
- ;; Now move all from tmp-dir to destination.
- (cl-loop with dirlist = (directory-files
- tmp-dir t directory-files-no-dot-files-regexp)
- for f in dirlist do
- (if (file-symlink-p f)
- (make-symbolic-link (file-truename f)
- (concat (file-name-as-directory directory)
- (helm-basename f)))
- (rename-file f directory))))
- (delete-directory tmp-dir t))))
-
-(defun helm-ff-serial-rename (_candidate)
- "Serial rename all marked files to `helm-ff-default-directory'.
-Rename only file of current directory, and symlink files coming from
-other directories.
-See `helm-ff-serial-rename-1'."
- (helm-ff-serial-rename-action 'rename))
-
-(defun helm-ff-serial-rename-by-symlink (_candidate)
- "Serial rename all marked files to `helm-ff-default-directory'.
-Rename only file of current directory, and symlink files coming from
-other directories.
-See `helm-ff-serial-rename-1'."
- (helm-ff-serial-rename-action 'symlink))
-
-(defun helm-ff-serial-rename-by-copying (_candidate)
- "Serial rename all marked files to `helm-ff-default-directory'.
-Rename only file of current directory, and copy files coming from
-other directories.
-See `helm-ff-serial-rename-1'."
- (helm-ff-serial-rename-action 'copy))
-
-(defvar helm-ff-query-replace-fnames-history-from nil)
-(defvar helm-ff-query-replace-fnames-history-to nil)
-(defun helm-ff-query-replace-on-filenames (candidates)
- "Query replace on filenames of CANDIDATES.
-This doesn't replace inside the files, only modify filenames."
- (with-helm-display-marked-candidates
- helm-marked-buffer-name
- (mapcar 'helm-basename candidates)
- (let* ((regexp (read-string "Replace regexp on filename(s): "
- nil 'helm-ff-query-replace-history-from
- (helm-basename (car candidates))))
- (str (read-string (format "Replace regexp `%s' with: " regexp)
- nil 'helm-ff-query-replace-history-to)))
- (cl-loop with query = "y"
- with count = 0
- for old in candidates
- for new = (concat (helm-basedir old)
- (replace-regexp-in-string
- (cond ((string= regexp "%.")
- (helm-basename old t))
- ((string= regexp ".%")
- (file-name-extension old))
- ((string= regexp "%")
- (helm-basename old))
- (t regexp))
- (save-match-data
- (cond ((string-match "\\\\#" str)
- (replace-match
- (format "%03d" (1+ count)) t t str))
- ((string= str "%u") #'upcase)
- ((string= str "%d") #'downcase)
- ((string= str "%c") #'capitalize)
- (t str)))
- (helm-basename old) t))
- ;; If `regexp' is not matched in `old'
- ;; `replace-regexp-in-string' will
- ;; return `old' unmodified.
- unless (string= old new)
- do (progn
- (when (file-exists-p new)
- (setq new (concat (file-name-sans-extension new)
- (format "(%s)" count)
- (file-name-extension new t))))
- (unless (string= query "!")
- (while (not (member
- (setq query
- (string
- (read-key
- (propertize
- (format
- "Replace `%s' by `%s' [!,y,n,q]"
- old new)
- 'face 'minibuffer-prompt))))
- '("y" "!" "n" "q")))
- (message "Please answer by y,n,! or q") (sit-for 1)))
- (when (string= query "q")
- (cl-return (message "Operation aborted")))
- (unless (string= query "n")
- (rename-file old new)
- (cl-incf count)))
- finally (message "%d Files renamed" count))))
- ;; This fix the emacs bug where "Emacs-Lisp:" is sent
- ;; in minibuffer (not the echo area).
- (sit-for 0.1)
- (with-current-buffer (window-buffer (minibuffer-window))
- (delete-minibuffer-contents)))
-
-;; The action.
-(defun helm-ff-query-replace-on-marked (_candidate)
- (let ((marked (helm-marked-candidates :with-wildcard t)))
- (helm-ff-query-replace-on-filenames marked)))
-
-;; The command for `helm-find-files-map'.
-(defun helm-ff-run-query-replace-on-marked ()
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-ff-query-replace-on-marked)))
-(put 'helm-ff-run-query-replace-on-marked 'helm-only t)
-
-(defun helm-ff-query-replace (_candidate)
- (let ((bufs (cl-loop for f in (helm-marked-candidates :with-wildcard t)
- collect (buffer-name (find-file-noselect f)))))
- (helm-buffer-query-replace-1 nil bufs)))
-
-(defun helm-ff-query-replace-regexp (_candidate)
- (let ((bufs (cl-loop for f in (helm-marked-candidates :with-wildcard t)
- collect (buffer-name (find-file-noselect f)))))
- (helm-buffer-query-replace-1 'regexp bufs)))
-
-(defun helm-ff-run-query-replace ()
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-ff-query-replace)))
-(put 'helm-ff-run-query-replace 'helm-only t)
-
-(defun helm-ff-run-query-replace-regexp ()
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-ff-query-replace-regexp)))
-(put 'helm-ff-run-query-replace-regexp 'helm-only t)
-
-(defun helm-ff-toggle-auto-update (_candidate)
- (setq helm-ff-auto-update-flag (not helm-ff-auto-update-flag))
- (setq helm-ff--auto-update-state helm-ff-auto-update-flag)
- (message "[Auto expansion %s]"
- (if helm-ff-auto-update-flag "enabled" "disabled")))
-
-(defun helm-ff-run-toggle-auto-update ()
- (interactive)
- (with-helm-alive-p
- (helm-attrset 'toggle-auto-update '(helm-ff-toggle-auto-update . never-split))
- (helm-execute-persistent-action 'toggle-auto-update)))
-(put 'helm-ff-run-toggle-auto-update 'helm-only t)
-
-(defun helm-ff-delete-char-backward ()
- "Disable helm find files auto update and delete char backward."
- (interactive)
- (with-helm-alive-p
- (setq helm-ff-auto-update-flag nil)
- (setq helm-ff--deleting-char-backward t)
- (call-interactively
- (lookup-key (current-global-map)
- (read-kbd-macro "DEL")))))
-(put 'helm-ff-delete-char-backward 'helm-only t)
-
-(defun helm-ff-delete-char-backward--exit-fn ()
- (setq helm-ff-auto-update-flag helm-ff--auto-update-state)
- (setq helm-ff--deleting-char-backward nil))
-
-(defun helm-ff-run-switch-to-history ()
- "Run Switch to history action from `helm-source-find-files'."
- (interactive)
- (with-helm-alive-p
- (when (helm-file-completion-source-p)
- (helm-exit-and-execute-action 'helm-find-files-switch-to-hist))))
-(put 'helm-ff-run-switch-to-history 'helm-only t)
-
-(defun helm-ff-run-grep ()
- "Run Grep action from `helm-source-find-files'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-find-files-grep)))
-(put 'helm-ff-run-grep 'helm-only t)
-
-(defun helm-ff-run-git-grep ()
- "Run git-grep action from `helm-source-find-files'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-ff-git-grep)))
-(put 'helm-ff-run-git-grep 'helm-only t)
-
-(defun helm-ff-run-grep-ag ()
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-find-files-ag)))
-(put 'helm-ff-run-grep-ag 'helm-only t)
-
-(defun helm-ff-run-pdfgrep ()
- "Run Pdfgrep action from `helm-source-find-files'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-ff-pdfgrep)))
-(put 'helm-ff-run-pdfgrep 'helm-only t)
-
-(defun helm-ff-run-zgrep ()
- "Run Grep action from `helm-source-find-files'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-ff-zgrep)))
-(put 'helm-ff-run-zgrep 'helm-only t)
-
-(defun helm-ff-run-copy-file ()
- "Run Copy file action from `helm-source-find-files'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-find-files-copy)))
-(put 'helm-ff-run-copy-file 'helm-only t)
-
-(defun helm-ff-run-rename-file ()
- "Run Rename file action from `helm-source-find-files'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-find-files-rename)))
-(put 'helm-ff-run-rename-file 'helm-only t)
-
-(defun helm-ff-run-byte-compile-file ()
- "Run Byte compile file action from `helm-source-find-files'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-find-files-byte-compile)))
-(put 'helm-ff-run-byte-compile-file 'helm-only t)
-
-(defun helm-ff-run-load-file ()
- "Run Load file action from `helm-source-find-files'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-find-files-load-files)))
-(put 'helm-ff-run-load-file 'helm-only t)
-
-(defun helm-ff-run-eshell-command-on-file ()
- "Run eshell command on file action from `helm-source-find-files'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action
- 'helm-find-files-eshell-command-on-file)))
-(put 'helm-ff-run-eshell-command-on-file 'helm-only t)
-
-(defun helm-ff-run-ediff-file ()
- "Run Ediff file action from `helm-source-find-files'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-find-files-ediff-files)))
-(put 'helm-ff-run-ediff-file 'helm-only t)
-
-(defun helm-ff-run-ediff-merge-file ()
- "Run Ediff merge file action from `helm-source-find-files'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action
- 'helm-find-files-ediff-merge-files)))
-(put 'helm-ff-run-ediff-merge-file 'helm-only t)
-
-(defun helm-ff-run-symlink-file ()
- "Run Symlink file action from `helm-source-find-files'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-find-files-symlink)))
-(put 'helm-ff-run-symlink-file 'helm-only t)
-
-(defun helm-ff-run-hardlink-file ()
- "Run Hardlink file action from `helm-source-find-files'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-find-files-hardlink)))
-(put 'helm-ff-run-hardlink-file 'helm-only t)
-
-(defun helm-ff-run-delete-file ()
- "Run Delete file action from `helm-source-find-files'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-delete-marked-files)))
-(put 'helm-ff-run-delete-file 'helm-only t)
-
-(defun helm-ff-run-complete-fn-at-point ()
- "Run complete file name action from `helm-source-find-files'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action
- 'helm-insert-file-name-completion-at-point)))
-(put 'helm-ff-run-complete-fn-at-point 'helm-only t)
-
-(defun helm-ff-run-switch-to-eshell ()
- "Run switch to eshell action from `helm-source-find-files'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-ff-switch-to-eshell)))
-(put 'helm-ff-run-switch-to-eshell 'helm-only t)
-
-(defun helm-ff-run-switch-other-window ()
- "Run switch to other window action from `helm-source-find-files'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-find-files-other-window)))
-(put 'helm-ff-run-switch-other-window 'helm-only t)
-
-(defun helm-ff-run-switch-other-frame ()
- "Run switch to other frame action from `helm-source-find-files'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'find-file-other-frame)))
-(put 'helm-ff-run-switch-other-frame 'helm-only t)
-
-(defun helm-ff-run-open-file-externally ()
- "Run open file externally command action from `helm-source-find-files'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-open-file-externally)))
-(put 'helm-ff-run-open-file-externally 'helm-only t)
-
-(defun helm-ff-run-open-file-with-default-tool ()
- "Run open file externally command action from `helm-source-find-files'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-open-file-with-default-tool)))
-(put 'helm-ff-run-open-file-with-default-tool 'helm-only t)
-
-(defun helm-ff-locate (candidate)
- "Locate action function for `helm-find-files'."
- (helm-locate-set-command)
- (let ((input (concat (helm-basename
- (expand-file-name
- candidate
- helm-ff-default-directory))
- ;; The locate '-b' option doesn't exists
- ;; in everything (es).
- (unless (and (eq system-type 'windows-nt)
- (string-match "^es" helm-locate-command))
- " -b"))))
- (helm-locate-1 helm-current-prefix-arg nil 'from-ff input)))
-
-(defun helm-ff-run-locate ()
- "Run locate action from `helm-source-find-files'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-ff-locate)))
-(put 'helm-ff-run-locate 'helm-only t)
-
-(defun helm-files-insert-as-org-link (candidate)
- (insert (format "[[%s][]]" candidate))
- (goto-char (- (point) 2)))
-
-(defun helm-ff-run-insert-org-link ()
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-files-insert-as-org-link)))
-(put 'helm-ff-run-insert-org-link 'helm-only t)
-
-(defun helm-ff-run-find-file-as-root ()
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-find-file-as-root)))
-(put 'helm-ff-run-find-file-as-root 'helm-only t)
-
-(defun helm-ff-run-find-alternate-file ()
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'find-alternate-file)))
-(put 'helm-ff-run-find-alternate-file 'helm-only t)
-
-(defun helm-ff-run-gnus-attach-files ()
- "Run gnus attach files command action from `helm-source-find-files'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-ff-gnus-attach-files)))
-(put 'helm-ff-run-gnus-attach-files 'helm-only t)
-
-(defun helm-ff-run-etags ()
- "Run Etags command action from `helm-source-find-files'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-ff-etags-select)))
-(put 'helm-ff-run-etags 'helm-only t)
-
-(defvar lpr-printer-switch)
-(defun helm-ff-print (_candidate)
- "Print marked files.
-
-You may to set in order
-variables `lpr-command',`lpr-switches' and/or `printer-name',
-but with no settings helm should detect your printer(s) and
-print with the default `lpr' settings.
-
-NOTE: DO NOT set the \"-P\" flag in `lpr-switches', if you really
-have to modify this, do it in `lpr-printer-switch'.
-
-Same as `dired-do-print' but for helm."
- (require 'lpr)
- (when (or helm-current-prefix-arg
- (not helm-ff-printer-list))
- (setq helm-ff-printer-list
- (helm-ff-find-printers)))
- (let* ((file-list (helm-marked-candidates :with-wildcard t))
- (len (length file-list))
- (printer-name (if helm-ff-printer-list
- (helm-comp-read
- "Printer: " helm-ff-printer-list)
- printer-name))
- (lpr-switches
- (if (and (stringp printer-name)
- (string< "" printer-name))
- (cons (concat lpr-printer-switch printer-name)
- lpr-switches)
- lpr-switches))
- (command (helm-read-string
- (format "Print *%s File(s):\n%s with: "
- len
- (mapconcat
- (lambda (f) (format "- %s\n" f))
- file-list ""))
- (when (and lpr-command lpr-switches)
- (mapconcat 'identity
- (cons lpr-command
- (if (stringp lpr-switches)
- (list lpr-switches)
- lpr-switches))
- " "))))
- (file-args (mapconcat (lambda (x)
- (format "'%s'" x))
- file-list " "))
- (cmd-line (concat command " " file-args)))
- (if command
- (start-process-shell-command "helm-print" nil cmd-line)
- (error "Error: Please verify your printer settings in Emacs."))))
-
-(defun helm-ff-run-print-file ()
- "Run Print file action from `helm-source-find-files'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-ff-print)))
-(put 'helm-ff-run-print-file 'helm-only t)
-
-(defun helm-ff-checksum (file)
- "Calculate the checksum of FILE.
-The checksum is copied to kill-ring."
- (let ((algo (intern (helm-comp-read
- "Algorithm: "
- '(md5 sha1 sha224 sha256 sha384 sha512)))))
- (kill-new (with-temp-buffer
- (insert-file-contents-literally file)
- (secure-hash algo (current-buffer))))
- (message "Checksum copied to kill-ring.")))
-
-(defun helm-ff-toggle-basename (_candidate)
- (with-helm-buffer
- (setq helm-ff-transformer-show-only-basename
- (not helm-ff-transformer-show-only-basename))
- (let* ((cand (helm-get-selection nil t))
- (target (if helm-ff-transformer-show-only-basename
- (helm-basename cand) cand)))
- (helm-force-update (regexp-quote target)))))
-
-(defun helm-ff-run-toggle-basename ()
- (interactive)
- (with-helm-alive-p
- (unless (helm-empty-source-p)
- (helm-ff-toggle-basename nil))))
-(put 'helm-ff-run-toggle-basename 'helm-only t)
-
-(defun helm-reduce-file-name (fname level)
- "Reduce FNAME by number LEVEL from end."
- (cl-loop with result
- with iter = (helm-iter-reduce-fname (expand-file-name fname))
- repeat level do (setq result (helm-iter-next iter))
- finally return (or result (expand-file-name "/"))))
-
-(defun helm-iter-reduce-fname (fname)
- "Yield FNAME reduced by one level at each call."
- (let ((split (split-string fname "/" t)))
- (unless (or (null split)
- (string-match "\\`\\(~\\|[[:alpha:]]:\\)" (car split)))
- (setq split (cons "/" split)))
- (lambda ()
- (when (and split (cdr split))
- (cl-loop for i in (setq split (butlast split))
- concat (if (string= i "/") i (concat i "/")))))))
-
-(defvar helm-find-files--level-tree nil)
-(defvar helm-find-files--level-tree-iterator nil)
-(defun helm-find-files-up-one-level (arg)
- "Go up one level like unix command `cd ..'.
-If prefix numeric arg is given go ARG level up."
- (interactive "p")
- (with-helm-alive-p
- (when (and (helm-file-completion-source-p)
- (not (helm-ff-invalid-tramp-name-p)))
- (with-helm-window
- (when helm-follow-mode
- (helm-follow-mode -1) (message nil)))
- ;; When going up one level we want to be at the line
- ;; corresponding to actual directory, so store this info
- ;; in `helm-ff-last-expanded'.
- (let ((cur-cand (helm-get-selection))
- (new-pattern (helm-reduce-file-name helm-pattern arg)))
- (cond ((file-directory-p helm-pattern)
- (setq helm-ff-last-expanded helm-ff-default-directory))
- ((file-exists-p helm-pattern)
- (setq helm-ff-last-expanded helm-pattern))
- ((and cur-cand (file-exists-p cur-cand))
- (setq helm-ff-last-expanded cur-cand)))
- (unless helm-find-files--level-tree
- (setq helm-find-files--level-tree
- (cons helm-ff-default-directory
- helm-find-files--level-tree)))
- (setq helm-find-files--level-tree-iterator nil)
- (push new-pattern helm-find-files--level-tree)
- (helm-set-pattern new-pattern helm-suspend-update-flag)
- (with-helm-after-update-hook (helm-ff-retrieve-last-expanded))))))
-(put 'helm-find-files-up-one-level 'helm-only t)
-
-(defun helm-find-files-down-last-level ()
- "Retrieve previous paths reached by `C-l' in helm-find-files."
- (interactive)
- (with-helm-alive-p
- (when (and (helm-file-completion-source-p)
- (not (helm-ff-invalid-tramp-name-p)))
- (unless helm-find-files--level-tree-iterator
- (setq helm-find-files--level-tree-iterator
- (helm-iter-list (cdr helm-find-files--level-tree))))
- (setq helm-find-files--level-tree nil)
- (helm-aif (helm-iter-next helm-find-files--level-tree-iterator)
- (helm-set-pattern it)
- (setq helm-find-files--level-tree-iterator nil)))))
-(put 'helm-find-files-down-last-level 'helm-only t)
-
-(defun helm-find-files--reset-level-tree ()
- (setq helm-find-files--level-tree-iterator nil
- helm-find-files--level-tree nil))
-
-(add-hook 'helm-cleanup-hook 'helm-find-files--reset-level-tree)
-(add-hook 'post-self-insert-hook 'helm-find-files--reset-level-tree)
-(add-hook 'helm-after-persistent-action-hook 'helm-find-files--reset-level-tree)
-
-(defun helm-ff-retrieve-last-expanded ()
- "Move overlay to last visited directory `helm-ff-last-expanded'.
-This happen after using `helm-find-files-up-one-level',
-or hitting C-j on \"..\"."
- (when helm-ff-last-expanded
- (let ((presel (if helm-ff-transformer-show-only-basename
- (helm-basename
- (directory-file-name helm-ff-last-expanded))
- (directory-file-name helm-ff-last-expanded))))
- (with-helm-window
- (when (re-search-forward (concat "^" (regexp-quote presel) "$") nil t)
- (forward-line 0)
- (helm-mark-current-line)))
- (setq helm-ff-last-expanded nil))))
-
-(defun helm-ff-move-to-first-real-candidate ()
- "When candidate is an incomplete file name move to first real candidate."
- (helm-aif (and (helm-file-completion-source-p)
- (not (helm-empty-source-p))
- (not (string-match
- "\\`[Dd]ired-"
- (assoc-default 'name (helm-get-current-source))))
- helm-ff--move-to-first-real-candidate
- (helm-get-selection))
- (unless (or (not (stringp it))
- (and (string-match helm-tramp-file-name-regexp it)
- (not (file-remote-p it nil t)))
- (file-exists-p it))
- (helm-next-line))))
-
-;;; Auto-update - helm-find-files auto expansion of directories.
-;;
-;;
-(defun helm-ff-update-when-only-one-matched ()
- "Expand to directory when sole completion.
-When only one candidate is remaining and it is a directory,
-expand to this directory.
-This happen only when `helm-ff-auto-update-flag' is non--nil
-or when `helm-pattern' is equal to \"~/\"."
- (when (and (helm-file-completion-source-p)
- (not (helm-ff-invalid-tramp-name-p)))
- (with-helm-window
- (let* ((history-p (string= (assoc-default
- 'name (helm-get-current-source))
- "Read File Name History"))
- (pat (if (string-match helm-tramp-file-name-regexp
- helm-pattern)
- (helm-create-tramp-name helm-pattern)
- helm-pattern))
- (completed-p (string= (file-name-as-directory
- (expand-file-name
- (substitute-in-file-name pat)))
- helm-ff-default-directory))
- (candnum (helm-get-candidate-number))
- (lt2-p (and (<= candnum 2)
- (>= (string-width (helm-basename helm-pattern)) 2)))
- (cur-cand (prog2
- (unless (or completed-p
- (file-exists-p pat)
- history-p (null lt2-p))
- ;; Only one non--existing candidate
- ;; and one directory candidate, move to it,
- ;; but not when renaming, copying etc...,
- ;; so for this use
- ;; `helm-ff-move-to-first-real-candidate'
- ;; instead of `helm-next-line' (Issue #910).
- (helm-ff-move-to-first-real-candidate))
- (helm-get-selection))))
- (when (and (or (and helm-ff-auto-update-flag
- (null helm-ff--deleting-char-backward)
- (not (get-buffer-window helm-action-buffer 'visible))
- ;; Issue #295
- ;; File predicates are returning t
- ;; with paths like //home/foo.
- ;; So check it is not the case by regexp
- ;; to allow user to do C-a / to start e.g
- ;; entering a tramp method e.g /sudo::.
- (not (string-match "\\`//" helm-pattern))
- (not (eq last-command 'helm-yank-text-at-point)))
- ;; Fix issue #542.
- (string= helm-pattern "~/")
- ;; Only one remaining directory, expand it.
- (and (= candnum 1)
- helm-ff--auto-update-state
- (file-accessible-directory-p pat)
- (null helm-ff--deleting-char-backward)))
- (or
- ;; Only one candidate remaining
- ;; and at least 2 char in basename.
- lt2-p
- ;; Already completed.
- completed-p)
- (not history-p) ; Don't try to auto complete in history.
- (stringp cur-cand)
- (file-accessible-directory-p cur-cand))
- (if (and (not (helm-dir-is-dot cur-cand)) ; [1]
- ;; Maybe we are here because completed-p is true
- ;; but check this again to be sure. (Windows fix)
- (<= candnum 2)) ; [2]
- ;; If after going to next line the candidate
- ;; is not one of "." or ".." [1]
- ;; and only one candidate is remaining [2],
- ;; assume candidate is a new directory to expand, and do it.
- (helm-set-pattern (file-name-as-directory cur-cand))
- ;; The candidate is one of "." or ".."
- ;; that mean we have entered the last letter of the directory name
- ;; in prompt, so expansion is already done, just add the "/" at end
- ;; of name unless helm-pattern ends with "."
- ;; (i.e we are writing something starting with ".")
- (unless (string-match "\\`.*[.]\\{1\\}\\'" helm-pattern)
- (helm-set-pattern
- ;; Need to expand-file-name to avoid e.g /ssh:host:./ in prompt.
- (expand-file-name (file-name-as-directory helm-pattern)))))
- (helm-check-minibuffer-input))))))
-
-(defun helm-ff-auto-expand-to-home-or-root ()
- "Allow expanding to home/user directory or root or text yanked after pattern."
- (when (and (helm-file-completion-source-p)
- (string-match
- "/?\\$.*/\\|/\\./\\|/\\.\\./\\|/~.*/\\|//\\|\\(/[[:alpha:]]:/\\|\\s\\+\\)"
- helm-pattern)
- (with-current-buffer (window-buffer (minibuffer-window)) (eolp))
- (not (string-match helm-ff-url-regexp helm-pattern)))
- (let* ((match (match-string 0 helm-pattern))
- (input (cond ((string= match "/./")
- (expand-file-name default-directory))
- ((string= helm-pattern "/../") "/")
- ((string-match-p "\\`/\\$" match)
- (let ((sub (substitute-in-file-name match)))
- (if (file-directory-p sub)
- sub (replace-regexp-in-string "/\\'" "" sub))))
- (t (expand-file-name
- (helm-substitute-in-filename helm-pattern)
- ;; [Windows] On UNC paths "/" expand to current machine,
- ;; so use the root of current Drive. (i.e "C:/")
- (and (memq system-type '(windows-nt ms-dos))
- (getenv "SystemDrive")) ; nil on Unix.
- )))))
- (if (file-directory-p input)
- (setq helm-ff-default-directory
- (setq input (file-name-as-directory input)))
- (setq helm-ff-default-directory (file-name-as-directory
- (file-name-directory input))))
- (with-helm-window
- (helm-set-pattern input)
- (helm-check-minibuffer-input)))))
-
-(defun helm-substitute-in-filename (fname)
- "Substitute all parts of FNAME from start up to \"~/\" or \"/\".
-On windows system substitute from start up to \"/[[:lower:]]:/\".
-This function is needed for `helm-ff-auto-expand-to-home-or-root'
-and should be used carefully elsewhere, or not at all, using
-`substitute-in-file-name' instead."
- (cond ((and ffap-url-regexp
- (string-match-p ffap-url-regexp fname))
- fname)
- ((and (file-remote-p fname)
- helm-substitute-in-filename-stay-on-remote)
- (let ((sub (substitute-in-file-name fname)))
- (if (file-directory-p sub)
- sub (replace-regexp-in-string "/\\'" "" sub))))
- (t
- (with-temp-buffer
- (insert fname)
- (goto-char (point-min))
- (skip-chars-forward "/") ;; Avoid infloop in UNC paths Issue #424
- (if (re-search-forward "~.*/?\\|//\\|/[[:alpha:]]:/" nil t)
- (let ((match (match-string 0)))
- (goto-char (if (or (string= match "//")
- (string-match-p "/[[:alpha:]]:/" match))
- (1+ (match-beginning 0))
- (match-beginning 0)))
- (buffer-substring-no-properties (point) (point-at-eol)))
- fname)))))
-
-(defun helm-point-file-in-dired (file)
- "Put point on filename FILE in dired buffer."
- (unless (and ffap-url-regexp
- (string-match-p ffap-url-regexp file))
- (let ((target (expand-file-name (helm-substitute-in-filename file))))
- (dired (file-name-directory target))
- (dired-goto-file target))))
-
-(defun helm-create-tramp-name (fname)
- "Build filename for `helm-pattern' like /su:: or /sudo::."
- (apply #'tramp-make-tramp-file-name
- (cl-loop with v = (tramp-dissect-file-name fname)
- for i across v collect i)))
-
-(cl-defun helm-ff-tramp-hostnames (&optional (pattern helm-pattern))
- "Get a list of hosts for tramp method found in `helm-pattern'.
-Argument PATTERN default to `helm-pattern', it is here only for debugging
-purpose."
- (when (string-match helm-tramp-file-name-regexp pattern)
- (let ((method (match-string 1 pattern))
- (tn (match-string 0 pattern))
- (all-methods (mapcar 'car tramp-methods)))
- (helm-fast-remove-dups
- (cl-loop for (f . h) in (tramp-get-completion-function method)
- append (cl-loop for e in (funcall f (car h))
- for host = (and (consp e) (cadr e))
- when (and host (not (member host all-methods)))
- collect (concat tn host)))
- :test 'equal))))
-
-(defun helm-ff-before-action-hook-fn ()
- "Exit helm when user try to execute action on an invalid tramp fname."
- (let ((cand (helm-get-selection)))
- (when (and (helm-file-completion-source-p)
- (stringp cand)
- (helm-ff-invalid-tramp-name-p cand) ; Check candidate.
- (helm-ff-invalid-tramp-name-p)) ; check helm-pattern.
- (error "Error: Unknown file or directory `%s'" cand))))
-(add-hook 'helm-before-action-hook 'helm-ff-before-action-hook-fn)
-
-(cl-defun helm-ff-invalid-tramp-name-p (&optional (pattern helm-pattern))
- "Return non--nil when PATTERN is an invalid tramp filename."
- (string= (helm-ff-set-pattern pattern)
- "Invalid tramp file name"))
-
-(defun helm-ff-set-pattern (pattern)
- "Handle tramp filenames in `helm-pattern'."
- (let ((methods (mapcar 'car tramp-methods))
- (reg "\\`/\\([^[/:]+\\|[^/]+]\\):.*:")
- cur-method tramp-name)
- ;; In some rare cases tramp can return a nil input,
- ;; so be sure pattern is a string for safety (Issue #476).
- (unless pattern (setq pattern ""))
- (cond ((string-match helm-ff-url-regexp pattern) pattern)
- ((string-match "\\`\\$" pattern)
- (substitute-in-file-name pattern))
- ((string= pattern "") "")
- ((string-match "\\`[.]\\{1,2\\}/\\'" pattern)
- (expand-file-name pattern))
- ((string-match ".*\\(~?/?[.]\\{1\\}/\\)\\'" pattern)
- (expand-file-name default-directory))
- ((string-match ".*\\(~//\\|//\\)\\'" pattern)
- (expand-file-name "/")) ; Expand to "/" or "c:/"
- ((string-match "\\`\\(~/\\|.*/~/\\)\\'" pattern)
- (expand-file-name "~/"))
- ;; Match "/method:maybe_hostname:~"
- ((and (string-match (concat reg "~") pattern)
- (setq cur-method (match-string 1 pattern))
- (member cur-method methods))
- (setq tramp-name (expand-file-name
- (helm-create-tramp-name
- (match-string 0 pattern))))
- (replace-match tramp-name nil t pattern))
- ;; Match "/method:maybe_hostname:"
- ((and (string-match reg pattern)
- (setq cur-method (match-string 1 pattern))
- (member cur-method methods))
- (setq tramp-name (helm-create-tramp-name
- (match-string 0 pattern)))
- (replace-match tramp-name nil t pattern))
- ;; Match "/hostname:"
- ((and (string-match helm-tramp-file-name-regexp pattern)
- (setq cur-method (match-string 1 pattern))
- (and cur-method (not (member cur-method methods))))
- (setq tramp-name (helm-create-tramp-name
- (match-string 0 pattern)))
- (replace-match tramp-name nil t pattern))
- ;; Match "/method:" in this case don't try to connect.
- ((and (not (string-match reg pattern))
- (string-match helm-tramp-file-name-regexp pattern)
- (member (match-string 1 pattern) methods))
- "Invalid tramp file name") ; Write in helm-buffer.
- ;; Return PATTERN unchanged.
- (t pattern))))
-
-(defun helm-find-files-get-candidates (&optional require-match)
- "Create candidate list for `helm-source-find-files'."
- (let* ((path (helm-ff-set-pattern helm-pattern))
- (dir-p (file-accessible-directory-p path))
- basedir
- invalid-basedir
- non-essential
- (tramp-verbose helm-tramp-verbose)) ; No tramp message when 0.
- (set-text-properties 0 (length path) nil path)
- ;; Issue #118 allow creation of newdir+newfile.
- (unless (or
- ;; A tramp file name not completed.
- (string= path "Invalid tramp file name")
- ;; An empty pattern
- (string= path "")
- ;; Check if base directory of PATH is valid.
- (helm-aif (file-name-directory path)
- ;; If PATH is a valid directory IT=PATH,
- ;; else IT=basedir of PATH.
- (file-directory-p it)))
- ;; BASEDIR is invalid, that's mean user is starting
- ;; to write a non--existing path in minibuffer
- ;; probably to create a 'new_dir' or a 'new_dir+new_file'.
- (setq invalid-basedir t))
- ;; Don't set now `helm-pattern' if `path' == "Invalid tramp file name"
- ;; like that the actual value (e.g /ssh:) is passed to
- ;; `helm-ff-tramp-hostnames'.
- (unless (or (string= path "Invalid tramp file name")
- invalid-basedir) ; Leave helm-pattern unchanged.
- (setq helm-ff-auto-update-flag ; [1]
- ;; Unless auto update is disabled at startup or
- ;; interactively, start auto updating only at third char.
- (unless (or (null helm-ff-auto-update-initial-value)
- (null helm-ff--auto-update-state)
- ;; But don't enable auto update when
- ;; deleting backward.
- helm-ff--deleting-char-backward
- (and dir-p (not (string-match-p "/\\'" path))))
- (or (>= (length (helm-basename path)) 3) dir-p)))
- (setq helm-pattern (helm-ff--transform-pattern-for-completion path))
- ;; This have to be set after [1] to allow deleting char backward.
- (setq basedir (expand-file-name
- (if (and dir-p helm-ff-auto-update-flag)
- ;; Add the final "/" to path
- ;; when `helm-ff-auto-update-flag' is enabled.
- (file-name-as-directory path)
- (if (string= path "") "/"
- (file-name-directory path)))))
- (setq helm-ff-default-directory
- (if (string= helm-pattern "")
- (expand-file-name "/") ; Expand to "/" or "c:/"
- ;; If path is an url *default-directory have to be nil.
- (unless (or (string-match helm-ff-url-regexp path)
- (and ffap-url-regexp
- (string-match ffap-url-regexp path)))
- basedir))))
- (cond ((string= path "Invalid tramp file name")
- (or (helm-ff-tramp-hostnames) ; Hostnames completion.
- (prog2
- ;; `helm-pattern' have not been modified yet.
- ;; Set it here to the value of `path' that should be now
- ;; "Invalid tramp file name" and set the candidates list
- ;; to ("Invalid tramp file name") to make `helm-pattern'
- ;; match single candidate "Invalid tramp file name".
- (setq helm-pattern path)
- ;; "Invalid tramp file name" is now printed
- ;; in `helm-buffer'.
- (list path))))
- ((or (and (file-regular-p path)
- (eq last-repeatable-command 'helm-execute-persistent-action))
- ;; `ffap-url-regexp' don't match until url is complete.
- (string-match helm-ff-url-regexp path)
- invalid-basedir
- (and (not (file-exists-p path)) (string-match "/$" path))
- (and ffap-url-regexp (string-match ffap-url-regexp path)))
- (list path))
- ((string= path "") (helm-ff-directory-files "/" t))
- ;; Check here if directory is accessible (not working on Windows).
- ((and (file-directory-p path) (not (file-readable-p path)))
- (list (format "file-error: Opening directory permission denied `%s'" path)))
- ;; A fast expansion of PATH is made only if `helm-ff-auto-update-flag'
- ;; is enabled.
- ((and dir-p helm-ff-auto-update-flag)
- (helm-ff-directory-files path t))
- (t (append (unless (or require-match
- ;; When `helm-ff-auto-update-flag' has been
- ;; disabled, whe don't want PATH to be added on top
- ;; if it is a directory.
- dir-p)
- (list path))
- (helm-ff-directory-files basedir t))))))
-
-(defun helm-ff-directory-files (directory &optional full)
- "List contents of DIRECTORY.
-Argument FULL mean absolute path.
-It is same as `directory-files' but always returns the
-dotted filename '.' and '..' even on root directories in Windows
-systems."
- (setq directory (file-name-as-directory
- (expand-file-name directory)))
- (let* (file-error
- (ls (condition-case err
- (directory-files
- directory full directory-files-no-dot-files-regexp)
- ;; Handle file-error from here for Windows
- ;; because predicates like `file-readable-p' and friends
- ;; seem broken on emacs for Windows systems (always returns t).
- ;; This should never be called on GNU/Linux/Unix
- ;; as the error is properly intercepted in
- ;; `helm-find-files-get-candidates' by `file-readable-p'.
- (file-error
- (prog1
- (list (format "%s:%s"
- (car err)
- (mapconcat 'identity (cdr err) " ")))
- (setq file-error t)))))
- (dot (concat directory "."))
- (dot2 (concat directory "..")))
- (append (and (not file-error) (list dot dot2)) ls)))
-
-(defun helm-ff-handle-backslash (fname)
- ;; Allow creation of filenames containing a backslash.
- (cl-loop with bad = '((92 . ""))
- for i across fname
- for isbad = (assq i bad)
- if isbad concat (cdr isbad)
- else concat (string i)))
-
-(defun helm-ff-fuzzy-matching-p ()
- (and helm-ff-fuzzy-matching
- (not (memq helm-mm-matching-method '(multi1 multi3p)))))
-
-(defun helm-ff--transform-pattern-for-completion (pattern)
- "Maybe return PATTERN with it's basename modified as a regexp.
-This happen only when `helm-ff-fuzzy-matching' is enabled.
-This provide a similar behavior as `ido-enable-flex-matching'.
-See also `helm--mapconcat-pattern'.
-If PATTERN is an url returns it unmodified.
-When PATTERN contain a space fallback to multi-match.
-If basename contain one or more space fallback to multi-match.
-If PATTERN is a valid directory name,return PATTERN unchanged."
- ;; handle bad filenames containing a backslash.
- (setq pattern (helm-ff-handle-backslash pattern))
- (let ((bn (helm-basename pattern))
- (bd (or (helm-basedir pattern) ""))
- (dir-p (file-directory-p pattern))
- (tramp-p (cl-loop for (m . f) in tramp-methods
- thereis (string-match m pattern))))
- ;; Always regexp-quote base directory name to handle
- ;; crap dirnames such e.g bookmark+
- (cond
- ((or (and dir-p tramp-p (string-match ":\\'" pattern))
- (string= pattern "")
- (and dir-p (<= (length bn) 2))
- ;; Fix Issue #541 when BD have a subdir similar
- ;; to BN, don't switch to match plugin
- ;; which will match both.
- (and dir-p (string-match (regexp-quote bn) bd)))
- ;; Use full PATTERN on e.g "/ssh:host:".
- (regexp-quote pattern))
- ;; Prefixing BN with a space call multi-match completion.
- ;; This allow showing all files/dirs matching BN (Issue #518).
- ;; FIXME: some multi-match methods may not work here.
- (dir-p (concat (regexp-quote bd) " " (regexp-quote bn)))
- ((or (not (helm-ff-fuzzy-matching-p))
- (string-match "\\s-" bn)) ; Fall back to multi-match.
- (concat (regexp-quote bd) bn))
- ((or (string-match "[*][.]?.*" bn) ; Allow entering wilcard.
- (string-match "/$" pattern) ; Allow mkdir.
- (string-match helm-ff-url-regexp pattern)
- (and (string= helm-ff-default-directory "/") tramp-p))
- ;; Don't treat wildcards ("*") as regexp char.
- ;; (e.g ./foo/*.el => ./foo/[*].el)
- (concat (regexp-quote bd)
- (replace-regexp-in-string "[*]" "[*]" bn)))
- (t (concat (regexp-quote bd)
- (if (>= (length bn) 2) ; wait 2nd char before concating.
- (helm--mapconcat-pattern bn)
- (concat ".*" (regexp-quote bn))))))))
-
-(defun helm-dir-is-dot (dir)
- (string-match "\\(?:/\\|\\`\\)\\.\\{1,2\\}\\'" dir))
-
-(defun helm-ff-save-history ()
- "Store the last value of `helm-ff-default-directory' in `helm-ff-history'.
-Note that only existing directories are saved here."
- (when (and helm-ff-default-directory
- (helm-file-completion-source-p)
- (file-directory-p helm-ff-default-directory))
- (set-text-properties 0 (length helm-ff-default-directory)
- nil helm-ff-default-directory)
- (push helm-ff-default-directory helm-ff-history)))
-(add-hook 'helm-cleanup-hook 'helm-ff-save-history)
-
-(defun helm-files-save-file-name-history (&optional force)
- "Save selected file to `file-name-history'."
- (let ((src-name (assoc-default 'name (helm-get-current-source))))
- (when (or force (helm-file-completion-source-p)
- (member src-name helm-files-save-history-extra-sources))
- (let ((mkd (helm-marked-candidates))
- (history-delete-duplicates t))
- (cl-loop for sel in mkd
- when (and sel
- (stringp sel)
- (file-exists-p sel)
- (not (file-directory-p sel)))
- do
- ;; we use `abbreviate-file-name' here because
- ;; other parts of Emacs seems to,
- ;; and we don't want to introduce duplicates.
- (add-to-history 'file-name-history
- (abbreviate-file-name sel)))))))
-(add-hook 'helm-exit-minibuffer-hook 'helm-files-save-file-name-history)
-
-(defun helm-ff-valid-symlink-p (file)
- (helm-aif (condition-case-unless-debug nil
- ;; `file-truename' send error
- ;; on cyclic symlinks (Issue #692).
- (file-truename file)
- (error nil))
- (file-exists-p it)))
-
-(defun helm-get-default-mode-for-file (filename)
- "Return the default mode to open FILENAME."
- (let ((mode (cl-loop for (r . m) in auto-mode-alist
- thereis (and (string-match r filename) m))))
- (or (and (symbolp mode) mode) "Fundamental")))
-
-(defun helm-ff-properties (candidate)
- "Show file properties of CANDIDATE in a tooltip or message."
- (let* ((all (helm-file-attributes candidate))
- (dired-line (helm-file-attributes
- candidate :dired t :human-size t))
- (type (cl-getf all :type))
- (mode-type (cl-getf all :mode-type))
- (owner (cl-getf all :uid))
- (owner-right (cl-getf all :user t))
- (group (cl-getf all :gid))
- (group-right (cl-getf all :group))
- (other-right (cl-getf all :other))
- (size (helm-file-human-size (cl-getf all :size)))
- (modif (cl-getf all :modif-time))
- (access (cl-getf all :access-time))
- (ext (helm-get-default-program-for-file candidate))
- (tooltip-hide-delay (or helm-tooltip-hide-delay tooltip-hide-delay)))
- (if (and (window-system) tooltip-mode)
- (tooltip-show
- (concat
- (helm-basename candidate) "\n"
- dired-line "\n"
- (format "Mode: %s\n" (helm-get-default-mode-for-file candidate))
- (format "Ext prog: %s\n" (or (and ext (replace-regexp-in-string
- " %s" "" ext))
- "Not defined"))
- (format "Type: %s: %s\n" type mode-type)
- (when (string= type "symlink")
- (format "True name: '%s'\n"
- (cond ((string-match "^\.#" (helm-basename candidate))
- "Autosave symlink")
- ((helm-ff-valid-symlink-p candidate)
- (file-truename candidate))
- (t "Invalid Symlink"))))
- (format "Owner: %s: %s\n" owner owner-right)
- (format "Group: %s: %s\n" group group-right)
- (format "Others: %s\n" other-right)
- (format "Size: %s\n" size)
- (format "Modified: %s\n" modif)
- (format "Accessed: %s\n" access)))
- (message dired-line) (sit-for 5))))
-
-(defun helm-ff-properties-persistent ()
- "Show properties without quitting helm."
- (interactive)
- (with-helm-alive-p
- (helm-attrset 'properties-action '(helm-ff-properties . never-split))
- (helm-execute-persistent-action 'properties-action)))
-(put 'helm-ff-properties-persistent 'helm-only t)
-
-(defun helm-ff-persistent-delete ()
- "Delete current candidate without quitting."
- (interactive)
- (with-helm-alive-p
- (helm-attrset 'quick-delete '(helm-ff-quick-delete . never-split))
- (helm-execute-persistent-action 'quick-delete)))
-(put 'helm-ff-persistent-delete 'helm-only t)
-
-(defun helm-ff-dot-file-p (file)
- "Check if FILE is `.' or `..'."
- (member (helm-basename file) '("." "..")))
-
-(defun helm-ff-quick-delete (_candidate)
- "Delete file CANDIDATE without quitting."
- (let ((marked (helm-marked-candidates)))
- (unwind-protect
- (save-selected-window
- (cl-loop for c in marked do
- (progn (helm-preselect
- (if (and helm-ff-transformer-show-only-basename
- (not (helm-ff-dot-file-p c)))
- (helm-basename c) c))
- (when (y-or-n-p
- (format "Really Delete file `%s'? " c))
- (helm-delete-file
- c helm-ff-signal-error-on-dot-files 'synchro)
- (helm-delete-current-selection)
- (message nil)))))
- (with-helm-buffer
- (setq helm-marked-candidates nil
- helm-visible-mark-overlays nil))
- (helm-force-update
- (let ((presel (helm-get-selection)))
- (regexp-quote (if (and helm-ff-transformer-show-only-basename
- (not (helm-ff-dot-file-p presel)))
- (helm-basename presel) presel)))))))
-
-(defun helm-ff-kill-buffer-fname (candidate)
- (let* ((buf (get-file-buffer candidate))
- (buf-name (buffer-name buf)))
- (cond ((and buf (eq buf (get-buffer helm-current-buffer)))
- (user-error
- "Can't kill `helm-current-buffer' without quitting session"))
- (buf (kill-buffer buf) (message "Buffer `%s' killed" buf-name))
- (t (message "No buffer to kill")))))
-
-(defun helm-ff-kill-or-find-buffer-fname (candidate)
- "Find file CANDIDATE or kill it's buffer if it is visible.
-Never kill `helm-current-buffer'.
-Never kill buffer modified.
-This is called normally on third hit of \
-\\<helm-map>\\[helm-execute-persistent-action]
-in `helm-find-files-persistent-action'."
- (let* ((buf (get-file-buffer candidate))
- (buf-name (buffer-name buf))
- (win (get-buffer-window buf))
- (helm--reading-passwd-or-string t))
- (cond ((and buf win (eq buf (get-buffer helm-current-buffer)))
- (user-error
- "Can't kill `helm-current-buffer' without quitting session"))
- ((and buf win (buffer-modified-p buf))
- (message "Can't kill modified buffer, please save it before"))
- ((and buf win)
- (kill-buffer buf)
- (set-window-buffer win helm-current-buffer)
- (message "Buffer `%s' killed" buf-name))
- (t (find-file candidate)))))
-
-(defun helm-ff-run-kill-buffer-persistent ()
- "Execute `helm-ff-kill-buffer-fname' without quitting."
- (interactive)
- (with-helm-alive-p
- (helm-attrset 'kill-buffer-fname 'helm-ff-kill-buffer-fname)
- (helm-execute-persistent-action 'kill-buffer-fname)))
-(put 'helm-ff-run-kill-buffer-persistent 'helm-only t)
-
-(defun helm-ff-prefix-filename (fname &optional file-or-symlinkp new-file)
- "Return filename FNAME maybe prefixed with [?] or [@].
-If FILE-OR-SYMLINKP is non--nil this mean we assume FNAME is an
-existing filename or valid symlink and there is no need to test it.
-NEW-FILE when non--nil mean FNAME is a non existing file and
-return FNAME prefixed with [?]."
- (let* ((prefix-new (propertize
- " " 'display
- (propertize "[?]" 'face 'helm-ff-prefix)))
- (prefix-url (propertize
- " " 'display
- (propertize "[@]" 'face 'helm-ff-prefix))))
- (cond (file-or-symlinkp fname)
- ((or (string-match helm-ff-url-regexp fname)
- (and ffap-url-regexp (string-match ffap-url-regexp fname)))
- (concat prefix-url " " fname))
- (new-file (concat prefix-new " " fname)))))
-
-(defun helm-ff-score-candidate-for-pattern (str pattern)
- (if (member str '("." ".."))
- 200
- (helm-score-candidate-for-pattern str pattern)))
-
-(defun helm-ff-sort-candidates (candidates _source)
- "Sort function for `helm-source-find-files'.
-Return candidates prefixed with basename of `helm-input' first."
- (if (or (and (file-directory-p helm-input)
- (string-match "/\\'" helm-input))
- (string-match "\\`\\$" helm-input)
- (null candidates))
- candidates
- (let* ((c1 (car candidates))
- (cand1real (if (consp c1) (cdr c1) c1))
- (cand1 (unless (file-exists-p cand1real) c1))
- (rest-cand (if cand1 (cdr candidates) candidates))
- (memo-src (make-hash-table :test 'equal))
- (all (sort rest-cand
- (lambda (s1 s2)
- (let* ((score (lambda (str)
- (helm-ff-score-candidate-for-pattern
- str (helm-basename helm-input))))
- (bn1 (helm-basename (if (consp s1) (cdr s1) s1)))
- (bn2 (helm-basename (if (consp s2) (cdr s2) s2)))
- (sc1 (or (gethash bn1 memo-src)
- (puthash bn1 (funcall score bn1) memo-src)))
- (sc2 (or (gethash bn2 memo-src)
- (puthash bn2 (funcall score bn2) memo-src))))
- (cond ((= sc1 sc2)
- (< (string-width bn1)
- (string-width bn2)))
- ((> sc1 sc2))))))))
- (if cand1 (cons cand1 all) all))))
-
-(defun helm-ff-filter-candidate-one-by-one (file)
- "`filter-one-by-one' Transformer function for `helm-source-find-files'."
- ;; Handle boring files
- (unless (and helm-ff-skip-boring-files
- (cl-loop for r in helm-boring-file-regexp-list
- ;; Prevent user doing silly thing like
- ;; adding the dotted files to boring regexps (#924).
- thereis (and (not (string-match "\\.$" file))
- (string-match r file))))
- ;; Handle tramp files.
- (if (and (string-match helm-tramp-file-name-regexp helm-pattern)
- helm-ff-tramp-not-fancy)
- (if helm-ff-transformer-show-only-basename
- (if (helm-dir-is-dot file)
- file
- (cons (or (helm-ff-get-host-from-tramp-invalid-fname file)
- (helm-basename file))
- file))
- file)
- ;; Now highlight.
- (let* ((disp (if (and helm-ff-transformer-show-only-basename
- (not (helm-dir-is-dot file))
- (not (and ffap-url-regexp
- (string-match ffap-url-regexp file)))
- (not (string-match helm-ff-url-regexp file)))
- (or (helm-ff-get-host-from-tramp-invalid-fname file)
- (helm-basename file)) file))
- (attr (file-attributes file))
- (type (car attr)))
-
- (cond ((string-match "file-error" file) file)
- ( ;; A not already saved file.
- (and (stringp type)
- (not (helm-ff-valid-symlink-p file))
- (not (string-match "^\.#" (helm-basename file))))
- (cons (helm-ff-prefix-filename
- (propertize disp 'face 'helm-ff-invalid-symlink) t)
- file))
- ;; A dotted directory symlinked.
- ((and (helm-ff-dot-file-p file) (stringp type))
- (cons (helm-ff-prefix-filename
- (propertize disp 'face 'helm-ff-dotted-symlink-directory) t)
- file))
- ;; A dotted directory.
- ((helm-ff-dot-file-p file)
- (cons (helm-ff-prefix-filename
- (propertize disp 'face 'helm-ff-dotted-directory) t)
- file))
- ;; A symlink.
- ((stringp type)
- (cons (helm-ff-prefix-filename
- (propertize disp 'face 'helm-ff-symlink) t)
- file))
- ;; A directory.
- ((eq t type)
- (cons (helm-ff-prefix-filename
- (propertize disp 'face 'helm-ff-directory) t)
- file))
- ;; An executable file.
- ((and attr (string-match "x" (nth 8 attr)))
- (cons (helm-ff-prefix-filename
- (propertize disp 'face 'helm-ff-executable) t)
- file))
- ;; A file.
- ((and attr (null type))
- (cons (helm-ff-prefix-filename
- (propertize disp 'face 'helm-ff-file) t)
- file))
- ;; A non--existing file.
- (t
- (cons (helm-ff-prefix-filename
- (propertize disp 'face 'helm-ff-file) nil 'new-file)
- file)))))))
-
-(defun helm-find-files-action-transformer (actions candidate)
- "Action transformer for `helm-source-find-files'."
- (let ((str-at-point (with-helm-current-buffer
- (buffer-substring-no-properties
- (point-at-bol) (point-at-eol)))))
- (cond ((with-helm-current-buffer
- (eq major-mode 'message-mode))
- (append actions
- '(("Gnus attach file(s)" . helm-ff-gnus-attach-files))))
- ((save-match-data
- (and ffap-url-regexp
- (not (string-match-p ffap-url-regexp str-at-point))
- (not (with-helm-current-buffer (eq major-mode 'dired-mode)))
- (string-match ":\\([0-9]+:?\\)" str-at-point)
- ))
- (append '(("Find file to line number" . helm-ff-goto-linum))
- actions))
- ((string-match (image-file-name-regexp) candidate)
- (append actions
- '(("Rotate image right `M-r'" . helm-ff-rotate-image-right)
- ("Rotate image left `M-l'" . helm-ff-rotate-image-left))))
- ((string-match "\.el$" (helm-aif (helm-marked-candidates)
- (car it) candidate))
- (append actions
- '(("Byte compile lisp file(s) `M-B, C-u to load'"
- . helm-find-files-byte-compile)
- ("Load File(s) `M-L'" . helm-find-files-load-files))))
- ((and (string-match "\.html?$" candidate)
- (file-exists-p candidate))
- (append actions
- '(("Browse url file" . browse-url-of-file))))
- ((or (string= (file-name-extension candidate) "pdf")
- (string= (file-name-extension candidate) "PDF"))
- (append actions
- '(("Pdfgrep File(s)" . helm-ff-pdfgrep))))
- (t actions))))
-
-(defun helm-ff-goto-linum (candidate)
- "Find file CANDIDATE and maybe jump to line number found in fname at point.
-line number should be added at end of fname preceded with \":\".
-e.g \"foo:12\"."
- (let ((linum (with-helm-current-buffer
- (let ((str (buffer-substring-no-properties
- (point-at-bol) (point-at-eol))))
- (when (string-match ":\\([0-9]+:?\\)" str)
- (match-string 1 str))))))
- (find-file candidate)
- (and linum (not (string= linum ""))
- (helm-goto-line (string-to-number linum) t))))
-
-(defun helm-ff-gnus-attach-files (_candidate)
- "Run `gnus-dired-attach' on `helm-marked-candidates' or CANDIDATE."
- (require 'gnus-dired)
- (let ((flist (helm-marked-candidates :with-wildcard t)))
- (gnus-dired-attach flist)))
-
-(defvar image-dired-display-image-buffer)
-(defun helm-ff-rotate-current-image-1 (file &optional num-arg)
- "Rotate current image at NUM-ARG degrees.
-This is a destructive operation on FILE made by external tool mogrify."
- (setq file (file-truename file)) ; For symlinked images.
- ;; When FILE is not an image-file, do nothing.
- (when (string-match (image-file-name-regexp) file)
- (if (executable-find "mogrify")
- (progn
- (shell-command (format "mogrify -rotate %s %s"
- (or num-arg 90)
- (shell-quote-argument file)))
- (when (buffer-live-p image-dired-display-image-buffer)
- (kill-buffer image-dired-display-image-buffer))
- (image-dired-display-image file)
- (message nil)
- (display-buffer (get-buffer image-dired-display-image-buffer)))
- (error "mogrify not found"))))
-
-(defun helm-ff-rotate-image-left (candidate)
- "Rotate image file CANDIDATE left.
-This affect directly file CANDIDATE."
- (helm-ff-rotate-current-image-1 candidate -90))
-
-(defun helm-ff-rotate-image-right (candidate)
- "Rotate image file CANDIDATE right.
-This affect directly file CANDIDATE."
- (helm-ff-rotate-current-image-1 candidate))
-
-(defun helm-ff-rotate-left-persistent ()
- "Rotate image left without quitting helm."
- (interactive)
- (with-helm-alive-p
- (helm-attrset 'image-action1 'helm-ff-rotate-image-left)
- (helm-execute-persistent-action 'image-action1)))
-(put 'helm-ff-rotate-left-persistent 'helm-only t)
-
-(defun helm-ff-rotate-right-persistent ()
- "Rotate image right without quitting helm."
- (interactive)
- (with-helm-alive-p
- (helm-attrset 'image-action2 'helm-ff-rotate-image-right)
- (helm-execute-persistent-action 'image-action2)))
-(put 'helm-ff-rotate-right-persistent 'helm-only t)
-
-(defun helm-ff-exif-data (candidate)
- "Extract exif data from file CANDIDATE using `helm-ff-exif-data-program'."
- (if (and helm-ff-exif-data-program
- (executable-find helm-ff-exif-data-program))
- (shell-command-to-string (format "%s %s %s"
- helm-ff-exif-data-program
- helm-ff-exif-data-program-args
- candidate))
- (format "No program %s found to extract exif"
- helm-ff-exif-data-program)))
-
-(defun helm-find-files-persistent-action (candidate)
- "Open subtree CANDIDATE without quitting helm.
-If CANDIDATE is not a directory expand CANDIDATE filename.
-If CANDIDATE is alone, open file CANDIDATE filename.
-That's mean:
-First hit on C-j expand CANDIDATE second hit open file.
-If a prefix arg is given or `helm-follow-mode' is on open file."
- (let* ((follow (or (buffer-local-value
- 'helm-follow-mode
- (get-buffer-create helm-buffer))
- helm--temp-follow-flag))
- (new-pattern (helm-get-selection))
- (num-lines-buf (with-current-buffer helm-buffer
- (count-lines (point-min) (point-max))))
- (insert-in-minibuffer (lambda (fname)
- (with-selected-window (minibuffer-window)
- (unless follow
- (delete-minibuffer-contents)
- (set-text-properties 0 (length fname)
- nil fname)
- (insert fname))))))
- (cond ((and (helm-ff-invalid-tramp-name-p)
- (string-match helm-tramp-file-name-regexp candidate))
- ;; First hit insert hostname and
- ;; second hit insert ":" and expand.
- (if (string= candidate helm-pattern)
- (funcall insert-in-minibuffer (concat candidate ":"))
- (funcall insert-in-minibuffer candidate)))
- (;; A symlink directory, expand it but not to its truename
- ;; unless a prefix arg is given.
- (and (file-directory-p candidate) (file-symlink-p candidate))
- (funcall insert-in-minibuffer
- (file-name-as-directory
- (if current-prefix-arg
- (file-truename (expand-file-name candidate))
- (expand-file-name candidate)))))
- ;; A directory, open it.
- ((file-directory-p candidate)
- (when (string= (helm-basename candidate) "..")
- (setq helm-ff-last-expanded helm-ff-default-directory))
- (funcall insert-in-minibuffer (file-name-as-directory
- (expand-file-name candidate))))
- ;; A symlink file, expand to it's true name. (first hit)
- ((and (file-symlink-p candidate) (not current-prefix-arg) (not follow))
- (funcall insert-in-minibuffer (file-truename candidate)))
- ;; A regular file, expand it, (first hit)
- ((and (>= num-lines-buf 3) (not current-prefix-arg) (not follow))
- (setq helm-pattern "") ; Force update.
- (funcall insert-in-minibuffer new-pattern))
- ;; An image file and it is the second hit on C-j,
- ;; show the file in `image-dired'.
- ((string-match (image-file-name-regexp) candidate)
- (when (buffer-live-p (get-buffer image-dired-display-image-buffer))
- (kill-buffer image-dired-display-image-buffer))
- ;; Fix emacs bug never fixed upstream.
- (unless (file-directory-p image-dired-dir)
- (make-directory image-dired-dir))
- (image-dired-display-image candidate)
- (message nil)
- (switch-to-buffer image-dired-display-image-buffer)
- (with-current-buffer image-dired-display-image-buffer
- (let ((exif-data (helm-ff-exif-data candidate)))
- (setq default-directory helm-ff-default-directory)
- (image-dired-update-property 'help-echo exif-data))))
- ;; Allow browsing archive on avfs fs.
- ;; Assume volume is already mounted with mountavfs.
- ((and helm-ff-avfs-directory
- (string-match
- (regexp-quote (expand-file-name helm-ff-avfs-directory))
- (file-name-directory candidate))
- (helm-ff-file-compressed-p candidate))
- (funcall insert-in-minibuffer (concat candidate "#")))
- ;; On second hit we open file.
- ;; On Third hit we kill it's buffer maybe.
- (t
- (helm-ff-kill-or-find-buffer-fname candidate)))))
-
-(defun helm-ff-file-compressed-p (candidate)
- "Whether CANDIDATE is a compressed file or not."
- (member (file-name-extension candidate)
- helm-ff-file-compressed-list))
-
-(defun helm-insert-file-name-completion-at-point (candidate)
- "Insert file name completion at point."
- (with-helm-current-buffer
- (if buffer-read-only
- (error "Error: Buffer `%s' is read-only" (buffer-name))
- (let* ((end (point))
- (tap (thing-at-point 'filename))
- (guess (and (stringp tap) (substring-no-properties tap)))
- (beg (- (point) (length guess)))
- (full-path-p (and (stringp guess)
- (or (string-match-p
- (concat "^" (getenv "HOME"))
- guess)
- (string-match-p
- "\\`\\(/\\|[[:lower:][:upper:]]:/\\)"
- guess)))))
- (set-text-properties 0 (length candidate) nil candidate)
- (if (and guess (not (string= guess ""))
- (or (string-match "^\\(~/\\|/\\|[[:lower:][:upper:]]:/\\)"
- guess)
- (file-exists-p candidate)))
- (progn
- (delete-region beg end)
- (insert (cond (full-path-p
- (expand-file-name candidate))
- ((string= (match-string 1 guess) "~/")
- (abbreviate-file-name candidate))
- (t (file-relative-name candidate)))))
- (insert (cond ((equal helm-current-prefix-arg '(4))
- (abbreviate-file-name candidate))
- ((equal helm-current-prefix-arg '(16))
- (file-relative-name candidate))
- (t candidate))))))))
-
-(cl-defun helm-find-files-history (&key (comp-read t))
- "The `helm-find-files' history.
-Show the first `helm-ff-history-max-length' elements of
-`helm-ff-history' in an `helm-comp-read'."
- (let ((history (when helm-ff-history
- (helm-fast-remove-dups helm-ff-history
- :test 'equal))))
- (when history
- (setq helm-ff-history
- (if (>= (length history) helm-ff-history-max-length)
- (cl-subseq history 0 helm-ff-history-max-length)
- history))
- (if comp-read
- (helm-comp-read
- "Switch to Directory: "
- helm-ff-history
- :name "Helm Find Files History"
- :must-match t)
- helm-ff-history))))
-
-(defun helm-find-files-1 (fname &optional preselect)
- "Find FNAME with `helm' completion.
-Like `find-file' but with `helm' support.
-Use it for non--interactive calls of `helm-find-files'."
- (when (get-buffer helm-action-buffer)
- (kill-buffer helm-action-buffer))
- (setq helm-find-files--toggle-bookmark nil)
- (let* ( ;; Be sure we don't erase the precedent minibuffer if some.
- (helm-ff-auto-update-initial-value
- (and helm-ff-auto-update-initial-value
- (not (minibuffer-window-active-p (minibuffer-window)))))
- (tap (thing-at-point 'filename))
- (def (and tap (or (file-remote-p tap)
- (expand-file-name tap)))))
- (unless helm-source-find-files
- (setq helm-source-find-files (helm-make-source
- "Find Files" 'helm-source-ffiles)))
- (mapc (lambda (hook)
- (add-hook 'helm-after-update-hook hook))
- '(helm-ff-move-to-first-real-candidate
- helm-ff-update-when-only-one-matched
- helm-ff-auto-expand-to-home-or-root))
- (unwind-protect
- (helm :sources 'helm-source-find-files
- :input fname
- :case-fold-search helm-file-name-case-fold-search
- :preselect preselect
- :ff-transformer-show-only-basename
- helm-ff-transformer-show-only-basename
- :default def
- :prompt "Find files or url: "
- :buffer "*helm find files*")
- (helm-attrset 'resume `(lambda ()
- (setq helm-ff-default-directory
- ,helm-ff-default-directory
- helm-ff-last-expanded
- ,helm-ff-last-expanded))
- helm-source-find-files)
- (setq helm-ff-default-directory nil))))
-
-(defun helm-find-files-cleanup ()
- (mapc (lambda (hook)
- (remove-hook 'helm-after-update-hook hook))
- '(helm-ff-auto-expand-to-home-or-root
- helm-ff-update-when-only-one-matched
- helm-ff-move-to-first-real-candidate)))
-
-(defun helm-find-files-toggle-to-bookmark ()
- "Toggle helm-bookmark for `helm-find-files' and `helm-find-files.'"
- (interactive)
- (with-helm-alive-p
- (with-helm-buffer
- (if (setq helm-find-files--toggle-bookmark
- (not helm-find-files--toggle-bookmark))
- (progn
- (helm-set-pattern "" t)
- (helm-set-sources '(helm-source-bookmark-helm-find-files)))
- ;; Switch back to helm-find-files.
- (helm-set-pattern "./" t) ; Back to initial directory of hff session.
- (helm-set-sources '(helm-source-find-files))
- (helm--maybe-update-keymap)))))
-(put 'helm-find-files-toggle-to-bookmark 'helm-only t)
-
-(defun helm-find-files-initial-input (&optional input)
- "Return INPUT if present, otherwise try to guess it."
- (let ((ffap-machine-p-known 'reject)
- (ffap-alist (and helm-ff-guess-ffap-filenames ffap-alist))
- (ffap-url-regexp (and helm-ff-guess-ffap-urls ffap-url-regexp)))
- (unless (eq major-mode 'image-mode)
- (or (and input (or (and (file-remote-p input) input)
- (expand-file-name input)))
- (helm-find-files-input
- (ffap-guesser)
- (thing-at-point 'filename))))))
-
-(defun helm-find-files-input (file-at-pt thing-at-pt)
- "Try to guess a default input for `helm-find-files'."
- (let* ((non-essential t)
- (remp (or (and file-at-pt (file-remote-p file-at-pt))
- (and thing-at-pt (file-remote-p thing-at-pt))))
- (def-dir (helm-current-directory))
- (urlp (and file-at-pt ffap-url-regexp
- (string-match ffap-url-regexp file-at-pt)))
- (lib (when helm-ff-search-library-in-sexp
- (helm-find-library-at-point)))
- (hlink (helm-ff-find-url-at-point))
- (file-p (and file-at-pt
- (not (string= file-at-pt ""))
- (not remp)
- (file-exists-p file-at-pt)
- thing-at-pt
- (not (string= thing-at-pt ""))
- (file-exists-p
- (file-name-directory
- (expand-file-name thing-at-pt def-dir))))))
- (cond (lib) ; e.g we are inside a require sexp.
- (hlink) ; String at point is an hyperlink.
- (file-p ; a regular file
- (helm-aif (ffap-file-at-point) (expand-file-name it)))
- (urlp file-at-pt) ; possibly an url or email.
- ((and file-at-pt
- (not remp)
- (file-exists-p file-at-pt))
- (expand-file-name file-at-pt)))))
-
-(defun helm-ff-find-url-at-point ()
- "Try to find link to an url in text-property at point."
- (let* ((he (get-text-property (point) 'help-echo))
- (ov (overlays-at (point)))
- (ov-he (and ov (overlay-get
- (car (overlays-at (point))) 'help-echo)))
- (w3m-l (get-text-property (point) 'w3m-href-anchor))
- (nt-prop (get-text-property (point) 'nt-link)))
- ;; Org link.
- (when (and (stringp he) (string-match "^LINK: " he))
- (setq he (replace-match "" t t he)))
- (cl-loop for i in (list he ov-he w3m-l nt-prop)
- thereis (and (stringp i) ffap-url-regexp (string-match ffap-url-regexp i) i))))
-
-(defun helm-find-library-at-point ()
- "Try to find library path at point.
-Find inside `require' and `declare-function' sexp."
- (require 'find-func)
- (let* ((beg-sexp (save-excursion (search-backward "(" (point-at-bol) t)))
- (end-sexp (save-excursion (search-forward ")" (point-at-eol) t)))
- (sexp (and beg-sexp end-sexp
- (buffer-substring-no-properties
- (1+ beg-sexp) (1- end-sexp)))))
- (ignore-errors
- (cond ((and sexp (string-match "require \'.+[^)]" sexp))
- (find-library-name
- (replace-regexp-in-string
- "'\\|\)\\|\(" ""
- ;; If require use third arg, ignore it,
- ;; always use library path found in `load-path'.
- (cl-second (split-string (match-string 0 sexp))))))
- ((and sexp (string-match-p "^declare-function" sexp))
- (find-library-name
- (replace-regexp-in-string
- "\"\\|ext:" ""
- (cl-third (split-string sexp)))))
- (t nil)))))
-
-\f
-;;; Handle copy, rename, symlink, relsymlink and hardlink from helm.
-;;
-;;
-(defun helm-ff--valid-default-directory ()
- (with-helm-current-buffer
- (cl-loop for b in (buffer-list)
- for cd = (with-current-buffer b default-directory)
- when (eq (car (file-attributes cd)) t)
- return cd)))
-
-(cl-defun helm-dired-action (candidate
- &key action follow (files (dired-get-marked-files)))
- "Execute ACTION on FILES to CANDIDATE.
-Where ACTION is a symbol that can be one of:
-'copy, 'rename, 'symlink,'relsymlink, 'hardlink or 'backup.
-Argument FOLLOW when non--nil specify to follow FILES to destination for the actions
-copy and rename."
- (when (get-buffer dired-log-buffer) (kill-buffer dired-log-buffer))
- ;; When default-directory in current-buffer is an invalid directory,
- ;; (e.g buffer-file directory have been renamed somewhere else)
- ;; be sure to use a valid value to give to dired-create-file.
- ;; i.e start-process is creating a process buffer based on default-directory.
- (let ((default-directory (helm-ff--valid-default-directory))
- (fn (cl-case action
- (copy 'dired-copy-file)
- (rename 'dired-rename-file)
- (symlink 'make-symbolic-link)
- (relsymlink 'dired-make-relative-symlink)
- (hardlink 'dired-hardlink)
- (backup 'backup-file)))
- (marker (cl-case action
- ((copy rename backup) dired-keep-marker-copy)
- (symlink dired-keep-marker-symlink)
- (relsymlink dired-keep-marker-relsymlink)
- (hardlink dired-keep-marker-hardlink)))
- (dirflag (and (= (length files) 1)
- (file-directory-p (car files))
- (not (file-directory-p candidate))))
- (dired-async-state (if (and (boundp 'dired-async-mode)
- dired-async-mode)
- 1 -1)))
- (and follow (fboundp 'dired-async-mode) (dired-async-mode -1))
- (when (and (cdr files) (not (file-directory-p candidate)))
- (error "%s: target `%s' is not a directory" action candidate))
- (unwind-protect
- (dired-create-files
- fn (symbol-name action) files
- ;; CANDIDATE is the destination.
- (if (file-directory-p candidate)
- ;; When CANDIDATE is a directory, build file-name in this directory.
- ;; Else we use CANDIDATE.
- (lambda (from)
- (expand-file-name (file-name-nondirectory from) candidate))
- (lambda (_from) candidate))
- marker)
- (and (fboundp 'dired-async-mode)
- (dired-async-mode dired-async-state)))
- (push (file-name-as-directory
- (if (file-directory-p candidate)
- (expand-file-name candidate)
- (file-name-directory candidate)))
- helm-ff-history)
- ;; If follow is non--nil we should not be in async mode.
- (when (and follow
- (not (memq action '(symlink relsymlink hardlink)))
- (not (get-buffer dired-log-buffer)))
- (let ((target (directory-file-name candidate)))
- (unwind-protect
- (progn
- (setq helm-ff-cand-to-mark
- (helm-get-dest-fnames-from-list files candidate dirflag))
- (with-helm-after-update-hook (helm-ff-maybe-mark-candidates))
- (if (and dirflag (eq action 'rename))
- (helm-find-files-1 (file-name-directory target)
- (if helm-ff-transformer-show-only-basename
- (helm-basename target) target))
- (helm-find-files-1 (file-name-as-directory
- (expand-file-name candidate)))))
- (setq helm-ff-cand-to-mark nil))))))
-
-(defun helm-get-dest-fnames-from-list (flist dest-cand rename-dir-flag)
- "Transform filenames of FLIST to abs of DEST-CAND.
-If RENAME-DIR-FLAG is non--nil collect the `directory-file-name' of transformed
-members of FLIST."
- ;; At this point files have been renamed/copied at destination.
- ;; That's mean DEST-CAND exists.
- (cl-loop
- with dest = (expand-file-name dest-cand)
- for src in flist
- for basename-src = (helm-basename src)
- for fname = (cond (rename-dir-flag (directory-file-name dest))
- ((file-directory-p dest)
- (concat (file-name-as-directory dest) basename-src))
- (t dest))
- when (file-exists-p fname)
- collect fname into tmp-list
- finally return (sort tmp-list 'string<)))
-
-(defun helm-ff-maybe-mark-candidates ()
- "Mark all candidates of list `helm-ff-cand-to-mark'.
-This is used when copying/renaming/symlinking etc... and
-following files to destination."
- (when (and (string= (assoc-default 'name (helm-get-current-source))
- (assoc-default 'name helm-source-find-files))
- helm-ff-cand-to-mark)
- (with-helm-window
- (while helm-ff-cand-to-mark
- (if (string= (car helm-ff-cand-to-mark) (helm-get-selection))
- (progn
- (helm-make-visible-mark)
- (helm-next-line)
- (setq helm-ff-cand-to-mark (cdr helm-ff-cand-to-mark)))
- (helm-next-line)))
- (unless (helm-this-visible-mark)
- (helm-prev-visible-mark)))))
-
-\f
-;;; Routines for files
-;;
-;;
-(defun helm-file-buffers (filename)
- "Returns a list of buffer names corresponding to FILENAME."
- (cl-loop with name = (expand-file-name filename)
- for buf in (buffer-list)
- for bfn = (buffer-file-name buf)
- when (and bfn (string= name bfn))
- collect (buffer-name buf)))
-
-(defun helm-delete-file (file &optional error-if-dot-file-p synchro)
- "Delete the given file after querying the user.
-Ask to kill buffers associated with that file, too."
- (when (and error-if-dot-file-p
- (helm-ff-dot-file-p file))
- (error "Error: Cannot operate on `.' or `..'"))
- (let ((buffers (helm-file-buffers file))
- (helm--reading-passwd-or-string t))
- (if (or (< emacs-major-version 24) synchro)
- ;; `dired-delete-file' in Emacs versions < 24
- ;; doesn't support delete-by-moving-to-trash
- ;; so use `delete-directory' and `delete-file'
- ;; that handle it.
- (cond ((and (not (file-symlink-p file))
- (file-directory-p file)
- (directory-files file t dired-re-no-dot))
- (when (y-or-n-p (format "Recursive delete of `%s'? " file))
- (delete-directory file 'recursive)))
- ((and (not (file-symlink-p file))
- (file-directory-p file))
- (delete-directory file))
- (t (delete-file file)))
- (dired-delete-file
- file dired-recursive-deletes delete-by-moving-to-trash))
- (when buffers
- (cl-dolist (buf buffers)
- (when (y-or-n-p (format "Kill buffer %s, too? " buf))
- (kill-buffer buf))))))
-
-(defun helm-delete-marked-files (_ignore)
- (let* ((files (helm-marked-candidates :with-wildcard t))
- (len (length files)))
- (with-helm-display-marked-candidates
- helm-marked-buffer-name
- (helm-ff--count-and-collect-dups files)
- (if (not (y-or-n-p (format "Delete *%s File(s)" len)))
- (message "(No deletions performed)")
- (cl-dolist (i files)
- (set-text-properties 0 (length i) nil i)
- (helm-delete-file i helm-ff-signal-error-on-dot-files))
- (message "%s File(s) deleted" len)))))
-
-(defun helm-find-file-or-marked (candidate)
- "Open file CANDIDATE or open helm marked files in separate windows.
-Called with a prefix arg open files in background without selecting them."
- (let ((marked (helm-marked-candidates :with-wildcard t))
- (url-p (and ffap-url-regexp ; we should have only one candidate.
- (string-match ffap-url-regexp candidate)))
- (ffap-newfile-prompt helm-ff-newfile-prompt-p)
- (find-file-wildcards nil)
- (make-dir-fn
- (lambda (dir &optional helm-ff)
- (when (or (not confirm-nonexistent-file-or-buffer)
- (y-or-n-p (format "Create directory `%s'? " dir)))
- (let ((dirfname (directory-file-name dir)))
- (if (file-exists-p dirfname)
- (error
- "Mkdir: Unable to create directory `%s': file exists."
- (helm-basename dirfname))
- (make-directory dir 'parent)))
- (when helm-ff
- ;; Allow having this new dir in history
- ;; to be able to retrieve it immediately
- ;; if we want to e.g copy a file from somewhere in it.
- (setq helm-ff-default-directory
- (file-name-as-directory dir))
- (push helm-ff-default-directory helm-ff-history))
- (or (and helm-ff (helm-find-files-1 dir)) t))))
- (helm--reading-passwd-or-string t))
- (if (cdr marked)
- (if helm-current-prefix-arg
- (dired-simultaneous-find-file marked nil)
- (mapc 'find-file-noselect (cdr marked))
- (find-file (car marked)))
- (if (and (not (file-exists-p candidate))
- (not url-p)
- (string-match "/$" candidate))
- ;; A a non--existing filename ending with /
- ;; Create a directory and jump to it.
- (funcall make-dir-fn candidate 'helm-ff)
- ;; A non--existing filename NOT ending with / or
- ;; an existing filename, create or jump to it.
- ;; If the basedir of candidate doesn't exists,
- ;; ask for creating it.
- (let ((dir (and (not url-p) (helm-basedir candidate))))
- (find-file-at-point
- (cond ((and dir (file-directory-p dir))
- (substitute-in-file-name candidate))
- (url-p candidate)
- ((funcall make-dir-fn dir) candidate))))))))
-
-(defun helm-shadow-boring-files (files)
- "Files matching `helm-boring-file-regexp' will be
-displayed with the `file-name-shadow' face if available."
- (helm-shadow-entries files helm-boring-file-regexp-list))
-
-(defun helm-skip-boring-files (files)
- "Files matching `helm-boring-file-regexp' will be skipped."
- (helm-skip-entries files helm-boring-file-regexp-list))
-
-(defun helm-skip-current-file (files)
- "Current file will be skipped."
- (remove (buffer-file-name helm-current-buffer) files))
-
-(defun helm-w32-pathname-transformer (args)
- "Change undesirable features of windows pathnames to ones more acceptable to
-other candidate transformers."
- (if (eq system-type 'windows-nt)
- (helm-transform-mapcar
- (lambda (x)
- (replace-regexp-in-string
- "/cygdrive/\\(.\\)" "\\1:"
- (replace-regexp-in-string "\\\\" "/" x)))
- args)
- args))
-
-(defun helm-transform-file-load-el (actions candidate)
- "Add action to load the file CANDIDATE if it is an emacs lisp
-file. Else return ACTIONS unmodified."
- (if (member (file-name-extension candidate) '("el" "elc"))
- (append actions '(("Load Emacs Lisp File" . load-file)))
- actions))
-
-(defun helm-transform-file-browse-url (actions candidate)
- "Add an action to browse the file CANDIDATE if it is a html file or URL.
-Else return ACTIONS unmodified."
- (let ((browse-action '("Browse with Browser" . browse-url)))
- (cond ((string-match "^http\\|^ftp" candidate)
- (cons browse-action actions))
- ((string-match "\\.html?$" candidate)
- (append actions (list browse-action)))
- (t actions))))
-
-(defun helm-multi-files-toggle-to-locate ()
- (interactive)
- (with-helm-alive-p
- (with-helm-buffer
- (if (setq helm-multi-files--toggle-locate
- (not helm-multi-files--toggle-locate))
- (progn
- (helm-set-sources (unless (memq 'helm-source-locate
- helm-sources)
- (cons 'helm-source-locate helm-sources)))
- (helm-set-source-filter '(helm-source-locate)))
- (helm-kill-async-processes)
- (helm-set-sources (remove 'helm-source-locate
- helm-for-files-preferred-list))
- (helm-set-source-filter nil)))))
-(put 'helm-multi-files-toggle-to-locate 'helm-only t)
-
-\f
-;;; List of files gleaned from every dired buffer
-;;
-;;
-(defun helm-files-in-all-dired-candidates ()
- (save-excursion
- (cl-loop for (f . b) in dired-buffers
- when (buffer-live-p b)
- append (let ((dir (with-current-buffer b dired-directory)))
- (if (listp dir) (cdr dir)
- (directory-files f t dired-re-no-dot))))))
-
-;; (dired '("~/" "~/.emacs.d/.emacs-custom.el" "~/.emacs.d/.emacs.bmk"))
-
-(defclass helm-files-dired-source (helm-source-sync helm-type-file)
- ((candidates :initform #'helm-files-in-all-dired-candidates)))
-
-(defvar helm-source-files-in-all-dired
- (helm-make-source "Files in all dired buffer." 'helm-files-dired-source))
-
-\f
-;;; File Cache
-;;
-;;
-(defvar file-cache-alist)
-
-(defclass helm-file-cache (helm-source-in-buffer helm-type-file)
- ((init :initform (lambda () (require 'filecache)))))
-
-(defun helm-file-cache-get-candidates ()
- (cl-loop for item in file-cache-alist append
- (cl-destructuring-bind (base &rest dirs) item
- (cl-loop for dir in dirs collect
- (concat dir base)))))
-
-(defvar helm-source-file-cache nil)
-
-(defcustom helm-file-cache-fuzzy-match nil
- "Enable fuzzy matching in `helm-source-file-cache' when non--nil."
- :group 'helm-files
- :type 'boolean
- :set (lambda (var val)
- (set var val)
- (setq helm-source-file-cache
- (helm-make-source "File Cache" 'helm-file-cache
- :fuzzy-match helm-file-cache-fuzzy-match
- :data 'helm-file-cache-get-candidates))))
-
-(cl-defun helm-file-cache-add-directory-recursively
- (dir &optional match (ignore-dirs t))
- (require 'filecache)
- (cl-loop for f in (helm-walk-directory
- dir
- :path 'full
- :directories nil
- :match match
- :skip-subdirs ignore-dirs)
- do (file-cache-add-file f)))
-
-(defun helm-ff-cache-add-file (_candidate)
- (require 'filecache)
- (let ((mkd (helm-marked-candidates :with-wildcard t)))
- (mapc 'file-cache-add-file mkd)))
-
-(defun helm-ff-file-cache-remove-file-1 (file)
- "Remove FILE from `file-cache-alist'."
- (let ((entry (assoc (helm-basename file) file-cache-alist))
- (dir (helm-basedir file))
- new-entry)
- (setq new-entry (remove dir entry))
- (when (= (length entry) 1)
- (setq new-entry nil))
- (setq file-cache-alist
- (cons new-entry (remove entry file-cache-alist)))))
-
-(defun helm-ff-file-cache-remove-file (_file)
- "Remove marked files from `file-cache-alist.'"
- (let ((mkd (helm-marked-candidates)))
- (mapc 'helm-ff-file-cache-remove-file-1 mkd)))
-
-(defun helm-transform-file-cache (actions _candidate)
- (let ((source (helm-get-current-source)))
- (if (string= (assoc-default 'name source) "File Cache")
- (append actions
- '(("Remove marked files from file-cache"
- . helm-ff-file-cache-remove-file)))
- actions)))
-
-\f
-;;; File name history
-;;
-;;
-(defvar helm-source-file-name-history
- (helm-build-sync-source "File Name History"
- :candidates 'file-name-history
- :persistent-action #'ignore
- :filtered-candidate-transformer #'helm-file-name-history-transformer
- :action 'helm-type-file-actions))
-
-(defvar helm-source--ff-file-name-history nil
- "[Internal] This source is build to be used with `helm-find-files'.
-Don't use it in your own code unless you know what you are doing.")
-
-(defun helm-file-name-history-transformer (candidates _source)
- (cl-loop for c in candidates collect
- (cond ((file-remote-p c)
- (cons (propertize c 'face 'helm-history-remote) c))
- ((file-exists-p c)
- (cons (propertize c 'face 'helm-ff-file) c))
- (t (cons (propertize c 'face 'helm-history-deleted) c)))))
-
-(defun helm-ff-file-name-history ()
- "Switch to `file-name-history' without quitting `helm-find-files'."
- (interactive)
- (unless helm-source--ff-file-name-history
- (setq helm-source--ff-file-name-history
- (helm-build-sync-source "File name history"
- :init (lambda ()
- (with-helm-alive-p
- (when helm-ff-file-name-history-use-recentf
- (require 'recentf)
- (or recentf-mode (recentf-mode 1)))))
- :candidates (lambda ()
- (if helm-ff-file-name-history-use-recentf
- recentf-list
- file-name-history))
- :fuzzy-match t
- :persistent-action 'ignore
- :migemo t
- :filtered-candidate-transformer 'helm-file-name-history-transformer
- :action (helm-make-actions
- "Find file" (lambda (candidate)
- (helm-set-pattern
- (expand-file-name candidate))
- (with-helm-after-update-hook (helm-exit-minibuffer)))
- "Find file in helm" (lambda (candidate)
- (helm-set-pattern
- (expand-file-name candidate)))))))
- (with-helm-alive-p
- (helm :sources 'helm-source--ff-file-name-history
- :buffer "*helm-file-name-history*"
- :allow-nest t
- :resume 'noresume)))
-(put 'helm-ff-file-name-history 'helm-only t)
-
-;;; Recentf files
-;;
-;;
-(defvar helm-recentf--basename-flag nil)
-
-(defun helm-recentf-pattern-transformer (pattern)
- (let ((pattern-no-flag (replace-regexp-in-string " -b" "" pattern)))
- (cond ((and (string-match " " pattern-no-flag)
- (string-match " -b\\'" pattern))
- (setq helm-recentf--basename-flag t)
- pattern-no-flag)
- ((string-match "\\([^ ]*\\) -b\\'" pattern)
- (prog1 (match-string 1 pattern)
- (setq helm-recentf--basename-flag t)))
- (t (setq helm-recentf--basename-flag nil)
- pattern))))
-
-(defcustom helm-turn-on-recentf t
- "Automatically turn on `recentf-mode' when non-nil."
- :group 'helm-files
- :type 'boolean)
-
-(defclass helm-recentf-source (helm-source-sync helm-type-file)
- ((init :initform (lambda ()
- (require 'recentf)
- (when helm-turn-on-recentf (recentf-mode 1))))
- (candidates :initform (lambda () recentf-list))
- (pattern-transformer :initform 'helm-recentf-pattern-transformer)
- (match-part :initform (lambda (candidate)
- (if (or helm-ff-transformer-show-only-basename
- helm-recentf--basename-flag)
- (helm-basename candidate) candidate)))
- (migemo :initform t)
- (persistent-action :initform 'helm-ff-kill-or-find-buffer-fname)))
-
-(defmethod helm--setup-source :after ((source helm-recentf-source))
- (setf (slot-value source 'action)
- (append (symbol-value (helm-actions-from-type-file))
- '(("Delete file(s) from recentf" .
- (lambda (_candidate)
- (cl-loop for file in (helm-marked-candidates)
- do (setq recentf-list (delq file recentf-list)))))))))
-
-(defvar helm-source-recentf nil
- "See (info \"(emacs)File Conveniences\").
-Set `recentf-max-saved-items' to a bigger value if default is too small.")
-
-(defcustom helm-recentf-fuzzy-match nil
- "Enable fuzzy matching in `helm-source-recentf' when non--nil."
- :group 'helm-files
- :type 'boolean
- :set (lambda (var val)
- (set var val)
- (setq helm-source-recentf
- (helm-make-source "Recentf" 'helm-recentf-source
- :fuzzy-match helm-recentf-fuzzy-match))))
-
-;;; Browse project
-;; Need dependencies:
-;; <https://github.com/emacs-helm/helm-ls-git>
-;; <https://github.com/emacs-helm/helm-ls-hg>
-;; Only hg and git are supported for now.
-(defvar helm--browse-project-cache (make-hash-table :test 'equal))
-(defvar helm-buffers-in-project-p)
-
-(defun helm-browse-project-get-buffers (root-directory)
- (cl-loop for b in (helm-buffer-list)
- ;; FIXME: Why default-directory is root-directory
- ;; for current-buffer when coming from helm-quit-and-find-file.
- for cd = (with-current-buffer b default-directory)
- for bn = (buffer-file-name (get-buffer b))
- if (or (and bn (file-in-directory-p bn root-directory))
- (and (null bn)
- (file-in-directory-p cd root-directory)))
- collect b))
-
-(defun helm-browse-project-build-buffers-source (directory)
- (helm-make-source "Buffers in project" 'helm-source-buffers
- :header-name (lambda (name)
- (format
- "%s (%s)"
- name (abbreviate-file-name directory)))
- :buffer-list (lambda () (helm-browse-project-get-buffers directory))))
-
-(defun helm-browse-project-find-files (directory &optional refresh)
- (when refresh (remhash directory helm--browse-project-cache))
- (unless (gethash directory helm--browse-project-cache)
- (puthash directory (helm-walk-directory
- directory
- :directories nil :path 'full :skip-subdirs t)
- helm--browse-project-cache))
- (helm :sources `(,(helm-browse-project-build-buffers-source directory)
- ,(helm-build-in-buffer-source "Browse project"
- :data (gethash directory helm--browse-project-cache)
- :header-name (lambda (name)
- (format
- "%s (%s)"
- name (abbreviate-file-name directory)))
- :match-part (lambda (c)
- (if (with-helm-buffer
- helm-ff-transformer-show-only-basename)
- (helm-basename c) c))
- :filter-one-by-one
- (lambda (c)
- (if (with-helm-buffer
- helm-ff-transformer-show-only-basename)
- (cons (propertize (helm-basename c)
- 'face 'helm-ff-file)
- c)
- (propertize c 'face 'helm-ff-file)))
- :keymap helm-generic-files-map
- :action 'helm-type-file-actions))
- :ff-transformer-show-only-basename nil
- :buffer "*helm browse project*"))
-
-;;;###autoload
-(defun helm-browse-project (arg)
- "Preconfigured helm to browse projects.
-Browse files and see status of project with its vcs.
-Only HG and GIT are supported for now.
-Fall back to `helm-browse-project-find-files'
-if current directory is not under control of one of those vcs.
-With a prefix ARG browse files recursively, with two prefix ARG
-rebuild the cache.
-If the current directory is found in the cache, start
-`helm-browse-project-find-files' even with no prefix ARG.
-NOTE: The prefix ARG have no effect on the VCS controlled directories.
-
-Needed dependencies for VCS:
-<https://github.com/emacs-helm/helm-ls-git>
-and
-<https://github.com/emacs-helm/helm-ls-hg>
-and
-<http://melpa.org/#/helm-ls-svn>."
- (interactive "P")
- (let ((helm-type-buffer-actions
- (remove (assoc "Browse project from buffer"
- helm-type-buffer-actions)
- helm-type-buffer-actions))
- (helm-buffers-in-project-p t))
- (cond ((and (require 'helm-ls-git nil t)
- (fboundp 'helm-ls-git-root-dir)
- (helm-ls-git-root-dir))
- (helm-ls-git-ls))
- ((and (require 'helm-ls-hg nil t)
- (fboundp 'helm-hg-root)
- (helm-hg-root))
- (helm-hg-find-files-in-project))
- ((and (require 'helm-ls-svn nil t)
- (fboundp 'helm-ls-svn-root-dir)
- (helm-ls-svn-root-dir))
- (helm-ls-svn-ls))
- (t (let ((cur-dir (helm-browse-project-get--root-dir
- (helm-current-directory))))
- (if (or arg (gethash cur-dir helm--browse-project-cache))
- (helm-browse-project-find-files cur-dir (equal arg '(16)))
- (helm :sources (helm-browse-project-build-buffers-source cur-dir)
- :buffer "*helm browse project*")))))))
-
-(defun helm-browse-project-get--root-dir (directory)
- (cl-loop with dname = (file-name-as-directory directory)
- while (and dname (not (gethash dname helm--browse-project-cache)))
- if (file-remote-p dname)
- do (setq dname nil) else
- do (setq dname (helm-basedir (substring dname 0 (1- (length dname)))))
- finally return (or dname (file-name-as-directory directory))))
-
-(defun helm-ff-browse-project (_candidate)
- "Browse project in current directory.
-See `helm-browse-project'."
- (with-helm-default-directory helm-ff-default-directory
- (helm-browse-project helm-current-prefix-arg)))
-
-(defun helm-ff-run-browse-project ()
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-ff-browse-project)))
-(put 'helm-ff-run-browse-project 'helm-only t)
-
-(defun helm-ff-gid (_candidate)
- (with-helm-default-directory helm-ff-default-directory
- (helm-gid)))
-
-(defun helm-ff-run-gid ()
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-ff-gid)))
-(put 'helm-ff-run-gid 'helm-only t)
-
-;;; session.el files
-;;
-;; session (http://emacs-session.sourceforge.net/) is an alternative to
-;; recentf that saves recent file history and much more.
-(defvar session-file-alist)
-(defvar helm-source-session
- (helm-build-sync-source "Session"
- :candidates (lambda ()
- (cl-delete-if-not (lambda (f)
- (or (string-match helm-tramp-file-name-regexp f)
- (file-exists-p f)))
- (mapcar 'car session-file-alist)))
- :keymap helm-generic-files-map
- :help-message helm-generic-file-help-message
- :action 'helm-type-file-actions)
- "File list from emacs-session.")
-
-\f
-;;; Files in current dir
-;;
-;;
-(defun helm-highlight-files (files)
- "A basic transformer for helm files sources.
-Colorize only symlinks, directories and files."
- (cl-loop for i in files
- for disp = (if (and helm-ff-transformer-show-only-basename
- (not (helm-dir-is-dot i))
- (not (and ffap-url-regexp
- (string-match ffap-url-regexp i)))
- (not (string-match helm-ff-url-regexp i)))
- (helm-basename i) i)
- for type = (and (null helm-ff-tramp-not-fancy)
- (car (file-attributes i)))
- collect
- (cond ((and helm-ff-tramp-not-fancy
- (string-match helm-tramp-file-name-regexp i))
- (cons disp i))
- ((stringp type)
- (cons (propertize disp
- 'face 'helm-ff-symlink
- 'help-echo (expand-file-name i))
- i))
- ((eq type t)
- (cons (propertize disp
- 'face 'helm-ff-directory
- 'help-echo (expand-file-name i))
- i))
- (t (cons (propertize disp
- 'face 'helm-ff-file
- 'help-echo (expand-file-name i))
- i)))))
-
-(defclass helm-files-in-current-dir-source (helm-source-sync helm-type-file)
- ((candidates :initform (lambda ()
- (with-helm-current-buffer
- (let ((dir (helm-current-directory)))
- (when (file-accessible-directory-p dir)
- (directory-files dir t))))))
- (pattern-transformer :initform 'helm-recentf-pattern-transformer)
- (match-part :initform (lambda (candidate)
- (if (or helm-ff-transformer-show-only-basename
- helm-recentf--basename-flag)
- (helm-basename candidate) candidate)))
- (fuzzy-match :initform t)
- (migemo :initform t)))
-
-(defvar helm-source-files-in-current-dir
- (helm-make-source "Files from Current Directory"
- helm-files-in-current-dir-source))
-
-\f
-;;; External searching file tools.
-;;
-;; Tracker desktop search
-(defvar helm-source-tracker-cand-incomplete nil "Contains incomplete candidate")
-(defun helm-source-tracker-transformer (candidates _source)
- (helm-log "received: %S" candidates)
- (cl-loop for cand in candidates
- for path = (when (stringp helm-source-tracker-cand-incomplete)
- (caar (helm-highlight-files
- (list helm-source-tracker-cand-incomplete))))
- for built = (if (not (stringp cand)) cand
- (let ((snippet cand))
- (unless (or (null path)
- (string= "" path)
- (not (string-match-p
- "\\`[[:space:]]*\\.\\.\\."
- snippet)))
- (let ((complete-candidate
- (cons (concat path "\n" snippet) path)))
- (setq helm-source-tracker-cand-incomplete nil)
- (helm-log "built: %S" complete-candidate)
- complete-candidate))))
- when (and (stringp cand)
- (string-match "\\`[[:space:]]*file://" cand))
- do (setq helm-source-tracker-cand-incomplete ; save path
- (replace-match "" t t cand)) end
- collect built))
-
-(defvar helm-source-tracker-search
- (helm-build-async-source "Tracker Search"
- :candidates-process
- (lambda ()
- (start-process "tracker-search-process" nil
- "tracker-search"
- "--disable-color"
- "--limit=512"
- helm-pattern))
- :filtered-candidate-transformer #'helm-source-tracker-transformer
- ;;(multiline) ; https://github.com/emacs-helm/helm/issues/529
- :keymap helm-generic-files-map
- :action 'helm-type-file-actions
- :action-transformer '(helm-transform-file-load-el
- helm-transform-file-browse-url)
- :requires-pattern 3)
- "Source for retrieving files matching the current input pattern
-with the tracker desktop search.")
-
-;; Spotlight (MacOS X desktop search)
-(defclass helm-mac-spotlight-source (helm-source-async helm-type-file)
- ((candidates-process :initform
- (lambda ()
- (start-process
- "mdfind-process" nil "mdfind" helm-pattern)))
- (requires-pattern :initform 3)))
-
-(defvar helm-source-mac-spotlight
- (helm-make-source "mdfind" helm-mac-spotlight-source)
- "Source for retrieving files via Spotlight's command line
-utility mdfind.")
-
-\f
-;;; Findutils
-;;
-;;
-(defvar helm-source-findutils
- (helm-build-async-source "Find"
- :header-name (lambda (name)
- (concat name " in [" (helm-default-directory) "]"))
- :candidates-process 'helm-find-shell-command-fn
- :filtered-candidate-transformer 'helm-findutils-transformer
- :action-transformer 'helm-transform-file-load-el
- :persistent-action 'helm-ff-kill-or-find-buffer-fname
- :action 'helm-type-file-actions
- :keymap helm-generic-files-map
- :candidate-number-limit 9999
- :requires-pattern 3))
-
-(defun helm-findutils-transformer (candidates _source)
- (let (non-essential
- (default-directory (helm-default-directory)))
- (cl-loop for i in candidates
- for abs = (expand-file-name
- (helm-aif (file-remote-p default-directory)
- (concat it i) i))
- for type = (car (file-attributes abs))
- for disp = (if (and helm-ff-transformer-show-only-basename
- (not (string-match "[.]\\{1,2\\}$" i)))
- (helm-basename abs) abs)
- collect (cond ((eq t type)
- (cons (propertize disp 'face 'helm-ff-directory)
- abs))
- ((stringp type)
- (cons (propertize disp 'face 'helm-ff-symlink)
- abs))
- (t (cons (propertize disp 'face 'helm-ff-file)
- abs))))))
-
-(defun helm-find--build-cmd-line ()
- (require 'find-cmd)
- (let* ((default-directory (or (file-remote-p default-directory 'localname)
- default-directory))
- (patterns+options (split-string helm-pattern "\\(\\`\\| +\\)\\* +"))
- (fold-case (helm-set-case-fold-search (car patterns+options)))
- (patterns (split-string (car patterns+options)))
- (additional-options (and (cdr patterns+options)
- (list (concat (cadr patterns+options) " "))))
- (ignored-dirs ())
- (ignored-files (when helm-findutils-skip-boring-files
- (cl-loop for f in completion-ignored-extensions
- if (string-match "/$" f)
- do (push (replace-match "" nil t f)
- ignored-dirs)
- else collect (concat "*" f))))
- (path-or-name (if helm-findutils-search-full-path
- '(ipath path) '(iname name)))
- (name-or-iname (if fold-case
- (car path-or-name) (cadr path-or-name))))
- (find-cmd (and ignored-dirs
- `(prune (name ,@ignored-dirs)))
- (and ignored-files
- `(not (name ,@ignored-files)))
- `(and ,@(mapcar
- (lambda (pattern)
- `(,name-or-iname ,(concat "*" pattern "*")))
- patterns)
- ,@additional-options))))
-
-(defun helm-find-shell-command-fn ()
- "Asynchronously fetch candidates for `helm-find'.
-Additional find options can be specified after a \"*\"
-separator."
- (let* (process-connection-type
- non-essential
- (cmd (helm-find--build-cmd-line))
- (proc (start-file-process-shell-command "hfind" helm-buffer cmd)))
- (helm-log "Find command:\n%s" cmd)
- (prog1 proc
- (set-process-sentinel
- proc
- (lambda (process event)
- (helm-process-deferred-sentinel-hook
- process event (helm-default-directory))
- (if (string= event "finished\n")
- (with-helm-window
- (setq mode-line-format
- '(" " mode-line-buffer-identification " "
- (:eval (format "L%s" (helm-candidate-number-at-point))) " "
- (:eval (propertize
- (format "[Find process finished - (%s results)]"
- (max (1- (count-lines
- (point-min) (point-max)))
- 0))
- 'face 'helm-locate-finish))))
- (force-mode-line-update))
- (helm-log "Error: Find %s"
- (replace-regexp-in-string "\n" "" event))))))))
-
-(defun helm-find-1 (dir)
- (let ((default-directory (file-name-as-directory dir)))
- (helm :sources 'helm-source-findutils
- :buffer "*helm find*"
- :ff-transformer-show-only-basename nil
- :case-fold-search helm-file-name-case-fold-search)))
-
-;; helm-find-files integration.
-(defun helm-ff-find-sh-command (_candidate)
- "Run `helm-find' from `helm-find-files'."
- (helm-find-1 helm-ff-default-directory))
-
-(defun helm-ff-run-find-sh-command ()
- "Run find shell command action with key from `helm-find-files'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-ff-find-sh-command)))
-(put 'helm-ff-run-find-sh-command 'helm-only t)
-
-\f
-;;; Preconfigured commands
-;;
-;;
-;;;###autoload
-(defun helm-find (arg)
- "Preconfigured `helm' for the find shell command.
-
-Recursively find files whose names are matched by all specified
-globbing PATTERNs under the current directory using the external
-program specified in `find-program' (usually \"find\"). Every
-input PATTERN is silently wrapped into two stars: *PATTERN*.
-
-With prefix argument, prompt for a directory to search.
-
-When user option `helm-findutils-search-full-path' is non-nil,
-match against complete paths, otherwise, against file names
-without directory part.
-
-The (possibly empty) list of globbing PATTERNs can be followed by
-the separator \"*\" plus any number of additional arguments that
-are passed to \"find\" literally."
- (interactive "P")
- (let ((directory
- (if arg
- (file-name-as-directory
- (read-directory-name "DefaultDirectory: "))
- default-directory)))
- (helm-find-1 directory)))
-
-(defvar org-directory)
-;;;###autoload
-(defun helm-find-files (arg)
- "Preconfigured `helm' for helm implementation of `find-file'.
-Called with a prefix arg show history if some.
-Don't call it from programs, use `helm-find-files-1' instead.
-This is the starting point for nearly all actions you can do on files."
- (interactive "P")
- (let* ((hist (and arg helm-ff-history (helm-find-files-history)))
- (default-input (or hist (helm-find-files-initial-input)))
- (input (cond ((and (eq major-mode 'org-agenda-mode)
- org-directory
- (not default-input))
- (expand-file-name org-directory))
- ((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)))))
- (input-as-presel (null (nth 0 (file-attributes input))))
- (presel (helm-aif (or hist
- (and input-as-presel input)
- (buffer-file-name (current-buffer))
- (and (eq major-mode 'dired-mode)
- default-input))
- (if helm-ff-transformer-show-only-basename
- (helm-basename it) it))))
- (set-text-properties 0 (length input) nil input)
- (helm-find-files-1 input (and presel (null helm-ff-no-preselect)
- (concat "^" (regexp-quote presel))))))
-
-;;;###autoload
-(defun helm-for-files ()
- "Preconfigured `helm' for opening files.
-Run all sources defined in `helm-for-files-preferred-list'."
- (interactive)
- (unless helm-source-buffers-list
- (setq helm-source-buffers-list
- (helm-make-source "Buffers" 'helm-source-buffers)))
- (helm :sources helm-for-files-preferred-list
- :ff-transformer-show-only-basename nil
- :buffer "*helm for files*"))
-
-;;;###autoload
-(defun helm-multi-files ()
- "Preconfigured helm similar to `helm-for-files' but that don't run locate.
-Allow toggling from locate to others sources.
-This allow seeing first if what you search is in other sources before launching
-locate."
- (interactive)
- (unless helm-source-buffers-list
- (setq helm-source-buffers-list
- (helm-make-source "Buffers" 'helm-source-buffers)))
- (setq helm-multi-files--toggle-locate nil)
- (let ((sources (remove 'helm-source-locate helm-for-files-preferred-list))
- (old-key (lookup-key
- helm-map
- (read-kbd-macro helm-multi-files-toggle-locate-binding))))
- (with-helm-temp-hook 'helm-after-initialize-hook
- (define-key helm-map (kbd helm-multi-files-toggle-locate-binding)
- 'helm-multi-files-toggle-to-locate))
- (unwind-protect
- (helm :sources sources
- :ff-transformer-show-only-basename nil
- :buffer "*helm multi files*")
- (define-key helm-map (kbd helm-multi-files-toggle-locate-binding)
- old-key))))
-
-;;;###autoload
-(defun helm-recentf ()
- "Preconfigured `helm' for `recentf'."
- (interactive)
- (helm :sources 'helm-source-recentf
- :ff-transformer-show-only-basename nil
- :buffer "*helm recentf*"))
-
-(provide 'helm-files)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-files.el ends here
+++ /dev/null
-;;; helm-font --- Font and ucs selection for Helm -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'helm)
-(require 'helm-help)
-
-(defgroup helm-font nil
- "Related applications to display fonts in helm."
- :group 'helm)
-
-(defvar helm-ucs-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map helm-map)
- (define-key map (kbd "<C-backspace>") 'helm-ucs-persistent-delete)
- (define-key map (kbd "<C-left>") 'helm-ucs-persistent-backward)
- (define-key map (kbd "<C-right>") 'helm-ucs-persistent-forward)
- (define-key map (kbd "<C-return>") 'helm-ucs-persistent-insert)
- map)
- "Keymap for `helm-ucs'.")
-
-(defface helm-ucs-char
- '((((class color) (background dark)) (:foreground "Gold")))
- "Face used to display ucs characters."
- :group 'helm-font)
-
-;;; Xfont selection
-;;
-;;
-(defvar helm-xfonts-cache nil)
-(defvar helm-previous-font nil)
-(defvar helm-source-xfonts
- (helm-build-sync-source "X Fonts"
- :init (lambda ()
- (unless helm-xfonts-cache
- (setq helm-xfonts-cache
- (x-list-fonts "*")))
- ;; Save current font so it can be restored in cleanup
- (setq helm-previous-font (cdr (assoc 'font (frame-parameters)))))
- :candidates 'helm-xfonts-cache
- :action '(("Copy font to kill ring" . (lambda (elm)
- (kill-new elm)))
- ("Set font" . (lambda (elm)
- (kill-new elm)
- (set-frame-font elm 'keep-size)
- (message "Font copied to kill ring"))))
- :cleanup (lambda ()
- ;; Restore previous font
- (set-frame-font helm-previous-font 'keep-size))
- :persistent-action (lambda (new-font)
- (set-frame-font new-font 'keep-size)
- (kill-new new-font))
- :persistent-help "Preview font and copy to kill-ring"))
-
-;;; 𝕌𝕔𝕤 𝕊𝕪𝕞𝕓𝕠𝕝 𝕔𝕠𝕞𝕡𝕝𝕖𝕥𝕚𝕠𝕟
-;;
-;;
-(defvar helm-ucs--max-len nil)
-(defvar helm-ucs--names nil)
-(defvar helm-ucs-history nil)
-
-(defun helm-calculate-ucs-max-len ()
- "Calculate the length of longest `ucs-names' candidate."
- (cl-loop for (_n . v) in (ucs-names)
- maximize (length (format "#x%x:" v)) into code
- maximize (max 1 (string-width (format "%c" v))) into char
- finally return (cons code char)))
-
-(defun helm-ucs-init ()
- "Initialize an helm buffer with ucs symbols.
-Only math* symbols are collected."
- (unless helm-ucs--max-len
- (setq helm-ucs--max-len
- (helm-calculate-ucs-max-len)))
- (or helm-ucs--names
- (setq helm-ucs--names
- (cl-loop for (n . v) in (ucs-names)
- for len = (length (format "#x%x:" v))
- for diff = (- (car helm-ucs--max-len) len)
- for code = (format "(#x%x): " v)
- for char = (propertize (format "%c" v)
- 'face 'helm-ucs-char)
- unless (string= "" n) collect
- (concat code (make-string diff ? )
- char " " n)))))
-
-(defun helm-ucs-forward-char (_candidate)
- (with-helm-current-buffer
- (forward-char 1)))
-
-(defun helm-ucs-backward-char (_candidate)
- (with-helm-current-buffer
- (forward-char -1)))
-
-(defun helm-ucs-delete-backward (_candidate)
- (with-helm-current-buffer
- (delete-char -1)))
-
-(defun helm-ucs-insert (candidate n)
- (when (string-match
- "^(\\(#x[a-f0-9]+\\)): *\\(.\\) *\\([^:]+\\)+"
- candidate)
- (with-helm-current-buffer
- (insert (match-string n candidate)))))
-
-(defun helm-ucs-insert-char (candidate)
- (helm-ucs-insert candidate 2))
-
-(defun helm-ucs-insert-code (candidate)
- (helm-ucs-insert candidate 1))
-
-(defun helm-ucs-insert-name (candidate)
- (helm-ucs-insert candidate 3))
-
-(defun helm-ucs-persistent-insert ()
- (interactive)
- (with-helm-alive-p
- (helm-attrset 'action-insert 'helm-ucs-insert-char)
- (helm-execute-persistent-action 'action-insert)))
-(put 'helm-ucs-persistent-insert 'helm-only t)
-
-(defun helm-ucs-persistent-forward ()
- (interactive)
- (with-helm-alive-p
- (helm-attrset 'action-forward 'helm-ucs-forward-char)
- (helm-execute-persistent-action 'action-forward)))
-(put 'helm-ucs-persistent-forward 'helm-only t)
-
-(defun helm-ucs-persistent-backward ()
- (interactive)
- (with-helm-alive-p
- (helm-attrset 'action-back 'helm-ucs-backward-char)
- (helm-execute-persistent-action 'action-back)))
-(put 'helm-ucs-persistent-backward 'helm-only t)
-
-(defun helm-ucs-persistent-delete ()
- (interactive)
- (with-helm-alive-p
- (helm-attrset 'action-delete 'helm-ucs-delete-backward)
- (helm-execute-persistent-action 'action-delete)))
-(put 'helm-ucs-persistent-delete 'helm-only t)
-
-(defvar helm-source-ucs
- (helm-build-in-buffer-source "Ucs names"
- :data #'helm-ucs-init
- :get-line #'buffer-substring
- :help-message 'helm-ucs-help-message
- :match-part (lambda (candidate) (cadr (split-string candidate ":")))
- :filtered-candidate-transformer
- (lambda (candidates _source) (sort candidates #'helm-generic-sort-fn))
- :action '(("Insert character" . helm-ucs-insert-char)
- ("Insert character name" . helm-ucs-insert-name)
- ("Insert character code in hex" . helm-ucs-insert-code)
- ("Forward char" . helm-ucs-forward-char)
- ("Backward char" . helm-ucs-backward-char)
- ("Delete char backward" . helm-ucs-delete-backward)))
- "Source for collecting `ucs-names' math symbols.")
-
-;;;###autoload
-(defun helm-select-xfont ()
- "Preconfigured `helm' to select Xfont."
- (interactive)
- (helm :sources 'helm-source-xfonts
- :buffer "*helm select xfont*"))
-
-;;;###autoload
-(defun helm-ucs ()
- "Preconfigured helm for `ucs-names' math symbols."
- (interactive)
- (let ((char (helm-aif (char-after) (string it))))
- (helm :sources 'helm-source-ucs
- :keymap helm-ucs-map
- :history 'helm-ucs-history
- :input (and char (multibyte-string-p char) char)
- :buffer "*helm ucs*")))
-
-(provide 'helm-font)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-font.el ends here
+++ /dev/null
-;;; helm-grep.el --- Helm Incremental Grep. -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Code:
-(require 'cl-lib)
-(require 'helm)
-(require 'helm-help)
-(require 'helm-regexp)
-
-;;; load wgrep proxy if it's available
-(require 'wgrep-helm nil t)
-
-(declare-function helm-buffer-list "helm-buffers")
-(declare-function helm-elscreen-find-file "helm-elscreen" (file))
-(declare-function View-quit "view")
-(declare-function doc-view-goto-page "doc-view" (page))
-(declare-function helm-mm-split-pattern "helm-multi-match")
-(declare-function helm--ansi-color-apply "helm-lib")
-(defvar helm--ansi-color-regexp)
-
-\f
-(defgroup helm-grep nil
- "Grep related Applications and libraries for Helm."
- :group 'helm)
-
-(defcustom helm-grep-default-command
- "grep --color=always -a -d skip %e -n%cH -e %p %f"
- "Default grep format command for `helm-do-grep-1'.
-Where:
-'%e' format spec is for --exclude or --include grep options or
- ack-grep --type option. (Not mandatory)
-
-'%c' format spec is for case-fold-search,
- whether to use the -i option of grep. (Not mandatory)
- When you specify this spec, helm grep will use smartcase
- that is when a upcase character is found in pattern case will
- be respected and no '-i' option will be used, otherwise, when
- no upcase character is found in pattern always use '-i'.
- If you don't want this behavior, don't use this spec and
- specify or not the '-i' option.
- Note that with ack-grep this is not needed, just specify
- the '--smart-case' option.
-
-'%p' format spec is for pattern. (Mandatory)
-
-'%f' format spec is for filenames. (Mandatory)
-
-If your grep version doesn't support the --exclude/include args
-don't specify the '%e' format spec.
-
-Helm also support ack-grep and git-grep ,
-here a default command example for ack-grep:
-
-\(setq helm-grep-default-command \"ack-grep -Hn --color --smart-case --no-group %e %p %f\"
- helm-grep-default-recurse-command \"ack-grep -H --color --smart-case --no-group %e %p %f\")
-
-You can ommit the %e spec if you don't want to be prompted for types.
-
-NOTE: Helm for ack-grep support ANSI sequences, so you can remove
-the \"--no-color\" option safely (recommended)
-However you should specify --color to enable multi matches highlighting
-because ack disable it when output is piped.
-
-Same for grep you can use safely the option \"--color=always\" (default).
-You can customize the color of matches using GREP_COLORS env var.
-e.g: \(setenv \"GREP_COLORS\" \"ms=30;43:mc=30;43:sl=01;37:cx=:fn=35:ln=32:bn=32:se=36\")
-
-To enable ANSI color in git-grep just add \"--color=always\".
-To customize the ANSI color in git-grep, GREP_COLORS have no effect,
-you will have to setup this in your .gitconfig:
-
- [color \"grep\"]
- match = black yellow
-
-where \"black\" is the foreground and \"yellow\" the background.
-See the git documentation for more infos.
-
-`helm-grep-default-command' and `helm-grep-default-recurse-command'are
-independents, so you can enable `helm-grep-default-command' with ack-grep
-and `helm-grep-default-recurse-command' with grep if you want to be faster
-on recursive grep.
-
-NOTE: Remote grepping is not available with ack-grep,
- and badly supported with grep because tramp handle badly
- repeated remote processes in a short delay (< to 5s)."
- :group 'helm-grep
- :type 'string)
-
-(defcustom helm-grep-default-recurse-command
- "grep --color=always -a -d recurse %e -n%cH -e %p %f"
- "Default recursive grep format command for `helm-do-grep-1'.
-See `helm-grep-default-command' for format specs and infos about ack-grep."
- :group 'helm-grep
- :type 'string)
-
-(defcustom helm-default-zgrep-command
- "zgrep --color=always -a -n%cH -e %p %f"
- "Default command for Zgrep.
-See `helm-grep-default-command' for infos on format specs.
-Option --color=always is supported and can be used safely
-to replace the helm internal match highlighting,
-see `helm-grep-default-command' for more infos."
- :group 'helm-grep
- :type 'string)
-
-(defcustom helm-pdfgrep-default-command
- "pdfgrep --color always -niH %s %s"
- "Default command for pdfgrep.
-Option \"--color always\" is supported starting helm version 1.7.8,
-when used matchs will be highlighted according to GREP_COLORS env var."
- :group 'helm-grep
- :type 'string)
-
-(defcustom helm-grep-use-ioccur-style-keys t
- "Use Arrow keys to jump to occurences."
- :group 'helm-grep
- :type 'boolean)
-
-(defcustom helm-pdfgrep-default-read-command nil
- "Default command to read pdf files from pdfgrep.
-Where '%f' format spec is filename and '%p' is page number.
-e.g In Ubuntu you can set it to:
-
- \"evince --page-label=%p '%f'\"
-
-If set to nil `doc-view-mode' will be used instead of an external command."
- :group 'helm-grep
- :type 'string)
-
-(defcustom helm-grep-max-length-history 100
- "Max number of elements to save in `helm-grep-history'."
- :group 'helm-grep
- :type 'integer)
-
-(defcustom helm-zgrep-file-extension-regexp
- ".*\\(\\.gz\\|\\.bz\\|\\.xz\\|\\.lzma\\)$"
- "Default file extensions zgrep will search in."
- :group 'helm-grep
- :type 'string)
-
-(defcustom helm-grep-preferred-ext nil
- "This file extension will be preselected for grep."
- :group 'helm-grep
- :type 'string)
-
-(defcustom helm-grep-save-buffer-name-no-confirm nil
- "when *hgrep* already exists,auto append suffix."
- :group 'helm-grep
- :type 'boolean)
-
-(defcustom helm-grep-ignored-files
- (cons ".#*" (delq nil (mapcar (lambda (s)
- (unless (string-match-p "/\\'" s)
- (concat "*" s)))
- completion-ignored-extensions)))
- "List of file names which `helm-grep' shall exclude."
- :group 'helm-grep
- :type '(repeat string))
-
-(defcustom helm-grep-ignored-directories
- helm-walk-ignore-directories
- "List of names of sub-directories which `helm-grep' shall not recurse into."
- :group 'helm-grep
- :type '(repeat string))
-
-(defcustom helm-grep-truncate-lines t
- "When nil the grep line that appears will not be truncated."
- :group 'helm-grep
- :type 'boolean)
-
-(defcustom helm-grep-file-path-style 'basename
- "File path display style when grep results are displayed.
-Possible value are:
- basename: displays only the filename, none of the directory path
- absolute: displays absolute path
- relative: displays relative path from root grep directory."
- :group 'helm-grep
- :type '(choice (const :tag "Basename" basename)
- (const :tag "Absolute" absolute)
- (const :tag "Relative" relative)))
-
-(defcustom helm-grep-actions
- (helm-make-actions
- "Find File" 'helm-grep-action
- "Find file other frame" 'helm-grep-other-frame
- (lambda () (and (locate-library "elscreen")
- "Find file in Elscreen"))
- 'helm-grep-jump-elscreen
- "Save results in grep buffer" 'helm-grep-save-results
- "Find file other window" 'helm-grep-other-window)
- "Actions for helm grep."
- :group 'helm-grep
- :type '(alist :key-type string :value-type function))
-
-\f
-;;; Faces
-;;
-;;
-(defgroup helm-grep-faces nil
- "Customize the appearance of helm-grep."
- :prefix "helm-"
- :group 'helm-grep
- :group 'helm-faces)
-
-(defface helm-grep-match
- '((((background light)) :foreground "#b00000")
- (((background dark)) :foreground "gold1"))
- "Face used to highlight grep matches."
- :group 'helm-grep-faces)
-
-(defface helm-grep-file
- '((t (:foreground "BlueViolet"
- :underline t)))
- "Face used to highlight grep results filenames."
- :group 'helm-grep-faces)
-
-(defface helm-grep-lineno
- '((t (:foreground "Darkorange1")))
- "Face used to highlight grep number lines."
- :group 'helm-grep-faces)
-
-(defface helm-grep-finish
- '((t (:foreground "Green")))
- "Face used in mode line when grep is finish."
- :group 'helm-grep-faces)
-
-(defface helm-grep-cmd-line
- '((t (:inherit diff-added)))
- "Face used to highlight grep command line when no results."
- :group 'helm-grep-faces)
-
-\f
-;;; Keymaps
-;;
-;;
-(defvar helm-grep-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map helm-map)
- (define-key map (kbd "M-<down>") 'helm-goto-next-file)
- (define-key map (kbd "M-<up>") 'helm-goto-precedent-file)
- (define-key map (kbd "C-c o") 'helm-grep-run-other-window-action)
- (define-key map (kbd "C-c C-o") 'helm-grep-run-other-frame-action)
- (define-key map (kbd "C-w") 'helm-yank-text-at-point)
- (define-key map (kbd "C-x C-s") 'helm-grep-run-save-buffer)
- (when helm-grep-use-ioccur-style-keys
- (define-key map (kbd "<right>") 'helm-execute-persistent-action)
- (define-key map (kbd "<left>") 'helm-grep-run-default-action))
- (delq nil map))
- "Keymap used in Grep sources.")
-
-(defvar helm-pdfgrep-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map helm-map)
- (define-key map (kbd "M-<down>") 'helm-goto-next-file)
- (define-key map (kbd "M-<up>") 'helm-goto-precedent-file)
- (define-key map (kbd "C-w") 'helm-yank-text-at-point)
- map)
- "Keymap used in pdfgrep.")
-
-(defvar helm-grep-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map (kbd "RET") 'helm-grep-mode-jump)
- (define-key map (kbd "C-o") 'helm-grep-mode-jump-other-window)
- (define-key map (kbd "<C-down>") 'helm-grep-mode-jump-other-window-forward)
- (define-key map (kbd "<C-up>") 'helm-grep-mode-jump-other-window-backward)
- (define-key map (kbd "<M-down>") 'helm-gm-next-file)
- (define-key map (kbd "<M-up>") 'helm-gm-precedent-file)
- (define-key map (kbd "M-n") 'helm-grep-mode-jump-other-window-forward)
- (define-key map (kbd "M-p") 'helm-grep-mode-jump-other-window-backward)
- (define-key map (kbd "M-N") 'helm-gm-next-file)
- (define-key map (kbd "M-P") 'helm-gm-precedent-file)
- map))
-
-\f
-;;; Internals vars
-;;
-;;
-(defvar helm-rzgrep-cache (make-hash-table :test 'equal))
-(defvar helm-grep-default-function 'helm-grep-init)
-(defvar helm-zgrep-recurse-flag nil)
-(defvar helm-grep-history nil)
-(defvar helm-grep-last-targets nil)
-(defvar helm-grep-include-files nil)
-(defvar helm-grep-in-recurse nil)
-(defvar helm-grep-use-zgrep nil)
-(defvar helm-grep-default-directory-fn nil
- "A function that should return a directory to expand candidate to.
-It is intended to use as a let-bound variable, DON'T set this globaly.")
-(defvar helm-pdfgrep-targets nil)
-(defvar helm-grep-last-cmd-line nil)
-(defvar helm-grep-split-line-regexp "^\\([[:lower:][:upper:]]?:?.*?\\):\\([0-9]+\\):\\(.*\\)")
-
-\f
-;;; Init
-;;
-;;
-(defun helm-grep-prepare-candidates (candidates in-directory)
- "Prepare filenames and directories CANDIDATES for grep command line."
- ;; If one or more candidate is a directory, search in all files
- ;; of this candidate (e.g /home/user/directory/*).
- ;; If r option is enabled search also in subdidrectories.
- ;; We need here to expand wildcards to support crap windows filenames
- ;; as grep doesn't accept quoted wildcards (e.g "dir/*.el").
- (if helm-zgrep-recurse-flag
- (mapconcat 'shell-quote-argument candidates " ")
- ;; When candidate is a directory, search in all its files.
- ;; NOTE that `file-expand-wildcards' will return also
- ;; directories, they will be ignored by grep but not
- ;; by ack-grep that will grep all files of this directory
- ;; without recursing in their subdirs though, see that as a one
- ;; level recursion with ack-grep.
- ;; So I leave it as it is, considering it is a feature. [1]
- (cl-loop for i in candidates append
- (cond ((string-match "^git" helm-grep-default-command)
- (list i))
- ;; Candidate is a directory and we use recursion or ack.
- ((and (file-directory-p i)
- (or helm-grep-in-recurse
- ;; ack-grep accept directory [1].
- (helm-grep-use-ack-p)))
- (list (expand-file-name i)))
- ;; Grep doesn't support directory only when not in recurse.
- ((file-directory-p i)
- (file-expand-wildcards
- (concat (file-name-as-directory (expand-file-name i)) "*") t))
- ;; Candidate is a file or wildcard and we use recursion, use the
- ;; current directory instead of candidate.
- ((and (or (file-exists-p i) (string-match "[*]" i))
- helm-grep-in-recurse)
- (list (expand-file-name
- (directory-file-name ; Needed for windoze.
- (file-name-directory (directory-file-name i))))))
- ;; Else should be one or more file/directory
- ;; possibly marked.
- ;; When real is a normal filename without wildcard
- ;; file-expand-wildcards returns a list of one file.
- ;; wildcards should have been already handled by
- ;; helm-read-file-name or helm-find-files but do it from
- ;; here too in case we are called from elsewhere.
- (t (file-expand-wildcards i t))) into all-files ; [1]
- finally return
- (let ((files (if (file-remote-p in-directory)
- ;; Grep don't understand tramp filenames
- ;; use the local name.
- (mapcar (lambda (x)
- (file-remote-p x 'localname))
- all-files)
- all-files)))
- (if (string-match "^git" helm-grep-default-command)
- (mapconcat 'identity files " ")
- (mapconcat 'shell-quote-argument files " "))))))
-
-(defun helm-grep-command (&optional recursive)
- (let* ((com (if recursive
- helm-grep-default-recurse-command
- helm-grep-default-command))
- (exe (and com (car (split-string com " ")))))
- (if (and exe (string= exe "git")) "git-grep" exe)))
-
-(cl-defun helm-grep-use-ack-p (&key where)
- (let* ((rec-com (helm-grep-command t))
- (norm-com (helm-grep-command))
- (norm-com-ack-p (string-match "\\`ack" norm-com))
- (rec-com-ack-p (and rec-com (string-match "\\`ack" rec-com))))
- (cl-case where
- (default (and norm-com norm-com-ack-p))
- (recursive (and rec-com rec-com-ack-p))
- (strict (and norm-com rec-com rec-com-ack-p norm-com-ack-p))
- (t (and (not (and norm-com (string= norm-com "git-grep")))
- (or (and norm-com norm-com-ack-p)
- (and rec-com rec-com-ack-p)))))))
-
-(defun helm-grep--prepare-cmd-line (only-files &optional include zgrep)
- (let* ((default-directory (or helm-ff-default-directory
- (helm-default-directory)
- default-directory))
- (fnargs (helm-grep-prepare-candidates
- only-files default-directory))
- (ignored-files (unless (helm-grep-use-ack-p)
- (mapconcat
- (lambda (x)
- (concat "--exclude="
- (shell-quote-argument x)))
- helm-grep-ignored-files " ")))
- (ignored-dirs (unless (helm-grep-use-ack-p)
- (mapconcat
- ;; Need grep version >=2.5.4
- ;; of Gnuwin32 on windoze.
- (lambda (x)
- (concat "--exclude-dir="
- (shell-quote-argument x)))
- helm-grep-ignored-directories " ")))
- (exclude (unless (helm-grep-use-ack-p)
- (if helm-grep-in-recurse
- (concat (or include ignored-files)
- " " ignored-dirs)
- ignored-files)))
- (types (and (helm-grep-use-ack-p)
- ;; When %e format spec is not specified
- ;; in `helm-grep-default-command'
- ;; 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")))
- (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)
- ((or "grep" "zgrep" "git-grep")
- "grep --color=always")
- ;; Sometimes ack-grep cmd is ack only.
- ((and (pred (string-match-p "ack")) ack)
- (format "%s --color" ack)))
- for p in it concat
- (format " | %s %s" pipcom (shell-quote-argument p)))
- "")))
- (format-spec
- helm-grep-default-command
- (delq nil
- (list (unless zgrep
- (if types
- (cons ?e types)
- (cons ?e exclude)))
- (cons ?c (or smartcase ""))
- (cons ?p (shell-quote-argument (car patterns)))
- (cons ?f fnargs)
- (cons ?m pipes))))))
-
-(defun helm-grep-init (cmd-line)
- "Start an asynchronous grep process with CMD-LINE using ZGREP if non--nil."
- (let* ((default-directory (or helm-ff-default-directory
- (helm-default-directory)
- default-directory))
- (zgrep (string-match "\\`zgrep" cmd-line))
- ;; Use pipe only with grep, zgrep or git-grep.
- (process-connection-type (and (not zgrep) (helm-grep-use-ack-p)))
- (tramp-verbose helm-tramp-verbose)
- non-essential)
- ;; Start grep process.
- (helm-log "Starting Grep process in directory `%s'" default-directory)
- (helm-log "Command line used was:\n\n%s"
- (concat ">>> " (propertize cmd-line 'face 'helm-grep-cmd-line) "\n\n"))
- (prog1 ; This function should return the process first.
- (start-file-process-shell-command
- "grep" helm-buffer cmd-line)
- ;; Init sentinel.
- (set-process-sentinel
- (get-buffer-process helm-buffer)
- (lambda (process event)
- (let* ((err (process-exit-status process))
- (noresult (= err 1)))
- (unless (and err (> err 0))
- (helm-process-deferred-sentinel-hook
- process event (helm-default-directory)))
- (cond ((and noresult
- ;; [FIXME] This is a workaround for zgrep
- ;; that exit with code 1
- ;; after a certain amount of results.
- (not (with-helm-buffer helm-grep-use-zgrep)))
- (with-helm-buffer
- (insert (concat "* Exit with code 1, no result found,"
- " command line was:\n\n "
- (propertize helm-grep-last-cmd-line
- 'face 'helm-grep-cmd-line)))
- (setq mode-line-format
- '(" " mode-line-buffer-identification " "
- (:eval (format "L%s" (helm-candidate-number-at-point))) " "
- (:eval (propertize
- (format
- "[%s process finished - (no results)] "
- (if helm-grep-use-zgrep
- "Zgrep"
- (capitalize
- (if helm-grep-in-recurse
- (helm-grep-command t)
- (helm-grep-command)))))
- 'face 'helm-grep-finish))))))
- ((string= event "finished\n")
- (with-helm-window
- (setq mode-line-format
- '(" " mode-line-buffer-identification " "
- (:eval (format "L%s" (helm-candidate-number-at-point))) " "
- (:eval (propertize
- (format
- "[%s process finished - (%s results)] "
- (if helm-grep-use-zgrep
- "Zgrep"
- (capitalize
- (if helm-grep-in-recurse
- (helm-grep-command t)
- (helm-grep-command))))
- (helm-get-candidate-number))
- 'face 'helm-grep-finish))))
- (force-mode-line-update)))
- ;; Catch error output in log.
- (t (helm-log
- "Error: %s %s"
- (if helm-grep-use-zgrep "Zgrep" "Grep")
- (replace-regexp-in-string "\n" "" event))))))))))
-
-(defun helm-grep-collect-candidates ()
- (let ((cmd-line (helm-grep--prepare-cmd-line
- helm-grep-last-targets
- helm-grep-include-files
- helm-grep-use-zgrep)))
- (set (make-local-variable 'helm-grep-last-cmd-line) cmd-line)
- (funcall helm-grep-default-function cmd-line)))
-
-\f
-;;; Actions
-;;
-;;
-(defun helm-grep-action (candidate &optional where mark)
- "Define a default action for `helm-do-grep-1' on CANDIDATE.
-WHERE can be one of other-window, elscreen, other-frame."
- (let* ((split (helm-grep-split-line candidate))
- (lineno (string-to-number (nth 1 split)))
- (loc-fname (or (with-current-buffer
- (if (eq major-mode 'helm-grep-mode)
- (current-buffer)
- helm-buffer)
- (get-text-property (point-at-bol) 'help-echo))
- (car split)))
- (tramp-method (file-remote-p (or helm-ff-default-directory
- default-directory) 'method))
- (tramp-host (file-remote-p (or helm-ff-default-directory
- default-directory) 'host))
- (tramp-prefix (concat "/" tramp-method ":" tramp-host ":"))
- (fname (if tramp-host
- (concat tramp-prefix loc-fname) loc-fname)))
- (cl-case where
- (other-window (find-file-other-window fname))
- (elscreen (helm-elscreen-find-file fname))
- (other-frame (find-file-other-frame fname))
- (grep (helm-grep-save-results-1))
- (pdf (if helm-pdfgrep-default-read-command
- (helm-pdfgrep-action-1 split lineno (car split))
- (find-file (car split)) (doc-view-goto-page lineno)))
- (t (find-file fname)))
- (unless (or (eq where 'grep) (eq where 'pdf))
- (helm-goto-line lineno))
- (when mark
- (set-marker (mark-marker) (point))
- (push-mark (point) 'nomsg))
- ;; Save history
- (unless (or helm-in-persistent-action
- (eq major-mode 'helm-grep-mode)
- (string= helm-pattern ""))
- (setq helm-grep-history
- (cons helm-pattern
- (delete helm-pattern helm-grep-history)))
- (when (> (length helm-grep-history)
- helm-grep-max-length-history)
- (setq helm-grep-history
- (delete (car (last helm-grep-history))
- helm-grep-history))))))
-
-(defun helm-grep-persistent-action (candidate)
- "Persistent action for `helm-do-grep-1'.
-With a prefix arg record CANDIDATE in `mark-ring'."
- (if current-prefix-arg
- (helm-grep-action candidate nil 'mark)
- (helm-grep-action candidate))
- (helm-highlight-current-line))
-
-(defun helm-grep-other-window (candidate)
- "Jump to result in other window from helm grep."
- (helm-grep-action candidate 'other-window))
-
-(defun helm-grep-other-frame (candidate)
- "Jump to result in other frame from helm grep."
- (helm-grep-action candidate 'other-frame))
-
-(defun helm-grep-jump-elscreen (candidate)
- "Jump to result in elscreen from helm grep."
- (helm-grep-action candidate 'elscreen))
-
-(defun helm-goto-next-or-prec-file (n)
- "Go to next or precedent candidate file in helm grep/etags buffers.
-If N is positive go forward otherwise go backward."
- (let* ((allow-mode (or (eq major-mode 'helm-grep-mode)
- (eq major-mode 'helm-moccur-mode)))
- (sel (if allow-mode
- (buffer-substring (point-at-bol) (point-at-eol))
- (helm-get-selection nil t)))
- (current-line-list (helm-grep-split-line sel))
- (current-fname (nth 0 current-line-list))
- (bob-or-eof (if (eq n 1) 'eobp 'bobp))
- (mark-maybe (lambda ()
- (if allow-mode
- (ignore)
- (helm-mark-current-line)))))
- (catch 'break
- (while (not (funcall bob-or-eof))
- (forward-line n) ; Go forward or backward depending of n value.
- ;; Exit when current-fname is not matched or in `helm-grep-mode'
- ;; the line is not a grep line i.e 'fname:num:tag'.
- (setq sel (buffer-substring (point-at-bol) (point-at-eol)))
- (unless (or (string= current-fname
- (car (helm-grep-split-line sel)))
- (and (eq major-mode 'helm-grep-mode)
- (not (get-text-property (point-at-bol) 'help-echo))))
- (funcall mark-maybe)
- (throw 'break nil))))
- (cond ((and (> n 0) (eobp))
- (re-search-backward ".")
- (forward-line 0)
- (funcall mark-maybe))
- ((and (< n 0) (bobp))
- (helm-aif (next-single-property-change (point-at-bol) 'help-echo)
- (goto-char it)
- (forward-line 1))
- (funcall mark-maybe)))
- (helm-log-run-hook 'helm-move-selection-after-hook)))
-
-;;;###autoload
-(defun helm-goto-precedent-file ()
- "Go to precedent file in helm grep/etags buffers."
- (interactive)
- (with-helm-alive-p
- (with-helm-window
- (helm-goto-next-or-prec-file -1))))
-(put 'helm-goto-precedent-file 'helm-only t)
-
-;;;###autoload
-(defun helm-goto-next-file ()
- "Go to precedent file in helm grep/etags buffers."
- (interactive)
- (with-helm-window
- (helm-goto-next-or-prec-file 1)))
-
-(defun helm-grep-run-default-action ()
- "Run grep default action from `helm-do-grep-1'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-grep-action)))
-(put 'helm-grep-run-default-action 'helm-only t)
-
-(defun helm-grep-run-other-window-action ()
- "Run grep goto other window action from `helm-do-grep-1'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-grep-other-window)))
-(put 'helm-grep-run-other-window-action 'helm-only t)
-
-(defun helm-grep-run-other-frame-action ()
- "Run grep goto other frame action from `helm-do-grep-1'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-grep-other-frame)))
-(put 'helm-grep-run-other-frame-action 'helm-only t)
-
-(defun helm-grep-run-save-buffer ()
- "Run grep save results action from `helm-do-grep-1'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-grep-save-results)))
-(put 'helm-grep-run-save-buffer 'helm-only t)
-
-\f
-;;; helm-grep-mode
-;;
-;;
-(defun helm-grep-save-results (candidate)
- (helm-grep-action candidate 'grep))
-
-(defun helm-grep-save-results-1 ()
- "Save helm grep result in a `helm-grep-mode' buffer."
- (let ((buf "*hgrep*")
- new-buf
- (pattern (with-helm-buffer helm-input-local))
- (src-name (assoc-default 'name (helm-get-current-source))))
- (when (get-buffer buf)
- (if helm-grep-save-buffer-name-no-confirm
- (setq new-buf (format "*hgrep|%s|-%s" pattern
- (format-time-string "%H-%M-%S*")))
- (setq new-buf (helm-read-string "GrepBufferName: " buf))
- (cl-loop for b in (helm-buffer-list)
- when (and (string= new-buf b)
- (not (y-or-n-p
- (format "Buffer `%s' already exists overwrite? "
- new-buf))))
- do (setq new-buf (helm-read-string "GrepBufferName: " "*hgrep "))))
- (setq buf new-buf))
- (with-current-buffer (get-buffer-create buf)
- (setq default-directory (or helm-ff-default-directory
- (helm-default-directory)
- default-directory))
- (setq buffer-read-only t)
- (let ((inhibit-read-only t))
- (erase-buffer)
- (insert "-*- mode: helm-grep -*-\n\n"
- (format "%s Results for `%s':\n\n" src-name pattern))
- (save-excursion
- (insert (with-current-buffer helm-buffer
- (goto-char (point-min)) (forward-line 1)
- (buffer-substring (point) (point-max))))))
- (helm-grep-mode))
- (pop-to-buffer buf)
- (message "Helm %s Results saved in `%s' buffer" src-name buf)))
-
-(define-derived-mode helm-grep-mode
- special-mode "helm-grep"
- "Major mode to provide actions in helm grep saved buffer.
-
-Special commands:
-\\{helm-grep-mode-map}"
- (set (make-local-variable 'helm-grep-last-cmd-line)
- (with-helm-buffer helm-grep-last-cmd-line))
- (set (make-local-variable 'revert-buffer-function)
- #'helm-grep-mode--revert-buffer-function))
-(put 'helm-grep-mode 'helm-only t)
-
-(defun helm-grep-mode--revert-buffer-function (&optional _ignore-auto _noconfirm)
- (goto-char (point-min))
- (when (re-search-forward helm-grep-split-line-regexp nil t) (forward-line 0))
- (let ((inhibit-read-only t))
- (delete-region (point) (point-max)))
- (message "Reverting buffer...")
- (let ((process-connection-type
- ;; Git needs a nil value otherwise it tries to use a pager.
- (null (string-match-p "\\`git" helm-grep-last-cmd-line))))
- (set-process-sentinel
- (start-file-process-shell-command
- "hgrep" (generate-new-buffer "*hgrep revert*") helm-grep-last-cmd-line)
- 'helm-grep-mode--sentinel)))
-
-(defun helm-grep-mode--sentinel (process event)
- (when (string= event "finished\n")
- (with-current-buffer (current-buffer)
- (let ((inhibit-read-only t))
- (save-excursion
- (cl-loop for l in (with-current-buffer (process-buffer process)
- (prog1 (split-string (buffer-string) "\n")
- (kill-buffer)))
- for line = (if (string-match-p helm--ansi-color-regexp l)
- (helm--ansi-color-apply l) l)
- when (string-match helm-grep-split-line-regexp line)
- do (insert (propertize
- (car (helm-grep-filter-one-by-one line))
- ;; needed for wgrep.
- 'helm-realvalue line)
- "\n"))))
- (message "Reverting buffer done"))))
-
-(defun helm-gm-next-file ()
- (interactive)
- (helm-goto-next-or-prec-file 1))
-
-(defun helm-gm-precedent-file ()
- (interactive)
- (helm-goto-next-or-prec-file -1))
-
-(defun helm-grep-mode-jump ()
- (interactive)
- (helm-grep-action
- (buffer-substring (point-at-bol) (point-at-eol))))
-
-(defun helm-grep-mode-jump-other-window-1 (arg)
- (let ((candidate (buffer-substring (point-at-bol) (point-at-eol))))
- (condition-case nil
- (progn
- (save-selected-window
- (helm-grep-action candidate 'other-window)
- (recenter))
- (forward-line arg))
- (error nil))))
-
-(defun helm-grep-mode-jump-other-window-forward ()
- (interactive)
- (helm-grep-mode-jump-other-window-1 1))
-
-(defun helm-grep-mode-jump-other-window-backward ()
- (interactive)
- (helm-grep-mode-jump-other-window-1 -1))
-
-(defun helm-grep-mode-jump-other-window ()
- (interactive)
- (let ((candidate (buffer-substring (point-at-bol) (point-at-eol))))
- (condition-case nil
- (helm-grep-action candidate 'other-window)
- (error nil))))
-
-\f
-;;; ack-grep types
-;;
-;;
-(defun helm-grep-hack-types ()
- "Return a list of known ack-grep types."
- (with-temp-buffer
- ;; "--help-types" works with both 1.96 and 2.1+, while
- ;; "--help types" works only with 1.96 Issue #422.
- ;; `helm-grep-command' should return the ack executable
- ;; when this function is used in the right context
- ;; i.e After checking is we are using ack-grep with
- ;; `helm-grep-use-ack-p'.
- (call-process (helm-grep-command t) nil t nil "--help-types")
- (goto-char (point-min))
- (cl-loop while (re-search-forward
- "^ *--\\(\\[no\\]\\)\\([^. ]+\\) *\\(.*\\)" nil t)
- collect (cons (concat (match-string 2)
- " [" (match-string 3) "]")
- (match-string 2))
- collect (cons (concat "no" (match-string 2)
- " [" (match-string 3) "]")
- (concat "no" (match-string 2))))))
-
-(defun helm-grep-ack-types-transformer (candidates _source)
- (cl-loop for i in candidates
- if (stringp i)
- collect (rassoc i helm-grep-ack-types-cache)
- else
- collect i))
-
-(defvar helm-grep-ack-types-cache nil)
-(defun helm-grep-read-ack-type ()
- "Select types for the '--type' argument of ack-grep."
- (require 'helm-mode)
- (require 'helm-adaptive)
- (setq helm-grep-ack-types-cache (helm-grep-hack-types))
- (let ((types (helm-comp-read
- "Types: " helm-grep-ack-types-cache
- :name "*Ack-grep types*"
- :marked-candidates t
- :must-match t
- :fc-transformer '(helm-adaptive-sort
- helm-grep-ack-types-transformer)
- :buffer "*helm ack-types*")))
- (mapconcat (lambda (type) (concat "--type=" type)) types " ")))
-
-\f
-;;; grep extensions
-;;
-;;
-(defun helm-grep-guess-extensions (files)
- "Try to guess file extensions in FILES list when using grep recurse.
-These extensions will be added to command line with --include arg of grep."
- (cl-loop with ext-list = (list helm-grep-preferred-ext "*")
- with lst = (if (file-directory-p (car files))
- (directory-files
- (car files) nil
- directory-files-no-dot-files-regexp)
- files)
- for i in lst
- for ext = (file-name-extension i 'dot)
- for glob = (and ext (not (string= ext ""))
- (concat "*" ext))
- unless (or (not glob)
- (and glob-list (member glob glob-list))
- (and glob-list (member glob ext-list))
- (and glob-list (member glob helm-grep-ignored-files)))
- collect glob into glob-list
- finally return (delq nil (append ext-list glob-list))))
-
-(defun helm-grep-get-file-extensions (files)
- "Try to return a list of file extensions to pass to '--include' arg of grep."
- (let* ((all-exts (helm-grep-guess-extensions
- (mapcar 'expand-file-name files)))
- (extensions (helm-comp-read "Search Only in: " all-exts
- :marked-candidates t
- :fc-transformer 'helm-adaptive-sort
- :buffer "*helm grep exts*"
- :name "*helm grep extensions*")))
- (when (listp extensions) ; Otherwise it is empty string returned by C-RET.
- ;; If extensions is a list of one string containing spaces,
- ;; assume user entered more than one glob separated by space(s) and
- ;; split this string to pass it later to mapconcat.
- ;; e.g '("*.el *.py")
- (cl-loop for i in extensions
- append (split-string-and-unquote i " ")))))
-
-\f
-;;; Set up source
-;;
-;;
-(defclass helm-grep-class (helm-source-async)
- ((candidates-process :initform 'helm-grep-collect-candidates)
- (filter-one-by-one :initform 'helm-grep-filter-one-by-one)
- (keymap :initform helm-grep-map)
- (nohighlight :initform t)
- (nomark :initform t)
- (candidate-number-limit :initform 9999)
- (help-message :initform 'helm-grep-help-message)
- (history :initform 'helm-grep-history)
- (action :initform 'helm-grep-actions)
- (persistent-action :initform 'helm-grep-persistent-action)
- (persistent-help :initform "Jump to line (`C-u' Record in mark ring)")
- (requires-pattern :initform 2)))
-
-(defvar helm-source-grep nil)
-
-(defun helm-do-grep-1 (targets &optional recurse zgrep exts default-input input)
- "Launch grep on a list of TARGETS files.
-When RECURSE is given use -r option of grep and prompt user
-to set the --include args of grep.
-You can give more than one arg separated by space at prompt.
-e.g *.el *.py *.tex.
-From lisp use the EXTS argument as a list of extensions as above.
-If you are using ack-grep, you will be prompted for --type
-instead and EXTS will be ignored.
-If prompt is empty `helm-grep-ignored-files' are added to --exclude.
-Argument DEFAULT-INPUT is use as `default' arg of `helm' and INPUT
-is used as `input' arg of `helm', See `helm' docstring.
-ZGREP when non--nil use zgrep instead, without prompting for a choice
-in recurse, and ignoring EXTS, search being made on
-`helm-zgrep-file-extension-regexp'."
- (when (and (helm-grep-use-ack-p)
- helm-ff-default-directory
- (file-remote-p helm-ff-default-directory))
- (error "Error: Remote operation not supported with ack-grep."))
- (let* (non-essential
- (exts (and recurse
- ;; [FIXME] I could handle this from helm-walk-directory.
- (not zgrep) ; zgrep doesn't handle -r opt.
- (not (helm-grep-use-ack-p :where 'recursive))
- (or exts (helm-grep-get-file-extensions targets))))
- (include-files
- (and exts
- (mapconcat (lambda (x)
- (concat "--include="
- (shell-quote-argument x)))
- (if (> (length exts) 1)
- (remove "*" exts)
- exts) " ")))
- (types (and (not include-files)
- (not zgrep)
- recurse
- (helm-grep-use-ack-p :where 'recursive)
- ;; When %e format spec is not specified
- ;; ignore types and do not prompt for choice.
- (string-match "%e" helm-grep-default-command)
- (helm-grep-read-ack-type)))
- (follow (and helm-follow-mode-persistent
- (assoc-default 'follow helm-source-grep)))
- (src-name (if zgrep
- "Zgrep"
- (capitalize (if recurse
- (helm-grep-command t)
- (helm-grep-command))))))
- ;; When called as action from an other source e.g *-find-files
- ;; we have to kill action buffer.
- (when (get-buffer helm-action-buffer)
- (kill-buffer helm-action-buffer))
- ;; If `helm-find-files' haven't already started,
- ;; give a default value to `helm-ff-default-directory'
- ;; and set locally `default-directory' to this value . See below [1].
- (unless helm-ff-default-directory
- (setq helm-ff-default-directory default-directory))
- ;; We need to store these vars locally
- ;; to pass infos later to `helm-resume'.
- (helm-set-local-variable
- 'helm-zgrep-recurse-flag (and recurse zgrep)
- 'helm-grep-last-targets targets
- 'helm-grep-include-files (or include-files types)
- 'helm-grep-in-recurse recurse
- 'helm-grep-use-zgrep zgrep
- 'helm-grep-default-command
- (cond (zgrep helm-default-zgrep-command)
- (recurse helm-grep-default-recurse-command)
- ;; When resuming, the local value of
- ;; `helm-grep-default-command' is used, only git-grep
- ;; should need this.
- (t helm-grep-default-command))
- 'default-directory helm-ff-default-directory) ;; [1]
- ;; Setup the source.
- (setq helm-source-grep (helm-make-source src-name 'helm-grep-class
- :follow follow))
- (helm
- :sources 'helm-source-grep
- :buffer (format "*helm %s*"
- (if zgrep "zgrep" (helm-grep-command recurse)))
- :default default-input
- :input input
- :keymap helm-grep-map
- :history 'helm-grep-history
- :truncate-lines helm-grep-truncate-lines)))
-
-\f
-;;; zgrep
-;;
-;;
-(defun helm-ff-zgrep-1 (flist recursive)
- (unwind-protect
- (let* ((def-dir (or helm-ff-default-directory
- default-directory))
- (only (if recursive
- (or (gethash def-dir helm-rzgrep-cache)
- (puthash
- def-dir
- (helm-walk-directory
- def-dir
- :directories nil
- :path 'full
- :match helm-zgrep-file-extension-regexp)
- helm-rzgrep-cache))
- flist)))
- (helm-do-grep-1 only recursive 'zgrep))
- (setq helm-zgrep-recurse-flag nil)))
-
-\f
-;;; transformers
-;;
-;;
-(defun helm-grep-split-line (line)
- "Split a grep output line."
- ;; The output of grep may send a truncated line in this chunk,
- ;; so don't split until grep line is valid, that is
- ;; once the second part of the line comes with next chunk
- ;; send by process.
- (when (string-match helm-grep-split-line-regexp line)
- ;; Don't use split-string because buffer/file name or string
- ;; may contain a ":".
- (cl-loop for n from 1 to 3 collect (match-string n line))))
-
-(defun helm-grep--filter-candidate-1 (candidate &optional dir)
- (let* ((root (or dir (and helm-grep-default-directory-fn
- (funcall helm-grep-default-directory-fn))))
- (ansi-p (string-match-p helm--ansi-color-regexp candidate))
- (line (if ansi-p (helm--ansi-color-apply candidate) candidate))
- (split (helm-grep-split-line line))
- (fname (if (and root split)
- (expand-file-name (car split) root)
- (car-safe split)))
- (lineno (nth 1 split))
- (str (nth 2 split))
- (display-fname (cl-ecase helm-grep-file-path-style
- (basename (and fname (file-name-nondirectory fname)))
- (absolute fname)
- (relative (and fname root
- (file-relative-name fname root))))))
- (if (and display-fname lineno str)
- (cons (concat (propertize display-fname
- 'face 'helm-grep-file
- 'help-echo fname)
- ":"
- (propertize lineno 'face 'helm-grep-lineno)
- ":"
- (if ansi-p str (helm-grep-highlight-match str t)))
- line)
- "")))
-
-(defun helm-grep-filter-one-by-one (candidate)
- "`filter-one-by-one' transformer function for `helm-do-grep-1'."
- (let ((helm-grep-default-directory-fn
- (or helm-grep-default-directory-fn
- (lambda () (or helm-ff-default-directory
- (and (null (eq major-mode 'helm-grep-mode))
- (helm-default-directory))
- default-directory)))))
- (if (consp candidate)
- ;; Already computed do nothing (default as input).
- candidate
- (and (stringp candidate)
- (helm-grep--filter-candidate-1 candidate)))))
-
-(defun helm-grep-highlight-match (str &optional multi-match)
- "Highlight in string STR all occurences matching `helm-pattern'."
- (let (beg end)
- (condition-case-unless-debug nil
- (with-temp-buffer
- (insert (propertize str 'read-only nil)) ; Fix (#1176)
- (goto-char (point-min))
- (cl-loop for reg in
- (if multi-match
- ;; (m)occur.
- (cl-loop for r in (helm-mm-split-pattern
- helm-pattern)
- unless (string-match "\\`!" r)
- collect
- (helm-aif (and helm-migemo-mode
- (assoc r helm-mm--previous-migemo-info))
- (cdr it) r))
- ;; async sources (grep, gid etc...)
- (list helm-input))
- do
- (while (and (re-search-forward reg nil t)
- (> (- (setq end (match-end 0))
- (setq beg (match-beginning 0))) 0))
- (add-text-properties beg end '(face helm-grep-match)))
- do (goto-char (point-min)))
- (buffer-string))
- (error nil))))
-
-\f
-;;; Grep from buffer list
-;;
-;;
-(defun helm-grep-buffers-1 (candidate &optional zgrep)
- "Run grep on all file--buffers or CANDIDATE if it is a file--buffer.
-If one of selected buffers is not a file--buffer,
-it is ignored and grep will run on all others file--buffers.
-If only one candidate is selected and it is not a file--buffer,
-switch to this buffer and run `helm-occur'.
-If a prefix arg is given run grep on all buffers ignoring non--file-buffers."
- (let* ((prefarg (or current-prefix-arg helm-current-prefix-arg))
- (helm-ff-default-directory
- (if (and helm-ff-default-directory
- (file-remote-p helm-ff-default-directory))
- default-directory
- helm-ff-default-directory))
- (cands (if prefarg
- (buffer-list)
- (helm-marked-candidates)))
- (win-conf (current-window-configuration))
- ;; Non--fname and remote buffers are ignored.
- (bufs (cl-loop for buf in cands
- for fname = (buffer-file-name (get-buffer buf))
- when (and fname (not (file-remote-p fname)))
- collect (expand-file-name fname))))
- (if bufs
- (if zgrep
- (helm-do-grep-1 bufs nil 'zgrep)
- (helm-do-grep-1 bufs))
- ;; bufs is empty, thats mean we have only CANDIDATE
- ;; and it is not a buffer-filename, fallback to occur.
- (switch-to-buffer candidate)
- (when (get-buffer helm-action-buffer)
- (kill-buffer helm-action-buffer))
- (helm-occur)
- (when (eq helm-exit-status 1)
- (set-window-configuration win-conf)))))
-
-(defun helm-grep-buffers (candidate)
- "Action to grep buffers."
- (helm-grep-buffers-1 candidate))
-
-(defun helm-zgrep-buffers (candidate)
- "Action to zgrep buffers."
- (helm-grep-buffers-1 candidate 'zgrep))
-
-\f
-;;; Helm interface for pdfgrep
-;; pdfgrep program <http://pdfgrep.sourceforge.net/>
-;; and a pdf-reader (e.g xpdf) are needed.
-;;
-(defvar helm-pdfgrep-default-function 'helm-pdfgrep-init)
-(defun helm-pdfgrep-init (only-files)
- "Start an asynchronous pdfgrep process in ONLY-FILES list."
- (let* ((default-directory (or helm-ff-default-directory
- default-directory))
- (fnargs (helm-grep-prepare-candidates
- (if (file-remote-p default-directory)
- (mapcar (lambda (x)
- (file-remote-p x 'localname))
- only-files)
- only-files)
- default-directory))
- (cmd-line (format helm-pdfgrep-default-command
- helm-pattern
- fnargs))
- process-connection-type)
- ;; Start pdf grep process.
- (helm-log "Starting Pdf Grep process in directory `%s'" default-directory)
- (helm-log "Command line used was:\n\n%s"
- (concat ">>> " (propertize cmd-line 'face 'helm-grep-cmd-line) "\n\n"))
- (prog1
- (start-file-process-shell-command
- "pdfgrep" helm-buffer cmd-line)
- (message nil)
- (set-process-sentinel
- (get-buffer-process helm-buffer)
- (lambda (_process event)
- (if (string= event "finished\n")
- (with-helm-window
- (setq mode-line-format
- '(" " mode-line-buffer-identification " "
- (:eval (format "L%s" (helm-candidate-number-at-point))) " "
- (:eval (propertize
- (format "[Pdfgrep Process Finish - %s result(s)] "
- (max (1- (count-lines
- (point-min) (point-max))) 0))
- 'face 'helm-grep-finish))))
- (force-mode-line-update))
- (helm-log "Error: Pdf grep %s"
- (replace-regexp-in-string "\n" "" event))))))))
-
-(defun helm-do-pdfgrep-1 (only)
- "Launch pdfgrep with a list of ONLY files."
- (unless (executable-find "pdfgrep")
- (error "Error: No such program `pdfgrep'."))
- (let* (helm-grep-in-recurse) ; recursion is never used in pdfgrep.
- ;; When called as action from an other source e.g *-find-files
- ;; we have to kill action buffer.
- (when (get-buffer helm-action-buffer)
- (kill-buffer helm-action-buffer))
- (setq helm-pdfgrep-targets only)
- (helm
- :sources (helm-build-async-source "PdfGrep"
- :init (lambda ()
- ;; If `helm-find-files' haven't already started,
- ;; give a default value to `helm-ff-default-directory'.
- (setq helm-ff-default-directory (or helm-ff-default-directory
- default-directory)))
- :candidates-process (lambda ()
- (funcall helm-pdfgrep-default-function helm-pdfgrep-targets))
- :nohighlight t
- :nomark t
- :filter-one-by-one #'helm-grep-filter-one-by-one
- :candidate-number-limit 9999
- :history 'helm-grep-history
- :keymap helm-pdfgrep-map
- :help-message 'helm-pdfgrep-help-message
- :action #'helm-pdfgrep-action
- :persistent-help "Jump to PDF Page"
- :requires-pattern 2)
- :buffer "*helm pdfgrep*"
- :history 'helm-grep-history)))
-
-(defun helm-pdfgrep-action (candidate)
- (helm-grep-action candidate 'pdf))
-
-(defun helm-pdfgrep-action-1 (_split pageno fname)
- (save-selected-window
- (start-file-process-shell-command
- "pdf-reader" nil
- (format-spec helm-pdfgrep-default-read-command
- (list (cons ?f fname) (cons ?p pageno))))))
-\f
-;;; AG - PT
-;;
-;; https://github.com/ggreer/the_silver_searcher
-;; https://github.com/monochromegane/the_platinum_searcher
-
-(defcustom helm-grep-ag-command
- "ag --line-numbers -S --hidden --color --nogroup %s %s %s"
- "The default command for AG or PT.
-Takes three format specs, the first for type(s), the second for pattern
-and the third for directory.
-
-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).
-
-You can use safely \"--color\" (default)."
- :group 'helm-grep
- :type 'string)
-
-(defun helm-grep--ag-command ()
- (car (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\"."
- (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)))))
-
-(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")))
- (cmd (format helm-grep-ag-command
- (mapconcat 'identity type " ")
- (shell-quote-argument (car patterns))
- (shell-quote-argument directory))))
- (helm-aif (cdr patterns)
- (concat cmd (cl-loop for p in it concat
- (format " | %s %s"
- pipe-cmd (shell-quote-argument p))))
- cmd)))
-
-(defun helm-grep-ag-init (directory &optional type)
- "Start AG process in DIRECTORY maybe searching only files of type TYPE."
- (let ((cmd-line (helm-grep-ag-prepare-cmd-line
- helm-pattern directory type)))
- (set (make-local-variable 'helm-grep-last-cmd-line) cmd-line)
- (helm-log "Starting %s process in directory `%s'"
- (helm-grep--ag-command) directory)
- (helm-log "Command line used was:\n\n%s"
- (concat ">>> " cmd-line "\n\n"))
- (prog1
- (start-process-shell-command
- "ag" helm-buffer cmd-line)
- (set-process-sentinel
- (get-buffer-process helm-buffer)
- (lambda (process event)
- (let* ((err (process-exit-status process))
- (noresult (= err 1)))
- (cond (noresult
- (with-helm-buffer
- (insert (concat "* Exit with code 1, no result found,"
- " command line was:\n\n "
- (propertize helm-grep-last-cmd-line
- 'face 'helm-grep-cmd-line)))
- (setq mode-line-format
- '(" " mode-line-buffer-identification " "
- (:eval (format "L%s" (helm-candidate-number-at-point))) " "
- (:eval (propertize
- (format
- "[%s process finished - (no results)] "
- (upcase (helm-grep--ag-command)))
- 'face 'helm-grep-finish))))))
- ((string= event "finished\n")
- (with-helm-window
- (setq mode-line-format
- '(" " mode-line-buffer-identification " "
- (:eval (format "L%s" (helm-candidate-number-at-point))) " "
- (:eval (propertize
- (format
- "[%s process finished - (%s results)] "
- (upcase (helm-grep--ag-command))
- (helm-get-candidate-number))
- 'face 'helm-grep-finish))))
- (force-mode-line-update)))
- (t (helm-log
- "Error: %s %s"
- (helm-grep--ag-command)
- (replace-regexp-in-string "\n" "" event))))))))))
-
-(defclass helm-grep-ag-class (helm-source-async)
- ((nohighlight :initform t)
- (keymap :initform helm-grep-map)
- (help-message :initform 'helm-grep-help-message)
- (filter-one-by-one :initform 'helm-grep-filter-one-by-one)
- (persistent-action :initform 'helm-grep-persistent-action)
- (candidate-number-limit :initform 99999)
- (requires-pattern :initform 2)
- (nomark :initform t)
- (action :initform 'helm-grep-actions)))
-
-(defvar helm-source-grep-ag nil)
-
-(defun helm-grep-ag-1 (directory &optional type)
- "Start helm ag in DIRECTORY maybe searching in files of type TYPE."
- (setq helm-source-grep-ag
- (helm-make-source (upcase (helm-grep--ag-command)) 'helm-grep-ag-class
- :header-name (lambda (name)
- (format "%s [%s]"
- name (abbreviate-file-name directory)))
- :candidates-process
- (lambda () (helm-grep-ag-init directory type))))
- (helm :sources 'helm-source-grep-ag
- :keymap helm-grep-map
- :truncate-lines helm-grep-truncate-lines
- :buffer (format "*helm %s*" (helm-grep--ag-command))))
-
-(defun helm-grep-ag (directory with-types)
- "Start grep AG in DIRECTORY.
-When WITH-TYPES is non-nil provide completion on AG types."
- (helm-grep-ag-1 directory
- (helm-aif (and with-types
- (helm-grep-ag-get-types))
- (helm-comp-read
- "Ag type: " it
- :must-match t
- :marked-candidates t
- :fc-transformer 'helm-adaptive-sort
- :buffer "*helm ag types*"))))
-
-;;; Git grep
-;;
-;;
-(defcustom helm-grep-git-grep-command
- "git --no-pager grep -n%cH --color=always --exclude-standard --no-index --full-name -e %p -- %f"
- "The git grep default command line.
-The option \"--color=always\" can be used safely.
-The color of matched items can be customized in your .gitconfig
-See `helm-grep-default-command' for more infos.
-
-The \"--exclude-standard\" and \"--no-index\" switches allow
-skipping unwanted files specified in ~/.gitignore_global
-and searching files not already staged.
-You have also to enable this in global \".gitconfig\" with
- \"git config --global core.excludesfile ~/.gitignore_global\"."
- :group 'helm-grep
- :type 'string)
-
-(defun helm-grep-git-1 (directory &optional all default input)
- "Run git-grep on DIRECTORY.
-If DIRECTORY is not inside or part of a git repo exit with error.
-If optional arg ALL is non-nil grep the whole repo otherwise start
-at DIRECTORY.
-Arg DEFAULT is what you will have with `next-history-element',
-arg INPUT is what you will have by default at prompt on startup."
- (require 'vc)
- (let* ((helm-grep-default-command helm-grep-git-grep-command)
- helm-grep-default-recurse-command
- ;; Expand filename of each candidate with the git root dir.
- ;; The filename will be in the help-echo prop.
- (helm-grep-default-directory-fn (lambda ()
- (vc-find-root directory ".git")))
- (helm-ff-default-directory (funcall helm-grep-default-directory-fn)))
- (cl-assert helm-ff-default-directory nil "Not inside a Git repository")
- (helm-do-grep-1 (if all '("") `(,(expand-file-name directory)))
- nil nil nil default input)))
-
-\f
-;;;###autoload
-(defun helm-do-grep-ag (arg)
- "Preconfigured helm for grepping with AG in `default-directory'.
-With prefix-arg prompt for type if available with your AG version."
- (interactive "P")
- (require 'helm-files)
- (helm-grep-ag default-directory arg))
-
-;;;###autoload
-(defun helm-grep-do-git-grep (arg)
- "Preconfigured helm for git-grepping `default-directory'.
-With a prefix arg ARG git-grep the whole repository."
- (interactive "P")
- (require 'helm-files)
- (helm-grep-git-1 default-directory arg))
-
-
-(provide 'helm-grep)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-grep.el ends here
+++ /dev/null
-;;; helm-help.el --- Help messages for Helm. -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Code:
-(require 'helm)
-
-(defvar helm-org-headings--nofilename)
-(declare-function helm-source-org-headings-for-files "helm-org.el")
-
-\f
-(defgroup helm-help nil
- "Embedded help for `helm'."
- :group 'helm)
-
-(defface helm-helper
- '((t :inherit helm-header))
- "Face for helm help string in minibuffer."
- :group 'helm-help)
-
-(defcustom helm-documentation-file "~/.emacs.d/helm-doc.org"
- "The file where you want to save helm documentation."
- :group 'helm-help
- :type 'string)
-\f
-(defvar helm-help--string-list '(helm-help-message
- helm-buffer-help-message
- helm-ff-help-message
- helm-read-file-name-help-message
- helm-generic-file-help-message
- helm-grep-help-message
- helm-pdfgrep-help-message
- helm-etags-help-message
- helm-ucs-help-message
- helm-bookmark-help-message
- helm-esh-help-message
- helm-buffers-ido-virtual-help-message
- helm-moccur-help-message
- helm-top-help-message
- helm-apt-help-message
- helm-el-package-help-message
- helm-M-x-help-message
- helm-imenu-help-message
- helm-colors-help-message
- helm-semantic-help-message
- helm-kmacro-help-message))
-
-\f
-;;;###autoload
-(defun helm-documentation (arg)
- "Preconfigured helm for helm documentation.
-With a prefix arg refresh the documentation.
-
-Find here the documentation of all sources actually documented."
- (interactive "P")
- (require 'helm-org)
- (when arg (delete-file helm-documentation-file)
- (helm-aif (get-file-buffer helm-documentation-file)
- (kill-buffer it)))
- (unless (file-exists-p helm-documentation-file)
- (with-temp-file helm-documentation-file
- (erase-buffer)
- (cl-loop for elm in helm-help--string-list
- for str = (symbol-value elm)
- do (insert (substitute-command-keys
- (if (functionp str) (funcall str) str))
- "\n\n"))))
- (let ((helm-org-headings--nofilename t))
- (helm :sources (helm-source-org-headings-for-files
- (list helm-documentation-file))
- :candidate-number-limit 99999
- :buffer "*helm documentation*")))
-\f
-;;; Local help messages.
-
-;;; `helm-buffer-list' help
-;;
-;;
-(defvar helm-buffer-help-message
- "* Helm Buffer
-
-** Tips
-
-*** Completion
-
-**** Major-mode
-
-You can enter a partial name of major-mode (e.g. lisp, sh) to narrow down buffers.
-To specify the major-mode, prefix it with \"*\" e.g. \"*lisp\".
-If you want to match all buffers but the ones with a specific major-mode (negation),
-prefix the major-mode with \"!\" e.g. \"*!lisp\".
-If you want to specify more than one major-mode, separate them with \",\",
-e.g. \"*!lisp,!sh,!fun\" will list all buffers but the ones in lisp-mode, sh-mode and
-fundamental-mode.
-
-Enter then a space and a pattern to narrow down to buffers matching this pattern.
-
-**** Search inside buffers
-
-If you enter a space and a pattern prefixed by \"@\" helm will search for text matching
-this pattern INSIDE the buffer (i.e not in the name of buffer).
-NOTE that if you enter your pattern prefixed with \"@\" but escaped, helm will search a buffer
-matching \"@pattern\" but will not search inside.
-
-**** Search by directory name
-
-If you prefix the beginning of pattern with \"/\" the match will occur on directory name
-of buffer, it is interesting to narrow down to one directory for example, subsequent string
-entered after a space will match on buffer-name only.
-Note that negation is not supported for matching on buffer-file-name.
-You can specify more than one directory starting from helm v1.6.8
-
-**** Fuzzy matching
-
-Note that if `helm-buffers-fuzzy-matching' is non--nil you will have
-fuzzy matching on buffer names (not on directory name matching and major-mode though).
-A pattern starting with \"^\" will disable fuzzy matching and will match by exact regexp.
-
-**** Examples
-
-if I enter in pattern prompt:
-
- \"*lisp ^helm @moc\"
-
-helm will narrow down the list by selecting only buffers that are in lisp mode, start by helm
-and match \"moc\" in their contents.
-
-if I enter in pattern prompt:
-
- \"*lisp ^helm moc\"
-
-Notice there is no \"@\" this time
-helm will look for lisp mode buffers starting by \"helm\" and have \"moc\" in their name.
-
-if I enter in pattern prompt:
-
- \"*!lisp !helm\"
-
-helm will narrow down to buffers that are not in \"lisp\" mode and that do not match \"helm\"
-
-if I enter in pattern prompt:
-
- /helm/ w3
-
-helm will narrow down to buffers that are in any \"helm\" subdirectory and matching w3.
-
-*** Creating buffers
-
-When creating a new buffer use \\[universal-argument] to choose a mode for your buffer in a list.
-This list is customizable, see `helm-buffers-favorite-modes'.
-
-*** Killing buffers
-
-You have a command to kill buffer(s) and quit emacs and a command to kill buffers one by one
-\(no marked\) without quitting helm.
-
-You can run this persistent kill buffer command either with the regular
-`helm-execute-persistent-action' called with a prefix arg (C-u C-j) or with its specific command
-`helm-buffer-run-kill-persistent' see binding below.
-
-*** Meaning of colors and prefixes for buffers
-
-Remote buffers are prefixed with '@'.
-Red => Buffer have its file modified on disk by an external process.
-Indianred2 => Buffer exists but its file have been deleted.
-Orange => Buffer is modified and its file not saved to disk.
-Italic => A non--file buffer.
-
-** Commands
-\\<helm-buffer-map>
-\\[helm-buffer-run-zgrep]\t\tGrep Buffer(s) works as zgrep too (C-u grep all buffers but non--file buffers).
-\\[helm-buffers-run-multi-occur]\t\tMulti Occur buffer or marked buffers. (C-u toggle force searching current-buffer).
-\\[helm-buffer-switch-other-window]\t\tSwitch other window.
-\\[helm-buffer-switch-other-frame]\t\tSwitch other frame.
-\\[helm-buffers-run-browse-project]\t\tBrowse Project from buffer.
-\\[helm-buffer-run-query-replace-regexp]\t\tQuery replace regexp in marked buffers.
-\\[helm-buffer-run-query-replace]\t\tQuery replace in marked buffers.
-\\[helm-buffer-run-ediff]\t\tEdiff current buffer with candidate. If two marked buffers ediff those buffers.
-\\[helm-buffer-run-ediff-merge]\t\tEdiff merge current buffer with candidate. If two marked buffers ediff merge those buffers.
-\\[helm-buffer-diff-persistent]\t\tToggle Diff buffer with saved file without quitting.
-\\[helm-buffer-revert-persistent]\t\tRevert buffer without quitting.
-\\[helm-buffer-save-persistent]\t\tSave buffer without quitting.
-\\[helm-buffer-run-kill-buffers]\t\tDelete marked buffers and quit.
-\\[helm-buffer-run-kill-persistent]\t\tDelete buffer without quitting helm.
-\\[helm-toggle-all-marks]\t\tToggle all marks.
-\\[helm-mark-all]\t\tMark all.
-\\[helm-toggle-buffers-details]\t\tToggle details.
-\\[helm-buffers-toggle-show-hidden-buffers]\t\tShow hidden buffers.
-\\[helm-buffers-mark-similar-buffers]\t\tMark all buffers with same type (color) than current.")
-
-;;; Find files help (`helm-find-files')
-;;
-;;
-(defvar helm-ff-help-message
- "* Helm Find Files
-
-** Tips
-
-*** Navigation summary
-
-For a better experience you can enable auto completion by setting
-`helm-ff-auto-update-initial-value' to non-nil in your init file.
-It is not enabled by default to not confuse new users.
-
-**** Use `C-j' (persistent action) on a directory to go down one level
-
-On a symlinked directory a prefix arg will allow expanding to its true name.
-
-**** Use `C-l' on a directory to go up one level
-
-**** Use `C-r' to walk back the resulting tree of all the `C-l' you did
-
-Note: The tree is reinitialized each time you enter a new tree with `C-j'
-or by entering some pattern in prompt.
-
-*** Find file at point
-
-Helm is using `ffap' partially or completely to find file at point
-depending on value of `helm-ff-guess-ffap-filenames'.
-You can use full `ffap' by setting this to non-nil (annoying).
-Default value is nil which make `ffap' working partially.
-
-**** Find file at number line
-
-With something like this at point:
-
- ~/elisp/helm/helm.el:1234
-
-Helm will find this file at line number 1234.
-
-**** Find url at point
-
-When an url is found at point, helm expand to that url only.
-Pressing RET jump to that url using `browse-url-browser-function'.
-
-**** Find mail at point
-
-When a mail address is found at point helm expand to this email address
-prefixed by \"mailto:\". Pressing RET open a message buffer with this mail
-address.
-
-*** Quick pattern expansion
-
-**** Enter `~/' at end of pattern to quickly reach home directory
-
-**** Enter `/' at end of pattern to quickly reach root of your file system
-
-**** Enter `./' at end of pattern to quickly reach `default-directory' (initial start of session)
-
-If you are already in `default-directory' this will move cursor on top.
-
-**** Enter `../' at end of pattern will reach upper directory, moving cursor on top
-
-NOTE: This is different from using `C-l' in that `C-l' doesn't move cursor on top but stays on previous
-subdir name.
-
-**** Enter any environment var (e.g. `$HOME') at end of pattern, it will be expanded
-
-**** You can yank any valid filename after pattern, it will be expanded
-
-**** Special case with url's at point
-
-This have no effect at end of an url, you have first to kill pattern (`C-k')
-before entering one of these quick expansions patterns.
-
-*** Helm find files is fuzzy matching (start on third char entered)
-
-e.g. \"fob\" or \"fbr\" will complete \"foobar\"
-but \"fb\" will wait for a third char for completing.
-
-*** Use `C-u C-j' to watch an image or `C-<down>'
-
-*** `C-j' on a filename will expand in helm-buffer to this filename
-
-Second hit on `C-j' will display buffer filename.
-Third hit on `C-j' will kill buffer filename.
-NOTE: `C-u C-j' will display buffer directly.
-
-*** To browse images directories turn on `helm-follow-mode' and navigate with arrow keys
-
-You can also use `helm-follow-action-forward' and `helm-follow-action-backward'
-\(`C-<down' and `C-<left>').
-
-*** You can turn off/on (toggle) autoupdate completion at any moment with `C-DEL'
-
-It is useful when auto completion is enabled and when trying to create a new file
-or directory you want to prevent helm trying to complete what you are writing.
-NOTE: On a terminal C-<backspace> may not work, use in this case C-c <backspace>.
-
-*** You can create a new directory and a new file at the same time
-
-Just write the path in prompt and press `<RET>'.
-e.g. You can create \"~/new/newnew/newnewnew/my_newfile.txt\".
-
-*** To create a new directory, add a \"/\" at end of new name and press <RET>
-
-*** To create a new file just write the filename not ending with \"/\"
-
-*** Recursive search from helm find files
-
-**** You can use helm browse project (see binding below)
-
-- With no prefix arg
- If your current directory is under version control
- with one of git or hg and you have installed helm-ls-git and/or helm-ls-hg
- https://github.com/emacs-helm/helm-ls-git.git
- https://github.com/emacs-helm/helm-ls-hg
- you will see all your files under version control, otherwise
- you will be back to helm-find-files.
-- With one prefix arg
- You will see all the files under this directory
- and other subdirectories (recursion) and this list of files will be cached.
-- With two prefix args
- same but the cache will be refreshed.
-
-**** You can start a recursive search with Locate of Find (See commands below)
-
-With Locate you can use a local db with a prefix arg. If the localdb doesn't already
-exists, you will be prompted for its creation, if it exists and you want to refresh it,
-give two prefix args.
-
-*** Insert filename at point or complete filename at point
-
-On insertion (no completion, i.e nothing at point):
-
-- `C-c i' => insert absolute file name.
-- `C-u C-c i' => insert abbreviate file name.
-- `C-u C-u C-c i' => insert relative file name.
-
-On completion:
-
-- target starts by ~/ => insert abbreviate file name.
-- target starts by / or [a-z]:/ => insert full path.
-- otherwise => insert relative file name.
-
-*** Using wildcard to select multiple files
-
-Use of wilcard is supported to give a set of files to an action:
-
-e.g. You can copy all the files with \".el\" extension by using \"*.el\"
-and then run your copy action.
-
-You can do the same but with \"**.el\" (note the two stars),
-this will select recursively all \".el\" files under current directory.
-
-Note that when copying recursively files, you may have files with same name
-dispatched in the different subdirectories, so when copying them in the same directory
-they would be overwrited. To avoid this helm have a special action called \"backup files\"
-that have the same behavior as the command line \"cp --backup=numbered\", it allows you
-copying for example many *.jpg files with the same name from different
-subdirectories in one directory.
-Files with same name are renamed like this: \"foo.txt.~1~\".
-NOTE: This command is available only when `dired-async-mode' is used.
-
-NOTE: When using an action that involve an external backend (e.g. grep), using \"**\"
-is not advised (even if it works fine) because it will be slower to select all your files,
-you have better time letting the backend doing it, it will be faster.
-However, if you know you have not many files it is reasonable to use this,
-also using not recursive wilcard (e.g. \"*.el\") is perfectly fine for this.
-
-This feature (\"**\") is activated by default with the option `helm-file-globstar'.
-It is different than the bash shopt globstar feature in that to list files with a named extension
-recursively you just have to specify e.g \"**.el\" whereas in bash you have to specify \"**/*.el\"
-which is not convenient as \"**.el\".
-The directory selection with \"**/\" like bash shopt globstar option is not supported yet.
-
-*** Query replace regexp on filenames
-
-You can rename your files by replacing only part of filenames matching
-a regexp.
-
-e.g Rename recursively all files with \".JPG\" extension to \".jpg\":
-Use the helm-file-globstar feature described in previous section by
-entering at end of helm-find-files pattern \"**.JPG\", then hit `M-%`,
-at first prompt enter \"JPG\", at second \"jpg\" and hit `RET`.
-
-Shortcut for basename without extension, only extension or all are available:
-
-- Basename without extension => \"%.\"
-- Only extension => \".%\"
-- All => \"%\"
-
-So in the example above you could do instead:
-At first prompt enter \".%\", at second \"jpg\" and hit `RET`.
-Note that when using this instead of using \"JPG\" at first prompt, all extensions
-will be renamed to \"jpg\" even if the extension of one of the files is e.g \"png\".
-
-If you want to rename a serie of files from number 001 to 00x use \\# inside the replacement
-string when you will be prompted for it.
-
-e.g To rename the files \"foo.jpg\" \"bar.jpg\" and \"baz.jpg\"
- to \"foo-001.jpg\" \"foo-002.jpg\" \"foo-003.jpg\"
-
-Use as replace regexp \"%.\" and as replacement string \"foo-\\#\".
-Where \"%.\" is same as regexp \".*\\.jpg\".
-
-Note: You can do this with the serial renames actions you will find in the action menu
- for more sophisticated renaming, but using query replace regexp on filenames
- is a fast way for most common serial replacements.
-
-Note also that unlike the serial rename actions the renamed files stay in their initial directory
-and are not renamed to current directory, IOW use this (\\#) to rename files inside current directory.
-
-In the second prompt (replace regexp with) shortcut for `upcase', `downcase' and `capitalize'
-are available, respectively `%u', `%d' and `%c'.
-
-*** Copying renaming asynchronously
-
-If you use async library (if you have installed helm from MELPA you do) you can enable
-async for copying/renaming etc... your files by enabling `dired-async-mode'.
-
-Note that even when async is enabled, running a copy/rename action with a prefix arg
-will execute action synchronously, it will follow also the first file of the marked files
-in its destination directory.
-
-*** Bookmark your `helm-find-files' session
-
-You can bookmark your `helm-find-files' session with `C-x r m'.
-You can retrieve later these bookmarks easily by using M-x helm-filtered-bookmarks
-or from the current `helm-find-files' session just hitting `C-x r b'.
-
-*** Run Gid from `helm-find-files'
-
-You can navigate to a project containing an ID file created with the `mkid'
-command from id-utils, and run the `gid' command which will use the symbol at point
-in `helm-current-buffer' as default.
-
-** Commands
-\\<helm-find-files-map>
-\\[helm-ff-run-locate]\t\tRun Locate (C-u to specify locate db, M-n insert basename of candidate)
-\\[helm-ff-run-browse-project]\t\tBrowse project (`C-u' recurse, `C-u C-u' recurse and refresh db)
-\\[helm-ff-run-find-sh-command]\t\tRun Find shell command from this directory.
-\\[helm-ff-run-grep]\t\tRun Grep (C-u Recursive).
-\\[helm-ff-run-pdfgrep]\t\tRun Pdfgrep on marked files.
-\\[helm-ff-run-zgrep]\t\tRun zgrep (C-u Recursive).
-\\[helm-ff-run-grep-ag]\t\tRun AG grep on current directory.
-\\[helm-ff-run-git-grep]\t\tRun git-grep on current directory.
-\\[helm-ff-run-gid]\t\tRun gid (id-utils).
-\\[helm-ff-run-etags]\t\tRun Etags (C-u use thing-at-point `C-u C-u' reload cache)
-\\[helm-ff-run-rename-file]\t\tRename File (C-u Follow).
-\\[helm-ff-run-query-replace-on-marked]\t\tQuery replace on marked files.
-\\[helm-ff-run-copy-file]\t\tCopy File (C-u Follow).
-\\[helm-ff-run-byte-compile-file]\t\tByte Compile File (C-u Load).
-\\[helm-ff-run-load-file]\t\tLoad File.
-\\[helm-ff-run-symlink-file]\t\tSymlink File.
-\\[helm-ff-run-hardlink-file]\t\tHardlink file.
-\\[helm-ff-run-delete-file]\t\tDelete File.
-\\[helm-ff-run-kill-buffer-persistent]\t\tKill buffer candidate without quitting.
-\\[helm-ff-persistent-delete]\t\tDelete file without quitting.
-\\[helm-ff-run-switch-to-eshell]\t\tSwitch to Eshell.
-\\[helm-ff-run-eshell-command-on-file]\t\tEshell command on file (C-u Apply on marked files, otherwise treat them sequentially).
-\\[helm-ff-run-ediff-file]\t\tEdiff file.
-\\[helm-ff-run-ediff-merge-file]\t\tEdiff merge file.
-\\[helm-ff-run-complete-fn-at-point]\t\tComplete file name at point.
-\\[helm-ff-run-switch-other-window]\t\tSwitch other window.
-\\[helm-ff-run-switch-other-frame]\t\tSwitch other frame.
-\\[helm-ff-run-open-file-externally]\t\tOpen file with external program (C-u to choose).
-\\[helm-ff-run-open-file-with-default-tool]\t\tOpen file externally with default tool.
-\\[helm-ff-rotate-left-persistent]\t\tRotate Image Left.
-\\[helm-ff-rotate-right-persistent]\t\tRotate Image Right.
-\\[helm-find-files-up-one-level]\t\tGo down precedent directory.
-\\[helm-ff-run-switch-to-history]\t\tSwitch to last visited directories history.
-\\[helm-ff-file-name-history]\t\tSwitch to file name history.
-\\[helm-ff-properties-persistent]\t\tShow file properties in a tooltip.
-\\[helm-mark-all]\t\tMark all visibles candidates.
-\\[helm-ff-run-toggle-auto-update]\t\tToggle auto expansion of directories.
-\\[helm-unmark-all]\t\tUnmark all candidates, visibles and invisibles.
-\\[helm-ff-run-gnus-attach-files]\t\tGnus attach files to message buffer.
-\\[helm-ff-run-print-file]\t\tPrint file, (C-u to refresh printers list).
-\\[helm-enlarge-window]\t\tEnlarge helm window.
-\\[helm-narrow-window]\t\tNarrow helm window.
-\\[helm-ff-run-toggle-basename]\t\tToggle basename/fullpath.
-\\[helm-ff-run-find-file-as-root]\t\tFind file as root.
-\\[helm-ff-run-find-alternate-file]\t\tFind alternate file.
-\\[helm-ff-run-insert-org-link]\t\tInsert org link.")
-
-;;; Help for `helm-read-file-name'
-;;
-;;
-(defvar helm-read-file-name-help-message
- "* Helm read file name
-
-** Tips
-
-If you are here, you are probably using a vanilla command like `find-file'
-helmized by `helm-mode', this is cool, but it is even better for your file
-navigation to use `helm-find-files' which is fully featured.
-
-*** Navigation
-
-**** Enter `~/' at end of pattern to quickly reach home directory
-
-**** Enter `/' at end of pattern to quickly reach root of your file system
-
-**** Enter `./' at end of pattern to quickly reach `default-directory' (initial start of session)
-
-If you are in `default-directory' move cursor on top.
-
-**** Enter `../' at end of pattern will reach upper directory, moving cursor on top
-
-NOTE: This different to using `C-l' in that `C-l' don't move cursor on top but stay on previous
-subdir name.
-
-**** You can complete with partial basename (start on third char entered)
-
-E.g. \"fob\" or \"fbr\" will complete \"foobar\"
-but \"fb\" will wait for a third char for completing.
-
-*** Persistent actions
-
-By default `helm-read-file-name' use the persistent actions of `helm-find-files'
-
-**** Use `C-u C-j' to watch an image
-
-**** `C-j' on a filename will expand in helm-buffer to this filename
-
-Second hit on `C-j' will display buffer filename.
-Third hit on `C-j' will kill buffer filename.
-NOTE: `C-u C-j' will display buffer directly.
-
-**** To browse images directories turn on `helm-follow-mode' and navigate with arrow keys
-
-*** Delete characters backward
-
-When you want to delete backward characters, e.g. to create a new file or directory,
-autoupdate may keep updating to an existent directory preventing you from doing so.
-In this case, type C-<backspace> and then <backspace>.
-This should not be needed when copying/renaming files because autoupdate is disabled
-by default in that case.
-NOTE: On a terminal C-<backspace> may not work, use in this case C-c <backspace>.
-
-*** Create new directory and files
-
-**** Create a new directory and a new file at the same time
-
-You can create a new directory and a new file at the same time,
-just write the path in prompt and press <RET>.
-E.g. You can create \"~/new/newnew/newnewnew/my_newfile.txt\".
-
-**** To create a new directory, add a \"/\" at end of new name and press <RET>
-
-**** To create a new file just write the filename not ending with \"/\"
-
-_NOTE_: File and directory creation work only in some commands (e.g `find-file')
-and will not work in other commands where it is not intended to return a file or a directory
-\(e.g `list-directory').
-
-** Commands
-\\<helm-read-file-map>
-\\[helm-find-files-up-one-level]\t\tGo down precedent directory.
-\\[helm-ff-run-toggle-auto-update]\t\tToggle auto expansion of directories.
-\\[helm-ff-run-toggle-basename]\t\tToggle basename.
-\\[helm-ff-file-name-history]\t\tFile name history.
-C/\\[helm-cr-empty-string]\t\tMaybe return empty string (unless `must-match').
-\\[helm-next-source]\t\tGoto next source.
-\\[helm-previous-source]\t\tGoto previous source.")
-
-;;; Generic file help - Used by locate.
-;;
-;;
-(defvar helm-generic-file-help-message
- "* Helm Generic files
-
-** Tips
-
-*** Locate
-
-You can add after writing search pattern any of the locate command line options.
-e.g. -b, -e, -n <number>...etc.
-See Man locate for more infos.
-
-Some other sources (at the moment recentf and file in current directory sources)
-support the -b flag for compatibility with locate when they are used with it.
-
-*** Browse project
-
-When your directory is not under version control,
-don't forget to refresh your cache when files have been added/removed in your directory.
-
-*** Find command
-
-Recursively search files using \"find\" shell command.
-
-Candidates are all filenames that match all given globbing patterns.
-This respects the options `helm-case-fold-search' and
-`helm-findutils-search-full-path'.
-
-You can pass arbitrary options directly to find after a \"*\" separator.
-For example, this would find all files matching \"book\" that are larger
-than 1 megabyte:
-
- book * -size +1M
-
-** Commands
-\\<helm-generic-files-map>
-\\[helm-ff-run-toggle-basename]\t\tToggle basename.
-\\[helm-ff-run-grep]\t\tRun grep (C-u recurse).
-\\[helm-ff-run-zgrep]\t\tRun zgrep.
-\\[helm-ff-run-gid]\t\tRun gid (id-utils).
-\\[helm-ff-run-pdfgrep]\t\tRun Pdfgrep on marked files.
-\\[helm-ff-run-copy-file]\t\tCopy file(s)
-\\[helm-ff-run-rename-file]\t\tRename file(s).
-\\[helm-ff-run-symlink-file]\t\tSymlink file(s).
-\\[helm-ff-run-hardlink-file]\t\tHardlink file(s).
-\\[helm-ff-run-delete-file]\t\tDelete file(s).
-\\[helm-ff-run-byte-compile-file]\t\tByte compile file(s) (C-u load) (elisp).
-\\[helm-ff-run-load-file]\t\tLoad file(s) (elisp).
-\\[helm-ff-run-ediff-file]\t\tEdiff file.
-\\[helm-ff-run-ediff-merge-file]\t\tEdiff merge file.
-\\[helm-ff-run-switch-other-window]\t\tSwitch other window.
-\\[helm-ff-properties-persistent]\t\tShow file properties.
-\\[helm-ff-run-etags]\t\tRun etags (C-u use tap, C-u C-u reload DB).
-\\[helm-yank-text-at-point]\t\tYank text at point.
-\\[helm-ff-run-open-file-externally]\t\tOpen file with external program (C-u to choose).
-\\[helm-ff-run-open-file-with-default-tool]\t\tOpen file externally with default tool.
-\\[helm-ff-run-insert-org-link]\t\tInsert org link.")
-
-;;; Grep help
-;;
-;;
-(defvar helm-grep-help-message
- "* Helm Grep
-
-** Tips
-
-*** You can start grep with a prefix arg to recurse in subdirectories
-However now that helm support git-grep and AG, you have better time
-using one of those for your recursives search.
-
-*** You can use wild card when selecting files (e.g. *.el)
-
-*** You can grep in many differents directories by marking files or wild cards
-
-*** You can save your results in a `helm-grep-mode' buffer, see commands below
-
-Once in this buffer you can use emacs-wgrep (external package not bundled with helm)
-to edit your changes.
-
-*** Helm grep is supporting multi matching starting from version 1.9.4.
-Just add a space between each pattern like in most helm commands.
-
-*** Important
-
-Grepping on remote file will work only with grep, not ack-grep, but it is
-anyway bad supported as tramp doesn't support multiple process running in a
-short delay (less than 5s actually) among other things,
-so I strongly advice hitting `C-!' (i.e suspend process)
-before entering anything in pattern, and hit again `C-!' when
-your regexp is ready to send to remote process, even if helm is handling
-this by delaying each process at 5s.
-Or even better don't use tramp at all and mount your remote file system on SSHFS.
-
-* Helm Gid
-
-** Tips
-
-Helm gid read the database created with the `mkid' command from id-utils.
-The name of the database file can be customized with `helm-gid-db-file-name', it
-is usually \"ID\".
-Helm Gid use the symbol at point as default-input.
-You have access to this command also from `helm-find-files' which allow you to
-navigate to another directory to consult its database.
-
-NOTE: Helm gid support multi matches but only the last pattern entered will be
-highlighted due to the lack of ~--color~ support in GID itself.
-
-* Helm AG
-
-** Tips
-
-Helm AG is different from grep or ack-grep in that it works on a directory and not
-a list of files.
-You can ignore files and directories by using a \".agignore\" file, local to directory
-or global when placed in home directory (See AG man page for more infos).
-This file supports same entries as what you will find in `helm-grep-ignored-files' and
-`helm-grep-ignored-directories'.
-As always you can access helm AG from `helm-find-files'.
-
-Starting at version 0.30 AG allow providing one or more TYPE argument on its command line.
-Helm provide completion on these TYPES arguments when available with your AG version,
-Use a prefix argument when starting helm ag session to get this completion.
-NOTE: You can mark several types to match in your ag query, however on the first versions of
-AG providing this, only one type was allowed, so in this case the last marked will take effect.
-
-* Helm git-grep
-
-Helm git-grep is searching from current directory
-(i.e default-directory or the directory currently browsed by helm-find-files).
-If this current directory is a subdirectory of project and you want to match
-also upper directories (i.e the whole project) use a prefix arg.
-
-** Commands
-\\<helm-grep-map>
-\\[helm-goto-next-file]\t\tNext File.
-\\[helm-goto-precedent-file]\t\tPrecedent File.
-\\[helm-yank-text-at-point]\t\tYank Text at point in minibuffer.
-\\[helm-grep-run-other-window-action]\t\tJump other window.
-\\[helm-grep-run-other-frame-action]\t\tJump other frame.
-\\[helm-grep-run-default-action]\t\tRun default action (Same as RET).
-\\[helm-grep-run-save-buffer]\t\tSave to a `helm-grep-mode' enabled buffer.")
-
-;;; Pdf grep help
-;;
-;;
-(defvar helm-pdfgrep-help-message
- "* Helm PdfGrep Map
-
-** Commands
-\\<helm-pdfgrep-map>
-\\[helm-goto-next-file]\t\tNext File.
-\\[helm-goto-precedent-file]\t\tPrecedent File.
-\\[helm-yank-text-at-point]\t\tYank Text at point in minibuffer.")
-
-;;; Etags help
-;;
-;;
-(defvar helm-etags-help-message
- "* Helm Etags Map
-
-** Commands
-\\<helm-etags-map>
-\\[helm-goto-next-file]\t\tNext File.
-\\[helm-goto-precedent-file]\t\tPrecedent File.
-\\[helm-yank-text-at-point]\t\tYank Text at point in minibuffer.")
-
-;;; Ucs help
-;;
-;;
-(defvar helm-ucs-help-message
- "* Helm Ucs
-
-** Tips
-
-Use commands below to insert unicode characters
-in current-buffer without quitting helm.
-
-** Commands
-\\<helm-ucs-map>
-\\[helm-ucs-persistent-insert]\t\tInsert char.
-\\[helm-ucs-persistent-forward]\t\tForward char.
-\\[helm-ucs-persistent-backward]\t\tBackward char.
-\\[helm-ucs-persistent-delete]\t\tDelete char backward.")
-
-;;; Bookmark help
-;;
-;;
-(defvar helm-bookmark-help-message
- "* Helm bookmark name
-
-** Commands
-\\<helm-bookmark-map>
-\\[helm-bookmark-run-jump-other-window]\t\tJump other window.
-\\[helm-bookmark-run-delete]\t\tDelete bookmark.
-\\[helm-bookmark-run-edit]\t\tEdit bookmark.
-\\[helm-bookmark-toggle-filename]\t\tToggle bookmark location visibility.")
-
-;;; Eshell command on file help
-;;
-;;
-(defvar helm-esh-help-message
- "* Helm eshell on file
-
-** Tips
-
-*** Passing extra args after filename
-
-Normally your command or alias will be called with file as argument. E.g.,
-
- <command> 'candidate_file'
-
-But you can also pass an argument or more after 'candidate_file' like this:
-
- <command> %s [extra_args]
-
-'candidate_file' will be added at '%s' and your command will look at this:
-
- <command> 'candidate_file' [extra_args]
-
-*** Specify many files as args (marked files)
-
-E.g. <command> file1 file2 ...
-
-Call `helm-find-files-eshell-command-on-file' with one prefix-arg
-Otherwise you can pass one prefix-arg from the command selection buffer.
-NOTE: This is not working on remote files.
-
-With two prefix-arg before starting or from the command selection buffer
-the output is printed to your `current-buffer'.
-
-Note that with no prefix-arg or a prefix-arg value of '(16) (C-u C-u)
-the command is called once for each file like this:
-
- <command> file1 <command> file2 etc...
-
-** Commands
-\\<helm-esh-on-file-map>")
-
-;;; Ido virtual buffer help
-;;
-;;
-(defvar helm-buffers-ido-virtual-help-message
- "* Helm ido virtual buffers
-
-** Commands
-\\<helm-buffers-ido-virtual-map>
-\\[helm-ff-run-switch-other-window]\t\tSwitch other window.
-\\[helm-ff-run-switch-other-frame]\t\tSwitch other frame.
-\\[helm-ff-run-grep]\t\tGrep file.
-\\[helm-ff-run-zgrep]\t\tZgrep file.
-\\[helm-ff-run-delete-file]\t\tDelete file.
-\\[helm-ff-run-open-file-externally]\t\tOpen file externally.")
-
-;;; Moccur help
-;;
-;;
-(defvar helm-moccur-help-message
- "* Helm Moccur
-
-** Tips
-
-*** Matching
-
-Multiple regexp matching is allowed, just enter a space to separate your regexps.
-
-Matching empty lines is supported with the regexp \"^$\", you will get the results
-with only the buffer-name and the line number, you can of course save and edit these
-results (i.e add text to the empty line) .
-
-*** Automatically matching symbol at point
-
-You can match automatically the symbol at point, but keeping
-the minibuffer empty ready to write into.
-This is disabled by default, to enable this you have to add `helm-source-occur'
-and `helm-source-moccur' to `helm-sources-using-default-as-input'.
-
-*** Jump to the corresponding line in the searched buffer
-
-You can do this with `C-j' (persistent-action), to do it repetitively
-you can use `C-<up>' and `C-<down>' or enable `helm-follow-mode' with `C-c C-f'.
-
-*** Saving results
-
-Same as with helm-grep, you can save the results with `C-x C-s'.
-Of course if you don't save your results, you can get back your session
-with `helm-resume'.
-
-*** Refreshing the resumed session.
-
-When the buffer(s) where you ran helm-(m)occur have been modified, you will be
-warned of this with the buffer flashing to red, you can refresh the buffer by running
-`C-c C-u'.
-This can be done automatically by customizing `helm-moccur-auto-update-on-resume'.
-
-*** Refreshing a saved buffer
-
-Type `g' to update your buffer.
-
-*** Edit a saved buffer
-
-First, install wgrep https://github.com/mhayashi1120/Emacs-wgrep
-and then:
-
-1) C-c C-p to edit the buffer(s).
-2) C-x C-s to save your changes.
-
-Tip: Use the excellent iedit https://github.com/tsdh/iedit
-to modify occurences in your buffer.
-
-** Commands
-\\<helm-moccur-map>
-\\[helm-goto-next-file]\t\tNext Buffer.
-\\[helm-goto-precedent-file]\t\tPrecedent Buffer.
-\\[helm-yank-text-at-point]\t\tYank Text at point in minibuffer.
-\\[helm-moccur-run-goto-line-ow]\t\tGoto line in other window.
-\\[helm-moccur-run-goto-line-of]\t\tGoto line in new frame.")
-
-;;; Helm Top
-;;
-;;
-(defvar helm-top-help-message
- "* Helm Top
-
-** Tips
-
-** Commands
-\\<helm-top-map>
-\\[helm-top-run-sort-by-com]\t\tSort by commands.
-\\[helm-top-run-sort-by-cpu]\t\tSort by cpu usage.
-\\[helm-top-run-sort-by-user]\t\tSort alphabetically by user.
-\\[helm-top-run-sort-by-mem]\t\tSort by memory.")
-
-;;; Helm Apt
-;;
-;;
-(defvar helm-apt-help-message
- "* Helm Apt
-
-** Tips
-
-** Commands
-\\<helm-apt-map>
-\\[helm-apt-show-all]\t\tShow all packages.
-\\[helm-apt-show-only-installed]\t\tShow installed packages only.
-\\[helm-apt-show-only-not-installed]\t\tShow not installed packages only.
-\\[helm-apt-show-only-deinstalled]\t\tShow deinstalled (not purged yet) packages only.>")
-
-;;; Helm elisp package
-;;
-;;
-(defvar helm-el-package-help-message
- "* Helm elisp package
-
-** Tips
-
-*** Compile all your packages asynchronously
-
-When using async (if you have installed from MELPA you do), only helm, helm-core,
-and magit are compiled asynchronously, if you want all your packages compiled async,
-add to your init file:
-
- (setq async-bytecomp-allowed-packages '(all))
-
-*** Upgrade elisp packages
-
-On initial start (when emacs is fetching packages on remote), if helm find
-package to upgrade it will start in the upgradables packages view showing the packages
-availables to upgrade.
-On further starts, you will have to refresh the list with `C-c C-u', if helm find upgrades
-you will have a message telling you some packages are available for upgrade, you can switch to
-upgrade view (see below) to see what packages are available for upgrade or just hit `C-c U'.
-to upgrade all.
-
-To see upgradables packages hit <M-U>.
-
-Then you can install all upgradables packages with the upgrade all action (`C-c C-u'),
-or upgrade only the specific packages by marking them (the new ones) and running
-the upgrade action (visible only when there is upgradables packages).
-Of course you can upgrade a single package by just running the upgrade action
-without marking it (`C-c u' or RET) .
-
-\*WARNING* You are strongly advised to RESTART emacs after UPGRADING packages.
-
-*** Meaning of flags prefixing packages (Emacs-25)
-
-- The flag \"S\" that prefix package names mean that this package is one of `package-selected-packages'.
-This feature is only available with emacs-25.
-
-- The flag \"U\" that prefix package names mean that this package is no more needed.
-This feature is only available with emacs-25.
-
-** Commands
-\\<helm-el-package-map>
-\\[helm-el-package-show-all]\t\tShow all packages.
-\\[helm-el-package-show-installed]\t\tShow installed packages only.
-\\[helm-el-package-show-uninstalled]\t\tShow not installed packages only.
-\\[helm-el-package-show-upgrade]\t\tShow upgradable packages only.
-\\[helm-el-run-package-install]\t\tInstall package(s).
-\\[helm-el-run-package-reinstall]\t\tReinstall package(s).
-\\[helm-el-run-package-uninstall]\t\tUninstall package(s).
-\\[helm-el-run-package-upgrade]\t\tUpgrade package(s).
-\\[helm-el-run-package-upgrade-all]\t\tUpgrade all packages upgradables.
-\\[helm-el-run-visit-homepage]\t\tVisit package homepage.")
-
-;;; Helm M-x
-;;
-;;
-(defvar helm-M-x-help-message
- "* Helm M-x
-
-** Tips
-
-*** You can get help on any command with persistent action (C-j)
-
-*** Prefix Args
-
-All the prefix args passed BEFORE running `helm-M-x' are ignored,
-you should get an error message if you do so.
-When you want to pass prefix args, pass them AFTER starting `helm-M-x',
-you will see a prefix arg counter appearing in mode-line notifying you
-the number of prefix args entered.")
-
-;;; helm-imenu
-;;
-;;
-(defvar helm-imenu-help-message
- "* Helm imenu
-
-** Tips
-
-** Commands
-\\<helm-imenu-map>
-\\[helm-imenu-next-section]\t\tGo to next section.
-\\[helm-imenu-previous-section]\t\tGo to previous section.")
-
-;;; helm-colors
-;;
-;;
-(defvar helm-colors-help-message
- "* Helm colors
-
-** Commands
-\\<helm-color-map>
-\\[helm-color-run-insert-name]\t\tInsert the entry'name.
-\\[helm-color-run-kill-name]\t\tKill the entry's name.
-\\[helm-color-run-insert-rgb]\t\tInsert entry in RGB format.
-\\[helm-color-run-kill-rgb]\t\tKill entry in RGB format.")
-
-;;; helm semantic
-;;
-;;
-(defvar helm-semantic-help-message
- "* Helm semantic
-
-** Tips
-
-** Commands
-\\<helm-semantic-map>")
-
-;;; helm kmacro
-;;
-;;
-(defvar helm-kmacro-help-message
- "* Helm kmacro
-
-** Tips
-
-- Start recording some keys with `f3'
-- Record new kmacro with `f4'
-- Start `helm-execute-kmacro' to list all your macros.
-
-Use persistent action to run your kmacro as many time as needed,
-you can change of kmacro with `helm-next-line' `helm-previous-line'.
-
-NOTE: You can't record keys running helm commands except `helm-M-x' unless
-you don't choose from there a command using helm completion.
-
-** Commands
-\\<helm-kmacro-map>")
-
-\f
-;;; Mode line strings
-;;
-;;
-;;;###autoload
-(defvar helm-comp-read-mode-line "\
-\\<helm-comp-read-map>\
-C/\\[helm-cr-empty-string]:Empty \
-\\<helm-map>\
-\\[helm-help]:Help \
-\\[helm-select-action]:Act \
-\\[helm-maybe-exit-minibuffer]/\
-f1/f2/f-n:NthAct \
-\\[helm-toggle-suspend-update]:Tog.suspend")
-
-;;;###autoload
-(defvar helm-read-file-name-mode-line-string "\
-\\<helm-read-file-map>\
-\\[helm-help]:Help \
-C/\\[helm-cr-empty-string]:Empty \
-\\<helm-map>\
-\\[helm-select-action]:Act \
-\\[helm-maybe-exit-minibuffer]/\
-f1/f2/f-n:NthAct \
-\\[helm-toggle-suspend-update]:Tog.suspend"
- "String displayed in mode-line in `helm-source-find-files'.")
-
-;;;###autoload
-(defvar helm-top-mode-line "\
-\\<helm-top-map>\
-\\[helm-help]:Help \
-\\<helm-map>\
-\\[helm-select-action]:Act \
-\\[helm-maybe-exit-minibuffer]/\
-f1/f2/f-n:NthAct \
-\\[helm-toggle-suspend-update]:Tog.suspend")
-
-\f
-;;; Attribute Documentation
-;;
-;;
-;;;###autoload
-(defun helm-describe-helm-attribute (helm-attribute)
- "Display the full documentation of HELM-ATTRIBUTE.
-HELM-ATTRIBUTE should be a symbol."
- (interactive (list (intern
- (completing-read
- "Describe helm attribute: "
- (mapcar 'symbol-name helm-attributes)
- nil t))))
- (with-output-to-temp-buffer "*Help*"
- (princ (get helm-attribute 'helm-attrdoc))))
-
-(helm-document-attribute 'name "mandatory"
- " The name of the source. It is also the heading which appears
- above the list of matches from the source. Must be unique.")
-
-(helm-document-attribute 'header-name "optional"
- " A function returning the display string of the header. Its
- argument is the name of the source. This attribute is useful to
- add an additional information with the source name.")
-
-(helm-document-attribute 'candidates "mandatory if candidates-in-buffer attribute is not provided"
- " Specifies how to retrieve candidates from the source. It can
- either be a variable name, a function called with no parameters
- or the actual list of candidates.
-
- The list must be a list whose members are strings, symbols
- or (DISPLAY . REAL) pairs.
-
- In case of (DISPLAY . REAL) pairs, the DISPLAY string is shown
- in the Helm buffer, but the REAL one is used as action
- argument when the candidate is selected. This allows a more
- readable presentation for candidates which would otherwise be,
- for example, too long or have a common part shared with other
- candidates which can be safely replaced with an abbreviated
- string for display purposes.
-
- Note that if the (DISPLAY . REAL) form is used then pattern
- matching is done on the displayed string, not on the real
- value.
-
- If the candidates have to be retrieved asynchronously (for
- example, by an external command which takes a while to run)
- then the function should start the external command
- asynchronously and return the associated process object.
- Helm will take care of managing the process (receiving the
- output from it, killing it if necessary, etc.). The process
- should return candidates matching the current pattern (see
- variable `helm-pattern'.)
- You should use instead `candidates-process' attribute for
- async processes, a warning will popup when using async process
- in a `candidates' attribute.
-
- Note that currently results from asynchronous sources appear
- last in the helm buffer regardless of their position in
- `helm-sources'.")
-
-(helm-document-attribute 'candidates-process
- "Same as `candidates' attributes but for process function."
- " You should use this attribute when using a function involving
- an async process instead of `candidates'.")
-
-(helm-document-attribute 'action "mandatory if type attribute is not provided"
- " It is a list of (DISPLAY . FUNCTION) pairs or FUNCTION.
- FUNCTION is called with one parameter: the selected candidate.
-
- An action other than the default can be chosen from this list
- of actions for the currently selected candidate (by default
- with TAB). The DISPLAY string is shown in the completions
- buffer and the FUNCTION is invoked when an action is
- selected. The first action of the list is the default.")
-
-(helm-document-attribute 'coerce "optional"
- " It's a function called with one argument: the selected
- candidate.
-
- This function is intended for type convertion. In normal case,
- the selected candidate (string) is passed to action
- function. If coerce function is specified, it is called just
- before action function.
-
- Example: converting string to symbol
- (coerce . intern)")
-
-(helm-document-attribute 'type "optional if action attribute is provided"
- " Indicates the type of the items the source returns.
-
- Merge attributes not specified in the source itself from
- `helm-type-attributes'.
-
- This attribute is implemented by plug-in.")
-
-(helm-document-attribute 'init "optional"
- " Function called with no parameters when helm is started. It
- is useful for collecting current state information which can be
- used to create the list of candidates later.
-
- For example, if a source needs to work with the current
- directory then it can store its value here, because later
- helm does its job in the minibuffer and in the
- `helm-buffer' and the current directory can be different
- there.")
-
-(helm-document-attribute 'match "optional"
- " List of functions called with one parameter: a candidate. The
- function should return non-nil if the candidate matches the
- current pattern (see variable `helm-pattern').
-
- This attribute allows the source to override the default
- pattern matching based on `string-match'. It can be used, for
- example, to implement a source for file names and do the
- pattern matching on the basename of files, since it's more
- likely one is typing part of the basename when searching for a
- file, instead of some string anywhere else in its path.
-
- If the list contains more than one function then the list of
- matching candidates from the source is constructed by appending
- the results after invoking the first function on all the
- potential candidates, then the next function, and so on. The
- matching candidates supplied by the first function appear first
- in the list of results and then results from the other
- functions, respectively.
-
- This attribute has no effect for asynchronous sources (see
- attribute `candidates'), since they perform pattern matching
- themselves.")
-
-(helm-document-attribute 'candidate-transformer "optional"
- " It's a function or a list of functions called with one argument
- when the completion list from the source is built. The argument
- is the list of candidates retrieved from the source. The
- function should return a transformed list of candidates which
- will be used for the actual completion. If it is a list of
- functions, it calls each function sequentially.
-
- This can be used to transform or remove items from the list of
- candidates.
-
- Note that `candidates' is run already, so the given transformer
- function should also be able to handle candidates with (DISPLAY
- . REAL) format.")
-
-(helm-document-attribute 'filtered-candidate-transformer "optional"
- " It has the same format as `candidate-transformer', except the
- function is called with two parameters: the candidate list and
- the source.
-
- This transformer is run on the candidate list which is already
- filtered by the current pattern. While `candidate-transformer'
- is run only once, it is run every time the input pattern is
- changed.
-
- It can be used to transform the candidate list dynamically, for
- example, based on the current pattern.
-
- In some cases it may also be more efficent to perform candidate
- transformation here, instead of with `candidate-transformer'
- even if this transformation is done every time the pattern is
- changed. For example, if a candidate set is very large then
- `candidate-transformer' transforms every candidate while only
- some of them will actually be dislpayed due to the limit
- imposed by `helm-candidate-number-limit'.
-
- Note that `candidates' and `candidate-transformer' is run
- already, so the given transformer function should also be able
- to handle candidates with (DISPLAY . REAL) format.
-
- This option has no effect for asynchronous sources. (Not yet,
- at least.")
-
-(helm-document-attribute 'action-transformer "optional"
- " It's a function or a list of functions called with two
- arguments when the action list from the source is
- assembled. The first argument is the list of actions, the
- second is the current selection. If it is a list of functions,
- it calls each function sequentially.
-
- The function should return a transformed action list.
-
- This can be used to customize the list of actions based on the
- currently selected candidate.")
-
-(helm-document-attribute 'pattern-transformer "optional"
- " It's a function or a list of functions called with one argument
- before computing matches. Its argument is `helm-pattern'.
- Functions should return transformed `helm-pattern'.
-
- It is useful to change interpretation of `helm-pattern'.")
-
-(helm-document-attribute 'volatile "optional"
- " Indicates the source assembles the candidate list dynamically,
- so it shouldn't be cached within a single Helm
- invocation. It is only applicable to synchronous sources,
- because asynchronous sources are not cached.")
-
-(helm-document-attribute 'requires-pattern "optional"
- " If present matches from the source are shown only if the
- pattern is not empty. Optionally, it can have an integer
- parameter specifying the required length of input which is
- useful in case of sources with lots of candidates.")
-
-(helm-document-attribute 'persistent-action "optional"
- " Can be a either a Function called with one parameter (the
- selected candidate) or a cons cell where first element is this
- same function and second element a symbol (e.g. never-split)
- that inform `helm-execute-persistent-action'to not split his
- window to execute this persistent action.")
-
-(helm-document-attribute 'candidates-in-buffer "optional"
- " Shortcut attribute for making and narrowing candidates using
- buffers. This newly-introduced attribute prevents us from
- forgetting to add volatile and match attributes.
-
- See docstring of `helm-candidates-in-buffer'.
-
- (candidates-in-buffer) is equivalent of three attributes:
- (candidates . helm-candidates-in-buffer)
- (volatile)
- (match identity)
-
- (candidates-in-buffer . candidates-function) is equivalent of:
- (candidates . candidates-function)
- (volatile)
- (match identity)
-
- This attribute is implemented by plug-in.")
-
-(helm-document-attribute 'search "optional"
- " List of functions like `re-search-forward' or `search-forward'.
- Buffer search function used by `helm-candidates-in-buffer'.
- By default, `helm-candidates-in-buffer' uses
- `re-search-forward'. This attribute is meant to be used with
- (candidates . helm-candidates-in-buffer) or
- (candidates-in-buffer) in short.")
-
-(helm-document-attribute 'get-line "optional"
- " A function like `buffer-substring-no-properties' or `buffer-substring'.
- This function converts point of line-beginning and point of line-end,
- which represents a candidate computed by `helm-candidates-in-buffer'.
- By default, `helm-candidates-in-buffer' uses
- `buffer-substring-no-properties'.")
-
-(helm-document-attribute 'display-to-real "optional"
- " Function called with one parameter; the selected candidate.
-
- The function transforms the selected candidate, and the result
- is passed to the action function. The display-to-real
- attribute provides another way to pass other string than one
- shown in Helm buffer.
-
- Traditionally, it is possible to make candidates,
- candidate-transformer or filtered-candidate-transformer
- function return a list with (DISPLAY . REAL) pairs. But if REAL
- can be generated from DISPLAY, display-to-real is more
- convenient and faster.")
-
-(helm-document-attribute 'real-to-display "optional"
- " Function called with one parameter; the selected candidate.
-
- The inverse of display-to-real attribute.
-
- The function transforms the selected candidate, which is passed
- to the action function, for display. The real-to-display
- attribute provides the other way to pass other string than one
- shown in Helm buffer.
-
- Traditionally, it is possible to make candidates,
- candidate-transformer or filtered-candidate-transformer
- function return a list with (DISPLAY . REAL) pairs. But if
- DISPLAY can be generated from REAL, real-to-display is more
- convenient.
-
- Note that DISPLAY parts returned from candidates /
- candidate-transformer are IGNORED as the name `display-to-real'
- says.")
-
-(helm-document-attribute 'cleanup "optional"
- " Function called with no parameters when *helm* buffer is
- closed. It is useful for killing unneeded candidates buffer.
-
- Note that the function is executed BEFORE performing action.")
-
-(helm-document-attribute 'candidate-number-limit "optional"
- " Override `helm-candidate-number-limit' only for this source.")
-
-(helm-document-attribute 'accept-empty "optional"
- " Pass empty string \"\" to action function.")
-
-(helm-document-attribute 'dummy "optional"
- " Set `helm-pattern' to candidate. If this attribute is
- specified, The candidates attribute is ignored.
-
- This attribute is implemented by plug-in.")
-
-(helm-document-attribute 'multiline "optional"
- " Enable to selection multiline candidates.")
-
-(helm-document-attribute 'update "optional"
- (substitute-command-keys
- " Function called with no parameters at before \"init\" function when \
-\\<helm-map>\\[helm-force-update] is pressed."))
-
-(helm-document-attribute 'mode-line "optional"
- " Source local `helm-mode-line-string' (included in
- `mode-line-format'). It accepts also variable/function name.")
-
-(helm-document-attribute 'header-line "optional"
- " Source local `header-line-format'.
- It accepts also variable/function name. ")
-
-(helm-document-attribute
- 'resume "optional"
- " Function called with no parameters at end of initialization
- when `helm-resume' is started.
- If this function try to do something against `helm-buffer', \(e.g. updating,
- searching etc...\) probably you should run it in a timer to ensure
- `helm-buffer' is ready.")
-
-(helm-document-attribute 'keymap "optional"
- " Specific keymap for this source.
- It is useful to have a keymap per source when using more than
- one source. Otherwise, a keymap can be set per command with
- `helm' argument KEYMAP. NOTE: when a source have `helm-map' as
- keymap attr, the global value of `helm-map' will override the
- actual local one.")
-
-(helm-document-attribute 'help-message "optional"
- " Help message for this source.
- If not present, `helm-help-message' value will be used.")
-
-(helm-document-attribute 'match-part "optional"
- " Allow matching candidate in the line with `candidates-in-buffer'.
- In candidates-in-buffer sources, match is done with
- `re-search-forward' which allow matching only a regexp on the
- `helm-buffer'; when this search is done, match-part allow
- matching only a specific part of the current line e.g. with a
- line like this:
-
- filename:candidate-containing-the-word-filename
-
- What you want is to ignore \"filename\" part and match only
- \"candidate-containing-the-word-filename\"
-
- So give a function matching only the part of candidate after \":\"
-
- If source contain match-part attribute, match is computed only
- on part of candidate returned by the call of function provided
- by this attribute. The function should have one arg, candidate,
- and return only a specific part of candidate.
-
- NOTE: This have effect only on sources using
- `candidates-in-buffer'.")
-
-(helm-document-attribute 'match-strict "optional"
- " When specifying a match function within a source and
- helm-multi-match is enabled, the result of all matching
- functions will be concatened, which in some cases is not what
- is wanted. When using `match-strict' only this or these
- functions will be used. You can specify those functions as a
- list of functions or a single symbol function. For anonymous
- function don't add the dot, e.g:
-
- \(match-strict (lambda () (foo))).")
-
-(helm-document-attribute 'nohighlight "optional"
- " Disable highlight match in this source.")
-
-(helm-document-attribute 'no-matchplugin "optional"
- " Disable matchplugin for this source.")
-
-(helm-document-attribute 'history "optional"
- " Allow passing history variable to helm from source.
- It should be a quoted symbol evaluated from source, i.e:
- (history . ,'history-var)")
-
-(helm-document-attribute 'follow "optional"
- " Enable `helm-follow-mode' for this source only.
- You must give it a value of 1 or -1, though giving a -1 value
- is surely not what you want, e.g: (follow . 1)
-
- See `helm-follow-mode' for more infos")
-
-(helm-document-attribute 'follow-delay "optional"
- " `helm-follow-mode' will execute persistent-action after this delay.
- Otherwise value of `helm-follow-input-idle-delay' is used if non--nil,
- If none of these are found fallback to `helm-input-idle-delay'.")
-
-(helm-document-attribute 'allow-dups "optional"
- " Allow helm collecting duplicates candidates.")
-
-(helm-document-attribute 'filter-one-by-one "optional"
- " A transformer function that treat candidates one by one.
- It is called with one arg the candidate.
- It is faster than `filtered-candidate-transformer' or `candidates-transformer',
- but should be used only in sources that recompute constantly their candidates,
- e.g. `helm-source-find-files'.
- Filtering happen early and candidates are treated
- one by one instead of re-looping on the whole list.
- If used with `filtered-candidate-transformer' or `candidates-transformer'
- these functions should treat the candidates transformed by the `filter-one-by-one'
- function in consequence.")
-
-(helm-document-attribute 'nomark "optional"
- " Don't allow marking candidates when this attribute is present.")
-
-(provide 'helm-help)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-help.el ends here
+++ /dev/null
-;;; helm-id-utils.el --- Helm interface for id-utils. -*- lexical-binding: t -*-
-
-;; Copyright (C) 2015 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Code:
-
-(require 'helm-grep)
-(require 'helm-help)
-
-(defgroup helm-id-utils nil
- "ID-Utils related Applications and libraries for Helm."
- :group 'helm)
-
-(defcustom helm-gid-program "gid"
- "Name of gid command (usually `gid').
-For Mac OS X users, if you install GNU coreutils, the name `gid'
-might be occupied by `id' from GNU coreutils, and you should set
-it to correct name (or absolute path), for example, if using
-MacPorts to install id-utils, it should be `gid32'."
- :group 'helm-id-utils
- :type 'file)
-
-(defcustom helm-gid-db-file-name "ID"
- "Name of a database file created by `mkid' command from `ID-utils'."
- :group 'helm-id-utils
- :type 'string)
-
-(defun helm-gid-candidates-process ()
- (let* ((patterns (split-string helm-pattern))
- (default-com (format "%s -r %s" helm-gid-program
- (shell-quote-argument (car patterns))))
- (cmd (helm-aif (cdr patterns)
- (concat default-com
- (cl-loop for p in it
- concat (format " | grep --color=always %s"
- (shell-quote-argument p))))
- default-com))
- (proc (start-process-shell-command
- "gid" helm-buffer cmd)))
- (set (make-local-variable 'helm-grep-last-cmd-line) cmd)
- (prog1 proc
- (set-process-sentinel
- proc (lambda (_process event)
- (when (string= event "finished\n")
- (with-helm-window
- (setq mode-line-format
- '(" " mode-line-buffer-identification " "
- (:eval (format "L%s" (helm-candidate-number-at-point))) " "
- (:eval (propertize
- (format "[Helm Gid process finished - (%s results)]"
- (max (1- (count-lines
- (point-min) (point-max)))
- 0))
- 'face 'helm-locate-finish))))
- (force-mode-line-update))
- (helm-log "Error: Gid %s"
- (replace-regexp-in-string "\n" "" event))))))))
-
-(defun helm-gid-filtered-candidate-transformer (candidates _source)
- ;; "gid -r" may add dups in some rare cases.
- (cl-loop for c in (helm-fast-remove-dups candidates :test 'equal)
- collect (helm-grep--filter-candidate-1 c)))
-
-(defclass helm-gid-source (helm-source-async)
- ((header-name
- :initform
- (lambda (name)
- (concat name " [" (helm-attr 'db-dir) "]")))
- (db-dir :initarg :db-dir
- :initform nil
- :custom string
- :documentation " Location of ID file.")
- (candidates-process :initform #'helm-gid-candidates-process)
- (filtered-candidate-transformer
- :initform #'helm-gid-filtered-candidate-transformer)
- (candidate-number-limit :initform 99999)
- (action :initform (helm-make-actions
- "Find File" 'helm-grep-action
- "Find file other frame" 'helm-grep-other-frame
- (lambda () (and (locate-library "elscreen")
- "Find file in Elscreen"))
- 'helm-grep-jump-elscreen
- "Save results in grep buffer" 'helm-grep-save-results
- "Find file other window" 'helm-grep-other-window))
- (persistent-action :initform 'helm-grep-persistent-action)
- (history :initform 'helm-grep-history)
- (nohighlight :initform t)
- (help-message :initform 'helm-grep-help-message)
- (requires-pattern :initform 2)))
-
-;;;###autoload
-(defun helm-gid ()
- "Preconfigured helm for `gid' command line of `ID-Utils'.
-Need A database created with the command `mkid'
-above `default-directory'.
-Need id-utils as dependency which provide `mkid', `gid' etc...
-See <https://www.gnu.org/software/idutils/>."
- (interactive)
- (let* ((db (locate-dominating-file
- default-directory
- helm-gid-db-file-name))
- (helm-grep-default-directory-fn
- (lambda () default-directory))
- (helm--maybe-use-default-as-input t))
- (cl-assert db nil "No DataBase found, create one with `mkid'")
- (helm :sources (helm-make-source "Gid" 'helm-gid-source
- :db-dir db)
- :buffer "*helm gid*"
- :keymap helm-grep-map
- :truncate-lines helm-grep-truncate-lines)))
-
-(provide 'helm-id-utils)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-id-utils ends here
+++ /dev/null
-;;; helm-imenu.el --- Helm interface for Imenu -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'helm)
-(require 'helm-lib)
-(require 'imenu)
-(require 'helm-utils)
-(require 'helm-help)
-
-\f
-(defgroup helm-imenu nil
- "Imenu related libraries and applications for helm."
- :group 'helm)
-
-(defcustom helm-imenu-delimiter " / "
- "Delimit types of candidates and his value in `helm-buffer'."
- :group 'helm-imenu
- :type 'string)
-
-(defcustom helm-imenu-execute-action-at-once-if-one
- #'helm-imenu--execute-action-at-once-p
- "Goto the candidate when only one is remaining."
- :group 'helm-imenu
- :type 'function)
-
-(defcustom helm-imenu-lynx-style-map t
- "Use Arrow keys to jump to occurences."
- :group 'helm-imenu
- :type 'boolean)
-
-(defcustom helm-imenu-all-buffer-assoc nil
- "Major mode association alist for `helm-imenu-in-all-buffers'.
-Allow `helm-imenu-in-all-buffers' searching in these associated buffers
-even if they are not derived from each other.
-The alist is bidirectional, i.e no need to add '((foo . bar) (bar . foo))
-only '((foo . bar)) is needed."
- :type '(alist :key-type symbol :value-type symbol)
- :group 'helm-imenu)
-\f
-;;; keymap
-(defvar helm-imenu-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map helm-map)
- (define-key map (kbd "M-<down>") 'helm-imenu-next-section)
- (define-key map (kbd "M-<up>") 'helm-imenu-previous-section)
- (when helm-imenu-lynx-style-map
- (define-key map (kbd "<left>") 'helm-maybe-exit-minibuffer)
- (define-key map (kbd "<right>") 'helm-execute-persistent-action))
- (delq nil map)))
-
-(defun helm-imenu-next-or-previous-section (n)
- (with-helm-buffer
- (let* ((fn (lambda ()
- (car (split-string (helm-get-selection nil t)
- helm-imenu-delimiter))))
- (curtype (funcall fn))
- (move-fn (if (> n 0) #'helm-next-line #'helm-previous-line))
- (stop-fn (if (> n 0)
- #'helm-end-of-source-p
- #'helm-beginning-of-source-p)))
- (catch 'break
- (while (not (funcall stop-fn))
- (funcall move-fn)
- (unless (string= curtype (funcall fn))
- (throw 'break nil)))))))
-
-(defun helm-imenu-next-section ()
- (interactive)
- (helm-imenu-next-or-previous-section 1))
-
-(defun helm-imenu-previous-section ()
- (interactive)
- (helm-imenu-next-or-previous-section -1))
-
-\f
-;;; Internals
-(defvar helm-cached-imenu-alist nil)
-(make-variable-buffer-local 'helm-cached-imenu-alist)
-
-(defvar helm-cached-imenu-candidates nil)
-(make-variable-buffer-local 'helm-cached-imenu-candidates)
-
-(defvar helm-cached-imenu-tick nil)
-(make-variable-buffer-local 'helm-cached-imenu-tick)
-
-\f
-(defvar helm-source-imenu nil "See (info \"(emacs)Imenu\")")
-(defvar helm-source-imenu-all nil)
-
-(defclass helm-imenu-source (helm-source-sync)
- ((candidates :initform 'helm-imenu-candidates)
- (candidate-transformer :initform 'helm-imenu-transformer)
- (persistent-action :initform 'helm-imenu-persistent-action)
- (persistent-help :initform "Show this entry")
- (keymap :initform helm-imenu-map)
- (help-message :initform 'helm-imenu-help-message)
- (action :initform 'helm-imenu-action)))
-
-(defcustom helm-imenu-fuzzy-match nil
- "Enable fuzzy matching in `helm-source-imenu'."
- :group 'helm-imenu
- :type 'boolean
- :set (lambda (var val)
- (set var val)
- (setq helm-source-imenu
- (helm-make-source "Imenu" 'helm-imenu-source
- :fuzzy-match helm-imenu-fuzzy-match))))
-\f
-(defun helm-imenu--maybe-switch-to-buffer (candidate)
- (helm-aif (marker-buffer (cdr candidate))
- (switch-to-buffer it)))
-
-(defun helm-imenu--execute-action-at-once-p ()
- (let ((cur (helm-get-selection))
- (mb (with-helm-current-buffer
- (save-excursion
- (goto-char (point-at-bol))
- (point-marker)))))
- (if (equal (cdr cur) mb)
- (prog1 nil
- (helm-set-pattern "")
- (helm-force-update))
- t)))
-
-(defun helm-imenu-action (candidate)
- "Default action for `helm-source-imenu'."
- (helm-log-run-hook 'helm-goto-line-before-hook)
- (helm-imenu--maybe-switch-to-buffer candidate)
- (imenu candidate)
- ;; If semantic is supported in this buffer
- ;; imenu used `semantic-imenu-goto-function'
- ;; and position have been highlighted,
- ;; no need to highlight again.
- (unless (eq imenu-default-goto-function
- 'semantic-imenu-goto-function)
- (helm-highlight-current-line nil nil nil nil 'pulse)))
-
-(defun helm-imenu-persistent-action (candidate)
- "Default persistent action for `helm-source-imenu'."
- (helm-imenu--maybe-switch-to-buffer candidate)
- (imenu candidate)
- (helm-highlight-current-line))
-
-(defun helm-imenu-candidates (&optional buffer)
- (with-current-buffer (or buffer helm-current-buffer)
- (let ((tick (buffer-modified-tick)))
- (if (eq helm-cached-imenu-tick tick)
- helm-cached-imenu-candidates
- (setq imenu--index-alist nil)
- (prog1 (setq helm-cached-imenu-candidates
- (let ((index (imenu--make-index-alist t)))
- (helm-imenu--candidates-1
- (delete (assoc "*Rescan*" index) index))))
- (setq helm-cached-imenu-tick tick))))))
-
-(defun helm-imenu-candidates-in-all-buffers ()
- (let* ((lst (buffer-list))
- (progress-reporter (make-progress-reporter
- "Imenu indexing buffers..." 1 (length lst))))
- (prog1
- (cl-loop for b in lst
- for count from 1
- when
- (and (with-current-buffer b
- (derived-mode-p 'prog-mode))
- (with-current-buffer b
- (helm-same-major-mode-p helm-current-buffer
- helm-imenu-all-buffer-assoc)))
- do (progress-reporter-update progress-reporter count)
- and
- append (with-current-buffer b
- (helm-imenu-candidates b)))
- (progress-reporter-done progress-reporter))))
-
-(defun helm-imenu--candidates-1 (alist)
- (cl-loop for elm in alist
- nconc (if (imenu--subalist-p elm)
- (helm-imenu--candidates-1
- (cl-loop for (e . v) in (cdr elm) collect
- (cons (propertize
- e 'helm-imenu-type (car elm))
- ;; If value is an integer, convert it
- ;; to a marker, otherwise it is a cons cell
- ;; and it will be converted on next recursions.
- ;; (Issue #1060) [1].
- (if (integerp v) (copy-marker v) v))))
- (and (cdr elm) ; bug in imenu, should not be needed.
- (setcdr elm (copy-marker (cdr elm))) ; Same as [1].
- (list elm)))))
-
-(defun helm-imenu--get-prop (item)
- ;; property value of ITEM can have itself
- ;; a property value which have itself a property value
- ;; ...and so on; Return a list of all these
- ;; properties values starting at ITEM.
- (let* ((prop (get-text-property 0 'helm-imenu-type item))
- (lst (list prop item)))
- (when prop
- (while prop
- (setq prop (get-text-property 0 'helm-imenu-type prop))
- (and prop (push prop lst)))
- lst)))
-
-(defun helm-imenu-transformer (candidates)
- (cl-loop for (k . v) in candidates
- for types = (or (helm-imenu--get-prop k)
- (list "Function" k))
- for bufname = (buffer-name (marker-buffer v))
- for disp1 = (mapconcat
- (lambda (x)
- (propertize
- x 'face (cond ((string= x "Variables")
- 'font-lock-variable-name-face)
- ((string= x "Function")
- 'font-lock-function-name-face)
- ((string= x "Types")
- 'font-lock-type-face))))
- types helm-imenu-delimiter)
- for disp = (propertize disp1 'help-echo bufname)
- collect
- (cons disp (cons k v))))
-\f
-;;;###autoload
-(defun helm-imenu ()
- "Preconfigured `helm' for `imenu'."
- (interactive)
- (unless helm-source-imenu
- (setq helm-source-imenu
- (helm-make-source "Imenu" 'helm-imenu-source
- :fuzzy-match helm-imenu-fuzzy-match)))
- (let ((imenu-auto-rescan t)
- (str (thing-at-point 'symbol))
- (helm-execute-action-at-once-if-one
- helm-imenu-execute-action-at-once-if-one))
- (helm :sources 'helm-source-imenu
- :default (list (concat "\\_<" str "\\_>") str)
- :preselect str
- :buffer "*helm imenu*")))
-
-;;;###autoload
-(defun helm-imenu-in-all-buffers ()
- "Preconfigured helm for fetching imenu entries in all buffers with similar mode as current.
-A mode is similar as current if it is the same, it is derived i.e `derived-mode-p'
-or it have an association in `helm-imenu-all-buffer-assoc'."
- (interactive)
- (unless helm-source-imenu-all
- (setq helm-source-imenu-all
- (helm-make-source "Imenu in all buffers" 'helm-imenu-source
- :candidates 'helm-imenu-candidates-in-all-buffers
- :fuzzy-match helm-imenu-fuzzy-match)))
- (let ((imenu-auto-rescan t)
- (str (thing-at-point 'symbol))
- (helm-execute-action-at-once-if-one
- helm-imenu-execute-action-at-once-if-one))
- (helm :sources 'helm-source-imenu-all
- :default (list (concat "\\_<" str "\\_>") str)
- :preselect (unless (memq 'helm-source-imenu-all
- helm-sources-using-default-as-input)
- str)
- :buffer "*helm imenu all*")))
-
-(provide 'helm-imenu)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-imenu.el ends here
+++ /dev/null
-;;; helm-info.el --- Browse info index with helm -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'helm)
-(require 'helm-lib)
-(require 'helm-plugin)
-(require 'info)
-
-(declare-function Info-index-nodes "info" (&optional file))
-(declare-function Info-goto-node "info" (&optional fork))
-(declare-function Info-find-node "info.el" (filename nodename &optional no-going-back))
-(defvar Info-history)
-(defvar Info-directory-list)
-\f
-;;; Customize
-
-(defgroup helm-info nil
- "Info-related applications and libraries for Helm."
- :group 'helm)
-
-(defcustom helm-info-default-sources
- '(helm-source-info-elisp
- helm-source-info-cl
- helm-source-info-eieio
- helm-source-info-pages)
- "Default sources to use for looking up symbols at point in Info
-files with `helm-info-at-point'."
- :group 'helm-info
- :type '(repeat (choice symbol)))
-\f
-;;; Build info-index sources with `helm-info-source' class.
-
-(cl-defun helm-info-init (&optional (file (helm-attr 'info-file)))
- ;; Allow reinit candidate buffer when using edebug.
- (helm-aif (and debug-on-error
- (helm-candidate-buffer))
- (kill-buffer it))
- (unless (helm-candidate-buffer)
- (save-window-excursion
- (info file)
- (let ((tobuf (helm-candidate-buffer 'global))
- Info-history
- start end line)
- (cl-dolist (node (Info-index-nodes))
- (Info-goto-node node)
- (goto-char (point-min))
- (while (search-forward "\n* " nil t)
- (unless (search-forward "Menu:\n" (1+ (point-at-eol)) t)
- (setq start (point-at-bol)
- ;; Fix issue #1503 by getting the invisible
- ;; info displayed on next line in long strings.
- ;; e.g "* Foo.\n (line 12)" instead of
- ;; "* Foo.(line 12)"
- end (or (save-excursion
- (goto-char (point-at-bol))
- (re-search-forward "(line +[0-9]+)" nil t))
- (point-at-eol))
- ;; Long string have a new line inserted before the
- ;; invisible spec, remove it.
- line (replace-regexp-in-string
- "\n" "" (buffer-substring start end)))
- (with-current-buffer tobuf
- (insert line)
- (insert "\n")))))))))
-
-(defun helm-info-goto (node-line)
- (Info-goto-node (car node-line))
- (helm-goto-line (cdr node-line)))
-
-(defun helm-info-display-to-real (line)
- (and (string-match
- ;; This regexp is stolen from Info-apropos-matches
- "\\* +\\([^\n]*.+[^\n]*\\):[ \t]+\\([^\n]*\\)\\.\\(?:[ \t\n]*(line +\\([0-9]+\\))\\)?" line)
- (cons (format "(%s)%s" (helm-attr 'info-file) (match-string 2 line))
- (string-to-number (or (match-string 3 line) "1")))))
-
-(defclass helm-info-source (helm-source-in-buffer)
- ((info-file :initarg :info-file
- :initform nil
- :custom 'string)
- (init :initform #'helm-info-init)
- (display-to-real :initform #'helm-info-display-to-real)
- (get-line :initform #'buffer-substring)
- (action :initform '(("Goto node" . helm-info-goto)))))
-
-(defmacro helm-build-info-source (fname &rest args)
- `(helm-make-source (concat "Info Index: " ,fname) 'helm-info-source
- :info-file ,fname ,@args))
-
-(defun helm-build-info-index-command (name doc source buffer)
- "Define a helm command NAME with documentation DOC.
-Arg SOURCE will be an existing helm source named
-`helm-source-info-<NAME>' and BUFFER a string buffer name."
- (defalias (intern (concat "helm-info-" name))
- (lambda ()
- (interactive)
- (helm :sources source
- :buffer buffer
- :candidate-number-limit 1000))
- doc))
-
-(defun helm-define-info-index-sources (var-value &optional commands)
- "Define helm sources named helm-source-info-<NAME>.
-Sources are generated for all entries of `helm-default-info-index-list'.
-If COMMANDS arg is non-nil, also build commands named `helm-info-<NAME>'.
-Where NAME is an element of `helm-default-info-index-list'."
- (cl-loop for str in var-value
- for sym = (intern (concat "helm-source-info-" str))
- do (set sym (helm-build-info-source str))
- when commands
- do (helm-build-info-index-command
- str (format "Predefined helm for %s info." str)
- sym (format "*helm info %s*" str))))
-
-(defun helm-info-index-set (var value)
- (set var value)
- (helm-define-info-index-sources value t))
-\f
-;;; Search Info files
-
-;; `helm-info' is the main entry point here. It prompts the user for an Info
-;; file, then a term in the file's index to jump to.
-
-(defvar helm-info-searched (make-ring 32)
- "Ring of previously searched Info files.")
-
-(defun helm-get-info-files ()
- "Return list of Info files to use for `helm-info'.
-
-Elements of the list are strings of Info file names without
-extensions (e.g. \"emacs\" for file \"emacs.info.gz\"). Info
-files are found by searching directories in
-`Info-directory-list'."
- (let ((files (cl-loop for d in (or Info-directory-list
- Info-default-directory-list)
- when (file-directory-p d)
- append (directory-files d nil "\\.info"))))
- (helm-fast-remove-dups
- (cl-loop for f in files collect
- (helm-file-name-sans-extension f))
- :test 'equal)))
-
-(defcustom helm-default-info-index-list
- (helm-get-info-files)
- "Info files to search in with `helm-info'."
- :group 'helm-info
- :type '(repeat (choice string))
- :set 'helm-info-index-set)
-
-(defun helm-info-search-index (candidate)
- "Search the index of CANDIDATE's Info file using the function
-helm-info-<CANDIDATE>."
- (let ((helm-info-function
- (intern-soft (concat "helm-info-" candidate))))
- (when (fboundp helm-info-function)
- (funcall helm-info-function)
- (ring-insert helm-info-searched candidate))))
-
-(defun helm-def-source--info-files ()
- "Return a `helm' source for Info files."
- (helm-build-sync-source "Helm Info"
- :candidates
- (lambda () (copy-sequence helm-default-info-index-list))
- :candidate-number-limit 999
- :candidate-transformer
- (lambda (candidates)
- (sort candidates #'string-lessp))
- :nomark t
- :action '(("Search index" . helm-info-search-index))))
-
-;;;###autoload
-(defun helm-info ()
- "Preconfigured `helm' for searching Info files' indices."
- (interactive)
- (let ((default (unless (ring-empty-p helm-info-searched)
- (ring-ref helm-info-searched 0))))
- (helm :sources (helm-def-source--info-files)
- :buffer "*helm Info*"
- :preselect (and default
- (concat "\\_<" (regexp-quote default) "\\_>")))))
-\f
-;;;; Info at point
-
-;; `helm-info-at-point' is the main entry point here. It searches for the
-;; symbol at point through the Info sources defined in
-;; `helm-info-default-sources' and jumps to it.
-
-(defvar helm-info--pages-cache nil
- "Cache for all Info pages on the system.")
-
-(defvar helm-source-info-pages
- (helm-build-sync-source "Info Pages"
- :init #'helm-info-pages-init
- :candidates (lambda () helm-info--pages-cache)
- :action '(("Show with Info" .(lambda (node-str)
- (info (replace-regexp-in-string
- "^[^:]+: " "" node-str)))))
- :requires-pattern 2)
- "Helm source for Info pages.")
-
-(defun helm-info-pages-init ()
- "Collect candidates for initial Info node Top."
- (if helm-info--pages-cache
- helm-info--pages-cache
- (let ((info-topic-regexp "\\* +\\([^:]+: ([^)]+)[^.]*\\)\\.")
- topics)
- (with-temp-buffer
- (Info-find-node "dir" "top")
- (goto-char (point-min))
- (while (re-search-forward info-topic-regexp nil t)
- (push (match-string-no-properties 1) topics))
- (kill-buffer))
- (setq helm-info--pages-cache topics))))
-
-;;;###autoload
-(defun helm-info-at-point ()
- "Preconfigured `helm' for searching info at point.
-With a prefix-arg insert symbol at point."
- (interactive)
- (helm :sources helm-info-default-sources
- :buffer "*helm info*"))
-\f
-(provide 'helm-info)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-info.el ends here
+++ /dev/null
-;;; helm-locate.el --- helm interface for locate. -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;; NOTE for WINDOZE users:
-;; You have to install Everything with his command line interface here:
-;; http://www.voidtools.com/download.php
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'helm)
-(require 'helm-types)
-(require 'helm-help)
-
-\f
-(defgroup helm-locate nil
- "Locate related Applications and libraries for Helm."
- :group 'helm)
-
-(defcustom helm-locate-db-file-regexp "m?locate\.db$"
- "Default regexp to match locate database.
-If nil Search in all files."
- :type 'string
- :group 'helm-locate)
-
-(defcustom helm-ff-locate-db-filename "locate.db"
- "The basename of the locatedb file you use locally in your directories.
-When this is set and `helm' find such a file in the directory from
-where you launch locate, it will use this file and will not prompt you
-for a db file.
-Note that this happen only when locate is launched with a prefix arg."
- :group 'helm-locate
- :type 'string)
-
-(defcustom helm-locate-command nil
- "A list of arguments for locate program.
-Normally the default value should work on any system.
-
-If nil it will be calculated when `helm-locate' startup
-with these default values for different systems:
-
-Gnu/linux: \"locate %s -e --regex %s\"
-berkeley-unix: \"locate %s %s\"
-windows-nt: \"es %s %s\"
-Others: \"locate %s %s\"
-
-This string will be passed to format so it should end with `%s'.
-The first format spec is used for the \"-i\" value of locate/es,
-So don't set it directly but use `helm-locate-case-fold-search'
-for this.
-The \"-r\" option must be the last option, however if not specified you will
-be able to specify it during helm invocation by prefixing the pattern
-you enter with \"-r\"."
- :type 'string
- :group 'helm-locate)
-
-(defcustom helm-locate-create-db-command
- "updatedb -l 0 -o %s -U %s"
- "Command used to create a locale locate db file."
- :type 'string
- :group 'helm-locate)
-
-(defcustom helm-locate-case-fold-search helm-case-fold-search
- "It have the same meaning as `helm-case-fold-search'.
-The -i option of locate will be used depending of value of
-`helm-pattern' when this is set to 'smart.
-When nil \"-i\" will not be used at all.
-and when non--nil it will always be used.
-NOTE: the -i option of the \"es\" command used on windows does
-the opposite of \"locate\" command."
- :group 'helm-locate
- :type 'symbol)
-
-(defcustom helm-locate-fuzzy-match nil
- "Enable fuzzy matching in `helm-locate'."
- :group 'helm-locate
- :type 'boolean)
-
-(defcustom helm-locate-project-list nil
- "A list of directories, your projects.
-When set, allow browsing recursively files in all
-directories of this list with `helm-projects-find-files'."
- :group 'helm-locate
- :type '(repeat string))
-
-\f
-(defvar helm-generic-files-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map helm-map)
- (define-key map (kbd "C-]") 'helm-ff-run-toggle-basename)
- (define-key map (kbd "C-s") 'helm-ff-run-grep)
- (define-key map (kbd "M-g s") 'helm-ff-run-grep)
- (define-key map (kbd "M-g z") 'helm-ff-run-zgrep)
- (define-key map (kbd "M-g p") 'helm-ff-run-pdfgrep)
- (define-key map (kbd "C-c g") 'helm-ff-run-gid)
- (define-key map (kbd "M-R") 'helm-ff-run-rename-file)
- (define-key map (kbd "M-C") 'helm-ff-run-copy-file)
- (define-key map (kbd "M-B") 'helm-ff-run-byte-compile-file)
- (define-key map (kbd "M-L") 'helm-ff-run-load-file)
- (define-key map (kbd "M-S") 'helm-ff-run-symlink-file)
- (define-key map (kbd "M-H") 'helm-ff-run-hardlink-file)
- (define-key map (kbd "M-D") 'helm-ff-run-delete-file)
- (define-key map (kbd "C-=") 'helm-ff-run-ediff-file)
- (define-key map (kbd "C-c =") 'helm-ff-run-ediff-merge-file)
- (define-key map (kbd "C-c o") 'helm-ff-run-switch-other-window)
- (define-key map (kbd "C-c C-o") 'helm-ff-run-switch-other-frame)
- (define-key map (kbd "M-i") 'helm-ff-properties-persistent)
- (define-key map (kbd "C-c C-x") 'helm-ff-run-open-file-externally)
- (define-key map (kbd "C-c X") 'helm-ff-run-open-file-with-default-tool)
- (define-key map (kbd "M-.") 'helm-ff-run-etags)
- (define-key map (kbd "C-w") 'helm-yank-text-at-point)
- (define-key map (kbd "C-c @") 'helm-ff-run-insert-org-link)
- map)
- "Generic Keymap for files.")
-
-\f
-(defface helm-locate-finish
- '((t (:foreground "Green")))
- "Face used in mode line when locate process is finish."
- :group 'helm-locate)
-
-\f
-(defun helm-ff-find-locatedb (&optional from-ff)
- "Try to find if a local locatedb file is available.
-The search is done in `helm-ff-default-directory' or
-fall back to `default-directory' if FROM-FF is nil."
- (when helm-ff-locate-db-filename
- (cond ((and helm-ff-default-directory
- from-ff
- (file-exists-p (expand-file-name
- helm-ff-locate-db-filename
- helm-ff-default-directory))
- (expand-file-name
- helm-ff-locate-db-filename
- helm-ff-default-directory)))
- ((and (not from-ff)
- (file-exists-p (expand-file-name
- helm-ff-locate-db-filename
- default-directory))
- (expand-file-name
- helm-ff-locate-db-filename
- default-directory))))))
-
-
-(defun helm-locate-create-db-default-function (db-name directory)
- "Default function used to create a locale locate db file.
-Argument DB-NAME name of the db file.
-Argument DIRECTORY root of file system subtree to scan."
- (format helm-locate-create-db-command db-name directory))
-
-(defvar helm-locate-create-db-function
- #'helm-locate-create-db-default-function
- "Function used to create a locale locate db file.
-It should receive the same arguments as
-`helm-locate-create-db-default-function'.")
-
-(defun helm-locate-1 (&optional localdb init from-ff default)
- "Generic function to run Locate.
-Prefix arg LOCALDB when (4) search and use a local locate db file when it
-exists or create it, when (16) force update of existing db file
-even if exists.
-It have no effect when locate command is 'es'.
-INIT is a string to use as initial input in prompt.
-See `helm-locate-with-db' and `helm-locate'."
- (require 'helm-mode)
- (helm-locate-set-command)
- (let ((pfn (lambda (candidate)
- (if (file-directory-p candidate)
- (message "Error: The locate Db should be a file")
- (if (= (shell-command
- (funcall helm-locate-create-db-function
- candidate
- helm-ff-default-directory))
- 0)
- (message "New locatedb file `%s' created" candidate)
- (error "Failed to create locatedb file `%s'" candidate)))))
- (locdb (and localdb
- (not (string-match "^es" helm-locate-command))
- (or (and (equal '(4) localdb)
- (helm-ff-find-locatedb from-ff))
- (helm-read-file-name
- "Create Locate Db file: "
- :initial-input (expand-file-name "locate.db"
- (or helm-ff-default-directory
- default-directory))
- :preselect helm-locate-db-file-regexp
- :test (lambda (x)
- (if helm-locate-db-file-regexp
- ;; Select only locate db files and directories
- ;; to allow navigation.
- (or (string-match
- helm-locate-db-file-regexp x)
- (file-directory-p x))
- x)))))))
- (when (and locdb (or (equal localdb '(16))
- (not (file-exists-p locdb))))
- (funcall pfn locdb))
- (helm-locate-with-db (and localdb locdb) init default)))
-
-(defun helm-locate-set-command ()
- "Setup `helm-locate-command' if not already defined."
- (unless helm-locate-command
- (setq helm-locate-command
- (cl-case system-type
- (gnu/linux "locate %s -e --regex %s")
- (berkeley-unix "locate %s %s")
- (windows-nt "es %s %s")
- (t "locate %s %s")))))
-
-(defvar helm-file-name-history nil)
-(defun helm-locate-with-db (&optional db initial-input default)
- "Run locate -d DB.
-If DB is not given or nil use locate without -d option.
-Argument DB can be given as a string or list of db files.
-Argument INITIAL-INPUT is a string to use as initial-input.
-See also `helm-locate'."
- (require 'helm-files)
- (when (and db (stringp db)) (setq db (list db)))
- (helm-locate-set-command)
- (let ((helm-locate-command
- (if db
- (replace-regexp-in-string
- "locate"
- (format "locate -d %s"
- (mapconcat 'identity
- ;; Remove eventually
- ;; marked directories by error.
- (cl-loop for i in db
- unless (file-directory-p i)
- collect i) ":"))
- helm-locate-command)
- helm-locate-command)))
- (setq helm-file-name-history (mapcar 'helm-basename file-name-history))
- (helm :sources 'helm-source-locate
- :buffer "*helm locate*"
- :ff-transformer-show-only-basename nil
- :input initial-input
- :default default
- :history 'helm-file-name-history)))
-
-(defun helm-locate-init ()
- "Initialize async locate process for `helm-source-locate'."
- (let* ((locate-is-es (string-match "\\`es" helm-locate-command))
- (real-locate (string-match "\\`locate" helm-locate-command))
- (case-sensitive-flag (if locate-is-es "-i" ""))
- (ignore-case-flag (if (or locate-is-es
- (not real-locate)) "" "-i"))
- (args (split-string helm-pattern " "))
- (cmd (format helm-locate-command
- (cl-case helm-locate-case-fold-search
- (smart (let ((case-fold-search nil))
- (if (string-match "[[:upper:]]" helm-pattern)
- case-sensitive-flag
- ignore-case-flag)))
- (t (if helm-locate-case-fold-search
- ignore-case-flag
- case-sensitive-flag)))
- (concat
- ;; The pattern itself.
- (shell-quote-argument (car args)) " "
- ;; Possible locate args added
- ;; after pattern, don't quote them.
- (mapconcat 'identity (cdr args) " ")))))
- (helm-log "Starting helm-locate process")
- (helm-log "Command line used was:\n\n%s"
- (concat ">>> " (propertize cmd 'face 'font-lock-comment-face) "\n\n"))
- (prog1
- (start-process-shell-command
- "locate-process" helm-buffer
- cmd)
- (set-process-sentinel
- (get-buffer-process helm-buffer)
- (lambda (process event)
- (let* ((err (process-exit-status process))
- (noresult (= err 1)))
- (cond (noresult
- (with-helm-buffer
- (unless (cdr helm-sources)
- (insert (concat "* Exit with code 1, no result found,"
- " command line was:\n\n "
- cmd)))))
- ((string= event "finished\n")
- (with-helm-window
- (setq mode-line-format
- '(" " mode-line-buffer-identification " "
- (:eval (format "L%s" (helm-candidate-number-at-point))) " "
- (:eval (propertize
- (format "[Locate process finished - (%s results)]"
- (max (1- (count-lines
- (point-min) (point-max)))
- 0))
- 'face 'helm-locate-finish))))
- (force-mode-line-update)))
- (t
- (helm-log "Error: Locate %s"
- (replace-regexp-in-string "\n" "" event))))))))))
-
-(defclass helm-locate-source (helm-source-async helm-type-file)
- ((init :initform 'helm-locate-set-command)
- (candidates-process :initform 'helm-locate-init)
- (requires-pattern :initform 3)
- (history :initform 'helm-file-name-history)
- (persistent-action :initform 'helm-ff-kill-or-find-buffer-fname)
- (candidate-number-limit :initform 9999)))
-
-(defvar helm-source-locate
- (helm-make-source "Locate" 'helm-locate-source
- :pattern-transformer 'helm-locate-pattern-transformer))
-
-(defun helm-locate-pattern-transformer (pattern)
- (if helm-locate-fuzzy-match
- (cond ((string-match
- " " (replace-regexp-in-string " -b" "" pattern)) pattern)
- ((string-match "\\([^ ]*\\) -b" pattern)
- (concat (helm--mapconcat-pattern
- (match-string 1 pattern)) " -b"))
- (t (helm--mapconcat-pattern pattern)))
- pattern))
-
-(defun helm-locate-find-dbs-in-projects (&optional update)
- (let* ((pfn (lambda (candidate directory)
- (unless (= (shell-command
- (funcall helm-locate-create-db-function
- candidate
- directory))
- 0)
- (error "Failed to create locatedb file `%s'" candidate)))))
- (cl-loop for p in helm-locate-project-list
- for db = (expand-file-name
- helm-ff-locate-db-filename
- (file-name-as-directory p))
- if (and (null update) (file-exists-p db))
- collect db
- else do (funcall pfn db p)
- and collect db)))
-
-;;;###autoload
-(defun helm-projects-find-files (update)
- "Find files with locate in `helm-locate-project-list'.
-With a prefix arg refresh the database in each project."
- (interactive "P")
- (helm-locate-set-command)
- (cl-assert (and (string-match-p "\\`locate" helm-locate-command)
- (executable-find "updatedb"))
- nil "Unsupported locate version")
- (let ((dbs (helm-locate-find-dbs-in-projects update)))
- (if dbs
- (helm-locate-with-db dbs)
- (user-error "No projects found, please setup `helm-locate-project-list'"))))
-
-;;;###autoload
-(defun helm-locate (arg)
- "Preconfigured `helm' for Locate.
-Note: you can add locate options after entering pattern.
-See 'man locate' for valid options and also `helm-locate-command'.
-
-You can specify a local database with prefix argument ARG.
-With two prefix arg, refresh the current local db or create it
-if it doesn't exists.
-
-To create a user specific db, use
-\"updatedb -l 0 -o db_path -U directory\".
-Where db_path is a filename matched by
-`helm-locate-db-file-regexp'."
- (interactive "P")
- (setq helm-ff-default-directory default-directory)
- (helm-locate-1 arg nil nil (thing-at-point 'filename)))
-
-(provide 'helm-locate)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-locate.el ends here
+++ /dev/null
-;;; helm-man.el --- Man and woman UI -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'helm)
-(require 'helm-help)
-
-(defvar woman-topic-all-completions)
-(defvar woman-manpath)
-(defvar woman-path)
-(defvar woman-expanded-directory-path)
-(declare-function woman-file-name "woman.el" (topic &optional re-cache))
-(declare-function woman-file-name-all-completions "woman.el" (topic))
-(declare-function Man-getpage-in-background "man.el" (topic))
-(declare-function woman-expand-directory-path "woman.el" (path-dirs path-regexps))
-(declare-function woman-topic-all-completions "woman.el" (path))
-(declare-function helm-generic-sort-fn "helm-utils.el" (S1 S2))
-
-(defgroup helm-man nil
- "Man and Woman applications for helm."
- :group 'helm)
-
-(defcustom helm-man-or-woman-function 'Man-getpage-in-background
- "Default command to display a man page."
- :group 'helm-man
- :type '(radio :tag "Preferred command to display a man page"
- (const :tag "Man" Man-getpage-in-background)
- (const :tag "Woman" woman)))
-
-(defcustom helm-man-format-switches "-l %s"
- "Arguments to pass to the `manual-entry' function.
-Arguments are passed to `manual-entry' with `format.'
-Default use \"-l\" which may not be supported on old man versions,
-in this case use \"%s\" as value to pass only the filename as argument.
-See Issue #1035"
- :group 'helm-man
- :type 'string)
-
-;; Internal
-(defvar helm-man--pages nil
- "All man pages on system.
-Will be calculated the first time you invoke helm with this
-source.")
-
-(defun helm-man-default-action (candidate)
- "Default action for jumping to a woman or man page from helm."
- (let ((wfiles (mapcar
- 'car (woman-file-name-all-completions candidate))))
- (condition-case nil
- (if (> (length wfiles) 1)
- (let ((file (helm-comp-read
- "ManFile: " wfiles :must-match t)))
- (if (eq helm-man-or-woman-function 'Man-getpage-in-background)
- (manual-entry (format helm-man-format-switches file))
- (woman-find-file file)))
- (funcall helm-man-or-woman-function candidate))
- ;; If woman is unable to format correctly
- ;; use man instead.
- (error (kill-buffer) ; Kill woman buffer.
- (Man-getpage-in-background candidate)))))
-
-(defun helm-man--init ()
- (require 'woman)
- (require 'helm-utils)
- (unless helm-man--pages
- (setq woman-expanded-directory-path
- (woman-expand-directory-path woman-manpath woman-path))
- (setq woman-topic-all-completions
- (woman-topic-all-completions woman-expanded-directory-path))
- (setq helm-man--pages (mapcar 'car woman-topic-all-completions)))
- (helm-init-candidates-in-buffer 'global helm-man--pages))
-
-(defvar helm-source-man-pages
- (helm-build-in-buffer-source "Manual Pages"
- :init #'helm-man--init
- :persistent-action #'ignore
- :filtered-candidate-transformer
- (lambda (candidates _source)
- (sort candidates #'helm-generic-sort-fn))
- :action '(("Display Man page" . helm-man-default-action))))
-
-;;;###autoload
-(defun helm-man-woman (arg)
- "Preconfigured `helm' for Man and Woman pages.
-With a prefix arg reinitialize the cache."
- (interactive "P")
- (when arg (setq helm-man--pages nil))
- (helm :sources 'helm-source-man-pages
- :buffer "*helm man woman*"))
-
-(provide 'helm-man)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-man.el ends here
+++ /dev/null
-;;; helm-misc.el --- Various functions for helm -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Code:
-(require 'cl-lib)
-(require 'helm)
-(require 'helm-help)
-(require 'helm-types)
-
-(declare-function display-time-world-display "time.el")
-(defvar display-time-world-list)
-
-\f
-(defgroup helm-misc nil
- "Various Applications and libraries for Helm."
- :group 'helm)
-
-(defcustom helm-time-zone-home-location "Paris"
- "The time zone of your home"
- :group 'helm-misc
- :type 'string)
-
-(defcustom helm-timezone-actions
- '(("Set timezone env (TZ)" . (lambda (candidate)
- (setenv "TZ" candidate))))
- "Actions for helm-timezone."
- :group 'helm-misc
- :type '(alist :key-type string :value-type function))
-
-(defcustom helm-mini-default-sources '(helm-source-buffers-list
- helm-source-recentf
- helm-source-buffer-not-found)
- "Default sources list used in `helm-mini'."
- :group 'helm-misc
- :type '(repeat (choice symbol)))
-
-(defface helm-time-zone-current
- '((t (:foreground "green")))
- "Face used to colorize current time in `helm-world-time'."
- :group 'helm-misc)
-
-(defface helm-time-zone-home
- '((t (:foreground "red")))
- "Face used to colorize home time in `helm-world-time'."
- :group 'helm-misc)
-
-
-\f
-;;; Latex completion
-(defvar LaTeX-math-menu)
-(defun helm-latex-math-candidates ()
- "Collect candidates for latex math completion."
- (cl-loop for i in (cddr LaTeX-math-menu)
- for elm = (cl-loop for s in i when (vectorp s)
- collect (cons (aref s 0) (aref s 1)))
- append elm))
-
-(defvar helm-source-latex-math
- '((name . "Latex Math Menu")
- (init . (lambda ()
- (with-helm-current-buffer
- (LaTeX-math-mode 1))))
- (candidate-number-limit . 9999)
- (candidates . helm-latex-math-candidates)
- (action . (lambda (candidate)
- (call-interactively candidate)))))
-
-\f
-;;; Jabber Contacts (jabber.el)
-(defun helm-jabber-online-contacts ()
- "List online Jabber contacts."
- (with-no-warnings
- (cl-loop for item in (jabber-concat-rosters)
- when (get item 'connected)
- collect
- (if (get item 'name)
- (cons (get item 'name) item)
- (cons (symbol-name item) item)))))
-
-(defvar helm-source-jabber-contacts
- '((name . "Jabber Contacts")
- (init . (lambda () (require 'jabber)))
- (candidates . (lambda () (mapcar 'car (helm-jabber-online-contacts))))
- (action . (lambda (x)
- (jabber-chat-with
- (jabber-read-account)
- (symbol-name
- (cdr (assoc x (helm-jabber-online-contacts)))))))))
-
-;;; World time
-;;
-(defun helm-time-zone-transformer (candidates _source)
- (cl-loop for i in candidates
- for (z . p) in display-time-world-list
- collect
- (cons
- (cond ((string-match (format-time-string "%H:%M" (current-time)) i)
- (propertize i 'face 'helm-time-zone-current))
- ((string-match helm-time-zone-home-location i)
- (propertize i 'face 'helm-time-zone-home))
- (t i))
- z)))
-
-(defvar helm-source-time-world
- (helm-build-in-buffer-source "Time World List"
- :data (lambda ()
- (with-temp-buffer
- (display-time-world-display display-time-world-list)
- (buffer-string)))
- :action 'helm-timezone-actions
- :filtered-candidate-transformer 'helm-time-zone-transformer))
-
-;;; LaCarte
-;;
-;;
-(declare-function lacarte-get-overall-menu-item-alist "ext:lacarte.el" (&optional MAPS))
-
-(defun helm-lacarte-candidate-transformer (cands)
- (mapcar (lambda (cand)
- (let* ((item (car cand))
- (match (string-match "[^>] \\((.*)\\)$" item)))
- (when match
- (put-text-property (match-beginning 1) (match-end 1)
- 'face 'helm-M-x-key item))
- cand))
- cands))
-
-(defclass helm-lacarte (helm-source-sync helm-type-command)
- ((init :initform (lambda () (require 'lacarte)))
- (candidates :initform 'helm-lacarte-get-candidates)
- (candidate-transformer :initform 'helm-lacarte-candidate-transformer)
- (candidate-number-limit :initform 9999)))
-
-(defun helm-lacarte-get-candidates (&optional maps)
- "Extract candidates for menubar using lacarte.el.
-See http://www.emacswiki.org/cgi-bin/wiki/download/lacarte.el.
-Optional argument MAPS is a list specifying which keymaps to use: it
-can contain the symbols `local', `global', and `minor', mean the
-current local map, current global map, and all current minor maps."
- (with-helm-current-buffer
- ;; FIXME: do we still need to remove possible '(nil) candidates.
- (lacarte-get-overall-menu-item-alist maps)))
-
-;;;###autoload
-(defun helm-browse-menubar ()
- "Preconfigured helm to the menubar using lacarte.el."
- (interactive)
- (require 'lacarte)
- (helm :sources (mapcar
- (lambda (spec) (helm-make-source (car spec) 'helm-lacarte
- :candidates (lambda () (helm-lacarte-get-candidates (cdr spec)))))
- '(("Major Mode" . (local))
- ("Minor Modes" . (minor))
- ("Global Map" . (global))))
- :buffer "*helm lacarte*"))
-
-(defun helm-call-interactively (cmd-or-name)
- "Execute CMD-OR-NAME as Emacs command.
-It is added to `extended-command-history'.
-`helm-current-prefix-arg' is used as the command's prefix argument."
- (setq extended-command-history
- (cons (helm-stringify cmd-or-name)
- (delete (helm-stringify cmd-or-name) extended-command-history)))
- (let ((current-prefix-arg helm-current-prefix-arg)
- (cmd (helm-symbolify cmd-or-name)))
- (if (stringp (symbol-function cmd))
- (execute-kbd-macro (symbol-function cmd))
- (setq this-command cmd)
- (call-interactively cmd))))
-
-;;; Minibuffer History
-;;
-;;
-(defvar helm-source-minibuffer-history
- (helm-build-sync-source "Minibuffer History"
- :header-name (lambda (name)
- (format "%s (%s)" name minibuffer-history-variable))
- :candidates
- (lambda ()
- (let ((history (cl-loop for i in
- (symbol-value minibuffer-history-variable)
- unless (string= "" i) collect i)))
- (if (consp (car history))
- (mapcar 'prin1-to-string history)
- history)))
- :migemo t
- :multiline t
- :action (lambda (candidate)
- (delete-minibuffer-contents)
- (insert candidate))))
-
-;;; Shell history
-;;
-;;
-(defun helm-comint-input-ring-action (candidate)
- "Default action for comint history."
- (with-helm-current-buffer
- (delete-region (comint-line-beginning-position) (point-max))
- (insert candidate)))
-
-(defvar helm-source-comint-input-ring
- '((name . "Comint history")
- (candidates . (lambda ()
- (with-helm-current-buffer
- (ring-elements comint-input-ring))))
- (action . helm-comint-input-ring-action))
- "Source that provide helm completion against `comint-input-ring'.")
-
-\f
-;;; Helm ratpoison UI
-;;
-;;
-(defvar helm-source-ratpoison-commands
- '((name . "Ratpoison Commands")
- (init . helm-ratpoison-commands-init)
- (candidates-in-buffer)
- (action ("Execute the command" . helm-ratpoison-commands-execute))
- (display-to-real . helm-ratpoison-commands-display-to-real)
- (candidate-number-limit)))
-
-(defun helm-ratpoison-commands-init ()
- (unless (helm-candidate-buffer)
- (with-current-buffer (helm-candidate-buffer 'global)
- ;; with ratpoison prefix key
- (save-excursion
- (call-process "ratpoison" nil (current-buffer) nil "-c" "help"))
- (while (re-search-forward "^\\([^ ]+\\) \\(.+\\)$" nil t)
- (replace-match "<ratpoison> \\1: \\2"))
- (goto-char (point-max))
- ;; direct binding
- (save-excursion
- (call-process "ratpoison" nil (current-buffer) nil "-c" "help top"))
- (while (re-search-forward "^\\([^ ]+\\) \\(.+\\)$" nil t)
- (replace-match "\\1: \\2")))))
-
-(defun helm-ratpoison-commands-display-to-real (display)
- (and (string-match ": " display)
- (substring display (match-end 0))))
-
-(defun helm-ratpoison-commands-execute (candidate)
- (call-process "ratpoison" nil nil nil "-ic" candidate))
-
-;;; Helm stumpwm UI
-;;
-;;
-(defvar helm-source-stumpwm-commands
- '((name . "Stumpwm Commands")
- (init . helm-stumpwm-commands-init)
- (candidates-in-buffer)
- (action ("Execute the command" . helm-stumpwm-commands-execute))
- (candidate-number-limit)))
-
-(defun helm-stumpwm-commands-init ()
- (with-current-buffer (helm-candidate-buffer 'global)
- (save-excursion
- (call-process "stumpish" nil (current-buffer) nil "commands"))
- (while (re-search-forward "[ ]*\\([^ ]+\\)[ ]*\n?" nil t)
- (replace-match "\n\\1\n"))
- (delete-blank-lines)
- (sort-lines nil (point-min) (point-max))
- (goto-char (point-max))))
-
-(defun helm-stumpwm-commands-execute (candidate)
- (call-process "stumpish" nil nil nil candidate))
-
-;;;###autoload
-(defun helm-world-time ()
- "Preconfigured `helm' to show world time.
-Default action change TZ environment variable locally to emacs."
- (interactive)
- (helm-other-buffer 'helm-source-time-world "*helm world time*"))
-
-;;;###autoload
-(defun helm-insert-latex-math ()
- "Preconfigured helm for latex math symbols completion."
- (interactive)
- (helm-other-buffer 'helm-source-latex-math "*helm latex*"))
-
-;;;###autoload
-(defun helm-ratpoison-commands ()
- "Preconfigured `helm' to execute ratpoison commands."
- (interactive)
- (helm-other-buffer 'helm-source-ratpoison-commands
- "*helm ratpoison commands*"))
-
-;;;###autoload
-(defun helm-stumpwm-commands()
- "Preconfigured helm for stumpwm commands."
- (interactive)
- (helm-other-buffer 'helm-source-stumpwm-commands
- "*helm stumpwm commands*"))
-
-;;;###autoload
-(defun helm-minibuffer-history ()
- "Preconfigured `helm' for `minibuffer-history'."
- (interactive)
- (let ((enable-recursive-minibuffers t))
- (helm :sources 'helm-source-minibuffer-history
- :buffer "*helm minibuffer-history*")))
-
-;;;###autoload
-(defun helm-comint-input-ring ()
- "Preconfigured `helm' that provide completion of `comint' history."
- (interactive)
- (when (derived-mode-p 'comint-mode)
- (helm :sources 'helm-source-comint-input-ring
- :input (buffer-substring-no-properties (comint-line-beginning-position)
- (point-at-eol))
- :buffer "*helm comint history*")))
-
-
-(provide 'helm-misc)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-misc.el ends here
+++ /dev/null
-;;; helm-mode.el --- Enable helm completion everywhere. -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'helm)
-(require 'helm-files)
-
-\f
-(defgroup helm-mode nil
- "Enable helm completion."
- :group 'helm)
-
-(defcustom helm-completing-read-handlers-alist
- '((describe-function . helm-completing-read-symbols)
- (describe-variable . helm-completing-read-symbols)
- (describe-symbol . helm-completing-read-symbols)
- (debug-on-entry . helm-completing-read-symbols)
- (find-function . helm-completing-read-symbols)
- (disassemble . helm-completing-read-symbols)
- (trace-function . helm-completing-read-symbols)
- (trace-function-foreground . helm-completing-read-symbols)
- (trace-function-background . helm-completing-read-symbols)
- (find-tag . helm-completing-read-with-cands-in-buffer)
- (org-capture . helm-org-completing-read-tags)
- (org-set-tags . helm-org-completing-read-tags)
- (ffap-alternate-file . nil)
- (tmm-menubar . nil)
- (find-file . nil)
- (execute-extended-command . nil))
- "Alist of handlers to replace `completing-read', `read-file-name' in `helm-mode'.
-Each entry is a cons cell like \(emacs_command . completing-read_handler\)
-where key and value are symbols.
-
-Each key is an Emacs command that use originaly `completing-read'.
-
-Each value maybe an helm function that take same arguments as
-`completing-read' plus NAME and BUFFER, where NAME is the name of the new
-helm source and BUFFER the name of the buffer we will use.
-This function prefix name must start by \"helm\".
-
-See `helm-completing-read-symbols' for example.
-
-Note that this function will be reused for ALL the `completing-read'
-of this command, so it should handle all cases, e.g
-If first `completing-read' complete against symbols and
-second `completing-read' should handle only buffer,
-your specialized function should handle the both.
-
-If the value of an entry is nil completion will fall back to
-emacs vanilla behavior.
-e.g If you want to disable helm completion for `describe-function':
-\(describe-function . nil\).
-
-Ido is also supported, you can use `ido-completing-read' and
-`ido-read-file-name' as value of an entry or just 'ido.
-e.g ido completion for `find-file':
-\(find-file . ido\)
-same as
-\(find-file . ido-read-file-name\)
-Note that you don't need to enable `ido-mode' for this to work."
- :group 'helm-mode
- :type '(alist :key-type symbol :value-type symbol))
-
-(defcustom helm-comp-read-case-fold-search helm-case-fold-search
- "Default Local setting of `helm-case-fold-search' for `helm-comp-read'.
-See `helm-case-fold-search' for more info."
- :group 'helm-mode
- :type 'symbol)
-
-(defcustom helm-mode-handle-completion-in-region t
- "Whether to replace or not `completion-in-region-function'.
-This enable support for `completing-read-multiple' and `completion-at-point'
-when non--nil."
- :group 'helm-mode
- :type 'boolean)
-
-(defcustom helm-mode-reverse-history t
- "Display history source after current source in `helm-mode' handled commands."
- :group 'helm-mode
- :type 'boolean)
-
-(defcustom helm-mode-no-completion-in-region-in-modes nil
- "A list of modes that do not want helm for `completion-in-region'."
- :group 'helm-mode
- :type 'boolean)
-
-(defcustom helm-completion-in-region-fuzzy-match nil
- "Whether `helm-completion-in-region' use fuzzy matching or not.
-Affect among others `completion-at-point', `completing-read-multiple'."
- :group 'helm-mode
- :type 'boolean)
-
-(defcustom helm-mode-fuzzy-match nil
- "Enable fuzzy matching in `helm-mode' globally.
-Note that this will slow down completion and modify sorting
-which is unwanted in many places.
-This affect only the functions with completing-read helmized by helm-mode.
-To fuzzy match `completion-at-point' and friends see
-`helm-completion-in-region-fuzzy-match'."
- :group 'helm-mode
- :type 'boolean)
-
-(defcustom helm-mode-minibuffer-setup-hook-black-list '(minibuffer-completion-help)
- "Incompatible `minibuffer-setup-hook' functions go here.
-A list of symbols.
-Helm-mode is rejecting all lambda's, byte-code fns
-and all functions belonging in this list from `minibuffer-setup-hook'."
- :group 'helm-mode
- :type '(repeat (choice symbol)))
-
-\f
-(defvar helm-comp-read-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map helm-map)
- (define-key map (kbd "<C-return>") 'helm-cr-empty-string)
- (define-key map (kbd "<M-RET>") 'helm-cr-empty-string)
- map)
- "Keymap for `helm-comp-read'.")
-
-(defvar helm-comp-read-must-match-map
- (let ((map (make-sparse-keymap)))
- (define-key map (kbd "RET")
- 'helm-confirm-and-exit-minibuffer)
- map)
- "Keymap use as must-match-map in `helm-comp-read' and `helm-read-file-name'.")
-
-\f
-;;; Internal
-;;
-;;
-;; Flag to know if `helm-pattern' have been added
-;; to candidate list in `helm-comp-read'.
-(defvar helm-cr-unknown-pattern-flag nil)
-
-\f
-;;; Helm `completing-read' replacement
-;;
-;;
-(defun helm-cr-empty-string ()
- "Return empty string."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action
- (lambda (_candidate)
- (identity "")))))
-(put 'helm-cr-empty-string 'helm-only t)
-
-(defun helm-mode--keyboard-quit ()
- ;; Use this instead of `keyboard-quit'
- ;; to avoid deactivating mark in current-buffer.
- (let ((debug-on-quit nil))
- (signal 'quit nil)))
-
-(cl-defun helm-comp-read-get-candidates (collection &optional test sort-fn alistp (input ""))
- "Convert COLLECTION to list removing elements that don't match TEST.
-See `helm-comp-read' about supported COLLECTION arguments.
-
-SORT-FN is a predicate to sort COLLECTION.
-
-ALISTP when non--nil will not use `all-completions' to collect
-candidates because it doesn't handle alists correctly for helm.
-i.e In `all-completions' the car of each pair is used as value.
-In helm we want to use the cdr instead like \(display . real\),
-so we return the alist as it is with no transformation by all-completions.
-
-e.g
-
-\(setq A '((a . 1) (b . 2) (c . 3)))
-==>((a . 1) (b . 2) (c . 3))
-\(helm-comp-read \"test: \" A :alistp nil
- :exec-when-only-one t
- :initial-input \"a\")
-==>\"a\" Which is not what we expect.
-
-\(helm-comp-read \"test: \" A :alistp t
- :exec-when-only-one t
- :initial-input \"1\")
-==>\"1\"
-
-See docstring of `all-completions' for more info.
-
-If COLLECTION is an `obarray', a TEST should be needed. See `obarray'."
- ;; Ensure COLLECTION is computed from `helm-current-buffer'
- ;; because some functions used as COLLECTION work
- ;; only in the context of current-buffer (Issue #1030) .
- (with-helm-current-buffer
- (let ((cands
- (cond ((vectorp collection)
- (all-completions input collection test))
- ((and (symbolp collection) (boundp collection)
- ;; Issue #324 history is let-bounded and given
- ;; quoted as hist argument of completing-read.
- ;; See example in `rcirc-browse-url'.
- (symbolp (symbol-value collection)))
- nil)
- ;; When collection is a symbol, most of the time
- ;; it should be a symbol used as a minibuffer-history.
- ;; The value of this symbol in this case return a list
- ;; of string which maybe are converted later as symbol
- ;; in special cases.
- ;; we treat here commandp as a special case as it return t
- ;; also with a string unless its last arg is provided.
- ;; Also, the history collections generally collect their
- ;; elements as string, so intern them to call predicate.
- ((and (symbolp collection) (boundp collection) test)
- (let ((predicate `(lambda (elm)
- (condition-case err
- (if (eq (quote ,test) 'commandp)
- (funcall (quote ,test) (intern elm))
- (funcall (quote ,test) elm))
- (wrong-type-argument
- (funcall (quote ,test) (intern elm)))))))
- (all-completions input (symbol-value collection) predicate)))
- ((and (symbolp collection) (boundp collection))
- (all-completions input (symbol-value collection)))
- ;; Normally file completion should not be handled here,
- ;; but special cases like `find-file-at-point' do it.
- ;; Handle here specially such cases.
- ((and (functionp collection) minibuffer-completing-file-name)
- (cl-loop for f in (funcall collection helm-pattern test t)
- unless (member f '("./" "../"))
- if (string-match ffap-url-regexp helm-pattern)
- collect f
- else
- collect (concat (file-name-as-directory
- (helm-basedir helm-pattern)) f)))
- ((functionp collection)
- (funcall collection input test t))
- ((and alistp test)
- (cl-loop for i in collection when (funcall test i) collect i))
- (alistp collection)
- (t (all-completions input collection test)))))
- (if sort-fn (sort cands sort-fn) cands))))
-
-(defun helm-cr-default-transformer (candidates _source)
- "Default filter candidate function for `helm-comp-read'."
- (cl-loop for c in candidates
- for cand = (if (stringp c) (replace-regexp-in-string "\\s\\" "" c) c)
- for pat = (replace-regexp-in-string "\\s\\" "" helm-pattern)
- if (and (equal cand pat) helm-cr-unknown-pattern-flag)
- collect
- (cons (concat (propertize
- " " 'display
- (propertize "[?]" 'face 'helm-ff-prefix))
- c)
- c)
- into lst
- else collect (if (and (stringp c)
- (string-match "\n" c))
- (cons (replace-regexp-in-string "\n" "->" c) c)
- c)
- into lst
- finally return (helm-fast-remove-dups lst :test 'equal)))
-
-(defun helm-comp-read--move-to-first-real-candidate ()
- (helm-aif (helm-get-selection nil 'withprop)
- (when (string= (get-text-property 0 'display it) "[?]")
- (helm-next-line))))
-
-;;;###autoload
-(cl-defun helm-comp-read (prompt collection
- &key
- test
- initial-input
- default
- preselect
- (buffer "*Helm Completions*")
- must-match
- fuzzy
- reverse-history
- (requires-pattern 0)
- history
- input-history
- (case-fold helm-comp-read-case-fold-search)
- (del-input t)
- (persistent-action nil)
- (persistent-help "DoNothing")
- (mode-line helm-comp-read-mode-line)
- help-message
- (keymap helm-comp-read-map)
- (name "Helm Completions")
- candidates-in-buffer
- exec-when-only-one
- quit-when-no-cand
- (volatile t)
- sort
- (fc-transformer 'helm-cr-default-transformer)
- hist-fc-transformer
- marked-candidates
- nomark
- (alistp t)
- (candidate-number-limit helm-candidate-number-limit))
- "Read a string in the minibuffer, with helm completion.
-
-It is helm `completing-read' equivalent.
-
-- PROMPT is the prompt name to use.
-
-- COLLECTION can be a list, vector, obarray or hash-table.
- It can be also a function that receives three arguments:
- the values string, predicate and t. See `all-completions' for more details.
-
-Keys description:
-
-- TEST: A predicate called with one arg i.e candidate.
-
-- INITIAL-INPUT: Same as input arg in `helm'.
-
-- PRESELECT: See preselect arg of `helm'.
-
-- DEFAULT: This option is used only for compatibility with regular
- Emacs `completing-read' (Same as DEFAULT arg of `completing-read').
-
-- BUFFER: Name of helm-buffer.
-
-- MUST-MATCH: Candidate selected must be one of COLLECTION.
-
-- FUZZY: Enable fuzzy matching.
-
-- REVERSE-HISTORY: When non--nil display history source after current
- source completion.
-
-- REQUIRES-PATTERN: Same as helm attribute, default is 0.
-
-- HISTORY: A list containing specific history, default is nil.
- When it is non--nil, all elements of HISTORY are displayed in
- a special source before COLLECTION.
-
-- INPUT-HISTORY: A symbol. the minibuffer input history will be
- stored there, if nil or not provided, `minibuffer-history'
- will be used instead.
-
-- CASE-FOLD: Same as `helm-case-fold-search'.
-
-- DEL-INPUT: Boolean, when non--nil (default) remove the partial
- minibuffer input from HISTORY is present.
-
-- PERSISTENT-ACTION: A function called with one arg i.e candidate.
-
-- PERSISTENT-HELP: A string to document PERSISTENT-ACTION.
-
-- MODE-LINE: A string or list to display in mode line.
- Default is `helm-comp-read-mode-line'.
-
-- KEYMAP: A keymap to use in this `helm-comp-read'.
- (the keymap will be shared with history source)
-
-- NAME: The name related to this local source.
-
-- EXEC-WHEN-ONLY-ONE: Bound `helm-execute-action-at-once-if-one'
- to non--nil. (possibles values are t or nil).
-
-- VOLATILE: Use volatile attribute.
-
-- SORT: A predicate to give to `sort' e.g `string-lessp'
- Use this only on small data as it is ineficient.
- If you want to sort faster add a sort function to
- FC-TRANSFORMER.
- Note that FUZZY when enabled is already providing a sort function.
-
-- FC-TRANSFORMER: A `filtered-candidate-transformer' function
- or a list of functions.
-
-- HIST-FC-TRANSFORMER: A `filtered-candidate-transformer'
- function for the history source.
-
-- MARKED-CANDIDATES: If non--nil return candidate or marked candidates as a list.
-
-- NOMARK: When non--nil don't allow marking candidates.
-
-- ALISTP: \(default is non--nil\) See `helm-comp-read-get-candidates'.
-
-- CANDIDATES-IN-BUFFER: when non--nil use a source build with
- `helm-source-in-buffer' which is much faster.
- Argument VOLATILE have no effect when CANDIDATES-IN-BUFFER is non--nil.
-
-Any prefix args passed during `helm-comp-read' invocation will be recorded
-in `helm-current-prefix-arg', otherwise if prefix args were given before
-`helm-comp-read' invocation, the value of `current-prefix-arg' will be used.
-That's mean you can pass prefix args before or after calling a command
-that use `helm-comp-read' See `helm-M-x' for example."
-
- (when (get-buffer helm-action-buffer)
- (kill-buffer helm-action-buffer))
- (let ((action-fn `(("Sole action (Identity)"
- . (lambda (candidate)
- (if ,marked-candidates
- (helm-marked-candidates)
- (identity candidate)))))))
- ;; Assume completion have been already required,
- ;; so always use 'confirm.
- (when (eq must-match 'confirm-after-completion)
- (setq must-match 'confirm))
- (let* ((minibuffer-completion-confirm must-match)
- (must-match-map (when must-match helm-comp-read-must-match-map))
- (loc-map (if must-match-map
- (make-composed-keymap
- must-match-map (or keymap helm-map))
- (or keymap helm-map)))
- (minibuffer-completion-predicate test)
- (minibuffer-completion-table collection)
- (helm-read-file-name-mode-line-string
- (replace-regexp-in-string "helm-maybe-exit-minibuffer"
- "helm-confirm-and-exit-minibuffer"
- helm-read-file-name-mode-line-string))
- (get-candidates (lambda ()
- (let ((cands (helm-comp-read-get-candidates
- collection test sort alistp)))
- (setq helm-cr-unknown-pattern-flag nil)
- (unless (or (eq must-match t)
- (string= helm-pattern "")
- (assoc helm-pattern cands)
- (assoc (intern helm-pattern) cands)
- (member helm-pattern cands)
- (member (downcase helm-pattern) cands)
- (member (upcase helm-pattern) cands))
- (setq cands (append (list
- ;; Unquote helm-pattern
- ;; when it is added
- ;; as candidate.
- (replace-regexp-in-string
- "\\s\\" "" helm-pattern))
- cands))
- (setq helm-cr-unknown-pattern-flag t))
- ;; When DEFAULT is initially a list, candidates
- ;; come already computed with DEFAULT list appended,
- ;; and DEFAULT is set to the car of this list.
- (if (and default (not (string= default "")))
- (delq nil (cons default (delete default cands)))
- cands))))
- (history-get-candidates (lambda ()
- (let ((all (helm-comp-read-get-candidates
- history test nil alistp)))
- (when all
- (delete
- ""
- (helm-fast-remove-dups
- (if (and default (not (string= default "")))
- (delq nil (cons default
- (delete default all)))
- all)
- :test 'equal))))))
- (src-hist (helm-build-sync-source (format "%s History" name)
- :candidates history-get-candidates
- :fuzzy-match fuzzy
- :filtered-candidate-transformer
- (append '((lambda (candidates sources)
- (cl-loop for i in candidates
- ;; Input is added to history in completing-read's
- ;; and may be regexp-quoted, so unquote it.
- for cand = (replace-regexp-in-string "\\s\\" "" i)
- collect cand)))
- (and hist-fc-transformer (helm-mklist hist-fc-transformer)))
- :persistent-action persistent-action
- :persistent-help persistent-help
- :mode-line mode-line
- :help-message help-message
- :action action-fn))
- (src (helm-build-sync-source name
- :candidates get-candidates
- :filtered-candidate-transformer fc-transformer
- :requires-pattern requires-pattern
- :persistent-action persistent-action
- :persistent-help persistent-help
- :fuzzy-match fuzzy
- :mode-line mode-line
- :help-message help-message
- :action action-fn
- :volatile volatile))
- (src-1 (helm-build-in-buffer-source name
- :data get-candidates
- :filtered-candidate-transformer fc-transformer
- :requires-pattern requires-pattern
- :persistent-action persistent-action
- :fuzzy-match fuzzy
- :persistent-help persistent-help
- :mode-line mode-line
- :help-message help-message
- :action action-fn))
- (src-list (list src-hist
- (if candidates-in-buffer
- src-1 src)))
- (helm-execute-action-at-once-if-one exec-when-only-one)
- (helm-quit-if-no-candidate quit-when-no-cand)
- result)
- (when nomark
- (setq src-list (cl-loop for src in src-list
- collect (cons '(nomark) src))))
- (when reverse-history (setq src-list (nreverse src-list)))
- (add-hook 'helm-after-update-hook 'helm-comp-read--move-to-first-real-candidate)
- (unwind-protect
- (setq result (helm
- :sources src-list
- :input initial-input
- :default default
- :preselect preselect
- :prompt prompt
- :resume 'noresume
- :candidate-number-limit candidate-number-limit
- :case-fold-search case-fold
- :keymap loc-map
- :history (and (symbolp input-history) input-history)
- :buffer buffer))
- (remove-hook 'helm-after-update-hook 'helm-comp-read--move-to-first-real-candidate))
- ;; Avoid adding an incomplete input to history.
- (when (and result history del-input)
- (cond ((and (symbolp history) ; History is a symbol.
- (not (symbolp (symbol-value history)))) ; Fix Issue #324.
- ;; Be sure history is not a symbol with a nil value.
- (helm-aif (symbol-value history) (setcar it result)))
- ((consp history) ; A list with a non--nil value.
- (setcar history result))
- (t ; Possibly a symbol with a nil value.
- (set history (list result)))))
- (or
- result
- (when (and (eq helm-exit-status 0)
- (eq must-match 'confirm))
- ;; Return empty string only if it is the DEFAULT
- ;; value and helm-pattern is empty.
- ;; otherwise return helm-pattern
- (if (and (string= helm-pattern "") default)
- default (identity helm-pattern)))
- (unless (or (eq helm-exit-status 1)
- must-match) ; FIXME this should not be needed now.
- default)
- (helm-mode--keyboard-quit)))))
-
-;; Generic completing-read
-;;
-;; Support also function as collection.
-;; e.g M-x man is supported.
-;; Support hash-table and vectors as collection.
-;; NOTE:
-;; Some crap emacs functions may not be supported
-;; like ffap-alternate-file (bad use of completing-read)
-;; and maybe others.
-;; Provide a mode `helm-mode' which turn on
-;; helm in all `completing-read' and `read-file-name' in Emacs.
-;;
-(defvar helm-completion-mode-string " Helm")
-
-(defvar helm-completion-mode-quit-message
- "Helm completion disabled")
-
-(defvar helm-completion-mode-start-message
- "Helm completion enabled")
-
-;;; Specialized handlers
-;;
-;;
-(defun helm-completing-read-symbols
- (prompt _collection test _require-match init
- hist default _inherit-input-method name buffer)
- "Specialized function for fast symbols completion in `helm-mode'."
- (require 'helm-elisp)
- (or
- (helm
- :sources (helm-build-in-buffer-source name
- :init (lambda ()
- (helm-apropos-init (lambda (x)
- (and (funcall test x)
- (not (keywordp x))))
- (or (car-safe default) default)))
- :filtered-candidate-transformer 'helm-apropos-default-sort-fn
- :fuzzy-match helm-mode-fuzzy-match
- :persistent-action
- (lambda (candidate)
- (helm-lisp-completion-persistent-action
- candidate name))
- :persistent-help (helm-lisp-completion-persistent-help))
- :prompt prompt
- :buffer buffer
- :input init
- :history hist
- :resume 'noresume
- :default (or default ""))
- (helm-mode--keyboard-quit)))
-
-
-;;; Generic completing read
-;;
-;;
-(defun helm-completing-read-default-1
- (prompt collection test require-match
- init hist default _inherit-input-method
- name buffer &optional cands-in-buffer exec-when-only-one)
- "Call `helm-comp-read' with same args as `completing-read'.
-Extra optional arg CANDS-IN-BUFFER mean use `candidates-in-buffer'
-method which is faster.
-It should be used when candidate list don't need to rebuild dynamically."
- (let ((history (or (car-safe hist) hist))
- (alistp cands-in-buffer)
- (initial-input (helm-aif (pcase init
- ((pred (stringp)) init)
- ;; INIT is a cons cell.
- (`(,l . ,_ll) l))
- (if minibuffer-completing-file-name it
- (regexp-quote it)))))
- (when (and default (listp default))
- ;; When DEFAULT is a list move the list on head of COLLECTION
- ;; and set it to its car. #bugfix `grep-read-files'.
- (setq collection
- ;; COLLECTION is maybe a function or a table.
- (append default
- (helm-comp-read-get-candidates
- collection test nil (listp collection))))
- ;; Ensure `all-completions' will not be used
- ;; a second time to recompute COLLECTION [1].
- (setq alistp t)
- (setq default (car default)))
- (helm-comp-read
- prompt collection
- :test test
- :history history
- :reverse-history helm-mode-reverse-history
- :input-history history
- :must-match require-match
- :alistp alistp ; Ensure `all-completions' is used when non-nil [1].
- :name name
- :requires-pattern (if (and (string= default "")
- (or (eq require-match 'confirm)
- (eq require-match
- 'confirm-after-completion)))
- 1 0)
- :candidates-in-buffer cands-in-buffer
- :exec-when-only-one exec-when-only-one
- :fuzzy helm-mode-fuzzy-match
- :buffer buffer
- ;; If DEF is not provided, fallback to empty string
- ;; to avoid `thing-at-point' to be appended on top of list
- :default (or default "")
- ;; Fail with special characters (e.g in gnus "nnimap+gmail:")
- ;; if regexp-quote is not used.
- ;; when init is added to history, it will be unquoted by
- ;; helm-comp-read.
- :initial-input initial-input)))
-
-(defun helm-completing-read-with-cands-in-buffer
- (prompt collection test require-match
- init hist default inherit-input-method
- name buffer)
- "Same as `helm-completing-read-default-1' but use candidates-in-buffer."
- ;; Some commands like find-tag may use `read-file-name' from inside
- ;; the calculation of collection. in this case it clash with
- ;; candidates-in-buffer that reuse precedent data (files) which is wrong.
- ;; So (re)calculate collection outside of main helm-session.
- (let ((cands (all-completions (or init "") collection)))
- (helm-completing-read-default-1 prompt cands test require-match
- init hist default inherit-input-method
- name buffer t)))
-
-(cl-defun helm--completing-read-default
- (prompt collection &optional
- predicate require-match
- initial-input hist def
- inherit-input-method)
- "An helm replacement of `completing-read'.
-This function should be used only as a `completing-read-function'.
-
-Don't use it directly, use instead `helm-comp-read' in your programs.
-
-See documentation of `completing-read' and `all-completions' for details."
- (let* ((current-command (or (helm-this-command) this-command))
- (str-command (helm-symbol-name current-command))
- (buf-name (format "*helm-mode-%s*" str-command))
- (entry (assq current-command
- helm-completing-read-handlers-alist))
- (def-com (cdr-safe entry))
- (str-defcom (and def-com (helm-symbol-name def-com)))
- (def-args (list prompt collection predicate require-match
- initial-input hist def inherit-input-method))
- ;; Append the two extra args needed to set the buffer and source name
- ;; in helm specialized functions.
- (any-args (append def-args (list str-command buf-name)))
- helm-completion-mode-start-message ; Be quiet
- helm-completion-mode-quit-message
- ;; Be sure this pesty *completion* buffer doesn't popup.
- ;; Note: `minibuffer-with-setup-hook' may setup a lambda
- ;; calling `minibuffer-completion-help' or other minibuffer
- ;; functions we DONT WANT here, in these cases removing the hook
- ;; (a symbol) have no effect. Issue #448.
- ;; Because `minibuffer-completion-table' and
- ;; `minibuffer-completion-predicate' are not bound
- ;; anymore here, these functions should have no effect now,
- ;; except in some rare cases like in `woman-file-name',
- ;; so remove all incompatible functions
- ;; from `minibuffer-setup-hook' (Issue #1205, #1240).
- ;; otherwise helm have not the time to close its initial session.
- (minibuffer-setup-hook
- (cl-loop for h in minibuffer-setup-hook
- unless (or (consp h) ; a lambda.
- (byte-code-function-p h)
- (memq h helm-mode-minibuffer-setup-hook-black-list))
- collect h))
- ;; Disable hack that could be used before `completing-read'.
- ;; i.e (push ?\t unread-command-events).
- unread-command-events)
- (when (eq def-com 'ido) (setq def-com 'ido-completing-read))
- (unless (or (not entry) def-com)
- ;; An entry in *read-handlers-alist exists but have
- ;; a nil value, so we exit from here, disable `helm-mode'
- ;; and run the command again with it original behavior.
- ;; `helm-mode' will be restored on exit.
- (cl-return-from helm--completing-read-default
- (unwind-protect
- (progn
- (helm-mode -1)
- (apply completing-read-function def-args))
- (helm-mode 1))))
- ;; If we use now `completing-read' we MUST turn off `helm-mode'
- ;; to avoid infinite recursion and CRASH. It will be reenabled on exit.
- (when (or (eq def-com 'completing-read)
- ;; All specialized functions are prefixed by "helm"
- (and (stringp str-defcom)
- (not (string-match "^helm" str-defcom))))
- (helm-mode -1))
- (unwind-protect
- (cond (;; An helm specialized function exists, run it.
- (and def-com helm-mode)
- (apply def-com any-args))
- (;; Try to handle `ido-completing-read' everywhere.
- (and def-com (eq def-com 'ido-completing-read))
- (setcar (memq collection def-args)
- (all-completions "" collection predicate))
- (apply def-com def-args))
- (;; User set explicitely `completing-read' or something similar
- ;; in *read-handlers-alist, use this with exactly the same
- ;; args as in `completing-read'.
- ;; If we are here `helm-mode' is now disabled.
- def-com
- (apply def-com def-args))
- (t ; Fall back to classic `helm-comp-read'.
- (helm-completing-read-default-1
- prompt collection predicate require-match
- initial-input hist def inherit-input-method
- str-command buf-name)))
- (helm-mode 1)
- ;; When exiting minibuffer, `this-command' is set to
- ;; `helm-exit-minibuffer', which is unwanted when starting
- ;; on another `completing-read', so restore `this-command' to
- ;; initial value when exiting.
- (setq this-command current-command))))
-\f
-;;; Generic read-file-name
-;;
-;;
-;;;###autoload
-(cl-defun helm-read-file-name
- (prompt
- &key
- (name "Read File Name")
- (initial-input default-directory)
- (buffer "*Helm file completions*")
- test
- (case-fold helm-file-name-case-fold-search)
- preselect
- history
- must-match
- default
- marked-candidates
- (candidate-number-limit helm-ff-candidate-number-limit)
- nomark
- (alistp t)
- (persistent-action 'helm-find-files-persistent-action)
- (persistent-help "Hit1 Expand Candidate, Hit2 or (C-u) Find file")
- (mode-line helm-read-file-name-mode-line-string))
- "Read a file name with helm completion.
-It is helm `read-file-name' emulation.
-
-Argument PROMPT is the default prompt to use.
-
-Keys description:
-
-- NAME: Source name, default to \"Read File Name\".
-
-- INITIAL-INPUT: Where to start read file name, default to `default-directory'.
-
-- BUFFER: `helm-buffer' name default to \"*Helm Completions*\".
-
-- TEST: A predicate called with one arg 'candidate'.
-
-- CASE-FOLD: Same as `helm-case-fold-search'.
-
-- PRESELECT: helm preselection.
-
-- HISTORY: Display HISTORY in a special source.
-
-- MUST-MATCH: Can be 'confirm, nil, or t.
-
-- MARKED-CANDIDATES: When non--nil return a list of marked candidates.
-
-- NOMARK: When non--nil don't allow marking candidates.
-
-- ALISTP: Don't use `all-completions' in history (take effect only on history).
-
-- PERSISTENT-ACTION: a persistent action function.
-
-- PERSISTENT-HELP: persistent help message.
-
-- MODE-LINE: A mode line message, default is `helm-read-file-name-mode-line-string'."
-
- (when (get-buffer helm-action-buffer)
- (kill-buffer helm-action-buffer))
- ;; Assume completion have been already required,
- ;; so always use 'confirm.
- (when (eq must-match 'confirm-after-completion)
- (setq must-match 'confirm))
- (mapc (lambda (hook)
- (add-hook 'helm-after-update-hook hook))
- '(helm-ff-move-to-first-real-candidate
- helm-ff-update-when-only-one-matched
- helm-ff-auto-expand-to-home-or-root))
- (let* ((action-fn `(("Sole action (Identity)"
- . (lambda (candidate)
- (if ,marked-candidates
- (helm-marked-candidates :with-wildcard t)
- (identity candidate))))))
- ;; Be sure we don't erase the underlying minibuffer if some.
- (helm-ff-auto-update-initial-value
- (and helm-ff-auto-update-initial-value
- (not (minibuffer-window-active-p (minibuffer-window)))))
- helm-full-frame
- (hist (and history (helm-comp-read-get-candidates
- history nil nil alistp)))
- (minibuffer-completion-confirm must-match)
- (must-match-map (when must-match helm-comp-read-must-match-map))
- (cmap (if must-match-map
- (make-composed-keymap
- must-match-map helm-read-file-map)
- helm-read-file-map))
- (minibuffer-completion-predicate test)
- (minibuffer-completing-file-name t)
- (helm-read-file-name-mode-line-string
- (replace-regexp-in-string "helm-maybe-exit-minibuffer"
- "helm-confirm-and-exit-minibuffer"
- helm-read-file-name-mode-line-string))
- (src-list
- (list
- ;; History source.
- (helm-build-sync-source (format "%s History" name)
- :header-name (lambda (name)
- (concat name (substitute-command-keys
- helm-find-files-doc-header)))
- :mode-line mode-line
- :candidates hist
- :nohighlight t
- :persistent-action persistent-action
- :persistent-help persistent-help
- :nomark nomark
- :action action-fn)
- ;; Other source.
- (helm-build-sync-source name
- :header-name (lambda (name)
- (concat name (substitute-command-keys
- helm-find-files-doc-header)))
- :init (lambda ()
- (setq helm-ff-auto-update-flag
- helm-ff-auto-update-initial-value)
- (setq helm-ff--auto-update-state
- helm-ff-auto-update-flag))
- :mode-line mode-line
- :help-message 'helm-read-file-name-help-message
- :nohighlight t
- :candidates
- (lambda ()
- (append (and (not (file-exists-p helm-pattern))
- (list helm-pattern))
- (if test
- (cl-loop with hn = (helm-ff-tramp-hostnames)
- for i in (helm-find-files-get-candidates
- must-match)
- when (or (member i hn) ; A tramp host
- (funcall test i)) ; Test ok
- collect i)
- (helm-find-files-get-candidates must-match))))
- :filtered-candidate-transformer 'helm-ff-sort-candidates
- :filter-one-by-one 'helm-ff-filter-candidate-one-by-one
- :persistent-action persistent-action
- :persistent-help persistent-help
- :volatile t
- :cleanup 'helm-find-files-cleanup
- :nomark nomark
- :action action-fn)))
- ;; Helm result.
- (result (helm
- :sources src-list
- :input (expand-file-name initial-input)
- :prompt prompt
- :keymap cmap
- :candidate-number-limit candidate-number-limit
- :resume 'noresume
- :case-fold-search case-fold
- :default default
- :buffer buffer
- :preselect preselect)))
- (or
- (cond ((and result (stringp result)
- (string= result "") ""))
- ((and result
- (stringp result)
- (file-equal-p result initial-input)
- default)
- (if (listp default) (car default) default))
- ((and result (stringp result))
- (expand-file-name result))
- ((and result (listp result))
- (mapcar #'expand-file-name result))
- (t result))
- (when (and (not (string= helm-pattern ""))
- (eq helm-exit-status 0)
- (eq must-match 'confirm))
- (identity helm-pattern))
- (helm-mode--keyboard-quit))))
-
-(defun helm-mode--default-filename (fname dir initial)
- (unless dir (setq dir default-directory))
- (unless (file-name-absolute-p dir)
- (setq dir (expand-file-name dir)))
- (unless (or fname (consp fname))
- (setq fname (expand-file-name
- (or initial buffer-file-name dir)
- dir)))
- (if (and fname (consp fname))
- (setq fname (cl-loop for f in fname
- collect (expand-file-name f dir)))
- (if (file-name-absolute-p fname)
- fname (expand-file-name fname dir))))
-
-(cl-defun helm--generic-read-file-name
- (prompt &optional dir default-filename mustmatch initial predicate)
- "Generic helm replacement of `read-file-name'.
-Don't use it directly, use instead `helm-read-file-name' in your programs."
- (let* ((init (or initial dir default-directory))
- (current-command (or (helm-this-command) this-command))
- (str-command (helm-symbol-name current-command))
- (helm--file-completion-sources
- (cons str-command
- (remove str-command helm--file-completion-sources)))
- (buf-name (format "*helm-mode-%s*" str-command))
- (entry (assq current-command
- helm-completing-read-handlers-alist))
- (def-com (cdr-safe entry))
- (str-defcom (and def-com (helm-symbol-name def-com)))
- (def-args (list prompt dir default-filename mustmatch initial predicate))
- ;; Append the two extra args needed to set the buffer and source name
- ;; in helm specialized functions.
- (any-args (append def-args (list str-command buf-name)))
- (ido-state ido-mode)
- helm-completion-mode-start-message ; Be quiet
- helm-completion-mode-quit-message ; Same here
- fname)
- (setq default-filename (helm-mode--default-filename
- default-filename dir initial))
- ;; Some functions that normally call `completing-read' can switch
- ;; brutally to `read-file-name' (e.g find-tag), in this case
- ;; the helm specialized function will fail because it is build
- ;; for `completing-read', so set it to 'incompatible to be sure
- ;; we switch to `helm-read-file-name' and don't try to call it
- ;; with wrong number of args.
- (when (eq def-com 'ido)
- (setq def-com 'ido-read-file-name) (ido-mode 1))
- (when (and def-com (> (length (help-function-arglist def-com)) 8))
- (setq def-com 'incompatible))
- (unless (or (not entry) def-com)
- (cl-return-from helm--generic-read-file-name
- (unwind-protect
- (progn
- (helm-mode -1)
- (apply read-file-name-function def-args))
- (helm-mode 1))))
- ;; If we use now `read-file-name' we MUST turn off `helm-mode'
- ;; to avoid infinite recursion and CRASH. It will be reenabled on exit.
- (when (or (eq def-com 'read-file-name)
- (eq def-com 'ido-read-file-name)
- (and (stringp str-defcom)
- (not (string-match "^helm" str-defcom))))
- (helm-mode -1))
- (unwind-protect
- (setq fname
- (cond (;; A specialized function exists, run it
- ;; with the two extra args specific to helm..
- (and def-com helm-mode
- (not (eq def-com 'ido-read-file-name))
- (not (eq def-com 'incompatible)))
- (apply def-com any-args))
- (;; Def-com value is `ido-read-file-name'
- ;; run it with default args.
- (and def-com (eq def-com 'ido-read-file-name))
- (ido-mode 1)
- (apply def-com def-args))
- (;; Def-com value is `read-file-name'
- ;; run it with default args.
- (eq def-com 'read-file-name)
- (apply def-com def-args))
- (t ; Fall back to classic `helm-read-file-name'.
- (helm-read-file-name
- prompt
- :name str-command
- :buffer buf-name
- :default default-filename
- :initial-input (expand-file-name init dir)
- :alistp nil
- :must-match mustmatch
- :test predicate))))
- (helm-mode 1)
- (ido-mode (if ido-state 1 -1))
- ;; Same comment as in `helm--completing-read-default'.
- (setq this-command current-command))
- (if (eq predicate 'file-directory-p) ; Using `read-directory-name'.
- (file-name-as-directory fname) fname)))
-
-(defun helm-mode--advice-lisp--local-variables (old--fn &rest args)
- (ignore-errors
- (apply old--fn args)))
-
-(defun helm--completion-in-region (start end collection &optional predicate)
- "Helm replacement of `completion--in-region'.
-Can be used as value for `completion-in-region-function'."
- (cl-declare (special require-match prompt))
- (if (memq major-mode helm-mode-no-completion-in-region-in-modes)
- (funcall helm--old-completion-in-region-function
- start end collection predicate)
- (advice-add
- 'lisp--local-variables
- :around #'helm-mode--advice-lisp--local-variables)
- (unwind-protect
- (let* ((enable-recursive-minibuffers t)
- (input (buffer-substring-no-properties start end))
- (current-command (or (helm-this-command) this-command))
- (str-command (helm-symbol-name current-command))
- (buf-name (format "*helm-mode-%s*" str-command))
- (require-match (or (and (boundp 'require-match) require-match)
- minibuffer-completion-confirm
- ;; If prompt have not been propagated here, that's
- ;; probably mean we have no prompt and we are in
- ;; completion-at-point or friend, so use a non--nil
- ;; value for require-match.
- (not (boundp 'prompt))))
- ;; `completion-extra-properties' is let-bounded in `completion-at-point'.
- ;; `afun' is a closure to call against each string in `data'.
- ;; it provide the annotation info for each string.
- ;; e.g "foo" => "foo <f>" where foo is a function.
- ;; See Issue #407.
- (afun (plist-get completion-extra-properties :annotation-function))
- (metadata (completion-metadata
- (buffer-substring-no-properties start (point))
- collection predicate))
- (data (completion-all-completions
- (buffer-substring start end)
- collection
- predicate
- (- (point) start)
- metadata))
- ;; `completion-all-completions' store the base-size in the last `cdr',
- ;; so data looks like this: '(a b c d . 0) and (last data) == (d . 0).
- (last-data (last data))
- (base-size (helm-aif (cdr (last data))
- (prog1 it
- (setcdr last-data nil))
- 0))
- (init-space-suffix (unless (or helm-completion-in-region-fuzzy-match
- (string-suffix-p " " input))
- " "))
- (file-comp-p (or (eq (completion-metadata-get metadata 'category) 'file)
- (helm-mode--in-file-completion-p)
- ;; Assume that when `afun' and `predicate' are null
- ;; we are in filename completion.
- (and (null afun) (null predicate))))
- ;; Completion-at-point and friends have no prompt.
- (result (if (stringp data)
- data
- (helm-comp-read
- (or (and (boundp 'prompt) prompt) "Pattern: ")
- (if file-comp-p
- (cl-loop for f in data unless
- (string-match "\\`\\.\\{1,2\\}/\\'" f)
- collect f)
- (if afun
- (mapcar (lambda (s)
- (let ((ann (funcall afun s)))
- (if ann
- (cons
- (concat
- s
- (propertize
- " " 'display
- (propertize
- ann
- 'face 'completions-annotations)))
- s)
- s)))
- data)
- data))
- :name str-command
- :fuzzy helm-completion-in-region-fuzzy-match
- :nomark t
- :initial-input
- (cond ((and file-comp-p
- (not (string-match "/\\'" input)))
- (concat (helm-basename input)
- (unless (string= input "")
- init-space-suffix)))
- ((string-match "/\\'" input) nil)
- ((or (null require-match)
- (stringp require-match))
- input)
- (t (concat input init-space-suffix)))
- :buffer buf-name
- :fc-transformer (append (list 'helm-cr-default-transformer)
- (unless helm-completion-in-region-fuzzy-match
- (list (lambda (candidates _source)
- (sort candidates 'helm-generic-sort-fn)))))
- :exec-when-only-one t
- :quit-when-no-cand
- (lambda ()
- ;; Delay message to overwrite "Quit".
- (run-with-timer
- 0.01 nil
- (lambda ()
- (message "[No matches]")))
- t) ; exit minibuffer immediately.
- :must-match require-match))))
- (when result
- (choose-completion-string
- result (current-buffer)
- (list (+ start base-size) end)
- completion-list-insert-choice-function)))
- (advice-remove 'lisp--local-variables
- #'helm-mode--advice-lisp--local-variables))))
-
-(defun helm-mode--in-file-completion-p ()
- (with-helm-current-buffer
- (run-hook-with-args-until-success 'file-name-at-point-functions)))
-
-(when (boundp 'completion-in-region-function)
- (defconst helm--old-completion-in-region-function completion-in-region-function))
-
-;;;###autoload
-(define-minor-mode helm-mode
- "Toggle generic helm completion.
-
-All functions in Emacs that use `completing-read'
-or `read-file-name' and friends will use helm interface
-when this mode is turned on.
-However you can modify this behavior for functions of your choice
-with `helm-completing-read-handlers-alist'.
-
-Called with a positive arg, turn on unconditionally, with a
-negative arg turn off.
-You can turn it on with `helm-mode'.
-
-Some crap emacs functions may not be supported,
-e.g `ffap-alternate-file' and maybe others
-You can add such functions to `helm-completing-read-handlers-alist'
-with a nil value.
-
-Note: This mode is incompatible with Emacs23."
- :group 'helm-mode
- :global t
- :lighter helm-completion-mode-string
- (cl-assert (boundp 'completing-read-function) nil
- "`helm-mode' not available, upgrade to Emacs-24")
- (if helm-mode
- (if (fboundp 'add-function)
- (progn
- (add-function :override completing-read-function
- #'helm--completing-read-default)
- (add-function :override read-file-name-function
- #'helm--generic-read-file-name)
- (when helm-mode-handle-completion-in-region
- (add-function :override completion-in-region-function
- #'helm--completion-in-region)))
- (setq completing-read-function 'helm--completing-read-default
- read-file-name-function 'helm--generic-read-file-name)
- (when (and (boundp 'completion-in-region-function)
- helm-mode-handle-completion-in-region)
- (setq completion-in-region-function #'helm--completion-in-region))
- (message helm-completion-mode-start-message))
- (if (fboundp 'remove-function)
- (progn
- (remove-function completing-read-function #'helm--completing-read-default)
- (remove-function read-file-name-function #'helm--generic-read-file-name)
- (remove-function completion-in-region-function #'helm--completion-in-region))
- (setq completing-read-function (and (fboundp 'completing-read-default)
- 'completing-read-default)
- read-file-name-function (and (fboundp 'read-file-name-default)
- 'read-file-name-default))
- (when (and (boundp 'completion-in-region-function)
- (boundp 'helm--old-completion-in-region-function))
- (setq completion-in-region-function helm--old-completion-in-region-function))
- (message helm-completion-mode-quit-message))))
-
-(provide 'helm-mode)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-mode.el ends here
+++ /dev/null
-;;; helm-multi-match.el --- Multiple regexp matching methods for helm -*- lexical-binding: t -*-
-
-;; Original Author: rubikitch
-
-;; Copyright (C) 2008 ~ 2011 rubikitch
-;; Copyright (C) 2011 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; Author: Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-;; URL: http://github.com/emacs-helm/helm
-
-;; 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/>.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'helm-lib)
-
-\f
-(defgroup helm-multi-match nil
- "Helm multi match."
- :group 'helm)
-
-(defcustom helm-mm-matching-method 'multi3
- "Matching method for helm match plugin.
-You can set here different methods to match candidates in helm.
-Here are the possible value of this symbol and their meaning:
-- multi1: Respect order, prefix of pattern must match.
-- multi2: Same but with partial match.
-- multi3: The best, multiple regexp match, allow negation.
-- multi3p: Same but prefix must match.
-
-Default is multi3, you should keep this for a better experience.
-
-Note that multi1 and multi3p are incompatible with fuzzy matching
-in file completion and by the way fuzzy matching will be disabled there
-when these options are used."
- :type '(radio :tag "Matching methods for helm"
- (const :tag "Multiple regexp 1 ordered with prefix match" multi1)
- (const :tag "Multiple regexp 2 ordered with partial match" multi2)
- (const :tag "Multiple regexp 3 matching no order, partial, best." multi3)
- (const :tag "Multiple regexp 3p matching with prefix match" multi3p))
- :group 'helm-multi-match)
-
-\f
-;; Internal
-(defconst helm-mm-default-match-functions
- '(helm-mm-exact-match helm-mm-match))
-(defconst helm-mm-default-search-functions
- '(helm-mm-exact-search helm-mm-search))
-
-\f
-;;; Build regexps
-;;
-;;
-(defvar helm-mm-space-regexp "[\\ ] "
- "Regexp to represent space itself in multiple regexp match.")
-
-(defun helm-mm-split-pattern (pattern)
- "Split PATTERN if it contain spaces and return resulting list.
-If spaces in PATTERN are escaped, don't split at this place.
-i.e \"foo bar\"=> (\"foo\" \"bar\")
-but \"foo\ bar\"=> (\"foobar\")."
- (if (string= pattern "")
- '("")
- (cl-loop for s in (split-string
- (replace-regexp-in-string helm-mm-space-regexp
- "\000\000" pattern)
- " " t)
- collect (replace-regexp-in-string "\000\000" " " s))))
-
-(defun helm-mm-1-make-regexp (pattern)
- "Replace spaces in PATTERN with \"\.*\"."
- (mapconcat 'identity (helm-mm-split-pattern pattern) ".*"))
-
-\f
-;;; Exact match.
-;;
-;;
-;; Internal.
-(defvar helm-mm-exact-pattern-str nil)
-(defvar helm-mm-exact-pattern-real nil)
-
-(defun helm-mm-exact-get-pattern (pattern)
- (unless (equal pattern helm-mm-exact-pattern-str)
- (setq helm-mm-exact-pattern-str pattern
- helm-mm-exact-pattern-real (concat "\n" pattern "\n")))
- helm-mm-exact-pattern-real)
-
-
-(cl-defun helm-mm-exact-match (str &optional (pattern helm-pattern))
- (if case-fold-search
- (progn
- (setq str (downcase str)
- pattern (downcase pattern))
- (string= str pattern))
- (string= str pattern)))
-
-(defun helm-mm-exact-search (pattern &rest _ignore)
- (and (search-forward (helm-mm-exact-get-pattern pattern) nil t)
- (forward-line -1)))
-
-\f
-;;; Prefix match
-;;
-;;
-;; Internal
-(defvar helm-mm-prefix-pattern-str nil)
-(defvar helm-mm-prefix-pattern-real nil)
-
-(defun helm-mm-prefix-get-pattern (pattern)
- (unless (equal pattern helm-mm-prefix-pattern-str)
- (setq helm-mm-prefix-pattern-str pattern
- helm-mm-prefix-pattern-real (concat "\n" pattern)))
- helm-mm-prefix-pattern-real)
-
-(defun helm-mm-prefix-match (str &optional pattern)
- ;; In filename completion basename and basedir may be
- ;; quoted, unquote them for string comparison (Issue #1283).
- (setq pattern (replace-regexp-in-string
- "\\\\" "" (or pattern helm-pattern)))
- (let ((len (length pattern)))
- (and (<= len (length str))
- (string= (substring str 0 len) pattern ))))
-
-(defun helm-mm-prefix-search (pattern &rest _ignore)
- (search-forward (helm-mm-prefix-get-pattern pattern) nil t))
-
-\f
-;;; Multiple regexp patterns 1 (order is preserved / prefix).
-;;
-;;
-;; Internal
-(defvar helm-mm-1-pattern-str nil)
-(defvar helm-mm-1-pattern-real nil)
-
-(defun helm-mm-1-get-pattern (pattern)
- (unless (equal pattern helm-mm-1-pattern-str)
- (setq helm-mm-1-pattern-str pattern
- helm-mm-1-pattern-real
- (concat "^" (helm-mm-1-make-regexp pattern))))
- helm-mm-1-pattern-real)
-
-(cl-defun helm-mm-1-match (str &optional (pattern helm-pattern))
- (string-match (helm-mm-1-get-pattern pattern) str))
-
-(defun helm-mm-1-search (pattern &rest _ignore)
- (re-search-forward (helm-mm-1-get-pattern pattern) nil t))
-
-\f
-;;; Multiple regexp patterns 2 (order is preserved / partial).
-;;
-;;
-;; Internal
-(defvar helm-mm-2-pattern-str nil)
-(defvar helm-mm-2-pattern-real nil)
-
-(defun helm-mm-2-get-pattern (pattern)
- (unless (equal pattern helm-mm-2-pattern-str)
- (setq helm-mm-2-pattern-str pattern
- helm-mm-2-pattern-real
- (concat "^.*" (helm-mm-1-make-regexp pattern))))
- helm-mm-2-pattern-real)
-
-(cl-defun helm-mm-2-match (str &optional (pattern helm-pattern))
- (string-match (helm-mm-2-get-pattern pattern) str))
-
-(defun helm-mm-2-search (pattern &rest _ignore)
- (re-search-forward (helm-mm-2-get-pattern pattern) nil t))
-
-\f
-;;; Multiple regexp patterns 3 (permutation).
-;;
-;;
-;; Internal
-(defvar helm-mm-3-pattern-str nil)
-(defvar helm-mm-3-pattern-list nil)
-
-(defun helm-mm-3-get-patterns (pattern)
- "Return `helm-mm-3-pattern-list', a list of predicate/regexp cons cells.
-e.g ((identity . \"foo\") (identity . \"bar\")).
-This is done only if `helm-mm-3-pattern-str' is same as PATTERN."
- (unless (equal pattern helm-mm-3-pattern-str)
- (setq helm-mm-3-pattern-str pattern
- helm-mm-3-pattern-list
- (helm-mm-3-get-patterns-internal pattern)))
- helm-mm-3-pattern-list)
-
-(defun helm-mm-3-get-patterns-internal (pattern)
- "Return a list of predicate/regexp cons cells.
-e.g ((identity . \"foo\") (identity . \"bar\"))."
- (unless (string= pattern "")
- (cl-loop for pat in (helm-mm-split-pattern pattern)
- collect (if (string= "!" (substring pat 0 1))
- (cons 'not (substring pat 1))
- (cons 'identity pat)))))
-
-(cl-defun helm-mm-3-match (str &optional (pattern helm-pattern))
- "Check if PATTERN match STR.
-When PATTERN contain a space, it is splitted and matching is done
-with the several resulting regexps against STR.
-e.g \"bar foo\" will match \"foobar\" and \"barfoo\".
-Argument PATTERN, a string, is transformed in a list of
-cons cell with `helm-mm-3-get-patterns' if it contain a space.
-e.g \"foo bar\"=>((identity . \"foo\") (identity . \"bar\")).
-Then each predicate of cons cell(s) is called with regexp of same
-cons cell against STR (a candidate).
-i.e (identity (string-match \"foo\" \"foo bar\")) => t."
- (let ((pat (helm-mm-3-get-patterns pattern)))
- (cl-loop for (predicate . regexp) in pat
- always (funcall predicate
- (condition-case _err
- ;; FIXME: Probably do nothing when
- ;; using fuzzy leaving the job
- ;; to the fuzzy fn.
- (string-match regexp str)
- (invalid-regexp nil))))))
-
-(defun helm-mm-3-search-base (pattern searchfn1 searchfn2)
- "Try to find PATTERN in `helm-buffer' with SEARCHFN1 and SEARCHFN2.
-This is the search function for `candidates-in-buffer' enabled sources.
-Use the same method as `helm-mm-3-match' except it search in buffer
-instead of matching on a string.
-i.e (identity (re-search-forward \"foo\" (point-at-eol) t)) => t."
- (cl-loop with pat = (if (stringp pattern)
- (helm-mm-3-get-patterns pattern)
- pattern)
- when (eq (caar pat) 'not) return
- ;; Pass the job to `helm-search-match-part'.
- (prog1 (list (point-at-bol) (point-at-eol))
- (forward-line 1))
- while (condition-case _err
- (funcall searchfn1 (or (cdar pat) "") nil t)
- (invalid-regexp nil))
- for bol = (point-at-bol)
- for eol = (point-at-eol)
- if (cl-loop for (pred . str) in (cdr pat) always
- (progn (goto-char bol)
- (funcall pred (condition-case _err
- (funcall searchfn2 str eol t)
- (invalid-regexp nil)))))
- do (goto-char eol) and return t
- else do (goto-char eol)
- finally return nil))
-
-(defun helm-mm-3-search (pattern &rest _ignore)
- (when (stringp pattern)
- (setq pattern (helm-mm-3-get-patterns pattern)))
- (helm-mm-3-search-base
- pattern 're-search-forward 're-search-forward))
-\f
-;;; mp-3 with migemo
-;;
-;;
-(defvar helm-mm--previous-migemo-info nil
- "[Internal] Cache previous migemo query.")
-(make-local-variable 'helm-mm--previous-migemo-info)
-
-(declare-function migemo-get-pattern "ext:migemo.el")
-(declare-function migemo-search-pattern-get "ext:migemo.el")
-
-(define-minor-mode helm-migemo-mode
- "Enable migemo in helm.
-It will be available in the sources handling it,
-i.e the sources which have the slot :migemo with non--nil value."
- :lighter " Hmio"
- :group 'helm
- :global t
- (cl-assert (featurep 'migemo)
- nil "No feature called migemo found, install migemo.el."))
-
-(defun helm-mm-migemo-get-pattern (pattern)
- (let ((regex (migemo-get-pattern pattern)))
- (if (ignore-errors (string-match regex "") t)
- (concat regex "\\|" pattern) pattern)))
-
-(defun helm-mm-migemo-search-pattern-get (pattern)
- (let ((regex (migemo-search-pattern-get pattern)))
- (if (ignore-errors (string-match regex "") t)
- (concat regex "\\|" pattern) pattern)))
-
-(defun helm-mm-migemo-string-match (pattern str)
- "Migemo version of `string-match'."
- (unless (assoc pattern helm-mm--previous-migemo-info)
- (with-helm-buffer
- (setq helm-mm--previous-migemo-info
- (push (cons pattern (helm-mm-migemo-get-pattern pattern))
- helm-mm--previous-migemo-info))))
- (string-match (assoc-default pattern helm-mm--previous-migemo-info) str))
-
-(cl-defun helm-mm-3-migemo-match (str &optional (pattern helm-pattern))
- (and helm-migemo-mode
- (cl-loop for (pred . re) in (helm-mm-3-get-patterns pattern)
- always (funcall pred (helm-mm-migemo-string-match re str)))))
-
-(defun helm-mm-migemo-forward (word &optional bound noerror count)
- (with-helm-buffer
- (unless (assoc word helm-mm--previous-migemo-info)
- (setq helm-mm--previous-migemo-info
- (push (cons word (if (delq 'ascii (find-charset-string word))
- word
- (helm-mm-migemo-search-pattern-get word)))
- helm-mm--previous-migemo-info))))
- (re-search-forward
- (assoc-default word helm-mm--previous-migemo-info) bound noerror count))
-
-(defun helm-mm-3-migemo-search (pattern &rest _ignore)
- (and helm-migemo-mode
- (helm-mm-3-search-base
- pattern 'helm-mm-migemo-forward 'helm-mm-migemo-forward)))
-
-\f
-;;; mp-3p- (multiple regexp pattern 3 with prefix search)
-;;
-;;
-(defun helm-mm-3p-match (str &optional pattern)
- "Check if PATTERN match STR.
-Same as `helm-mm-3-match' but more strict, matching against prefix also.
-e.g \"bar foo\" will match \"barfoo\" but not \"foobar\" contrarily to
-`helm-mm-3-match'."
- (let* ((pat (helm-mm-3-get-patterns (or pattern helm-pattern)))
- (first (car pat)))
- (and (funcall (car first) (helm-mm-prefix-match str (cdr first)))
- (cl-loop for (predicate . regexp) in (cdr pat)
- always (funcall predicate (string-match regexp str))))))
-
-(defun helm-mm-3p-search (pattern &rest _ignore)
- (when (stringp pattern)
- (setq pattern (helm-mm-3-get-patterns pattern)))
- (helm-mm-3-search-base
- pattern 'helm-mm-prefix-search 're-search-forward))
-
-\f
-;;; Generic multi-match/search functions
-;;
-;;
-(cl-defun helm-mm-match (str &optional (pattern helm-pattern))
- (let ((fun (cl-ecase helm-mm-matching-method
- (multi1 #'helm-mm-1-match)
- (multi2 #'helm-mm-2-match)
- (multi3 #'helm-mm-3-match)
- (multi3p #'helm-mm-3p-match))))
- (funcall fun str pattern)))
-
-(defun helm-mm-search (pattern &rest _ignore)
- (let ((fun (cl-ecase helm-mm-matching-method
- (multi1 #'helm-mm-1-search)
- (multi2 #'helm-mm-2-search)
- (multi3 #'helm-mm-3-search)
- (multi3p #'helm-mm-3p-search))))
- (funcall fun pattern)))
-
-
-(provide 'helm-multi-match)
-
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-multi-match.el ends here
+++ /dev/null
-;;; helm-net.el --- helm browse url and search web. -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'helm)
-(require 'helm-help)
-(require 'url)
-(require 'xml)
-(require 'browse-url)
-
-\f
-(defgroup helm-net nil
- "Net related applications and libraries for Helm."
- :group 'helm)
-
-(defcustom helm-google-suggest-default-browser-function nil
- "The browse url function you prefer to use with google suggest.
-When nil, use the first browser function available
-See `helm-browse-url-default-browser-alist'."
- :group 'helm-net
- :type 'symbol)
-
-(defcustom helm-home-url "http://www.google.fr"
- "Default url to use as home url."
- :group 'helm-net
- :type 'string)
-
-(defcustom helm-surfraw-default-browser-function nil
- "The browse url function you prefer to use with surfraw.
-When nil, fallback to `browse-url-browser-function'."
- :group 'helm-net
- :type 'symbol)
-
-(defcustom helm-google-suggest-url
- "http://google.com/complete/search?output=toolbar&q="
- "URL used for looking up Google suggestions."
- :type 'string
- :group 'helm-net)
-
-(defcustom helm-google-suggest-search-url
- "http://www.google.com/search?ie=utf-8&oe=utf-8&q=%s"
- "URL used for Google searching."
- :type 'string
- :group 'helm-net)
-
-(defcustom helm-net-prefer-curl nil
- "When non--nil use CURL external program to fetch data.
-Otherwise `url-retrieve-synchronously' is used."
- :type 'boolean
- :group 'helm-net)
-
-(defvaralias 'helm-google-suggest-use-curl-p 'helm-net-prefer-curl)
-(make-obsolete-variable 'helm-google-suggest-use-curl-p 'helm-net-prefer-curl "1.7.7")
-
-(defcustom helm-surfraw-duckduckgo-url
- "https://duckduckgo.com/lite/?q=%s&kp=1"
- "The duckduckgo url.
-This is a format string, don't forget the `%s'.
-If you have personal settings saved on duckduckgo you should have
-a personal url, see your settings on duckduckgo."
- :type 'string
- :group 'helm-net)
-
-(defcustom helm-wikipedia-suggest-url
- "https://en.wikipedia.org/w/api.php?action=opensearch&search="
- "Url used for looking up Wikipedia suggestions."
- :type 'string
- :group 'helm-net)
-
-(defcustom helm-search-suggest-action-wikipedia-url
- "https://en.wikipedia.org/wiki/Special:Search?search=%s"
- "The Wikipedia search url.
-This is a format string, don't forget the `%s'."
- :type 'string
- :group 'helm-net)
-
-(defcustom helm-wikipedia-summary-url
- "http://en.wikipedia.org/w/api.php?action=parse&format=json&prop=text§ion=0&page="
- "URL for getting the summary of a Wikipedia topic."
- :type 'string
- :group 'helm-net)
-
-(defcustom helm-wikipedia-follow-delay 2
- "Delay before wikipedia summary popup."
- :type 'number
- :group 'helm-net)
-
-(defcustom helm-search-suggest-action-youtube-url
- "http://www.youtube.com/results?aq=f&search_query=%s"
- "The Youtube search url.
-This is a format string, don't forget the `%s'."
- :type 'string
- :group 'helm-net)
-
-(defcustom helm-search-suggest-action-imdb-url
- "http://www.imdb.com/find?s=all&q=%s"
- "The IMDb search url.
-This is a format string, don't forget the `%s'."
- :type 'string
- :group 'helm-net)
-
-(defcustom helm-search-suggest-action-google-maps-url
- "http://maps.google.com/maps?f=q&source=s_q&q=%s"
- "The Google Maps search url.
-This is a format string, don't forget the `%s'."
- :type 'string
- :group 'helm-net)
-
-(defcustom helm-search-suggest-action-google-news-url
- "http://www.google.com/search?safe=off&prmd=nvlifd&source=lnms&tbs=nws:1&q=%s"
- "The Google News search url.
-This is a format string, don't forget the `%s'."
- :type 'string
- :group 'helm-net)
-
-(defcustom helm-google-suggest-actions
- '(("Google Search" . helm-google-suggest-action)
- ("Wikipedia" . (lambda (candidate)
- (helm-search-suggest-perform-additional-action
- helm-search-suggest-action-wikipedia-url
- candidate)))
- ("Youtube" . (lambda (candidate)
- (helm-search-suggest-perform-additional-action
- helm-search-suggest-action-youtube-url
- candidate)))
- ("IMDb" . (lambda (candidate)
- (helm-search-suggest-perform-additional-action
- helm-search-suggest-action-imdb-url
- candidate)))
- ("Google Maps" . (lambda (candidate)
- (helm-search-suggest-perform-additional-action
- helm-search-suggest-action-google-maps-url
- candidate)))
- ("Google News" . (lambda (candidate)
- (helm-search-suggest-perform-additional-action
- helm-search-suggest-action-google-news-url
- candidate))))
- "List of actions for google suggest sources."
- :group 'helm-net
- :type '(alist :key-type string :value-type function))
-
-(defcustom helm-browse-url-firefox-new-window "-new-tab"
- "Allow choosing to browse url in new window or new tab.
-Can be \"-new-tab\" (default) or \"-new-window\"."
- :group 'helm-net
- :type '(radio
- (const :tag "New tab" "-new-tab")
- (const :tag "New window" "-new-window")))
-
-\f
-;;; Additional actions for search suggestions
-;;
-;;
-;; Internal
-
-(defun helm-search-suggest-perform-additional-action (url query)
- "Perform the search via URL using QUERY as input."
- (browse-url (format url (url-hexify-string query))))
-
-(defun helm-net--url-retrieve-sync (request parser)
- (if helm-net-prefer-curl
- (with-temp-buffer
- (call-process "curl" nil t nil request)
- (funcall parser))
- (with-current-buffer (url-retrieve-synchronously request)
- (funcall parser))))
-
-\f
-;;; Google Suggestions
-;;
-;;
-(defun helm-google-suggest-parser ()
- (cl-loop
- with result-alist = (xml-get-children
- (car (xml-parse-region
- (point-min) (point-max)))
- 'CompleteSuggestion)
- for i in result-alist collect
- (cdr (cl-caadr (assoc 'suggestion i)))))
-
-(defun helm-google-suggest-fetch (input)
- "Fetch suggestions for INPUT from XML buffer."
- (let ((request (concat helm-google-suggest-url
- (url-hexify-string input))))
- (helm-net--url-retrieve-sync
- request #'helm-google-suggest-parser)))
-
-(defun helm-google-suggest-set-candidates (&optional request-prefix)
- "Set candidates with result and number of google results found."
- (let ((suggestions (helm-google-suggest-fetch
- (or (and request-prefix
- (concat request-prefix
- " " helm-pattern))
- helm-pattern))))
- (if (member helm-pattern suggestions)
- suggestions
- ;; if there is no suggestion exactly matching the input then
- ;; prepend a Search on Google item to the list
- (append
- suggestions
- (list (cons (format "Search for '%s' on Google" helm-input)
- helm-input))))))
-
-(defun helm-ggs-set-number-result (num)
- (if num
- (progn
- (and (numberp num) (setq num (number-to-string num)))
- (cl-loop for i in (reverse (split-string num "" t))
- for count from 1
- append (list i) into C
- when (= count 3)
- append (list ",") into C
- and do (setq count 0)
- finally return
- (replace-regexp-in-string
- "^," "" (mapconcat 'identity (reverse C) ""))))
- "?"))
-
-(defun helm-google-suggest-action (candidate)
- "Default action to jump to a google suggested candidate."
- (let ((arg (format helm-google-suggest-search-url
- (url-hexify-string candidate))))
- (helm-aif helm-google-suggest-default-browser-function
- (funcall it arg)
- (helm-browse-url arg))))
-
-(defvar helm-google-suggest-default-function
- 'helm-google-suggest-set-candidates
- "Default function to use in helm google suggest.")
-
-(defvar helm-source-google-suggest
- (helm-build-sync-source "Google Suggest"
- :candidates (lambda ()
- (funcall helm-google-suggest-default-function))
- :action 'helm-google-suggest-actions
- :volatile t
- :keymap helm-map
- :requires-pattern 3))
-
-(defun helm-google-suggest-emacs-lisp ()
- "Try to emacs lisp complete with google suggestions."
- (helm-google-suggest-set-candidates "emacs lisp"))
-
-;;; Wikipedia suggestions
-;;
-;;
-(declare-function json-read-from-string "json" (string))
-(defun helm-wikipedia-suggest-fetch ()
- "Fetch Wikipedia suggestions and return them as a list."
- (require 'json)
- (let ((request (concat helm-wikipedia-suggest-url
- (url-hexify-string helm-pattern))))
- (helm-net--url-retrieve-sync
- request #'helm-wikipedia--parse-buffer)))
-
-(defun helm-wikipedia--parse-buffer ()
- (goto-char (point-min))
- (when (re-search-forward "^\\[.+\\[\\(.*\\)\\]\\]" nil t)
- (cl-loop for i across (aref (json-read-from-string (match-string 0)) 1)
- collect i into result
- finally return (or result
- (append
- result
- (list (cons (format "Search for '%s' on wikipedia"
- helm-pattern)
- helm-pattern)))))))
-
-(defvar helm-wikipedia--summary-cache (make-hash-table :test 'equal))
-(defun helm-wikipedia-persistent-action (candidate)
- (unless (string= (format "Search for '%s' on wikipedia"
- helm-pattern)
- (helm-get-selection nil t))
- (message "Fetching summary from Wikipedia...")
- (let ((buf (get-buffer-create "*helm wikipedia summary*"))
- result mess)
- (while (progn
- (setq result (or (gethash candidate helm-wikipedia--summary-cache)
- (puthash candidate
- (prog1
- (helm-wikipedia-fetch-summary candidate)
- (setq mess "Done"))
- helm-wikipedia--summary-cache)))
- (when (and result
- (listp result))
- (setq candidate (cdr result))
- (message "Redirected to %s" candidate)
- t)))
- (if (not result)
- (message "Error when getting summary.")
- (with-current-buffer buf
- (erase-buffer)
- (setq cursor-type nil)
- (insert result)
- (fill-region (point-min) (point-max))
- (goto-char (point-min)))
- (display-buffer buf)
- (message mess)))))
-
-(defun helm-wikipedia-fetch-summary (input)
- (let* ((request (concat helm-wikipedia-summary-url
- (url-hexify-string input))))
- (helm-net--url-retrieve-sync
- request #'helm-wikipedia--parse-summary)))
-
-(defun helm-wikipedia--parse-summary ()
- (goto-char (point-min))
- (when (search-forward "{" nil t)
- (let ((result (cdr (assoc '*
- (assoc 'text
- (assoc 'parse
- (json-read-from-string
- (buffer-substring-no-properties
- (1- (point)) (point-max)))))))))
- (when result
- (if (string-match "<span class=\"redirectText\"><a href=[^>]+>\\([^<]+\\)" result)
- (cons 'redirect (match-string 1 result))
-
- ;; find the beginning of the summary text in the result
-
- ;; check if there is a table before the summary and skip that
- (when (or (string-match "</table>\\(\n<div.*?</div>\\)?\n<p>" result)
- ;; otherwise just find the first paragraph
- (string-match "<p>" result))
- ;; remove cruft and do a simple formatting
- (replace-regexp-in-string
- "Cite error: .*" ""
- (replace-regexp-in-string
- " " ""
- (replace-regexp-in-string
- "\\[[^\]]+\\]" ""
- (replace-regexp-in-string
- "<[^>]*>" ""
- (replace-regexp-in-string
- "</p>\n<p>" "\n\n"
- (substring result (match-end 0)))))))))))))
-
-
-(defvar helm-source-wikipedia-suggest
- (helm-build-sync-source "Wikipedia Suggest"
- :candidates #'helm-wikipedia-suggest-fetch
- :action '(("Wikipedia" . (lambda (candidate)
- (helm-search-suggest-perform-additional-action
- helm-search-suggest-action-wikipedia-url
- candidate))))
- :persistent-action #'helm-wikipedia-persistent-action
- :volatile t
- :keymap helm-map
- :follow 1
- :follow-delay helm-wikipedia-follow-delay
- :requires-pattern 3))
-
-\f
-;;; Web browser functions.
-;;
-;;
-;; If default setting of `w3m-command' is not
-;; what you want and you modify it, you will have to reeval
-;; also `helm-browse-url-default-browser-alist'.
-
-(defvar helm-browse-url-chromium-program "chromium-browser")
-(defvar helm-browse-url-uzbl-program "uzbl-browser")
-(defvar helm-browse-url-conkeror-program "conkeror")
-(defvar helm-browse-url-default-browser-alist
- `((,(or (and (boundp 'w3m-command) w3m-command)
- "/usr/bin/w3m") . w3m-browse-url)
- (,browse-url-firefox-program . browse-url-firefox)
- (,helm-browse-url-chromium-program . helm-browse-url-chromium)
- (,helm-browse-url-conkeror-program . helm-browse-url-conkeror)
- (,helm-browse-url-uzbl-program . helm-browse-url-uzbl)
- (,browse-url-kde-program . browse-url-kde)
- (,browse-url-gnome-moz-program . browse-url-gnome-moz)
- (,browse-url-mozilla-program . browse-url-mozilla)
- (,browse-url-galeon-program . browse-url-galeon)
- (,browse-url-netscape-program . browse-url-netscape)
- (,browse-url-mosaic-program . browse-url-mosaic)
- (,browse-url-xterm-program . browse-url-text-xterm)
- ("emacs" . eww-browse-url))
- "*Alist of \(executable . function\) to try to find a suitable url browser.")
-
-(cl-defun helm-generic-browser (url cmd-name &rest args)
- "Browse URL with NAME browser."
- (let ((proc (concat cmd-name " " url)))
- (message "Starting %s..." cmd-name)
- (apply 'start-process proc nil cmd-name
- (append args (list url)))
- (set-process-sentinel
- (get-process proc)
- (lambda (process event)
- (when (string= event "finished\n")
- (message "%s process %s" process event))))))
-
-(defun helm-browse-url-firefox (url &optional _ignore)
- "Same as `browse-url-firefox' but detach from emacs.
-So when you quit emacs you can keep your firefox open
-and not be prompted to kill firefox process.
-
-NOTE: Probably not supported on some systems (e.g Windows)."
- (interactive (list (read-string "URL: " (browse-url-url-at-point))
- nil))
- (let ((process-environment (browse-url-process-environment)))
- (call-process-shell-command
- (format "(%s %s %s &)"
- browse-url-firefox-program
- helm-browse-url-firefox-new-window
- url))))
-
-(defun helm-browse-url-chromium (url &optional _ignore)
- "Browse URL with google chrome browser."
- (interactive "sURL: ")
- (helm-generic-browser
- url helm-browse-url-chromium-program))
-
-(defun helm-browse-url-uzbl (url &optional _ignore)
- "Browse URL with uzbl browser."
- (interactive "sURL: ")
- (helm-generic-browser url helm-browse-url-uzbl-program "-u"))
-
-(defun helm-browse-url-conkeror (url &optional _ignore)
- "Browse URL with conkeror browser."
- (interactive "sURL: ")
- (helm-generic-browser url helm-browse-url-conkeror-program))
-
-(defun helm-browse-url-default-browser (url &rest args)
- "Find the first available browser and ask it to load URL."
- (let ((default-browser-fn
- (cl-loop for (exe . fn) in helm-browse-url-default-browser-alist
- thereis (and exe (executable-find exe) (fboundp fn) fn))))
- (if default-browser-fn
- (apply default-browser-fn url args)
- (error "No usable browser found"))))
-
-(defun helm-browse-url (url &rest args)
- "Default command to browse URL."
- (if browse-url-browser-function
- (browse-url url args)
- (helm-browse-url-default-browser url args)))
-
-\f
-;;; Surfraw
-;;
-;; Need external program surfraw.
-;; <http://surfraw.alioth.debian.org/>
-
-;; Internal
-(defvar helm-surfraw-engines-history nil)
-(defvar helm-surfraw-input-history nil)
-(defvar helm-surfraw--elvi-cache nil)
-
-(defun helm-build-elvi-list ()
- "Return list of all engines and descriptions handled by surfraw."
- (or helm-surfraw--elvi-cache
- (setq helm-surfraw--elvi-cache
- (cdr (with-temp-buffer
- (call-process "surfraw" nil t nil "-elvi")
- (split-string (buffer-string) "\n"))))))
-
-;;;###autoload
-(defun helm-surfraw (pattern engine)
- "Preconfigured `helm' to search PATTERN with search ENGINE."
- (interactive (list (read-string "SearchFor: "
- nil 'helm-surfraw-input-history
- (thing-at-point 'symbol))
- (helm-comp-read
- "Engine: "
- (helm-build-elvi-list)
- :must-match t
- :name "Surfraw Search Engines"
- :del-input nil
- :history helm-surfraw-engines-history)))
- (let* ((engine-nodesc (car (split-string engine)))
- (url (if (string= engine-nodesc "duckduckgo")
- ;; "sr duckduckgo -p foo" is broken, workaround.
- (format helm-surfraw-duckduckgo-url
- (url-hexify-string pattern))
- (with-temp-buffer
- (apply 'call-process "surfraw" nil t nil
- (append (list engine-nodesc "-p") (split-string pattern)))
- (replace-regexp-in-string
- "\n" "" (buffer-string)))))
- (browse-url-browser-function (or helm-surfraw-default-browser-function
- browse-url-browser-function)))
- (if (string= engine-nodesc "W")
- (helm-browse-url helm-home-url)
- (helm-browse-url url)
- (setq helm-surfraw-engines-history
- (cons engine (delete engine helm-surfraw-engines-history))))))
-
-;;;###autoload
-(defun helm-google-suggest ()
- "Preconfigured `helm' for google search with google suggest."
- (interactive)
- (helm-other-buffer 'helm-source-google-suggest "*helm google*"))
-
-;;;###autoload
-(defun helm-wikipedia-suggest ()
- "Preconfigured `helm' for Wikipedia lookup with Wikipedia suggest."
- (interactive)
- (helm :sources 'helm-source-wikipedia-suggest
- :buffer "*helm wikipedia*"))
-
-
-(provide 'helm-net)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-net.el ends here
+++ /dev/null
-;;; helm-org.el --- Helm for org headlines and keywords completion -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Code:
-(require 'cl-lib)
-(require 'helm)
-(require 'helm-utils)
-(require 'org)
-
-(declare-function org-agenda-switch-to "org-agenda.el")
-
-(defgroup helm-org nil
- "Org related functions for helm."
- :group 'helm)
-
-(defcustom helm-org-headings-fontify nil
- "Fontify org buffers before parsing them.
-This reflect fontification in helm-buffer when non--nil.
-NOTE: This will be slow on large org buffers."
- :group 'helm-org
- :type 'boolean)
-
-(defcustom helm-org-format-outline-path nil
- "Show all org level as path."
- :group 'helm-org
- :type 'boolean)
-
-(defcustom helm-org-show-filename nil
- "Show org filenames in `helm-org-agenda-files-headings' when non--nil.
-Note this have no effect in `helm-org-in-buffer-headings'."
- :group 'helm-org
- :type 'boolean)
-
-(defcustom helm-org-headings-min-depth 1
- "Minimum depth of org headings to start with."
- :group 'helm-org
- :type 'integer)
-
-(defcustom helm-org-headings-max-depth 8
- "Go down to this maximum depth of org headings."
- :group 'helm-org
- :type 'integer)
-
-(defcustom helm-org-headings-actions
- '(("Go to heading" . helm-org-goto-marker)
- ("Open in indirect buffer `C-RET'" . helm-org--open-heading-in-indirect-buffer)
- ("Refile to this heading `C-w`''" . helm-org-heading-refile)
- ("Insert link to this heading `C-l`''" . helm-org-insert-link-to-heading-at-marker))
- "Default actions alist for
- `helm-source-org-headings-for-files'."
- :group 'helm-org
- :type '(alist :key-type string :value-type function))
-
-(defcustom helm-org-truncate-lines t
- "Truncate org-header-lines when non-nil"
- :type 'boolean
- :group 'helm-org)
-
-;;; Org capture templates
-;;
-;;
-(defvar org-capture-templates)
-(defun helm-source-org-capture-templates ()
- (helm-build-sync-source "Org Capture Templates:"
- :candidates (cl-loop for template in org-capture-templates
- collect (cons (nth 1 template) (nth 0 template)))
- :action '(("Do capture" . (lambda (template-shortcut)
- (org-capture nil template-shortcut))))))
-
-;;; Org headings
-;;
-;;
-(defun helm-org-goto-marker (marker)
- (switch-to-buffer (marker-buffer marker))
- (goto-char (marker-position marker))
- (org-show-context)
- (re-search-backward "^\\*+ " nil t)
- (org-show-entry))
-
-(defun helm-org--open-heading-in-indirect-buffer (marker)
- (helm-org-goto-marker marker)
- (org-tree-to-indirect-buffer)
-
- ;; Put the non-indirect buffer at the bottom of the prev-buffers
- ;; list so it won't be selected when the indirect buffer is killed
- (set-window-prev-buffers nil (append (cdr (window-prev-buffers))
- (car (window-prev-buffers)))))
-
-(defun helm-org--run-open-heading-in-indirect-buffer ()
- "Open selected Org heading in an indirect buffer."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action #'helm-org--open-heading-in-indirect-buffer)))
-(put 'helm-org--run-open-heading-in-indirect-buffer 'helm-only t)
-
-(defvar helm-org-headings-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map helm-map)
- (define-key map (kbd "<C-return>") 'helm-org--run-open-heading-in-indirect-buffer)
- (define-key map (kbd "C-w") 'helm-org-heading-refile)
- (define-key map (kbd "C-l") 'helm-org-insert-link-to-heading-at-marker)
- map)
- "Keymap for `helm-source-org-headings-for-files'.")
-
-(defclass helm-org-headings-class (helm-source-sync)
- ((parents
- :initarg :parents
- :initform nil
- :custom boolean)
- (match :initform
- (lambda (candidate)
- (string-match
- helm-pattern
- (helm-aif (get-text-property 0 'helm-real-display candidate)
- it
- candidate))))
- (action :initform 'helm-org-headings-actions)
- (keymap :initform 'helm-org-headings-map)))
-
-(defmethod helm--setup-source :after ((source helm-org-headings-class))
- (let ((parents (slot-value source 'parents)))
- (setf (slot-value source 'candidate-transformer)
- (lambda (candidates)
- (let ((cands (helm-org-get-candidates candidates parents)))
- (if parents (nreverse cands) cands))))))
-
-(defun helm-source-org-headings-for-files (filenames &optional parents)
- (helm-make-source "Org Headings" 'helm-org-headings-class
- :parents parents
- :candidates filenames))
-
-(defun helm-org-get-candidates (filenames &optional parents)
- (apply #'append
- (mapcar (lambda (filename)
- (helm-org--get-candidates-in-file
- filename
- helm-org-headings-fontify
- (or parents (null helm-org-show-filename))
- parents))
- filenames)))
-
-(defun helm-org--get-candidates-in-file (filename &optional fontify nofname parents)
- (with-current-buffer (pcase filename
- ((pred bufferp) filename)
- ((pred stringp) (find-file-noselect filename)))
- (let ((match-fn (if fontify
- #'match-string
- #'match-string-no-properties))
- (search-fn (lambda ()
- (re-search-forward
- org-complex-heading-regexp nil t)))
- (file (unless nofname
- (concat (helm-basename filename) ":"))))
- (when parents
- (add-function :around (var search-fn)
- (lambda (old-fn &rest args)
- (when (org-up-heading-safe)
- (apply old-fn args)))))
- (save-excursion
- (save-restriction
- (widen)
- (unless parents (goto-char (point-min)))
- ;; clear cache for new version of org-get-outline-path
- (and (boundp 'org-outline-path-cache)
- (setq org-outline-path-cache nil))
- (cl-loop with width = (window-width (helm-window))
- while (funcall search-fn)
- for beg = (point-at-bol)
- for end = (point-at-eol)
- when (and fontify
- (null (text-property-any
- beg end 'fontified t)))
- do (jit-lock-fontify-now beg end)
- for level = (length (match-string-no-properties 1))
- for heading = (funcall match-fn 4)
- if (and (>= level helm-org-headings-min-depth)
- (<= level helm-org-headings-max-depth))
- collect `(,(propertize
- (if helm-org-format-outline-path
- (org-format-outline-path
- ;; org-get-outline-path changed in signature and behaviour since org's
- ;; commit 105a4466971. Let's fall-back to the new version in case
- ;; of wrong-number-of-arguments error.
- (condition-case nil
- (append (apply #'org-get-outline-path
- (unless parents
- (list t level heading)))
- (list heading))
- (wrong-number-of-arguments
- (org-get-outline-path t t)))
- width file)
- (if file
- (concat file (funcall match-fn 0))
- (funcall match-fn 0)))
- 'helm-real-display heading)
- . ,(point-marker))))))))
-
-(defun helm-org-insert-link-to-heading-at-marker (marker)
- (with-current-buffer (marker-buffer marker)
- (let ((heading-name (save-excursion (goto-char (marker-position marker))
- (nth 4 (org-heading-components))))
- (file-name (buffer-file-name)))
- (with-helm-current-buffer
- (org-insert-link
- file-name (concat "file:" file-name "::*" heading-name))))))
-
-(defun helm-org-heading-refile (marker)
- (save-selected-window
- (when (eq major-mode 'org-agenda-mode)
- (org-agenda-switch-to))
- (org-cut-subtree)
- (let ((target-level (with-current-buffer (marker-buffer marker)
- (goto-char (marker-position marker))
- (org-current-level))))
- (helm-org-goto-marker marker)
- (org-end-of-subtree t t)
- (org-paste-subtree (+ target-level 1)))))
-
-;;;###autoload
-(defun helm-org-agenda-files-headings ()
- "Preconfigured helm for org files headings."
- (interactive)
- (helm :sources (helm-source-org-headings-for-files (org-agenda-files))
- :candidate-number-limit 99999
- :truncate-lines helm-org-truncate-lines
- :buffer "*helm org headings*"))
-
-;;;###autoload
-(defun helm-org-in-buffer-headings ()
- "Preconfigured helm for org buffer headings."
- (interactive)
- (let ((helm-org-show-filename nil))
- (helm :sources (helm-source-org-headings-for-files
- (list (current-buffer)))
- :candidate-number-limit 99999
- :truncate-lines helm-org-truncate-lines
- :buffer "*helm org inbuffer*")))
-
-;;;###autoload
-(defun helm-org-parent-headings ()
- "Preconfigured helm for org headings that are parents of the
-current heading."
- (interactive)
- ;; Use a large max-depth to ensure all parents are displayed.
- (let ((helm-org-headings-min-depth 1)
- (helm-org-headings-max-depth 50))
- (helm :sources (helm-source-org-headings-for-files
- (list (current-buffer)) t)
- :candidate-number-limit 99999
- :truncate-lines helm-org-truncate-lines
- :buffer "*helm org parent headings*")))
-
-;;;###autoload
-(defun helm-org-capture-templates ()
- "Preconfigured helm for org templates."
- (interactive)
- (helm :sources (helm-source-org-capture-templates)
- :candidate-number-limit 99999
- :truncate-lines helm-org-truncate-lines
- :buffer "*helm org capture templates*"))
-
-;;; Org tag completion
-
-;; Based on code from Anders Johansson posted on 3 Mar 2016 at
-;; <https://groups.google.com/d/msg/emacs-helm/tA6cn6TUdRY/G1S3TIdzBwAJ>
-
-(defvar crm-separator)
-
-;;;###autoload
-(defun helm-org-completing-read-tags (prompt collection pred req initial
- hist def inherit-input-method _name _buffer)
- (if (not (string= "Tags: " prompt))
- ;; Not a tags prompt. Use normal completion by calling
- ;; `org-icompleting-read' again without this function in
- ;; `helm-completing-read-handlers-alist'
- (let ((helm-completing-read-handlers-alist
- (rassq-delete-all
- 'helm-org-completing-read-tags
- helm-completing-read-handlers-alist)))
- (org-icompleting-read
- prompt collection pred req initial hist def inherit-input-method))
- ;; Tags prompt
- (let* ((curr (and (stringp initial)
- (not (string= initial ""))
- (org-split-string initial ":")))
- (table (delete curr
- (org-uniquify
- (mapcar 'car org-last-tags-completion-table))))
- (crm-separator ":\\|,\\|\\s-"))
- (cl-letf (((symbol-function 'crm-complete-word)
- 'self-insert-command))
- (mapconcat 'identity
- (completing-read-multiple
- prompt table pred nil initial hist def)
- ":")))))
-
-(provide 'helm-org)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-org.el ends here
+++ /dev/null
-(define-package "helm" "20160530.424" "Helm is an Emacs incremental and narrowing framework"
- '((emacs "24.3")
- (async "1.9")
- (popup "0.5.3")
- (helm-core "1.9.6"))
- :url "https://emacs-helm.github.io/helm/")
-;; Local Variables:
-;; no-byte-compile: t
-;; End:
+++ /dev/null
-;;; helm-plugin.el --- Helm plugins -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'helm)
-(require 'helm-utils)
-
-\f
-;;; Plug-in: `info-index'
-;;
-;;
-(defun helm-make-info-source (source file)
- `(,@source
- (name . ,(concat "Info Index: " file))
- (info-file . ,file)
- (init . helm-info-init)
- (display-to-real . helm-info-display-to-real)
- (get-line . buffer-substring)
- (candidates-in-buffer)
- (action ("Goto node" . helm-info-goto))))
-
-(defun helm-compile-source--info-index (source)
- (helm-aif (helm-interpret-value (assoc-default 'info-index source))
- (helm-make-info-source source it)
- source))
-
-(add-to-list 'helm-compile-source-functions 'helm-compile-source--info-index)
-
-(helm-document-attribute 'info-index "info-index plugin"
- " Create a source of info index very easily.
-
- Example:
-
- (defvar helm-source-info-wget '((info-index . \"wget\"))")
-
-\f
-;;; Plug-in: `candidates-file'
-;;
-;; List all lines in a file.
-(defun helm-compile-source--candidates-file (source)
- (if (assoc-default 'candidates-file source)
- `((init helm-p-candidates-file-init
- ,@(let ((orig-init (assoc-default 'init source)))
- (cond ((null orig-init) nil)
- ((functionp orig-init) (list orig-init))
- (t orig-init))))
- (candidates-in-buffer)
- ,@source)
- source))
-(add-to-list 'helm-compile-source-functions 'helm-compile-source--candidates-file)
-
-(defun helm-p-candidates-file-init ()
- (cl-destructuring-bind (file &optional updating)
- (helm-mklist (helm-attr 'candidates-file))
- (setq file (helm-interpret-value file))
- (with-current-buffer (helm-candidate-buffer 'global)
- (insert-file-contents file)
- (when updating
- (buffer-disable-undo)
- (font-lock-mode -1)
- (auto-revert-mode 1)))))
-
-(helm-document-attribute 'candidates-file "candidates-file plugin"
- " Use a file as the candidates buffer.
-
- 1st argument is a filename, string or function name or variable
- name. If optional 2nd argument is non-nil, the file is opened with
- `auto-revert-mode' enabled.
-
- Example:
-
- \(defvar helm-source-test-file
- '((name . \"test1\")
- (candidates-file \"~/.emacs.el\" t)))
-
- Will list all lines in .emacs.el.")
-
-\f
-;;; Plug-in: `persistent-help'
-;;
-;; Add help about persistent action in `helm-buffer' header.
-(defun helm-compile-source--persistent-help (source)
- (if (assoc 'header-line source)
- source
- (append source '((header-line . helm-persistent-help-string)))))
-(add-to-list 'helm-compile-source-functions 'helm-compile-source--persistent-help)
-
-(defun helm-persistent-help-string ()
- (substitute-command-keys
- (concat "\\<helm-map>\\[helm-execute-persistent-action]: "
- (or (helm-interpret-value (helm-attr 'persistent-help))
- (helm-aif (or (assoc-default
- 'persistent-action
- (helm-get-current-source))
- (assoc-default
- 'action (helm-get-current-source)))
- (cond ((symbolp it)
- (symbol-name it))
- ((listp it)
- (or (ignore-errors (caar it)) ""))))
- "")
- " (keeping session)")))
-
-\f
-;;; Document new attributes
-;;
-;;
-(helm-document-attribute 'persistent-help "persistent-help plug-in"
- " A string to explain persistent-action of this source. It also
- accepts a function or a variable name.")
-
-
-(provide 'helm-plugin)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-plugin ends here
+++ /dev/null
-;;; helm-regexp.el --- In buffer regexp searching and replacement for helm. -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'helm)
-(require 'helm-help)
-(require 'helm-utils)
-(require 'helm-plugin)
-
-(declare-function helm-mm-split-pattern "helm-multi-match")
-
-\f
-(defgroup helm-regexp nil
- "Regexp related Applications and libraries for Helm."
- :group 'helm)
-
-(defcustom helm-moccur-always-search-in-current nil
- "Helm multi occur always search in current buffer when non--nil."
- :group 'helm-regexp
- :type 'boolean)
-
-(defcustom helm-moccur-use-ioccur-style-keys t
- "Similar to `helm-grep-use-ioccur-style-keys' but for multi occur."
- :group 'helm-regexp
- :type 'boolean)
-
-(defcustom helm-moccur-auto-update-on-resume nil
- "Allow auto updating helm-(m)occur buffer when outdated.
-noask => Always update without asking
-nil => Don't update but signal buffer needs update
-never => Never update and do not signal buffer needs update
-Any other non--nil value update after confirmation."
- :group 'helm-regexp
- :type '(radio :tag "Allow auto updating helm-(m)occur buffer when outdated."
- (const :tag "Always update without asking" noask)
- (const :tag "Never update and do not signal buffer needs update" never)
- (const :tag "Don't update but signal buffer needs update" nil)
- (const :tag "Update after confirmation" t)))
-
-(defcustom helm-source-multi-occur-actions
- '(("Go to Line" . helm-moccur-goto-line)
- ("Goto line other window" . helm-moccur-goto-line-ow)
- ("Goto line new frame" . helm-moccur-goto-line-of))
- "Actions for helm-occur and helm-moccur."
- :group 'helm-regexp
- :type '(alist :key-type string :value-type function))
-
-(defcustom helm-moccur-truncate-lines t
- "When nil the (m)occur line that appears will not be truncated."
- :group 'helm-regexp
- :type 'boolean)
-
-\f
-(defface helm-moccur-buffer
- '((t (:foreground "DarkTurquoise" :underline t)))
- "Face used to highlight moccur buffer names."
- :group 'helm-regexp)
-
-(defface helm-resume-need-update
- '((t (:background "red")))
- "Face used to flash moccur buffer when it needs update."
- :group 'helm-regexp)
-
-\f
-(defvar helm-moccur-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map helm-map)
- (define-key map (kbd "M-<down>") 'helm-goto-next-file)
- (define-key map (kbd "M-<up>") 'helm-goto-precedent-file)
- (define-key map (kbd "C-w") 'helm-yank-text-at-point)
- (define-key map (kbd "C-c o") 'helm-moccur-run-goto-line-ow)
- (define-key map (kbd "C-c C-o") 'helm-moccur-run-goto-line-of)
- (define-key map (kbd "C-x C-s") 'helm-moccur-run-save-buffer)
- (when helm-moccur-use-ioccur-style-keys
- (define-key map (kbd "<right>") 'helm-execute-persistent-action)
- (define-key map (kbd "<left>") 'helm-moccur-run-default-action))
- (delq nil map))
- "Keymap used in Moccur source.")
-
-\f
-;; History vars
-(defvar helm-build-regexp-history nil)
-(defvar helm-occur-history nil)
-
-(defun helm-query-replace-regexp (_candidate)
- "Query replace regexp from `helm-regexp'.
-With a prefix arg replace only matches surrounded by word boundaries,
-i.e Don't replace inside a word, regexp is surrounded with \\bregexp\\b."
- (let ((regexp helm-input))
- (apply 'query-replace-regexp
- (helm-query-replace-args regexp))))
-
-(defun helm-kill-regexp-as-sexp (_candidate)
- "Kill regexp in a format usable in lisp code."
- (helm-regexp-kill-new
- (prin1-to-string helm-input)))
-
-(defun helm-kill-regexp (_candidate)
- "Kill regexp as it is in `helm-pattern'."
- (helm-regexp-kill-new helm-input))
-
-(defun helm-query-replace-args (regexp)
- "create arguments of `query-replace-regexp' action in `helm-regexp'."
- (let ((region-only (helm-region-active-p)))
- (list
- regexp
- (query-replace-read-to regexp
- (format "Query replace %sregexp %s"
- (if helm-current-prefix-arg "word " "")
- (if region-only "in region " ""))
- t)
- helm-current-prefix-arg
- (when region-only (region-beginning))
- (when region-only (region-end)))))
-
-(defvar helm-source-regexp
- (helm-build-in-buffer-source "Regexp Builder"
- :init (lambda ()
- (helm-init-candidates-in-buffer
- 'global (with-temp-buffer
- (insert-buffer-substring helm-current-buffer)
- (buffer-string))))
- :get-line #'helm-regexp-get-line
- :persistent-action #'helm-regexp-persistent-action
- :persistent-help "Show this line"
- :multiline t
- :matchplugin nil
- :requires-pattern 2
- :mode-line "Press TAB to select action."
- :action '(("Kill Regexp as sexp" . helm-kill-regexp-as-sexp)
- ("Query Replace Regexp (C-u Not inside word.)"
- . helm-query-replace-regexp)
- ("Kill Regexp" . helm-kill-regexp))))
-
-(defun helm-regexp-get-line (s e)
- (let ((matches (match-data))
- (line (buffer-substring s e)))
- (propertize
- (cl-loop with ln = (format "%5d: %s" (1- (line-number-at-pos s)) line)
- for i from 0 to (1- (/ (length matches) 2))
- concat (format "\n %s'%s'" (format "Group %d: " i)
- (match-string i))
- into ln1
- finally return (concat ln ln1))
- 'helm-realvalue s)))
-
-(defun helm-regexp-persistent-action (pt)
- (helm-goto-char pt)
- (helm-highlight-current-line))
-
-(defun helm-regexp-kill-new (input)
- (kill-new input)
- (message "Killed: %s" input))
-
-\f
-;;; Occur
-;;
-;;
-(defvar helm-source-occur nil)
-(defun helm-occur-init-source ()
- (unless helm-source-occur
- (setq helm-source-occur
- (helm-make-source "Occur" 'helm-source-multi-occur))))
-
-\f
-;;; Multi occur
-;;
-;;
-
-;; Internal
-(defvar helm-multi-occur-buffer-list nil)
-(defvar helm-multi-occur-buffer-tick nil)
-(defun helm-moccur-init ()
- "Create the initial helm multi occur buffer."
- (helm-init-candidates-in-buffer
- 'global
- (cl-loop with buffers = (helm-attr 'moccur-buffers)
- for buf in buffers
- for bufstr = (with-current-buffer buf (buffer-string))
- do (add-text-properties
- 0 (length bufstr)
- `(buffer-name ,(buffer-name (get-buffer buf)))
- bufstr)
- concat bufstr)))
-
-(defun helm-moccur--next-or-previous-char ()
- (save-excursion
- (or (re-search-forward "^." nil t)
- (re-search-backward "^." nil t))))
-
-(defun helm-moccur-get-line (beg end)
- "Format line for `helm-source-moccur'."
- (prog1
- (format "%s:%d:%s"
- (get-text-property (if (= beg end)
- (helm-moccur--next-or-previous-char)
- beg)
- 'buffer-name)
- (save-restriction
- (narrow-to-region (or (previous-single-property-change
- (point) 'buffer-name) 1)
- (or (next-single-property-change
- (if (= beg end)
- (helm-moccur--next-or-previous-char)
- (point))
- 'buffer-name)
- (point-max)))
- (line-number-at-pos beg))
- ;; When matching empty line, use empty string
- ;; to allow saving and modifying with wgrep.
- (if (= beg end) "" (buffer-substring beg end)))
- ;; When matching empty line, forward char ("\n")
- ;; to not be blocked forever here.
- (when (= beg end) (forward-char 1))))
-
-(cl-defun helm-moccur-action (candidate
- &optional (method (quote buffer)) mark)
- "Jump to CANDIDATE with METHOD.
-arg METHOD can be one of buffer, buffer-other-window, buffer-other-frame."
- (require 'helm-grep)
- (let* ((split (helm-grep-split-line candidate))
- (buf (car split))
- (lineno (string-to-number (nth 1 split)))
- (split-pat (helm-mm-split-pattern helm-input)))
- (cl-case method
- (buffer (switch-to-buffer buf))
- (buffer-other-window (switch-to-buffer-other-window buf))
- (buffer-other-frame (switch-to-buffer-other-frame buf)))
- (helm-goto-line lineno)
- ;; Move point to the nearest matching regexp from bol.
- (cl-loop for reg in split-pat
- when (save-excursion
- (condition-case _err
- (if helm-migemo-mode
- (helm-mm-migemo-forward reg (point-at-eol) t)
- (re-search-forward reg (point-at-eol) t))
- (invalid-regexp nil)))
- collect (match-beginning 0) into pos-ls
- finally (when pos-ls (goto-char (apply #'min pos-ls))))
- (when mark
- (set-marker (mark-marker) (point))
- (push-mark (point) 'nomsg))))
-
-(defun helm-moccur-persistent-action (candidate)
- (helm-moccur-goto-line candidate)
- (helm-highlight-current-line))
-
-(defun helm-moccur-goto-line (candidate)
- "From multi occur, switch to buffer and go to nth 1 CANDIDATE line."
- (helm-moccur-action
- candidate 'buffer (or current-prefix-arg ; persistent.
- helm-current-prefix-arg))) ; exit.
-
-(defun helm-moccur-goto-line-ow (candidate)
- "Go to CANDIDATE line in other window.
-Same as `helm-moccur-goto-line' but go in other window."
- (helm-moccur-action
- candidate 'buffer-other-window
- (or current-prefix-arg ; persistent.
- helm-current-prefix-arg))) ; exit.
-
-(defun helm-moccur-goto-line-of (candidate)
- "Go to CANDIDATE line in new frame.
-Same as `helm-moccur-goto-line' but go in new frame."
- (helm-moccur-action
- candidate 'buffer-other-frame
- (or current-prefix-arg ; persistent.
- helm-current-prefix-arg))) ; exit.
-
-(defun helm-moccur-run-goto-line-ow ()
- "Run goto line other window action from `helm-source-moccur'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-moccur-goto-line-ow)))
-(put 'helm-moccur-run-goto-line-ow 'helm-only t)
-
-(defun helm-moccur-run-goto-line-of ()
- "Run goto line new frame action from `helm-source-moccur'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-moccur-goto-line-of)))
-(put 'helm-moccur-run-goto-line-of 'helm-only t)
-
-(defun helm-moccur-run-default-action ()
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-moccur-goto-line)))
-(put 'helm-moccur-run-default-action 'helm-only t)
-
-(defvar helm-source-moccur nil)
-(defclass helm-source-multi-occur (helm-source-in-buffer)
- ((init :initform (lambda ()
- (require 'helm-grep)
- (helm-moccur-init)))
- (filter-one-by-one :initform 'helm-moccur-filter-one-by-one)
- (get-line :initform helm-moccur-get-line)
- (nohighlight :initform t)
- (nomark :initform t)
- (migemo :initform t)
- (action :initform 'helm-source-multi-occur-actions)
- (persistent-action :initform 'helm-moccur-persistent-action)
- (persistent-help :initform "Go to line")
- (resume :initform 'helm-moccur-resume-fn)
- (candidate-number-limit :initform 9999)
- (help-message :initform 'helm-moccur-help-message)
- (keymap :initform helm-moccur-map)
- (history :initform 'helm-occur-history)
- (requires-pattern :initform 2)))
-
-(defun helm-moccur-resume-fn ()
- (with-helm-buffer
- (let (new-tick-ls buffer-is-modified)
- (set (make-local-variable 'helm-multi-occur-buffer-list)
- (cl-loop for b in helm-multi-occur-buffer-list
- when (buffer-live-p (get-buffer b))
- collect b))
- (setq buffer-is-modified (/= (length helm-multi-occur-buffer-list)
- (length (helm-attr 'moccur-buffers))))
- (helm-attrset 'moccur-buffers helm-multi-occur-buffer-list)
- (setq new-tick-ls (cl-loop for b in helm-multi-occur-buffer-list
- collect (buffer-chars-modified-tick (get-buffer b))))
- (when buffer-is-modified
- (setq helm-multi-occur-buffer-tick new-tick-ls))
- (cl-assert (> (length helm-multi-occur-buffer-list) 0) nil
- "helm-resume error: helm-(m)occur buffer list is empty")
- (unless (eq helm-moccur-auto-update-on-resume 'never)
- (when (or buffer-is-modified
- (cl-loop for b in helm-multi-occur-buffer-list
- for new-tick = (buffer-chars-modified-tick (get-buffer b))
- for tick in helm-multi-occur-buffer-tick
- thereis (/= tick new-tick)))
- (helm-aif helm-moccur-auto-update-on-resume
- (when (or (eq it 'noask)
- (y-or-n-p "Helm (m)occur Buffer outdated, update? "))
- (run-with-idle-timer 0.1 nil (lambda ()
- (with-helm-buffer
- (helm-force-update)
- (message "Helm (m)occur Buffer have been udated")
- (sit-for 1) (message nil))))
- (unless buffer-is-modified (setq helm-multi-occur-buffer-tick new-tick-ls)))
- (run-with-idle-timer 0.1 nil (lambda ()
- (with-helm-buffer
- (let ((ov (make-overlay (save-excursion
- (goto-char (point-min))
- (forward-line 1)
- (point))
- (point-max))))
- (overlay-put ov 'face 'helm-resume-need-update)
- (sit-for 0.3) (delete-overlay ov)
- (message "[Helm occur Buffer outdated (C-c C-u to update)]")))))
- (unless buffer-is-modified
- (with-helm-after-update-hook
- (setq helm-multi-occur-buffer-tick new-tick-ls)
- (message "Helm (m)occur Buffer have been udated")))))))))
-
-(defun helm-moccur-filter-one-by-one (candidate)
- "`filter-one-by-one' function for `helm-source-moccur'."
- (require 'helm-grep)
- (let* ((split (helm-grep-split-line candidate))
- (buf (car split))
- (lineno (nth 1 split))
- (str (nth 2 split)))
- (cons (concat (propertize
- buf
- 'face 'helm-moccur-buffer
- 'help-echo (buffer-file-name
- (get-buffer buf))
- 'buffer-name buf)
- ":"
- (propertize lineno 'face 'helm-grep-lineno)
- ":"
- (helm-grep-highlight-match str t))
- candidate)))
-
-(defun helm-multi-occur-1 (buffers &optional input)
- "Main function to call `helm-source-moccur' with BUFFERS list."
- (let ((bufs (if helm-moccur-always-search-in-current
- (cons
- ;; will become helm-current-buffer later.
- (buffer-name (current-buffer))
- (remove helm-current-buffer buffers))
- buffers)))
- (unless helm-source-moccur
- (setq helm-source-moccur
- (helm-make-source "Moccur" 'helm-source-multi-occur)))
- (helm-attrset 'moccur-buffers bufs helm-source-moccur)
- (helm-set-local-variable 'helm-multi-occur-buffer-list bufs)
- (helm-set-local-variable
- 'helm-multi-occur-buffer-tick
- (cl-loop for b in bufs
- collect (buffer-chars-modified-tick (get-buffer b)))))
- (helm :sources 'helm-source-moccur
- :buffer "*helm multi occur*"
- :history 'helm-occur-history
- :keymap helm-moccur-map
- :input input
- :truncate-lines helm-moccur-truncate-lines))
-
-(defun helm-moccur-run-save-buffer ()
- "Run moccur save results action from `helm-moccur'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action 'helm-moccur-save-results)))
-(put 'helm-moccur-run-save-buffer 'helm-only t)
-
-\f
-;;; helm-moccur-mode
-;;
-;;
-(defvar helm-moccur-mode-map
- (let ((map (make-sparse-keymap)))
- (define-key map (kbd "RET") 'helm-moccur-mode-goto-line)
- (define-key map (kbd "C-o") 'helm-moccur-mode-goto-line-ow)
- (define-key map (kbd "<C-down>") 'helm-moccur-mode-goto-line-ow-forward)
- (define-key map (kbd "<C-up>") 'helm-moccur-mode-goto-line-ow-backward)
- (define-key map (kbd "<M-down>") 'helm-gm-next-file)
- (define-key map (kbd "<M-up>") 'helm-gm-precedent-file)
- (define-key map (kbd "M-n") 'helm-moccur-mode-goto-line-ow-forward)
- (define-key map (kbd "M-p") 'helm-moccur-mode-goto-line-ow-backward)
- (define-key map (kbd "M-N") 'helm-gm-next-file)
- (define-key map (kbd "M-P") 'helm-gm-precedent-file)
- map))
-
-(defun helm-moccur-mode-goto-line ()
- (interactive)
- (helm-aif (get-text-property (point) 'helm-realvalue)
- (helm-moccur-goto-line it)))
-
-(defun helm-moccur-mode-goto-line-ow ()
- (interactive)
- (helm-aif (get-text-property (point) 'helm-realvalue)
- (helm-moccur-goto-line-ow it)))
-
-(defun helm-moccur-mode-goto-line-ow-forward-1 (arg)
- (condition-case nil
- (progn
- (save-selected-window
- (helm-moccur-mode-goto-line-ow)
- (recenter))
- (forward-line arg))
- (error nil)))
-
-(defun helm-moccur-mode-goto-line-ow-forward ()
- (interactive)
- (helm-moccur-mode-goto-line-ow-forward-1 1))
-
-(defun helm-moccur-mode-goto-line-ow-backward ()
- (interactive)
- (helm-moccur-mode-goto-line-ow-forward-1 -1))
-
-(defun helm-moccur-save-results (_candidate)
- "Save helm moccur results in a `helm-moccur-mode' buffer."
- (let ((buf "*hmoccur*")
- new-buf)
- (when (get-buffer buf)
- (setq new-buf (helm-read-string "OccurBufferName: " buf))
- (cl-loop for b in (helm-buffer-list)
- when (and (string= new-buf b)
- (not (y-or-n-p
- (format "Buffer `%s' already exists overwrite? "
- new-buf))))
- do (setq new-buf (helm-read-string "OccurBufferName: " "*hmoccur ")))
- (setq buf new-buf))
- (with-current-buffer (get-buffer-create buf)
- (setq buffer-read-only t)
- (let ((inhibit-read-only t))
- (erase-buffer)
- (insert "-*- mode: helm-moccur -*-\n\n"
- (format "Moccur Results for `%s':\n\n" helm-input))
- (save-excursion
- (insert (with-current-buffer helm-buffer
- (goto-char (point-min)) (forward-line 1)
- (buffer-substring (point) (point-max))))))
- (helm-moccur-mode))
- (pop-to-buffer buf)
- (message "Helm Moccur Results saved in `%s' buffer" buf)))
-
-;;;###autoload
-(define-derived-mode helm-moccur-mode
- special-mode "helm-moccur"
- "Major mode to provide actions in helm moccur saved buffer.
-
-Special commands:
-\\{helm-moccur-mode-map}"
- (set (make-local-variable 'helm-multi-occur-buffer-list)
- (with-helm-buffer helm-multi-occur-buffer-list))
- (set (make-local-variable 'revert-buffer-function)
- #'helm-moccur-mode--revert-buffer-function))
-(put 'helm-moccur-mode 'helm-only t)
-
-(defun helm-moccur-mode--revert-buffer-function (&optional _ignore-auto _noconfirm)
- (goto-char (point-min))
- (let (pattern)
- (when (re-search-forward "^Moccur Results for `\\(.*\\)'" nil t)
- (setq pattern (match-string 1))
- (forward-line 0)
- (when (re-search-forward "^$" nil t)
- (forward-line 1))
- (let ((inhibit-read-only t)
- (buffer (current-buffer))
- (buflst helm-multi-occur-buffer-list))
- (delete-region (point) (point-max))
- (message "Reverting buffer...")
- (save-excursion
- (with-temp-buffer
- (insert
- "\n"
- (cl-loop for buf in buflst
- for bufstr = (or (and (buffer-live-p (get-buffer buf))
- (with-current-buffer buf
- (buffer-string)))
- "")
- unless (string= bufstr "")
- do (add-text-properties
- 0 (length bufstr)
- `(buffer-name ,(buffer-name (get-buffer buf)))
- bufstr)
- concat bufstr)
- "\n")
- (goto-char (point-min))
- (cl-loop with helm-pattern = pattern
- while (helm-mm-search pattern)
- for line = (helm-moccur-get-line (point-at-bol) (point-at-eol))
- when line
- do (with-current-buffer buffer
- (insert
- (propertize
- (car (helm-moccur-filter-one-by-one line))
- 'helm-realvalue line)
- "\n")))))
- (message "Reverting buffer done")))))
-
-\f
-;;; Predefined commands
-;;
-;;
-
-;;;###autoload
-(defun helm-regexp ()
- "Preconfigured helm to build regexps.
-`query-replace-regexp' can be run from there against found regexp."
- (interactive)
- (save-restriction
- (when (and (helm-region-active-p)
- ;; Don't narrow to region if buffer is already narrowed.
- (not (helm-current-buffer-narrowed-p (current-buffer))))
- (narrow-to-region (region-beginning) (region-end)))
- (helm :sources helm-source-regexp
- :buffer "*helm regexp*"
- :prompt "Regexp: "
- :history 'helm-build-regexp-history)))
-
-;;;###autoload
-(defun helm-occur ()
- "Preconfigured helm for Occur."
- (interactive)
- (helm-occur-init-source)
- (let ((bufs (list (buffer-name (current-buffer)))))
- (helm-attrset 'moccur-buffers bufs helm-source-occur)
- (helm-set-local-variable 'helm-multi-occur-buffer-list bufs)
- (helm-set-local-variable
- 'helm-multi-occur-buffer-tick
- (cl-loop for b in bufs
- collect (buffer-chars-modified-tick (get-buffer b)))))
- (helm :sources 'helm-source-occur
- :buffer "*helm occur*"
- :history 'helm-occur-history
- :preselect (and (memq 'helm-source-occur helm-sources-using-default-as-input)
- (format "%s:%d:" (regexp-quote (buffer-name))
- (line-number-at-pos (point))))
- :truncate-lines helm-moccur-truncate-lines))
-
-;;;###autoload
-(defun helm-occur-from-isearch ()
- "Invoke `helm-occur' from isearch."
- (interactive)
- (let ((input (if isearch-regexp
- isearch-string
- (regexp-quote isearch-string)))
- (bufs (list (buffer-name (current-buffer)))))
- (isearch-exit)
- (helm-occur-init-source)
- (helm-attrset 'moccur-buffers bufs helm-source-occur)
- (helm-set-local-variable 'helm-multi-occur-buffer-list bufs)
- (helm-set-local-variable
- 'helm-multi-occur-buffer-tick
- (cl-loop for b in bufs
- collect (buffer-chars-modified-tick (get-buffer b))))
- (helm :sources 'helm-source-occur
- :buffer "*helm occur*"
- :history 'helm-occur-history
- :input input
- :truncate-lines helm-moccur-truncate-lines)))
-
-;;;###autoload
-(defun helm-multi-occur-from-isearch (&optional _arg)
- "Invoke `helm-multi-occur' from isearch.
-
-With a prefix arg, reverse the behavior of
-`helm-moccur-always-search-in-current'.
-The prefix arg can be set before calling
-`helm-multi-occur-from-isearch' or during the buffer selection."
- (interactive "p")
- (let (buf-list
- helm-moccur-always-search-in-current
- (input (if isearch-regexp
- isearch-string
- (regexp-quote isearch-string))))
- (isearch-exit)
- (setq buf-list (helm-comp-read "Buffers: "
- (helm-buffer-list)
- :name "Occur in buffer(s)"
- :marked-candidates t))
- (setq helm-moccur-always-search-in-current
- (if (or current-prefix-arg
- helm-current-prefix-arg)
- (not helm-moccur-always-search-in-current)
- helm-moccur-always-search-in-current))
- (helm-multi-occur-1 buf-list input)))
-
-
-(provide 'helm-regexp)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-regexp.el ends here
+++ /dev/null
-;;; helm-ring.el --- kill-ring, mark-ring, and register browsers for helm. -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'helm)
-(require 'helm-utils)
-(require 'helm-help)
-(require 'helm-elisp)
-
-(declare-function undo-tree-restore-state-from-register "ext:undo-tree.el" (register))
-
-\f
-(defgroup helm-ring nil
- "Ring related Applications and libraries for Helm."
- :group 'helm)
-
-(defcustom helm-kill-ring-threshold 3
- "Minimum length of a candidate to be listed by `helm-source-kill-ring'."
- :type 'integer
- :group 'helm-ring)
-
-(defcustom helm-kill-ring-max-lines-number 5
- "Max number of lines displayed per candidate in kill-ring browser.
-If nil or zero (disabled), don't truncate candidate, show all."
- :type '(choice (const :tag "Disabled" nil)
- (integer :tag "Max number of lines"))
- :group 'helm-ring)
-
-(defcustom helm-register-max-offset 160
- "Max size of string register entries before truncating."
- :group 'helm-ring
- :type 'integer)
-
-(defcustom helm-kill-ring-actions
- '(("Yank" . helm-kill-ring-action)
- ("Delete" . (lambda (_candidate)
- (cl-loop for cand in (helm-marked-candidates)
- do (setq kill-ring
- (delete cand kill-ring))))))
- "List of actions for kill ring source."
- :group 'helm-ring
- :type '(alist :key-type string :value-type function))
-
-\f
-;;; Kill ring
-;;
-;;
-(defvar helm-kill-ring-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map helm-map)
- (define-key map (kbd "M-y") 'helm-next-line)
- (define-key map (kbd "M-u") 'helm-previous-line)
- map)
- "Keymap for `helm-show-kill-ring'.")
-
-(defvar helm-source-kill-ring
- (helm-build-sync-source "Kill Ring"
- :init (lambda () (helm-attrset 'last-command last-command))
- :candidates #'helm-kill-ring-candidates
- :filtered-candidate-transformer #'helm-kill-ring-transformer
- :action 'helm-kill-ring-actions
- :persistent-action (lambda (_candidate) (ignore))
- :persistent-help "DoNothing"
- :keymap helm-kill-ring-map
- :migemo t
- :multiline t)
- "Source for browse and insert contents of kill-ring.")
-
-(defun helm-kill-ring-candidates ()
- (cl-loop for kill in (helm-fast-remove-dups kill-ring :test 'equal)
- unless (or (< (length kill) helm-kill-ring-threshold)
- (string-match "\\`[\n[:blank:]]+\\'" kill))
- collect kill))
-
-(defun helm-kill-ring-transformer (candidates _source)
- "Display only the `helm-kill-ring-max-lines-number' lines of candidate."
- (cl-loop for i in candidates
- when (get-text-property 0 'read-only i)
- do (set-text-properties 0 (length i) '(read-only nil) i)
- for nlines = (with-temp-buffer (insert i) (count-lines (point-min) (point-max)))
- if (and helm-kill-ring-max-lines-number
- (> nlines helm-kill-ring-max-lines-number))
- collect (cons
- (with-temp-buffer
- (insert i)
- (goto-char (point-min))
- (concat
- (buffer-substring
- (point-min)
- (save-excursion
- (forward-line helm-kill-ring-max-lines-number)
- (point)))
- "[...]")) i)
- else collect i))
-
-(defun helm-kill-ring-action (str)
- "Insert STR in `kill-ring' and set STR to the head.
-If this action is executed just after `yank',
-replace with STR as yanked string."
- (with-helm-current-buffer
- (setq kill-ring (delete str kill-ring))
- ;; Adding a `delete-selection' property
- ;; to `helm-kill-ring-action' is not working
- ;; because `this-command' will be `helm-maybe-exit-minibuffer',
- ;; so use this workaround (Issue #1520).
- (when (and (region-active-p) delete-selection-mode)
- (delete-region (region-beginning) (region-end)))
- (if (not (eq (helm-attr 'last-command helm-source-kill-ring) 'yank))
- (insert-for-yank str)
- ;; from `yank-pop'
- (let ((inhibit-read-only t)
- (before (< (point) (mark t))))
- (if before
- (funcall (or yank-undo-function 'delete-region) (point) (mark t))
- (funcall (or yank-undo-function 'delete-region) (mark t) (point)))
- (setq yank-undo-function nil)
- (set-marker (mark-marker) (point) helm-current-buffer)
- (insert-for-yank str)
- ;; Set the window start back where it was in the yank command,
- ;; if possible.
- (set-window-start (selected-window) yank-window-start t)
- (when before
- ;; This is like exchange-point-and-mark, but doesn't activate the mark.
- ;; It is cleaner to avoid activation, even though the command
- ;; loop would deactivate the mark because we inserted text.
- (goto-char (prog1 (mark t)
- (set-marker (mark-marker) (point) helm-current-buffer))))))
- (kill-new str)))
-
-\f
-;;;; <Mark ring>
-;; DO NOT use these sources with other sources use
-;; the commands `helm-mark-ring', `helm-global-mark-ring' or
-;; `helm-all-mark-rings' instead.
-
-(defun helm-mark-ring-line-string-at-pos (pos)
- "Return line string at position POS."
- (save-excursion
- (goto-char pos)
- (forward-line 0)
- (let ((line (car (split-string (thing-at-point 'line) "[\n\r]"))))
- (if (string= "" line)
- "<EMPTY LINE>"
- line))))
-
-(defun helm-mark-ring-get-candidates ()
- (with-helm-current-buffer
- (cl-loop with marks = (if (mark t) (cons (mark-marker) mark-ring) mark-ring)
- for i in marks
- with max-line-number = (line-number-at-pos (point-max))
- with width = (length (number-to-string max-line-number))
- for m = (format (concat "%" (number-to-string width) "d: %s")
- (line-number-at-pos i)
- (helm-mark-ring-line-string-at-pos i))
- unless (and recip (member m recip))
- collect m into recip
- finally return recip)))
-
-(defvar helm-source-mark-ring
- (helm-build-sync-source "mark-ring"
- :candidates #'helm-mark-ring-get-candidates
- :action '(("Goto line"
- . (lambda (candidate)
- (helm-goto-line (string-to-number candidate)))))
- :persistent-action (lambda (candidate)
- (helm-goto-line (string-to-number candidate))
- (helm-highlight-current-line))
- :persistent-help "Show this line"))
-
-;;; Global-mark-ring
-(defvar helm-source-global-mark-ring
- (helm-build-sync-source "global-mark-ring"
- :candidates #'helm-global-mark-ring-get-candidates
- :action '(("Goto line"
- . (lambda (candidate)
- (let ((items (split-string candidate ":")))
- (switch-to-buffer (cl-second items))
- (helm-goto-line (string-to-number (car items)))))))
- :persistent-action (lambda (candidate)
- (let ((items (split-string candidate ":")))
- (switch-to-buffer (cl-second items))
- (helm-goto-line (string-to-number (car items)))
- (helm-highlight-current-line)))
- :persistent-help "Show this line"))
-
-(defun helm-global-mark-ring-format-buffer (marker)
- (with-current-buffer (marker-buffer marker)
- (goto-char marker)
- (forward-line 0)
- (let ((line (pcase (thing-at-point 'line)
- ((and line (pred stringp)
- (guard (not (string-match-p "\\`\n?\\'" line))))
- (car (split-string line "[\n\r]")))
- (_ "<EMPTY LINE>"))))
- (format "%7d:%s: %s"
- (line-number-at-pos) (marker-buffer marker) line))))
-
-(defun helm-global-mark-ring-get-candidates ()
- (let ((marks global-mark-ring))
- (when marks
- (cl-loop for i in marks
- for mb = (marker-buffer i)
- for gm = (unless (or (string-match "^ " (format "%s" mb))
- (null mb))
- (helm-global-mark-ring-format-buffer i))
- when (and gm (not (member gm recip)))
- collect gm into recip
- finally return recip))))
-
-(defun helm--push-mark (&optional location nomsg activate)
- "[Internal] Don't use directly, use instead `helm-push-mark-mode'."
- (unless (null (mark t))
- (setq mark-ring (cons (copy-marker (mark-marker)) mark-ring))
- (when (> (length mark-ring) mark-ring-max)
- (move-marker (car (nthcdr mark-ring-max mark-ring)) nil)
- (setcdr (nthcdr (1- mark-ring-max) mark-ring) nil)))
- (set-marker (mark-marker) (or location (point)) (current-buffer))
- ;; Now push the mark on the global mark ring.
- (setq global-mark-ring (cons (copy-marker (mark-marker))
- ;; Avoid having multiple entries
- ;; for same buffer in `global-mark-ring'.
- (cl-loop with mb = (current-buffer)
- for m in global-mark-ring
- for nmb = (marker-buffer m)
- unless (eq mb nmb)
- collect m)))
- (when (> (length global-mark-ring) global-mark-ring-max)
- (move-marker (car (nthcdr global-mark-ring-max global-mark-ring)) nil)
- (setcdr (nthcdr (1- global-mark-ring-max) global-mark-ring) nil))
- (or nomsg executing-kbd-macro (> (minibuffer-depth) 0)
- (message "Mark set"))
- (when (or activate (not transient-mark-mode))
- (set-mark (mark t)))
- nil)
-
-(defadvice push-mark (around helm-push-mark-mode)
- (helm--push-mark location nomsg activate))
-
-;;;###autoload
-(define-minor-mode helm-push-mark-mode
- "Provide an improved version of `push-mark'.
-Modify the behavior of `push-mark' to update
-the `global-mark-ring' after each new visit."
- :group 'helm-ring
- :global t
- (if helm-push-mark-mode
- (if (fboundp 'advice-add)
- (advice-add 'push-mark :override #'helm--push-mark)
- (ad-activate 'push-mark))
- (if (fboundp 'advice-remove)
- (advice-remove 'push-mark #'helm--push-mark)
- (ad-deactivate 'push-mark))))
-\f
-;;;; <Register>
-;;; Insert from register
-(defvar helm-source-register
- (helm-build-sync-source "Registers"
- :candidates #'helm-register-candidates
- :action-transformer #'helm-register-action-transformer
- :persistent-help ""
- :multiline t
- :action '(("Delete Register(s)" .
- (lambda (_candidate)
- (cl-loop for candidate in (helm-marked-candidates)
- for register = (car candidate)
- do (setq register-alist
- (delq (assoc register register-alist)
- register-alist)))))))
- "See (info \"(emacs)Registers\")")
-
-(defun helm-register-candidates ()
- "Collecting register contents and appropriate commands."
- (cl-loop for (char . val) in register-alist
- for key = (single-key-description char)
- for string-actions =
- (cond
- ((numberp val)
- (list (int-to-string val)
- 'insert-register
- 'increment-register))
- ((markerp val)
- (let ((buf (marker-buffer val)))
- (if (null buf)
- (list "a marker in no buffer")
- (list (concat
- "a buffer position:"
- (buffer-name buf)
- ", position "
- (int-to-string (marker-position val)))
- 'jump-to-register
- 'insert-register))))
- ((and (consp val) (window-configuration-p (car val)))
- (list "window configuration."
- 'jump-to-register))
- ((and (vectorp val)
- (fboundp 'undo-tree-register-data-p)
- (undo-tree-register-data-p (elt val 1)))
- (list
- "Undo-tree entry."
- 'undo-tree-restore-state-from-register))
- ((or (and (vectorp val) (eq 'registerv (aref val 0)))
- (and (consp val) (frame-configuration-p (car val))))
- (list "frame configuration."
- 'jump-to-register))
- ((and (consp val) (eq (car val) 'file))
- (list (concat "file:"
- (prin1-to-string (cdr val))
- ".")
- 'jump-to-register))
- ((and (consp val) (eq (car val) 'file-query))
- (list (concat "file:a file-query reference: file "
- (car (cdr val))
- ", position "
- (int-to-string (car (cdr (cdr val))))
- ".")
- 'jump-to-register))
- ((consp val)
- (let ((lines (format "%4d" (length val))))
- (list (format "%s: %s\n" lines
- (truncate-string-to-width
- (mapconcat 'identity (list (car val))
- "^J") (- (window-width) 15)))
- 'insert-register)))
- ((stringp val)
- (list
- ;; without properties
- (concat (substring-no-properties
- val 0 (min (length val) helm-register-max-offset))
- (if (> (length val) helm-register-max-offset)
- "[...]" ""))
- 'insert-register
- 'append-to-register
- 'prepend-to-register)))
- unless (null string-actions) ; Fix Issue #1107.
- collect (cons (format "Register %3s:\n %s" key (car string-actions))
- (cons char (cdr string-actions)))))
-
-(defun helm-register-action-transformer (actions register-and-functions)
- "Decide actions by the contents of register."
- (cl-loop with transformer-actions = nil
- with func-actions =
- '((insert-register
- "Insert Register" .
- (lambda (c) (insert-register (car c))))
- (jump-to-register
- "Jump to Register" .
- (lambda (c) (jump-to-register (car c))))
- (append-to-register
- "Append Region to Register" .
- (lambda (c) (append-to-register
- (car c) (region-beginning) (region-end))))
- (prepend-to-register
- "Prepend Region to Register" .
- (lambda (c) (prepend-to-register
- (car c) (region-beginning) (region-end))))
- (increment-register
- "Increment Prefix Arg to Register" .
- (lambda (c) (increment-register
- helm-current-prefix-arg (car c))))
- (undo-tree-restore-state-from-register
- "Restore Undo-tree register" .
- (lambda (c) (and (fboundp 'undo-tree-restore-state-from-register)
- (undo-tree-restore-state-from-register (car c))))))
- for func in (cdr register-and-functions)
- for cell = (assq func func-actions)
- when cell
- do (push (cdr cell) transformer-actions)
- finally return (append (nreverse transformer-actions) actions)))
-
-;;;###autoload
-(defun helm-mark-ring ()
- "Preconfigured `helm' for `helm-source-mark-ring'."
- (interactive)
- (helm :sources 'helm-source-mark-ring
- :resume 'noresume
- :buffer "*helm mark*"))
-
-;;;###autoload
-(defun helm-global-mark-ring ()
- "Preconfigured `helm' for `helm-source-global-mark-ring'."
- (interactive)
- (helm :sources 'helm-source-global-mark-ring
- :resume 'noresume
- :buffer "*helm global mark*"))
-
-;;;###autoload
-(defun helm-all-mark-rings ()
- "Preconfigured `helm' for `helm-source-global-mark-ring' and \
-`helm-source-mark-ring'."
- (interactive)
- (helm :sources '(helm-source-mark-ring
- helm-source-global-mark-ring)
- :resume 'noresume
- :buffer "*helm mark ring*"))
-
-;;;###autoload
-(defun helm-register ()
- "Preconfigured `helm' for Emacs registers."
- (interactive)
- (helm :sources 'helm-source-register
- :resume 'noresume
- :buffer "*helm register*"))
-
-;;;###autoload
-(defun helm-show-kill-ring ()
- "Preconfigured `helm' for `kill-ring'.
-It is drop-in replacement of `yank-pop'.
-
-First call open the kill-ring browser, next calls move to next line."
- (interactive)
- (let ((enable-recursive-minibuffers t))
- (helm :sources helm-source-kill-ring
- :buffer "*helm kill ring*"
- :resume 'noresume
- :allow-nest t)))
-
-;;;###autoload
-(defun helm-execute-kmacro ()
- "Preconfigured helm for keyboard macros.
-Define your macros with `f3' and `f4'.
-See (info \"(emacs) Keyboard Macros\") for detailed infos.
-This command is useful when used with persistent action."
- (interactive)
- (helm :sources
- (helm-build-sync-source "Kmacro"
- :candidates (lambda ()
- (helm-fast-remove-dups
- (cons (kmacro-ring-head)
- kmacro-ring)
- :test 'equal))
- :multiline t
- :candidate-transformer
- (lambda (candidates)
- (cl-loop for c in candidates collect
- (propertize (help-key-description (car c) nil)
- 'helm-realvalue c)))
- :persistent-help "Execute kmacro"
- :help-message 'helm-kmacro-help-message
- :action
- (helm-make-actions
- "Execute kmacro (`C-u <n>' to execute <n> times)"
- (lambda (candidate)
- (interactive)
- ;; Move candidate on top of list for next use.
- (setq kmacro-ring (delete candidate kmacro-ring))
- (kmacro-push-ring)
- (kmacro-split-ring-element candidate)
- (kmacro-exec-ring-item
- candidate helm-current-prefix-arg))))
- :buffer "*helm kmacro*"))
-
-(provide 'helm-ring)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-ring.el ends here
+++ /dev/null
-;;; helm-semantic.el --- Helm interface for Semantic -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012 ~ 2016 Daniel Hackney <danNOSPAMhaxney.org>
-;; Author: Daniel Hackney <danNOSPAMhaxney.org>
-
-;; 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/>.
-
-;;; Commentary:
-
-;; Uses `candidates-in-buffer' for speed.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'semantic)
-(require 'helm-help)
-(require 'helm-imenu)
-
-(declare-function pulse-momentary-highlight-one-line "pulse.el" (point &optional face))
-
-(defgroup helm-semantic nil
- "Semantic tags related libraries and applications for helm."
- :group 'helm)
-
-(defcustom helm-semantic-lynx-style-map t
- "Use Arrow keys to jump to occurences."
- :group 'helm-semantic
- :type 'boolean)
-
-(defcustom helm-semantic-display-style
- '((python-mode . semantic-format-tag-summarize)
- (c-mode . semantic-format-tag-concise-prototype-c-mode)
- (emacs-lisp-mode . semantic-format-tag-abbreviate-emacs-lisp-mode))
- "Function to present a semantic tag according to `major-mode'.
-
-It is an alist where the `car' of each element is a `major-mode' and
-the `cdr' a `semantic-format-tag-*' function.
-
-If no function is found for current `major-mode', fall back to
-`semantic-format-tag-summarize' default function.
-
-You can have more or less informations depending of the `semantic-format-tag-*'
-function you choose.
-
-All the supported functions are prefixed with \"semantic-format-tag-\",
-you have completion on these functions with `C-M i' in the customize interface."
- :group 'helm-semantic
- :type '(alist :key-type symbol :value-type symbol))
-
-;;; keymap
-(defvar helm-semantic-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map helm-map)
- (when helm-semantic-lynx-style-map
- (define-key map (kbd "<left>") 'helm-maybe-exit-minibuffer)
- (define-key map (kbd "<right>") 'helm-execute-persistent-action))
- (delq nil map)))
-
-;; Internals vars
-(defvar helm-semantic--tags-cache nil)
-
-(defun helm-semantic--fetch-candidates (tags depth &optional class)
- "Write the contents of TAGS to the current buffer."
- (let ((class class) cur-type
- (stylefn (or (with-helm-current-buffer
- (assoc-default major-mode helm-semantic-display-style))
- #'semantic-format-tag-summarize)))
- (cl-dolist (tag tags)
- (when (listp tag)
- (cl-case (setq cur-type (semantic-tag-class tag))
- ((function variable type)
- (let ((spaces (make-string (* depth 2) ?\s))
- (type-p (eq cur-type 'type)))
- (unless (and (> depth 0) (not type-p))
- (setq class nil))
- (insert
- (if (and class (not type-p))
- (format "%s%s(%s) "
- spaces (if (< depth 2) "" "├►") class)
- spaces)
- ;; Save the tag for later
- (propertize (funcall stylefn tag nil t)
- 'semantic-tag tag)
- "\n")
- (and type-p (setq class (car tag)))
- ;; Recurse to children
- (unless (eq cur-type 'function)
- (helm-semantic--fetch-candidates
- (semantic-tag-components tag) (1+ depth) class))))
-
- ;; Don't do anything with packages or includes for now
- ((package include)
- (insert
- (propertize (funcall stylefn tag nil t)
- 'semantic-tag tag)
- "\n")
- )
- ;; Catch-all
- (t))))))
-
-(defun helm-semantic-default-action (_candidate &optional persistent)
- ;; By default, helm doesn't pass on the text properties of the selection.
- ;; Fix this.
- (helm-log-run-hook 'helm-goto-line-before-hook)
- (with-current-buffer helm-buffer
- (when (looking-at " ")
- (goto-char (next-single-property-change
- (point-at-bol) 'semantic-tag nil (point-at-eol))))
- (let ((tag (get-text-property (point) 'semantic-tag)))
- (semantic-go-to-tag tag)
- (unless persistent
- (pulse-momentary-highlight-one-line (point))))))
-
-(defun helm-semantic--maybe-set-needs-update ()
- (with-helm-current-buffer
- (when (semantic-parse-tree-needs-update-p)
- (semantic-parse-tree-set-needs-update))))
-
-(defvar helm-source-semantic nil)
-
-(defclass helm-semantic-source (helm-source-in-buffer)
- ((init :initform (lambda ()
- (helm-semantic--maybe-set-needs-update)
- (setq helm-semantic--tags-cache (semantic-fetch-tags))
- (with-current-buffer (helm-candidate-buffer 'global)
- (let ((major-mode (with-helm-current-buffer major-mode)))
- (helm-semantic--fetch-candidates helm-semantic--tags-cache 0)))))
- (get-line :initform 'buffer-substring)
- (persistent-help :initform "Show this entry")
- (keymap :initform 'helm-semantic-map)
- (help-message :initform 'helm-semantic-help-message)
- (persistent-action :initform (lambda (elm)
- (helm-semantic-default-action elm t)
- (helm-highlight-current-line)))
- (action :initform 'helm-semantic-default-action)))
-
-(defcustom helm-semantic-fuzzy-match nil
- "Enable fuzzy matching in `helm-source-semantic'."
- :group 'helm-semantic
- :type 'boolean
- :set (lambda (var val)
- (set var val)
- (setq helm-source-semantic
- (helm-make-source "Semantic Tags" 'helm-semantic-source
- :fuzzy-match helm-semantic-fuzzy-match))))
-
-;;;###autoload
-(defun helm-semantic (arg)
- "Preconfigured `helm' for `semantic'.
-If ARG is supplied, pre-select symbol at point instead of current"
- (interactive "P")
- (let ((tag (helm-aif (semantic-current-tag-parent)
- (cons (format "\\_<%s\\_>" (car it))
- (format "\\_<%s\\_>" (car (semantic-current-tag))))
- (format "\\_<%s\\_>" (car (semantic-current-tag))))))
- (unless helm-source-semantic
- (setq helm-source-semantic
- (helm-make-source "Semantic Tags" 'helm-semantic-source
- :fuzzy-match helm-semantic-fuzzy-match)))
- (helm :sources 'helm-source-semantic
- :candidate-number-limit 9999
- :preselect (if arg
- (thing-at-point 'symbol)
- tag)
- :buffer "*helm semantic*")))
-
-;;;###autoload
-(defun helm-semantic-or-imenu (arg)
- "Preconfigured helm for `semantic' or `imenu'.
-If ARG is supplied, pre-select symbol at point instead of current
-semantic tag in scope.
-
-If `semantic-mode' is active in the current buffer, then use
-semantic for generating tags, otherwise fall back to `imenu'.
-Fill in the symbol at point by default."
- (interactive "P")
- (unless helm-source-semantic
- (setq helm-source-semantic
- (helm-make-source "Semantic Tags" 'helm-semantic-source
- :fuzzy-match helm-semantic-fuzzy-match)))
- (unless helm-source-imenu
- (setq helm-source-imenu
- (helm-make-source "Imenu" 'helm-imenu-source
- :fuzzy-match helm-imenu-fuzzy-match)))
- (let* ((source (if (semantic-active-p)
- 'helm-source-semantic
- 'helm-source-imenu))
- (imenu-p (eq source 'helm-source-imenu))
- (imenu-auto-rescan imenu-p)
- (str (thing-at-point 'symbol))
- (helm-execute-action-at-once-if-one
- (and imenu-p
- helm-imenu-execute-action-at-once-if-one))
- (tag (helm-aif (semantic-current-tag-parent)
- (cons (format "\\_<%s\\_>" (car it))
- (format "\\_<%s\\_>" (car (semantic-current-tag))))
- (format "\\_<%s\\_>" (car (semantic-current-tag))))))
- (helm :sources source
- :candidate-number-limit 9999
- :default (and imenu-p (list (concat "\\_<" str "\\_>") str))
- :preselect (if (or arg imenu-p) str tag)
- :buffer "*helm semantic/imenu*")))
-
-(provide 'helm-semantic)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-semantic.el ends here
+++ /dev/null
-;;; helm-sys.el --- System related functions for helm. -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'helm)
-(require 'helm-help)
-(require 'helm-utils)
-
-\f
-(defgroup helm-sys nil
- "System related helm library."
- :group 'helm)
-
-(defface helm-top-columns
- '((t :inherit helm-header))
- "Face for helm help string in minibuffer."
- :group 'helm-sys)
-
-\f
-(defun helm-top-command-set-fn (var _value)
- (set var
- (cl-case system-type
- (darwin "env COLUMNS=%s ps -axo pid,user,pri,nice,ucomm,tty,start,vsz,%%cpu,%%mem,etime,command")
- (t "env COLUMNS=%s top -b -n 1"))))
-
-(defcustom helm-top-command "env COLUMNS=%s top -b -n 1"
- "Top command used to display output of top.
-To use top command, a version supporting batch mode (-b option) is needed.
-On Mac OSX top command doesn't support this, so ps command
-is used by default instead.
-If you modify this the number and order of elements displayed
-should be the same as top command to have the sort commands
-working properly, that is 12 elements with the 2 first being
-PID and USER and the last 4 being %CPU, %MEM, TIME and COMMAND.
-A format string where %s will be replaced with `frame-width'."
- :group 'helm-sys
- :type 'string
- :set 'helm-top-command-set-fn)
-
-(defcustom helm-top-poll-delay 1.5
- "Helm top poll after this dealy when `helm-top-poll-mode' is enabled.
-The minimal delay allowed is 1.5, if less than this helm-top will use 1.5."
- :group 'helm-sys
- :type 'float)
-
-(defcustom helm-top-poll-delay-post-command 1.0
- "Helm top stop polling during this delay.
-This delay is additioned to `helm-top-poll-delay' after emacs stop
-being idle."
- :group 'helm-sys
- :type 'float)
-
-(defcustom helm-top-poll-preselection 'linum
- "Stay on same line or follow candidate when `helm-top-poll' update display.
-Possible values are 'candidate or 'linum."
- :group'helm-sys
- :type '(radio :tag "Preferred preselection action for helm-top"
- (const :tag "Follow candidate" candidate)
- (const :tag "Stay on same line" linum)))
-\f
-;;; Top (process)
-;;
-;;
-(defvar helm-top-sort-fn nil)
-(defvar helm-top-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map helm-map)
- (define-key map (kbd "M-P") 'helm-top-run-sort-by-cpu)
- (define-key map (kbd "M-C") 'helm-top-run-sort-by-com)
- (define-key map (kbd "M-M") 'helm-top-run-sort-by-mem)
- (define-key map (kbd "M-U") 'helm-top-run-sort-by-user)
- map))
-
-(defvar helm-top-after-init-hook nil
- "Local hook for helm-top.")
-
-(defvar helm-top--poll-timer nil)
-
-(defun helm-top-poll (&optional no-update delay)
- (when helm-top--poll-timer
- (cancel-timer helm-top--poll-timer))
- (condition-case nil
- (progn
- (when (and (helm-alive-p) (null no-update))
- ;; Fix quitting while process is running
- ;; by binding `with-local-quit' in init function
- ;; Issue #1521.
- (helm-force-update
- (cl-ecase helm-top-poll-preselection
- (candidate (replace-regexp-in-string
- "[0-9]+" "[0-9]+"
- (regexp-quote (helm-get-selection nil t))))
- (linum `(lambda ()
- (goto-char (point-min))
- (forward-line ,(helm-candidate-number-at-point)))))))
- (setq helm-top--poll-timer
- (run-with-idle-timer
- (helm-aif (current-idle-time)
- (time-add it (seconds-to-time
- (or delay (helm-top--poll-delay))))
- (or delay (helm-top--poll-delay)))
- nil
- 'helm-top-poll)))
- (quit (cancel-timer helm-top--poll-timer))))
-
-(defun helm-top--poll-delay ()
- (max 1.5 helm-top-poll-delay))
-
-(defun helm-top-poll-no-update ()
- (helm-top-poll t (+ (helm-top--poll-delay)
- helm-top-poll-delay-post-command)))
-
-(defun helm-top-initialize-poll-hooks ()
- ;; When emacs is idle during say 20s
- ;; the idle timer will run in 20+1.5 s.
- ;; This is fine when emacs stays idle, because the next timer
- ;; will run at 21.5+1.5 etc... so the display will be updated
- ;; at every 1.5 seconds.
- ;; But as soon as emacs looses its idleness, the next update
- ;; will occur at say 21+1.5 s, so we have to reinitialize
- ;; the timer at 0+1.5.
- (add-hook 'post-command-hook 'helm-top-poll-no-update)
- (add-hook 'focus-in-hook 'helm-top-poll-no-update))
-
-;;;###autoload
-(define-minor-mode helm-top-poll-mode
- "Refresh automatically helm top buffer once enabled."
- :group 'helm-top
- :global t
- (if helm-top-poll-mode
- (progn
- (add-hook 'helm-top-after-init-hook 'helm-top-poll-no-update)
- (add-hook 'helm-top-after-init-hook 'helm-top-initialize-poll-hooks))
- (remove-hook 'helm-top-after-init-hook 'helm-top-poll-no-update)
- (remove-hook 'helm-top-after-init-hook 'helm-top-initialize-poll-hooks)))
-
-(defvar helm-source-top
- (helm-build-in-buffer-source "Top"
- :header-name (lambda (name)
- (concat name (if helm-top-poll-mode
- " (auto updating)"
- " (Press C-c C-u to refresh)")))
- :init #'helm-top-init
- :after-init-hook 'helm-top-after-init-hook
- :cleanup (lambda ()
- (when helm-top--poll-timer
- (cancel-timer helm-top--poll-timer))
- (remove-hook 'post-command-hook 'helm-top-poll-no-update)
- (remove-hook 'focus-in-hook 'helm-top-poll-no-update))
- :nomark t
- :display-to-real #'helm-top-display-to-real
- :persistent-action #'helm-top-sh-persistent-action
- :persistent-help "SIGTERM"
- :help-message 'helm-top-help-message
- :follow 'never
- :keymap helm-top-map
- :filtered-candidate-transformer #'helm-top-sort-transformer
- :action-transformer #'helm-top-action-transformer))
-
-(defvar helm-top--line nil)
-(defun helm-top-transformer (candidates _source)
- "Transformer for `helm-top'.
-Return empty string for non--valid candidates."
- (cl-loop for disp in candidates collect
- (cond ((string-match "^ *[0-9]+" disp) disp)
- ((string-match "^ *PID" disp)
- (setq helm-top--line (cons (propertize disp 'face 'helm-top-columns) "")))
- (t (cons disp "")))
- into lst
- finally return (or (member helm-top--line lst)
- (cons helm-top--line lst))))
-
-(defun helm-top--skip-top-line ()
- (let ((src-name (assoc-default 'name (helm-get-current-source))))
- (helm-aif (and (stringp src-name)
- (string= src-name "Top")
- (helm-get-selection nil t))
- (when (string-match-p "^ *PID" it)
- (helm-next-line)))))
-
-(defun helm-top-action-transformer (actions _candidate)
- "Action transformer for `top'.
-Show actions only on line starting by a PID."
- (let ((disp (helm-get-selection nil t)))
- (cond ((string-match "^ *[0-9]+" disp)
- (list '("kill (SIGTERM)" . (lambda (pid) (helm-top-sh "TERM" pid)))
- '("kill (SIGKILL)" . (lambda (pid) (helm-top-sh "KILL" pid)))
- '("kill (SIGINT)" . (lambda (pid) (helm-top-sh "INT" pid)))
- '("kill (Choose signal)"
- . (lambda (pid)
- (helm-top-sh
- (helm-comp-read (format "Kill [%s] with signal: " pid)
- '("ALRM" "HUP" "INT" "KILL" "PIPE" "POLL"
- "PROF" "TERM" "USR1" "USR2" "VTALRM"
- "STKFLT" "PWR" "WINCH" "CHLD" "URG"
- "TSTP" "TTIN" "TTOU" "STOP" "CONT"
- "ABRT" "FPE" "ILL" "QUIT" "SEGV"
- "TRAP" "SYS" "EMT" "BUS" "XCPU" "XFSZ")
- :must-match t)
- pid)))))
- (t actions))))
-
-(defun helm-top-sh (sig pid)
- "Run kill shell command with signal SIG on PID for `helm-top'."
- (let ((cmd (format "kill -%s %s" sig pid)))
- (message "Executed %s\n%s" cmd (shell-command-to-string cmd))))
-
-(defun helm-top-sh-persistent-action (pid)
- (delete-other-windows)
- (helm-top-sh "TERM" pid)
- (helm-force-update))
-
-(defun helm-top-init ()
- "Insert output of top command in candidate buffer."
- (with-local-quit
- (unless helm-top-sort-fn (helm-top-set-mode-line "CPU"))
- (with-current-buffer (helm-candidate-buffer 'global)
- (call-process-shell-command
- (format helm-top-command (frame-width))
- nil (current-buffer)))))
-
-(defun helm-top-display-to-real (line)
- "Return pid only from LINE."
- (car (split-string line)))
-
-;; Sort top command
-
-(defun helm-top-set-mode-line (str)
- (if (string-match "Sort:\\[\\(.*\\)\\] " helm-top-mode-line)
- (setq helm-top-mode-line (replace-match str nil nil helm-top-mode-line 1))
- (setq helm-top-mode-line (concat (format "Sort:[%s] " str) helm-top-mode-line))))
-
-(defun helm-top-sort-transformer (candidates source)
- (helm-top-transformer
- (if helm-top-sort-fn
- (cl-loop for c in candidates
- if (string-match "^ *[0-9]+" c)
- collect c into pid-cands
- else collect c into header-cands
- finally return (append
- header-cands
- (sort pid-cands helm-top-sort-fn)))
- candidates)
- source))
-
-(defun helm-top-sort-by-com (s1 s2)
- (let* ((split-1 (split-string s1))
- (split-2 (split-string s2))
- (com-1 (nth 11 split-1))
- (com-2 (nth 11 split-2)))
- (string< com-1 com-2)))
-
-(defun helm-top-sort-by-mem (s1 s2)
- (let* ((split-1 (split-string s1))
- (split-2 (split-string s2))
- (mem-1 (string-to-number (nth 9 split-1)))
- (mem-2 (string-to-number (nth 9 split-2))))
- (> mem-1 mem-2)))
-
-(defun helm-top-sort-by-user (s1 s2)
- (let* ((split-1 (split-string s1))
- (split-2 (split-string s2))
- (user-1 (nth 1 split-1))
- (user-2 (nth 1 split-2)))
- (string< user-1 user-2)))
-
-(defun helm-top-run-sort-by-com ()
- (interactive)
- (helm-top-set-mode-line "COM")
- (setq helm-top-sort-fn 'helm-top-sort-by-com)
- (helm-update (replace-regexp-in-string
- "[0-9]+" "[0-9]+"
- (regexp-quote (helm-get-selection nil t)))))
-
-(defun helm-top-run-sort-by-cpu ()
- (interactive)
- (helm-top-set-mode-line "CPU")
- (setq helm-top-sort-fn nil)
- (helm-update (replace-regexp-in-string
- "[0-9]+" "[0-9]+"
- (regexp-quote (helm-get-selection nil t)))))
-
-(defun helm-top-run-sort-by-mem ()
- (interactive)
- (helm-top-set-mode-line "MEM")
- (setq helm-top-sort-fn 'helm-top-sort-by-mem)
- (helm-update (replace-regexp-in-string
- "[0-9]+" "[0-9]+"
- (regexp-quote (helm-get-selection nil t)))))
-
-(defun helm-top-run-sort-by-user ()
- (interactive)
- (helm-top-set-mode-line "USER")
- (setq helm-top-sort-fn 'helm-top-sort-by-user)
- (helm-update (replace-regexp-in-string
- "[0-9]+" "[0-9]+"
- (regexp-quote (helm-get-selection nil t)))))
-
-\f
-;;; X RandR resolution change
-;;
-;;
-;;; FIXME I do not care multi-display.
-
-(defun helm-xrandr-info ()
- "Return a pair with current X screen number and current X display name."
- (with-temp-buffer
- (call-process "xrandr" nil (current-buffer) nil
- "--current")
- (let (screen output)
- (goto-char (point-min))
- (save-excursion
- (when (re-search-forward "\\(^Screen \\)\\([0-9]\\):" nil t)
- (setq screen (match-string 2))))
- (when (re-search-forward "^\\(.*\\) connected" nil t)
- (setq output (match-string 1)))
- (list screen output))))
-
-(defun helm-xrandr-screen ()
- "Return current X screen number."
- (car (helm-xrandr-info)))
-
-(defun helm-xrandr-output ()
- "Return current X display name."
- (cadr (helm-xrandr-info)))
-
-(defvar helm-source-xrandr-change-resolution
- '((name . "Change Resolution")
- (candidates
- . (lambda ()
- (with-temp-buffer
- (call-process "xrandr" nil (current-buffer) nil
- "--screen" (helm-xrandr-screen) "-q")
- (goto-char 1)
- (cl-loop with modes = nil
- while (re-search-forward " \\([0-9]+x[0-9]+\\)" nil t)
- for mode = (match-string 1)
- unless (member mode modes)
- collect mode into modes
- finally return modes))))
- (action
- ("Change Resolution"
- . (lambda (mode)
- (call-process "xrandr" nil nil nil
- "--screen" (helm-xrandr-screen)
- "--output" (helm-xrandr-output)
- "--mode" mode))))))
-
-\f
-;;; Emacs process
-;;
-;;
-(defvar helm-source-emacs-process
- '((name . "Emacs Process")
- (init . (lambda () (list-processes--refresh)))
- (candidates . (lambda () (mapcar #'process-name (process-list))))
- (persistent-action . (lambda (elm)
- (delete-process (get-process elm))
- (helm-delete-current-selection)))
- (persistent-help . "Kill Process")
- (action ("Kill Process" . (lambda (elm)
- (delete-process (get-process elm)))))))
-
-\f
-;;;###autoload
-(defun helm-top ()
- "Preconfigured `helm' for top command."
- (interactive)
- (add-hook 'helm-after-update-hook 'helm-top--skip-top-line)
- (save-window-excursion
- (unless helm-alive-p (delete-other-windows))
- (unwind-protect
- (helm :sources 'helm-source-top
- :buffer "*helm top*" :full-frame t
- :candidate-number-limit 9999
- :preselect "^\\s-*[0-9]+")
- (remove-hook 'helm-after-update-hook 'helm-top--skip-top-line))))
-
-;;;###autoload
-(defun helm-list-emacs-process ()
- "Preconfigured `helm' for emacs process."
- (interactive)
- (helm-other-buffer 'helm-source-emacs-process "*helm process*"))
-
-;;;###autoload
-(defun helm-xrandr-set ()
- "Preconfigured helm for xrandr."
- (interactive)
- (helm :sources 'helm-source-xrandr-change-resolution
- :buffer "*helm xrandr*"))
-
-(provide 'helm-sys)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-sys.el ends here
+++ /dev/null
-;;; helm-tags.el --- Helm for Etags. -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'helm)
-(require 'helm-help)
-(require 'helm-utils)
-(require 'helm-grep)
-
-\f
-(defgroup helm-tags nil
- "Tags related Applications and libraries for Helm."
- :group 'helm)
-
-(defcustom helm-etags-tag-file-name "TAGS"
- "Etags tag file name."
- :type 'string
- :group 'helm-tags)
-
-(defcustom helm-etags-tag-file-search-limit 10
- "The limit level of directory to search tag file.
-Don't search tag file deeply if outside this value."
- :type 'number
- :group 'helm-tags)
-
-(defcustom helm-etags-match-part-only 'tag
- "Allow choosing the tag part of CANDIDATE in `helm-source-etags-select'.
-A tag looks like this:
- filename: \(defun foo
-You can choose matching against the tag part (i.e \"(defun foo\"),
-or against the whole candidate (i.e \"(filename:5:(defun foo\")."
- :type '(choice
- (const :tag "Match only tag" tag)
- (const :tag "Match all file+tag" all))
- :group 'helm-tags)
-
-(defcustom helm-etags-execute-action-at-once-if-one t
- "Whether to jump straight to the selected tag if there's only
-one match."
- :type 'boolean
- :group 'helm-tags)
-
-\f
-(defgroup helm-tags-faces nil
- "Customize the appearance of helm-tags faces."
- :prefix "helm-"
- :group 'helm-tags
- :group 'helm-faces)
-
-(defface helm-etags-file
- '((t (:foreground "Lightgoldenrod4"
- :underline t)))
- "Face used to highlight etags filenames."
- :group 'helm-tags-faces)
-
-\f
-;;; Etags
-;;
-;;
-(defun helm-etags-run-switch-other-window ()
- "Run switch to other window action from `helm-source-etags-select'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action
- (lambda (c)
- (helm-etags-action-goto 'find-file-other-window c)))))
-(put 'helm-etags-run-switch-other-window 'helm-only t)
-
-(defun helm-etags-run-switch-other-frame ()
- "Run switch to other frame action from `helm-source-etags-select'."
- (interactive)
- (with-helm-alive-p
- (helm-exit-and-execute-action
- (lambda (c)
- (helm-etags-action-goto 'find-file-other-frame c)))))
-(put 'helm-etags-run-switch-other-frame 'helm-only t)
-
-(defvar helm-etags-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map helm-map)
- (define-key map (kbd "M-<down>") 'helm-goto-next-file)
- (define-key map (kbd "M-<up>") 'helm-goto-precedent-file)
- (define-key map (kbd "C-w") 'helm-yank-text-at-point)
- (define-key map (kbd "C-c o") 'helm-etags-run-switch-other-window)
- (define-key map (kbd "C-c C-o") 'helm-etags-run-switch-other-frame)
- map)
- "Keymap used in Etags.")
-
-(defvar helm-etags-mtime-alist nil
- "Store the last modification time of etags files here.")
-(defvar helm-etags-cache (make-hash-table :test 'equal)
- "Cache content of etags files used here for faster access.")
-
-(defun helm-etags-get-tag-file (&optional directory)
- "Return the path of etags file if found.
-Lookes recursively in parents directorys for a
-`helm-etags-tag-file-name' file."
- ;; Get tag file from `default-directory' or upper directory.
- (let ((current-dir (helm-etags-find-tag-file-directory
- (or directory default-directory))))
- ;; Return nil if not find tag file.
- (when current-dir
- (expand-file-name helm-etags-tag-file-name current-dir))))
-
-(defun helm-etags-all-tag-files ()
- "Return files from the following sources;
- 1) An automatically located file in the parent directories, by `helm-etags-get-tag-file'.
- 2) `tags-file-name', which is commonly set by `find-tag' command.
- 3) `tags-table-list' which is commonly set by `visit-tags-table' command."
- (helm-fast-remove-dups
- (delq nil
- (append (list (helm-etags-get-tag-file)
- tags-file-name)
- tags-table-list))
- :test 'equal))
-
-(defun helm-etags-find-tag-file-directory (current-dir)
- "Try to find the directory containing tag file.
-If not found in CURRENT-DIR search in upper directory."
- (let ((file-exists? (lambda (dir)
- (let ((tag-path (expand-file-name
- helm-etags-tag-file-name dir)))
- (and (stringp tag-path)
- (file-regular-p tag-path)
- (file-readable-p tag-path))))))
- (cl-loop with count = 0
- until (funcall file-exists? current-dir)
- ;; Return nil if outside the value of
- ;; `helm-etags-tag-file-search-limit'.
- if (= count helm-etags-tag-file-search-limit)
- do (cl-return nil)
- ;; Or search upper directories.
- else
- do (cl-incf count)
- (setq current-dir (expand-file-name (concat current-dir "../")))
- finally return current-dir)))
-
-(defun helm-etags-get-header-name (_x)
- "Create header name for this helm etags session."
- (concat "Etags in "
- (with-helm-current-buffer
- (helm-etags-get-tag-file))))
-
-(defun helm-etags-create-buffer (file)
- "Create the `helm-buffer' based on contents of etags tag FILE."
- (let* (max
- (split (with-temp-buffer
- (insert-file-contents file)
- (prog1
- (split-string (buffer-string) "\n" 'omit-nulls)
- (setq max (line-number-at-pos (point-max))))))
- (progress-reporter (make-progress-reporter "Loading tag file..." 0 max)))
- (cl-loop
- with fname
- with cand
- for i in split for count from 0
- for elm = (unless (string-match "^\x0c" i) ;; "^L"
- (helm-aif (string-match "\177" i) ;; "^?"
- (substring i 0 it)
- i))
- for linum = (when (string-match "[0-9]+,?[0-9]*$" i)
- (car (split-string (match-string 0 i) ",")))
- do (cond ((and elm (string-match "^\\([^,]+\\),[0-9]+$" elm))
- (setq fname (propertize (match-string 1 elm)
- 'face 'helm-etags-file)))
- (elm (setq cand (format "%s:%s:%s" fname linum elm)))
- (t (setq cand nil)))
- when cand do (progn
- (insert (propertize (concat cand "\n") 'linum linum))
- (progress-reporter-update progress-reporter count)))))
-
-(defun helm-etags-init ()
- "Feed `helm-buffer' using `helm-etags-cache' or tag file.
-If no entry in cache, create one."
- (let ((tagfiles (helm-etags-all-tag-files)))
- (when tagfiles
- (with-current-buffer (helm-candidate-buffer 'global)
- (dolist (f tagfiles)
- (helm-aif (gethash f helm-etags-cache)
- ;; An entry is present in cache, insert it.
- (insert it)
- ;; No entry, create a new buffer using content of tag file (slower).
- (helm-etags-create-buffer f)
- ;; Store content of buffer in cache.
- (puthash f (buffer-string) helm-etags-cache)
- ;; Store or set the last modification of tag file.
- (helm-aif (assoc f helm-etags-mtime-alist)
- ;; If an entry exists modify it.
- (setcdr it (helm-etags-mtime f))
- ;; No entry create a new one.
- (add-to-list 'helm-etags-mtime-alist
- (cons f (helm-etags-mtime f))))))))))
-
-(defvar helm-source-etags-select nil
- "Helm source for Etags.")
-
-(defun helm-etags-build-source ()
- (helm-build-in-buffer-source "Etags"
- :header-name 'helm-etags-get-header-name
- :init 'helm-etags-init
- :get-line 'buffer-substring
- :match-part (lambda (candidate)
- ;; Match only the tag part of CANDIDATE
- ;; and not the filename.
- (cl-case helm-etags-match-part-only
- (tag (cl-caddr (helm-grep-split-line candidate)))
- (t candidate)))
- :fuzzy-match helm-etags-fuzzy-match
- :help-message 'helm-etags-help-message
- :keymap helm-etags-map
- :action '(("Go to tag" . (lambda (c)
- (helm-etags-action-goto 'find-file c)))
- ("Go to tag in other window" . (lambda (c)
- (helm-etags-action-goto
- 'find-file-other-window
- c)))
- ("Go to tag in other frame" . (lambda (c)
- (helm-etags-action-goto
- 'find-file-other-frame
- c))))
- :persistent-help "Go to line"
- :persistent-action (lambda (candidate)
- (helm-etags-action-goto 'find-file candidate)
- (helm-highlight-current-line))))
-
-(defcustom helm-etags-fuzzy-match nil
- "Use fuzzy matching in `helm-etags-select'."
- :group 'helm-tags
- :type 'boolean
- :set (lambda (var val)
- (set var val)
- (setq helm-source-etags-select
- (helm-etags-build-source))))
-
-(defvar find-tag-marker-ring)
-
-(defun helm-etags-action-goto (switcher candidate)
- "Helm default action to jump to an etags entry in other window."
- (require 'etags)
- (helm-log-run-hook 'helm-goto-line-before-hook)
- (let* ((split (helm-grep-split-line candidate))
- (fname (cl-loop for tagf being the hash-keys of helm-etags-cache
- for f = (expand-file-name
- (car split) (file-name-directory tagf))
- when (file-exists-p f)
- return f))
- (elm (cl-caddr split))
- (linum (string-to-number (cadr split))))
- (if (null fname)
- (error "file %s not found" fname)
- (ring-insert find-tag-marker-ring (point-marker))
- (funcall switcher fname)
- (helm-goto-line linum t)
- (when (search-forward elm nil t)
- (goto-char (match-beginning 0))))))
-
-(defun helm-etags-mtime (file)
- "Last modification time of etags tag FILE."
- (cadr (nth 5 (file-attributes file))))
-
-(defun helm-etags-file-modified-p (file)
- "Check if tag FILE have been modified in this session.
-If FILE is nil return nil."
- (let ((last-modif (and file
- (assoc-default file helm-etags-mtime-alist))))
- (and last-modif
- (/= last-modif (helm-etags-mtime file)))))
-
-;;;###autoload
-(defun helm-etags-select (reinit)
- "Preconfigured helm for etags.
-If called with a prefix argument REINIT
-or if any of the tag files have been modified, reinitialize cache.
-
-This function aggregates three sources of tag files:
-
- 1) An automatically located file in the parent directories,
- by `helm-etags-get-tag-file'.
- 2) `tags-file-name', which is commonly set by `find-tag' command.
- 3) `tags-table-list' which is commonly set by `visit-tags-table' command."
- (interactive "P")
- (let ((tag-files (helm-etags-all-tag-files))
- (helm-execute-action-at-once-if-one
- helm-etags-execute-action-at-once-if-one)
- (str (if (region-active-p)
- (buffer-substring-no-properties
- (region-beginning) (region-end))
- ;; Use a raw syntax-table to determine tap.
- ;; This may be wrong when calling etags
- ;; with hff from a buffer that use
- ;; a different syntax, but most of the time it
- ;; should be better.
- (with-syntax-table (standard-syntax-table)
- (thing-at-point 'symbol)))))
- (if (cl-notany 'file-exists-p tag-files)
- (message "Error: No tag file found.\
-Create with etags shell command, or visit with `find-tag' or `visit-tags-table'.")
- (cl-loop for k being the hash-keys of helm-etags-cache
- unless (member k tag-files)
- do (remhash k helm-etags-cache))
- (mapc (lambda (f)
- (when (or (equal reinit '(4))
- (and helm-etags-mtime-alist
- (helm-etags-file-modified-p f)))
- (remhash f helm-etags-cache)))
- tag-files)
- (unless helm-source-etags-select
- (setq helm-source-etags-select
- (helm-etags-build-source)))
- (helm :sources 'helm-source-etags-select
- :keymap helm-etags-map
- :default (if helm-etags-fuzzy-match
- str
- (list (concat "\\_<" str "\\_>") str))
- :buffer "*helm etags*"))))
-
-(provide 'helm-tags)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-tags.el ends here
+++ /dev/null
-;;; helm-types.el --- Helm types classes and methods. -*- lexical-binding: t -*-
-
-;; Copyright (C) 2015 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; Author: Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-;; URL: http://github.com/emacs-helm/helm
-
-;; 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/>.
-
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'eieio)
-
-\f
-;; Files
-(defclass helm-type-file (helm-source) ()
- "A class to define helm type file.")
-
-(defmethod helm-source-get-action-from-type ((object helm-type-file))
- (slot-value object 'action))
-
-(defun helm-actions-from-type-file ()
- (let ((source (make-instance 'helm-type-file)))
- (helm--setup-source source)
- (helm-source-get-action-from-type source)))
-
-(defcustom helm-type-file-actions
- (helm-make-actions
- "Find file" 'helm-find-many-files
- "Find file as root" 'helm-find-file-as-root
- "Find file other window" 'helm-find-files-other-window
- "Find file other frame" 'find-file-other-frame
- "Open dired in file's directory" 'helm-open-dired
- "Grep File(s) `C-u recurse'" 'helm-find-files-grep
- "Zgrep File(s) `C-u Recurse'" 'helm-ff-zgrep
- "Pdfgrep File(s)" 'helm-ff-pdfgrep
- "Insert as org link" 'helm-files-insert-as-org-link
- "Checksum File" 'helm-ff-checksum
- "Ediff File" 'helm-find-files-ediff-files
- "Ediff Merge File" 'helm-find-files-ediff-merge-files
- "Etags `M-., C-u reload tag file'" 'helm-ff-etags-select
- "View file" 'view-file
- "Insert file" 'insert-file
- "Add marked files to file-cache" 'helm-ff-cache-add-file
- "Delete file(s)" 'helm-delete-marked-files
- "Copy file(s) `M-C, C-u to follow'" 'helm-find-files-copy
- "Rename file(s) `M-R, C-u to follow'" 'helm-find-files-rename
- "Symlink files(s) `M-S, C-u to follow'" 'helm-find-files-symlink
- "Relsymlink file(s) `C-u to follow'" 'helm-find-files-relsymlink
- "Hardlink file(s) `M-H, C-u to follow'" 'helm-find-files-hardlink
- "Open file externally (C-u to choose)" 'helm-open-file-externally
- "Open file with default tool" 'helm-open-file-with-default-tool
- "Find file in hex dump" 'hexl-find-file)
- "Default actions for type files."
- :group 'helm-files
- :type '(alist :key-type string :value-type function))
-
-(defmethod helm--setup-source :primary ((_source helm-type-file)))
-
-(defmethod helm--setup-source :before ((source helm-type-file))
- (setf (slot-value source 'action) 'helm-type-file-actions)
- (setf (slot-value source 'persistent-help) "Show this file")
- (setf (slot-value source 'action-transformer)
- '(helm-transform-file-load-el
- helm-transform-file-browse-url
- helm-transform-file-cache))
- (setf (slot-value source 'candidate-transformer)
- '(helm-skip-boring-files
- helm-highlight-files
- helm-w32-pathname-transformer))
- (setf (slot-value source 'help-message) 'helm-generic-file-help-message)
- (setf (slot-value source 'mode-line) (list "File(s)" helm-mode-line-string))
- (setf (slot-value source 'keymap) helm-generic-files-map))
-
-\f
-;; Bookmarks
-(defclass helm-type-bookmark (helm-source) ()
- "A class to define type bookmarks.")
-
-(defcustom helm-type-bookmark-actions
- (helm-make-actions
- "Jump to bookmark" 'helm-bookmark-jump
- "Jump to BM other window" 'helm-bookmark-jump-other-window
- "Bookmark edit annotation" 'bookmark-edit-annotation
- "Bookmark show annotation" 'bookmark-show-annotation
- "Delete bookmark(s)" 'helm-delete-marked-bookmarks
- "Edit Bookmark" 'helm-bookmark-edit-bookmark
- "Rename bookmark" 'helm-bookmark-rename
- "Relocate bookmark" 'bookmark-relocate)
- "Default actions for type bookmarks."
- :group 'helm-bookmark
- :type '(alist :key-type string
- :value-type function))
-
-(defmethod helm-source-get-action-from-type ((object helm-type-bookmark))
- (slot-value object 'action))
-
-(defmethod helm--setup-source :primary ((_source helm-type-bookmark)))
-
-(defmethod helm--setup-source :before ((source helm-type-bookmark))
- (setf (slot-value source 'action) 'helm-type-bookmark-actions)
- (setf (slot-value source 'keymap) helm-bookmark-map)
- (setf (slot-value source 'mode-line) (list "Bookmark(s)" helm-mode-line-string))
- (setf (slot-value source 'help-message) 'helm-bookmark-help-message)
- (setf (slot-value source 'migemo) t))
-
-\f
-;; Buffers
-(defclass helm-type-buffer (helm-source) ()
- "A class to define type buffer.")
-
-(defcustom helm-type-buffer-actions
- (helm-make-actions
- "Switch to buffer(s)" 'helm-switch-to-buffers
- (lambda () (and (locate-library "popwin")
- "Switch to buffer in popup window"))
- 'popwin:popup-buffer
- "Switch to buffer(s) other window `C-c o'"
- 'helm-switch-to-buffers-other-window
- "Switch to buffer other frame `C-c C-o'"
- 'switch-to-buffer-other-frame
- (lambda () (and (locate-library "elscreen")
- "Display buffer in Elscreen"))
- 'helm-find-buffer-on-elscreen
- "Browse project from buffer"
- 'helm-buffers-browse-project
- "Query replace regexp `C-M-%'"
- 'helm-buffer-query-replace-regexp
- "Query replace `M-%'" 'helm-buffer-query-replace
- "View buffer" 'view-buffer
- "Display buffer" 'display-buffer
- "Grep buffers `M-g s' (C-u grep all buffers)"
- 'helm-zgrep-buffers
- "Multi occur buffer(s) `C-s'" 'helm-multi-occur-as-action
- "Revert buffer(s) `M-U'" 'helm-revert-marked-buffers
- "Insert buffer" 'insert-buffer
- "Kill buffer(s) `M-D'" 'helm-kill-marked-buffers
- "Diff with file `C-='" 'diff-buffer-with-file
- "Ediff Marked buffers `C-c ='" 'helm-ediff-marked-buffers
- "Ediff Merge marked buffers `M-='"
- (lambda (candidate)
- (helm-ediff-marked-buffers candidate t)))
- "Default actions for type buffers."
- :group 'helm-buffers
- :type '(alist :key-type string :value-type function))
-
-(defmethod helm-source-get-action-from-type ((object helm-type-buffer))
- (slot-value object 'action))
-
-(defmethod helm--setup-source :primary ((_source helm-type-buffer)))
-
-(defmethod helm--setup-source :before ((source helm-type-buffer))
- (setf (slot-value source 'action) 'helm-type-buffer-actions)
- (setf (slot-value source 'persistent-help) "Show this buffer")
- (setf (slot-value source 'mode-line) (list "Buffer(s)" helm-mode-line-string))
- (setf (slot-value source 'filtered-candidate-transformer)
- '(helm-skip-boring-buffers
- helm-buffers-sort-transformer
- helm-highlight-buffers)))
-\f
-;; Functions
-(defclass helm-type-function (helm-source) ()
- "A class to define helm type function.")
-
-(defcustom helm-type-function-actions
- (helm-make-actions
- "Describe command" 'describe-function
- "Add command to kill ring" 'helm-kill-new
- "Go to command's definition" 'find-function
- "Debug on entry" 'debug-on-entry
- "Cancel debug on entry" 'cancel-debug-on-entry
- "Trace function" 'trace-function
- "Trace function (background)" 'trace-function-background
- "Untrace function" 'untrace-function)
- "Default actions for type functions."
- :group 'helm-elisp
- :type '(alist :key-type string :value-type function))
-
-(defmethod helm-source-get-action-from-type ((object helm-type-function))
- (slot-value object 'action))
-
-(defun helm-actions-from-type-function ()
- (let ((source (make-instance 'helm-type-function)))
- (helm--setup-source source)
- (helm-source-get-action-from-type source)))
-
-(defmethod helm--setup-source :primary ((_source helm-type-function)))
-
-(defmethod helm--setup-source :before ((source helm-type-function))
- (setf (slot-value source 'action) 'helm-type-function-actions)
- (setf (slot-value source 'action-transformer)
- 'helm-transform-function-call-interactively)
- (setf (slot-value source 'candidate-transformer)
- 'helm-mark-interactive-functions)
- (setf (slot-value source 'coerce) 'helm-symbolify))
-
-\f
-;; Commands
-(defclass helm-type-command (helm-source) ()
- "A class to define helm type command.")
-
-(defun helm-actions-from-type-command ()
- (let ((source (make-instance 'helm-type-command)))
- (helm--setup-source source)
- (helm-source-get-action-from-type source)))
-
-(defcustom helm-type-command-actions
- (append (helm-make-actions
- "Call interactively" 'helm-call-interactively)
- (helm-actions-from-type-function))
- "Default actions for type command."
- :group 'helm-command
- :type '(alist :key-type string :value-type function))
-
-(defmethod helm--setup-source :primary ((_source helm-type-command)))
-
-(defmethod helm--setup-source :before ((source helm-type-command))
- (setf (slot-value source 'action) 'helm-type-command-actions)
- (setf (slot-value source 'coerce) 'helm-symbolify)
- (setf (slot-value source 'persistent-action) 'describe-function))
-
-;; Timers
-(defclass helm-type-timers (helm-source) ()
- "A class to define helm type timers.")
-
-(defcustom helm-type-timers-actions
- '(("Cancel Timer" . (lambda (_timer)
- (let ((mkd (helm-marked-candidates)))
- (cl-loop for timer in mkd
- do (cancel-timer timer)))))
- ("Describe Function" . (lambda (tm)
- (describe-function (timer--function tm))))
- ("Find Function" . (lambda (tm)
- (helm-aif (timer--function tm)
- (if (byte-code-function-p it)
- (message "Can't find anonymous function `%s'" it)
- (find-function it))))))
- "Default actions for type timers."
- :group 'helm-elisp
- :type '(alist :key-type string :value-type function))
-
-(defmethod helm--setup-source :primary ((_source helm-type-timers)))
-
-(defmethod helm--setup-source :before ((source helm-type-timers))
- (setf (slot-value source 'action) 'helm-type-timers-actions)
- (setf (slot-value source 'persistent-action)
- (lambda (tm)
- (describe-function (timer--function tm))))
- (setf (slot-value source 'persistent-help) "Describe Function"))
-\f
-;; Builders.
-(defun helm-build-type-file ()
- (helm-make-type 'helm-type-file))
-
-(defun helm-build-type-function ()
- (helm-make-type 'helm-type-function))
-
-(defun helm-build-type-command ()
- (helm-make-type 'helm-type-command))
-
-(provide 'helm-types)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-types.el ends here
+++ /dev/null
-;;; helm-utils.el --- Utilities Functions for helm. -*- lexical-binding: t -*-
-
-;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; 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/>.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'helm)
-(require 'helm-help)
-(require 'compile) ; Fixme: Is this needed?
-(require 'dired)
-
-(declare-function helm-find-files-1 "helm-files.el" (fname &optional preselect))
-(declare-function popup-tip "ext:popup")
-(defvar winner-boring-buffers)
-
-\f
-(defgroup helm-utils nil
- "Utilities routines for Helm."
- :group 'helm)
-
-(defcustom helm-su-or-sudo "sudo"
- "What command to use for root access."
- :type 'string
- :group 'helm-utils)
-
-(defcustom helm-default-kbsize 1024.0
- "Default Kbsize to use for showing files size.
-It is a float, usually 1024.0 but could be 1000.0 on some systems."
- :group 'helm-utils
- :type 'float)
-
-(define-obsolete-variable-alias
- 'helm-highlight-number-lines-around-point
- 'helm-highlight-matches-around-point-max-lines
- "20160119")
-
-(defcustom helm-highlight-matches-around-point-max-lines 15
- "Number of lines around point where matched items are highlighted."
- :group 'helm-utils
- :type 'integer)
-
-(defcustom helm-buffers-to-resize-on-pa nil
- "A list of helm buffers where the helm-window should be reduced on persistent actions."
- :group 'helm-utils
- :type '(repeat (choice string)))
-
-(defcustom helm-resize-on-pa-text-height 12
- "The size of the helm-window when resizing on persistent action."
- :group 'helm-utils
- :type 'integer)
-
-(defcustom helm-sources-using-help-echo-popup '("Moccur" "Imenu in all buffers"
- "Ack-Grep" "AG" "Gid" "Git-Grep")
- "Show the buffer name or the filename in a popup at selection."
- :group 'helm-utils
- :type '(repeat (choice string)))
-
-(defcustom helm-html-decode-entities-function #'helm-html-decode-entities-string
- "Function used to decode html entities in html bookmarks.
-Helm comes by default with `helm-html-decode-entities-string', if you need something
-more sophisticated you can use `w3m-decode-entities-string' if available.
-
-In emacs itself org-entities seems broken and `xml-substitute-numeric-entities'
-supports only numeric entities."
- :group 'helm-utils
- :type 'function)
-
-\f
-(defvar helm-goto-line-before-hook '(helm-save-current-pos-to-mark-ring)
- "Run before jumping to line.
-This hook run when jumping from `helm-goto-line', `helm-etags-default-action',
-and `helm-imenu-default-action'.
-This allow you to retrieve a previous position after using the different helm
-tools for searching (etags, grep, gid, (m)occur etc...).
-By default positions are added to `mark-ring' you can also add to register
-by using instead (or adding) `helm-save-pos-to-register-before-jump'.
-In this case last position is added to the register
-`helm-save-pos-before-jump-register'.")
-
-(defvar helm-save-pos-before-jump-register ?_
- "The register where `helm-save-pos-to-register-before-jump' save position.")
-
-(defconst helm-html-entities-alist
- '((""" . 34) ;; "
- (">" . 62) ;; >
- ("<" . 60) ;; <
- ("&" . 38) ;; &
- ("€" . 8364) ;; €
- ("Ÿ" . 89) ;; Y
- ("¡" . 161) ;; ¡
- ("¢" . 162) ;; ¢
- ("£" . 163) ;; £
- ("¤" . 164) ;; ¤
- ("¥" . 165) ;; ¥
- ("¦" . 166) ;; ¦
- ("§" . 167) ;; §
- ("¨" . 32) ;; SPC
- ("©" . 169) ;; ©
- ("ª" . 97) ;; a
- ("«" . 171) ;; «
- ("¬" . 172) ;; ¬
- ("&masr;" . 174) ;; ®
- ("°" . 176) ;; °
- ("±" . 177) ;; ±
- ("²" . 50) ;; 2
- ("³" . 51) ;; 3
- ("´" . 39) ;; '
- ("µ" . 956) ;; μ
- ("¶" . 182) ;; ¶
- ("·" . 183) ;; ·
- ("¸" . 32) ;; SPC
- ("¹" . 49) ;; 1
- ("º" . 111) ;; o
- ("»" . 187) ;; »
- ("¼" . 49) ;; 1
- ("½" . 49) ;; 1
- ("¾" . 51) ;; 3
- ("¿" . 191) ;; ¿
- ("À" . 192) ;; À
- ("Á" . 193) ;; Á
- ("Â" . 194) ;; Â
- ("Ã" . 195) ;; Ã
- ("Ä" . 196) ;; Ä
- ("Å" . 197) ;; Å
- ("&Aelig" . 198) ;; Æ
- ("Ç" . 199) ;; Ç
- ("È" . 200) ;; È
- ("É" . 201) ;; É
- ("Ê" . 202) ;; Ê
- ("Ë" . 203) ;; Ë
- ("Ì" . 204) ;; Ì
- ("Í" . 205) ;; Í
- ("Î" . 206) ;; Î
- ("Ï" . 207) ;; Ï
- ("ð" . 208) ;; Ð
- ("Ñ" . 209) ;; Ñ
- ("Ò" . 210) ;; Ò
- ("Ó" . 211) ;; Ó
- ("Ô" . 212) ;; Ô
- ("Õ" . 213) ;; Õ
- ("Ö" . 214) ;; Ö
- ("×" . 215) ;; ×
- ("Ø" . 216) ;; Ø
- ("Ù" . 217) ;; Ù
- ("Ú" . 218) ;; Ú
- ("Û" . 219) ;; Û
- ("Ü" . 220) ;; Ü
- ("Ý" . 221) ;; Ý
- ("þ" . 222) ;; Þ
- ("ß" . 223) ;; ß
- ("à" . 224) ;; à
- ("á" . 225) ;; á
- ("â" . 226) ;; â
- ("ã" . 227) ;; ã
- ("ä" . 228) ;; ä
- ("å" . 229) ;; å
- ("æ" . 230) ;; æ
- ("ç" . 231) ;; ç
- ("è" . 232) ;; è
- ("é" . 233) ;; é
- ("ê" . 234) ;; ê
- ("ë" . 235) ;; ë
- ("ì" . 236) ;; ì
- ("í" . 237) ;; í
- ("î" . 238) ;; î
- ("ï" . 239) ;; ï
- ("ð" . 240) ;; ð
- ("ñ" . 241) ;; ñ
- ("ò" . 242) ;; ò
- ("ó" . 243) ;; ó
- ("ô" . 244) ;; ô
- ("õ" . 245) ;; õ
- ("ö" . 246) ;; ö
- ("÷" . 247) ;; ÷
- ("ø" . 248) ;; ø
- ("ù" . 249) ;; ù
- ("ú" . 250) ;; ú
- ("û" . 251) ;; û
- ("ü" . 252) ;; ü
- ("ý" . 253) ;; ý
- ("þ" . 254) ;; þ
- ("ÿ" . 255) ;; ÿ
- ("®" . 174) ;; ®
- ("­" . 173)) ;;
-
- "Table of html character entities and values.")
-\f
-;;; Faces.
-;;
-(defface helm-selection-line
- '((t (:inherit highlight :distant-foreground "black")))
- "Face used in the `helm-current-buffer' when jumping to candidate."
- :group 'helm-faces)
-
-(defface helm-match-item
- '((t (:inherit isearch)))
- "Face used to highlight item matched in a selected line."
- :group 'helm-faces)
-
-\f
-;; CUA workaround
-(defadvice cua-delete-region (around helm-avoid-cua activate)
- (ignore-errors ad-do-it))
-
-(defadvice copy-region-as-kill (around helm-avoid-cua activate)
- (if cua-mode
- (ignore-errors ad-do-it)
- ad-do-it))
-
-\f
-;;; Utils functions
-;;
-;;
-(defun helm-switch-to-buffers (buffer-or-name &optional other-window)
- "Switch to buffer BUFFER-OR-NAME.
-If more than one buffer marked switch to these buffers in separate windows.
-If OTHER-WINDOW is specified keep current-buffer and switch to others buffers
-in separate windows."
- (let* ((mkds (helm-marked-candidates))
- (size (/ (window-height) (length mkds))))
- (or (<= window-min-height size)
- (error "Too many buffers to visit simultaneously."))
- (helm-aif (cdr mkds)
- (progn
- (if other-window
- (switch-to-buffer-other-window (car mkds))
- (switch-to-buffer (car mkds)))
- (save-selected-window
- (cl-loop for b in it
- do (progn
- (select-window (split-window))
- (switch-to-buffer b)))))
- (if other-window
- (switch-to-buffer-other-window buffer-or-name)
- (switch-to-buffer buffer-or-name)))))
-
-(defun helm-switch-to-buffers-other-window (buffer-or-name)
- "switch to buffer BUFFER-OR-NAME in other window.
-See `helm-switch-to-buffers' for switching to marked buffers."
- (helm-switch-to-buffers buffer-or-name t))
-
-(cl-defun helm-current-buffer-narrowed-p (&optional
- (buffer helm-current-buffer))
- "Check if BUFFER is narrowed.
-Default is `helm-current-buffer'."
- (with-current-buffer buffer
- (let ((beg (point-min))
- (end (point-max))
- (total (buffer-size)))
- (or (/= beg 1) (/= end (1+ total))))))
-
-(defun helm-goto-char (loc)
- "Go to char, revealing if necessary."
- (goto-char loc)
- (when (or (eq major-mode 'org-mode)
- (and (boundp 'outline-minor-mode)
- outline-minor-mode))
- (require 'org) ; On some old Emacs versions org may not be loaded.
- (org-reveal)))
-
-(defun helm-goto-line (lineno &optional noanim)
- "Goto LINENO opening only outline headline if needed.
-Animation is used unless NOANIM is non--nil."
- (helm-log-run-hook 'helm-goto-line-before-hook)
- (goto-char (point-min))
- (helm-goto-char (point-at-bol lineno))
- (unless noanim
- (helm-highlight-current-line nil nil nil nil 'pulse)))
-
-(defun helm-save-pos-to-register-before-jump ()
- "Save current buffer position to `helm-save-pos-before-jump-register'.
-To use this add it to `helm-goto-line-before-hook'."
- (with-helm-current-buffer
- (unless helm-in-persistent-action
- (point-to-register helm-save-pos-before-jump-register))))
-
-(defun helm-save-current-pos-to-mark-ring ()
- "Save current buffer position to mark ring.
-To use this add it to `helm-goto-line-before-hook'."
- (with-helm-current-buffer
- (unless helm-in-persistent-action
- (set-marker (mark-marker) (point))
- (push-mark (point) 'nomsg))))
-
-(defun helm-show-all-in-this-source-only (arg)
- "Show only current source of this helm session with all its candidates.
-With a numeric prefix arg show only the ARG number of candidates."
- (interactive "p")
- (with-helm-alive-p
- (with-helm-window
- (with-helm-default-directory (helm-default-directory)
- (let ((helm-candidate-number-limit (and (> arg 1) arg)))
- (helm-set-source-filter
- (list (assoc-default 'name (helm-get-current-source)))))))))
-(put 'helm-show-all-in-this-source-only 'helm-only t)
-
-(defun helm-display-all-sources ()
- "Display all sources previously hidden by `helm-set-source-filter'."
- (interactive)
- (with-helm-alive-p
- (helm-set-source-filter nil)))
-(put 'helm-display-all-sources 'helm-only t)
-
-(defun helm-displaying-source-names ()
- "Return the list of sources name for this helm session."
- (with-current-buffer helm-buffer
- (goto-char (point-min))
- (cl-loop with pos
- while (setq pos (next-single-property-change (point) 'helm-header))
- do (goto-char pos)
- collect (buffer-substring-no-properties (point-at-bol)(point-at-eol))
- do (forward-line 1))))
-
-(defun helm-handle-winner-boring-buffers ()
- "Add `helm-buffer' to `winner-boring-buffers' when quitting/exiting helm.
-Add this function to `helm-cleanup-hook' when you don't want to see helm buffers
-after running winner-undo/redo."
- (require 'winner)
- (cl-pushnew helm-buffer winner-boring-buffers :test 'equal))
-(add-hook 'helm-cleanup-hook #'helm-handle-winner-boring-buffers)
-
-(defun helm-quit-and-find-file ()
- "Drop into `helm-find-files' from `helm'.
-If current selection is a buffer or a file, `helm-find-files'
-from its directory."
- (interactive)
- (with-helm-alive-p
- (require 'helm-grep)
- (helm-run-after-exit
- (lambda (f)
- ;; Ensure specifics `helm-execute-action-at-once-if-one'
- ;; fns don't run here.
- (let (helm-execute-action-at-once-if-one)
- (if (file-exists-p f)
- (helm-find-files-1 (file-name-directory f)
- (concat
- "^"
- (regexp-quote
- (if helm-ff-transformer-show-only-basename
- (helm-basename f) f))))
- (helm-find-files-1 f))))
- (let* ((sel (helm-get-selection))
- (marker (if (consp sel) (markerp (cdr sel))))
- (grep-line (and (stringp sel)
- (helm-grep-split-line sel)))
- (bmk-name (and (stringp sel)
- (not grep-line)
- (replace-regexp-in-string "\\`\\*" "" sel)))
- (bmk (and bmk-name (assoc bmk-name bookmark-alist)))
- (buf (helm-aif (and (bufferp sel) (get-buffer sel))
- (buffer-name it)))
- (default-preselection (or (buffer-file-name helm-current-buffer)
- default-directory)))
- (cond
- ;; Buffer.
- (buf (or (buffer-file-name sel)
- (car (rassoc buf dired-buffers))
- (and (with-current-buffer buf
- (eq major-mode 'org-agenda-mode))
- org-directory
- (expand-file-name org-directory))
- (with-current-buffer buf default-directory)))
- ;; imenu (marker).
- (marker
- (or (buffer-file-name (marker-buffer (cdr sel)))
- default-preselection))
- ;; Bookmark.
- (bmk (helm-aif (bookmark-get-filename bmk)
- (if (and ffap-url-regexp
- (string-match ffap-url-regexp it))
- it (expand-file-name it))
- default-directory))
- ((or (file-remote-p sel)
- (file-exists-p sel))
- (expand-file-name sel))
- ;; Grep.
- ((and grep-line (file-exists-p (car grep-line)))
- (expand-file-name (car grep-line)))
- ;; Occur.
- (grep-line
- (with-current-buffer (get-buffer (car grep-line))
- (or (buffer-file-name) default-directory)))
- ;; Url.
- ((and ffap-url-regexp (string-match ffap-url-regexp sel)) sel)
- ;; Default.
- (t default-preselection))))))
-(put 'helm-quit-and-find-file 'helm-only t)
-
-(defun helm-generic-sort-fn (s1 s2)
- "Sort predicate function for helm candidates.
-Args S1 and S2 can be single or \(display . real\) candidates,
-that is sorting is done against real value of candidate."
- (let* ((pattern (regexp-quote helm-pattern))
- (reg1 (concat "\\_<" pattern "\\_>"))
- (reg2 (concat "\\_<" pattern))
- (reg3 helm-pattern)
- (split (split-string pattern))
- (str1 (if (consp s1) (cdr s1) s1))
- (str2 (if (consp s2) (cdr s2) s2))
- (score (lambda (str r1 r2 r3 lst)
- (+ (if (string-match (concat "\\`" pattern) str) 1 0)
- (cond ((string-match r1 str) 5)
- ((and (string-match " " pattern)
- (string-match (concat "\\_<" (car lst)) str)
- (cl-loop for r in (cdr lst)
- always (string-match r str))) 4)
- ((and (string-match " " pattern)
- (cl-loop for r in lst always (string-match r str))) 3)
- ((string-match r2 str) 2)
- ((string-match r3 str) 1)
- (t 0)))))
- (sc1 (funcall score str1 reg1 reg2 reg3 split))
- (sc2 (funcall score str2 reg1 reg2 reg3 split)))
- (cond ((or (zerop (string-width pattern))
- (and (zerop sc1) (zerop sc2)))
- (string-lessp str1 str2))
- ((= sc1 sc2)
- (< (length str1) (length str2)))
- (t (> sc1 sc2)))))
-
-(defun helm-ff-get-host-from-tramp-invalid-fname (fname)
- "Extract hostname from an incomplete tramp file name.
-Return nil on valid file name remote or not."
- (let* ((str (helm-basename fname))
- (split (split-string str ":"))
- (meth (car (member (car split) (mapcar 'car tramp-methods)))))
- (when (and meth (<= (length split) 2))
- (cadr split))))
-
-(cl-defun helm-file-human-size (size &optional (kbsize helm-default-kbsize))
- "Return a string showing SIZE of a file in human readable form.
-SIZE can be an integer or a float depending it's value.
-`file-attributes' will take care of that to avoid overflow error.
-KBSIZE is a floating point number, defaulting to `helm-default-kbsize'."
- (cl-loop with result = (cons "B" size)
- for i in '("k" "M" "G" "T" "P" "E" "Z" "Y")
- while (>= (cdr result) kbsize)
- do (setq result (cons i (/ (cdr result) kbsize)))
- finally return
- (pcase (car result)
- (`"B" (format "%s" size))
- (suffix (format "%.1f%s" (cdr result) suffix)))))
-
-(cl-defun helm-file-attributes
- (file &key type links uid gid access-time modif-time
- status size mode gid-change inode device-num dired human-size
- mode-type mode-owner mode-group mode-other (string t))
- "Return `file-attributes' elements of FILE separately according to key value.
-Availables keys are:
-- TYPE: Same as nth 0 `files-attributes' if STRING is nil
- otherwise return either symlink, directory or file (default).
-- LINKS: See nth 1 `files-attributes'.
-- UID: See nth 2 `files-attributes'.
-- GID: See nth 3 `files-attributes'.
-- ACCESS-TIME: See nth 4 `files-attributes', however format time
- when STRING is non--nil (the default).
-- MODIF-TIME: See nth 5 `files-attributes', same as above.
-- STATUS: See nth 6 `files-attributes', same as above.
-- SIZE: See nth 7 `files-attributes'.
-- MODE: See nth 8 `files-attributes'.
-- GID-CHANGE: See nth 9 `files-attributes'.
-- INODE: See nth 10 `files-attributes'.
-- DEVICE-NUM: See nth 11 `files-attributes'.
-- DIRED: A line similar to what 'ls -l' return.
-- HUMAN-SIZE: The size in human form, see `helm-file-human-size'.
-- MODE-TYPE, mode-owner,mode-group, mode-other: Split what
- nth 7 `files-attributes' return in four categories.
-- STRING: When non--nil (default) `helm-file-attributes' return
- more friendly values.
-If you want the same behavior as `files-attributes' ,
-\(but with return values in proplist\) use a nil value for STRING.
-However when STRING is non--nil, time and type value are different from what
-you have in `file-attributes'."
- (let* ((all (cl-destructuring-bind
- (type links uid gid access-time modif-time
- status size mode gid-change inode device-num)
- (file-attributes file string)
- (list :type (if string
- (cond ((stringp type) "symlink") ; fname
- (type "directory") ; t
- (t "file")) ; nil
- type)
- :links links
- :uid uid
- :gid gid
- :access-time (if string
- (format-time-string
- "%Y-%m-%d %R" access-time)
- access-time)
- :modif-time (if string
- (format-time-string
- "%Y-%m-%d %R" modif-time)
- modif-time)
- :status (if string
- (format-time-string
- "%Y-%m-%d %R" status)
- status)
- :size size
- :mode mode
- :gid-change gid-change
- :inode inode
- :device-num device-num)))
- (modes (helm-split-mode-file-attributes (cl-getf all :mode))))
- (cond (type (cl-getf all :type))
- (links (cl-getf all :links))
- (uid (cl-getf all :uid))
- (gid (cl-getf all :gid))
- (access-time (cl-getf all :access-time))
- (modif-time (cl-getf all :modif-time))
- (status (cl-getf all :status))
- (size (cl-getf all :size))
- (mode (cl-getf all :mode))
- (gid-change (cl-getf all :gid-change))
- (inode (cl-getf all :inode))
- (device-num (cl-getf all :device-num))
- (dired (concat
- (helm-split-mode-file-attributes
- (cl-getf all :mode) t) " "
- (number-to-string (cl-getf all :links)) " "
- (cl-getf all :uid) ":"
- (cl-getf all :gid) " "
- (if human-size
- (helm-file-human-size (cl-getf all :size))
- (int-to-string (cl-getf all :size))) " "
- (cl-getf all :modif-time)))
- (human-size (helm-file-human-size (cl-getf all :size)))
- (mode-type (cl-getf modes :mode-type))
- (mode-owner (cl-getf modes :user))
- (mode-group (cl-getf modes :group))
- (mode-other (cl-getf modes :other))
- (t (append all modes)))))
-
-(defun helm-split-mode-file-attributes (str &optional string)
- "Split mode file attributes STR into a proplist.
-If STRING is non--nil return instead a space separated string."
- (cl-loop with type = (substring str 0 1)
- with cdr = (substring str 1)
- for i across cdr
- for count from 1
- if (<= count 3)
- concat (string i) into user
- if (and (> count 3) (<= count 6))
- concat (string i) into group
- if (and (> count 6) (<= count 9))
- concat (string i) into other
- finally return
- (if string
- (mapconcat 'identity (list type user group other) " ")
- (list :mode-type type :user user :group group :other other))))
-
-(defmacro with-helm-display-marked-candidates (buffer-or-name candidates &rest body)
- (declare (indent 0) (debug t))
- (helm-with-gensyms (buffer window)
- `(let* ((,buffer (temp-buffer-window-setup ,buffer-or-name))
- (helm-always-two-windows t)
- (helm-split-window-default-side
- (if (eq helm-split-window-default-side 'same)
- 'below helm-split-window-default-side))
- helm-split-window-in-side-p
- helm-reuse-last-window-split-state
- ,window)
- (with-current-buffer ,buffer
- (dired-format-columns-of-files ,candidates))
- (unwind-protect
- (with-selected-window
- (setq ,window (temp-buffer-window-show
- ,buffer
- '(display-buffer-below-selected
- (window-height . fit-window-to-buffer))))
- (progn ,@body))
- (quit-window 'kill ,window)))))
-
-;;; Persistent Action Helpers
-;;
-;;
-;; Internal
-(defvar helm-match-line-overlay nil)
-(defvar helm--match-item-overlays nil)
-
-(defun helm-highlight-current-line (&optional start end buf face pulse)
- "Highlight and underline current position"
- (let* ((start (or start (line-beginning-position)))
- (end (or end (1+ (line-end-position))))
- (start-match (if (or (null helm-highlight-matches-around-point-max-lines)
- (zerop helm-highlight-matches-around-point-max-lines))
- start
- (save-excursion
- (forward-line
- (- helm-highlight-matches-around-point-max-lines))
- (point-at-bol))))
- (end-match (if (or (null helm-highlight-matches-around-point-max-lines)
- (zerop helm-highlight-matches-around-point-max-lines))
- end
- (save-excursion
- (forward-line
- helm-highlight-matches-around-point-max-lines)
- (point-at-eol))))
- (args (list start end buf)))
- (if (not helm-match-line-overlay)
- (setq helm-match-line-overlay (apply 'make-overlay args))
- (apply 'move-overlay helm-match-line-overlay args))
- (overlay-put helm-match-line-overlay
- 'face (or face 'helm-selection-line))
- (catch 'empty-line
- (cl-loop with ov
- for r in (helm-remove-if-match
- "\\`!" (split-string helm-input))
- do (save-excursion
- (goto-char start-match)
- (while (condition-case _err
- (if helm-migemo-mode
- (helm-mm-migemo-forward r end-match t)
- (re-search-forward r end-match t))
- (invalid-regexp nil))
- (let ((s (match-beginning 0))
- (e (match-end 0)))
- (if (= s e)
- (throw 'empty-line nil)
- (push (setq ov (make-overlay s e))
- helm--match-item-overlays)
- (overlay-put ov 'face 'helm-match-item)
- (overlay-put ov 'priority 1)))))))
- (recenter)
- (when pulse
- (sit-for 0.3)
- (helm-match-line-cleanup))))
-
-(defun helm-match-line-cleanup ()
- (when helm-match-line-overlay
- (delete-overlay helm-match-line-overlay)
- (setq helm-match-line-overlay nil))
- (when helm--match-item-overlays
- (mapc 'delete-overlay helm--match-item-overlays)))
-
-(defun helm-match-line-update ()
- (when helm-match-line-overlay
- (delete-overlay helm-match-line-overlay)
- (helm-highlight-current-line)))
-
-(defun helm-persistent-autoresize-hook ()
- (when (and helm-buffers-to-resize-on-pa
- (member helm-buffer helm-buffers-to-resize-on-pa)
- (eq helm-split-window-state 'vertical))
- (set-window-text-height (helm-window) helm-resize-on-pa-text-height)))
-
-(add-hook 'helm-after-persistent-action-hook 'helm-persistent-autoresize-hook)
-(add-hook 'helm-cleanup-hook 'helm-match-line-cleanup)
-(add-hook 'helm-after-persistent-action-hook 'helm-match-line-update)
-
-;;; Popup buffer-name or filename in grep/moccur/imenu-all.
-;;
-(defvar helm--show-help-echo-timer nil)
-
-(defun helm-cancel-help-echo-timer ()
- (when helm--show-help-echo-timer
- (cancel-timer helm--show-help-echo-timer)
- (setq helm--show-help-echo-timer nil)))
-
-(defun helm-show-help-echo ()
- (when helm--show-help-echo-timer
- (cancel-timer helm--show-help-echo-timer)
- (setq helm--show-help-echo-timer nil))
- (when (and helm-alive-p
- (member (assoc-default 'name (helm-get-current-source))
- helm-sources-using-help-echo-popup))
- (setq helm--show-help-echo-timer
- (run-with-idle-timer
- 1 nil
- (lambda ()
- (with-helm-window
- (helm-aif (get-text-property (point-at-bol) 'help-echo)
- (popup-tip (concat " " (abbreviate-file-name it))
- :around nil
- :point (save-excursion
- (end-of-visual-line) (point))))))))))
-
-;;;###autoload
-(define-minor-mode helm-popup-tip-mode
- "Show help-echo informations in a popup tip at end of line."
- :global t
- (require 'popup)
- (if helm-popup-tip-mode
- (progn
- (add-hook 'helm-update-hook 'helm-show-help-echo) ; Needed for async sources.
- (add-hook 'helm-move-selection-after-hook 'helm-show-help-echo)
- (add-hook 'helm-cleanup-hook 'helm-cancel-help-echo-timer))
- (remove-hook 'helm-update-hook 'helm-show-help-echo)
- (remove-hook 'helm-move-selection-after-hook 'helm-show-help-echo)
- (remove-hook 'helm-cleanup-hook 'helm-cancel-help-echo-timer)))
-
-(defun helm-open-file-with-default-tool (file)
- "Open FILE with the default tool on this platform."
- (let (process-connection-type)
- (if (eq system-type 'windows-nt)
- (helm-w32-shell-execute-open-file file)
- (start-process "helm-open-file-with-default-tool"
- nil
- (cond ((eq system-type 'gnu/linux)
- "xdg-open")
- ((or (eq system-type 'darwin) ;; Mac OS X
- (eq system-type 'macos)) ;; Mac OS 9
- "open"))
- file))))
-
-(defun helm-open-dired (file)
- "Opens a dired buffer in FILE's directory. If FILE is a
-directory, open this directory."
- (if (file-directory-p file)
- (dired file)
- (dired (file-name-directory file))
- (dired-goto-file file)))
-
-(defun helm-require-or-error (feature function)
- (or (require feature nil t)
- (error "Need %s to use `%s'." feature function)))
-
-(defun helm-find-file-as-root (candidate)
- (let* ((buf (helm-basename candidate))
- (host (file-remote-p candidate 'host))
- (remote-path (format "/%s:%s:%s"
- helm-su-or-sudo
- (or host "")
- (expand-file-name
- (if host
- (file-remote-p candidate 'localname)
- candidate))))
- non-essential)
- (if (buffer-live-p (get-buffer buf))
- (progn
- (set-buffer buf)
- (find-alternate-file remote-path))
- (find-file remote-path))))
-
-(defun helm-find-many-files (_ignore)
- (let ((helm--reading-passwd-or-string t))
- (mapc 'find-file (helm-marked-candidates))))
-
-(defun helm-read-repeat-string (prompt &optional count)
- "Prompt as many time PROMPT is not empty.
-If COUNT is non--nil add a number after each prompt."
- (cl-loop with elm
- while (not (string= elm ""))
- for n from 1
- do (when count
- (setq prompt (concat prompt (int-to-string n) ": ")))
- collect (setq elm (helm-read-string prompt)) into lis
- finally return (remove "" lis)))
-
-(defun helm-html-bookmarks-to-alist (file url-regexp bmk-regexp)
- "Parse html bookmark FILE and return an alist with (title . url) as elements."
- (let (bookmarks-alist url title)
- (with-temp-buffer
- (insert-file-contents file)
- (goto-char (point-min))
- (while (re-search-forward "href=\\|^ *<DT><A HREF=" nil t)
- (forward-line 0)
- (when (re-search-forward url-regexp nil t)
- (setq url (match-string 0)))
- (when (re-search-forward bmk-regexp nil t)
- (setq title (funcall helm-html-decode-entities-function
- (match-string 1))))
- (push (cons title url) bookmarks-alist)
- (forward-line)))
- (nreverse bookmarks-alist)))
-
-(defun helm-html-entity-to-string (entity)
- "Replace an html ENTITY by its string value.
-When unable to decode ENTITY returns nil."
- (helm-aif (assoc entity helm-html-entities-alist)
- (string (cdr it))
- (save-match-data
- (when (string-match "[0-9]+" entity)
- (string (string-to-number (match-string 0 entity)))))))
-
-(defun helm-html-decode-entities-string (str)
- "Decode entities in the string STR."
- (save-match-data
- (with-temp-buffer
- (insert str)
- (goto-char (point-min))
- (while (re-search-forward "&#?\\([^;]*\\);" nil t)
- (helm-aif (helm-html-entity-to-string (match-string 0))
- (replace-match it)))
- (buffer-string))))
-
-(provide 'helm-utils)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-utils.el ends here
--- /dev/null
+#!/bin/sh
+
+
+## Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+##
+## 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/>.
+
+## Commentary:
+
+# Preconfigured `emacs -Q' with a basic Helm configuration.
+# Run it from this directory or symlink it somewhere in your PATH.
+
+# If TEMP env var exists, use it, otherwise declare it.
+test -z "$TEMP" && TEMP="/tmp"
+
+CONF_FILE="$TEMP/helm-cfg.el"
+EMACS=emacs
+
+case $1 in
+ -P)
+ shift 1
+ EMACS=$1
+ shift 1
+ ;;
+ -h)
+ echo "Usage: ${0##*/} [-P} Emacs path [-h} help [--] EMACS ARGS"
+ exit 1
+ ;;
+esac
+
+LOAD_PATH=$($EMACS -q -batch --eval "(prin1 load-path)")
+
+cd "${0%/*}" || exit 1
+
+# Check if autoload file exists.
+# It may be in a different directory if emacs-helm.sh is a symlink.
+TRUENAME=$(find . -samefile "$0" -printf "%l")
+if [ ! -z "$TRUENAME" ]; then
+ AUTO_FILE="${TRUENAME%/*}/helm-autoloads.el"
+else
+ AUTO_FILE="helm-autoloads.el"
+fi
+if [ ! -e "$AUTO_FILE" ]; then
+ echo No autoloads found, please run make first to generate autoload file
+ exit 1
+fi
+
+
+cat > $CONF_FILE <<EOF
+(setq initial-scratch-message (concat initial-scratch-message
+";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\\n\
+;; This Emacs is Powered by \`HELM' using\\n\
+;; emacs program \"$EMACS\".\\n\
+;; This is a minimal \`helm' configuration to discover \`helm' or debug it.\\n\
+;; You can retrieve this minimal configuration in \"$CONF_FILE\".\\n\
+;; Some original Emacs commands are replaced by their \`helm' counterparts:\\n\\n\
+;; - \`find-file'(C-x C-f) =>\`helm-find-files'\\n\
+;; - \`occur'(M-s o) =>\`helm-occur'\\n\
+;; - \`list-buffers'(C-x C-b) =>\`helm-buffers-list'\\n\
+;; - \`completion-at-point'(M-tab) =>\`helm-lisp-completion-at-point'[1]\\n\
+;; - \`dabbrev-expand'(M-/) =>\`helm-dabbrev'\\n\
+;; - \`execute-extended-command'(M-x) =>\`helm-M-x'\\n\\n
+;; Some other Emacs commands are \"helmized\" by \`helm-mode'.\\n\
+;; [1] Coming with emacs-24.4, \`completion-at-point' is \"helmized\" by \`helm-mode'\\n\
+;; which provides Helm completion in many places like \`shell-mode'.\\n\
+;; Find context help for most Helm commands with \`C-h m'.\\n\
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\\n\\n"))
+
+(setq load-path (quote $LOAD_PATH))
+(require 'package)
+;; User may be using a non standard \`package-user-dir'.
+;; Modify \`package-directory-list' instead of \`package-user-dir'
+;; in case the user starts Helm from a non-ELPA installation.
+(unless (file-equal-p package-user-dir "~/.emacs.d/elpa")
+ (add-to-list 'package-directory-list (directory-file-name
+ (file-name-directory
+ (directory-file-name default-directory)))))
+
+(setq package-load-list '((helm-core t) (helm t) (async t) (popup t)))
+(package-initialize)
+(add-to-list 'load-path (file-name-directory (file-truename "$0")))
+(setq default-frame-alist '((vertical-scroll-bars . nil)
+ (tool-bar-lines . 0)
+ (menu-bar-lines . 0)
+ (fullscreen . nil)))
+(blink-cursor-mode -1)
+(require 'helm-config)
+(helm-mode 1)
+(define-key global-map [remap find-file] 'helm-find-files)
+(define-key global-map [remap occur] 'helm-occur)
+(define-key global-map [remap list-buffers] 'helm-buffers-list)
+(define-key global-map [remap dabbrev-expand] 'helm-dabbrev)
+(define-key global-map [remap execute-extended-command] 'helm-M-x)
+(unless (boundp 'completion-in-region-function)
+ (define-key lisp-interaction-mode-map [remap completion-at-point] 'helm-lisp-completion-at-point)
+ (define-key emacs-lisp-mode-map [remap completion-at-point] 'helm-lisp-completion-at-point))
+(add-hook 'kill-emacs-hook #'(lambda () (and (file-exists-p "$CONF_FILE") (delete-file "$CONF_FILE"))))
+EOF
+
+$EMACS -Q -l "$CONF_FILE" "$@"
--- /dev/null
+;;; helm-adaptive.el --- Adaptive Sorting of Candidates. -*- lexical-binding: t -*-
+
+;; Original Author: Tamas Patrovics
+
+;; Copyright (C) 2007 Tamas Patrovics
+;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'helm)
+
+\f
+(defgroup helm-adapt nil
+ "Adaptative sorting of candidates for Helm."
+ :group 'helm)
+
+(defcustom helm-adaptive-history-file
+ "~/.emacs.d/helm-adaptive-history"
+ "Path of file where history information is stored.
+When nil history is not saved nor restored after emacs restart unless
+you save/restore `helm-adaptive-history' with something else like
+psession or desktop."
+ :type 'string
+ :group 'helm-adapt)
+
+(defcustom helm-adaptive-history-length 50
+ "Maximum number of candidates stored for a source."
+ :type 'number
+ :group 'helm-adapt)
+
+(defcustom helm-adaptive-sort-by-frequent-recent-usage t
+ "Try to sort on an average of frequent and recent usage when non-nil.
+
+When nil sort on frequency usage only.
+
+Only frequency:
+When candidate have low frequency, you have to hit on it many times to
+make it going up on top.
+
+Frequency+recent:
+Even with a low frequency, candidate go up on top. If a candidate
+have a high frequency but it is not used since some time, it goes
+down slowly, but as soon you reuse it it go up on top quickly."
+ :group 'helm-adapt
+ :type 'boolean)
+\f
+;; Internal
+(defvar helm-adaptive-done nil
+ "nil if history information is not yet stored for the current
+selection.")
+
+(defvar helm-adaptive-history nil
+ "Contains the stored history information.
+Format: ((SOURCE-NAME (SELECTED-CANDIDATE (PATTERN . NUMBER-OF-USE) ...) ...) ...)")
+
+(defconst helm-adaptive-freq-coefficient 5)
+(defconst helm-adaptive-recent-coefficient 2)
+
+(defun helm-adaptive-done-reset ()
+ (setq helm-adaptive-done nil))
+
+;;;###autoload
+(define-minor-mode helm-adaptive-mode
+ "Toggle adaptive sorting in all sources."
+ :group 'helm-adapt
+ :require 'helm-adaptive
+ :global t
+ (if helm-adaptive-mode
+ (progn
+ (unless helm-adaptive-history
+ (helm-adaptive-maybe-load-history))
+ (add-hook 'kill-emacs-hook 'helm-adaptive-save-history)
+ ;; Should run at beginning of `helm-initial-setup'.
+ (add-hook 'helm-before-initialize-hook 'helm-adaptive-done-reset)
+ ;; Should run at beginning of `helm-exit-minibuffer'.
+ (add-hook 'helm-before-action-hook 'helm-adaptive-store-selection)
+ ;; Should run at beginning of `helm-select-action'.
+ (add-hook 'helm-select-action-hook 'helm-adaptive-store-selection))
+ (helm-adaptive-save-history)
+ (setq helm-adaptive-history nil)
+ (remove-hook 'kill-emacs-hook 'helm-adaptive-save-history)
+ (remove-hook 'helm-before-initialize-hook 'helm-adaptive-done-reset)
+ (remove-hook 'helm-before-action-hook 'helm-adaptive-store-selection)
+ (remove-hook 'helm-select-action-hook 'helm-adaptive-store-selection)))
+
+(defun helm-adapt-use-adaptive-p (&optional source-name)
+ "Return current source only if it use adaptive history, nil otherwise."
+ (when helm-adaptive-mode
+ (let* ((source (or source-name (helm-get-current-source)))
+ (adapt-source (or (assoc-default 'filtered-candidate-transformer source)
+ (assoc-default 'candidate-transformer source))))
+ (if (listp adapt-source)
+ (and (memq 'helm-adaptive-sort adapt-source) source)
+ (and (eq adapt-source 'helm-adaptive-sort) source)))))
+
+(defun helm-adaptive-store-selection ()
+ "Store history information for the selected candidate."
+ (unless helm-adaptive-done
+ (setq helm-adaptive-done t)
+ (let ((source (helm-adapt-use-adaptive-p)))
+ (when source
+ (let* ((source-name (assoc-default 'name source))
+ (source-info (or (assoc source-name helm-adaptive-history)
+ (progn
+ (push (list source-name) helm-adaptive-history)
+ (car helm-adaptive-history))))
+ (selection (helm-get-selection nil t))
+ (selection-info (progn
+ (setcdr source-info
+ (cons
+ (let ((found (assoc selection (cdr source-info))))
+ (if (not found)
+ ;; new entry
+ (list selection)
+ ;; move entry to the beginning of the
+ ;; list, so that it doesn't get
+ ;; trimmed when the history is
+ ;; truncated
+ (setcdr source-info
+ (delete found (cdr source-info)))
+ found))
+ (cdr source-info)))
+ (cadr source-info)))
+ (pattern-info (progn
+ (setcdr selection-info
+ (cons
+ (let ((found (assoc helm-pattern (cdr selection-info))))
+ (if (not found)
+ ;; new entry
+ (cons helm-pattern 0)
+ ;; move entry to the beginning of the
+ ;; list, so if two patterns used the
+ ;; same number of times then the one
+ ;; used last appears first in the list
+ (setcdr selection-info
+ (delete found (cdr selection-info)))
+ found))
+ (cdr selection-info)))
+ (cadr selection-info)))
+ (timestamp-info (helm-aif (assq 'timestamp (cdr selection-info))
+ it
+ (setcdr selection-info (cons (cons 'timestamp 0) (cdr selection-info)))
+ (cadr selection-info))))
+ ;; Increase usage count.
+ (setcdr pattern-info (1+ (cdr pattern-info)))
+ ;; Update timestamp.
+ (setcdr timestamp-info (float-time))
+ ;; Truncate history if needed.
+ (if (> (length (cdr selection-info)) helm-adaptive-history-length)
+ (setcdr selection-info
+ (cl-subseq (cdr selection-info) 0 helm-adaptive-history-length))))))))
+
+(defun helm-adaptive-maybe-load-history ()
+ "Load `helm-adaptive-history-file' which contain `helm-adaptive-history'.
+Returns nil if `helm-adaptive-history-file' doesn't exist."
+ (when (and helm-adaptive-history-file
+ (file-readable-p helm-adaptive-history-file))
+ (load-file helm-adaptive-history-file)))
+
+(defun helm-adaptive-save-history (&optional arg)
+ "Save history information to file given by `helm-adaptive-history-file'."
+ (interactive "p")
+ (when helm-adaptive-history-file
+ (with-temp-buffer
+ (insert
+ ";; -*- mode: emacs-lisp -*-\n"
+ ";; History entries used for helm adaptive display.\n")
+ (let (print-length print-level)
+ (prin1 `(setq helm-adaptive-history ',helm-adaptive-history)
+ (current-buffer)))
+ (insert ?\n)
+ (write-region (point-min) (point-max) helm-adaptive-history-file nil
+ (unless arg 'quiet)))))
+
+(defun helm-adaptive-sort (candidates source)
+ "Sort the CANDIDATES for SOURCE by usage frequency.
+This is a filtered candidate transformer you can use with the
+`filtered-candidate-transformer' attribute."
+ (let* ((source-name (assoc-default 'name source))
+ (source-info (assoc source-name helm-adaptive-history)))
+ (if source-info
+ (let ((usage
+ ;; Loop in the SOURCE entry of `helm-adaptive-history'
+ ;; and assemble a list containing the (CANDIDATE
+ ;; . USAGE-COUNT) pairs.
+ (cl-loop with cf = (if helm-adaptive-sort-by-frequent-recent-usage
+ helm-adaptive-freq-coefficient 1)
+ with cr = helm-adaptive-recent-coefficient
+ for (src-cand . infos) in (cdr source-info)
+ for count-freq = 0
+ for count-rec =
+ (helm-aif (and helm-adaptive-sort-by-frequent-recent-usage
+ (assq 'timestamp infos))
+ (* cr (+ (float-time) (cdr it)))
+ 0)
+ do (cl-loop for (pattern . score) in
+ (remove (assq 'timestamp infos) infos)
+ ;; If current pattern is equal to
+ ;; the previously used one then
+ ;; this candidate has priority
+ ;; (that's why its count-freq is
+ ;; boosted by 10000) and it only
+ ;; has to compete with other
+ ;; candidates which were also
+ ;; selected with the same pattern.
+ if (equal pattern helm-pattern)
+ return (setq count-freq (+ 10000 score))
+ else do (cl-incf count-freq score))
+ and collect (cons src-cand (+ (* count-freq cf) count-rec))
+ into results
+ ;; Sort the list in descending order, so
+ ;; candidates with highest priority come
+ ;; first.
+ finally return
+ (sort results (lambda (first second)
+ (> (cdr first) (cdr second)))))))
+ (if (consp usage)
+ ;; Put those candidates first which have the highest usage count.
+ (cl-loop for (cand . _freq) in usage
+ for info = (or (and (assq 'multiline source)
+ (replace-regexp-in-string
+ "\n\\'" "" cand))
+ cand)
+ when (cl-member info candidates
+ :test 'helm-adaptive-compare)
+ collect (car it) into sorted
+ and do (setq candidates
+ (cl-remove info candidates
+ :test 'helm-adaptive-compare))
+ finally return (append sorted candidates))
+ (message "Your `%s' is maybe corrupted or too old, \
+you should reinitialize it with `helm-reset-adaptive-history'"
+ helm-adaptive-history-file)
+ (sit-for 1)
+ candidates))
+ ;; if there is no information stored for this source then do nothing
+ candidates)))
+
+;;;###autoload
+(defun helm-reset-adaptive-history ()
+ "Delete all `helm-adaptive-history' and his file.
+Useful when you have a old or corrupted `helm-adaptive-history-file'."
+ (interactive)
+ (when (y-or-n-p "Really delete all your `helm-adaptive-history'? ")
+ (setq helm-adaptive-history nil)
+ (delete-file helm-adaptive-history-file)))
+
+(defun helm-adaptive-compare (x y)
+ "Compare display parts if some of candidates X and Y.
+
+Arguments X and Y are cons cell in (DISPLAY . REAL) format or atoms."
+ (equal (if (listp x) (car x) x)
+ (if (listp y) (car y) y)))
+
+
+(provide 'helm-adaptive)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-adaptive.el ends here
--- /dev/null
+;;; helm-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+
+(add-to-list 'load-path (directory-file-name
+ (or (file-name-directory #$) (car load-path))))
+
+\f
+;;;### (autoloads nil "helm-adaptive" "helm-adaptive.el" (0 0 0 0))
+;;; Generated autoloads from helm-adaptive.el
+
+(defvar helm-adaptive-mode nil "\
+Non-nil if Helm-Adaptive mode is enabled.
+See the `helm-adaptive-mode' command
+for a description of this minor mode.
+Setting this variable directly does not take effect;
+either customize it (see the info node `Easy Customization')
+or call the function `helm-adaptive-mode'.")
+
+(custom-autoload 'helm-adaptive-mode "helm-adaptive" nil)
+
+(autoload 'helm-adaptive-mode "helm-adaptive" "\
+Toggle adaptive sorting in all sources.
+
+\(fn &optional ARG)" t nil)
+
+(autoload 'helm-reset-adaptive-history "helm-adaptive" "\
+Delete all `helm-adaptive-history' and his file.
+Useful when you have a old or corrupted `helm-adaptive-history-file'.
+
+\(fn)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-adaptive" '("helm-adapt")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-bookmark" "helm-bookmark.el" (0 0 0 0))
+;;; Generated autoloads from helm-bookmark.el
+
+(autoload 'helm-bookmarks "helm-bookmark" "\
+Preconfigured `helm' for bookmarks.
+
+\(fn)" t nil)
+
+(autoload 'helm-filtered-bookmarks "helm-bookmark" "\
+Preconfigured helm for bookmarks (filtered by category).
+Optional source `helm-source-bookmark-addressbook' is loaded
+only if external addressbook-bookmark package is installed.
+
+\(fn)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-bookmark" '("helm-" "bmkext-jump-" "bookmark")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-buffers" "helm-buffers.el" (0 0 0 0))
+;;; Generated autoloads from helm-buffers.el
+
+(autoload 'helm-buffers-list "helm-buffers" "\
+Preconfigured `helm' to list buffers.
+
+\(fn)" t nil)
+
+(autoload 'helm-mini "helm-buffers" "\
+Preconfigured `helm' lightweight version (buffer -> recentf).
+
+\(fn)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-buffers" '("helm-")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-color" "helm-color.el" (0 0 0 0))
+;;; Generated autoloads from helm-color.el
+
+(autoload 'helm-colors "helm-color" "\
+Preconfigured `helm' for color.
+
+\(fn)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-color" '("helm-")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-command" "helm-command.el" (0 0 0 0))
+;;; Generated autoloads from helm-command.el
+
+(autoload 'helm-M-x "helm-command" "\
+Preconfigured `helm' for Emacs commands.
+It is `helm' replacement of regular `M-x' `execute-extended-command'.
+
+Unlike regular `M-x' emacs vanilla `execute-extended-command' command,
+the prefix args if needed, can be passed AFTER starting `helm-M-x'.
+When a prefix arg is passed BEFORE starting `helm-M-x', the first `C-u'
+while in `helm-M-x' session will disable it.
+
+You can get help on each command by persistent action.
+
+\(fn ARG &optional COMMAND-NAME)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-command" '("helm-")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-config" "helm-config.el" (0 0 0 0))
+;;; Generated autoloads from helm-config.el
+
+(autoload 'helm-configuration "helm-config" "\
+Customize `helm'.
+
+\(fn)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-config" '("helm-")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-dabbrev" "helm-dabbrev.el" (0 0 0 0))
+;;; Generated autoloads from helm-dabbrev.el
+
+(autoload 'helm-dabbrev "helm-dabbrev" "\
+Preconfigured helm for dynamic abbreviations.
+
+\(fn)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-dabbrev" '("helm-dabbrev-")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-elisp" "helm-elisp.el" (0 0 0 0))
+;;; Generated autoloads from helm-elisp.el
+
+(autoload 'helm-lisp-completion-at-point "helm-elisp" "\
+Preconfigured helm for lisp symbol completion at point.
+
+\(fn)" t nil)
+
+(autoload 'helm-complete-file-name-at-point "helm-elisp" "\
+Preconfigured helm to complete file name at point.
+
+\(fn &optional FORCE)" t nil)
+
+(autoload 'helm-lisp-indent "helm-elisp" "\
+
+
+\(fn)" t nil)
+
+(autoload 'helm-lisp-completion-or-file-name-at-point "helm-elisp" "\
+Preconfigured helm to complete lisp symbol or filename at point.
+Filename completion happen if string start after or between a double quote.
+
+\(fn)" t nil)
+
+(autoload 'helm-apropos "helm-elisp" "\
+Preconfigured helm to describe commands, functions, variables and faces.
+In non interactives calls DEFAULT argument should be provided as a string,
+i.e the `symbol-name' of any existing symbol.
+
+\(fn DEFAULT)" t nil)
+
+(autoload 'helm-manage-advice "helm-elisp" "\
+Preconfigured `helm' to disable/enable function advices.
+
+\(fn)" t nil)
+
+(autoload 'helm-locate-library "helm-elisp" "\
+Preconfigured helm to locate elisp libraries.
+
+\(fn)" t nil)
+
+(autoload 'helm-timers "helm-elisp" "\
+Preconfigured `helm' for timers.
+
+\(fn)" t nil)
+
+(autoload 'helm-complex-command-history "helm-elisp" "\
+Preconfigured helm for complex command history.
+
+\(fn)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-elisp" '("helm-" "with-helm-show-completion")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-elisp-package" "helm-elisp-package.el"
+;;;;;; (0 0 0 0))
+;;; Generated autoloads from helm-elisp-package.el
+
+(autoload 'helm-list-elisp-packages "helm-elisp-package" "\
+Preconfigured helm for listing and handling emacs packages.
+
+\(fn ARG)" t nil)
+
+(autoload 'helm-list-elisp-packages-no-fetch "helm-elisp-package" "\
+Preconfigured helm for emacs packages.
+
+Same as `helm-list-elisp-packages' but don't fetch packages on remote.
+Called with a prefix ARG always fetch packages on remote.
+
+\(fn ARG)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-elisp-package" '("helm-")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-eshell" "helm-eshell.el" (0 0 0 0))
+;;; Generated autoloads from helm-eshell.el
+
+(autoload 'helm-esh-pcomplete "helm-eshell" "\
+Preconfigured helm to provide helm completion in eshell.
+
+\(fn)" t nil)
+
+(autoload 'helm-eshell-history "helm-eshell" "\
+Preconfigured helm for eshell history.
+
+\(fn)" t nil)
+
+(autoload 'helm-eshell-prompts "helm-eshell" "\
+Pre-configured `helm' to browse the prompts of the current Eshell.
+
+\(fn)" t nil)
+
+(autoload 'helm-eshell-prompts-all "helm-eshell" "\
+Pre-configured `helm' to browse the prompts of all Eshell sessions.
+
+\(fn)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-eshell" '("helm-e")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-eval" "helm-eval.el" (0 0 0 0))
+;;; Generated autoloads from helm-eval.el
+
+(autoload 'helm-eval-expression "helm-eval" "\
+Preconfigured helm for `helm-source-evaluation-result'.
+
+\(fn ARG)" t nil)
+
+(autoload 'helm-eval-expression-with-eldoc "helm-eval" "\
+Preconfigured helm for `helm-source-evaluation-result' with `eldoc' support.
+
+\(fn)" t nil)
+
+(autoload 'helm-calcul-expression "helm-eval" "\
+Preconfigured helm for `helm-source-calculation-result'.
+
+\(fn)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-eval" '("helm-")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-external" "helm-external.el" (0 0 0 0))
+;;; Generated autoloads from helm-external.el
+
+(autoload 'helm-run-external-command "helm-external" "\
+Preconfigured `helm' to run External PROGRAM asyncronously from Emacs.
+If program is already running exit with error.
+You can set your own list of commands with
+`helm-external-commands-list'.
+
+\(fn PROGRAM)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-external" '("helm-")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-files" "helm-files.el" (0 0 0 0))
+;;; Generated autoloads from helm-files.el
+
+(autoload 'helm-projects-history "helm-files" "\
+
+
+\(fn)" t nil)
+
+(autoload 'helm-browse-project "helm-files" "\
+Preconfigured helm to browse projects.
+Browse files and see status of project with its vcs.
+Only HG and GIT are supported for now.
+Fall back to `helm-browse-project-find-files'
+if current directory is not under control of one of those vcs.
+With a prefix ARG browse files recursively, with two prefix ARG
+rebuild the cache.
+If the current directory is found in the cache, start
+`helm-browse-project-find-files' even with no prefix ARG.
+NOTE: The prefix ARG have no effect on the VCS controlled directories.
+
+Needed dependencies for VCS:
+<https://github.com/emacs-helm/helm-ls-git>
+and
+<https://github.com/emacs-helm/helm-ls-hg>.
+
+\(fn ARG)" t nil)
+
+(autoload 'helm-find-files "helm-files" "\
+Preconfigured `helm' for helm implementation of `find-file'.
+Called with a prefix arg show history if some.
+Don't call it from programs, use `helm-find-files-1' instead.
+This is the starting point for nearly all actions you can do on files.
+
+\(fn ARG)" t nil)
+
+(autoload 'helm-delete-tramp-connection "helm-files" "\
+Allow deleting tramp connection or marked tramp connections at once.
+
+This replace `tramp-cleanup-connection' which is partially broken in
+emacs < to 25.1.50.1 (See Emacs Bug#24432).
+
+It allows additionally to delete more than one connection at once.
+
+\(fn)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-files" '("helm-" "eshell-command-aliases-list")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-find" "helm-find.el" (0 0 0 0))
+;;; Generated autoloads from helm-find.el
+
+(autoload 'helm-find "helm-find" "\
+Preconfigured `helm' for the find shell command.
+
+Recursively find files whose names are matched by all specified
+globbing PATTERNs under the current directory using the external
+program specified in `find-program' (usually \"find\"). Every
+input PATTERN is silently wrapped into two stars: *PATTERN*.
+
+With prefix argument, prompt for a directory to search.
+
+When user option `helm-findutils-search-full-path' is non-nil,
+match against complete paths, otherwise, against file names
+without directory part.
+
+The (possibly empty) list of globbing PATTERNs can be followed by
+the separator \"*\" plus any number of additional arguments that
+are passed to \"find\" literally.
+
+\(fn ARG)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-find" '("helm-")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-font" "helm-font.el" (0 0 0 0))
+;;; Generated autoloads from helm-font.el
+
+(autoload 'helm-select-xfont "helm-font" "\
+Preconfigured `helm' to select Xfont.
+
+\(fn)" t nil)
+
+(autoload 'helm-ucs "helm-font" "\
+Preconfigured helm for `ucs-names'.
+
+Called with a prefix arg force reloading cache.
+
+\(fn ARG)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-font" '("helm-")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-for-files" "helm-for-files.el" (0 0 0
+;;;;;; 0))
+;;; Generated autoloads from helm-for-files.el
+
+(autoload 'helm-for-files "helm-for-files" "\
+Preconfigured `helm' for opening files.
+Run all sources defined in `helm-for-files-preferred-list'.
+
+\(fn)" t nil)
+
+(autoload 'helm-multi-files "helm-for-files" "\
+Preconfigured helm like `helm-for-files' but running locate only on demand.
+
+Allow toggling back and forth from locate to others sources with
+`helm-multi-files-toggle-locate-binding' key.
+This avoid launching needlessly locate when what you search is already
+found.
+
+\(fn)" t nil)
+
+(autoload 'helm-recentf "helm-for-files" "\
+Preconfigured `helm' for `recentf'.
+
+\(fn)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-for-files" '("helm-")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-grep" "helm-grep.el" (0 0 0 0))
+;;; Generated autoloads from helm-grep.el
+
+(autoload 'helm-goto-precedent-file "helm-grep" "\
+Go to precedent file in helm grep/etags buffers.
+
+\(fn)" t nil)
+
+(autoload 'helm-goto-next-file "helm-grep" "\
+Go to precedent file in helm grep/etags buffers.
+
+\(fn)" t nil)
+
+(autoload 'helm-do-grep-ag "helm-grep" "\
+Preconfigured helm for grepping with AG in `default-directory'.
+With prefix-arg prompt for type if available with your AG version.
+
+\(fn ARG)" t nil)
+
+(autoload 'helm-grep-do-git-grep "helm-grep" "\
+Preconfigured helm for git-grepping `default-directory'.
+With a prefix arg ARG git-grep the whole repository.
+
+\(fn ARG)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-grep" '("helm-")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-help" "helm-help.el" (0 0 0 0))
+;;; Generated autoloads from helm-help.el
+
+(autoload 'helm-documentation "helm-help" "\
+Preconfigured Helm for Helm documentation.
+With a prefix arg refresh the documentation.
+
+Find here the documentation of all documented sources.
+
+\(fn)" t nil)
+
+(defvar helm-comp-read-mode-line "\\<helm-comp-read-map>C/\\[helm-cr-empty-string]:Empty \\<helm-map>\\[helm-help]:Help \\[helm-select-action]:Act \\[helm-maybe-exit-minibuffer]/f1/f2/f-n:NthAct \\[helm-toggle-suspend-update]:Tog.suspend")
+
+(defvar helm-read-file-name-mode-line-string "\\<helm-read-file-map>\\[helm-help]:Help C/\\[helm-cr-empty-string]:Empty \\<helm-map>\\[helm-select-action]:Act \\[helm-maybe-exit-minibuffer]/f1/f2/f-n:NthAct \\[helm-toggle-suspend-update]:Tog.suspend" "\
+String displayed in mode-line in `helm-source-find-files'.")
+
+(defvar helm-top-mode-line "\\<helm-top-map>\\[helm-help]:Help \\<helm-map>\\[helm-select-action]:Act \\[helm-maybe-exit-minibuffer]/f1/f2/f-n:NthAct \\[helm-toggle-suspend-update]:Tog.suspend")
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-help" '("helm-")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-id-utils" "helm-id-utils.el" (0 0 0 0))
+;;; Generated autoloads from helm-id-utils.el
+
+(autoload 'helm-gid "helm-id-utils" "\
+Preconfigured helm for `gid' command line of `ID-Utils'.
+Need A database created with the command `mkid'
+above `default-directory'.
+Need id-utils as dependency which provide `mkid', `gid' etc...
+See <https://www.gnu.org/software/idutils/>.
+
+\(fn)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-id-utils" '("helm-gid-")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-imenu" "helm-imenu.el" (0 0 0 0))
+;;; Generated autoloads from helm-imenu.el
+
+(autoload 'helm-imenu "helm-imenu" "\
+Preconfigured `helm' for `imenu'.
+
+\(fn)" t nil)
+
+(autoload 'helm-imenu-in-all-buffers "helm-imenu" "\
+Preconfigured helm for fetching imenu entries in all buffers with similar mode as current.
+A mode is similar as current if it is the same, it is derived i.e `derived-mode-p'
+or it have an association in `helm-imenu-all-buffer-assoc'.
+
+\(fn)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-imenu" '("helm-")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-info" "helm-info.el" (0 0 0 0))
+;;; Generated autoloads from helm-info.el
+
+(autoload 'helm-info "helm-info" "\
+Preconfigured `helm' for searching Info files' indices.
+
+With a prefix argument \\[universal-argument], set REFRESH to non-nil.
+
+Optional parameter REFRESH, when non-nil, reevaluates
+`helm-default-info-index-list'. If the variable has been
+customized, set it to its saved value. If not, set it to its
+standard value. See `custom-reevaluate-setting' for more.
+
+REFRESH is useful when new Info files are installed. If
+`helm-default-info-index-list' has not been customized, the new
+Info files are made available.
+
+\(fn &optional REFRESH)" t nil)
+
+(autoload 'helm-info-at-point "helm-info" "\
+Preconfigured `helm' for searching info at point.
+
+\(fn)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-info" '("helm-")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-locate" "helm-locate.el" (0 0 0 0))
+;;; Generated autoloads from helm-locate.el
+
+(autoload 'helm-projects-find-files "helm-locate" "\
+Find files with locate in `helm-locate-project-list'.
+With a prefix arg refresh the database in each project.
+
+\(fn UPDATE)" t nil)
+
+(autoload 'helm-locate "helm-locate" "\
+Preconfigured `helm' for Locate.
+Note: you can add locate options after entering pattern.
+See 'man locate' for valid options and also `helm-locate-command'.
+
+You can specify a local database with prefix argument ARG.
+With two prefix arg, refresh the current local db or create it
+if it doesn't exists.
+
+To create a user specific db, use
+\"updatedb -l 0 -o db_path -U directory\".
+Where db_path is a filename matched by
+`helm-locate-db-file-regexp'.
+
+\(fn ARG)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-locate" '("helm-")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-man" "helm-man.el" (0 0 0 0))
+;;; Generated autoloads from helm-man.el
+
+(autoload 'helm-man-woman "helm-man" "\
+Preconfigured `helm' for Man and Woman pages.
+With a prefix arg reinitialize the cache.
+
+\(fn ARG)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-man" '("helm-")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-misc" "helm-misc.el" (0 0 0 0))
+;;; Generated autoloads from helm-misc.el
+
+(autoload 'helm-world-time "helm-misc" "\
+Preconfigured `helm' to show world time.
+Default action change TZ environment variable locally to emacs.
+
+\(fn)" t nil)
+
+(autoload 'helm-insert-latex-math "helm-misc" "\
+Preconfigured helm for latex math symbols completion.
+
+\(fn)" t nil)
+
+(autoload 'helm-ratpoison-commands "helm-misc" "\
+Preconfigured `helm' to execute ratpoison commands.
+
+\(fn)" t nil)
+
+(autoload 'helm-stumpwm-commands "helm-misc" "\
+Preconfigured helm for stumpwm commands.
+
+\(fn)" t nil)
+
+(autoload 'helm-minibuffer-history "helm-misc" "\
+Preconfigured `helm' for `minibuffer-history'.
+
+\(fn)" t nil)
+
+(autoload 'helm-comint-input-ring "helm-misc" "\
+Preconfigured `helm' that provide completion of `comint' history.
+
+\(fn)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-misc" '("helm-")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-mode" "helm-mode.el" (0 0 0 0))
+;;; Generated autoloads from helm-mode.el
+
+(autoload 'helm-comp-read "helm-mode" "\
+Read a string in the minibuffer, with helm completion.
+
+It is helm `completing-read' equivalent.
+
+- PROMPT is the prompt name to use.
+
+- COLLECTION can be a list, vector, obarray or hash-table.
+ It can be also a function that receives three arguments:
+ the values string, predicate and t. See `all-completions' for more details.
+
+Keys description:
+
+- TEST: A predicate called with one arg i.e candidate.
+
+- INITIAL-INPUT: Same as input arg in `helm'.
+
+- PRESELECT: See preselect arg of `helm'.
+
+- DEFAULT: This option is used only for compatibility with regular
+ Emacs `completing-read' (Same as DEFAULT arg of `completing-read').
+
+- BUFFER: Name of helm-buffer.
+
+- MUST-MATCH: Candidate selected must be one of COLLECTION.
+
+- FUZZY: Enable fuzzy matching.
+
+- REVERSE-HISTORY: When non--nil display history source after current
+ source completion.
+
+- REQUIRES-PATTERN: Same as helm attribute, default is 0.
+
+- HISTORY: A list containing specific history, default is nil.
+ When it is non--nil, all elements of HISTORY are displayed in
+ a special source before COLLECTION.
+
+- INPUT-HISTORY: A symbol. the minibuffer input history will be
+ stored there, if nil or not provided, `minibuffer-history'
+ will be used instead.
+
+- CASE-FOLD: Same as `helm-case-fold-search'.
+
+- DEL-INPUT: Boolean, when non--nil (default) remove the partial
+ minibuffer input from HISTORY is present.
+
+- PERSISTENT-ACTION: A function called with one arg i.e candidate.
+
+- PERSISTENT-HELP: A string to document PERSISTENT-ACTION.
+
+- MODE-LINE: A string or list to display in mode line.
+ Default is `helm-comp-read-mode-line'.
+
+- KEYMAP: A keymap to use in this `helm-comp-read'.
+ (the keymap will be shared with history source)
+
+- NAME: The name related to this local source.
+
+- HEADER-NAME: A function to alter NAME, see `helm'.
+
+- EXEC-WHEN-ONLY-ONE: Bound `helm-execute-action-at-once-if-one'
+ to non--nil. (possibles values are t or nil).
+
+- VOLATILE: Use volatile attribute.
+
+- SORT: A predicate to give to `sort' e.g `string-lessp'
+ Use this only on small data as it is ineficient.
+ If you want to sort faster add a sort function to
+ FC-TRANSFORMER.
+ Note that FUZZY when enabled is already providing a sort function.
+
+- FC-TRANSFORMER: A `filtered-candidate-transformer' function
+ or a list of functions.
+
+- HIST-FC-TRANSFORMER: A `filtered-candidate-transformer'
+ function for the history source.
+
+- MARKED-CANDIDATES: If non--nil return candidate or marked candidates as a list.
+
+- NOMARK: When non--nil don't allow marking candidates.
+
+- ALISTP: (default is non--nil) See `helm-comp-read-get-candidates'.
+
+- CANDIDATES-IN-BUFFER: when non--nil use a source build with
+ `helm-source-in-buffer' which is much faster.
+ Argument VOLATILE have no effect when CANDIDATES-IN-BUFFER is non--nil.
+
+- MATCH-PART: Allow matching only one part of candidate.
+ See match-part documentation in `helm-source'.
+
+- ALLOW-NEST: Allow nesting this `helm-comp-read' in a helm session.
+ See `helm'.
+
+- MULTILINE: See multiline in `helm-source'.
+
+Any prefix args passed during `helm-comp-read' invocation will be recorded
+in `helm-current-prefix-arg', otherwise if prefix args were given before
+`helm-comp-read' invocation, the value of `current-prefix-arg' will be used.
+That's mean you can pass prefix args before or after calling a command
+that use `helm-comp-read' See `helm-M-x' for example.
+
+\(fn PROMPT COLLECTION &key TEST INITIAL-INPUT DEFAULT PRESELECT (BUFFER \"*Helm Completions*\") MUST-MATCH FUZZY REVERSE-HISTORY (REQUIRES-PATTERN 0) HISTORY INPUT-HISTORY (CASE-FOLD helm-comp-read-case-fold-search) (DEL-INPUT t) (PERSISTENT-ACTION nil) (PERSISTENT-HELP \"DoNothing\") (MODE-LINE helm-comp-read-mode-line) HELP-MESSAGE (KEYMAP helm-comp-read-map) (NAME \"Helm Completions\") HEADER-NAME CANDIDATES-IN-BUFFER MATCH-PART EXEC-WHEN-ONLY-ONE QUIT-WHEN-NO-CAND (VOLATILE t) SORT FC-TRANSFORMER HIST-FC-TRANSFORMER MARKED-CANDIDATES NOMARK (ALISTP t) (CANDIDATE-NUMBER-LIMIT helm-candidate-number-limit) MULTILINE ALLOW-NEST)" nil nil)
+
+(autoload 'helm-read-file-name "helm-mode" "\
+Read a file name with helm completion.
+It is helm `read-file-name' emulation.
+
+Argument PROMPT is the default prompt to use.
+
+Keys description:
+
+- NAME: Source name, default to \"Read File Name\".
+
+- INITIAL-INPUT: Where to start read file name, default to `default-directory'.
+
+- BUFFER: `helm-buffer' name default to \"*Helm Completions*\".
+
+- TEST: A predicate called with one arg 'candidate'.
+
+- CASE-FOLD: Same as `helm-case-fold-search'.
+
+- PRESELECT: helm preselection.
+
+- HISTORY: Display HISTORY in a special source.
+
+- MUST-MATCH: Can be 'confirm, nil, or t.
+
+- FUZZY: Enable fuzzy matching when non-nil (Enabled by default).
+
+- MARKED-CANDIDATES: When non--nil return a list of marked candidates.
+
+- NOMARK: When non--nil don't allow marking candidates.
+
+- ALISTP: Don't use `all-completions' in history (take effect only on history).
+
+- PERSISTENT-ACTION-IF: a persistent if action function.
+
+- PERSISTENT-HELP: persistent help message.
+
+- MODE-LINE: A mode line message, default is `helm-read-file-name-mode-line-string'.
+
+\(fn PROMPT &key (NAME \"Read File Name\") (INITIAL-INPUT default-directory) (BUFFER \"*Helm file completions*\") TEST (CASE-FOLD helm-file-name-case-fold-search) PRESELECT HISTORY MUST-MATCH (FUZZY t) DEFAULT MARKED-CANDIDATES (CANDIDATE-NUMBER-LIMIT helm-ff-candidate-number-limit) NOMARK (ALISTP t) (PERSISTENT-ACTION-IF \\='helm-find-files-persistent-action-if) (PERSISTENT-HELP \"Hit1 Expand Candidate, Hit2 or (C-u) Find file\") (MODE-LINE helm-read-file-name-mode-line-string))" nil nil)
+
+(defvar helm-mode nil "\
+Non-nil if Helm mode is enabled.
+See the `helm-mode' command
+for a description of this minor mode.
+Setting this variable directly does not take effect;
+either customize it (see the info node `Easy Customization')
+or call the function `helm-mode'.")
+
+(custom-autoload 'helm-mode "helm-mode" nil)
+
+(autoload 'helm-mode "helm-mode" "\
+Toggle generic helm completion.
+
+All functions in Emacs that use `completing-read'
+or `read-file-name' and friends will use helm interface
+when this mode is turned on.
+
+However you can modify this behavior for functions of your choice
+with `helm-completing-read-handlers-alist'.
+
+Also commands using `completion-in-region' will be helmized when
+`helm-mode-handle-completion-in-region' is non nil, you can modify
+this behavior with `helm-mode-no-completion-in-region-in-modes'.
+
+Called with a positive arg, turn on unconditionally, with a
+negative arg turn off.
+You can turn it on with `helm-mode'.
+
+Some crap emacs functions may not be supported,
+e.g `ffap-alternate-file' and maybe others
+You can add such functions to `helm-completing-read-handlers-alist'
+with a nil value.
+
+About `ido-mode':
+When you are using `helm-mode', DO NOT use `ido-mode', instead if you
+want some commands use `ido', add these commands to
+`helm-completing-read-handlers-alist' with `ido' as value.
+
+Note: This mode is incompatible with Emacs23.
+
+\(fn &optional ARG)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-mode" '("helm-")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-net" "helm-net.el" (0 0 0 0))
+;;; Generated autoloads from helm-net.el
+
+(autoload 'helm-browse-url-firefox "helm-net" "\
+Same as `browse-url-firefox' but detach from emacs.
+
+So when you quit emacs you can keep your firefox session open
+and not be prompted to kill firefox process.
+
+NOTE: Probably not supported on some systems (e.g Windows).
+
+\(fn URL &optional IGNORE)" t nil)
+
+(autoload 'helm-browse-url-opera "helm-net" "\
+Browse URL with opera browser and detach from emacs.
+
+So when you quit emacs you can keep your opera session open
+and not be prompted to kill opera process.
+
+NOTE: Probably not supported on some systems (e.g Windows).
+
+\(fn URL &optional IGNORE)" t nil)
+
+(autoload 'helm-browse-url-chromium "helm-net" "\
+Browse URL with google chrome browser.
+
+\(fn URL &optional IGNORE)" t nil)
+
+(autoload 'helm-browse-url-uzbl "helm-net" "\
+Browse URL with uzbl browser.
+
+\(fn URL &optional IGNORE)" t nil)
+
+(autoload 'helm-browse-url-conkeror "helm-net" "\
+Browse URL with conkeror browser.
+
+\(fn URL &optional IGNORE)" t nil)
+
+(autoload 'helm-surfraw "helm-net" "\
+Preconfigured `helm' to search PATTERN with search ENGINE.
+
+\(fn PATTERN ENGINE)" t nil)
+
+(autoload 'helm-google-suggest "helm-net" "\
+Preconfigured `helm' for google search with google suggest.
+
+\(fn)" t nil)
+
+(autoload 'helm-wikipedia-suggest "helm-net" "\
+Preconfigured `helm' for Wikipedia lookup with Wikipedia suggest.
+
+\(fn)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-net" '("helm-")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-org" "helm-org.el" (0 0 0 0))
+;;; Generated autoloads from helm-org.el
+
+(autoload 'helm-org-agenda-files-headings "helm-org" "\
+Preconfigured helm for org files headings.
+
+\(fn)" t nil)
+
+(autoload 'helm-org-in-buffer-headings "helm-org" "\
+Preconfigured helm for org buffer headings.
+
+\(fn)" t nil)
+
+(autoload 'helm-org-parent-headings "helm-org" "\
+Preconfigured helm for org headings that are parents of the
+current heading.
+
+\(fn)" t nil)
+
+(autoload 'helm-org-capture-templates "helm-org" "\
+Preconfigured helm for org templates.
+
+\(fn)" t nil)
+
+(autoload 'helm-org-completing-read-tags "helm-org" "\
+Completing read function for Org tags.
+
+This function is used as a `completing-read' function in
+`helm-completing-read-handlers-alist' by `org-set-tags' and
+`org-capture'.
+
+NOTE: Org tag completion will work only if you disable org fast tag
+selection, see (info \"(org) setting tags\").
+
+\(fn PROMPT COLLECTION PRED REQ INITIAL HIST DEF INHERIT-INPUT-METHOD NAME BUFFER)" nil nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-org" '("helm-")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-regexp" "helm-regexp.el" (0 0 0 0))
+;;; Generated autoloads from helm-regexp.el
+
+(autoload 'helm-moccur-mode "helm-regexp" "\
+Major mode to provide actions in helm moccur saved buffer.
+
+Special commands:
+\\{helm-moccur-mode-map}
+
+\(fn)" t nil)
+
+(autoload 'helm-regexp "helm-regexp" "\
+Preconfigured helm to build regexps.
+`query-replace-regexp' can be run from there against found regexp.
+
+\(fn)" t nil)
+
+(autoload 'helm-occur "helm-regexp" "\
+Preconfigured helm for searching lines matching pattern in `current-buffer'.
+
+When `helm-source-occur' is member of
+`helm-sources-using-default-as-input' which is the default,
+symbol at point is searched at startup.
+
+When a region is marked search only in this region by narrowing.
+
+To search in multiples buffers start from one of the commands listing
+buffers (i.e. a helm command using `helm-source-buffers-list' like
+`helm-mini') and use the multi occur buffers action.
+
+This is the helm implementation that collect lines matching pattern
+like vanilla emacs `occur' but have nothing to do with it, the search
+engine beeing completely different.
+
+\(fn)" t nil)
+
+(autoload 'helm-occur-from-isearch "helm-regexp" "\
+Invoke `helm-occur' from isearch.
+
+\(fn)" t nil)
+
+(autoload 'helm-multi-occur-from-isearch "helm-regexp" "\
+Invoke `helm-multi-occur' from isearch.
+
+With a prefix arg, reverse the behavior of
+`helm-moccur-always-search-in-current'.
+The prefix arg can be set before calling
+`helm-multi-occur-from-isearch' or during the buffer selection.
+
+\(fn &optional ARG)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-regexp" '("helm-")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-ring" "helm-ring.el" (0 0 0 0))
+;;; Generated autoloads from helm-ring.el
+
+(autoload 'helm-mark-ring "helm-ring" "\
+Preconfigured `helm' for `helm-source-mark-ring'.
+
+\(fn)" t nil)
+
+(autoload 'helm-global-mark-ring "helm-ring" "\
+Preconfigured `helm' for `helm-source-global-mark-ring'.
+
+\(fn)" t nil)
+
+(autoload 'helm-all-mark-rings "helm-ring" "\
+Preconfigured `helm' for `helm-source-global-mark-ring' and `helm-source-mark-ring'.
+
+\(fn)" t nil)
+
+(autoload 'helm-register "helm-ring" "\
+Preconfigured `helm' for Emacs registers.
+
+\(fn)" t nil)
+
+(autoload 'helm-show-kill-ring "helm-ring" "\
+Preconfigured `helm' for `kill-ring'.
+It is drop-in replacement of `yank-pop'.
+
+First call open the kill-ring browser, next calls move to next line.
+
+\(fn)" t nil)
+
+(autoload 'helm-execute-kmacro "helm-ring" "\
+Preconfigured helm for keyboard macros.
+Define your macros with `f3' and `f4'.
+See (info \"(emacs) Keyboard Macros\") for detailed infos.
+This command is useful when used with persistent action.
+
+\(fn)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-ring" '("helm-")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-semantic" "helm-semantic.el" (0 0 0 0))
+;;; Generated autoloads from helm-semantic.el
+
+(autoload 'helm-semantic "helm-semantic" "\
+Preconfigured `helm' for `semantic'.
+If ARG is supplied, pre-select symbol at point instead of current
+
+\(fn ARG)" t nil)
+
+(autoload 'helm-semantic-or-imenu "helm-semantic" "\
+Preconfigured helm for `semantic' or `imenu'.
+If ARG is supplied, pre-select symbol at point instead of current
+semantic tag in scope.
+
+If `semantic-mode' is active in the current buffer, then use
+semantic for generating tags, otherwise fall back to `imenu'.
+Fill in the symbol at point by default.
+
+\(fn ARG)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-semantic" '("helm-s")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-sys" "helm-sys.el" (0 0 0 0))
+;;; Generated autoloads from helm-sys.el
+
+(defvar helm-top-poll-mode nil "\
+Non-nil if Helm-Top-Poll mode is enabled.
+See the `helm-top-poll-mode' command
+for a description of this minor mode.
+Setting this variable directly does not take effect;
+either customize it (see the info node `Easy Customization')
+or call the function `helm-top-poll-mode'.")
+
+(custom-autoload 'helm-top-poll-mode "helm-sys" nil)
+
+(autoload 'helm-top-poll-mode "helm-sys" "\
+Refresh automatically helm top buffer once enabled.
+
+\(fn &optional ARG)" t nil)
+
+(autoload 'helm-top "helm-sys" "\
+Preconfigured `helm' for top command.
+
+\(fn)" t nil)
+
+(autoload 'helm-list-emacs-process "helm-sys" "\
+Preconfigured `helm' for emacs process.
+
+\(fn)" t nil)
+
+(autoload 'helm-xrandr-set "helm-sys" "\
+Preconfigured helm for xrandr.
+
+\(fn)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-sys" '("helm-")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-tags" "helm-tags.el" (0 0 0 0))
+;;; Generated autoloads from helm-tags.el
+
+(autoload 'helm-etags-select "helm-tags" "\
+Preconfigured helm for etags.
+If called with a prefix argument REINIT
+or if any of the tag files have been modified, reinitialize cache.
+
+This function aggregates three sources of tag files:
+
+ 1) An automatically located file in the parent directories,
+ by `helm-etags-get-tag-file'.
+ 2) `tags-file-name', which is commonly set by `find-tag' command.
+ 3) `tags-table-list' which is commonly set by `visit-tags-table' command.
+
+\(fn REINIT)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-tags" '("helm-")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-types" "helm-types.el" (0 0 0 0))
+;;; Generated autoloads from helm-types.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-types" '("helm-")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-utils" "helm-utils.el" (0 0 0 0))
+;;; Generated autoloads from helm-utils.el
+
+(defvar helm-popup-tip-mode nil "\
+Non-nil if Helm-Popup-Tip mode is enabled.
+See the `helm-popup-tip-mode' command
+for a description of this minor mode.
+Setting this variable directly does not take effect;
+either customize it (see the info node `Easy Customization')
+or call the function `helm-popup-tip-mode'.")
+
+(custom-autoload 'helm-popup-tip-mode "helm-utils" nil)
+
+(autoload 'helm-popup-tip-mode "helm-utils" "\
+Show help-echo informations in a popup tip at end of line.
+
+\(fn &optional ARG)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-utils" '("helm-" "with-helm-display-marked-candidates")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-x-files" "helm-x-files.el" (0 0 0 0))
+;;; Generated autoloads from helm-x-files.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-x-files" '("helm-")))
+
+;;;***
+\f
+;;;### (autoloads nil nil ("helm-easymenu.el" "helm-pkg.el") (0 0
+;;;;;; 0 0))
+
+;;;***
+\f
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; coding: utf-8
+;; End:
+;;; helm-autoloads.el ends here
--- /dev/null
+;;; helm-bookmark.el --- Helm for Emacs regular Bookmarks. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Code:
+(require 'cl-lib)
+(require 'bookmark)
+(require 'helm)
+(require 'helm-lib)
+(require 'helm-help)
+(require 'helm-types)
+(require 'helm-utils)
+(require 'helm-info)
+(require 'helm-adaptive)
+(require 'helm-net)
+
+(declare-function helm-browse-project "helm-files" (arg))
+(declare-function addressbook-bookmark-edit "ext:addressbook-bookmark.el" (bookmark))
+\f
+(defgroup helm-bookmark nil
+ "Predefined configurations for `helm.el'."
+ :group 'helm)
+
+(defcustom helm-bookmark-show-location nil
+ "Show location of bookmark on display."
+ :group 'helm-bookmark
+ :type 'boolean)
+
+(defcustom helm-bookmark-default-filtered-sources
+ (append '(helm-source-bookmark-org
+ helm-source-bookmark-files&dirs
+ helm-source-bookmark-helm-find-files
+ helm-source-bookmark-info
+ helm-source-bookmark-gnus
+ helm-source-bookmark-man
+ helm-source-bookmark-images
+ helm-source-bookmark-w3m)
+ (list 'helm-source-bookmark-uncategorized
+ 'helm-source-bookmark-set))
+ "List of sources to use in `helm-filtered-bookmarks'."
+ :group 'helm-bookmark
+ :type '(repeat (choice symbol)))
+
+\f
+(defface helm-bookmark-info
+ '((t (:foreground "green")))
+ "Face used for W3m Emacs bookmarks (not w3m bookmarks)."
+ :group 'helm-bookmark)
+
+(defface helm-bookmark-w3m
+ '((t (:foreground "yellow")))
+ "Face used for W3m Emacs bookmarks (not w3m bookmarks)."
+ :group 'helm-bookmark)
+
+(defface helm-bookmark-gnus
+ '((t (:foreground "magenta")))
+ "Face used for Gnus bookmarks."
+ :group 'helm-bookmark)
+
+(defface helm-bookmark-man
+ '((t (:foreground "Orange4")))
+ "Face used for Woman/man bookmarks."
+ :group 'helm-bookmark)
+
+(defface helm-bookmark-file
+ '((t (:foreground "Deepskyblue2")))
+ "Face used for file bookmarks."
+ :group 'helm-bookmark)
+
+(defface helm-bookmark-file-not-found
+ '((t (:foreground "Slategray4")))
+ "Face used for file bookmarks."
+ :group 'helm-bookmark)
+
+(defface helm-bookmark-directory
+ '((t (:inherit helm-ff-directory)))
+ "Face used for file bookmarks."
+ :group 'helm-bookmark)
+
+(defface helm-bookmark-addressbook
+ '((t (:foreground "tomato")))
+ "Face used for addressbook bookmarks."
+ :group 'helm-bookmark)
+
+\f
+(defvar helm-bookmark-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map helm-map)
+ (define-key map (kbd "C-c o") 'helm-bookmark-run-jump-other-window)
+ (define-key map (kbd "C-c C-o") 'helm-bookmark-run-jump-other-frame)
+ (define-key map (kbd "C-d") 'helm-bookmark-run-delete)
+ (define-key map (kbd "C-]") 'helm-bookmark-toggle-filename)
+ (define-key map (kbd "M-e") 'helm-bookmark-run-edit)
+ map)
+ "Generic Keymap for emacs bookmark sources.")
+
+(defclass helm-source-basic-bookmarks (helm-source-in-buffer helm-type-bookmark)
+ ((init :initform (lambda ()
+ (bookmark-maybe-load-default-file)
+ (helm-init-candidates-in-buffer
+ 'global
+ (bookmark-all-names))))
+ (filtered-candidate-transformer :initform 'helm-bookmark-transformer)))
+
+(defvar helm-source-bookmarks
+ (helm-make-source "Bookmarks" 'helm-source-basic-bookmarks)
+ "See (info \"(emacs)Bookmarks\").")
+
+(defun helm-bookmark-transformer (candidates _source)
+ (cl-loop for i in candidates
+ for loc = (bookmark-location i)
+ for len = (string-width i)
+ for trunc = (if (> len bookmark-bmenu-file-column)
+ (helm-substring i bookmark-bmenu-file-column)
+ i)
+ for sep = (make-string (- (+ bookmark-bmenu-file-column 2)
+ (length trunc))
+ ? )
+ if helm-bookmark-show-location
+ collect (cons (concat trunc sep (if (listp loc) (car loc) loc)) i)
+ else collect i))
+
+(defun helm-bookmark-toggle-filename-1 (_candidate)
+ (let* ((real (helm-get-selection helm-buffer))
+ (trunc (if (> (string-width real) bookmark-bmenu-file-column)
+ (helm-substring real bookmark-bmenu-file-column)
+ real))
+ (loc (bookmark-location real)))
+ (setq helm-bookmark-show-location (not helm-bookmark-show-location))
+ (helm-update (if helm-bookmark-show-location
+ (concat (regexp-quote trunc)
+ " +"
+ (regexp-quote
+ (if (listp loc) (car loc) loc)))
+ (regexp-quote real)))))
+
+(defun helm-bookmark-toggle-filename ()
+ "Toggle bookmark location visibility."
+ (interactive)
+ (with-helm-alive-p
+ (helm-attrset 'toggle-filename
+ '(helm-bookmark-toggle-filename-1 . never-split))
+ (helm-execute-persistent-action 'toggle-filename)))
+(put 'helm-bookmark-toggle-filename 'helm-only t)
+
+(defun helm-bookmark-jump (candidate)
+ "Jump to bookmark action."
+ (let ((current-prefix-arg helm-current-prefix-arg)
+ non-essential)
+ (bookmark-jump candidate)))
+
+(defun helm-bookmark-jump-other-frame (candidate)
+ "Jump to bookmark in other frame action."
+ (let ((current-prefix-arg helm-current-prefix-arg)
+ non-essential)
+ (bookmark-jump candidate 'switch-to-buffer-other-frame)))
+
+(defun helm-bookmark-jump-other-window (candidate)
+ "Jump to bookmark in other window action."
+ (let (non-essential)
+ (bookmark-jump-other-window candidate)))
+
+\f
+;;; bookmark-set
+;;
+(defvar helm-source-bookmark-set
+ (helm-build-dummy-source "Set Bookmark"
+ :filtered-candidate-transformer
+ (lambda (_candidates _source)
+ (list (or (and (not (string= helm-pattern ""))
+ helm-pattern)
+ "Enter a bookmark name to record")))
+ :action '(("Set bookmark" . (lambda (candidate)
+ (if (string= helm-pattern "")
+ (message "No bookmark name given for record")
+ (bookmark-set candidate))))))
+ "See (info \"(emacs)Bookmarks\").")
+
+\f
+;;; Predicates
+;;
+(defconst helm-bookmark--non-file-filename " - no file -"
+ "Name to use for `filename' entry, for non-file bookmarks.")
+
+(defun helm-bookmark-gnus-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is a Gnus bookmark.
+BOOKMARK is a bookmark name or a bookmark record."
+ (or (eq (bookmark-get-handler bookmark) 'bmkext-jump-gnus)
+ (eq (bookmark-get-handler bookmark) 'gnus-summary-bookmark-jump)
+ (eq (bookmark-get-handler bookmark) 'bookmarkp-jump-gnus)))
+
+(defun helm-bookmark-w3m-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is a W3m bookmark.
+BOOKMARK is a bookmark name or a bookmark record."
+ (or (eq (bookmark-get-handler bookmark) 'bmkext-jump-w3m)
+ (eq (bookmark-get-handler bookmark) 'bookmark-w3m-bookmark-jump)
+ (eq (bookmark-get-handler bookmark) 'bookmarkp-jump-w3m)))
+
+(defun helm-bookmark-woman-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is a Woman bookmark.
+BOOKMARK is a bookmark name or a bookmark record."
+ (or (eq (bookmark-get-handler bookmark) 'bmkext-jump-woman)
+ (eq (bookmark-get-handler bookmark) 'woman-bookmark-jump)
+ (eq (bookmark-get-handler bookmark) 'bookmarkp-jump-woman)))
+
+(defun helm-bookmark-man-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is a Man bookmark.
+BOOKMARK is a bookmark name or a bookmark record."
+ (or (eq (bookmark-get-handler bookmark) 'bmkext-jump-man)
+ (eq (bookmark-get-handler bookmark) 'Man-bookmark-jump)
+ (eq (bookmark-get-handler bookmark) 'bookmarkp-jump-man)))
+
+(defun helm-bookmark-woman-man-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is a Man or Woman bookmark.
+BOOKMARK is a bookmark name or a bookmark record."
+ (or (helm-bookmark-man-bookmark-p bookmark)
+ (helm-bookmark-woman-bookmark-p bookmark)))
+
+(defun helm-bookmark-info-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK is an Info bookmark.
+BOOKMARK is a bookmark name or a bookmark record."
+ (eq (bookmark-get-handler bookmark) 'Info-bookmark-jump))
+
+(defun helm-bookmark-image-bookmark-p (bookmark)
+ "Return non-nil if BOOKMARK bookmarks an image file."
+ (if (stringp bookmark)
+ (assq 'image-type (assq bookmark bookmark-alist))
+ (assq 'image-type bookmark)))
+
+(defun helm-bookmark-file-p (bookmark)
+ "Return non-nil if BOOKMARK bookmarks a file or directory.
+BOOKMARK is a bookmark name or a bookmark record.
+This excludes bookmarks of a more specific kind (Info, Gnus, and W3m)."
+ (let* ((filename (bookmark-get-filename bookmark))
+ (isnonfile (equal filename helm-bookmark--non-file-filename)))
+ (and filename (not isnonfile) (not (bookmark-get-handler bookmark)))))
+
+(defun helm-bookmark-org-file-p (bookmark)
+ (let* ((filename (bookmark-get-filename bookmark)))
+ (or (string-suffix-p ".org" filename t)
+ (string-suffix-p ".org_archive" filename t))))
+
+(defun helm-bookmark-helm-find-files-p (bookmark)
+ "Return non-nil if BOOKMARK bookmarks a `helm-find-files' session.
+BOOKMARK is a bookmark name or a bookmark record."
+ (eq (bookmark-get-handler bookmark) 'helm-ff-bookmark-jump))
+
+(defun helm-bookmark-addressbook-p (bookmark)
+ "Return non--nil if BOOKMARK is a contact recorded with addressbook-bookmark.
+BOOKMARK is a bookmark name or a bookmark record."
+ (if (listp bookmark)
+ (string= (assoc-default 'type bookmark) "addressbook")
+ (string= (assoc-default
+ 'type (assoc bookmark bookmark-alist)) "addressbook")))
+
+(defun helm-bookmark-uncategorized-bookmark-p (bookmark)
+ "Return non--nil if BOOKMARK match no known category."
+ (cl-loop for pred in '(helm-bookmark-org-file-p
+ helm-bookmark-addressbook-p
+ helm-bookmark-gnus-bookmark-p
+ helm-bookmark-w3m-bookmark-p
+ helm-bookmark-woman-man-bookmark-p
+ helm-bookmark-info-bookmark-p
+ helm-bookmark-image-bookmark-p
+ helm-bookmark-file-p
+ helm-bookmark-helm-find-files-p
+ helm-bookmark-addressbook-p)
+ never (funcall pred bookmark)))
+
+(defun helm-bookmark-filter-setup-alist (fn)
+ "Return a filtered `bookmark-alist' sorted alphabetically."
+ (cl-loop for b in bookmark-alist
+ for name = (car b)
+ when (funcall fn b) collect
+ (propertize name 'location (bookmark-location name))))
+\f
+;;; Bookmark handlers
+;;
+(defvar w3m-async-exec)
+(defun helm-bookmark-jump-w3m (bookmark)
+ "Jump to W3m bookmark BOOKMARK, setting a new tab.
+If `browse-url-browser-function' is set to something else
+than `w3m-browse-url' use it."
+ (require 'helm-net)
+ (let* ((file (or (bookmark-prop-get bookmark 'filename)
+ (bookmark-prop-get bookmark 'url)))
+ (buf (generate-new-buffer-name "*w3m*"))
+ (w3m-async-exec nil)
+ ;; If user don't have anymore w3m installed let it browse its
+ ;; bookmarks with default browser otherwise assume bookmark
+ ;; have been bookmarked from w3m and use w3m.
+ (browse-url-browser-function (or (and (fboundp 'w3m-browse-url)
+ (executable-find "w3m")
+ 'w3m-browse-url)
+ browse-url-browser-function))
+ (really-use-w3m (equal browse-url-browser-function 'w3m-browse-url)))
+ (helm-browse-url file really-use-w3m)
+ (when really-use-w3m
+ (bookmark-default-handler
+ `("" (buffer . ,buf) . ,(bookmark-get-bookmark-record bookmark))))))
+
+;; All bookmarks recorded with the handler provided with w3m
+;; (`bookmark-w3m-bookmark-jump') will use our handler which open
+;; the bookmark in a new tab or in an external browser depending
+;; on `browse-url-browser-function'.
+(defalias 'bookmark-w3m-bookmark-jump 'helm-bookmark-jump-w3m)
+
+;; Provide compatibility with old handlers provided in external
+;; packages bookmark-extensions.el and bookmark+.
+(defalias 'bmkext-jump-woman 'woman-bookmark-jump)
+(defalias 'bmkext-jump-man 'Man-bookmark-jump)
+(defalias 'bmkext-jump-w3m 'helm-bookmark-jump-w3m)
+(defalias 'bmkext-jump-gnus 'gnus-summary-bookmark-jump)
+(defalias 'bookmarkp-jump-gnus 'gnus-summary-bookmark-jump)
+(defalias 'bookmarkp-jump-w3m 'helm-bookmark-jump-w3m)
+(defalias 'bookmarkp-jump-woman 'woman-bookmark-jump)
+(defalias 'bookmarkp-jump-man 'Man-bookmark-jump)
+
+\f
+;;;; Filtered bookmark sources
+;;
+;;
+(defclass helm-source-filtered-bookmarks (helm-source-in-buffer helm-type-bookmark)
+ ((filtered-candidate-transformer
+ :initform '(helm-adaptive-sort
+ helm-highlight-bookmark))))
+
+;;; W3m bookmarks.
+;;
+(defun helm-bookmark-w3m-setup-alist ()
+ "Specialized filter function for bookmarks w3m."
+ (helm-bookmark-filter-setup-alist 'helm-bookmark-w3m-bookmark-p))
+
+(defvar helm-source-bookmark-w3m
+ (helm-make-source "Bookmark W3m" 'helm-source-filtered-bookmarks
+ :init (lambda ()
+ (bookmark-maybe-load-default-file)
+ (helm-init-candidates-in-buffer
+ 'global (helm-bookmark-w3m-setup-alist)))))
+
+;;; Images
+;;
+(defun helm-bookmark-images-setup-alist ()
+ "Specialized filter function for images bookmarks."
+ (helm-bookmark-filter-setup-alist 'helm-bookmark-image-bookmark-p))
+
+(defvar helm-source-bookmark-images
+ (helm-make-source "Bookmark Images" 'helm-source-filtered-bookmarks
+ :init (lambda ()
+ (bookmark-maybe-load-default-file)
+ (helm-init-candidates-in-buffer
+ 'global (helm-bookmark-images-setup-alist)))))
+
+;;; Woman Man
+;;
+(defun helm-bookmark-man-setup-alist ()
+ "Specialized filter function for bookmarks w3m."
+ (helm-bookmark-filter-setup-alist 'helm-bookmark-woman-man-bookmark-p))
+
+(defvar helm-source-bookmark-man
+ (helm-make-source "Bookmark Woman&Man" 'helm-source-filtered-bookmarks
+ :init (lambda ()
+ (bookmark-maybe-load-default-file)
+ (helm-init-candidates-in-buffer
+ 'global (helm-bookmark-man-setup-alist)))))
+
+;;; Org files
+;;
+(defun helm-bookmark-org-setup-alist ()
+ "Specialized filter function for Org file bookmarks."
+ (helm-bookmark-filter-setup-alist 'helm-bookmark-org-file-p))
+
+(defvar helm-source-bookmark-org
+ (helm-make-source " Bookmarked Org files" 'helm-source-filtered-bookmarks
+ :init (lambda ()
+ (bookmark-maybe-load-default-file)
+ (helm-init-candidates-in-buffer
+ 'global (helm-bookmark-org-setup-alist)))))
+
+;;; Gnus
+;;
+(defun helm-bookmark-gnus-setup-alist ()
+ "Specialized filter function for bookmarks gnus."
+ (helm-bookmark-filter-setup-alist 'helm-bookmark-gnus-bookmark-p))
+
+(defvar helm-source-bookmark-gnus
+ (helm-make-source "Bookmark Gnus" 'helm-source-filtered-bookmarks
+ :init (lambda ()
+ (bookmark-maybe-load-default-file)
+ (helm-init-candidates-in-buffer
+ 'global (helm-bookmark-gnus-setup-alist)))))
+
+;;; Info
+;;
+(defun helm-bookmark-info-setup-alist ()
+ "Specialized filter function for bookmarks info."
+ (helm-bookmark-filter-setup-alist 'helm-bookmark-info-bookmark-p))
+
+(defvar helm-source-bookmark-info
+ (helm-make-source "Bookmark Info" 'helm-source-filtered-bookmarks
+ :init (lambda ()
+ (bookmark-maybe-load-default-file)
+ (helm-init-candidates-in-buffer
+ 'global (helm-bookmark-info-setup-alist)))))
+
+;;; Files and directories
+;;
+(defun helm-bookmark-local-files-setup-alist ()
+ "Specialized filter function for bookmarks locals files."
+ (helm-bookmark-filter-setup-alist 'helm-bookmark-file-p))
+
+(defvar helm-source-bookmark-files&dirs
+ (helm-make-source "Bookmark Files&Directories" 'helm-source-filtered-bookmarks
+ :init (lambda ()
+ (bookmark-maybe-load-default-file)
+ (helm-init-candidates-in-buffer
+ 'global (helm-bookmark-local-files-setup-alist)))))
+
+;;; Helm find files sessions.
+;;
+(defun helm-bookmark-helm-find-files-setup-alist ()
+ "Specialized filter function for `helm-find-files' bookmarks."
+ (helm-bookmark-filter-setup-alist 'helm-bookmark-helm-find-files-p))
+
+(defun helm-bookmark-browse-project (candidate)
+ "Run `helm-browse-project' from action."
+ (with-helm-default-directory
+ (bookmark-get-filename candidate)
+ (helm-browse-project nil)))
+
+(defun helm-bookmark-run-browse-project ()
+ "Run `helm-bookmark-browse-project' from keyboard."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-bookmark-browse-project)))
+(put 'helm-bookmark-run-browse-project 'helm-only t)
+
+(defvar helm-bookmark-find-files-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map helm-bookmark-map)
+ (define-key map (kbd "C-x C-d") 'helm-bookmark-run-browse-project)
+ map))
+
+(defclass helm-bookmark-override-inheritor (helm-source) ())
+
+(defmethod helm--setup-source ((source helm-bookmark-override-inheritor))
+ ;; Ensure `helm-source-in-buffer' method is called.
+ (call-next-method)
+ (setf (slot-value source 'action)
+ (helm-append-at-nth
+ (cl-loop for (name . action) in helm-type-bookmark-actions
+ unless (memq action '(helm-bookmark-jump-other-frame
+ helm-bookmark-jump-other-window))
+ collect (cons name action))
+ '(("Browse project" . helm-bookmark-browse-project)) 1))
+ (setf (slot-value source 'keymap) helm-bookmark-find-files-map))
+
+(defclass helm-bookmark-find-files-class (helm-source-filtered-bookmarks
+ helm-bookmark-override-inheritor)
+ ())
+
+(defvar helm-source-bookmark-helm-find-files
+ (helm-make-source "Bookmark helm-find-files sessions" 'helm-bookmark-find-files-class
+ :init (lambda ()
+ (bookmark-maybe-load-default-file)
+ (helm-init-candidates-in-buffer
+ 'global (helm-bookmark-helm-find-files-setup-alist)))
+ :persistent-action (lambda (_candidate) (ignore))
+ :persistent-help "Do nothing"))
+
+;;; Uncategorized bookmarks
+;;
+(defun helm-bookmark-uncategorized-setup-alist ()
+ "Specialized filter function for uncategorized bookmarks."
+ (helm-bookmark-filter-setup-alist 'helm-bookmark-uncategorized-bookmark-p))
+
+(defvar helm-source-bookmark-uncategorized
+ (helm-make-source "Bookmark uncategorized" 'helm-source-filtered-bookmarks
+ :init (lambda ()
+ (bookmark-maybe-load-default-file)
+ (helm-init-candidates-in-buffer
+ 'global (helm-bookmark-uncategorized-setup-alist)))))
+
+;;; Transformer
+;;
+\f
+(defun helm-highlight-bookmark (bookmarks _source)
+ "Used as `filtered-candidate-transformer' to colorize bookmarks."
+ (let ((non-essential t))
+ (cl-loop for i in bookmarks
+ for isfile = (bookmark-get-filename i)
+ for hff = (helm-bookmark-helm-find-files-p i)
+ for handlerp = (and (fboundp 'bookmark-get-handler)
+ (bookmark-get-handler i))
+ for isw3m = (and (fboundp 'helm-bookmark-w3m-bookmark-p)
+ (helm-bookmark-w3m-bookmark-p i))
+ for isgnus = (and (fboundp 'helm-bookmark-gnus-bookmark-p)
+ (helm-bookmark-gnus-bookmark-p i))
+ for isman = (and (fboundp 'helm-bookmark-man-bookmark-p) ; Man
+ (helm-bookmark-man-bookmark-p i))
+ for iswoman = (and (fboundp 'helm-bookmark-woman-bookmark-p) ; Woman
+ (helm-bookmark-woman-bookmark-p i))
+ for isannotation = (bookmark-get-annotation i)
+ for isabook = (string= (bookmark-prop-get i 'type)
+ "addressbook")
+ for isinfo = (eq handlerp 'Info-bookmark-jump)
+ for loc = (bookmark-location i)
+ for len = (string-width i)
+ for trunc = (if (and helm-bookmark-show-location
+ (> len bookmark-bmenu-file-column))
+ (helm-substring
+ i bookmark-bmenu-file-column)
+ i)
+ ;; Add a * if bookmark have annotation
+ if (and isannotation (not (string-equal isannotation "")))
+ do (setq trunc (concat "*" (if helm-bookmark-show-location trunc i)))
+ for sep = (and helm-bookmark-show-location
+ (make-string (- (+ bookmark-bmenu-file-column 2)
+ (string-width trunc))
+ ? ))
+ for bmk = (cond ( ;; info buffers
+ isinfo
+ (propertize trunc 'face 'helm-bookmark-info
+ 'help-echo isfile))
+ ( ;; w3m buffers
+ isw3m
+ (propertize trunc 'face 'helm-bookmark-w3m
+ 'help-echo isfile))
+ ( ;; gnus buffers
+ isgnus
+ (propertize trunc 'face 'helm-bookmark-gnus
+ 'help-echo isfile))
+ ( ;; Man Woman
+ (or iswoman isman)
+ (propertize trunc 'face 'helm-bookmark-man
+ 'help-echo isfile))
+ ( ;; Addressbook
+ isabook
+ (propertize trunc 'face 'helm-bookmark-addressbook))
+ (;; Directories (helm-find-files)
+ hff
+ (if (and (file-remote-p isfile)
+ (not (file-remote-p isfile nil t)))
+ (propertize trunc 'face 'helm-bookmark-file-not-found
+ 'help-echo isfile)
+ (propertize trunc 'face 'helm-bookmark-directory
+ 'help-echo isfile)))
+ ( ;; Directories (dired)
+ (and isfile
+ ;; This is needed because `non-essential'
+ ;; is not working on Emacs-24.2 and the behavior
+ ;; of tramp seems to have changed since previous
+ ;; versions (Need to reenter password even if a
+ ;; first connection have been established,
+ ;; probably when host is named differently
+ ;; i.e machine/localhost)
+ (and (not (file-remote-p isfile))
+ (file-directory-p isfile)))
+ (propertize trunc 'face 'helm-bookmark-directory
+ 'help-echo isfile))
+ ( ;; Non existing files.
+ (and isfile
+ ;; Be safe and call `file-exists-p'
+ ;; only if file is not remote or
+ ;; remote but connected.
+ (or (and (file-remote-p isfile)
+ (not (file-remote-p isfile nil t)))
+ (not (file-exists-p isfile))))
+ (propertize trunc 'face 'helm-bookmark-file-not-found
+ 'help-echo isfile))
+ ( ;; regular files
+ t
+ (propertize trunc 'face 'helm-bookmark-file
+ 'help-echo isfile)))
+ collect (if helm-bookmark-show-location
+ (cons (concat bmk sep (if (listp loc) (car loc) loc))
+ i)
+ (cons bmk i)))))
+
+\f
+;;; Edit/rename/save bookmarks.
+;;
+;;
+(defun helm-bookmark-edit-bookmark (bookmark-name)
+ "Edit bookmark's name and file name, and maybe save them.
+BOOKMARK-NAME is the current (old) name of the bookmark to be renamed."
+ (let ((bmk (helm-bookmark-get-bookmark-from-name bookmark-name))
+ (handler (bookmark-prop-get bookmark-name 'handler)))
+ (if (eq handler 'addressbook-bookmark-jump)
+ (addressbook-bookmark-edit
+ (assoc bmk bookmark-alist))
+ (helm-bookmark-edit-bookmark-1 bookmark-name handler))))
+
+(defun helm-bookmark-edit-bookmark-1 (bookmark-name handler)
+ (let* ((helm--reading-passwd-or-string t)
+ (bookmark-fname (bookmark-get-filename bookmark-name))
+ (bookmark-loc (bookmark-prop-get bookmark-name 'location))
+ (new-name (read-from-minibuffer "Name: " bookmark-name))
+ (new-loc (read-from-minibuffer "FileName or Location: "
+ (or bookmark-fname
+ (if (consp bookmark-loc)
+ (car bookmark-loc)
+ bookmark-loc))))
+ (docid (and (eq handler 'mu4e-bookmark-jump)
+ (read-number "Docid: " (cdr bookmark-loc)))))
+ (when docid
+ (setq new-loc (cons new-loc docid)))
+ (when (and (not (equal new-name "")) (not (equal new-loc ""))
+ (y-or-n-p "Save changes? "))
+ (if bookmark-fname
+ (progn
+ (helm-bookmark-rename bookmark-name new-name 'batch)
+ (bookmark-set-filename new-name new-loc))
+ (bookmark-prop-set
+ (bookmark-get-bookmark bookmark-name) 'location new-loc)
+ (helm-bookmark-rename bookmark-name new-name 'batch))
+ (helm-bookmark-maybe-save-bookmark)
+ (list new-name new-loc))))
+
+(defun helm-bookmark-maybe-save-bookmark ()
+ "Increment save counter and maybe save `bookmark-alist'."
+ (setq bookmark-alist-modification-count (1+ bookmark-alist-modification-count))
+ (when (bookmark-time-to-save-p) (bookmark-save)))
+
+(defun helm-bookmark-rename (old &optional new batch)
+ "Change bookmark's name from OLD to NEW.
+Interactively:
+ If called from the keyboard, then prompt for OLD.
+ If called from the menubar, select OLD from a menu.
+If NEW is nil, then prompt for its string value.
+
+If BATCH is non-nil, then do not rebuild the menu list.
+
+While the user enters the new name, repeated `C-w' inserts consecutive
+words from the buffer into the new bookmark name."
+ (interactive (list (bookmark-completing-read "Old bookmark name")))
+ (bookmark-maybe-historicize-string old)
+ (bookmark-maybe-load-default-file)
+ (save-excursion (skip-chars-forward " ") (setq bookmark-yank-point (point)))
+ (setq bookmark-current-buffer (current-buffer))
+ (let ((newname (or new (read-from-minibuffer
+ "New name: " nil
+ (let ((now-map (copy-keymap minibuffer-local-map)))
+ (define-key now-map "\C-w" 'bookmark-yank-word)
+ now-map)
+ nil 'bookmark-history))))
+ (bookmark-set-name old newname)
+ (setq bookmark-current-bookmark newname)
+ (unless batch (bookmark-bmenu-surreptitiously-rebuild-list))
+ (helm-bookmark-maybe-save-bookmark) newname))
+
+(defun helm-bookmark-run-edit ()
+ "Run `helm-bookmark-edit-bookmark' from keyboard."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-bookmark-edit-bookmark)))
+(put 'helm-bookmark-run-edit 'helm-only t)
+
+\f
+(defun helm-bookmark-run-jump-other-frame ()
+ "Jump to bookmark other frame from keyboard."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-bookmark-jump-other-frame)))
+(put 'helm-bookmark-run-jump-other-frame 'helm-only t)
+
+(defun helm-bookmark-run-jump-other-window ()
+ "Jump to bookmark from keyboard."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-bookmark-jump-other-window)))
+(put 'helm-bookmark-run-jump-other-window 'helm-only t)
+
+(defun helm-bookmark-run-delete ()
+ "Delete bookmark from keyboard."
+ (interactive)
+ (with-helm-alive-p
+ (when (y-or-n-p "Delete bookmark(s)?")
+ (helm-exit-and-execute-action 'helm-delete-marked-bookmarks))))
+(put 'helm-bookmark-run-delete 'helm-only t)
+
+(defun helm-bookmark-get-bookmark-from-name (bmk)
+ "Return bookmark name even if it is a bookmark with annotation.
+e.g prepended with *."
+ (let ((bookmark (replace-regexp-in-string "\\`\\*" "" bmk)))
+ (if (assoc bookmark bookmark-alist) bookmark bmk)))
+
+(defun helm-delete-marked-bookmarks (_ignore)
+ "Delete this bookmark or all marked bookmarks."
+ (cl-dolist (i (helm-marked-candidates))
+ (bookmark-delete (helm-bookmark-get-bookmark-from-name i)
+ 'batch)))
+
+
+;;;###autoload
+(defun helm-bookmarks ()
+ "Preconfigured `helm' for bookmarks."
+ (interactive)
+ (helm :sources '(helm-source-bookmarks
+ helm-source-bookmark-set)
+ :buffer "*helm bookmarks*"
+ :default (buffer-name helm-current-buffer)))
+
+;;;###autoload
+(defun helm-filtered-bookmarks ()
+ "Preconfigured helm for bookmarks (filtered by category).
+Optional source `helm-source-bookmark-addressbook' is loaded
+only if external addressbook-bookmark package is installed."
+ (interactive)
+ (helm :sources helm-bookmark-default-filtered-sources
+ :prompt "Search Bookmark: "
+ :buffer "*helm filtered bookmarks*"
+ :default (list (thing-at-point 'symbol)
+ (buffer-name helm-current-buffer))))
+
+(provide 'helm-bookmark)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-bookmark.el ends here
--- /dev/null
+;;; helm-buffers.el --- helm support for buffers. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Code:
+\f
+(require 'cl-lib)
+(require 'helm)
+(require 'helm-types)
+(require 'helm-utils)
+(require 'helm-grep)
+(require 'helm-regexp)
+(require 'helm-help)
+
+(declare-function ido-make-buffer-list "ido" (default))
+(declare-function ido-add-virtual-buffers-to-list "ido")
+(declare-function helm-comp-read "helm-mode")
+(declare-function helm-browse-project "helm-files")
+
+\f
+(defgroup helm-buffers nil
+ "Buffers related Applications and libraries for Helm."
+ :group 'helm)
+
+(defcustom helm-boring-buffer-regexp-list
+ '("\\` " "\\`\\*helm" "\\`\\*Echo Area" "\\`\\*Minibuf")
+ "The regexp list that match boring buffers.
+Buffer candidates matching these regular expression will be
+filtered from the list of candidates if the
+`helm-skip-boring-buffers' candidate transformer is used."
+ :type '(repeat (choice regexp))
+ :group 'helm-buffers)
+
+(defcustom helm-white-buffer-regexp-list nil
+ "The regexp list of not boring buffers.
+These buffers will be displayed even if they match one of
+`helm-boring-buffer-regexp-list'."
+ :type '(repeat (choice regexp))
+ :group 'helm-buffers)
+
+(defcustom helm-buffers-favorite-modes '(lisp-interaction-mode
+ emacs-lisp-mode
+ text-mode
+ org-mode)
+ "List of preferred mode to open new buffers with."
+ :type '(repeat (choice function))
+ :group 'helm-buffers)
+
+(defcustom helm-buffer-max-length 20
+ "Max length of buffer names before truncate.
+When disabled (nil) use the longest buffer-name length found."
+ :group 'helm-buffers
+ :type '(choice (const :tag "Disabled" nil)
+ (integer :tag "Length before truncate")))
+
+(defcustom helm-buffer-details-flag t
+ "Always show details in buffer list when non--nil."
+ :group 'helm-buffers
+ :type 'boolean)
+
+(defcustom helm-buffers-fuzzy-matching nil
+ "Fuzzy matching buffer names when non--nil.
+Only buffer names are fuzzy matched when this is enabled,
+`major-mode' matching is not affected by this."
+ :group 'helm-buffers
+ :type 'boolean)
+
+(defcustom helm-buffer-skip-remote-checking nil
+ "Ignore checking for `file-exists-p' on remote files."
+ :group 'helm-buffers
+ :type 'boolean)
+
+(defcustom helm-buffers-truncate-lines t
+ "Truncate lines in `helm-buffers-list' when non--nil."
+ :group 'helm-buffers
+ :type 'boolean)
+
+(defcustom helm-mini-default-sources '(helm-source-buffers-list
+ helm-source-recentf
+ helm-source-buffer-not-found)
+ "Default sources list used in `helm-mini'.
+
+When adding a source here it is up to you to ensure the library of
+this source is accessible and properly loaded."
+ :group 'helm-buffers
+ :type '(repeat (choice symbol)))
+
+(defcustom helm-buffers-end-truncated-string "..."
+ "The string to display at end of truncated buffer names."
+ :type 'string
+ :group 'helm-buffers)
+
+(defcustom helm-buffers-column-separator " "
+ "Separator for columns in buffer listing."
+ :type 'string
+ :group 'helm-buffers)
+
+(defcustom helm-buffer--pretty-names '((dired-mode . "Dired")
+ (lisp-interaction-mode . "Lisp Inter"))
+ "An alist specifying pretty names for modes.
+Most of the time buffer's `mode-name' is a string so no need to add it
+here as there is no need to compute it, but sometimes it may be a
+mode-line specification which may be costly to compute, in this case
+add here the pretty name as a string to avoid this costly computation.
+Also if some pretty names are too long you can add your own
+abbreviation here."
+ :type '(alist :key-type symbol :value-type string)
+ :group 'helm-buffers)
+\f
+;;; Faces
+;;
+;;
+(defgroup helm-buffers-faces nil
+ "Customize the appearance of helm-buffers."
+ :prefix "helm-"
+ :group 'helm-buffers
+ :group 'helm-faces)
+
+(defface helm-buffer-saved-out
+ '((t (:foreground "red" :background "black")))
+ "Face used for buffer files modified outside of emacs."
+ :group 'helm-buffers-faces)
+
+(defface helm-buffer-not-saved
+ '((t (:foreground "Indianred2")))
+ "Face used for buffer files not already saved on disk."
+ :group 'helm-buffers-faces)
+
+(defface helm-buffer-modified
+ '((t :inherit font-lock-comment-face))
+ "Face used for modified buffers."
+ :group 'helm-buffers-faces)
+
+(defface helm-buffer-size
+ '((((background dark)) :foreground "RosyBrown")
+ (((background light)) :foreground "SlateGray"))
+ "Face used for buffer size."
+ :group 'helm-buffers-faces)
+
+(defface helm-buffer-process
+ '((t (:foreground "Sienna3")))
+ "Face used for process status in buffer."
+ :group 'helm-buffers-faces)
+
+(defface helm-buffer-directory
+ '((t (:foreground "DarkRed" :background "LightGray")))
+ "Face used for directories in `helm-buffers-list'."
+ :group 'helm-buffers-faces)
+
+(defface helm-buffer-file
+ '((t :inherit font-lock-builtin-face))
+ "Face for buffer file names in `helm-buffers-list'."
+ :group 'helm-buffers-faces)
+
+(defface helm-buffer-archive
+ '((t (:foreground "Gold")))
+ "Face for archive file names in `helm-buffers-list'."
+ :group 'helm-buffers-faces)
+
+(defface helm-non-file-buffer
+ '((t (:inherit italic)))
+ "Face used for non-file buffers in `helm-buffers-list'."
+ :group 'helm-buffers-faces)
+
+(defvar helm-buffers-tick-counter nil
+ "Allows recording local changes to a non-file buffer.
+Typical usage of this var is for modes that want to see if
+their buffers have changed since last visit.
+Such programs may want to record tick counter after visiting their
+buffers like this:
+
+ (setq helm-buffers-tick-counter (buffer-modified-tick))
+
+Note that this variable is buffer-local.")
+(make-variable-buffer-local 'helm-buffers-tick-counter)
+
+\f
+;;; Buffers keymap
+;;
+(defvar helm-buffer-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map helm-map)
+ ;; No need to have separate command for grep and zgrep
+ ;; as we don't use recursivity for buffers.
+ ;; So use zgrep for both as it is capable to handle non--compressed files.
+ (define-key map (kbd "M-g s") 'helm-buffer-run-zgrep)
+ (define-key map (kbd "C-s") 'helm-buffers-run-multi-occur)
+ (define-key map (kbd "C-x C-d") 'helm-buffers-run-browse-project)
+ (define-key map (kbd "C-c o") 'helm-buffer-switch-other-window)
+ (define-key map (kbd "C-c C-o") 'helm-buffer-switch-other-frame)
+ (define-key map (kbd "C-c =") 'helm-buffer-run-ediff)
+ (define-key map (kbd "M-=") 'helm-buffer-run-ediff-merge)
+ (define-key map (kbd "C-=") 'helm-buffer-diff-persistent)
+ (define-key map (kbd "M-G") 'helm-buffer-revert-persistent)
+ (define-key map (kbd "C-c d") 'helm-buffer-run-kill-persistent)
+ (define-key map (kbd "M-D") 'helm-buffer-run-kill-buffers)
+ (define-key map (kbd "C-x C-s") 'helm-buffer-save-persistent)
+ (define-key map (kbd "C-M-%") 'helm-buffer-run-query-replace-regexp)
+ (define-key map (kbd "M-%") 'helm-buffer-run-query-replace)
+ (define-key map (kbd "M-R") 'helm-buffer-run-rename-buffer)
+ (define-key map (kbd "M-m") 'helm-toggle-all-marks)
+ (define-key map (kbd "M-a") 'helm-mark-all)
+ (define-key map (kbd "C-]") 'helm-toggle-buffers-details)
+ (define-key map (kbd "C-c a") 'helm-buffers-toggle-show-hidden-buffers)
+ (define-key map (kbd "C-M-SPC") 'helm-buffers-mark-similar-buffers)
+ map)
+ "Keymap for buffer sources in helm.")
+
+(defvar helm-buffers-ido-virtual-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map helm-map)
+ (define-key map (kbd "C-c o") 'helm-ff-run-switch-other-window)
+ (define-key map (kbd "C-c C-o") 'helm-ff-run-switch-other-frame)
+ (define-key map (kbd "M-g s") 'helm-ff-run-grep)
+ (define-key map (kbd "M-g z") 'helm-ff-run-zgrep)
+ (define-key map (kbd "M-D") 'helm-ff-run-delete-file)
+ (define-key map (kbd "C-c C-x") 'helm-ff-run-open-file-externally)
+ map))
+
+\f
+(defvar helm-buffer-max-len-mode nil)
+(defvar helm-buffers-in-project-p nil)
+(defvar helm-source-buffers-list nil)
+
+(defun helm-buffers-list--init ()
+ (require 'dired)
+ ;; Issue #51 Create the list before `helm-buffer' creation.
+ ;; We were using a global cache in the past and 'candidates was
+ ;; bound to this cache, this was a problem when using more than one
+ ;; source with a different 'buffer-list fn as the same cache was
+ ;; reused in each source (issue #1907), now 'candidates attr is set
+ ;; directly so that each list of candidates is local to source.
+ (helm-attrset 'candidates (funcall (helm-attr 'buffer-list)))
+ (let ((result (cl-loop with allbufs = (memq 'helm-shadow-boring-buffers
+ (helm-attr
+ 'filtered-candidate-transformer
+ helm-source-buffers-list))
+ for b in (if allbufs
+ (helm-attr 'candidates)
+ (helm-skip-boring-buffers
+ (helm-attr 'candidates)
+ helm-source-buffers-list))
+ maximize (length b) into len-buf
+ maximize (length (helm-buffer--format-mode-name b))
+ into len-mode
+ finally return (cons len-buf len-mode))))
+ (unless (default-value 'helm-buffer-max-length)
+ (helm-set-local-variable 'helm-buffer-max-length (car result)))
+ (unless (default-value 'helm-buffer-max-len-mode)
+ (helm-set-local-variable 'helm-buffer-max-len-mode (cdr result)))))
+
+(defclass helm-source-buffers (helm-source-sync helm-type-buffer)
+ ((buffer-list
+ :initarg :buffer-list
+ :initform #'helm-buffer-list
+ :custom function
+ :documentation
+ " A function with no arguments to create buffer list.")
+ (init :initform 'helm-buffers-list--init)
+ (multimatch :initform nil)
+ (match :initform 'helm-buffers-match-function)
+ (persistent-action :initform 'helm-buffers-list-persistent-action)
+ (keymap :initform helm-buffer-map)
+ (migemo :initform 'nomultimatch)
+ (volatile :initform t)
+ (nohighlight :initform t)
+ (resume :initform (lambda () (setq helm-buffers-in-project-p nil)))
+ (help-message :initform 'helm-buffer-help-message)))
+
+(defvar helm-source-buffer-not-found
+ (helm-build-dummy-source
+ "Create buffer"
+ :action (helm-make-actions
+ "Create buffer (C-u choose mode)"
+ (lambda (candidate)
+ (let ((mjm (or (and helm-current-prefix-arg
+ (intern-soft (helm-comp-read
+ "Major-mode: "
+ helm-buffers-favorite-modes)))
+ (cl-loop for (r . m) in auto-mode-alist
+ when (string-match r candidate)
+ return m)))
+ (buffer (get-buffer-create candidate)))
+ (if mjm
+ (with-current-buffer buffer (funcall mjm))
+ (set-buffer-major-mode buffer))
+ (switch-to-buffer buffer))))))
+
+(defvar ido-temp-list)
+(defvar ido-ignored-list)
+(defvar ido-process-ignore-lists)
+(defvar ido-use-virtual-buffers)
+(defvar ido-virtual-buffers)
+
+(defvar helm-source-ido-virtual-buffers
+ (helm-build-sync-source "Ido virtual buffers"
+ :candidates (lambda ()
+ (let (ido-temp-list
+ ido-ignored-list
+ (ido-process-ignore-lists t))
+ (when ido-use-virtual-buffers
+ (ido-add-virtual-buffers-to-list)
+ ido-virtual-buffers)))
+ :fuzzy-match helm-buffers-fuzzy-matching
+ :keymap helm-buffers-ido-virtual-map
+ :help-message 'helm-buffers-ido-virtual-help-message
+ :action '(("Find file" . helm-find-many-files)
+ ("Find file other window" . find-file-other-window)
+ ("Find file other frame" . find-file-other-frame)
+ ("Find file as root" . helm-find-file-as-root)
+ ("Grep File(s) `C-u recurse'" . helm-find-files-grep)
+ ("Zgrep File(s) `C-u Recurse'" . helm-ff-zgrep)
+ ("View file" . view-file)
+ ("Delete file(s)" . helm-delete-marked-files)
+ ("Open file externally (C-u to choose)"
+ . helm-open-file-externally))))
+
+\f
+(defvar ido-use-virtual-buffers)
+(defvar ido-ignore-buffers)
+(defun helm-buffer-list ()
+ "Return the current list of buffers.
+Currently visible buffers are put at the end of the list.
+See `ido-make-buffer-list' for more infos."
+ (require 'ido)
+ (let ((ido-process-ignore-lists t)
+ ido-ignored-list
+ ido-ignore-buffers
+ ido-use-virtual-buffers)
+ (ido-make-buffer-list nil)))
+
+(defun helm-buffer-size (buffer)
+ "Return size of BUFFER."
+ (with-current-buffer buffer
+ (save-restriction
+ (widen)
+ (helm-file-human-size
+ (- (position-bytes (point-max))
+ (position-bytes (point-min)))))))
+
+(defun helm-buffer--show-details (buf-name prefix help-echo
+ size mode dir face1 face2
+ proc details type)
+ (append
+ (list
+ (concat prefix
+ (propertize buf-name 'face face1
+ 'help-echo help-echo
+ 'type type)))
+ (and details
+ (list size mode
+ (propertize
+ (if proc
+ (format "(%s %s in `%s')"
+ (process-name proc)
+ (process-status proc) dir)
+ (format "(in `%s')" dir))
+ 'face face2)))))
+
+(defun helm-buffer--format-mode-name (buf)
+ "Prevent using `format-mode-line' as much as possible."
+ (with-current-buffer buf
+ (helm-acond ((assq major-mode helm-buffer--pretty-names)
+ (cdr it))
+ ((stringp mode-name) mode-name)
+ (t (format-mode-line mode-name)))))
+
+(defun helm-buffer--details (buffer &optional details)
+ (require 'dired)
+ (let* ((mode (helm-buffer--format-mode-name buffer))
+ (buf (get-buffer buffer))
+ (size (propertize (helm-buffer-size buf)
+ 'face 'helm-buffer-size))
+ (proc (get-buffer-process buf))
+ (dir (with-current-buffer buffer
+ (helm-aif default-directory (abbreviate-file-name it))))
+ (file-name (helm-aif (buffer-file-name buf) (abbreviate-file-name it)))
+ (name (buffer-name buf))
+ (name-prefix (when (and dir (file-remote-p dir))
+ (propertize "@ " 'face 'helm-ff-prefix)))
+ (archive-p (and (fboundp 'tramp-archive-file-name-p)
+ (tramp-archive-file-name-p dir))))
+ (when name-prefix
+ ;; Remote tramp buffer names may be hexified, make them more readable.
+ (setq dir (helm-url-unhex-string dir)
+ name (helm-url-unhex-string name)))
+ ;; Handle tramp archive buffers specially.
+ (if archive-p
+ (helm-buffer--show-details
+ name name-prefix file-name size mode dir
+ 'helm-buffer-archive 'helm-buffer-process nil details 'filebuf)
+ ;; No fancy things on remote buffers.
+ (if (and name-prefix helm-buffer-skip-remote-checking)
+ (helm-buffer--show-details
+ name name-prefix file-name size mode dir
+ 'helm-buffer-file 'helm-buffer-process nil details 'filebuf)
+ (cond
+ (;; A dired buffer.
+ (rassoc buf dired-buffers)
+ (helm-buffer--show-details
+ name name-prefix dir size mode dir
+ 'helm-buffer-directory 'helm-buffer-process nil details 'dired))
+ ;; A buffer file modified somewhere outside of emacs.=>red
+ ((and file-name
+ (file-exists-p file-name)
+ (not (verify-visited-file-modtime buf)))
+ (helm-buffer--show-details
+ name name-prefix file-name size mode dir
+ 'helm-buffer-saved-out 'helm-buffer-process nil details 'modout))
+ ;; A new buffer file not already saved on disk (or a deleted file) .=>indianred2
+ ((and file-name (not (file-exists-p file-name)))
+ (helm-buffer--show-details
+ name name-prefix file-name size mode dir
+ 'helm-buffer-not-saved 'helm-buffer-process nil details 'notsaved))
+ ;; A buffer file modified and not saved on disk.=>orange
+ ((and file-name (buffer-modified-p buf))
+ (helm-buffer--show-details
+ name name-prefix file-name size mode dir
+ 'helm-buffer-modified 'helm-buffer-process nil details 'mod))
+ ;; A buffer file not modified and saved on disk.=>green
+ (file-name
+ (helm-buffer--show-details
+ name name-prefix file-name size mode dir
+ 'helm-buffer-file 'helm-buffer-process nil details 'filebuf))
+ ;; A non-file, modified buffer
+ ((with-current-buffer name
+ (and helm-buffers-tick-counter
+ (/= helm-buffers-tick-counter (buffer-modified-tick))))
+ (helm-buffer--show-details
+ name (and proc name-prefix) dir size mode dir
+ 'helm-buffer-modified 'helm-buffer-process proc details 'nofile-mod))
+ ;; Any non--file buffer.=>italic
+ (t
+ (helm-buffer--show-details
+ name (and proc name-prefix) dir size mode dir
+ 'helm-non-file-buffer 'helm-buffer-process proc details 'nofile)))))))
+
+(defun helm-highlight-buffers (buffers _source)
+ "Transformer function to highlight BUFFERS list.
+Should be called after others transformers i.e (boring buffers)."
+ (cl-loop for i in buffers
+ for (name size mode meta) = (if helm-buffer-details-flag
+ (helm-buffer--details i 'details)
+ (helm-buffer--details i))
+ for truncbuf = (if (> (string-width name) helm-buffer-max-length)
+ (helm-substring-by-width
+ name helm-buffer-max-length
+ helm-buffers-end-truncated-string)
+ (concat name
+ (make-string
+ (- (+ helm-buffer-max-length
+ (length
+ helm-buffers-end-truncated-string))
+ (string-width name))
+ ? )))
+ for len = (length mode)
+ when (> len helm-buffer-max-len-mode)
+ do (setq helm-buffer-max-len-mode len)
+ for fmode = (concat (make-string
+ (- (max helm-buffer-max-len-mode len) len) ? )
+ mode)
+ ;; The max length of a number should be 1023.9X where X is the
+ ;; units, this is 7 characters.
+ for formatted-size = (and size (format "%7s" size))
+ collect (let ((helm-pattern (helm-buffers--pattern-sans-filters
+ (and helm-buffers-fuzzy-matching ""))))
+ (cons (if helm-buffer-details-flag
+ (concat
+ (funcall helm-fuzzy-matching-highlight-fn
+ truncbuf)
+ helm-buffers-column-separator
+ formatted-size
+ helm-buffers-column-separator
+ fmode
+ helm-buffers-column-separator
+ meta)
+ (funcall helm-fuzzy-matching-highlight-fn name))
+ (get-buffer i)))))
+
+(defun helm-buffer--get-preselection (buffer)
+ (let ((bufname (buffer-name buffer)))
+ (when (and bufname
+ (file-remote-p (with-current-buffer bufname
+ default-directory)))
+ (setq bufname (concat "@ " (helm-url-unhex-string bufname))))
+ (concat "^"
+ (if (and (null helm-buffer-details-flag)
+ (numberp helm-buffer-max-length)
+ (> (string-width bufname)
+ helm-buffer-max-length))
+ (regexp-quote
+ (helm-substring-by-width
+ bufname helm-buffer-max-length
+ helm-buffers-end-truncated-string))
+ (concat (regexp-quote bufname)
+ (if helm-buffer-details-flag
+ "$" "[[:blank:]]+"))))))
+
+(defun helm-toggle-buffers-details ()
+ (interactive)
+ (with-helm-alive-p
+ (let* ((buf (helm-get-selection))
+ (preselect (helm-buffer--get-preselection buf)))
+ (setq helm-buffer-details-flag (not helm-buffer-details-flag))
+ (helm-update (lambda ()
+ (helm-awhile (re-search-forward preselect nil t)
+ (helm-mark-current-line)
+ (when (equal buf (helm-get-selection))
+ (cl-return t))))))))
+(put 'helm-toggle-buffers-details 'helm-only t)
+
+(defun helm-buffers--pattern-sans-filters (&optional separator)
+ (cl-loop for p in (helm-mm-split-pattern helm-pattern)
+ unless (member (substring p 0 1) '("*" "/" "@" "!"))
+ collect p into lst
+ finally return (mapconcat 'identity lst (or separator " "))))
+
+(defun helm-buffers-sort-transformer (candidates source)
+ (if (string= helm-pattern "")
+ candidates
+ (if helm-buffers-fuzzy-matching
+ (let ((helm-pattern (helm-buffers--pattern-sans-filters)))
+ (funcall helm-fuzzy-sort-fn candidates source))
+ (sort candidates
+ (lambda (s1 s2)
+ (< (string-width s1) (string-width s2)))))))
+
+(defun helm-buffers-mark-similar-buffers-1 ()
+ (with-helm-window
+ (let* ((src (helm-get-current-source))
+ (type (get-text-property
+ 0 'type (helm-get-selection nil 'withprop src))))
+ (save-excursion
+ (goto-char (helm-get-previous-header-pos))
+ (helm-next-line)
+ (let* ((next-head (helm-get-next-header-pos))
+ (end (and next-head
+ (save-excursion
+ (goto-char next-head)
+ (forward-line -1)
+ (point))))
+ (maxpoint (or end (point-max))))
+ (while (< (point) maxpoint)
+ (helm-mark-current-line)
+ (let ((cand (helm-get-selection nil 'withprop src)))
+ (when (and (not (helm-this-visible-mark))
+ (eq (get-text-property 0 'type cand) type))
+ (helm-make-visible-mark)))
+ (forward-line 1) (end-of-line))))
+ (helm-mark-current-line)
+ (helm-display-mode-line src t)
+ (message "%s candidates marked" (length helm-marked-candidates)))))
+
+(defun helm-buffers-mark-similar-buffers ()
+ "Mark All buffers that have same property `type' than current.
+i.e same color."
+ (interactive)
+ (with-helm-alive-p
+ (let ((marked (helm-marked-candidates)))
+ (if (and (>= (length marked) 1)
+ (with-helm-window helm-visible-mark-overlays))
+ (helm-unmark-all)
+ (helm-buffers-mark-similar-buffers-1)))))
+(put 'helm-buffers-mark-similar-buffers 'helm-only t)
+
+\f
+;;; match functions
+;;
+(defun helm-buffer--match-mjm (pattern mjm)
+ (when (string-match "\\`\\*" pattern)
+ (cl-loop with patterns = (split-string (substring pattern 1) ",")
+ for pat in patterns
+ if (string-match "\\`!" pat)
+ collect (string-match (substring pat 1) mjm) into neg
+ else collect (string-match pat mjm) into pos
+ finally return
+ (let ((neg-test (cl-loop for i in neg thereis (numberp i)))
+ (pos-test (cl-loop for i in pos thereis (numberp i))))
+ (or
+ (and neg (not pos) (not neg-test))
+ (and pos pos-test)
+ (and neg neg-test (not neg-test)))))))
+
+(defvar helm-buffer--memo-hash (make-hash-table :test 'equal))
+(defun helm-buffer--memo-pattern (pattern)
+ (or (gethash pattern helm-buffer--memo-hash)
+ (puthash pattern (helm--mapconcat-pattern pattern)
+ helm-buffer--memo-hash)))
+
+(defun helm-buffer--match-pattern (pattern candidate &optional nofuzzy)
+ (let ((bfn (if (and helm-buffers-fuzzy-matching
+ (not nofuzzy)
+ (not helm-migemo-mode)
+ (not (string-match "\\`\\^" pattern)))
+ #'helm-buffer--memo-pattern
+ #'identity))
+ (mfn (if helm-migemo-mode
+ #'helm-mm-migemo-string-match #'string-match)))
+ (if (string-match "\\`!" pattern)
+ (not (funcall mfn (funcall bfn (substring pattern 1))
+ candidate))
+ (funcall mfn (funcall bfn pattern) candidate))))
+
+(defun helm-buffers--match-from-mjm (candidate)
+ (let* ((cand (replace-regexp-in-string "^\\s-\\{1\\}" "" candidate))
+ (buf (get-buffer cand))
+ (regexp (cl-loop with pattern = helm-pattern
+ for p in (helm-mm-split-pattern pattern)
+ when (string-match "\\`\\*" p)
+ return p)))
+ (if regexp
+ (when buf
+ (with-current-buffer buf
+ (let ((mjm (symbol-name major-mode)))
+ (helm-buffer--match-mjm regexp mjm))))
+ t)))
+
+(defun helm-buffers--match-from-pat (candidate)
+ (let* ((regexp-list (cl-loop with pattern = helm-pattern
+ for p in (helm-mm-split-pattern pattern)
+ unless (string-match
+ "\\`\\(\\*\\|/\\|@\\)" p)
+ collect p))
+ (nofuzzy (cdr regexp-list)))
+ (if regexp-list
+ (cl-loop for re in regexp-list
+ always (helm-buffer--match-pattern re candidate nofuzzy))
+ t)))
+
+(defun helm-buffers--match-from-inside (candidate)
+ (let* ((cand (replace-regexp-in-string "^\\s-\\{1\\}" "" candidate))
+ (buf (get-buffer cand))
+ (regexp (cl-loop with pattern = helm-pattern
+ for p in (helm-mm-split-pattern pattern)
+ when (string-match "\\`@\\(.*\\)" p)
+ return (match-string 1 p))))
+ (if (and buf regexp)
+ (with-current-buffer buf
+ (save-excursion
+ (goto-char (point-min))
+ (if helm-migemo-mode
+ (helm-mm-migemo-forward regexp nil t)
+ (re-search-forward regexp nil t))))
+ t)))
+
+(defun helm-buffers--match-from-directory (candidate)
+ (let* ((cand (replace-regexp-in-string "^\\s-\\{1\\}" "" candidate))
+ (buf (get-buffer cand))
+ (buf-fname (or (buffer-file-name buf)
+ (car-safe (rassoc buf dired-buffers))))
+ (regexps (cl-loop with pattern = helm-pattern
+ for p in (helm-mm-split-pattern pattern)
+ when (string-match "\\`/" p)
+ collect p)))
+ (if regexps
+ (cl-loop for re in regexps
+ thereis
+ (and buf-fname
+ (string-match
+ (substring re 1) (helm-basedir buf-fname))))
+ t)))
+
+(defun helm-buffers-match-function (candidate)
+ "Default function to match buffers."
+ (and (helm-buffers--match-from-pat candidate)
+ (helm-buffers--match-from-mjm candidate)
+ (helm-buffers--match-from-inside candidate)
+ (helm-buffers--match-from-directory candidate)))
+
+\f
+(defun helm-buffer-query-replace-1 (&optional regexp-flag buffers)
+ "Query replace in marked buffers.
+If REGEXP-FLAG is given use `query-replace-regexp'."
+ (let ((prompt (if regexp-flag "Query replace regexp" "Query replace"))
+ (bufs (or buffers (helm-marked-candidates)))
+ (helm--reading-passwd-or-string t))
+ (cl-loop with args = (query-replace-read-args prompt regexp-flag t)
+ for buf in bufs
+ do
+ (save-window-excursion
+ (switch-to-buffer buf)
+ (save-excursion
+ (let ((case-fold-search t))
+ (goto-char (point-min))
+ (apply #'perform-replace
+ (list (nth 0 args) (nth 1 args)
+ t regexp-flag (nth 2 args) nil
+ multi-query-replace-map))))))))
+
+(defun helm-buffer-query-replace-regexp (_candidate)
+ (helm-buffer-query-replace-1 'regexp))
+
+(defun helm-buffer-query-replace (_candidate)
+ (helm-buffer-query-replace-1))
+
+(defun helm-buffer-toggle-diff (candidate)
+ "Toggle diff buffer CANDIDATE with it's file."
+ (helm-aif (get-buffer-window "*Diff*" 'visible)
+ (progn (kill-buffer "*Diff*")
+ (set-window-buffer it helm-current-buffer))
+ (diff-buffer-with-file (get-buffer candidate))))
+
+(defun helm-buffer-diff-persistent ()
+ "Toggle diff buffer without quitting helm."
+ (interactive)
+ (with-helm-alive-p
+ (helm-attrset 'diff-action 'helm-buffer-toggle-diff)
+ (helm-execute-persistent-action 'diff-action)))
+(put 'helm-buffer-diff-persistent 'helm-only t)
+
+(defun helm-revert-buffer (candidate)
+ (with-current-buffer candidate
+ (helm-aif (buffer-file-name)
+ (and (file-exists-p it) (revert-buffer t t)))))
+
+(defun helm-revert-marked-buffers (_ignore)
+ (mapc 'helm-revert-buffer (helm-marked-candidates)))
+
+(defun helm-buffer-revert-and-update (_candidate)
+ (with-helm-buffer
+ (let ((marked (helm-marked-candidates))
+ (preselect (helm-buffers--quote-truncated-buffer
+ (helm-get-selection))))
+ (cl-loop for buf in marked do (helm-revert-buffer buf))
+ (when helm-marked-candidates (helm-unmark-all))
+ (helm-update preselect))))
+
+(defun helm-buffer-revert-persistent ()
+ "Revert buffer without quitting helm."
+ (interactive)
+ (with-helm-alive-p
+ (helm-attrset 'revert-action '(helm-buffer-revert-and-update . never-split))
+ (helm-execute-persistent-action 'revert-action)))
+(put 'helm-buffer-revert-persistent 'helm-only t)
+
+(defun helm-buffer-save-and-update (_candidate)
+ (with-helm-buffer
+ (let ((marked (helm-marked-candidates))
+ (preselect (helm-get-selection nil t))
+ (enable-recursive-minibuffers t))
+ (cl-loop for buf in marked do
+ (with-current-buffer (get-buffer buf)
+ (when (buffer-file-name) (save-buffer))))
+ (when helm-marked-candidates (helm-unmark-all))
+ (helm-update (regexp-quote preselect)))))
+
+(defun helm-buffer-save-persistent ()
+ "Save buffer without quitting helm."
+ (interactive)
+ (with-helm-alive-p
+ (helm-attrset 'save-action '(helm-buffer-save-and-update . never-split))
+ (helm-execute-persistent-action 'save-action)))
+(put 'helm-buffer-save-persistent 'helm-only t)
+
+(defun helm-buffers-rename-buffer (candidate)
+ (with-current-buffer candidate
+ (rename-buffer (helm-read-string "New name: " (buffer-name)) t)))
+
+(defun helm-buffer-run-rename-buffer ()
+ "Run rename buffer action from `helm-source-buffers-list'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-buffers-rename-buffer)))
+(put 'helm-buffer-run-rename-buffer 'helm-only t)
+
+(defun helm-buffer-run-kill-persistent ()
+ "Kill buffer without quitting helm."
+ (interactive)
+ (with-helm-alive-p
+ (helm-attrset 'kill-action '(helm-buffers-persistent-kill . never-split))
+ (helm-execute-persistent-action 'kill-action)))
+(put 'helm-buffer-run-kill-persistent 'helm-only t)
+
+(defun helm-kill-marked-buffers (_ignore)
+ (let* ((bufs (helm-marked-candidates))
+ (killed-bufs (cl-count-if 'kill-buffer bufs)))
+ (when (buffer-live-p helm-buffer)
+ (with-helm-buffer
+ (setq helm-marked-candidates nil
+ helm-visible-mark-overlays nil)))
+ (message "Killed %s buffer(s)" killed-bufs)))
+
+(defun helm-buffer-run-kill-buffers ()
+ "Run kill buffer action from `helm-source-buffers-list'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-kill-marked-buffers)))
+(put 'helm-buffer-run-kill-buffers 'helm-only t)
+
+(defun helm-buffer-run-grep ()
+ "Run Grep action from `helm-source-buffers-list'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-grep-buffers)))
+(put 'helm-buffer-run-grep 'helm-only t)
+
+(defun helm-buffer-run-zgrep ()
+ "Run Grep action from `helm-source-buffers-list'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-zgrep-buffers)))
+(put 'helm-buffer-run-zgrep 'helm-only t)
+
+(defun helm-buffer-run-query-replace-regexp ()
+ "Run Query replace regexp action from `helm-source-buffers-list'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-buffer-query-replace-regexp)))
+(put 'helm-buffer-run-query-replace-regexp 'helm-only t)
+
+(defun helm-buffer-run-query-replace ()
+ "Run Query replace action from `helm-source-buffers-list'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-buffer-query-replace)))
+(put 'helm-buffer-run-query-replace 'helm-only t)
+
+(defun helm-buffer-switch-other-window ()
+ "Run switch to other window action from `helm-source-buffers-list'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-buffer-switch-buffers-other-window)))
+(put 'helm-buffer-switch-other-window 'helm-only t)
+
+(defun helm-buffer-switch-other-frame ()
+ "Run switch to other frame action from `helm-source-buffers-list'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'switch-to-buffer-other-frame)))
+(put 'helm-buffer-switch-other-frame 'helm-only t)
+
+(defun helm-buffer-switch-buffers (_candidate)
+ "Switch to buffer candidates and replace current buffer.
+
+If more than one buffer marked switch to these buffers in separate windows.
+If a prefix arg is given split windows vertically."
+ (let ((buffers (helm-marked-candidates)))
+ (helm-window-show-buffers buffers)))
+
+(defun helm-buffer-switch-buffers-other-window (_candidate)
+ "Switch to marked buffers in other windows."
+ (let ((buffers (helm-marked-candidates)))
+ (helm-window-show-buffers buffers t)))
+
+(defun helm-buffer-run-ediff ()
+ "Run ediff action from `helm-source-buffers-list'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-ediff-marked-buffers)))
+(put 'helm-buffer-run-ediff 'helm-only t)
+
+(defun helm-buffer-run-ediff-merge ()
+ "Run ediff action from `helm-source-buffers-list'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-ediff-marked-buffers-merge)))
+(put 'helm-buffer-run-ediff-merge 'helm-only t)
+
+(defun helm-buffers-persistent-kill-1 (buffer-or-name)
+ "Persistent action to kill buffer."
+ (let ((buf (get-buffer buffer-or-name)) helm-buf-or-cur)
+ (if (or (and (eql buf (get-buffer helm-current-buffer))
+ (setq helm-buf-or-cur "helm-current-buffer"))
+ (and (eql buf (get-buffer helm-buffer))
+ (setq helm-buf-or-cur "helm-buffer")))
+ (progn
+ (message "Can't kill `%s' without quitting session" helm-buf-or-cur)
+ (sit-for 1))
+ (kill-buffer buf)
+ (helm-delete-current-selection))))
+
+(defun helm-buffers--quote-truncated-buffer (buffer)
+ (let ((bufname (and (bufferp buffer)
+ (buffer-name buffer))))
+ (when (and bufname
+ (file-remote-p (with-current-buffer bufname
+ default-directory)))
+ (setq bufname (concat "@ " (helm-url-unhex-string bufname))))
+ (when bufname
+ (regexp-quote
+ (if (and helm-buffer-max-length
+ helm-buffer-details-flag)
+ (helm-substring-by-width
+ bufname helm-buffer-max-length
+ "")
+ bufname)))))
+
+(defun helm-buffers-persistent-kill (_buffer)
+ (let ((marked (helm-marked-candidates))
+ (sel (helm-get-selection)))
+ (unwind-protect
+ (cl-loop for b in marked
+ do (progn
+ ;; We need to preselect each marked because
+ ;; helm-buffers-persistent-kill is deleting
+ ;; current selection.
+ (helm-preselect
+ (format "^%s"
+ (helm-buffers--quote-truncated-buffer b)))
+ (helm-buffers-persistent-kill-1 b)
+ (message nil)
+ (helm--remove-marked-and-update-mode-line b)))
+ (with-helm-buffer
+ (setq helm-marked-candidates nil
+ helm-visible-mark-overlays nil))
+ (helm-force-update (helm-buffers--quote-truncated-buffer sel)))))
+
+(defun helm-buffers-list-persistent-action (candidate)
+ (let ((current (window-buffer helm-persistent-action-display-window)))
+ (if (or (helm-follow-mode-p)
+ (eql current (get-buffer helm-current-buffer))
+ (not (eql current (get-buffer candidate))))
+ (switch-to-buffer candidate)
+ (if (and helm-persistent-action-display-window
+ (window-dedicated-p
+ (next-window helm-persistent-action-display-window 1)))
+ (delete-window helm-persistent-action-display-window)
+ (switch-to-buffer helm-current-buffer)))))
+
+(defun helm-ediff-marked-buffers (_candidate &optional merge)
+ "Ediff 2 marked buffers or CANDIDATE and `helm-current-buffer'.
+With optional arg MERGE call `ediff-merge-buffers'."
+ (let ((lg-lst (length (helm-marked-candidates)))
+ buf1 buf2)
+ (cl-case lg-lst
+ (0
+ (error "Error:You have to mark at least 1 buffer"))
+ (1
+ (setq buf1 helm-current-buffer
+ buf2 (cl-first (helm-marked-candidates))))
+ (2
+ (setq buf1 (cl-first (helm-marked-candidates))
+ buf2 (cl-second (helm-marked-candidates))))
+ (t
+ (error "Error:Too many buffers marked!")))
+ (if merge
+ (ediff-merge-buffers buf1 buf2)
+ (ediff-buffers buf1 buf2))))
+
+(defun helm-ediff-marked-buffers-merge (candidate)
+ "Ediff merge `helm-current-buffer' with CANDIDATE.
+See `helm-ediff-marked-buffers'."
+ (helm-ediff-marked-buffers candidate t))
+
+(defun helm-multi-occur-as-action (_candidate)
+ "Multi occur action for `helm-source-buffers-list'.
+Can be used by any source that list buffers."
+ (let ((helm-moccur-always-search-in-current
+ (if helm-current-prefix-arg
+ (not helm-moccur-always-search-in-current)
+ helm-moccur-always-search-in-current))
+ (buffers (helm-marked-candidates))
+ (input (cl-loop for i in (split-string helm-pattern " " t)
+ thereis (and (string-match "\\`@\\(.*\\)" i)
+ (match-string 1 i)))))
+ (helm-multi-occur-1 buffers input)))
+
+(defun helm-buffers-run-multi-occur ()
+ "Run `helm-multi-occur-as-action' by key."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-multi-occur-as-action)))
+(put 'helm-buffers-run-multi-occur 'helm-only t)
+
+(defun helm-buffers-toggle-show-hidden-buffers ()
+ (interactive)
+ (with-helm-alive-p
+ (let ((filter-attrs (helm-attr 'filtered-candidate-transformer
+ helm-source-buffers-list)))
+ (if (memq 'helm-shadow-boring-buffers filter-attrs)
+ (helm-attrset 'filtered-candidate-transformer
+ (cons 'helm-skip-boring-buffers
+ (remove 'helm-shadow-boring-buffers
+ filter-attrs))
+ helm-source-buffers-list)
+ (helm-attrset 'filtered-candidate-transformer
+ (cons 'helm-shadow-boring-buffers
+ (remove 'helm-skip-boring-buffers
+ filter-attrs))
+ helm-source-buffers-list))
+ (helm-force-update))))
+(put 'helm-buffers-toggle-show-hidden-buffers 'helm-only t)
+
+(defun helm-buffers-browse-project (buf)
+ "Browse project from buffer."
+ (with-current-buffer buf
+ (helm-browse-project helm-current-prefix-arg)))
+
+(defun helm-buffers-run-browse-project ()
+ "Run `helm-buffers-browse-project' from key."
+ (interactive)
+ (with-helm-alive-p
+ (if helm-buffers-in-project-p
+ (user-error "You are already browsing this project")
+ (helm-exit-and-execute-action 'helm-buffers-browse-project))))
+\f
+;;; Candidate Transformers
+;;
+;;
+(defun helm-skip-boring-buffers (buffers _source)
+ (helm-skip-entries buffers
+ helm-boring-buffer-regexp-list
+ helm-white-buffer-regexp-list))
+
+(defun helm-shadow-boring-buffers (buffers _source)
+ "Buffers matching `helm-boring-buffer-regexp' will be
+displayed with the `file-name-shadow' face if available."
+ (helm-shadow-entries buffers helm-boring-buffer-regexp-list))
+
+\f
+;;;###autoload
+(defun helm-buffers-list ()
+ "Preconfigured `helm' to list buffers."
+ (interactive)
+ (unless helm-source-buffers-list
+ (setq helm-source-buffers-list
+ (helm-make-source "Buffers" 'helm-source-buffers)))
+ (helm :sources '(helm-source-buffers-list
+ helm-source-ido-virtual-buffers
+ helm-source-buffer-not-found)
+ :buffer "*helm buffers*"
+ :keymap helm-buffer-map
+ :truncate-lines helm-buffers-truncate-lines))
+
+;;;###autoload
+(defun helm-mini ()
+ "Preconfigured `helm' lightweight version \(buffer -> recentf\)."
+ (interactive)
+ (require 'helm-x-files)
+ (unless helm-source-buffers-list
+ (setq helm-source-buffers-list
+ (helm-make-source "Buffers" 'helm-source-buffers)))
+ (helm :sources helm-mini-default-sources
+ :buffer "*helm mini*"
+ :ff-transformer-show-only-basename nil
+ :truncate-lines helm-buffers-truncate-lines))
+
+(defun helm-quit-and-helm-mini ()
+ "Drop into `helm-mini' from `helm'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-run-after-exit 'helm-mini)))
+
+(provide 'helm-buffers)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-buffers.el ends here
--- /dev/null
+;;; helm-color.el --- colors and faces -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Code:
+(require 'cl-lib)
+(require 'helm)
+(require 'helm-help)
+(require 'helm-elisp)
+
+;;; Customize Face
+;;
+;;
+(defun helm-custom-faces-init ()
+ "Initialize buffer for `helm-source-customize-face'."
+ (unless (helm-candidate-buffer)
+ (save-selected-window
+ (list-faces-display)
+ (message nil))
+ (helm-init-candidates-in-buffer
+ 'global
+ (with-current-buffer (get-buffer "*Faces*")
+ (buffer-substring
+ (next-single-char-property-change (point-min) 'face)
+ (point-max))))
+ (kill-buffer "*Faces*")))
+
+(defvar helm-source-customize-face
+ (helm-build-in-buffer-source "Customize Face"
+ :init 'helm-custom-faces-init
+ :get-line 'buffer-substring
+ :persistent-action (lambda (candidate)
+ (helm-elisp--persistent-help
+ (intern (car (split-string candidate)))
+ 'helm-describe-face))
+ :persistent-help "Describe face"
+ :action '(("Customize"
+ . (lambda (line)
+ (customize-face (intern (car (split-string line))))))
+ ("Copy name"
+ . (lambda (line)
+ (kill-new (car (split-string line " " t)))))))
+ "See (info \"(emacs)Faces\")")
+
+;;; Colors browser
+;;
+;;
+(defun helm-colors-init ()
+ (unless (helm-candidate-buffer)
+ (save-selected-window
+ (list-colors-display)
+ (message nil))
+ (helm-init-candidates-in-buffer
+ 'global
+ (with-current-buffer (get-buffer "*Colors*")
+ (buffer-string)))
+ (kill-buffer "*Colors*")))
+
+(defun helm-color-insert-name (candidate)
+ (with-helm-current-buffer
+ (insert (helm-colors-get-name candidate))))
+
+(defun helm-color-kill-name (candidate)
+ (kill-new (helm-colors-get-name candidate)))
+
+(defun helm-color-insert-rgb (candidate)
+ (with-helm-current-buffer
+ (insert (helm-colors-get-rgb candidate))))
+
+(defun helm-color-kill-rgb (candidate)
+ (kill-new (helm-colors-get-rgb candidate)))
+
+(defun helm-color-run-insert-name ()
+ "Insert name of color from `helm-source-colors'"
+ (interactive)
+ (with-helm-alive-p (helm-exit-and-execute-action 'helm-color-insert-name)))
+(put 'helm-color-run-insert-name 'helm-only t)
+
+(defun helm-color-run-kill-name ()
+ "Kill name of color from `helm-source-colors'"
+ (interactive)
+ (with-helm-alive-p (helm-exit-and-execute-action 'helm-color-kill-name)))
+(put 'helm-color-run-kill-name 'helm-only t)
+
+(defun helm-color-run-insert-rgb ()
+ "Insert RGB of color from `helm-source-colors'"
+ (interactive)
+ (with-helm-alive-p (helm-exit-and-execute-action 'helm-color-insert-rgb)))
+(put 'helm-color-run-insert-rgb 'helm-only t)
+
+(defun helm-color-run-kill-rgb ()
+ "Kill RGB of color from `helm-source-colors'"
+ (interactive)
+ (with-helm-alive-p (helm-exit-and-execute-action 'helm-color-kill-rgb)))
+(put 'helm-color-run-kill-rgb 'helm-only t)
+
+(defvar helm-color-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map helm-map)
+ (define-key map (kbd "C-c n") 'helm-color-run-insert-name)
+ (define-key map (kbd "C-c N") 'helm-color-run-kill-name)
+ (define-key map (kbd "C-c r") 'helm-color-run-insert-rgb)
+ (define-key map (kbd "C-c R") 'helm-color-run-kill-rgb)
+ map))
+
+(defvar helm-source-colors
+ (helm-build-in-buffer-source "Colors"
+ :init 'helm-colors-init
+ :get-line 'buffer-substring
+ :keymap helm-color-map
+ :persistent-help "Kill entry in RGB format."
+ :persistent-action 'helm-color-kill-rgb
+ :help-message 'helm-colors-help-message
+ :action
+ '(("Copy Name (C-c N)" . helm-color-kill-name)
+ ("Copy RGB (C-c R)" . helm-color-kill-rgb)
+ ("Insert Name (C-c n)" . helm-color-insert-name)
+ ("Insert RGB (C-c r)" . helm-color-insert-rgb))))
+
+(defun helm-colors-get-name (candidate)
+ "Get color name."
+ (replace-regexp-in-string
+ " " ""
+ (with-temp-buffer
+ (insert (capitalize candidate))
+ (goto-char (point-min))
+ (search-forward-regexp "\\s-\\{2,\\}")
+ (delete-region (point) (point-max))
+ (buffer-string))))
+
+(defun helm-colors-get-rgb (candidate)
+ "Get color RGB."
+ (replace-regexp-in-string
+ " " ""
+ (with-temp-buffer
+ (insert (capitalize candidate))
+ (goto-char (point-max))
+ (search-backward-regexp "\\s-\\{2,\\}")
+ (delete-region (point) (point-min))
+ (buffer-string))))
+
+;;;###autoload
+(defun helm-colors ()
+ "Preconfigured `helm' for color."
+ (interactive)
+ (helm :sources '(helm-source-colors helm-source-customize-face)
+ :buffer "*helm colors*"))
+
+(provide 'helm-color)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-color.el ends here
--- /dev/null
+;;; helm-command.el --- Helm execute-exended-command. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'helm)
+(require 'helm-help)
+(require 'helm-mode)
+(require 'helm-elisp)
+
+\f
+(defgroup helm-command nil
+ "Emacs command related Applications and libraries for Helm."
+ :group 'helm)
+
+(defcustom helm-M-x-requires-pattern 0
+ "Value of requires-pattern for `helm-M-x'.
+Show all candidates on startup when 0 (default)."
+ :group 'helm-command
+ :type 'boolean)
+
+(defcustom helm-M-x-always-save-history nil
+ "`helm-M-x' Save command in `extended-command-history' even when it fail."
+ :group 'helm-command
+ :type 'boolean)
+
+(defcustom helm-M-x-reverse-history nil
+ "The history source of `helm-M-x' appear in second position when non--nil."
+ :group 'helm-command
+ :type 'boolean)
+
+(defcustom helm-M-x-fuzzy-match nil
+ "Enable fuzzy matching in `helm-M-x' when non--nil."
+ :group 'helm-command
+ :type 'boolean)
+
+(defcustom helm-M-x-default-sort-fn #'helm-M-x-fuzzy-sort-candidates
+ "Default sort function for `helm-M-x'.
+
+It should sort against REAL value of candidates.
+
+It is used only when `helm-M-x-fuzzy-match' is enabled."
+ :group 'helm-command
+ :type 'function)
+\f
+;;; Faces
+;;
+;;
+(defgroup helm-command-faces nil
+ "Customize the appearance of helm-command."
+ :prefix "helm-"
+ :group 'helm-command
+ :group 'helm-faces)
+
+(defface helm-M-x-key '((t (:foreground "orange" :underline t)))
+ "Face used in helm-M-x to show keybinding."
+ :group 'helm-command-faces)
+
+\f
+(defvar helm-M-x-input-history nil)
+(defvar helm-M-x-prefix-argument nil
+ "Prefix argument before calling `helm-M-x'.")
+
+\f
+(defun helm-M-x-get-major-mode-command-alist (mode-map)
+ "Return alist of MODE-MAP."
+ (when mode-map
+ (cl-loop for key being the key-seqs of mode-map using (key-bindings com)
+ for str-key = (key-description key)
+ for ismenu = (string-match "<menu-bar>" str-key)
+ unless ismenu collect (cons str-key com))))
+
+(defun helm-get-mode-map-from-mode (mode)
+ "Guess the mode-map name according to MODE.
+Some modes don't use conventional mode-map name
+so we need to guess mode-map name. e.g python-mode ==> py-mode-map.
+Return nil if no mode-map found."
+ (cl-loop ;; Start with a conventional mode-map name.
+ with mode-map = (intern-soft (format "%s-map" mode))
+ with mode-string = (symbol-name mode)
+ with mode-name = (replace-regexp-in-string "-mode" "" mode-string)
+ while (not mode-map)
+ for count downfrom (length mode-name)
+ ;; Return when no result after parsing entire string.
+ when (eq count 0) return nil
+ for sub-name = (substring mode-name 0 count)
+ do (setq mode-map (intern-soft (format "%s-map" (concat sub-name "-mode"))))
+ finally return mode-map))
+
+(defun helm-M-x-current-mode-map-alist ()
+ "Return mode-map alist of current `major-mode'."
+ (let ((map-sym (helm-get-mode-map-from-mode major-mode)))
+ (when (and map-sym (boundp map-sym))
+ (helm-M-x-get-major-mode-command-alist (symbol-value map-sym)))))
+
+
+(defun helm-M-x-transformer-1 (candidates &optional sort)
+ "Transformer function to show bindings in emacs commands.
+Show global bindings and local bindings according to current `major-mode'.
+If SORT is non nil sort list with `helm-generic-sort-fn'.
+Note that SORT should not be used when fuzzy matching because
+fuzzy matching is running its own sort function with a different algorithm."
+ (with-helm-current-buffer
+ (cl-loop with local-map = (helm-M-x-current-mode-map-alist)
+ for cand in candidates
+ for local-key = (car (rassq cand local-map))
+ for key = (substitute-command-keys (format "\\[%s]" cand))
+ unless (get (intern (if (consp cand) (car cand) cand)) 'helm-only)
+ collect
+ (cons (cond ((and (string-match "^M-x" key) local-key)
+ (format "%s (%s)"
+ cand (propertize
+ local-key
+ 'face 'helm-M-x-key)))
+ ((string-match "^M-x" key) cand)
+ (t (format "%s (%s)"
+ cand (propertize
+ key
+ 'face 'helm-M-x-key))))
+ cand)
+ into ls
+ finally return
+ (if sort (sort ls #'helm-generic-sort-fn) ls))))
+
+(defun helm-M-x-transformer (candidates _source)
+ "Transformer function for `helm-M-x' candidates."
+ (helm-M-x-transformer-1 candidates (null helm--in-fuzzy)))
+
+(defun helm-M-x-transformer-hist (candidates _source)
+ "Transformer function for `helm-M-x' candidates."
+ (helm-M-x-transformer-1 candidates))
+
+(defun helm-M-x--notify-prefix-arg ()
+ ;; Notify a prefix-arg set AFTER calling M-x.
+ (when prefix-arg
+ (with-helm-window
+ (helm-display-mode-line (helm-get-current-source) 'force))))
+
+(defun helm-cmd--get-current-function-name ()
+ (save-excursion
+ (beginning-of-defun)
+ (cadr (split-string (buffer-substring-no-properties
+ (point-at-bol) (point-at-eol))))))
+
+(defun helm-cmd--get-preconfigured-commands (&optional dir)
+ (let* ((helm-dir (or dir (helm-basedir (locate-library "helm"))))
+ (helm-autoload-file (expand-file-name "helm-autoloads.el" helm-dir))
+ results)
+ (when (file-exists-p helm-autoload-file)
+ (with-temp-buffer
+ (insert-file-contents helm-autoload-file)
+ (while (re-search-forward "Preconfigured" nil t)
+ (push (substring (helm-cmd--get-current-function-name) 1) results))))
+ results))
+
+(defvar helm-M-x-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map helm-comp-read-map)
+ (define-key map (kbd "C-u") nil)
+ (define-key map (kbd "C-u") 'helm-M-x-universal-argument)
+ map))
+
+(defun helm-M-x-universal-argument ()
+ "Same as `universal-argument' but for `helm-M-x'."
+ (interactive)
+ (if helm-M-x-prefix-argument
+ (progn (setq helm-M-x-prefix-argument nil)
+ (let ((inhibit-read-only t))
+ (with-selected-window (minibuffer-window)
+ (save-excursion
+ (goto-char (point-min))
+ (delete-char (- (minibuffer-prompt-width) (length "M-x "))))))
+ (message "Initial prefix arg disabled"))
+ (setq prefix-arg (list 4))
+ (universal-argument--mode)))
+(put 'helm-M-x-universal-argument 'helm-only t)
+
+(defun helm-M-x-fuzzy-sort-candidates (candidates _source)
+ (helm-fuzzy-matching-default-sort-fn-1 candidates t))
+
+(defun helm-M-x-read-extended-command (&optional collection history)
+ "Read command name to invoke in `helm-M-x'.
+Helm completion is not provided when executing or defining
+kbd macros.
+Optional arg COLLECTION is to allow using another COLLECTION
+than the default which is OBARRAY."
+ (if (or defining-kbd-macro executing-kbd-macro)
+ (if helm-mode
+ (unwind-protect
+ (progn
+ (helm-mode -1)
+ (read-extended-command))
+ (helm-mode 1))
+ (read-extended-command))
+ (let* ((helm-fuzzy-sort-fn helm-M-x-default-sort-fn)
+ (helm--mode-line-display-prefarg t)
+ (tm (run-at-time 1 0.1 'helm-M-x--notify-prefix-arg))
+ (helm-move-selection-after-hook
+ (cons (lambda () (setq current-prefix-arg nil))
+ helm-move-selection-after-hook)))
+ (setq extended-command-history
+ (cl-loop for c in extended-command-history
+ when (and c (commandp (intern c)))
+ do (set-text-properties 0 (length c) nil c)
+ and collect c))
+ (unwind-protect
+ (progn
+ (setq current-prefix-arg nil)
+ (helm-comp-read
+ (concat (cond
+ ((eq helm-M-x-prefix-argument '-) "- ")
+ ((and (consp helm-M-x-prefix-argument)
+ (eq (car helm-M-x-prefix-argument) 4)) "C-u ")
+ ((and (consp helm-M-x-prefix-argument)
+ (integerp (car helm-M-x-prefix-argument)))
+ (format "%d " (car helm-M-x-prefix-argument)))
+ ((integerp helm-M-x-prefix-argument)
+ (format "%d " helm-M-x-prefix-argument)))
+ "M-x ")
+ (or collection obarray)
+ :test 'commandp
+ :requires-pattern helm-M-x-requires-pattern
+ :name "Emacs Commands"
+ :buffer "*helm M-x*"
+ :persistent-action (lambda (candidate)
+ (helm-elisp--persistent-help
+ candidate 'helm-describe-function))
+ :persistent-help "Describe this command"
+ :history (or history extended-command-history)
+ :reverse-history helm-M-x-reverse-history
+ :input-history 'helm-M-x-input-history
+ :del-input nil
+ :help-message 'helm-M-x-help-message
+ :keymap helm-M-x-map
+ :must-match t
+ :match-part (lambda (c) (car (split-string c)))
+ :fuzzy helm-M-x-fuzzy-match
+ :nomark t
+ :candidates-in-buffer t
+ :fc-transformer 'helm-M-x-transformer
+ :hist-fc-transformer 'helm-M-x-transformer-hist))
+ (cancel-timer tm)
+ (setq helm--mode-line-display-prefarg nil)))))
+
+;;;###autoload
+(defun helm-M-x (_arg &optional command-name)
+ "Preconfigured `helm' for Emacs commands.
+It is `helm' replacement of regular `M-x' `execute-extended-command'.
+
+Unlike regular `M-x' emacs vanilla `execute-extended-command' command,
+the prefix args if needed, can be passed AFTER starting `helm-M-x'.
+When a prefix arg is passed BEFORE starting `helm-M-x', the first `C-u'
+while in `helm-M-x' session will disable it.
+
+You can get help on each command by persistent action."
+ (interactive
+ (progn
+ (setq helm-M-x-prefix-argument current-prefix-arg)
+ (list current-prefix-arg (helm-M-x-read-extended-command))))
+ (unless (string= command-name "")
+ (let ((sym-com (and (stringp command-name) (intern-soft command-name))))
+ (when sym-com
+ ;; Avoid having `this-command' set to *exit-minibuffer.
+ (setq this-command sym-com
+ ;; Handle C-x z (repeat) Issue #322
+ real-this-command sym-com)
+ ;; If helm-M-x is called with regular emacs completion (kmacro)
+ ;; use the value of arg otherwise use helm-current-prefix-arg.
+ (let ((prefix-arg (or helm-current-prefix-arg helm-M-x-prefix-argument)))
+ (cl-flet ((save-hist (command)
+ (setq extended-command-history
+ (cons command (delete command extended-command-history)))))
+ (condition-case-unless-debug err
+ (progn
+ (command-execute sym-com 'record)
+ (save-hist command-name))
+ (error
+ (when helm-M-x-always-save-history
+ (save-hist command-name))
+ (signal (car err) (cdr err))))))))))
+(put 'helm-M-x 'interactive-only 'command-execute)
+
+(provide 'helm-command)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-command.el ends here
--- /dev/null
+;;; helm-config.el --- Applications library for `helm.el' -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Code:
+
+\f
+;;; Require
+;;
+;;
+(declare-function async-bytecomp-package-mode "ext:async-bytecomp.el")
+(when (require 'async-bytecomp nil t)
+ (and (fboundp 'async-bytecomp-package-mode)
+ (async-bytecomp-package-mode 1)))
+
+\f
+(defgroup helm-config nil
+ "Various configurations for Helm."
+ :group 'helm)
+
+(defcustom helm-command-prefix-key "C-x c"
+ "The key `helm-command-prefix' is bound to in the global map."
+ :type '(choice (string :tag "Key") (const :tag "no binding"))
+ :group 'helm-config
+ :set
+ (lambda (var key)
+ (when (and (boundp var) (symbol-value var))
+ (define-key (current-global-map)
+ (read-kbd-macro (symbol-value var)) nil))
+ (when key
+ (define-key (current-global-map)
+ (read-kbd-macro key) 'helm-command-prefix))
+ (set var key)))
+
+(defcustom helm-minibuffer-history-key "C-r"
+ "The key `helm-minibuffer-history' is bound to in minibuffer local maps."
+ :type '(choice (string :tag "Key") (const :tag "no binding"))
+ :group 'helm-config
+ :set
+ (lambda (var key)
+ (cl-dolist (map '(minibuffer-local-completion-map
+ minibuffer-local-filename-completion-map
+ minibuffer-local-filename-must-match-map ; Emacs 23.1.+
+ minibuffer-local-isearch-map
+ minibuffer-local-map
+ minibuffer-local-must-match-filename-map ; Older Emacsen
+ minibuffer-local-must-match-map
+ minibuffer-local-ns-map))
+ (when (and (boundp map) (keymapp (symbol-value map)))
+ (when (and (boundp var) (symbol-value var))
+ (define-key (symbol-value map)
+ (read-kbd-macro (symbol-value var)) nil))
+ (when key
+ (define-key (symbol-value map)
+ (read-kbd-macro key) 'helm-minibuffer-history))))
+ (set var key)))
+\f
+;;; Command Keymap
+;;
+;;
+(defvar helm-command-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map (kbd "a") 'helm-apropos)
+ (define-key map (kbd "e") 'helm-etags-select)
+ (define-key map (kbd "l") 'helm-locate)
+ (define-key map (kbd "s") 'helm-surfraw)
+ (define-key map (kbd "r") 'helm-regexp)
+ (define-key map (kbd "m") 'helm-man-woman)
+ (define-key map (kbd "t") 'helm-top)
+ (define-key map (kbd "/") 'helm-find)
+ (define-key map (kbd "i") 'helm-semantic-or-imenu)
+ (define-key map (kbd "I") 'helm-imenu-in-all-buffers)
+ (define-key map (kbd "<tab>") 'helm-lisp-completion-at-point)
+ (define-key map (kbd "p") 'helm-list-emacs-process)
+ (define-key map (kbd "C-x r b") 'helm-filtered-bookmarks)
+ (define-key map (kbd "M-y") 'helm-show-kill-ring)
+ (define-key map (kbd "C-c <SPC>") 'helm-all-mark-rings)
+ (define-key map (kbd "C-x C-f") 'helm-find-files)
+ (define-key map (kbd "f") 'helm-multi-files)
+ (define-key map (kbd "C-:") 'helm-eval-expression-with-eldoc)
+ (define-key map (kbd "C-,") 'helm-calcul-expression)
+ (define-key map (kbd "M-x") 'helm-M-x)
+ (define-key map (kbd "M-s o") 'helm-occur)
+ (define-key map (kbd "M-g a") 'helm-do-grep-ag)
+ (define-key map (kbd "c") 'helm-colors)
+ (define-key map (kbd "F") 'helm-select-xfont)
+ (define-key map (kbd "8") 'helm-ucs)
+ (define-key map (kbd "C-c f") 'helm-recentf)
+ (define-key map (kbd "C-c g") 'helm-google-suggest)
+ (define-key map (kbd "h i") 'helm-info-at-point)
+ (define-key map (kbd "h r") 'helm-info-emacs)
+ (define-key map (kbd "h g") 'helm-info-gnus)
+ (define-key map (kbd "h h") 'helm-documentation)
+ (define-key map (kbd "C-x C-b") 'helm-buffers-list)
+ (define-key map (kbd "C-x r i") 'helm-register)
+ (define-key map (kbd "C-c C-x") 'helm-run-external-command)
+ (define-key map (kbd "b") 'helm-resume)
+ (define-key map (kbd "M-g i") 'helm-gid)
+ (define-key map (kbd "@") 'helm-list-elisp-packages)
+ map))
+
+;; Don't override the keymap we just defined with an empty
+;; keymap. This also protect bindings changed by the user.
+(defvar helm-command-prefix)
+(define-prefix-command 'helm-command-prefix)
+(fset 'helm-command-prefix helm-command-map)
+(setq helm-command-prefix helm-command-map)
+
+\f
+;;; Menu
+
+(require 'helm-easymenu)
+
+\f
+;;;###autoload
+(defun helm-configuration ()
+ "Customize `helm'."
+ (interactive)
+ (customize-group "helm"))
+
+\f
+;;; Fontlock
+(cl-dolist (mode '(emacs-lisp-mode lisp-interaction-mode))
+ (font-lock-add-keywords
+ mode
+ '(("(\\<\\(with-helm-after-update-hook\\)\\>" 1 font-lock-keyword-face)
+ ("(\\<\\(with-helm-temp-hook\\)\\>" 1 font-lock-keyword-face)
+ ("(\\<\\(with-helm-window\\)\\>" 1 font-lock-keyword-face)
+ ("(\\<\\(with-helm-quittable\\)\\>" 1 font-lock-keyword-face)
+ ("(\\<\\(with-helm-current-buffer\\)\\>" 1 font-lock-keyword-face)
+ ("(\\<\\(with-helm-buffer\\)\\>" 1 font-lock-keyword-face)
+ ("(\\<\\(with-helm-show-completion\\)\\>" 1 font-lock-keyword-face)
+ ("(\\<\\(with-helm-default-directory\\)\\>" 1 font-lock-keyword-face)
+ ("(\\<\\(with-helm-restore-variables\\)\\>" 1 font-lock-keyword-face)
+ ("(\\<\\(helm-multi-key-defun\\)\\>" 1 font-lock-keyword-face)
+ ("(\\<\\(helm-while-no-input\\)\\>" 1 font-lock-keyword-face)
+ ("(\\<\\(helm-aif\\)\\>" 1 font-lock-keyword-face)
+ ("(\\<\\(helm-awhile\\)\\>" 1 font-lock-keyword-face)
+ ("(\\<\\(helm-acond\\)\\>" 1 font-lock-keyword-face)
+ ("(\\<\\(helm-aand\\)\\>" 1 font-lock-keyword-face)
+ ("(\\<\\(helm-with-gensyms\\)\\>" 1 font-lock-keyword-face)
+ ("(\\<\\(helm-read-answer\\)\\>" 1 font-lock-keyword-face))))
+
+\f
+;;; Load the autoload file
+;; It should have been generated either by
+;; package.el or the make file.
+
+(load "helm-autoloads" nil t)
+
+(provide 'helm-config)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-config.el ends here
--- /dev/null
+;;; helm-dabbrev.el --- Helm implementation of dabbrev. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Code:
+
+(require 'helm)
+(require 'helm-lib)
+(require 'helm-help)
+(require 'helm-elisp) ; For show-completion.
+\f
+(defgroup helm-dabbrev nil
+ "Dabbrev related Applications and libraries for Helm."
+ :group 'helm)
+
+(defcustom helm-dabbrev-always-search-all t
+ "Always search in all buffers when non--nil.
+Note that even if nil, a search in all buffers
+will occur if the length of candidates is <= than
+`helm-dabbrev-max-length-result'."
+ :group 'helm-dabbrev
+ :type 'boolean)
+
+(defcustom helm-dabbrev-candidates-number-limit 1000
+ "Maximum number of candidates to collect.
+
+Higher this number is, slower the computation of candidates will be.
+You can use safely a higher value with emacs-26+.
+Note that this have nothing to do with `helm-candidate-number-limit'."
+ :group 'helm-dabbrev
+ :type 'integer)
+
+(defcustom helm-dabbrev-ignored-buffers-regexps
+ '("\\*helm" "\\*Messages" "\\*Echo Area" "\\*Buffer List")
+ "List of regexps matching names of buffers that helm-dabbrev should not check."
+ :group 'helm-dabbrev
+ :type '(repeat regexp))
+
+(defcustom helm-dabbrev-related-buffer-fn #'helm-dabbrev--same-major-mode-p
+ "A function that decide if a buffer to search in is related to `current-buffer'.
+This is actually determined by comparing `major-mode' of the buffer to search
+and the `current-buffer'.
+The function take one arg, the buffer which is current, look at
+`helm-dabbrev--same-major-mode-p' for example.
+
+When nil all buffers are considered related to `current-buffer'."
+ :group 'helm-dabbrev
+ :type 'function)
+
+(defcustom helm-dabbrev-major-mode-assoc nil
+ "Major mode association alist.
+This allow helm-dabbrev searching in buffers with the associated `major-mode'.
+e.g \(emacs-lisp-mode . lisp-interaction-mode\)
+will allow searching in the lisp-interaction-mode buffer when `current-buffer'
+is an `emacs-lisp-mode' buffer and vice versa i.e
+no need to provide \(lisp-interaction-mode . emacs-lisp-mode\) association.
+
+When nil check is the searched buffer have same `major-mode'
+than the `current-buffer'.
+This have no effect when `helm-dabbrev-related-buffer-fn' is nil or of course
+bound to a function that doesn't handle this var."
+ :type '(alist :key-type symbol :value-type symbol)
+ :group 'helm-dabbrev)
+
+(defcustom helm-dabbrev-lineno-around 30
+ "Search first in this number of lines before an after point."
+ :group 'helm-dabbrev
+ :type 'integer)
+
+(defcustom helm-dabbrev-cycle-threshold 5
+ "Number of time helm-dabbrev cycle before displaying helm completion.
+When nil or 0 disable cycling."
+ :group 'helm-dabbrev
+ :type '(choice (const :tag "Cycling disabled" nil) integer))
+
+(defcustom helm-dabbrev-case-fold-search 'smart
+ "Set `case-fold-search' in `helm-dabbrev'.
+Same as `helm-case-fold-search' but for `helm-dabbrev'.
+Note that this is not affecting searching in helm buffer,
+but the initial search for all candidates in buffer(s)."
+ :group 'helm-dabbrev
+ :type '(choice (const :tag "Ignore case" t)
+ (const :tag "Respect case" nil)
+ (other :tag "Smart" 'smart)))
+
+(defcustom helm-dabbrev-use-thread nil
+ "[EXPERIMENTAL] Compute candidates asynchronously (partially) when non nil.
+
+The idea is to compute candidates while cycling the first ones, so
+this is available only if `helm-dabbrev-cycle-threshold' is not 0 or
+nil, also it is available only on emacs-26+ (needs threads).
+
+This is reasonably working when you don't have to complete a huge list
+of candidates, otherwise you will have a small delay after the first cycle
+because thread is released unexpectedly when helm-dabbrev exit after
+first insertion.
+
+IOW keep `helm-dabbrev-candidates-number-limit' to a reasonable
+value (I don't!) and give enough prefix before completing e.g. for
+completing \"helm-dabbrev\" use \"helm-d\" and not \"he\" if you want
+to use this."
+ :group 'helm-dabbrev
+ :type 'boolean)
+
+(defvaralias 'helm-dabbrev--regexp 'helm-dabbrev-separator-regexp)
+(make-obsolete-variable 'helm-dabbrev--regexp
+ 'helm-dabbrev-separator-regexp "2.8.3")
+;; Check for beginning of line should happen last (^\n\\|^).
+(defvar helm-dabbrev-separator-regexp
+ "\\s-\\|\t\\|[(\\[\\{\"'`=<$;,@.#+]\\|\\s\\\\|^\n\\|^"
+ "Regexp matching the start of a dabbrev candidate.")
+
+\f
+(defvar helm-dabbrev-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map helm-map)
+ (define-key map (kbd "M-/") 'helm-next-line)
+ (define-key map (kbd "M-:") 'helm-previous-line)
+ map))
+
+;; Internal
+(defvar helm-dabbrev--cache nil)
+(defvar helm-dabbrev--data nil)
+(cl-defstruct helm-dabbrev-info dabbrev limits iterator)
+(defvar helm-dabbrev--already-tried nil)
+(defvar helm-dabbrev--current-thread nil)
+
+\f
+(defun helm-dabbrev--buffer-list ()
+ (cl-loop for buf in (buffer-list)
+ unless (cl-loop for r in helm-dabbrev-ignored-buffers-regexps
+ thereis (string-match r (buffer-name buf)))
+ collect buf))
+
+(defun helm-dabbrev--same-major-mode-p (start-buffer)
+ "Decide if current-buffer is related to START-BUFFER."
+ (helm-same-major-mode-p start-buffer helm-dabbrev-major-mode-assoc))
+
+(defun helm-dabbrev--collect (str limit ignore-case all)
+ (let* ((case-fold-search ignore-case)
+ (buffer1 (current-buffer)) ; start buffer.
+ (minibuf (minibufferp buffer1))
+ result pos-before pos-after
+ (search-and-store
+ (lambda (pattern direction)
+ (while (and (<= (length result) limit)
+ (cl-case direction
+ (1 (search-forward pattern nil t))
+ (-1 (search-backward pattern nil t))
+ (2 (let ((pos
+ (save-excursion
+ (forward-line
+ helm-dabbrev-lineno-around)
+ (point))))
+ (setq pos-after pos)
+ (search-forward pattern pos t)))
+ (-2 (let ((pos
+ (save-excursion
+ (forward-line
+ (- helm-dabbrev-lineno-around))
+ (point))))
+ (setq pos-before pos)
+ (search-backward pattern pos t)))))
+ (let* ((pbeg (match-beginning 0))
+ (replace-regexp (concat "\\(" helm-dabbrev-separator-regexp
+ "\\)\\'"))
+ (match-word (helm-dabbrev--search
+ pattern pbeg replace-regexp)))
+ (when (and match-word (not (member match-word result)))
+ (push match-word result)))))))
+ (catch 'break
+ (dolist (buf (if all (helm-dabbrev--buffer-list)
+ (list (current-buffer))))
+ (with-current-buffer buf
+ (when (or minibuf ; check against all buffers when in minibuffer.
+ (if helm-dabbrev-related-buffer-fn
+ (funcall helm-dabbrev-related-buffer-fn buffer1)
+ t))
+ (save-excursion
+ ;; Start searching before thing before point.
+ (goto-char (- (point) (length str)))
+ ;; Search the last 30 lines before point.
+ (funcall search-and-store str -2)) ; store pos [1]
+ (save-excursion
+ ;; Search the next 30 lines after point.
+ (funcall search-and-store str 2)) ; store pos [2]
+ (save-excursion
+ ;; Search all before point.
+ ;; If limit is reached in previous call of
+ ;; search-and-store pos-before is never set and
+ ;; goto-char will fail, so check it.
+ (when pos-before
+ (goto-char pos-before) ; start from [1]
+ (funcall search-and-store str -1)))
+ (save-excursion
+ ;; Search all after point.
+ ;; Same comment as above for pos-after.
+ (when pos-after
+ (goto-char pos-after) ; start from [2]
+ (funcall search-and-store str 1)))))
+ (when (>= (length result) limit) (throw 'break nil))))
+ (nreverse result)))
+
+(defun helm-dabbrev--search (pattern beg sep-regexp)
+ "Search word or symbol at point matching PATTERN.
+Argument BEG is corresponding to the previous match-beginning search.
+The search starts at (1- BEG) with a regexp starting with
+`helm-dabbrev-separator-regexp' followed by PATTERN followed by a
+regexp matching syntactically any word or symbol.
+The possible false positives matching SEP-REGEXP at end are finally
+removed."
+ (let ((eol (point-at-eol)))
+ (save-excursion
+ (goto-char (1- beg))
+ (when (re-search-forward
+ (concat "\\("
+ helm-dabbrev-separator-regexp
+ "\\)"
+ "\\(?99:\\("
+ (regexp-quote pattern)
+ "\\(\\sw\\|\\s_\\)+\\)\\)")
+ eol t)
+ (replace-regexp-in-string
+ sep-regexp ""
+ (match-string-no-properties 99))))))
+
+(defun helm-dabbrev--get-candidates (dabbrev &optional limit)
+ (cl-assert dabbrev nil "[No Match]")
+ (helm-dabbrev--collect
+ dabbrev (or limit helm-dabbrev-candidates-number-limit)
+ (cl-case helm-dabbrev-case-fold-search
+ (smart (helm-set-case-fold-search-1 dabbrev))
+ (t helm-dabbrev-case-fold-search))
+ helm-dabbrev-always-search-all))
+\f
+(defun helm-dabbrev-default-action (candidate)
+ (with-helm-current-buffer
+ (let* ((limits (helm-bounds-of-thing-before-point
+ helm-dabbrev-separator-regexp))
+ (beg (car limits))
+ (end (point)))
+ (run-with-timer
+ 0.01 nil
+ 'helm-insert-completion-at-point
+ beg end candidate))))
+
+;;;###autoload
+(cl-defun helm-dabbrev ()
+ "Preconfigured helm for dynamic abbreviations."
+ (interactive)
+ (let ((dabbrev (helm-thing-before-point
+ nil helm-dabbrev-separator-regexp))
+ (limits (helm-bounds-of-thing-before-point
+ helm-dabbrev-separator-regexp))
+ (enable-recursive-minibuffers t)
+ (cycling-disabled-p (or (null helm-dabbrev-cycle-threshold)
+ (zerop helm-dabbrev-cycle-threshold)))
+ (helm-execute-action-at-once-if-one t)
+ (helm-quit-if-no-candidate
+ (lambda ()
+ (message "[Helm-dabbrev: No expansion found]"))))
+ (cl-assert (and (stringp dabbrev) (not (string= dabbrev "")))
+ nil "[Helm-dabbrev: Nothing found before point]")
+ (when (and
+ ;; have been called at least once.
+ (helm-dabbrev-info-p helm-dabbrev--data)
+ ;; But user have moved with some other command
+ ;; in the meaning time.
+ (not (eq last-command 'helm-dabbrev)))
+ (setq helm-dabbrev--data nil))
+ ;; When candidates are requested in helm directly without cycling,
+ ;; we need them right now before running helm, so no need to use a
+ ;; thread here.
+ (when cycling-disabled-p
+ (setq helm-dabbrev--cache (helm-dabbrev--get-candidates dabbrev)))
+ (unless (or cycling-disabled-p
+ (helm-dabbrev-info-p helm-dabbrev--data))
+ (setq helm-dabbrev--data
+ (make-helm-dabbrev-info
+ :dabbrev dabbrev
+ :limits limits
+ :iterator
+ (helm-iter-list
+ (cl-loop for i in (helm-dabbrev--get-candidates
+ dabbrev helm-dabbrev-cycle-threshold)
+ when (string-match-p
+ (concat "^" (regexp-quote dabbrev)) i)
+ collect i))))
+ ;; Thread is released as soon as helm-dabbrev exits after first
+ ;; insertion so this is unusable for now, keep it like this for
+ ;; now hooping the situation with threads will be improved in
+ ;; emacs. The idea is to compute whole list of candidates in
+ ;; background while cycling with the first
+ ;; helm-dabbrev-cycle-threshold ones.
+ (when (and (fboundp 'make-thread) helm-dabbrev-use-thread)
+ (setq helm-dabbrev--current-thread
+ (make-thread
+ (lambda ()
+ (setq helm-dabbrev--cache
+ (helm-dabbrev--get-candidates dabbrev)))))))
+ (let ((iter (and (helm-dabbrev-info-p helm-dabbrev--data)
+ (helm-dabbrev-info-iterator helm-dabbrev--data)))
+ deactivate-mark)
+ ;; Cycle until iterator is consumed.
+ (helm-aif (and iter (helm-iter-next iter))
+ (progn
+ (helm-insert-completion-at-point
+ (car (helm-dabbrev-info-limits helm-dabbrev--data))
+ ;; END is the end of the previous inserted string, not
+ ;; the end (apart for first insertion) of the initial string.
+ (cdr limits) it)
+ ;; Move already tried candidates to end of list.
+ (push it helm-dabbrev--already-tried))
+ ;; Iterator is now empty, reset dabbrev to initial value
+ ;; and start helm completion.
+ (let* ((old-dabbrev (if (helm-dabbrev-info-p helm-dabbrev--data)
+ (helm-dabbrev-info-dabbrev helm-dabbrev--data)
+ dabbrev))
+ (only-one (null (cdr (all-completions
+ old-dabbrev
+ helm-dabbrev--already-tried)))))
+ (unless helm-dabbrev-use-thread
+ (message "Waiting for helm-dabbrev candidates...")
+ (setq helm-dabbrev--cache
+ (helm-dabbrev--get-candidates old-dabbrev)))
+ ;; If the length of candidates is only one when computed
+ ;; that's mean the unique matched item have already been
+ ;; inserted by the iterator, so no need to reinsert the old dabbrev,
+ ;; just let helm exiting with "No expansion found".
+ (unless (or only-one cycling-disabled-p)
+ (setq dabbrev old-dabbrev
+ limits (helm-dabbrev-info-limits helm-dabbrev--data))
+ (setq helm-dabbrev--data nil)
+ (delete-region (car limits) (point))
+ (insert dabbrev))
+ ;; Cycling is finished, block until helm-dabbrev--cache have
+ ;; finished to complete.
+ (when (and (fboundp 'thread-join)
+ helm-dabbrev-use-thread
+ (thread-alive-p helm-dabbrev--current-thread))
+ (thread-join helm-dabbrev--current-thread))
+ (when (and (null cycling-disabled-p) only-one)
+ (cl-return-from helm-dabbrev
+ (message "[Helm-dabbrev: No expansion found]")))
+ (with-helm-show-completion (car limits) (cdr limits)
+ (unwind-protect
+ (helm :sources
+ (helm-build-in-buffer-source "Dabbrev Expand"
+ :data
+ (cl-loop for cand in helm-dabbrev--cache
+ unless
+ (member cand helm-dabbrev--already-tried)
+ collect cand into lst
+ finally return
+ (append lst helm-dabbrev--already-tried))
+ :persistent-action 'ignore
+ :persistent-help "DoNothing"
+ :keymap helm-dabbrev-map
+ :action 'helm-dabbrev-default-action
+ :group 'helm-dabbrev)
+ :buffer "*helm dabbrev*"
+ :input (concat "^" dabbrev " ")
+ :resume 'noresume
+ :allow-nest t)
+ (setq helm-dabbrev--already-tried nil))))))))
+
+(provide 'helm-dabbrev)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-dabbrev.el ends here
--- /dev/null
+;;; helm-easymenu.el --- Helm easymenu definitions. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2015 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Code:
+
+(require 'easymenu)
+
+(easy-menu-add-item
+ nil '("Tools")
+ '("Helm"
+ ["Find any Files/Buffers" helm-multi-files t]
+ ["Helm Everywhere (Toggle)" helm-mode t]
+ ["Helm resume" helm-resume t]
+ "----"
+ ("Files"
+ ["Find files" helm-find-files t]
+ ["Recent Files" helm-recentf t]
+ ["Locate" helm-locate t]
+ ["Search Files with find" helm-find t]
+ ["Bookmarks" helm-filtered-bookmarks t])
+ ("Buffers"
+ ["Find buffers" helm-buffers-list t])
+ ("Commands"
+ ["Emacs Commands" helm-M-x t]
+ ["Externals Commands" helm-run-external-command t])
+ ("Help"
+ ["Helm Apropos" helm-apropos t])
+ ("Info"
+ ["Info at point" helm-info-at-point t]
+ ["Emacs Manual index" helm-info-emacs t]
+ ["Gnus Manual index" helm-info-gnus t]
+ ["Helm documentation" helm-documentation t])
+ ("Org"
+ ["Org headlines in org agenda files" helm-org-agenda-files-headings t]
+ ["Org headlines in buffer" helm-org-in-buffer-headings t])
+ ("Elpa"
+ ["Elisp packages" helm-list-elisp-packages t]
+ ["Elisp packages no fetch" helm-list-elisp-packages-no-fetch t])
+ ("Tools"
+ ["Occur" helm-occur t]
+ ["Grep current directory with AG" helm-do-grep-ag t]
+ ["Gid" helm-gid t]
+ ["Etags" helm-etags-select t]
+ ["Lisp complete at point" helm-lisp-completion-at-point t]
+ ["Browse Kill ring" helm-show-kill-ring t]
+ ["Browse register" helm-register t]
+ ["Mark Ring" helm-all-mark-rings t]
+ ["Regexp handler" helm-regexp t]
+ ["Colors & Faces" helm-colors t]
+ ["Show xfonts" helm-select-xfont t]
+ ["Ucs Symbols" helm-ucs t]
+ ["Imenu" helm-imenu t]
+ ["Imenu all" helm-imenu-in-all-buffers t]
+ ["Semantic or Imenu" helm-semantic-or-imenu t]
+ ["Google Suggest" helm-google-suggest t]
+ ["Eval expression" helm-eval-expression-with-eldoc t]
+ ["Calcul expression" helm-calcul-expression t]
+ ["Man pages" helm-man-woman t]
+ ["Top externals process" helm-top t]
+ ["Emacs internals process" helm-list-emacs-process t])
+ "----"
+ ["Preferred Options" helm-configuration t])
+ "Spell Checking")
+
+(easy-menu-add-item nil '("Tools") '("----") "Spell Checking")
+
+
+(provide 'helm-easymenu)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-easymenu.el ends here
--- /dev/null
+;;; helm-elisp-package.el --- helm interface for package.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Code:
+(require 'cl-lib)
+(require 'helm)
+(require 'helm-help)
+(require 'package)
+
+(defgroup helm-el-package nil
+ "helm elisp packages."
+ :group 'helm)
+
+(defcustom helm-el-package-initial-filter 'all
+ "Show only installed, upgraded or all packages at startup."
+ :group 'helm-el-package
+ :type '(radio :tag "Initial filter for elisp packages"
+ (const :tag "Show all packages" all)
+ (const :tag "Show installed packages" installed)
+ (const :tag "Show not installed packages" uninstalled)
+ (const :tag "Show upgradable packages" upgrade)))
+
+(defcustom helm-el-truncate-lines t
+ "Truncate lines in helm-buffer when non--nil."
+ :group 'helm-el-package
+ :type 'boolean)
+
+;; internals vars
+(defvar helm-el-package--show-only 'all)
+(defvar helm-el-package--initialized-p nil)
+(defvar helm-el-package--tabulated-list nil)
+(defvar helm-el-package--upgrades nil)
+(defvar helm-el-package--removable-packages nil)
+
+;; Shutup bytecompiler for emacs-24*
+(defvar package-menu-async) ; Only available on emacs-25.
+(declare-function async-byte-recompile-directory "ext:async-bytecomp.el")
+
+(defun helm-el-package--init ()
+ (let (package-menu-async
+ (inhibit-read-only t))
+ (when (null package-alist)
+ (setq helm-el-package--show-only 'all))
+ (when (and (fboundp 'package--removable-packages)
+ (setq helm-el-package--removable-packages
+ (package--removable-packages))
+ (fboundp 'package-autoremove))
+ (package-autoremove))
+ (unwind-protect
+ (progn
+ (save-selected-window
+ (if (and helm-el-package--initialized-p
+ (fboundp 'package-show-package-list))
+ ;; Use this as `list-packages' doesn't work
+ ;; properly (empty buffer) when called from lisp
+ ;; with 'no-fetch (emacs-25 WA).
+ (package-show-package-list)
+ (when helm--force-updating-p (message "Refreshing packages list..."))
+ (list-packages helm-el-package--initialized-p))
+ (setq helm-el-package--initialized-p t)
+ (message nil))
+ (helm-init-candidates-in-buffer
+ 'global
+ (with-current-buffer (get-buffer "*Packages*")
+ (setq helm-el-package--tabulated-list tabulated-list-entries)
+ (remove-text-properties (point-min) (point-max)
+ '(read-only button follow-link category))
+ (buffer-string)))
+ (setq helm-el-package--upgrades (helm-el-package-menu--find-upgrades))
+ (if helm--force-updating-p
+ (if helm-el-package--upgrades
+ (message "Refreshing packages list done, [%d] package(s) to upgrade"
+ (length helm-el-package--upgrades))
+ (message "Refreshing packages list done, no upgrades available"))
+ (setq helm-el-package--show-only (if helm-el-package--upgrades
+ 'upgrade
+ helm-el-package-initial-filter))))
+ (kill-buffer "*Packages*"))))
+
+(defun helm-el-package-describe (candidate)
+ (let ((id (get-text-property 0 'tabulated-list-id candidate)))
+ (describe-package (if (fboundp 'package-desc-name)
+ (package-desc-name id)
+ (car id)))))
+
+(defun helm-el-package-visit-homepage (candidate)
+ (let* ((id (get-text-property 0 'tabulated-list-id candidate))
+ (pkg (if (fboundp 'package-desc-name) (package-desc-name id)
+ (car id)))
+ (desc (cadr (assoc pkg package-archive-contents)))
+ (extras (package-desc-extras desc))
+ (url (and (listp extras) (cdr-safe (assoc :url extras)))))
+ (if (stringp url)
+ (browse-url url)
+ (message "Package %s has no homepage"
+ (propertize (symbol-name pkg)
+ 'face 'font-lock-keyword-face)))))
+
+(defun helm-el-run-visit-homepage ()
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-el-package-visit-homepage)))
+(put 'helm-el-run-visit-homepage 'helm-only t)
+
+(defun helm-el-package-install-1 (pkg-list)
+ (cl-loop with mkd = pkg-list
+ for p in mkd
+ for id = (get-text-property 0 'tabulated-list-id p)
+ for pkg = (if (fboundp 'package-desc-name) id (car id))
+ do (package-install pkg)
+ collect pkg into installed-list
+ finally do (if (fboundp 'package-desc-full-name)
+ (message (format "%d packages installed:\n(%s)"
+ (length installed-list)
+ (mapconcat #'package-desc-full-name
+ installed-list ", ")))
+ (message (format "%d packages installed:\n(%s)"
+ (length installed-list)
+ (mapconcat 'symbol-name installed-list ", "))))))
+
+(defun helm-el-package-install (_candidate)
+ (helm-el-package-install-1 (helm-marked-candidates)))
+
+(defun helm-el-run-package-install ()
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-el-package-install)))
+(put 'helm-el-run-package-install 'helm-only t)
+
+(defun helm-el-package-uninstall-1 (pkg-list &optional force)
+ (cl-loop with mkd = pkg-list
+ for p in mkd
+ for id = (get-text-property 0 'tabulated-list-id p)
+ do
+ (condition-case-unless-debug err
+ (with-no-warnings
+ (if (fboundp 'package-desc-full-name)
+ ;; emacs 24.4
+ (condition-case nil
+ (package-delete id force)
+ (wrong-number-of-arguments
+ (package-delete id)))
+ ;; emacs 24.3
+ (package-delete (symbol-name (car id))
+ (package-version-join (cdr id)))))
+ (error (message (cadr err))))
+ ;; Seems like package-descs are symbols with props instead of
+ ;; vectors in emacs-27, use package-desc-name to ensure
+ ;; compatibility in all emacs versions.
+ unless (assoc (package-desc-name id) package-alist)
+ collect (if (fboundp 'package-desc-full-name)
+ id
+ (cons (symbol-name (car id))
+ (package-version-join (cdr id))))
+ into delete-list
+ finally do (if delete-list
+ (if (fboundp 'package-desc-full-name)
+ ;; emacs 24.4
+ (message (format "%d packages deleted:\n(%s)"
+ (length delete-list)
+ (mapconcat #'package-desc-full-name
+ delete-list ", ")))
+ ;; emacs 24.3
+ (message (format "%d packages deleted:\n(%s)"
+ (length delete-list)
+ (mapconcat (lambda (x)
+ (concat (car x) "-" (cdr x)))
+ delete-list ", ")))
+ ;; emacs 24.3 doesn't update
+ ;; its `package-alist' after deleting.
+ (cl-loop for p in package-alist
+ when (assq (symbol-name (car p)) delete-list)
+ do (setq package-alist (delete p package-alist))))
+ "No package deleted")))
+
+(defun helm-el-package-uninstall (_candidate)
+ (helm-el-package-uninstall-1 (helm-marked-candidates) helm-current-prefix-arg))
+
+(defun helm-el-run-package-uninstall ()
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-el-package-uninstall)))
+(put 'helm-el-run-package-uninstall 'helm-only t)
+
+(defun helm-el-package-menu--find-upgrades ()
+ (cl-loop for entry in helm-el-package--tabulated-list
+ for pkg-desc = (car entry)
+ for status = (package-desc-status pkg-desc)
+ when (member status '("installed" "unsigned" "dependency"))
+ collect pkg-desc
+ into installed
+ when (member status '("available" "new"))
+ collect (cons (package-desc-name pkg-desc) pkg-desc)
+ into available
+ finally return
+ (cl-loop for pkg in installed
+ for avail-pkg = (assq (package-desc-name pkg) available)
+ when (and avail-pkg
+ (version-list-< (package-desc-version pkg)
+ (package-desc-version
+ (cdr avail-pkg))))
+ collect avail-pkg)))
+
+(defun helm-el-package-upgrade-1 (pkg-list)
+ (cl-loop for p in pkg-list
+ for pkg-desc = (car p)
+ for upgrade = (cdr (assq (package-desc-name pkg-desc)
+ helm-el-package--upgrades))
+ do
+ (cond ((null upgrade)
+ (ignore))
+ ((equal pkg-desc upgrade)
+ ;;Install.
+ (with-no-warnings
+ (if (boundp 'package-selected-packages)
+ (package-install pkg-desc t)
+ (package-install pkg-desc))))
+ (t
+ ;; Delete.
+ (if (boundp 'package-selected-packages)
+ (with-no-warnings
+ (package-delete pkg-desc t t))
+ (package-delete pkg-desc))))))
+
+(defun helm-el-package-upgrade (_candidate)
+ (helm-el-package-upgrade-1
+ (cl-loop with pkgs = (helm-marked-candidates)
+ for p in helm-el-package--tabulated-list
+ for pkg = (car p)
+ if (member (symbol-name (package-desc-name pkg)) pkgs)
+ collect p)))
+
+(defun helm-el-run-package-upgrade ()
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-el-package-upgrade)))
+(put 'helm-el-run-package-upgrade 'helm-only t)
+
+(defun helm-el-package-upgrade-all ()
+ (if helm-el-package--upgrades
+ (with-helm-display-marked-candidates
+ helm-marked-buffer-name (mapcar (lambda (x) (symbol-name (car x)))
+ helm-el-package--upgrades)
+ (when (y-or-n-p "Upgrade all packages? ")
+ (helm-el-package-upgrade-1 helm-el-package--tabulated-list)))
+ (message "No packages to upgrade actually!")))
+
+(defun helm-el-package-upgrade-all-action (_candidate)
+ (helm-el-package-upgrade-all))
+
+(defun helm-el-run-package-upgrade-all ()
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-el-package-upgrade-all-action)))
+(put 'helm-el-run-package-upgrade-all 'helm-only t)
+
+(defun helm-el-package--transformer (candidates _source)
+ (cl-loop for c in candidates
+ for id = (get-text-property 0 'tabulated-list-id c)
+ for name = (if (fboundp 'package-desc-name)
+ (and id (package-desc-name id))
+ (car id))
+ for desc = (package-desc-status id)
+ for built-in-p = (and (package-built-in-p name)
+ (not (member desc '("available" "new"
+ "installed" "dependency"))))
+ for installed-p = (member desc '("installed" "dependency"))
+ for upgrade-p = (assq name helm-el-package--upgrades)
+ for user-installed-p = (and (boundp 'package-selected-packages)
+ (memq name package-selected-packages))
+ do (when user-installed-p (put-text-property 0 2 'display "S " c))
+ do (when (memq name helm-el-package--removable-packages)
+ (put-text-property 0 2 'display "U " c)
+ (put-text-property
+ 2 (+ (length (symbol-name name)) 2)
+ 'face 'font-lock-variable-name-face c))
+ for cand = (cons c (car (split-string c)))
+ when (or (and built-in-p
+ (eq helm-el-package--show-only 'built-in))
+ (and upgrade-p
+ (eq helm-el-package--show-only 'upgrade))
+ (and installed-p
+ (eq helm-el-package--show-only 'installed))
+ (and (not installed-p)
+ (not built-in-p)
+ (eq helm-el-package--show-only 'uninstalled))
+ (eq helm-el-package--show-only 'all))
+ collect cand))
+
+(defun helm-el-package-show-built-in ()
+ (interactive)
+ (with-helm-alive-p
+ (setq helm-el-package--show-only 'built-in)
+ (helm-update)))
+(put 'helm-el-package-show-built-in 'helm-only t)
+
+(defun helm-el-package-show-upgrade ()
+ (interactive)
+ (with-helm-alive-p
+ (setq helm-el-package--show-only 'upgrade)
+ (helm-update)))
+(put 'helm-el-package-show-upgrade 'helm-only t)
+
+(defun helm-el-package-show-installed ()
+ (interactive)
+ (with-helm-alive-p
+ (setq helm-el-package--show-only 'installed)
+ (helm-update)))
+(put 'helm-el-package-show-installed 'helm-only t)
+
+(defun helm-el-package-show-all ()
+ (interactive)
+ (with-helm-alive-p
+ (setq helm-el-package--show-only 'all)
+ (helm-update)))
+(put 'helm-el-package-show-all 'helm-only t)
+
+(defun helm-el-package-show-uninstalled ()
+ (interactive)
+ (with-helm-alive-p
+ (setq helm-el-package--show-only 'uninstalled)
+ (helm-update)))
+(put 'helm-el-package-show-uninstalled 'helm-only t)
+
+(defvar helm-el-package-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map helm-map)
+ (define-key map (kbd "M-I") 'helm-el-package-show-installed)
+ (define-key map (kbd "M-O") 'helm-el-package-show-uninstalled)
+ (define-key map (kbd "M-U") 'helm-el-package-show-upgrade)
+ (define-key map (kbd "M-B") 'helm-el-package-show-built-in)
+ (define-key map (kbd "M-A") 'helm-el-package-show-all)
+ (define-key map (kbd "C-c i") 'helm-el-run-package-install)
+ (define-key map (kbd "C-c r") 'helm-el-run-package-reinstall)
+ (define-key map (kbd "C-c d") 'helm-el-run-package-uninstall)
+ (define-key map (kbd "C-c u") 'helm-el-run-package-upgrade)
+ (define-key map (kbd "C-c U") 'helm-el-run-package-upgrade-all)
+ (define-key map (kbd "C-c @") 'helm-el-run-visit-homepage)
+ map))
+
+(defvar helm-source-list-el-package nil)
+(defclass helm-list-el-package-source (helm-source-in-buffer)
+ ((init :initform 'helm-el-package--init)
+ (get-line :initform 'buffer-substring)
+ (filtered-candidate-transformer :initform 'helm-el-package--transformer)
+ (action-transformer :initform 'helm-el-package--action-transformer)
+ (help-message :initform 'helm-el-package-help-message)
+ (keymap :initform helm-el-package-map)
+ (update :initform 'helm-el-package--update)
+ (candidate-number-limit :initform 9999)
+ (action :initform '(("Describe package" . helm-el-package-describe)
+ ("Visit homepage" . helm-el-package-visit-homepage)))
+ (group :initform 'helm-el-package)))
+
+(defun helm-el-package--action-transformer (actions candidate)
+ (let* ((pkg-desc (get-text-property 0 'tabulated-list-id candidate))
+ (status (package-desc-status pkg-desc))
+ (pkg-name (package-desc-name pkg-desc))
+ (built-in (and (package-built-in-p pkg-name)
+ (not (member status '("available" "new"
+ "installed" "dependency")))))
+ (acts (if helm-el-package--upgrades
+ (append actions '(("Upgrade all packages"
+ . helm-el-package-upgrade-all-action)))
+ actions)))
+ (cond (built-in '(("Describe package" . helm-el-package-describe)))
+ ((and (package-installed-p pkg-name)
+ (cdr (assq pkg-name helm-el-package--upgrades))
+ (member status '("installed" "dependency")))
+ (append '(("Upgrade package(s)" . helm-el-package-upgrade)
+ ("Uninstall package(s)" . helm-el-package-uninstall))
+ acts))
+ ((and (package-installed-p pkg-name)
+ (cdr (assq pkg-name helm-el-package--upgrades))
+ (string= status "available"))
+ (append '(("Upgrade package(s)" . helm-el-package-upgrade))
+ acts))
+ ((and (package-installed-p pkg-name)
+ (or (null (package-built-in-p pkg-name))
+ (and (package-built-in-p pkg-name)
+ (assq pkg-name package-alist))))
+ (append acts '(("Reinstall package(s)" . helm-el-package-reinstall)
+ ("Recompile package(s)" . helm-el-package-recompile)
+ ("Uninstall package(s)" . helm-el-package-uninstall))))
+ (t (append acts '(("Install packages(s)" . helm-el-package-install)))))))
+
+(defun helm-el-package--update ()
+ (setq helm-el-package--initialized-p nil))
+
+(defun helm-el-package-recompile (_pkg)
+ (cl-loop for p in (helm-marked-candidates)
+ for pkg-desc = (get-text-property 0 'tabulated-list-id p)
+ for name = (package-desc-name pkg-desc)
+ for dir = (package-desc-dir pkg-desc)
+ do (if (fboundp 'async-byte-recompile-directory)
+ (async-byte-recompile-directory dir)
+ (when (y-or-n-p (format "Really recompile `%s' while already loaded ?" name))
+ (byte-recompile-directory dir 0 t)))))
+
+(defun helm-el-package-reinstall (_pkg)
+ (cl-loop for p in (helm-marked-candidates)
+ for pkg-desc = (get-text-property 0 'tabulated-list-id p)
+ for name = (package-desc-name pkg-desc)
+ do (if (boundp 'package-selected-packages)
+ (with-no-warnings
+ (package-delete pkg-desc 'force 'nosave)
+ ;; pkg-desc contain the description
+ ;; of the installed package just removed
+ ;; and is BTW no more valid.
+ ;; Use the entry in package-archive-content
+ ;; which is the non--installed package entry.
+ ;; For some reason `package-install'
+ ;; need a pkg-desc (package-desc-p) for the build-in
+ ;; packages already installed, the name (as symbol)
+ ;; fails with such packages.
+ (package-install
+ (cadr (assq name package-archive-contents)) t))
+ (package-delete pkg-desc)
+ (package-install name))))
+
+(defun helm-el-run-package-reinstall ()
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-el-package-reinstall)))
+(put 'helm-el-run-package-reinstall 'helm-only t)
+
+;;;###autoload
+(defun helm-list-elisp-packages (arg)
+ "Preconfigured helm for listing and handling emacs packages."
+ (interactive "P")
+ (when arg (setq helm-el-package--initialized-p nil))
+ (unless helm-source-list-el-package
+ (setq helm-source-list-el-package
+ (helm-make-source "list packages" 'helm-list-el-package-source)))
+ (helm :sources 'helm-source-list-el-package
+ :truncate-lines helm-el-truncate-lines
+ :full-frame t
+ :buffer "*helm list packages*"))
+
+;;;###autoload
+(defun helm-list-elisp-packages-no-fetch (arg)
+ "Preconfigured helm for emacs packages.
+
+Same as `helm-list-elisp-packages' but don't fetch packages on remote.
+Called with a prefix ARG always fetch packages on remote."
+ (interactive "P")
+ (let ((helm-el-package--initialized-p (null arg)))
+ (helm-list-elisp-packages nil)))
+
+(provide 'helm-elisp-package)
+
+;;; helm-elisp-package.el ends here
--- /dev/null
+;;; helm-elisp.el --- Elisp symbols completion for helm. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Code:
+(require 'cl-lib)
+(require 'helm)
+(require 'helm-lib)
+(require 'helm-help)
+(require 'helm-types)
+(require 'helm-utils)
+(require 'helm-info)
+(require 'helm-eval)
+(require 'helm-files)
+
+(declare-function 'helm-describe-function "helm-lib")
+(declare-function 'helm-describe-variable "helm-lib")
+(declare-function 'helm-describe-face "helm-lib")
+
+\f
+;;; Customizable values
+
+(defgroup helm-elisp nil
+ "Elisp related Applications and libraries for Helm."
+ :group 'helm)
+
+(defcustom helm-turn-on-show-completion t
+ "Display candidate in `current-buffer' while moving selection when non--nil."
+ :group 'helm-elisp
+ :type 'boolean)
+
+(defcustom helm-show-completion-min-window-height 7
+ "Minimum completion window height used in show completion.
+This is used in macro `with-helm-show-completion'."
+ :group 'helm-elisp
+ :type 'integer)
+
+(defcustom helm-lisp-quoted-function-list
+ '(funcall apply mapc cl-mapc mapcar cl-mapcar
+ callf callf2 cl-callf cl-callf2 fset
+ fboundp fmakunbound symbol-function)
+ "List of function where quoted function completion happen.
+e.g give only function names after \(funcall '."
+ :group 'helm-elisp
+ :type '(repeat (choice symbol)))
+
+(defcustom helm-lisp-unquoted-function-list
+ '(function defadvice)
+ "List of function where unquoted function completion happen.
+e.g give only function names after \(function ."
+ :group 'helm-elisp
+ :type '(repeat (choice symbol)))
+
+(defcustom helm-apropos-fuzzy-match nil
+ "Enable fuzzy matching for `helm-apropos' when non-nil."
+ :group 'helm-elisp
+ :type 'boolean)
+
+(defcustom helm-lisp-fuzzy-completion nil
+ "Enable fuzzy matching in emacs-lisp completion when non-nil.
+NOTE: This enable fuzzy matching in helm native implementation of
+elisp completion, but not on helmized elisp completion, i.e
+fuzzy completion is not available in `completion-at-point'."
+ :group 'helm-elisp
+ :type 'boolean)
+
+(defcustom helm-apropos-function-list '(helm-def-source--emacs-commands
+ helm-def-source--emacs-functions
+ helm-def-source--eieio-classes
+ helm-def-source--eieio-generic
+ helm-def-source--emacs-variables
+ helm-def-source--emacs-faces)
+ "A list of functions that build helm sources to use in `helm-apropos'."
+ :group 'helm-elisp
+ :type '(repeat (choice symbol)))
+
+(defcustom helm-apropos-defaut-info-lookup-sources '(helm-source-info-elisp
+ helm-source-info-cl
+ helm-source-info-eieio)
+ "A list of sources to look into when searching info page of a symbol."
+ :group 'helm-elisp
+ :type '(repeat (choice symbol)))
+
+(defcustom helm-show-completion-display-function
+ (if (display-graphic-p)
+ #'helm-display-buffer-in-own-frame
+ #'helm-show-completion-default-display-function)
+ "The function used to display helm completion buffer.
+
+This function is used by `with-helm-show-completion', when nil
+fallback to `helm-default-display-buffer'.
+
+Default is to use a separate frame on graphic display and
+`helm-show-completion-default-display-function' on non graphic
+display."
+ :group 'helm-elisp
+ :type 'function)
+\f
+;;; Faces
+;;
+;;
+(defgroup helm-elisp-faces nil
+ "Customize the appearance of helm-elisp."
+ :prefix "helm-"
+ :group 'helm-elisp
+ :group 'helm-faces)
+
+(defface helm-lisp-show-completion
+ '((t (:background "DarkSlateGray")))
+ "Face used for showing candidates in `helm-lisp-completion'."
+ :group 'helm-elisp-faces)
+
+(defface helm-lisp-completion-info
+ '((t (:foreground "red")))
+ "Face used for showing info in `helm-lisp-completion'."
+ :group 'helm-elisp-faces)
+
+(defcustom helm-elisp-help-function
+ 'helm-elisp-show-help
+ "Function for displaying help for Lisp symbols."
+ :group 'helm-elisp
+ :type '(choice (function :tag "Open help for the symbol."
+ helm-elisp-show-help)
+ (function :tag "Show one liner in modeline."
+ helm-elisp-show-doc-modeline)))
+
+(defcustom helm-locate-library-fuzzy-match t
+ "Enable fuzzy-matching in `helm-locate-library' when non--nil."
+ :type 'boolean
+ :group 'helm-elisp)
+
+\f
+;;; Show completion.
+;;
+;; Provide show completion with macro `with-helm-show-completion'.
+
+(defvar helm-show-completion-overlay nil)
+
+;; Called each time cursor move in helm-buffer.
+(defun helm-show-completion ()
+ (with-helm-current-buffer
+ (overlay-put helm-show-completion-overlay
+ 'display (substring-no-properties
+ (helm-get-selection)))))
+
+(defun helm-show-completion-init-overlay (beg end)
+ (setq helm-show-completion-overlay (make-overlay beg end))
+ (overlay-put helm-show-completion-overlay
+ 'face 'helm-lisp-show-completion))
+
+(defun helm-show-completion-default-display-function (buffer &rest _args)
+ "A special resized helm window is used depending on position in BUFFER."
+ (with-selected-window (selected-window)
+ (if (window-dedicated-p)
+ (helm-default-display-buffer buffer)
+ (let* ((screen-size (+ (count-screen-lines (window-start) (point) t)
+ 1 ; mode-line
+ (if header-line-format 1 0))) ; header-line
+ (def-size (- (window-height)
+ helm-show-completion-min-window-height))
+ (upper-height (max window-min-height (min screen-size def-size)))
+ split-window-keep-point)
+ (recenter -1)
+ (set-window-buffer (if (active-minibuffer-window)
+ (minibuffer-selected-window)
+ (split-window nil upper-height
+ helm-split-window-default-side))
+ buffer)))))
+
+(defmacro with-helm-show-completion (beg end &rest body)
+ "Show helm candidate in an overlay at point.
+BEG and END are the beginning and end position of the current completion
+in `helm-current-buffer'.
+BODY is an helm call where we want to enable show completion.
+If `helm-turn-on-show-completion' is nil do nothing."
+ (declare (indent 2) (debug t))
+ `(unwind-protect
+ (if helm-turn-on-show-completion
+ (let ((helm-move-selection-after-hook
+ (append (list 'helm-show-completion)
+ helm-move-selection-after-hook))
+ (helm-split-window-default-side
+ (if (eq helm-split-window-default-side 'same)
+ 'below helm-split-window-default-side))
+ helm-split-window-inside-p
+ helm-reuse-last-window-split-state)
+ (helm-set-local-variable
+ 'helm-display-function
+ (or helm-show-completion-display-function
+ 'helm-default-display-buffer))
+ (helm-show-completion-init-overlay ,beg ,end)
+ ,@body)
+ ,@body)
+ (when (and helm-show-completion-overlay
+ (overlayp helm-show-completion-overlay))
+ (delete-overlay helm-show-completion-overlay))))
+
+\f
+;;; Lisp symbol completion.
+;;
+;;
+(defun helm-lisp-completion--predicate-at-point (beg)
+ ;; Return a predicate for `all-completions'.
+ (let ((fn-sym-p (lambda ()
+ (or
+ (and (eq (char-before) ?\ )
+ (save-excursion
+ (skip-syntax-backward " " (point-at-bol))
+ (memq (symbol-at-point)
+ helm-lisp-unquoted-function-list)))
+ (and (eq (char-before) ?\')
+ (save-excursion
+ (forward-char -1)
+ (eq (char-before) ?\#)))))))
+ (save-excursion
+ (goto-char beg)
+ (if (or
+ ;; Complete on all symbols in non--lisp modes (logs mail etc..)
+ (not (memq major-mode '(emacs-lisp-mode
+ lisp-interaction-mode
+ inferior-emacs-lisp-mode)))
+ (not (or (funcall fn-sym-p)
+ (and (eq (char-before) ?\')
+ (save-excursion
+ (forward-char (if (funcall fn-sym-p) -2 -1))
+ (skip-syntax-backward " " (point-at-bol))
+ (memq (symbol-at-point)
+ helm-lisp-quoted-function-list)))
+ (eq (char-before) ?\())) ; no paren before str.
+ ;; Looks like we are in a let statement.
+ (condition-case nil
+ (progn (up-list -2) (forward-char 1)
+ (eq (char-after) ?\())
+ (error nil)))
+ (lambda (sym)
+ (or (boundp sym) (fboundp sym) (symbol-plist sym)))
+ #'fboundp))))
+
+(defun helm-thing-before-point (&optional limits regexp)
+ "Return symbol name before point.
+If REGEXP is specified return what REGEXP find before point.
+By default match the beginning of symbol before point.
+With LIMITS arg specified return the beginning and end position
+of symbol before point."
+ (save-excursion
+ (let (beg
+ (end (point))
+ (boundary (field-beginning nil nil (point-at-bol))))
+ (if (re-search-backward (or regexp "\\_<") boundary t)
+ (setq beg (match-end 0))
+ (setq beg boundary))
+ (unless (= beg end)
+ (if limits
+ (cons beg end)
+ (buffer-substring-no-properties beg end))))))
+
+(defun helm-bounds-of-thing-before-point (&optional regexp)
+ "Get the beginning and end position of `helm-thing-before-point'.
+Return a cons \(beg . end\)."
+ (helm-thing-before-point 'limits regexp))
+
+(defun helm-insert-completion-at-point (beg end str)
+ ;; When there is no space after point
+ ;; we are completing inside a symbol or
+ ;; after a partial symbol with the next arg aside
+ ;; without space, in this case mark the region.
+ ;; deleting it would remove the
+ ;; next arg which is unwanted.
+ (delete-region beg end)
+ (insert str)
+ (let ((pos (cdr (or (bounds-of-thing-at-point 'symbol)
+ ;; needed for helm-dabbrev.
+ (bounds-of-thing-at-point 'filename)))))
+ (when (and pos (< (point) pos))
+ (push-mark pos t t))))
+
+(defvar helm-lisp-completion--cache nil)
+(defvar helm-lgst-len nil)
+;;;###autoload
+(defun helm-lisp-completion-at-point ()
+ "Preconfigured helm for lisp symbol completion at point."
+ (interactive)
+ (setq helm-lgst-len 0)
+ (let* ((target (helm-thing-before-point))
+ (beg (car (helm-bounds-of-thing-before-point)))
+ (end (point))
+ (pred (and beg (helm-lisp-completion--predicate-at-point beg)))
+ (loc-vars (and (fboundp 'elisp--local-variables)
+ (ignore-errors
+ (mapcar #'symbol-name (elisp--local-variables)))))
+ (glob-syms (and target pred (all-completions target obarray pred)))
+ (candidates (append loc-vars glob-syms))
+ (helm-quit-if-no-candidate t)
+ (helm-execute-action-at-once-if-one t)
+ (enable-recursive-minibuffers t))
+ (setq helm-lisp-completion--cache (cl-loop for sym in candidates
+ for len = (length sym)
+ when (> len helm-lgst-len)
+ do (setq helm-lgst-len len)
+ collect sym))
+ (if candidates
+ (with-helm-show-completion beg end
+ ;; Overlay is initialized now in helm-current-buffer.
+ (helm
+ :sources (helm-build-in-buffer-source "Lisp completion"
+ :data helm-lisp-completion--cache
+ :persistent-action `(helm-lisp-completion-persistent-action .
+ ,(and (eq helm-elisp-help-function
+ 'helm-elisp-show-doc-modeline)
+ 'never-split))
+ :nomark t
+ :match-part (lambda (c) (car (split-string c)))
+ :fuzzy-match helm-lisp-fuzzy-completion
+ :persistent-help (helm-lisp-completion-persistent-help)
+ :filtered-candidate-transformer
+ 'helm-lisp-completion-transformer
+ :action (lambda (candidate)
+ (with-helm-current-buffer
+ (run-with-timer
+ 0.01 nil
+ 'helm-insert-completion-at-point
+ beg end candidate))))
+ :input (if helm-lisp-fuzzy-completion
+ target (concat target " "))
+ :resume 'noresume
+ :truncate-lines t
+ :buffer "*helm lisp completion*"
+ :allow-nest t))
+ (message "[No Match]"))))
+
+(defun helm-lisp-completion-persistent-action (candidate &optional name)
+ "Show documentation for the function.
+Documentation is shown briefly in mode-line or completely
+in other window according to the value of `helm-elisp-help-function'."
+ (funcall helm-elisp-help-function candidate name))
+
+(defun helm-lisp-completion-persistent-help ()
+ "Return persistent-help according to the value of `helm-elisp-help-function'"
+ (cl-ecase helm-elisp-help-function
+ (helm-elisp-show-doc-modeline "Show brief doc in mode-line")
+ (helm-elisp-show-help "Toggle show help for the symbol")))
+
+(defun helm-elisp--show-help-1 (candidate &optional name)
+ (let ((sym (intern-soft candidate)))
+ (cl-typecase sym
+ ((and fboundp boundp)
+ (if (member name '("describe-function" "describe-variable"))
+ (funcall (intern (format "helm-%s" name)) sym)
+ ;; When there is no way to know what to describe
+ ;; prefer describe-function.
+ (helm-describe-function sym)))
+ (fbound (helm-describe-function sym))
+ (bound (helm-describe-variable sym))
+ (face (helm-describe-face sym)))))
+
+(defun helm-elisp-show-help (candidate &optional name)
+ "Show full help for the function CANDIDATE.
+Arg NAME specify the name of the top level function
+calling helm generic completion (e.g \"describe-function\")
+which allow calling the right function when CANDIDATE symbol
+refers at the same time to variable and a function."
+ (helm-elisp--persistent-help
+ candidate 'helm-elisp--show-help-1 name))
+
+(defun helm-elisp-show-doc-modeline (candidate &optional name)
+ "Show brief documentation for the function in modeline."
+ (let ((cursor-in-echo-area t)
+ mode-line-in-non-selected-windows)
+ (helm-show-info-in-mode-line
+ (propertize
+ (helm-get-first-line-documentation
+ (intern candidate) name)
+ 'face 'helm-lisp-completion-info))))
+
+(defun helm-lisp-completion-transformer (candidates _source)
+ "Helm candidates transformer for lisp completion."
+ (cl-loop for c in candidates
+ for sym = (intern c)
+ for annot = (cl-typecase sym
+ (command " (Com)")
+ (class " (Class)")
+ (generic " (Gen)")
+ (fbound " (Fun)")
+ (bound " (Var)")
+ (face " (Face)"))
+ for spaces = (make-string (- helm-lgst-len (length c)) ? )
+ collect (cons (concat c spaces annot) c) into lst
+ finally return (sort lst #'helm-generic-sort-fn)))
+
+(defun helm-get-first-line-documentation (sym &optional name)
+ "Return first line documentation of symbol SYM.
+If SYM is not documented, return \"Not documented\"."
+ (let ((doc (cl-typecase sym
+ ((and fboundp boundp)
+ (cond ((string= name "describe-function")
+ (documentation sym t))
+ ((string= name "describe-variable")
+ (documentation-property sym 'variable-documentation t))
+ (t (documentation sym t))))
+ (fbound (documentation sym t))
+ (bound (documentation-property sym 'variable-documentation t))
+ (face (face-documentation sym)))))
+ (if (and doc (not (string= doc ""))
+ ;; `documentation' return "\n\n(args...)"
+ ;; for CL-style functions.
+ (not (string-match-p "^\n\n" doc)))
+ (car (split-string doc "\n"))
+ "Not documented")))
+
+;;; File completion.
+;;
+;; Complete file name at point.
+
+;;;###autoload
+(defun helm-complete-file-name-at-point (&optional force)
+ "Preconfigured helm to complete file name at point."
+ (interactive)
+ (require 'helm-mode)
+ (let* ((tap (thing-at-point 'filename))
+ beg
+ (init (and tap
+ (or force
+ (save-excursion
+ (end-of-line)
+ (search-backward tap (point-at-bol) t)
+ (setq beg (point))
+ (looking-back "[^'`( ]" (1- (point)))))
+ (expand-file-name
+ (substring-no-properties tap))))
+ (end (point))
+ (helm-quit-if-no-candidate t)
+ (helm-execute-action-at-once-if-one t)
+ completion)
+ (with-helm-show-completion beg end
+ (setq completion (helm-read-file-name "FileName: "
+ :initial-input init)))
+ (when (and completion (not (string= completion "")))
+ (delete-region beg end) (insert (if (string-match "^~" tap)
+ (abbreviate-file-name completion)
+ completion)))))
+
+;;;###autoload
+(defun helm-lisp-indent ()
+ ;; It is meant to use with `helm-define-multi-key' which
+ ;; does not support args for functions yet, so use `current-prefix-arg'
+ ;; for now instead of (interactive "P").
+ (interactive)
+ (let ((tab-always-indent (or (eq tab-always-indent 'complete)
+ tab-always-indent)))
+ (indent-for-tab-command current-prefix-arg)))
+
+;;;###autoload
+(defun helm-lisp-completion-or-file-name-at-point ()
+ "Preconfigured helm to complete lisp symbol or filename at point.
+Filename completion happen if string start after or between a double quote."
+ (interactive)
+ (let* ((tap (thing-at-point 'filename)))
+ (if (and tap (save-excursion
+ (end-of-line)
+ (search-backward tap (point-at-bol) t)
+ (looking-back "[^'`( ]" (1- (point)))))
+ (helm-complete-file-name-at-point)
+ (helm-lisp-completion-at-point))))
+
+\f
+;;; Apropos
+;;
+;;
+(defvar helm-apropos-history nil)
+
+(defun helm-apropos-init (test default)
+ "Init candidates buffer for `helm-apropos' sources."
+ (require 'helm-help)
+ (helm-init-candidates-in-buffer 'global
+ (let ((default-symbol (and (stringp default)
+ (intern-soft default)))
+ (symbols (all-completions "" obarray test)))
+ (if (and default-symbol (funcall test default-symbol))
+ (cons default-symbol symbols)
+ symbols))))
+
+(defun helm-apropos-init-faces (default)
+ "Init candidates buffer for faces for `helm-apropos'."
+ (require 'helm-help)
+ (with-current-buffer (helm-candidate-buffer 'global)
+ (goto-char (point-min))
+ (let ((default-symbol (and (stringp default)
+ (intern-soft default)))
+ (faces (face-list)))
+ (when (and default-symbol (facep default-symbol))
+ (insert (concat default "\n")))
+ (insert
+ (mapconcat #'prin1-to-string
+ (if default
+ (cl-remove-if (lambda (sym) (string= sym default)) faces)
+ faces)
+ "\n")))))
+
+(defun helm-apropos-default-sort-fn (candidates _source)
+ (if (string= helm-pattern "")
+ candidates
+ (sort candidates #'helm-generic-sort-fn)))
+
+(defun helm-apropos-clean-history-variable (candidate)
+ (with-helm-current-buffer ; var is maybe local
+ (let* ((sym (intern-soft candidate))
+ (cands (symbol-value sym))
+ (mkds (and (listp cands)
+ (helm-comp-read "Delete entry: "
+ cands :marked-candidates t))))
+ (cl-assert (listp mkds) nil "Variable value is not a list")
+ (cl-loop for elm in mkds do
+ (if (local-variable-p sym)
+ (set (make-local-variable sym)
+ (setq cands (delete elm cands)))
+ (set sym (setq cands (delete elm cands))))))))
+
+(defun helm-apropos-clean-ring (candidate)
+ (with-helm-current-buffer ; var is maybe local
+ (let* ((sym (intern-soft candidate))
+ (val (symbol-value sym))
+ (cands (and (ring-p val) (ring-elements val)))
+ (mkds (and cands (helm-comp-read
+ "Delete entry: "
+ cands :marked-candidates t))))
+ (when mkds
+ (cl-loop for elm in mkds do
+ (ring-remove
+ val (helm-position
+ elm
+ (ring-elements val)
+ :test 'equal))
+ and do (if (local-variable-p sym)
+ (set (make-local-variable sym) val)
+ (set sym val)))))))
+
+(defun helm-apropos-action-transformer (actions candidate)
+ (let* ((sym (helm-symbolify candidate))
+ (val (with-helm-current-buffer (symbol-value sym))))
+ (cond ((custom-variable-p sym)
+ (append
+ actions
+ (let ((standard-value (eval (car (get sym 'standard-value)))))
+ (unless (equal standard-value (symbol-value sym))
+ `(("Reset Variable to default value"
+ . ,(lambda (candidate)
+ (let ((sym (helm-symbolify candidate)))
+ (set sym standard-value)))))))
+ '(("Customize variable" .
+ (lambda (candidate)
+ (customize-option (helm-symbolify candidate)))))))
+ ((and val (with-helm-current-buffer (ring-p (symbol-value sym))))
+ (append actions
+ '(("Clean ring" . helm-apropos-clean-ring))))
+ ((and (string-match-p "history" candidate) (listp val))
+ (append actions
+ '(("Clean variable" .
+ helm-apropos-clean-history-variable))))
+ (t actions))))
+
+(defun helm-def-source--emacs-variables (&optional default)
+ (helm-build-in-buffer-source "Variables"
+ :init (lambda ()
+ (helm-apropos-init
+ (lambda (x) (and (boundp x) (not (keywordp x)))) default))
+ :fuzzy-match helm-apropos-fuzzy-match
+ :filtered-candidate-transformer (and (null helm-apropos-fuzzy-match)
+ 'helm-apropos-default-sort-fn)
+ :nomark t
+ :persistent-action (lambda (candidate)
+ (helm-elisp--persistent-help
+ candidate 'helm-describe-variable))
+ :persistent-help "Toggle describe variable"
+ :action '(("Describe variable" . helm-describe-variable)
+ ("Find variable" . helm-find-variable)
+ ("Info lookup" . helm-info-lookup-symbol)
+ ("Set variable" . helm-set-variable))
+ :action-transformer 'helm-apropos-action-transformer))
+
+(defun helm-def-source--emacs-faces (&optional default)
+ "Create `helm' source for faces to be displayed with
+`helm-apropos'."
+ (helm-build-in-buffer-source "Faces"
+ :init (lambda () (helm-apropos-init-faces default))
+ :fuzzy-match helm-apropos-fuzzy-match
+ :filtered-candidate-transformer
+ (append (and (null helm-apropos-fuzzy-match)
+ '(helm-apropos-default-sort-fn))
+ (list
+ (lambda (candidates _source)
+ (cl-loop for c in candidates
+ collect (propertize c 'face (intern c))))))
+ :persistent-action (lambda (candidate)
+ (helm-elisp--persistent-help
+ candidate 'helm-describe-face))
+ :persistent-help "Toggle describe face"
+ :action '(("Describe face" . helm-describe-face)
+ ("Find face" . helm-find-face-definition)
+ ("Customize face" . (lambda (candidate)
+ (customize-face (helm-symbolify candidate)))))))
+
+(defun helm-def-source--emacs-commands (&optional default)
+ (helm-build-in-buffer-source "Commands"
+ :init (lambda ()
+ (helm-apropos-init 'commandp default))
+ :fuzzy-match helm-apropos-fuzzy-match
+ :filtered-candidate-transformer (and (null helm-apropos-fuzzy-match)
+ 'helm-apropos-default-sort-fn)
+ :nomark t
+ :persistent-action (lambda (candidate)
+ (helm-elisp--persistent-help
+ candidate 'helm-describe-function))
+ :persistent-help "Toggle describe command"
+ :action '(("Describe function" . helm-describe-function)
+ ("Find function" . helm-find-function)
+ ("Info lookup" . helm-info-lookup-symbol))))
+
+(defun helm-def-source--emacs-functions (&optional default)
+ (helm-build-in-buffer-source "Functions"
+ :init (lambda ()
+ (helm-apropos-init (lambda (x)
+ (and (fboundp x)
+ (not (commandp x))
+ (not (generic-p x))
+ (not (class-p x))))
+ default))
+ :fuzzy-match helm-apropos-fuzzy-match
+ :filtered-candidate-transformer (and (null helm-apropos-fuzzy-match)
+ 'helm-apropos-default-sort-fn)
+ :persistent-action (lambda (candidate)
+ (helm-elisp--persistent-help
+ candidate 'helm-describe-function))
+ :persistent-help "Toggle describe function"
+ :nomark t
+ :action '(("Describe function" . helm-describe-function)
+ ("Find function" . helm-find-function)
+ ("Info lookup" . helm-info-lookup-symbol))))
+
+(defun helm-def-source--eieio-classes (&optional default)
+ (helm-build-in-buffer-source "Classes"
+ :init (lambda ()
+ (helm-apropos-init (lambda (x)
+ (class-p x))
+ default))
+ :fuzzy-match helm-apropos-fuzzy-match
+ :filtered-candidate-transformer (and (null helm-apropos-fuzzy-match)
+ 'helm-apropos-default-sort-fn)
+ :nomark t
+ :persistent-action (lambda (candidate)
+ (helm-elisp--persistent-help
+ candidate 'helm-describe-function))
+ :persistent-help "Toggle describe class"
+ :action '(("Describe function" . helm-describe-function)
+ ("Find function" . helm-find-function)
+ ("Info lookup" . helm-info-lookup-symbol))))
+
+(defun helm-def-source--eieio-generic (&optional default)
+ (helm-build-in-buffer-source "Generic functions"
+ :init (lambda ()
+ (helm-apropos-init (lambda (x)
+ (generic-p x))
+ default))
+ :fuzzy-match helm-apropos-fuzzy-match
+ :filtered-candidate-transformer (and (null helm-apropos-fuzzy-match)
+ 'helm-apropos-default-sort-fn)
+ :nomark t
+ :persistent-action (lambda (candidate)
+ (helm-elisp--persistent-help
+ candidate 'helm-describe-function))
+ :persistent-help "Toggle describe generic function"
+ :action '(("Describe function" . helm-describe-function)
+ ("Find function" . helm-find-function)
+ ("Info lookup" . helm-info-lookup-symbol))))
+
+(defun helm-info-lookup-fallback-source (candidate)
+ (let ((sym (helm-symbolify candidate))
+ src-name fn)
+ (cond ((class-p sym)
+ (setq fn #'helm-describe-function
+ src-name "Describe class"))
+ ((generic-p sym)
+ (setq fn #'helm-describe-function
+ src-name "Describe generic function"))
+ ((fboundp sym)
+ (setq fn #'helm-describe-function
+ src-name "Describe function"))
+ ((facep sym)
+ (setq fn #'helm-describe-face
+ src-name "Describe face"))
+ (t
+ (setq fn #'helm-describe-variable
+ src-name "Describe variable")))
+ (helm-build-sync-source src-name
+ :candidates (list candidate)
+ :persistent-action (lambda (candidate)
+ (helm-elisp--persistent-help
+ candidate fn))
+ :persistent-help src-name
+ :nomark t
+ :action fn)))
+
+(defun helm-info-lookup-symbol-1 (c)
+ (let ((helm-execute-action-at-once-if-one 'current-source))
+ (helm :sources (append helm-apropos-defaut-info-lookup-sources
+ (list (helm-info-lookup-fallback-source c)))
+ :resume 'noresume
+ :buffer "*helm lookup*"
+ :input c)))
+
+(defun helm-info-lookup-symbol (candidate)
+ ;; ???:Running an idle-timer allows not catching RET when exiting
+ ;; with the fallback source.
+ ;; (run-with-idle-timer 0.01 nil #'helm-info-lookup-symbol-1 candidate)
+ (helm-info-lookup-symbol-1 candidate))
+
+;;;###autoload
+(defun helm-apropos (default)
+ "Preconfigured helm to describe commands, functions, variables and faces.
+In non interactives calls DEFAULT argument should be provided as a string,
+i.e the `symbol-name' of any existing symbol."
+ (interactive (list (thing-at-point 'symbol)))
+ (helm :sources
+ (mapcar (lambda (func)
+ (funcall func default))
+ helm-apropos-function-list)
+ :history 'helm-apropos-history
+ :buffer "*helm apropos*"
+ :preselect (and default (concat "\\_<" (regexp-quote default) "\\_>"))))
+
+\f
+;;; Advices
+;;
+;;
+(defvar helm-source-advice
+ (helm-build-sync-source "Function Advice"
+ :init (lambda () (require 'advice))
+ :candidates 'helm-advice-candidates
+ :action (helm-make-actions "Toggle Enable/Disable" 'helm-advice-toggle)
+ :persistent-action 'helm-advice-persistent-action
+ :nomark t
+ :multiline t
+ :persistent-help "Toggle describe function / C-u C-j: Toggle advice"))
+
+(defun helm-advice-candidates ()
+ (cl-loop for (fname) in ad-advised-functions
+ for function = (intern fname)
+ append
+ (cl-loop for class in ad-advice-classes append
+ (cl-loop for advice in (ad-get-advice-info-field function class)
+ for enabled = (ad-advice-enabled advice)
+ collect
+ (cons (format
+ "%s %s %s"
+ (if enabled "Enabled " "Disabled")
+ (propertize fname 'face 'font-lock-function-name-face)
+ (ad-make-single-advice-docstring advice class nil))
+ (list function class advice))))))
+
+(defun helm-advice-persistent-action (func-class-advice)
+ (if current-prefix-arg
+ (helm-advice-toggle func-class-advice)
+ (describe-function (car func-class-advice))))
+
+(defun helm-advice-toggle (func-class-advice)
+ (cl-destructuring-bind (function _class advice) func-class-advice
+ (cond ((ad-advice-enabled advice)
+ (ad-advice-set-enabled advice nil)
+ (message "Disabled"))
+ (t
+ (ad-advice-set-enabled advice t)
+ (message "Enabled")))
+ (ad-activate function)
+ (and helm-in-persistent-action
+ (helm-advice-update-current-display-string))))
+
+(defun helm-advice-update-current-display-string ()
+ (helm-edit-current-selection
+ (let ((newword (cond ((looking-at "Disabled") "Enabled")
+ ((looking-at "Enabled") "Disabled"))))
+ (when newword
+ (delete-region (point) (progn (forward-word 1) (point)))
+ (insert newword)))))
+
+;;;###autoload
+(defun helm-manage-advice ()
+ "Preconfigured `helm' to disable/enable function advices."
+ (interactive)
+ (helm-other-buffer 'helm-source-advice "*helm advice*"))
+
+\f
+;;; Locate elisp library
+;;
+;;
+(defun helm-locate-library-scan-list ()
+ (cl-loop for dir in load-path
+ with load-suffixes = '(".el")
+ when (file-directory-p dir)
+ append (directory-files
+ dir t (concat (regexp-opt (get-load-suffixes))
+ "\\'"))))
+
+;;;###autoload
+(defun helm-locate-library ()
+ "Preconfigured helm to locate elisp libraries."
+ (interactive)
+ (helm :sources (helm-build-in-buffer-source "Elisp libraries (Scan)"
+ :data #'helm-locate-library-scan-list
+ :fuzzy-match helm-locate-library-fuzzy-match
+ :keymap helm-generic-files-map
+ :search (unless helm-locate-library-fuzzy-match
+ (lambda (regexp)
+ (re-search-forward
+ (if helm-ff-transformer-show-only-basename
+ (replace-regexp-in-string
+ "\\`\\^" "" regexp)
+ regexp)
+ nil t)))
+ :match-part (lambda (candidate)
+ (if helm-ff-transformer-show-only-basename
+ (helm-basename candidate) candidate))
+ :filter-one-by-one (lambda (c)
+ (if helm-ff-transformer-show-only-basename
+ (cons (helm-basename c) c) c))
+ :action (helm-actions-from-type-file))
+ :ff-transformer-show-only-basename nil
+ :buffer "*helm locate library*"))
+
+(defun helm-set-variable (var)
+ "Set value to VAR interactively."
+ (let* ((sym (helm-symbolify var))
+ (val (default-value sym)))
+ (set-default sym (eval-minibuffer (format "Set `%s': " var)
+ (if (or (stringp val) (memq val '(nil t)))
+ (prin1-to-string val)
+ (format "'%s" (prin1-to-string val)))))))
+
+\f
+;;; Elisp Timers.
+;;
+;;
+(defclass helm-absolute-time-timers-class (helm-source-sync helm-type-timers)
+ ((candidates :initform timer-list)
+ (allow-dups :initform t)
+ (candidate-transformer
+ :initform
+ (lambda (candidates)
+ (cl-loop for timer in candidates
+ collect (cons (helm-elisp--format-timer timer) timer))))))
+
+(defvar helm-source-absolute-time-timers
+ (helm-make-source "Absolute Time Timers" 'helm-absolute-time-timers-class))
+
+(defclass helm-idle-time-timers-class (helm-source-sync helm-type-timers)
+ ((candidates :initform timer-idle-list)
+ (allow-dups :initform t)
+ (candidate-transformer
+ :initform
+ (lambda (candidates)
+ (cl-loop for timer in candidates
+ collect (cons (helm-elisp--format-timer timer) timer))))))
+
+(defvar helm-source-idle-time-timers
+ (helm-make-source "Idle Time Timers" 'helm-idle-time-timers-class))
+
+(defun helm-elisp--format-timer (timer)
+ (format "%s repeat=%s %s(%s)"
+ (let ((time (timer--time timer)))
+ (if (timer--idle-delay timer)
+ (format-time-string "idle-for=%5s" time)
+ (format-time-string "%m/%d %T" time)))
+ (or (timer--repeat-delay timer) "nil")
+ (mapconcat 'identity (split-string
+ (prin1-to-string (timer--function timer))
+ "\n") " ")
+ (mapconcat 'prin1-to-string (timer--args timer) " ")))
+
+;;;###autoload
+(defun helm-timers ()
+ "Preconfigured `helm' for timers."
+ (interactive)
+ (helm :sources '(helm-source-absolute-time-timers
+ helm-source-idle-time-timers)
+ :buffer "*helm timers*"))
+
+\f
+;;; Complex command history
+;;
+;;
+(defun helm-btf--usable-p ()
+ "Return t if current version of `backtrace-frame' accept 2 arguments."
+ (condition-case nil
+ (progn (backtrace-frame 1 'condition-case) t)
+ (wrong-number-of-arguments nil)))
+
+(if (helm-btf--usable-p) ; Check if BTF accept more than one arg.
+ ;; Emacs 24.4.
+ (dont-compile
+ (defvar helm-sexp--last-sexp nil)
+ ;; This wont work compiled.
+ (defun helm-sexp-eval-1 ()
+ (interactive)
+ (unwind-protect
+ (progn
+ ;; Trick called-interactively-p into thinking that `cand' is
+ ;; an interactive call, See `repeat-complex-command'.
+ (add-hook 'called-interactively-p-functions
+ #'helm-complex-command-history--called-interactively-skip)
+ (eval (read helm-sexp--last-sexp)))
+ (remove-hook 'called-interactively-p-functions
+ #'helm-complex-command-history--called-interactively-skip)))
+
+ (defun helm-complex-command-history--called-interactively-skip (i _frame1 frame2)
+ (and (eq 'eval (cadr frame2))
+ (eq 'helm-sexp-eval-1
+ (cadr (backtrace-frame (+ i 2) #'called-interactively-p)))
+ 1))
+
+ (defun helm-sexp-eval (_candidate)
+ (call-interactively #'helm-sexp-eval-1)))
+ ;; Emacs 24.3
+ (defun helm-sexp-eval (cand)
+ (let ((sexp (read cand)))
+ (condition-case err
+ (if (> (length (remove nil sexp)) 1)
+ (eval sexp)
+ (apply 'call-interactively sexp))
+ (error (message "Evaluating gave an error: %S" err)
+ nil)))))
+
+(defvar helm-source-complex-command-history
+ (helm-build-sync-source "Complex Command History"
+ :candidates (lambda ()
+ ;; Use cdr to avoid adding
+ ;; `helm-complex-command-history' here.
+ (cl-loop for i in command-history
+ unless (equal i '(helm-complex-command-history))
+ collect (prin1-to-string i)))
+ :action (helm-make-actions
+ "Eval" (lambda (candidate)
+ (and (boundp 'helm-sexp--last-sexp)
+ (setq helm-sexp--last-sexp candidate))
+ (let ((command (read candidate)))
+ (unless (equal command (car command-history))
+ (setq command-history (cons command command-history))))
+ (run-with-timer 0.1 nil #'helm-sexp-eval candidate))
+ "Edit and eval" (lambda (candidate)
+ (edit-and-eval-command "Eval: " (read candidate))))
+ :persistent-action #'helm-sexp-eval
+ :multiline t))
+
+;;;###autoload
+(defun helm-complex-command-history ()
+ "Preconfigured helm for complex command history."
+ (interactive)
+ (helm :sources 'helm-source-complex-command-history
+ :buffer "*helm complex commands*"))
+
+(provide 'helm-elisp)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-elisp.el ends here
--- /dev/null
+;;; helm-eshell.el --- pcomplete and eshell completion for helm. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Commentary:
+;;
+;; Enable like this in .emacs:
+;; (add-hook 'eshell-mode-hook
+;; (lambda ()
+;; (eshell-cmpl-initialize)
+;; (define-key eshell-mode-map [remap eshell-pcomplete] 'helm-esh-pcomplete)
+;; (define-key eshell-mode-map (kbd "M-s f") 'helm-eshell-prompts-all)))
+;; (define-key eshell-mode-map (kbd "M-r") 'helm-eshell-history)))
+
+
+;;; Code:
+(require 'cl-lib)
+(require 'helm)
+(require 'helm-lib)
+(require 'helm-help)
+(require 'helm-elisp)
+
+(declare-function eshell-read-aliases-list "em-alias")
+(declare-function eshell-send-input "esh-mode" (&optional use-region queue-p no-newline))
+(declare-function eshell-bol "esh-mode")
+(declare-function eshell-parse-arguments "esh-arg" (beg end))
+(declare-function eshell-backward-argument "esh-mode" (&optional arg))
+(declare-function helm-quote-whitespace "helm-lib")
+(declare-function eshell-skip-prompt "em-prompt")
+(defvar eshell-special-chars-outside-quoting)
+
+\f
+(defgroup helm-eshell nil
+ "Helm eshell completion and history."
+ :group 'helm)
+
+\f
+(defcustom helm-eshell-fuzzy-match nil
+ "Enable fuzzy matching in `helm-esh-pcomplete' when non--nil."
+ :group 'helm-eshell
+ :type 'boolean)
+
+\f
+(defvar helm-eshell-history-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map helm-map)
+ (define-key map (kbd "M-p") 'helm-next-line)
+ map)
+ "Keymap for `helm-eshell-history'.")
+
+(defvar helm-esh-completion-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map helm-map)
+ (define-key map (kbd "TAB") 'helm-next-line)
+ map)
+ "Keymap for `helm-esh-pcomplete'.")
+
+(defvar helm-eshell--quit-flag nil)
+
+\f
+(defclass helm-esh-source (helm-source-sync)
+ ((init :initform (lambda ()
+ (setq pcomplete-current-completions nil
+ pcomplete-last-completion-raw nil)
+ ;; Eshell-command add this hook in all minibuffers
+ ;; Remove it for the helm one. (Fixed in Emacs24)
+ (remove-hook 'minibuffer-setup-hook 'eshell-mode)))
+ (candidates :initform 'helm-esh-get-candidates)
+ ;(nomark :initform t)
+ (persistent-action :initform 'ignore)
+ (nohighlight :initform t)
+ (filtered-candidate-transformer
+ :initform
+ (lambda (candidates _sources)
+ (cl-loop
+ for i in candidates
+ collect
+ (cond ((string-match "\\`~/?" helm-ec-target)
+ (abbreviate-file-name i))
+ ((string-match "\\`/" helm-ec-target) i)
+ (t
+ (file-relative-name i)))
+ into lst
+ finally return (sort lst 'helm-generic-sort-fn))))
+ (action :initform 'helm-ec-insert))
+ "Helm class to define source for Eshell completion.")
+
+;; Internal.
+(defvar helm-ec-target "")
+(defun helm-ec-insert (_candidate)
+ "Replace text at point with CANDIDATE.
+The function that call this should set `helm-ec-target' to thing at point."
+ (set (make-local-variable 'comint-file-name-quote-list)
+ eshell-special-chars-outside-quoting)
+ (let ((pt (point)))
+ (when (and helm-ec-target
+ (search-backward helm-ec-target nil t)
+ (string= (buffer-substring (point) pt) helm-ec-target))
+ (delete-region (point) pt)))
+ (when (string-match "\\`\\*" helm-ec-target) (insert "*"))
+ (let ((marked (helm-marked-candidates)))
+ (prog1 t ;; Makes helm returns t on action.
+ (insert
+ (mapconcat
+ (lambda (x)
+ (cond ((string-match "\\`~/" helm-ec-target)
+ ;; Strip out the first escape char added by
+ ;; `comint-quote-filename' before "~" (Issue #1803).
+ (substring (comint-quote-filename (abbreviate-file-name x)) 1))
+ ((string-match "\\`/" helm-ec-target)
+ (comint-quote-filename x))
+ (t
+ (concat (and (string-match "\\`[.]/" helm-ec-target) "./")
+ (comint-quote-filename
+ (file-relative-name x))))))
+ marked " ")
+ (or (helm-aand (car (last marked))
+ (string-match-p "/\\'" it)
+ "")
+ " ")))))
+
+(defun helm-esh-get-candidates ()
+ "Get candidates for eshell completion using `pcomplete'."
+ (catch 'pcompleted
+ (with-helm-current-buffer
+ (let* ((pcomplete-stub)
+ pcomplete-seen pcomplete-norm-func
+ pcomplete-args pcomplete-last pcomplete-index
+ (pcomplete-autolist pcomplete-autolist)
+ (pcomplete-suffix-list pcomplete-suffix-list)
+ (table (pcomplete-completions))
+ (entry (or (try-completion helm-pattern
+ (pcomplete-entries))
+ helm-pattern)))
+ (cl-loop ;; expand entry too to be able to compare it with file-cand.
+ with exp-entry = (and (stringp entry)
+ (not (string= entry ""))
+ (file-name-as-directory
+ (expand-file-name entry default-directory)))
+ with comps = (all-completions pcomplete-stub table)
+ unless comps return (prog1 nil
+ ;; Don't add final space when
+ ;; there is no completion (issue #1990).
+ (setq helm-eshell--quit-flag t)
+ (message "No completions of %s" pcomplete-stub))
+ for i in comps
+ ;; Transform the related names to abs names.
+ for file-cand = (and exp-entry
+ (if (file-remote-p i) i
+ (expand-file-name
+ i (file-name-directory entry))))
+ ;; Compare them to avoid dups.
+ for file-entry-p = (and (stringp exp-entry)
+ (stringp file-cand)
+ ;; Fix :/tmp/foo/ $ cd foo
+ (not (file-directory-p file-cand))
+ (file-equal-p exp-entry file-cand))
+ if (and file-cand (or (file-remote-p file-cand)
+ (file-exists-p file-cand))
+ (not file-entry-p))
+ collect file-cand into ls
+ else
+ ;; Avoid adding entry here.
+ unless file-entry-p collect i into ls
+ finally return
+ (if (and exp-entry
+ (file-directory-p exp-entry)
+ ;; If the car of completion list is
+ ;; an executable, probably we are in
+ ;; command completion, so don't add a
+ ;; possible file related entry here.
+ (and ls (not (executable-find (car ls))))
+ ;; Don't add entry if already in prompt.
+ (not (file-equal-p exp-entry pcomplete-stub)))
+ (append (list exp-entry)
+ ;; Entry should not be here now but double check.
+ (remove entry ls))
+ ls))))))
+\f
+;;; Eshell history.
+;;
+;;
+(defclass helm-eshell-history-source (helm-source-sync)
+ ((init :initform
+ (lambda ()
+ ;; Same comment as in `helm-source-esh'.
+ (remove-hook 'minibuffer-setup-hook 'eshell-mode)))
+ (candidates
+ :initform
+ (lambda ()
+ (with-helm-current-buffer
+ (cl-loop for c from 0 to (ring-length eshell-history-ring)
+ collect (eshell-get-history c)))))
+ (nomark :initform t)
+ (multiline :initform t)
+ (keymap :initform helm-eshell-history-map)
+ (candidate-number-limit :initform 9999)
+ (action :initform (lambda (candidate)
+ (eshell-kill-input)
+ (insert candidate))))
+ "Helm class to define source for Eshell history.")
+
+\f
+;;;###autoload
+(defun helm-esh-pcomplete ()
+ "Preconfigured helm to provide helm completion in eshell."
+ (interactive)
+ (let* ((helm-quit-if-no-candidate t)
+ (helm-execute-action-at-once-if-one t)
+ (end (point-marker))
+ (beg (save-excursion (eshell-bol) (point)))
+ (args (catch 'eshell-incomplete
+ (eshell-parse-arguments beg end)))
+ (target
+ (or (and (looking-back " " (1- (point))) " ")
+ (buffer-substring-no-properties
+ (save-excursion
+ (eshell-backward-argument 1) (point))
+ end)))
+ (users-comp (string= target "~"))
+ (first (car args)) ; Maybe lisp delimiter "(".
+ last ; Will be the last but parsed by pcomplete.
+ del-space
+ del-dot)
+ (setq helm-ec-target (or target " ")
+ end (point)
+ ;; Reset beg for `with-helm-show-completion'.
+ beg (or (and target (not (string= target " "))
+ (- end (length target)))
+ ;; Nothing at point.
+ (progn (insert " ") (setq del-space t) (point))))
+ (when (string-match "\\`[~.]*.*/[.]\\'" target)
+ ;; Fix completion on
+ ;; "~/.", "~/[...]/.", and "../."
+ (delete-char -1) (setq del-dot t)
+ (setq helm-ec-target (substring helm-ec-target 0 (1- (length helm-ec-target)))))
+ (cond ((eq first ?\()
+ (helm-lisp-completion-or-file-name-at-point))
+ ;; In eshell `pcomplete-parse-arguments' is called
+ ;; with `pcomplete-parse-arguments-function'
+ ;; locally bound to `eshell-complete-parse-arguments'
+ ;; which is calling `lisp-complete-symbol',
+ ;; calling it before would popup the
+ ;; *completions* buffer.
+ (t (setq last (replace-regexp-in-string
+ "\\`\\*" ""
+ (car (last (ignore-errors
+ (pcomplete-parse-arguments))))))
+ ;; Set helm-eshell--quit-flag to non-nil only on
+ ;; quit, this tells to not add final suffix when quitting
+ ;; helm.
+ (add-hook 'helm-quit-hook 'helm-eshell--quit-hook-fn)
+ (with-helm-show-completion beg end
+ (unwind-protect
+ (or (helm :sources (helm-make-source "Eshell completions" 'helm-esh-source
+ :fuzzy-match helm-eshell-fuzzy-match)
+ :buffer "*helm pcomplete*"
+ :keymap helm-esh-completion-map
+ :resume 'noresume
+ :input (if (and (stringp last)
+ (not (string= last ""))
+ (not users-comp)
+ ;; Fix completion on
+ ;; "../" see #1832.
+ (or (file-exists-p last)
+ (helm-aand
+ (file-name-directory last)
+ (file-directory-p it))))
+ (if (and (file-directory-p last)
+ (string-match "\\`[~.]*.*/[.]\\'" target))
+ ;; Fix completion on
+ ;; "~/.", "~/[...]/.", and "../."
+ (expand-file-name
+ (concat (helm-basedir (file-name-as-directory last))
+ (regexp-quote (helm-basename target))))
+ (expand-file-name last))
+ ;; Don't add "~" to input to
+ ;; provide completion on all
+ ;; users instead of only on
+ ;; current $HOME (#1832).
+ (unless users-comp last)))
+ ;; Delete removed dot on quit
+ (and del-dot (prog1 t (insert ".")))
+ ;; A space is needed to have completion, remove
+ ;; it when nothing found.
+ (and del-space (looking-back "\\s-" (1- (point)))
+ (delete-char -1))
+ (if (and (null helm-eshell--quit-flag)
+ (and (stringp last) (file-directory-p last))
+ (looking-back "\\([.]\\{1,2\\}\\|[^/]\\)\\'"
+ (1- (point))))
+ (prog1 t (insert "/"))
+ ;; We need another flag for space here, but
+ ;; global to pass it to `helm-quit-hook', this
+ ;; space is added when point is just after
+ ;; previous completion and there is no
+ ;; more completion, see issue #1832.
+ (unless (or helm-eshell--quit-flag
+ (looking-back "/\\'" (1- (point))))
+ (prog1 t (insert " ")))
+ (when (and helm-eshell--quit-flag
+ (string-match-p "[.]\\{2\\}\\'" last))
+ (insert "/"))))
+ (remove-hook 'helm-quit-hook 'helm-eshell--quit-hook-fn)
+ (setq helm-eshell--quit-flag nil)))))))
+
+(defun helm-eshell--quit-hook-fn ()
+ (setq helm-eshell--quit-flag t))
+
+;;;###autoload
+(defun helm-eshell-history ()
+ "Preconfigured helm for eshell history."
+ (interactive)
+ (let* ((end (point))
+ (beg (save-excursion (eshell-bol) (point)))
+ (input (buffer-substring beg end))
+ flag-empty)
+ (when (eq beg end)
+ (insert " ")
+ (setq flag-empty t)
+ (setq end (point)))
+ (unwind-protect
+ (with-helm-show-completion beg end
+ (helm :sources (helm-make-source "Eshell history"
+ 'helm-eshell-history-source)
+ :buffer "*helm eshell history*"
+ :resume 'noresume
+ :input input))
+ (when (and flag-empty
+ (looking-back " " (1- (point))))
+ (delete-char -1)))))
+
+\f
+;;; Eshell prompts
+;;
+(defface helm-eshell-prompts-promptidx
+ '((t (:foreground "cyan")))
+ "Face used to highlight Eshell prompt index."
+ :group 'helm-eshell-faces)
+
+(defface helm-eshell-prompts-buffer-name
+ '((t (:foreground "green")))
+ "Face used to highlight Eshell buffer name."
+ :group 'helm-eshell-faces)
+
+(defcustom helm-eshell-prompts-promptidx-p t
+ "Show prompt number."
+ :group 'helm-eshell
+ :type 'boolean)
+
+(defvar helm-eshell-prompts-keymap
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map helm-map)
+ (define-key map (kbd "C-c o") 'helm-eshell-prompts-other-window)
+ (define-key map (kbd "C-c C-o") 'helm-eshell-prompts-other-frame)
+ map)
+ "Keymap for `helm-eshell-prompt-all'.")
+
+(defvar eshell-prompt-regexp)
+(defvar eshell-highlight-prompt)
+
+(defun helm-eshell-prompts-list (&optional buffer)
+ "List the prompts in Eshell BUFFER.
+
+Return a list of (\"prompt\" (point) (buffer-name) prompt-index))
+e.g. (\"ls\" 162 \"*eshell*\" 3).
+If BUFFER is nil, use current buffer."
+ (with-current-buffer (or buffer (current-buffer))
+ (when (eq major-mode 'eshell-mode)
+ (save-excursion
+ (goto-char (point-min))
+ (let (result (count 1))
+ (helm-awhile (re-search-forward eshell-prompt-regexp nil t)
+ (when (or (and eshell-highlight-prompt
+ (get-text-property (match-beginning 0) 'read-only))
+ (null eshell-highlight-prompt))
+ (push (list (buffer-substring-no-properties
+ it (point-at-eol))
+ it (buffer-name) count)
+ result)
+ (setq count (1+ count))))
+ (nreverse result))))))
+
+(defun helm-eshell-prompts-list-all ()
+ "List the prompts of all Eshell buffers.
+See `helm-eshell-prompts-list'."
+ (cl-loop for b in (buffer-list)
+ append (helm-eshell-prompts-list b)))
+
+(defun helm-eshell-prompts-transformer (candidates &optional all)
+ ;; ("ls" 162 "*eshell*" 3) => ("*eshell*:3:ls" . ("ls" 162 "*eshell*" 3))
+ (cl-loop for (prt pos buf id) in candidates
+ collect `(,(concat
+ (when all
+ (concat (propertize
+ buf
+ 'face 'helm-eshell-prompts-buffer-name)
+ ":"))
+ (when helm-eshell-prompts-promptidx-p
+ (concat (propertize
+ (number-to-string id)
+ 'face 'helm-eshell-prompts-promptidx)
+ ":"))
+ prt)
+ . ,(list prt pos buf id))))
+
+(defun helm-eshell-prompts-all-transformer (candidates)
+ (helm-eshell-prompts-transformer candidates t))
+
+(cl-defun helm-eshell-prompts-goto (candidate &optional (action 'switch-to-buffer))
+ ;; Candidate format: ("ls" 162 "*eshell*" 3)
+ (let ((buf (nth 2 candidate)))
+ (unless (and (string= (buffer-name) buf)
+ (eq action 'switch-to-buffer))
+ (funcall action buf))
+ (goto-char (nth 1 candidate))
+ (recenter)))
+
+(defun helm-eshell-prompts-goto-other-window (candidate)
+ (helm-eshell-prompts-goto candidate 'switch-to-buffer-other-window))
+
+(defun helm-eshell-prompts-goto-other-frame (candidate)
+ (helm-eshell-prompts-goto candidate 'switch-to-buffer-other-frame))
+
+(defun helm-eshell-prompts-other-window ()
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-eshell-prompts-goto-other-window)))
+(put 'helm-eshell-prompts-other-window 'helm-only t)
+
+(defun helm-eshell-prompts-other-frame ()
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-eshell-prompts-goto-other-frame)))
+(put 'helm-eshell-prompts-other-frame 'helm-only t)
+
+;;;###autoload
+(defun helm-eshell-prompts ()
+ "Pre-configured `helm' to browse the prompts of the current Eshell."
+ (interactive)
+ (if (eq major-mode 'eshell-mode)
+ (helm :sources
+ (helm-build-sync-source "Eshell prompts"
+ :candidates (helm-eshell-prompts-list)
+ :candidate-transformer 'helm-eshell-prompts-transformer
+ :action '(("Go to prompt" . helm-eshell-prompts-goto)))
+ :buffer "*helm Eshell prompts*")
+ (message "Current buffer is not an Eshell buffer")))
+
+;;;###autoload
+(defun helm-eshell-prompts-all ()
+ "Pre-configured `helm' to browse the prompts of all Eshell sessions."
+ (interactive)
+ (helm :sources
+ (helm-build-sync-source "All Eshell prompts"
+ :candidates (helm-eshell-prompts-list-all)
+ :candidate-transformer 'helm-eshell-prompts-all-transformer
+ :action '(("Go to prompt" . helm-eshell-prompts-goto)
+ ("Go to prompt in other window `C-c o`" .
+ helm-eshell-prompts-goto-other-window)
+ ("Go to prompt in other frame `C-c C-o`" .
+ helm-eshell-prompts-goto-other-frame))
+ :keymap helm-eshell-prompts-keymap)
+ :buffer "*helm Eshell all prompts*"))
+
+(provide 'helm-eshell)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-eshell ends here
--- /dev/null
+;;; helm-eval.el --- eval expressions from helm. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Code:
+(require 'cl-lib)
+(require 'helm)
+(require 'helm-help)
+(require 'eldoc)
+(require 'edebug)
+
+\f
+(defgroup helm-eval nil
+ "Eval related Applications and libraries for Helm."
+ :group 'helm)
+
+(defcustom helm-eldoc-in-minibuffer-show-fn
+ 'helm-show-info-in-mode-line
+ "A function to display eldoc info.
+Should take one arg: the string to display."
+ :group 'helm-eval
+ :type 'symbol)
+
+(defcustom helm-show-info-in-mode-line-delay 12
+ "Eldoc will show info in mode-line during this delay if user is idle."
+ :type 'integer
+ :group 'helm-eval)
+
+\f
+;;; Eldoc compatibility between emacs-24 and emacs-25
+;;
+(if (require 'elisp-mode nil t) ; emacs-25
+ ;; Maybe the eldoc functions have been
+ ;; already aliased by eldoc-eval.
+ (cl-loop for (f . a) in '((eldoc-current-symbol .
+ elisp--current-symbol)
+ (eldoc-fnsym-in-current-sexp .
+ elisp--fnsym-in-current-sexp)
+ (eldoc-get-fnsym-args-string .
+ elisp-get-fnsym-args-string)
+ (eldoc-get-var-docstring .
+ elisp-get-var-docstring))
+ unless (fboundp f)
+ do (defalias f a))
+ ;; Emacs-24.
+ (declare-function eldoc-current-symbol "eldoc")
+ (declare-function eldoc-get-fnsym-args-string "eldoc" (sym &optional index))
+ (declare-function eldoc-get-var-docstring "eldoc" (sym))
+ (declare-function eldoc-fnsym-in-current-sexp "eldoc"))
+
+;;; Evaluation Result
+;;
+;;
+;; Internal
+(defvar helm-eldoc-active-minibuffers-list nil)
+
+(defvar helm-eval-expression-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map helm-map)
+ (define-key map (kbd "<C-return>") 'helm-eval-new-line-and-indent)
+ (define-key map (kbd "<M-tab>") 'lisp-indent-line)
+ (define-key map (kbd "<C-tab>") 'helm-lisp-completion-at-point)
+ (define-key map (kbd "C-p") 'previous-line)
+ (define-key map (kbd "C-n") 'next-line)
+ (define-key map (kbd "<up>") 'previous-line)
+ (define-key map (kbd "<down>") 'next-line)
+ (define-key map (kbd "<right>") 'forward-char)
+ (define-key map (kbd "<left>") 'backward-char)
+ map))
+
+(defun helm-build-evaluation-result-source ()
+ (helm-build-dummy-source "Evaluation Result"
+ :multiline t
+ :mode-line "C-RET: nl-and-indent, M-tab: reindent, C-tab:complete, C-p/n: next/prec-line."
+ :filtered-candidate-transformer (lambda (_candidates _source)
+ (list
+ (condition-case nil
+ (with-helm-current-buffer
+ (pp-to-string
+ (if edebug-active
+ (edebug-eval-expression
+ (read helm-pattern))
+ (eval (read helm-pattern)))))
+ (error "Error"))))
+ :nohighlight t
+ :keymap helm-eval-expression-map
+ :action '(("Copy result to kill-ring" . (lambda (candidate)
+ (kill-new
+ (replace-regexp-in-string
+ "\n" "" candidate))
+ (message "Result copied to kill-ring")))
+ ("copy sexp to kill-ring" . (lambda (_candidate)
+ (kill-new helm-input)
+ (message "Sexp copied to kill-ring"))))))
+
+(defun helm-eval-new-line-and-indent ()
+ (interactive)
+ (newline) (lisp-indent-line))
+
+(defun helm-eldoc-store-minibuffer ()
+ "Store minibuffer buffer name in `helm-eldoc-active-minibuffers-list'."
+ (with-selected-window (minibuffer-window)
+ (push (current-buffer) helm-eldoc-active-minibuffers-list)))
+
+(defun helm-eldoc-show-in-eval ()
+ "Return eldoc in mode-line for current minibuffer input."
+ (let ((buf (window-buffer (active-minibuffer-window))))
+ (condition-case err
+ (when (member buf helm-eldoc-active-minibuffers-list)
+ (with-current-buffer buf
+ (let* ((sym (save-excursion
+ (unless (looking-back ")\\|\"" (1- (point)))
+ (forward-char -1))
+ (eldoc-current-symbol)))
+ (info-fn (eldoc-fnsym-in-current-sexp))
+ (doc (or (eldoc-get-var-docstring sym)
+ (eldoc-get-fnsym-args-string
+ (car info-fn) (cadr info-fn)))))
+ (when doc (funcall helm-eldoc-in-minibuffer-show-fn doc)))))
+ (error (message "Eldoc in minibuffer error: %S" err) nil))))
+
+(defun helm-show-info-in-mode-line (str)
+ "Display string STR in mode-line."
+ (save-selected-window
+ (with-current-buffer helm-buffer
+ (let ((mode-line-format (concat " " str)))
+ (force-mode-line-update)
+ (sit-for helm-show-info-in-mode-line-delay))
+ (force-mode-line-update))))
+
+;;; Calculation Result
+;;
+;;
+(defvar helm-source-calculation-result
+ (helm-build-dummy-source "Calculation Result"
+ :filtered-candidate-transformer (lambda (_candidates _source)
+ (list
+ (condition-case nil
+ (calc-eval helm-pattern)
+ (error "error"))))
+ :nohighlight t
+ :action '(("Copy result to kill-ring" . (lambda (candidate)
+ (kill-new candidate)
+ (message "Result \"%s\" copied to kill-ring"
+ candidate)))
+ ("Copy operation to kill-ring" . (lambda (_candidate)
+ (kill-new helm-input)
+ (message "Calculation copied to kill-ring"))))))
+
+;;;###autoload
+(defun helm-eval-expression (arg)
+ "Preconfigured helm for `helm-source-evaluation-result'."
+ (interactive "P")
+ (helm :sources (helm-build-evaluation-result-source)
+ :input (when arg (thing-at-point 'sexp))
+ :buffer "*helm eval*"
+ :echo-input-in-header-line nil
+ :history 'read-expression-history))
+
+(defvar eldoc-idle-delay)
+;;;###autoload
+(defun helm-eval-expression-with-eldoc ()
+ "Preconfigured helm for `helm-source-evaluation-result' with `eldoc' support. "
+ (interactive)
+ (let ((timer (run-with-idle-timer
+ eldoc-idle-delay 'repeat
+ 'helm-eldoc-show-in-eval)))
+ (unwind-protect
+ (minibuffer-with-setup-hook
+ 'helm-eldoc-store-minibuffer
+ (call-interactively 'helm-eval-expression))
+ (and timer (cancel-timer timer))
+ (setq helm-eldoc-active-minibuffers-list
+ (cdr helm-eldoc-active-minibuffers-list)))))
+
+;;;###autoload
+(defun helm-calcul-expression ()
+ "Preconfigured helm for `helm-source-calculation-result'."
+ (interactive)
+ (helm :sources 'helm-source-calculation-result
+ :buffer "*helm calcul*"))
+
+(provide 'helm-eval)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-eval.el ends here
--- /dev/null
+;;; helm-external.el --- Run Externals commands within Emacs with helm completion. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'helm)
+(require 'helm-help)
+(require 'helm-net)
+
+\f
+(defgroup helm-external nil
+ "External related Applications and libraries for Helm."
+ :group 'helm)
+
+(defcustom helm-raise-command nil
+ "A shell command to jump to a window running specific program.
+Need external program wmctrl.
+This will be use with `format', so use something like \"wmctrl -xa %s\"."
+ :type 'string
+ :group 'helm-external)
+
+(defcustom helm-external-programs-associations nil
+ "Alist to store externals programs associated with file extension.
+This variable overhide setting in .mailcap file.
+e.g : '\(\(\"jpg\" . \"gqview\"\) (\"pdf\" . \"xpdf\"\)\) "
+ :type '(alist :key-type string :value-type string)
+ :group 'helm-external)
+
+(defcustom helm-default-external-file-browser "nautilus"
+ "Default external file browser for your system.
+Directories will be opened externally with it when
+opening file externally in `helm-find-files'.
+Set to nil if you do not have external file browser
+or do not want to use it.
+Windows users should set that to \"explorer.exe\"."
+ :group 'helm-external
+ :type 'string)
+
+\f
+;;; Internals
+(defvar helm-external-command-history nil)
+(defvar helm-external-commands-list nil
+ "A list of all external commands the user can execute.
+If this variable is not set by the user, it will be calculated
+automatically.")
+
+(defun helm-external-commands-list-1 (&optional sort)
+ "Returns a list of all external commands the user can execute.
+If `helm-external-commands-list' is non-nil it will
+return its contents. Else it calculates all external commands
+and sets `helm-external-commands-list'."
+ (helm-aif helm-external-commands-list
+ it
+ (setq helm-external-commands-list
+ (cl-loop
+ for dir in (split-string (getenv "PATH") path-separator)
+ when (and (file-exists-p dir) (file-accessible-directory-p dir))
+ for lsdir = (cl-loop for i in (directory-files dir t)
+ for bn = (file-name-nondirectory i)
+ when (and (not (member bn completions))
+ (not (file-directory-p i))
+ (file-executable-p i))
+ collect bn)
+ append lsdir into completions
+ finally return
+ (if sort (sort completions 'string-lessp) completions)))))
+
+(defun helm-run-or-raise (exe &optional file)
+ "Run asynchronously EXE or jump to the application window.
+If EXE is already running just jump to his window if `helm-raise-command'
+is non--nil.
+When FILE argument is provided run EXE with FILE."
+ (let* ((real-com (car (split-string exe)))
+ (proc (if file (concat real-com " " file) real-com))
+ process-connection-type)
+ (if (get-process proc)
+ (if helm-raise-command
+ (shell-command (format helm-raise-command real-com))
+ (error "Error: %s is already running" real-com))
+ (when (member real-com helm-external-commands-list)
+ (message "Starting %s..." real-com)
+ (if file
+ (start-process-shell-command
+ proc nil (format "%s %s"
+ real-com
+ (shell-quote-argument
+ (if (eq system-type 'windows-nt)
+ (helm-w32-prepare-filename file)
+ (expand-file-name file)))))
+ (start-process-shell-command proc nil real-com))
+ (set-process-sentinel
+ (get-process proc)
+ (lambda (process event)
+ (when (and (string= event "finished\n")
+ helm-raise-command
+ (not (helm-get-pid-from-process-name real-com)))
+ (shell-command (format helm-raise-command "emacs")))
+ (message "%s process...Finished." process))))
+ (setq helm-external-commands-list
+ (cons real-com
+ (delete real-com helm-external-commands-list))))))
+
+(defun helm-get-mailcap-for-file (filename)
+ "Get the command to use for FILENAME from mailcap files."
+ (mailcap-parse-mailcaps)
+ (let* ((ext (file-name-extension filename))
+ (mime (when ext (mailcap-extension-to-mime ext)))
+ (result (when mime (mailcap-mime-info mime))))
+ ;; If elisp file have no associations in .mailcap
+ ;; `mailcap-maybe-eval' is returned, in this case just return nil.
+ (when (stringp result) (helm-basename result))))
+
+(defun helm-get-default-program-for-file (filename)
+ "Try to find a default program to open FILENAME.
+Try first in `helm-external-programs-associations' and then in mailcap file
+if nothing found return nil."
+ (let* ((ext (file-name-extension filename))
+ (def-prog (assoc-default ext helm-external-programs-associations)))
+ (cond ((and def-prog (not (string= def-prog ""))) def-prog)
+ ((and helm-default-external-file-browser (file-directory-p filename))
+ helm-default-external-file-browser)
+ (t (helm-get-mailcap-for-file filename)))))
+
+(defun helm-open-file-externally (file)
+ "Open FILE with an external program.
+Try to guess which program to use with `helm-get-default-program-for-file'.
+If not found or a prefix arg is given query the user which tool to use."
+ (let* ((fname (expand-file-name file))
+ (collection (helm-external-commands-list-1 'sort))
+ (def-prog (helm-get-default-program-for-file fname))
+ (program (if (or helm-current-prefix-arg (not def-prog))
+ ;; Prefix arg or no default program.
+ (prog1
+ (helm-comp-read
+ "Program: " collection
+ :must-match t
+ :name "Open file Externally"
+ :del-input nil
+ :history helm-external-command-history)
+ ;; Always prompt to set this program as default.
+ (setq def-prog nil))
+ ;; No prefix arg or default program exists.
+ def-prog)))
+ (unless (or def-prog ; Association exists, no need to record it.
+ ;; Don't try to record non--filenames associations (e.g urls).
+ (not (file-exists-p fname)))
+ (when
+ (y-or-n-p
+ (format
+ "Do you want to make `%s' the default program for this kind of files? "
+ program))
+ (helm-aif (assoc (file-name-extension fname)
+ helm-external-programs-associations)
+ (setq helm-external-programs-associations
+ (delete it helm-external-programs-associations)))
+ (push (cons (file-name-extension fname)
+ (helm-read-string
+ "Program (Add args maybe and confirm): " program))
+ helm-external-programs-associations)
+ (customize-save-variable 'helm-external-programs-associations
+ helm-external-programs-associations)))
+ (helm-run-or-raise program file)
+ (setq helm-external-command-history
+ (cons program
+ (delete program
+ (cl-loop for i in helm-external-command-history
+ when (executable-find i) collect i))))))
+
+;;;###autoload
+(defun helm-run-external-command (program)
+ "Preconfigured `helm' to run External PROGRAM asyncronously from Emacs.
+If program is already running exit with error.
+You can set your own list of commands with
+`helm-external-commands-list'."
+ (interactive (list
+ (helm-comp-read
+ "RunProgram: "
+ (helm-external-commands-list-1 'sort)
+ :must-match t
+ :del-input nil
+ :name "External Commands"
+ :history helm-external-command-history)))
+ (helm-run-or-raise program)
+ (setq helm-external-command-history
+ (cons program (delete program
+ (cl-loop for i in helm-external-command-history
+ when (executable-find i) collect i)))))
+
+
+(provide 'helm-external)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-external ends here
--- /dev/null
+;;; helm-files.el --- helm file browser and related. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Code:
+\f
+(require 'cl-lib)
+(require 'helm)
+(require 'helm-types)
+(require 'helm-utils)
+(require 'helm-grep)
+(require 'helm-help)
+(require 'helm-locate)
+(require 'helm-tags)
+(require 'helm-buffers)
+(eval-when-compile
+ (require 'thingatpt)
+ (require 'ffap)
+ (require 'dired-aux)
+ (require 'dired-x)
+ (require 'tramp)
+ (require 'image-dired))
+
+(declare-function find-library-name "find-func.el" (library))
+(declare-function w32-shell-execute "ext:w32fns.c" (operation document &optional parameters show-flag))
+(declare-function gnus-dired-attach "ext:gnus-dired.el" (files-to-attach))
+(declare-function image-dired-display-image "image-dired.el" (file &optional original-size))
+(declare-function image-dired-update-property "image-dired.el" (prop value))
+(declare-function eshell-read-aliases-list "em-alias")
+(declare-function eshell-send-input "esh-mode" (&optional use-region queue-p no-newline))
+(declare-function eshell-kill-input "esh-mode")
+(declare-function eshell-bol "esh-mode")
+(declare-function eshell-reset "esh-mode.el")
+(declare-function eshell/cd "em-dirs.el")
+(declare-function eshell-next-prompt "em-prompt.el")
+(declare-function eshell-quote-argument "esh-arg.el")
+(declare-function helm-ls-git-ls "ext:helm-ls-git")
+(declare-function helm-hg-find-files-in-project "ext:helm-ls-hg")
+(declare-function helm-gid "helm-id-utils.el")
+(declare-function helm-find-1 "helm-find")
+(declare-function helm-get-default-program-for-file "helm-external")
+(declare-function helm-open-file-externally "helm-external")
+
+(defvar recentf-list)
+(defvar helm-mm-matching-method)
+(defvar dired-async-mode)
+(defvar org-directory)
+\f
+(defgroup helm-files nil
+ "Files applications and libraries for Helm."
+ :group 'helm)
+
+(defcustom helm-tramp-verbose 0
+ "Just like `tramp-verbose' but specific to helm.
+When set to 0 don't show tramp messages in helm.
+If you want to have the default tramp messages set it to 3."
+ :type 'integer
+ :group 'helm-files)
+
+(defcustom helm-ff-auto-update-initial-value nil
+ "Auto update when only one candidate directory is matched.
+Default value when starting `helm-find-files' is nil because
+it prevent using <backspace> to delete char backward and by the way
+confuse beginners.
+For a better experience with `helm-find-files' set this to non--nil
+and use C-<backspace> to toggle it."
+ :group 'helm-files
+ :type 'boolean)
+
+(defcustom helm-ff-lynx-style-map t
+ "Use arrow keys to navigate with `helm-find-files'.
+You will have to restart Emacs or reeval `helm-find-files-map'
+and `helm-read-file-map' for this take effect."
+ :group 'helm-files
+ :type 'boolean)
+
+(defcustom helm-ff-history-max-length 100
+ "Number of elements shown in `helm-find-files' history."
+ :group 'helm-files
+ :type 'integer)
+
+(defcustom helm-ff-fuzzy-matching t
+ "Enable fuzzy matching for `helm-find-files' when non--nil.
+See `helm-ff--transform-pattern-for-completion' for more info."
+ :group 'helm-files
+ :type 'boolean)
+
+(defcustom helm-ff-exif-data-program "exiftran"
+ "Program used to extract exif data of an image file."
+ :group 'helm-files
+ :type 'string)
+
+(defcustom helm-ff-exif-data-program-args "-d"
+ "Arguments used for `helm-ff-exif-data-program'."
+ :group 'helm-files
+ :type 'string)
+
+(defcustom helm-ff-newfile-prompt-p t
+ "Whether Prompt or not when creating new file.
+This set `ffap-newfile-prompt'."
+ :type 'boolean
+ :group 'helm-files)
+
+(defcustom helm-ff-avfs-directory "~/.avfs"
+ "The default avfs directory, usually '~/.avfs'.
+When this is set you will be able to expand archive filenames with `C-j'
+inside an avfs directory mounted with mountavfs.
+See <http://sourceforge.net/projects/avf/>."
+ :type 'string
+ :group 'helm-files)
+
+(defcustom helm-ff-file-compressed-list '("gz" "bz2" "zip" "7z")
+ "Minimal list of compressed files extension."
+ :type '(repeat (choice string))
+ :group 'helm-files)
+
+(defcustom helm-ff-printer-list nil
+ "A list of available printers on your system.
+When non--nil let you choose a printer to print file.
+Otherwise when nil the variable `printer-name' will be used.
+On Unix based systems (lpstat command needed) you don't need to set this,
+`helm-ff-find-printers' will find a list of available printers for you."
+ :type '(repeat (choice string))
+ :group 'helm-files)
+
+(defcustom helm-ff-transformer-show-only-basename t
+ "Show only basename of candidates in `helm-find-files'.
+This can be toggled at anytime from `helm-find-files' with \
+\\<helm-find-files-map>\\[helm-ff-run-toggle-basename]."
+ :type 'boolean
+ :group 'helm-files)
+
+(defcustom helm-ff-signal-error-on-dot-files t
+ "Signal error when file is `.' or `..' on file deletion when non--nil.
+Default is non--nil.
+WARNING: Setting this to nil is unsafe and can cause deletion of a whole tree."
+ :group 'helm-files
+ :type 'boolean)
+
+(defcustom helm-ff-search-library-in-sexp nil
+ "Search for library in `require' and `declare-function' sexp."
+ :group 'helm-files
+ :type 'boolean)
+
+(defcustom helm-tooltip-hide-delay 25
+ "Hide tooltips automatically after this many seconds."
+ :group 'helm-files
+ :type 'integer)
+
+(defcustom helm-ff-file-name-history-use-recentf nil
+ "Use `recentf-list' instead of `file-name-history' in `helm-find-files'."
+ :group 'helm-files
+ :type 'boolean)
+
+(defcustom helm-ff-skip-boring-files nil
+ "Non--nil to skip files matching regexps in
+`helm-boring-file-regexp-list'.
+
+This take effect in `helm-find-files' and file completion used by `helm-mode'
+i.e `helm-read-file-name'.
+Note that when non-nil this will slow down slightly `helm-find-files'."
+ :group 'helm-files
+ :type 'boolean)
+
+(defcustom helm-ff-candidate-number-limit 5000
+ "The `helm-candidate-number-limit' for `helm-find-files' and friends.
+Note that when going one level up with `\\<helm-find-files-map>\\[helm-find-files-up-one-level]'
+The length of directory will be used instead if it is higher than this
+value, this to avoid failing to preselect the previous directory/file if
+this one is situated lower than `helm-ff-candidate-number-limit' num
+candidate."
+ :group 'helm-files
+ :type 'integer)
+
+(defcustom helm-ff-up-one-level-preselect t
+ "Always preselect previous directory when going one level up.
+
+When non nil `candidate-number-limit' source value is modified
+dynamically when going one level up if the position of previous
+candidate in its directory is > to `helm-ff-candidate-number-limit'.
+
+This can be helpful to disable this and reduce
+`helm-ff-candidate-number-limit' if you often navigate across very
+large directories."
+ :group 'helm-files
+ :type 'boolean)
+
+(defcustom helm-files-save-history-extra-sources
+ '("Find" "Locate" "Recentf"
+ "Files from Current Directory" "File Cache")
+ "Extras source that save candidate to `file-name-history'."
+ :group 'helm-files
+ :type '(repeat (choice string)))
+
+(defcustom helm-find-files-before-init-hook nil
+ "Hook that run before initialization of `helm-find-files'."
+ :group 'helm-files
+ :type 'hook)
+
+(defcustom helm-find-files-after-init-hook nil
+ "Hook that run after initialization of `helm-find-files'."
+ :group 'helm-files
+ :type 'hook)
+
+(defcustom helm-find-files-bookmark-prefix "Helm-find-files: "
+ "bookmark name prefix of `helm-find-files' sessions."
+ :group 'helm-files
+ :type 'string)
+
+(defcustom helm-ff-guess-ffap-filenames nil
+ "Use ffap to guess local filenames at point in `helm-find-files'.
+This doesn't disable url or mail at point, see
+`helm-ff-guess-ffap-urls' for this."
+ :group 'helm-files
+ :type 'boolean)
+
+(defcustom helm-ff-guess-ffap-urls t
+ "Use ffap to guess local urls at point in `helm-find-files'.
+This doesn't disable guessing filenames at point,
+see `helm-ff-guess-ffap-filenames' for this.
+See also `ffap-url-unwrap-remote' that may override this variable."
+ :group 'helm-files
+ :type 'boolean)
+
+(defcustom helm-ff-no-preselect nil
+ "When non--nil `helm-find-files' starts at root of current directory."
+ :group 'helm-files
+ :type 'boolean)
+
+(defcustom helm-find-files-ignore-thing-at-point nil
+ "Use only `default-directory' as default input in `helm-find-files'.
+I.e text under cursor in `current-buffer' is ignored.
+Note that when non-nil you will be unable to complete filename at point
+in `current-buffer'."
+ :group 'helm-files
+ :type 'boolean)
+
+(defcustom helm-substitute-in-filename-stay-on-remote nil
+ "Don't switch back to local filesystem when expanding pattern with / or ~/."
+ :group 'helm-files
+ :type 'boolean)
+
+(defcustom helm-ff-goto-first-real-dired-exceptions '(dired-goto-file)
+ "Dired commands that are allowed moving to first real candidate."
+ :group 'helm-files
+ :type '(repeat (choice symbol)))
+
+(defcustom helm-mounted-network-directories nil
+ "A list of directories used for mounting remotes filesystem.
+
+When nil `helm-file-on-mounted-network-p' always return nil otherwise
+it checks if a file is in one of these directories.
+
+Remote filesystem are generally mounted with sshfs."
+ :group 'helm-files
+ :type '(repeat string))
+
+(defcustom helm-browse-project-default-find-files-fn
+ #'helm-browse-project-walk-directory
+ "The default function to retrieve files in a non-vc directory.
+
+A function that takes a directory name as only arg."
+ :group 'helm-files
+ :type 'function)
+
+(defcustom helm-ff-kill-or-find-buffer-fname-fn
+ #'helm-ff-kill-or-find-buffer-fname
+ "Default function used to expand non-directory filenames in `helm-find-files'.
+
+This variable will take effect only in `helm-find-files', it affects
+the behavior of persistent-action on filenames and non-existing
+filenames.
+
+The default is to expand filename on first hit on
+\\<helm-map>\\[helm-execute-persistent-action], pop buffer in other
+window on second hit and finally kill this buffer on third hit, this
+is very handy to create several new buffers, or when navigating, show
+quickly the buffer of file to see its contents briefly before killing
+it and continue navigating.
+
+However some users may not want this, so to disable this behavior just
+set this to `ignore' function.
+
+Of course you can also write your own function to do something else."
+ :group 'helm-files
+ :type 'function)
+
+(defcustom helm-modes-using-escaped-strings
+ '(eshell-mode shell-mode term-mode)
+ "Modes that requires string's insertion to be escaped."
+ :group 'helm-files
+ :type '(repeat symbol))
+
+(defcustom helm-ff-allow-recursive-deletes nil
+ "when 'always don't prompt for recursive deletion of directories.
+When nil, will ask for recursive deletion.
+Note that when deleting multiple directories you can answer ! when
+prompted to avoid beeing asked for next directories, so it is probably
+better to not modify this variable."
+ :group 'helm-files
+ :type '(choice
+ (const :tag "Delete non-empty directories" t)
+ (const :tag "Confirm for each directory" nil)))
+
+(defcustom helm-ff-delete-files-function #'helm-delete-marked-files
+ "The function to use by default to delete files.
+
+Default is to delete files synchronously, other choice is to delete
+files asynchronously.
+
+BE AWARE that when deleting async you will not be warned about
+recursive deletion of directories, IOW non empty directories will be
+deleted with no warnings in background!!!
+
+It is the function that will be used when using `\\<helm-find-files-map>\\[helm-ff-run-delete-file]'
+from `helm-find-files'."
+ :group 'helm-files
+ :type '(choice (function :tag "Delete files synchronously."
+ helm-delete-marked-files)
+ (function :tag "Delete files asynchronously."
+ helm-delete-marked-files-async)))
+
+(defcustom helm-trash-remote-files nil
+ "Allow trashing remote files when non-nil.
+
+Deleting remote files with tramp doesn't work out of the box, it is
+why it is disabled by default.
+
+Following is NOT documented in tramp AFAIK but tramp is using
+external trash command in its `delete-file' and `delete-directory'
+handlers.
+
+If you want to enable this you will have to install the 'trash' command
+on remote (or locally if you want to trash as root), the package on
+Ubuntu based distribution is 'trash-cli'."
+ :group 'helm-files
+ :type 'boolean)
+
+(defcustom helm-list-directory-function
+ (cl-case system-type
+ (gnu/linux #'helm-list-dir-external)
+ (berkeley-unix #'helm-list-dir-external)
+ (windows-nt #'helm-list-dir-lisp)
+ (t #'helm-list-dir-lisp))
+ "The function used in `helm-find-files' to list remote directories.
+
+Actually helm provides two functions to do this: `helm-list-dir-lisp'
+and `helm-list-dir-external'.
+
+Using `helm-list-dir-external' will provides a similar display to what
+provided with local files i.e. colorized symlinks, executables files
+etc... whereas using `helm-list-dir-lisp' will allow colorizing only
+directories but is more portable.
+
+NOTE that `helm-list-dir-external' needs ls and awk as dependencies."
+ :type 'function
+ :group 'helm-files)
+\f
+;;; Faces
+;;
+;;
+(defgroup helm-files-faces nil
+ "Customize the appearance of helm-files."
+ :prefix "helm-"
+ :group 'helm-files
+ :group 'helm-faces)
+
+(defface helm-ff-prefix
+ '((t (:background "yellow" :foreground "black")))
+ "Face used to prefix new file or url paths in `helm-find-files'."
+ :group 'helm-files-faces)
+
+(defface helm-ff-executable
+ '((t (:foreground "green")))
+ "Face used for executable files in `helm-find-files'."
+ :group 'helm-files-faces)
+
+(defface helm-ff-suid
+ '((t (:background "red" :foreground "white")))
+ "Face used for suid files in `helm-find-files'."
+ :group 'helm-files-faces)
+
+(defface helm-ff-directory
+ '((t (:foreground "DarkRed" :background "LightGray")))
+ "Face used for directories in `helm-find-files'."
+ :group 'helm-files-faces)
+
+(defface helm-ff-dotted-directory
+ '((t (:foreground "black" :background "DimGray")))
+ "Face used for dotted directories in `helm-find-files'."
+ :group 'helm-files-faces)
+
+(defface helm-ff-dotted-symlink-directory
+ '((t (:foreground "DarkOrange" :background "DimGray")))
+ "Face used for dotted symlinked directories in `helm-find-files'."
+ :group 'helm-files-faces)
+
+(defface helm-ff-symlink
+ '((t :inherit font-lock-comment-face))
+ "Face used for symlinks in `helm-find-files'."
+ :group 'helm-files-faces)
+
+(defface helm-ff-invalid-symlink
+ '((t (:foreground "black" :background "red")))
+ "Face used for invalid symlinks in `helm-find-files'."
+ :group 'helm-files-faces)
+
+(defface helm-ff-denied
+ '((t (:foreground "red" :background "black")))
+ "Face used for non accessible files in `helm-find-files'."
+ :group 'helm-files-faces)
+
+(defface helm-ff-file
+ '((t (:inherit font-lock-builtin-face)))
+ "Face used for file names in `helm-find-files'."
+ :group 'helm-files-faces)
+
+(defface helm-ff-truename
+ '((t (:inherit font-lock-string-face)))
+ "Face used for symlink truenames in `helm-find-files'."
+ :group 'helm-files-faces)
+
+(defface helm-ff-dirs
+ '((t (:inherit font-lock-function-name-face)))
+ "Face used for file names in recursive dirs completion in `helm-find-files'."
+ :group 'helm-files-faces)
+
+(defface helm-ff-socket
+ '((t (:foreground "DeepPink")))
+ "Face used for socket files in `helm-find-files'."
+ :group 'helm-files-faces)
+
+(defface helm-ff-pipe
+ '((t (:foreground "yellow" :background "black")))
+ "Face used for named pipes and character device files in `helm-find-files'."
+ :group 'helm-files-faces)
+
+(defface helm-history-deleted
+ '((t (:inherit helm-ff-invalid-symlink)))
+ "Face used for deleted files in `file-name-history'."
+ :group 'helm-files-faces)
+
+(defface helm-history-remote
+ '((t (:foreground "Indianred1")))
+ "Face used for remote files in `file-name-history'."
+ :group 'helm-files-faces)
+
+(defface helm-delete-async-message
+ '((t (:foreground "yellow")))
+ "Face used for mode-line message."
+ :group 'helm-files-faces)
+\f
+;;; Helm-find-files - The helm file browser.
+;;
+;; Keymaps
+(defvar helm-find-files-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map helm-map)
+ (define-key map (kbd "RET") 'helm-ff-RET)
+ (define-key map (kbd "C-]") 'helm-ff-run-toggle-basename)
+ (define-key map (kbd "C-x C-f") 'helm-ff-run-locate)
+ (define-key map (kbd "C-x C-d") 'helm-ff-run-browse-project)
+ (define-key map (kbd "C-x r m") 'helm-ff-bookmark-set)
+ (define-key map (kbd "C-x r b") 'helm-find-files-toggle-to-bookmark)
+ (define-key map (kbd "C-x C-q") 'helm-ff-run-marked-files-in-dired)
+ (define-key map (kbd "C-s") 'helm-ff-run-grep)
+ (define-key map (kbd "M-g s") 'helm-ff-run-grep)
+ (define-key map (kbd "M-g p") 'helm-ff-run-pdfgrep)
+ (define-key map (kbd "M-g z") 'helm-ff-run-zgrep)
+ (define-key map (kbd "M-g a") 'helm-ff-run-grep-ag)
+ (define-key map (kbd "M-g g") 'helm-ff-run-git-grep)
+ (define-key map (kbd "M-g i") 'helm-ff-run-gid)
+ (define-key map (kbd "M-.") 'helm-ff-run-etags)
+ (define-key map (kbd "M-R") 'helm-ff-run-rename-file)
+ (define-key map (kbd "M-C") 'helm-ff-run-copy-file)
+ (define-key map (kbd "M-B") 'helm-ff-run-byte-compile-file)
+ (define-key map (kbd "M-L") 'helm-ff-run-load-file)
+ (define-key map (kbd "M-S") 'helm-ff-run-symlink-file)
+ (define-key map (kbd "M-Y") 'helm-ff-run-relsymlink-file)
+ (define-key map (kbd "M-H") 'helm-ff-run-hardlink-file)
+ (define-key map (kbd "M-D") 'helm-ff-run-delete-file)
+ (define-key map (kbd "M-K") 'helm-ff-run-kill-buffer-persistent)
+ (define-key map (kbd "M-T") 'helm-ff-run-touch-files)
+ (define-key map (kbd "C-c d") 'helm-ff-persistent-delete)
+ (define-key map (kbd "M-e") 'helm-ff-run-switch-to-eshell)
+ (define-key map (kbd "C-c i") 'helm-ff-run-complete-fn-at-point)
+ (define-key map (kbd "C-c o") 'helm-ff-run-switch-other-window)
+ (define-key map (kbd "C-c C-o") 'helm-ff-run-switch-other-frame)
+ (define-key map (kbd "C-c C-x") 'helm-ff-run-open-file-externally)
+ (define-key map (kbd "C-c C-v") 'helm-ff-run-preview-file-externally)
+ (define-key map (kbd "C-c X") 'helm-ff-run-open-file-with-default-tool)
+ (define-key map (kbd "M-!") 'helm-ff-run-eshell-command-on-file)
+ (define-key map (kbd "M-@") 'helm-ff-run-query-replace-fnames-on-marked)
+ (define-key map (kbd "M-%") 'helm-ff-run-query-replace)
+ (define-key map (kbd "C-M-%") 'helm-ff-run-query-replace-regexp)
+ (define-key map (kbd "C-c =") 'helm-ff-run-ediff-file)
+ (define-key map (kbd "M-=") 'helm-ff-run-ediff-merge-file)
+ (define-key map (kbd "M-p") 'helm-find-files-history)
+ (define-key map (kbd "C-c h") 'helm-ff-file-name-history)
+ (define-key map (kbd "M-i") 'helm-ff-properties-persistent)
+ (define-key map (kbd "C-}") 'helm-narrow-window)
+ (define-key map (kbd "C-{") 'helm-enlarge-window)
+ (define-key map (kbd "C-<backspace>") 'helm-ff-run-toggle-auto-update)
+ (define-key map (kbd "C-c <DEL>") 'helm-ff-run-toggle-auto-update)
+ (define-key map (kbd "C-c C-a") 'helm-ff-run-mail-attach-files)
+ (define-key map (kbd "C-c p") 'helm-ff-run-print-file)
+ (define-key map (kbd "C-c /") 'helm-ff-run-find-sh-command)
+ ;; Next 2 have no effect if candidate is not an image file.
+ (define-key map (kbd "M-l") 'helm-ff-rotate-left-persistent)
+ (define-key map (kbd "M-r") 'helm-ff-rotate-right-persistent)
+ (define-key map (kbd "C-l") 'helm-find-files-up-one-level)
+ (define-key map (kbd "C-r") 'helm-find-files-down-last-level)
+ (define-key map (kbd "C-c r") 'helm-ff-run-find-file-as-root)
+ (define-key map (kbd "C-x C-v") 'helm-ff-run-find-alternate-file)
+ (define-key map (kbd "C-c @") 'helm-ff-run-insert-org-link)
+ (helm-define-key-with-subkeys map (kbd "DEL") ?\d 'helm-ff-delete-char-backward
+ '((C-backspace . helm-ff-run-toggle-auto-update)
+ ([C-c DEL] . helm-ff-run-toggle-auto-update))
+ nil 'helm-ff-delete-char-backward--exit-fn)
+ (when helm-ff-lynx-style-map
+ (define-key map (kbd "<left>") 'helm-find-files-up-one-level)
+ (define-key map (kbd "<right>") 'helm-execute-persistent-action))
+ (delq nil map))
+ "Keymap for `helm-find-files'.")
+
+(defvar helm-read-file-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map helm-map)
+ (define-key map (kbd "<C-return>") 'helm-cr-empty-string)
+ (define-key map (kbd "M-RET") 'helm-cr-empty-string)
+ (define-key map (kbd "C-]") 'helm-ff-run-toggle-basename)
+ (define-key map (kbd "C-.") 'helm-find-files-up-one-level)
+ (define-key map (kbd "C-l") 'helm-find-files-up-one-level)
+ (define-key map (kbd "C-r") 'helm-find-files-down-last-level)
+ (define-key map (kbd "C-c h") 'helm-ff-file-name-history)
+ (define-key map (kbd "C-<backspace>") 'helm-ff-run-toggle-auto-update)
+ (define-key map (kbd "C-c <DEL>") 'helm-ff-run-toggle-auto-update)
+ (helm-define-key-with-subkeys map (kbd "DEL") ?\d 'helm-ff-delete-char-backward
+ '((C-backspace . helm-ff-run-toggle-auto-update)
+ ([C-c DEL] . helm-ff-run-toggle-auto-update))
+ nil 'helm-ff-delete-char-backward--exit-fn)
+ (when helm-ff-lynx-style-map
+ (define-key map (kbd "<left>") 'helm-find-files-up-one-level)
+ (define-key map (kbd "<right>") 'helm-execute-persistent-action)
+ (define-key map (kbd "<M-left>") 'helm-previous-source)
+ (define-key map (kbd "<M-right>") 'helm-next-source))
+ (delq nil map))
+ "Keymap for `helm-read-file-name'.")
+
+\f
+;; Internal.
+(defvar helm-find-files-doc-header " (\\<helm-find-files-map>\\[helm-find-files-up-one-level]: Go up one level)"
+ "*The doc that is inserted in the Name header of a find-files or dired source.")
+(defvar helm-ff-auto-update-flag nil
+ "Internal, flag to turn on/off auto-update in `helm-find-files'.
+Don't set it directly, use instead `helm-ff-auto-update-initial-value'.")
+(defvar helm-ff-last-expanded nil
+ "Store last expanded directory or file.")
+(defvar helm-ff-default-directory nil)
+(defvar helm-ff-history nil)
+(defvar helm-ff-cand-to-mark nil)
+(defvar helm-ff-url-regexp
+ "\\`\\(news\\(post\\)?:\\|nntp:\\|mailto:\\|file:\\|\\(ftp\\|https?\\|telnet\\|gopher\\|www\\|wais\\):/?/?\\).*"
+ "Same as `ffap-url-regexp' but match earlier possible url.")
+;; helm-tramp-file-name-regexp is based on old version of
+;; tramp-file-name-regexp i.e. "\\`/\\([^[/:]+\\|[^/]+]\\):" but it
+;; seems it is wrong and a simpler regexp is enough, let's try it and
+;; watch out!
+(defvar helm-tramp-file-name-regexp "\\`/\\([^/:|]+\\):")
+(defvar helm-marked-buffer-name "*helm marked*")
+(defvar helm-ff--auto-update-state nil)
+(defvar helm-ff--deleting-char-backward nil)
+(defvar helm-multi-files--toggle-locate nil)
+(defvar helm-ff--move-to-first-real-candidate t)
+(defvar helm-find-files--toggle-bookmark nil)
+(defvar helm-ff--tramp-methods nil)
+(defvar helm-ff--directory-files-hash (make-hash-table :test 'equal))
+(defvar helm-ff-history-buffer-name "*helm-find-files history*")
+\f
+;;; Helm-find-files
+;;
+;;
+(defcustom helm-find-files-actions
+ (helm-make-actions
+ "Find File" 'helm-find-file-or-marked
+ "Find file in Dired" 'helm-point-file-in-dired
+ "View file" 'view-file
+ "Query replace fnames on marked `M-@'" 'helm-ff-query-replace-fnames-on-marked
+ "Marked files in dired `C-x C-q, C-u wdired'" 'helm-marked-files-in-dired
+ "Query replace contents on marked `M-%'" 'helm-ff-query-replace
+ "Query replace regexp contents on marked `C-M-%'" 'helm-ff-query-replace-regexp
+ "Attach file(s) to mail buffer `C-c C-a'" 'helm-ff-mail-attach-files
+ "Serial rename files" 'helm-ff-serial-rename
+ "Serial rename by symlinking files" 'helm-ff-serial-rename-by-symlink
+ "Serial rename by copying files" 'helm-ff-serial-rename-by-copying
+ "Open file with default tool" 'helm-open-file-with-default-tool
+ "Find file in hex dump" 'hexl-find-file
+ "Browse project `C-x C-d'" 'helm-ff-browse-project
+ "Complete at point `C-c i'" 'helm-insert-file-name-completion-at-point
+ "Insert as org link `C-c @'" 'helm-files-insert-as-org-link
+ "Find shell command `C-c /'" 'helm-ff-find-sh-command
+ "Add marked files to file-cache" 'helm-ff-cache-add-file
+ "Open file externally `C-c C-x, C-u to choose'" 'helm-open-file-externally
+ "Grep File(s) `C-s, C-u Recurse'" 'helm-find-files-grep
+ "Grep current directory with AG `M-g a, C-u select type'" 'helm-find-files-ag
+ "Git grep `M-g g, C-u from root'" 'helm-ff-git-grep
+ "Zgrep File(s) `M-g z, C-u Recurse'" 'helm-ff-zgrep
+ "Gid `M-g i'" 'helm-ff-gid
+ "Switch to Eshell `M-e'" 'helm-ff-switch-to-eshell
+ "Etags `M-., C-u reload tag file'" 'helm-ff-etags-select
+ "Eshell command on file(s) `M-!, C-u take all marked as arguments.'"
+ 'helm-find-files-eshell-command-on-file
+ "Find file as root `C-c r'" 'helm-find-file-as-root
+ "Find alternate file `C-x C-v'" 'find-alternate-file
+ "Ediff File `C-c ='" 'helm-find-files-ediff-files
+ "Ediff Merge File `M-='" 'helm-find-files-ediff-merge-files
+ (lambda () (format "Delete File(s)%s `M-D' (C-u reverse trash)"
+ (if (eq helm-ff-delete-files-function
+ 'helm-delete-marked-files-async)
+ " async" "")))
+ 'helm-delete-marked-files
+ "Touch File(s) `M-T'" 'helm-ff-touch-files
+ "Copy file(s) `M-C, C-u to follow'" 'helm-find-files-copy
+ "Rename file(s) `M-R, C-u to follow'" 'helm-find-files-rename
+ "Backup files" 'helm-find-files-backup
+ "Symlink files(s) `M-S, C-u to follow'" 'helm-find-files-symlink
+ "Relsymlink file(s) `M-Y, C-u to follow'" 'helm-find-files-relsymlink
+ "Hardlink file(s) `M-H, C-u to follow'" 'helm-find-files-hardlink
+ "Find file other window `C-c o'" 'helm-find-files-other-window
+ "Find file other frame `C-c C-o'" 'find-file-other-frame
+ "Print File `C-c p, C-u to refresh'" 'helm-ff-print
+ "Locate `C-x C-f, C-u to specify locate db'" 'helm-ff-locate)
+ "Actions for `helm-find-files'."
+ :group 'helm-files
+ :type '(alist :key-type string :value-type function))
+
+(defvar helm-source-find-files nil
+ "The main source to browse files.
+Should not be used among other sources.")
+
+(defclass helm-source-ffiles (helm-source-sync)
+ ((header-name
+ :initform (lambda (name)
+ (concat name (substitute-command-keys
+ helm-find-files-doc-header))))
+ (init
+ :initform (lambda ()
+ (setq helm-ff-auto-update-flag
+ helm-ff-auto-update-initial-value)
+ (setq helm-ff--auto-update-state
+ helm-ff-auto-update-flag)
+ (helm-set-local-variable 'bookmark-make-record-function
+ #'helm-ff-make-bookmark-record)
+ (require 'helm-external)))
+ (candidates :initform 'helm-find-files-get-candidates)
+ (filtered-candidate-transformer
+ :initform '(helm-ff-sort-candidates
+ (lambda (candidates _source)
+ (cl-loop for f in candidates
+ for ff = (helm-ff-filter-candidate-one-by-one f)
+ when ff collect ff))))
+ (persistent-action-if :initform 'helm-find-files-persistent-action-if)
+ (persistent-help :initform "Hit1 Expand Candidate, Hit2 or (C-u) Find file")
+ (help-message :initform 'helm-ff-help-message)
+ (mode-line :initform (list "File(s)" helm-mode-line-string))
+ (volatile :initform t)
+ (cleanup :initform 'helm-find-files-cleanup)
+ (migemo :initform t)
+ (nohighlight :initform t)
+ (keymap :initform helm-find-files-map)
+ (candidate-number-limit :initform 'helm-ff-candidate-number-limit)
+ (action-transformer
+ :initform 'helm-find-files-action-transformer)
+ (action :initform 'helm-find-files-actions)
+ (before-init-hook :initform 'helm-find-files-before-init-hook)
+ (after-init-hook :initform 'helm-find-files-after-init-hook)
+ (group :initform 'helm-files)))
+
+;; Bookmark handlers.
+;;
+(defun helm-ff-make-bookmark-record ()
+ "The `bookmark-make-record-function' for `helm-find-files'."
+ (with-helm-buffer
+ `((filename . ,helm-ff-default-directory)
+ (presel . ,(helm-get-selection))
+ (handler . helm-ff-bookmark-jump))))
+
+(defun helm-ff-bookmark-jump (bookmark)
+ "bookmark handler for `helm-find-files'."
+ (let ((fname (bookmark-prop-get bookmark 'filename))
+ (presel (bookmark-prop-get bookmark 'presel)))
+ ;; Force tramp connection with `file-directory-p' before lauching
+ ;; hff otherwise the directory name is inserted on top before
+ ;; tramp starts and display candidates. FNAME is here always a
+ ;; directory.
+ (when (file-directory-p fname)
+ (helm-find-files-1 fname (if helm-ff-transformer-show-only-basename
+ (helm-basename presel)
+ presel)))))
+
+(defun helm-ff-bookmark-set ()
+ "Record `helm-find-files' session in bookmarks."
+ (interactive)
+ (with-helm-alive-p
+ (with-helm-buffer
+ (bookmark-set
+ (concat helm-find-files-bookmark-prefix
+ (abbreviate-file-name helm-ff-default-directory))))
+ (message "Helm find files session bookmarked! ")))
+(put 'helm-ff-bookmark-set 'helm-only t)
+
+(defcustom helm-dwim-target nil
+ "Default target directory for file actions.
+
+Define the directory where you want to start navigating for the target
+directory when copying, renaming etc... You can use the
+`default-directory' of `next-window', the current
+`default-directory' or have completion on all the directories
+belonging to each window."
+ :group 'helm-files
+ :type '(radio :tag "Define default target directory for file actions."
+ (const :tag "Directory belonging to next window" next-window)
+ (const :tag "Completion on directories belonging to each window" completion)
+ (const :tag "Use initial directory or `default-directory'" nil)))
+
+(defun helm-dwim-target-directory ()
+ "Try to return a suitable directory according to `helm-dwim-target'."
+ (with-helm-current-buffer
+ (let* ((wins (remove (get-buffer-window helm-marked-buffer-name)
+ (window-list)))
+ (num-windows (length wins)))
+ (expand-file-name
+ (cond ((and (> num-windows 1)
+ (eq helm-dwim-target 'completion))
+ (helm-comp-read "Browse target starting from: "
+ (append (list (or (car-safe helm-ff-history)
+ default-directory)
+ default-directory)
+ (cl-loop for w in wins collect
+ (with-selected-window w
+ default-directory)))))
+ ((and (> num-windows 1)
+ (eq helm-dwim-target 'next-window))
+ (with-selected-window (next-window)
+ default-directory))
+ ((or (= num-windows 1)
+ (null helm-dwim-target))
+ ;; Using the car of *ff-history allow
+ ;; staying in the directory visited instead of
+ ;; current.
+ (or (car-safe helm-ff-history) default-directory)))))))
+
+(defun helm-ff--count-and-collect-dups (files)
+ (cl-loop with dups = (make-hash-table :test 'equal)
+ for f in files
+ for file = (if (file-directory-p f)
+ (concat (helm-basename f) "/")
+ (helm-basename f))
+ for count = (gethash file dups)
+ if count do (puthash file (1+ count) dups)
+ else do (puthash file 1 dups)
+ finally return (cl-loop for k being the hash-keys in dups
+ using (hash-value v)
+ if (> v 1)
+ collect (format "%s(%s)" k v)
+ else
+ collect k)))
+
+(defun helm-find-files-do-action (action)
+ "Generic function for creating actions from `helm-source-find-files'.
+ACTION must be an action supported by `helm-dired-action'."
+ (require 'dired-async)
+ (let* ((ifiles (mapcar 'expand-file-name ; Allow modify '/foo/.' -> '/foo'
+ (helm-marked-candidates :with-wildcard t)))
+ (cand (helm-get-selection)) ; Target
+ (prefarg helm-current-prefix-arg)
+ (prompt (format "%s %s file(s) to: "
+ (if (and (and (fboundp 'dired-async-mode)
+ dired-async-mode)
+ (null prefarg))
+ (concat "Async " (symbol-name action))
+ (capitalize (symbol-name action)))
+ (length ifiles)))
+ helm-ff--move-to-first-real-candidate
+ helm-display-source-at-screen-top ; prevent setting window-start.
+ helm-ff-auto-update-initial-value
+ ;; It is not possible to rename a file to a boring name when
+ ;; helm-ff-skip-boring-files is enabled
+ helm-ff-skip-boring-files
+ ;; If HFF is using a frame use a frame as well.
+ (helm-actions-inherit-frame-settings t)
+ helm-use-frame-when-more-than-two-windows
+ (dest (with-helm-display-marked-candidates
+ helm-marked-buffer-name
+ (helm-ff--count-and-collect-dups ifiles)
+ (with-helm-current-buffer
+ (helm-read-file-name
+ prompt
+ :preselect (unless (cdr ifiles)
+ (concat
+ "^"
+ (regexp-quote
+ (if helm-ff-transformer-show-only-basename
+ (helm-basename cand) cand))))
+ :initial-input (helm-dwim-target-directory)
+ :history (helm-find-files-history nil :comp-read nil)))))
+ (dest-dir-p (file-directory-p dest))
+ (dest-dir (helm-basedir dest)))
+ (unless (or dest-dir-p (file-directory-p dest-dir))
+ (when (y-or-n-p (format "Create directory `%s'? " dest-dir))
+ (make-directory dest-dir t)))
+ (helm-dired-action
+ dest :files ifiles :action action :follow prefarg)))
+
+(defun helm-find-files-copy (_candidate)
+ "Copy files from `helm-find-files'."
+ (helm-find-files-do-action 'copy))
+
+(defun helm-find-files-backup (_candidate)
+ "Backup files from `helm-find-files'.
+This reproduce the behavior of \"cp --backup=numbered from to\"."
+ (cl-assert (and (fboundp 'dired-async-mode) dired-async-mode) nil
+ "Backup only available when `dired-async-mode' is enabled")
+ (helm-find-files-do-action 'backup))
+
+(defun helm-find-files-rename (_candidate)
+ "Rename files from `helm-find-files'."
+ (helm-find-files-do-action 'rename))
+
+(defun helm-find-files-symlink (_candidate)
+ "Symlink files from `helm-find-files'."
+ (helm-find-files-do-action 'symlink))
+
+(defun helm-find-files-relsymlink (_candidate)
+ "Relsymlink files from `helm-find-files'."
+ (helm-find-files-do-action 'relsymlink))
+
+(defun helm-find-files-hardlink (_candidate)
+ "Hardlink files from `helm-find-files'."
+ (helm-find-files-do-action 'hardlink))
+
+(defun helm-find-files-other-window (_candidate)
+ "Keep current-buffer and open files in separate windows.
+When a prefix arg is detected files are opened in a vertical windows
+layout."
+ (let* ((files (helm-marked-candidates))
+ (buffers (mapcar 'find-file-noselect files)))
+ (helm-window-show-buffers buffers t)))
+
+(defun helm-find-files-byte-compile (_candidate)
+ "Byte compile elisp files from `helm-find-files'."
+ (let ((files (helm-marked-candidates :with-wildcard t))
+ (parg helm-current-prefix-arg))
+ (cl-loop for fname in files
+ do (byte-compile-file fname parg))))
+
+(defun helm-find-files-load-files (_candidate)
+ "Load elisp files from `helm-find-files'."
+ (let ((files (helm-marked-candidates :with-wildcard t)))
+ (cl-loop for fname in files
+ do (load fname))))
+
+(defun helm-find-files-ediff-files-1 (candidate &optional merge)
+ "Generic function to ediff/merge files in `helm-find-files'."
+ (let* ((helm-dwim-target 'next-window)
+ (bname (helm-basename candidate))
+ (marked (helm-marked-candidates :with-wildcard t))
+ (prompt (if merge "Ediff Merge `%s' With File: "
+ "Ediff `%s' With File: "))
+ (fun (if merge 'ediff-merge-files 'ediff-files))
+ (input (helm-dwim-target-directory))
+ (presel (if helm-ff-transformer-show-only-basename
+ (helm-basename candidate)
+ (expand-file-name
+ (helm-basename candidate)
+ input))))
+ (if (= (length marked) 2)
+ (funcall fun (car marked) (cadr marked))
+ (funcall fun candidate (helm-read-file-name
+ (format prompt bname)
+ :initial-input input
+ :preselect presel)))))
+
+(defun helm-find-files-ediff-files (candidate)
+ (helm-find-files-ediff-files-1 candidate))
+
+(defun helm-find-files-ediff-merge-files (candidate)
+ (helm-find-files-ediff-files-1 candidate 'merge))
+
+(defun helm-find-files-grep (_candidate)
+ "Default action to grep files from `helm-find-files'."
+ (helm-do-grep-1 (helm-marked-candidates :with-wildcard t)
+ helm-current-prefix-arg))
+
+(defun helm-ff-git-grep (_candidate)
+ "Default action to git-grep `helm-ff-default-directory'."
+ (helm-grep-git-1 helm-ff-default-directory helm-current-prefix-arg))
+
+(defun helm-find-files-ag (_candidate)
+ (helm-grep-ag helm-ff-default-directory
+ helm-current-prefix-arg))
+
+(defun helm-ff-zgrep (_candidate)
+ "Default action to zgrep files from `helm-find-files'."
+ (helm-ff-zgrep-1 (helm-marked-candidates :with-wildcard t) helm-current-prefix-arg))
+
+(defun helm-ff-pdfgrep (_candidate)
+ "Default action to pdfgrep files from `helm-find-files'."
+ (let* ((recurse nil)
+ (cands (cl-loop for file in (helm-marked-candidates :with-wildcard t)
+ for dir = (file-directory-p file)
+ when dir do (setq recurse t)
+ when (or dir
+ (string= (file-name-extension file) "pdf")
+ (string= (file-name-extension file) "PDF"))
+ collect file)))
+ (when cands
+ (helm-do-pdfgrep-1 cands recurse))))
+
+(defun helm-ff-etags-select (candidate)
+ "Default action to jump to etags from `helm-find-files'."
+ (when (get-buffer helm-action-buffer)
+ (kill-buffer helm-action-buffer))
+ (let* ((source-name (assoc-default 'name (helm-get-current-source)))
+ (default-directory (if (string= source-name "Find Files")
+ helm-ff-default-directory
+ (file-name-directory candidate))))
+ (helm-etags-select helm-current-prefix-arg)))
+
+(defvar eshell-command-aliases-list nil)
+(defvar helm-eshell-command-on-file-input-history nil)
+(defun helm-find-files-eshell-command-on-file-1 (&optional map)
+ "Run `eshell-command' on CANDIDATE or marked candidates.
+This is done possibly with an eshell alias, if no alias found, you can type in
+an eshell command.
+
+Only aliases accepting a file as argument at the end of command line
+are collected, i.e aliases ending with \"$1\" or \"$*\".
+
+Basename of CANDIDATE can be a wild-card.
+e.g you can do \"eshell-command command *.el\"
+Where \"*.el\" is the CANDIDATE.
+
+It is possible to do eshell-command command <CANDIDATE> <some more args>
+like this: \"command %s some more args\".
+
+If MAP is given run `eshell-command' on all marked files at once,
+Otherwise, run `eshell-command' on each marked files.
+In other terms, with a prefix arg do on the three marked files
+\"foo\" \"bar\" \"baz\":
+
+\"eshell-command command foo bar baz\"
+
+otherwise do
+
+\"eshell-command command foo\"
+\"eshell-command command bar\"
+\"eshell-command command baz\"
+
+Note:
+You have to setup some aliases in eshell with the `alias' command or
+by editing yourself the file `eshell-aliases-file' to make this
+working."
+ (require 'em-alias) (eshell-read-aliases-list)
+ (when (or eshell-command-aliases-list
+ (y-or-n-p "No eshell aliases found, run eshell-command without alias anyway? "))
+ (let* ((cand-list (helm-marked-candidates))
+ (default-directory (or helm-ff-default-directory
+ ;; If candidate is an url *-ff-default-directory is nil
+ ;; so keep value of default-directory.
+ default-directory))
+ (command (helm-comp-read
+ "Command: "
+ (cl-loop for (a c) in (eshell-read-aliases-list)
+ ;; Positional arguments may be double
+ ;; quoted (Issue #1881).
+ when (string-match "[\"]?.*\\(\\$1\\|\\$\\*\\)[\"]?\\'" c)
+ collect (propertize a 'help-echo c) into ls
+ finally return (sort ls 'string<))
+ :buffer "*helm eshell on file*"
+ :name "Eshell command"
+ :mode-line
+ '("Eshell alias"
+ "C-h m: Help, \\[universal-argument]: Insert output at point")
+ :help-message 'helm-esh-help-message
+ :input-history
+ 'helm-eshell-command-on-file-input-history))
+ (alias-value (car (assoc-default command eshell-command-aliases-list)))
+ cmd-line)
+ (if (or (equal helm-current-prefix-arg '(16))
+ (equal map '(16)))
+ ;; Two time C-u from `helm-comp-read' mean print to current-buffer.
+ ;; i.e `eshell-command' will use this value.
+ (setq current-prefix-arg '(16))
+ ;; Else reset the value of `current-prefix-arg'
+ ;; to avoid printing in current-buffer.
+ (setq current-prefix-arg nil))
+ (if (and (or
+ ;; One prefix-arg have been passed before `helm-comp-read'.
+ ;; If map have been set with C-u C-u (value == '(16))
+ ;; ignore it.
+ (and map (equal map '(4)))
+ ;; One C-u from `helm-comp-read'.
+ (equal helm-current-prefix-arg '(4))
+ ;; An alias that finish with $*
+ (and alias-value
+ ;; If command is an alias be sure it accept
+ ;; more than one arg i.e $*.
+ (string-match "\\$\\*$" alias-value)))
+ (cdr cand-list))
+
+ ;; Run eshell-command with ALL marked files as arguments.
+ ;; This wont work on remote files, because tramp handlers depends
+ ;; on `default-directory' (limitation).
+ (let ((mapfiles (mapconcat 'eshell-quote-argument cand-list " ")))
+ (if (string-match "'%s'\\|\"%s\"\\|%s" command)
+ (setq cmd-line (format command mapfiles)) ; See [1]
+ (setq cmd-line (format "%s %s" command mapfiles)))
+ (helm-log "%S" cmd-line)
+ (eshell-command cmd-line))
+
+ ;; Run eshell-command on EACH marked files.
+ ;; To work with tramp handler we have to call
+ ;; COMMAND on basename of each file, using
+ ;; its basedir as `default-directory'.
+ (cl-loop for f in cand-list
+ for dir = (and (not (string-match helm--url-regexp f))
+ (helm-basedir f))
+ for file = (eshell-quote-argument
+ (format "%s" (if (and dir (file-remote-p dir))
+ (helm-basename f) f)))
+ for com = (if (string-match "'%s'\\|\"%s\"\\|%s" command)
+ ;; [1] This allow to enter other args AFTER filename
+ ;; i.e <command %s some_more_args>
+ (format command file)
+ (format "%s %s" command file))
+ do (let ((default-directory (or dir default-directory)))
+ (eshell-command com)))))))
+
+(defun helm-find-files-eshell-command-on-file (_candidate)
+ "Run `eshell-command' on CANDIDATE or marked candidates.
+See `helm-find-files-eshell-command-on-file-1' for more info."
+ (helm-find-files-eshell-command-on-file-1 helm-current-prefix-arg))
+
+(defun helm-ff-switch-to-eshell (_candidate)
+ "Switch to eshell and cd to `helm-ff-default-directory'.
+
+With a numeric prefix arg switch to numbered eshell buffer, if no
+prefix arg provided and more than one eshell buffer exists, provide
+completions on those buffers. If only one eshell buffer exists,
+switch to this one, if no eshell buffer exists or if the numeric
+prefix arg eshell buffer doesn't exists, create it and switch to it."
+ (let ((cd-eshell (lambda ()
+ (eshell/cd helm-ff-default-directory)
+ (eshell-reset)))
+ (bufs (cl-loop for b in (mapcar 'buffer-name (buffer-list))
+ when (helm-ff--eshell-interactive-buffer-p b)
+ collect b)))
+ (helm-aif (and (null helm-current-prefix-arg)
+ (if (cdr bufs)
+ (helm-comp-read "Switch to eshell buffer: " bufs
+ :must-match t)
+ (car bufs)))
+ (switch-to-buffer it)
+ (eshell helm-current-prefix-arg))
+ (unless (get-buffer-process (current-buffer))
+ (funcall cd-eshell))))
+
+(defun helm-ff--eshell-interactive-buffer-p (buffer)
+ (with-current-buffer buffer
+ (and (eq major-mode 'eshell-mode)
+ (save-excursion
+ (goto-char (point-min))
+ (eshell-next-prompt 1)
+ (null (eql (point) (point-min)))))))
+
+(defun helm-ff-touch-files (_candidate)
+ "The touch files action for helm-find-files."
+ (let* ((files (helm-marked-candidates))
+ (split (cl-loop for f in files
+ for spt = (unless helm-current-prefix-arg
+ (cons (helm-basedir f)
+ (split-string f ", ?")))
+ if spt
+ append (cl-loop with dir = (car spt)
+ for ff in (cdr spt)
+ collect (expand-file-name ff dir))
+ else collect f))
+ (timestamp (helm-comp-read
+ "Timestamp (default Now): "
+ (cl-loop for f in split
+ for time = (file-attributes f)
+ for date = (and time
+ (format-time-string
+ "%Y-%m-%d %H:%M:%S"
+ (nth 5 time)))
+ when date
+ collect (cons (format "%s: %s"
+ (helm-basename f) date)
+ date))
+ :default
+ (format-time-string "%Y-%m-%d %H:%M:%S"
+ (current-time))))
+ (failures
+ (cl-loop with default-directory = helm-ff-default-directory
+ for f in split
+ for file = (or (file-remote-p f 'localname) f)
+ when (> (process-file
+ "touch" nil nil nil "-d" timestamp file)
+ 0)
+ collect f)))
+ (when failures
+ (message "Failed to touch *%s files:\n%s"
+ (length failures)
+ (mapconcat (lambda (f) (format "- %s\n" f)) failures "")))))
+
+(defun helm-ff-run-touch-files ()
+ "Used to interactively run touch file action from keyboard."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-ff-touch-files)))
+(put 'helm-ff-run-touch-files 'helm-only t)
+
+(defun helm-ff-serial-rename-action (method)
+ "Rename all marked files in `helm-ff-default-directory' with METHOD.
+See `helm-ff-serial-rename-1'."
+ (let* ((helm--reading-passwd-or-string t)
+ (cands (helm-marked-candidates :with-wildcard t))
+ (def-name (car cands))
+ (name (helm-read-string "NewName: "
+ (replace-regexp-in-string
+ "[0-9]+$" ""
+ (helm-basename
+ def-name
+ (file-name-extension def-name)))))
+ (start (read-number "StartAtNumber: "))
+ (extension (helm-read-string "Extension: "
+ (file-name-extension (car cands))))
+ (dir (expand-file-name
+ (helm-read-file-name
+ "Serial Rename to directory: "
+ :initial-input
+ (expand-file-name helm-ff-default-directory)
+ :test 'file-directory-p
+ :must-match t)))
+ done)
+ (with-helm-display-marked-candidates
+ helm-marked-buffer-name (helm-ff--count-and-collect-dups cands)
+ (if (y-or-n-p
+ (format "Rename %s file(s) to <%s> like this ?\n%s "
+ (length cands) dir (format "%s <-> %s%s.%s"
+ (helm-basename (car cands))
+ name start extension)))
+ (progn
+ (helm-ff-serial-rename-1
+ dir cands name start extension :method method)
+ (setq done t)
+ (message nil))))
+ (if done
+ (with-helm-current-buffer (helm-find-files-1 dir))
+ (message "Operation aborted"))))
+
+(defun helm-ff-member-directory-p (file directory)
+ (let ((dir-file (expand-file-name
+ (file-name-as-directory (file-name-directory file))))
+ (cur-dir (expand-file-name (file-name-as-directory directory))))
+ (string= dir-file cur-dir)))
+
+(cl-defun helm-ff-serial-rename-1
+ (directory collection new-name start-at-num extension &key (method 'rename))
+ "rename files in COLLECTION to DIRECTORY with the prefix name NEW-NAME.
+Rename start at number START-AT-NUM - ex: prefixname-01.jpg.
+EXTENSION is the file extension to use, in empty prompt,
+reuse the original extension of file.
+METHOD can be one of rename, copy or symlink.
+Files will be renamed if they are files of current directory, otherwise they
+will be treated with METHOD.
+Default METHOD is rename."
+ ;; Maybe remove directories selected by error in collection.
+ (setq collection (cl-remove-if 'file-directory-p collection))
+ (let* ((tmp-dir (file-name-as-directory
+ (concat (file-name-as-directory directory)
+ (symbol-name (cl-gensym "tmp")))))
+ (fn (cl-case method
+ (copy 'copy-file)
+ (symlink 'make-symbolic-link)
+ (rename 'rename-file)
+ (t (error "Error: Unknown method %s" method)))))
+ (make-directory tmp-dir)
+ (unwind-protect
+ (progn
+ ;; Rename all files to tmp-dir with new-name.
+ ;; If files are not from start directory, use method
+ ;; to move files to tmp-dir.
+ (cl-loop for i in collection
+ for count from start-at-num
+ for fnum = (if (< count 10) "0%s" "%s")
+ for nname = (concat tmp-dir new-name (format fnum count)
+ (if (not (string= extension ""))
+ (format ".%s" (replace-regexp-in-string
+ "[.]" "" extension))
+ (file-name-extension i 'dot)))
+ do (if (helm-ff-member-directory-p i directory)
+ (rename-file i nname)
+ (funcall fn i nname)))
+ ;; Now move all from tmp-dir to destination.
+ (cl-loop with dirlist = (directory-files
+ tmp-dir t directory-files-no-dot-files-regexp)
+ for f in dirlist do
+ (if (file-symlink-p f)
+ (make-symbolic-link (file-truename f)
+ (concat (file-name-as-directory directory)
+ (helm-basename f)))
+ (rename-file f directory))))
+ (delete-directory tmp-dir t))))
+
+(defun helm-ff-serial-rename (_candidate)
+ "Serial rename all marked files to `helm-ff-default-directory'.
+Rename only file of current directory, and symlink files coming from
+other directories.
+See `helm-ff-serial-rename-1'."
+ (helm-ff-serial-rename-action 'rename))
+
+(defun helm-ff-serial-rename-by-symlink (_candidate)
+ "Serial rename all marked files to `helm-ff-default-directory'.
+Rename only file of current directory, and symlink files coming from
+other directories.
+See `helm-ff-serial-rename-1'."
+ (helm-ff-serial-rename-action 'symlink))
+
+(defun helm-ff-serial-rename-by-copying (_candidate)
+ "Serial rename all marked files to `helm-ff-default-directory'.
+Rename only file of current directory, and copy files coming from
+other directories.
+See `helm-ff-serial-rename-1'."
+ (helm-ff-serial-rename-action 'copy))
+
+(defvar helm-ff-query-replace-fnames-history-from nil)
+(defvar helm-ff-query-replace-fnames-history-to nil)
+(defun helm-ff-query-replace-on-filenames (candidates)
+ "Query replace on filenames of CANDIDATES.
+This doesn't replace inside the files, only modify filenames."
+ (with-helm-display-marked-candidates
+ helm-marked-buffer-name
+ (mapcar 'helm-basename candidates)
+ (let* ((regexp (read-string "Replace regexp on filename(s): "
+ nil 'helm-ff-query-replace-history-from
+ (helm-basename (car candidates))))
+ (rep (read-string (format "Replace regexp `%s' with: " regexp)
+ nil 'helm-ff-query-replace-history-to))
+ subexp)
+ (cl-loop with query = "y"
+ with count = 0
+ with target = nil
+ for old in candidates
+ for new = (concat (helm-basedir old)
+ (helm--replace-regexp-in-buffer-string
+ (save-match-data
+ (cond ((string= regexp "%.")
+ (setq subexp 1)
+ (helm-ff--prepare-str-with-regexp
+ (setq target (helm-basename old t))))
+ ((string= regexp ".%")
+ (setq subexp 1)
+ (helm-ff--prepare-str-with-regexp
+ (setq target (file-name-extension old))))
+ ((string= regexp "%")
+ (regexp-quote
+ (setq target (helm-basename old))))
+ ((string-match "%:\\([0-9]+\\):\\([0-9]+\\)" regexp)
+ (setq subexp 1)
+ (let ((beg (match-string 1 regexp))
+ (end (match-string 2 regexp))
+ (str (helm-basename old)))
+ (setq target (substring str
+ (string-to-number beg)
+ (string-to-number end)))
+ (helm-ff--prepare-str-with-regexp str beg end)))
+ (t regexp)))
+ (save-match-data
+ (cond (;; Handle incremental
+ ;; replacement with \# in
+ ;; search and replace
+ ;; feature in placeholder \@.
+ (string-match
+ "\\\\@/\\(.*\\)/\\(\\(?99:.*\\)\\\\#\\)/"
+ rep)
+ (replace-regexp-in-string
+ (match-string 1 rep)
+ (concat (match-string 99 rep)
+ (format "%03d" (1+ count)))
+ target))
+ ;; Incremental replacement
+ ;; before or after \@.
+ ((and (string-match-p "\\\\#" rep)
+ (string-match "\\\\@" rep))
+ (replace-regexp-in-string
+ "\\\\#" (format "%03d" (1+ count))
+ (replace-match target t t rep)))
+ ;; Simple incremental replacement.
+ ((string-match "\\\\#" rep)
+ (replace-match
+ (format "%03d" (1+ count)) t t rep))
+ ;; Substring replacement in placeholder.
+ ((string-match
+ "\\\\@:\\([0-9]*\\):\\([0-9]*\\)" rep)
+ (replace-match (substring
+ target
+ (string-to-number
+ (match-string 1 rep))
+ (pcase (match-string 2 rep)
+ ((pred (string= ""))
+ (length target))
+ (res (string-to-number res))))
+ t t rep))
+ ;; Search and replace in
+ ;; placeholder. Doesn't
+ ;; handle incremental here.
+ ((string-match "\\\\@/\\(.*\\)/\\(.*\\)/" rep)
+ (replace-match (replace-regexp-in-string
+ (match-string 1 rep)
+ (match-string 2 rep)
+ target t)
+ t t rep))
+ ;; Simple replacement by placeholder.
+ ((string-match "\\\\@" rep)
+ (replace-match target t t rep))
+ ;; Replacement with
+ ;; upcase, downcase or
+ ;; capitalized text.
+ ((string= rep "%u") #'upcase)
+ ((string= rep "%d") #'downcase)
+ ((string= rep "%c") #'capitalize)
+ ;; Simple replacement with
+ ;; whole replacement regexp.
+ (t rep)))
+ (helm-basename old) t nil subexp))
+ ;; If `regexp' is not matched in `old'
+ ;; `replace-regexp-in-string' will
+ ;; return `old' unmodified.
+ unless (string= old new)
+ do (progn
+ (when (file-exists-p new)
+ (setq new (concat (file-name-sans-extension new)
+ (format "(%s)" count)
+ (file-name-extension new t))))
+ (unless (string= query "!")
+ (setq query (helm-read-answer (format
+ "Replace `%s' by `%s' [!,y,n,q]"
+ old new)
+ '("y" "n" "!" "q"))))
+ (when (string= query "q")
+ (cl-return (message "Operation aborted")))
+ (unless (string= query "n")
+ (rename-file old new)
+ (cl-incf count)))
+ finally (message "%d Files renamed" count))))
+ ;; This fix the emacs bug where "Emacs-Lisp:" is sent
+ ;; in minibuffer (not the echo area).
+ (sit-for 0.1)
+ (with-current-buffer (window-buffer (minibuffer-window))
+ (delete-minibuffer-contents)))
+
+(defun helm-ff--prepare-str-with-regexp (str &optional rep1 rep2)
+ ;; This is used in `helm-ff-query-replace-on-filenames' to prepare
+ ;; STR when REGEXP is specified as substring e.g %:1:3 in this case
+ ;; substring from 1 to 3 in STR will be enclosed with parenthesis to
+ ;; match this substring as a subexp e.g %:1:3 on string "emacs" will
+ ;; be replaced by "e\\(ma\\)cs" using subexp 1 like this:
+ ;; (helm--replace-regexp-in-buffer-string "e\\(ma\\)cs" "fo" "emacs" nil t 1)
+ ;; => "efocs"
+ ;; ^^
+ ;; Where "1" and "3" will be strings extracted with match-string
+ ;; from regexp and refered respectively in this function as REP1 and
+ ;; REP2.
+ (let* ((from (or (and rep1 (string-to-number rep1)) 0))
+ (to (or (and rep2 (string-to-number rep2)) (length str)))
+ (subexp (concat "\\(" (regexp-quote (substring str from to)) "\\)"))
+ (before-str (unless (zerop from)
+ (regexp-quote (substring str 0 from))))
+ (after-str (unless (= to (length str))
+ (regexp-quote (substring str to (length str))))))
+ (concat before-str subexp after-str)))
+
+;; The action.
+(defun helm-ff-query-replace-fnames-on-marked (_candidate)
+ (let ((marked (helm-marked-candidates :with-wildcard t)))
+ (helm-ff-query-replace-on-filenames marked)))
+
+;; The command for `helm-find-files-map'.
+(defun helm-ff-run-query-replace-fnames-on-marked ()
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-ff-query-replace-fnames-on-marked)))
+(put 'helm-ff-run-query-replace-fnames-on-marked 'helm-only t)
+
+(defun helm-ff-query-replace (_candidate)
+ (let ((bufs (cl-loop for f in (helm-marked-candidates :with-wildcard t)
+ collect (buffer-name (find-file-noselect f)))))
+ (helm-buffer-query-replace-1 nil bufs)))
+
+(defun helm-ff-query-replace-regexp (_candidate)
+ (let ((bufs (cl-loop for f in (helm-marked-candidates :with-wildcard t)
+ collect (buffer-name (find-file-noselect f)))))
+ (helm-buffer-query-replace-1 'regexp bufs)))
+
+(defun helm-ff-run-query-replace ()
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-ff-query-replace)))
+(put 'helm-ff-run-query-replace 'helm-only t)
+
+(defun helm-ff-run-query-replace-regexp ()
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-ff-query-replace-regexp)))
+(put 'helm-ff-run-query-replace-regexp 'helm-only t)
+
+(defun helm-ff-toggle-auto-update (_candidate)
+ (if helm-ff--deleting-char-backward
+ (progn
+ (message "[Auto expansion disabled]")
+ (sit-for 1) (message nil)
+ (setq helm-ff--auto-update-state nil))
+ (setq helm-ff-auto-update-flag (not helm-ff-auto-update-flag))
+ (setq helm-ff--auto-update-state helm-ff-auto-update-flag)
+ (message "[Auto expansion %s]"
+ (if helm-ff-auto-update-flag "enabled" "disabled"))))
+
+(defun helm-ff-run-toggle-auto-update ()
+ (interactive)
+ (with-helm-alive-p
+ (helm-attrset 'toggle-auto-update '(helm-ff-toggle-auto-update . never-split))
+ (helm-execute-persistent-action 'toggle-auto-update)))
+(put 'helm-ff-run-toggle-auto-update 'helm-only t)
+
+(defun helm-ff-delete-char-backward ()
+ "Disable helm find files auto update and delete char backward."
+ (interactive)
+ (with-helm-alive-p
+ (setq helm-ff-auto-update-flag nil)
+ (setq helm-ff--deleting-char-backward t)
+ (call-interactively
+ (lookup-key (current-global-map)
+ (read-kbd-macro "DEL")))
+ (helm--update-header-line)))
+(put 'helm-ff-delete-char-backward 'helm-only t)
+
+(defun helm-ff-delete-char-backward--exit-fn ()
+ (setq helm-ff-auto-update-flag helm-ff--auto-update-state)
+ (setq helm-ff--deleting-char-backward nil))
+
+(defun helm-ff-RET-1 (&optional must-match)
+ "Used for RET action in `helm-find-files'.
+See `helm-ff-RET' for details.
+If MUST-MATCH is specified exit with
+`helm-confirm-and-exit-minibuffer' which handle must-match mechanism."
+ (let* ((cands (helm-marked-candidates))
+ (sel (car cands)))
+ (cl-assert sel nil "Trying to exit with no candidates")
+ (if (and (not (cdr cands))
+ (file-directory-p sel)
+ (not (string= "." (helm-basename sel))))
+ (helm-execute-persistent-action)
+ (if must-match
+ (helm-confirm-and-exit-minibuffer)
+ (helm-maybe-exit-minibuffer)))))
+
+(defun helm-ff-RET ()
+ "Default action for RET in `helm-find-files'.
+
+Behave differently depending of `helm-selection':
+
+- candidate basename is \".\" => open it in dired.
+- candidate is a directory => expand it.
+- candidate is a file => open it.
+- marked candidates (1+) => open them with default action."
+ (interactive)
+ (helm-ff-RET-1))
+
+(defun helm-ff-RET-must-match ()
+ "Same as `helm-ff-RET' but used in must-match map."
+ (interactive)
+ (helm-ff-RET-1 t))
+
+(defun helm-ff-run-grep ()
+ "Run Grep action from `helm-source-find-files'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-find-files-grep)))
+(put 'helm-ff-run-grep 'helm-only t)
+
+(defun helm-ff-run-git-grep ()
+ "Run git-grep action from `helm-source-find-files'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-ff-git-grep)))
+(put 'helm-ff-run-git-grep 'helm-only t)
+
+(defun helm-ff-run-grep-ag ()
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-find-files-ag)))
+(put 'helm-ff-run-grep-ag 'helm-only t)
+
+(defun helm-ff-run-pdfgrep ()
+ "Run Pdfgrep action from `helm-source-find-files'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-ff-pdfgrep)))
+(put 'helm-ff-run-pdfgrep 'helm-only t)
+
+(defun helm-ff-run-zgrep ()
+ "Run Grep action from `helm-source-find-files'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-ff-zgrep)))
+(put 'helm-ff-run-zgrep 'helm-only t)
+
+(defun helm-ff-run-copy-file ()
+ "Run Copy file action from `helm-source-find-files'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-find-files-copy)))
+(put 'helm-ff-run-copy-file 'helm-only t)
+
+(defun helm-ff-run-rename-file ()
+ "Run Rename file action from `helm-source-find-files'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-find-files-rename)))
+(put 'helm-ff-run-rename-file 'helm-only t)
+
+(defun helm-ff-run-byte-compile-file ()
+ "Run Byte compile file action from `helm-source-find-files'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-find-files-byte-compile)))
+(put 'helm-ff-run-byte-compile-file 'helm-only t)
+
+(defun helm-ff-run-load-file ()
+ "Run Load file action from `helm-source-find-files'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-find-files-load-files)))
+(put 'helm-ff-run-load-file 'helm-only t)
+
+(defun helm-ff-run-eshell-command-on-file ()
+ "Run eshell command on file action from `helm-source-find-files'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action
+ 'helm-find-files-eshell-command-on-file)))
+(put 'helm-ff-run-eshell-command-on-file 'helm-only t)
+
+(defun helm-ff-run-ediff-file ()
+ "Run Ediff file action from `helm-source-find-files'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-find-files-ediff-files)))
+(put 'helm-ff-run-ediff-file 'helm-only t)
+
+(defun helm-ff-run-ediff-merge-file ()
+ "Run Ediff merge file action from `helm-source-find-files'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action
+ 'helm-find-files-ediff-merge-files)))
+(put 'helm-ff-run-ediff-merge-file 'helm-only t)
+
+(defun helm-ff-run-symlink-file ()
+ "Run Symlink file action from `helm-source-find-files'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-find-files-symlink)))
+(put 'helm-ff-run-symlink-file 'helm-only t)
+
+(defun helm-ff-run-relsymlink-file ()
+ "Run Symlink file action from `helm-source-find-files'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-find-files-relsymlink)))
+(put 'helm-ff-run-relsymlink-file 'helm-only t)
+
+(defun helm-ff-run-hardlink-file ()
+ "Run Hardlink file action from `helm-source-find-files'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-find-files-hardlink)))
+(put 'helm-ff-run-hardlink-file 'helm-only t)
+
+(defun helm-ff-delete-files (candidate)
+ "Delete files default action."
+ (funcall helm-ff-delete-files-function candidate))
+
+(defun helm-ff-run-delete-file ()
+ "Run Delete file action from `helm-source-find-files'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action #'helm-ff-delete-files)))
+(put 'helm-ff-run-delete-file 'helm-only t)
+
+(defun helm-ff-run-complete-fn-at-point ()
+ "Run complete file name action from `helm-source-find-files'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action
+ 'helm-insert-file-name-completion-at-point)))
+(put 'helm-ff-run-complete-fn-at-point 'helm-only t)
+
+(defun helm-ff-run-switch-to-eshell ()
+ "Run switch to eshell action from `helm-source-find-files'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-ff-switch-to-eshell)))
+(put 'helm-ff-run-switch-to-eshell 'helm-only t)
+
+(defun helm-ff-run-switch-other-window ()
+ "Run switch to other window action from `helm-source-find-files'.
+When a prefix arg is provided, split is done vertically."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-find-files-other-window)))
+(put 'helm-ff-run-switch-other-window 'helm-only t)
+
+(defun helm-ff-run-switch-other-frame ()
+ "Run switch to other frame action from `helm-source-find-files'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'find-file-other-frame)))
+(put 'helm-ff-run-switch-other-frame 'helm-only t)
+
+(defun helm-ff-run-open-file-externally ()
+ "Run open file externally command action from `helm-source-find-files'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-open-file-externally)))
+(put 'helm-ff-run-open-file-externally 'helm-only t)
+
+(defun helm-ff-run-open-file-with-default-tool ()
+ "Run open file externally command action from `helm-source-find-files'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-open-file-with-default-tool)))
+(put 'helm-ff-run-open-file-with-default-tool 'helm-only t)
+
+(defun helm-ff-locate (candidate)
+ "Locate action function for `helm-find-files'."
+ (helm-locate-set-command)
+ (let ((default (concat (helm-basename
+ (expand-file-name
+ candidate
+ helm-ff-default-directory))
+ (unless (or
+ ;; "-b" is already added when fuzzy matching.
+ helm-locate-fuzzy-match
+ ;; The locate '-b' option doesn't exists
+ ;; in everything (es).
+ (and (eq system-type 'windows-nt)
+ (string-match "^es" helm-locate-command)))
+ " -b"))))
+ (helm-locate-1 helm-current-prefix-arg nil 'from-ff default)))
+
+(defun helm-ff-run-locate ()
+ "Run locate action from `helm-source-find-files'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-ff-locate)))
+(put 'helm-ff-run-locate 'helm-only t)
+
+(defun helm-files-insert-as-org-link (candidate)
+ (insert (format "[[%s][]]" candidate))
+ (goto-char (- (point) 2)))
+
+(defun helm-ff-run-insert-org-link ()
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-files-insert-as-org-link)))
+(put 'helm-ff-run-insert-org-link 'helm-only t)
+
+(defun helm-ff-run-find-file-as-root ()
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-find-file-as-root)))
+(put 'helm-ff-run-find-file-as-root 'helm-only t)
+
+(defun helm-ff-run-find-alternate-file ()
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'find-alternate-file)))
+(put 'helm-ff-run-find-alternate-file 'helm-only t)
+
+(defun helm-ff-run-mail-attach-files ()
+ "Run mail attach files command action from `helm-source-find-files'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-ff-mail-attach-files)))
+(put 'helm-ff-run-mail-attach-files 'helm-only t)
+
+(defun helm-ff-run-etags ()
+ "Run Etags command action from `helm-source-find-files'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-ff-etags-select)))
+(put 'helm-ff-run-etags 'helm-only t)
+
+(defvar lpr-printer-switch)
+(defun helm-ff-print (_candidate)
+ "Print marked files.
+
+You may to set in order
+variables `lpr-command',`lpr-switches' and/or `printer-name',
+but with no settings helm should detect your printer(s) and
+print with the default `lpr' settings.
+
+NOTE: DO NOT set the \"-P\" flag in `lpr-switches', if you really
+have to modify this, do it in `lpr-printer-switch'.
+
+Same as `dired-do-print' but for helm."
+ (require 'lpr)
+ (when (or helm-current-prefix-arg
+ (not helm-ff-printer-list))
+ (setq helm-ff-printer-list
+ (helm-ff-find-printers)))
+ (let* ((file-list (helm-marked-candidates :with-wildcard t))
+ (len (length file-list))
+ (printer-name (if helm-ff-printer-list
+ (helm-comp-read
+ "Printer: " helm-ff-printer-list)
+ printer-name))
+ (lpr-switches
+ (if (and (stringp printer-name)
+ (string< "" printer-name))
+ (cons (concat lpr-printer-switch printer-name)
+ lpr-switches)
+ lpr-switches))
+ (command (helm-read-string
+ (format "Print *%s File(s):\n%s with: "
+ len
+ (mapconcat
+ (lambda (f) (format "- %s\n" f))
+ file-list ""))
+ (when (and lpr-command lpr-switches)
+ (mapconcat 'identity
+ (cons lpr-command
+ (if (stringp lpr-switches)
+ (list lpr-switches)
+ lpr-switches))
+ " "))))
+ (file-args (mapconcat (lambda (x)
+ (format "'%s'" x))
+ file-list " "))
+ (cmd-line (concat command " " file-args)))
+ (if command
+ (start-process-shell-command "helm-print" nil cmd-line)
+ (error "Error: Please verify your printer settings in Emacs."))))
+
+(defun helm-ff-run-print-file ()
+ "Run Print file action from `helm-source-find-files'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-ff-print)))
+(put 'helm-ff-run-print-file 'helm-only t)
+
+(defun helm-ff-checksum (file)
+ "Calculate the checksum of FILE.
+The checksum is copied to kill-ring."
+ (cl-assert (file-regular-p file)
+ nil "`%s' is not a regular file" file)
+ (let ((algo (intern (helm-comp-read
+ "Algorithm: "
+ '(md5 sha1 sha224 sha256 sha384 sha512))))
+ (bn (helm-basename file)))
+ (message "Calculating %s checksum for %s..." algo bn)
+ (async-let ((sum (with-temp-buffer
+ (insert-file-contents-literally file)
+ (secure-hash algo (current-buffer)))))
+ (kill-new sum)
+ (message "Calculating %s checksum for `%s' done and copied to kill-ring" algo bn))))
+
+(defun helm-ff-toggle-basename (_candidate)
+ (with-helm-buffer
+ (setq helm-ff-transformer-show-only-basename
+ (not helm-ff-transformer-show-only-basename))
+ (let* ((cand (helm-get-selection nil t))
+ (target (if helm-ff-transformer-show-only-basename
+ (helm-basename cand) cand)))
+ (helm-force-update (concat (regexp-quote target) "$")))))
+
+(defun helm-ff-run-toggle-basename ()
+ (interactive)
+ (with-helm-alive-p
+ (unless (helm-empty-source-p)
+ (helm-ff-toggle-basename nil))))
+(put 'helm-ff-run-toggle-basename 'helm-only t)
+
+(defun helm-reduce-file-name (fname level)
+ "Reduce FNAME by number LEVEL from end."
+ ;; This version comes from issue #2004 (UNC paths) and should fix it.
+ (while (> level 0)
+ (unless (or (string= fname "/")
+ (string= (file-remote-p fname 'localname) "/"))
+ (setq fname (expand-file-name
+ (concat (expand-file-name fname) "/../"))))
+ (setq level (1- level)))
+ fname)
+
+(defvar helm-find-files--level-tree nil)
+(defvar helm-find-files--level-tree-iterator nil)
+(defun helm-find-files-up-one-level (arg)
+ "Go up one level like unix command `cd ..'.
+If prefix numeric arg is given go ARG level up."
+ (interactive "p")
+ (with-helm-alive-p
+ (let ((src (helm-get-current-source)))
+ (when (and (helm-file-completion-source-p src)
+ (not (helm-ff--invalid-tramp-name-p)))
+ (with-helm-window
+ (when (helm-follow-mode-p)
+ (helm-follow-mode -1) (message nil)))
+ ;; When going up one level we want to be at the line
+ ;; corresponding to actual directory, so store this info
+ ;; in `helm-ff-last-expanded'.
+ (let ((cur-cand (helm-get-selection nil nil src))
+ (new-pattern (helm-reduce-file-name helm-pattern arg)))
+ ;; Ensure visibility on all candidates for preselection.
+ (helm-attrset 'candidate-number-limit
+ (if helm-ff-up-one-level-preselect
+ (max (gethash new-pattern
+ helm-ff--directory-files-hash
+ helm-ff-candidate-number-limit)
+ helm-ff-candidate-number-limit)
+ helm-ff-candidate-number-limit))
+ (cond ((file-directory-p helm-pattern)
+ (setq helm-ff-last-expanded helm-ff-default-directory))
+ ((file-exists-p helm-pattern)
+ (setq helm-ff-last-expanded helm-pattern))
+ ((and cur-cand (file-exists-p cur-cand))
+ (setq helm-ff-last-expanded cur-cand)))
+ (unless helm-find-files--level-tree
+ (setq helm-find-files--level-tree
+ (cons helm-ff-default-directory
+ helm-find-files--level-tree)))
+ (setq helm-find-files--level-tree-iterator nil)
+ (push new-pattern helm-find-files--level-tree)
+ (helm-set-pattern new-pattern helm-suspend-update-flag)
+ (with-helm-after-update-hook (helm-ff-retrieve-last-expanded)))))))
+(put 'helm-find-files-up-one-level 'helm-only t)
+
+(defun helm-find-files-down-last-level ()
+ "Retrieve previous paths reached by `C-l' in helm-find-files."
+ (interactive)
+ (with-helm-alive-p
+ (when (and (helm-file-completion-source-p)
+ (not (helm-ff--invalid-tramp-name-p)))
+ (unless helm-find-files--level-tree-iterator
+ (setq helm-find-files--level-tree-iterator
+ (helm-iter-list (cdr helm-find-files--level-tree))))
+ (setq helm-find-files--level-tree nil)
+ (helm-aif (helm-iter-next helm-find-files--level-tree-iterator)
+ (helm-set-pattern it)
+ (setq helm-find-files--level-tree-iterator nil)))))
+(put 'helm-find-files-down-last-level 'helm-only t)
+
+(defun helm-find-files--reset-level-tree ()
+ (setq helm-find-files--level-tree-iterator nil
+ helm-find-files--level-tree nil))
+
+(add-hook 'helm-cleanup-hook 'helm-find-files--reset-level-tree)
+(add-hook 'post-self-insert-hook 'helm-find-files--reset-level-tree)
+(add-hook 'helm-after-persistent-action-hook 'helm-find-files--reset-level-tree)
+
+(defun helm-ff-retrieve-last-expanded ()
+ "Move overlay to last visited directory `helm-ff-last-expanded'.
+This happen after using `helm-find-files-up-one-level',
+or hitting C-j on \"..\"."
+ (when helm-ff-last-expanded
+ (let ((presel (if helm-ff-transformer-show-only-basename
+ (helm-basename
+ (directory-file-name helm-ff-last-expanded))
+ (directory-file-name helm-ff-last-expanded))))
+ (with-helm-window
+ (when (re-search-forward (concat "^" (regexp-quote presel) "$") nil t)
+ (forward-line 0)
+ (helm-mark-current-line)))
+ (setq helm-ff-last-expanded nil))))
+
+(defun helm-ff-move-to-first-real-candidate ()
+ "When candidate is an incomplete file name move to first real candidate."
+ (let* ((src (helm-get-current-source))
+ (name (assoc-default 'name src))
+ ;; Ensure `helm-file-completion-source-p' returns nil on
+ ;; `helm-read-file-name' history.
+ minibuffer-completing-file-name)
+ (helm-aif (and (helm-file-completion-source-p src)
+ (not (helm-empty-source-p))
+ ;; Prevent dired commands moving to first real
+ ;; (Issue #910).
+ (or (memq (intern-soft name)
+ helm-ff-goto-first-real-dired-exceptions)
+ (not (string-match "\\`[Dd]ired-" name)))
+ helm-ff--move-to-first-real-candidate
+ (helm-get-selection nil nil src))
+ (unless (or (not (stringp it))
+ (and (string-match helm-tramp-file-name-regexp it)
+ (not (file-remote-p it nil t)))
+ (file-exists-p it))
+ (helm-next-line)))))
+
+;;; Auto-update - helm-find-files auto expansion of directories.
+;;
+;;
+(defun helm-ff-update-when-only-one-matched ()
+ "Expand to directory when sole completion.
+When only one candidate is remaining and it is a directory,
+expand to this directory.
+This happen only when `helm-ff-auto-update-flag' is non--nil
+or when `helm-pattern' is equal to \"~/\"."
+ (let ((src (helm-get-current-source)))
+ (when (and (helm-file-completion-source-p src)
+ (not (get-buffer-window helm-action-buffer 'visible))
+ (not (helm-ff--invalid-tramp-name-p))
+ (not (string-match-p "\\`[.]\\{2\\}[^/]+"
+ (helm-basename helm-pattern))))
+ (with-helm-buffer
+ (let* ((history-p (string= (assoc-default 'name src)
+ "Read File Name History"))
+ (pat (if (string-match helm-tramp-file-name-regexp
+ helm-pattern)
+ (helm-ff--create-tramp-name helm-pattern)
+ helm-pattern))
+ (completed-p (string= (file-name-as-directory
+ (expand-file-name
+ (substitute-in-file-name pat)))
+ helm-ff-default-directory))
+ (candnum (helm-get-candidate-number))
+ (lt2-p (and (<= candnum 2)
+ (>= (string-width (helm-basename helm-pattern)) 2)))
+ (cur-cand (prog2
+ (unless (or completed-p
+ (file-exists-p pat)
+ history-p (null lt2-p))
+ ;; Only one non--existing candidate
+ ;; and one directory candidate, move to it,
+ ;; but not when renaming, copying etc...,
+ ;; so for this use
+ ;; `helm-ff-move-to-first-real-candidate'
+ ;; instead of `helm-next-line' (Issue #910).
+ (helm-ff-move-to-first-real-candidate))
+ (helm-get-selection nil nil src))))
+ (when (and (or (and helm-ff-auto-update-flag
+ (null helm-ff--deleting-char-backward)
+ ;; Issue #295
+ ;; File predicates are returning t
+ ;; with paths like //home/foo.
+ ;; So check it is not the case by regexp
+ ;; to allow user to do C-a / to start e.g
+ ;; entering a tramp method e.g /sudo::.
+ (not (string-match "\\`//" helm-pattern))
+ (not (eq last-command 'helm-yank-text-at-point)))
+ ;; Fix issue #542.
+ (string= helm-pattern "~/")
+ ;; Only one remaining directory, expand it.
+ (and (= candnum 1)
+ helm-ff--auto-update-state
+ (file-accessible-directory-p pat)
+ (null helm-ff--deleting-char-backward)))
+ (or
+ ;; Only one candidate remaining
+ ;; and at least 2 char in basename.
+ lt2-p
+ ;; Already completed.
+ completed-p)
+ (not history-p) ; Don't try to auto complete in history.
+ (stringp cur-cand)
+ (file-accessible-directory-p cur-cand))
+ (if (and (not (helm-dir-is-dot cur-cand)) ; [1]
+ ;; Maybe we are here because completed-p is true
+ ;; but check this again to be sure. (Windows fix)
+ (<= candnum 2)) ; [2]
+ ;; If after going to next line the candidate
+ ;; is not one of "." or ".." [1]
+ ;; and only one candidate is remaining [2],
+ ;; assume candidate is a new directory to expand, and do it.
+ (helm-set-pattern (file-name-as-directory cur-cand))
+ ;; The candidate is one of "." or ".."
+ ;; that mean we have entered the last letter of the directory name
+ ;; in prompt, so expansion is already done, just add the "/" at end
+ ;; of name unless helm-pattern ends with "."
+ ;; (i.e we are writing something starting with ".")
+ (unless (string-match "\\`.*[.]\\{1\\}\\'" helm-pattern)
+ (helm-set-pattern
+ ;; Need to expand-file-name to avoid e.g /ssh:host:./ in prompt.
+ (expand-file-name (file-name-as-directory helm-pattern)))))
+ (helm-check-minibuffer-input)))))))
+
+(defun helm-ff-auto-expand-to-home-or-root ()
+ "Allow expanding to home/user directory or root or text yanked after pattern."
+ (when (and (helm-file-completion-source-p)
+ (with-current-buffer (window-buffer (minibuffer-window)) (eolp))
+ (not (string-match helm-ff-url-regexp helm-pattern)))
+ (cond ((and (not (file-remote-p helm-pattern))
+ (null (file-exists-p helm-pattern))
+ (string-match-p
+ "\\`\\([.]\\|\\s-\\)\\{2\\}[^/]+"
+ (helm-basename helm-pattern))
+ (string-match-p "/\\'" helm-pattern))
+ (helm-ff-recursive-dirs helm-pattern)
+ (with-helm-window (helm-check-minibuffer-input)))
+ ((string-match
+ "\\(?:\\`~/\\)\\|/?\\$.*/\\|/\\./\\|/\\.\\./\\|/~.*/\\|//\\|\\(/[[:alpha:]]:/\\|\\s\\+\\)"
+ helm-pattern)
+ (let* ((match (match-string 0 helm-pattern))
+ (input (cond ((string= match "/./")
+ (expand-file-name default-directory))
+ ((string= helm-pattern "/../") "/")
+ ((string-match-p "\\`/\\$" match)
+ (let ((sub (substitute-in-file-name match)))
+ (if (file-directory-p sub)
+ sub (replace-regexp-in-string "/\\'" "" sub))))
+ (t (helm-ff--expand-substitued-pattern helm-pattern)))))
+ ;; `file-directory-p' returns t on "/home/me/." (issue #1844).
+ (if (and (file-directory-p input)
+ (not (string-match-p "[^.]\\.\\'" input)))
+ (setq helm-ff-default-directory
+ (setq input (file-name-as-directory input)))
+ (setq helm-ff-default-directory (file-name-as-directory
+ (file-name-directory input))))
+ (with-helm-window
+ (helm-set-pattern input)
+ (helm-check-minibuffer-input)))))))
+
+(defun helm-ff--expand-file-name-no-dot (name &optional directory)
+ "Prevent expanding \"/home/user/.\" to \"/home/user\"."
+ ;; Issue #1844 - If user enter "~/." to type an hidden filename
+ ;; don't expand to /home/him e.g.
+ ;; (expand-file-name "~/.") =>"/home/thierry"
+ ;; (helm-ff--expand-substitued-pattern "~/.") =>"/home/thierry/."
+ (concat (expand-file-name name directory)
+ (and (string-match "[^.]\\.\\'" name) "/.")))
+
+(defun helm-ff--expand-substitued-pattern (pattern)
+ ;; [Windows] On UNC paths "/" expand to current machine,
+ ;; so use the root of current Drive. (i.e "C:/")
+ (let* ((directory (and (memq system-type '(windows-nt ms-dos))
+ (getenv "SystemDrive")))
+ ;; On Windows use a simple call to `expand-file-name' to
+ ;; avoid Issue #2004.
+ (expand-fn (if directory
+ #'expand-file-name
+ #'helm-ff--expand-file-name-no-dot)))
+ (funcall expand-fn (helm-substitute-in-filename pattern)
+ ;; directory is nil on Nix.
+ directory)))
+
+(defun helm-substitute-in-filename (fname)
+ "Substitute all parts of FNAME from start up to \"~/\" or \"/\".
+On windows system substitute from start up to \"/[[:lower:]]:/\".
+This function is needed for `helm-ff-auto-expand-to-home-or-root'
+and should be used carefully elsewhere, or not at all, using
+`substitute-in-file-name' instead."
+ (cond ((and helm--url-regexp
+ (string-match-p helm--url-regexp fname))
+ fname)
+ ((and (file-remote-p fname)
+ helm-substitute-in-filename-stay-on-remote)
+ (let ((sub (substitute-in-file-name fname)))
+ (if (file-directory-p sub)
+ sub (replace-regexp-in-string "/\\'" "" sub))))
+ (t
+ (with-temp-buffer
+ (insert fname)
+ (goto-char (point-min))
+ (when (memq system-type '(windows-nt ms-dos))
+ (skip-chars-forward "/")) ;; Avoid infloop in UNC paths Issue #424
+ (if (re-search-forward "~.*/?\\|//\\|/[[:alpha:]]:/" nil t)
+ (let ((match (match-string 0)))
+ (goto-char (if (or (string= match "//")
+ (string-match-p "/[[:alpha:]]:/" match))
+ (1+ (match-beginning 0))
+ (match-beginning 0)))
+ (buffer-substring-no-properties (point) (point-at-eol)))
+ fname)))))
+
+(defun helm-point-file-in-dired (file)
+ "Put point on filename FILE in dired buffer."
+ (unless (and helm--url-regexp
+ (string-match-p helm--url-regexp file))
+ (let ((target (expand-file-name (helm-substitute-in-filename file))))
+ (dired (file-name-directory target))
+ (dired-goto-file target))))
+
+(defun helm-marked-files-in-dired (_candidate)
+ "Open a dired buffer with only marked files.
+
+With a prefix arg toggle dired buffer to wdired mode."
+ (advice-add 'wdired-finish-edit :override #'helm--advice-wdired-finish-edit)
+ (advice-add 'wdired-get-filename :override #'helm--advice-wdired-get-filename)
+ (let* ((marked (helm-marked-candidates :with-wildcard t))
+ (current (car marked)))
+ (unless (and helm--url-regexp
+ (string-match-p helm--url-regexp current))
+ (let ((target (expand-file-name (helm-substitute-in-filename current))))
+ (dired (cons helm-ff-default-directory marked))
+ (dired-goto-file target)
+ (when (or helm-current-prefix-arg current-prefix-arg)
+ (call-interactively 'wdired-change-to-wdired-mode))))))
+
+(defun helm-ff-run-marked-files-in-dired ()
+ "Execute `helm-marked-files-in-dired' interactively."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-marked-files-in-dired)))
+(put 'helm-ff-run-marked-files-in-dired 'helm-only t)
+
+(defun helm-ff--create-tramp-name (fname)
+ "Build filename from `helm-pattern' like /su:: or /sudo::."
+ ;; `tramp-make-tramp-file-name' takes 7 args on emacs-26 whereas it
+ ;; takes only 5 args in emacs-24/25.
+ (apply #'tramp-make-tramp-file-name
+ ;; `tramp-dissect-file-name' returns a list in emacs-26
+ ;; whereas in 24.5 it returns a vector, thus the car is a
+ ;; symbol (`tramp-file-name') which is not needed as argument
+ ;; for `tramp-make-tramp-file-name' so transform the cdr in
+ ;; vector, and for 24.5 use directly the returned value.
+ (cl-loop with v = (helm-ff--tramp-cons-or-vector
+ (tramp-dissect-file-name fname))
+ for i across v collect i)))
+
+(defun helm-ff--tramp-cons-or-vector (vector-or-cons)
+ "Return VECTOR-OR-CONS as a vector."
+ (pcase vector-or-cons
+ (`(,_l . ,ll) (vconcat ll))
+ ((and vec (pred vectorp)) vec)))
+
+(defun helm-ff--get-tramp-methods ()
+ "Returns a list of the car of `tramp-methods'."
+ (or helm-ff--tramp-methods
+ (setq helm-ff--tramp-methods (mapcar 'car tramp-methods))))
+
+(defun helm-ff--previous-mh-tramp-method (str)
+ (save-match-data
+ (with-temp-buffer
+ (insert str)
+ (when (re-search-backward
+ (concat "\\([|]\\)\\("
+ (mapconcat 'identity (helm-ff--get-tramp-methods) "\\|")
+ "\\):")
+ nil t)
+ (list
+ (buffer-substring-no-properties (point-at-bol) (match-beginning 2))
+ (buffer-substring-no-properties (match-beginning 2) (match-end 2)))))))
+
+(defun helm-ff--get-host-from-tramp-invalid-fname (fname)
+ "Extract hostname from an incomplete tramp file name.
+Return nil on valid file name remote or not."
+ ;; Check first if whole file is remote (file-remote-p is inefficient
+ ;; in this case) otherwise we are matching e.g. /home/you/ssh:foo/
+ ;; which is not a remote name.
+ ;; FIXME this will not work with a directory or a file named like
+ ;; "ssh:foo" and located at root (/) but it seems there is no real
+ ;; solution apart disabling tramp-mode when a file/dir located at /
+ ;; is matching helm-tramp-file-name-regexp; This would prevent usage
+ ;; of tramp if one have such a directory at / (who would want to
+ ;; have such a dir at / ???) See emacs-bug#31489.
+ (when (string-match-p helm-tramp-file-name-regexp fname)
+ (let* ((bn (helm-basename fname))
+ (bd (replace-regexp-in-string (regexp-quote bn) "" fname))
+ (split (split-string bn ":" t))
+ (meth (car (member (car split)
+ (helm-ff--get-tramp-methods)))))
+ (and meth (string= bd "/") (car (last split))))))
+
+(cl-defun helm-ff--tramp-hostnames (&optional (pattern helm-pattern))
+ "Get a list of hosts for tramp method found in `helm-pattern'.
+Argument PATTERN default to `helm-pattern', it is here only for debugging
+purpose."
+ (when (string-match helm-tramp-file-name-regexp pattern)
+ (let* ((mh-method (helm-ff--previous-mh-tramp-method pattern))
+ (method (or (cadr mh-method) (match-string 1 pattern)))
+ (current-mh-host (helm-aif (and mh-method
+ (helm-ff--get-host-from-tramp-invalid-fname pattern))
+ (concat (car mh-method) method ":"
+ (car (split-string it "|" t)))))
+ (all-methods (helm-ff--get-tramp-methods))
+ (comps (cl-loop for (f . h) in (tramp-get-completion-function method)
+ append (cl-loop for e in (funcall f (car h))
+ for host = (and (consp e) (cadr e))
+ when (and host (not (member host all-methods)))
+ collect (concat (or (car mh-method) "/")
+ method ":" host)))))
+ (helm-fast-remove-dups
+ (delq nil (cons current-mh-host comps))
+ :test 'equal))))
+
+(defun helm-ff-before-action-hook-fn ()
+ "Exit helm when user try to execute action on an invalid tramp fname."
+ (let* ((src (helm-get-current-source))
+ (cand (helm-get-selection nil nil src)))
+ (when (and (helm-file-completion-source-p src)
+ (stringp cand)
+ (helm-ff--invalid-tramp-name-p cand) ; Check candidate.
+ (helm-ff--invalid-tramp-name-p)) ; check helm-pattern.
+ (error "Error: Unknown file or directory `%s'" cand))))
+(add-hook 'helm-before-action-hook 'helm-ff-before-action-hook-fn)
+
+(cl-defun helm-ff--invalid-tramp-name-p (&optional (pattern helm-pattern))
+ "Return non--nil when PATTERN is an invalid tramp filename."
+ (string= (helm-ff-set-pattern pattern)
+ "Invalid tramp file name"))
+
+(defun helm-ff--tramp-postfixed-p (str)
+ (let (result)
+ (save-match-data
+ (with-temp-buffer
+ (save-excursion (insert str))
+ (helm-awhile (search-forward ":" nil t)
+ (if (save-excursion
+ (forward-char -1)
+ (looking-back
+ (mapconcat 'identity (helm-ff--get-tramp-methods) "\\|")
+ (point-at-bol)))
+ (setq result nil)
+ (setq result it)))))
+ result))
+
+(defun helm-ff-set-pattern (pattern)
+ "Handle tramp filenames in `helm-pattern'."
+ (let* ((methods (helm-ff--get-tramp-methods))
+ ;; Returns the position of last ":" entered.
+ (postfixed (helm-ff--tramp-postfixed-p pattern))
+ (reg "\\`/\\([^[/:]+\\|[^/]+]\\):.*:")
+ cur-method tramp-name)
+ ;; In some rare cases tramp can return a nil input,
+ ;; so be sure pattern is a string for safety (Issue #476).
+ (unless pattern (setq pattern ""))
+ (cond ((string-match helm-ff-url-regexp pattern) pattern)
+ ((string-match "\\`\\$" pattern)
+ (substitute-in-file-name pattern))
+ ((string= pattern "") "")
+ ((string-match "\\`[.]\\{1,2\\}/\\'" pattern)
+ (expand-file-name pattern))
+ ;; Directories ending by a dot (issue #1940)
+ ((string-match "[^/][.]/\\'" pattern)
+ (expand-file-name pattern))
+ ((string-match ".*\\(~?/?[.]\\{1\\}/\\)\\'" pattern)
+ (expand-file-name default-directory))
+ ((string-match ".*\\(~//\\|//\\)\\'" pattern)
+ (expand-file-name "/")) ; Expand to "/" or "c:/"
+ ((string-match "\\`\\(~/\\|.*/~/\\)\\'" pattern)
+ (expand-file-name "~/"))
+ ((string-match "\\`~/" pattern)
+ (expand-file-name pattern))
+ ;; Match "/method:maybe_hostname:~"
+ ((and (string-match (concat reg "~") pattern)
+ postfixed
+ (setq cur-method (match-string 1 pattern))
+ (member cur-method methods))
+ (setq tramp-name (expand-file-name
+ (helm-ff--create-tramp-name
+ (match-string 0 pattern))))
+ (replace-match tramp-name nil t pattern))
+ ;; Match "/method:maybe_hostname:"
+ ((and (string-match reg pattern)
+ postfixed
+ (setq cur-method (match-string 1 pattern))
+ (member cur-method methods))
+ (setq tramp-name (helm-ff--create-tramp-name
+ (match-string 0 pattern)))
+ (replace-match tramp-name nil t pattern))
+ ;; Match "/hostname:"
+ ((and (string-match helm-tramp-file-name-regexp pattern)
+ postfixed
+ (setq cur-method (match-string 1 pattern))
+ (and cur-method (not (member cur-method methods))))
+ (setq tramp-name (helm-ff--create-tramp-name
+ (match-string 0 pattern)))
+ (replace-match tramp-name nil t pattern))
+ ;; Match "/method:" in this case don't try to connect.
+ ((and (null postfixed)
+ (string-match helm-tramp-file-name-regexp pattern)
+ (member (match-string 1 pattern) methods))
+ "Invalid tramp file name") ; Write in helm-buffer.
+ ;; Return PATTERN unchanged.
+ (t pattern))))
+
+(defun helm-find-files-get-candidates (&optional require-match)
+ "Create candidate list for `helm-source-find-files'."
+ (let* ((path (helm-ff-set-pattern helm-pattern))
+ (dir-p (file-accessible-directory-p path))
+ basedir
+ invalid-basedir
+ non-essential
+ (tramp-verbose helm-tramp-verbose)) ; No tramp message when 0.
+ ;; Tramp check if path is valid without waiting a valid
+ ;; connection and may send a file-error.
+ (setq helm--ignore-errors (file-remote-p path))
+ (set-text-properties 0 (length path) nil path)
+ ;; Issue #118 allow creation of newdir+newfile.
+ (unless (or
+ ;; A tramp file name not completed.
+ (string= path "Invalid tramp file name")
+ ;; An empty pattern
+ (string= path "")
+ (and (string-match-p ":\\'" path)
+ (helm-ff--tramp-postfixed-p path))
+ ;; Check if base directory of PATH is valid.
+ (helm-aif (file-name-directory path)
+ ;; If PATH is a valid directory IT=PATH,
+ ;; else IT=basedir of PATH.
+ (file-directory-p it)))
+ ;; BASEDIR is invalid, that's mean user is starting
+ ;; to write a non--existing path in minibuffer
+ ;; probably to create a 'new_dir' or a 'new_dir+new_file'.
+ (setq invalid-basedir t))
+ ;; Don't set now `helm-pattern' if `path' == "Invalid tramp file name"
+ ;; like that the actual value (e.g /ssh:) is passed to
+ ;; `helm-ff--tramp-hostnames'.
+ (unless (or (string= path "Invalid tramp file name")
+ invalid-basedir) ; Leave helm-pattern unchanged.
+ (setq helm-ff-auto-update-flag ; [1]
+ ;; Unless auto update is disabled start auto updating only
+ ;; at third char.
+ (unless (or (null helm-ff--auto-update-state)
+ ;; But don't enable auto update when
+ ;; deleting backward.
+ helm-ff--deleting-char-backward
+ (and dir-p (not (string-match-p "/\\'" path))))
+ (or (>= (length (helm-basename path)) 3) dir-p)))
+ ;; At this point the tramp connection is triggered.
+ (helm-log
+ "Pattern=%S"
+ (setq helm-pattern (helm-ff--transform-pattern-for-completion path)))
+ ;; This have to be set after [1] to allow deleting char backward.
+ (setq basedir (or (helm-aand
+ (if (and dir-p helm-ff-auto-update-flag)
+ ;; Add the final "/" to path
+ ;; when `helm-ff-auto-update-flag' is enabled.
+ (file-name-as-directory path)
+ (if (string= path "")
+ "/" (file-name-directory path)))
+ (expand-file-name it))
+ default-directory))
+ (setq helm-ff-default-directory
+ (if (string= helm-pattern "")
+ (expand-file-name "/") ; Expand to "/" or "c:/"
+ ;; If path is an url *default-directory have to be nil.
+ (unless (or (string-match helm-ff-url-regexp path)
+ (and helm--url-regexp
+ (string-match helm--url-regexp path)))
+ basedir))))
+ (when (and (string-match ":\\'" path)
+ (file-remote-p basedir nil t))
+ (setq helm-pattern basedir))
+ (cond ((string= path "Invalid tramp file name")
+ (or (helm-ff--tramp-hostnames) ; Hostnames completion.
+ (prog2
+ ;; `helm-pattern' have not been modified yet.
+ ;; Set it here to the value of `path' that should be now
+ ;; "Invalid tramp file name" and set the candidates list
+ ;; to ("Invalid tramp file name") to make `helm-pattern'
+ ;; match single candidate "Invalid tramp file name".
+ (setq helm-pattern path)
+ ;; "Invalid tramp file name" is now printed
+ ;; in `helm-buffer'.
+ (list path))))
+ ((or (and (file-regular-p path)
+ (eq last-repeatable-command 'helm-execute-persistent-action))
+ ;; `ffap-url-regexp' don't match until url is complete.
+ (string-match helm-ff-url-regexp path)
+ invalid-basedir
+ (and (not (file-exists-p path)) (string-match "/$" path))
+ (and helm--url-regexp (string-match helm--url-regexp path)))
+ (list path))
+ ((string= path "") (helm-ff-directory-files "/"))
+ ;; Check here if directory is accessible (not working on Windows).
+ ((and (file-directory-p path) (not (file-readable-p path)))
+ (list (format "file-error: Opening directory permission denied `%s'" path)))
+ ;; A fast expansion of PATH is made only if `helm-ff-auto-update-flag'
+ ;; is enabled.
+ ((and dir-p helm-ff-auto-update-flag)
+ (helm-ff-directory-files path))
+ (t (append (unless (or require-match
+ ;; When `helm-ff-auto-update-flag' has been
+ ;; disabled, whe don't want PATH to be added on top
+ ;; if it is a directory.
+ dir-p)
+ (list path))
+ (helm-ff-directory-files basedir))))))
+
+(defun helm-list-directory (directory)
+ "List directory DIRECTORY.
+
+If DIRECTORY is remote use `helm-list-directory-function' otherwise use
+`directory-files'."
+ (if (file-remote-p directory)
+ (funcall helm-list-directory-function directory)
+ (directory-files directory t directory-files-no-dot-files-regexp)))
+
+(defun helm-list-dir-lisp (directory)
+ "List DIRECTORY with `file-name-all-completions' as backend.
+
+Add a `helm-ff-dir' property on each fname ending with \"/\"."
+ ;; NOTE: `file-name-all-completions' and `directory-files' and most
+ ;; tramp file handlers don't handle cntrl characters in fnames, so
+ ;; the displayed files will be plain wrong in this case, even worst
+ ;; the filenames will be splitted in two or more filenames.
+ (cl-loop for f in (sort (file-name-all-completions "" directory)
+ 'string-lessp)
+ unless (or (string= f "")
+ (member f '("./" "../"))
+ ;; Ignore the tramp names from /
+ ;; completion, e.g. ssh: scp: etc...
+ (char-equal (aref f (1- (length f))) ?:))
+ if (and (helm--dir-name-p f)
+ (helm--dir-file-name f directory))
+ collect (propertize it 'helm-ff-dir t)
+ else collect (propertize (expand-file-name f directory)
+ 'helm-ff-file t)))
+
+(defun helm-list-dir-external (dir)
+ "List directory DIR with external shell command as backend.
+
+This function is fast enough to be used for remote files and save the
+type of files at the same time in a property for using it later in the
+transformer."
+ (let ((default-directory (file-name-as-directory
+ (expand-file-name dir))))
+ (with-temp-buffer
+ (when (eq (process-file-shell-command
+ (format
+ ;; -A remove dot files, -F append [*=@|/>] at eof
+ ;; and -Q quote the real filename. If not using -Q,
+ ;; there is no way to distinguish if foo* is a real
+ ;; file or if it is foo the executable file so with
+ ;; -Q we have "foo"* for the executable file foo and
+ ;; "foo*" for the real file foo. The downside is
+ ;; that we need an extra step to remove the quotes
+ ;; at the end which impact performances.
+ "ls -A -1 -F -b -Q | awk -v dir=%s '{print dir $1}'"
+ (shell-quote-argument default-directory))
+ nil t nil)
+ 0)
+ (goto-char (point-min))
+ (save-excursion
+ (while (re-search-forward "[*=@|/>]$" nil t)
+ ;; A line looks like /home/you/"foo"@
+ (helm-acase (match-string 0)
+ ("*" (replace-match "")
+ (put-text-property
+ (point-at-bol) (point-at-eol) 'helm-ff-exe t))
+ ("@" (replace-match "")
+ (put-text-property
+ (point-at-bol) (point-at-eol) 'helm-ff-sym t))
+ ("/" (replace-match "")
+ (put-text-property
+ (point-at-bol) (point-at-eol) 'helm-ff-dir t))
+ (("=" "|" ">") (replace-match "")))))
+ (while (re-search-forward "[\"]" nil t)
+ (replace-match ""))
+ (add-text-properties (point-min) (point-max) '(helm-ff-file t))
+ (split-string (buffer-string) "\n" t)))))
+
+(defun helm-ff-directory-files (directory)
+ "List contents of DIRECTORY.
+Argument FULL mean absolute path.
+It is same as `directory-files' but always returns the
+dotted filename '.' and '..' even on root directories in Windows
+systems."
+ (setq directory (file-name-as-directory
+ (expand-file-name directory)))
+ (let* (file-error
+ (ls (condition-case err
+ (helm-list-directory directory)
+ ;; Handle file-error from here for Windows
+ ;; because predicates like `file-readable-p' and friends
+ ;; seem broken on emacs for Windows systems (always returns t).
+ ;; This should never be called on GNU/Linux/Unix
+ ;; as the error is properly intercepted in
+ ;; `helm-find-files-get-candidates' by `file-readable-p'.
+ (file-error
+ (prog1
+ (list (format "%s:%s"
+ (car err)
+ (mapconcat 'identity (cdr err) " ")))
+ (setq file-error t)))))
+ (dot (concat directory "."))
+ (dot2 (concat directory "..")))
+ (puthash directory (+ (length ls) 2) helm-ff--directory-files-hash)
+ (append (and (not file-error) (list dot dot2)) ls)))
+
+(defun helm-ff-handle-backslash (fname)
+ ;; Allow creation of filenames containing a backslash.
+ (cl-loop with bad = '((92 . ""))
+ for i across fname
+ if (assq i bad) concat (cdr it)
+ else concat (string i)))
+
+(defun helm-ff-fuzzy-matching-p ()
+ (and helm-ff-fuzzy-matching
+ (not (memq helm-mm-matching-method '(multi1 multi3p)))))
+
+(defun helm-ff--transform-pattern-for-completion (pattern)
+ "Maybe return PATTERN with it's basename modified as a regexp.
+This happen only when `helm-ff-fuzzy-matching' is enabled.
+This provide a similar behavior as `ido-enable-flex-matching'.
+See also `helm--mapconcat-pattern'.
+If PATTERN is an url returns it unmodified.
+When PATTERN contain a space fallback to multi-match.
+If basename contain one or more space fallback to multi-match.
+If PATTERN is a valid directory name,return PATTERN unchanged."
+ ;; handle bad filenames containing a backslash (no more needed in
+ ;; emacs-26, also prevent regexp matching with e.g. "\|").
+ ;; (setq pattern (helm-ff-handle-backslash pattern))
+ (let ((bn (helm-basename pattern))
+ (bd (or (helm-basedir pattern) ""))
+ ;; Trigger tramp connection with file-directory-p.
+ (dir-p (file-directory-p pattern))
+ (tramp-p (cl-loop for (m . f) in tramp-methods
+ thereis (string-match m pattern))))
+ ;; Always regexp-quote base directory name to handle
+ ;; crap dirnames such e.g bookmark+
+ (cond
+ ((or (and dir-p tramp-p (string-match ":\\'" pattern))
+ (string= pattern "")
+ (and dir-p (<= (length bn) 2))
+ ;; Fix Issue #541 when BD have a subdir similar
+ ;; to BN, don't switch to match plugin
+ ;; which will match both.
+ (and dir-p (string-match (regexp-quote bn) bd)))
+ ;; Use full PATTERN on e.g "/ssh:host:".
+ (regexp-quote pattern))
+ ;; Prefixing BN with a space call multi-match completion.
+ ;; This allow showing all files/dirs matching BN (Issue #518).
+ ;; FIXME: some multi-match methods may not work here.
+ (dir-p (concat (regexp-quote bd) " " (regexp-quote bn)))
+ ((or (not (helm-ff-fuzzy-matching-p))
+ (string-match "\\s-" bn)) ; Fall back to multi-match.
+ (concat (regexp-quote bd) bn))
+ ((or (string-match "[*][.]?.*" bn) ; Allow entering wilcard.
+ (string-match "/$" pattern) ; Allow mkdir.
+ (string-match helm-ff-url-regexp pattern)
+ (and (string= helm-ff-default-directory "/") tramp-p))
+ ;; Don't treat wildcards ("*") as regexp char.
+ ;; (e.g ./foo/*.el => ./foo/[*].el)
+ (concat (regexp-quote bd)
+ (replace-regexp-in-string "[*]" "[*]" bn)))
+ (t (concat (regexp-quote bd)
+ (if (>= (length bn) 2) ; wait 2nd char before concating.
+ (helm--mapconcat-pattern bn)
+ (concat ".*" (regexp-quote bn))))))))
+
+(defun helm-dir-is-dot (dir)
+ (string-match "\\(?:/\\|\\`\\)\\.\\{1,2\\}\\'" dir))
+
+(defun helm-ff-save-history ()
+ "Store the last value of `helm-ff-default-directory' in `helm-ff-history'.
+Note that only existing directories are saved here."
+ (when (and helm-ff-default-directory
+ (helm-file-completion-source-p)
+ (file-directory-p helm-ff-default-directory))
+ (set-text-properties 0 (length helm-ff-default-directory)
+ nil helm-ff-default-directory)
+ (push helm-ff-default-directory helm-ff-history)))
+(add-hook 'helm-cleanup-hook 'helm-ff-save-history)
+
+(defun helm-files-save-file-name-history (&optional force)
+ "Save marked files to `file-name-history'."
+ (let* ((src (helm-get-current-source))
+ (src-name (assoc-default 'name src)))
+ (when (or force (helm-file-completion-source-p src)
+ (member src-name helm-files-save-history-extra-sources))
+ (let ((mkd (helm-marked-candidates :with-wildcard t))
+ (history-delete-duplicates t))
+ (cl-loop for sel in mkd
+ when (and sel
+ (stringp sel)
+ (file-exists-p sel)
+ (not (file-directory-p sel)))
+ do
+ ;; we use `abbreviate-file-name' here because
+ ;; other parts of Emacs seems to,
+ ;; and we don't want to introduce duplicates.
+ (add-to-history 'file-name-history
+ (abbreviate-file-name sel)))))))
+(add-hook 'helm-exit-minibuffer-hook 'helm-files-save-file-name-history)
+
+(defun helm-ff-valid-symlink-p (file)
+ (helm-aif (condition-case-unless-debug nil
+ ;; `file-truename' send error
+ ;; on cyclic symlinks (Issue #692).
+ (file-truename file)
+ (error nil))
+ (file-exists-p it)))
+
+(defun helm-get-default-mode-for-file (filename)
+ "Return the default mode to open FILENAME."
+ (let ((mode (cl-loop for (r . m) in auto-mode-alist
+ thereis (and (string-match r filename) m))))
+ (or (and (symbolp mode) mode) "Fundamental")))
+
+(defun helm-ff-properties (candidate)
+ "Show file properties of CANDIDATE in a tooltip or message."
+ (require 'helm-external) ; For `helm-get-default-program-for-file'.
+ (helm-aif (helm-file-attributes candidate)
+ (let* ((all it)
+ (dired-line (helm-file-attributes
+ candidate :dired t :human-size t))
+ (type (cl-getf all :type))
+ (mode-type (cl-getf all :mode-type))
+ (owner (cl-getf all :uid))
+ (owner-right (cl-getf all :user t))
+ (group (cl-getf all :gid))
+ (group-right (cl-getf all :group))
+ (other-right (cl-getf all :other))
+ (size (helm-file-human-size (cl-getf all :size)))
+ (modif (cl-getf all :modif-time))
+ (access (cl-getf all :access-time))
+ (ext (helm-get-default-program-for-file candidate))
+ (tooltip-hide-delay (or helm-tooltip-hide-delay tooltip-hide-delay)))
+ (if (and (display-graphic-p) tooltip-mode)
+ (tooltip-show
+ (concat
+ (helm-basename candidate) "\n"
+ dired-line "\n"
+ (format "Mode: %s\n" (helm-get-default-mode-for-file candidate))
+ (format "Ext prog: %s\n" (or (and ext (replace-regexp-in-string
+ " %s" "" ext))
+ "Not defined"))
+ (format "Type: %s: %s\n" type mode-type)
+ (when (string= type "symlink")
+ (format "True name: '%s'\n"
+ (cond ((string-match "^\.#" (helm-basename candidate))
+ "Autosave symlink")
+ ((helm-ff-valid-symlink-p candidate)
+ (file-truename candidate))
+ (t "Invalid Symlink"))))
+ (format "Owner: %s: %s\n" owner owner-right)
+ (format "Group: %s: %s\n" group group-right)
+ (format "Others: %s\n" other-right)
+ (format "Size: %s\n" size)
+ (format "Modified: %s\n" modif)
+ (format "Accessed: %s\n" access)))
+ (message dired-line) (sit-for 5)))
+ (message "Permission denied, file not readable")))
+
+(defun helm-ff-properties-persistent ()
+ "Show properties without quitting helm."
+ (interactive)
+ (with-helm-alive-p
+ (helm-attrset 'properties-action '(helm-ff-properties . never-split))
+ (helm-execute-persistent-action 'properties-action)))
+(put 'helm-ff-properties-persistent 'helm-only t)
+
+(defun helm-ff-persistent-delete ()
+ "Delete current candidate without quitting."
+ (interactive)
+ (with-helm-alive-p
+ (helm-attrset 'quick-delete '(helm-ff-quick-delete . never-split))
+ (helm-execute-persistent-action 'quick-delete)))
+(put 'helm-ff-persistent-delete 'helm-only t)
+
+(defun helm-ff-dot-file-p (file)
+ "Check if FILE is `.' or `..'."
+ (member (helm-basename file) '("." "..")))
+
+(defun helm-ff-kill-buffer-fname (candidate)
+ (let* ((buf (get-file-buffer candidate))
+ (buf-name (buffer-name buf)))
+ (cond ((and buf (eq buf (get-buffer helm-current-buffer)))
+ (user-error
+ "Can't kill `helm-current-buffer' without quitting session"))
+ (buf (kill-buffer buf) (message "Buffer `%s' killed" buf-name))
+ (t (message "No buffer to kill")))))
+
+(defun helm-ff-kill-or-find-buffer-fname (candidate)
+ "Find file CANDIDATE or kill it's buffer if it is visible.
+Never kill `helm-current-buffer'.
+Never kill buffer modified.
+This is called normally on third hit of \
+\\<helm-map>\\[helm-execute-persistent-action]
+in `helm-find-files-persistent-action-if'."
+ (let* ((buf (get-file-buffer candidate))
+ (buf-name (buffer-name buf))
+ (win (get-buffer-window buf))
+ (helm--reading-passwd-or-string t))
+ (cond ((and buf win (eq buf (get-buffer helm-current-buffer)))
+ (user-error
+ "Can't kill `helm-current-buffer' without quitting session"))
+ ((and buf win (buffer-modified-p buf))
+ (message "Can't kill modified buffer, please save it before"))
+ ((and buf win)
+ (kill-buffer buf)
+ (if (and helm-persistent-action-display-window
+ (window-dedicated-p (next-window win 1)))
+ (delete-window helm-persistent-action-display-window)
+ (set-window-buffer win helm-current-buffer))
+ (message "Buffer `%s' killed" buf-name))
+ (t (find-file candidate)))))
+
+(defun helm-ff-run-kill-buffer-persistent ()
+ "Execute `helm-ff-kill-buffer-fname' without quitting."
+ (interactive)
+ (with-helm-alive-p
+ (helm-attrset 'kill-buffer-fname 'helm-ff-kill-buffer-fname)
+ (helm-execute-persistent-action 'kill-buffer-fname)))
+(put 'helm-ff-run-kill-buffer-persistent 'helm-only t)
+
+;; Preview with external tool
+(defun helm-ff-persistent-open-file-externally (file)
+ (require 'helm-external)
+ (if (helm-get-default-program-for-file file)
+ (helm-open-file-externally file)
+ (message "Please configure an external program for `*%s' file in `helm-external-programs-associations'"
+ (file-name-extension file t))))
+
+(defun helm-ff-run-preview-file-externally ()
+ (interactive)
+ (with-helm-alive-p
+ (helm-attrset 'open-file-externally '(helm-ff-persistent-open-file-externally . never-split))
+ (helm-execute-persistent-action 'open-file-externally)))
+(put 'helm-ff-run-preview-file-externally 'helm-only t)
+
+(defun helm-ff-prefix-filename (fname &optional file-or-symlinkp new-file)
+ "Return filename FNAME maybe prefixed with [?] or [@].
+If FILE-OR-SYMLINKP is non--nil this mean we assume FNAME is an
+existing filename or valid symlink and there is no need to test it.
+NEW-FILE when non--nil mean FNAME is a non existing file and
+return FNAME prefixed with [?]."
+ (let* ((prefix-new (propertize
+ " " 'display
+ (propertize "[?]" 'face 'helm-ff-prefix)))
+ (prefix-url (propertize
+ " " 'display
+ (propertize "[@]" 'face 'helm-ff-prefix))))
+ (cond (file-or-symlinkp fname)
+ ((or (string-match helm-ff-url-regexp fname)
+ (and helm--url-regexp (string-match helm--url-regexp fname)))
+ (concat prefix-url " " fname))
+ (new-file (concat prefix-new " " fname)))))
+
+(defun helm-ff-score-candidate-for-pattern (str pattern)
+ (if (member str '("." ".."))
+ 200
+ (helm-score-candidate-for-pattern str pattern)))
+
+(defun helm-ff-sort-candidates-1 (candidates input)
+ "Sort function for `helm-source-find-files'.
+Return candidates prefixed with basename of INPUT first."
+ (if (or (and (file-directory-p input)
+ (string-match "/\\'" input))
+ (string-match "\\`\\$" input)
+ (null candidates))
+ candidates
+ (let* ((c1 (car candidates))
+ (cand1real (if (consp c1) (cdr c1) c1))
+ (cand1 (unless (file-exists-p cand1real) c1))
+ (rest-cand (if cand1 (cdr candidates) candidates))
+ (memo-src (make-hash-table :test 'equal))
+ (all (sort rest-cand
+ (lambda (s1 s2)
+ (let* ((score (lambda (str)
+ (helm-ff-score-candidate-for-pattern
+ str (helm-basename input))))
+ (bn1 (helm-basename (if (consp s1) (cdr s1) s1)))
+ (bn2 (helm-basename (if (consp s2) (cdr s2) s2)))
+ (sc1 (or (gethash bn1 memo-src)
+ (puthash bn1 (funcall score bn1) memo-src)))
+ (sc2 (or (gethash bn2 memo-src)
+ (puthash bn2 (funcall score bn2) memo-src))))
+ (cond ((= sc1 sc2)
+ (< (string-width bn1)
+ (string-width bn2)))
+ ((> sc1 sc2))))))))
+ (if cand1 (cons cand1 all) all))))
+
+(defun helm-ff-sort-candidates (candidates _source)
+ "Sort function for `helm-source-find-files'.
+Return candidates prefixed with basename of `helm-input' first."
+ (helm-ff-sort-candidates-1 candidates helm-input))
+
+(defun helm-ff-boring-file-p (file)
+ ;; Prevent user doing silly thing like
+ ;; adding the dotted files to boring regexps (#924).
+ (and (not (string-match "\\.$" file))
+ (string-match helm-ff--boring-regexp file)))
+
+(defun helm-ff-filter-candidate-one-by-one (file)
+ "`filter-one-by-one' Transformer function for `helm-source-find-files'."
+ ;; Handle boring files
+ (let ((basename (helm-basename file))
+ dot)
+ (unless (and helm-ff-skip-boring-files
+ (helm-ff-boring-file-p basename))
+
+ ;; Handle tramp files with minimal highlighting.
+ (if (and (or (string-match-p helm-tramp-file-name-regexp helm-pattern)
+ (helm-file-on-mounted-network-p helm-pattern)))
+ (let* (hostp
+ (disp (if (and helm-ff-transformer-show-only-basename
+ (not (setq dot (helm-dir-is-dot file))))
+ (or (setq hostp
+ (helm-ff--get-host-from-tramp-invalid-fname
+ file))
+ basename)
+ file)))
+ ;; Filename with cntrl chars e.g. foo^J
+ ;; This will not work as long as most tramp file handlers doesn't
+ ;; handle such case, e.g. file-name-all-completions,
+ ;; directory-files, file-name-nondirectory etc...
+ ;; Keep it though in case they fix this upstream...
+ (setq disp (replace-regexp-in-string "[[:cntrl:]]" "?" disp))
+ (cond (;; Dot directories . and ..
+ dot (propertize file 'face 'helm-ff-dotted-directory))
+ ;; Directories.
+ ((get-text-property 1 'helm-ff-dir file)
+ (cons (propertize disp 'face 'helm-ff-directory) file))
+ ;; Executable files.
+ ((get-text-property 1 'helm-ff-exe file)
+ (cons (propertize disp 'face 'helm-ff-executable) file))
+ ;; Symlinks.
+ ((get-text-property 1 'helm-ff-sym file)
+ (cons (propertize disp 'face 'helm-ff-symlink) file))
+ ;; Regular files.
+ ((get-text-property 1 'helm-ff-file file)
+ (cons (propertize disp 'face 'helm-ff-file) file))
+ ;; non existing files.
+ (t (cons (helm-ff-prefix-filename
+ (propertize disp 'face 'helm-ff-file)
+ hostp (unless hostp 'new-file))
+ file))))
+
+ ;; Highlight local files showing everything, symlinks, exe,
+ ;; dirs etc...
+ (let* ((disp (if (and helm-ff-transformer-show-only-basename
+ (not (setq dot (helm-dir-is-dot file)))
+ (not (and helm--url-regexp
+ (string-match helm--url-regexp file)))
+ (not (string-match helm-ff-url-regexp file)))
+ (or (helm-ff--get-host-from-tramp-invalid-fname file)
+ basename)
+ file))
+ (attr (file-attributes file))
+ (type (car attr))
+ x-bit)
+ ;; Filename cntrl chars e.g. foo^J
+ (setq disp (replace-regexp-in-string "[[:cntrl:]]" "?" disp))
+ (cond ((string-match "file-error" file) file)
+ (;; A dead symlink.
+ (and (stringp type)
+ (not (helm-ff-valid-symlink-p file))
+ (not (string-match "^\\.#" basename)))
+ (cons (propertize disp 'face 'helm-ff-invalid-symlink)
+ file))
+ ;; A dotted directory symlinked.
+ ((and dot (stringp type))
+ (cons (propertize disp 'face 'helm-ff-dotted-symlink-directory)
+ file))
+ ;; A dotted directory.
+ ((helm-ff-dot-file-p file)
+ (cons (propertize disp 'face 'helm-ff-dotted-directory)
+ file))
+ ;; A symlink.
+ ((stringp type)
+ (cons (propertize disp 'display
+ (concat (propertize disp 'face 'helm-ff-symlink)
+ " -> "
+ (propertize (abbreviate-file-name type)
+ 'face 'helm-ff-truename)))
+ file))
+ ;; A directory.
+ ((eq t type)
+ (cons (propertize disp 'face 'helm-ff-directory)
+ file))
+ ;; A character device file.
+ ((and attr (string-match
+ "\\`[cp]" (setq x-bit (substring (nth 8 attr) 0 4))))
+ (cons (propertize disp 'face 'helm-ff-pipe)
+ file))
+ ;; A socket file.
+ ((and attr (string-match "\\`[s]" x-bit))
+ (cons (propertize disp 'face 'helm-ff-socket)
+ file))
+ ;; An executable file.
+ ((and attr
+ (string-match
+ "x\\'" x-bit))
+ (cons (propertize disp 'face 'helm-ff-executable)
+ file))
+ ;; An executable file with suid
+ ((and attr (string-match "s\\'" x-bit))
+ (cons (propertize disp 'face 'helm-ff-suid)
+ file))
+ ;; A file.
+ ((and attr (null type))
+ (cons (propertize disp 'face 'helm-ff-file)
+ file))
+ ;; A non--existing file.
+ (t (cons (helm-ff-prefix-filename
+ (propertize disp 'face 'helm-ff-file) nil 'new-file)
+ file))))))))
+
+(defun helm-find-files-action-transformer (actions candidate)
+ "Action transformer for `helm-source-find-files'."
+ (let ((str-at-point (with-helm-current-buffer
+ (buffer-substring-no-properties
+ (point-at-bol) (point-at-eol)))))
+ (when (file-regular-p candidate)
+ (setq actions (helm-append-at-nth
+ actions '(("Checksum File" . helm-ff-checksum)) 4)))
+ (cond ((and (string-match "Trash/files/?\\'" (helm-basedir candidate))
+ (not (member (helm-basename candidate) '("." "..")))
+ (file-exists-p candidate)
+ (executable-find "trash"))
+ (helm-append-at-nth
+ actions
+ '(("Restore file(s) from trash" . helm-restore-file-from-trash)
+ ("Delete file(s) from trash" . helm-ff-trash-rm))
+ 1))
+ ((and helm--url-regexp
+ (not (string-match-p helm--url-regexp str-at-point))
+ (not (with-helm-current-buffer (eq major-mode 'dired-mode)))
+ (string-match-p ":\\([0-9]+:?\\)" str-at-point))
+ (append '(("Find file to line number" . helm-ff-goto-linum))
+ actions))
+ ((string-match (image-file-name-regexp) candidate)
+ (helm-append-at-nth
+ actions
+ '(("Rotate image right `M-r'" . helm-ff-rotate-image-right)
+ ("Rotate image left `M-l'" . helm-ff-rotate-image-left))
+ 3))
+ ((string-match "\\.el$" (helm-aif (helm-marked-candidates)
+ (car it) candidate))
+ (helm-append-at-nth
+ actions
+ '(("Byte compile lisp file(s) `M-B, C-u to load'"
+ . helm-find-files-byte-compile)
+ ("Load File(s) `M-L'" . helm-find-files-load-files))
+ 2))
+ ((and (string-match "\\.html?$" candidate)
+ (file-exists-p candidate))
+ (helm-append-at-nth
+ actions '(("Browse url file" . browse-url-of-file)) 2))
+ ((or (string= (file-name-extension candidate) "pdf")
+ (string= (file-name-extension candidate) "PDF"))
+ (helm-append-at-nth
+ actions '(("Pdfgrep File(s)" . helm-ff-pdfgrep)) 4))
+ (t actions))))
+
+(defun helm-ff-trash-action (fn names &rest args)
+ "Execute a trash action FN on marked files.
+
+Arg NAMES is a list of strings to pass to messages
+e.g. '(\"delete\" \"deleting\"), ARGS are other args to be passed to FN."
+ (let ((mkd (helm-marked-candidates))
+ errors)
+ (with-helm-display-marked-candidates
+ helm-marked-buffer-name
+ (helm-ff--count-and-collect-dups (mapcar 'helm-basename mkd))
+ (when (y-or-n-p (format "%s %s files from trash? "
+ (capitalize (car names))
+ (length mkd)))
+ (message "%s files from trash..." (capitalize (cadr names)))
+ (cl-loop for f in mkd do
+ (condition-case err
+ (apply fn f args)
+ (error (push (format "%s" (cadr err)) errors)
+ nil)))))
+ (if errors
+ (display-warning 'helm
+ (with-temp-buffer
+ (insert (format-time-string "%Y-%m-%d %H:%M:%S\n"
+ (current-time)))
+ (insert (format
+ "Failed to %s %s/%s files from trash\n"
+ (car names) (length errors) (length mkd)))
+ (insert (mapconcat 'identity errors "\n") "\n\f")
+ (buffer-string))
+ :error
+ "*helm restore warnings*")
+ (message "%s %s files from trash done"
+ (capitalize (cadr names)) (length mkd)))))
+
+(defun helm-ff-trash-rm (_candidate)
+ "Delete marked-files from a Trash directory.
+
+The Trash directory should be a directory compliant with
+<http://freedesktop.org/wiki/Specifications/trash-spec> and each file
+should have its '*.trashinfo' correspondent file in Trash/info
+directory."
+ (helm-ff-trash-action 'helm-ff-trash-rm-1 '("delete" "deleting")))
+
+(defun helm-restore-file-from-trash (_candidate)
+ "Restore marked-files from a Trash directory.
+
+The Trash directory should be a directory compliant with
+<http://freedesktop.org/wiki/Specifications/trash-spec> and each file
+should have its '*.trashinfo' correspondent file in Trash/info
+directory."
+ (let* ((default-directory (file-name-as-directory
+ helm-ff-default-directory))
+ (trashed-files (with-temp-buffer
+ (process-file "trash-list" nil t nil)
+ (split-string (buffer-string) "\n"))))
+ (helm-ff-trash-action 'helm-restore-file-from-trash-1
+ '("restore" "restoring")
+ trashed-files)))
+
+(defun helm-ff-trash-rm-1 (file)
+ (let ((info-file (concat (helm-reduce-file-name file 2)
+ "info/" (helm-basename file)
+ ".trashinfo")))
+ (cl-assert (file-exists-p file)
+ nil (format "No such file or directory `%s'"
+ file))
+ (cl-assert (file-exists-p info-file)
+ nil (format "No such file or directory `%s'"
+ info-file))
+ (delete-file file)
+ (delete-file info-file)))
+
+(defun helm-restore-file-from-trash-1 (file trashed-files)
+ "Restore FILE from a trash directory.
+Arg TRASHED-FILES is the list of files in the trash directory obtained
+with 'trash-list' command."
+ (let ((info-file (concat (helm-reduce-file-name file 2)
+ "info/"
+ (helm-basename file)
+ ".trashinfo"))
+ (dest-file (helm-ff--get-dest-file-from-trash
+ trashed-files file)))
+ (cl-assert (not (file-exists-p dest-file)) nil
+ (format "File `%s' already exists" dest-file))
+ (cl-assert dest-file nil "No such file in trash")
+ (rename-file file dest-file)
+ (delete-file info-file)))
+
+(defun helm-ff--get-dest-file-from-trash (trashed-files file)
+ (cl-loop for f in trashed-files
+ when (string-match
+ (concat (regexp-quote (helm-basename file))
+ "\\'")
+ f)
+ return
+ (replace-regexp-in-string
+ "\\`\\([0-9]\\{2,4\\}[-:][0-9]\\{2\\}[:-][0-9]\\{2\\} \\)\\{2\\}"
+ "" f)))
+
+(defun helm-ff-goto-linum (candidate)
+ "Find file CANDIDATE and maybe jump to line number found in fname at point.
+line number should be added at end of fname preceded with \":\".
+e.g \"foo:12\"."
+ (let ((linum (with-helm-current-buffer
+ (let ((str (buffer-substring-no-properties
+ (point-at-bol) (point-at-eol))))
+ (when (string-match ":\\([0-9]+:?\\)" str)
+ (match-string 1 str))))))
+ (find-file candidate)
+ (and linum (not (string= linum ""))
+ (helm-goto-line (string-to-number linum) t))))
+
+(defun helm-ff-mail-attach-files (_candidate)
+ "Run `mml-attach-file' on `helm-marked-candidates'."
+ (require 'mml)
+ (let ((flist (helm-marked-candidates :with-wildcard t))
+ (dest-buf (and (derived-mode-p 'message-mode 'mail-mode)
+ (current-buffer)))
+ bufs)
+ (unless dest-buf
+ (setq bufs (cl-loop for b in (buffer-list)
+ when (with-current-buffer b
+ (derived-mode-p 'message-mode 'mail-mode))
+ collect (buffer-name b)))
+ (if (and bufs (y-or-n-p "Attach files to existing mail composition buffer? "))
+ (setq dest-buf
+ (if (cdr bufs)
+ (helm-comp-read "Attach to buffer: " bufs :nomark t)
+ (car bufs)))
+ (compose-mail)
+ (setq dest-buf (current-buffer))))
+ (switch-to-buffer dest-buf)
+ (save-restriction
+ (widen)
+ (save-excursion
+ (goto-char (point-max))
+ (cl-loop for f in flist
+ do (mml-attach-file f (or (mm-default-file-encoding f)
+ "application/octet-stream")))))))
+
+(defvar image-dired-display-image-buffer)
+(defun helm-ff-rotate-current-image-1 (file &optional num-arg)
+ "Rotate current image at NUM-ARG degrees.
+This is a destructive operation on FILE made by external tool mogrify."
+ (setq file (file-truename file)) ; For symlinked images.
+ ;; When FILE is not an image-file, do nothing.
+ (when (string-match (image-file-name-regexp) file)
+ (if (executable-find "mogrify")
+ (progn
+ (shell-command (format "mogrify -rotate %s %s"
+ (or num-arg 90)
+ (shell-quote-argument file)))
+ (when (buffer-live-p image-dired-display-image-buffer)
+ (kill-buffer image-dired-display-image-buffer))
+ (image-dired-display-image file)
+ (message nil)
+ (display-buffer (get-buffer image-dired-display-image-buffer)))
+ (error "mogrify not found"))))
+
+(defun helm-ff-rotate-image-left (candidate)
+ "Rotate image file CANDIDATE left.
+This affect directly file CANDIDATE."
+ (helm-ff-rotate-current-image-1 candidate -90))
+
+(defun helm-ff-rotate-image-right (candidate)
+ "Rotate image file CANDIDATE right.
+This affect directly file CANDIDATE."
+ (helm-ff-rotate-current-image-1 candidate))
+
+(defun helm-ff-rotate-left-persistent ()
+ "Rotate image left without quitting helm."
+ (interactive)
+ (with-helm-alive-p
+ (helm-attrset 'image-action1 'helm-ff-rotate-image-left)
+ (helm-execute-persistent-action 'image-action1)))
+(put 'helm-ff-rotate-left-persistent 'helm-only t)
+
+(defun helm-ff-rotate-right-persistent ()
+ "Rotate image right without quitting helm."
+ (interactive)
+ (with-helm-alive-p
+ (helm-attrset 'image-action2 'helm-ff-rotate-image-right)
+ (helm-execute-persistent-action 'image-action2)))
+(put 'helm-ff-rotate-right-persistent 'helm-only t)
+
+(defun helm-ff-exif-data (candidate)
+ "Extract exif data from file CANDIDATE using `helm-ff-exif-data-program'."
+ (if (and helm-ff-exif-data-program
+ (executable-find helm-ff-exif-data-program))
+ (shell-command-to-string (format "%s %s %s"
+ helm-ff-exif-data-program
+ helm-ff-exif-data-program-args
+ candidate))
+ (format "No program %s found to extract exif"
+ helm-ff-exif-data-program)))
+
+(cl-defun helm-find-files-persistent-action-if (candidate)
+ "Open subtree CANDIDATE without quitting helm.
+If CANDIDATE is not a directory expand CANDIDATE filename.
+If CANDIDATE is alone, open file CANDIDATE filename.
+That's mean:
+First hit on C-j expand CANDIDATE second hit open file.
+If a prefix arg is given or `helm-follow-mode' is on open file."
+ (let* ((follow (or (helm-follow-mode-p)
+ helm--temp-follow-flag))
+ (image-cand (string-match-p (image-file-name-regexp) candidate))
+ (new-pattern (helm-get-selection))
+ (num-lines-buf (with-current-buffer helm-buffer
+ (count-lines (point-min) (point-max))))
+ (insert-in-minibuffer (lambda (fname)
+ (with-selected-window (or (active-minibuffer-window)
+ (minibuffer-window))
+ (unless follow
+ (delete-minibuffer-contents)
+ (set-text-properties 0 (length fname)
+ nil fname)
+ (insert fname))))))
+ (helm-attrset 'candidate-number-limit helm-ff-candidate-number-limit)
+ (unless image-cand
+ (when follow
+ (helm-follow-mode -1)
+ (cl-return-from helm-find-files-persistent-action-if
+ (message "Helm-follow-mode allowed only on images, disabling"))))
+ (cond ((and (helm-ff--invalid-tramp-name-p)
+ (string-match helm-tramp-file-name-regexp candidate))
+ (cons (lambda (_candidate)
+ ;; First hit insert hostname and
+ ;; second hit insert ":" and expand.
+ (if (string= candidate helm-pattern)
+ (funcall insert-in-minibuffer (concat candidate ":"))
+ (funcall insert-in-minibuffer candidate)))
+ 'never-split))
+ (;; A symlink directory, expand it but not to its truename
+ ;; unless a prefix arg is given.
+ (and (file-directory-p candidate) (file-symlink-p candidate))
+ (cons (lambda (_candidate)
+ (funcall insert-in-minibuffer
+ (file-name-as-directory
+ (if current-prefix-arg
+ (file-truename (expand-file-name candidate))
+ (expand-file-name candidate)))))
+ 'never-split))
+ ;; A directory, open it.
+ ((file-directory-p candidate)
+ (cons (lambda (_candidate)
+ (when (string= (helm-basename candidate) "..")
+ (setq helm-ff-last-expanded helm-ff-default-directory))
+ (funcall insert-in-minibuffer (file-name-as-directory
+ (expand-file-name candidate))))
+ 'never-split))
+ ;; A symlink file, expand to it's true name. (first hit)
+ ((and (file-symlink-p candidate) (not current-prefix-arg) (not follow))
+ (cons (lambda (_candidate)
+ (funcall insert-in-minibuffer (file-truename candidate)))
+ 'never-split))
+ ;; A regular file, expand it, (first hit)
+ ((and (>= num-lines-buf 3) (not current-prefix-arg) (not follow))
+ (cons (lambda (_candidate)
+ (setq helm-pattern "") ; Force update.
+ (funcall insert-in-minibuffer new-pattern))
+ 'never-split))
+ ;; An image file and it is the second hit on C-j,
+ ;; show the file in `image-dired'.
+ (image-cand
+ (lambda (_candidate)
+ (require 'image-dired)
+ (let* ((win (get-buffer-window
+ image-dired-display-image-buffer 'visible))
+ (fname (and win
+ (with-selected-window win
+ (get-text-property (point-min)
+ 'original-file-name))))
+ (remove-buf-only (and win
+ fname
+ (with-helm-buffer
+ (file-equal-p candidate fname)))))
+ (when remove-buf-only
+ (with-helm-window
+ (if (and helm-persistent-action-display-window
+ (window-dedicated-p (next-window win 1)))
+ (delete-window helm-persistent-action-display-window)
+ (set-window-buffer win helm-current-buffer))))
+ (when (buffer-live-p (get-buffer image-dired-display-image-buffer))
+ (kill-buffer image-dired-display-image-buffer))
+ (unless remove-buf-only
+ ;; Fix emacs bug never fixed upstream.
+ (unless (file-directory-p image-dired-dir)
+ (make-directory image-dired-dir))
+ (switch-to-buffer image-dired-display-image-buffer)
+ (message "Resizing image...")
+ (cl-letf (((symbol-function 'message) #'ignore))
+ (image-dired-display-image candidate))
+ (message "Resizing image done")
+ (with-current-buffer image-dired-display-image-buffer
+ (let ((exif-data (helm-ff-exif-data candidate)))
+ (setq default-directory helm-ff-default-directory)
+ (image-dired-update-property 'help-echo exif-data)))))))
+ ;; Allow browsing archive on avfs fs.
+ ;; Assume volume is already mounted with mountavfs.
+ ((helm-aand helm-ff-avfs-directory
+ (file-name-directory candidate)
+ (string-match
+ (regexp-quote (expand-file-name helm-ff-avfs-directory))
+ it)
+ (helm-ff-file-compressed-p candidate))
+ (cons (lambda (_candidate)
+ (funcall insert-in-minibuffer (concat candidate "#/")))
+ 'never-split))
+ ;; File doesn't exists and basename starts with ".." or " ",
+ ;; Start a recursive search for directories.
+ ((and (not (file-exists-p candidate))
+ (not (file-remote-p candidate))
+ (string-match-p "\\`\\([.]\\|\\s-\\)\\{2\\}[^/]+"
+ (helm-basename candidate)))
+ ;; As soon as the final "/" is added the job is passed
+ ;; to `helm-ff-auto-expand-to-home-or-root'.
+ (cons (lambda (_candidate)
+ (funcall insert-in-minibuffer (concat candidate "/")))
+ 'never-split))
+ ;; File is not existing and have no basedir, typically when
+ ;; user hit C-k (minibuffer is empty) and then write foo and
+ ;; hit C-j. This make clear that when no basedir, helm will
+ ;; create the file in default-directory.
+ ((and (not (file-exists-p candidate))
+ (not (helm-basedir candidate)))
+ (cons (lambda (_candidate)
+ (funcall insert-in-minibuffer
+ (expand-file-name candidate default-directory)))
+ 'never-split))
+ ;; On second hit we open file.
+ ;; On Third hit we kill it's buffer maybe.
+ (t
+ (lambda (_candidate)
+ (funcall helm-ff-kill-or-find-buffer-fname-fn candidate))))))
+
+\f
+;;; Recursive dirs completion
+;;
+(defun helm-find-files-recursive-dirs (directory &optional input)
+ (when (string-match "\\(\\s-+\\|[.]\\)\\{2\\}" input)
+ (setq input (replace-match "" nil t input)))
+ (message "Recursively searching %s from %s ..."
+ input (abbreviate-file-name directory))
+ ;; Ensure to not create a new frame
+ (let (helm-actions-inherit-frame-settings)
+ (helm :sources
+ (helm-make-source
+ "Recursive directories" 'helm-locate-subdirs-source
+ :basedir (if (string-match-p
+ "\\`es" helm-locate-recursive-dirs-command)
+ directory
+ (shell-quote-argument directory))
+ :subdir (shell-quote-argument input)
+ :candidate-transformer
+ `((lambda (candidates)
+ (cl-loop for c in candidates
+ when (and (file-directory-p c)
+ (null (helm-boring-directory-p
+ c helm-boring-file-regexp-list))
+ (string-match-p ,(regexp-quote input)
+ (helm-basename c)))
+ collect (propertize c 'face 'helm-ff-dirs)))
+ helm-w32-pathname-transformer
+ (lambda (candidates)
+ (helm-ff-sort-candidates-1 candidates ,input)))
+ :persistent-action 'ignore
+ :action (lambda (c)
+ (helm-set-pattern
+ (file-name-as-directory (expand-file-name c)))))
+ :candidate-number-limit 999999
+ :allow-nest t
+ :resume 'noresume
+ :ff-transformer-show-only-basename nil
+ :buffer "*helm recursive dirs*")))
+
+(defun helm-ff-recursive-dirs (_candidate)
+ "Launch a recursive search in `helm-ff-default-directory'."
+ (with-helm-default-directory helm-ff-default-directory
+ (helm-find-files-recursive-dirs
+ (helm-current-directory)
+ (helm-basename (helm-get-selection)))))
+
+(defun helm-ff-file-compressed-p (candidate)
+ "Whether CANDIDATE is a compressed file or not."
+ (member (file-name-extension candidate)
+ helm-ff-file-compressed-list))
+
+(defun helm-ff--fname-at-point ()
+ "Try to guess fname at point."
+ (let ((end (point))
+ (limit (helm-aif (bounds-of-thing-at-point 'filename)
+ (car it)
+ (point))))
+ (save-excursion
+ (while (re-search-backward "\\(~\\|/\\|[[:lower:][:upper:]]:/\\)"
+ limit t))
+ (buffer-substring-no-properties (point) end))))
+
+(defun helm-insert-file-name-completion-at-point (_candidate)
+ "Insert file name completion at point.
+
+When completing i.e. there is already something at point, insert
+filename abbreviated, relative or full according to initial input,
+whereas when inserting i.e. there is nothing at point, insert filename
+full, abbreviated or relative according to prefix arg, respectively no
+prefix arg, one prefix arg or two prefix arg."
+ (with-helm-current-buffer
+ (if buffer-read-only
+ (error "Error: Buffer `%s' is read-only" (buffer-name))
+ (let* ((mkds (helm-marked-candidates :with-wildcard t))
+ (candidate (car mkds))
+ (end (point))
+ (tap (helm-ff--fname-at-point))
+ (guess (and (stringp tap)
+ (substring-no-properties tap)))
+ (beg (if guess (- (point) (length guess)) (point)))
+ (full-path-p (and (stringp guess)
+ (or (string-match-p
+ (concat "^" (getenv "HOME"))
+ guess)
+ (string-match-p
+ "\\`\\(/\\|[[:lower:][:upper:]]:/\\)"
+ guess))))
+ (escape-fn (with-helm-current-buffer
+ (if (memq major-mode
+ helm-modes-using-escaped-strings)
+ #'shell-quote-argument #'identity))))
+ (insert
+ (funcall escape-fn (helm-ff--insert-fname
+ candidate beg end full-path-p guess))
+ (if (cdr mkds) " " "")
+ (mapconcat escape-fn
+ (cl-loop for f in (cdr mkds)
+ collect (helm-ff--insert-fname f))
+ " "))))))
+
+(defun helm-ff--insert-fname (candidate &optional beg end full-path guess)
+ (set-text-properties 0 (length candidate) nil candidate)
+ (if (and beg end guess (not (string= guess ""))
+ (or (string-match
+ "^\\(~/\\|/\\|[[:lower:][:upper:]]:/\\)"
+ guess)
+ (file-exists-p candidate)))
+ (prog1
+ (cond (full-path
+ (expand-file-name candidate))
+ ((string= (match-string 1 guess) "~/")
+ (abbreviate-file-name candidate))
+ (t (file-relative-name candidate)))
+ (delete-region beg end))
+ (cond ((equal helm-current-prefix-arg '(4))
+ (abbreviate-file-name candidate))
+ ((equal helm-current-prefix-arg '(16))
+ (file-relative-name candidate))
+ (t candidate))))
+
+(cl-defun helm-find-files-history (arg &key (comp-read t))
+ "The `helm-find-files' history.
+Show the first `helm-ff-history-max-length' elements of
+`helm-ff-history' in an `helm-comp-read'."
+ (interactive "p")
+ (let ((history (when helm-ff-history
+ (helm-fast-remove-dups helm-ff-history
+ :test 'equal))))
+ (when history
+ (setq helm-ff-history
+ (if (>= (length history) helm-ff-history-max-length)
+ (cl-subseq history 0 helm-ff-history-max-length)
+ history))
+ (if comp-read
+ (let ((src (helm-build-sync-source "Helm Find Files History"
+ :candidates helm-ff-history
+ :fuzzy-match (helm-ff-fuzzy-matching-p)
+ :persistent-action 'ignore
+ :migemo t
+ :action (lambda (candidate)
+ (if arg
+ (helm-set-pattern
+ (expand-file-name candidate))
+ (identity candidate))))))
+ (helm :sources src
+ :resume 'noresume
+ :buffer helm-ff-history-buffer-name
+ :allow-nest t))
+ helm-ff-history))))
+(put 'helm-find-files-history 'helm-only t)
+
+(defun helm-find-files-1 (fname &optional preselect)
+ "Find FNAME filename with PRESELECT filename preselected.
+
+Use it for non--interactive calls of `helm-find-files'."
+ (require 'tramp)
+ ;; Resolve FNAME now outside of helm.
+ ;; [FIXME] When `helm-find-files-1' is used directly from lisp
+ ;; and FNAME is an abbreviated path, for some reasons
+ ;; `helm-update' is called many times before resolving
+ ;; the abbreviated path (Issue #1939) so be sure to pass a
+ ;; full path to helm-find-files-1.
+ (unless (string-match-p helm-ff-url-regexp fname)
+ (setq fname (expand-file-name (substitute-in-file-name fname))))
+ (when (get-buffer helm-action-buffer)
+ (kill-buffer helm-action-buffer))
+ (setq helm-find-files--toggle-bookmark nil)
+ (let* ( ;; Be sure we don't erase the precedent minibuffer if some.
+ (helm-ff-auto-update-initial-value
+ (and helm-ff-auto-update-initial-value
+ (not (minibuffer-window-active-p (minibuffer-window)))))
+ (tap (thing-at-point 'filename))
+ (def (and tap (or (file-remote-p tap)
+ (expand-file-name tap)))))
+ (helm-set-local-variable 'helm-follow-mode-persistent nil)
+ (unless helm-source-find-files
+ (setq helm-source-find-files (helm-make-source
+ "Find Files" 'helm-source-ffiles)))
+ (when (helm-attr 'follow helm-source-find-files)
+ (helm-attrset 'follow -1 helm-source-find-files))
+ (helm-ff-setup-update-hook)
+ (add-hook 'helm-resume-after-hook 'helm-ff--update-resume-after-hook)
+ (unwind-protect
+ (helm :sources 'helm-source-find-files
+ :input fname
+ :case-fold-search helm-file-name-case-fold-search
+ :preselect preselect
+ :ff-transformer-show-only-basename
+ helm-ff-transformer-show-only-basename
+ :default def
+ :prompt "Find files or url: "
+ :buffer "*helm find files*")
+ (helm-ff--update-resume-after-hook nil t)
+ (setq helm-ff-default-directory nil))))
+
+(defun helm-ff--update-resume-after-hook (sources &optional nohook)
+ "Meant to be used in `helm-resume-after-hook'.
+When NOHOOK is non nil run inconditionally, otherwise only when source
+is helm-source-find-files."
+ (when (or nohook (string= "Find Files"
+ (assoc-default 'name (car sources))))
+ (helm-attrset 'resume `(lambda ()
+ (helm-ff-setup-update-hook)
+ (setq helm-ff-default-directory
+ ,helm-ff-default-directory
+ helm-ff-last-expanded
+ ,helm-ff-last-expanded))
+ helm-source-find-files)))
+
+(defun helm-ff-clean-initial-input ()
+ ;; When using hff in an external frame initial input is printed in
+ ;; the minibuffer of initial-frame, delete it.
+ (with-selected-frame helm-initial-frame
+ (helm-clean-up-minibuffer)))
+
+(defun helm-ff-setup-update-hook ()
+ (dolist (hook '(helm-ff-clean-initial-input ; Add to be called first.
+ helm-ff-move-to-first-real-candidate
+ helm-ff-update-when-only-one-matched
+ helm-ff-auto-expand-to-home-or-root))
+ (add-hook 'helm-after-update-hook hook)))
+
+(defun helm-find-files-cleanup ()
+ (mapc (lambda (hook)
+ (remove-hook 'helm-after-update-hook hook))
+ '(helm-ff-auto-expand-to-home-or-root
+ helm-ff-update-when-only-one-matched
+ helm-ff-move-to-first-real-candidate
+ helm-ff-clean-initial-input)))
+
+(defun helm-find-files-toggle-to-bookmark ()
+ "Toggle helm-bookmark for `helm-find-files' and `helm-find-files.'"
+ (interactive)
+ (require 'helm-bookmark)
+ (with-helm-alive-p
+ (with-helm-buffer
+ (if (setq helm-find-files--toggle-bookmark
+ (not helm-find-files--toggle-bookmark))
+ (progn
+ (helm-set-pattern "" t)
+ (helm-set-sources '(helm-source-bookmark-helm-find-files)))
+ ;; Switch back to helm-find-files.
+ (helm-set-pattern "./" t) ; Back to initial directory of hff session.
+ (helm-set-sources '(helm-source-find-files))
+ (helm--maybe-update-keymap)))))
+(put 'helm-find-files-toggle-to-bookmark 'helm-only t)
+
+(defun helm-find-files-initial-input (&optional input)
+ "Return INPUT if present, otherwise try to guess it."
+ (unless (eq major-mode 'image-mode)
+ (or (and input (or (and (file-remote-p input) input)
+ (expand-file-name input)))
+ (helm-find-files-input
+ (helm-ffap-guesser)
+ (thing-at-point 'filename)))))
+
+(defun helm-ffap-guesser ()
+ "Same as `ffap-guesser' but without gopher and machine support."
+ (require 'ffap)
+ ;; Avoid "Stack overflow in regexp matcher" error
+ ;; in evil `ffap-guesser' by removing crap `ffap-gopher-at-point'
+ ;; (bug fixed in emacs-26 #25391) .
+ ;; `ffap-machine-at-point' have been removed too as it was anyway
+ ;; disabled with `ffap-machine-p-known' bound to 'reject.
+ ;; `ffap-file-at-point' can be neutralized with
+ ;; `helm-ff-guess-ffap-filenames' and `ffap-url-at-point' with
+ ;; `helm-ff-guess-ffap-urls'
+ ;; Note also that `ffap-url-unwrap-remote' can override these
+ ;; variables.
+ (let ((ffap-alist (and helm-ff-guess-ffap-filenames ffap-alist))
+ (ffap-url-regexp helm--url-regexp))
+ (if (eq major-mode 'dired-mode)
+ (let ((beg (save-excursion (dired-move-to-filename)))
+ (end (save-excursion (dired-move-to-end-of-filename t))))
+ (helm-aif (and beg end (member (buffer-substring beg end)
+ '("." "..")))
+ (concat (file-name-as-directory
+ (expand-file-name dired-directory))
+ (car it))
+ (dired-get-filename 'no-dir t)))
+ (let* ((beg (and (use-region-p) (region-beginning)))
+ (end (and (use-region-p) (region-end)))
+ (str (and beg end (buffer-substring-no-properties beg end)))
+ (ffap (or (and helm-ff-guess-ffap-urls ffap-url-regexp
+ (ffap-fixup-url (ffap-url-at-point)))
+ (ffap-file-at-point))))
+ ;; Workaround emacs bugs:
+ ;; When the region is active and a file is detected
+ ;; `ffap-string-at-point' returns the region prefixed with
+ ;; "/", e.g. at a beginning of a patch (first bug) and make
+ ;; `file-remote-p' returning an error (second bug), so in such
+ ;; case returns the region itself instead of the region
+ ;; corrupted by ffap.
+ (if (and str ffap) str ffap)))))
+
+(defun helm-find-files-input (file-at-pt thing-at-pt)
+ "Try to guess a default input for `helm-find-files'."
+ (let* ((non-essential t)
+ (remp (or (and file-at-pt (file-remote-p file-at-pt))
+ (and thing-at-pt (file-remote-p thing-at-pt))))
+ (def-dir (helm-current-directory))
+ (urlp (and file-at-pt helm--url-regexp
+ (string-match helm--url-regexp file-at-pt)))
+ (lib (when helm-ff-search-library-in-sexp
+ (helm-find-library-at-point)))
+ (hlink (helm-ff-find-url-at-point))
+ (file-p (and file-at-pt
+ (not (string= file-at-pt ""))
+ (not remp)
+ (file-exists-p file-at-pt)
+ thing-at-pt
+ (not (string= thing-at-pt ""))
+ (file-exists-p
+ (file-name-directory
+ (expand-file-name thing-at-pt def-dir))))))
+ (cond (lib) ; e.g we are inside a require sexp.
+ (hlink) ; String at point is an hyperlink.
+ (file-p ; a regular file
+ (and file-at-pt (if (not (member (helm-basename file-at-pt)
+ '("." "..")))
+ (expand-file-name file-at-pt)
+ file-at-pt)))
+ (urlp (helm-html-decode-entities-string file-at-pt)) ; possibly an url or email.
+ ((and file-at-pt
+ (not remp)
+ (file-exists-p file-at-pt))
+ (expand-file-name file-at-pt)))))
+
+(defun helm-ff-find-url-at-point ()
+ "Try to find link to an url in text-property at point."
+ (let* ((he (get-text-property (point) 'help-echo))
+ (ov (overlays-at (point)))
+ (ov-he (and ov (overlay-get
+ (car (overlays-at (point))) 'help-echo)))
+ (w3m-l (get-text-property (point) 'w3m-href-anchor))
+ (nt-prop (get-text-property (point) 'nt-link)))
+ ;; Org link.
+ (when (and (stringp he) (string-match "^LINK: " he))
+ (setq he (replace-match "" t t he)))
+ (cl-loop for i in (list he ov-he w3m-l nt-prop)
+ thereis (and (stringp i) helm--url-regexp (string-match helm--url-regexp i) i))))
+
+(defun helm-find-library-at-point ()
+ "Try to find library path at point.
+Find inside `require' and `declare-function' sexp."
+ (require 'find-func)
+ (let* ((beg-sexp (save-excursion (search-backward "(" (point-at-bol) t)))
+ (end-sexp (save-excursion (search-forward ")" (point-at-eol) t)))
+ (sexp (and beg-sexp end-sexp
+ (buffer-substring-no-properties
+ (1+ beg-sexp) (1- end-sexp)))))
+ (ignore-errors
+ (cond ((and sexp (string-match "require \'.+[^)]" sexp))
+ (find-library-name
+ (replace-regexp-in-string
+ "'\\|\)\\|\(" ""
+ ;; If require use third arg, ignore it,
+ ;; always use library path found in `load-path'.
+ (cl-second (split-string (match-string 0 sexp))))))
+ ((and sexp (string-match-p "^declare-function" sexp))
+ (find-library-name
+ (replace-regexp-in-string
+ "\"\\|ext:" ""
+ (cl-third (split-string sexp)))))
+ (t nil)))))
+
+\f
+;;; Handle copy, rename, symlink, relsymlink and hardlink from helm.
+;;
+;;
+(defun helm-ff--valid-default-directory ()
+ (with-helm-current-buffer
+ (cl-loop for b in (buffer-list)
+ for cd = (with-current-buffer b default-directory)
+ when (eq (car (file-attributes cd)) t)
+ return cd)))
+
+(cl-defun helm-dired-action (candidate
+ &key action follow (files (dired-get-marked-files)))
+ "Execute ACTION on FILES to CANDIDATE.
+Where ACTION is a symbol that can be one of:
+'copy, 'rename, 'symlink,'relsymlink, 'hardlink or 'backup.
+Argument FOLLOW when non--nil specify to follow FILES to destination for the actions
+copy and rename."
+ (require 'dired-async)
+ (require 'dired-x) ; For dired-keep-marker-relsymlink
+ (when (get-buffer dired-log-buffer) (kill-buffer dired-log-buffer))
+ ;; When default-directory in current-buffer is an invalid directory,
+ ;; (e.g buffer-file directory have been renamed somewhere else)
+ ;; be sure to use a valid value to give to dired-create-file.
+ ;; i.e start-process is creating a process buffer based on default-directory.
+ (let ((default-directory (helm-ff--valid-default-directory))
+ (fn (cl-case action
+ (copy 'dired-copy-file)
+ (rename 'dired-rename-file)
+ (symlink 'make-symbolic-link)
+ (relsymlink 'dired-make-relative-symlink)
+ (hardlink 'dired-hardlink)
+ (backup 'backup-file)))
+ (marker (cl-case action
+ ((copy rename backup) dired-keep-marker-copy)
+ (symlink dired-keep-marker-symlink)
+ (relsymlink dired-keep-marker-relsymlink)
+ (hardlink dired-keep-marker-hardlink)))
+ (dirflag (and (= (length files) 1)
+ (file-directory-p (car files))
+ (not (file-directory-p candidate))))
+ (dired-async-state (if (and (boundp 'dired-async-mode)
+ dired-async-mode)
+ 1 -1)))
+ (and follow (fboundp 'dired-async-mode) (dired-async-mode -1))
+ (when (and (cdr files) (not (file-directory-p candidate)))
+ (error "%s: target `%s' is not a directory" action candidate))
+ (unwind-protect
+ (dired-create-files
+ fn (symbol-name action) files
+ ;; CANDIDATE is the destination.
+ (if (file-directory-p candidate)
+ ;; When CANDIDATE is a directory, build file-name in this directory.
+ ;; Else we use CANDIDATE.
+ (lambda (from)
+ (expand-file-name (file-name-nondirectory from) candidate))
+ (lambda (_from) candidate))
+ marker)
+ (and (fboundp 'dired-async-mode)
+ (dired-async-mode dired-async-state)))
+ (push (file-name-as-directory
+ (if (file-directory-p candidate)
+ (expand-file-name candidate)
+ (file-name-directory candidate)))
+ helm-ff-history)
+ ;; If follow is non--nil we should not be in async mode.
+ (when (and follow
+ (not (memq action '(symlink relsymlink hardlink)))
+ (not (get-buffer dired-log-buffer)))
+ (let ((target (directory-file-name candidate)))
+ (unwind-protect
+ (progn
+ (setq helm-ff-cand-to-mark
+ (helm-get-dest-fnames-from-list files candidate dirflag))
+ (with-helm-after-update-hook (helm-ff-maybe-mark-candidates))
+ (if (and dirflag (eq action 'rename))
+ (helm-find-files-1 (file-name-directory target)
+ (if helm-ff-transformer-show-only-basename
+ (helm-basename target) target))
+ (helm-find-files-1 (file-name-as-directory
+ (expand-file-name candidate)))))
+ (setq helm-ff-cand-to-mark nil))))))
+
+(defun helm-get-dest-fnames-from-list (flist dest-cand rename-dir-flag)
+ "Transform filenames of FLIST to abs of DEST-CAND.
+If RENAME-DIR-FLAG is non--nil collect the `directory-file-name' of transformed
+members of FLIST."
+ ;; At this point files have been renamed/copied at destination.
+ ;; That's mean DEST-CAND exists.
+ (cl-loop
+ with dest = (expand-file-name dest-cand)
+ for src in flist
+ for basename-src = (helm-basename src)
+ for fname = (cond (rename-dir-flag (directory-file-name dest))
+ ((file-directory-p dest)
+ (concat (file-name-as-directory dest) basename-src))
+ (t dest))
+ when (file-exists-p fname)
+ collect fname into tmp-list
+ finally return (sort tmp-list 'string<)))
+
+(defun helm-ff-maybe-mark-candidates ()
+ "Mark all candidates of list `helm-ff-cand-to-mark'.
+This is used when copying/renaming/symlinking etc... and
+following files to destination."
+ (when (and (string= (assoc-default 'name (helm-get-current-source))
+ (assoc-default 'name helm-source-find-files))
+ helm-ff-cand-to-mark)
+ (with-helm-window
+ (while helm-ff-cand-to-mark
+ (if (string= (car helm-ff-cand-to-mark) (helm-get-selection))
+ (progn
+ (helm-make-visible-mark)
+ (helm-next-line)
+ (setq helm-ff-cand-to-mark (cdr helm-ff-cand-to-mark)))
+ (helm-next-line)))
+ (unless (helm-this-visible-mark)
+ (helm-prev-visible-mark)))))
+
+\f
+;;; Routines for files
+;;
+;;
+(defun helm-file-buffers (filename)
+ "Returns a list of buffer names corresponding to FILENAME."
+ (cl-loop with name = (expand-file-name filename)
+ for buf in (buffer-list)
+ for bfn = (buffer-file-name buf)
+ when (and bfn (string= name bfn))
+ collect (buffer-name buf)))
+
+(defun helm-ff--delete-by-moving-to-trash (file)
+ "Decide to trash or delete FILE.
+Returns non-nil when FILE needs to be trashed."
+ (let ((remote (file-remote-p file)))
+ (or
+ (and delete-by-moving-to-trash
+ (null helm-current-prefix-arg)
+ (null current-prefix-arg)
+ (or (and remote helm-trash-remote-files)
+ (null remote)))
+ (and (null delete-by-moving-to-trash)
+ (or helm-current-prefix-arg
+ current-prefix-arg)
+ (or (and remote helm-trash-remote-files)
+ (null remote))))))
+
+(defun helm-ff-quick-delete (_candidate)
+ "Delete file CANDIDATE without quitting.
+
+When a prefix arg is given, meaning of `delete-by-moving-to-trash' is
+inversed."
+ (with-helm-window
+ (let ((marked (helm-marked-candidates)))
+ (unwind-protect
+ (cl-loop with trash = (helm-ff--delete-by-moving-to-trash (car marked))
+ for c in marked do
+ (progn (helm-preselect
+ (concat "^" (regexp-quote
+ (if (and helm-ff-transformer-show-only-basename
+ (not (helm-ff-dot-file-p c)))
+ (helm-basename c) c))))
+ (when (y-or-n-p
+ (format "Really %s file `%s'? "
+ (if trash "Trash" "Delete")
+ (abbreviate-file-name c)))
+ (helm-delete-file
+ c helm-ff-signal-error-on-dot-files 'synchro trash)
+ (helm-delete-current-selection)
+ (message nil)
+ (helm--remove-marked-and-update-mode-line c))))
+ (setq helm-marked-candidates nil
+ helm-visible-mark-overlays nil)
+ (helm-force-update
+ (let ((presel (helm-get-selection)))
+ (concat "^" (regexp-quote (if (and helm-ff-transformer-show-only-basename
+ (not (helm-ff-dot-file-p presel)))
+ (helm-basename presel) presel)))))))))
+
+(defun helm-delete-file (file &optional error-if-dot-file-p synchro trash)
+ "Delete FILE after querying the user.
+
+When a prefix arg is given, meaning of `delete-by-moving-to-trash' is
+inversed.
+
+Return error when ERROR-IF-DOT-FILE-P is non nil and user tries to
+delete a dotted file i.e. \".\" or \"..\".
+
+Ask user when directory are not empty to allow recursive deletion
+unless `helm-ff-allow-recursive-deletes' is non nil.
+When user is asked and reply with \"!\" don't ask for remaining
+directories.
+
+Ask to kill buffers associated with that file, too.
+
+When TRASH is non nil, trash FILE even if `delete-by-moving-to-trash'
+is nil."
+ (require 'dired)
+ (cl-block nil
+ (when (and error-if-dot-file-p
+ (helm-ff-dot-file-p file))
+ (error "Error: Cannot operate on `.' or `..'"))
+ (let ((buffers (helm-file-buffers file))
+ (helm--reading-passwd-or-string t)
+ (file-attrs (file-attributes file))
+ (trash (or trash (helm-ff--delete-by-moving-to-trash file)))
+ (delete-by-moving-to-trash trash))
+ (cond ((and (eq (nth 0 file-attrs) t)
+ (directory-files file t dired-re-no-dot))
+ ;; Synchro means persistent deletion from HFF.
+ (if synchro
+ (when (or helm-ff-allow-recursive-deletes
+ trash
+ (y-or-n-p (format "Recursive delete of `%s'? "
+ (abbreviate-file-name file))))
+ (delete-directory file 'recursive trash))
+ ;; Avoid using dired-delete-file really annoying in
+ ;; emacs-26 but allows using ! (instead of all) to not
+ ;; confirm anymore for recursive deletion of
+ ;; directory. This is not persistent for all session
+ ;; like emacs-26 does with dired-delete-file (think it
+ ;; is a bug).
+ (if (or helm-ff-allow-recursive-deletes trash)
+ (delete-directory file 'recursive trash)
+ (helm-acase (helm-read-answer (format "Recursive delete of `%s'? [y,n,!,q]"
+ (abbreviate-file-name file))
+ '("y" "n" "!" "q"))
+ ("y" (delete-directory file 'recursive trash))
+ ("!" (setq helm-ff-allow-recursive-deletes t)
+ (delete-directory file 'recursive trash))
+ ("n" (cl-return 'skip))
+ ("q" (throw 'helm-abort-delete-file
+ (progn
+ (message "Abort file deletion") (sleep-for 1))))))))
+ ((eq (nth 0 file-attrs) t)
+ (delete-directory file nil trash))
+ (t (delete-file file trash)))
+ (when buffers
+ (cl-dolist (buf buffers)
+ (when (y-or-n-p (format "Kill buffer %s, too? " buf))
+ (kill-buffer buf)))))))
+
+(defun helm-delete-marked-files (_ignore)
+ "Delete marked files with `helm-delete-file'.
+
+When a prefix arg is given, meaning of `delete-by-moving-to-trash' is
+inversed."
+ (let* ((files (helm-marked-candidates :with-wildcard t))
+ (len 0)
+ (trash (helm-ff--delete-by-moving-to-trash (car files)))
+ (prmt (if trash "Trash" "Delete"))
+ (old--allow-recursive-deletes helm-ff-allow-recursive-deletes))
+ (with-helm-display-marked-candidates
+ helm-marked-buffer-name
+ (helm-ff--count-and-collect-dups files)
+ (if (not (y-or-n-p (format "%s *%s File(s)" prmt (length files))))
+ (message "(No deletions performed)")
+ (catch 'helm-abort-delete-file
+ (unwind-protect
+ (cl-dolist (i files)
+ (set-text-properties 0 (length i) nil i)
+ (let ((res (helm-delete-file
+ i helm-ff-signal-error-on-dot-files nil trash)))
+ (if (eq res 'skip)
+ (progn (message "Directory is not empty, skipping")
+ (sleep-for 1))
+ (cl-incf len))))
+ (setq helm-ff-allow-recursive-deletes old--allow-recursive-deletes)))
+ (message "%s File(s) %s" len (if trash "trashed" "deleted"))))))
+
+;;; Delete files async
+;;
+;;
+(defvar helm-ff-delete-log-file
+ (expand-file-name "helm-delete-file.log" user-emacs-directory)
+ "The file use to communicate with emacs child when deleting files async.")
+
+(defvar helm-ff--trash-flag nil)
+
+(define-minor-mode helm-ff--delete-async-modeline-mode
+ "Notify mode-line that an async process run."
+ :group 'dired-async
+ :global t
+ ;; FIXME: Handle jobs like in dired-async, needs first to allow
+ ;; naming properly processes in async, they are actually all named
+ ;; emacs and running `async-batch-invoke', so if one copy a file and
+ ;; delete another file at the same time it may clash.
+ :lighter (:eval (propertize (format " %s file(s) async ..."
+ (if helm-ff--trash-flag
+ "Trashing" "Deleting"))
+ 'face 'helm-delete-async-message))
+ (unless helm-ff--delete-async-modeline-mode
+ (let ((visible-bell t)) (ding))
+ (setq helm-ff--trash-flag nil)))
+
+(defun helm-delete-async-mode-line-message (text face &rest args)
+ "Notify end of async operation in `mode-line'."
+ (message nil)
+ (let ((mode-line-format (concat
+ " " (propertize
+ (if args
+ (apply #'format text args)
+ text)
+ 'face face))))
+ (force-mode-line-update)
+ (sit-for 3)
+ (force-mode-line-update)))
+
+(defun helm-delete-marked-files-async (_ignore)
+ "Same as `helm-delete-marked-files' but async.
+
+When a prefix arg is given, meaning of `delete-by-moving-to-trash' is
+inversed.
+
+This function is not using `helm-delete-file' and BTW not asking user
+for recursive deletion of directory, be warned that directories are
+always deleted with no warnings."
+ (let* ((files (helm-marked-candidates :with-wildcard t))
+ (trash (helm-ff--delete-by-moving-to-trash (car files)))
+ (prmt (if trash "Trash" "Delete"))
+ (buffers (cl-loop for file in files
+ for buf = (helm-file-buffers file)
+ when buf append buf))
+ (callback (lambda (result)
+ (helm-ff--delete-async-modeline-mode -1)
+ (when (file-exists-p helm-ff-delete-log-file)
+ (display-warning 'helm
+ (with-temp-buffer
+ (insert-file-contents
+ helm-ff-delete-log-file)
+ (buffer-string))
+ :error
+ "*helm delete files*")
+ (fit-window-to-buffer (get-buffer-window
+ "*helm delete files*"))
+ (delete-file helm-ff-delete-log-file))
+ (when buffers
+ (dolist (buf buffers)
+ (let ((last-nonmenu-event t))
+ (when (y-or-n-p (format "Kill buffer %s, too? " buf))
+ (kill-buffer buf)))))
+ (run-with-timer
+ 0.1 nil
+ (lambda ()
+ (helm-delete-async-mode-line-message
+ "%s (%s/%s) file(s) async done"
+ 'helm-delete-async-message
+ (if trash "Trashing" "Deleting")
+ result (length files))))))
+ ;; Workaround emacs-26 bug with tramp see
+ ;; https://github.com/jwiegley/emacs-async/issues/80.
+ (async-quiet-switch "-q"))
+ (setq helm-ff--trash-flag trash)
+ (with-helm-display-marked-candidates
+ helm-marked-buffer-name
+ (helm-ff--count-and-collect-dups files)
+ (if (not (y-or-n-p (format "%s *%s File(s)" prmt (length files))))
+ (message "(No deletions performed)")
+ (async-start
+ `(lambda ()
+ ;; `delete-by-moving-to-trash' have to be set globally,
+ ;; using the TRASH argument of delete-file or
+ ;; delete-directory is not enough.
+ (setq delete-by-moving-to-trash ,trash)
+ (let ((result 0))
+ (dolist (file ',files result)
+ (condition-case err
+ (cond ((eq (nth 0 (file-attributes file)) t)
+ (delete-directory file 'recursive ,trash)
+ (setq result (1+ result)))
+ (t (delete-file file ,trash)
+ (setq result (1+ result))))
+ (error (with-temp-file ,helm-ff-delete-log-file
+ (insert (format-time-string "%x:%H:%M:%S\n"))
+ (insert (format "%s:%s\n\f"
+ (car err)
+ (mapconcat 'identity (cdr err) " ")))))))))
+ callback)
+ (helm-ff--delete-async-modeline-mode 1)))))
+
+(defun helm-find-file-or-marked (candidate)
+ "Open file CANDIDATE or open helm marked files in separate windows.
+Called with one prefix arg open files in separate windows in a
+vertical split.
+Called with two prefix arg open files in background without selecting them."
+ (let ((marked (helm-marked-candidates :with-wildcard t))
+ (url-p (and helm--url-regexp ; we should have only one candidate.
+ (string-match helm--url-regexp candidate)))
+ (ffap-newfile-prompt helm-ff-newfile-prompt-p)
+ (find-file-wildcards nil)
+ (helm--reading-passwd-or-string t))
+ (if (cdr marked)
+ (if (equal helm-current-prefix-arg '(16))
+ (mapcar 'find-file-noselect marked)
+ ;; If helm-current-prefix-arg is detected split is done
+ ;; vertically.
+ (helm-window-show-buffers (mapcar 'find-file-noselect marked)))
+ (let ((dir (and (not url-p) (helm-basedir candidate))))
+ (cond ((and dir (file-directory-p dir))
+ (find-file (substitute-in-file-name candidate)))
+ (url-p (find-file-at-point candidate))
+ ;; A a non--existing filename ending with /
+ ;; Create a directory and jump to it.
+ ((and (not (file-exists-p candidate))
+ (string-match "/$" candidate))
+ (helm-ff--mkdir candidate 'helm-ff))
+ ;; A non--existing filename NOT ending with / or
+ ;; an existing filename, create or jump to it.
+ ;; If the basedir of candidate doesn't exists,
+ ;; ask for creating it.
+ (dir
+ (helm-ff--mkdir dir)
+ (find-file candidate))
+ ;; Find file at `default-directory' when basedir is
+ ;; unspecified e.g user hit C-k foo RET.
+ (t (find-file candidate)))))))
+
+(defun helm-ff--mkdir (dir &optional helm-ff)
+ (when (or (not confirm-nonexistent-file-or-buffer)
+ (y-or-n-p (format "Create directory `%s'? "
+ (abbreviate-file-name
+ (expand-file-name dir)))))
+ (let ((dirfname (directory-file-name dir)))
+ (if (file-exists-p dirfname)
+ (error
+ "Mkdir: Unable to create directory `%s': file exists."
+ (helm-basename dirfname))
+ (make-directory dir 'parent)))
+ (when helm-ff
+ ;; Allow having this new dir in history
+ ;; to be able to retrieve it immediately
+ ;; if we want to e.g copy a file from somewhere in it.
+ (setq helm-ff-default-directory
+ (file-name-as-directory (expand-file-name dir)))
+ (push helm-ff-default-directory helm-ff-history))
+ (or (and helm-ff (helm-find-files-1 dir)) t)))
+
+(defun helm-transform-file-load-el (actions candidate)
+ "Add action to load the file CANDIDATE if it is an emacs lisp
+file. Else return ACTIONS unmodified."
+ (if (member (file-name-extension candidate) '("el" "elc"))
+ (append actions '(("Load Emacs Lisp File" . load-file)))
+ actions))
+
+(defun helm-transform-file-browse-url (actions candidate)
+ "Add an action to browse the file CANDIDATE if it is a html file or URL.
+Else return ACTIONS unmodified."
+ (let ((browse-action '("Browse with Browser" . browse-url)))
+ (cond ((string-match "^http\\|^ftp" candidate)
+ (cons browse-action actions))
+ ((string-match "\\.html?$" candidate)
+ (append actions (list browse-action)))
+ (t actions))))
+
+(defun helm-file-on-mounted-network-p (file)
+ "Returns non-nil when FILE is part of a mounted remote directory.
+
+This function is checking `helm-mounted-network-directories' list."
+ (when helm-mounted-network-directories
+ (cl-loop for dir in helm-mounted-network-directories
+ thereis (file-in-directory-p file dir))))
+
+;; helm-find-files bindings for filecache
+(defvar file-cache-alist)
+
+(defun helm-ff-cache-add-file (_candidate)
+ (require 'filecache)
+ (let ((mkd (helm-marked-candidates :with-wildcard t)))
+ (mapc 'file-cache-add-file mkd)))
+
+(defun helm-ff-file-cache-remove-file-1 (file)
+ "Remove FILE from `file-cache-alist'."
+ (let ((entry (assoc (helm-basename file) file-cache-alist))
+ (dir (helm-basedir file))
+ new-entry)
+ (setq new-entry (remove dir entry))
+ (when (= (length entry) 1)
+ (setq new-entry nil))
+ (setq file-cache-alist
+ (cons new-entry (remove entry file-cache-alist)))))
+
+(defun helm-ff-file-cache-remove-file (_file)
+ "Remove marked files from `file-cache-alist.'"
+ (let ((mkd (helm-marked-candidates)))
+ (mapc 'helm-ff-file-cache-remove-file-1 mkd)))
+
+\f
+;;; File name history
+;;
+;;
+(defvar helm-source-file-name-history
+ (helm-build-sync-source "File Name History"
+ :candidates 'file-name-history
+ :persistent-action #'ignore
+ :filtered-candidate-transformer #'helm-file-name-history-transformer
+ :action 'helm-type-file-actions))
+
+(defvar helm-source--ff-file-name-history nil
+ "[Internal] This source is build to be used with `helm-find-files'.
+Don't use it in your own code unless you know what you are doing.")
+
+(defun helm-file-name-history-transformer (candidates _source)
+ (cl-loop for c in candidates collect
+ (cond ((or (file-remote-p c)
+ (and (fboundp 'tramp-archive-file-name-p)
+ (tramp-archive-file-name-p c)))
+ (cons (propertize c 'face 'helm-history-remote) c))
+ ((file-exists-p c)
+ (cons (propertize c 'face 'helm-ff-file) c))
+ (t (cons (propertize c 'face 'helm-history-deleted) c)))))
+
+(defun helm-ff-file-name-history ()
+ "Switch to `file-name-history' without quitting `helm-find-files'."
+ (interactive)
+ (unless helm-source--ff-file-name-history
+ (setq helm-source--ff-file-name-history
+ (helm-build-sync-source "File name history"
+ :init (lambda ()
+ (with-helm-alive-p
+ (require 'tramp-archive nil t)
+ (when helm-ff-file-name-history-use-recentf
+ (require 'recentf)
+ (or recentf-mode (recentf-mode 1)))))
+ :candidates (lambda ()
+ (if helm-ff-file-name-history-use-recentf
+ recentf-list
+ file-name-history))
+ :fuzzy-match t
+ :persistent-action 'ignore
+ :migemo t
+ :filtered-candidate-transformer 'helm-file-name-history-transformer
+ :action (helm-make-actions
+ "Find file" (lambda (candidate)
+ (helm-set-pattern
+ (expand-file-name candidate))
+ (with-helm-after-update-hook (helm-exit-minibuffer)))
+ "Find file in helm" (lambda (candidate)
+ (helm-set-pattern
+ (expand-file-name candidate)))))))
+ (with-helm-alive-p
+ (helm :sources 'helm-source--ff-file-name-history
+ :buffer "*helm-file-name-history*"
+ :allow-nest t
+ :resume 'noresume)))
+(put 'helm-ff-file-name-history 'helm-only t)
+\f
+;;; Browse project
+;; Need dependencies:
+;; <https://github.com/emacs-helm/helm-ls-git>
+;; <https://github.com/emacs-helm/helm-ls-hg>
+;; Only hg and git are supported for now.
+(defvar helm--browse-project-cache (make-hash-table :test 'equal))
+(defvar helm-buffers-in-project-p)
+
+(defun helm-browse-project-get-buffers (root-directory)
+ (cl-loop for b in (helm-buffer-list)
+ ;; FIXME: Why default-directory is root-directory
+ ;; for current-buffer when coming from helm-quit-and-find-file.
+ for cd = (with-current-buffer b default-directory)
+ for bn = (buffer-file-name (get-buffer b))
+ if (or (and bn (file-in-directory-p bn root-directory))
+ (and (null bn)
+ (not (file-remote-p cd))
+ (file-in-directory-p cd root-directory)))
+ collect b))
+
+(defun helm-browse-project-build-buffers-source (directory)
+ (helm-make-source "Buffers in project" 'helm-source-buffers
+ :header-name (lambda (name)
+ (format
+ "%s (%s)"
+ name (abbreviate-file-name directory)))
+ :buffer-list (lambda () (helm-browse-project-get-buffers directory))))
+
+(defun helm-browse-project-walk-directory (directory)
+ "Default function for `helm-browse-project-default-find-files-fn'."
+ (helm-walk-directory
+ directory
+ :directories nil :path 'full :skip-subdirs t))
+
+(defun helm-browse-project-ag-find-files (directory)
+ "A suitable function for `helm-browse-project-default-find-files-fn'.
+
+Needs AG as backend."
+ (with-temp-buffer
+ (call-process-shell-command
+ (format "ag --hidden -g '.*' %s" directory)
+ nil t nil)
+ (mapcar (lambda (f) (expand-file-name f directory))
+ (split-string (buffer-string) "\n"))))
+
+(defun helm-browse-project-find-files (directory &optional refresh)
+ (when refresh (remhash directory helm--browse-project-cache))
+ (unless (gethash directory helm--browse-project-cache)
+ (puthash directory (funcall helm-browse-project-default-find-files-fn
+ directory)
+ helm--browse-project-cache))
+ (helm :sources `(,(helm-browse-project-build-buffers-source directory)
+ ,(helm-build-in-buffer-source "Browse project"
+ :data (gethash directory helm--browse-project-cache)
+ :header-name (lambda (name)
+ (format
+ "%s (%s)"
+ name (abbreviate-file-name directory)))
+ :match-part (lambda (c)
+ (if (with-helm-buffer
+ helm-ff-transformer-show-only-basename)
+ (helm-basename c) c))
+ :filter-one-by-one
+ (lambda (c)
+ (if (with-helm-buffer
+ helm-ff-transformer-show-only-basename)
+ (cons (propertize (helm-basename c)
+ 'face 'helm-ff-file)
+ c)
+ (propertize c 'face 'helm-ff-file)))
+ :keymap helm-generic-files-map
+ :action 'helm-type-file-actions))
+ :ff-transformer-show-only-basename nil
+ :buffer "*helm browse project*"))
+
+(defvar helm-browse-project-history nil)
+
+;;;###autoload
+(defun helm-projects-history ()
+ (interactive)
+ (helm :sources
+ (helm-build-sync-source "Project history"
+ :candidates helm-browse-project-history
+ :action (lambda (candidate)
+ (with-helm-default-directory candidate
+ (helm-browse-project nil))))
+ :buffer "*helm browse project history*"))
+
+;;;###autoload
+(defun helm-browse-project (arg)
+ "Preconfigured helm to browse projects.
+Browse files and see status of project with its vcs.
+Only HG and GIT are supported for now.
+Fall back to `helm-browse-project-find-files'
+if current directory is not under control of one of those vcs.
+With a prefix ARG browse files recursively, with two prefix ARG
+rebuild the cache.
+If the current directory is found in the cache, start
+`helm-browse-project-find-files' even with no prefix ARG.
+NOTE: The prefix ARG have no effect on the VCS controlled directories.
+
+Needed dependencies for VCS:
+<https://github.com/emacs-helm/helm-ls-git>
+and
+<https://github.com/emacs-helm/helm-ls-hg>."
+ (interactive "P")
+ (let ((helm-type-buffer-actions
+ (remove (assoc "Browse project from buffer"
+ helm-type-buffer-actions)
+ helm-type-buffer-actions))
+ (helm-buffers-in-project-p t))
+ (cl-flet ((push-to-hist (root)
+ (setq helm-browse-project-history
+ (cons root (delete root helm-browse-project-history)))))
+ (helm-acond ((and (require 'helm-ls-git nil t)
+ (fboundp 'helm-ls-git-root-dir)
+ (helm-ls-git-root-dir))
+ (push-to-hist it)
+ (helm-ls-git-ls))
+ ((and (require 'helm-ls-hg nil t)
+ (fboundp 'helm-hg-root)
+ (helm-hg-root))
+ (push-to-hist it)
+ (helm-hg-find-files-in-project))
+ ((helm-browse-project-get--root-dir (helm-current-directory))
+ (if (or arg (gethash it helm--browse-project-cache))
+ (progn
+ (push-to-hist it)
+ (helm-browse-project-find-files it (equal arg '(16))))
+ (helm :sources (helm-browse-project-build-buffers-source it)
+ :buffer "*helm browse project*")))))))
+
+(defun helm-browse-project-get--root-dir (directory)
+ (cl-loop with dname = (file-name-as-directory directory)
+ while (and dname (not (gethash dname helm--browse-project-cache)))
+ if (file-remote-p dname)
+ do (setq dname nil) else
+ do (setq dname (helm-basedir (substring dname 0 (1- (length dname)))))
+ finally return (or dname (file-name-as-directory directory))))
+
+(defun helm-ff-browse-project (_candidate)
+ "Browse project in current directory.
+See `helm-browse-project'."
+ (with-helm-default-directory helm-ff-default-directory
+ (helm-browse-project helm-current-prefix-arg)))
+
+(defun helm-ff-run-browse-project ()
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-ff-browse-project)))
+(put 'helm-ff-run-browse-project 'helm-only t)
+
+(defun helm-ff-gid (_candidate)
+ (with-helm-default-directory helm-ff-default-directory
+ (helm-gid)))
+
+(defun helm-ff-run-gid ()
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-ff-gid)))
+(put 'helm-ff-run-gid 'helm-only t)
+
+;; helm-find bindings for helm-find-files.
+(defun helm-ff-find-sh-command (_candidate)
+ "Run `helm-find' from `helm-find-files'."
+ (require 'helm-find)
+ (helm-find-1 helm-ff-default-directory))
+
+(defun helm-ff-run-find-sh-command ()
+ "Run find shell command action with key from `helm-find-files'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-ff-find-sh-command)))
+(put 'helm-ff-run-find-sh-command 'helm-only t)
+
+\f
+;;;###autoload
+(defun helm-find-files (arg)
+ "Preconfigured `helm' for helm implementation of `find-file'.
+Called with a prefix arg show history if some.
+Don't call it from programs, use `helm-find-files-1' instead.
+This is the starting point for nearly all actions you can do on files."
+ (interactive "P")
+ (let* ((hist (and arg helm-ff-history (helm-find-files-history nil)))
+ (smart-input (or hist (helm-find-files-initial-input)))
+ (default-input (expand-file-name (helm-current-directory)))
+ (input (cond ((and (null hist)
+ helm-find-files-ignore-thing-at-point)
+ default-input)
+ ((and (eq major-mode 'org-agenda-mode)
+ org-directory
+ (not smart-input))
+ (expand-file-name org-directory))
+ ((and (eq major-mode 'dired-mode) smart-input)
+ (file-name-directory smart-input))
+ ((and (not (string= smart-input ""))
+ smart-input))
+ (t default-input)))
+ (input-as-presel (null (nth 0 (file-attributes input))))
+ (presel (helm-aif (or hist
+ (and input-as-presel input)
+ (buffer-file-name (current-buffer))
+ (and (eq major-mode 'dired-mode)
+ smart-input))
+ (if (and helm-ff-transformer-show-only-basename
+ (null hist)
+ (not (string-match-p "[.]\\{1,2\\}\\'" it)))
+ (helm-basename it) it))))
+ ;; Continue using the same display function as history which used
+ ;; probably itself the same display function as inner HFF call,
+ ;; i.e. if history was using frame use a frame otherwise use a window.
+ (when (and hist (buffer-live-p (get-buffer helm-ff-history-buffer-name)))
+ (helm-set-local-variable 'helm-display-function
+ (with-current-buffer helm-ff-history-buffer-name
+ helm-display-function)
+ 'helm--last-frame-parameters
+ (with-current-buffer helm-ff-history-buffer-name
+ helm--last-frame-parameters)))
+ (set-text-properties 0 (length input) nil input)
+ (setq current-prefix-arg nil)
+ ;; Allow next helm session to reuse helm--last-frame-parameters as
+ ;; resume would do.
+ (let ((helm--executing-helm-action (not (null hist))))
+ (helm-find-files-1 input (and presel (null helm-ff-no-preselect)
+ (concat "^" (regexp-quote presel)))))))
+
+;;;###autoload
+(defun helm-delete-tramp-connection ()
+ "Allow deleting tramp connection or marked tramp connections at once.
+
+This replace `tramp-cleanup-connection' which is partially broken in
+emacs < to 25.1.50.1 (See Emacs Bug#24432).
+
+It allows additionally to delete more than one connection at once."
+ (interactive)
+ (let ((helm-quit-if-no-candidate
+ (lambda ()
+ (message "No Tramp connection found"))))
+ (helm :sources (helm-build-sync-source "Tramp connections"
+ :candidates (tramp-list-connections)
+ :candidate-transformer (lambda (candidates)
+ (cl-loop for v in candidates
+ for name = (apply #'tramp-make-tramp-file-name
+ (cl-loop with v = (helm-ff--tramp-cons-or-vector v)
+ for i across v collect i))
+ when (or (processp (tramp-get-connection-process v))
+ (buffer-live-p (get-buffer (tramp-buffer-name v))))
+ collect (cons name v)))
+ :action (lambda (_vec)
+ (let ((vecs (helm-marked-candidates)))
+ (cl-loop for v in vecs
+ do (progn
+ (tramp-cleanup-connection v)
+ (remhash v tramp-cache-data))))))
+ :buffer "*helm tramp connections*")))
+
+
+(provide 'helm-files)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-files.el ends here
--- /dev/null
+;;; helm-find.el --- helm interface for find command. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Code:
+
+(require 'helm-files)
+(require 'helm-external)
+
+(defcustom helm-findutils-skip-boring-files t
+ "Ignore boring files in find command results."
+ :group 'helm-files
+ :type 'boolean)
+
+(defcustom helm-findutils-search-full-path nil
+ "Search in full path with shell command find when non--nil.
+I.e use the -path/ipath arguments of find instead of -name/iname."
+ :group 'helm-files
+ :type 'boolean)
+
+(defvar helm-source-findutils
+ (helm-build-async-source "Find"
+ :header-name (lambda (name)
+ (concat name " in [" (helm-default-directory) "]"))
+ :candidates-process 'helm-find-shell-command-fn
+ :filtered-candidate-transformer 'helm-findutils-transformer
+ :action-transformer 'helm-transform-file-load-el
+ :persistent-action 'helm-ff-kill-or-find-buffer-fname
+ :action 'helm-type-file-actions
+ :keymap helm-generic-files-map
+ :candidate-number-limit 9999
+ :requires-pattern 3))
+
+(defun helm-findutils-transformer (candidates _source)
+ (let (non-essential
+ (default-directory (helm-default-directory)))
+ (cl-loop for i in candidates
+ for abs = (expand-file-name
+ (helm-aif (file-remote-p default-directory)
+ (concat it i) i))
+ for type = (car (file-attributes abs))
+ for disp = (if (and helm-ff-transformer-show-only-basename
+ (not (string-match "[.]\\{1,2\\}$" i)))
+ (helm-basename abs) abs)
+ collect (cond ((eq t type)
+ (cons (propertize disp 'face 'helm-ff-directory)
+ abs))
+ ((stringp type)
+ (cons (propertize disp 'face 'helm-ff-symlink)
+ abs))
+ (t (cons (propertize disp 'face 'helm-ff-file)
+ abs))))))
+
+(defun helm-find--build-cmd-line ()
+ (require 'find-cmd)
+ (let* ((default-directory (or (file-remote-p default-directory 'localname)
+ default-directory))
+ (patterns+options (split-string helm-pattern "\\(\\`\\| +\\)\\* +"))
+ (fold-case (helm-set-case-fold-search (car patterns+options)))
+ (patterns (split-string (car patterns+options)))
+ (additional-options (and (cdr patterns+options)
+ (list (concat (cadr patterns+options) " "))))
+ (ignored-dirs ())
+ (ignored-files (when helm-findutils-skip-boring-files
+ (cl-loop for f in completion-ignored-extensions
+ if (string-match "/$" f)
+ do (push (replace-match "" nil t f)
+ ignored-dirs)
+ else collect (concat "*" f))))
+ (path-or-name (if helm-findutils-search-full-path
+ '(ipath path) '(iname name)))
+ (name-or-iname (if fold-case
+ (car path-or-name) (cadr path-or-name))))
+ (find-cmd (and ignored-dirs
+ `(prune (name ,@ignored-dirs)))
+ (and ignored-files
+ `(not (name ,@ignored-files)))
+ `(and ,@(mapcar
+ (lambda (pattern)
+ `(,name-or-iname ,(concat "*" pattern "*")))
+ patterns)
+ ,@additional-options))))
+
+(defun helm-find-shell-command-fn ()
+ "Asynchronously fetch candidates for `helm-find'.
+Additional find options can be specified after a \"*\"
+separator."
+ (let* (process-connection-type
+ non-essential
+ (cmd (helm-find--build-cmd-line))
+ (proc (start-file-process-shell-command "hfind" helm-buffer cmd)))
+ (helm-log "Find command:\n%s" cmd)
+ (prog1 proc
+ (set-process-sentinel
+ proc
+ (lambda (process event)
+ (helm-process-deferred-sentinel-hook
+ process event (helm-default-directory))
+ (if (string= event "finished\n")
+ (with-helm-window
+ (setq mode-line-format
+ '(" " mode-line-buffer-identification " "
+ (:eval (format "L%s" (helm-candidate-number-at-point))) " "
+ (:eval (propertize
+ (format "[Find process finished - (%s results)]"
+ (max (1- (count-lines
+ (point-min) (point-max)))
+ 0))
+ 'face 'helm-locate-finish))))
+ (force-mode-line-update))
+ (helm-log "Error: Find %s"
+ (replace-regexp-in-string "\n" "" event))))))))
+
+(defun helm-find-1 (dir)
+ (let ((default-directory (file-name-as-directory dir)))
+ (helm :sources 'helm-source-findutils
+ :buffer "*helm find*"
+ :ff-transformer-show-only-basename nil
+ :case-fold-search helm-file-name-case-fold-search)))
+
+\f
+;;; Preconfigured commands
+;;
+;;
+;;;###autoload
+(defun helm-find (arg)
+ "Preconfigured `helm' for the find shell command.
+
+Recursively find files whose names are matched by all specified
+globbing PATTERNs under the current directory using the external
+program specified in `find-program' (usually \"find\"). Every
+input PATTERN is silently wrapped into two stars: *PATTERN*.
+
+With prefix argument, prompt for a directory to search.
+
+When user option `helm-findutils-search-full-path' is non-nil,
+match against complete paths, otherwise, against file names
+without directory part.
+
+The (possibly empty) list of globbing PATTERNs can be followed by
+the separator \"*\" plus any number of additional arguments that
+are passed to \"find\" literally."
+ (interactive "P")
+ (let ((directory
+ (if arg
+ (file-name-as-directory
+ (read-directory-name "DefaultDirectory: "))
+ default-directory)))
+ (helm-find-1 directory)))
+
+(provide 'helm-find)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-find.el ends here
--- /dev/null
+;;; helm-font --- Font and ucs selection for Helm -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'helm)
+(require 'helm-help)
+
+\f
+(defgroup helm-font nil
+ "Related applications to display fonts in helm."
+ :group 'helm)
+
+(defcustom helm-ucs-recent-size 10
+ "Number of recent chars to keep."
+ :type 'integer
+ :group 'helm-font)
+
+(defcustom helm-ucs-actions
+ '(("Insert character" . helm-ucs-insert-char)
+ ("Insert character name" . helm-ucs-insert-name)
+ ("Insert character code in hex" . helm-ucs-insert-code)
+ ("Kill marked characters" . helm-ucs-kill-char)
+ ("Kill name" . helm-ucs-kill-name)
+ ("Kill code" . helm-ucs-kill-code))
+ "Actions for `helm-source-ucs'."
+ :group 'helm-font
+ :type '(alist :key-type string :value-type function))
+
+(defvar helm-ucs-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map helm-map)
+ (define-key map (kbd "<C-backspace>") 'helm-ucs-persistent-delete)
+ (define-key map (kbd "<C-left>") 'helm-ucs-persistent-backward)
+ (define-key map (kbd "<C-right>") 'helm-ucs-persistent-forward)
+ (define-key map (kbd "C-c SPC") 'helm-ucs-persistent-insert-space)
+ map)
+ "Keymap for `helm-ucs'.")
+
+(defface helm-ucs-char
+ '((((class color) (background dark)) (:foreground "Gold")))
+ "Face used to display ucs characters."
+ :group 'helm-font)
+\f
+;;; Xfont selection
+;;
+;;
+(defvar helm-xfonts-cache nil)
+(defvar helm-previous-font nil)
+(defvar helm-source-xfonts
+ (helm-build-sync-source "X Fonts"
+ :init (lambda ()
+ (unless helm-xfonts-cache
+ (setq helm-xfonts-cache
+ (x-list-fonts "*")))
+ ;; Save current font so it can be restored in cleanup
+ (setq helm-previous-font (cdr (assq 'font (frame-parameters)))))
+ :candidates 'helm-xfonts-cache
+ :action '(("Copy font to kill ring" . (lambda (elm)
+ (kill-new elm)))
+ ("Set font" . (lambda (elm)
+ (kill-new elm)
+ (set-frame-font elm 'keep-size)
+ (message "Font copied to kill ring"))))
+ :cleanup (lambda ()
+ ;; Restore previous font
+ (set-frame-font helm-previous-font 'keep-size))
+ :persistent-action (lambda (new-font)
+ (set-frame-font new-font 'keep-size)
+ (kill-new new-font))
+ :persistent-help "Preview font and copy to kill-ring"))
+
+\f
+;;; 𝕌𝕔𝕤 𝕊𝕪𝕞𝕓𝕠𝕝 𝕔𝕠𝕞𝕡𝕝𝕖𝕥𝕚𝕠𝕟
+;;
+;;
+(defvar helm-ucs--max-len nil)
+(defvar helm-ucs--names nil)
+(defvar helm-ucs-history nil)
+(defvar helm-ucs-recent nil
+ "Ring of recent `helm-ucs' selections.")
+
+(defun helm-calculate-ucs-alist-max-len (names)
+ "Calculate the length of the longest NAMES list candidate."
+ (cl-loop for (_n . v) in names
+ maximize (length (format "#x%x:" v)) into code
+ maximize (max 1 (string-width (format "%c" v))) into char
+ finally return (cons code char)))
+
+(defun helm-calculate-ucs-hash-table-max-len (names)
+ "Calculate the length of the longest NAMES hash table candidate."
+ (cl-loop for _n being the hash-keys of names
+ using (hash-values v)
+ maximize (length (format "#x%x:" v)) into code
+ maximize (max 1 (string-width (format "%c" v))) into char
+ finally return (cons code char)))
+
+(defun helm-calculate-ucs-max-len ()
+ "Calculate the length of longest `ucs-names' candidate."
+ (let ((ucs-struct (ucs-names)))
+ (if (hash-table-p ucs-struct)
+ (helm-calculate-ucs-hash-table-max-len ucs-struct)
+ (helm-calculate-ucs-alist-max-len ucs-struct))))
+
+(defun helm-ucs-collect-symbols-alist (names)
+ "Collect ucs symbols from the NAMES list."
+ (cl-loop with pr = (make-progress-reporter
+ "collecting ucs names"
+ 0 (length names))
+ for (n . v) in names
+ for count from 1
+ for xcode = (format "#x%x:" v)
+ for len = (length xcode)
+ for diff = (- (car helm-ucs--max-len) len)
+ for code = (format "(#x%x): " v)
+ for char = (propertize (format "%c" v)
+ 'face 'helm-ucs-char)
+ unless (or (string= "" n)
+ ;; `char-displayable-p' return a font object or
+ ;; t for some char that are displayable but have
+ ;; no special font (e.g 10) so filter out char
+ ;; with no font.
+ (not (fontp (char-displayable-p (read xcode)))))
+ collect
+ (concat code (make-string diff ? )
+ char " " n)
+ and do (progress-reporter-update pr count)))
+
+(defun helm-ucs-collect-symbols-hash-table (names)
+ "Collect ucs symbols from the NAMES hash-table."
+ (cl-loop with pr = (make-progress-reporter
+ "collecting ucs names"
+ 0 (hash-table-count names))
+ for n being the hash-keys of names
+ using (hash-values v)
+ for count from 1
+ for xcode = (format "#x%x:" v)
+ for len = (length xcode)
+ for diff = (- (car helm-ucs--max-len) len)
+ for code = (format "(#x%x): " v)
+ for char = (propertize (format "%c" v)
+ 'face 'helm-ucs-char)
+ unless (or (string= "" n)
+ (not (fontp (char-displayable-p (read xcode)))))
+ collect
+ (concat code (make-string diff ? )
+ char " " n)
+ and do (progress-reporter-update pr count)))
+
+(defun helm-ucs-collect-symbols (ucs-struct)
+ "Collect ucs symbols from UCS-STRUCT.
+
+Depending on the Emacs version, the variable `ucs-names' can
+either be an alist or a hash-table."
+ (if (hash-table-p ucs-struct)
+ (helm-ucs-collect-symbols-hash-table ucs-struct)
+ (helm-ucs-collect-symbols-alist ucs-struct)))
+
+(defun helm-ucs-init ()
+ "Initialize an helm buffer with ucs symbols.
+Only math* symbols are collected."
+ (unless helm-ucs--max-len
+ (setq helm-ucs--max-len
+ (helm-calculate-ucs-max-len)))
+ (or helm-ucs--names
+ (setq helm-ucs--names
+ (helm-ucs-collect-symbols (ucs-names)))))
+
+;; Actions (insertion)
+
+(defun helm-ucs-match (candidate n)
+ "Return the N part of an ucs CANDIDATE.
+Where N=1 is the ucs code, N=2 the ucs char and N=3 the ucs name."
+ (when (string-match
+ "^(\\(#x[a-f0-9]+\\)): *\\(.\\) *\\([^:]+\\)+"
+ candidate)
+ (match-string n candidate)))
+
+(defun helm-ucs-save-recentest (candidate)
+ (let ((lst (cons candidate (delete candidate helm-ucs-recent))))
+ (setq helm-ucs-recent
+ (if (> (length lst) helm-ucs-recent-size)
+ (nbutlast lst 1)
+ lst))))
+
+(defun helm-ucs-insert (candidate n)
+ "Insert the N part of CANDIDATE."
+ (with-helm-current-buffer
+ (helm-ucs-save-recentest candidate)
+ (insert (helm-ucs-match candidate n))))
+
+(defun helm-ucs-insert-char (candidate)
+ "Insert ucs char part of CANDIDATE at point."
+ (helm-ucs-insert candidate 2))
+
+(defun helm-ucs-insert-code (candidate)
+ "Insert ucs code part of CANDIDATE at point."
+ (helm-ucs-insert candidate 1))
+
+(defun helm-ucs-insert-name (candidate)
+ "Insert ucs name part of CANDIDATE at point."
+ (helm-ucs-insert candidate 3))
+
+;; Kill actions
+(defun helm-ucs-kill-char (_candidate)
+ "Action that concatenate ucs marked chars."
+ (let ((marked (helm-marked-candidates)))
+ (cl-loop for candidate in marked
+ do (helm-ucs-save-recentest candidate))
+ (kill-new (mapconcat (lambda (x)
+ (helm-ucs-match x 2))
+ marked ""))))
+
+(defun helm-ucs-kill-code (candidate)
+ (helm-ucs-save-recentest candidate)
+ (kill-new (helm-ucs-match candidate 1)))
+
+(defun helm-ucs-kill-name (candidate)
+ (helm-ucs-save-recentest candidate)
+ (kill-new (helm-ucs-match candidate 3)))
+
+;; Navigation in current-buffer (persistent)
+
+(defun helm-ucs-forward-char (_candidate)
+ (with-helm-current-buffer
+ (forward-char 1)))
+
+(defun helm-ucs-backward-char (_candidate)
+ (with-helm-current-buffer
+ (forward-char -1)))
+
+(defun helm-ucs-delete-backward (_candidate)
+ (with-helm-current-buffer
+ (delete-char -1)))
+
+(defun helm-ucs-insert-space (_candidate)
+ (with-helm-current-buffer
+ (insert " ")))
+
+(defun helm-ucs-persistent-forward ()
+ (interactive)
+ (with-helm-alive-p
+ (helm-attrset 'action-forward 'helm-ucs-forward-char)
+ (helm-execute-persistent-action 'action-forward)))
+(put 'helm-ucs-persistent-forward 'helm-only t)
+
+(defun helm-ucs-persistent-backward ()
+ (interactive)
+ (with-helm-alive-p
+ (helm-attrset 'action-back 'helm-ucs-backward-char)
+ (helm-execute-persistent-action 'action-back)))
+(put 'helm-ucs-persistent-backward 'helm-only t)
+
+(defun helm-ucs-persistent-delete ()
+ (interactive)
+ (with-helm-alive-p
+ (helm-attrset 'action-delete 'helm-ucs-delete-backward)
+ (helm-execute-persistent-action 'action-delete)))
+(put 'helm-ucs-persistent-delete 'helm-only t)
+
+(defun helm-ucs-persistent-insert-space ()
+ (interactive)
+ (with-helm-alive-p
+ (helm-attrset 'action-insert-space 'helm-ucs-insert-space)
+ (helm-execute-persistent-action 'action-insert-space)))
+
+(defvar helm-source-ucs-recent
+ (helm-build-sync-source "Recent UCS"
+ :action helm-ucs-actions
+ :candidates (lambda () helm-ucs-recent)
+ :help-message helm-ucs-help-message
+ :keymap helm-ucs-map
+ :volatile t))
+
+(defvar helm-source-ucs
+ (helm-build-in-buffer-source "UCS names"
+ :data #'helm-ucs-init
+ :get-line #'buffer-substring
+ :help-message 'helm-ucs-help-message
+ :filtered-candidate-transformer
+ (lambda (candidates _source) (sort candidates #'helm-generic-sort-fn))
+ :action helm-ucs-actions
+ :persistent-action (lambda (candidate)
+ (helm-ucs-insert-char candidate)
+ (helm-force-update))
+ :keymap helm-ucs-map)
+ "Source for collecting `ucs-names' math symbols.")
+\f
+;;;###autoload
+(defun helm-select-xfont ()
+ "Preconfigured `helm' to select Xfont."
+ (interactive)
+ (helm :sources 'helm-source-xfonts
+ :buffer "*helm select xfont*"))
+
+;;;###autoload
+(defun helm-ucs (arg)
+ "Preconfigured helm for `ucs-names'.
+
+Called with a prefix arg force reloading cache."
+ (interactive "P")
+ (when arg
+ (setq helm-ucs--names nil
+ helm-ucs--max-len nil
+ ucs-names nil))
+ (let ((char (helm-aif (char-after) (string it))))
+ (helm :sources (list helm-source-ucs-recent helm-source-ucs)
+ :history 'helm-ucs-history
+ :input (and char (multibyte-string-p char) char)
+ :buffer "*helm ucs*")))
+
+(provide 'helm-font)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-font.el ends here
--- /dev/null
+;;; helm-for-files.el --- helm-for-files and related. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Code:
+
+(require 'helm-files)
+(require 'helm-external)
+(require 'helm-bookmark)
+
+(defcustom helm-multi-files-toggle-locate-binding "C-c p"
+ "Default binding to switch back and forth locate in `helm-multi-files'."
+ :group 'helm-files
+ :type 'string)
+
+(defcustom helm-for-files-preferred-list
+ '(helm-source-buffers-list
+ helm-source-recentf
+ helm-source-bookmarks
+ helm-source-file-cache
+ helm-source-files-in-current-dir
+ helm-source-locate)
+ "Your preferred sources for `helm-for-files' and `helm-multi-files'.
+
+When adding a source here it is up to you to ensure the library of
+this source is accessible and properly loaded."
+ :type '(repeat (choice symbol))
+ :group 'helm-files)
+
+(defcustom helm-for-files-tramp-not-fancy t
+ "Colorize remote files when non nil.
+
+Be aware that a nil value will make tramp display very slow."
+ :group 'helm-files
+ :type 'boolean)
+
+;;; File Cache
+;;
+;;
+(defvar file-cache-alist)
+
+(defclass helm-file-cache (helm-source-in-buffer helm-type-file)
+ ((init :initform (lambda () (require 'filecache)))))
+
+(defun helm-file-cache-get-candidates ()
+ (cl-loop for item in file-cache-alist append
+ (cl-destructuring-bind (base &rest dirs) item
+ (cl-loop for dir in dirs collect
+ (concat dir base)))))
+
+(defvar helm-source-file-cache nil)
+
+(defcustom helm-file-cache-fuzzy-match nil
+ "Enable fuzzy matching in `helm-source-file-cache' when non--nil."
+ :group 'helm-files
+ :type 'boolean
+ :set (lambda (var val)
+ (set var val)
+ (setq helm-source-file-cache
+ (helm-make-source "File Cache" 'helm-file-cache
+ :fuzzy-match helm-file-cache-fuzzy-match
+ :data 'helm-file-cache-get-candidates))))
+
+(cl-defun helm-file-cache-add-directory-recursively
+ (dir &optional match (ignore-dirs t))
+ (require 'filecache)
+ (cl-loop for f in (helm-walk-directory
+ dir
+ :path 'full
+ :directories nil
+ :match match
+ :skip-subdirs ignore-dirs)
+ do (file-cache-add-file f)))
+
+(defun helm-transform-file-cache (actions _candidate)
+ (let ((source (helm-get-current-source)))
+ (if (string= (assoc-default 'name source) "File Cache")
+ (append actions
+ '(("Remove marked files from file-cache"
+ . helm-ff-file-cache-remove-file)))
+ actions)))
+
+;;; Recentf files
+;;
+;;
+(defvar helm-recentf--basename-flag nil)
+
+(defun helm-recentf-pattern-transformer (pattern)
+ (let ((pattern-no-flag (replace-regexp-in-string " -b" "" pattern)))
+ (cond ((and (string-match " " pattern-no-flag)
+ (string-match " -b\\'" pattern))
+ (setq helm-recentf--basename-flag t)
+ pattern-no-flag)
+ ((string-match "\\([^ ]*\\) -b\\'" pattern)
+ (prog1 (match-string 1 pattern)
+ (setq helm-recentf--basename-flag t)))
+ (t (setq helm-recentf--basename-flag nil)
+ pattern))))
+
+(defcustom helm-turn-on-recentf t
+ "Automatically turn on `recentf-mode' when non-nil."
+ :group 'helm-files
+ :type 'boolean)
+
+(defclass helm-recentf-source (helm-source-sync helm-type-file)
+ ((init :initform (lambda ()
+ (require 'recentf)
+ (when helm-turn-on-recentf (recentf-mode 1))))
+ (candidates :initform (lambda () recentf-list))
+ (pattern-transformer :initform 'helm-recentf-pattern-transformer)
+ (match-part :initform (lambda (candidate)
+ (if (or helm-ff-transformer-show-only-basename
+ helm-recentf--basename-flag)
+ (helm-basename candidate) candidate)))
+ (migemo :initform t)
+ (persistent-action :initform 'helm-ff-kill-or-find-buffer-fname)))
+
+(defmethod helm--setup-source :after ((source helm-recentf-source))
+ (setf (slot-value source 'action)
+ (append (symbol-value (helm-actions-from-type-file))
+ '(("Delete file(s) from recentf" .
+ (lambda (_candidate)
+ (cl-loop for file in (helm-marked-candidates)
+ do (setq recentf-list (delete file recentf-list)))))))))
+
+(defvar helm-source-recentf nil
+ "See (info \"(emacs)File Conveniences\").
+Set `recentf-max-saved-items' to a bigger value if default is too small.")
+
+(defcustom helm-recentf-fuzzy-match nil
+ "Enable fuzzy matching in `helm-source-recentf' when non--nil."
+ :group 'helm-files
+ :type 'boolean
+ :set (lambda (var val)
+ (set var val)
+ (let ((helm-fuzzy-sort-fn 'helm-fuzzy-matching-sort-fn-preserve-ties-order))
+ (setq helm-source-recentf
+ (helm-make-source "Recentf" 'helm-recentf-source
+ :fuzzy-match helm-recentf-fuzzy-match)))))
+
+\f
+;;; Files in current dir
+;;
+;;
+(defun helm-highlight-files (files _source)
+ "A basic transformer for helm files sources.
+Colorize only symlinks, directories and files."
+ (cl-loop with mp-fn = (or (assoc-default
+ 'match-part (helm-get-current-source))
+ 'identity)
+ for i in files
+ for disp = (if (and helm-ff-transformer-show-only-basename
+ (not (helm-dir-is-dot i))
+ (not (and helm--url-regexp
+ (string-match helm--url-regexp i)))
+ (not (string-match helm-ff-url-regexp i)))
+ (helm-basename i) (abbreviate-file-name i))
+ for isremote = (or (file-remote-p i)
+ (helm-file-on-mounted-network-p i))
+ ;; Call file-attributes only if:
+ ;; - file is not remote
+ ;; - helm-for-files--tramp-not-fancy is nil and file is remote AND
+ ;; connected. (Issue #1679)
+ for type = (and (or (null isremote)
+ (and (null helm-for-files-tramp-not-fancy)
+ (file-remote-p i nil t)))
+ (car (file-attributes i)))
+ collect
+ (cond ((and (null type) isremote) (cons disp i))
+ ((stringp type)
+ (cons (propertize disp
+ 'face 'helm-ff-symlink
+ 'match-part (funcall mp-fn disp)
+ 'help-echo (expand-file-name i))
+ i))
+ ((eq type t)
+ (cons (propertize disp
+ 'face 'helm-ff-directory
+ 'match-part (funcall mp-fn disp)
+ 'help-echo (expand-file-name i))
+ i))
+ (t (cons (propertize disp
+ 'face 'helm-ff-file
+ 'match-part (funcall mp-fn disp)
+ 'help-echo (expand-file-name i))
+ i)))))
+
+(defclass helm-files-in-current-dir-source (helm-source-sync helm-type-file)
+ ((candidates :initform (lambda ()
+ (with-helm-current-buffer
+ (let ((dir (helm-current-directory)))
+ (when (file-accessible-directory-p dir)
+ (directory-files dir t))))))
+ (pattern-transformer :initform 'helm-recentf-pattern-transformer)
+ (match-part :initform (lambda (candidate)
+ (if (or helm-ff-transformer-show-only-basename
+ helm-recentf--basename-flag)
+ (helm-basename candidate) candidate)))
+ (fuzzy-match :initform t)
+ (migemo :initform t)))
+
+(defvar helm-source-files-in-current-dir
+ (helm-make-source "Files from Current Directory"
+ 'helm-files-in-current-dir-source))
+
+;;;###autoload
+(defun helm-for-files ()
+ "Preconfigured `helm' for opening files.
+Run all sources defined in `helm-for-files-preferred-list'."
+ (interactive)
+ (require 'helm-x-files)
+ (unless helm-source-buffers-list
+ (setq helm-source-buffers-list
+ (helm-make-source "Buffers" 'helm-source-buffers)))
+ (helm :sources helm-for-files-preferred-list
+ :ff-transformer-show-only-basename nil
+ :buffer "*helm for files*"
+ :truncate-lines helm-buffers-truncate-lines))
+
+(defun helm-multi-files-toggle-to-locate ()
+ (interactive)
+ (with-helm-alive-p
+ (with-helm-buffer
+ (if (setq helm-multi-files--toggle-locate
+ (not helm-multi-files--toggle-locate))
+ (progn
+ (helm-set-sources (unless (memq 'helm-source-locate
+ helm-sources)
+ (cons 'helm-source-locate helm-sources)))
+ (helm-set-source-filter '(helm-source-locate)))
+ (helm-kill-async-processes)
+ (helm-set-sources (remove 'helm-source-locate
+ helm-for-files-preferred-list))
+ (helm-set-source-filter nil)))))
+(put 'helm-multi-files-toggle-to-locate 'helm-only t)
+
+;;;###autoload
+(defun helm-multi-files ()
+ "Preconfigured helm like `helm-for-files' but running locate only on demand.
+
+Allow toggling back and forth from locate to others sources with
+`helm-multi-files-toggle-locate-binding' key.
+This avoid launching needlessly locate when what you search is already
+found."
+ (interactive)
+ (require 'helm-x-files)
+ (unless helm-source-buffers-list
+ (setq helm-source-buffers-list
+ (helm-make-source "Buffers" 'helm-source-buffers)))
+ (setq helm-multi-files--toggle-locate nil)
+ (helm-locate-set-command)
+ (helm-set-local-variable 'helm-async-outer-limit-hook
+ (list (lambda ()
+ (when (and helm-locate-fuzzy-match
+ (not (string-match-p
+ "\\s-" helm-pattern)))
+ (helm-redisplay-buffer)))))
+ (let ((sources (remove 'helm-source-locate helm-for-files-preferred-list))
+ (helm-locate-command
+ (if helm-locate-fuzzy-match
+ (unless (string-match-p "\\`locate -b" helm-locate-command)
+ (replace-regexp-in-string
+ "\\`locate" "locate -b" helm-locate-command))
+ helm-locate-command))
+ (old-key (lookup-key
+ helm-map
+ (read-kbd-macro helm-multi-files-toggle-locate-binding))))
+ (with-helm-temp-hook 'helm-after-initialize-hook
+ (define-key helm-map (kbd helm-multi-files-toggle-locate-binding)
+ 'helm-multi-files-toggle-to-locate))
+ (unwind-protect
+ (helm :sources sources
+ :ff-transformer-show-only-basename nil
+ :buffer "*helm multi files*"
+ :truncate-lines helm-buffers-truncate-lines)
+ (define-key helm-map (kbd helm-multi-files-toggle-locate-binding)
+ old-key))))
+
+;;;###autoload
+(defun helm-recentf ()
+ "Preconfigured `helm' for `recentf'."
+ (interactive)
+ (helm :sources 'helm-source-recentf
+ :ff-transformer-show-only-basename nil
+ :buffer "*helm recentf*"))
+
+(provide 'helm-for-files)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-for-files.el ends here
--- /dev/null
+;;; helm-grep.el --- Helm Incremental Grep. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Code:
+(require 'cl-lib)
+(require 'format-spec)
+(require 'helm)
+(require 'helm-help)
+(require 'helm-regexp)
+
+;;; load wgrep proxy if it's available
+(require 'wgrep-helm nil t)
+
+(declare-function helm-buffer-list "helm-buffers")
+(declare-function View-quit "view")
+(declare-function doc-view-goto-page "doc-view" (page))
+(declare-function pdf-view-goto-page "pdf-view" (page &optional window))
+(declare-function helm-mm-split-pattern "helm-multi-match")
+(declare-function helm--ansi-color-apply "helm-lib")
+(defvar helm--ansi-color-regexp)
+
+\f
+(defgroup helm-grep nil
+ "Grep related Applications and libraries for Helm."
+ :group 'helm)
+
+(defcustom helm-grep-default-command
+ "grep --color=always -a -d skip %e -n%cH -e %p %f"
+ "Default grep format command for `helm-do-grep-1'.
+Where:
+'%e' format spec is for --exclude or --include grep options or
+ ack-grep --type option. (Not mandatory)
+
+'%c' format spec is for case-fold-search,
+ whether to use the -i option of grep. (Not mandatory)
+ When you specify this spec, helm grep will use smartcase
+ that is when a upcase character is found in pattern case will
+ be respected and no '-i' option will be used, otherwise, when
+ no upcase character is found in pattern always use '-i'.
+ If you don't want this behavior, don't use this spec and
+ specify or not the '-i' option.
+ Note that with ack-grep this is not needed, just specify
+ the '--smart-case' option.
+
+'%p' format spec is for pattern. (Mandatory)
+
+'%f' format spec is for filenames. (Mandatory)
+
+If your grep version doesn't support the --exclude/include args
+don't specify the '%e' format spec.
+
+Helm also support ack-grep and git-grep ,
+here a default command example for ack-grep:
+
+\(setq helm-grep-default-command \"ack-grep -Hn --color --smart-case --no-group %e %p %f\"
+ helm-grep-default-recurse-command \"ack-grep -H --color --smart-case --no-group %e %p %f\")
+
+You can ommit the %e spec if you don't want to be prompted for types.
+
+NOTE: Helm for ack-grep support ANSI sequences, so you can remove
+the \"--no-color\" option safely (recommended)
+However you should specify --color to enable multi matches highlighting
+because ack disable it when output is piped.
+
+Same for grep you can use safely the option \"--color=always\" (default).
+You can customize the color of matches using GREP_COLORS env var.
+e.g: \(setenv \"GREP_COLORS\" \"ms=30;43:mc=30;43:sl=01;37:cx=:fn=35:ln=32:bn=32:se=36\")
+
+To enable ANSI color in git-grep just add \"--color=always\".
+To customize the ANSI color in git-grep, GREP_COLORS have no effect,
+you will have to setup this in your .gitconfig:
+
+ [color \"grep\"]
+ match = black yellow
+
+where \"black\" is the foreground and \"yellow\" the background.
+See the git documentation for more infos.
+
+`helm-grep-default-command' and `helm-grep-default-recurse-command'are
+independents, so you can enable `helm-grep-default-command' with ack-grep
+and `helm-grep-default-recurse-command' with grep if you want to be faster
+on recursive grep.
+
+NOTE: Remote grepping is not available with ack-grep,
+ and badly supported with grep because tramp handle badly
+ repeated remote processes in a short delay (< to 5s)."
+ :group 'helm-grep
+ :type 'string)
+
+(defcustom helm-grep-default-recurse-command
+ "grep --color=always -a -d recurse %e -n%cH -e %p %f"
+ "Default recursive grep format command for `helm-do-grep-1'.
+See `helm-grep-default-command' for format specs and infos about ack-grep."
+ :group 'helm-grep
+ :type 'string)
+
+(defcustom helm-default-zgrep-command
+ "zgrep --color=always -a -n%cH -e %p %f"
+ "Default command for Zgrep.
+See `helm-grep-default-command' for infos on format specs.
+Option --color=always is supported and can be used safely
+to replace the helm internal match highlighting,
+see `helm-grep-default-command' for more infos."
+ :group 'helm-grep
+ :type 'string)
+
+(defcustom helm-pdfgrep-default-command
+ "pdfgrep --color always -niH %s %s"
+ "Default command for pdfgrep.
+Option \"--color always\" is supported starting helm version 1.7.8,
+when used matchs will be highlighted according to GREP_COLORS env var."
+ :group 'helm-grep
+ :type 'string)
+
+(defcustom helm-pdfgrep-default-recurse-command
+ "pdfgrep --color always -rniH %s %s"
+ "Default recurse command for pdfgrep.
+Option \"--color always\" is supported starting helm version 1.7.8,
+when used matchs will be highlighted according to GREP_COLORS env var."
+ :group 'helm-grep
+ :type 'string)
+
+(defcustom helm-grep-use-ioccur-style-keys t
+ "Use Arrow keys to jump to occurences."
+ :group 'helm-grep
+ :type 'boolean)
+
+(defcustom helm-pdfgrep-default-read-command nil
+ "Default command to read pdf files from pdfgrep.
+Where '%f' format spec is filename and '%p' is page number.
+e.g In Ubuntu you can set it to:
+
+ \"evince --page-label=%p '%f'\"
+
+If set to nil either `doc-view-mode' or `pdf-view-mode' will be used
+instead of an external command."
+ :group 'helm-grep
+ :type 'string)
+
+(defcustom helm-grep-max-length-history 100
+ "Max number of elements to save in `helm-grep-history'."
+ :group 'helm-grep
+ :type 'integer)
+
+(defcustom helm-zgrep-file-extension-regexp
+ ".*\\(\\.gz\\|\\.bz\\|\\.xz\\|\\.lzma\\)$"
+ "Default file extensions zgrep will search in."
+ :group 'helm-grep
+ :type 'string)
+
+(defcustom helm-grep-preferred-ext nil
+ "This file extension will be preselected for grep."
+ :group 'helm-grep
+ :type 'string)
+
+(defcustom helm-grep-save-buffer-name-no-confirm nil
+ "when *hgrep* already exists,auto append suffix."
+ :group 'helm-grep
+ :type 'boolean)
+
+(defcustom helm-grep-ignored-files
+ (cons ".#*" (delq nil (mapcar (lambda (s)
+ (unless (string-match-p "/\\'" s)
+ (concat "*" s)))
+ completion-ignored-extensions)))
+ "List of file names which `helm-grep' shall exclude."
+ :group 'helm-grep
+ :type '(repeat string))
+
+(defcustom helm-grep-ignored-directories
+ helm-walk-ignore-directories
+ "List of names of sub-directories which `helm-grep' shall not recurse into."
+ :group 'helm-grep
+ :type '(repeat string))
+
+(defcustom helm-grep-truncate-lines t
+ "When nil the grep line that appears will not be truncated."
+ :group 'helm-grep
+ :type 'boolean)
+
+(defcustom helm-grep-file-path-style 'basename
+ "File path display style when grep results are displayed.
+Possible value are:
+ basename: displays only the filename, none of the directory path
+ absolute: displays absolute path
+ relative: displays relative path from root grep directory."
+ :group 'helm-grep
+ :type '(choice (const :tag "Basename" basename)
+ (const :tag "Absolute" absolute)
+ (const :tag "Relative" relative)))
+
+(defcustom helm-grep-actions
+ (helm-make-actions
+ "Find File" 'helm-grep-action
+ "Find file other frame" 'helm-grep-other-frame
+ "Save results in grep buffer" 'helm-grep-save-results
+ "Find file other window (C-u vertically)" 'helm-grep-other-window)
+ "Actions for helm grep."
+ :group 'helm-grep
+ :type '(alist :key-type string :value-type function))
+
+(defcustom helm-grep-pipe-cmd-switches nil
+ "A list of additional parameters to pass to grep pipe command.
+This will be used for pipe command for multiple pattern matching
+for grep, zgrep ack-grep and git-grep backends.
+If you add extra args for ack-grep, use ack-grep options,
+for others (grep, zgrep and git-grep) use grep options.
+Here are the commands where you may want to add switches:
+
+ grep --color=always
+ ack-grep --smart-case --color
+
+You probably don't need to use this unless you know what you are doing."
+ :group 'helm-grep
+ :type 'string)
+
+(defcustom helm-grep-ag-pipe-cmd-switches nil
+ "A list of additional parameters to pass to grep-ag pipe command.
+Use parameters compatibles with the backend you are using
+\(i.e AG for AG, PT for PT or RG for RG)
+
+You probably don't need to use this unless you know what you are doing."
+ :group 'helm-grep
+ :type 'string)
+
+\f
+;;; Faces
+;;
+;;
+(defgroup helm-grep-faces nil
+ "Customize the appearance of helm-grep."
+ :prefix "helm-"
+ :group 'helm-grep
+ :group 'helm-faces)
+
+(defface helm-grep-match
+ '((((background light)) :foreground "#b00000")
+ (((background dark)) :foreground "gold1"))
+ "Face used to highlight grep matches.
+Have no effect when grep backend use \"--color=\"."
+ :group 'helm-grep-faces)
+
+(defface helm-grep-file
+ '((t (:foreground "BlueViolet"
+ :underline t)))
+ "Face used to highlight grep results filenames."
+ :group 'helm-grep-faces)
+
+(defface helm-grep-lineno
+ '((t (:foreground "Darkorange1")))
+ "Face used to highlight grep number lines."
+ :group 'helm-grep-faces)
+
+(defface helm-grep-finish
+ '((t (:foreground "Green")))
+ "Face used in mode line when grep is finish."
+ :group 'helm-grep-faces)
+
+(defface helm-grep-cmd-line
+ '((t (:inherit font-lock-type-face)))
+ "Face used to highlight grep command line when no results."
+ :group 'helm-grep-faces)
+
+\f
+;;; Keymaps
+;;
+;;
+(defvar helm-grep-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map helm-map)
+ (define-key map (kbd "M-<down>") 'helm-goto-next-file)
+ (define-key map (kbd "M-<up>") 'helm-goto-precedent-file)
+ (define-key map (kbd "C-c o") 'helm-grep-run-other-window-action)
+ (define-key map (kbd "C-c C-o") 'helm-grep-run-other-frame-action)
+ (define-key map (kbd "C-x C-s") 'helm-grep-run-save-buffer)
+ (when helm-grep-use-ioccur-style-keys
+ (define-key map (kbd "<right>") 'helm-execute-persistent-action)
+ (define-key map (kbd "<left>") 'helm-grep-run-default-action))
+ (delq nil map))
+ "Keymap used in Grep sources.")
+
+(defvar helm-pdfgrep-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map helm-map)
+ (define-key map (kbd "M-<down>") 'helm-goto-next-file)
+ (define-key map (kbd "M-<up>") 'helm-goto-precedent-file)
+ map)
+ "Keymap used in pdfgrep.")
+
+(defvar helm-grep-mode-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map (kbd "RET") 'helm-grep-mode-jump)
+ (define-key map (kbd "C-o") 'helm-grep-mode-jump-other-window)
+ (define-key map (kbd "<C-down>") 'helm-grep-mode-jump-other-window-forward)
+ (define-key map (kbd "<C-up>") 'helm-grep-mode-jump-other-window-backward)
+ (define-key map (kbd "<M-down>") 'helm-gm-next-file)
+ (define-key map (kbd "<M-up>") 'helm-gm-precedent-file)
+ (define-key map (kbd "M-n") 'helm-grep-mode-jump-other-window-forward)
+ (define-key map (kbd "M-p") 'helm-grep-mode-jump-other-window-backward)
+ (define-key map (kbd "M-N") 'helm-gm-next-file)
+ (define-key map (kbd "M-P") 'helm-gm-precedent-file)
+ map))
+
+\f
+;;; Internals vars
+;;
+;;
+(defvar helm-rzgrep-cache (make-hash-table :test 'equal))
+(defvar helm-grep-default-function 'helm-grep-init)
+(defvar helm-zgrep-recurse-flag nil)
+(defvar helm-grep-history nil)
+(defvar helm-grep-ag-history nil)
+(defvar helm-grep-last-targets nil)
+(defvar helm-grep-include-files nil)
+(defvar helm-grep-in-recurse nil)
+(defvar helm-grep-use-zgrep nil)
+(defvar helm-grep-default-directory-fn nil
+ "A function that should return a directory to expand candidate to.
+It is intended to use as a let-bound variable, DON'T set this globaly.")
+(defvar helm-pdfgrep-targets nil)
+(defvar helm-grep-last-cmd-line nil)
+(defvar helm-grep-split-line-regexp "^\\([[:lower:][:upper:]]?:?.*?\\):\\([0-9]+\\):\\(.*\\)")
+
+\f
+;;; Init
+;;
+;;
+(defun helm-grep-prepare-candidates (candidates in-directory)
+ "Prepare filenames and directories CANDIDATES for grep command line."
+ ;; If one or more candidate is a directory, search in all files
+ ;; of this candidate (e.g /home/user/directory/*).
+ ;; If r option is enabled search also in subdidrectories.
+ ;; We need here to expand wildcards to support crap windows filenames
+ ;; as grep doesn't accept quoted wildcards (e.g "dir/*.el").
+ (if helm-zgrep-recurse-flag
+ (mapconcat 'shell-quote-argument candidates " ")
+ ;; When candidate is a directory, search in all its files.
+ ;; NOTE that `file-expand-wildcards' will return also
+ ;; directories, they will be ignored by grep but not
+ ;; by ack-grep that will grep all files of this directory
+ ;; without recursing in their subdirs though, see that as a one
+ ;; level recursion with ack-grep.
+ ;; So I leave it as it is, considering it is a feature. [1]
+ (cl-loop for i in candidates append
+ (cond ((string-match "^git" helm-grep-default-command)
+ (list i))
+ ;; Candidate is a directory and we use recursion or ack.
+ ((and (file-directory-p i)
+ (or helm-grep-in-recurse
+ ;; ack-grep accept directory [1].
+ (helm-grep-use-ack-p)))
+ (list (expand-file-name i)))
+ ;; Grep doesn't support directory only when not in recurse.
+ ((file-directory-p i)
+ (file-expand-wildcards
+ (concat (file-name-as-directory (expand-file-name i)) "*") t))
+ ;; Candidate is a file or wildcard and we use recursion, use the
+ ;; current directory instead of candidate.
+ ((and (or (file-exists-p i) (string-match "[*]" i))
+ helm-grep-in-recurse)
+ (list (expand-file-name
+ (directory-file-name ; Needed for windoze.
+ (file-name-directory (directory-file-name i))))))
+ ;; Else should be one or more file/directory
+ ;; possibly marked.
+ ;; When real is a normal filename without wildcard
+ ;; file-expand-wildcards returns a list of one file.
+ ;; wildcards should have been already handled by
+ ;; helm-read-file-name or helm-find-files but do it from
+ ;; here too in case we are called from elsewhere.
+ (t (file-expand-wildcards i t))) into all-files ; [1]
+ finally return
+ (let ((files (if (file-remote-p in-directory)
+ ;; Grep don't understand tramp filenames
+ ;; use the local name.
+ (mapcar (lambda (x)
+ (file-remote-p x 'localname))
+ all-files)
+ all-files)))
+ ;; When user mark files and use recursion with grep
+ ;; backend enabled, the loop collect on each marked
+ ;; candidate its `file-name-directory' and we endup with
+ ;; duplicates (Issue #1714). FIXME: For now as a quick fix
+ ;; I just remove dups here but I should handle this inside
+ ;; the cond above.
+ (setq files (helm-fast-remove-dups files :test 'equal))
+ (if (string-match "^git" helm-grep-default-command)
+ (mapconcat 'identity files " ")
+ (mapconcat 'shell-quote-argument files " "))))))
+
+(defun helm-grep-command (&optional recursive grep)
+ (let* ((com (if recursive
+ helm-grep-default-recurse-command
+ helm-grep-default-command))
+ (exe (if grep
+ (symbol-name grep)
+ (and com (car (split-string com " "))))))
+ (if (and exe (string= exe "git")) "git-grep" exe)))
+
+(cl-defun helm-grep-use-ack-p (&key where)
+ (let* ((rec-com (helm-grep-command t))
+ (norm-com (helm-grep-command))
+ (norm-com-ack-p (string-match "\\`ack" norm-com))
+ (rec-com-ack-p (and rec-com (string-match "\\`ack" rec-com))))
+ (cl-case where
+ (default (and norm-com norm-com-ack-p))
+ (recursive (and rec-com rec-com-ack-p))
+ (strict (and norm-com rec-com rec-com-ack-p norm-com-ack-p))
+ (t (and (not (and norm-com (string= norm-com "git-grep")))
+ (or (and norm-com norm-com-ack-p)
+ (and rec-com rec-com-ack-p)))))))
+
+(defun helm-grep--pipe-command-for-grep-command (smartcase pipe-switches &optional grep-cmd)
+ (pcase (or grep-cmd (helm-grep-command))
+ ;; Use grep for GNU regexp based tools.
+ ((or "grep" "zgrep" "git-grep")
+ (format "grep --color=always%s %s"
+ (if smartcase " -i" "")
+ pipe-switches))
+ ;; Use ack-grep for PCRE based tools.
+ ;; Sometimes ack-grep cmd is ack only.
+ ((and (pred (string-match-p "ack")) ack)
+ (format "%s --smart-case --color %s" ack pipe-switches))))
+
+(defun helm-grep--prepare-cmd-line (only-files &optional include zgrep)
+ (let* ((default-directory (or helm-ff-default-directory
+ (helm-default-directory)
+ default-directory))
+ (fnargs (helm-grep-prepare-candidates
+ only-files default-directory))
+ (ignored-files (unless (helm-grep-use-ack-p)
+ (mapconcat
+ (lambda (x)
+ (concat "--exclude="
+ (shell-quote-argument x)))
+ helm-grep-ignored-files " ")))
+ (ignored-dirs (unless (helm-grep-use-ack-p)
+ (mapconcat
+ ;; Need grep version >=2.5.4
+ ;; of Gnuwin32 on windoze.
+ (lambda (x)
+ (concat "--exclude-dir="
+ (shell-quote-argument x)))
+ helm-grep-ignored-directories " ")))
+ (exclude (unless (helm-grep-use-ack-p)
+ (if helm-grep-in-recurse
+ (concat (or include ignored-files)
+ " " ignored-dirs)
+ ignored-files)))
+ (types (and (helm-grep-use-ack-p)
+ ;; When %e format spec is not specified
+ ;; in `helm-grep-default-command'
+ ;; 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")))
+ (helm-grep-default-command
+ (concat helm-grep-default-command " %m")) ; `%m' like multi.
+ (patterns (helm-mm-split-pattern helm-pattern t))
+ (pipe-switches (mapconcat 'identity helm-grep-pipe-cmd-switches " "))
+ (pipes
+ (helm-aif (cdr patterns)
+ (cl-loop with pipcom = (helm-grep--pipe-command-for-grep-command
+ smartcase pipe-switches)
+ for p in it concat
+ (format " | %s %s" pipcom (shell-quote-argument p)))
+ "")))
+ (format-spec
+ helm-grep-default-command
+ (delq nil
+ (list (unless zgrep
+ (if types
+ (cons ?e types)
+ (cons ?e exclude)))
+ (cons ?c (or smartcase ""))
+ (cons ?p (shell-quote-argument (car patterns)))
+ (cons ?f fnargs)
+ (cons ?m pipes))))))
+
+(defun helm-grep-init (cmd-line)
+ "Start an asynchronous grep process with CMD-LINE using ZGREP if non--nil."
+ (let* ((default-directory (or helm-ff-default-directory
+ (helm-default-directory)
+ default-directory))
+ (zgrep (string-match "\\`zgrep" cmd-line))
+ ;; Use pipe only with grep, zgrep or git-grep.
+ (process-connection-type (and (not zgrep) (helm-grep-use-ack-p)))
+ (tramp-verbose helm-tramp-verbose)
+ (start-time (float-time))
+ (proc-name (if helm-grep-use-zgrep
+ "Zgrep"
+ (capitalize
+ (if helm-grep-in-recurse
+ (helm-grep-command t)
+ (helm-grep-command)))))
+ non-essential)
+ ;; Start grep process.
+ (helm-log "Starting Grep process in directory `%s'" default-directory)
+ (helm-log "Command line used was:\n\n%s"
+ (concat ">>> " (propertize cmd-line 'face 'helm-grep-cmd-line) "\n\n"))
+ (prog1 ; This function should return the process first.
+ (start-file-process-shell-command
+ proc-name helm-buffer cmd-line)
+ ;; Init sentinel.
+ (set-process-sentinel
+ (get-buffer-process helm-buffer)
+ (lambda (process event)
+ (let* ((err (process-exit-status process))
+ (noresult (= err 1)))
+ (unless (and err (> err 0))
+ (helm-process-deferred-sentinel-hook
+ process event (helm-default-directory)))
+ (cond ((and noresult
+ ;; This is a workaround for zgrep
+ ;; that exit with code 1
+ ;; after a certain amount of results.
+ (with-helm-buffer (helm-empty-buffer-p)))
+ (with-helm-buffer
+ (insert (concat "* Exit with code 1, no result found,"
+ " command line was:\n\n "
+ (propertize helm-grep-last-cmd-line
+ 'face 'helm-grep-cmd-line)))
+ (setq mode-line-format
+ `(" " mode-line-buffer-identification " "
+ (:eval (format "L%s" (helm-candidate-number-at-point))) " "
+ (:eval (propertize
+ (format
+ "[%s process finished - (no results)] "
+ ,proc-name)
+ 'face 'helm-grep-finish))))))
+ ((or (string= event "finished\n")
+ (and noresult
+ ;; This is a workaround for zgrep
+ ;; that exit with code 1
+ ;; after a certain amount of results.
+ (with-helm-buffer (not (helm-empty-buffer-p)))))
+ (helm-log "%s process finished with %s results in %fs"
+ proc-name
+ (helm-get-candidate-number)
+ (- (float-time) start-time))
+ (helm-maybe-show-help-echo)
+ (with-helm-window
+ (setq mode-line-format
+ `(" " mode-line-buffer-identification " "
+ (:eval (format "L%s" (helm-candidate-number-at-point))) " "
+ (:eval (propertize
+ (format
+ "[%s process finished in %.2fs - (%s results)] "
+ ,proc-name
+ ,(- (float-time) start-time)
+ (helm-get-candidate-number))
+ 'face 'helm-grep-finish))))
+ (force-mode-line-update)
+ (when helm-allow-mouse
+ (helm--bind-mouse-for-selection helm-selection-point))))
+ ;; Catch error output in log.
+ (t (helm-log
+ "Error: %s %s"
+ proc-name
+ (replace-regexp-in-string "\n" "" event))))))))))
+
+(defun helm-grep-collect-candidates ()
+ (let ((cmd-line (helm-grep--prepare-cmd-line
+ helm-grep-last-targets
+ helm-grep-include-files
+ helm-grep-use-zgrep)))
+ (set (make-local-variable 'helm-grep-last-cmd-line) cmd-line)
+ (funcall helm-grep-default-function cmd-line)))
+
+\f
+;;; Actions
+;;
+;;
+(defun helm-grep-action (candidate &optional where)
+ "Define a default action for `helm-do-grep-1' on CANDIDATE.
+WHERE can be one of other-window, other-frame."
+ (let* ((split (helm-grep-split-line candidate))
+ (split-pat (helm-mm-split-pattern helm-input))
+ (lineno (string-to-number (nth 1 split)))
+ (loc-fname (or (with-current-buffer
+ (if (eq major-mode 'helm-grep-mode)
+ (current-buffer)
+ helm-buffer)
+ (get-text-property (point-at-bol) 'helm-grep-fname))
+ (car split)))
+ (tramp-method (file-remote-p (or helm-ff-default-directory
+ default-directory) 'method))
+ (tramp-host (file-remote-p (or helm-ff-default-directory
+ default-directory) 'host))
+ (tramp-prefix (concat "/" tramp-method ":" tramp-host ":"))
+ (fname (if tramp-host
+ (concat tramp-prefix loc-fname) loc-fname)))
+ (cl-case where
+ (other-window (helm-window-show-buffers
+ (list (find-file-noselect fname)) t))
+ (other-frame (find-file-other-frame fname))
+ (grep (helm-grep-save-results-1))
+ (pdf (if helm-pdfgrep-default-read-command
+ (helm-pdfgrep-action-1 split lineno (car split))
+ (find-file (car split)) (if (derived-mode-p 'pdf-view-mode)
+ (pdf-view-goto-page lineno)
+ (doc-view-goto-page lineno))))
+ (t (find-file fname)))
+ (unless (or (eq where 'grep) (eq where 'pdf))
+ (helm-goto-line lineno))
+ ;; Move point to the nearest matching regexp from bol.
+ (cl-loop for reg in split-pat
+ when (save-excursion
+ (condition-case _err
+ (if helm-migemo-mode
+ (helm-mm-migemo-forward reg (point-at-eol) t)
+ (re-search-forward reg (point-at-eol) t))
+ (invalid-regexp nil)))
+ collect (match-beginning 0) into pos-ls
+ finally (when pos-ls (goto-char (apply #'min pos-ls))))
+ ;; Save history
+ (unless (or helm-in-persistent-action
+ (eq major-mode 'helm-grep-mode)
+ (string= helm-pattern ""))
+ (setq helm-grep-history
+ (cons helm-pattern
+ (delete helm-pattern helm-grep-history)))
+ (when (> (length helm-grep-history)
+ helm-grep-max-length-history)
+ (setq helm-grep-history
+ (delete (car (last helm-grep-history))
+ helm-grep-history))))))
+
+(defun helm-grep-persistent-action (candidate)
+ "Persistent action for `helm-do-grep-1'.
+With a prefix arg record CANDIDATE in `mark-ring'."
+ (helm-grep-action candidate)
+ (helm-highlight-current-line))
+
+(defun helm-grep-other-window (candidate)
+ "Jump to result in other window from helm grep."
+ (helm-grep-action candidate 'other-window))
+
+(defun helm-grep-other-frame (candidate)
+ "Jump to result in other frame from helm grep."
+ (helm-grep-action candidate 'other-frame))
+
+(defun helm-goto-next-or-prec-file (n)
+ "Go to next or precedent candidate file in helm grep/etags buffers.
+If N is positive go forward otherwise go backward."
+ (let* ((allow-mode (or (eq major-mode 'helm-grep-mode)
+ (eq major-mode 'helm-moccur-mode)))
+ (sel (if allow-mode
+ (buffer-substring (point-at-bol) (point-at-eol))
+ (helm-get-selection nil t)))
+ (current-line-list (helm-grep-split-line sel))
+ (current-fname (nth 0 current-line-list))
+ (bob-or-eof (if (eq n 1) 'eobp 'bobp))
+ (mark-maybe (lambda ()
+ (if allow-mode
+ (ignore)
+ (helm-mark-current-line)))))
+ (catch 'break
+ (while (not (funcall bob-or-eof))
+ (forward-line n) ; Go forward or backward depending of n value.
+ ;; Exit when current-fname is not matched or in `helm-grep-mode'
+ ;; the line is not a grep line i.e 'fname:num:tag'.
+ (setq sel (buffer-substring (point-at-bol) (point-at-eol)))
+ (when helm-allow-mouse
+ (helm--mouse-reset-selection-help-echo))
+ (unless (or (string= current-fname
+ (car (helm-grep-split-line sel)))
+ (and (eq major-mode 'helm-grep-mode)
+ (not (get-text-property (point-at-bol) 'helm-grep-fname))))
+ (funcall mark-maybe)
+ (throw 'break nil))))
+ (cond ((and (> n 0) (eobp))
+ (re-search-backward ".")
+ (forward-line 0)
+ (funcall mark-maybe))
+ ((and (< n 0) (bobp))
+ (helm-aif (next-single-property-change (point-at-bol) 'helm-grep-fname)
+ (goto-char it)
+ (forward-line 1))
+ (funcall mark-maybe)))
+ (unless allow-mode
+ (helm-follow-execute-persistent-action-maybe)
+ (helm-log-run-hook 'helm-move-selection-after-hook))))
+
+;;;###autoload
+(defun helm-goto-precedent-file ()
+ "Go to precedent file in helm grep/etags buffers."
+ (interactive)
+ (with-helm-alive-p
+ (with-helm-window
+ (helm-goto-next-or-prec-file -1))))
+(put 'helm-goto-precedent-file 'helm-only t)
+
+;;;###autoload
+(defun helm-goto-next-file ()
+ "Go to precedent file in helm grep/etags buffers."
+ (interactive)
+ (with-helm-window
+ (helm-goto-next-or-prec-file 1)))
+
+(defun helm-grep-run-default-action ()
+ "Run grep default action from `helm-do-grep-1'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-grep-action)))
+(put 'helm-grep-run-default-action 'helm-only t)
+
+(defun helm-grep-run-other-window-action ()
+ "Run grep goto other window action from `helm-do-grep-1'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-grep-other-window)))
+(put 'helm-grep-run-other-window-action 'helm-only t)
+
+(defun helm-grep-run-other-frame-action ()
+ "Run grep goto other frame action from `helm-do-grep-1'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-grep-other-frame)))
+(put 'helm-grep-run-other-frame-action 'helm-only t)
+
+(defun helm-grep-run-save-buffer ()
+ "Run grep save results action from `helm-do-grep-1'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-grep-save-results)))
+(put 'helm-grep-run-save-buffer 'helm-only t)
+
+\f
+;;; helm-grep-mode
+;;
+;;
+(defun helm-grep-save-results (candidate)
+ (helm-grep-action candidate 'grep))
+
+(defun helm-grep-save-results-1 ()
+ "Save helm grep result in a `helm-grep-mode' buffer."
+ (let ((buf "*hgrep*")
+ new-buf
+ (pattern (with-helm-buffer helm-input-local))
+ (src-name (assoc-default 'name (helm-get-current-source))))
+ (when (get-buffer buf)
+ (if helm-grep-save-buffer-name-no-confirm
+ (setq new-buf (format "*hgrep|%s|-%s" pattern
+ (format-time-string "%H-%M-%S*")))
+ (setq new-buf (helm-read-string "GrepBufferName: " buf))
+ (cl-loop for b in (helm-buffer-list)
+ when (and (string= new-buf b)
+ (not (y-or-n-p
+ (format "Buffer `%s' already exists overwrite? "
+ new-buf))))
+ do (setq new-buf (helm-read-string "GrepBufferName: " "*hgrep "))))
+ (setq buf new-buf))
+ (with-current-buffer (get-buffer-create buf)
+ (setq default-directory (or helm-ff-default-directory
+ (helm-default-directory)
+ default-directory))
+ (setq buffer-read-only t)
+ (let ((inhibit-read-only t)
+ (map (make-sparse-keymap)))
+ (erase-buffer)
+ (insert "-*- mode: helm-grep -*-\n\n"
+ (format "%s Results for `%s':\n\n" src-name pattern))
+ (save-excursion
+ (insert (with-current-buffer helm-buffer
+ (goto-char (point-min)) (forward-line 1)
+ (buffer-substring (point) (point-max)))))
+ (save-excursion
+ (while (not (eobp))
+ (add-text-properties (point-at-bol) (point-at-eol)
+ `(keymap ,map
+ help-echo ,(concat
+ (get-text-property
+ (point) 'helm-grep-fname)
+ "\nmouse-1: set point\nmouse-2: jump to selection")
+ mouse-face highlight))
+ (define-key map [mouse-1] 'mouse-set-point)
+ (define-key map [mouse-2] 'helm-grep-mode-mouse-jump)
+ (define-key map [mouse-3] 'ignore)
+ (forward-line 1))))
+ (helm-grep-mode))
+ (pop-to-buffer buf)
+ (message "Helm %s Results saved in `%s' buffer" src-name buf)))
+
+(defun helm-grep-mode-mouse-jump (event)
+ (interactive "e")
+ (let* ((window (posn-window (event-end event)))
+ (pos (posn-point (event-end event))))
+ (with-selected-window window
+ (when (eq major-mode 'helm-grep-mode)
+ (goto-char pos)
+ (helm-grep-mode-jump)))))
+(put 'helm-grep-mode-mouse-jump 'helm-only t)
+
+(define-derived-mode helm-grep-mode
+ special-mode "helm-grep"
+ "Major mode to provide actions in helm grep saved buffer.
+
+Special commands:
+\\{helm-grep-mode-map}"
+ (set (make-local-variable 'helm-grep-last-cmd-line)
+ (with-helm-buffer helm-grep-last-cmd-line))
+ (set (make-local-variable 'revert-buffer-function)
+ #'helm-grep-mode--revert-buffer-function))
+(put 'helm-grep-mode 'helm-only t)
+
+(defun helm-grep-mode--revert-buffer-function (&optional _ignore-auto _noconfirm)
+ (goto-char (point-min))
+ (when (re-search-forward helm-grep-split-line-regexp nil t) (forward-line 0))
+ (let ((inhibit-read-only t))
+ (delete-region (point) (point-max)))
+ (message "Reverting buffer...")
+ (let ((process-connection-type
+ ;; Git needs a nil value otherwise it tries to use a pager.
+ (null (string-match-p "\\`git" helm-grep-last-cmd-line))))
+ (set-process-sentinel
+ (start-file-process-shell-command
+ "hgrep" (generate-new-buffer "*hgrep revert*") helm-grep-last-cmd-line)
+ 'helm-grep-mode--sentinel)))
+
+(defun helm-grep-mode--sentinel (process event)
+ (when (string= event "finished\n")
+ (with-current-buffer (current-buffer)
+ (let ((inhibit-read-only t))
+ (save-excursion
+ (cl-loop for l in (with-current-buffer (process-buffer process)
+ (prog1 (split-string (buffer-string) "\n")
+ (kill-buffer)))
+ for line = (if (string-match-p helm--ansi-color-regexp l)
+ (helm--ansi-color-apply l) l)
+ when (string-match helm-grep-split-line-regexp line)
+ do (insert (propertize
+ (car (helm-grep-filter-one-by-one line))
+ ;; needed for wgrep.
+ 'helm-realvalue line)
+ "\n"))))
+ (message "Reverting buffer done"))))
+
+(defun helm-gm-next-file ()
+ (interactive)
+ (helm-goto-next-or-prec-file 1))
+
+(defun helm-gm-precedent-file ()
+ (interactive)
+ (helm-goto-next-or-prec-file -1))
+
+(defun helm-grep-mode-jump ()
+ (interactive)
+ (helm-grep-action
+ (buffer-substring (point-at-bol) (point-at-eol)))
+ (helm-match-line-cleanup-pulse))
+
+(defun helm-grep-mode-jump-other-window-1 (arg)
+ (let ((candidate (buffer-substring (point-at-bol) (point-at-eol))))
+ (condition-case nil
+ (progn
+ (save-selected-window
+ (helm-grep-action candidate 'other-window)
+ (helm-match-line-cleanup-pulse)
+ (recenter))
+ (forward-line arg))
+ (error nil))))
+
+(defun helm-grep-mode-jump-other-window-forward ()
+ (interactive)
+ (helm-grep-mode-jump-other-window-1 1))
+
+(defun helm-grep-mode-jump-other-window-backward ()
+ (interactive)
+ (helm-grep-mode-jump-other-window-1 -1))
+
+(defun helm-grep-mode-jump-other-window ()
+ (interactive)
+ (let ((candidate (buffer-substring (point-at-bol) (point-at-eol))))
+ (condition-case nil
+ (progn (helm-grep-action candidate 'other-window)
+ (helm-match-line-cleanup-pulse))
+ (error nil))))
+
+\f
+;;; ack-grep types
+;;
+;;
+(defun helm-grep-hack-types ()
+ "Return a list of known ack-grep types."
+ (with-temp-buffer
+ ;; "--help-types" works with both 1.96 and 2.1+, while
+ ;; "--help types" works only with 1.96 Issue #422.
+ ;; `helm-grep-command' should return the ack executable
+ ;; when this function is used in the right context
+ ;; i.e After checking is we are using ack-grep with
+ ;; `helm-grep-use-ack-p'.
+ (call-process (helm-grep-command t) nil t nil "--help-types")
+ (goto-char (point-min))
+ (cl-loop while (re-search-forward
+ "^ *--\\(\\[no\\]\\)\\([^. ]+\\) *\\(.*\\)" nil t)
+ collect (cons (concat (match-string 2)
+ " [" (match-string 3) "]")
+ (match-string 2))
+ collect (cons (concat "no" (match-string 2)
+ " [" (match-string 3) "]")
+ (concat "no" (match-string 2))))))
+
+(defun helm-grep-ack-types-transformer (candidates _source)
+ (cl-loop for i in candidates
+ if (stringp i)
+ collect (rassoc i helm-grep-ack-types-cache)
+ else
+ collect i))
+
+(defvar helm-grep-ack-types-cache nil)
+(defun helm-grep-read-ack-type ()
+ "Select types for the '--type' argument of ack-grep."
+ (require 'helm-mode)
+ (require 'helm-adaptive)
+ (setq helm-grep-ack-types-cache (helm-grep-hack-types))
+ (let ((types (helm-comp-read
+ "Types: " helm-grep-ack-types-cache
+ :name "*Ack-grep types*"
+ :marked-candidates t
+ :must-match t
+ :fc-transformer '(helm-adaptive-sort
+ helm-grep-ack-types-transformer)
+ :buffer "*helm ack-types*")))
+ (mapconcat (lambda (type) (concat "--type=" type)) types " ")))
+
+\f
+;;; grep extensions
+;;
+;;
+(defun helm-grep-guess-extensions (files)
+ "Try to guess file extensions in FILES list when using grep recurse.
+These extensions will be added to command line with --include arg of grep."
+ (cl-loop with ext-list = (list helm-grep-preferred-ext "*")
+ with lst = (if (file-directory-p (car files))
+ (directory-files
+ (car files) nil
+ directory-files-no-dot-files-regexp)
+ files)
+ for i in lst
+ for ext = (file-name-extension i 'dot)
+ for glob = (and ext (not (string= ext ""))
+ (concat "*" ext))
+ unless (or (not glob)
+ (and glob-list (member glob glob-list))
+ (and glob-list (member glob ext-list))
+ (and glob-list (member glob helm-grep-ignored-files)))
+ collect glob into glob-list
+ finally return (delq nil (append ext-list glob-list))))
+
+(defun helm-grep-get-file-extensions (files)
+ "Try to return a list of file extensions to pass to '--include' arg of grep."
+ (require 'helm-adaptive)
+ (let* ((all-exts (helm-grep-guess-extensions
+ (mapcar 'expand-file-name files)))
+ (extensions (helm-comp-read "Search Only in: " all-exts
+ :marked-candidates t
+ :fc-transformer 'helm-adaptive-sort
+ :buffer "*helm grep exts*"
+ :name "*helm grep extensions*")))
+ (when (listp extensions) ; Otherwise it is empty string returned by C-RET.
+ ;; If extensions is a list of one string containing spaces,
+ ;; assume user entered more than one glob separated by space(s) and
+ ;; split this string to pass it later to mapconcat.
+ ;; e.g '("*.el *.py")
+ (cl-loop for i in extensions
+ append (split-string-and-unquote i " ")))))
+
+\f
+;;; Set up source
+;;
+;;
+(defvar helm-grep-before-init-hook nil
+ "Hook that runs before initialization of the helm buffer.")
+
+(defvar helm-grep-after-init-hook nil
+ "Hook that runs after initialization of the helm buffer.")
+
+(defclass helm-grep-class (helm-source-async)
+ ((candidates-process :initform 'helm-grep-collect-candidates)
+ (filter-one-by-one :initform 'helm-grep-filter-one-by-one)
+ (keymap :initform helm-grep-map)
+ (pcre :initarg :pcre :initform nil
+ :documentation
+ " Backend is using pcre regexp engine when non--nil.")
+ (nohighlight :initform t)
+ (nomark :initform t)
+ (backend :initarg :backend
+ :initform nil
+ :documentation
+ " The grep backend that will be used.
+ It is actually used only as an internal flag
+ and don't set the backend by itself.
+ You probably don't want to modify this.")
+ (candidate-number-limit :initform 9999)
+ (help-message :initform 'helm-grep-help-message)
+ (history :initform 'helm-grep-history)
+ (action :initform 'helm-grep-actions)
+ (persistent-action :initform 'helm-grep-persistent-action)
+ (persistent-help :initform "Jump to line (`C-u' Record in mark ring)")
+ (requires-pattern :initform 2)
+ (before-init-hook :initform 'helm-grep-before-init-hook)
+ (after-init-hook :initform 'helm-grep-after-init-hook)
+ (group :initform 'helm-grep)))
+
+(defvar helm-source-grep nil)
+
+(defmethod helm--setup-source ((source helm-grep-class))
+ (call-next-method)
+ (helm-aif (and helm-follow-mode-persistent
+ (if (eq (slot-value source 'backend) 'git)
+ helm-source-grep-git
+ helm-source-grep))
+ (setf (slot-value source 'follow)
+ (assoc-default 'follow it))))
+
+(cl-defun helm-do-grep-1 (targets &optional recurse backend exts
+ default-input input (source 'helm-source-grep))
+ "Launch helm using backend BACKEND on a list of TARGETS files.
+
+When RECURSE is given and BACKEND is 'grep' use -r option of
+BACKEND and prompt user for EXTS to set the --include args of BACKEND.
+Interactively you can give more than one arg separated by space at prompt.
+e.g
+ $Pattern: *.el *.py *.tex
+
+From lisp use the EXTS argument as a list of extensions as above.
+If you are using ack-grep, you will be prompted for --type
+instead and EXTS will be ignored.
+If prompt is empty `helm-grep-ignored-files' are added to --exclude.
+
+Argument DEFAULT-INPUT is use as `default' arg of `helm' and INPUT
+is used as `input' arg of `helm', See `helm' docstring.
+
+Arg BACKEND when non--nil specify which backend to use
+It is used actually to specify 'zgrep' or 'git'.
+When BACKEND 'zgrep' is used don't prompt for a choice
+in recurse, and ignore EXTS, search being made recursively on files matching
+`helm-zgrep-file-extension-regexp' only."
+ (let* (non-essential
+ (ack-rec-p (helm-grep-use-ack-p :where 'recursive))
+ (exts (and recurse
+ ;; [FIXME] I could handle this from helm-walk-directory.
+ (not (eq backend 'zgrep)) ; zgrep doesn't handle -r opt.
+ (not ack-rec-p)
+ (or exts (helm-grep-get-file-extensions targets))))
+ (include-files
+ (and exts
+ (mapconcat (lambda (x)
+ (concat "--include="
+ (shell-quote-argument x)))
+ (if (> (length exts) 1)
+ (remove "*" exts)
+ exts) " ")))
+ (types (and (not include-files)
+ (not (eq backend 'zgrep))
+ recurse
+ ack-rec-p
+ ;; When %e format spec is not specified
+ ;; ignore types and do not prompt for choice.
+ (string-match "%e" helm-grep-default-command)
+ (helm-grep-read-ack-type)))
+ (src-name (capitalize (helm-grep-command recurse backend)))
+ (com (cond ((eq backend 'zgrep) helm-default-zgrep-command)
+ ((eq backend 'git) helm-grep-git-grep-command)
+ (recurse helm-grep-default-recurse-command)
+ ;; When resuming, the local value of
+ ;; `helm-grep-default-command' is used, only git-grep
+ ;; should need this.
+ (t helm-grep-default-command))))
+ ;; When called as action from an other source e.g *-find-files
+ ;; we have to kill action buffer.
+ (when (get-buffer helm-action-buffer)
+ (kill-buffer helm-action-buffer))
+ ;; If `helm-find-files' haven't already started,
+ ;; give a default value to `helm-ff-default-directory'
+ ;; and set locally `default-directory' to this value . See below [1].
+ (unless helm-ff-default-directory
+ (setq helm-ff-default-directory default-directory))
+ ;; We need to store these vars locally
+ ;; to pass infos later to `helm-resume'.
+ (helm-set-local-variable
+ 'helm-zgrep-recurse-flag (and recurse (eq backend 'zgrep))
+ 'helm-grep-last-targets targets
+ 'helm-grep-include-files (or include-files types)
+ 'helm-grep-in-recurse recurse
+ 'helm-grep-use-zgrep (eq backend 'zgrep)
+ 'helm-grep-default-command com
+ 'default-directory helm-ff-default-directory) ;; [1]
+ ;; Setup the source.
+ (set source (helm-make-source src-name 'helm-grep-class
+ :backend backend
+ :pcre (string-match-p "\\`ack" com)))
+ (helm
+ :sources source
+ :buffer (format "*helm %s*" (helm-grep-command recurse backend))
+ :default default-input
+ :input input
+ :keymap helm-grep-map
+ :history 'helm-grep-history
+ :truncate-lines helm-grep-truncate-lines)))
+
+\f
+;;; zgrep
+;;
+;;
+(defun helm-ff-zgrep-1 (flist recursive)
+ (unwind-protect
+ (let* ((def-dir (or helm-ff-default-directory
+ default-directory))
+ (only (if recursive
+ (or (gethash def-dir helm-rzgrep-cache)
+ (puthash
+ def-dir
+ (helm-walk-directory
+ def-dir
+ :directories nil
+ :path 'full
+ :match helm-zgrep-file-extension-regexp)
+ helm-rzgrep-cache))
+ flist)))
+ (helm-do-grep-1 only recursive 'zgrep))
+ (setq helm-zgrep-recurse-flag nil)))
+
+\f
+;;; transformers
+;;
+;;
+(defun helm-grep-split-line (line)
+ "Split a grep output line."
+ ;; The output of grep may send a truncated line in this chunk,
+ ;; so don't split until grep line is valid, that is
+ ;; once the second part of the line comes with next chunk
+ ;; send by process.
+ (when (string-match helm-grep-split-line-regexp line)
+ ;; Don't use split-string because buffer/file name or string
+ ;; may contain a ":".
+ (cl-loop for n from 1 to 3 collect (match-string n line))))
+
+(defun helm-grep--filter-candidate-1 (candidate &optional dir)
+ (let* ((root (or dir (and helm-grep-default-directory-fn
+ (funcall helm-grep-default-directory-fn))))
+ (ansi-p (string-match-p helm--ansi-color-regexp candidate))
+ (line (if ansi-p (helm--ansi-color-apply candidate) candidate))
+ (split (helm-grep-split-line line))
+ (fname (if (and root split)
+ ;; Filename should always be provided as a local
+ ;; path, if the root directory is remote, the
+ ;; tramp prefix will be added before executing
+ ;; action, see `helm-grep-action' and issue #2032.
+ (expand-file-name (car split)
+ (or (file-remote-p root 'localname)
+ root))
+ (car-safe split)))
+ (lineno (nth 1 split))
+ (str (nth 2 split))
+ (display-fname (cl-ecase helm-grep-file-path-style
+ (basename (and fname (file-name-nondirectory fname)))
+ (absolute fname)
+ (relative (and fname root
+ (file-relative-name fname root))))))
+ (if (and display-fname lineno str)
+ (cons (concat (propertize display-fname
+ 'face 'helm-grep-file
+ 'help-echo (abbreviate-file-name fname)
+ 'helm-grep-fname fname)
+ ":"
+ (propertize lineno 'face 'helm-grep-lineno)
+ ":"
+ (if ansi-p str (helm-grep-highlight-match str t)))
+ line)
+ "")))
+
+(defun helm-grep-filter-one-by-one (candidate)
+ "`filter-one-by-one' transformer function for `helm-do-grep-1'."
+ (let ((helm-grep-default-directory-fn
+ (or helm-grep-default-directory-fn
+ (lambda () (or helm-ff-default-directory
+ (and (null (eq major-mode 'helm-grep-mode))
+ (helm-default-directory))
+ default-directory)))))
+ (if (consp candidate)
+ ;; Already computed do nothing (default as input).
+ candidate
+ (and (stringp candidate)
+ (helm-grep--filter-candidate-1 candidate)))))
+
+(defun helm-grep-highlight-match (str &optional multi-match)
+ "Highlight in string STR all occurences matching `helm-pattern'."
+ (let (beg end)
+ (condition-case-unless-debug nil
+ (with-temp-buffer
+ (insert (propertize str 'read-only nil)) ; Fix (#1176)
+ (goto-char (point-min))
+ (cl-loop for reg in
+ (if multi-match
+ ;; (m)occur.
+ (cl-loop for r in (helm-mm-split-pattern
+ helm-pattern)
+ unless (string-match "\\`!" r)
+ collect
+ (helm-aif (and helm-migemo-mode
+ (assoc r helm-mm--previous-migemo-info))
+ (cdr it) r))
+ ;; async sources (grep, gid etc...)
+ (list helm-input))
+ do
+ (while (and (re-search-forward reg nil t)
+ (> (- (setq end (match-end 0))
+ (setq beg (match-beginning 0))) 0))
+ (helm-add-face-text-properties beg end 'helm-grep-match))
+ do (goto-char (point-min)))
+ (buffer-string))
+ (error nil))))
+
+\f
+;;; Grep from buffer list
+;;
+;;
+(defun helm-grep-buffers-1 (candidate &optional zgrep)
+ "Run grep on all file--buffers or CANDIDATE if it is a file--buffer.
+If one of selected buffers is not a file--buffer,
+it is ignored and grep will run on all others file--buffers.
+If only one candidate is selected and it is not a file--buffer,
+switch to this buffer and run `helm-occur'.
+If a prefix arg is given run grep on all buffers ignoring non--file-buffers."
+ (let* ((prefarg (or current-prefix-arg helm-current-prefix-arg))
+ (helm-ff-default-directory
+ (if (and helm-ff-default-directory
+ (file-remote-p helm-ff-default-directory))
+ default-directory
+ helm-ff-default-directory))
+ (cands (if prefarg
+ (buffer-list)
+ (helm-marked-candidates)))
+ (win-conf (current-window-configuration))
+ ;; Non--fname and remote buffers are ignored.
+ (bufs (cl-loop for buf in cands
+ for fname = (buffer-file-name (get-buffer buf))
+ when (and fname (not (file-remote-p fname)))
+ collect (expand-file-name fname))))
+ (if bufs
+ (if zgrep
+ (helm-do-grep-1 bufs nil 'zgrep)
+ (helm-do-grep-1 bufs))
+ ;; bufs is empty, thats mean we have only CANDIDATE
+ ;; and it is not a buffer-filename, fallback to occur.
+ (switch-to-buffer candidate)
+ (when (get-buffer helm-action-buffer)
+ (kill-buffer helm-action-buffer))
+ (helm-occur)
+ (when (eq helm-exit-status 1)
+ (set-window-configuration win-conf)))))
+
+(defun helm-grep-buffers (candidate)
+ "Action to grep buffers."
+ (helm-grep-buffers-1 candidate))
+
+(defun helm-zgrep-buffers (candidate)
+ "Action to zgrep buffers."
+ (helm-grep-buffers-1 candidate 'zgrep))
+
+\f
+;;; Helm interface for pdfgrep
+;; pdfgrep program <http://pdfgrep.sourceforge.net/>
+;; and a pdf-reader (e.g xpdf) are needed.
+;;
+(defvar helm-pdfgrep-default-function 'helm-pdfgrep-init)
+(defun helm-pdfgrep-init (only-files &optional recurse)
+ "Start an asynchronous pdfgrep process in ONLY-FILES list."
+ (let* ((default-directory (or helm-ff-default-directory
+ default-directory))
+ (fnargs (helm-grep-prepare-candidates
+ (if (file-remote-p default-directory)
+ (mapcar (lambda (x)
+ (file-remote-p x 'localname))
+ only-files)
+ only-files)
+ default-directory))
+ (cmd-line (format (if recurse
+ helm-pdfgrep-default-recurse-command
+ helm-pdfgrep-default-command)
+ helm-pattern
+ fnargs))
+ process-connection-type)
+ ;; Start pdf grep process.
+ (helm-log "Starting Pdf Grep process in directory `%s'" default-directory)
+ (helm-log "Command line used was:\n\n%s"
+ (concat ">>> " (propertize cmd-line 'face 'helm-grep-cmd-line) "\n\n"))
+ (prog1
+ (start-file-process-shell-command
+ "pdfgrep" helm-buffer cmd-line)
+ (message nil)
+ (set-process-sentinel
+ (get-buffer-process helm-buffer)
+ (lambda (_process event)
+ (if (string= event "finished\n")
+ (with-helm-window
+ (setq mode-line-format
+ '(" " mode-line-buffer-identification " "
+ (:eval (format "L%s" (helm-candidate-number-at-point))) " "
+ (:eval (propertize
+ (format "[Pdfgrep Process Finish - %s result(s)] "
+ (max (1- (count-lines
+ (point-min) (point-max))) 0))
+ 'face 'helm-grep-finish))))
+ (force-mode-line-update)
+ (when helm-allow-mouse
+ (helm--bind-mouse-for-selection helm-selection-point)))
+ (helm-log "Error: Pdf grep %s"
+ (replace-regexp-in-string "\n" "" event))))))))
+
+(defun helm-do-pdfgrep-1 (only &optional recurse)
+ "Launch pdfgrep with a list of ONLY files."
+ (unless (executable-find "pdfgrep")
+ (error "Error: No such program `pdfgrep'."))
+ (let (helm-grep-in-recurse) ; recursion is implemented differently in *pdfgrep.
+ ;; When called as action from an other source e.g *-find-files
+ ;; we have to kill action buffer.
+ (when (get-buffer helm-action-buffer)
+ (kill-buffer helm-action-buffer))
+ (setq helm-pdfgrep-targets only)
+ (helm
+ :sources (helm-build-async-source "PdfGrep"
+ :init (lambda ()
+ ;; If `helm-find-files' haven't already started,
+ ;; give a default value to `helm-ff-default-directory'.
+ (setq helm-ff-default-directory (or helm-ff-default-directory
+ default-directory)))
+ :candidates-process (lambda ()
+ (funcall helm-pdfgrep-default-function
+ helm-pdfgrep-targets recurse))
+ :nohighlight t
+ :nomark t
+ :filter-one-by-one #'helm-grep-filter-one-by-one
+ :candidate-number-limit 9999
+ :history 'helm-grep-history
+ :keymap helm-pdfgrep-map
+ :help-message 'helm-pdfgrep-help-message
+ :action #'helm-pdfgrep-action
+ :persistent-help "Jump to PDF Page"
+ :requires-pattern 2)
+ :buffer "*helm pdfgrep*"
+ :history 'helm-grep-history)))
+
+(defun helm-pdfgrep-action (candidate)
+ (helm-grep-action candidate 'pdf))
+
+(defun helm-pdfgrep-action-1 (_split pageno fname)
+ (save-selected-window
+ (start-file-process-shell-command
+ "pdf-reader" nil
+ (format-spec helm-pdfgrep-default-read-command
+ (list (cons ?f fname) (cons ?p pageno))))))
+\f
+;;; 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, PT or RG.
+
+Takes three format specs, the first for type(s), the second for pattern
+and the third for directory.
+
+You can use safely \"--color\" (used by default) with AG RG and PT.
+
+For ripgrep here is the command line to use:
+
+ rg --color=always --smart-case --no-heading --line-number %s %s %s
+
+NOTE: Old versions of ripgrep was not supporting colors in emacs and a
+workaround had to be used (i.e prefixing command line with
+\"TERM=eterm-color\"), this is no more needed.
+See issue <https://github.com/BurntSushi/ripgrep/issues/182> for more infos.
+
+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.
+
+When modifying the default colors of matches with e.g \"--color-match\" option of AG
+you may want to modify as well `helm-grep-ag-pipe-cmd-switches' to have all matches
+colorized with same color in multi match."
+ :group 'helm-grep
+ :type 'string)
+
+(defun 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\"
+Ripgrep (rg) types are also supported if this backend is used."
+ (with-temp-buffer
+ (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 (helm-mm-split-pattern pattern t))
+ (pipe-switches (mapconcat 'identity helm-grep-ag-pipe-cmd-switches " "))
+ (pipe-cmd (helm-acase (helm-grep--ag-command)
+ (("ag" "pt")
+ (format "%s -S --color%s" it (concat " " pipe-switches)))
+ ("rg" (format "rg -N -S --color=always%s"
+ (concat " " pipe-switches)))))
+ (cmd (format helm-grep-ag-command
+ (mapconcat 'identity type " ")
+ (shell-quote-argument (car patterns))
+ (shell-quote-argument directory))))
+ (helm-aif (cdr patterns)
+ (concat cmd (cl-loop for p in it concat
+ (format " | %s %s"
+ pipe-cmd (shell-quote-argument p))))
+ cmd)))
+
+(defun helm-grep-ag-init (directory &optional type)
+ "Start AG process in DIRECTORY maybe searching only files of type TYPE."
+ (let ((default-directory (or helm-ff-default-directory
+ (helm-default-directory)
+ default-directory))
+ (cmd-line (helm-grep-ag-prepare-cmd-line
+ helm-pattern (or (file-remote-p directory 'localname)
+ directory)
+ type))
+ (start-time (float-time))
+ (proc-name (helm-grep--ag-command)))
+ (set (make-local-variable 'helm-grep-last-cmd-line) cmd-line)
+ (helm-log "Starting %s process in directory `%s'"
+ proc-name directory)
+ (helm-log "Command line used was:\n\n%s"
+ (concat ">>> " cmd-line "\n\n"))
+ (prog1
+ (start-file-process-shell-command
+ proc-name helm-buffer cmd-line)
+ (set-process-sentinel
+ (get-buffer-process helm-buffer)
+ (lambda (process event)
+ (let* ((err (process-exit-status process))
+ (noresult (= err 1)))
+ (cond (noresult
+ (with-helm-buffer
+ (insert (concat "* Exit with code 1, no result found,"
+ " command line was:\n\n "
+ (propertize helm-grep-last-cmd-line
+ 'face 'helm-grep-cmd-line)))
+ (setq mode-line-format
+ `(" " mode-line-buffer-identification " "
+ (:eval (format "L%s" (helm-candidate-number-at-point))) " "
+ (:eval (propertize
+ (format
+ "[%s process finished - (no results)] "
+ ,(upcase proc-name))
+ 'face 'helm-grep-finish))))))
+ ((string= event "finished\n")
+ (helm-log "%s process finished with %s results in %fs"
+ proc-name
+ (helm-get-candidate-number)
+ (- (float-time) start-time))
+ (helm-maybe-show-help-echo)
+ (with-helm-window
+ (setq mode-line-format
+ `(" " mode-line-buffer-identification " "
+ (:eval (format "L%s" (helm-candidate-number-at-point))) " "
+ (:eval (propertize
+ (format
+ "[%s process finished in %.2fs - (%s results)] "
+ ,(upcase proc-name)
+ ,(- (float-time) start-time)
+ (helm-get-candidate-number))
+ 'face 'helm-grep-finish))))
+ (force-mode-line-update)
+ (when helm-allow-mouse
+ (helm--bind-mouse-for-selection helm-selection-point))))
+ (t (helm-log
+ "Error: %s %s"
+ proc-name
+ (replace-regexp-in-string "\n" "" event))))))))))
+
+(defclass helm-grep-ag-class (helm-source-async)
+ ((nohighlight :initform t)
+ (pcre :initarg :pcre :initform t
+ :documentation
+ " Backend is using pcre regexp engine when non--nil.")
+ (keymap :initform helm-grep-map)
+ (history :initform 'helm-grep-ag-history)
+ (help-message :initform 'helm-grep-help-message)
+ (filter-one-by-one :initform 'helm-grep-filter-one-by-one)
+ (persistent-action :initform 'helm-grep-persistent-action)
+ (persistent-help :initform "Jump to line (`C-u' Record in mark ring)")
+ (candidate-number-limit :initform 99999)
+ (requires-pattern :initform 2)
+ (nomark :initform t)
+ (action :initform 'helm-grep-actions)
+ (group :initform 'helm-grep)))
+
+(defvar helm-source-grep-ag nil)
+
+(defmethod helm--setup-source ((source helm-grep-ag-class))
+ (call-next-method)
+ (helm-aif (and helm-follow-mode-persistent
+ helm-source-grep-ag
+ (assoc-default 'follow helm-source-grep-ag))
+ (setf (slot-value source 'follow) it)))
+
+(defun helm-grep-ag-1 (directory &optional type)
+ "Start helm ag in DIRECTORY maybe searching in files of type TYPE."
+ (setq helm-source-grep-ag
+ (helm-make-source (upcase (helm-grep--ag-command)) 'helm-grep-ag-class
+ :header-name (lambda (name)
+ (format "%s [%s]"
+ name (abbreviate-file-name directory)))
+ :candidates-process
+ (lambda () (helm-grep-ag-init directory type))))
+ (helm :sources 'helm-source-grep-ag
+ :keymap helm-grep-map
+ :history 'helm-grep-ag-history
+ :truncate-lines helm-grep-truncate-lines
+ :buffer (format "*helm %s*" (helm-grep--ag-command))))
+
+(defun helm-grep-ag (directory with-types)
+ "Start grep AG in DIRECTORY.
+When WITH-TYPES is non-nil provide completion on AG types."
+ (require 'helm-adaptive)
+ (helm-grep-ag-1 directory
+ (helm-aif (and with-types
+ (helm-grep-ag-get-types))
+ (helm-comp-read
+ "Ag type: " it
+ :must-match t
+ :marked-candidates t
+ :fc-transformer 'helm-adaptive-sort
+ :buffer "*helm ag types*"))))
+
+;;; Git grep
+;;
+;;
+(defvar helm-source-grep-git nil)
+
+(defcustom helm-grep-git-grep-command
+ "git --no-pager grep -n%cH --color=always --full-name -e %p -- %f"
+ "The git grep default command line.
+The option \"--color=always\" can be used safely.
+The color of matched items can be customized in your .gitconfig
+See `helm-grep-default-command' for more infos.
+
+The \"--exclude-standard\" and \"--no-index\" switches allow
+skipping unwanted files specified in ~/.gitignore_global
+and searching files not already staged (not enabled by default).
+
+You have also to enable this in global \".gitconfig\" with
+ \"git config --global core.excludesfile ~/.gitignore_global\"."
+ :group 'helm-grep
+ :type 'string)
+
+(defun helm-grep-git-1 (directory &optional all default input)
+ "Run git-grep on DIRECTORY.
+If DIRECTORY is not inside or part of a git repo exit with error.
+If optional arg ALL is non-nil grep the whole repo otherwise start
+at DIRECTORY.
+Arg DEFAULT is what you will have with `next-history-element',
+arg INPUT is what you will have by default at prompt on startup."
+ (require 'vc)
+ (let* (helm-grep-default-recurse-command
+ ;; Expand filename of each candidate with the git root dir.
+ ;; The filename will be in the helm-grep-fname prop.
+ (helm-grep-default-directory-fn (lambda ()
+ (vc-find-root directory ".git")))
+ (helm-ff-default-directory (funcall helm-grep-default-directory-fn)))
+ (cl-assert helm-ff-default-directory nil "Not inside a Git repository")
+ (helm-do-grep-1 (if all '("") `(,(expand-file-name directory)))
+ nil 'git nil default input 'helm-source-grep-git)))
+
+\f
+;;;###autoload
+(defun helm-do-grep-ag (arg)
+ "Preconfigured helm for grepping with AG in `default-directory'.
+With prefix-arg prompt for type if available with your AG version."
+ (interactive "P")
+ (require 'helm-files)
+ (helm-grep-ag (expand-file-name default-directory) arg))
+
+;;;###autoload
+(defun helm-grep-do-git-grep (arg)
+ "Preconfigured helm for git-grepping `default-directory'.
+With a prefix arg ARG git-grep the whole repository."
+ (interactive "P")
+ (require 'helm-files)
+ (helm-grep-git-1 default-directory arg))
+
+
+(provide 'helm-grep)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-grep.el ends here
--- /dev/null
+;;; helm-help.el --- Help messages for Helm. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Code:
+(require 'helm)
+
+(defvar helm-org-headings--nofilename)
+(declare-function helm-source-org-headings-for-files "helm-org.el")
+
+\f
+(defgroup helm-help nil
+ "Embedded help for `helm'."
+ :group 'helm)
+
+(defface helm-helper
+ '((t :inherit helm-header))
+ "Face for Helm help string in minibuffer."
+ :group 'helm-help)
+\f
+(defvar helm-help--string-list '(helm-help-message
+ helm-buffer-help-message
+ helm-ff-help-message
+ helm-read-file-name-help-message
+ helm-generic-file-help-message
+ helm-grep-help-message
+ helm-pdfgrep-help-message
+ helm-etags-help-message
+ helm-ucs-help-message
+ helm-bookmark-help-message
+ helm-esh-help-message
+ helm-buffers-ido-virtual-help-message
+ helm-moccur-help-message
+ helm-top-help-message
+ helm-el-package-help-message
+ helm-M-x-help-message
+ helm-imenu-help-message
+ helm-colors-help-message
+ helm-semantic-help-message
+ helm-kmacro-help-message))
+
+(defvar helm-documentation-buffer-name "*helm documentation*")
+\f
+;;;###autoload
+(defun helm-documentation ()
+ "Preconfigured Helm for Helm documentation.
+With a prefix arg refresh the documentation.
+
+Find here the documentation of all documented sources."
+ (interactive)
+ (require 'helm-org)
+ (with-current-buffer (get-buffer-create helm-documentation-buffer-name)
+ (let ((inhibit-read-only t))
+ (erase-buffer)
+ (cl-loop for elm in helm-help--string-list
+ for str = (helm-interpret-value elm)
+ do (insert (substitute-command-keys str) "\n\n"))
+ (org-mode))
+ (setq buffer-read-only t)
+ (view-mode))
+ (let ((helm-org-headings--nofilename t))
+ (helm :sources (helm-source-org-headings-for-files
+ (list (get-buffer helm-documentation-buffer-name)))
+ :candidate-number-limit 99999
+ :buffer "*helm doc*")))
+\f
+;;; Local help messages.
+
+;;; `helm-buffer-list' help
+;;
+;;
+(defvar helm-buffer-help-message
+ "* Helm Buffer
+
+** Tips
+
+*** Completion
+
+**** Major-mode
+
+You can enter a partial major-mode name (e.g. lisp, sh) to narrow down buffers.
+To specify the major-mode, prefix it with \"*\" e.g. \"*lisp\".
+
+If you want to match all buffers but the ones with a specific major-mode
+\(negation), prefix the major-mode with \"!\" e.g. \"*!lisp\".
+
+If you want to specify more than one major-mode, separate them with \",\",
+e.g. \"*!lisp,!sh,!fun\" lists all buffers but the ones in lisp-mode, sh-mode
+and fundamental-mode.
+
+Then enter a space followed by a pattern to narrow down to buffers matching this
+pattern.
+
+**** Search inside buffers
+
+If you enter a space and a pattern prefixed by \"@\", Helm searches for text
+matching this pattern \*inside* the buffer (i.e. not in the name of the buffer).
+
+If you enter a pattern prefixed with an escaped \"@\", Helm searches for a
+buffer matching \"@pattern\" but does not search inside.
+
+**** Search by directory name
+
+If you prefix the pattern with \"/\", Helm matches over the directory names
+of the buffers.
+
+This feature can be used to narrow down the search to one directory while
+subsequent strings entered after a space match over the buffer name only.
+
+Note that negation is not supported for matching on buffer filename.
+
+Starting from Helm v1.6.8, you can specify more than one directory.
+
+**** Fuzzy matching
+
+`helm-buffers-fuzzy-matching' turns on fuzzy matching on buffer names, but not
+on directory names or major modes. A pattern starting with \"^\" disables fuzzy
+matching and matches by exact regexp.
+
+**** Examples
+
+With the following pattern
+
+ \"*lisp ^helm @moc\"
+
+Helm narrows down the list by selecting only the buffers that are in lisp mode,
+start with \"helm\" and which content matches \"moc\".
+
+Without the \"@\"
+
+ \"*lisp ^helm moc\"
+
+Helm looks for lisp mode buffers starting with \"helm\" and containing \"moc\"
+in their name.
+
+With this other pattern
+
+ \"*!lisp !helm\"
+
+Helm narrows down to buffers that are not in \"lisp\" mode and that do not match
+\"helm\".
+
+With this last pattern
+
+ /helm/ w3
+
+Helm narrows down to buffers that are in any \"helm\" subdirectory and
+matching \"w3\".
+
+*** Creating buffers
+
+When creating a new buffer, use `\\[universal-argument]' to choose a mode from a
+list. This list is customizable, see `helm-buffers-favorite-modes'.
+
+*** Killing buffers
+
+You can kill buffers either one by one or all the marked buffers at once.
+
+One kill-buffer command leaves Helm while the other is persistent. Run the
+persistent kill-buffer command either with the regular
+`helm-execute-persistent-action' called with a prefix argument (`\\[universal-argument] \\<helm-map>\\[helm-execute-persistent-action]')
+or with its specific command `helm-buffer-run-kill-persistent'. See the
+bindings below.
+
+*** Switching to buffers
+
+To switch to a buffer, press RET, to switch to a buffer in another window, select this buffer
+and press \\<helm-buffer-map>\\[helm-buffer-switch-other-window], when called with a prefix arg
+the buffer will be displayed vertically in other window.
+If you mark more than one buffer, the marked buffers will be displayed in different windows.
+
+*** Meaning of colors and prefixes for buffers
+
+Remote buffers are prefixed with '@'.
+Red => Buffer's file was modified on disk by an external process.
+Indianred2 => Buffer exists but its file has been deleted.
+Orange => Buffer is modified and not saved to disk.
+Italic => A non-file buffer.
+Yellow => Tramp archive buffer.
+
+** Commands
+\\<helm-buffer-map>
+\\[helm-buffer-run-zgrep]\t\tGrep Buffer(s) works as zgrep too (`\\[universal-argument]' to grep all buffers but non-file buffers).
+\\[helm-buffers-run-multi-occur]\t\tMulti-Occur buffer or marked buffers (`\\[universal-argument]' to toggle force-searching current-buffer).
+\\[helm-buffer-switch-other-window]\t\tSwitch to other window.
+\\[helm-buffer-switch-other-frame]\t\tSwitch to other frame.
+\\[helm-buffers-run-browse-project]\t\tBrowse project from buffer.
+\\[helm-buffer-run-query-replace-regexp]\t\tQuery-replace-regexp in marked buffers.
+\\[helm-buffer-run-query-replace]\t\tQuery-replace in marked buffers.
+\\[helm-buffer-run-ediff]\t\tEdiff current buffer with candidate. With two marked buffers, ediff those buffers.
+\\[helm-buffer-run-ediff-merge]\t\tEdiff-merge current buffer with candidate. With two marked buffers, ediff-merge those buffers.
+\\[helm-buffer-diff-persistent]\t\tToggle Diff-buffer with saved file without leaving Helm.
+\\[helm-buffer-revert-persistent]\t\tRevert buffer without leaving Helm.
+\\[helm-buffer-save-persistent]\t\tSave buffer without leaving Helm.
+\\[helm-buffer-run-kill-buffers]\t\tDelete marked buffers and leave Helm.
+\\[helm-buffer-run-kill-persistent]\t\tDelete buffer without leaving Helm.
+\\[helm-buffer-run-rename-buffer]\t\tRename buffer.
+\\[helm-toggle-all-marks]\t\tToggle all marks.
+\\[helm-mark-all]\t\tMark all.
+\\[helm-toggle-buffers-details]\t\tToggle details.
+\\[helm-buffers-toggle-show-hidden-buffers]\t\tShow hidden buffers.
+\\[helm-buffers-mark-similar-buffers]\t\tMark all buffers of the same type (color) as current buffer.")
+
+;;; Find files help (`helm-find-files')
+;;
+;;
+(defvar helm-ff-help-message
+ "* Helm Find Files
+
+** Tips
+
+*** Navigation summary
+
+For a better experience you can enable auto completion by setting
+`helm-ff-auto-update-initial-value' to non-nil in your init file. It is not
+enabled by default to not confuse new users.
+
+**** Use `\\<helm-find-files-map>\\[helm-execute-persistent-action]' (persistent action) on a directory to go down one level
+
+On a symlinked directory a prefix argument expands to its true name.
+
+**** Use `\\<helm-find-files-map>\\[helm-find-files-up-one-level]' on a directory to go up one level
+
+**** Use `\\<helm-find-files-map>\\[helm-find-files-down-last-level]' to walk back the resulting tree of all the `\\<helm-map>\\[helm-execute-persistent-action]' you did
+
+The tree is reinitialized each time you browse a new tree with
+`\\<helm-map>\\[helm-execute-persistent-action]' or by entering some pattern in the prompt.
+
+**** `RET' behavior
+
+It behaves differently depending on `helm-selection' (current candidate in helm-buffer):
+
+- candidate basename is \".\" => Open it in dired.
+- candidate is a directory => Expand it.
+- candidate is a file => Open it.
+- marked candidates (1+) => Open them with default action.
+
+Note that when copying, renaming, etc. from `helm-find-files' the
+destination file is selected with `helm-read-file-name'.
+
+To avoid confusion when using `read-file-name' or `read-directory-name', `RET'
+follows its standard Emacs behaviour, i.e. it exits the minibuffer as soon as
+you press `RET'. If you want the same behavior as in `helm-find-files', bind
+`helm-ff-RET' to the `helm-read-file-map':
+
+ (define-key helm-read-file-map (kbd \"RET\") 'helm-ff-RET)
+
+*** Find file at point
+
+Helm uses `ffap' partially or completely to find file at point depending on the
+value of `helm-ff-guess-ffap-filenames': if non-nil, support is complete
+\(annoying), if nil, support is partial.
+
+**** Find file at line number
+
+When text at point is in the form of
+
+ ~/elisp/helm/helm.el:1234
+
+Helm finds this file at the indicated line number, here 1234.
+
+**** Find URL at point
+
+When a URL is found at point, Helm expands to that URL only.
+Pressing `RET' opens that URL using `browse-url-browser-function'.
+
+**** Find e-mail address at point
+
+When an e-mail address is found at point, Helm expands to this e-mail address
+prefixed with \"mailto:\". Pressing `RET' opens a message buffer with that
+e-mail address.
+
+*** Quick pattern expansion
+
+**** Enter `~/' at end of pattern to quickly reach home directory
+
+**** Enter `/' at end of pattern to quickly reach the file system root
+
+**** Enter `./' at end of pattern to quickly reach `default-directory'
+
+\(As per its value at the beginning of the session.)
+
+If you already are in the `default-directory' this will move the cursor to the top.
+
+**** Enter `../' at end of pattern will reach upper directory, moving cursor to the top
+
+This is different from using `\\<helm-find-files-map>\\[helm-find-files-up-one-level]' in that it moves
+the cursor to the top instead of remaining on the previous subdir name.
+
+**** Enter `..name/' at end of pattern to start a recursive search
+
+It searches directories matching \"name\" under the current directory, see the
+\"Recursive completion on subdirectories\" section below for more details.
+
+**** Any environment variable (e.g. `$HOME') at end of pattern gets expanded
+
+**** Any valid filename yanked after pattern gets expanded
+
+**** Special case: URL at point
+
+The quick expansions do not take effect after end a URL, you must kill the
+pattern first (`\\[helm-delete-minibuffer-contents]').
+
+*** Helm-find-files supports fuzzy matching
+
+It starts from the third character of the pattern.
+
+For instance \"fob\" or \"fbr\" will complete \"foobar\" but \"fb\" needs a
+third character in order to complete it.
+
+*** Use `\\[universal-argument] \\[helm-execute-persistent-action]' or `\\[helm-follow-action-forward]' to display an image
+
+*** `\\[helm-execute-persistent-action]' on a filename expands to that filename in the Helm buffer
+
+Second hit displays the buffer filename.
+Third hit kills the buffer filename.
+Note: `\\[universal-argument] \\[helm-execute-persistent-action]' displays the buffer directly.
+
+*** Browse images directories with `helm-follow-mode' and navigate up/down
+
+You can also use `helm-follow-action-forward' and `helm-follow-action-backward' with
+`\\[helm-follow-action-forward]' and `\\[helm-follow-action-backward]' respectively.
+
+*** Toggle auto-completion with `\\[helm-ff-run-toggle-auto-update]'
+
+It is useful when trying to create a new file or directory and you don't want
+Helm to complete what you are writing.
+
+Note: On a terminal, the default binding `C-<backspace>' may not work.
+In this case use `C-c <backspace>'.
+
+*** You can create a new directory and a new file at the same time
+
+Simply write the path in the prompt and press `RET', e.g.
+\"~/new/newnew/newnewnew/my_newfile.txt\".
+
+*** To create a new directory, append a \"/\" to the new name and press `RET'
+
+*** To create a new file, enter a filename not ending with \"/\"
+
+Note that when you enter a new name, this one is prefixed with
+\[?] if you are in a writable directory. If you are in a directory
+where you have no write permission the new file name is not
+prefixed and is colored in red. There is not such distinction
+when using tramp, new filename just appear on top of buffer.
+
+*** Recursive search from Helm-find-files
+
+**** You can use Helm-browse-project (see binding below)
+
+- With no prefix argument:
+If the current directory is under version control with either git or hg and
+helm-ls-git and/or helm-ls-hg are installed, it lists all the files under
+version control. Otherwise it falls back to Helm-find-files. See
+https://github.com/emacs-helm/helm-ls-git and
+https://github.com/emacs-helm/helm-ls-hg.
+
+- With one prefix argument:
+List all the files under this directory and other subdirectories
+\(recursion) and this list of files will be cached.
+
+- With two prefix arguments:
+Same but the cache is refreshed.
+
+**** You can start a recursive search with \"locate\" or \"find\"
+
+See \"Note\" in the [[Recusive completion on subdirectories][section on subdirectories]].
+
+Using \"locate\", you can enable the local database with a prefix argument. If the
+local database doesn't already exists, you will be prompted for its creation.
+If it exists and you want to refresh it, give it two prefix args.
+
+When using locate the helm-buffer remains empty until you type something.
+Regardless Helm uses the basename of the pattern entered in the helm-find-files
+session by default. Hitting `\\[next-history-element]' should just kick in the
+locate search with this pattern. If you want Helm to automatically do this, add
+`helm-source-locate' to `helm-sources-using-default-as-input'.
+
+**** Recursive completion on subdirectories
+
+Starting from the directory you are currently browsing, it is possible to have
+completion of all directories underneath. Say you are at \"/home/you/foo/\" and
+you want to go to \"/home/you/foo/bar/baz/somewhere/else\", simply type
+\"/home/you/foo/..else\" and hit `\\[helm-execute-persistent-action]' or enter
+the final \"/\". Helm will then list all possible directories under \"foo\"
+matching \"else\".
+
+Entering two spaces before \"else\" instead of two dots also works.
+
+Note: Completion on subdirectories uses \"locate\" as backend, you can configure
+the command with `helm-locate-recursive-dirs-command'. Because this completion
+uses an index, the directory tree displayed may be out-of-date and not reflect
+the latest change until you update the index (using \"updatedb\" for \"locate\").
+
+If for some reason you cannot use an index, the \"find\" command from
+\"findutils\" can be used instead. It will be slower though. You need to pass
+the basedir as first argument of \"find\" and the subdir as the value for
+'-(i)regex' or '-(i)name' with the two format specs that are mandatory in
+`helm-locate-recursive-dirs-command'.
+
+Examples:
+- \"find %s -type d -name '*%s*'\"
+- \"find %s -type d -regex .*%s.*$\"
+
+*** Insert filename at point or complete filename at point
+
+On insertion (not on completion, i.e. there is nothing at point):
+
+- `\\[helm-ff-run-complete-fn-at-point]': insert absolute file name.
+- `\\[universal-argument] \\[helm-ff-run-complete-fn-at-point]': insert abbreviated file name.
+- `\\[universal-argument] \\[universal-argument] \\[helm-ff-run-complete-fn-at-point]': insert relative file name.
+
+On completion:
+
+- Target starts with \"~/\": insert abbreviate file name.
+- target starts with \"/\" or \"[a-z]:/\": insert full path.
+- Otherwise: insert relative file name.
+
+*** Use the wildcard to select multiple files
+
+Use of wilcard is supported to run an action over a set of files.
+
+Example: You can copy all the files with \".el\" extension by using \"*.el\" and
+then run copy action.
+
+Similarly, \"**.el\" (note the two stars) will recursively select all \".el\"
+files under the current directory.
+
+Note that when recursively copying files, you may have files with same name
+dispatched across different subdirectories, so when copying them in the same
+directory they will get overwritten. To avoid this Helm has a special action
+called \"backup files\" that has the same behavior as the command line \"cp -f
+--backup=numbered\": it allows you to copy many files with the same name from
+different subdirectories into one directory. Files with same name are renamed
+as follows: \"foo.txt.~1~\". Like with the --force option of cp, it is possible
+to backup files in current directory.
+
+This command is available only when `dired-async-mode' is active.
+
+When using an action that involves an external backend (e.g. grep), using \"**\"
+is not recommended (even thought it works fine) because it will be slower to
+select all the files. You are better off leaving the backend to do it, it will
+be faster. However, if you know you have not many files it is reasonable to use
+this, also using not recursive wilcard (e.g. \"*.el\") is perfectly fine for
+this.
+
+The \"**\" feature is active by default in the option `helm-file-globstar'. It
+is different from the Bash \"shopt globstar\" feature in that to list files with
+a named extension recursively you would write \"**.el\" whereas in Bash it would
+be \"**/*.el\". Directory selection with \"**/\" like Bash \"shopt globstar\"
+option is not supported yet.
+
+*** Query replace regexp on filenames
+
+Replace different parts of a file basename with something else.
+
+When calling this action you will be prompted twice as with
+`query-replace', first for the matching expression of the text to
+replace and second for the replacement text. Several facilities,
+however, are provided to make the two prompts more powerfull.
+
+**** Syntax of the first prompt
+
+In addition to simple regexps, these shortcuts are available:
+
+- Basename without extension => \"%.\"
+- Only extension => \".%\"
+- Substring => \"%:<from>:<to>\"
+- Whole basename => \"%\"
+
+**** Syntax of the second prompt
+
+In addition to a simple string to use as replacement, here is what you can use:
+
+- A placeholder refering to what you have selected in the first prompt: \"\\@\".
+
+After this placeholder you can use a search-and-replace syntax à-la sed:
+
+ \"\\@/<regexp>/<replacement>/
+
+You can select a substring from the string represented by the placeholder:
+
+ \"\\@:<from>:<to>\"
+
+- A special character representing a number which is incremented: \"\\#\".
+
+- Shortcuts for `upcase', `downcase' and `capitalize'
+are available as`%u', `%d' and `%c' respectively.
+
+**** Examples
+
+***** Recursively rename all files with \".JPG\" extension to \".jpg\"
+
+Use the `helm-file-globstar' feature described in [[Using wildcard to select multiple files][recursive globbing]]
+by entering \"**.JPG\" at the end of the Helm-find-files pattern, then hit
+\\<helm-map>\\[helm-ff-query-replace-on-filenames]: First \"JPG\", then \"jpg\"
+and hit `RET'.
+
+Alternatively you can enter \".%\" at the first prompt, then \"jpg\" and hit
+`RET'. Note that when using this instead of using \"JPG\" at the first prompt,
+all extensions will be renamed to \"jpg\" even if the extension of one of the
+files is, say, \"png\". If you want to keep the original extension you can use
+\"%d\" at the second prompt (downcase).
+
+***** Batch-rename files from number 001 to 00x
+
+Use \"\\#\" inside the second prompt.
+
+Example 1: To rename the files
+
+ foo.jpg
+ bar.jpg
+ baz.jpg
+
+to
+
+ foo-001.jpg
+ foo-002.jpg
+ foo-003.jpg
+
+use \"%.\" as matching regexp and \"foo-\\#\" as replacement string.
+
+Example 2: To rename the files
+
+ foo.jpg
+ bar.jpg
+ baz.jpg
+
+to
+
+ foo-001.jpg
+ bar-002.jpg
+ baz-003.jpg
+
+use as matching regexp \"%.\" and as replacement string \"\\@-\\#\".
+
+***** Replace a substring
+
+Use \"%:<from>:<to>\".
+
+Example: To rename files
+
+ foo.jpg
+ bar.jpg
+ baz.jpg
+
+to
+
+ fOo.jpg
+ bAr.jpg
+ bAz.jpg
+
+use as matching regexp \"%:1:2\" and as replacement string \"%u\" (upcase).
+
+Note that you \*cannot* use \"%.\" and \".%\" along with substring replacement.
+
+***** Modify the string from the placeholder (\\@)
+
+- By substring, i.e. only using the substring of the placeholder: \"\\@:<from>:<to>\".
+The length of placeholder is used for <to> when unspecified.
+
+Example 1: \"\\@:0:2\" replaces from the beginning to the second char of the placeholder.
+
+Example 2: \\@:2: replaces from the second char of the placeholder to the end.
+
+- By search-and-replace: \"\\@/<regexp>/<replacement>/\".
+
+Incremental replacement is also handled in <replacement>.
+
+Example 3: \"\\@/foo/bar/\" replaces \"foo\" by \"bar\" in the placeholder.
+
+Example 4: \"\\@/foo/-\\#/\" replaces \"foo\" in the placeholder by 001, 002, etc.
+
+***** Clash in replacements (avoid overwriting files)
+
+When performing any of these replacement operations you may end up with same
+names as replacement. In such cases Helm numbers the file that would otherwise
+overwritten. For instance, should you remove the \"-m<n>\" part from the files
+\"emacs-m1.txt\", \"emacs-m2.txt\" and \"emacs-m3.txt\" you would end up with
+three files named \"emacs.txt\", the second renaming overwriting first file, and
+the third renaming overwriting second file and so on. Instead Helm will
+automatically rename the second and third files as \"emacs(1).txt\" and
+\"emacs(2).txt\" respectively.
+
+***** Query-replace on filenames vs. serial-rename action
+
+Unlike the [[Serial renaming][serial rename]] actions, the files renamed with
+the query-replace action stay in their initial directory and are not moved to
+the current directory. As such, using \"\\#\" to serial-rename files only makes
+sense for files inside the same directory. It even keeps renaming files
+with an incremental number in the next directories.
+
+*** Serial-rename
+
+You can use the serial-rename actions to rename, copy or symlink marked files to
+a specific directory or in the current directory with all the files numbered
+incrementally.
+
+- Serial-rename by renaming:
+Rename all marked files with incremental numbering to a specific directory.
+
+- Serial-rename by copying:
+Copy all marked files with incremental numbering to a specific directory.
+
+- Serial-rename by symlinking:
+Symlink all marked files with incremental numbering to a specific directory.
+
+*** Edit marked files in a dired buffer
+
+You can open a dired buffer containing only marked files with `\\<helm-find-files-map>\\[helm-ff-run-marked-files-in-dired]'.
+With a prefix argument you can open this same dired buffer in wdired mode for
+editing. Note that wildcards are supported as well, so you can use e.g.
+\"*.txt\" to select all \".txt\" files in the current directory or \"**.txt\" to
+select all files recursively from the current directory.
+See [[Use the wildcard to select multiple files]] section above.
+
+*** Defining default target directory for copying, renaming, etc
+
+You can customize `helm-dwim-target' to behave differently depending on the
+windows open in the current frame. Default is to provide completion on all
+directories associated to each window.
+
+*** Copying and renaming asynchronously
+
+If you have the async library installed (if you got Helm from MELPA you do), you
+can use it for copying/renaming files by enabling `dired-async-mode'.
+
+Note that even when async is enabled, running a copy/rename action with a prefix
+argument will execute action synchronously. Moreover it will follow the first
+file of the marked files in its destination directory.
+
+When `dired-async-mode' is enabled, an additional action named \"Backup files\"
+will be available. (Such command is not natively available in Emacs).
+See [[Use the wildcard to select multiple files]] for details.
+
+*** Bookmark the `helm-find-files' session
+
+You can bookmark the `helm-find-files' session with `\\[helm-ff-bookmark-set]'.
+You can later retrieve these bookmarks by calling `helm-filtered-bookmarks'
+or, from the current `helm-find-files' session, by hitting `\\[helm-find-files-toggle-to-bookmark]'.
+
+*** Grep files from `helm-find-files'
+
+You can grep individual files from `helm-find-files' by using
+\`\\<helm-find-files-map>\\[helm-ff-run-grep]'. This same command can also
+recursively grep files from the current directory when called with a prefix
+argument. In this case you will be prompted for the file extensions to use
+\(grep backend) or the types of files to use (ack-grep backend). See the
+`helm-grep-default-command' documentation to set this up. For compressed files
+or archives, use zgrep with \`\\<helm-find-files-map>\\[helm-ff-run-zgrep]'.
+
+Otherwise you can use recursive commands like \`\\<helm-find-files-map>\\[helm-ff-run-grep-ag]' or `\\<helm-find-files-map>\\[helm-ff-run-git-grep]'
+that are much faster than using `\\<helm-find-files-map>\\[helm-ff-run-grep]' with a prefix argument.
+See `helm-grep-ag-command' and `helm-grep-git-grep-command' to set this up.
+
+You can also use \"id-utils\"' GID with \`\\<helm-find-files-map>\\[helm-ff-run-gid]'
+by creating an ID index file with the \"mkid\" shell command.
+
+All those grep commands use the symbol at point as the default pattern.
+Note that default is different from input (nothing is added to the prompt until
+you hit `\\[next-history-element]').
+
+**** Grepping on remote files
+
+On remote files grep is not well supported by TRAMP unless you suspend updates before
+entering the pattern and re-enable it once your pattern is ready.
+To toggle suspend-update, use `\\<helm-map>\\[helm-toggle-suspend-update]'.
+
+*** Setting up aliases in Eshell allows you to set up powerful customized commands
+
+Adding Eshell aliases to your `eshell-aliases-file' or using the
+`alias' command from Eshell allows you to create personalized
+commands not available in `helm-find-files' actions and use them
+from `\\<helm-find-files-map>\\[helm-ff-run-eshell-command-on-file]'.
+
+Example: You want a command to uncompress some \"*.tar.gz\" files from `helm-find-files':
+
+1) Create an Eshell alias named, say, \"untargz\" with the command
+\"alias untargz tar zxvf $*\".
+
+2) Now from `helm-find-files' select the \"*.tar.gz\" file (you can also
+mark files if needed) and hit `\\<helm-find-files-map>\\[helm-ff-run-eshell-command-on-file]'.
+
+Note: When using marked files with this, the meaning of the prefix argument is
+quite subtle. Say you have \"foo\", \"bar\" and \"baz\" marked; when you run
+the alias command `example' on these files with no prefix argument it will run
+`example' sequentially on each file:
+
+$ example foo
+$ example bar
+$ example baz
+
+With a prefix argument however it will apply `example' on all files at once:
+
+$ example foo bar baz
+
+Of course the alias command should support this.
+
+*** Using TRAMP with `helm-find-files' to read remote directories
+
+`helm-find-files' works fine with TRAMP despite some limitations.
+
+- Grepping files is not very well supported when used incrementally.
+See [[Grepping on remote files]].
+
+- Locate does not work on remote directories.
+
+**** A TRAMP syntax crash course
+
+Please refer to TRAMP's documentation for more details.
+
+- Connect to host 192.168.0.4 as user \"foo\":
+
+/scp:192.168.0.4@foo:
+
+- Connect to host 192.168.0.4 as user \"foo\" on port 2222:
+
+/scp:192.168.0.4@foo#2222:
+
+- Connect to host 192.168.0.4 as root using multihops syntax:
+
+/ssh:192.168.0.4@foo|sudo:192.168.0.4:
+
+Note: You can also use `tramp-default-proxies-alist' when connecting often to
+the same hosts.
+
+As a rule of thumb, prefer the scp method unless using multihops (which only
+works with the ssh method), especially when copying large files.
+
+You need to hit `C-j' once on top of a directory on the first connection
+to complete the pattern in the minibuffer.
+
+**** Display color for directories, symlinks etc... with tramp
+
+Starting at helm version 2.9.7 it is somewhat possible to
+colorize fnames by listing files without loosing performances with
+external commands (ls and awk) if your system is compatible.
+For this you can use `helm-list-dir-external' as value
+for `helm-list-directory-function'.
+
+See `helm-list-directory-function' documentation for more infos.
+
+**** Completing host
+
+As soon as you enter the first \":\" after method e.g =/scp:= you will
+have some completion about previously used hosts or from your =~/.ssh/config=
+file, hitting `\\[helm-execute-persistent-action]' or `right' on a candidate will insert this host in minibuffer
+without addind the ending \":\", second hit insert the last \":\".
+As soon the last \":\" is entered TRAMP will kick in and you should see the list
+of candidates soon after.
+
+When connection fails, be sure to delete your TRAMP connection with M-x
+`helm-delete-tramp-connection' before retrying.
+
+**** Editing local files as root
+
+Use the sudo method:
+
+\"/sudo:host:\" or simply \"/sudo::\".
+
+*** Attach files to a mail buffer (message-mode)
+
+If you are in a `message-mode' or `mail-mode' buffer, that action will appear
+in action menu, otherwise it is available at any time with \\<helm-find-files-map>\\[helm-ff-run-mail-attach-files].
+It behaves as follows:
+
+- If you are in a (mail or message) buffer, files are attached there.
+
+- If you are not in a mail buffer but one or more mail buffers exist, you are
+prompted to attach files to one of these mail buffers.
+
+- If you are not in a mail buffer and no mail buffer exists,
+a new mail buffer is created with the attached files in it.
+
+*** Open files in separate windows
+
+When [[Marked candidates][marking]] multiple files or using [[Use the wildcard to select multiple files][wildcard]], helm allow opening all
+this files in separate windows using an horizontal layout or a
+vertical layout if you used a prefix arg, when no more windows can be
+displayed in frame, next files are opened in background without being
+displayed. When using \\<helm-find-files-map>\\[helm-ff-run-switch-other-window] the current
+buffer is kept and files are displayed next to it with same behavior as above.
+When using two prefix args, files are opened in background without beeing displayed.
+
+*** Expand archives as directories in a avfs directory
+
+If you have mounted your filesystem with mountavfs,
+you can expand archives in the \"~/.avfs\" directory with \\<helm-map>\\[helm-execute-persistent-action].
+
+*** Tramp archive support (emacs-27+ only)
+
+If your emacs have library tramp-archive.el, you can browse the
+content of archives with emacs and BTW helm-find-files. However this beeing
+experimental and not very fast, helm doesn't provide an automatic
+expansion and detection of archives, you will have to add the final /
+manually and may have to force update (\\<helm-map>\\[helm-refresh])
+or remove and add again the final / until tramp finish decompressing archive.
+
+*** Touch files
+
+In the completion buffer, you can choose the default which is the current-time, it is
+the first candidate or the timestamp of one of the selected files.
+If you need to use something else, use \\<helm-map>\\[next-history-element] and edit
+the date in minibuffer.
+It is also a way to quickly create a new file without opening a buffer, saving it
+and killing it.
+To touch more than one new file, separate you filenames with a comma (\",\").
+If one wants to create (touch) a new file with comma inside the name use a prefix arg,
+this will prevent splitting the name and create multiple files.
+
+*** Delete files
+
+You can delete files without quitting helm with
+`\\<helm-find-files-map>\\[helm-ff-persistent-delete]' or delete files and quit helm with `\\[helm-ff-run-delete-file]'.
+
+In the second method you can choose to
+make this command asynchronous by customizing
+\`helm-ff-delete-files-function'.
+
+_WARNING_: When deleting files asynchronously you will NOT be
+WARNED if directories are not empty, that's mean non empty directories will
+be deleted in background without asking.
+
+A good compromise is to trash your files
+when using asynchronous method (see [[Trashing files][Trashing files]]).
+
+When choosing synchronous delete, you can allow recursive
+deletion of directories with `helm-ff-allow-recursive-deletes'.
+Note that when trashing (synchronous) you are not asked for recursive deletion.
+
+Note that `helm-ff-allow-recursive-deletes' have no effect when
+deleting asynchronously.
+
+First method (persistent delete) is always synchronous.
+
+Note that when a prefix arg is given, trashing behavior is inversed.
+See [[Trashing files][Trashing files]].
+
+**** Trashing files
+
+If you want to trash your files instead of deleting them you can
+set `delete-by-moving-to-trash' to non nil, like this your files
+will be moved to trash instead of beeing deleted.
+
+You can reverse at any time the behavior of `delete-by-moving-to-trash' by using
+a prefix arg with any of the delete files command.
+
+On GNULinux distribution, when navigating to a Trash directory you
+can restore any file in ..Trash/files directory with the 'Restore
+from trash' action you will find in action menu (needs the
+trash-cli package installed).
+You can as well delete files from Trash directories with the 'delete files from trash'
+action.
+
+Tip: Navigate to your Trash/files directories with `helm-find-files' and set a bookmark
+there with \\<helm-find-files-map>\\[helm-ff-bookmark-set] for fast access to Trash.
+
+_WARNING:_
+
+If you have an ENV var XDG_DATA_HOME in your .profile or .bash_profile
+and this var is set to something like $HOME/.local/share (like preconized)
+`move-file-to-trash' may try to create $HOME/.local/share/Trash (literally)
+and its subdirs in the directory where you are actually trying to trash files.
+because `move-file-to-trash' is interpreting XDG_DATA_HOME literally instead
+of evaling its value (with `substitute-in-file-name').
+
+***** Trashing remote files with tramp
+
+Trashing remote files (or local files with sudo method) is disabled by default
+because tramp is requiring the 'trash' command to be installed, if you want to
+trash your remote files, customize `helm-trash-remote-files'.
+The package on most GNU/Linux based distributions is trash-cli, it is available [[https://github.com/andreafrancia/trash-cli][here]].
+
+NOTE:
+When deleting your files with sudo method, your trashed files will not be listed
+with trash-list until you log in as root.
+
+** Commands
+\\<helm-find-files-map>
+\\[helm-ff-run-locate]\t\tRun `locate' (`\\[universal-argument]' to specify locate database, `M-n' to insert basename of candidate).
+\\[helm-ff-run-browse-project]\t\tBrowse project (`\\[universal-argument]' to recurse, `\\[universal-argument] \\[universal-argument]' to recurse and refresh database).
+\\[helm-ff-run-find-sh-command]\t\tRun `find' shell command from this directory.
+\\[helm-ff-run-grep]\t\tRun Grep (`\\[universal-argument]' to recurse).
+\\[helm-ff-run-pdfgrep]\t\tRun Pdfgrep on marked files.
+\\[helm-ff-run-zgrep]\t\tRun zgrep (`\\[universal-argument]' to recurse).
+\\[helm-ff-run-grep-ag]\t\tRun AG grep on current directory.
+\\[helm-ff-run-git-grep]\t\tRun git-grep on current directory.
+\\[helm-ff-run-gid]\t\tRun gid (id-utils).
+\\[helm-ff-run-etags]\t\tRun Etags (`\\[universal-argument]' to use thing-at-point, `\\[universal-argument] \\[universal-argument]' to reload cache).
+\\[helm-ff-run-rename-file]\t\tRename Files (`\\[universal-argument]' to follow).
+\\[helm-ff-run-query-replace-fnames-on-marked]\t\tQuery replace on marked files.
+\\[helm-ff-run-copy-file]\t\tCopy Files (`\\[universal-argument]' to follow).
+\\[helm-ff-run-byte-compile-file]\t\tByte Compile Files (`\\[universal-argument]' to load).
+\\[helm-ff-run-load-file]\t\tLoad Files.
+\\[helm-ff-run-symlink-file]\t\tSymlink Files.
+\\[helm-ff-run-hardlink-file]\t\tHardlink files.
+\\[helm-ff-run-relsymlink-file]\t\tRelative symlink Files.
+\\[helm-ff-run-delete-file]\t\tDelete Files.
+\\[helm-ff-run-touch-files]\t\tTouch files.
+\\[helm-ff-run-kill-buffer-persistent]\t\tKill buffer candidate without leaving Helm.
+\\[helm-ff-persistent-delete]\t\tDelete file without leaving Helm.
+\\[helm-ff-run-switch-to-eshell]\t\tSwitch to Eshell.
+\\[helm-ff-run-eshell-command-on-file]\t\tEshell command on file (`\\[universal-argument]' to apply on marked files, otherwise treat them sequentially).
+\\[helm-ff-run-ediff-file]\t\tEdiff file.
+\\[helm-ff-run-ediff-merge-file]\t\tEdiff merge file.
+\\[helm-ff-run-complete-fn-at-point]\t\tComplete file name at point.
+\\[helm-ff-run-switch-other-window]\t\tSwitch to other window.
+\\[helm-ff-run-switch-other-frame]\t\tSwitch to other frame.
+\\[helm-ff-run-open-file-externally]\t\tOpen file with external program (`\\[universal-argument]' to choose).
+\\[helm-ff-run-preview-file-externally]\t\tPreview file with external program.
+\\[helm-ff-run-open-file-with-default-tool]\t\tOpen file externally with default tool.
+\\[helm-ff-rotate-left-persistent]\t\tRotate image left.
+\\[helm-ff-rotate-right-persistent]\t\tRotate image right.
+\\[helm-find-files-up-one-level]\t\tGo to parent directory.
+\\[helm-find-files-history]\t\tSwitch to the visited-directory history.
+\\[helm-ff-file-name-history]\t\tSwitch to file name history.
+\\[helm-ff-properties-persistent]\t\tShow file properties in a tooltip.
+\\[helm-mark-all]\t\tMark all visible candidates.
+\\[helm-ff-run-toggle-auto-update]\t\tToggle auto-expansion of directories.
+\\[helm-unmark-all]\t\tUnmark all candidates, visible and invisible ones.
+\\[helm-ff-run-gnus-attach-files]\t\tGnus' attach files to message buffer.
+\\[helm-ff-run-print-file]\t\tPrint file, (`\\[universal-argument]' to refresh printer list).
+\\[helm-enlarge-window]\t\tEnlarge Helm window.
+\\[helm-narrow-window]\t\tNarrow Helm window.
+\\[helm-ff-run-toggle-basename]\t\tToggle basename/fullpath.
+\\[helm-ff-run-find-file-as-root]\t\tFind file as root.
+\\[helm-ff-run-find-alternate-file]\t\tFind alternate file.
+\\[helm-ff-run-insert-org-link]\t\tInsert org link.
+\\[helm-ff-bookmark-set]\t\tSet bookmark to current directory.
+\\[helm-find-files-toggle-to-bookmark]\t\tJump to bookmark list.")
+
+;;; Help for `helm-read-file-name'
+;;
+;;
+(defun helm-read-file-name-help-message ()
+ (let ((name (if helm-alive-p
+ (assoc-default 'name (helm-get-current-source))
+ "generic")))
+ (format
+ "* Helm `%s' read file name completion
+
+This is `%s' read file name completion that have been \"helmized\"
+because you have enabled [[Helm mode][helm-mode]]'.
+Don't confuse this with `helm-find-files' which is a native helm command,
+see [[Helm functions vs helmized emacs functions]].
+
+** Tips
+
+*** Navigation
+
+**** Enter `~/' at end of pattern to quickly reach home directory
+
+**** Enter `/' at end of pattern to quickly reach the file system root
+
+**** Enter `./' at end of pattern to quickly reach `default-directory'
+
+\(As per its value at the beginning of the session.)
+
+If you already are in the `default-directory' this will move the cursor to the top.
+
+**** Enter `../' at end of pattern will reach upper directory, moving cursor on top
+
+This is different from using `\\[helm-find-files-up-one-level]' in that it moves
+the cursor to the top instead of remaining on the previous subdir name.
+
+**** You can complete with partial basename
+
+It starts from the third character of the pattern.
+
+For instance \"fob\" or \"fbr\" will complete \"foobar\" but \"fb\" needs a
+third character in order to complete it.
+
+*** Persistent actions
+
+By default `helm-read-file-name' uses the persistent actions of `helm-find-files'.
+
+**** Use `\\[universal-argument] \\<helm-map>\\[helm-execute-persistent-action]' to display an image
+
+**** `\\<helm-map>\\[helm-execute-persistent-action]' on a filename will expand to this filename in Helm-buffer
+
+Second hit displays the buffer filename.
+Third hit kills the buffer filename.
+Note: `\\[universal-argument] \\<helm-map>\\[helm-execute-persistent-action]' displays the buffer directly.
+
+**** Browse images directories with `helm-follow-mode' and navigate up/down
+
+*** Delete characters backward
+
+When you want to delete characters backward, e.g. to create a new file or directory,
+auto-update may come in the way when it keeps updating to an existent directory.
+In that case, type `C-<backspace>' and then `<backspace>'.
+This should not be needed when copying/renaming files because autoupdate is disabled
+by default in that case.
+
+Note: On a terminal, the default binding `C-<backspace>' may not work.
+In this case use `C-c <backspace>'.
+
+*** Create new directories and files
+
+**** You can create a new directory and a new file at the same time
+
+Simply write the path in prompt and press `RET', e.g.
+\"~/new/newnew/newnewnew/my_newfile.txt\".
+
+**** To create a new directory, append a \"/\" at to the new name and press `RET'
+
+**** To create a new file, enter a filename not ending with \"/\"
+
+File and directory creation works only with some commands (e.g. `find-file')
+and it will not work with others where it is not intended to return a file or
+a directory \(e.g `list-directory').
+
+*** Exiting minibuffer with empty string
+
+You can exit minibuffer with empty string with \\<helm-read-file--map>\\[helm-cr-empty-string].
+It is useful when some commands are prompting continuously until you enter an empty prompt.
+
+** Commands
+\\<helm-read-file-map>
+\\[helm-find-files-up-one-level]\t\tGo to parent directory.
+\\[helm-ff-run-toggle-auto-update]\t\tToggle auto-expansion of directories.
+\\[helm-ff-run-toggle-basename]\t\tToggle basename.
+\\[helm-ff-file-name-history]\t\tFile name history.
+C/\\[helm-cr-empty-string]\t\tReturn empty string unless `must-match' is non-nil.
+\\[helm-next-source]\t\tGo to next source.
+\\[helm-previous-source]\t\tGo to previous source."
+ name name)))
+
+;;; Generic file help - Used by locate.
+;;
+;;
+(defvar helm-generic-file-help-message
+ "* Helm Generic files
+
+** Tips
+
+*** Locate
+
+You can append to the search pattern any of the locate command line options,
+e.g. -b, -e, -n <number>, etc. See the locate(1) man page for more details.
+
+Some other sources (at the moment \"recentf\" and \"file in current directory\")
+support the -b flag for compatibility with locate when they are used with it.
+
+When you enable fuzzy matching on locate with `helm-locate-fuzzy-match', the
+search will be performed on basename only for efficiency (so don't add \"-b\" at
+prompt). As soon as you separate the patterns with spaces, fuzzy matching will
+be disabled and search will be done on the full filename. Note that in
+multi-match, fuzzy is completely disabled, which means that each pattern is a
+match regexp (i.e. \"helm\" will match \"helm\" but \"hlm\" will \*not* match
+\"helm\").
+
+*** Browse project
+
+When the current directory is not under version control, don't forget to refresh
+the cache when files have been added/removed in the directory.
+
+*** Find command
+
+Recursively search files using the \"find\" shell command.
+
+Candidates are all filenames that match all given globbing patterns. This
+respects the options `helm-case-fold-search' and
+`helm-findutils-search-full-path'.
+
+You can pass arbitrary \"find\" options directly after a \"*\" separator.
+For example, this would find all files matching \"book\" that are larger
+than 1 megabyte:
+
+ book * -size +1M
+
+** Commands
+\\<helm-generic-files-map>
+\\[helm-ff-run-toggle-basename]\t\tToggle basename.
+\\[helm-ff-run-grep]\t\tRun grep (`\\[universal-argument]' to recurse).
+\\[helm-ff-run-zgrep]\t\tRun zgrep.
+\\[helm-ff-run-gid]\t\tRun GID (id-utils).
+\\[helm-ff-run-pdfgrep]\t\tRun PDFgrep on marked files.
+\\[helm-ff-run-copy-file]\t\tCopy file(s)
+\\[helm-ff-run-rename-file]\t\tRename file(s).
+\\[helm-ff-run-symlink-file]\t\tSymlink file(s).
+\\[helm-ff-run-hardlink-file]\t\tHardlink file(s).
+\\[helm-ff-run-delete-file]\t\tDelete file(s).
+\\[helm-ff-run-byte-compile-file]\t\tByte compile Elisp file(s) (`\\[universal-argument]' to load).
+\\[helm-ff-run-load-file]\t\tLoad Elisp file(s).
+\\[helm-ff-run-ediff-file]\t\tEdiff file.
+\\[helm-ff-run-ediff-merge-file]\t\tEdiff-merge file.
+\\[helm-ff-run-switch-other-window]\t\tSwitch to other window.
+\\[helm-ff-properties-persistent]\t\tShow file properties.
+\\[helm-ff-run-etags]\t\tRun etags (`\\[universal-argument]' to use tap, `\\[universal-argument] \\[universal-argument]' to reload the database).
+\\[helm-yank-text-at-point]\t\tYank text at point.
+\\[helm-ff-run-open-file-externally]\t\tOpen file with external program (`\\[universal-argument]' to choose).
+\\[helm-ff-run-open-file-with-default-tool]\t\tOpen file externally with default tool.
+\\[helm-ff-run-insert-org-link]\t\tInsert org link.")
+
+;;; Grep help
+;;
+;;
+(defvar helm-grep-help-message
+ "* Helm Grep
+
+** Tips
+
+*** Use a prefix argument to grep recursively
+
+With Helm supporting git-grep and AG however, you are better off using one of
+them for recursive searches.
+
+*** You can use wild cards when selecting files (e.g. \"*.el\")
+
+*** You can grep in many different directories by marking files or using wild cards
+
+*** You can save the result in a `helm-grep-mode' buffer
+
+See [[Commands][commands]] below.
+
+Once in that buffer you can use \"emacs-wgrep\" (external package not bundled with Helm)
+to edit your changes.
+
+*** Helm-grep supports multi-matching
+
+\(Starting from version 1.9.4.)
+
+Simply add a space between each pattern as for most Helm commands.
+
+*** See full path of selected candidate
+
+Add (helm-popup-tip-mode 1) in your init file or enable it interactively with
+M-x helm-popup-tip-mode.
+
+*** Open file in other window
+
+The command \\<helm-grep-map>\\[helm-grep-run-other-window-action] allow you to open file
+in other window horizontally or vertically if a prefix arg is supplied.
+
+*** Performance over TRAMP
+
+Grepping works but it is badly supported as TRAMP doesn't support multiple
+processes running in a short delay (less than 5s) among other things.
+
+Helm uses a special hook to suspend the process automatically while you are
+typing. Even if Helm handles this automatically by delaying each process by 5s,
+you are adviced to this manually by hitting `\\<helm-map>\\[helm-toggle-suspend-update]' (suspend process) before
+typing, and hit again `\\<helm-map>\\[helm-toggle-suspend-update]' when the regexp is ready to send to the remote
+process. For simple regexps, there should be no need for this.
+
+Another solution is to not use TRAMP at all and mount your remote file system via
+SSHFS.
+
+* Helm GID
+
+** Tips
+
+Helm-GID reads the database created with the `mkid' command from id-utils.
+The name of the database file can be customized with `helm-gid-db-file-name', it
+is usually \"ID\".
+
+Helm-GID use the symbol at point as default-input. This command is also
+accessible from `helm-find-files' which allow you to navigate to another
+directory to consult its database.
+
+Note: Helm-GID supports multi-matches but only the last pattern entered will be
+highlighted since there is no ~--color~-like option in GID itself.
+
+* Helm AG
+
+** Tips
+
+Helm-AG is different from grep or ack-grep in that it works on a directory and
+not on a list of files.
+
+You can ignore files and directories with a \".agignore\" file, local to a
+directory or global when placed in the home directory. \(See the AG man page for
+more details.) That file follows the same syntax as `helm-grep-ignored-files'
+and `helm-grep-ignored-directories'.
+
+As always you can access Helm AG from `helm-find-files'.
+
+Starting with version 0.30, AG accepts one or more TYPE arguments on its command
+line. Helm provides completion on these TYPE arguments when available with your
+AG version. Use a prefix argument when starting a Helm-AG session to enable this
+completion.
+
+Note: You can mark several types to match in the AG query. The first AG
+versions providing this feature allowed only one type, so in this case only the
+last mark will be used.
+
+* Helm git-grep
+
+Helm-git-grep searches the current directory, i.e the default directory or the
+directory in Helm-find-files. If this current directory is a subdirectory of a
+project and you want to also match parent directories (i.e the whole project),
+use a prefix argument.
+
+** Commands
+\\<helm-grep-map>
+\\[helm-goto-next-file]\t\tNext File.
+\\[helm-goto-precedent-file]\t\tPrevious File.
+\\[helm-yank-text-at-point]\t\tYank text at point in minibuffer.
+\\[helm-grep-run-other-window-action]\t\tJump to other window.
+\\[helm-grep-run-other-frame-action]\t\tJump to other frame.
+\\[helm-grep-run-default-action]\t\tRun default action (same as `RET').
+\\[helm-grep-run-save-buffer]\t\tSave to a `helm-grep-mode' enabled buffer.")
+
+;;; PDF grep help
+;;
+;;
+(defvar helm-pdfgrep-help-message
+ "* Helm PDFgrep Map
+
+** Commands
+\\<helm-pdfgrep-map>
+\\[helm-goto-next-file]\t\tNext file.
+\\[helm-goto-precedent-file]\t\tPrevious file.
+\\[helm-yank-text-at-point]\t\tYank text at point in minibuffer.")
+
+;;; Etags help
+;;
+;;
+(defvar helm-etags-help-message
+ "* Helm Etags Map
+
+** Commands
+\\<helm-etags-map>
+\\[helm-goto-next-file]\t\tNext file.
+\\[helm-goto-precedent-file]\t\tPrevious file.
+\\[helm-yank-text-at-point]\t\tYank text at point in minibuffer.")
+
+;;; UCS help
+;;
+;;
+(defvar helm-ucs-help-message
+ "* Helm UCS
+
+** Tips
+
+Use commands below to insert unicode characters in current buffer without
+leaving Helm.
+
+** Commands
+\\<helm-ucs-map>
+\\[helm-ucs-persistent-insert]\t\tInsert character.
+\\[helm-ucs-persistent-forward]\t\tForward character.
+\\[helm-ucs-persistent-backward]\t\tBackward character.
+\\[helm-ucs-persistent-delete]\t\tDelete character backward.
+\\[helm-ucs-persistent-insert-space]\t\tInsert space.")
+
+;;; Bookmark help
+;;
+;;
+(defvar helm-bookmark-help-message
+ "* Helm bookmark name
+
+** Commands
+\\<helm-bookmark-map>
+\\[helm-bookmark-run-jump-other-window]\t\tJump other window.
+\\[helm-bookmark-run-delete]\t\tDelete bookmark.
+\\[helm-bookmark-run-edit]\t\tEdit bookmark.
+\\[helm-bookmark-toggle-filename]\t\tToggle bookmark location visibility.")
+
+;;; Eshell command on file help
+;;
+;;
+(defvar helm-esh-help-message
+ "* Helm Eshell on file
+
+** Tips
+
+*** Pass extra arguments after filename
+
+Normally the command or alias will be called with file as argument. For instance
+
+ <command> candidate_file
+
+But you can also pass an argument or more after \"candidate_file\" like this:
+
+ <command> %s [extra_args]
+
+\"candidate_file\" will be added at \"%s\" and the command will look at this:
+
+ <command> candidate_file [extra_args]
+
+*** Specify marked files as arguments
+
+Example:
+
+ <command> file1 file2...
+
+Call `helm-find-files-eshell-command-on-file' with one prefix argument. Otherwise
+you can pass one prefix argument from the command selection buffer.
+
+Note: This does not work on remote files.
+
+With two prefix-args the output is printed to the `current-buffer'.
+
+With no prefix argument or a prefix argument value of '(16) (`\\[universal-argument] \\[universal-argument]')
+the command is called once for each file like this:
+
+ <command> file1
+ <command> file2
+ ...
+
+** Commands
+\\<helm-esh-on-file-map>")
+
+;;; Ido virtual buffer help
+;;
+;;
+(defvar helm-buffers-ido-virtual-help-message
+ "* Helm Ido virtual buffers
+
+** Commands
+\\<helm-buffers-ido-virtual-map>
+\\[helm-ff-run-switch-other-window]\t\tSwitch to other window.
+\\[helm-ff-run-switch-other-frame]\t\tSwitch to other frame.
+\\[helm-ff-run-grep]\t\tGrep file.
+\\[helm-ff-run-zgrep]\t\tZgrep file.
+\\[helm-ff-run-delete-file]\t\tDelete file.
+\\[helm-ff-run-open-file-externally]\t\tOpen file externally.")
+
+;;; Moccur help
+;;
+;;
+(defvar helm-moccur-help-message
+ "* Helm Moccur
+
+** Tips
+
+*** Matching
+
+Multiple regexp matching is allowed, simply enter a space to separate the regexps.
+
+Matching empty lines is supported with the regexp \"^$\", you then get the
+results displayed as the buffer-name and the line number only. You can
+save and edit these results, i.e. add text to the empty line.
+
+*** Automatically match symbol at point
+
+Helm can automatically match the symbol at point while keeping the minibuffer
+empty, ready to be written to. This behaviour is disabled by default. To
+enable this you need to add `helm-source-occur' and `helm-source-moccur' to
+`helm-sources-using-default-as-input'.
+
+*** Jump to the corresponding line in the searched buffer
+
+You can do this with `\\<helm-map>\\[helm-execute-persistent-action]' (persistent-action), to do it repeatedly
+you can use `\\<helm-map>\\[helm-follow-action-forward]' and `\\<helm-map>\\[helm-follow-action-backward]' or enable `helm-follow-mode' with `\\<helm-map>\\[helm-follow-mode]'.
+
+*** Switch to buffer in other window
+
+The command \\<helm-moccur-map>\\[helm-moccur-run-goto-line-ow] allow you to switch to buffer
+in other window horizontally or vertically if a prefix arg is supplied.
+
+*** Save the results
+
+Similarly to Helm-grep, you can save the results with `\\<helm-map>\\[helm-moccur-run-save-buffer]'.
+Once in the saved buffer, you can edit it, see [[Edit a saved buffer][below]].
+
+Of course if you don't save the results, you can resume the Helm session with
+`helm-resume'.
+
+*** Refresh the resumed session
+
+When the buffer(s) where you ran helm-(m)occur get(s) modified, the Helm buffer
+will flash red as a warning. You can refresh the buffer by running `\\<helm-map>\\[helm-refresh]'.
+This can be done automatically by customizing `helm-moccur-auto-update-on-resume'.
+
+*** Refresh a saved buffer
+
+Type `g' to update the buffer.
+
+*** Edit a saved buffer
+
+First, install wgrep (https://github.com/mhayashi1120/Emacs-wgrep) and then:
+
+1) `C-c C-p' (`wgrep-change-to-wgrep-mode') to edit the buffer(s).
+2) `C-x C-s' to save your changes.
+
+Tip: Use the excellent iedit (https://github.com/victorhge/iedit) to modify all
+occurences at once in the buffer.
+
+*** Search in region
+
+When searching in current-buffer with `helm-occur', if a region
+is found helm will search in this region only. If you marked
+this region with `mark-defun' the symbol that was at point before
+marking defun will be used when `helm-source-occur' is member of
+`helm-sources-using-default-as-input'.
+
+** Commands
+\\<helm-moccur-map>
+\\[helm-goto-next-file]\t\tNext buffer.
+\\[helm-goto-precedent-file]\t\tPrevious buffer.
+\\[helm-yank-text-at-point]\t\tYank text at point in minibuffer.
+\\[helm-moccur-run-goto-line-ow]\t\tGo to line in other window.
+\\[helm-moccur-run-goto-line-of]\t\tGo to line in new frame.")
+
+;;; Helm Top
+;;
+;;
+(defvar helm-top-help-message
+ "* Helm Top
+
+** Commands
+\\<helm-top-map>
+\\[helm-top-run-sort-by-com]\t\tSort by commands.
+\\[helm-top-run-sort-by-cpu]\t\tSort by CPU usage.
+\\[helm-top-run-sort-by-user]\t\tSort alphabetically by user.
+\\[helm-top-run-sort-by-mem]\t\tSort by memory.")
+
+;;; Helm Elisp package
+;;
+;;
+(defvar helm-el-package-help-message
+ "* Helm Elisp package
+
+** Tips
+
+*** Compile all your packages asynchronously
+
+If you use async (if you have installed Helm from MELPA you do), only \"helm\",
+\"helm-core\", and \"magit\" are compiled asynchronously. If you want all your
+packages compiled asynchronously, add this to your init file:
+
+ (setq async-bytecomp-allowed-packages '(all))
+
+*** Upgrade Elisp packages
+
+On initialization (when Emacs is fetching packages on remote), if Helm finds
+packages to upgrade, it will start in the upgradable packages view showing the packages
+available for upgrade.
+
+On subsequent runs, you will have to refresh the list with `C-c \\[universal-argument]'. If Helm
+finds upgrades you can switch to upgrade view (see below) to see what packages
+are available for upgrade or simply hit `C-c U' to upgrade them all.
+
+To see upgradable packages hit `M-U'.
+
+Then you can install all upgradable packages with the \"upgrade all\" action
+\(`C-c \\[universal-argument]'), or upgrade only specific packages by marking them and running the
+\"upgrade\" action (visible only when there are upgradable packages). Of course
+you can upgrade a single package by just running the \"upgrade\" action without
+marking it (`C-c u' or `RET') .
+
+\*Warning:* You are strongly advised to \*restart* Emacs after \*upgrading* packages.
+
+*** Meaning of flags prefixing packages
+
+\(Emacs ≥25)
+
+- The flag \"S\" that prefixes package names means that the packages belong to `package-selected-packages'.
+
+- The flag \"U\" that prefix package names mean that this package is no more needed.
+
+** Commands
+\\<helm-el-package-map>
+\\[helm-el-package-show-all]\t\tShow all packages.
+\\[helm-el-package-show-installed]\t\tShow installed packages only.
+\\[helm-el-package-show-uninstalled]\t\tShow non-installed packages only.
+\\[helm-el-package-show-upgrade]\t\tShow upgradable packages only.
+\\[helm-el-package-show-built-in]\t\tShow built-in packages only.
+\\[helm-el-run-package-install]\t\tInstall package(s).
+\\[helm-el-run-package-reinstall]\t\tReinstall package(s).
+\\[helm-el-run-package-uninstall]\t\tUninstall package(s).
+\\[helm-el-run-package-upgrade]\t\tUpgrade package(s).
+\\[helm-el-run-package-upgrade-all]\t\tUpgrade all packages.
+\\[helm-el-run-visit-homepage]\t\tVisit package homepage.")
+
+;;; Helm M-x
+;;
+;;
+(defvar helm-M-x-help-message
+ "* Helm M-x
+
+** Tips
+
+*** You can get help on any command with persistent action (\\[helm-execute-persistent-action])
+
+*** Prefix arguments
+
+You must pass prefix arguments \*after* starting `helm-M-x'. A mode-line
+counter will display the number of given prefix arguments.
+
+If you pass prefix arguments before running `helm-M-x', it will be displayed in the prompt.
+The first `\\[universal-argument]' after `helm-M-x' clears those prefix arguments.")
+
+;;; Helm imenu
+;;
+;;
+(defvar helm-imenu-help-message
+ "* Helm Imenu
+
+** Commands
+\\<helm-imenu-map>
+\\[helm-imenu-next-section]\t\tGo to next section.
+\\[helm-imenu-previous-section]\t\tGo to previous section.")
+
+;;; Helm colors
+;;
+;;
+(defvar helm-colors-help-message
+ "* Helm colors
+
+** Commands
+\\<helm-color-map>
+\\[helm-color-run-insert-name]\t\tInsert the entry name.
+\\[helm-color-run-kill-name]\t\tKill the entry name.
+\\[helm-color-run-insert-rgb]\t\tInsert entry in RGB format.
+\\[helm-color-run-kill-rgb]\t\tKill entry in RGB format.")
+
+;;; Helm Semantic
+;;
+;;
+(defvar helm-semantic-help-message
+ "* Helm Semantic
+
+** Commands
+\\<helm-semantic-map>")
+
+;;; Helm kmacro
+;;
+;;
+(defvar helm-kmacro-help-message
+ "* Helm kmacro
+
+** Tips
+
+- Start recording a kmacro with `f3'.
+- End the kmacro recording with `f4'.
+- Run `helm-execute-kmacro' to list all your kmacros.
+
+Use persistent action to run your kmacro as many time as needed.
+You can browse the kmacros with `helm-next-line' and `helm-previous-line'.
+
+Note: You can't record keys running Helm commands except `helm-M-x', under the
+condition that you don't choose a command using Helm completion.
+
+** Commands
+\\<helm-kmacro-map>")
+
+;;; Kill ring
+;;
+;;
+(defvar helm-kill-ring-help-message
+ "* Helm kill ring
+
+** Tips
+
+Every Helm session lets you save a candidate to the kill-ring / clipboard /
+primary-selection with `\\<helm-map>\\[helm-kill-selection-and-quit]'.
+
+To save space, Helm-kill-ring truncates the candidates longer than
+`helm-kill-ring-max-offset'.
+`\\<helm-kill-ring-map>\\[helm-kill-ring-kill-selection]' then saves the whole
+text and not the truncated value. The view of truncated candidates can be
+toggled; see the command list below.
+
+As opposed to `yank', numeric prefix arguments are ignored with
+`helm-show-kill-ring': there is no need for them since selection happens within
+Helm. Moreover Helm has [[Shortcuts for executing Default Action on the nth
+candidate][Shortcuts for executing Default Action on the nth candidate]].
+
+It is recommended to globally bind `M-y' to `helm-show-kill-ring'. Once in the
+Helm-kill-ring session you can navigate to next/previous line with `M-y' and
+`M-u' for convenience. Of course `\\[helm-next-line]' and `\\[helm-previous-line]' are still available.
+
+It is possible to delete candidates from the kill ring.
+
+You can concatenate marked candidates and yank them in the current
+buffer, thus creating a new entry in the kill ring. Candidates are
+concatenated with `helm-kill-ring-separator' as default but you can
+change interactively the separator while yanking by using two prefix
+args. When you have something else than \"\\n\" as default value for
+`helm-kill-ring-separator' and you want to use \"\\n\" from prompt, use
+`C-q C-j' to enter a newline in prompt.
+
+To not push a new entry in the kill ring, use `\\<helm-map>\\[helm-copy-to-buffer]' instead of RET
+\(note that you can't change separator with this).
+
+When inserting candidates with the default action (`RET'), `point' is placed at
+the end of the candidate and `mark' at the beginning. You can revert this behavior
+by using a prefix argument, i.e. `C-u RET', like the regular `yank' command does.
+
+** Commands
+\\<helm-kill-ring-map>
+\\[helm-next-line]\t\tNext line.
+\\[helm-previous-line]\t\tPrevious line.
+\\[helm-kill-ring-delete]\t\tDelete entry.
+\\[helm-kill-ring-toggle-truncated]\t\tToggle truncated view of candidate.
+\\[helm-kill-ring-kill-selection]\t\tKill non-truncated of selection.")
+
+;;; Org headings
+;;
+;;
+(defvar helm-org-headings-help-message
+ "* Helm Org headings
+
+** Tips
+
+*** Refiling
+
+You can refile one or more headings at a time.
+
+To refile one heading, move the point to the entry you want to refile and run
+\\[helm-org-in-buffer-headings]. Then select the heading you want to refile to
+and press \\<helm-org-headings-map>\\[helm-org-run-refile-heading-to] or select the refile action from the actions menu.
+
+To refile multiple headings, run \\[helm-org-in-buffer-headings] and mark the
+headings you want to refile. Then select the heading you want to refile to
+\(without marking it) and press \\<helm-org-headings-map>\\[helm-org-run-refile-heading-to] or select the refile action from the
+actions menu.
+
+*** Tags completion
+
+Tags completion use `completing-read-multiple', perhaps have a
+look at its docstring.
+
+**** Single tag
+
+From an org heading hit C-c C-c which provide a
+\"Tags\" prompt, then hit TAB and RET if you want to enter an
+existing tag or write a new tag in prompt. At this point you end
+up with an entry in your prompt, if you enter RET, the entry is
+added as tag in your org header.
+
+**** Multiple tags
+
+If you want to add more tag to your org header, add a separator[1] after
+your tag and write a new tag or hit TAB to find another existing
+tag, and so on until you have all the tags you want
+e.g \"foo,bar,baz\" then press RET to finally add the tags to your
+org header.
+Note: [1] A separator can be a comma, a colon i.e. [,:] or a space.
+
+** Commands
+\\<helm-org-headings-map>
+\\[helm-org-run-open-heading-in-indirect-buffer]\t\tOpen heading in indirect buffer.
+\\[helm-org-run-refile-heading-to]\t\tRefile current or marked headings to selection.
+\\[helm-org-run-insert-link-to-heading-at-marker]\t\tInsert link at point to selection."
+ )
+
+;;; Completing-read
+;;
+(defun helm-comp-read-help-message ()
+ (let ((com (assoc-default 'name (helm-get-current-source))))
+ (format
+ "* Helm completing-read completion for `%s'
+
+Command `%s' is using a `completing-read' for completion on your input,
+this completion have been \"helmized\" because you have enabled [[Helm mode][helm-mode]]'.
+
+** Tips
+
+*** Disabling or use something else than helm for completion of some commands
+
+You can disable helm completion or use something else for specific commands of your choice,
+for this customize variable `helm-completing-read-handlers-alist'.
+
+*** Exiting minibuffer with empty string
+
+You can exit minibuffer with empty string with \\<helm-comp-read-map>\\[helm-cr-empty-string].
+It is useful when some commands are prompting continuously until you enter an empty prompt.
+
+** Commands
+\\<helm-comp-read-map>
+\\[helm-cr-empty-string]\t\tExit minibuffer with empty string."
+ com com)))
+
+\f
+;;; Mode line strings
+;;
+;;
+;;;###autoload
+(defvar helm-comp-read-mode-line "\
+\\<helm-comp-read-map>\
+C/\\[helm-cr-empty-string]:Empty \
+\\<helm-map>\
+\\[helm-help]:Help \
+\\[helm-select-action]:Act \
+\\[helm-maybe-exit-minibuffer]/\
+f1/f2/f-n:NthAct \
+\\[helm-toggle-suspend-update]:Tog.suspend")
+
+;;;###autoload
+(defvar helm-read-file-name-mode-line-string "\
+\\<helm-read-file-map>\
+\\[helm-help]:Help \
+C/\\[helm-cr-empty-string]:Empty \
+\\<helm-map>\
+\\[helm-select-action]:Act \
+\\[helm-maybe-exit-minibuffer]/\
+f1/f2/f-n:NthAct \
+\\[helm-toggle-suspend-update]:Tog.suspend"
+ "String displayed in mode-line in `helm-source-find-files'.")
+
+;;;###autoload
+(defvar helm-top-mode-line "\
+\\<helm-top-map>\
+\\[helm-help]:Help \
+\\<helm-map>\
+\\[helm-select-action]:Act \
+\\[helm-maybe-exit-minibuffer]/\
+f1/f2/f-n:NthAct \
+\\[helm-toggle-suspend-update]:Tog.suspend")
+
+
+(provide 'helm-help)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-help.el ends here
--- /dev/null
+;;; helm-id-utils.el --- Helm interface for id-utils. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2015 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Code:
+
+(require 'helm-grep)
+(require 'helm-help)
+
+(defgroup helm-id-utils nil
+ "ID-Utils related Applications and libraries for Helm."
+ :group 'helm)
+
+(defcustom helm-gid-program "gid"
+ "Name of gid command (usually `gid').
+For Mac OS X users, if you install GNU coreutils, the name `gid'
+might be occupied by `id' from GNU coreutils, and you should set
+it to correct name (or absolute path), for example, if using
+MacPorts to install id-utils, it should be `gid32'."
+ :group 'helm-id-utils
+ :type 'file)
+
+(defcustom helm-gid-db-file-name "ID"
+ "Name of a database file created by `mkid' command from `ID-utils'."
+ :group 'helm-id-utils
+ :type 'string)
+
+(defun helm-gid-candidates-process ()
+ (let* ((patterns (helm-mm-split-pattern helm-pattern))
+ (default-com (format "%s -r %s" helm-gid-program
+ (shell-quote-argument (car patterns))))
+ (cmd (helm-aif (cdr patterns)
+ (concat default-com
+ (cl-loop for p in it
+ concat (format " | grep --color=always %s"
+ (shell-quote-argument p))))
+ default-com))
+ (proc (start-process-shell-command
+ "gid" helm-buffer cmd)))
+ (set (make-local-variable 'helm-grep-last-cmd-line) cmd)
+ (prog1 proc
+ (set-process-sentinel
+ proc (lambda (_process event)
+ (when (string= event "finished\n")
+ (helm-maybe-show-help-echo)
+ (with-helm-window
+ (setq mode-line-format
+ '(" " mode-line-buffer-identification " "
+ (:eval (format "L%s" (helm-candidate-number-at-point))) " "
+ (:eval (propertize
+ (format "[Helm Gid process finished - (%s results)]"
+ (max (1- (count-lines
+ (point-min) (point-max)))
+ 0))
+ 'face 'helm-locate-finish))))
+ (force-mode-line-update))
+ (helm-log "Error: Gid %s"
+ (replace-regexp-in-string "\n" "" event))))))))
+
+(defun helm-gid-filtered-candidate-transformer (candidates _source)
+ ;; "gid -r" may add dups in some rare cases.
+ (cl-loop for c in (helm-fast-remove-dups candidates :test 'equal)
+ collect (helm-grep--filter-candidate-1 c)))
+
+(defclass helm-gid-source (helm-source-async)
+ ((header-name
+ :initform
+ (lambda (name)
+ (concat name " [" (helm-attr 'db-dir) "]")))
+ (db-dir :initarg :db-dir
+ :initform nil
+ :custom string
+ :documentation " Location of ID file.")
+ (candidates-process :initform #'helm-gid-candidates-process)
+ (filtered-candidate-transformer
+ :initform #'helm-gid-filtered-candidate-transformer)
+ (candidate-number-limit :initform 99999)
+ (action :initform (helm-make-actions
+ "Find File" 'helm-grep-action
+ "Find file other frame" 'helm-grep-other-frame
+ "Save results in grep buffer" 'helm-grep-save-results
+ "Find file other window" 'helm-grep-other-window))
+ (persistent-action :initform 'helm-grep-persistent-action)
+ (history :initform 'helm-grep-history)
+ (nohighlight :initform t)
+ (help-message :initform 'helm-grep-help-message)
+ (requires-pattern :initform 2)))
+
+;;;###autoload
+(defun helm-gid ()
+ "Preconfigured helm for `gid' command line of `ID-Utils'.
+Need A database created with the command `mkid'
+above `default-directory'.
+Need id-utils as dependency which provide `mkid', `gid' etc...
+See <https://www.gnu.org/software/idutils/>."
+ (interactive)
+ (let* ((db (locate-dominating-file
+ default-directory
+ helm-gid-db-file-name))
+ (helm-grep-default-directory-fn
+ (lambda () default-directory))
+ (helm--maybe-use-default-as-input t))
+ (cl-assert db nil "No DataBase found, create one with `mkid'")
+ (helm :sources (helm-make-source "Gid" 'helm-gid-source
+ :db-dir db)
+ :buffer "*helm gid*"
+ :keymap helm-grep-map
+ :truncate-lines helm-grep-truncate-lines)))
+
+(provide 'helm-id-utils)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-id-utils ends here
--- /dev/null
+;;; helm-imenu.el --- Helm interface for Imenu -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'helm)
+(require 'helm-lib)
+(require 'imenu)
+(require 'helm-utils)
+(require 'helm-help)
+
+\f
+(defgroup helm-imenu nil
+ "Imenu related libraries and applications for helm."
+ :group 'helm)
+
+(defcustom helm-imenu-delimiter " / "
+ "Delimit types of candidates and his value in `helm-buffer'."
+ :group 'helm-imenu
+ :type 'string)
+
+(defcustom helm-imenu-execute-action-at-once-if-one
+ #'helm-imenu--execute-action-at-once-p
+ "Goto the candidate when only one is remaining."
+ :group 'helm-imenu
+ :type 'function)
+
+(defcustom helm-imenu-lynx-style-map t
+ "Use Arrow keys to jump to occurences."
+ :group 'helm-imenu
+ :type 'boolean)
+
+(defcustom helm-imenu-all-buffer-assoc nil
+ "Major mode association alist for `helm-imenu-in-all-buffers'.
+Allow `helm-imenu-in-all-buffers' searching in these associated buffers
+even if they are not derived from each other.
+The alist is bidirectional, i.e no need to add '((foo . bar) (bar . foo))
+only '((foo . bar)) is needed."
+ :type '(alist :key-type symbol :value-type symbol)
+ :group 'helm-imenu)
+
+(defcustom helm-imenu-in-all-buffers-separate-sources t
+ "Display imenu index of each buffer in its own source when non-nil.
+
+When nil all candidates are displayed in a single source.
+
+NOTE: Each source will have as name \"Imenu <buffer-name>\".
+`helm-source-imenu-all' will not be set, however it will continue
+to be used as a flag for using default as input, if you do not want
+this behavior, remove it from `helm-sources-using-default-as-input'
+even if not using a single source to display imenu in all buffers."
+ :type 'boolean
+ :group 'helm-imenu)
+
+(defcustom helm-imenu-type-faces
+ '(("^Variables$" . font-lock-variable-name-face)
+ ("^\\(Function\\|Functions\\|Defuns\\)$" . font-lock-function-name-face)
+ ("^\\(Types\\|Provides\\|Requires\\|Classes\\|Class\\|Includes\\|Imports\\|Misc\\|Code\\)$" . font-lock-type-face))
+ "Faces for showing type in helm-imenu.
+This is a list of cons cells. The cdr of each cell is a face to be used,
+and it can also just be like \\='(:foreground \"yellow\").
+Each car is a regexp match pattern of the imenu type string."
+ :group 'helm-faces
+ :type '(repeat
+ (cons
+ (regexp :tag "Imenu type regexp pattern")
+ (sexp :tag "Face"))))
+
+(defcustom helm-imenu-extra-modes nil
+ "Extra modes where helm-imenu-in-all-buffers should look into."
+ :group 'helm-imenu
+ :type '(repeat symbol))
+\f
+;;; keymap
+(defvar helm-imenu-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map helm-map)
+ (define-key map (kbd "M-<down>") 'helm-imenu-next-section)
+ (define-key map (kbd "M-<up>") 'helm-imenu-previous-section)
+ (when helm-imenu-lynx-style-map
+ (define-key map (kbd "<left>") 'helm-maybe-exit-minibuffer)
+ (define-key map (kbd "<right>") 'helm-execute-persistent-action)
+ (define-key map (kbd "M-<left>") 'helm-previous-source)
+ (define-key map (kbd "M-<right>") 'helm-next-source))
+ (delq nil map)))
+
+(defun helm-imenu-next-or-previous-section (n)
+ (with-helm-buffer
+ (let* ((fn (lambda ()
+ (car (split-string (helm-get-selection nil t)
+ helm-imenu-delimiter))))
+ (curtype (funcall fn))
+ (move-fn (if (> n 0) #'helm-next-line #'helm-previous-line))
+ (stop-fn (if (> n 0)
+ #'helm-end-of-source-p
+ #'helm-beginning-of-source-p)))
+ (catch 'break
+ (while (not (funcall stop-fn))
+ (funcall move-fn)
+ (unless (string= curtype (funcall fn))
+ (throw 'break nil)))))))
+
+(defun helm-imenu-next-section ()
+ (interactive)
+ (helm-imenu-next-or-previous-section 1))
+
+(defun helm-imenu-previous-section ()
+ (interactive)
+ (helm-imenu-next-or-previous-section -1))
+
+\f
+;;; Internals
+(defvar helm-cached-imenu-alist nil)
+(make-variable-buffer-local 'helm-cached-imenu-alist)
+
+(defvar helm-cached-imenu-candidates nil)
+(make-variable-buffer-local 'helm-cached-imenu-candidates)
+
+(defvar helm-cached-imenu-tick nil)
+(make-variable-buffer-local 'helm-cached-imenu-tick)
+
+(defvar helm-imenu--in-all-buffers-cache nil)
+\f
+(defvar helm-source-imenu nil "See (info \"(emacs)Imenu\")")
+(defvar helm-source-imenu-all nil)
+
+(defclass helm-imenu-source (helm-source-sync)
+ ((candidates :initform 'helm-imenu-candidates)
+ (candidate-transformer :initform 'helm-imenu-transformer)
+ (persistent-action :initform 'helm-imenu-persistent-action)
+ (persistent-help :initform "Show this entry")
+ (nomark :initform t)
+ (keymap :initform helm-imenu-map)
+ (help-message :initform 'helm-imenu-help-message)
+ (action :initform 'helm-imenu-action)
+ (group :initform 'helm-imenu)))
+
+(defcustom helm-imenu-fuzzy-match nil
+ "Enable fuzzy matching in `helm-source-imenu'."
+ :group 'helm-imenu
+ :type 'boolean
+ :set (lambda (var val)
+ (set var val)
+ (setq helm-source-imenu
+ (helm-make-source "Imenu" 'helm-imenu-source
+ :fuzzy-match helm-imenu-fuzzy-match))))
+\f
+(defun helm-imenu--maybe-switch-to-buffer (candidate)
+ (let ((cand (cdr candidate)))
+ (helm-aif (and (markerp cand) (marker-buffer cand))
+ (switch-to-buffer it))))
+
+(defun helm-imenu--execute-action-at-once-p ()
+ (let ((cur (helm-get-selection))
+ (mb (with-helm-current-buffer
+ (save-excursion
+ (goto-char (point-at-bol))
+ (point-marker)))))
+ (if (equal (cdr cur) mb)
+ (prog1 nil
+ (helm-set-pattern "")
+ (helm-force-update))
+ t)))
+
+(defun helm-imenu-action (candidate)
+ "Default action for `helm-source-imenu'."
+ (helm-log-run-hook 'helm-goto-line-before-hook)
+ (helm-imenu--maybe-switch-to-buffer candidate)
+ (imenu candidate)
+ ;; If semantic is supported in this buffer
+ ;; imenu used `semantic-imenu-goto-function'
+ ;; and position have been highlighted,
+ ;; no need to highlight again.
+ (unless (eq imenu-default-goto-function
+ 'semantic-imenu-goto-function)
+ (helm-highlight-current-line)))
+
+(defun helm-imenu-persistent-action (candidate)
+ "Default persistent action for `helm-source-imenu'."
+ (helm-imenu--maybe-switch-to-buffer candidate)
+ (imenu candidate)
+ (helm-highlight-current-line))
+
+(defun helm-imenu-candidates (&optional buffer)
+ (with-current-buffer (or buffer helm-current-buffer)
+ (let ((tick (buffer-modified-tick)))
+ (if (eq helm-cached-imenu-tick tick)
+ helm-cached-imenu-candidates
+ (setq imenu--index-alist nil)
+ (prog1 (setq helm-cached-imenu-candidates
+ (let ((index (imenu--make-index-alist t)))
+ (helm-imenu--candidates-1
+ (delete (assoc "*Rescan*" index) index))))
+ (setq helm-cached-imenu-tick tick))))))
+
+(defun helm-imenu-candidates-in-all-buffers (&optional build-sources)
+ (let* ((lst (buffer-list))
+ (progress-reporter (make-progress-reporter
+ "Imenu indexing buffers..." 1 (length lst))))
+ (prog1
+ (cl-loop with cur-buf = (if build-sources
+ (current-buffer) helm-current-buffer)
+ for b in lst
+ for count from 1
+ when (with-current-buffer b
+ (and (or (member major-mode helm-imenu-extra-modes)
+ (derived-mode-p 'prog-mode))
+ (helm-same-major-mode-p
+ cur-buf helm-imenu-all-buffer-assoc)))
+ if build-sources
+ collect (helm-make-source
+ (format "Imenu in %s" (buffer-name b))
+ 'helm-imenu-source
+ :candidates (with-current-buffer b
+ (helm-imenu-candidates b))
+ :fuzzy-match helm-imenu-fuzzy-match)
+ else
+ append (with-current-buffer b
+ (helm-imenu-candidates b))
+ do (progress-reporter-update progress-reporter count))
+ (progress-reporter-done progress-reporter))))
+
+(defun helm-imenu--candidates-1 (alist)
+ (cl-loop for elm in alist
+ nconc (cond
+ ((imenu--subalist-p elm)
+ (helm-imenu--candidates-1
+ (cl-loop for (e . v) in (cdr elm) collect
+ (cons (propertize
+ e 'helm-imenu-type (car elm))
+ ;; If value is an integer, convert it
+ ;; to a marker, otherwise it is a cons cell
+ ;; and it will be converted on next recursions.
+ ;; (Issue #1060) [1].
+ (if (integerp v) (copy-marker v) v)))))
+ ((listp (cdr elm))
+ (and elm (list elm)))
+ (t
+ ;; bug in imenu, should not be needed.
+ (and (cdr elm)
+ ;; Semantic uses overlays whereas imenu uses
+ ;; markers (issue #1706).
+ (setcdr elm (pcase (cdr elm) ; Same as [1].
+ ((and ov (pred overlayp))
+ (copy-overlay ov))
+ ((and mk (or (pred markerp)
+ (pred integerp)))
+ (copy-marker mk))))
+ (list elm))))))
+
+(defun helm-imenu--get-prop (item)
+ ;; property value of ITEM can have itself
+ ;; a property value which have itself a property value
+ ;; ...and so on; Return a list of all these
+ ;; properties values starting at ITEM.
+ (let* ((prop (get-text-property 0 'helm-imenu-type item))
+ (lst (list prop item)))
+ (when prop
+ (while prop
+ (setq prop (get-text-property 0 'helm-imenu-type prop))
+ (and prop (push prop lst)))
+ lst)))
+
+(defun helm-imenu-transformer (candidates)
+ (cl-loop for (k . v) in candidates
+ ;; (k . v) == (symbol-name . marker)
+ for bufname = (buffer-name
+ (pcase v
+ ((pred overlayp) (overlay-buffer v))
+ ((or (pred markerp) (pred integerp))
+ (marker-buffer v))))
+ for types = (or (helm-imenu--get-prop k)
+ (list (if (with-current-buffer bufname
+ (derived-mode-p 'prog-mode))
+ "Function"
+ "Top level")
+ k))
+ for disp1 = (mapconcat
+ (lambda (x)
+ (propertize
+ x 'face
+ (cl-loop for (p . f) in helm-imenu-type-faces
+ when (string-match p x) return f
+ finally return 'default)))
+ types helm-imenu-delimiter)
+ for disp = (propertize disp1 'help-echo bufname)
+ collect
+ (cons disp (cons k v))))
+\f
+;;;###autoload
+(defun helm-imenu ()
+ "Preconfigured `helm' for `imenu'."
+ (interactive)
+ (unless helm-source-imenu
+ (setq helm-source-imenu
+ (helm-make-source "Imenu" 'helm-imenu-source
+ :fuzzy-match helm-imenu-fuzzy-match)))
+ (let ((imenu-auto-rescan t)
+ (str (thing-at-point 'symbol))
+ (helm-execute-action-at-once-if-one
+ helm-imenu-execute-action-at-once-if-one))
+ (helm :sources 'helm-source-imenu
+ :default (list (concat "\\_<" (and str (regexp-quote str)) "\\_>") str)
+ :preselect str
+ :buffer "*helm imenu*")))
+
+;;;###autoload
+(defun helm-imenu-in-all-buffers ()
+ "Preconfigured helm for fetching imenu entries in all buffers with similar mode as current.
+A mode is similar as current if it is the same, it is derived i.e `derived-mode-p'
+or it have an association in `helm-imenu-all-buffer-assoc'."
+ (interactive)
+ (unless helm-imenu-in-all-buffers-separate-sources
+ (unless helm-source-imenu-all
+ (setq helm-source-imenu-all
+ (helm-make-source "Imenu in all buffers" 'helm-imenu-source
+ :init (lambda ()
+ ;; Use a cache to avoid repeatedly sending
+ ;; progress-reporter message when updating
+ ;; (Issue #1704).
+ (setq helm-imenu--in-all-buffers-cache
+ (helm-imenu-candidates-in-all-buffers)))
+ :candidates 'helm-imenu--in-all-buffers-cache
+ :fuzzy-match helm-imenu-fuzzy-match))))
+ (let ((imenu-auto-rescan t)
+ (str (thing-at-point 'symbol))
+ (helm-execute-action-at-once-if-one
+ helm-imenu-execute-action-at-once-if-one)
+ (helm--maybe-use-default-as-input
+ (not (null (memq 'helm-source-imenu-all
+ helm-sources-using-default-as-input))))
+ (sources (if helm-imenu-in-all-buffers-separate-sources
+ (helm-imenu-candidates-in-all-buffers 'build-sources)
+ '(helm-source-imenu-all))))
+ (helm :sources sources
+ :default (list (concat "\\_<" (and str (regexp-quote str)) "\\_>") str)
+ :preselect (unless helm--maybe-use-default-as-input str)
+ :buffer "*helm imenu all*")))
+
+(provide 'helm-imenu)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-imenu.el ends here
--- /dev/null
+;;; helm-info.el --- Browse info index with helm -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'helm)
+(require 'helm-lib)
+(require 'helm-utils)
+(require 'info)
+
+(declare-function Info-index-nodes "info" (&optional file))
+(declare-function Info-goto-node "info" (&optional fork))
+(declare-function Info-find-node "info.el" (filename nodename &optional no-going-back))
+(defvar Info-history)
+(defvar Info-directory-list)
+\f
+;;; Customize
+
+(defgroup helm-info nil
+ "Info-related applications and libraries for Helm."
+ :group 'helm)
+
+(defcustom helm-info-default-sources
+ '(helm-source-info-elisp
+ helm-source-info-cl
+ helm-source-info-eieio
+ helm-source-info-pages)
+ "Default sources to use for looking up symbols at point in Info
+files with `helm-info-at-point'."
+ :group 'helm-info
+ :type '(repeat (choice symbol)))
+\f
+;;; Build info-index sources with `helm-info-source' class.
+
+(cl-defun helm-info-init (&optional (file (helm-attr 'info-file)))
+ ;; Allow reinit candidate buffer when using edebug.
+ (helm-aif (and debug-on-error
+ (helm-candidate-buffer))
+ (kill-buffer it))
+ (unless (helm-candidate-buffer)
+ (save-selected-window
+ (info file " *helm info temp buffer*")
+ (let ((tobuf (helm-candidate-buffer 'global))
+ Info-history
+ start end line)
+ (cl-dolist (node (Info-index-nodes))
+ (Info-goto-node node)
+ (goto-char (point-min))
+ (while (search-forward "\n* " nil t)
+ (unless (search-forward "Menu:\n" (1+ (point-at-eol)) t)
+ (setq start (point-at-bol)
+ ;; Fix issue #1503 by getting the invisible
+ ;; info displayed on next line in long strings.
+ ;; e.g "* Foo.\n (line 12)" instead of
+ ;; "* Foo.(line 12)"
+ end (or (save-excursion
+ (goto-char (point-at-bol))
+ (re-search-forward "(line +[0-9]+)" nil t))
+ (point-at-eol))
+ ;; Long string have a new line inserted before the
+ ;; invisible spec, remove it.
+ line (replace-regexp-in-string
+ "\n" "" (buffer-substring start end)))
+ (with-current-buffer tobuf
+ (insert line)
+ (insert "\n")))))
+ (bury-buffer)))))
+
+(defun helm-info-goto (node-line)
+ (Info-goto-node (car node-line))
+ (helm-goto-line (cdr node-line)))
+
+(defun helm-info-display-to-real (line)
+ (and (string-match
+ ;; This regexp is stolen from Info-apropos-matches
+ "\\* +\\([^\n]*.+[^\n]*\\):[ \t]+\\([^\n]*\\)\\.\\(?:[ \t\n]*(line +\\([0-9]+\\))\\)?" line)
+ (cons (format "(%s)%s" (helm-attr 'info-file) (match-string 2 line))
+ (string-to-number (or (match-string 3 line) "1")))))
+
+(defclass helm-info-source (helm-source-in-buffer)
+ ((info-file :initarg :info-file
+ :initform nil
+ :custom 'string)
+ (init :initform #'helm-info-init)
+ (display-to-real :initform #'helm-info-display-to-real)
+ (get-line :initform #'buffer-substring)
+ (action :initform '(("Goto node" . helm-info-goto)))))
+
+(defmacro helm-build-info-source (fname &rest args)
+ `(helm-make-source (concat "Info Index: " ,fname) 'helm-info-source
+ :info-file ,fname ,@args))
+
+(defun helm-build-info-index-command (name doc source buffer)
+ "Define a helm command NAME with documentation DOC.
+Arg SOURCE will be an existing helm source named
+`helm-source-info-<NAME>' and BUFFER a string buffer name."
+ (defalias (intern (concat "helm-info-" name))
+ (lambda ()
+ (interactive)
+ (helm :sources source
+ :buffer buffer
+ :candidate-number-limit 1000))
+ doc))
+
+(defun helm-define-info-index-sources (var-value &optional commands)
+ "Define helm sources named helm-source-info-<NAME>.
+Sources are generated for all entries of `helm-default-info-index-list'.
+If COMMANDS arg is non-nil, also build commands named `helm-info-<NAME>'.
+Where NAME is an element of `helm-default-info-index-list'."
+ (cl-loop for str in var-value
+ for sym = (intern (concat "helm-source-info-" str))
+ do (set sym (helm-build-info-source str))
+ when commands
+ do (helm-build-info-index-command
+ str (format "Predefined helm for %s info." str)
+ sym (format "*helm info %s*" str))))
+
+(defun helm-info-index-set (var value)
+ (set var value)
+ (helm-define-info-index-sources value t))
+\f
+;;; Search Info files
+
+;; `helm-info' is the main entry point here. It prompts the user for an Info
+;; file, then a term in the file's index to jump to.
+
+(defvar helm-info-searched (make-ring 32)
+ "Ring of previously searched Info files.")
+
+(defun helm-get-info-files ()
+ "Return list of Info files to use for `helm-info'.
+
+Elements of the list are strings of Info file names without
+extensions (e.g. \"emacs\" for file \"emacs.info.gz\"). Info
+files are found by searching directories in
+`Info-directory-list'."
+ (let ((files (cl-loop for d in (or Info-directory-list
+ Info-default-directory-list)
+ when (file-directory-p d)
+ append (directory-files d nil "\\.info"))))
+ (helm-fast-remove-dups
+ (cl-loop for f in files collect
+ (helm-file-name-sans-extension f))
+ :test 'equal)))
+
+(defcustom helm-default-info-index-list
+ (helm-get-info-files)
+ "Info files to search in with `helm-info'."
+ :group 'helm-info
+ :type '(repeat (choice string))
+ :set 'helm-info-index-set)
+
+(defun helm-info-search-index (candidate)
+ "Search the index of CANDIDATE's Info file using the function
+helm-info-<CANDIDATE>."
+ (let ((helm-info-function
+ (intern-soft (concat "helm-info-" candidate))))
+ (when (fboundp helm-info-function)
+ (funcall helm-info-function)
+ (ring-insert helm-info-searched candidate))))
+
+(defun helm-def-source--info-files ()
+ "Return a `helm' source for Info files."
+ (helm-build-sync-source "Helm Info"
+ :candidates
+ (lambda () (copy-sequence helm-default-info-index-list))
+ :candidate-number-limit 999
+ :candidate-transformer
+ (lambda (candidates)
+ (sort candidates #'string-lessp))
+ :nomark t
+ :action '(("Search index" . helm-info-search-index))))
+
+;;;###autoload
+(defun helm-info (&optional refresh)
+ "Preconfigured `helm' for searching Info files' indices.
+
+With a prefix argument \\[universal-argument], set REFRESH to non-nil.
+
+Optional parameter REFRESH, when non-nil, reevaluates
+`helm-default-info-index-list'. If the variable has been
+customized, set it to its saved value. If not, set it to its
+standard value. See `custom-reevaluate-setting' for more.
+
+REFRESH is useful when new Info files are installed. If
+`helm-default-info-index-list' has not been customized, the new
+Info files are made available."
+ (interactive "P")
+ (let ((default (unless (ring-empty-p helm-info-searched)
+ (ring-ref helm-info-searched 0))))
+ (when refresh
+ (custom-reevaluate-setting 'helm-default-info-index-list))
+ (helm :sources (helm-def-source--info-files)
+ :buffer "*helm Info*"
+ :preselect (and default
+ (concat "\\_<" (regexp-quote default) "\\_>")))))
+\f
+;;;; Info at point
+
+;; `helm-info-at-point' is the main entry point here. It searches for the
+;; symbol at point through the Info sources defined in
+;; `helm-info-default-sources' and jumps to it.
+
+(defvar helm-info--pages-cache nil
+ "Cache for all Info pages on the system.")
+
+(defvar helm-source-info-pages
+ (helm-build-sync-source "Info Pages"
+ :init #'helm-info-pages-init
+ :candidates (lambda () helm-info--pages-cache)
+ :action '(("Show with Info" .
+ (lambda (node-str)
+ (info (replace-regexp-in-string
+ "^[^:]+: " "" node-str)))))
+ :requires-pattern 2)
+ "Helm source for Info pages.")
+
+(defun helm-info-pages-init ()
+ "Collect candidates for initial Info node Top."
+ (or helm-info--pages-cache
+ (let ((info-topic-regexp "\\* +\\([^:]+: ([^)]+)[^.]*\\)\\."))
+ (save-selected-window
+ (info "dir" " *helm info temp buffer*")
+ (Info-find-node "dir" "top")
+ (goto-char (point-min))
+ (while (re-search-forward info-topic-regexp nil t)
+ (push (match-string-no-properties 1)
+ helm-info--pages-cache))
+ (kill-buffer)))))
+
+;;;###autoload
+(defun helm-info-at-point ()
+ "Preconfigured `helm' for searching info at point."
+ (interactive)
+ (cl-loop for src in helm-info-default-sources
+ for name = (if (symbolp src)
+ (assoc 'name (symbol-value src))
+ (assoc 'name src))
+ unless name
+ do (warn "Couldn't build source `%S' without its info file" src))
+ (helm :sources helm-info-default-sources
+ :buffer "*helm info*"))
+\f
+(provide 'helm-info)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-info.el ends here
--- /dev/null
+;;; helm-locate.el --- helm interface for locate. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;; NOTE for WINDOZE users:
+;; You have to install Everything with his command line interface here:
+;; http://www.voidtools.com/download.php
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'helm)
+(require 'helm-types)
+(require 'helm-help)
+
+\f
+(defgroup helm-locate nil
+ "Locate related Applications and libraries for Helm."
+ :group 'helm)
+
+(defcustom helm-locate-db-file-regexp "m?locate\.db$"
+ "Default regexp to match locate database.
+If nil Search in all files."
+ :type 'string
+ :group 'helm-locate)
+
+(defcustom helm-ff-locate-db-filename "locate.db"
+ "The basename of the locatedb file you use locally in your directories.
+When this is set and `helm' find such a file in the directory from
+where you launch locate, it will use this file and will not prompt you
+for a db file.
+Note that this happen only when locate is launched with a prefix arg."
+ :group 'helm-locate
+ :type 'string)
+
+(defcustom helm-locate-command nil
+ "A list of arguments for locate program.
+
+Helm will calculate a default value for your system on startup unless
+`helm-locate-command' is non-nil, here the default values it will use
+according to your system:
+
+Gnu/linux: \"locate %s -e -A --regex %s\"
+berkeley-unix: \"locate %s %s\"
+windows-nt: \"es %s %s\"
+Others: \"locate %s %s\"
+
+This string will be passed to format so it should end with `%s'.
+The first format spec is used for the \"-i\" value of locate/es,
+So don't set it directly but use `helm-locate-case-fold-search'
+for this.
+
+The last option must be the one preceding pattern i.e \"-r\" or \"--regex\".
+
+You will be able to pass other options such as \"-b\" or \"l\"
+during helm invocation after entering pattern only when multi matching,
+not when fuzzy matching.
+
+Note that the \"-b\" option is added automatically by helm when
+var `helm-locate-fuzzy-match' is non-nil and switching back from
+multimatch to fuzzy matching (this is done automatically when a space
+is detected in pattern)."
+ :type 'string
+ :group 'helm-locate)
+
+(defcustom helm-locate-create-db-command
+ "updatedb -l 0 -o '%s' -U '%s'"
+ "Command used to create a locale locate db file."
+ :type 'string
+ :group 'helm-locate)
+
+(defcustom helm-locate-case-fold-search helm-case-fold-search
+ "It have the same meaning as `helm-case-fold-search'.
+The -i option of locate will be used depending of value of
+`helm-pattern' when this is set to 'smart.
+When nil \"-i\" will not be used at all.
+and when non--nil it will always be used.
+NOTE: the -i option of the \"es\" command used on windows does
+the opposite of \"locate\" command."
+ :group 'helm-locate
+ :type 'symbol)
+
+(defcustom helm-locate-fuzzy-match nil
+ "Enable fuzzy matching in `helm-locate'.
+Note that when this is enabled searching is done on basename."
+ :group 'helm-locate
+ :type 'boolean)
+
+(defcustom helm-locate-fuzzy-sort-fn
+ #'helm-locate-default-fuzzy-sort-fn
+ "Default fuzzy matching sort function for locate."
+ :group 'helm-locate
+ :type 'boolean)
+
+(defcustom helm-locate-project-list nil
+ "A list of directories, your projects.
+When set, allow browsing recursively files in all
+directories of this list with `helm-projects-find-files'."
+ :group 'helm-locate
+ :type '(repeat string))
+
+(defcustom helm-locate-recursive-dirs-command "locate -i -e -A --regex '^%s' '%s.*$'"
+ "Command used for recursive directories completion in `helm-find-files'.
+
+For Windows and `es' use something like \"es -r ^%s.*%s.*$\"
+
+The two format specs are mandatory.
+
+If for some reasons you can't use locate because your filesystem
+doesn't have a data base, you can use find command from findutils but
+be aware that it will be much slower, see `helm-find-files' embebded
+help for more infos."
+ :type 'string
+ :group 'helm-files)
+
+\f
+(defvar helm-generic-files-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map helm-map)
+ (define-key map (kbd "C-]") 'helm-ff-run-toggle-basename)
+ (define-key map (kbd "C-s") 'helm-ff-run-grep)
+ (define-key map (kbd "M-g s") 'helm-ff-run-grep)
+ (define-key map (kbd "M-g z") 'helm-ff-run-zgrep)
+ (define-key map (kbd "M-g p") 'helm-ff-run-pdfgrep)
+ (define-key map (kbd "C-c g") 'helm-ff-run-gid)
+ (define-key map (kbd "M-R") 'helm-ff-run-rename-file)
+ (define-key map (kbd "M-C") 'helm-ff-run-copy-file)
+ (define-key map (kbd "M-B") 'helm-ff-run-byte-compile-file)
+ (define-key map (kbd "M-L") 'helm-ff-run-load-file)
+ (define-key map (kbd "M-S") 'helm-ff-run-symlink-file)
+ (define-key map (kbd "M-H") 'helm-ff-run-hardlink-file)
+ (define-key map (kbd "M-D") 'helm-ff-run-delete-file)
+ (define-key map (kbd "C-=") 'helm-ff-run-ediff-file)
+ (define-key map (kbd "C-c =") 'helm-ff-run-ediff-merge-file)
+ (define-key map (kbd "C-c o") 'helm-ff-run-switch-other-window)
+ (define-key map (kbd "C-c r") 'helm-ff-run-find-file-as-root)
+ (define-key map (kbd "C-c C-o") 'helm-ff-run-switch-other-frame)
+ (define-key map (kbd "M-i") 'helm-ff-properties-persistent)
+ (define-key map (kbd "C-c C-x") 'helm-ff-run-open-file-externally)
+ (define-key map (kbd "C-c X") 'helm-ff-run-open-file-with-default-tool)
+ (define-key map (kbd "M-.") 'helm-ff-run-etags)
+ (define-key map (kbd "C-c @") 'helm-ff-run-insert-org-link)
+ (define-key map (kbd "C-x C-q") 'helm-ff-run-marked-files-in-dired)
+ (define-key map (kbd "C-c C-a") 'helm-ff-run-mail-attach-files)
+ map)
+ "Generic Keymap for files.")
+
+\f
+(defface helm-locate-finish
+ '((t (:foreground "Green")))
+ "Face used in mode line when locate process is finish."
+ :group 'helm-locate)
+
+\f
+(defun helm-ff-find-locatedb (&optional from-ff)
+ "Try to find if a local locatedb file is available.
+The search is done in `helm-ff-default-directory' or
+fall back to `default-directory' if FROM-FF is nil."
+ (helm-aif (and helm-ff-locate-db-filename
+ (locate-dominating-file
+ (or (and from-ff
+ helm-ff-default-directory)
+ default-directory)
+ helm-ff-locate-db-filename))
+ (expand-file-name helm-ff-locate-db-filename it)))
+
+(defun helm-locate-create-db-default-function (db-name directory)
+ "Default function used to create a locale locate db file.
+Argument DB-NAME name of the db file.
+Argument DIRECTORY root of file system subtree to scan."
+ (format helm-locate-create-db-command
+ db-name (expand-file-name directory)))
+
+(defvar helm-locate-create-db-function
+ #'helm-locate-create-db-default-function
+ "Function used to create a locale locate db file.
+It should receive the same arguments as
+`helm-locate-create-db-default-function'.")
+
+(defun helm-locate-1 (&optional localdb init from-ff default)
+ "Generic function to run Locate.
+Prefix arg LOCALDB when (4) search and use a local locate db file when it
+exists or create it, when (16) force update of existing db file
+even if exists.
+It have no effect when locate command is 'es'.
+INIT is a string to use as initial input in prompt.
+See `helm-locate-with-db' and `helm-locate'."
+ (require 'helm-mode)
+ (helm-locate-set-command)
+ (let ((pfn (lambda (candidate)
+ (if (file-directory-p candidate)
+ (message "Error: The locate Db should be a file")
+ (if (= (shell-command
+ (funcall helm-locate-create-db-function
+ candidate
+ helm-ff-default-directory))
+ 0)
+ (message "New locatedb file `%s' created" candidate)
+ (error "Failed to create locatedb file `%s'" candidate)))))
+ (locdb (and localdb
+ (not (string-match "^es" helm-locate-command))
+ (or (and (equal '(4) localdb)
+ (helm-ff-find-locatedb from-ff))
+ (helm-read-file-name
+ "Create Locate Db file: "
+ :initial-input (expand-file-name "locate.db"
+ (or helm-ff-default-directory
+ default-directory))
+ :preselect helm-locate-db-file-regexp
+ :test (lambda (x)
+ (if helm-locate-db-file-regexp
+ ;; Select only locate db files and directories
+ ;; to allow navigation.
+ (or (string-match
+ helm-locate-db-file-regexp x)
+ (file-directory-p x))
+ x)))))))
+ (when (and locdb (or (equal localdb '(16))
+ (not (file-exists-p locdb))))
+ (funcall pfn locdb))
+ (helm-locate-with-db (and localdb locdb) init default)))
+
+(defun helm-locate-set-command ()
+ "Setup `helm-locate-command' if not already defined."
+ (unless helm-locate-command
+ (setq helm-locate-command
+ (cl-case system-type
+ (gnu/linux "locate %s -e -A --regex %s")
+ (berkeley-unix "locate %s %s")
+ (windows-nt "es %s %s")
+ (t "locate %s %s")))))
+
+(defun helm-locate-initial-setup ()
+ (require 'helm-for-files)
+ (helm-locate-set-command))
+
+(defvar helm-file-name-history nil)
+(defun helm-locate-with-db (&optional db initial-input default)
+ "Run locate -d DB.
+If DB is not given or nil use locate without -d option.
+Argument DB can be given as a string or list of db files.
+Argument INITIAL-INPUT is a string to use as initial-input.
+See also `helm-locate'."
+ (require 'helm-files)
+ (when (and db (stringp db)) (setq db (list db)))
+ (helm-locate-set-command)
+ (let ((helm-locate-command
+ (if db
+ (replace-regexp-in-string
+ "locate"
+ (format (if helm-locate-fuzzy-match
+ "locate -b -d '%s'" "locate -d '%s'")
+ (mapconcat 'identity
+ ;; Remove eventually
+ ;; marked directories by error.
+ (cl-loop for i in db
+ unless (file-directory-p i)
+ ;; expand-file-name to resolve
+ ;; abbreviated fnames not
+ ;; expanding inside single
+ ;; quotes i.e. '%s'.
+ collect (expand-file-name i))
+ ":"))
+ helm-locate-command)
+ (if (and helm-locate-fuzzy-match
+ (not (string-match-p "\\`locate -b" helm-locate-command)))
+ (replace-regexp-in-string
+ "\\`locate" "locate -b" helm-locate-command)
+ helm-locate-command))))
+ (setq helm-file-name-history (mapcar 'helm-basename file-name-history))
+ (helm :sources 'helm-source-locate
+ :buffer "*helm locate*"
+ :ff-transformer-show-only-basename nil
+ :input initial-input
+ :default default
+ :history 'helm-file-name-history)))
+
+(defun helm-locate-init ()
+ "Initialize async locate process for `helm-source-locate'."
+ (let* ((locate-is-es (string-match "\\`es" helm-locate-command))
+ (real-locate (string-match "\\`locate" helm-locate-command))
+ (case-sensitive-flag (if locate-is-es "-i" ""))
+ (ignore-case-flag (if (or locate-is-es
+ (not real-locate)) "" "-i"))
+ (args (helm-mm-split-pattern helm-pattern))
+ (cmd (format helm-locate-command
+ (cl-case helm-locate-case-fold-search
+ (smart (let ((case-fold-search nil))
+ (if (string-match "[[:upper:]]" helm-pattern)
+ case-sensitive-flag
+ ignore-case-flag)))
+ (t (if helm-locate-case-fold-search
+ ignore-case-flag
+ case-sensitive-flag)))
+ (concat
+ ;; The pattern itself.
+ (shell-quote-argument (car args)) " "
+ ;; Possible locate args added
+ ;; after pattern, don't quote them.
+ (mapconcat 'identity (cdr args) " "))))
+ (default-directory (if (file-directory-p default-directory)
+ default-directory "/")))
+ (helm-log "Starting helm-locate process")
+ (helm-log "Command line used was:\n\n%s"
+ (concat ">>> " (propertize cmd 'face 'font-lock-comment-face) "\n\n"))
+ (prog1
+ (start-process-shell-command
+ "locate-process" helm-buffer
+ cmd)
+ (set-process-sentinel
+ (get-buffer-process helm-buffer)
+ (lambda (process event)
+ (let* ((err (process-exit-status process))
+ (noresult (= err 1)))
+ (cond (noresult
+ (with-helm-buffer
+ (unless (cdr helm-sources)
+ (insert (concat "* Exit with code 1, no result found,"
+ " command line was:\n\n "
+ cmd)))))
+ ((string= event "finished\n")
+ (when (and helm-locate-fuzzy-match
+ (not (string-match-p "\\s-" helm-pattern)))
+ (helm-redisplay-buffer))
+ (with-helm-window
+ (setq mode-line-format
+ '(" " mode-line-buffer-identification " "
+ (:eval (format "L%s" (helm-candidate-number-at-point))) " "
+ (:eval (propertize
+ (format "[Locate process finished - (%s results)]"
+ (max (1- (count-lines
+ (point-min) (point-max)))
+ 0))
+ 'face 'helm-locate-finish))))
+ (force-mode-line-update)))
+ (t
+ (helm-log "Error: Locate %s"
+ (replace-regexp-in-string "\n" "" event))))))))))
+
+(defun helm-locate-default-fuzzy-sort-fn (candidates)
+ "Default sort function for files in fuzzy matching.
+Sort is done on basename of CANDIDATES."
+ (helm-fuzzy-matching-default-sort-fn-1 candidates nil t))
+
+(defclass helm-locate-source (helm-source-async helm-type-file)
+ ((init :initform 'helm-locate-initial-setup)
+ (candidates-process :initform 'helm-locate-init)
+ (requires-pattern :initform 3)
+ (history :initform 'helm-file-name-history)
+ (persistent-action :initform 'helm-ff-kill-or-find-buffer-fname)
+ (candidate-number-limit :initform 9999)
+ (redisplay :initform (progn helm-locate-fuzzy-sort-fn))
+ (group :initform 'helm-locate)))
+
+(defvar helm-source-locate
+ (helm-make-source "Locate" 'helm-locate-source
+ :pattern-transformer 'helm-locate-pattern-transformer
+ ;; :match-part is only used here to tell helm which part
+ ;; of candidate to highlight.
+ :match-part (lambda (candidate)
+ (if (or (string-match-p " -b\\'" helm-pattern)
+ (and helm-locate-fuzzy-match
+ (not (string-match "\\s-" helm-pattern))))
+ (helm-basename candidate)
+ candidate))))
+
+(defun helm-locate-pattern-transformer (pattern)
+ (if helm-locate-fuzzy-match
+ ;; When fuzzy is enabled helm add "-b" option on startup.
+ (cond ((string-match-p " " pattern)
+ (when (string-match "\\`locate -b" helm-locate-command)
+ (setq helm-locate-command
+ (replace-match "locate" t t helm-locate-command)))
+ pattern)
+ (t
+ (unless (string-match-p "\\`locate -b" helm-locate-command)
+ (setq helm-locate-command
+ (replace-regexp-in-string
+ "\\`locate" "locate -b" helm-locate-command)))
+ (helm--mapconcat-pattern pattern)))
+ pattern))
+
+(defun helm-locate-find-dbs-in-projects (&optional update)
+ (let* ((pfn (lambda (candidate directory)
+ (unless (= (shell-command
+ (funcall helm-locate-create-db-function
+ candidate
+ directory))
+ 0)
+ (error "Failed to create locatedb file `%s'" candidate)))))
+ (cl-loop for p in helm-locate-project-list
+ for db = (expand-file-name
+ helm-ff-locate-db-filename
+ (file-name-as-directory p))
+ if (and (null update) (file-exists-p db))
+ collect db
+ else do (funcall pfn db p)
+ and collect db)))
+
+;;; Directory completion for hff.
+;;
+(defclass helm-locate-subdirs-source (helm-source-in-buffer)
+ ((basedir :initarg :basedir
+ :initform nil
+ :custom string)
+ (subdir :initarg :subdir
+ :initform nil
+ :custom 'string)
+ (data :initform #'helm-locate-init-subdirs)
+ (group :initform 'helm-locate)))
+
+(defun helm-locate-init-subdirs ()
+ (with-temp-buffer
+ (call-process-shell-command
+ (format helm-locate-recursive-dirs-command
+ (if (string-match-p "\\`es" helm-locate-recursive-dirs-command)
+ ;; Fix W32 paths.
+ (replace-regexp-in-string
+ "/" "\\\\\\\\" (helm-attr 'basedir))
+ (helm-attr 'basedir))
+ (helm-attr 'subdir))
+ nil t nil)
+ (buffer-string)))
+
+;;;###autoload
+(defun helm-projects-find-files (update)
+ "Find files with locate in `helm-locate-project-list'.
+With a prefix arg refresh the database in each project."
+ (interactive "P")
+ (helm-locate-set-command)
+ (cl-assert (and (string-match-p "\\`locate" helm-locate-command)
+ (executable-find "updatedb"))
+ nil "Unsupported locate version")
+ (let ((dbs (helm-locate-find-dbs-in-projects update)))
+ (if dbs
+ (helm-locate-with-db dbs)
+ (user-error "No projects found, please setup `helm-locate-project-list'"))))
+
+;;;###autoload
+(defun helm-locate (arg)
+ "Preconfigured `helm' for Locate.
+Note: you can add locate options after entering pattern.
+See 'man locate' for valid options and also `helm-locate-command'.
+
+You can specify a local database with prefix argument ARG.
+With two prefix arg, refresh the current local db or create it
+if it doesn't exists.
+
+To create a user specific db, use
+\"updatedb -l 0 -o db_path -U directory\".
+Where db_path is a filename matched by
+`helm-locate-db-file-regexp'."
+ (interactive "P")
+ (helm-set-local-variable 'helm-async-outer-limit-hook
+ (list (lambda ()
+ (when (and helm-locate-fuzzy-match
+ (not (string-match-p
+ "\\s-" helm-pattern)))
+ (helm-redisplay-buffer)))))
+ (setq helm-ff-default-directory default-directory)
+ (helm-locate-1 arg nil nil (thing-at-point 'filename)))
+
+(provide 'helm-locate)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-locate.el ends here
--- /dev/null
+;;; helm-man.el --- Man and woman UI -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'helm)
+(require 'helm-help)
+
+(defvar woman-topic-all-completions)
+(defvar woman-manpath)
+(defvar woman-path)
+(defvar woman-expanded-directory-path)
+(declare-function woman-file-name "woman.el" (topic &optional re-cache))
+(declare-function woman-file-name-all-completions "woman.el" (topic))
+(declare-function Man-getpage-in-background "man.el" (topic))
+(declare-function woman-expand-directory-path "woman.el" (path-dirs path-regexps))
+(declare-function woman-topic-all-completions "woman.el" (path))
+(declare-function helm-generic-sort-fn "helm-utils.el" (S1 S2))
+
+(defgroup helm-man nil
+ "Man and Woman applications for helm."
+ :group 'helm)
+
+(defcustom helm-man-or-woman-function 'Man-getpage-in-background
+ "Default command to display a man page."
+ :group 'helm-man
+ :type '(radio :tag "Preferred command to display a man page"
+ (const :tag "Man" Man-getpage-in-background)
+ (const :tag "Woman" woman)))
+
+(defcustom helm-man-format-switches (cl-case system-type
+ ((darwin macos) "%s")
+ (t "-l %s"))
+ "Arguments to pass to the `manual-entry' function.
+Arguments are passed to `manual-entry' with `format.'"
+ :group 'helm-man
+ :type 'string)
+
+;; Internal
+(defvar helm-man--pages nil
+ "All man pages on system.
+Will be calculated the first time you invoke helm with this
+source.")
+
+(defun helm-man-default-action (candidate)
+ "Default action for jumping to a woman or man page from helm."
+ (let ((wfiles (mapcar #'car (woman-file-name-all-completions candidate))))
+ (condition-case nil
+ (let ((file (if (cdr wfiles)
+ (helm-comp-read "ManFile: " wfiles :must-match t)
+ (car wfiles))))
+ (if (eq helm-man-or-woman-function 'Man-getpage-in-background)
+ (manual-entry (format helm-man-format-switches file))
+ (condition-case nil
+ (woman-find-file file)
+ ;; If woman is unable to format correctly
+ ;; try Man instead.
+ (error (kill-buffer)
+ (manual-entry (format helm-man-format-switches file))))))
+ ;; If even Man failed with file as argument, try again with Man
+ ;; but using Topic candidate instead of the file calculated by
+ ;; woman.
+ (error (kill-buffer)
+ (Man-getpage-in-background candidate)))))
+
+(defun helm-man--init ()
+ (require 'woman)
+ (require 'helm-utils)
+ (unless helm-man--pages
+ (setq woman-expanded-directory-path
+ (woman-expand-directory-path woman-manpath woman-path))
+ (setq woman-topic-all-completions
+ (woman-topic-all-completions woman-expanded-directory-path))
+ (setq helm-man--pages (mapcar 'car woman-topic-all-completions)))
+ (helm-init-candidates-in-buffer 'global helm-man--pages))
+
+(defvar helm-source-man-pages
+ (helm-build-in-buffer-source "Manual Pages"
+ :init #'helm-man--init
+ :persistent-action #'ignore
+ :filtered-candidate-transformer
+ (lambda (candidates _source)
+ (sort candidates #'helm-generic-sort-fn))
+ :action '(("Display Man page" . helm-man-default-action))
+ :group 'helm-man))
+
+;;;###autoload
+(defun helm-man-woman (arg)
+ "Preconfigured `helm' for Man and Woman pages.
+With a prefix arg reinitialize the cache."
+ (interactive "P")
+ (when arg (setq helm-man--pages nil))
+ (helm :sources 'helm-source-man-pages
+ :buffer "*helm man woman*"))
+
+(provide 'helm-man)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-man.el ends here
--- /dev/null
+;;; helm-misc.el --- Various functions for helm -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Code:
+(require 'cl-lib)
+(require 'helm)
+(require 'helm-help)
+(require 'helm-types)
+
+(declare-function display-time-world-display "time.el")
+(defvar display-time-world-list)
+(declare-function LaTeX-math-mode "ext:latex.el")
+(declare-function jabber-chat-with "ext:jabber.el")
+(declare-function jabber-read-account "ext:jabber.el")
+
+\f
+(defgroup helm-misc nil
+ "Various Applications and libraries for Helm."
+ :group 'helm)
+
+(defcustom helm-time-zone-home-location "Paris"
+ "The time zone of your home"
+ :group 'helm-misc
+ :type 'string)
+
+(defcustom helm-timezone-actions
+ '(("Set timezone env (TZ)" . (lambda (candidate)
+ (setenv "TZ" candidate))))
+ "Actions for helm-timezone."
+ :group 'helm-misc
+ :type '(alist :key-type string :value-type function))
+
+(defface helm-time-zone-current
+ '((t (:foreground "green")))
+ "Face used to colorize current time in `helm-world-time'."
+ :group 'helm-misc)
+
+(defface helm-time-zone-home
+ '((t (:foreground "red")))
+ "Face used to colorize home time in `helm-world-time'."
+ :group 'helm-misc)
+
+
+\f
+;;; Latex completion
+;;
+;; Test
+;; (setq LaTeX-math-menu '("Math"
+;; ["foo" val0 t]
+;; ("bar"
+;; ["baz" val1 t])
+;; ("aze"
+;; ["zer" val2 t])
+;; ("AMS"
+;; ("rec"
+;; ["fer" val3 t])
+;; ("rty"
+;; ["der" val4 t]))
+;; ("ABC"
+;; ("xcv"
+;; ["sdf" val5 t])
+;; ("dfg"
+;; ["fgh" val6 t]))))
+;; (helm-latex-math-candidates)
+;; =>
+;; (("foo" . val0)
+;; ("baz" . val1)
+;; ("zer" . val2)
+;; ("fer" . val3)
+;; ("der" . val4)
+;; ("sdf" . val5)
+;; ("fgh" . val6))
+
+(defvar LaTeX-math-menu)
+(defun helm-latex-math-candidates ()
+ (cl-labels ((helm-latex--math-collect (L)
+ (cond ((vectorp L)
+ (list (cons (aref L 0) (aref L 1))))
+ ((listp L)
+ (cl-loop for a in L nconc
+ (helm-latex--math-collect a))))))
+ (helm-latex--math-collect LaTeX-math-menu)))
+
+(defvar helm-source-latex-math
+ (helm-build-sync-source "Latex Math Menu"
+ :init (lambda ()
+ (with-helm-current-buffer
+ (LaTeX-math-mode 1)))
+ :candidate-number-limit 9999
+ :candidates 'helm-latex-math-candidates
+ :action (lambda (candidate)
+ (call-interactively candidate))))
+
+\f
+;;; Jabber Contacts (jabber.el)
+(defun helm-jabber-online-contacts ()
+ "List online Jabber contacts."
+ (with-no-warnings
+ (cl-loop for item in (jabber-concat-rosters)
+ when (get item 'connected)
+ collect
+ (if (get item 'name)
+ (cons (get item 'name) item)
+ (cons (symbol-name item) item)))))
+
+(defvar helm-source-jabber-contacts
+ (helm-build-sync-source "Jabber Contacts"
+ :init (lambda () (require 'jabber))
+ :candidates (lambda () (mapcar 'car (helm-jabber-online-contacts)))
+ :action (lambda (x)
+ (jabber-chat-with
+ (jabber-read-account)
+ (symbol-name
+ (cdr (assoc x (helm-jabber-online-contacts))))))))
+
+;;; World time
+;;
+(defvar zoneinfo-style-world-list)
+(defvar legacy-style-world-list)
+
+(defun helm-time-zone-transformer (candidates _source)
+ (cl-loop for i in candidates
+ for (z . p) in display-time-world-list
+ collect
+ (cons
+ (cond ((string-match (format-time-string "%H:%M" (current-time)) i)
+ (propertize i 'face 'helm-time-zone-current))
+ ((string-match helm-time-zone-home-location i)
+ (propertize i 'face 'helm-time-zone-home))
+ (t i))
+ z)))
+
+(defvar helm-source-time-world
+ (helm-build-in-buffer-source "Time World List"
+ :init (lambda ()
+ (require 'time)
+ (unless (and display-time-world-list
+ (listp display-time-world-list))
+ ;; adapted from `time--display-world-list' from
+ ;; emacs-27 for compatibility as
+ ;; `display-time-world-list' is set by default to t.
+ (setq display-time-world-list
+ ;; Determine if zoneinfo style timezones are
+ ;; supported by testing that America/New York and
+ ;; Europe/London return different timezones.
+ (let ((nyt (format-time-string "%z" nil "America/New_York"))
+ (gmt (format-time-string "%z" nil "Europe/London")))
+ (if (string-equal nyt gmt)
+ legacy-style-world-list
+ zoneinfo-style-world-list)))))
+ :data (lambda ()
+ (with-temp-buffer
+ (display-time-world-display display-time-world-list)
+ (buffer-string)))
+ :action 'helm-timezone-actions
+ :filtered-candidate-transformer 'helm-time-zone-transformer))
+
+;;; Commands
+;;
+(defun helm-call-interactively (cmd-or-name)
+ "Execute CMD-OR-NAME as Emacs command.
+It is added to `extended-command-history'.
+`helm-current-prefix-arg' is used as the command's prefix argument."
+ (setq extended-command-history
+ (cons (helm-stringify cmd-or-name)
+ (delete (helm-stringify cmd-or-name) extended-command-history)))
+ (let ((current-prefix-arg helm-current-prefix-arg)
+ (cmd (helm-symbolify cmd-or-name)))
+ (if (stringp (symbol-function cmd))
+ (execute-kbd-macro (symbol-function cmd))
+ (setq this-command cmd)
+ (call-interactively cmd))))
+
+;;; Minibuffer History
+;;
+;;
+(defvar helm-minibuffer-history-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map helm-map)
+ (define-key map [remap helm-minibuffer-history] 'undefined)
+ map))
+
+(defcustom helm-minibuffer-history-must-match t
+ "Allow inserting non matching elements when nil or 'confirm."
+ :group 'helm-misc
+ :type '(choice
+ (const :tag "Must match" t)
+ (const :tag "Confirm" 'confirm)
+ (const :tag "Always allow" nil)))
+
+;;; Shell history
+;;
+;;
+(defun helm-comint-input-ring-action (candidate)
+ "Default action for comint history."
+ (with-helm-current-buffer
+ (delete-region (comint-line-beginning-position) (point-max))
+ (insert candidate)))
+
+(defvar helm-source-comint-input-ring
+ (helm-build-sync-source "Comint history"
+ :candidates (lambda ()
+ (with-helm-current-buffer
+ (ring-elements comint-input-ring)))
+ :action 'helm-comint-input-ring-action)
+ "Source that provide helm completion against `comint-input-ring'.")
+
+\f
+;;; Helm ratpoison UI
+;;
+;;
+(defvar helm-source-ratpoison-commands
+ (helm-build-in-buffer-source "Ratpoison Commands"
+ :init 'helm-ratpoison-commands-init
+ :action (helm-make-actions
+ "Execute the command" 'helm-ratpoison-commands-execute)
+ :display-to-real 'helm-ratpoison-commands-display-to-real
+ :candidate-number-limit 999999))
+
+(defun helm-ratpoison-commands-init ()
+ (unless (helm-candidate-buffer)
+ (with-current-buffer (helm-candidate-buffer 'global)
+ ;; with ratpoison prefix key
+ (save-excursion
+ (call-process "ratpoison" nil (current-buffer) nil "-c" "help"))
+ (while (re-search-forward "^\\([^ ]+\\) \\(.+\\)$" nil t)
+ (replace-match "<ratpoison> \\1: \\2"))
+ (goto-char (point-max))
+ ;; direct binding
+ (save-excursion
+ (call-process "ratpoison" nil (current-buffer) nil "-c" "help top"))
+ (while (re-search-forward "^\\([^ ]+\\) \\(.+\\)$" nil t)
+ (replace-match "\\1: \\2")))))
+
+(defun helm-ratpoison-commands-display-to-real (display)
+ (and (string-match ": " display)
+ (substring display (match-end 0))))
+
+(defun helm-ratpoison-commands-execute (candidate)
+ (call-process "ratpoison" nil nil nil "-ic" candidate))
+
+;;; Helm stumpwm UI
+;;
+;;
+(defvar helm-source-stumpwm-commands
+ (helm-build-in-buffer-source "Stumpwm Commands"
+ :init 'helm-stumpwm-commands-init
+ :action (helm-make-actions
+ "Execute the command" 'helm-stumpwm-commands-execute)
+ :candidate-number-limit 999999))
+
+(defun helm-stumpwm-commands-init ()
+ (with-current-buffer (helm-candidate-buffer 'global)
+ (save-excursion
+ (call-process "stumpish" nil (current-buffer) nil "commands"))
+ (while (re-search-forward "[ ]*\\([^ ]+\\)[ ]*\n?" nil t)
+ (replace-match "\n\\1\n"))
+ (delete-blank-lines)
+ (sort-lines nil (point-min) (point-max))
+ (goto-char (point-max))))
+
+(defun helm-stumpwm-commands-execute (candidate)
+ (call-process "stumpish" nil nil nil candidate))
+
+;;;###autoload
+(defun helm-world-time ()
+ "Preconfigured `helm' to show world time.
+Default action change TZ environment variable locally to emacs."
+ (interactive)
+ (helm-other-buffer 'helm-source-time-world "*helm world time*"))
+
+;;;###autoload
+(defun helm-insert-latex-math ()
+ "Preconfigured helm for latex math symbols completion."
+ (interactive)
+ (helm-other-buffer 'helm-source-latex-math "*helm latex*"))
+
+;;;###autoload
+(defun helm-ratpoison-commands ()
+ "Preconfigured `helm' to execute ratpoison commands."
+ (interactive)
+ (helm-other-buffer 'helm-source-ratpoison-commands
+ "*helm ratpoison commands*"))
+
+;;;###autoload
+(defun helm-stumpwm-commands()
+ "Preconfigured helm for stumpwm commands."
+ (interactive)
+ (helm-other-buffer 'helm-source-stumpwm-commands
+ "*helm stumpwm commands*"))
+
+;;;###autoload
+(defun helm-minibuffer-history ()
+ "Preconfigured `helm' for `minibuffer-history'."
+ (interactive)
+ (cl-assert (minibuffer-window-active-p (selected-window)) nil
+ "Error: Attempt to use minibuffer history outside a minibuffer")
+ (let* ((enable-recursive-minibuffers t)
+ (query-replace-p (or (eq last-command 'query-replace)
+ (eq last-command 'query-replace-regexp)))
+ (elm (helm-comp-read "pattern: "
+ (cl-loop for i in
+ (symbol-value minibuffer-history-variable)
+ unless (string= "" i) collect i into history
+ finally return
+ (if (consp (car history))
+ (mapcar 'prin1-to-string history)
+ history))
+ :header-name
+ (lambda (name)
+ (format "%s (%s)" name minibuffer-history-variable))
+ :buffer "*helm minibuffer-history*"
+ :must-match helm-minibuffer-history-must-match
+ :multiline t
+ :keymap helm-minibuffer-history-map
+ :allow-nest t)))
+ ;; Fix issue #1667 with emacs-25+ `query-replace-from-to-separator'.
+ (when (and (boundp 'query-replace-from-to-separator) query-replace-p)
+ (let ((pos (string-match "\0" elm)))
+ (and pos
+ (add-text-properties
+ pos (1+ pos)
+ `(display ,query-replace-from-to-separator separator t)
+ elm))))
+ (delete-minibuffer-contents)
+ (insert elm)))
+
+;;;###autoload
+(defun helm-comint-input-ring ()
+ "Preconfigured `helm' that provide completion of `comint' history."
+ (interactive)
+ (when (derived-mode-p 'comint-mode)
+ (helm :sources 'helm-source-comint-input-ring
+ :input (buffer-substring-no-properties (comint-line-beginning-position)
+ (point-at-eol))
+ :buffer "*helm comint history*")))
+
+
+(provide 'helm-misc)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-misc.el ends here
--- /dev/null
+;;; helm-mode.el --- Enable helm completion everywhere. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'helm)
+(require 'helm-lib)
+(require 'helm-files)
+
+(defvar crm-separator)
+
+\f
+(defgroup helm-mode nil
+ "Enable helm completion."
+ :group 'helm)
+
+(defcustom helm-completing-read-handlers-alist
+ '((describe-function . helm-completing-read-symbols)
+ (describe-variable . helm-completing-read-symbols)
+ (describe-symbol . helm-completing-read-symbols)
+ (debug-on-entry . helm-completing-read-symbols)
+ (find-function . helm-completing-read-symbols)
+ (disassemble . helm-completing-read-symbols)
+ (trace-function . helm-completing-read-symbols)
+ (trace-function-foreground . helm-completing-read-symbols)
+ (trace-function-background . helm-completing-read-symbols)
+ (find-tag . helm-completing-read-default-find-tag)
+ (org-capture . helm-org-completing-read-tags)
+ (org-set-tags . helm-org-completing-read-tags)
+ (ffap-alternate-file . nil)
+ (tmm-menubar . nil)
+ (find-file . nil)
+ (find-file-at-point . helm-completing-read-sync-default-handler)
+ (ffap . helm-completing-read-sync-default-handler)
+ (execute-extended-command . nil)
+ (dired-do-rename . helm-read-file-name-handler-1)
+ (dired-do-copy . helm-read-file-name-handler-1)
+ (dired-do-symlink . helm-read-file-name-handler-1)
+ (dired-do-relsymlink . helm-read-file-name-handler-1)
+ (dired-do-hardlink . helm-read-file-name-handler-1)
+ (basic-save-buffer . helm-read-file-name-handler-1)
+ (write-file . helm-read-file-name-handler-1)
+ (write-region . helm-read-file-name-handler-1))
+ "Completing read functions for specific Emacs commands.
+
+By default `helm-mode' use `helm-completing-read-default-handler' to
+provide helm completion in each `completing-read' or `read-file-name'
+found, but other functions can be specified here for specific
+commands. This also allow disabling helm completion for some commands
+when needed.
+
+Each entry is a cons cell like (EMACS_COMMAND . COMPLETING-READ_HANDLER)
+where key and value are symbols.
+
+Each key is an Emacs command that use originaly `completing-read'.
+
+Each value maybe a helm function that takes same arguments as
+`completing-read' plus NAME and BUFFER, where NAME is the name of the new
+helm source and BUFFER the name of the buffer we will use, but it can
+be also a function not using helm, in this case the function should
+take same args as `completing-read' and not be prefixed by \"helm-\".
+
+`helm' will use the name of the command calling `completing-read' as
+NAME and BUFFER will be computed as well with NAME but prefixed with
+\"*helm-mode-\".
+
+This function prefix name must start by \"helm-\" when it uses helm,
+otherwise `helm' assumes the function is not a helm function and
+expects same args as `completing-read', this allow you to define a
+handler not using helm completion.
+
+Example:
+
+ (defun foo/test ()
+ (interactive)
+ (message \"%S\" (completing-read \"test: \" '(a b c d e))))
+
+ (defun helm-foo/test-completing-read-handler (prompt collection
+ predicate require-match
+ initial-input hist def
+ inherit-input-method
+ name buffer)
+ (helm-comp-read prompt collection :marked-candidates t
+ :name name
+ :buffer buffer))
+
+ (add-to-list 'helm-completing-read-handlers-alist
+ '(foo/test . helm-foo/test-completing-read-handler))
+
+
+We want here to make the regular `completing-read' in `foo/test'
+returns a list of candidate(s) instead of a single candidate.
+
+Note that this function will be reused for ALL the `completing-read'
+of this command, so it should handle all cases, e.g
+If first `completing-read' complete against symbols and
+second `completing-read' should handle only buffer,
+your specialized function should handle the both.
+
+If the value of an entry is nil completion will fall back to
+emacs vanilla behavior.
+Example:
+
+If you want to disable helm completion for `describe-function', use:
+
+ (describe-function . nil)
+
+Ido is also supported, you can use `ido-completing-read' and
+`ido-read-file-name' as value of an entry or just 'ido.
+Example:
+Enable ido completion for `find-file':
+
+ (find-file . ido)
+
+same as
+
+ (find-file . ido-read-file-name)
+
+Note that you don't need to enable `ido-mode' for this to work, see
+`helm-mode' documentation."
+ :group 'helm-mode
+ :type '(alist :key-type symbol :value-type symbol))
+
+(defcustom helm-comp-read-case-fold-search helm-case-fold-search
+ "Default Local setting of `helm-case-fold-search' for `helm-comp-read'.
+See `helm-case-fold-search' for more info."
+ :group 'helm-mode
+ :type 'symbol)
+
+(defcustom helm-mode-handle-completion-in-region t
+ "Whether to replace or not `completion-in-region-function'.
+This enable support for `completing-read-multiple' and `completion-at-point'
+when non--nil."
+ :group 'helm-mode
+ :type 'boolean)
+
+(defcustom helm-mode-reverse-history t
+ "Display history source after current source in `helm-mode' handled commands."
+ :group 'helm-mode
+ :type 'boolean)
+
+(defcustom helm-mode-no-completion-in-region-in-modes nil
+ "A list of modes that do not want helm for `completion-in-region'."
+ :group 'helm-mode
+ :type 'boolean)
+
+(defcustom helm-completion-in-region-fuzzy-match nil
+ "Whether `helm-completion-in-region' use fuzzy matching or not.
+Affect among others `completion-at-point', `completing-read-multiple'."
+ :group 'helm-mode
+ :type 'boolean)
+
+(defcustom helm-completion-in-region-default-sort-fn
+ 'helm-completion-in-region-sort-fn
+ "The default sort function to sort candidates in completion-in-region.
+
+When nil no sorting is done.
+The function is a `filtered-candidate-transformer' function which takes
+two args CANDIDATES and SOURCE.
+It will be used only when `helm-completion-in-region-fuzzy-match' is
+nil otherwise fuzzy use its own sort function."
+ :group 'helm-mode
+ :type 'function)
+
+(defcustom helm-mode-fuzzy-match nil
+ "Enable fuzzy matching in `helm-mode' globally.
+Note that this will slow down completion and modify sorting
+which is unwanted in many places.
+This affect only the functions with completing-read helmized by helm-mode.
+To fuzzy match `completion-at-point' and friends see
+`helm-completion-in-region-fuzzy-match'."
+ :group 'helm-mode
+ :type 'boolean)
+
+(defcustom helm-mode-minibuffer-setup-hook-black-list '(minibuffer-completion-help)
+ "Incompatible `minibuffer-setup-hook' functions go here.
+A list of symbols.
+Helm-mode is rejecting all lambda's, byte-code fns
+and all functions belonging in this list from `minibuffer-setup-hook'."
+ :group 'helm-mode
+ :type '(repeat (choice symbol)))
+
+(defcustom helm-completing-read-dynamic-complete nil
+ "Use dynamic completion in `completing-read' when non-nil.
+
+The default is to not use this because it is most of the time unneeded
+in `completing-read' and thus it is much more slower.
+If you feel one emacs function need this you have better time to tell
+`helm-mode' to use a dynamic completion for this function only by using
+`helm-completing-read-handlers-alist' with an entry like this:
+
+ (my-function . helm-completing-read-sync-default-handler)
+
+So you should not change the default setting of this variable unless you
+know what you are doing."
+ :group 'helm-mode
+ :type 'boolean)
+
+\f
+(defvar helm-comp-read-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map helm-map)
+ (define-key map (kbd "<C-return>") 'helm-cr-empty-string)
+ (define-key map (kbd "M-RET") 'helm-cr-empty-string)
+ map)
+ "Keymap for `helm-comp-read'.")
+\f
+;;; helm-comp-read
+;;
+;;
+(defun helm-cr-empty-string ()
+ "Return empty string."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action
+ (lambda (_candidate)
+ (identity "")))))
+(put 'helm-cr-empty-string 'helm-only t)
+
+(defun helm-mode--keyboard-quit ()
+ ;; Use this instead of `keyboard-quit'
+ ;; to avoid deactivating mark in current-buffer.
+ (let ((debug-on-quit nil))
+ (signal 'quit nil)))
+
+(cl-defun helm-comp-read-get-candidates (collection &optional
+ test sort-fn alistp
+ (input helm-pattern))
+ "Convert COLLECTION to list removing elements that don't match TEST.
+See `helm-comp-read' about supported COLLECTION arguments.
+
+SORT-FN is a predicate to sort COLLECTION.
+
+ALISTP when non--nil will not use `all-completions' to collect
+candidates because it doesn't handle alists correctly for helm.
+i.e In `all-completions' the car of each pair is used as value.
+In helm we want to use the cdr instead like \(display . real\),
+so we return the alist as it is with no transformation by
+`all-completions'.
+
+e.g
+
+\(setq A '((a . 1) (b . 2) (c . 3)))
+==>((a . 1) (b . 2) (c . 3))
+\(helm-comp-read \"test: \" A :alistp nil
+ :exec-when-only-one t
+ :initial-input \"a\")
+==>\"a\" Which is not what we expect.
+
+\(helm-comp-read \"test: \" A :alistp t
+ :exec-when-only-one t
+ :initial-input \"1\")
+==>\"1\"
+
+See docstring of `all-completions' for more info.
+
+INPUT is the string you want to complete against, defaulting to
+`helm-pattern' which is the value of what you enter in minibuffer.
+Note that when using a function as COLLECTION this value will be
+available with the input argument of the function only when using a
+sync source from `helm-comp-read', i.e not using
+`:candidates-in-buffer', otherwise the function is called only once
+with an empty string as value for `helm-pattern' because
+`helm-pattern' is not yet computed, which is what we want otherwise
+data would not be fully collected at init time.
+
+If COLLECTION is an `obarray', a TEST should be needed. See `obarray'."
+ ;; Ensure COLLECTION is computed from `helm-current-buffer'
+ ;; because some functions used as COLLECTION work
+ ;; only in the context of current-buffer (Issue #1030) .
+ (with-helm-current-buffer
+ (let ((cands
+ (cond ((vectorp collection)
+ (all-completions input collection test))
+ ((and (symbolp collection) (boundp collection)
+ ;; Issue #324 history is let-bounded and given
+ ;; quoted as hist argument of completing-read.
+ ;; See example in `rcirc-browse-url'.
+ (symbolp (symbol-value collection)))
+ nil)
+ ;; When collection is a symbol, most of the time
+ ;; it should be a symbol used as a minibuffer-history.
+ ;; The value of this symbol in this case return a list
+ ;; of string which maybe are converted later as symbol
+ ;; in special cases.
+ ;; we treat here commandp as a special case as it return t
+ ;; also with a string unless its last arg is provided.
+ ;; Also, the history collections generally collect their
+ ;; elements as string, so intern them to call predicate.
+ ((and (symbolp collection) (boundp collection) test)
+ (let ((predicate (lambda (elm)
+ (condition-case _err
+ (if (eq test 'commandp)
+ (funcall test (intern elm))
+ (funcall test elm))
+ (wrong-type-argument
+ (funcall test (intern elm)))))))
+ (all-completions input (symbol-value collection) predicate)))
+ ((and (symbolp collection) (boundp collection))
+ (all-completions input (symbol-value collection)))
+ ;; Normally file completion should not be handled here,
+ ;; but special cases like `find-file-at-point' do it.
+ ;; Handle here specially such cases.
+ ((and (functionp collection) (not (string= input ""))
+ minibuffer-completing-file-name)
+ (cl-loop for f in (funcall collection input test t)
+ unless (member f '("./" "../"))
+ if (string-match helm--url-regexp input)
+ collect f
+ else
+ collect (concat (file-name-as-directory
+ (helm-basedir input))
+ f)))
+ ((functionp collection)
+ (funcall collection input test t))
+ ((and alistp (null test)) collection)
+ ;; Next test ensure circular objects are removed
+ ;; with `all-completions' (Issue #1530).
+ (t (all-completions input collection test)))))
+ (if sort-fn (sort cands sort-fn) cands))))
+
+(defun helm-cr--pattern-in-candidates-p (candidates)
+ (or (assoc helm-pattern candidates)
+ (assq (intern helm-pattern) candidates)
+ (member helm-pattern candidates)
+ (member (downcase helm-pattern) candidates)
+ (member (upcase helm-pattern) candidates)))
+
+(defun helm-cr-default-transformer (candidates source)
+ "Default filter candidate function for `helm-comp-read'."
+ (let ((must-match (helm-attr 'must-match source))
+ unknown-pattern)
+ (unless (or (eq must-match t)
+ (string= helm-pattern "")
+ (helm-cr--pattern-in-candidates-p candidates))
+ (setq candidates (append (list
+ ;; Unquote helm-pattern
+ ;; when it is added
+ ;; as candidate: Why? #2015
+ ;; (replace-regexp-in-string
+ ;; "\\s\\" "" helm-pattern)
+ helm-pattern)
+ candidates))
+ ;; Notify pattern have been added to candidates.
+ (setq unknown-pattern t))
+ (cl-loop for c in candidates
+ for cand = (if (stringp c)
+ (replace-regexp-in-string "\\s\\" "" c)
+ c)
+ for pat = (replace-regexp-in-string "\\s\\" "" helm-pattern)
+ if (and (or (equal c pat) (equal c helm-pattern))
+ unknown-pattern)
+ collect
+ (cons (concat (propertize
+ " " 'display
+ (propertize "[?]" 'face 'helm-ff-prefix))
+ c)
+ c)
+ into lst
+ else collect (if (and (stringp cand)
+ (string-match "\n" cand))
+ (cons (replace-regexp-in-string "\n" "->" c) c)
+ c)
+ into lst
+ finally return (helm-fast-remove-dups lst :test 'equal))))
+
+(defun helm-comp-read--move-to-first-real-candidate ()
+ (helm-aif (helm-get-selection nil 'withprop)
+ (when (string= (get-text-property 0 'display it) "[?]")
+ (helm-next-line))))
+
+(defun helm-cr-default (default cands)
+ (delq nil
+ (cond ((and (stringp default) (not (string= default "")))
+ (cons default (delete default cands)))
+ ((consp default)
+ (append (cl-loop for d in default
+ ;; Don't convert
+ ;; nil to "nil" (i.e the string)
+ ;; it will be delq'ed on top.
+ collect (if (null d) d (helm-stringify d)))
+ cands))
+ (t cands))))
+
+;;;###autoload
+(cl-defun helm-comp-read (prompt collection
+ &key
+ test
+ initial-input
+ default
+ preselect
+ (buffer "*Helm Completions*")
+ must-match
+ fuzzy
+ reverse-history
+ (requires-pattern 0)
+ history
+ input-history
+ (case-fold helm-comp-read-case-fold-search)
+ (del-input t)
+ (persistent-action nil)
+ (persistent-help "DoNothing")
+ (mode-line helm-comp-read-mode-line)
+ help-message
+ (keymap helm-comp-read-map)
+ (name "Helm Completions")
+ header-name
+ candidates-in-buffer
+ match-part
+ exec-when-only-one
+ quit-when-no-cand
+ (volatile t)
+ sort
+ fc-transformer
+ hist-fc-transformer
+ marked-candidates
+ nomark
+ (alistp t)
+ (candidate-number-limit helm-candidate-number-limit)
+ multiline
+ allow-nest)
+ "Read a string in the minibuffer, with helm completion.
+
+It is helm `completing-read' equivalent.
+
+- PROMPT is the prompt name to use.
+
+- COLLECTION can be a list, vector, obarray or hash-table.
+ It can be also a function that receives three arguments:
+ the values string, predicate and t. See `all-completions' for more details.
+
+Keys description:
+
+- TEST: A predicate called with one arg i.e candidate.
+
+- INITIAL-INPUT: Same as input arg in `helm'.
+
+- PRESELECT: See preselect arg of `helm'.
+
+- DEFAULT: This option is used only for compatibility with regular
+ Emacs `completing-read' (Same as DEFAULT arg of `completing-read').
+
+- BUFFER: Name of helm-buffer.
+
+- MUST-MATCH: Candidate selected must be one of COLLECTION.
+
+- FUZZY: Enable fuzzy matching.
+
+- REVERSE-HISTORY: When non--nil display history source after current
+ source completion.
+
+- REQUIRES-PATTERN: Same as helm attribute, default is 0.
+
+- HISTORY: A list containing specific history, default is nil.
+ When it is non--nil, all elements of HISTORY are displayed in
+ a special source before COLLECTION.
+
+- INPUT-HISTORY: A symbol. the minibuffer input history will be
+ stored there, if nil or not provided, `minibuffer-history'
+ will be used instead.
+
+- CASE-FOLD: Same as `helm-case-fold-search'.
+
+- DEL-INPUT: Boolean, when non--nil (default) remove the partial
+ minibuffer input from HISTORY is present.
+
+- PERSISTENT-ACTION: A function called with one arg i.e candidate.
+
+- PERSISTENT-HELP: A string to document PERSISTENT-ACTION.
+
+- MODE-LINE: A string or list to display in mode line.
+ Default is `helm-comp-read-mode-line'.
+
+- KEYMAP: A keymap to use in this `helm-comp-read'.
+ (the keymap will be shared with history source)
+
+- NAME: The name related to this local source.
+
+- HEADER-NAME: A function to alter NAME, see `helm'.
+
+- EXEC-WHEN-ONLY-ONE: Bound `helm-execute-action-at-once-if-one'
+ to non--nil. (possibles values are t or nil).
+
+- VOLATILE: Use volatile attribute.
+
+- SORT: A predicate to give to `sort' e.g `string-lessp'
+ Use this only on small data as it is ineficient.
+ If you want to sort faster add a sort function to
+ FC-TRANSFORMER.
+ Note that FUZZY when enabled is already providing a sort function.
+
+- FC-TRANSFORMER: A `filtered-candidate-transformer' function
+ or a list of functions.
+
+- HIST-FC-TRANSFORMER: A `filtered-candidate-transformer'
+ function for the history source.
+
+- MARKED-CANDIDATES: If non--nil return candidate or marked candidates as a list.
+
+- NOMARK: When non--nil don't allow marking candidates.
+
+- ALISTP: \(default is non--nil\) See `helm-comp-read-get-candidates'.
+
+- CANDIDATES-IN-BUFFER: when non--nil use a source build with
+ `helm-source-in-buffer' which is much faster.
+ Argument VOLATILE have no effect when CANDIDATES-IN-BUFFER is non--nil.
+
+- MATCH-PART: Allow matching only one part of candidate.
+ See match-part documentation in `helm-source'.
+
+- ALLOW-NEST: Allow nesting this `helm-comp-read' in a helm session.
+ See `helm'.
+
+- MULTILINE: See multiline in `helm-source'.
+
+Any prefix args passed during `helm-comp-read' invocation will be recorded
+in `helm-current-prefix-arg', otherwise if prefix args were given before
+`helm-comp-read' invocation, the value of `current-prefix-arg' will be used.
+That's mean you can pass prefix args before or after calling a command
+that use `helm-comp-read' See `helm-M-x' for example."
+
+ (when (get-buffer helm-action-buffer)
+ (kill-buffer helm-action-buffer))
+ (let ((action-fn `(("Sole action (Identity)"
+ . (lambda (candidate)
+ (if ,marked-candidates
+ (helm-marked-candidates)
+ (identity candidate)))))))
+ ;; Assume completion have been already required,
+ ;; so always use 'confirm.
+ (when (eq must-match 'confirm-after-completion)
+ (setq must-match 'confirm))
+ (let* ((minibuffer-completion-confirm must-match)
+ (must-match-map (when must-match
+ (let ((map (make-sparse-keymap)))
+ (define-key map (kbd "RET")
+ 'helm-confirm-and-exit-minibuffer)
+ map)))
+ (loc-map (if must-match-map
+ (make-composed-keymap
+ must-match-map (or keymap helm-map))
+ (or keymap helm-map)))
+ (minibuffer-completion-predicate test)
+ (minibuffer-completion-table collection)
+ (helm-read-file-name-mode-line-string
+ (replace-regexp-in-string "helm-maybe-exit-minibuffer"
+ "helm-confirm-and-exit-minibuffer"
+ helm-read-file-name-mode-line-string))
+ (get-candidates
+ (lambda ()
+ (let ((cands (helm-comp-read-get-candidates
+ collection test sort alistp
+ ;; This should not be needed as
+ ;; `helm-pattern' is not yet computed when
+ ;; calling this from :init when
+ ;; candidates-in-buffer is in use.
+ (if candidates-in-buffer "" helm-pattern))))
+ (helm-cr-default default cands))))
+ (history-get-candidates
+ (lambda ()
+ (let ((cands (helm-comp-read-get-candidates
+ history test nil alistp)))
+ (when cands
+ (delete "" (helm-cr-default default cands))))))
+ (src-hist (helm-build-sync-source (format "%s History" name)
+ :candidates history-get-candidates
+ :fuzzy-match fuzzy
+ :multiline multiline
+ :match-part match-part
+ :filtered-candidate-transformer
+ (append '((lambda (candidates sources)
+ (cl-loop for i in candidates
+ ;; Input is added to history in completing-read's
+ ;; and may be regexp-quoted, so unquote it
+ ;; but check if cand is a string (it may be at this stage
+ ;; a symbol or nil) Issue #1553.
+ when (stringp i)
+ collect (replace-regexp-in-string "\\s\\" "" i))))
+ (and hist-fc-transformer (helm-mklist hist-fc-transformer)))
+ :persistent-action persistent-action
+ :persistent-help persistent-help
+ :keymap loc-map
+ :mode-line mode-line
+ :help-message help-message
+ :action action-fn))
+ (src (helm-build-sync-source name
+ :candidates get-candidates
+ :match-part match-part
+ :multiline multiline
+ :header-name header-name
+ :filtered-candidate-transformer
+ (append (helm-mklist fc-transformer)
+ '(helm-cr-default-transformer))
+ :requires-pattern requires-pattern
+ :persistent-action persistent-action
+ :persistent-help persistent-help
+ :fuzzy-match fuzzy
+ :keymap loc-map
+ :mode-line mode-line
+ :help-message help-message
+ :action action-fn
+ :volatile volatile))
+ (src-1 (helm-build-in-buffer-source name
+ :data get-candidates
+ :match-part match-part
+ :multiline multiline
+ :header-name header-name
+ :filtered-candidate-transformer
+ (append (helm-mklist fc-transformer)
+ '(helm-cr-default-transformer))
+ :requires-pattern requires-pattern
+ :persistent-action persistent-action
+ :fuzzy-match fuzzy
+ :keymap loc-map
+ :persistent-help persistent-help
+ :mode-line mode-line
+ :help-message help-message
+ :action action-fn))
+ (src-list (list src-hist
+ (cons (cons 'must-match must-match)
+ (if candidates-in-buffer
+ src-1 src))))
+ (helm-execute-action-at-once-if-one exec-when-only-one)
+ (helm-quit-if-no-candidate quit-when-no-cand)
+ result)
+ (when nomark
+ (setq src-list (cl-loop for src in src-list
+ collect (cons '(nomark) src))))
+ (when reverse-history (setq src-list (nreverse src-list)))
+ (add-hook 'helm-after-update-hook 'helm-comp-read--move-to-first-real-candidate)
+ (unwind-protect
+ (setq result (helm
+ :sources src-list
+ :input initial-input
+ :default default
+ :preselect preselect
+ :prompt prompt
+ :resume 'noresume
+ :keymap loc-map ;; Needed with empty collection.
+ :allow-nest allow-nest
+ :candidate-number-limit candidate-number-limit
+ :case-fold-search case-fold
+ :history (and (symbolp input-history) input-history)
+ :buffer buffer))
+ (remove-hook 'helm-after-update-hook 'helm-comp-read--move-to-first-real-candidate))
+ ;; Avoid adding an incomplete input to history.
+ (when (and result history del-input)
+ (cond ((and (symbolp history) ; History is a symbol.
+ (not (symbolp (symbol-value history)))) ; Fix Issue #324.
+ ;; Be sure history is not a symbol with a nil value.
+ (helm-aif (symbol-value history) (setcar it result)))
+ ((consp history) ; A list with a non--nil value.
+ (setcar history result))
+ (t ; Possibly a symbol with a nil value.
+ (set history (list result)))))
+ (or result (helm-mode--keyboard-quit)))))
+
+\f
+;; Generic completing-read
+;;
+;; Support also function as collection.
+;; e.g M-x man is supported.
+;; Support hash-table and vectors as collection.
+;; NOTE:
+;; Some crap emacs functions may not be supported
+;; like ffap-alternate-file (bad use of completing-read)
+;; and maybe others.
+;; Provide a mode `helm-mode' which turn on
+;; helm in all `completing-read' and `read-file-name' in Emacs.
+;;
+(defvar helm-completion-mode-string " Helm")
+
+(defvar helm-completion-mode-quit-message
+ "Helm completion disabled")
+
+(defvar helm-completion-mode-start-message
+ "Helm completion enabled")
+
+;;; Specialized handlers
+;;
+;;
+(defun helm-completing-read-symbols
+ (prompt _collection test _require-match init
+ hist default _inherit-input-method name buffer)
+ "Specialized function for fast symbols completion in `helm-mode'."
+ (require 'helm-elisp)
+ (or
+ (helm
+ :sources (helm-build-in-buffer-source name
+ :init (lambda ()
+ (helm-apropos-init (lambda (x)
+ (and (funcall test x)
+ (not (keywordp x))))
+ (or (car-safe default) default)))
+ :filtered-candidate-transformer 'helm-apropos-default-sort-fn
+ :help-message #'helm-comp-read-help-message
+ :fuzzy-match helm-mode-fuzzy-match
+ :persistent-action
+ (lambda (candidate)
+ (helm-lisp-completion-persistent-action
+ candidate name))
+ :persistent-help (helm-lisp-completion-persistent-help))
+ :prompt prompt
+ :buffer buffer
+ :input init
+ :history hist
+ :resume 'noresume
+ :default (or default ""))
+ (helm-mode--keyboard-quit)))
+
+
+;;; Generic completing read
+;;
+;;
+(defun helm-completing-read-default-1
+ (prompt collection test require-match
+ init hist default _inherit-input-method
+ name buffer &optional cands-in-buffer exec-when-only-one)
+ "Call `helm-comp-read' with same args as `completing-read'.
+Extra optional arg CANDS-IN-BUFFER mean use `candidates-in-buffer'
+method which is faster.
+It should be used when candidate list don't need to rebuild dynamically."
+ (let ((history (or (car-safe hist) hist))
+ (initial-input (helm-aif (pcase init
+ ((pred (stringp)) init)
+ ;; INIT is a cons cell.
+ (`(,l . ,_ll) l))
+ (if minibuffer-completing-file-name it
+ (regexp-quote it)))))
+ (helm-comp-read
+ prompt collection
+ :test test
+ :history history
+ :reverse-history helm-mode-reverse-history
+ :input-history history
+ :must-match require-match
+ :alistp nil
+ :help-message #'helm-comp-read-help-message
+ :name name
+ :requires-pattern (if (and (stringp default)
+ (string= default "")
+ (or (eq require-match 'confirm)
+ (eq require-match
+ 'confirm-after-completion)))
+ 1 0)
+ :candidates-in-buffer cands-in-buffer
+ :exec-when-only-one exec-when-only-one
+ :fuzzy helm-mode-fuzzy-match
+ :buffer buffer
+ ;; If DEF is not provided, fallback to empty string
+ ;; to avoid `thing-at-point' to be appended on top of list
+ :default (or default "")
+ ;; Fail with special characters (e.g in gnus "nnimap+gmail:")
+ ;; if regexp-quote is not used.
+ ;; when init is added to history, it will be unquoted by
+ ;; helm-comp-read.
+ :initial-input initial-input)))
+
+(defun helm-completing-read-default-find-tag
+ (prompt collection test require-match
+ init hist default inherit-input-method
+ name buffer)
+ "Specialized `helm-mode' handler for `find-tag'."
+ ;; Some commands like find-tag may use `read-file-name' from inside
+ ;; the calculation of collection. in this case it clash with
+ ;; candidates-in-buffer that reuse precedent data (files) which is wrong.
+ ;; So (re)calculate collection outside of main helm-session.
+ (let* ((cands (helm-comp-read-get-candidates
+ collection test nil nil)))
+ (helm-completing-read-default-1 prompt cands test require-match
+ init hist default inherit-input-method
+ name buffer t)))
+
+(defun helm-completing-read-sync-default-handler
+ (prompt collection test require-match
+ init hist default inherit-input-method
+ name buffer)
+ "`helm-mode' handler using sync source as backend."
+ (helm-completing-read-default-1 prompt collection test require-match
+ init hist default inherit-input-method
+ name buffer))
+
+(defun helm-completing-read-default-handler
+ (prompt collection test require-match
+ init hist default inherit-input-method
+ name buffer)
+ "Default `helm-mode' handler for all `completing-read'."
+ (helm-completing-read-default-1 prompt collection test require-match
+ init hist default inherit-input-method
+ name buffer
+ (null helm-completing-read-dynamic-complete)))
+
+(defun helm--generic-read-buffer (prompt &optional default require-match predicate)
+ "The `read-buffer-function' for `helm-mode'.
+Affects `switch-to-buffer' and related."
+ (let ((collection (helm-buffer-list)))
+ (helm--completing-read-default
+ prompt collection predicate require-match nil nil default)))
+
+(cl-defun helm--completing-read-default
+ (prompt collection &optional
+ predicate require-match
+ initial-input hist def
+ inherit-input-method)
+ "An helm replacement of `completing-read'.
+This function should be used only as a `completing-read-function'.
+
+Don't use it directly, use instead `helm-comp-read' in your programs.
+
+See documentation of `completing-read' and `all-completions' for details."
+ (let* ((current-command (or (helm-this-command) this-command))
+ (str-command (helm-symbol-name current-command))
+ (buf-name (format "*helm-mode-%s*" str-command))
+ (entry (assq current-command
+ helm-completing-read-handlers-alist))
+ (def-com (cdr-safe entry))
+ (str-defcom (and def-com (helm-symbol-name def-com)))
+ (def-args (list prompt collection predicate require-match
+ initial-input hist def inherit-input-method))
+ ;; Append the two extra args needed to set the buffer and source name
+ ;; in helm specialized functions.
+ (any-args (append def-args (list str-command buf-name)))
+ helm-completion-mode-start-message ; Be quiet
+ helm-completion-mode-quit-message
+ ;; Be sure this pesty *completion* buffer doesn't popup.
+ ;; Note: `minibuffer-with-setup-hook' may setup a lambda
+ ;; calling `minibuffer-completion-help' or other minibuffer
+ ;; functions we DONT WANT here, in these cases removing the hook
+ ;; (a symbol) have no effect. Issue #448.
+ ;; Because `minibuffer-completion-table' and
+ ;; `minibuffer-completion-predicate' are not bound
+ ;; anymore here, these functions should have no effect now,
+ ;; except in some rare cases like in `woman-file-name',
+ ;; so remove all incompatible functions
+ ;; from `minibuffer-setup-hook' (Issue #1205, #1240).
+ ;; otherwise helm have not the time to close its initial session.
+ (minibuffer-setup-hook
+ (cl-loop for h in minibuffer-setup-hook
+ unless (or (consp h) ; a lambda.
+ (byte-code-function-p h)
+ (memq h helm-mode-minibuffer-setup-hook-black-list))
+ collect h))
+ ;; Disable hack that could be used before `completing-read'.
+ ;; i.e (push ?\t unread-command-events).
+ unread-command-events
+ (default-handler
+ ;; Typically when COLLECTION is a function, we can assume
+ ;; the intention is completing dynamically according to
+ ;; input; If one want to use in-buffer handler for specific
+ ;; usage with a function as collection he can specify it in
+ ;; helm-completing-read-handlers-alist.
+ (if (functionp collection)
+ #'helm-completing-read-sync-default-handler
+ #'helm-completing-read-default-handler)))
+ (when (eq def-com 'ido) (setq def-com 'ido-completing-read))
+ (unless (or (not entry) def-com)
+ ;; An entry in *read-handlers-alist exists but have
+ ;; a nil value, so we exit from here, disable `helm-mode'
+ ;; and run the command again with it original behavior.
+ ;; `helm-mode' will be restored on exit.
+ (cl-return-from helm--completing-read-default
+ (unwind-protect
+ (progn
+ (helm-mode -1)
+ (apply completing-read-function def-args))
+ (helm-mode 1))))
+ ;; If we use now `completing-read' we MUST turn off `helm-mode'
+ ;; to avoid infinite recursion and CRASH. It will be reenabled on exit.
+ (when (or (eq def-com 'completing-read)
+ ;; All specialized functions are prefixed by "helm"
+ (and (stringp str-defcom)
+ (not (string-match "^helm" str-defcom))))
+ (helm-mode -1))
+ (unwind-protect
+ (cond (;; An helm specialized function exists, run it.
+ (and def-com helm-mode)
+ (apply def-com any-args))
+ (;; Try to handle `ido-completing-read' everywhere.
+ (and def-com (eq def-com 'ido-completing-read))
+ (setcar (memq collection def-args)
+ (all-completions "" collection predicate))
+ (apply def-com def-args))
+ (;; User set explicitely `completing-read' or something similar
+ ;; in *read-handlers-alist, use this with exactly the same
+ ;; args as in `completing-read'.
+ ;; If we are here `helm-mode' is now disabled.
+ def-com
+ (apply def-com def-args))
+ (;; Use by default a in-buffer handler unless
+ ;; COLLECTION is a function.
+ t
+ (funcall default-handler
+ prompt collection predicate require-match
+ initial-input hist def inherit-input-method
+ str-command buf-name)))
+ (helm-mode 1)
+ ;; When exiting minibuffer, `this-command' is set to
+ ;; `helm-exit-minibuffer', which is unwanted when starting
+ ;; on another `completing-read', so restore `this-command' to
+ ;; initial value when exiting.
+ (setq this-command current-command))))
+\f
+;;; Generic read-file-name
+;;
+;;
+;;;###autoload
+(cl-defun helm-read-file-name
+ (prompt
+ &key
+ (name "Read File Name")
+ (initial-input default-directory)
+ (buffer "*Helm file completions*")
+ test
+ (case-fold helm-file-name-case-fold-search)
+ preselect
+ history
+ must-match
+ (fuzzy t)
+ default
+ marked-candidates
+ (candidate-number-limit helm-ff-candidate-number-limit)
+ nomark
+ (alistp t)
+ (persistent-action-if 'helm-find-files-persistent-action-if)
+ (persistent-help "Hit1 Expand Candidate, Hit2 or (C-u) Find file")
+ (mode-line helm-read-file-name-mode-line-string))
+ "Read a file name with helm completion.
+It is helm `read-file-name' emulation.
+
+Argument PROMPT is the default prompt to use.
+
+Keys description:
+
+- NAME: Source name, default to \"Read File Name\".
+
+- INITIAL-INPUT: Where to start read file name, default to `default-directory'.
+
+- BUFFER: `helm-buffer' name default to \"*Helm Completions*\".
+
+- TEST: A predicate called with one arg 'candidate'.
+
+- CASE-FOLD: Same as `helm-case-fold-search'.
+
+- PRESELECT: helm preselection.
+
+- HISTORY: Display HISTORY in a special source.
+
+- MUST-MATCH: Can be 'confirm, nil, or t.
+
+- FUZZY: Enable fuzzy matching when non-nil (Enabled by default).
+
+- MARKED-CANDIDATES: When non--nil return a list of marked candidates.
+
+- NOMARK: When non--nil don't allow marking candidates.
+
+- ALISTP: Don't use `all-completions' in history (take effect only on history).
+
+- PERSISTENT-ACTION-IF: a persistent if action function.
+
+- PERSISTENT-HELP: persistent help message.
+
+- MODE-LINE: A mode line message, default is `helm-read-file-name-mode-line-string'."
+ (require 'tramp)
+ (when (get-buffer helm-action-buffer)
+ (kill-buffer helm-action-buffer))
+ ;; Assume completion have been already required,
+ ;; so always use 'confirm.
+ (when (eq must-match 'confirm-after-completion)
+ (setq must-match 'confirm))
+ (mapc (lambda (hook)
+ (add-hook 'helm-after-update-hook hook))
+ '(helm-ff-move-to-first-real-candidate
+ helm-ff-update-when-only-one-matched
+ helm-ff-auto-expand-to-home-or-root))
+ (let* ((action-fn `(("Sole action (Identity)"
+ . (lambda (candidate)
+ (if ,marked-candidates
+ (helm-marked-candidates :with-wildcard t)
+ (identity candidate))))))
+ ;; Be sure we don't erase the underlying minibuffer if some.
+ (helm-ff-auto-update-initial-value
+ (and helm-ff-auto-update-initial-value
+ (not (minibuffer-window-active-p (minibuffer-window)))))
+ helm-follow-mode-persistent
+ (helm-ff-fuzzy-matching
+ (and fuzzy
+ (not (memq helm-mm-matching-method '(multi1 multi3p)))))
+ (hist (and history (helm-comp-read-get-candidates
+ history nil nil alistp)))
+ (minibuffer-completion-confirm must-match)
+ (must-match-map (when must-match
+ (let ((map (make-sparse-keymap)))
+ (define-key map (kbd "RET")
+ (let ((fn (lookup-key helm-read-file-map (kbd "RET"))))
+ (if (eq fn 'helm-ff-RET)
+ #'helm-ff-RET-must-match
+ #'helm-confirm-and-exit-minibuffer)))
+ map)))
+ (cmap (if must-match-map
+ (make-composed-keymap
+ must-match-map helm-read-file-map)
+ helm-read-file-map))
+ (minibuffer-completion-predicate test)
+ (minibuffer-completing-file-name t)
+ (helm--completing-file-name t)
+ (helm-read-file-name-mode-line-string
+ (replace-regexp-in-string "helm-maybe-exit-minibuffer"
+ "helm-confirm-and-exit-minibuffer"
+ helm-read-file-name-mode-line-string))
+ (src-list
+ (list
+ ;; History source.
+ (helm-build-sync-source (format "%s History" name)
+ :header-name (lambda (name)
+ (concat name (substitute-command-keys
+ helm-find-files-doc-header)))
+ :mode-line mode-line
+ :candidates hist
+ :nohighlight t
+ :fuzzy-match fuzzy
+ :persistent-action-if persistent-action-if
+ :persistent-help persistent-help
+ :keymap cmap
+ :nomark nomark
+ :action action-fn)
+ ;; Other source.
+ (helm-build-sync-source name
+ :header-name (lambda (name)
+ (concat name (substitute-command-keys
+ helm-find-files-doc-header)))
+ :init (lambda ()
+ (setq helm-ff-auto-update-flag
+ helm-ff-auto-update-initial-value)
+ (setq helm-ff--auto-update-state
+ helm-ff-auto-update-flag))
+ :mode-line mode-line
+ :help-message 'helm-read-file-name-help-message
+ :nohighlight t
+ :candidates
+ (lambda ()
+ (append (and (not (file-exists-p helm-pattern))
+ (not (helm-ff--invalid-tramp-name-p helm-pattern))
+ (list helm-pattern))
+ (if test
+ (cl-loop with hn = (helm-ff--tramp-hostnames)
+ for i in (helm-find-files-get-candidates
+ must-match)
+ when (or (member i hn) ; A tramp host
+ (funcall test i)) ; Test ok
+ collect i)
+ (helm-find-files-get-candidates must-match))))
+ :filtered-candidate-transformer 'helm-ff-sort-candidates
+ :filter-one-by-one 'helm-ff-filter-candidate-one-by-one
+ :persistent-action-if persistent-action-if
+ :persistent-help persistent-help
+ :volatile t
+ :keymap cmap
+ :cleanup 'helm-find-files-cleanup
+ :nomark nomark
+ :action action-fn)))
+ ;; Helm result.
+ (result (helm
+ :sources (if helm-mode-reverse-history
+ (reverse src-list) src-list)
+ :input (expand-file-name initial-input)
+ :prompt prompt
+ :candidate-number-limit candidate-number-limit
+ :resume 'noresume
+ :case-fold-search case-fold
+ :default default
+ :buffer buffer
+ :full-frame nil
+ :preselect preselect)))
+ (or
+ (cond ((and result (stringp result)
+ (string= result "") ""))
+ ((and result
+ (stringp result)
+ (file-equal-p result initial-input)
+ default)
+ (if (listp default) (car default) default))
+ ((and result (listp result))
+ (mapcar #'expand-file-name result))
+ ((and result (file-directory-p result))
+ (file-name-as-directory (expand-file-name result)))
+ (result (expand-file-name result)))
+ (helm-mode--keyboard-quit))))
+
+(defun helm-mode--default-filename (fname dir initial)
+ (unless dir (setq dir default-directory))
+ (unless (file-name-absolute-p dir)
+ (setq dir (expand-file-name dir)))
+ (unless (or fname (consp fname))
+ (setq fname (expand-file-name
+ (or initial buffer-file-name dir)
+ dir)))
+ (if (and fname (consp fname))
+ (setq fname (cl-loop for f in fname
+ collect (expand-file-name f dir)))
+ (if (file-name-absolute-p fname)
+ fname (expand-file-name fname dir))))
+
+(cl-defun helm--generic-read-file-name
+ (prompt &optional dir default-filename mustmatch initial predicate)
+ "Generic helm replacement of `read-file-name'.
+Don't use it directly, use instead `helm-read-file-name' in your programs."
+ (let* ((init (or initial dir default-directory))
+ (current-command (or (helm-this-command) this-command))
+ (str-command (helm-symbol-name current-command))
+ (helm--file-completion-sources
+ (cons str-command
+ (remove str-command helm--file-completion-sources)))
+ (buf-name (format "*helm-mode-%s*" str-command))
+ (entry (assq current-command
+ helm-completing-read-handlers-alist))
+ (def-com (cdr-safe entry))
+ (str-defcom (and def-com (helm-symbol-name def-com)))
+ ;; Don't modify the original args list for emacs generic functions.
+ (def-args (list prompt dir default-filename mustmatch initial predicate))
+ ;; Append the two extra args needed to set the buffer and source name
+ ;; in helm specialized functions.
+ (any-args (append def-args (list str-command buf-name)))
+ (ido-state ido-mode)
+ helm-completion-mode-start-message ; Be quiet
+ helm-completion-mode-quit-message ; Same here
+ fname)
+ ;; Build `default-filename' with `dir'+`initial' when
+ ;; `default-filename' is not specified.
+ ;; See `read-file-name' docstring for more infos.
+ (setq default-filename (helm-mode--default-filename
+ default-filename dir initial))
+ ;; Some functions that normally call `completing-read' can switch
+ ;; brutally to `read-file-name' (e.g find-tag), in this case
+ ;; the helm specialized function will fail because it is build
+ ;; for `completing-read', so set it to 'incompatible to be sure
+ ;; we switch to `helm-read-file-name' and don't try to call it
+ ;; with wrong number of args.
+ (when (eq def-com 'ido)
+ (setq def-com 'ido-read-file-name) (ido-mode 1))
+ (when (and def-com (> (length (help-function-arglist def-com)) 8))
+ (setq def-com 'incompatible))
+ (unless (or (not entry) def-com)
+ (cl-return-from helm--generic-read-file-name
+ (unwind-protect
+ (progn
+ (helm-mode -1)
+ (apply read-file-name-function def-args))
+ (helm-mode 1))))
+ ;; If we use now `read-file-name' we MUST turn off `helm-mode'
+ ;; to avoid infinite recursion and CRASH. It will be reenabled on exit.
+ (when (or (eq def-com 'read-file-name)
+ (eq def-com 'ido-read-file-name)
+ (and (stringp str-defcom)
+ (not (string-match "^helm" str-defcom))))
+ (helm-mode -1))
+ (unwind-protect
+ (setq fname
+ (cond (;; A specialized function exists, run it
+ ;; with the two extra args specific to helm.
+ ;; Note that the helm handler should ensure
+ ;; :initial-input is not nil i.e. Use init
+ ;; which fallback to default-directory instead
+ ;; of INITIAL.
+ (and def-com helm-mode
+ (not (eq def-com 'ido-read-file-name))
+ (not (eq def-com 'incompatible)))
+ (apply def-com any-args))
+ (;; Def-com value is `ido-read-file-name'
+ ;; run it with default args.
+ (and def-com (eq def-com 'ido-read-file-name))
+ (ido-mode 1)
+ (apply def-com def-args))
+ (;; Def-com value is `read-file-name'
+ ;; run it with default args.
+ (eq def-com 'read-file-name)
+ (apply def-com def-args))
+ (t ; Fall back to classic `helm-read-file-name'.
+ (helm-read-file-name
+ prompt
+ :name str-command
+ :buffer buf-name
+ :default default-filename
+ ;; Helm handlers should always have a non nil INITIAL arg.
+ :initial-input (expand-file-name init dir)
+ :alistp nil
+ :must-match mustmatch
+ :test predicate))))
+ (helm-mode 1)
+ (ido-mode (if ido-state 1 -1))
+ ;; Same comment as in `helm--completing-read-default'.
+ (setq this-command current-command))
+ (if (and
+ ;; Using `read-directory-name'.
+ (eq predicate 'file-directory-p)
+ ;; `file-name-as-directory' return "./" when FNAME is
+ ;; empty string.
+ (not (string= fname "")))
+ (file-name-as-directory fname) fname)))
+
+;; Read file name handler with history (issue #1652)
+(defun helm-read-file-name-handler-1 (prompt dir default-filename
+ mustmatch initial predicate
+ name buffer)
+ "A `read-file-name' handler with history.
+Can be added to `helm-completing-read-handlers-alist' for functions
+that need a `read-file-name' function with directory history.
+The `helm-find-files' history `helm-ff-history' is used here."
+ (let ((helm-always-two-windows t)
+ (helm-split-window-default-side
+ (if (eq helm-split-window-default-side 'same)
+ 'below helm-split-window-default-side))
+ helm-split-window-inside-p
+ helm-reuse-last-window-split-state
+ ;; Helm handlers should always have a non nil INITIAL arg.
+ (init (or initial dir default-directory)))
+ (helm-read-file-name
+ prompt
+ :name name
+ :history helm-ff-history
+ :buffer buffer
+ :default default-filename
+ :initial-input (expand-file-name init dir)
+ :alistp nil
+ :must-match mustmatch
+ :test predicate)))
+
+\f
+;;; Completion in region
+;;
+(defun helm-mode--advice-lisp--local-variables (old--fn &rest args)
+ (ignore-errors
+ (apply old--fn args)))
+
+(defun helm-completion-in-region-sort-fn (candidates _source)
+ "Default sort function for completion-in-region."
+ (sort candidates 'helm-generic-sort-fn))
+
+(defun helm--completion-in-region (start end collection &optional predicate)
+ "Helm replacement of `completion--in-region'.
+Can be used as value for `completion-in-region-function'."
+ (cl-declare (special require-match prompt))
+ (if (memq major-mode helm-mode-no-completion-in-region-in-modes)
+ (funcall helm--old-completion-in-region-function
+ start end collection predicate)
+ (advice-add
+ 'lisp--local-variables
+ :around #'helm-mode--advice-lisp--local-variables)
+ (unwind-protect
+ (let* ((enable-recursive-minibuffers t)
+ (input (buffer-substring-no-properties start end))
+ (current-command (or (helm-this-command) this-command))
+ (crm (eq current-command 'crm-complete))
+ (str-command (helm-symbol-name current-command))
+ (buf-name (format "*helm-mode-%s*" str-command))
+ (require-match (or (and (boundp 'require-match) require-match)
+ minibuffer-completion-confirm
+ ;; If prompt have not been propagated here, that's
+ ;; probably mean we have no prompt and we are in
+ ;; completion-at-point or friend, so use a non--nil
+ ;; value for require-match.
+ (not (boundp 'prompt))))
+ ;; `completion-extra-properties' is let-bounded in `completion-at-point'.
+ ;; `afun' is a closure to call against each string in `data'.
+ ;; it provide the annotation info for each string.
+ ;; e.g "foo" => "foo <f>" where foo is a function.
+ ;; See Issue #407.
+ (afun (plist-get completion-extra-properties :annotation-function))
+ (metadata (completion-metadata
+ (buffer-substring-no-properties start (point))
+ collection predicate))
+ (data (completion-all-completions
+ (buffer-substring start end)
+ collection
+ predicate
+ (- (point) start)
+ metadata))
+ ;; `completion-all-completions' store the base-size in the last `cdr',
+ ;; so data looks like this: '(a b c d . 0) and (last data) == (d . 0).
+ (last-data (last data))
+ (base-size (helm-aif (cdr (last data))
+ (prog1 it
+ (setcdr last-data nil))
+ 0))
+ (init-space-suffix (unless (or helm-completion-in-region-fuzzy-match
+ (string-suffix-p " " input)
+ (string= input ""))
+ " "))
+ (file-comp-p (or (eq (completion-metadata-get metadata 'category) 'file)
+ (helm-mode--in-file-completion-p)
+ ;; Assume that when `afun' and `predicate' are null
+ ;; we are in filename completion.
+ (and (null afun) (null predicate))))
+ ;; Completion-at-point and friends have no prompt.
+ (result (if (stringp data)
+ data
+ (helm-comp-read
+ (or (and (boundp 'prompt) prompt) "Pattern: ")
+ (if file-comp-p
+ (cl-loop for f in data unless
+ (string-match "\\`\\.\\{1,2\\}/\\'" f)
+ collect f)
+ (if afun
+ (mapcar (lambda (s)
+ (let ((ann (funcall afun s)))
+ (if ann
+ (cons
+ (concat
+ s
+ (propertize
+ " " 'display
+ (propertize
+ ann
+ 'face 'completions-annotations)))
+ s)
+ s)))
+ data)
+ data))
+ :name str-command
+ :fuzzy helm-completion-in-region-fuzzy-match
+ :nomark (null crm)
+ :marked-candidates crm
+ :initial-input
+ (cond ((and file-comp-p
+ (not (string-match "/\\'" input)))
+ (concat (helm-basename input)
+ init-space-suffix))
+ ((string-match "/\\'" input) nil)
+ ((or (null require-match)
+ (stringp require-match))
+ input)
+ (t (concat input init-space-suffix)))
+ :buffer buf-name
+ :fc-transformer (append '(helm-cr-default-transformer)
+ (unless (or helm-completion-in-region-fuzzy-match
+ (null helm-completion-in-region-default-sort-fn))
+ (list helm-completion-in-region-default-sort-fn)))
+ :exec-when-only-one t
+ :quit-when-no-cand
+ (lambda ()
+ ;; Delay message to overwrite "Quit".
+ (run-with-timer
+ 0.01 nil
+ (lambda ()
+ (message "[No matches]")))
+ t) ; exit minibuffer immediately.
+ :must-match require-match))))
+ (cond ((stringp result)
+ (choose-completion-string
+ result (current-buffer)
+ (list (+ start base-size) end)
+ completion-list-insert-choice-function))
+ ((consp result) ; crm.
+ (let ((beg (+ start base-size))
+ (sep ","))
+ ;; Try to find a default separator.
+ (save-excursion
+ (goto-char beg)
+ (when (looking-back crm-separator (1- (point)))
+ (setq sep (match-string 0))))
+ (funcall completion-list-insert-choice-function
+ beg end (mapconcat 'identity result sep))))
+ (t nil)))
+ (advice-remove 'lisp--local-variables
+ #'helm-mode--advice-lisp--local-variables))))
+
+(defun helm-mode--in-file-completion-p ()
+ (with-helm-current-buffer
+ (run-hook-with-args-until-success 'file-name-at-point-functions)))
+
+(when (boundp 'completion-in-region-function)
+ (defconst helm--old-completion-in-region-function completion-in-region-function))
+
+;;;###autoload
+(define-minor-mode helm-mode
+ "Toggle generic helm completion.
+
+All functions in Emacs that use `completing-read'
+or `read-file-name' and friends will use helm interface
+when this mode is turned on.
+
+However you can modify this behavior for functions of your choice
+with `helm-completing-read-handlers-alist'.
+
+Also commands using `completion-in-region' will be helmized when
+`helm-mode-handle-completion-in-region' is non nil, you can modify
+this behavior with `helm-mode-no-completion-in-region-in-modes'.
+
+Called with a positive arg, turn on unconditionally, with a
+negative arg turn off.
+You can turn it on with `helm-mode'.
+
+Some crap emacs functions may not be supported,
+e.g `ffap-alternate-file' and maybe others
+You can add such functions to `helm-completing-read-handlers-alist'
+with a nil value.
+
+About `ido-mode':
+When you are using `helm-mode', DO NOT use `ido-mode', instead if you
+want some commands use `ido', add these commands to
+`helm-completing-read-handlers-alist' with `ido' as value.
+
+Note: This mode is incompatible with Emacs23."
+ :group 'helm-mode
+ :global t
+ :lighter helm-completion-mode-string
+ (cl-assert (boundp 'completing-read-function) nil
+ "`helm-mode' not available, upgrade to Emacs-24")
+ (if helm-mode
+ (if (fboundp 'add-function)
+ (progn
+ (add-function :override completing-read-function
+ #'helm--completing-read-default)
+ (add-function :override read-file-name-function
+ #'helm--generic-read-file-name)
+ (add-function :override read-buffer-function
+ #'helm--generic-read-buffer)
+ (when helm-mode-handle-completion-in-region
+ (add-function :override completion-in-region-function
+ #'helm--completion-in-region)))
+ (setq completing-read-function 'helm--completing-read-default
+ read-file-name-function 'helm--generic-read-file-name
+ read-buffer-function 'helm--generic-read-buffer)
+ (when (and (boundp 'completion-in-region-function)
+ helm-mode-handle-completion-in-region)
+ (setq completion-in-region-function #'helm--completion-in-region))
+ (message helm-completion-mode-start-message))
+ (if (fboundp 'remove-function)
+ (progn
+ (remove-function completing-read-function #'helm--completing-read-default)
+ (remove-function read-file-name-function #'helm--generic-read-file-name)
+ (remove-function read-buffer-function #'helm--generic-read-buffer)
+ (remove-function completion-in-region-function #'helm--completion-in-region))
+ (setq completing-read-function (and (fboundp 'completing-read-default)
+ 'completing-read-default)
+ read-file-name-function (and (fboundp 'read-file-name-default)
+ 'read-file-name-default)
+ read-buffer-function (and (fboundp 'read-buffer) 'read-buffer))
+ (when (and (boundp 'completion-in-region-function)
+ (boundp 'helm--old-completion-in-region-function))
+ (setq completion-in-region-function helm--old-completion-in-region-function))
+ (message helm-completion-mode-quit-message))))
+
+(provide 'helm-mode)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-mode.el ends here
--- /dev/null
+;;; helm-net.el --- helm browse url and search web. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'helm)
+(require 'helm-help)
+(require 'url)
+(require 'xml)
+(require 'browse-url)
+
+\f
+(defgroup helm-net nil
+ "Net related applications and libraries for Helm."
+ :group 'helm)
+
+(defcustom helm-google-suggest-default-browser-function nil
+ "The browse url function you prefer to use with google suggest.
+When nil, use the first browser function available
+See `helm-browse-url-default-browser-alist'."
+ :group 'helm-net
+ :type 'symbol)
+
+(defcustom helm-home-url "https://www.google.com"
+ "Default url to use as home url."
+ :group 'helm-net
+ :type 'string)
+
+(defcustom helm-surfraw-default-browser-function nil
+ "The browse url function you prefer to use with surfraw.
+When nil, fallback to `browse-url-browser-function'."
+ :group 'helm-net
+ :type 'symbol)
+
+(defcustom helm-google-suggest-url
+ "https://encrypted.google.com/complete/search?output=toolbar&q=%s"
+ "URL used for looking up Google suggestions.
+This is a format string, don't forget the `%s'."
+ :type 'string
+ :group 'helm-net)
+
+(defcustom helm-google-suggest-search-url
+ "https://encrypted.google.com/search?ie=utf-8&oe=utf-8&q=%s"
+ "URL used for Google searching.
+This is a format string, don't forget the `%s'."
+ :type 'string
+ :group 'helm-net)
+
+(defvaralias 'helm-google-suggest-use-curl-p 'helm-net-prefer-curl)
+(make-obsolete-variable 'helm-google-suggest-use-curl-p 'helm-net-prefer-curl "1.7.7")
+
+(defcustom helm-net-prefer-curl nil
+ "When non--nil use CURL external program to fetch data.
+Otherwise `url-retrieve-synchronously' is used."
+ :type 'boolean
+ :group 'helm-net)
+
+(defcustom helm-surfraw-duckduckgo-url
+ "https://duckduckgo.com/lite/?q=%s&kp=1"
+ "The duckduckgo url.
+This is a format string, don't forget the `%s'.
+If you have personal settings saved on duckduckgo you should have
+a personal url, see your settings on duckduckgo."
+ :type 'string
+ :group 'helm-net)
+
+(defcustom helm-wikipedia-suggest-url
+ "https://en.wikipedia.org/w/api.php?action=opensearch&search=%s"
+ "Url used for looking up Wikipedia suggestions.
+This is a format string, don't forget the `%s'."
+ :type 'string
+ :group 'helm-net)
+
+(defcustom helm-search-suggest-action-wikipedia-url
+ "https://en.wikipedia.org/wiki/Special:Search?search=%s"
+ "The Wikipedia search url.
+This is a format string, don't forget the `%s'."
+ :type 'string
+ :group 'helm-net)
+
+(defcustom helm-wikipedia-summary-url
+ "https://en.wikipedia.org/w/api.php?action=parse&format=json&prop=text§ion=0&page=%s"
+ "URL for getting the summary of a Wikipedia topic.
+This is a format string, don't forget the `%s'."
+ :type 'string
+ :group 'helm-net)
+
+(defcustom helm-search-suggest-action-youtube-url
+ "https://www.youtube.com/results?aq=f&search_query=%s"
+ "The Youtube search url.
+This is a format string, don't forget the `%s'."
+ :type 'string
+ :group 'helm-net)
+
+(defcustom helm-search-suggest-action-imdb-url
+ "http://www.imdb.com/find?s=all&q=%s"
+ "The IMDb search url.
+This is a format string, don't forget the `%s'."
+ :type 'string
+ :group 'helm-net)
+
+(defcustom helm-search-suggest-action-google-maps-url
+ "https://maps.google.com/maps?f=q&source=s_q&q=%s"
+ "The Google Maps search url.
+This is a format string, don't forget the `%s'."
+ :type 'string
+ :group 'helm-net)
+
+(defcustom helm-search-suggest-action-google-news-url
+ "https://www.google.com/search?safe=off&prmd=nvlifd&source=lnms&tbs=nws:1&q=%s"
+ "The Google News search url.
+This is a format string, don't forget the `%s'."
+ :type 'string
+ :group 'helm-net)
+
+(defcustom helm-google-suggest-actions
+ '(("Google Search" . helm-google-suggest-action)
+ ("Wikipedia" . (lambda (candidate)
+ (helm-search-suggest-perform-additional-action
+ helm-search-suggest-action-wikipedia-url
+ candidate)))
+ ("Youtube" . (lambda (candidate)
+ (helm-search-suggest-perform-additional-action
+ helm-search-suggest-action-youtube-url
+ candidate)))
+ ("IMDb" . (lambda (candidate)
+ (helm-search-suggest-perform-additional-action
+ helm-search-suggest-action-imdb-url
+ candidate)))
+ ("Google Maps" . (lambda (candidate)
+ (helm-search-suggest-perform-additional-action
+ helm-search-suggest-action-google-maps-url
+ candidate)))
+ ("Google News" . (lambda (candidate)
+ (helm-search-suggest-perform-additional-action
+ helm-search-suggest-action-google-news-url
+ candidate))))
+ "List of actions for google suggest sources."
+ :group 'helm-net
+ :type '(alist :key-type string :value-type function))
+
+(defcustom helm-browse-url-firefox-new-window "-new-tab"
+ "Allow choosing to browse url in new window or new tab.
+Can be \"-new-tab\" (default) or \"-new-window\"."
+ :group 'helm-net
+ :type '(radio
+ (const :tag "New tab" "-new-tab")
+ (const :tag "New window" "-new-window")))
+
+\f
+;;; Additional actions for search suggestions
+;;
+;;
+;; Internal
+
+(defun helm-search-suggest-perform-additional-action (url query)
+ "Perform the search via URL using QUERY as input."
+ (browse-url (format url (url-hexify-string query))))
+
+(defun helm-net--url-retrieve-sync (request parser)
+ (if helm-net-prefer-curl
+ (with-temp-buffer
+ (call-process "curl" nil t nil request)
+ (funcall parser))
+ (with-current-buffer (url-retrieve-synchronously request)
+ (funcall parser))))
+
+\f
+;;; Google Suggestions
+;;
+;;
+(defun helm-google-suggest-parser ()
+ (cl-loop
+ with result-alist = (xml-get-children
+ (car (xml-parse-region
+ (point-min) (point-max)))
+ 'CompleteSuggestion)
+ for i in result-alist collect
+ (cdr (cl-caadr (assq 'suggestion i)))))
+
+(defun helm-google-suggest-fetch (input)
+ "Fetch suggestions for INPUT from XML buffer."
+ (let ((request (format helm-google-suggest-url
+ (url-hexify-string input))))
+ (helm-net--url-retrieve-sync
+ request #'helm-google-suggest-parser)))
+
+(defun helm-google-suggest-set-candidates (&optional request-prefix)
+ "Set candidates with result and number of google results found."
+ (let ((suggestions (helm-google-suggest-fetch
+ (or (and request-prefix
+ (concat request-prefix
+ " " helm-pattern))
+ helm-pattern))))
+ (if (member helm-pattern suggestions)
+ suggestions
+ ;; if there is no suggestion exactly matching the input then
+ ;; prepend a Search on Google item to the list
+ (append
+ suggestions
+ (list (cons (format "Search for '%s' on Google" helm-input)
+ helm-input))))))
+
+(defun helm-ggs-set-number-result (num)
+ (if num
+ (progn
+ (and (numberp num) (setq num (number-to-string num)))
+ (cl-loop for i in (reverse (split-string num "" t))
+ for count from 1
+ append (list i) into C
+ when (= count 3)
+ append (list ",") into C
+ and do (setq count 0)
+ finally return
+ (replace-regexp-in-string
+ "^," "" (mapconcat 'identity (reverse C) ""))))
+ "?"))
+
+(defun helm-google-suggest-action (candidate)
+ "Default action to jump to a google suggested candidate."
+ (let ((arg (format helm-google-suggest-search-url
+ (url-hexify-string candidate))))
+ (helm-aif helm-google-suggest-default-browser-function
+ (funcall it arg)
+ (helm-browse-url arg))))
+
+(defvar helm-google-suggest-default-function
+ 'helm-google-suggest-set-candidates
+ "Default function to use in helm google suggest.")
+
+(defvar helm-source-google-suggest
+ (helm-build-sync-source "Google Suggest"
+ :candidates (lambda ()
+ (funcall helm-google-suggest-default-function))
+ :action 'helm-google-suggest-actions
+ :volatile t
+ :keymap helm-map
+ :requires-pattern 3))
+
+(defun helm-google-suggest-emacs-lisp ()
+ "Try to emacs lisp complete with google suggestions."
+ (helm-google-suggest-set-candidates "emacs lisp"))
+
+;;; Wikipedia suggestions
+;;
+;;
+(declare-function json-read-from-string "json" (string))
+(defun helm-wikipedia-suggest-fetch ()
+ "Fetch Wikipedia suggestions and return them as a list."
+ (require 'json)
+ (let ((request (format helm-wikipedia-suggest-url
+ (url-hexify-string helm-pattern))))
+ (helm-net--url-retrieve-sync
+ request #'helm-wikipedia--parse-buffer)))
+
+(defun helm-wikipedia--parse-buffer ()
+ (goto-char (point-min))
+ (when (re-search-forward "^\\[.+\\[\\(.*\\)\\]\\]" nil t)
+ (cl-loop for i across (aref (json-read-from-string (match-string 0)) 1)
+ collect i into result
+ finally return (or result
+ (append
+ result
+ (list (cons (format "Search for '%s' on wikipedia"
+ helm-pattern)
+ helm-pattern)))))))
+
+(defvar helm-wikipedia--summary-cache (make-hash-table :test 'equal))
+(defun helm-wikipedia-show-summary (input)
+ "Show Wikipedia summary for INPUT in new buffer."
+ (interactive)
+ (let ((buffer (get-buffer-create "*helm wikipedia summary*"))
+ (summary (helm-wikipedia--get-summary input)))
+ (with-current-buffer buffer
+ (visual-line-mode)
+ (erase-buffer)
+ (insert summary)
+ (pop-to-buffer (current-buffer))
+ (goto-char (point-min)))))
+
+(defun helm-wikipedia-persistent-action (candidate)
+ (unless (string= (format "Search for '%s' on wikipedia"
+ helm-pattern)
+ (helm-get-selection nil t))
+ (message "Fetching summary from Wikipedia...")
+ (let ((buf (get-buffer-create "*helm wikipedia summary*"))
+ (result (helm-wikipedia--get-summary candidate)))
+ (with-current-buffer buf
+ (erase-buffer)
+ (setq cursor-type nil)
+ (insert result)
+ (fill-region (point-min) (point-max))
+ (goto-char (point-min)))
+ (display-buffer buf))))
+
+(defun helm-wikipedia--get-summary (input)
+ "Return Wikipedia summary for INPUT as string.
+Follows any redirections from Wikipedia, and stores results in
+`helm-wikipedia--summary-cache'."
+ (let (result)
+ (while (progn
+ (setq result (or (gethash input helm-wikipedia--summary-cache)
+ (puthash input
+ (helm-wikipedia--fetch-summary input)
+ helm-wikipedia--summary-cache)))
+ (when (and result
+ (listp result))
+ (setq input (cdr result))
+ (message "Redirected to %s" input)
+ t)))
+ (unless result
+ (error "Error when getting summary."))
+ result))
+
+(defun helm-wikipedia--fetch-summary (input)
+ (let* ((request (format helm-wikipedia-summary-url
+ (url-hexify-string input))))
+ (helm-net--url-retrieve-sync
+ request #'helm-wikipedia--parse-summary)))
+
+(defun helm-wikipedia--parse-summary ()
+ (goto-char (point-min))
+ (when (search-forward "{" nil t)
+ (let ((result (cdr (assq '*
+ (assq 'text
+ (assq 'parse
+ (json-read-from-string
+ (buffer-substring-no-properties
+ (1- (point)) (point-max)))))))))
+ (when result
+ (if (string-match "<span class=\"redirectText\"><a href=[^>]+>\\([^<]+\\)" result)
+ (cons 'redirect (match-string 1 result))
+
+ ;; find the beginning of the summary text in the result
+
+ ;; check if there is a table before the summary and skip that
+ (when (or (string-match "</table>\\(\n<div.*?</div>\\)?\n<p>" result)
+ ;; otherwise just find the first paragraph
+ (string-match "<p>" result))
+ ;; remove cruft and do a simple formatting
+ (replace-regexp-in-string
+ "Cite error: .*" ""
+ (replace-regexp-in-string
+ " " ""
+ (replace-regexp-in-string
+ "\\[[^\]]+\\]" ""
+ (replace-regexp-in-string
+ "<[^>]*>" ""
+ (replace-regexp-in-string
+ "</p>\n<p>" "\n\n"
+ (substring result (match-end 0)))))))))))))
+
+
+(defvar helm-wikipedia-map
+ (let ((map (copy-keymap helm-map)))
+ (define-key map (kbd "<C-return>") 'helm-wikipedia-show-summary-action)
+ map)
+ "Keymap for `helm-wikipedia-suggest'.")
+
+(defvar helm-source-wikipedia-suggest
+ (helm-build-sync-source "Wikipedia Suggest"
+ :candidates #'helm-wikipedia-suggest-fetch
+ :action '(("Wikipedia" . (lambda (candidate)
+ (helm-search-suggest-perform-additional-action
+ helm-search-suggest-action-wikipedia-url
+ candidate)))
+ ("Show summary in new buffer (C-RET)" . helm-wikipedia-show-summary))
+ :persistent-action #'helm-wikipedia-persistent-action
+ :persistent-help "show summary"
+ :volatile t
+ :keymap helm-wikipedia-map
+ :requires-pattern 3))
+
+(defun helm-wikipedia-show-summary-action ()
+ "Exit Helm buffer and call `helm-wikipedia-show-summary' with selected candidate."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-wikipedia-show-summary)))
+
+\f
+;;; Web browser functions.
+;;
+;;
+;; If default setting of `w3m-command' is not
+;; what you want and you modify it, you will have to reeval
+;; also `helm-browse-url-default-browser-alist'.
+
+(defvar helm-browse-url-chromium-program "chromium-browser")
+(defvar helm-browse-url-uzbl-program "uzbl-browser")
+(defvar helm-browse-url-conkeror-program "conkeror")
+(defvar helm-browse-url-opera-program "opera")
+(defvar helm-browse-url-default-browser-alist
+ `((,(or (and (boundp 'w3m-command) w3m-command)
+ "/usr/bin/w3m") . w3m-browse-url)
+ (,browse-url-firefox-program . browse-url-firefox)
+ (,helm-browse-url-chromium-program . helm-browse-url-chromium)
+ (,helm-browse-url-conkeror-program . helm-browse-url-conkeror)
+ (,helm-browse-url-opera-program . helm-browse-url-opera)
+ (,helm-browse-url-uzbl-program . helm-browse-url-uzbl)
+ (,browse-url-kde-program . browse-url-kde)
+ (,browse-url-gnome-moz-program . browse-url-gnome-moz)
+ (,browse-url-mozilla-program . browse-url-mozilla)
+ (,browse-url-galeon-program . browse-url-galeon)
+ (,browse-url-netscape-program . browse-url-netscape)
+ (,browse-url-mosaic-program . browse-url-mosaic)
+ (,browse-url-xterm-program . browse-url-text-xterm)
+ ("emacs" . eww-browse-url))
+ "*Alist of \(executable . function\) to try to find a suitable url browser.")
+
+(cl-defun helm-generic-browser (url cmd-name &rest args)
+ "Browse URL with NAME browser."
+ (let ((proc (concat cmd-name " " url)))
+ (message "Starting %s..." cmd-name)
+ (apply 'start-process proc nil cmd-name
+ (append args (list url)))
+ (set-process-sentinel
+ (get-process proc)
+ (lambda (process event)
+ (when (string= event "finished\n")
+ (message "%s process %s" process event))))))
+
+;;;###autoload
+(defun helm-browse-url-firefox (url &optional _ignore)
+ "Same as `browse-url-firefox' but detach from emacs.
+
+So when you quit emacs you can keep your firefox session open
+and not be prompted to kill firefox process.
+
+NOTE: Probably not supported on some systems (e.g Windows)."
+ (interactive (list (read-string "URL: " (browse-url-url-at-point))
+ nil))
+ (setq url (browse-url-encode-url url))
+ (let ((process-environment (browse-url-process-environment)))
+ (call-process-shell-command
+ (format "(%s %s %s &)"
+ browse-url-firefox-program
+ helm-browse-url-firefox-new-window
+ (shell-quote-argument url)))))
+
+;;;###autoload
+(defun helm-browse-url-opera (url &optional _ignore)
+ "Browse URL with opera browser and detach from emacs.
+
+So when you quit emacs you can keep your opera session open
+and not be prompted to kill opera process.
+
+NOTE: Probably not supported on some systems (e.g Windows)."
+ (interactive (list (read-string "URL: " (browse-url-url-at-point))
+ nil))
+ (setq url (browse-url-encode-url url))
+ (let ((process-environment (browse-url-process-environment)))
+ (call-process-shell-command
+ (format "(%s %s &)"
+ helm-browse-url-opera-program (shell-quote-argument url)))))
+
+;;;###autoload
+(defun helm-browse-url-chromium (url &optional _ignore)
+ "Browse URL with google chrome browser."
+ (interactive "sURL: ")
+ (helm-generic-browser
+ url helm-browse-url-chromium-program))
+
+;;;###autoload
+(defun helm-browse-url-uzbl (url &optional _ignore)
+ "Browse URL with uzbl browser."
+ (interactive "sURL: ")
+ (helm-generic-browser url helm-browse-url-uzbl-program "-u"))
+
+;;;###autoload
+(defun helm-browse-url-conkeror (url &optional _ignore)
+ "Browse URL with conkeror browser."
+ (interactive "sURL: ")
+ (helm-generic-browser url helm-browse-url-conkeror-program))
+
+(defun helm-browse-url-default-browser (url &rest args)
+ "Find the first available browser and ask it to load URL."
+ (let ((default-browser-fn
+ (cl-loop for (exe . fn) in helm-browse-url-default-browser-alist
+ thereis (and exe (executable-find exe) (fboundp fn) fn))))
+ (if default-browser-fn
+ (apply default-browser-fn url args)
+ (error "No usable browser found"))))
+
+(defun helm-browse-url (url &rest args)
+ "Default command to browse URL."
+ (if browse-url-browser-function
+ (browse-url url args)
+ (helm-browse-url-default-browser url args)))
+
+\f
+;;; Surfraw
+;;
+;; Need external program surfraw.
+;; <http://surfraw.alioth.debian.org/>
+
+;; Internal
+(defvar helm-surfraw-engines-history nil)
+(defvar helm-surfraw-input-history nil)
+(defvar helm-surfraw--elvi-cache nil)
+
+(defun helm-build-elvi-list ()
+ "Return list of all engines and descriptions handled by surfraw."
+ (or helm-surfraw--elvi-cache
+ (setq helm-surfraw--elvi-cache
+ (cdr (with-temp-buffer
+ (call-process "surfraw" nil t nil "-elvi")
+ (split-string (buffer-string) "\n"))))))
+
+;;;###autoload
+(defun helm-surfraw (pattern engine)
+ "Preconfigured `helm' to search PATTERN with search ENGINE."
+ (interactive
+ (list
+ (let* ((default (if (use-region-p)
+ (buffer-substring-no-properties
+ (region-beginning) (region-end))
+ (thing-at-point 'symbol)))
+ (prompt (if default
+ (format "SearchFor (default %s): " default)
+ "SearchFor: ")))
+ (read-string prompt nil 'helm-surfraw-input-history default))
+ (helm-comp-read
+ "Engine: "
+ (helm-build-elvi-list)
+ :must-match t
+ :name "Surfraw Search Engines"
+ :del-input nil
+ :history helm-surfraw-engines-history)))
+ (let* ((engine-nodesc (car (split-string engine)))
+ (url (if (string= engine-nodesc "duckduckgo")
+ ;; "sr duckduckgo -p foo" is broken, workaround.
+ (format helm-surfraw-duckduckgo-url
+ (url-hexify-string pattern))
+ (with-temp-buffer
+ (apply 'call-process "surfraw" nil t nil
+ (append (list engine-nodesc "-p") (split-string pattern)))
+ (replace-regexp-in-string
+ "\n" "" (buffer-string)))))
+ (browse-url-browser-function (or helm-surfraw-default-browser-function
+ browse-url-browser-function)))
+ (if (string= engine-nodesc "W")
+ (helm-browse-url helm-home-url)
+ (helm-browse-url url)
+ (setq helm-surfraw-engines-history
+ (cons engine (delete engine helm-surfraw-engines-history))))))
+
+;;;###autoload
+(defun helm-google-suggest ()
+ "Preconfigured `helm' for google search with google suggest."
+ (interactive)
+ (helm-other-buffer 'helm-source-google-suggest "*helm google*"))
+
+;;;###autoload
+(defun helm-wikipedia-suggest ()
+ "Preconfigured `helm' for Wikipedia lookup with Wikipedia suggest."
+ (interactive)
+ (helm :sources 'helm-source-wikipedia-suggest
+ :buffer "*helm wikipedia*"))
+
+
+(provide 'helm-net)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-net.el ends here
--- /dev/null
+;;; helm-org.el --- Helm for org headlines and keywords completion -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Code:
+(require 'cl-lib)
+(require 'helm)
+(require 'helm-utils)
+(require 'org)
+\f
+;; Load org-with-point-at macro when compiling
+(eval-when-compile
+ (require 'org-macs))
+
+(declare-function org-agenda-switch-to "org-agenda.el")
+
+(defgroup helm-org nil
+ "Org related functions for helm."
+ :group 'helm)
+
+(defcustom helm-org-headings-fontify nil
+ "Fontify org buffers before parsing them.
+This reflect fontification in helm-buffer when non--nil.
+NOTE: This will be slow on large org buffers."
+ :group 'helm-org
+ :type 'boolean)
+
+(defcustom helm-org-format-outline-path nil
+ "Show all org level as path."
+ :group 'helm-org
+ :type 'boolean)
+
+(defcustom helm-org-show-filename nil
+ "Show org filenames in `helm-org-agenda-files-headings' when non--nil.
+Note this have no effect in `helm-org-in-buffer-headings'."
+ :group 'helm-org
+ :type 'boolean)
+
+(defcustom helm-org-headings-min-depth 1
+ "Minimum depth of org headings to start with."
+ :group 'helm-org
+ :type 'integer)
+
+(defcustom helm-org-headings-max-depth 8
+ "Go down to this maximum depth of org headings."
+ :group 'helm-org
+ :type 'integer)
+
+(defcustom helm-org-headings-actions
+ '(("Go to heading" . helm-org-goto-marker)
+ ("Open in indirect buffer `C-c i'" . helm-org--open-heading-in-indirect-buffer)
+ ("Refile heading(s) (marked-to-selected|current-to-selected) `C-c w`" . helm-org--refile-heading-to)
+ ("Insert link to this heading `C-c l`" . helm-org-insert-link-to-heading-at-marker))
+ "Default actions alist for
+ `helm-source-org-headings-for-files'."
+ :group 'helm-org
+ :type '(alist :key-type string :value-type function))
+
+(defcustom helm-org-truncate-lines t
+ "Truncate org-header-lines when non-nil"
+ :type 'boolean
+ :group 'helm-org)
+
+(defcustom helm-org-ignore-autosaves nil
+ "Ignore autosave files when starting `helm-org-agenda-files-headings'."
+ :type 'boolean
+ :group 'helm-org)
+
+\f
+;;; Org capture templates
+;;
+;;
+(defvar org-capture-templates)
+(defun helm-source-org-capture-templates ()
+ (helm-build-sync-source "Org Capture Templates:"
+ :candidates (cl-loop for template in org-capture-templates
+ collect (cons (nth 1 template) (nth 0 template)))
+ :action '(("Do capture" . (lambda (template-shortcut)
+ (org-capture nil template-shortcut))))))
+\f
+;;; Org headings
+;;
+;;
+(defun helm-org-goto-marker (marker)
+ (switch-to-buffer (marker-buffer marker))
+ (goto-char (marker-position marker))
+ (org-show-context)
+ (re-search-backward "^\\*+ " nil t)
+ (org-show-entry))
+
+(defun helm-org--open-heading-in-indirect-buffer (marker)
+ (helm-org-goto-marker marker)
+ (org-tree-to-indirect-buffer)
+
+ ;; Put the non-indirect buffer at the bottom of the prev-buffers
+ ;; list so it won't be selected when the indirect buffer is killed
+ (set-window-prev-buffers nil (append (cdr (window-prev-buffers))
+ (car (window-prev-buffers)))))
+
+(defun helm-org-run-open-heading-in-indirect-buffer ()
+ "Open selected Org heading in an indirect buffer."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action #'helm-org--open-heading-in-indirect-buffer)))
+(put 'helm-org-run-open-heading-in-indirect-buffer 'helm-only t)
+
+(defvar helm-org-headings-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map helm-map)
+ (define-key map (kbd "C-c i") 'helm-org-run-open-heading-in-indirect-buffer)
+ (define-key map (kbd "C-c w") 'helm-org-run-refile-heading-to)
+ (define-key map (kbd "C-c l") 'helm-org-run-insert-link-to-heading-at-marker)
+ map)
+ "Keymap for `helm-source-org-headings-for-files'.")
+
+(defclass helm-org-headings-class (helm-source-sync)
+ ((parents
+ :initarg :parents
+ :initform nil
+ :custom boolean)
+ (match :initform
+ (lambda (candidate)
+ (string-match
+ helm-pattern
+ (helm-aif (get-text-property 0 'helm-real-display candidate)
+ it
+ candidate))))
+ (help-message :initform 'helm-org-headings-help-message)
+ (action :initform 'helm-org-headings-actions)
+ (keymap :initform 'helm-org-headings-map)
+ (group :initform 'helm-org)))
+
+(defmethod helm--setup-source :after ((source helm-org-headings-class))
+ (let ((parents (slot-value source 'parents)))
+ (setf (slot-value source 'candidate-transformer)
+ (lambda (candidates)
+ (let ((cands (helm-org-get-candidates candidates parents)))
+ (if parents (nreverse cands) cands))))))
+
+(defun helm-source-org-headings-for-files (filenames &optional parents)
+ (helm-make-source "Org Headings" 'helm-org-headings-class
+ :filtered-candidate-transformer 'helm-org-startup-visibility
+ :parents parents
+ :candidates filenames))
+
+(defun helm-org-startup-visibility (candidates _source)
+ "Indent headings and hide leading stars displayed in the helm buffer.
+If `org-startup-indented' and `org-hide-leading-stars' are nil, do
+nothing to CANDIDATES."
+ (cl-loop for i in candidates
+ collect
+ ;; Transformation is not needed if these variables are t.
+ (if (or helm-org-show-filename helm-org-format-outline-path)
+ (cons
+ (car i) (cdr i))
+ (cons
+ (if helm-org-headings-fontify
+ (when (string-match "^\\(\\**\\)\\(\\* \\)\\(.*\n?\\)" (car i))
+ (replace-match "\\1\\2\\3" t nil (car i)))
+ (when (string-match "^\\(\\**\\)\\(\\* \\)\\(.*\n?\\)" (car i))
+ (let ((foreground (org-find-invisible-foreground)))
+ (with-helm-current-buffer
+ (cond
+ ;; org-startup-indented is t, and org-hide-leading-stars is t
+ ;; Or: #+STARTUP: indent hidestars
+ ((and org-startup-indented org-hide-leading-stars)
+ (with-helm-buffer
+ (require 'org-indent)
+ (org-indent-mode 1)
+ (replace-match
+ (format "%s\\2\\3"
+ (propertize (replace-match "\\1" t nil (car i))
+ 'face `(:foreground ,foreground)))
+ t nil (car i))))
+ ;; org-startup-indented is nil, org-hide-leading-stars is t
+ ;; Or: #+STARTUP: noindent hidestars
+ ((and (not org-startup-indented) org-hide-leading-stars)
+ (with-helm-buffer
+ (replace-match
+ (format "%s\\2\\3"
+ (propertize (replace-match "\\1" t nil (car i))
+ 'face `(:foreground ,foreground)))
+ t nil (car i))))
+ ;; org-startup-indented is nil, and org-hide-leading-stars is nil
+ ;; Or: #+STARTUP: noindent showstars
+ (t
+ (with-helm-buffer
+ (replace-match "\\1\\2\\3" t nil (car i)))))))))
+ (cdr i)))))
+
+(defun helm-org-get-candidates (filenames &optional parents)
+ (apply #'append
+ (mapcar (lambda (filename)
+ (helm-org--get-candidates-in-file
+ filename
+ helm-org-headings-fontify
+ (or parents (null helm-org-show-filename))
+ parents))
+ filenames)))
+
+(defun helm-org--get-candidates-in-file (filename &optional fontify nofname parents)
+ (with-current-buffer (pcase filename
+ ((pred bufferp) filename)
+ ((pred stringp) (find-file-noselect filename t)))
+ (let ((match-fn (if fontify
+ #'match-string
+ #'match-string-no-properties))
+ (search-fn (lambda ()
+ (re-search-forward
+ org-complex-heading-regexp nil t)))
+ (file (unless (or (bufferp filename) nofname)
+ (concat (helm-basename filename) ":"))))
+ (when parents
+ (add-function :around (var search-fn)
+ (lambda (old-fn &rest args)
+ (when (org-up-heading-safe)
+ (apply old-fn args)))))
+ (save-excursion
+ (save-restriction
+ (unless (and (bufferp filename)
+ (buffer-base-buffer filename))
+ ;; Only widen direct buffers, not indirect ones.
+ (widen))
+ (unless parents (goto-char (point-min)))
+ ;; clear cache for new version of org-get-outline-path
+ (and (boundp 'org-outline-path-cache)
+ (setq org-outline-path-cache nil))
+ (cl-loop with width = (window-width (helm-window))
+ while (funcall search-fn)
+ for beg = (point-at-bol)
+ for end = (point-at-eol)
+ when (and fontify
+ (null (text-property-any
+ beg end 'fontified t)))
+ do (jit-lock-fontify-now beg end)
+ for level = (length (match-string-no-properties 1))
+ for heading = (funcall match-fn 4)
+ if (and (>= level helm-org-headings-min-depth)
+ (<= level helm-org-headings-max-depth))
+ collect `(,(propertize
+ (if helm-org-format-outline-path
+ (org-format-outline-path
+ ;; org-get-outline-path changed in signature and behaviour since org's
+ ;; commit 105a4466971. Let's fall-back to the new version in case
+ ;; of wrong-number-of-arguments error.
+ (condition-case nil
+ (append (apply #'org-get-outline-path
+ (unless parents
+ (list t level heading)))
+ (list heading))
+ (wrong-number-of-arguments
+ (org-get-outline-path t t)))
+ width file)
+ (if file
+ (concat file (funcall match-fn 0))
+ (funcall match-fn 0)))
+ 'helm-real-display heading)
+ . ,(point-marker))))))))
+
+(defun helm-org-insert-link-to-heading-at-marker (marker)
+ (with-current-buffer (marker-buffer marker)
+ (let ((heading-name (save-excursion (goto-char (marker-position marker))
+ (nth 4 (org-heading-components))))
+ (file-name (buffer-file-name)))
+ (with-helm-current-buffer
+ (org-insert-link
+ file-name (concat "file:" file-name "::*" heading-name))))))
+
+(defun helm-org-run-insert-link-to-heading-at-marker ()
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action
+ 'helm-org-insert-link-to-heading-at-marker)))
+
+(defun helm-org--refile-heading-to (marker)
+ "Refile headings to heading at MARKER.
+If multiple candidates are marked in the Helm session, they will
+all be refiled. If no headings are marked, the selected heading
+will be refiled."
+ (let* ((victims (with-helm-buffer (helm-marked-candidates)))
+ (buffer (marker-buffer marker))
+ (filename (buffer-file-name buffer))
+ (rfloc (list nil filename nil marker)))
+ (when (and (= 1 (length victims))
+ (equal (helm-get-selection) (car victims)))
+ ;; No candidates are marked; we are refiling the entry at point
+ ;; to the selected heading
+ (setq victims (list (point))))
+ ;; Probably best to check that everything returned a value
+ (when (and victims buffer filename rfloc)
+ (cl-loop for victim in victims
+ do (org-with-point-at victim
+ (org-refile nil nil rfloc))))))
+
+(defun helm-org-in-buffer-preselect ()
+ (if (org-on-heading-p)
+ (buffer-substring-no-properties (point-at-bol) (point-at-eol))
+ (save-excursion
+ (outline-previous-visible-heading 1)
+ (buffer-substring-no-properties (point-at-bol) (point-at-eol)))))
+
+(defun helm-org-run-refile-heading-to ()
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-org--refile-heading-to)))
+(put 'helm-org-run-refile-heading-to 'helm-only t)
+\f
+;;;###autoload
+(defun helm-org-agenda-files-headings ()
+ "Preconfigured helm for org files headings."
+ (interactive)
+ (let ((autosaves (cl-loop for f in (org-agenda-files)
+ when (file-exists-p
+ (expand-file-name
+ (concat "#" (helm-basename f) "#")
+ (helm-basedir f)))
+ collect (helm-basename f))))
+ (when (or (null autosaves)
+ helm-org-ignore-autosaves
+ (y-or-n-p (format "%s have auto save data, continue?"
+ (mapconcat 'identity autosaves ", "))))
+ (helm :sources (helm-source-org-headings-for-files (org-agenda-files))
+ :candidate-number-limit 99999
+ :truncate-lines helm-org-truncate-lines
+ :buffer "*helm org headings*"))))
+
+;;;###autoload
+(defun helm-org-in-buffer-headings ()
+ "Preconfigured helm for org buffer headings."
+ (interactive)
+ (let (helm-org-show-filename)
+ (helm :sources (helm-source-org-headings-for-files
+ (list (current-buffer)))
+ :candidate-number-limit 99999
+ :preselect (helm-org-in-buffer-preselect)
+ :truncate-lines helm-org-truncate-lines
+ :buffer "*helm org inbuffer*")))
+
+;;;###autoload
+(defun helm-org-parent-headings ()
+ "Preconfigured helm for org headings that are parents of the
+current heading."
+ (interactive)
+ ;; Use a large max-depth to ensure all parents are displayed.
+ (let ((helm-org-headings-min-depth 1)
+ (helm-org-headings-max-depth 50))
+ (helm :sources (helm-source-org-headings-for-files
+ (list (current-buffer)) t)
+ :candidate-number-limit 99999
+ :truncate-lines helm-org-truncate-lines
+ :buffer "*helm org parent headings*")))
+
+;;;###autoload
+(defun helm-org-capture-templates ()
+ "Preconfigured helm for org templates."
+ (interactive)
+ (helm :sources (helm-source-org-capture-templates)
+ :candidate-number-limit 99999
+ :truncate-lines helm-org-truncate-lines
+ :buffer "*helm org capture templates*"))
+\f
+;;; Org tag completion
+
+;; Based on code from Anders Johansson posted on 3 Mar 2016 at
+;; <https://groups.google.com/d/msg/emacs-helm/tA6cn6TUdRY/G1S3TIdzBwAJ>
+
+(defvar crm-separator)
+
+;;;###autoload
+(defun helm-org-completing-read-tags (prompt collection pred req initial
+ hist def inherit-input-method _name _buffer)
+ "Completing read function for Org tags.
+
+This function is used as a `completing-read' function in
+`helm-completing-read-handlers-alist' by `org-set-tags' and
+`org-capture'.
+
+NOTE: Org tag completion will work only if you disable org fast tag
+selection, see (info \"(org) setting tags\")."
+ (if (not (string= "Tags: " prompt))
+ ;; Not a tags prompt. Use normal completion by calling
+ ;; `org-icompleting-read' again without this function in
+ ;; `helm-completing-read-handlers-alist'
+ (let ((helm-completing-read-handlers-alist
+ (rassq-delete-all
+ 'helm-org-completing-read-tags
+ (copy-alist helm-completing-read-handlers-alist))))
+ (org-icompleting-read
+ prompt collection pred req initial hist def inherit-input-method))
+ ;; Tags prompt
+ (let* ((curr (and (stringp initial)
+ (not (string= initial ""))
+ (org-split-string initial ":")))
+ (table (delete curr
+ (org-uniquify
+ (mapcar 'car org-last-tags-completion-table))))
+ (crm-separator ":\\|,\\|\\s-"))
+ (cl-letf (((symbol-function 'crm-complete-word)
+ 'self-insert-command))
+ (mapconcat 'identity
+ (completing-read-multiple
+ prompt table pred nil initial hist def)
+ ":")))))
+
+(provide 'helm-org)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-org.el ends here
--- /dev/null
+(define-package "helm" "20181110.1615" "Helm is an Emacs incremental and narrowing framework"
+ '((emacs "24.4")
+ (async "1.9.3")
+ (popup "0.5.3")
+ (helm-core "3.0"))
+ :url "https://emacs-helm.github.io/helm/")
+;; Local Variables:
+;; no-byte-compile: t
+;; End:
--- /dev/null
+;;; helm-regexp.el --- In buffer regexp searching and replacement for helm. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'helm)
+(require 'helm-help)
+(require 'helm-utils)
+
+(declare-function helm-mm-split-pattern "helm-multi-match")
+
+\f
+(defgroup helm-regexp nil
+ "Regexp related Applications and libraries for Helm."
+ :group 'helm)
+
+(defcustom helm-moccur-always-search-in-current nil
+ "Helm multi occur always search in current buffer when non--nil."
+ :group 'helm-regexp
+ :type 'boolean)
+
+(defcustom helm-moccur-use-ioccur-style-keys t
+ "Similar to `helm-grep-use-ioccur-style-keys' but for multi occur."
+ :group 'helm-regexp
+ :type 'boolean)
+
+(defcustom helm-moccur-auto-update-on-resume nil
+ "Allow auto updating helm-(m)occur buffer when outdated.
+noask => Always update without asking
+nil => Don't update but signal buffer needs update
+never => Never update and do not signal buffer needs update
+Any other non--nil value update after confirmation."
+ :group 'helm-regexp
+ :type '(radio :tag "Allow auto updating helm-(m)occur buffer when outdated."
+ (const :tag "Always update without asking" noask)
+ (const :tag "Never update and do not signal buffer needs update" never)
+ (const :tag "Don't update but signal buffer needs update" nil)
+ (const :tag "Update after confirmation" t)))
+
+(defcustom helm-source-multi-occur-actions
+ '(("Go to Line" . helm-moccur-goto-line)
+ ("Goto line other window (C-u vertically)" . helm-moccur-goto-line-ow)
+ ("Goto line new frame" . helm-moccur-goto-line-of))
+ "Actions for helm-occur and helm-moccur."
+ :group 'helm-regexp
+ :type '(alist :key-type string :value-type function))
+
+(defcustom helm-moccur-truncate-lines t
+ "When nil the (m)occur line that appears will not be truncated."
+ :group 'helm-regexp
+ :type 'boolean)
+
+(defcustom helm-moccur-show-buffer-fontification nil
+ "Show fontification of searched buffer in results when non nil.
+
+This enable or disable fontification globally in results, but you can
+override this default setting with `helm-moccur-buffer-substring-fn-for-modes'."
+ :group 'helm-regexp
+ :type '(radio :tag "Allow preserving fontification of searched buffer in results"
+ (const :tag "Don't preserve buffer fontification" nil)
+ (const :tag "Preserve buffer fontification" t)))
+
+(defcustom helm-moccur-buffer-substring-fn-for-modes
+ '((mu4e-headers-mode . buffer-substring)
+ (package-menu-mode . buffer-substring-no-properties))
+ "Alist that allow configuring the function to use for storing a buffer.
+
+Can be one of `buffer-substring' or `buffer-substring-no-properties'.
+Allow overriding the global effect of `helm-moccur-show-buffer-fontification'
+for a specific mode."
+ :group 'helm-regexp
+ :type '(alist :key-type (symbol :tag "Mode")
+ :value-type (radio (const :tag "With text properties" buffer-substring)
+ (const :tag "Without text properties" buffer-substring-no-properties))))
+
+(defcustom helm-occur-show-buffer-name nil
+ "Show buffer name in `helm-occur' results when non-nil.
+
+Not that this doesn't affect `helm-moccur' results and
+`helm-moccur-mode' buffers where buffer names are always shown."
+ :group 'helm-regexp
+ :type 'boolean)
+\f
+(defface helm-moccur-buffer
+ '((t (:foreground "DarkTurquoise" :underline t)))
+ "Face used to highlight moccur buffer names."
+ :group 'helm-regexp)
+
+(defface helm-resume-need-update
+ '((t (:background "red")))
+ "Face used to flash moccur buffer when it needs update."
+ :group 'helm-regexp)
+
+\f
+(defvar helm-moccur-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map helm-map)
+ (define-key map (kbd "M-<down>") 'helm-goto-next-file)
+ (define-key map (kbd "M-<up>") 'helm-goto-precedent-file)
+ (define-key map (kbd "C-c o") 'helm-moccur-run-goto-line-ow)
+ (define-key map (kbd "C-c C-o") 'helm-moccur-run-goto-line-of)
+ (define-key map (kbd "C-x C-s") 'helm-moccur-run-save-buffer)
+ (when helm-moccur-use-ioccur-style-keys
+ (define-key map (kbd "<right>") 'helm-execute-persistent-action)
+ (define-key map (kbd "<left>") 'helm-moccur-run-default-action))
+ (delq nil map))
+ "Keymap used in Moccur source.")
+
+\f
+;; History vars
+(defvar helm-build-regexp-history nil)
+(defvar helm-occur-history nil)
+
+(defun helm-query-replace-regexp (_candidate)
+ "Query replace regexp from `helm-regexp'.
+With a prefix arg replace only matches surrounded by word boundaries,
+i.e Don't replace inside a word, regexp is surrounded with \\bregexp\\b."
+ (let ((regexp helm-input))
+ (apply 'query-replace-regexp
+ (helm-query-replace-args regexp))))
+
+(defun helm-kill-regexp-as-sexp (_candidate)
+ "Kill regexp in a format usable in lisp code."
+ (helm-regexp-kill-new
+ (prin1-to-string helm-input)))
+
+(defun helm-kill-regexp (_candidate)
+ "Kill regexp as it is in `helm-pattern'."
+ (helm-regexp-kill-new helm-input))
+
+(defun helm-query-replace-args (regexp)
+ "create arguments of `query-replace-regexp' action in `helm-regexp'."
+ (let ((region-only (helm-region-active-p)))
+ (list
+ regexp
+ (query-replace-read-to regexp
+ (format "Query replace %sregexp %s"
+ (if helm-current-prefix-arg "word " "")
+ (if region-only "in region " ""))
+ t)
+ helm-current-prefix-arg
+ (when region-only (region-beginning))
+ (when region-only (region-end)))))
+
+(defvar helm-source-regexp
+ (helm-build-in-buffer-source "Regexp Builder"
+ :init (lambda ()
+ (helm-init-candidates-in-buffer
+ 'global (with-temp-buffer
+ (insert-buffer-substring helm-current-buffer)
+ (buffer-string))))
+ :get-line #'helm-regexp-get-line
+ :persistent-action #'helm-regexp-persistent-action
+ :persistent-help "Show this line"
+ :multiline t
+ :multimatch nil
+ :requires-pattern 2
+ :group 'helm-regexp
+ :mode-line "Press TAB to select action."
+ :action '(("Kill Regexp as sexp" . helm-kill-regexp-as-sexp)
+ ("Query Replace Regexp (C-u Not inside word.)"
+ . helm-query-replace-regexp)
+ ("Kill Regexp" . helm-kill-regexp))))
+
+(defun helm-regexp-get-line (s e)
+ (let ((matches (match-data))
+ (line (buffer-substring s e)))
+ (propertize
+ (cl-loop with ln = (format "%5d: %s" (1- (line-number-at-pos s)) line)
+ for i from 0 to (1- (/ (length matches) 2))
+ if (match-string i)
+ concat (format "\n%s%s'%s'"
+ (make-string 10 ? ) (format "Group %d: " i) it)
+ into ln1
+ finally return (concat ln ln1))
+ 'helm-realvalue s)))
+
+(defun helm-regexp-persistent-action (pt)
+ (helm-goto-char pt)
+ (helm-highlight-current-line))
+
+(defun helm-regexp-kill-new (input)
+ (kill-new (substring-no-properties input))
+ (message "Killed: %s" input))
+
+\f
+;;; Occur
+;;
+;;
+(defvar helm-source-occur nil)
+(defun helm-occur-init-source ()
+ (unless helm-source-occur
+ (setq helm-source-occur
+ (helm-make-source "Occur" 'helm-source-multi-occur))))
+
+\f
+;;; Multi occur
+;;
+;;
+
+;; Internal
+(defvar helm-multi-occur-buffer-list nil)
+(defvar helm-multi-occur-buffer-tick nil)
+(defvar helm-occur--invisible nil
+ "[INTERNAL] Hide buffer name in results when non-nil.
+Should be a local var to helm-buffer to allow resuming.")
+
+(defun helm-moccur-init ()
+ "Create the initial helm multi occur buffer."
+ (helm-init-candidates-in-buffer
+ 'global
+ (cl-loop with buffers = (helm-attr 'moccur-buffers)
+ with bsubstring = (if helm-moccur-show-buffer-fontification
+ #'buffer-substring #'buffer-substring-no-properties)
+ for buf in buffers
+ for bufstr = (with-current-buffer buf
+ (helm-aif (assq major-mode
+ helm-moccur-buffer-substring-fn-for-modes)
+ (setq bsubstring (cdr it)))
+ ;; A leading space is needed to allow helm
+ ;; searching the first line of buffer
+ ;; (#1725).
+ (concat (if (memql (char-after (point-min))
+ '(? ?\t ?\n))
+ "" " ")
+ (funcall bsubstring (point-min) (point-max))))
+ do (add-text-properties
+ 0 (length bufstr)
+ `(buffer-name ,(buffer-name (get-buffer buf)))
+ bufstr)
+ concat bufstr)))
+
+(defun helm-moccur--next-or-previous-char ()
+ (save-excursion
+ (or (re-search-forward "^." nil t)
+ (re-search-backward "^." nil t))))
+
+(defun helm-moccur-get-line (beg end)
+ "Format line for `helm-source-moccur'."
+ (prog1
+ (format "%s:%d:%s"
+ (get-text-property (if (= beg end)
+ (helm-moccur--next-or-previous-char)
+ beg)
+ 'buffer-name)
+ (save-restriction
+ (narrow-to-region (or (previous-single-property-change
+ (point) 'buffer-name)
+ (point-at-bol 2))
+ (or (next-single-property-change
+ (if (= beg end)
+ (helm-moccur--next-or-previous-char)
+ (point))
+ 'buffer-name)
+ (point-max)))
+ (line-number-at-pos beg))
+ ;; When matching empty line, use empty string
+ ;; to allow saving and modifying with wgrep.
+ (if (= beg end) "" (buffer-substring beg end)))
+ ;; When matching empty line, forward char ("\n")
+ ;; to not be blocked forever here.
+ (when (= beg end) (forward-char 1))))
+
+(cl-defun helm-moccur-action (candidate
+ &optional (method (quote buffer)))
+ "Jump to CANDIDATE with METHOD.
+arg METHOD can be one of buffer, buffer-other-window, buffer-other-frame."
+ (require 'helm-grep)
+ (let* ((split (helm-grep-split-line candidate))
+ (buf (car split))
+ (lineno (string-to-number (nth 1 split)))
+ (split-pat (helm-mm-split-pattern helm-input)))
+ (cl-case method
+ (buffer (switch-to-buffer buf))
+ (buffer-other-window (helm-window-show-buffers (list buf) t))
+ (buffer-other-frame (switch-to-buffer-other-frame buf)))
+ (with-current-buffer buf
+ (helm-goto-line lineno)
+ ;; Move point to the nearest matching regexp from bol.
+ (cl-loop for reg in split-pat
+ when (save-excursion
+ (condition-case _err
+ (if helm-migemo-mode
+ (helm-mm-migemo-forward reg (point-at-eol) t)
+ (re-search-forward reg (point-at-eol) t))
+ (invalid-regexp nil)))
+ collect (match-beginning 0) into pos-ls
+ finally (when pos-ls (goto-char (apply #'min pos-ls)))))))
+
+(defun helm-moccur-persistent-action (candidate)
+ (helm-moccur-goto-line candidate)
+ (helm-highlight-current-line))
+
+(defun helm-moccur-goto-line (candidate)
+ "From multi occur, switch to buffer and go to nth 1 CANDIDATE line."
+ (helm-moccur-action
+ candidate 'buffer))
+
+(defun helm-moccur-goto-line-ow (candidate)
+ "Go to CANDIDATE line in other window.
+Same as `helm-moccur-goto-line' but go in other window."
+ (helm-moccur-action
+ candidate 'buffer-other-window))
+
+(defun helm-moccur-goto-line-of (candidate)
+ "Go to CANDIDATE line in new frame.
+Same as `helm-moccur-goto-line' but go in new frame."
+ (helm-moccur-action
+ candidate 'buffer-other-frame))
+
+(defun helm-moccur-run-goto-line-ow ()
+ "Run goto line other window action from `helm-source-moccur'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-moccur-goto-line-ow)))
+(put 'helm-moccur-run-goto-line-ow 'helm-only t)
+
+(defun helm-moccur-run-goto-line-of ()
+ "Run goto line new frame action from `helm-source-moccur'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-moccur-goto-line-of)))
+(put 'helm-moccur-run-goto-line-of 'helm-only t)
+
+(defun helm-moccur-run-default-action ()
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-moccur-goto-line)))
+(put 'helm-moccur-run-default-action 'helm-only t)
+
+(defvar helm-moccur-before-init-hook nil
+ "Hook that runs before initialization of the helm buffer.")
+
+(defvar helm-moccur-after-init-hook nil
+ "Hook that runs after initialization of the helm buffer.")
+
+(defvar helm-source-moccur nil)
+(defclass helm-source-multi-occur (helm-source-in-buffer)
+ ((init :initform (lambda ()
+ (require 'helm-grep)
+ (helm-moccur-init)))
+ (filter-one-by-one :initform 'helm-moccur-filter-one-by-one)
+ (get-line :initform helm-moccur-get-line)
+ (nohighlight :initform t)
+ (nomark :initform t)
+ (migemo :initform t)
+ (action :initform 'helm-source-multi-occur-actions)
+ (persistent-action :initform 'helm-moccur-persistent-action)
+ (persistent-help :initform "Go to line")
+ (resume :initform 'helm-moccur-resume-fn)
+ (candidate-number-limit :initform 9999)
+ (help-message :initform 'helm-moccur-help-message)
+ (keymap :initform helm-moccur-map)
+ (history :initform 'helm-occur-history)
+ (requires-pattern :initform 2)
+ (before-init-hook :initform 'helm-moccur-before-init-hook)
+ (after-init-hook :initform 'helm-moccur-after-init-hook)
+ (group :initform 'helm-regexp)))
+
+(defun helm-moccur-resume-fn ()
+ (with-helm-buffer
+ (let (new-tick-ls buffer-is-modified)
+ (set (make-local-variable 'helm-multi-occur-buffer-list)
+ (cl-loop for b in helm-multi-occur-buffer-list
+ when (buffer-live-p (get-buffer b))
+ collect b))
+ (setq buffer-is-modified (/= (length helm-multi-occur-buffer-list)
+ (length (helm-attr 'moccur-buffers))))
+ (helm-attrset 'moccur-buffers helm-multi-occur-buffer-list)
+ (setq new-tick-ls (cl-loop for b in helm-multi-occur-buffer-list
+ collect (buffer-chars-modified-tick (get-buffer b))))
+ (when buffer-is-modified
+ (setq helm-multi-occur-buffer-tick new-tick-ls))
+ (cl-assert (> (length helm-multi-occur-buffer-list) 0) nil
+ "helm-resume error: helm-(m)occur buffer list is empty")
+ (unless (eq helm-moccur-auto-update-on-resume 'never)
+ (when (or buffer-is-modified
+ (cl-loop for b in helm-multi-occur-buffer-list
+ for new-tick = (buffer-chars-modified-tick (get-buffer b))
+ for tick in helm-multi-occur-buffer-tick
+ thereis (/= tick new-tick)))
+ (helm-aif helm-moccur-auto-update-on-resume
+ (when (or (eq it 'noask)
+ (y-or-n-p "Helm (m)occur Buffer outdated, update? "))
+ (run-with-idle-timer 0.1 nil (lambda ()
+ (with-helm-buffer
+ (helm-force-update)
+ (message "Helm (m)occur Buffer have been udated")
+ (sit-for 1) (message nil))))
+ (unless buffer-is-modified (setq helm-multi-occur-buffer-tick new-tick-ls)))
+ (run-with-idle-timer 0.1 nil (lambda ()
+ (with-helm-buffer
+ (let ((ov (make-overlay (save-excursion
+ (goto-char (point-min))
+ (forward-line 1)
+ (point))
+ (point-max))))
+ (overlay-put ov 'face 'helm-resume-need-update)
+ (sit-for 0.3) (delete-overlay ov)
+ (message "[Helm occur Buffer outdated (C-c C-u to update)]")))))
+ (unless buffer-is-modified
+ (with-helm-after-update-hook
+ (setq helm-multi-occur-buffer-tick new-tick-ls)
+ (message "Helm (m)occur Buffer have been udated")))))))))
+
+(defun helm-moccur-filter-one-by-one (candidate &optional outside-helm)
+ "`filter-one-by-one' function for `helm-source-moccur'."
+ (require 'helm-grep)
+ (let* ((split (helm-grep-split-line candidate))
+ (buf (car split))
+ (lineno (nth 1 split))
+ (str (nth 2 split)))
+ (cons (concat (propertize
+ buf
+ 'invisible (and (null outside-helm)
+ (with-helm-buffer
+ helm-occur--invisible))
+ 'face 'helm-moccur-buffer
+ 'help-echo (buffer-file-name
+ (get-buffer buf))
+ 'buffer-name buf)
+ (propertize ":" 'invisible (and (null outside-helm)
+ (with-helm-buffer
+ helm-occur--invisible)))
+ (propertize lineno 'face 'helm-grep-lineno)
+ ":"
+ (helm-grep-highlight-match str t))
+ candidate)))
+
+(defun helm-multi-occur-1 (buffers &optional input)
+ "Main function to call `helm-source-moccur' with BUFFERS list."
+ (let ((bufs (if helm-moccur-always-search-in-current
+ (cons
+ ;; will become helm-current-buffer later.
+ (buffer-name (current-buffer))
+ (remove helm-current-buffer buffers))
+ buffers)))
+ (unless helm-source-moccur
+ (setq helm-source-moccur
+ (helm-make-source "Moccur" 'helm-source-multi-occur)))
+ (helm-attrset 'moccur-buffers bufs helm-source-moccur)
+ (helm-set-local-variable 'helm-multi-occur-buffer-list bufs)
+ (helm-set-local-variable
+ 'helm-multi-occur-buffer-tick
+ (cl-loop for b in bufs
+ collect (buffer-chars-modified-tick (get-buffer b)))))
+ (helm :sources 'helm-source-moccur
+ :buffer "*helm multi occur*"
+ :default (helm-aif (thing-at-point 'symbol) (regexp-quote it))
+ :history 'helm-occur-history
+ :keymap helm-moccur-map
+ :input input
+ :truncate-lines helm-moccur-truncate-lines))
+
+(defun helm-moccur-run-save-buffer ()
+ "Run moccur save results action from `helm-moccur'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-moccur-save-results)))
+(put 'helm-moccur-run-save-buffer 'helm-only t)
+
+\f
+;;; helm-moccur-mode
+;;
+;;
+(defvar helm-moccur-mode-map
+ (let ((map (make-sparse-keymap)))
+ (define-key map (kbd "RET") 'helm-moccur-mode-goto-line)
+ (define-key map (kbd "C-o") 'helm-moccur-mode-goto-line-ow)
+ (define-key map (kbd "<C-down>") 'helm-moccur-mode-goto-line-ow-forward)
+ (define-key map (kbd "<C-up>") 'helm-moccur-mode-goto-line-ow-backward)
+ (define-key map (kbd "<M-down>") 'helm-gm-next-file)
+ (define-key map (kbd "<M-up>") 'helm-gm-precedent-file)
+ (define-key map (kbd "M-n") 'helm-moccur-mode-goto-line-ow-forward)
+ (define-key map (kbd "M-p") 'helm-moccur-mode-goto-line-ow-backward)
+ (define-key map (kbd "M-N") 'helm-gm-next-file)
+ (define-key map (kbd "M-P") 'helm-gm-precedent-file)
+ map))
+
+(defun helm-moccur-mode-goto-line ()
+ (interactive)
+ (helm-aif (get-text-property (point) 'helm-realvalue)
+ (progn (helm-moccur-goto-line it) (helm-match-line-cleanup-pulse))))
+
+(defun helm-moccur-mode-goto-line-ow ()
+ (interactive)
+ (helm-aif (get-text-property (point) 'helm-realvalue)
+ (progn (helm-moccur-goto-line-ow it) (helm-match-line-cleanup-pulse))))
+
+(defun helm-moccur-mode-goto-line-ow-forward-1 (arg)
+ (condition-case nil
+ (progn
+ (save-selected-window
+ (helm-moccur-mode-goto-line-ow)
+ (recenter))
+ (forward-line arg))
+ (error nil)))
+
+(defun helm-moccur-mode-goto-line-ow-forward ()
+ (interactive)
+ (helm-moccur-mode-goto-line-ow-forward-1 1))
+
+(defun helm-moccur-mode-goto-line-ow-backward ()
+ (interactive)
+ (helm-moccur-mode-goto-line-ow-forward-1 -1))
+
+(defun helm-moccur-save-results (_candidate)
+ "Save helm moccur results in a `helm-moccur-mode' buffer."
+ (let ((buf "*hmoccur*")
+ new-buf)
+ (when (get-buffer buf)
+ (setq new-buf (helm-read-string "OccurBufferName: " buf))
+ (cl-loop for b in (helm-buffer-list)
+ when (and (string= new-buf b)
+ (not (y-or-n-p
+ (format "Buffer `%s' already exists overwrite? "
+ new-buf))))
+ do (setq new-buf (helm-read-string "OccurBufferName: " "*hmoccur ")))
+ (setq buf new-buf))
+ (with-current-buffer (get-buffer-create buf)
+ (setq buffer-read-only t)
+ (let ((inhibit-read-only t)
+ (map (make-sparse-keymap)))
+ (erase-buffer)
+ (insert "-*- mode: helm-moccur -*-\n\n"
+ (format "Moccur Results for `%s':\n\n" helm-input))
+ (save-excursion
+ (insert (with-current-buffer helm-buffer
+ (goto-char (point-min)) (forward-line 1)
+ (buffer-substring (point) (point-max)))))
+ (save-excursion
+ (while (not (eobp))
+ (add-text-properties
+ (point-at-bol) (point-at-eol)
+ `(keymap ,map
+ help-echo ,(concat
+ (buffer-file-name
+ (get-buffer (get-text-property
+ (point) 'buffer-name)))
+ "\nmouse-1: set point\nmouse-2: jump to selection")
+ mouse-face highlight
+ invisible nil))
+ (define-key map [mouse-1] 'mouse-set-point)
+ (define-key map [mouse-2] 'helm-moccur-mode-mouse-goto-line)
+ (define-key map [mouse-3] 'ignore)
+ (forward-line 1))))
+ (helm-moccur-mode))
+ (pop-to-buffer buf)
+ (message "Helm Moccur Results saved in `%s' buffer" buf)))
+
+(defun helm-moccur-mode-mouse-goto-line (event)
+ (interactive "e")
+ (let* ((window (posn-window (event-end event)))
+ (pos (posn-point (event-end event))))
+ (with-selected-window window
+ (when (eq major-mode 'helm-moccur-mode)
+ (goto-char pos)
+ (helm-moccur-mode-goto-line)))))
+(put 'helm-moccur-mode-mouse-goto-line 'helm-only t)
+
+;;;###autoload
+(define-derived-mode helm-moccur-mode
+ special-mode "helm-moccur"
+ "Major mode to provide actions in helm moccur saved buffer.
+
+Special commands:
+\\{helm-moccur-mode-map}"
+ (set (make-local-variable 'helm-multi-occur-buffer-list)
+ (with-helm-buffer helm-multi-occur-buffer-list))
+ (set (make-local-variable 'revert-buffer-function)
+ #'helm-moccur-mode--revert-buffer-function))
+(put 'helm-moccur-mode 'helm-only t)
+
+(defun helm-moccur-mode--revert-buffer-function (&optional _ignore-auto _noconfirm)
+ (goto-char (point-min))
+ (let (pattern)
+ (when (re-search-forward "^Moccur Results for `\\(.*\\)'" nil t)
+ (setq pattern (match-string 1))
+ (forward-line 0)
+ (when (re-search-forward "^$" nil t)
+ (forward-line 1))
+ (let ((inhibit-read-only t)
+ (buffer (current-buffer))
+ (buflst helm-multi-occur-buffer-list)
+ (bsubstring (if helm-moccur-show-buffer-fontification
+ #'buffer-substring #'buffer-substring-no-properties)))
+ (delete-region (point) (point-max))
+ (message "Reverting buffer...")
+ (save-excursion
+ (with-temp-buffer
+ (insert
+ "\n"
+ (cl-loop for buf in buflst
+ for bufstr = (or (and (buffer-live-p (get-buffer buf))
+ (with-current-buffer buf
+ (funcall bsubstring
+ (point-min) (point-max))))
+ "")
+ unless (string= bufstr "")
+ do (add-text-properties
+ 0 (length bufstr)
+ `(buffer-name ,(buffer-name (get-buffer buf)))
+ bufstr)
+ concat bufstr)
+ "\n")
+ (goto-char (point-min))
+ (cl-loop with helm-pattern = pattern
+ while (helm-mm-search pattern)
+ for line = (helm-moccur-get-line (point-at-bol) (point-at-eol))
+ when line
+ do (with-current-buffer buffer
+ (insert
+ (propertize
+ (car (helm-moccur-filter-one-by-one line t))
+ 'helm-realvalue line)
+ "\n")))))
+ (message "Reverting buffer done")))))
+
+\f
+;;; Predefined commands
+;;
+;;
+
+;;;###autoload
+(defun helm-regexp ()
+ "Preconfigured helm to build regexps.
+`query-replace-regexp' can be run from there against found regexp."
+ (interactive)
+ (save-restriction
+ (when (and (helm-region-active-p)
+ ;; Don't narrow to region if buffer is already narrowed.
+ (not (helm-current-buffer-narrowed-p (current-buffer))))
+ (narrow-to-region (region-beginning) (region-end)))
+ (helm :sources helm-source-regexp
+ :buffer "*helm regexp*"
+ :prompt "Regexp: "
+ :history 'helm-build-regexp-history)))
+
+;;;###autoload
+(defun helm-occur ()
+ "Preconfigured helm for searching lines matching pattern in `current-buffer'.
+
+When `helm-source-occur' is member of
+`helm-sources-using-default-as-input' which is the default,
+symbol at point is searched at startup.
+
+When a region is marked search only in this region by narrowing.
+
+To search in multiples buffers start from one of the commands listing
+buffers (i.e. a helm command using `helm-source-buffers-list' like
+`helm-mini') and use the multi occur buffers action.
+
+This is the helm implementation that collect lines matching pattern
+like vanilla emacs `occur' but have nothing to do with it, the search
+engine beeing completely different."
+ (interactive)
+ (helm-occur-init-source)
+ (let ((bufs (list (buffer-name (current-buffer)))))
+ (helm-attrset 'moccur-buffers bufs helm-source-occur)
+ (helm-set-local-variable 'helm-multi-occur-buffer-list bufs)
+ (helm-set-local-variable
+ 'helm-multi-occur-buffer-tick
+ (cl-loop for b in bufs
+ collect (buffer-chars-modified-tick (get-buffer b)))))
+ (helm-set-local-variable 'helm-occur--invisible
+ (null helm-occur-show-buffer-name))
+ (save-restriction
+ (let (def pos)
+ (when (use-region-p)
+ ;; When user mark defun with `mark-defun' with intention of
+ ;; using helm-occur on this region, it is relevant to use the
+ ;; thing-at-point located at previous position which have been
+ ;; pushed to `mark-ring'.
+ (setq def (save-excursion
+ (goto-char (setq pos (car mark-ring)))
+ (helm-aif (thing-at-point 'symbol) (regexp-quote it))))
+ (narrow-to-region (region-beginning) (region-end)))
+ (unwind-protect
+ (helm :sources 'helm-source-occur
+ :buffer "*helm occur*"
+ :default (or def (helm-aif (thing-at-point 'symbol) (regexp-quote it)))
+ :history 'helm-occur-history
+ :preselect (and (memq 'helm-source-occur helm-sources-using-default-as-input)
+ (format "%s:%d:" (regexp-quote (buffer-name))
+ (line-number-at-pos (or pos (point)))))
+ :truncate-lines helm-moccur-truncate-lines)
+ (deactivate-mark t)))))
+
+;;;###autoload
+(defun helm-occur-from-isearch ()
+ "Invoke `helm-occur' from isearch."
+ (interactive)
+ (let ((input (if isearch-regexp
+ isearch-string
+ (regexp-quote isearch-string)))
+ (bufs (list (buffer-name (current-buffer)))))
+ (isearch-exit)
+ (helm-occur-init-source)
+ (helm-attrset 'moccur-buffers bufs helm-source-occur)
+ (helm-set-local-variable 'helm-multi-occur-buffer-list bufs)
+ (helm-set-local-variable
+ 'helm-multi-occur-buffer-tick
+ (cl-loop for b in bufs
+ collect (buffer-chars-modified-tick (get-buffer b))))
+ (helm-set-local-variable 'helm-occur--invisible
+ (null helm-occur-show-buffer-name))
+ (helm :sources 'helm-source-occur
+ :buffer "*helm occur*"
+ :history 'helm-occur-history
+ :input input
+ :truncate-lines helm-moccur-truncate-lines)))
+
+;;;###autoload
+(defun helm-multi-occur-from-isearch (&optional _arg)
+ "Invoke `helm-multi-occur' from isearch.
+
+With a prefix arg, reverse the behavior of
+`helm-moccur-always-search-in-current'.
+The prefix arg can be set before calling
+`helm-multi-occur-from-isearch' or during the buffer selection."
+ (interactive "p")
+ (let (buf-list
+ helm-moccur-always-search-in-current
+ (input (if isearch-regexp
+ isearch-string
+ (regexp-quote isearch-string))))
+ (isearch-exit)
+ (setq buf-list (helm-comp-read "Buffers: "
+ (helm-buffer-list)
+ :name "Occur in buffer(s)"
+ :marked-candidates t))
+ (setq helm-moccur-always-search-in-current
+ (if (or current-prefix-arg
+ helm-current-prefix-arg)
+ (not helm-moccur-always-search-in-current)
+ helm-moccur-always-search-in-current))
+ (helm-multi-occur-1 buf-list input)))
+
+
+(provide 'helm-regexp)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-regexp.el ends here
--- /dev/null
+;;; helm-ring.el --- kill-ring, mark-ring, and register browsers for helm. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'helm)
+(require 'helm-utils)
+(require 'helm-help)
+(require 'helm-elisp)
+
+(declare-function undo-tree-restore-state-from-register "ext:undo-tree.el" (register))
+
+\f
+(defgroup helm-ring nil
+ "Ring related Applications and libraries for Helm."
+ :group 'helm)
+
+(defcustom helm-kill-ring-threshold 3
+ "Minimum length of a candidate to be listed by `helm-source-kill-ring'."
+ :type 'integer
+ :group 'helm-ring)
+
+(defcustom helm-kill-ring-max-offset 400
+ "Max number of chars displayed per candidate in kill-ring browser.
+When `t', don't truncate candidate, show all.
+By default it is approximatively the number of bits contained in five lines
+of 80 chars each i.e 80*5.
+Note that if you set this to nil multiline will be disabled, i.e you
+will not have anymore separators between candidates."
+ :type '(choice (const :tag "Disabled" t)
+ (integer :tag "Max candidate offset"))
+ :group 'helm-ring)
+
+(defcustom helm-kill-ring-actions
+ '(("Yank marked" . helm-kill-ring-action-yank)
+ ("Delete marked" . helm-kill-ring-action-delete))
+ "List of actions for kill ring source."
+ :group 'helm-ring
+ :type '(alist :key-type string :value-type function))
+
+(defcustom helm-kill-ring-separator "\n"
+ "The separator used to separate marked candidates when yanking."
+ :group 'helm-ring
+ :type 'string)
+
+(defcustom helm-register-max-offset 160
+ "Max size of string register entries before truncating."
+ :group 'helm-ring
+ :type 'integer)
+\f
+;;; Kill ring
+;;
+;;
+(defvar helm-kill-ring-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map helm-map)
+ (define-key map (kbd "M-y") 'helm-next-line)
+ (define-key map (kbd "M-u") 'helm-previous-line)
+ (define-key map (kbd "M-D") 'helm-kill-ring-delete)
+ (define-key map (kbd "C-]") 'helm-kill-ring-toggle-truncated)
+ (define-key map (kbd "C-c C-k") 'helm-kill-ring-kill-selection)
+ map)
+ "Keymap for `helm-show-kill-ring'.")
+
+(defvar helm-source-kill-ring
+ (helm-build-sync-source "Kill Ring"
+ :init (lambda ()
+ (helm-attrset 'last-command last-command)
+ (helm-attrset 'multiline helm-kill-ring-max-offset))
+ :candidates #'helm-kill-ring-candidates
+ :filtered-candidate-transformer #'helm-kill-ring-transformer
+ :action 'helm-kill-ring-actions
+ :persistent-action 'ignore
+ :help-message 'helm-kill-ring-help-message
+ :persistent-help "DoNothing"
+ :keymap helm-kill-ring-map
+ :migemo t
+ :multiline 'helm-kill-ring-max-offset
+ :group 'helm-ring)
+ "Source for browse and insert contents of kill-ring.")
+
+(defun helm-kill-ring-candidates ()
+ (cl-loop for kill in (helm-fast-remove-dups kill-ring :test 'equal)
+ unless (or (< (length kill) helm-kill-ring-threshold)
+ (string-match "\\`[\n[:blank:]]+\\'" kill))
+ collect kill))
+
+(defun helm-kill-ring-transformer (candidates _source)
+ "Ensure CANDIDATES are not read-only."
+ (cl-loop for i in candidates
+ when (get-text-property 0 'read-only i)
+ do (set-text-properties 0 (length i) '(read-only nil) i)
+ collect i))
+
+(defvar helm-kill-ring--truncated-flag nil)
+(defun helm-kill-ring-toggle-truncated ()
+ "Toggle truncated view of candidates in helm kill-ring browser."
+ (interactive)
+ (with-helm-alive-p
+ (setq helm-kill-ring--truncated-flag (not helm-kill-ring--truncated-flag))
+ (let* ((cur-cand (helm-get-selection))
+ (presel-fn (lambda ()
+ (helm-kill-ring--preselect-fn cur-cand))))
+ (helm-attrset 'multiline
+ (if helm-kill-ring--truncated-flag
+ 15000000
+ helm-kill-ring-max-offset))
+ (helm-update presel-fn))))
+(put 'helm-kill-ring-toggle-truncated 'helm-only t)
+
+(defun helm-kill-ring-kill-selection ()
+ "Store the real value of candidate in kill-ring.
+Same as `helm-kill-selection-and-quit' called with a prefix arg."
+ (interactive)
+ (helm-kill-selection-and-quit t))
+(put 'helm-kill-ring-kill-selection 'helm-only t)
+
+(defun helm-kill-ring--preselect-fn (candidate)
+ "Internal, used to preselect CANDIDATE when toggling truncated view."
+ ;; Preselection by regexp may not work if candidate is huge, so walk
+ ;; the helm buffer until selection is on CANDIDATE.
+ (helm-awhile (condition-case-unless-debug nil
+ (and (not (helm-pos-header-line-p))
+ (helm-get-selection))
+ (error nil))
+ (if (string= it candidate)
+ (cl-return)
+ (helm-next-line))))
+
+(defun helm-kill-ring-action-yank (_str)
+ "Insert concatenated marked candidates in current-buffer.
+
+When two prefix args are given prompt to choose separator, otherwise
+use `helm-kill-ring-separator' as default."
+ (let ((marked (helm-marked-candidates))
+ (sep (if (equal helm-current-prefix-arg '(16))
+ (read-string "Separator: ")
+ helm-kill-ring-separator)))
+ (helm-kill-ring-action-yank-1
+ (cl-loop for c in (butlast marked)
+ concat (concat c sep) into str
+ finally return (concat str (car (last marked)))))))
+
+(defun helm-kill-ring-action-yank-1 (str)
+ "Insert STR in `kill-ring' and set STR to the head.
+
+When called with a prefix arg, point and mark are exchanged without
+activating region.
+If this action is executed just after `yank',
+replace with STR as yanked string."
+ (let ((yank-fn (lambda (&optional before yank-pop)
+ (insert-for-yank str)
+ ;; Set the window start back where it was in
+ ;; the yank command, if possible.
+ (when yank-pop
+ (set-window-start (selected-window) yank-window-start t))
+ (when (or (equal helm-current-prefix-arg '(4)) before)
+ ;; Same as exchange-point-and-mark but without
+ ;; activating region.
+ (goto-char (prog1 (mark t)
+ (set-marker (mark-marker)
+ (point)
+ helm-current-buffer)))))))
+ ;; Prevent inserting and saving highlighted items.
+ (set-text-properties 0 (length str) nil str)
+ (with-helm-current-buffer
+ (unwind-protect
+ (progn
+ (setq kill-ring (delete str kill-ring))
+ ;; Adding a `delete-selection' property
+ ;; to `helm-kill-ring-action' is not working
+ ;; because `this-command' will be `helm-maybe-exit-minibuffer',
+ ;; so use this workaround (Issue #1520).
+ (when (and (region-active-p) delete-selection-mode)
+ (delete-region (region-beginning) (region-end)))
+ (if (not (eq (helm-attr 'last-command helm-source-kill-ring) 'yank))
+ (progn
+ ;; Ensure mark is at beginning of inserted text.
+ (push-mark)
+ ;; When yanking in a helm minibuffer we need a small
+ ;; delay to detect the mark in previous minibuffer. [1]
+ (run-with-timer 0.01 nil yank-fn))
+ ;; from `yank-pop'
+ (let ((inhibit-read-only t)
+ (before (< (point) (mark t))))
+ (if before
+ (funcall (or yank-undo-function 'delete-region) (point) (mark t))
+ (funcall (or yank-undo-function 'delete-region) (mark t) (point)))
+ (setq yank-undo-function nil)
+ (set-marker (mark-marker) (point) helm-current-buffer)
+ ;; Same as [1] but use the same mark and point as in
+ ;; the initial yank according to BEFORE even if no
+ ;; prefix arg is given.
+ (run-with-timer 0.01 nil yank-fn before 'pop))))
+ (kill-new str)))))
+(define-obsolete-function-alias 'helm-kill-ring-action 'helm-kill-ring-action-yank "2.4.0")
+
+(defun helm-kill-ring-action-delete (_candidate)
+ "Delete marked candidates from `kill-ring'."
+ (cl-loop for c in (helm-marked-candidates)
+ do (setq kill-ring
+ (delete c kill-ring))))
+
+(defun helm-kill-ring-delete ()
+ "Delete marked candidates from `kill-ring'.
+
+This is a command for `helm-kill-ring-map'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action 'helm-kill-ring-action-delete)))
+
+\f
+;;;; <Mark ring>
+;; DO NOT use these sources with other sources use
+;; the commands `helm-mark-ring', `helm-global-mark-ring' or
+;; `helm-all-mark-rings' instead.
+
+(defun helm-mark-ring-line-string-at-pos (pos)
+ "Return line string at position POS."
+ (save-excursion
+ (goto-char pos)
+ (forward-line 0)
+ (let ((line (car (split-string (thing-at-point 'line) "[\n\r]"))))
+ (remove-text-properties 0 (length line) '(read-only) line)
+ (if (string= "" line)
+ "<EMPTY LINE>"
+ line))))
+
+(defun helm-mark-ring-get-candidates ()
+ (with-helm-current-buffer
+ (cl-loop with marks = (if (mark t)
+ (cons (mark-marker) mark-ring)
+ mark-ring)
+ for marker in marks
+ with max-line-number = (line-number-at-pos (point-max))
+ with width = (length (number-to-string max-line-number))
+ for m = (format (concat "%" (number-to-string width) "d: %s")
+ (line-number-at-pos marker)
+ (helm-mark-ring-line-string-at-pos marker))
+ unless (and recip (assoc m recip))
+ collect (cons m marker) into recip
+ finally return recip)))
+
+(defun helm-mark-ring-default-action (candidate)
+ (let ((target (copy-marker candidate)))
+ (helm-aif (marker-buffer candidate)
+ (progn
+ (switch-to-buffer it)
+ (helm-log-run-hook 'helm-goto-line-before-hook)
+ (helm-match-line-cleanup)
+ (with-helm-current-buffer
+ (unless helm-yank-point (setq helm-yank-point (point))))
+ (helm-goto-char target)
+ (helm-highlight-current-line))
+ ;; marker points to no buffer, no need to dereference it, just
+ ;; delete it.
+ (setq mark-ring (delete target mark-ring))
+ (error "Marker points to no buffer"))))
+
+(defvar helm-source-mark-ring
+ (helm-build-sync-source "mark-ring"
+ :candidates #'helm-mark-ring-get-candidates
+ :action '(("Goto line" . helm-mark-ring-default-action))
+ :persistent-help "Show this line"
+ :group 'helm-ring))
+
+;;; Global-mark-ring
+(defvar helm-source-global-mark-ring
+ (helm-build-sync-source "global-mark-ring"
+ :candidates #'helm-global-mark-ring-get-candidates
+ :action '(("Goto line" . helm-mark-ring-default-action))
+ :persistent-help "Show this line"
+ :group 'helm-ring))
+
+(defun helm-global-mark-ring-format-buffer (marker)
+ (with-current-buffer (marker-buffer marker)
+ (goto-char marker)
+ (forward-line 0)
+ (let ((line (pcase (thing-at-point 'line)
+ ((and line (pred stringp)
+ (guard (not (string-match-p "\\`\n?\\'" line))))
+ (car (split-string line "[\n\r]")))
+ (_ "<EMPTY LINE>"))))
+ (remove-text-properties 0 (length line) '(read-only) line)
+ (format "%7d:%s: %s"
+ (line-number-at-pos) (marker-buffer marker) line))))
+
+(defun helm-global-mark-ring-get-candidates ()
+ (let ((marks global-mark-ring))
+ (when marks
+ (cl-loop for marker in marks
+ for mb = (marker-buffer marker)
+ for gm = (unless (or (string-match "^ " (format "%s" mb))
+ (null mb))
+ (helm-global-mark-ring-format-buffer marker))
+ when (and gm (not (assoc gm recip)))
+ collect (cons gm marker) into recip
+ finally return recip))))
+\f
+;;;; <Register>
+;;; Insert from register
+(defvar helm-source-register
+ (helm-build-sync-source "Registers"
+ :candidates #'helm-register-candidates
+ :action-transformer #'helm-register-action-transformer
+ :persistent-help ""
+ :multiline t
+ :action '(("Delete Register(s)" .
+ (lambda (_candidate)
+ (cl-loop for candidate in (helm-marked-candidates)
+ for register = (car candidate)
+ do (setq register-alist
+ (delq (assoc register register-alist)
+ register-alist))))))
+ :group 'helm-ring)
+ "See (info \"(emacs)Registers\")")
+
+(defun helm-register-candidates ()
+ "Collecting register contents and appropriate commands."
+ (cl-loop for (char . val) in register-alist
+ for key = (single-key-description char)
+ for string-actions =
+ (cond
+ ((numberp val)
+ (list (int-to-string val)
+ 'insert-register
+ 'increment-register))
+ ((markerp val)
+ (let ((buf (marker-buffer val)))
+ (if (null buf)
+ (list "a marker in no buffer")
+ (list (concat
+ "a buffer position:"
+ (buffer-name buf)
+ ", position "
+ (int-to-string (marker-position val)))
+ 'jump-to-register
+ 'insert-register))))
+ ((and (consp val) (window-configuration-p (car val)))
+ (list "window configuration."
+ 'jump-to-register))
+ ((and (vectorp val)
+ (fboundp 'undo-tree-register-data-p)
+ (undo-tree-register-data-p (elt val 1)))
+ (list
+ "Undo-tree entry."
+ 'undo-tree-restore-state-from-register))
+ ((or (and (vectorp val) (eq 'registerv (aref val 0)))
+ (and (consp val) (frame-configuration-p (car val))))
+ (list "frame configuration."
+ 'jump-to-register))
+ ((and (consp val) (eq (car val) 'file))
+ (list (concat "file:"
+ (prin1-to-string (cdr val))
+ ".")
+ 'jump-to-register))
+ ((and (consp val) (eq (car val) 'file-query))
+ (list (concat "file:a file-query reference: file "
+ (car (cdr val))
+ ", position "
+ (int-to-string (car (cdr (cdr val))))
+ ".")
+ 'jump-to-register))
+ ((consp val)
+ (let ((lines (format "%4d" (length val))))
+ (list (format "%s: %s\n" lines
+ (truncate-string-to-width
+ (mapconcat 'identity (list (car val))
+ "^J") (- (window-width) 15)))
+ 'insert-register)))
+ ((stringp val)
+ (list
+ ;; without properties
+ (concat (substring-no-properties
+ val 0 (min (length val) helm-register-max-offset))
+ (if (> (length val) helm-register-max-offset)
+ "[...]" ""))
+ 'insert-register
+ 'append-to-register
+ 'prepend-to-register)))
+ unless (null string-actions) ; Fix Issue #1107.
+ collect (cons (format "Register %3s:\n %s" key (car string-actions))
+ (cons char (cdr string-actions)))))
+
+(defun helm-register-action-transformer (actions register-and-functions)
+ "Decide actions by the contents of register."
+ (cl-loop with func-actions =
+ '((insert-register
+ "Insert Register" .
+ (lambda (c) (insert-register (car c))))
+ (jump-to-register
+ "Jump to Register" .
+ (lambda (c) (jump-to-register (car c))))
+ (append-to-register
+ "Append Region to Register" .
+ (lambda (c) (append-to-register
+ (car c) (region-beginning) (region-end))))
+ (prepend-to-register
+ "Prepend Region to Register" .
+ (lambda (c) (prepend-to-register
+ (car c) (region-beginning) (region-end))))
+ (increment-register
+ "Increment Prefix Arg to Register" .
+ (lambda (c) (increment-register
+ helm-current-prefix-arg (car c))))
+ (undo-tree-restore-state-from-register
+ "Restore Undo-tree register" .
+ (lambda (c) (and (fboundp 'undo-tree-restore-state-from-register)
+ (undo-tree-restore-state-from-register (car c))))))
+ for func in (cdr register-and-functions)
+ when (assq func func-actions)
+ collect (cdr it) into transformer-actions
+ finally return (append transformer-actions actions)))
+
+;;;###autoload
+(defun helm-mark-ring ()
+ "Preconfigured `helm' for `helm-source-mark-ring'."
+ (interactive)
+ (helm :sources 'helm-source-mark-ring
+ :resume 'noresume
+ :buffer "*helm mark*"))
+
+;;;###autoload
+(defun helm-global-mark-ring ()
+ "Preconfigured `helm' for `helm-source-global-mark-ring'."
+ (interactive)
+ (helm :sources 'helm-source-global-mark-ring
+ :resume 'noresume
+ :buffer "*helm global mark*"))
+
+;;;###autoload
+(defun helm-all-mark-rings ()
+ "Preconfigured `helm' for `helm-source-global-mark-ring' and \
+`helm-source-mark-ring'."
+ (interactive)
+ (helm :sources '(helm-source-mark-ring
+ helm-source-global-mark-ring)
+ :resume 'noresume
+ :buffer "*helm mark ring*"))
+
+;;;###autoload
+(defun helm-register ()
+ "Preconfigured `helm' for Emacs registers."
+ (interactive)
+ (helm :sources 'helm-source-register
+ :resume 'noresume
+ :buffer "*helm register*"))
+
+;;;###autoload
+(defun helm-show-kill-ring ()
+ "Preconfigured `helm' for `kill-ring'.
+It is drop-in replacement of `yank-pop'.
+
+First call open the kill-ring browser, next calls move to next line."
+ (interactive)
+ (setq helm-kill-ring--truncated-flag nil)
+ (let ((enable-recursive-minibuffers t))
+ (helm :sources helm-source-kill-ring
+ :buffer "*helm kill ring*"
+ :resume 'noresume
+ :allow-nest t)))
+
+;;;###autoload
+(defun helm-execute-kmacro ()
+ "Preconfigured helm for keyboard macros.
+Define your macros with `f3' and `f4'.
+See (info \"(emacs) Keyboard Macros\") for detailed infos.
+This command is useful when used with persistent action."
+ (interactive)
+ (let ((helm-quit-if-no-candidate
+ (lambda () (message "No kbd macro has been defined"))))
+ (helm :sources
+ (helm-build-sync-source "Kmacro"
+ :candidates (lambda ()
+ (helm-fast-remove-dups
+ (cons (kmacro-ring-head)
+ kmacro-ring)
+ :test 'equal))
+ :multiline t
+ :candidate-transformer
+ (lambda (candidates)
+ (cl-loop for c in candidates collect
+ (propertize (help-key-description (car c) nil)
+ 'helm-realvalue c)))
+ :persistent-help "Execute kmacro"
+ :help-message 'helm-kmacro-help-message
+ :action
+ (helm-make-actions
+ "Execute kmacro (`C-u <n>' to execute <n> times)"
+ 'helm-kbd-macro-execute
+ "Concat marked macros"
+ 'helm-kbd-macro-concat-macros
+ "Delete marked macros"
+ 'helm-kbd-macro-delete-macro
+ "Edit marked macro"
+ 'helm-kbd-macro-edit-macro)
+ :group 'helm-ring)
+ :buffer "*helm kmacro*")))
+
+(defun helm-kbd-macro-execute (candidate)
+ ;; Move candidate on top of list for next use.
+ (setq kmacro-ring (delete candidate kmacro-ring))
+ (kmacro-push-ring)
+ (kmacro-split-ring-element candidate)
+ (kmacro-exec-ring-item
+ candidate helm-current-prefix-arg))
+
+(defun helm-kbd-macro-concat-macros (_candidate)
+ (let ((mkd (helm-marked-candidates)))
+ (when (cdr mkd)
+ (kmacro-push-ring)
+ (setq last-kbd-macro
+ (mapconcat 'identity
+ (cl-loop for km in mkd
+ if (vectorp km)
+ append (cl-loop for k across km collect
+ (key-description (vector k)))
+ into result
+ else collect (car km) into result
+ finally return result)
+ "")))))
+
+(defun helm-kbd-macro-delete-macro (_candidate)
+ (let ((mkd (helm-marked-candidates)))
+ (kmacro-push-ring)
+ (cl-loop for km in mkd
+ do (setq kmacro-ring (delete km kmacro-ring)))
+ (kmacro-pop-ring1)))
+
+(defun helm-kbd-macro-edit-macro (candidate)
+ (kmacro-push-ring)
+ (setq kmacro-ring (delete candidate kmacro-ring))
+ (kmacro-split-ring-element candidate)
+ (kmacro-edit-macro))
+
+(provide 'helm-ring)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-ring.el ends here
--- /dev/null
+;;; helm-semantic.el --- Helm interface for Semantic -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 ~ 2017 Daniel Hackney <danNOSPAMhaxney.org>
+;; 2012 ~ 2018 Thierry Volpiatto<thierry.volpiattoNOSPAMgmail.com>
+
+;; Author: Daniel Hackney <danNOSPAMhaxney.org>
+
+;; 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/>.
+
+;;; Commentary:
+
+;; Uses `candidates-in-buffer' for speed.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'semantic)
+(require 'helm-help)
+(require 'helm-imenu)
+
+(declare-function pulse-momentary-highlight-one-line "pulse.el" (point &optional face))
+
+(defgroup helm-semantic nil
+ "Semantic tags related libraries and applications for helm."
+ :group 'helm)
+
+(defcustom helm-semantic-lynx-style-map t
+ "Use Arrow keys to jump to occurences."
+ :group 'helm-semantic
+ :type 'boolean)
+
+(defcustom helm-semantic-display-style
+ '((python-mode . semantic-format-tag-summarize)
+ (c-mode . semantic-format-tag-concise-prototype-c-mode)
+ (emacs-lisp-mode . semantic-format-tag-abbreviate-emacs-lisp-mode))
+ "Function to present a semantic tag according to `major-mode'.
+
+It is an alist where the `car' of each element is a `major-mode' and
+the `cdr' a `semantic-format-tag-*' function.
+
+If no function is found for current `major-mode', fall back to
+`semantic-format-tag-summarize' default function.
+
+You can have more or less informations depending of the `semantic-format-tag-*'
+function you choose.
+
+All the supported functions are prefixed with \"semantic-format-tag-\",
+you have completion on these functions with `C-M i' in the customize interface."
+ :group 'helm-semantic
+ :type '(alist :key-type symbol :value-type symbol))
+
+;;; keymap
+(defvar helm-semantic-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map helm-map)
+ (when helm-semantic-lynx-style-map
+ (define-key map (kbd "<left>") 'helm-maybe-exit-minibuffer)
+ (define-key map (kbd "<right>") 'helm-execute-persistent-action))
+ (delq nil map)))
+
+;; Internals vars
+(defvar helm-semantic--tags-cache nil)
+
+(defun helm-semantic--fetch-candidates (tags depth &optional class)
+ "Write the contents of TAGS to the current buffer."
+ (let ((class class) cur-type
+ (stylefn (or (with-helm-current-buffer
+ (assoc-default major-mode helm-semantic-display-style))
+ #'semantic-format-tag-summarize)))
+ (cl-dolist (tag tags)
+ (when (listp tag)
+ (cl-case (setq cur-type (semantic-tag-class tag))
+ ((function variable type)
+ (let ((spaces (make-string (* depth 2) ?\s))
+ (type-p (eq cur-type 'type)))
+ (unless (and (> depth 0) (not type-p))
+ (setq class nil))
+ (insert
+ (if (and class (not type-p))
+ (format "%s%s(%s) "
+ spaces (if (< depth 2) "" "├►") class)
+ spaces)
+ ;; Save the tag for later
+ (propertize (funcall stylefn tag nil t)
+ 'semantic-tag tag)
+ "\n")
+ (and type-p (setq class (car tag)))
+ ;; Recurse to children
+ (unless (eq cur-type 'function)
+ (helm-semantic--fetch-candidates
+ (semantic-tag-components tag) (1+ depth) class))))
+
+ ;; Don't do anything with packages or includes for now
+ ((package include)
+ (insert
+ (propertize (funcall stylefn tag nil t)
+ 'semantic-tag tag)
+ "\n")
+ )
+ ;; Catch-all
+ (t))))))
+
+(defun helm-semantic-default-action (_candidate &optional persistent)
+ ;; By default, helm doesn't pass on the text properties of the selection.
+ ;; Fix this.
+ (helm-log-run-hook 'helm-goto-line-before-hook)
+ (with-current-buffer helm-buffer
+ (when (looking-at " ")
+ (goto-char (next-single-property-change
+ (point-at-bol) 'semantic-tag nil (point-at-eol))))
+ (let ((tag (get-text-property (point) 'semantic-tag)))
+ (semantic-go-to-tag tag)
+ (unless persistent
+ (pulse-momentary-highlight-one-line (point))))))
+
+(defun helm-semantic--maybe-set-needs-update ()
+ (with-helm-current-buffer
+ (when (semantic-parse-tree-needs-update-p)
+ (semantic-parse-tree-set-needs-update))))
+
+(defvar helm-source-semantic nil)
+
+(defclass helm-semantic-source (helm-source-in-buffer)
+ ((init :initform (lambda ()
+ (helm-semantic--maybe-set-needs-update)
+ (setq helm-semantic--tags-cache (semantic-fetch-tags))
+ (with-current-buffer (helm-candidate-buffer 'global)
+ (let ((major-mode (with-helm-current-buffer major-mode)))
+ (helm-semantic--fetch-candidates helm-semantic--tags-cache 0)))))
+ (get-line :initform 'buffer-substring)
+ (persistent-help :initform "Show this entry")
+ (keymap :initform 'helm-semantic-map)
+ (help-message :initform 'helm-semantic-help-message)
+ (persistent-action :initform (lambda (elm)
+ (helm-semantic-default-action elm t)
+ (helm-highlight-current-line)))
+ (action :initform 'helm-semantic-default-action)))
+
+(defcustom helm-semantic-fuzzy-match nil
+ "Enable fuzzy matching in `helm-source-semantic'."
+ :group 'helm-semantic
+ :type 'boolean
+ :set (lambda (var val)
+ (set var val)
+ (setq helm-source-semantic
+ (helm-make-source "Semantic Tags" 'helm-semantic-source
+ :fuzzy-match helm-semantic-fuzzy-match))))
+
+;;;###autoload
+(defun helm-semantic (arg)
+ "Preconfigured `helm' for `semantic'.
+If ARG is supplied, pre-select symbol at point instead of current"
+ (interactive "P")
+ (let ((tag (helm-aif (car (semantic-current-tag-parent))
+ (let ((curtag (car (semantic-current-tag))))
+ (if (string= it curtag)
+ (format "\\_<%s\\_>" curtag)
+ (cons (format "\\_<%s\\_>" it)
+ (format "\\_<%s\\_>" curtag))))
+ (format "\\_<%s\\_>" (car (semantic-current-tag))))))
+ (unless helm-source-semantic
+ (setq helm-source-semantic
+ (helm-make-source "Semantic Tags" 'helm-semantic-source
+ :fuzzy-match helm-semantic-fuzzy-match)))
+ (helm :sources 'helm-source-semantic
+ :candidate-number-limit 9999
+ :preselect (if arg
+ (thing-at-point 'symbol)
+ tag)
+ :buffer "*helm semantic*")))
+
+;;;###autoload
+(defun helm-semantic-or-imenu (arg)
+ "Preconfigured helm for `semantic' or `imenu'.
+If ARG is supplied, pre-select symbol at point instead of current
+semantic tag in scope.
+
+If `semantic-mode' is active in the current buffer, then use
+semantic for generating tags, otherwise fall back to `imenu'.
+Fill in the symbol at point by default."
+ (interactive "P")
+ (unless helm-source-semantic
+ (setq helm-source-semantic
+ (helm-make-source "Semantic Tags" 'helm-semantic-source
+ :fuzzy-match helm-semantic-fuzzy-match)))
+ (unless helm-source-imenu
+ (setq helm-source-imenu
+ (helm-make-source "Imenu" 'helm-imenu-source
+ :fuzzy-match helm-imenu-fuzzy-match)))
+ (let* ((source (if (semantic-active-p)
+ 'helm-source-semantic
+ 'helm-source-imenu))
+ (imenu-p (eq source 'helm-source-imenu))
+ (imenu-auto-rescan imenu-p)
+ (str (thing-at-point 'symbol))
+ (helm-execute-action-at-once-if-one
+ (and imenu-p
+ helm-imenu-execute-action-at-once-if-one))
+ (tag (helm-aif (car (semantic-current-tag-parent))
+ (let ((curtag (car (semantic-current-tag))))
+ (if (string= it curtag)
+ (format "\\_<%s\\_>" curtag)
+ (cons (format "\\_<%s\\_>" it)
+ (format "\\_<%s\\_>" curtag))))
+ (format "\\_<%s\\_>" (car (semantic-current-tag))))))
+ (helm :sources source
+ :candidate-number-limit 9999
+ :default (and imenu-p (list (concat "\\_<" (and str (regexp-quote str)) "\\_>") str))
+ :preselect (if (or arg imenu-p) str tag)
+ :buffer "*helm semantic/imenu*")))
+
+(provide 'helm-semantic)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-semantic.el ends here
--- /dev/null
+;;; helm-sys.el --- System related functions for helm. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'helm)
+(require 'helm-help)
+(require 'helm-utils)
+
+\f
+(defgroup helm-sys nil
+ "System related helm library."
+ :group 'helm)
+
+(defface helm-top-columns
+ '((t :inherit helm-header))
+ "Face for helm help string in minibuffer."
+ :group 'helm-sys)
+
+\f
+(defcustom helm-top-command
+ (cl-case system-type
+ (darwin "env COLUMNS=%s ps -axo pid,user,pri,nice,ucomm,tty,start_time,vsz,%%cpu,%%mem,etime,command")
+ (t "env COLUMNS=%s top -b -n 1"))
+ "Top command used to display output of top.
+A format string where %s will be replaced with `frame-width'.
+
+To use 'top' command, a version supporting batch mode (-b option) is needed.
+On Mac OSX 'top' command doesn't support this, so ps command
+is used instead by default.
+Normally 'top' command output have 12 columns, but in some versions you may
+have less than this, so you can either customize top to use 12 columns with the
+interactives 'f' and 'W' commands of top, or modify
+`helm-top-sort-columns-alist' to fit with the number of columns
+your 'top' command is using.
+
+If you modify 'ps' command be sure that 'pid' comes in first
+and \"env COLUMNS=%s\" is specified at beginning of command.
+Ensure also that no elements contain spaces (e.g use start_time and not start).
+Same as for 'top' you can customize `helm-top-sort-columns-alist' to make sort commands
+working properly according to your settings."
+ :group 'helm-sys
+ :type 'string)
+
+(defcustom helm-top-sort-columns-alist '((com . 11)
+ (mem . 9)
+ (cpu . 8)
+ (user . 1))
+ "Allow defining which column to use when sorting output of top/ps command.
+Only com, mem, cpu and user are sorted, so no need to put something else there,
+it will have no effect.
+Note that column numbers are counted from zero, i.e column 1 is the nth 0 column."
+ :group 'helm-sys
+ :type '(alist :key-type symbol :value-type (integer :tag "Column number")))
+
+(defcustom helm-top-poll-delay 1.5
+ "Helm top poll after this delay when `helm-top-poll-mode' is enabled.
+The minimal delay allowed is 1.5, if less than this helm-top will use 1.5."
+ :group 'helm-sys
+ :type 'float)
+
+(defcustom helm-top-poll-delay-post-command 1.0
+ "Helm top stop polling during this delay.
+This delay is additioned to `helm-top-poll-delay' after emacs stop
+being idle."
+ :group 'helm-sys
+ :type 'float)
+
+(defcustom helm-top-poll-preselection 'linum
+ "Stay on same line or follow candidate when `helm-top-poll' update display.
+Possible values are 'candidate or 'linum.
+This affect also sorting functions in the same way."
+ :group'helm-sys
+ :type '(radio :tag "Preferred preselection action for helm-top"
+ (const :tag "Follow candidate" candidate)
+ (const :tag "Stay on same line" linum)))
+\f
+;;; Top (process)
+;;
+;;
+(defvar helm-top-sort-fn nil)
+(defvar helm-top-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map helm-map)
+ (define-key map (kbd "M-P") 'helm-top-run-sort-by-cpu)
+ (define-key map (kbd "M-C") 'helm-top-run-sort-by-com)
+ (define-key map (kbd "M-M") 'helm-top-run-sort-by-mem)
+ (define-key map (kbd "M-U") 'helm-top-run-sort-by-user)
+ map))
+
+(defvar helm-top-after-init-hook nil
+ "Local hook for helm-top.")
+
+(defvar helm-top--poll-timer nil)
+
+(defun helm-top-poll (&optional no-update delay)
+ (when helm-top--poll-timer
+ (cancel-timer helm-top--poll-timer))
+ (condition-case nil
+ (progn
+ (when (and (helm--alive-p) (null no-update))
+ ;; Fix quitting while process is running
+ ;; by binding `with-local-quit' in init function
+ ;; Issue #1521.
+ (helm-force-update
+ (cl-ecase helm-top-poll-preselection
+ (candidate (replace-regexp-in-string
+ "[0-9]+" "[0-9]+"
+ (regexp-quote (helm-get-selection nil t))))
+ (linum `(lambda ()
+ (goto-char (point-min))
+ (forward-line ,(helm-candidate-number-at-point)))))))
+ (setq helm-top--poll-timer
+ (run-with-idle-timer
+ (helm-aif (current-idle-time)
+ (time-add it (seconds-to-time
+ (or delay (helm-top--poll-delay))))
+ (or delay (helm-top--poll-delay)))
+ nil
+ 'helm-top-poll)))
+ (quit (cancel-timer helm-top--poll-timer))))
+
+(defun helm-top--poll-delay ()
+ (max 1.5 helm-top-poll-delay))
+
+(defun helm-top-poll-no-update ()
+ (helm-top-poll t (+ (helm-top--poll-delay)
+ helm-top-poll-delay-post-command)))
+
+(defun helm-top-initialize-poll-hooks ()
+ ;; When emacs is idle during say 20s
+ ;; the idle timer will run in 20+1.5 s.
+ ;; This is fine when emacs stays idle, because the next timer
+ ;; will run at 21.5+1.5 etc... so the display will be updated
+ ;; at every 1.5 seconds.
+ ;; But as soon as emacs looses its idleness, the next update
+ ;; will occur at say 21+1.5 s, so we have to reinitialize
+ ;; the timer at 0+1.5.
+ (add-hook 'post-command-hook 'helm-top-poll-no-update)
+ (add-hook 'focus-in-hook 'helm-top-poll-no-update))
+
+;;;###autoload
+(define-minor-mode helm-top-poll-mode
+ "Refresh automatically helm top buffer once enabled."
+ :group 'helm-top
+ :global t
+ (if helm-top-poll-mode
+ (progn
+ (add-hook 'helm-top-after-init-hook 'helm-top-poll-no-update)
+ (add-hook 'helm-top-after-init-hook 'helm-top-initialize-poll-hooks))
+ (remove-hook 'helm-top-after-init-hook 'helm-top-poll-no-update)
+ (remove-hook 'helm-top-after-init-hook 'helm-top-initialize-poll-hooks)))
+
+(defvar helm-source-top
+ (helm-build-in-buffer-source "Top"
+ :header-name (lambda (name)
+ (concat name (if helm-top-poll-mode
+ " (auto updating)"
+ " (Press C-c C-u to refresh)")))
+ :init #'helm-top-init
+ :after-init-hook 'helm-top-after-init-hook
+ :cleanup (lambda ()
+ (when helm-top--poll-timer
+ (cancel-timer helm-top--poll-timer))
+ (remove-hook 'post-command-hook 'helm-top-poll-no-update)
+ (remove-hook 'focus-in-hook 'helm-top-poll-no-update))
+ :display-to-real #'helm-top-display-to-real
+ :persistent-action '(helm-top-sh-persistent-action . never-split)
+ :persistent-help "SIGTERM"
+ :help-message 'helm-top-help-message
+ :mode-line 'helm-top-mode-line
+ :follow 'never
+ :keymap helm-top-map
+ :filtered-candidate-transformer #'helm-top-sort-transformer
+ :action-transformer #'helm-top-action-transformer
+ :group 'helm-sys))
+
+(defvar helm-top--line nil)
+(defun helm-top-transformer (candidates _source)
+ "Transformer for `helm-top'.
+Return empty string for non--valid candidates."
+ (cl-loop for disp in candidates collect
+ (cond ((string-match "^ *[0-9]+" disp) disp)
+ ((string-match "^ *PID" disp)
+ (setq helm-top--line (cons (propertize disp 'face 'helm-top-columns) "")))
+ (t (cons disp "")))
+ into lst
+ finally return (or (member helm-top--line lst)
+ (cons helm-top--line lst))))
+
+(defun helm-top--skip-top-line ()
+ (let* ((src (helm-get-current-source))
+ (src-name (assoc-default 'name src)))
+ (helm-aif (and (stringp src-name)
+ (string= src-name "Top")
+ (helm-get-selection nil t src))
+ (when (string-match-p "^ *PID" it)
+ (helm-next-line)))))
+
+(defun helm-top-action-transformer (actions _candidate)
+ "Action transformer for `top'.
+Show actions only on line starting by a PID."
+ (let ((disp (helm-get-selection nil t)))
+ (cond ((string-match "\\` *[0-9]+" disp)
+ (list '("kill (SIGTERM)" . (lambda (_pid)
+ (helm-top-sh "TERM" (helm-top--marked-pids))))
+ '("kill (SIGKILL)" . (lambda (_pid)
+ (helm-top-sh "KILL" (helm-top--marked-pids))))
+ '("kill (SIGINT)" . (lambda (_pid)
+ (helm-top-sh "INT" (helm-top--marked-pids))))
+ '("kill (Choose signal)"
+ . (lambda (_pid)
+ (let ((pids (helm-top--marked-pids)))
+ (helm-top-sh
+ (helm-comp-read (format "Kill %d pids with signal: "
+ (length pids))
+ '("ALRM" "HUP" "INT" "KILL" "PIPE" "POLL"
+ "PROF" "TERM" "USR1" "USR2" "VTALRM"
+ "STKFLT" "PWR" "WINCH" "CHLD" "URG"
+ "TSTP" "TTIN" "TTOU" "STOP" "CONT"
+ "ABRT" "FPE" "ILL" "QUIT" "SEGV"
+ "TRAP" "SYS" "EMT" "BUS" "XCPU" "XFSZ")
+ :must-match t)
+ pids))))))
+ (t actions))))
+
+(defun helm-top--marked-pids ()
+ (helm-remove-if-not-match "\\`[0-9]+\\'" (helm-marked-candidates)))
+
+(defun helm-top-sh (sig pids)
+ "Run kill shell command with signal SIG on PIDS for `helm-top'."
+ (message "kill -%s %s exited with status %s"
+ sig (mapconcat 'identity pids " ")
+ (apply #'call-process
+ "kill" nil nil nil (format "-%s" sig) pids)))
+
+(defun helm-top-sh-persistent-action (pid)
+ (helm-top-sh "TERM" (list pid))
+ (helm-delete-current-selection))
+
+(defun helm-top-init ()
+ "Insert output of top command in candidate buffer."
+ (with-local-quit
+ (unless helm-top-sort-fn (helm-top-set-mode-line "CPU"))
+ (with-current-buffer (helm-candidate-buffer 'global)
+ (call-process-shell-command
+ (format helm-top-command (frame-width))
+ nil (current-buffer)))))
+
+(defun helm-top-display-to-real (line)
+ "Return pid only from LINE."
+ (car (split-string line)))
+
+;; Sort top command
+
+(defun helm-top-set-mode-line (str)
+ (if (string-match "Sort:\\[\\(.*\\)\\] " helm-top-mode-line)
+ (setq helm-top-mode-line (replace-match str nil nil helm-top-mode-line 1))
+ (setq helm-top-mode-line (concat (format "Sort:[%s] " str) helm-top-mode-line))))
+
+(defun helm-top-sort-transformer (candidates source)
+ (helm-top-transformer
+ (if helm-top-sort-fn
+ (cl-loop for c in candidates
+ if (string-match "^ *[0-9]+" c)
+ collect c into pid-cands
+ else collect c into header-cands
+ finally return (append
+ header-cands
+ (sort pid-cands helm-top-sort-fn)))
+ candidates)
+ source))
+
+(defun helm-top-sort-by-com (s1 s2)
+ (let* ((split-1 (split-string s1))
+ (split-2 (split-string s2))
+ (col (cdr (assq 'com helm-top-sort-columns-alist)))
+ (com-1 (nth col split-1))
+ (com-2 (nth col split-2)))
+ (string< com-1 com-2)))
+
+(defun helm-top-sort-by-mem (s1 s2)
+ (let* ((split-1 (split-string s1))
+ (split-2 (split-string s2))
+ (col (cdr (assq 'mem helm-top-sort-columns-alist)))
+ (mem-1 (string-to-number (nth col split-1)))
+ (mem-2 (string-to-number (nth col split-2))))
+ (> mem-1 mem-2)))
+
+(defun helm-top-sort-by-cpu (s1 s2)
+ (let* ((split-1 (split-string s1))
+ (split-2 (split-string s2))
+ (col (cdr (assq 'cpu helm-top-sort-columns-alist)))
+ (cpu-1 (string-to-number (nth col split-1)))
+ (cpu-2 (string-to-number (nth col split-2))))
+ (> cpu-1 cpu-2)))
+
+(defun helm-top-sort-by-user (s1 s2)
+ (let* ((split-1 (split-string s1))
+ (split-2 (split-string s2))
+ (col (cdr (assq 'user helm-top-sort-columns-alist)))
+ (user-1 (nth col split-1))
+ (user-2 (nth col split-2)))
+ (string< user-1 user-2)))
+
+(defun helm-top--preselect-fn ()
+ (if (eq helm-top-poll-preselection 'linum)
+ `(lambda ()
+ (goto-char (point-min))
+ (forward-line ,(helm-candidate-number-at-point)))
+ (replace-regexp-in-string
+ "[0-9]+" "[0-9]+"
+ (regexp-quote (helm-get-selection nil t)))))
+
+(defun helm-top-run-sort-by-com ()
+ (interactive)
+ (helm-top-set-mode-line "COM")
+ (setq helm-top-sort-fn 'helm-top-sort-by-com)
+ (helm-update (helm-top--preselect-fn)))
+
+(defun helm-top-run-sort-by-cpu ()
+ (interactive)
+ (helm-top-set-mode-line "CPU")
+ ;; Force sorting by CPU even if some versions of top are using by
+ ;; default CPU sorting (Issue #1908).
+ (setq helm-top-sort-fn 'helm-top-sort-by-cpu)
+ (helm-update (helm-top--preselect-fn)))
+
+(defun helm-top-run-sort-by-mem ()
+ (interactive)
+ (helm-top-set-mode-line "MEM")
+ (setq helm-top-sort-fn 'helm-top-sort-by-mem)
+ (helm-update (helm-top--preselect-fn)))
+
+(defun helm-top-run-sort-by-user ()
+ (interactive)
+ (helm-top-set-mode-line "USER")
+ (setq helm-top-sort-fn 'helm-top-sort-by-user)
+ (helm-update (helm-top--preselect-fn)))
+
+\f
+;;; X RandR resolution change
+;;
+;;
+;;; FIXME I do not care multi-display.
+
+(defun helm-xrandr-info ()
+ "Return a pair with current X screen number and current X display name."
+ (with-temp-buffer
+ (call-process "xrandr" nil (current-buffer) nil
+ "--current")
+ (let (screen output)
+ (goto-char (point-min))
+ (save-excursion
+ (when (re-search-forward "\\(^Screen \\)\\([0-9]\\):" nil t)
+ (setq screen (match-string 2))))
+ (when (re-search-forward "^\\(.*\\) connected" nil t)
+ (setq output (match-string 1)))
+ (list screen output))))
+
+(defun helm-xrandr-screen ()
+ "Return current X screen number."
+ (car (helm-xrandr-info)))
+
+(defun helm-xrandr-output ()
+ "Return current X display name."
+ (cadr (helm-xrandr-info)))
+
+(defvar helm-source-xrandr-change-resolution
+ (helm-build-sync-source "Change Resolution"
+ :candidates
+ (lambda ()
+ (with-temp-buffer
+ (call-process "xrandr" nil (current-buffer) nil
+ "--screen" (helm-xrandr-screen) "-q")
+ (goto-char 1)
+ (cl-loop while (re-search-forward " \\([0-9]+x[0-9]+\\)" nil t)
+ for mode = (match-string 1)
+ unless (member mode modes)
+ collect mode into modes
+ finally return modes)))
+ :action
+ (helm-make-actions "Change Resolution"
+ (lambda (mode)
+ (call-process "xrandr" nil nil nil
+ "--screen" (helm-xrandr-screen)
+ "--output" (helm-xrandr-output)
+ "--mode" mode)))))
+
+\f
+;;; Emacs process
+;;
+;;
+(defvar helm-source-emacs-process
+ (helm-build-sync-source "Emacs Process"
+ :init (lambda ()
+ (let (tabulated-list-use-header-line)
+ (list-processes--refresh)))
+ :candidates (lambda () (mapcar #'process-name (process-list)))
+ :persistent-action (lambda (elm)
+ (delete-process (get-process elm))
+ (helm-delete-current-selection))
+ :persistent-help "Kill Process"
+ :action (helm-make-actions "Kill Process"
+ (lambda (_elm)
+ (cl-loop for p in (helm-marked-candidates)
+ do (delete-process (get-process p)))))))
+
+\f
+;;;###autoload
+(defun helm-top ()
+ "Preconfigured `helm' for top command."
+ (interactive)
+ (add-hook 'helm-after-update-hook 'helm-top--skip-top-line)
+ (save-window-excursion
+ (unless helm-alive-p (delete-other-windows))
+ (unwind-protect
+ (helm :sources 'helm-source-top
+ :buffer "*helm top*" :full-frame t
+ :candidate-number-limit 9999
+ :preselect "^\\s-*[0-9]+"
+ :truncate-lines helm-show-action-window-other-window)
+ (remove-hook 'helm-after-update-hook 'helm-top--skip-top-line))))
+
+;;;###autoload
+(defun helm-list-emacs-process ()
+ "Preconfigured `helm' for emacs process."
+ (interactive)
+ (helm-other-buffer 'helm-source-emacs-process "*helm process*"))
+
+;;;###autoload
+(defun helm-xrandr-set ()
+ "Preconfigured helm for xrandr."
+ (interactive)
+ (helm :sources 'helm-source-xrandr-change-resolution
+ :buffer "*helm xrandr*"))
+
+(provide 'helm-sys)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-sys.el ends here
--- /dev/null
+;;; helm-tags.el --- Helm for Etags. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'helm)
+(require 'helm-help)
+(require 'helm-utils)
+(require 'helm-grep)
+
+\f
+(defgroup helm-tags nil
+ "Tags related Applications and libraries for Helm."
+ :group 'helm)
+
+(defcustom helm-etags-tag-file-name "TAGS"
+ "Etags tag file name."
+ :type 'string
+ :group 'helm-tags)
+
+(defcustom helm-etags-tag-file-search-limit 10
+ "The limit level of directory to search tag file.
+Don't search tag file deeply if outside this value."
+ :type 'number
+ :group 'helm-tags)
+
+(defcustom helm-etags-match-part-only 'tag
+ "Allow choosing the tag part of CANDIDATE in `helm-source-etags-select'.
+A tag looks like this:
+ filename: \(defun foo
+You can choose matching against the tag part (i.e \"(defun foo\"),
+or against the whole candidate (i.e \"(filename:5:(defun foo\")."
+ :type '(choice
+ (const :tag "Match only tag" tag)
+ (const :tag "Match all file+tag" all))
+ :group 'helm-tags)
+
+(defcustom helm-etags-execute-action-at-once-if-one t
+ "Whether to jump straight to the selected tag if there's only
+one match."
+ :type 'boolean
+ :group 'helm-tags)
+
+\f
+(defgroup helm-tags-faces nil
+ "Customize the appearance of helm-tags faces."
+ :prefix "helm-"
+ :group 'helm-tags
+ :group 'helm-faces)
+
+(defface helm-etags-file
+ '((t (:foreground "Lightgoldenrod4"
+ :underline t)))
+ "Face used to highlight etags filenames."
+ :group 'helm-tags-faces)
+
+\f
+;;; Etags
+;;
+;;
+(defun helm-etags-run-switch-other-window ()
+ "Run switch to other window action from `helm-source-etags-select'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action
+ (lambda (c)
+ (helm-etags-action-goto 'find-file-other-window c)))))
+(put 'helm-etags-run-switch-other-window 'helm-only t)
+
+(defun helm-etags-run-switch-other-frame ()
+ "Run switch to other frame action from `helm-source-etags-select'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-exit-and-execute-action
+ (lambda (c)
+ (helm-etags-action-goto 'find-file-other-frame c)))))
+(put 'helm-etags-run-switch-other-frame 'helm-only t)
+
+(defvar helm-etags-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map helm-map)
+ (define-key map (kbd "M-<down>") 'helm-goto-next-file)
+ (define-key map (kbd "M-<up>") 'helm-goto-precedent-file)
+ (define-key map (kbd "C-c o") 'helm-etags-run-switch-other-window)
+ (define-key map (kbd "C-c C-o") 'helm-etags-run-switch-other-frame)
+ map)
+ "Keymap used in Etags.")
+
+(defvar helm-etags-mtime-alist nil
+ "Store the last modification time of etags files here.")
+(defvar helm-etags-cache (make-hash-table :test 'equal)
+ "Cache content of etags files used here for faster access.")
+
+(defun helm-etags-get-tag-file (&optional directory)
+ "Return the path of etags file if found.
+Lookes recursively in parents directorys for a
+`helm-etags-tag-file-name' file."
+ ;; Get tag file from `default-directory' or upper directory.
+ (let ((current-dir (helm-etags-find-tag-file-directory
+ (or directory default-directory))))
+ ;; Return nil if not find tag file.
+ (when current-dir
+ (expand-file-name helm-etags-tag-file-name current-dir))))
+
+(defun helm-etags-all-tag-files ()
+ "Return files from the following sources;
+ 1) An automatically located file in the parent directories, by `helm-etags-get-tag-file'.
+ 2) `tags-file-name', which is commonly set by `find-tag' command.
+ 3) `tags-table-list' which is commonly set by `visit-tags-table' command."
+ (helm-fast-remove-dups
+ (delq nil
+ (append (list (helm-etags-get-tag-file)
+ tags-file-name)
+ tags-table-list))
+ :test 'equal))
+
+(defun helm-etags-find-tag-file-directory (current-dir)
+ "Try to find the directory containing tag file.
+If not found in CURRENT-DIR search in upper directory."
+ (let ((file-exists? (lambda (dir)
+ (let ((tag-path (expand-file-name
+ helm-etags-tag-file-name dir)))
+ (and (stringp tag-path)
+ (file-regular-p tag-path)
+ (file-readable-p tag-path))))))
+ (cl-loop with count = 0
+ until (funcall file-exists? current-dir)
+ ;; Return nil if outside the value of
+ ;; `helm-etags-tag-file-search-limit'.
+ if (= count helm-etags-tag-file-search-limit)
+ do (cl-return nil)
+ ;; Or search upper directories.
+ else
+ do (cl-incf count)
+ (setq current-dir (expand-file-name (concat current-dir "../")))
+ finally return current-dir)))
+
+(defun helm-etags-get-header-name (_x)
+ "Create header name for this helm etags session."
+ (concat "Etags in "
+ (with-helm-current-buffer
+ (helm-etags-get-tag-file))))
+
+(defun helm-etags-create-buffer (file)
+ "Create the `helm-buffer' based on contents of etags tag FILE."
+ (let* (max
+ (split (with-temp-buffer
+ (insert-file-contents file)
+ (prog1
+ (split-string (buffer-string) "\n" 'omit-nulls)
+ (setq max (line-number-at-pos (point-max))))))
+ (progress-reporter (make-progress-reporter "Loading tag file..." 0 max)))
+ (cl-loop
+ with fname
+ with cand
+ for i in split for count from 0
+ for elm = (unless (string-match "^\x0c" i) ;; "^L"
+ (helm-aif (string-match "\177" i) ;; "^?"
+ (substring i 0 it)
+ i))
+ for linum = (when (string-match "[0-9]+,?[0-9]*$" i)
+ (car (split-string (match-string 0 i) ",")))
+ do (cond ((and elm (string-match "^\\([^,]+\\),[0-9]+$" elm))
+ (setq fname (propertize (match-string 1 elm)
+ 'face 'helm-etags-file)))
+ (elm (setq cand (format "%s:%s:%s" fname linum elm)))
+ (t (setq cand nil)))
+ when cand do (progn
+ (insert (propertize (concat cand "\n") 'linum linum))
+ (progress-reporter-update progress-reporter count)))))
+
+(defun helm-etags-init ()
+ "Feed `helm-buffer' using `helm-etags-cache' or tag file.
+If no entry in cache, create one."
+ (let ((tagfiles (helm-etags-all-tag-files)))
+ (when tagfiles
+ (with-current-buffer (helm-candidate-buffer 'global)
+ (dolist (f tagfiles)
+ (helm-aif (gethash f helm-etags-cache)
+ ;; An entry is present in cache, insert it.
+ (insert it)
+ ;; No entry, create a new buffer using content of tag file (slower).
+ (helm-etags-create-buffer f)
+ ;; Store content of buffer in cache.
+ (puthash f (buffer-string) helm-etags-cache)
+ ;; Store or set the last modification of tag file.
+ (helm-aif (assoc f helm-etags-mtime-alist)
+ ;; If an entry exists modify it.
+ (setcdr it (helm-etags-mtime f))
+ ;; No entry create a new one.
+ (cl-pushnew (cons f (helm-etags-mtime f))
+ helm-etags-mtime-alist
+ :test 'equal))))))))
+
+(defvar helm-source-etags-select nil
+ "Helm source for Etags.")
+
+(defun helm-etags-build-source ()
+ (helm-build-in-buffer-source "Etags"
+ :header-name 'helm-etags-get-header-name
+ :init 'helm-etags-init
+ :get-line 'buffer-substring
+ :match-part (lambda (candidate)
+ ;; Match only the tag part of CANDIDATE
+ ;; and not the filename.
+ (cl-case helm-etags-match-part-only
+ (tag (cl-caddr (helm-grep-split-line candidate)))
+ (t candidate)))
+ :fuzzy-match helm-etags-fuzzy-match
+ :help-message 'helm-etags-help-message
+ :keymap helm-etags-map
+ :action '(("Go to tag" . (lambda (c)
+ (helm-etags-action-goto 'find-file c)))
+ ("Go to tag in other window" . (lambda (c)
+ (helm-etags-action-goto
+ 'find-file-other-window
+ c)))
+ ("Go to tag in other frame" . (lambda (c)
+ (helm-etags-action-goto
+ 'find-file-other-frame
+ c))))
+ :group 'helm-tags
+ :persistent-help "Go to line"
+ :persistent-action (lambda (candidate)
+ (helm-etags-action-goto 'find-file candidate)
+ (helm-highlight-current-line))))
+
+(defcustom helm-etags-fuzzy-match nil
+ "Use fuzzy matching in `helm-etags-select'."
+ :group 'helm-tags
+ :type 'boolean
+ :set (lambda (var val)
+ (set var val)
+ (setq helm-source-etags-select
+ (helm-etags-build-source))))
+
+(defvar find-tag-marker-ring)
+
+(defsubst helm-etags--file-from-tag (fname)
+ (cl-loop for ext in
+ (cons "" (remove "" tags-compression-info-list))
+ for file = (concat fname ext)
+ when (file-exists-p file)
+ return file))
+
+(defun helm-etags-action-goto (switcher candidate)
+ "Helm default action to jump to an etags entry in other window."
+ (require 'etags)
+ (deactivate-mark t)
+ (helm-log-run-hook 'helm-goto-line-before-hook)
+ (let* ((split (helm-grep-split-line candidate))
+ (fname (cl-loop for tagf being the hash-keys of helm-etags-cache
+ for f = (expand-file-name
+ (car split) (file-name-directory tagf))
+ ;; Try to find an existing file, possibly compressed.
+ when (helm-etags--file-from-tag f)
+ return it))
+ (elm (cl-caddr split))
+ (linum (string-to-number (cadr split))))
+ (if (null fname)
+ (error "file %s not found" fname)
+ (ring-insert find-tag-marker-ring (point-marker))
+ (funcall switcher fname)
+ (helm-goto-line linum t)
+ (when (search-forward elm nil t)
+ (goto-char (match-beginning 0))))))
+
+(defun helm-etags-mtime (file)
+ "Last modification time of etags tag FILE."
+ (cadr (nth 5 (file-attributes file))))
+
+(defun helm-etags-file-modified-p (file)
+ "Check if tag FILE have been modified in this session.
+If FILE is nil return nil."
+ (let ((last-modif (and file
+ (assoc-default file helm-etags-mtime-alist))))
+ (and last-modif
+ (/= last-modif (helm-etags-mtime file)))))
+
+;;;###autoload
+(defun helm-etags-select (reinit)
+ "Preconfigured helm for etags.
+If called with a prefix argument REINIT
+or if any of the tag files have been modified, reinitialize cache.
+
+This function aggregates three sources of tag files:
+
+ 1) An automatically located file in the parent directories,
+ by `helm-etags-get-tag-file'.
+ 2) `tags-file-name', which is commonly set by `find-tag' command.
+ 3) `tags-table-list' which is commonly set by `visit-tags-table' command."
+ (interactive "P")
+ (let ((tag-files (helm-etags-all-tag-files))
+ (helm-execute-action-at-once-if-one
+ helm-etags-execute-action-at-once-if-one)
+ (str (if (region-active-p)
+ (buffer-substring-no-properties
+ (region-beginning) (region-end))
+ (thing-at-point 'symbol))))
+ (if (cl-notany 'file-exists-p tag-files)
+ (message "Error: No tag file found.\
+Create with etags shell command, or visit with `find-tag' or `visit-tags-table'.")
+ (cl-loop for k being the hash-keys of helm-etags-cache
+ unless (member k tag-files)
+ do (remhash k helm-etags-cache))
+ (mapc (lambda (f)
+ (when (or (equal reinit '(4))
+ (and helm-etags-mtime-alist
+ (helm-etags-file-modified-p f)))
+ (remhash f helm-etags-cache)))
+ tag-files)
+ (unless helm-source-etags-select
+ (setq helm-source-etags-select
+ (helm-etags-build-source)))
+ (helm :sources 'helm-source-etags-select
+ :keymap helm-etags-map
+ :default (if helm-etags-fuzzy-match
+ str
+ (list (concat "\\_<" str "\\_>") str))
+ :buffer "*helm etags*"))))
+
+(provide 'helm-tags)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-tags.el ends here
--- /dev/null
+;;; helm-types.el --- Helm types classes and methods. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2015 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; Author: Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+;; URL: http://github.com/emacs-helm/helm
+
+;; 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/>.
+
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'eieio)
+
+\f
+;; Files
+(defclass helm-type-file (helm-source) ()
+ "A class to define helm type file.")
+
+(defmethod helm-source-get-action-from-type ((object helm-type-file))
+ (slot-value object 'action))
+
+(defun helm-actions-from-type-file ()
+ (let ((source (make-instance 'helm-type-file)))
+ (helm--setup-source source)
+ (helm-source-get-action-from-type source)))
+
+(defcustom helm-type-file-actions
+ (helm-make-actions
+ "Find file" 'helm-find-many-files
+ "Find file as root" 'helm-find-file-as-root
+ "Find file other window" 'helm-find-files-other-window
+ "Find file other frame" 'find-file-other-frame
+ "Open dired in file's directory" 'helm-open-dired
+ "Attach file(s) to mail buffer `C-c C-a'" 'helm-ff-mail-attach-files
+ "Marked files in dired" 'helm-marked-files-in-dired
+ "Grep File(s) `C-u recurse'" 'helm-find-files-grep
+ "Zgrep File(s) `C-u Recurse'" 'helm-ff-zgrep
+ "Pdfgrep File(s)" 'helm-ff-pdfgrep
+ "Insert as org link" 'helm-files-insert-as-org-link
+ "Checksum File" 'helm-ff-checksum
+ "Ediff File" 'helm-find-files-ediff-files
+ "Ediff Merge File" 'helm-find-files-ediff-merge-files
+ "Etags `M-., C-u reload tag file'" 'helm-ff-etags-select
+ "View file" 'view-file
+ "Insert file" 'insert-file
+ "Add marked files to file-cache" 'helm-ff-cache-add-file
+ "Delete file(s)" 'helm-ff-delete-files
+ "Copy file(s) `M-C, C-u to follow'" 'helm-find-files-copy
+ "Rename file(s) `M-R, C-u to follow'" 'helm-find-files-rename
+ "Symlink files(s) `M-S, C-u to follow'" 'helm-find-files-symlink
+ "Relsymlink file(s) `C-u to follow'" 'helm-find-files-relsymlink
+ "Hardlink file(s) `M-H, C-u to follow'" 'helm-find-files-hardlink
+ "Open file externally (C-u to choose)" 'helm-open-file-externally
+ "Open file with default tool" 'helm-open-file-with-default-tool
+ "Find file in hex dump" 'hexl-find-file)
+ "Default actions for type files."
+ :group 'helm-files
+ :type '(alist :key-type string :value-type function))
+
+(defmethod helm--setup-source :primary ((_source helm-type-file)))
+
+(defmethod helm--setup-source :before ((source helm-type-file))
+ (setf (slot-value source 'action) 'helm-type-file-actions)
+ (setf (slot-value source 'persistent-help) "Show this file")
+ (setf (slot-value source 'action-transformer)
+ '(helm-transform-file-load-el
+ helm-transform-file-browse-url
+ helm-transform-file-cache))
+ (setf (slot-value source 'candidate-transformer)
+ '(helm-skip-boring-files
+ helm-w32-pathname-transformer))
+ (setf (slot-value source 'filtered-candidate-transformer)
+ 'helm-highlight-files)
+ (setf (slot-value source 'help-message) 'helm-generic-file-help-message)
+ (setf (slot-value source 'mode-line) (list "File(s)" helm-mode-line-string))
+ (setf (slot-value source 'keymap) helm-generic-files-map)
+ (setf (slot-value source 'group) 'helm-files))
+
+\f
+;; Bookmarks
+(defclass helm-type-bookmark (helm-source) ()
+ "A class to define type bookmarks.")
+
+(defcustom helm-type-bookmark-actions
+ (helm-make-actions
+ "Jump to bookmark" 'helm-bookmark-jump
+ "Jump to BM other window" 'helm-bookmark-jump-other-window
+ "Jump to BM other frame" 'helm-bookmark-jump-other-frame
+ "Bookmark edit annotation" 'bookmark-edit-annotation
+ "Bookmark show annotation" 'bookmark-show-annotation
+ "Delete bookmark(s)" 'helm-delete-marked-bookmarks
+ "Edit Bookmark" 'helm-bookmark-edit-bookmark
+ "Rename bookmark" 'helm-bookmark-rename
+ "Relocate bookmark" 'bookmark-relocate)
+ "Default actions for type bookmarks."
+ :group 'helm-bookmark
+ :type '(alist :key-type string
+ :value-type function))
+
+(defmethod helm-source-get-action-from-type ((object helm-type-bookmark))
+ (slot-value object 'action))
+
+(defmethod helm--setup-source :primary ((_source helm-type-bookmark)))
+
+(defmethod helm--setup-source :before ((source helm-type-bookmark))
+ (setf (slot-value source 'action) 'helm-type-bookmark-actions)
+ (setf (slot-value source 'keymap) helm-bookmark-map)
+ (setf (slot-value source 'mode-line) (list "Bookmark(s)" helm-mode-line-string))
+ (setf (slot-value source 'help-message) 'helm-bookmark-help-message)
+ (setf (slot-value source 'migemo) t)
+ (setf (slot-value source 'follow) 'never)
+ (setf (slot-value source 'group) 'helm-bookmark))
+
+\f
+;; Buffers
+(defclass helm-type-buffer (helm-source) ()
+ "A class to define type buffer.")
+
+(defcustom helm-type-buffer-actions
+ (helm-make-actions
+ "Switch to buffer(s)" 'helm-buffer-switch-buffers
+ "Switch to buffer(s) other window `C-c o'"
+ 'helm-buffer-switch-buffers-other-window
+ "Switch to buffer other frame `C-c C-o'"
+ 'switch-to-buffer-other-frame
+ "Browse project from buffer"
+ 'helm-buffers-browse-project
+ "Query replace regexp `C-M-%'"
+ 'helm-buffer-query-replace-regexp
+ "Query replace `M-%'" 'helm-buffer-query-replace
+ "View buffer" 'view-buffer
+ "Display buffer" 'display-buffer
+ "Rename buffer" 'helm-buffers-rename-buffer
+ "Grep buffers `M-g s' (C-u grep all buffers)"
+ 'helm-zgrep-buffers
+ "Multi occur buffer(s) `C-s'" 'helm-multi-occur-as-action
+ "Revert buffer(s) `M-U'" 'helm-revert-marked-buffers
+ "Insert buffer" 'insert-buffer
+ "Kill buffer(s) `M-D'" 'helm-kill-marked-buffers
+ "Diff with file `C-='" 'diff-buffer-with-file
+ "Ediff Marked buffers `C-c ='" 'helm-ediff-marked-buffers
+ "Ediff Merge marked buffers `M-='"
+ (lambda (candidate)
+ (helm-ediff-marked-buffers candidate t)))
+ "Default actions for type buffers."
+ :group 'helm-buffers
+ :type '(alist :key-type string :value-type function))
+
+(defmethod helm-source-get-action-from-type ((object helm-type-buffer))
+ (slot-value object 'action))
+
+(defmethod helm--setup-source :primary ((_source helm-type-buffer)))
+
+(defmethod helm--setup-source :before ((source helm-type-buffer))
+ (setf (slot-value source 'action) 'helm-type-buffer-actions)
+ (setf (slot-value source 'persistent-help) "Show this buffer")
+ (setf (slot-value source 'mode-line) (list "Buffer(s)" helm-mode-line-string))
+ (setf (slot-value source 'filtered-candidate-transformer)
+ '(helm-skip-boring-buffers
+ helm-buffers-sort-transformer
+ helm-highlight-buffers))
+ (setf (slot-value source 'group) 'helm-buffers))
+\f
+;; Functions
+(defclass helm-type-function (helm-source) ()
+ "A class to define helm type function.")
+
+(defcustom helm-type-function-actions
+ (helm-make-actions
+ "Describe command" 'describe-function
+ "Add command to kill ring" 'helm-kill-new
+ "Go to command's definition" 'find-function
+ "Debug on entry" 'debug-on-entry
+ "Cancel debug on entry" 'cancel-debug-on-entry
+ "Trace function" 'trace-function
+ "Trace function (background)" 'trace-function-background
+ "Untrace function" 'untrace-function)
+ "Default actions for type functions."
+ :group 'helm-elisp
+ :type '(alist :key-type string :value-type function))
+
+(defmethod helm-source-get-action-from-type ((object helm-type-function))
+ (slot-value object 'action))
+
+(defun helm-actions-from-type-function ()
+ (let ((source (make-instance 'helm-type-function)))
+ (helm--setup-source source)
+ (helm-source-get-action-from-type source)))
+
+(defmethod helm--setup-source :primary ((_source helm-type-function)))
+
+(defmethod helm--setup-source :before ((source helm-type-function))
+ (setf (slot-value source 'action) 'helm-type-function-actions)
+ (setf (slot-value source 'action-transformer)
+ 'helm-transform-function-call-interactively)
+ (setf (slot-value source 'candidate-transformer)
+ 'helm-mark-interactive-functions)
+ (setf (slot-value source 'coerce) 'helm-symbolify))
+
+\f
+;; Commands
+(defclass helm-type-command (helm-source) ()
+ "A class to define helm type command.")
+
+(defun helm-actions-from-type-command ()
+ (let ((source (make-instance 'helm-type-command)))
+ (helm--setup-source source)
+ (helm-source-get-action-from-type source)))
+
+(defcustom helm-type-command-actions
+ (append (helm-make-actions
+ "Call interactively" 'helm-call-interactively)
+ (helm-actions-from-type-function))
+ "Default actions for type command."
+ :group 'helm-command
+ :type '(alist :key-type string :value-type function))
+
+(defmethod helm--setup-source :primary ((_source helm-type-command)))
+
+(defmethod helm--setup-source :before ((source helm-type-command))
+ (setf (slot-value source 'action) 'helm-type-command-actions)
+ (setf (slot-value source 'coerce) 'helm-symbolify)
+ (setf (slot-value source 'persistent-action) 'describe-function)
+ (setf (slot-value source 'group) 'helm-command))
+
+;; Timers
+(defclass helm-type-timers (helm-source) ()
+ "A class to define helm type timers.")
+
+(defcustom helm-type-timers-actions
+ '(("Cancel Timer" . (lambda (_timer)
+ (let ((mkd (helm-marked-candidates)))
+ (cl-loop for timer in mkd
+ do (cancel-timer timer)))))
+ ("Describe Function" . (lambda (tm)
+ (describe-function (timer--function tm))))
+ ("Find Function" . (lambda (tm)
+ (helm-aif (timer--function tm)
+ (if (byte-code-function-p it)
+ (message "Can't find anonymous function `%s'" it)
+ (find-function it))))))
+ "Default actions for type timers."
+ :group 'helm-elisp
+ :type '(alist :key-type string :value-type function))
+
+(defmethod helm--setup-source :primary ((_source helm-type-timers)))
+
+(defmethod helm--setup-source :before ((source helm-type-timers))
+ (setf (slot-value source 'action) 'helm-type-timers-actions)
+ (setf (slot-value source 'persistent-action)
+ (lambda (tm)
+ (describe-function (timer--function tm))))
+ (setf (slot-value source 'persistent-help) "Describe Function")
+ (setf (slot-value source 'group) 'helm-elisp))
+\f
+;; Builders.
+(defun helm-build-type-file ()
+ (helm-make-type 'helm-type-file))
+
+(defun helm-build-type-function ()
+ (helm-make-type 'helm-type-function))
+
+(defun helm-build-type-command ()
+ (helm-make-type 'helm-type-command))
+
+(provide 'helm-types)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-types.el ends here
--- /dev/null
+;;; helm-utils.el --- Utilities Functions for helm. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'helm)
+(require 'helm-help)
+(eval-when-compile (require 'dired))
+
+(declare-function helm-find-files-1 "helm-files.el" (fname &optional preselect))
+(declare-function popup-tip "ext:popup")
+(defvar winner-boring-buffers)
+(defvar helm-show-completion-overlay)
+
+\f
+(defgroup helm-utils nil
+ "Utilities routines for Helm."
+ :group 'helm)
+
+(defcustom helm-su-or-sudo "sudo"
+ "What command to use for root access."
+ :type 'string
+ :group 'helm-utils)
+
+(defcustom helm-default-kbsize 1024.0
+ "Default Kbsize to use for showing files size.
+It is a float, usually 1024.0 but could be 1000.0 on some systems."
+ :group 'helm-utils
+ :type 'float)
+
+(define-obsolete-variable-alias
+ 'helm-highlight-number-lines-around-point
+ 'helm-highlight-matches-around-point-max-lines
+ "20160119")
+
+(defcustom helm-highlight-matches-around-point-max-lines 15
+ "Number of lines around point where matched items are highlighted."
+ :group 'helm-utils
+ :type 'integer)
+
+(defcustom helm-buffers-to-resize-on-pa nil
+ "A list of helm buffers where the helm-window should be reduced on persistent actions."
+ :group 'helm-utils
+ :type '(repeat (choice string)))
+
+(defcustom helm-resize-on-pa-text-height 12
+ "The size of the helm-window when resizing on persistent action."
+ :group 'helm-utils
+ :type 'integer)
+
+(defcustom helm-sources-using-help-echo-popup '("Moccur" "Imenu in all buffers"
+ "Ack-Grep" "AG" "RG" "Gid" "Git-Grep")
+ "Show the buffer name or the filename in a popup at selection."
+ :group 'helm-utils
+ :type '(repeat (choice string)))
+
+(defcustom helm-html-decode-entities-function #'helm-html-decode-entities-string
+ "Function used to decode html entities in html bookmarks.
+Helm comes by default with `helm-html-decode-entities-string', if you need something
+more sophisticated you can use `w3m-decode-entities-string' if available.
+
+In emacs itself org-entities seems broken and `xml-substitute-numeric-entities'
+supports only numeric entities."
+ :group 'helm-utils
+ :type 'function)
+
+\f
+(defvar helm-goto-line-before-hook '(helm-save-current-pos-to-mark-ring)
+ "Run before jumping to line.
+This hook run when jumping from `helm-goto-line', `helm-etags-default-action',
+and `helm-imenu-default-action'.
+This allow you to retrieve a previous position after using the different helm
+tools for searching (etags, grep, gid, (m)occur etc...).
+By default positions are added to `mark-ring' you can also add to register
+by using instead (or adding) `helm-save-pos-to-register-before-jump'.
+In this case last position is added to the register
+`helm-save-pos-before-jump-register'.")
+
+(defvar helm-save-pos-before-jump-register ?_
+ "The register where `helm-save-pos-to-register-before-jump' save position.")
+
+(defconst helm-html-entities-alist
+ '((""" . 34) ;; "
+ (">" . 62) ;; >
+ ("<" . 60) ;; <
+ ("&" . 38) ;; &
+ ("€" . 8364) ;; €
+ ("Ÿ" . 89) ;; Y
+ ("¡" . 161) ;; ¡
+ ("¢" . 162) ;; ¢
+ ("£" . 163) ;; £
+ ("¤" . 164) ;; ¤
+ ("¥" . 165) ;; ¥
+ ("¦" . 166) ;; ¦
+ ("§" . 167) ;; §
+ ("¨" . 32) ;; SPC
+ ("©" . 169) ;; ©
+ ("ª" . 97) ;; a
+ ("«" . 171) ;; «
+ ("¬" . 172) ;; ¬
+ ("&masr;" . 174) ;; ®
+ ("°" . 176) ;; °
+ ("±" . 177) ;; ±
+ ("²" . 50) ;; 2
+ ("³" . 51) ;; 3
+ ("´" . 39) ;; '
+ ("µ" . 956) ;; μ
+ ("¶" . 182) ;; ¶
+ ("·" . 183) ;; ·
+ ("¸" . 32) ;; SPC
+ ("¹" . 49) ;; 1
+ ("º" . 111) ;; o
+ ("»" . 187) ;; »
+ ("¼" . 49) ;; 1
+ ("½" . 49) ;; 1
+ ("¾" . 51) ;; 3
+ ("¿" . 191) ;; ¿
+ ("À" . 192) ;; À
+ ("Á" . 193) ;; Á
+ ("Â" . 194) ;; Â
+ ("Ã" . 195) ;; Ã
+ ("Ä" . 196) ;; Ä
+ ("Å" . 197) ;; Å
+ ("&Aelig" . 198) ;; Æ
+ ("Ç" . 199) ;; Ç
+ ("È" . 200) ;; È
+ ("É" . 201) ;; É
+ ("Ê" . 202) ;; Ê
+ ("Ë" . 203) ;; Ë
+ ("Ì" . 204) ;; Ì
+ ("Í" . 205) ;; Í
+ ("Î" . 206) ;; Î
+ ("Ï" . 207) ;; Ï
+ ("ð" . 208) ;; Ð
+ ("Ñ" . 209) ;; Ñ
+ ("Ò" . 210) ;; Ò
+ ("Ó" . 211) ;; Ó
+ ("Ô" . 212) ;; Ô
+ ("Õ" . 213) ;; Õ
+ ("Ö" . 214) ;; Ö
+ ("×" . 215) ;; ×
+ ("Ø" . 216) ;; Ø
+ ("Ù" . 217) ;; Ù
+ ("Ú" . 218) ;; Ú
+ ("Û" . 219) ;; Û
+ ("Ü" . 220) ;; Ü
+ ("Ý" . 221) ;; Ý
+ ("þ" . 222) ;; Þ
+ ("ß" . 223) ;; ß
+ ("à" . 224) ;; à
+ ("á" . 225) ;; á
+ ("â" . 226) ;; â
+ ("ã" . 227) ;; ã
+ ("ä" . 228) ;; ä
+ ("å" . 229) ;; å
+ ("æ" . 230) ;; æ
+ ("ç" . 231) ;; ç
+ ("è" . 232) ;; è
+ ("é" . 233) ;; é
+ ("ê" . 234) ;; ê
+ ("ë" . 235) ;; ë
+ ("ì" . 236) ;; ì
+ ("í" . 237) ;; í
+ ("î" . 238) ;; î
+ ("ï" . 239) ;; ï
+ ("ð" . 240) ;; ð
+ ("ñ" . 241) ;; ñ
+ ("ò" . 242) ;; ò
+ ("ó" . 243) ;; ó
+ ("ô" . 244) ;; ô
+ ("õ" . 245) ;; õ
+ ("ö" . 246) ;; ö
+ ("÷" . 247) ;; ÷
+ ("ø" . 248) ;; ø
+ ("ù" . 249) ;; ù
+ ("ú" . 250) ;; ú
+ ("û" . 251) ;; û
+ ("ü" . 252) ;; ü
+ ("ý" . 253) ;; ý
+ ("þ" . 254) ;; þ
+ ("ÿ" . 255) ;; ÿ
+ ("®" . 174) ;; ®
+ ("­" . 173)) ;;
+
+ "Table of html character entities and values.")
+
+(defvar helm-find-many-files-after-hook nil
+ "Hook that run at end of `helm-find-many-files'.")
+\f
+;;; Faces.
+;;
+(defface helm-selection-line
+ '((t (:inherit highlight :distant-foreground "black")))
+ "Face used in the `helm-current-buffer' when jumping to candidate."
+ :group 'helm-faces)
+
+(defface helm-match-item
+ '((t (:inherit isearch)))
+ "Face used to highlight item matched in a selected line."
+ :group 'helm-faces)
+
+\f
+;;; Utils functions
+;;
+;;
+(defcustom helm-window-prefer-horizontal-split nil
+ "Maybe switch to other window vertically when non nil.
+
+Possible values are t, nil and `decide'.
+
+When t switch vertically.
+When nil switch horizontally.
+When `decide' try to guess if it is possible to switch vertically
+according to the setting of `split-width-threshold' and the size of
+the window from where splitting is done.
+
+Note that when using `decide' and `split-width-threshold' is nil, the
+behavior is the same that with a nil value."
+ :group 'helm-utils
+ :type '(choice
+ (const :tag "Split window vertically" t)
+ (const :tag "Split window horizontally" nil)
+ (symbol :tag "Guess how to split window" 'decide)))
+
+(defcustom helm-window-show-buffers-function #'helm-window-default-split-fn
+ "The default function to use when opening several buffers at once.
+It is typically used to rearrange windows."
+ :group 'helm-utils
+ :type '(choice
+ (function :tag "Split windows vertically or horizontally"
+ helm-window-default-split-fn)
+ (function :tag "Split in alternate windows"
+ helm-window-alternate-split-fn)
+ (function :tag "Split windows in mosaic"
+ helm-window-mosaic-fn)))
+
+(defun helm-window-show-buffers (buffers &optional other-window)
+ "Show BUFFERS.
+
+If more than one buffer marked switch to these buffers in separate windows.
+If OTHER-WINDOW is non-nil, keep current buffer and switch to others buffers
+in separate windows.
+If a prefix arg is given split windows vertically."
+ (let ((initial-ow-fn (if (cdr (window-list))
+ #'switch-to-buffer-other-window
+ #'helm-window-other-window)))
+ (if (cdr buffers)
+ (funcall helm-window-show-buffers-function buffers
+ (and other-window initial-ow-fn))
+ (if other-window
+ (funcall initial-ow-fn (car buffers))
+ (switch-to-buffer (car buffers))))))
+
+(defun helm-window-default-split-fn (candidates &optional other-window-fn)
+ "Split windows in one direction and balance them.
+
+Direction can be controlled via `helm-window-prefer-horizontal-split'.
+If a prefix arg is given split windows the other direction.
+This function is suitable for `helm-window-show-buffers-function'."
+ (if other-window-fn
+ (funcall other-window-fn (car candidates))
+ (switch-to-buffer (car candidates)))
+ (save-selected-window
+ (cl-loop with nosplit
+ for b in (cdr candidates)
+ when nosplit return
+ (message "Too many buffers to visit simultaneously")
+ do (condition-case _err
+ (helm-window-other-window b 'balance)
+ (error (setq nosplit t) nil)))))
+
+(defun helm-window-alternate-split-fn (candidates &optional other-window-fn)
+ "Split windows horizontally and vertically in alternate fashion.
+
+Direction can be controlled via `helm-window-prefer-horizontal-split'.
+If a prefix arg is given split windows the other direction.
+This function is suitable for `helm-window-show-buffers-function'."
+ (if other-window-fn
+ (funcall other-window-fn (car candidates))
+ (switch-to-buffer (car candidates)))
+ (let (right-side)
+ (save-selected-window
+ (cl-loop with nosplit
+ for b in (cdr candidates)
+ when nosplit return
+ (message "Too many buffers to visit simultaneously")
+ do (condition-case _err
+ (let ((helm-current-prefix-arg right-side))
+ (helm-window-other-window b)
+ (setq right-side (not right-side)))
+ (error (setq nosplit t) nil))))))
+
+(defun helm-window-mosaic-fn (candidates &optional other-window-fn)
+ "Make an as-square-as-possible window mosaic of the CANDIDATES buffers.
+
+If rectangular, the long side is in the direction given by
+`helm-window-prefer-horizontal-split': if non-nil, it is horizontal, vertical
+otherwise.
+If OTHER-WINDOW-FN is non-nil, current windows are included in the mosaic.
+This function is suitable for `helm-window-show-buffers-function'."
+ (when other-window-fn
+ (setq candidates (append (mapcar 'window-buffer (window-list)) candidates)))
+ (delete-other-windows)
+ (let* ((helm-window-prefer-horizontal-split
+ (if (eq helm-window-prefer-horizontal-split 'decide)
+ (and (numberp split-width-threshold)
+ (>= (window-width (selected-window))
+ split-width-threshold))
+ helm-window-prefer-horizontal-split))
+ mosaic-length-tile-count
+ mosaic-width-tile-count
+ mosaic-length-tile-size
+ mosaic-width-tile-size
+ next-window)
+ ;; If 4 tiles, make 2x2 mosaic.
+ ;; If 5-6 tiles, make 2x3 mosaic with direction depending on `helm-window-prefer-horizontal-split'.
+ ;; If 7-9 tiles, make 3x3 mosaic. And so on.
+ (setq mosaic-length-tile-count (ceiling (sqrt (length candidates))))
+ (setq mosaic-width-tile-count
+ (if (<= (length candidates) (* mosaic-length-tile-count (1- mosaic-length-tile-count)))
+ (1- mosaic-length-tile-count)
+ mosaic-length-tile-count))
+ ;; We lower-bound the tile size, otherwise the function would
+ ;; fail during the first inner split.
+ ;; There is consequently no need to check for errors when
+ ;; splitting.
+ (let ((frame-mosaic-length-direction-size (frame-height))
+ (frame-mosaic-width-direction-size (frame-width))
+ (window-mosaic-length-direction-min-size window-min-height)
+ (window-mosaic-width-direction-min-size window-min-width))
+ (if helm-window-prefer-horizontal-split
+ (setq frame-mosaic-length-direction-size (frame-width)
+ frame-mosaic-width-direction-size (frame-height)
+ window-mosaic-length-direction-min-size window-min-width
+ window-mosaic-width-direction-min-size window-min-height))
+ (setq mosaic-length-tile-size (max
+ (/ frame-mosaic-length-direction-size mosaic-length-tile-count)
+ window-mosaic-length-direction-min-size)
+ mosaic-width-tile-size (max
+ (/ frame-mosaic-width-direction-size mosaic-width-tile-count)
+ window-mosaic-width-direction-min-size))
+ ;; Shorten `candidates' to `max-tiles' elements.
+ (let ((max-tiles (* (/ frame-mosaic-length-direction-size mosaic-length-tile-size)
+ (/ frame-mosaic-width-direction-size mosaic-width-tile-size))))
+ (when (> (length candidates) max-tiles)
+ (message "Too many buffers to visit simultaneously")
+ (setcdr (nthcdr (- max-tiles 1) candidates) nil))))
+ ;; Make the mosaic.
+ (while candidates
+ (when (> (length candidates) mosaic-length-tile-count)
+ (setq next-window (split-window nil
+ mosaic-width-tile-size
+ (not helm-window-prefer-horizontal-split))))
+ (switch-to-buffer (pop candidates))
+ (dotimes (_ (min (1- mosaic-length-tile-count) (length candidates)))
+ (select-window (split-window nil
+ mosaic-length-tile-size
+ helm-window-prefer-horizontal-split))
+ (switch-to-buffer (pop candidates)))
+ (when next-window
+ (select-window next-window)))))
+
+(defun helm-window-other-window (buffer-or-name &optional balance)
+ "Switch to BUFFER-OR-NAME in other window.
+Direction can be controlled via `helm-window-prefer-horizontal-split'.
+If a prefix arg is given split windows the other direction.
+When argument BALANCE is provided `balance-windows'."
+ (let* ((helm-window-prefer-horizontal-split
+ (if (eq helm-window-prefer-horizontal-split 'decide)
+ (and (numberp split-width-threshold)
+ (>= (window-width (selected-window))
+ split-width-threshold))
+ helm-window-prefer-horizontal-split))
+ (right-side (if helm-window-prefer-horizontal-split
+ (not helm-current-prefix-arg)
+ helm-current-prefix-arg)))
+ (select-window (split-window nil nil right-side))
+ (and balance (balance-windows))
+ (switch-to-buffer buffer-or-name)))
+
+(cl-defun helm-current-buffer-narrowed-p (&optional
+ (buffer helm-current-buffer))
+ "Check if BUFFER is narrowed.
+Default is `helm-current-buffer'."
+ (with-current-buffer buffer
+ (let ((beg (point-min))
+ (end (point-max))
+ (total (buffer-size)))
+ (or (/= beg 1) (/= end (1+ total))))))
+
+(defun helm-goto-char (loc)
+ "Go to char, revealing if necessary."
+ (require 'org) ; On some old Emacs versions org may not be loaded.
+ (goto-char loc)
+ (let ((fn (cond ((eq major-mode 'org-mode) #'org-reveal)
+ ((and (boundp 'outline-minor-mode)
+ outline-minor-mode)
+ (lambda () (outline-flag-subtree nil))))))
+ ;; outline may fail in some conditions e.g. with markdown enabled
+ ;; (issue #1919).
+ (condition-case nil
+ (and fn (funcall fn))
+ (error nil))))
+
+(defun helm-goto-line (lineno &optional noanim)
+ "Goto LINENO opening only outline headline if needed.
+Animation is used unless NOANIM is non--nil."
+ (helm-log-run-hook 'helm-goto-line-before-hook)
+ (helm-match-line-cleanup)
+ (unless helm-alive-p
+ (with-helm-current-buffer
+ (unless helm-yank-point (setq helm-yank-point (point)))))
+ (goto-char (point-min))
+ (helm-goto-char (point-at-bol lineno))
+ (unless noanim
+ (helm-highlight-current-line)))
+
+(defun helm-save-pos-to-register-before-jump ()
+ "Save current buffer position to `helm-save-pos-before-jump-register'.
+To use this add it to `helm-goto-line-before-hook'."
+ (with-helm-current-buffer
+ (unless helm-in-persistent-action
+ (point-to-register helm-save-pos-before-jump-register))))
+
+(defun helm-save-current-pos-to-mark-ring ()
+ "Save current buffer position to mark ring.
+To use this add it to `helm-goto-line-before-hook'."
+ (with-helm-current-buffer
+ (unless helm-in-persistent-action
+ (set-marker (mark-marker) (point))
+ (push-mark (point) 'nomsg))))
+
+(defun helm-show-all-in-this-source-only (arg)
+ "Show only current source of this helm session with all its candidates.
+With a numeric prefix arg show only the ARG number of candidates."
+ (interactive "p")
+ (with-helm-alive-p
+ (with-helm-window
+ (with-helm-default-directory (helm-default-directory)
+ (let ((helm-candidate-number-limit (and (> arg 1) arg)))
+ (helm-set-source-filter
+ (list (assoc-default 'name (helm-get-current-source)))))))))
+(put 'helm-show-all-in-this-source-only 'helm-only t)
+
+(defun helm-display-all-sources ()
+ "Display all sources previously hidden by `helm-set-source-filter'."
+ (interactive)
+ (with-helm-alive-p
+ (helm-set-source-filter nil)))
+(put 'helm-display-all-sources 'helm-only t)
+
+(defun helm-displaying-source-names ()
+ "Return the list of sources name for this helm session."
+ (with-current-buffer helm-buffer
+ (goto-char (point-min))
+ (cl-loop with pos
+ while (setq pos (next-single-property-change (point) 'helm-header))
+ do (goto-char pos)
+ collect (buffer-substring-no-properties (point-at-bol)(point-at-eol))
+ do (forward-line 1))))
+
+(defun helm-handle-winner-boring-buffers ()
+ "Add `helm-buffer' to `winner-boring-buffers' when quitting/exiting helm.
+Add this function to `helm-cleanup-hook' when you don't want to see helm buffers
+after running winner-undo/redo."
+ (require 'winner)
+ (cl-pushnew helm-buffer winner-boring-buffers :test 'equal))
+(add-hook 'helm-cleanup-hook #'helm-handle-winner-boring-buffers)
+
+(defun helm-quit-and-find-file ()
+ "Drop into `helm-find-files' from `helm'.
+If current selection is a buffer or a file, `helm-find-files'
+from its directory."
+ (interactive)
+ (with-helm-alive-p
+ (require 'helm-grep)
+ (require 'helm-elisp)
+ (helm-run-after-exit
+ (lambda (f)
+ ;; Ensure specifics `helm-execute-action-at-once-if-one'
+ ;; fns don't run here.
+ (let (helm-execute-action-at-once-if-one
+ helm-actions-inherit-frame-settings) ; use this-command
+ (if (file-exists-p f)
+ (helm-find-files-1 (file-name-directory f)
+ (concat
+ "^"
+ (regexp-quote
+ (if helm-ff-transformer-show-only-basename
+ (helm-basename f) f))))
+ (helm-find-files-1 f))))
+ (let* ((sel (helm-get-selection))
+ (marker (if (consp sel) (markerp (cdr sel))))
+ (grep-line (and (stringp sel)
+ (helm-grep-split-line sel)))
+ (bmk-name (and (stringp sel)
+ (not grep-line)
+ (replace-regexp-in-string "\\`\\*" "" sel)))
+ (bmk (and bmk-name (assoc bmk-name bookmark-alist)))
+ (buf (helm-aif (and (bufferp sel) (get-buffer sel))
+ (buffer-name it)))
+ (default-preselection (or (buffer-file-name helm-current-buffer)
+ default-directory)))
+ (cond
+ ;; Buffer.
+ (buf (or (buffer-file-name sel)
+ (car (rassoc buf dired-buffers))
+ (and (with-current-buffer buf
+ (eq major-mode 'org-agenda-mode))
+ org-directory
+ (expand-file-name org-directory))
+ (with-current-buffer buf
+ (expand-file-name default-directory))))
+ ;; imenu (marker).
+ (marker
+ (or (buffer-file-name (marker-buffer (cdr sel)))
+ default-preselection))
+ ;; Bookmark.
+ (bmk (helm-aif (bookmark-get-filename bmk)
+ (if (and helm--url-regexp
+ (string-match helm--url-regexp it))
+ it (expand-file-name it))
+ (expand-file-name default-directory)))
+ ((and (stringp sel) (or (file-remote-p sel)
+ (file-exists-p sel)))
+ (expand-file-name sel))
+ ;; Grep.
+ ((and grep-line (file-exists-p (car grep-line)))
+ (expand-file-name (car grep-line)))
+ ;; Occur.
+ (grep-line
+ (with-current-buffer (get-buffer (car grep-line))
+ (expand-file-name (or (buffer-file-name) default-directory))))
+ ;; Url.
+ ((and (stringp sel) helm--url-regexp (string-match helm--url-regexp sel)) sel)
+ ;; Exit brutally from a `with-helm-show-completion'
+ ((and helm-show-completion-overlay
+ (overlayp helm-show-completion-overlay))
+ (delete-overlay helm-show-completion-overlay)
+ (remove-hook 'helm-move-selection-after-hook 'helm-show-completion)
+ (expand-file-name default-preselection))
+ ;; Default.
+ (t (expand-file-name default-preselection)))))))
+(put 'helm-quit-and-find-file 'helm-only t)
+
+(defun helm-generic-sort-fn (s1 s2)
+ "Sort predicate function for helm candidates.
+Args S1 and S2 can be single or \(display . real\) candidates,
+that is sorting is done against real value of candidate."
+ (let* ((qpattern (regexp-quote helm-pattern))
+ (reg1 (concat "\\_<" qpattern "\\_>"))
+ (reg2 (concat "\\_<" qpattern))
+ (reg3 helm-pattern)
+ (split (helm-mm-split-pattern helm-pattern))
+ (str1 (if (consp s1) (cdr s1) s1))
+ (str2 (if (consp s2) (cdr s2) s2))
+ (score (lambda (str r1 r2 r3 lst)
+ (+ (if (string-match (concat "\\`" qpattern) str) 1 0)
+ (cond ((string-match r1 str) 5)
+ ((and (string-match " " qpattern)
+ (string-match
+ (concat "\\_<" (regexp-quote (car lst))) str)
+ (cl-loop for r in (cdr lst)
+ always (string-match r str))) 4)
+ ((and (string-match " " qpattern)
+ (cl-loop for r in lst
+ always (string-match r str))) 3)
+ ((string-match r2 str) 2)
+ ((string-match r3 str) 1)
+ (t 0)))))
+ (sc1 (funcall score str1 reg1 reg2 reg3 split))
+ (sc2 (funcall score str2 reg1 reg2 reg3 split)))
+ (cond ((or (zerop (string-width qpattern))
+ (and (zerop sc1) (zerop sc2)))
+ (string-lessp str1 str2))
+ ((= sc1 sc2)
+ (< (length str1) (length str2)))
+ (t (> sc1 sc2)))))
+
+(cl-defun helm-file-human-size (size &optional (kbsize helm-default-kbsize))
+ "Return a string showing SIZE of a file in human readable form.
+SIZE can be an integer or a float depending it's value.
+`file-attributes' will take care of that to avoid overflow error.
+KBSIZE is a floating point number, defaulting to `helm-default-kbsize'."
+ (cl-loop with result = (cons "B" size)
+ for i in '("k" "M" "G" "T" "P" "E" "Z" "Y")
+ while (>= (cdr result) kbsize)
+ do (setq result (cons i (/ (cdr result) kbsize)))
+ finally return
+ (helm-acase (car result)
+ ("B" (format "%s" size))
+ (t (format "%.1f%s" (cdr result) it)))))
+
+(cl-defun helm-file-attributes
+ (file &key type links uid gid access-time modif-time
+ status size mode gid-change inode device-num dired human-size
+ mode-type mode-owner mode-group mode-other (string t))
+ "Return `file-attributes' elements of FILE separately according to key value.
+Availables keys are:
+- TYPE: Same as nth 0 `files-attributes' if STRING is nil
+ otherwise return either symlink, directory or file (default).
+- LINKS: See nth 1 `files-attributes'.
+- UID: See nth 2 `files-attributes'.
+- GID: See nth 3 `files-attributes'.
+- ACCESS-TIME: See nth 4 `files-attributes', however format time
+ when STRING is non--nil (the default).
+- MODIF-TIME: See nth 5 `files-attributes', same as above.
+- STATUS: See nth 6 `files-attributes', same as above.
+- SIZE: See nth 7 `files-attributes'.
+- MODE: See nth 8 `files-attributes'.
+- GID-CHANGE: See nth 9 `files-attributes'.
+- INODE: See nth 10 `files-attributes'.
+- DEVICE-NUM: See nth 11 `files-attributes'.
+- DIRED: A line similar to what 'ls -l' return.
+- HUMAN-SIZE: The size in human form, see `helm-file-human-size'.
+- MODE-TYPE, mode-owner,mode-group, mode-other: Split what
+ nth 7 `files-attributes' return in four categories.
+- STRING: When non--nil (default) `helm-file-attributes' return
+ more friendly values.
+If you want the same behavior as `files-attributes' ,
+\(but with return values in proplist\) use a nil value for STRING.
+However when STRING is non--nil, time and type value are different from what
+you have in `file-attributes'."
+ (helm-aif (file-attributes file string)
+ (let* ((all (cl-destructuring-bind
+ (type links uid gid access-time modif-time
+ status size mode gid-change inode device-num)
+ it
+ (list :type (if string
+ (cond ((stringp type) "symlink") ; fname
+ (type "directory") ; t
+ (t "file")) ; nil
+ type)
+ :links links
+ :uid uid
+ :gid gid
+ :access-time (if string
+ (format-time-string
+ "%Y-%m-%d %R" access-time)
+ access-time)
+ :modif-time (if string
+ (format-time-string
+ "%Y-%m-%d %R" modif-time)
+ modif-time)
+ :status (if string
+ (format-time-string
+ "%Y-%m-%d %R" status)
+ status)
+ :size size
+ :mode mode
+ :gid-change gid-change
+ :inode inode
+ :device-num device-num)))
+ (modes (helm-split-mode-file-attributes (cl-getf all :mode))))
+ (cond (type (cl-getf all :type))
+ (links (cl-getf all :links))
+ (uid (cl-getf all :uid))
+ (gid (cl-getf all :gid))
+ (access-time (cl-getf all :access-time))
+ (modif-time (cl-getf all :modif-time))
+ (status (cl-getf all :status))
+ (size (cl-getf all :size))
+ (mode (cl-getf all :mode))
+ (gid-change (cl-getf all :gid-change))
+ (inode (cl-getf all :inode))
+ (device-num (cl-getf all :device-num))
+ (dired (concat
+ (helm-split-mode-file-attributes
+ (cl-getf all :mode) t) " "
+ (number-to-string (cl-getf all :links)) " "
+ (cl-getf all :uid) ":"
+ (cl-getf all :gid) " "
+ (if human-size
+ (helm-file-human-size (cl-getf all :size))
+ (int-to-string (cl-getf all :size))) " "
+ (cl-getf all :modif-time)))
+ (human-size (helm-file-human-size (cl-getf all :size)))
+ (mode-type (cl-getf modes :mode-type))
+ (mode-owner (cl-getf modes :user))
+ (mode-group (cl-getf modes :group))
+ (mode-other (cl-getf modes :other))
+ (t (append all modes))))))
+
+(defun helm-split-mode-file-attributes (str &optional string)
+ "Split mode file attributes STR into a proplist.
+If STRING is non--nil return instead a space separated string."
+ (cl-loop with type = (substring str 0 1)
+ with cdr = (substring str 1)
+ for i across cdr
+ for count from 1
+ if (<= count 3)
+ concat (string i) into user
+ if (and (> count 3) (<= count 6))
+ concat (string i) into group
+ if (and (> count 6) (<= count 9))
+ concat (string i) into other
+ finally return
+ (if string
+ (mapconcat 'identity (list type user group other) " ")
+ (list :mode-type type :user user :group group :other other))))
+
+(defun helm-format-columns-of-files (files)
+ "Same as `dired-format-columns-of-files'.
+Inlined here for compatibility."
+ (let ((beg (point)))
+ (completion--insert-strings files)
+ (put-text-property beg (point) 'mouse-face nil)))
+
+(defmacro with-helm-display-marked-candidates (buffer-or-name candidates &rest body)
+ (declare (indent 0) (debug t))
+ (helm-with-gensyms (buffer window)
+ `(let* ((,buffer (temp-buffer-window-setup ,buffer-or-name))
+ (helm-always-two-windows t)
+ (helm-split-window-default-side
+ (if (eq helm-split-window-default-side 'same)
+ 'below helm-split-window-default-side))
+ helm-split-window-inside-p
+ helm-reuse-last-window-split-state
+ ,window)
+ (with-current-buffer ,buffer
+ (helm-format-columns-of-files ,candidates))
+ (unwind-protect
+ (with-selected-window
+ (setq ,window (temp-buffer-window-show
+ ,buffer
+ '(display-buffer-below-selected
+ (window-height . fit-window-to-buffer))))
+ (progn ,@body))
+ (quit-window 'kill ,window)))))
+
+;;; Persistent Action Helpers
+;;
+;;
+;; Internal
+(defvar helm-match-line-overlay nil)
+(defvar helm--match-item-overlays nil)
+
+(defun helm-highlight-current-line (&optional start end buf face)
+ "Highlight and underline current position"
+ (let* ((start (or start (line-beginning-position)))
+ (end (or end (1+ (line-end-position))))
+ start-match end-match
+ (args (list start end buf))
+ (case-fold-search (if helm-alive-p
+ (helm-set-case-fold-search)
+ case-fold-search)))
+ ;; Highlight the current line.
+ (if (not helm-match-line-overlay)
+ (setq helm-match-line-overlay (apply 'make-overlay args))
+ (apply 'move-overlay helm-match-line-overlay args))
+ (overlay-put helm-match-line-overlay
+ 'face (or face 'helm-selection-line))
+ ;; Now highlight matches only if we are in helm session, we are
+ ;; maybe coming from helm-grep-mode or helm-moccur-mode buffers.
+ (when helm-alive-p
+ (if (or (null helm-highlight-matches-around-point-max-lines)
+ (zerop helm-highlight-matches-around-point-max-lines))
+ (setq start-match start
+ end-match end)
+ (setq start-match
+ (save-excursion
+ (forward-line
+ (- helm-highlight-matches-around-point-max-lines))
+ (point-at-bol))
+ end-match
+ (save-excursion
+ (forward-line
+ helm-highlight-matches-around-point-max-lines)
+ (point-at-bol))))
+ (catch 'empty-line
+ (cl-loop with ov
+ for r in (helm-remove-if-match
+ "\\`!" (helm-mm-split-pattern
+ (if (with-helm-buffer
+ ;; Needed for highlighting AG matches.
+ (assq 'pcre (helm-get-current-source)))
+ (helm--translate-pcre-to-elisp helm-input)
+ helm-input)))
+ do (save-excursion
+ (goto-char start-match)
+ (while (condition-case _err
+ (if helm-migemo-mode
+ (helm-mm-migemo-forward r end-match t)
+ (re-search-forward r end-match t))
+ (invalid-regexp nil))
+ (let ((s (match-beginning 0))
+ (e (match-end 0)))
+ (if (= s e)
+ (throw 'empty-line nil)
+ (push (setq ov (make-overlay s e))
+ helm--match-item-overlays)
+ (overlay-put ov 'face 'helm-match-item)
+ (overlay-put ov 'priority 1))))))))
+ (recenter)))
+
+(defun helm--translate-pcre-to-elisp (regexp)
+ "Should translate pcre REGEXP to elisp regexp.
+Assume regexp is a pcre based regexp."
+ (with-temp-buffer
+ (insert " " regexp " ")
+ (goto-char (point-min))
+ (save-excursion
+ ;; match (){}| unquoted
+ (helm-awhile (and (re-search-forward "\\([(){}|]\\)" nil t)
+ (match-string 1))
+ (let ((pos (match-beginning 1)))
+ (if (eql (char-before pos) ?\\)
+ (delete-region pos (1- pos))
+ (replace-match (concat "\\" it) t t nil 1)))))
+ ;; match \s or \S
+ (helm-awhile (and (re-search-forward "\\S\\?\\(\\s\\[sS]\\)[^-]" nil t)
+ (match-string 1))
+ (replace-match (concat it "-") t t nil 1))
+ (buffer-substring (1+ (point-min)) (1- (point-max)))))
+
+(defun helm-match-line-cleanup ()
+ (when helm-match-line-overlay
+ (delete-overlay helm-match-line-overlay)
+ (setq helm-match-line-overlay nil))
+ (when helm--match-item-overlays
+ (mapc 'delete-overlay helm--match-item-overlays)))
+
+(defun helm-match-line-cleanup-maybe ()
+ (when (helm-empty-buffer-p)
+ (helm-match-line-cleanup)))
+
+(defun helm-match-line-update ()
+ (when helm-match-line-overlay
+ (delete-overlay helm-match-line-overlay)
+ (helm-highlight-current-line)))
+
+(defun helm-persistent-autoresize-hook ()
+ (when (and helm-buffers-to-resize-on-pa
+ (member helm-buffer helm-buffers-to-resize-on-pa)
+ (eq helm-split-window-state 'vertical))
+ (set-window-text-height (helm-window) helm-resize-on-pa-text-height)))
+
+(defun helm-match-line-cleanup-pulse ()
+ (run-with-timer 0.3 nil #'helm-match-line-cleanup))
+
+(add-hook 'helm-after-update-hook 'helm-match-line-cleanup-maybe)
+(add-hook 'helm-after-persistent-action-hook 'helm-persistent-autoresize-hook)
+(add-hook 'helm-cleanup-hook 'helm-match-line-cleanup)
+(add-hook 'helm-after-action-hook 'helm-match-line-cleanup-pulse)
+(add-hook 'helm-after-persistent-action-hook 'helm-match-line-update)
+
+;;; Popup buffer-name or filename in grep/moccur/imenu-all.
+;;
+(defvar helm--show-help-echo-timer nil)
+
+(defun helm-cancel-help-echo-timer ()
+ (when helm--show-help-echo-timer
+ (cancel-timer helm--show-help-echo-timer)
+ (setq helm--show-help-echo-timer nil)))
+
+(defun helm-maybe-show-help-echo ()
+ (when helm--show-help-echo-timer
+ (cancel-timer helm--show-help-echo-timer)
+ (setq helm--show-help-echo-timer nil))
+ (when (and helm-alive-p
+ helm-popup-tip-mode
+ (member (assoc-default 'name (helm-get-current-source))
+ helm-sources-using-help-echo-popup))
+ (setq helm--show-help-echo-timer
+ (run-with-timer
+ 1 nil
+ (lambda ()
+ (save-selected-window
+ (with-helm-window
+ (helm-aif (get-text-property (point-at-bol) 'help-echo)
+ (popup-tip (concat " " (abbreviate-file-name
+ (replace-regexp-in-string "\n.*" "" it)))
+ :around nil
+ :point (save-excursion
+ (end-of-visual-line) (point)))))))))))
+
+;;;###autoload
+(define-minor-mode helm-popup-tip-mode
+ "Show help-echo informations in a popup tip at end of line."
+ :global t
+ (require 'popup)
+ (if helm-popup-tip-mode
+ (progn
+ (add-hook 'helm-move-selection-after-hook 'helm-maybe-show-help-echo)
+ (add-hook 'helm-cleanup-hook 'helm-cancel-help-echo-timer))
+ (remove-hook 'helm-move-selection-after-hook 'helm-maybe-show-help-echo)
+ (remove-hook 'helm-cleanup-hook 'helm-cancel-help-echo-timer)))
+
+(defun helm-open-file-with-default-tool (file)
+ "Open FILE with the default tool on this platform."
+ (let (process-connection-type)
+ (if (eq system-type 'windows-nt)
+ (helm-w32-shell-execute-open-file file)
+ (start-process "helm-open-file-with-default-tool"
+ nil
+ (cond ((eq system-type 'gnu/linux)
+ "xdg-open")
+ ((or (eq system-type 'darwin) ;; Mac OS X
+ (eq system-type 'macos)) ;; Mac OS 9
+ "open"))
+ file))))
+
+(defun helm-open-dired (file)
+ "Opens a dired buffer in FILE's directory. If FILE is a
+directory, open this directory."
+ (if (file-directory-p file)
+ (dired file)
+ (dired (file-name-directory file))
+ (dired-goto-file file)))
+
+(defun helm-require-or-error (feature function)
+ (or (require feature nil t)
+ (error "Need %s to use `%s'." feature function)))
+
+(defun helm-find-file-as-root (candidate)
+ (let* ((buf (helm-basename candidate))
+ (host (file-remote-p candidate 'host))
+ (remote-path (format "/%s:%s:%s"
+ helm-su-or-sudo
+ (or host "")
+ (expand-file-name
+ (if host
+ (file-remote-p candidate 'localname)
+ candidate))))
+ non-essential)
+ (if (buffer-live-p (get-buffer buf))
+ (progn
+ (set-buffer buf)
+ (find-alternate-file remote-path))
+ (find-file remote-path))))
+
+(defun helm-find-many-files (_ignore)
+ "Simple action that run `find-file' on marked candidates.
+Run `helm-find-many-files-after-hook' at end"
+ (let ((helm--reading-passwd-or-string t))
+ (mapc 'find-file (helm-marked-candidates))
+ (helm-log-run-hook 'helm-find-many-files-after-hook)))
+
+(defun helm-read-repeat-string (prompt &optional count)
+ "Prompt as many time PROMPT is not empty.
+If COUNT is non--nil add a number after each prompt."
+ (cl-loop with elm
+ while (not (string= elm ""))
+ for n from 1
+ do (when count
+ (setq prompt (concat prompt (int-to-string n) ": ")))
+ collect (setq elm (helm-read-string prompt)) into lis
+ finally return (remove "" lis)))
+
+(defun helm-html-bookmarks-to-alist (file url-regexp bmk-regexp)
+ "Parse html bookmark FILE and return an alist with (title . url) as elements."
+ (let (bookmarks-alist url title)
+ (with-temp-buffer
+ (insert-file-contents file)
+ (goto-char (point-min))
+ (while (re-search-forward "href=\\|^ *<DT><A HREF=" nil t)
+ (forward-line 0)
+ (when (re-search-forward url-regexp nil t)
+ (setq url (match-string 0)))
+ (when (re-search-forward bmk-regexp nil t)
+ (setq title (url-unhex-string
+ (funcall helm-html-decode-entities-function
+ (match-string 1)))))
+ (push (cons title url) bookmarks-alist)
+ (forward-line)))
+ (nreverse bookmarks-alist)))
+
+(defun helm-html-entity-to-string (entity)
+ "Replace an html ENTITY by its string value.
+When unable to decode ENTITY returns nil."
+ (helm-aif (assoc entity helm-html-entities-alist)
+ (string (cdr it))
+ (save-match-data
+ (when (string-match "[0-9]+" entity)
+ (string (string-to-number (match-string 0 entity)))))))
+
+(defun helm-html-decode-entities-string (str)
+ "Decode entities in the string STR."
+ (save-match-data
+ (with-temp-buffer
+ (insert str)
+ (goto-char (point-min))
+ (while (re-search-forward "&#?\\([^;]*\\);" nil t)
+ (helm-aif (helm-html-entity-to-string (match-string 0))
+ (replace-match it)))
+ (buffer-string))))
+
+(provide 'helm-utils)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-utils.el ends here
--- /dev/null
+;;; helm-x-files.el --- helm auxiliary functions and sources. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; 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/>.
+
+;;; Code:
+
+(require 'helm-for-files)
+
+\f
+;;; List of files gleaned from every dired buffer
+;;
+;;
+(defun helm-files-in-all-dired-candidates ()
+ (save-excursion
+ (cl-loop for (f . b) in dired-buffers
+ when (buffer-live-p b)
+ append (let ((dir (with-current-buffer b dired-directory)))
+ (if (listp dir) (cdr dir)
+ (directory-files f t dired-re-no-dot))))))
+
+;; (dired '("~/" "~/.emacs.d/.emacs-custom.el" "~/.emacs.d/.emacs.bmk"))
+
+(defclass helm-files-dired-source (helm-source-sync helm-type-file)
+ ((candidates :initform #'helm-files-in-all-dired-candidates)))
+
+(defvar helm-source-files-in-all-dired
+ (helm-make-source "Files in all dired buffer." 'helm-files-dired-source))
+
+;;; session.el files
+;;
+;; session (http://emacs-session.sourceforge.net/) is an alternative to
+;; recentf that saves recent file history and much more.
+(defvar session-file-alist)
+(defclass helm-source-session-class (helm-source-sync)
+ ((candidates :initform (lambda ()
+ (cl-delete-if-not
+ (lambda (f)
+ (or (string-match helm-tramp-file-name-regexp f)
+ (file-exists-p f)))
+ (mapcar 'car session-file-alist))))
+ (keymap :initform helm-generic-files-map)
+ (help-message :initform helm-generic-file-help-message)
+ (action :initform 'helm-type-file-actions)))
+
+(defvar helm-source-session nil
+ "File list from emacs-session.")
+
+(defcustom helm-session-fuzzy-match nil
+ "Enable fuzzy matching in `helm-source-session' when non--nil."
+ :group 'helm-files
+ :type 'boolean
+ :set (lambda (var val)
+ (set var val)
+ (setq helm-source-session
+ (helm-make-source "Session" 'helm-source-session-class
+ :fuzzy-match val))))
+
+\f
+;;; External searching file tools.
+;;
+;; Tracker desktop search
+
+(defun helm-source-tracker-transformer (candidates _source)
+ ;; loop through tracker candidates selecting out file:// lines
+ ;; then select part after file:// and url decode to get straight filenames
+ (cl-loop for cand in candidates
+ when (and (stringp cand)
+ (string-match "\\`[[:space:]]*file://\\(.*\\)" cand))
+ collect (url-unhex-string (match-string 1 cand))))
+
+(defvar helm-source-tracker-search
+ (helm-build-async-source "Tracker Search"
+ :candidates-process
+ (lambda ()
+ ;; the tracker-search command has been deprecated, now invoke via tracker
+ ;; also, disable the contextual snippets which we don't currently use
+ (start-process "tracker-search-process" nil
+ "tracker" "search"
+ "--disable-snippets"
+ "--disable-color"
+ "--limit=512"
+ helm-pattern))
+ ;; new simplified transformer of tracker search results
+ :filtered-candidate-transformer #'helm-source-tracker-transformer
+ ;;(multiline) ; https://github.com/emacs-helm/helm/issues/529
+ :keymap helm-generic-files-map
+ :action 'helm-type-file-actions
+ :action-transformer '(helm-transform-file-load-el
+ helm-transform-file-browse-url)
+ :requires-pattern 3)
+ "Source for retrieving files matching the current input pattern
+with the tracker desktop search.")
+
+;; Spotlight (MacOS X desktop search)
+(defclass helm-mac-spotlight-source (helm-source-async helm-type-file)
+ ((candidates-process :initform
+ (lambda ()
+ (start-process
+ "mdfind-process" nil "mdfind" helm-pattern)))
+ (requires-pattern :initform 3)))
+
+(defvar helm-source-mac-spotlight
+ (helm-make-source "mdfind" 'helm-mac-spotlight-source)
+ "Source for retrieving files via Spotlight's command line
+utility mdfind.")
+
+(provide 'helm-x-files)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-x-files.el ends here
+++ /dev/null
-;;; helm-aws-autoloads.el --- automatically extracted autoloads
-;;
-;;; Code:
-(add-to-list 'load-path (or (file-name-directory #$) (car load-path)))
-\f
-;;;### (autoloads nil "helm-aws" "helm-aws.el" (22215 7747 0 0))
-;;; Generated autoloads from helm-aws.el
-
-(autoload 'helm-aws "helm-aws" "\
-Show helm with a table of aws information.
-
-\(fn)" t nil)
-
-;;;***
-\f
-;; Local Variables:
-;; version-control: never
-;; no-byte-compile: t
-;; no-update-autoloads: t
-;; End:
-;;; helm-aws-autoloads.el ends here
+++ /dev/null
-(define-package "helm-aws" "20151124.133" "Manage AWS EC2 server instances directly from Emacs" '((helm "1.5.3") (cl-lib "0.5") (s "1.9.0")) :url "https://github.com/istib/helm-aws")
+++ /dev/null
-;;; helm-aws.el --- Manage AWS EC2 server instances directly from Emacs
-
-;; Copyright (C) 2014 istib
-
-;; Author: istib
-;; URL: https://github.com/istib/helm-aws
-;; Package-Version: 20151124.133
-;; Version: 20141205.1
-;; X-Original-Version: 0.2
-;; Package-Requires: ((helm "1.5.3")(cl-lib "0.5")(s "1.9.0"))
-;; Keywords:
-
-;; This file is not 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:
-
-;; Manage AWS EC2 server instances directly from Emacs
-
-;; A call to `helm-aws' will show a list of running instances on your configured
-;; AWS account. Helm actions to launch a terminal, dired, or ping are accessible.
-;;
-;; Requires a configured installation of AWS command-line interface (http://aws.amazon.com/cli/)
-
-
-;;; Code:
-(require 'json)
-(require 'cl-lib)
-(require 's)
-
-(defvar aws-user-account
- "ubuntu"
- "User account name for AWS servers. Assuming that your PEM keys are placed on each instance.")
-
-(defvar aws-ec2-command
- "aws ec2 describe-instances"
- "Command to list instances. Run `aws configure` to set up AWS cli.")
-
-(defun aws-run-ec2-command ()
- "Return the full json from running describe-instances."
- (let ((aws-result-buffer (generate-new-buffer-name "*aws-ec2*")))
- (with-temp-buffer
- (shell-command aws-ec2-command (current-buffer) nil)
- (buffer-substring-no-properties (point-min) (point-max)))))
-
-(defun aws-parse-server-list (input)
- "Extract instances from describe-instances.
-Argument INPUT json input in string form."
- (let* ((json-object-type 'plist)
- (aws-json (json-read-from-string input))
- (reservations (plist-get aws-json :Reservations))
- (instances (mapcar (lambda (el) (plist-get el :Instances)) reservations))
- (instance-vector (cdr instances)) ;; drop first, as it's metadata
- (instance-list (mapcar (lambda (x) (elt x 0)) instance-vector)))
- instance-list))
-
-(defun aws-is-instance-active-p (instance)
- "Predicate that determines whether the given INSTANCE is running."
- (let* ((state (plist-get instance :State))
- (code (plist-get state :Code)))
- (eq code 16)))
-
-(defun aws-format-instance-helm-row (instance)
- "Constructs a human-friendly string of a server instance.
-show: <name>, <IP> and <launch date>.
-Argument INSTANCE is the aws json in plist form"
- (let* ((ip (plist-get instance :PrivateIpAddress))
- (instance-id (plist-get instance :InstanceId))
- (instance-state (plist-get (plist-get instance :State) :Name))
- (tags (plist-get instance :Tags))
- (nameTag (cl-remove-if-not #'(lambda (tag) (string= (plist-get tag :Key) "Name")) tags))
- (name (if (= (length nameTag) 1) (plist-get (elt nameTag 0) :Value) instance-id))
- (launch-time (plist-get instance :LaunchTime))
- (launch-date (car (split-string launch-time "T")))
- (formatted-string
- (concat (format "%-30s" (s-truncate 30 name)) " | "
- (format "%15s" ip) " | "
- (format "%-10s" instance-state) " | "
- launch-date)))
- (cons formatted-string instance)))
-
-(defun aws-get-ip-from-instance (instance-json)
- "Extracts IP address from INSTANCE-JSON."
- (plist-get instance-json :PrivateIpAddress))
-
-(defun aws-sort-helm-rows (a b)
- "Compare results from `aws-format-instance-helm-row' A and B."
- (string< (downcase (car a)) (downcase (car b))))
-
-(defun aws-get-active-instances ()
- "Used to populate data for `helm-aws'."
- (let* ((aws-result (aws-run-ec2-command))
- (instance-list (aws-parse-server-list aws-result))
- (instance-list (mapcar 'aws-format-instance-helm-row instance-list))
- (instance-list (sort instance-list 'aws-sort-helm-rows))
- )
- instance-list))
-
-(defun aws-ssh-into-instance (ip-address)
- "Use SSH to connect to remote instance.
-Argument IP-ADDRESS is the ip address for the instance you want ssh to."
- (let ((switches (list ip-address "-l" aws-user-account)))
- (set-buffer (apply 'make-term "ssh" "ssh" nil switches))
- (term-mode)
- (term-char-mode)
- (switch-to-buffer "*ssh*")))
-
-(defun aws-find-file-on-instance (ip-address)
- "Use dired to access directory structure of remote instance.
-Argument IP-ADDRESS is the ip address for the instance you want to run `find-file' on."
- (let ((path (concat "/ssh:" aws-user-account "@" ip-address ":")))
- (find-file path)))
-
-(defun aws-instance-details (instance-json)
- "Dump the instance json into a buffer *aws-details*.
-Argument INSTANCE-JSON is the json behind the row of helm data."
- (interactive)
- (let* ((json-encoding-pretty-print t)
- (json (json-encode instance-json)))
- (switch-to-buffer (get-buffer-create "*aws-details*"))
- (let ((inhibit-read-only t))
- (erase-buffer)
- (delete-other-windows)
- (insert json)
- (goto-char (point-min))
- (set-buffer-modified-p nil)
- (view-mode)
- (message "Press q to quit."))))
-
-(defun aws-instance-toggle-stop-start (instance-json)
- "Toggle the instance state for INSTANCE-JSON.
-If it is stopped, start it. If it is running, stop it."
- (let* ((instance-id (plist-get instance-json :InstanceId))
- (instance-state (plist-get (plist-get instance-json :State) :Name))
- (toggle-action (if (string= instance-state "running") "stop-instances" "start-instances"))
- (command (format "aws ec2 %s --instance-ids %s" toggle-action instance-id)))
- (compile command)))
-
-;;;###autoload
-(defun helm-aws ()
- "Show helm with a table of aws information."
- (interactive)
- (let ((choices (aws-get-active-instances)))
- (helm
- :buffer "*helm-aws*"
- :sources '((name . "EC2 Instances")
- (candidates . choices)
- (action . (("SSH" .
- (lambda (instance-json)
- (aws-ssh-into-instance (aws-get-ip-from-instance instance-json))))
- ("Dired" .
- (lambda (instance-json)
- (aws-find-file-on-instance (aws-get-ip-from-instance instance-json))))
- ("Ping" .
- (lambda (instance-json)
- (ping (aws-get-ip-from-instance instance-json))))
- ("Insert IP into buffer" .
- (lambda (instance-json)
- (insert (aws-get-ip-from-instance instance-json))))
- ("Save instance json to buffer" . aws-instance-details)
- ("Toggle Stop/Start instance" . aws-instance-toggle-stop-start)))))))
-
-(provide 'helm-aws)
-
-;;; helm-aws.el ends here
--- /dev/null
+;;; helm-aws-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+
+(add-to-list 'load-path (directory-file-name
+ (or (file-name-directory #$) (car load-path))))
+
+\f
+;;;### (autoloads nil "helm-aws" "helm-aws.el" (0 0 0 0))
+;;; Generated autoloads from helm-aws.el
+
+(autoload 'helm-aws "helm-aws" "\
+Show helm with a table of aws information.
+
+\(fn)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-aws" '("aws-")))
+
+;;;***
+\f
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; coding: utf-8
+;; End:
+;;; helm-aws-autoloads.el ends here
--- /dev/null
+;;; -*- no-byte-compile: t -*-
+(define-package "helm-aws" "20180514.1032" "Manage AWS EC2 server instances directly from Emacs" '((helm "1.5.3") (cl-lib "0.5") (s "1.9.0")) :commit "b36c744b3f00f458635a91d1f5158fccbb5baef6" :authors '(("istib")) :maintainer '("istib") :url "https://github.com/istib/helm-aws")
--- /dev/null
+;;; helm-aws.el --- Manage AWS EC2 server instances directly from Emacs
+
+;; Copyright (C) 2014 istib
+
+;; Author: istib
+;; URL: https://github.com/istib/helm-aws
+;; Package-Version: 20180514.1032
+;; Version: 20141205.1
+;; X-Original-Version: 0.2
+;; Package-Requires: ((helm "1.5.3")(cl-lib "0.5")(s "1.9.0"))
+;; Keywords:
+
+;; This file is not 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:
+
+;; Manage AWS EC2 server instances directly from Emacs
+
+;; A call to `helm-aws' will show a list of running instances on your configured
+;; AWS account. Helm actions to launch a terminal, dired, or ping are accessible.
+;;
+;; Requires a configured installation of AWS command-line interface (http://aws.amazon.com/cli/)
+
+
+;;; Code:
+(require 'json)
+(require 'cl-lib)
+(require 's)
+
+(defgroup helm-aws-faces nil
+ "Customize the appearance of helm-aws."
+ :prefix "helm-"
+ :group 'helm-aws
+ :group 'helm-faces)
+
+(defface helm-aws-instance-state-running
+ '((t :inherit font-lock-builtin-face))
+ "Face used for running instances in `helm-aws'."
+ :group 'helm-aws-faces)
+
+(defface helm-aws-instance-state-stopped
+ '((t :inherit font-lock-comment-face
+ :slant italic
+ :foreground "red"))
+ "Face used for stopped instances in `helm-aws'."
+ :group 'helm-aws-faces)
+
+(defface helm-aws-instance-state-terminated
+ '((t :inherit font-lock-comment-face
+ :strike-through t))
+ "Face used for terminated instances in `helm-aws'."
+ :group 'helm-aws-faces)
+
+(defvar aws-user-account
+ "ubuntu"
+ "User account name for AWS servers. Assuming that your PEM keys are placed on each instance.")
+
+(defvar aws-ec2-command
+ "aws ec2 describe-instances"
+ "Command to list instances. Run `aws configure` to set up AWS cli.")
+
+(defun aws-run-ec2-command ()
+ "Return the full json from running describe-instances."
+ (let ((aws-result-buffer (generate-new-buffer-name "*aws-ec2*")))
+ (with-temp-buffer
+ (shell-command aws-ec2-command (current-buffer) nil)
+ (buffer-substring-no-properties (point-min) (point-max)))))
+
+(defun aws-parse-server-list (input)
+ "Extract instances from describe-instances.
+Argument INPUT json input in string form."
+ (let* ((json-object-type 'plist)
+ (aws-json (json-read-from-string input))
+ (reservations (plist-get aws-json :Reservations))
+ (instances (mapcar (lambda (el) (plist-get el :Instances)) reservations))
+ (instance-vector (cdr instances)) ;; drop first, as it's metadata
+ (instance-list (mapcar (lambda (x) (elt x 0)) instance-vector)))
+ instance-list))
+
+(defun aws-is-instance-active-p (instance)
+ "Predicate that determines whether the given INSTANCE is running."
+ (let* ((state (plist-get instance :State))
+ (code (plist-get state :Code)))
+ (eq code 16)))
+
+(defun aws-format-instance-helm-row (instance)
+ "Constructs a human-friendly string of a server instance.
+show: <name>, <IP> and <launch date>.
+Argument INSTANCE is the aws json in plist form"
+ (let* ((ip (plist-get instance :PrivateIpAddress))
+ (instance-id (plist-get instance :InstanceId))
+ (instance-state (plist-get (plist-get instance :State) :Name))
+ (tags (plist-get instance :Tags))
+ (nameTag (cl-remove-if-not #'(lambda (tag) (string= (plist-get tag :Key) "Name")) tags))
+ (name (if (= (length nameTag) 1) (plist-get (elt nameTag 0) :Value) instance-id))
+ (launch-time (plist-get instance :LaunchTime))
+ (launch-date (car (split-string launch-time "T")))
+ (formatted-string
+ (concat
+ (propertize (format "%-30s" (s-truncate 30 name))
+ 'face (cond ((string= instance-state "stopped")
+ 'helm-aws-instance-state-stopped)
+ ((string= instance-state "terminated")
+ 'helm-aws-instance-state-terminated)
+ (t 'helm-aws-instance-state-running)))
+ " | " (format "%15s" (or ip ""))
+ " | " launch-date)))
+ (cons formatted-string instance)))
+
+(defun aws-get-ip-from-instance (instance-json)
+ "Extracts IP address from INSTANCE-JSON."
+ (plist-get instance-json :PrivateIpAddress))
+
+(defun aws-sort-helm-rows (a b)
+ "Compare results from `aws-format-instance-helm-row' A and B."
+ (string< (downcase (car a)) (downcase (car b))))
+
+(defun aws-get-active-instances ()
+ "Used to populate data for `helm-aws'."
+ (let* ((aws-result (aws-run-ec2-command))
+ (instance-list (aws-parse-server-list aws-result))
+ (instance-list (mapcar 'aws-format-instance-helm-row instance-list))
+ (instance-list (sort instance-list 'aws-sort-helm-rows))
+ )
+ instance-list))
+
+(defun aws-ssh-into-instance (ip-address)
+ "Use SSH to connect to remote instance.
+Argument IP-ADDRESS is the ip address for the instance you want ssh to."
+ (let ((switches (list ip-address "-l" aws-user-account)))
+ (set-buffer (apply 'make-term "ssh" "ssh" nil switches))
+ (term-mode)
+ (term-char-mode)
+ (switch-to-buffer "*ssh*")))
+
+(defun aws-find-file-on-instance (ip-address)
+ "Use dired to access directory structure of remote instance.
+Argument IP-ADDRESS is the ip address for the instance you want to run `find-file' on."
+ (let ((path (concat "/ssh:" aws-user-account "@" ip-address ":")))
+ (find-file path)))
+
+(defun aws-instance-details (instance-json)
+ "Dump the instance json into a buffer *aws-details*.
+Argument INSTANCE-JSON is the json behind the row of helm data."
+ (interactive)
+ (let* ((json-encoding-pretty-print t)
+ (json (json-encode instance-json)))
+ (switch-to-buffer (get-buffer-create "*aws-details*"))
+ (let ((inhibit-read-only t))
+ (erase-buffer)
+ (delete-other-windows)
+ (insert json)
+ (goto-char (point-min))
+ (set-buffer-modified-p nil)
+ (view-mode)
+ (message "Press q to quit."))))
+
+(defun aws-compile (command &optional comint)
+ "Invoke the compile function without saving buffers."
+ (let ((compilation-save-buffers-predicate '(lambda () nil)))
+ (compile command comint)))
+
+(defun aws-instance-toggle-stop-start (instance-json)
+ "Toggle the instance state for INSTANCE-JSON.
+If it is stopped, start it. If it is running, stop it."
+ (let* ((instance-id (plist-get instance-json :InstanceId))
+ (instance-state (plist-get (plist-get instance-json :State) :Name))
+ (toggle-action (if (string= instance-state "running") "stop-instances" "start-instances"))
+ (command (format "aws ec2 %s --instance-ids %s" toggle-action instance-id)))
+ (aws-compile command)))
+
+;;;###autoload
+(defun helm-aws ()
+ "Show helm with a table of aws information."
+ (interactive)
+ (let ((choices (aws-get-active-instances)))
+ (helm
+ :buffer "*helm-aws*"
+ :sources `((name . "EC2 Instances")
+ (candidates . ,choices)
+ (action . (("SSH" .
+ (lambda (instance-json)
+ (aws-ssh-into-instance (aws-get-ip-from-instance instance-json))))
+ ("Dired" .
+ (lambda (instance-json)
+ (aws-find-file-on-instance (aws-get-ip-from-instance instance-json))))
+ ("Ping" .
+ (lambda (instance-json)
+ (ping (aws-get-ip-from-instance instance-json))))
+ ("Insert IP into buffer" .
+ (lambda (instance-json)
+ (insert (aws-get-ip-from-instance instance-json))))
+ ("Save instance json to buffer" . aws-instance-details)
+ ("Toggle Stop/Start instance" . aws-instance-toggle-stop-start)))))))
+
+(provide 'helm-aws)
+
+;;; helm-aws.el ends here
+++ /dev/null
-Manage AWS EC2 server instances directly from Emacs
-
-A call to `helm-aws' will show a list of running instances on your configured
-AWS account. Helm actions to launch a terminal, dired, or ping are accessible.
-
-Requires a configured installation of AWS command-line interface (http://aws.amazon.com/cli/)
+++ /dev/null
-;;; helm-c-yasnippet-autoloads.el --- automatically extracted autoloads
-;;
-;;; Code:
-(add-to-list 'load-path (or (file-name-directory #$) (car load-path)))
-\f
-;;;### (autoloads nil "helm-c-yasnippet" "helm-c-yasnippet.el" (22156
-;;;;;; 56481 0 0))
-;;; Generated autoloads from helm-c-yasnippet.el
-
-(autoload 'helm-yas-complete "helm-c-yasnippet" "\
-List of yasnippet snippets using `helm' interface.
-
-\(fn)" t nil)
-
-(autoload 'helm-yas-visit-snippet-file "helm-c-yasnippet" "\
-List of yasnippet snippet files
-
-\(fn)" t nil)
-
-(autoload 'helm-yas-create-snippet-on-region "helm-c-yasnippet" "\
-Create a snippet from region.
-
-\(fn &optional START END FILE-NAME)" t nil)
-
-;;;***
-\f
-;; Local Variables:
-;; version-control: never
-;; no-byte-compile: t
-;; no-update-autoloads: t
-;; End:
-;;; helm-c-yasnippet-autoloads.el ends here
+++ /dev/null
-(define-package "helm-c-yasnippet" "20151231.10" "helm source for yasnippet.el" '((helm "1.7.7") (yasnippet "0.8.0") (cl-lib "0.3")) :keywords '("convenience" "emulation"))
+++ /dev/null
-;;; helm-c-yasnippet.el --- helm source for yasnippet.el -*- lexical-binding: t -*-
-
-;; Copyright (C) 2008, 2009, 2010, 2011 Kenji.I (Kenji Imakado) <ken.imakaadoNOSPAMgmail.com>
-;; Copyright (C) 2012,2013 Yuhei Maeda <yuhei.maeda_at_gmail.com>
-;; Copyright (C) 2014 Yuhei Maeda <yuhei.maeda_at_gmail.com>, Yasuyuki Oka <yasuyk_at_gmail.com>
-
-;; Author: Kenji.I (Kenji Imakado) <ken.imakaadoNOSPAMgmail.com>
-;; Version: 0.6.7
-;; Package-Version: 20151231.10
-;; Package-Requires: ((helm "1.7.7") (yasnippet "0.8.0") (cl-lib "0.3"))
-;; Keywords: convenience, emulation
-
-;; 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 2, or (at your option)
-;; any later version.
-
-;; This file 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 GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
-
-;;; Commentary:
-
-;; Actions: Insert snippet, Open snippet file, Open snippet file other window
-;; C-z: execute-persistent-action
-
-;;; Changelog:
-;; 2012/08/11 Port to helm
-;; Fixed bug on yasnippet 0.7.0
-;; 2012/08/23 Support yasnippet 0.8.0
-;;
-
-;;; Commands:
-;;
-;; Below are complete command list:
-;;
-;; `helm-yas-complete'
-;; List of yasnippet snippets using `helm' interface.
-;; `helm-yas-create-snippet-on-region'
-;; Create a snippet from region.
-;;
-;;; Customizable Options:
-;;
-;; Below are customizable option list:
-;;
-;; `helm-yas-not-display-dups'
-;; if non-nil not display duplicate snippet otherwise display all snippet
-;; default = t
-;; `helm-yas-display-msg-after-complete'
-;; if non-nil display snippet key message in minibuffer after Complete
-;; default = t
-;; `helm-yas-space-match-any-greedy'
-;; if non-nil helm pattern space match anyword greedy.
-;; default = nil
-;; `helm-yas-display-key-on-candidate'
-;; if non-nil helm display candidate(snippet name) include key
-;; default = nil
-
-;; here's my yasnippet's configuration
-;; (require 'yasnippet)
-;; (require 'helm-c-yasnippet)
-;; (setq helm-yas-space-match-any-greedy t) ;[default: nil]
-;; (global-set-key (kbd "C-c y") 'helm-yas-complete)
-;; (yas-global-mode 1)
-;; (yas-load-directory "<path>/<to>/snippets/")
-
-;;; Code:
-(require 'cl-lib)
-(require 'helm)
-(require 'helm-files)
-(require 'yasnippet)
-
-(defgroup helm-yasnippet nil
- "helm config yasnippet"
- :group 'helm)
-
-(defcustom helm-yas-not-display-dups t
- "if non-nil not display duplicate snippet otherwise display all snippet"
- :type 'boolean
- :group 'helm-yasnippet)
-
-(defcustom helm-yas-display-msg-after-complete t
- "if non-nil display snippet key message in minibuffer after Complete"
- :type 'boolean
- :group 'helm-yasnippet)
-
-(defcustom helm-yas-space-match-any-greedy nil
- "if non-nil helm pattern space match anyword greedy.
-pattern regexp: \"if else\" replace to \"if.*else\"
-match \"if (...) { ... } else { ... }\" and \"if, elsif, else ...\"
-quite convenience
-Default: nil"
- :type 'boolean
- :group 'helm-yasnippet)
-
-(defcustom helm-yas-display-key-on-candidate nil
- "if non-nil helm display candidate(snippet name) include key
-ex. [for] for (...) { ... }
-otherwise display just name
-ex. for (...) { ... }"
- :type 'boolean
- :group 'helm-yasnippet)
-
-(defcustom helm-yas-create-new-snippet-insert-function
- 'helm-yas-create-new-snippet-insert
- "Function to be called when create new insert file."
- :type 'function
- :group 'helm-yasnippet)
-
-(defface helm-yas-key '((t (:foreground "orange" :underline t)))
- "Face used in helm-yas-complete to show key triggers."
- :group 'helm-yasnippet)
-
-(defvar helm-yas-cur-snippets-alist nil)
-
-(defun helm-yas-create-new-snippet-insert (selected-text snippet-file)
- "Insert SELECTED-TEXT into SNIPPET-FILE."
- (let* ((name (file-name-sans-extension
- (file-name-nondirectory
- (directory-file-name snippet-file))))
- (string-format "# -*- mode: snippet -*-\n#name : %s\n#key : %s\n#contributor : %s\n# --\n"))
- (insert (format string-format name name user-full-name) selected-text)))
-
-(defun helm-yas-create-new-snippet-file (selected-text snippet-file)
- "Create snippet file with inserted SELECTED-TEXT into SNIPPET-FILE."
- (with-current-buffer (find-file snippet-file)
- (snippet-mode)
- (funcall helm-yas-create-new-snippet-insert-function selected-text snippet-file)))
-
-(defun helm-yas-create-new-snippet (selected-text &optional snippet-file)
- "Create snippet from SELECTED-TEXT into SNIPPET-FILE.
-If SNIPPET-FILE is nil, asks file name.
-If SNIPPET-FILE does not contain directory, it is placed in default snippet directory."
- (let* ((major-mode-dir (regexp-quote (symbol-name major-mode)))
- (yas-dir (expand-file-name (or (car-safe yas-snippet-dirs) yas-snippet-dirs)))
- (snippet-dir
- (or (helm-yas-find-recursively major-mode-dir yas-dir 'snippet-file)
- (let ((target-dir (format "%s/%s/" yas-dir major-mode-dir)))
- (if (yes-or-no-p (format "%s doesn't exist. Would you like to create this directory?" target-dir))
- (progn
- (make-directory target-dir)
- target-dir)
- (deactivate-mark)
- (error "Snippet creation failed"))))))
- (setq snippet-file
- (helm-aif snippet-file
- (expand-file-name snippet-file snippet-dir)
- (read-file-name "create snippet : " snippet-dir snippet-dir)))
- (when (file-exists-p snippet-file)
- (error "can't create file [%s] already exists" (file-name-nondirectory snippet-file)))
- (helm-yas-create-new-snippet-file selected-text snippet-file)))
-
-(defun helm-yas-find-recursively (regexp &optional directory predicate)
- (let* ((directory (or directory default-directory))
- (predfunc (cl-case predicate
- (dir 'file-directory-p)
- (file 'file-regular-p)
- (otherwise 'identity)))
- (files (cl-remove-if (lambda (s) (string-match "^\\." (file-name-nondirectory s))) (directory-files directory t)))
- (found nil)
- (result nil))
- (cl-loop for file in files
- unless found
- do (if (and (funcall predfunc file)
- (string-match regexp file))
- (progn (setq found t)
- (return (file-name-as-directory file)))
- (when (file-directory-p file)
- (setq result (helm-yas-find-recursively regexp file predicate))))
- finally (return result))))
-
-
-(defun helm-yas-build-cur-snippets-alist (&optional table)
- (let ((yas-choose-keys-first nil)
- (yas-choose-tables-first nil)
- (yas-buffer-local-condition 'always))
- (let* ((result-alist '((candidates) (transformed) (template-key-alist) (template-file-alist)))
- (cur-tables
- (if table
- (list table)
- (yas--get-snippet-tables)))
- (hash-value-alist nil))
- (let ((hashes (cl-loop for table in cur-tables
- collect (yas--table-hash table))))
- (cl-loop for hash in hashes
- do (maphash (lambda (k v)
- (let (a)
- (maphash (lambda (_n te)
- (setq a (append (list (cons k te)) a)))
- v)
- (setq hash-value-alist (append a hash-value-alist))))
- hash))
- (cl-loop with transformed
- with templates
- with template-key-alist
- with template-file-alist
- for lst in hash-value-alist
- for key = (car lst)
- for template-struct = (cdr lst)
- for name = (yas--template-name template-struct) ;`yas--template-name'
- for template = (yas--template-content template-struct) ;`yas--template-content'
- for file = (yas--template-load-file template-struct) ;`yas--template-content'
- do (progn (push template templates)
- (push `(,name . ,template) transformed)
- (push `(,template . ,key) template-key-alist)
- (push `(,template . ,file) template-file-alist)
- )
- finally (progn (push `(candidates . ,templates) result-alist)
- (push `(transformed . ,transformed) result-alist)
- (push `(template-file-alist . ,template-file-alist) result-alist)
- (push `(template-key-alist . ,template-key-alist) result-alist)))
- result-alist)
- )))
-
-(defun helm-yas-get-cmp-context ()
- "Return list (initial-input point-start point-end)
-like `yas--current-key'"
- (let ((start (point))
- (end (point))
- (syntax "w_"))
- (condition-case nil
- (save-excursion
- (when mark-active
- (error ""))
- (skip-syntax-backward syntax)
- (setq start (point))
- (values (buffer-substring-no-properties start end) start end))
- (error (values "" (point) (point))))))
-
-(defun helm-yas-get-key-by-template (template alist) ;str template
- "Return key"
- (assoc-default template (assoc-default 'template-key-alist alist)))
-
-(defun helm-yas-get-candidates (alist)
- "Return list of template"
- (assoc-default 'candidates alist 'eq))
-
-(defun helm-yas-get-transformed-list (alist initial-input)
- "Return list of dotlist, (DISPLAY . REAL) DISPLAY is name of snippet, REAL is template of snippet"
- (let ((transformed-list (assoc-default 'transformed alist 'eq)))
- (cond
- ;; display key on candidate ex: [for] for (...) { ... }
- (helm-yas-display-key-on-candidate
- (setq transformed-list (cl-remove-if-not (lambda (lst)
- (string-match (concat "^" (regexp-quote initial-input)) (car lst)))
- transformed-list))
- (setq transformed-list (cl-loop for dotlst in transformed-list
- for name = (car dotlst)
- for template = (cdr dotlst)
- for key = (helm-yas-get-key-by-template template alist)
- for name-inc-key = (concat "[" (propertize key 'face 'helm-yas-key) "] " name)
- collect `(,name-inc-key . ,template))))
-
- ;; default ex: for (...) { ... }
- (t
- (setq transformed-list (cl-remove-if-not (lambda (lst)
- (string-match (concat "^" (regexp-quote initial-input)) (car lst)))
- transformed-list))))
- (when helm-yas-not-display-dups
- (setq transformed-list (delete-dups transformed-list)))
- ;; sort
- (setq transformed-list (cl-sort transformed-list 'string< :key 'car))
- transformed-list))
-
-(defun helm-yas-find-file-snippet-by-template (template &optional other-window)
- (let* ((path (helm-yas-get-path-by-template template))
- ;; (let* ((path (assoc-default template (assoc-default 'template-file-alist helm-yas-cur-snippets-alist)))
- (ff-func (if other-window 'find-file-other-window 'find-file)))
- (if path
- (funcall ff-func path)
- (message "not found snippet file"))))
-
-(defun helm-yas-get-path-by-template (template)
- (assoc-default template (assoc-default 'template-file-alist helm-yas-cur-snippets-alist)))
-
-(defun helm-yas-match (candidate)
- "if customize variable `helm-yas-space-match-any-greedy' is non-nil
-space match anyword greedy"
- (cond
- (helm-yas-space-match-any-greedy
- (let ((re (replace-regexp-in-string "[ \t]+" ".*" helm-pattern)))
- (string-match re candidate)))
- (t
- (string-match helm-pattern candidate))))
-
-(defvar helm-yas-initial-input "")
-(defvar helm-yas-point-start nil)
-(defvar helm-yas-point-end nil)
-(defvar helm-yas-selected-text "" "region text if mark-active otherwise \"\"")
-(defvar helm-source-yasnippet
- `((name . "Yasnippet")
- (init . (lambda ()
- (setq helm-yas-selected-text (if mark-active (buffer-substring-no-properties (region-beginning) (region-end)) ""))
- (multiple-value-setq
- (helm-yas-initial-input helm-yas-point-start helm-yas-point-end) (helm-yas-get-cmp-context)) ;return values(str point point)
- (setq helm-yas-cur-snippets-alist (helm-yas-build-cur-snippets-alist))))
- (candidates . (helm-yas-get-candidates helm-yas-cur-snippets-alist))
- (candidate-transformer . (lambda (candidates)
- (helm-yas-get-transformed-list helm-yas-cur-snippets-alist helm-yas-initial-input)))
- (action . (("Insert snippet" . (lambda (template)
- (yas-expand-snippet template helm-yas-point-start helm-yas-point-end)
- (when helm-yas-display-msg-after-complete
- (message "this snippet is bound to [ %s ]"
- (helm-yas-get-key-by-template template helm-yas-cur-snippets-alist)))))
- ("Open snippet file" . (lambda (template)
- (helm-yas-find-file-snippet-by-template template)))
- ("Open snippet file other window" . (lambda (template)
- (helm-yas-find-file-snippet-by-template template t)))
- ("Create new snippet on region" . (lambda (template)
- (helm-yas-create-new-snippet helm-yas-selected-text)))
- ("Reload All Snippts" . (lambda (template)
- (yas-reload-all)
- (message "Reload All Snippts done")))
- ("Rename snippet file" . (lambda (template)
- (let* ((path (or (helm-yas-get-path-by-template template) ""))
- (dir (file-name-directory path))
- (filename (file-name-nondirectory path))
- (rename-to (read-string (concat "rename [" filename "] to: "))))
- (rename-file path (concat dir rename-to))
- (yas-reload-all))))
- ("Delete snippet file" . (lambda (template)
- (let ((path (or (helm-yas-get-path-by-template template) "")))
- (when (y-or-n-p "really delete?")
- (delete-file path)
- (yas-reload-all)))))))
- (persistent-action . (lambda (template)
- (helm-yas-find-file-snippet-by-template template)))
- (match . (helm-yas-match))))
-
-
-;;; visit template
-(defun helm-yas-all-templates ()
- (let ((tables (yas--get-snippet-tables)))
- (cl-loop for table in tables
- append (yas--table-templates table))))
-
-(defun helm-yas-snippet-files-candidates ()
- "called in `helm-source-yasnippet-snippet-files' candidates"
- (let ((yas-choose-keys-first nil)
- (yas-choose-tables-first nil)
- (yas-buffer-local-condition 'always))
- (with-current-buffer helm-current-buffer
- (cl-mapcar 'yas--template-load-file
- (mapcar 'cdr
- (helm-yas-all-templates))))))
-
-(defun helm-yas--visit-files-transformer (candidate)
- (file-name-nondirectory candidate))
-
-;; (helm 'helm-source-yasnippet-snippet-files)
-(defvar helm-source-yasnippet-snippet-files
- (helm-build-sync-source "yasnippet snippet files"
- :candidates #'helm-yas-snippet-files-candidates
- :real-to-display #'helm-yas--visit-files-transformer
- :action (helm-actions-from-type-file)))
-
-\f
-;;; Commands
-
-;;;###autoload
-(defun helm-yas-complete ()
- "List of yasnippet snippets using `helm' interface."
- (interactive)
- (helm 'helm-source-yasnippet))
-
-;;;###autoload
-(defun helm-yas-visit-snippet-file ()
- "List of yasnippet snippet files"
- (interactive)
- (helm 'helm-source-yasnippet-snippet-files))
-
-;;;###autoload
-(defun helm-yas-create-snippet-on-region (&optional start end file-name)
- "Create a snippet from region."
- (interactive "r")
- (let ((str (buffer-substring-no-properties start end)))
- (helm-yas-create-new-snippet str file-name)))
-;; (helm-yas-create-snippet-on-region (region-beginning) (region-end) "aaaa")
-
-
-(define-obsolete-variable-alias 'helm-c-yas-not-display-dups 'helm-yas-not-display-dups "0.6.4")
-(define-obsolete-variable-alias 'helm-c-yas-display-msg-after-complete 'helm-yas-display-msg-after-complete "0.6.4")
-(define-obsolete-variable-alias 'helm-c-yas-space-match-any-greedy 'helm-yas-space-match-any-greedy "0.6.4")
-(define-obsolete-variable-alias 'helm-c-yas-display-key-on-candidate 'helm-yas-display-key-on-candidate "0.6.4")
-(define-obsolete-variable-alias 'helm-c-yas-cur-snippets-alist 'helm-yas-cur-snippets-alist "0.6.4")
-(define-obsolete-variable-alias 'helm-c-yas-initial-input 'helm-yas-initial-input "0.6.4")
-(define-obsolete-variable-alias 'helm-c-yas-point-start 'helm-yas-point-start "0.6.4")
-(define-obsolete-variable-alias 'helm-c-yas-point-end 'helm-yas-point-end "0.6.4")
-(define-obsolete-variable-alias 'helm-c-yas-selected-text 'helm-yas-selected-text "0.6.4")
-(define-obsolete-variable-alias 'helm-c-source-yasnippet 'helm-source-yasnippet "0.6.4")
-(define-obsolete-variable-alias 'helm-c-source-yasnippet-snippet-files 'helm-source-yasnippet-snippet-files "0.6.4")
-
-(define-obsolete-function-alias 'helm-c-yas-create-new-snippet 'helm-yas-create-new-snippet "0.6.4")
-(define-obsolete-function-alias 'helm-c-yas-find-recursively 'helm-yas-find-recursively "0.6.4")
-(define-obsolete-function-alias 'helm-c-yas-build-cur-snippets-alist 'helm-yas-build-cur-snippets-alist "0.6.4")
-(define-obsolete-function-alias 'helm-c-yas-get-cmp-context 'helm-yas-get-cmp-context "0.6.4")
-(define-obsolete-function-alias 'helm-c-yas-get-key-by-template 'helm-yas-get-key-by-template "0.6.4")
-(define-obsolete-function-alias 'helm-c-yas-get-candidates 'helm-yas-get-candidates "0.6.4")
-(define-obsolete-function-alias 'helm-c-yas-get-transformed-list 'helm-yas-get-transformed-list "0.6.4")
-(define-obsolete-function-alias 'helm-c-yas-find-file-snippet-by-template 'helm-yas-find-file-snippet-by-template "0.6.4")
-(define-obsolete-function-alias 'helm-c-yas-get-path-by-template 'helm-yas-get-path-by-template "0.6.4")
-(define-obsolete-function-alias 'helm-c-yas-match 'helm-yas-match "0.6.4")
-(define-obsolete-function-alias 'helm-c-yas-all-templates 'helm-yas-all-templates "0.6.4")
-(define-obsolete-function-alias 'helm-c-yas-snippet-files-candidates 'helm-yas-snippet-files-candidates "0.6.4")
-(define-obsolete-function-alias 'helm-c-yas-complete 'helm-yas-complete "0.6.4")
-(define-obsolete-function-alias 'helm-c-yas-visit-snippet-file 'helm-yas-visit-snippet-file "0.6.4")
-(define-obsolete-function-alias 'helm-c-yas-create-snippet-on-region 'helm-yas-create-snippet-on-region "0.6.4")
-
-(provide 'helm-c-yasnippet)
-;;; helm-c-yasnippet.el ends here
--- /dev/null
+;;; helm-c-yasnippet-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+
+(add-to-list 'load-path (directory-file-name
+ (or (file-name-directory #$) (car load-path))))
+
+\f
+;;;### (autoloads nil "helm-c-yasnippet" "helm-c-yasnippet.el" (0
+;;;;;; 0 0 0))
+;;; Generated autoloads from helm-c-yasnippet.el
+
+(autoload 'helm-yas-complete "helm-c-yasnippet" "\
+List of yasnippet snippets using `helm' interface.
+
+\(fn)" t nil)
+
+(autoload 'helm-yas-visit-snippet-file "helm-c-yasnippet" "\
+List of yasnippet snippet files
+
+\(fn)" t nil)
+
+(autoload 'helm-yas-create-snippet-on-region "helm-c-yasnippet" "\
+Create a snippet from region.
+
+\(fn &optional START END FILE-NAME)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-c-yasnippet" '("helm-")))
+
+;;;***
+\f
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; coding: utf-8
+;; End:
+;;; helm-c-yasnippet-autoloads.el ends here
--- /dev/null
+;;; -*- no-byte-compile: t -*-
+(define-package "helm-c-yasnippet" "20170128.1542" "helm source for yasnippet.el" '((helm "1.7.7") (yasnippet "0.8.0") (cl-lib "0.3")) :commit "65ca732b510bfc31636708aebcfe4d2d845b59b0" :keywords '("convenience" "emulation") :authors '(("Kenji.I (Kenji Imakado)" . "ken.imakaadoNOSPAMgmail.com")) :maintainer '("Kenji.I (Kenji Imakado)" . "ken.imakaadoNOSPAMgmail.com"))
--- /dev/null
+;;; helm-c-yasnippet.el --- helm source for yasnippet.el -*- lexical-binding: t -*-
+
+;; Copyright (C) 2008, 2009, 2010, 2011 Kenji.I (Kenji Imakado) <ken.imakaadoNOSPAMgmail.com>
+;; Copyright (C) 2012,2013 Yuhei Maeda <yuhei.maeda_at_gmail.com>
+;; Copyright (C) 2014 Yuhei Maeda <yuhei.maeda_at_gmail.com>, Yasuyuki Oka <yasuyk_at_gmail.com>
+
+;; Author: Kenji.I (Kenji Imakado) <ken.imakaadoNOSPAMgmail.com>
+;; Version: 0.6.7
+;; Package-Version: 20170128.1542
+;; Package-Requires: ((helm "1.7.7") (yasnippet "0.8.0") (cl-lib "0.3"))
+;; Keywords: convenience, emulation
+
+;; 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 2, or (at your option)
+;; any later version.
+
+;; This file 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 GNU Emacs; see the file COPYING. If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+
+;; Actions: Insert snippet, Open snippet file, Open snippet file other window
+;; C-z: execute-persistent-action
+
+;;; Changelog:
+;; 2012/08/11 Port to helm
+;; Fixed bug on yasnippet 0.7.0
+;; 2012/08/23 Support yasnippet 0.8.0
+;;
+
+;;; Commands:
+;;
+;; Below are complete command list:
+;;
+;; `helm-yas-complete'
+;; List of yasnippet snippets using `helm' interface.
+;; `helm-yas-create-snippet-on-region'
+;; Create a snippet from region.
+;;
+;;; Customizable Options:
+;;
+;; Below are customizable option list:
+;;
+;; `helm-yas-not-display-dups'
+;; if non-nil not display duplicate snippet otherwise display all snippet
+;; default = t
+;; `helm-yas-display-msg-after-complete'
+;; if non-nil display snippet key message in minibuffer after Complete
+;; default = t
+;; `helm-yas-space-match-any-greedy'
+;; if non-nil helm pattern space match anyword greedy.
+;; default = nil
+;; `helm-yas-display-key-on-candidate'
+;; if non-nil helm display candidate(snippet name) include key
+;; default = nil
+
+;; here's my yasnippet's configuration
+;; (require 'yasnippet)
+;; (require 'helm-c-yasnippet)
+;; (setq helm-yas-space-match-any-greedy t) ;[default: nil]
+;; (global-set-key (kbd "C-c y") 'helm-yas-complete)
+;; (yas-global-mode 1)
+;; (yas-load-directory "<path>/<to>/snippets/")
+
+;;; Code:
+(require 'cl-lib)
+(require 'helm)
+(require 'helm-files)
+(require 'yasnippet)
+
+(defgroup helm-yasnippet nil
+ "helm config yasnippet"
+ :group 'helm)
+
+(defcustom helm-yas-not-display-dups t
+ "if non-nil not display duplicate snippet otherwise display all snippet"
+ :type 'boolean
+ :group 'helm-yasnippet)
+
+(defcustom helm-yas-display-msg-after-complete t
+ "if non-nil display snippet key message in minibuffer after Complete"
+ :type 'boolean
+ :group 'helm-yasnippet)
+
+(defcustom helm-yas-space-match-any-greedy nil
+ "if non-nil helm pattern space match anyword greedy.
+pattern regexp: \"if else\" replace to \"if.*else\"
+match \"if (...) { ... } else { ... }\" and \"if, elsif, else ...\"
+quite convenience
+Default: nil"
+ :type 'boolean
+ :group 'helm-yasnippet)
+
+(defcustom helm-yas-display-key-on-candidate nil
+ "if non-nil helm display candidate(snippet name) include key
+ex. [for] for (...) { ... }
+otherwise display just name
+ex. for (...) { ... }"
+ :type 'boolean
+ :group 'helm-yasnippet)
+
+(defcustom helm-yas-create-new-snippet-insert-function
+ 'helm-yas-create-new-snippet-insert
+ "Function to be called when create new insert file."
+ :type 'function
+ :group 'helm-yasnippet)
+
+(defface helm-yas-key '((t (:foreground "orange" :underline t)))
+ "Face used in helm-yas-complete to show key triggers."
+ :group 'helm-yasnippet)
+
+(defvar helm-yas-cur-snippets-alist nil)
+
+(defun helm-yas-create-new-snippet-insert (selected-text snippet-file)
+ "Insert SELECTED-TEXT into SNIPPET-FILE."
+ (let* ((name (file-name-sans-extension
+ (file-name-nondirectory
+ (directory-file-name snippet-file))))
+ (string-format "# -*- mode: snippet -*-\n#name : %s\n#key : %s\n#contributor : %s\n# --\n"))
+ (insert (format string-format name name user-full-name) selected-text)))
+
+(defun helm-yas-create-new-snippet-file (selected-text snippet-file)
+ "Create snippet file with inserted SELECTED-TEXT into SNIPPET-FILE."
+ (with-current-buffer (find-file snippet-file)
+ (snippet-mode)
+ (funcall helm-yas-create-new-snippet-insert-function selected-text snippet-file)))
+
+(defun helm-yas-create-new-snippet (selected-text &optional snippet-file)
+ "Create snippet from SELECTED-TEXT into SNIPPET-FILE.
+If SNIPPET-FILE is nil, asks file name.
+If SNIPPET-FILE does not contain directory, it is placed in default snippet directory."
+ (let* ((major-mode-dir (symbol-name major-mode))
+ (yas-dir (file-name-as-directory (expand-file-name (or (car-safe yas-snippet-dirs) yas-snippet-dirs))))
+ (snippet-dir
+ (or (helm-yas-find-recursively (regexp-quote major-mode-dir) yas-dir 'snippet-file)
+ (let ((target-dir (file-name-as-directory (concat yas-dir major-mode-dir))))
+ (if (yes-or-no-p (format "%s doesn't exist. Would you like to create this directory?" target-dir))
+ (progn
+ (make-directory target-dir)
+ target-dir)
+ (deactivate-mark)
+ (error "Snippet creation failed"))))))
+ (setq snippet-file
+ (helm-aif snippet-file
+ (expand-file-name snippet-file snippet-dir)
+ (read-file-name "create snippet : " snippet-dir snippet-dir)))
+ (when (file-exists-p snippet-file)
+ (error "can't create file [%s] already exists" (file-name-nondirectory snippet-file)))
+ (helm-yas-create-new-snippet-file selected-text snippet-file)))
+
+(defun helm-yas-find-recursively (regexp &optional directory predicate)
+ (let* ((directory (or directory default-directory))
+ (predfunc (cl-case predicate
+ (dir 'file-directory-p)
+ (file 'file-regular-p)
+ (otherwise 'identity)))
+ (files (cl-remove-if (lambda (s) (string-match "^\\." (file-name-nondirectory s))) (directory-files directory t)))
+ (found nil)
+ (result nil))
+ (cl-loop for file in files
+ unless found
+ do (if (and (funcall predfunc file)
+ (string-match regexp file))
+ (progn (setq found t)
+ (cl-return (file-name-as-directory file)))
+ (when (file-directory-p file)
+ (setq result (helm-yas-find-recursively regexp file predicate))))
+ finally (cl-return result))))
+
+
+(defun helm-yas-build-cur-snippets-alist (&optional table)
+ (let ((yas-choose-keys-first nil)
+ (yas-choose-tables-first nil)
+ (yas-buffer-local-condition 'always))
+ (let* ((result-alist '((candidates) (transformed) (template-key-alist) (template-file-alist)))
+ (cur-tables
+ (if table
+ (list table)
+ (yas--get-snippet-tables)))
+ (hash-value-alist nil))
+ (let ((hashes (cl-loop for table in cur-tables
+ collect (yas--table-hash table))))
+ (cl-loop for hash in hashes
+ do (maphash (lambda (k v)
+ (let (a)
+ (maphash (lambda (_n te)
+ (setq a (append (list (cons k te)) a)))
+ v)
+ (setq hash-value-alist (append a hash-value-alist))))
+ hash))
+ (cl-loop with transformed
+ with templates
+ with template-key-alist
+ with template-file-alist
+ for lst in hash-value-alist
+ for key = (car lst)
+ for template-struct = (cdr lst)
+ for name = (yas--template-name template-struct) ;`yas--template-name'
+ for template = (yas--template-content template-struct) ;`yas--template-content'
+ for file = (yas--template-load-file template-struct) ;`yas--template-content'
+ do (progn (push template templates)
+ (push `(,name . ,template) transformed)
+ (push `(,template . ,key) template-key-alist)
+ (push `(,template . ,file) template-file-alist)
+ )
+ finally (progn (push `(candidates . ,templates) result-alist)
+ (push `(transformed . ,transformed) result-alist)
+ (push `(template-file-alist . ,template-file-alist) result-alist)
+ (push `(template-key-alist . ,template-key-alist) result-alist)))
+ result-alist)
+ )))
+
+(defun helm-yas-get-cmp-context ()
+ "Return list (initial-input point-start point-end)
+like `yas--current-key'"
+ (let ((start (point))
+ (end (point))
+ (syntax "w_"))
+ (condition-case nil
+ (save-excursion
+ (when mark-active
+ (error ""))
+ (skip-syntax-backward syntax)
+ (setq start (point))
+ (cl-values (buffer-substring-no-properties start end) start end))
+ (error (cl-values "" (point) (point))))))
+
+(defun helm-yas-get-key-by-template (template alist) ;str template
+ "Return key"
+ (assoc-default template (assoc-default 'template-key-alist alist)))
+
+(defun helm-yas-get-candidates (alist)
+ "Return list of template"
+ (assoc-default 'candidates alist 'eq))
+
+(defun helm-yas-get-transformed-list (alist initial-input)
+ "Return list of dotlist, (DISPLAY . REAL) DISPLAY is name of snippet, REAL is template of snippet"
+ (let ((transformed-list (assoc-default 'transformed alist 'eq)))
+ (cond
+ ;; display key on candidate ex: [for] for (...) { ... }
+ (helm-yas-display-key-on-candidate
+ (setq transformed-list (cl-remove-if-not (lambda (lst)
+ (string-match (concat "^" (regexp-quote initial-input)) (car lst)))
+ transformed-list))
+ (setq transformed-list (cl-loop for dotlst in transformed-list
+ for name = (car dotlst)
+ for template = (cdr dotlst)
+ for key = (helm-yas-get-key-by-template template alist)
+ for name-inc-key = (concat "[" (propertize key 'face 'helm-yas-key) "] " name)
+ collect `(,name-inc-key . ,template))))
+
+ ;; default ex: for (...) { ... }
+ (t
+ (setq transformed-list (cl-remove-if-not (lambda (lst)
+ (string-match (concat "^" (regexp-quote initial-input)) (car lst)))
+ transformed-list))))
+ (when helm-yas-not-display-dups
+ (setq transformed-list (delete-dups transformed-list)))
+ ;; sort
+ (setq transformed-list (cl-sort transformed-list 'string< :key 'car))
+ transformed-list))
+
+(defun helm-yas-find-file-snippet-by-template (template &optional other-window)
+ (let* ((path (helm-yas-get-path-by-template template))
+ ;; (let* ((path (assoc-default template (assoc-default 'template-file-alist helm-yas-cur-snippets-alist)))
+ (ff-func (if other-window 'find-file-other-window 'find-file)))
+ (if path
+ (funcall ff-func path)
+ (message "not found snippet file"))))
+
+(defun helm-yas-get-path-by-template (template)
+ (assoc-default template (assoc-default 'template-file-alist helm-yas-cur-snippets-alist)))
+
+(defun helm-yas-match (candidate)
+ "if customize variable `helm-yas-space-match-any-greedy' is non-nil
+space match anyword greedy"
+ (cond
+ (helm-yas-space-match-any-greedy
+ (let ((re (replace-regexp-in-string "[ \t]+" ".*" helm-pattern)))
+ (string-match re candidate)))
+ (t
+ (string-match helm-pattern candidate))))
+
+(defvar helm-yas-initial-input "")
+(defvar helm-yas-point-start nil)
+(defvar helm-yas-point-end nil)
+(defvar helm-yas-selected-text "" "region text if mark-active otherwise \"\"")
+(defvar helm-source-yasnippet
+ `((name . "Yasnippet")
+ (init . (lambda ()
+ (setq helm-yas-selected-text (if mark-active (buffer-substring-no-properties (region-beginning) (region-end)) ""))
+ (cl-multiple-value-setq
+ (helm-yas-initial-input helm-yas-point-start helm-yas-point-end) (helm-yas-get-cmp-context)) ;return values(str point point)
+ (setq helm-yas-cur-snippets-alist (helm-yas-build-cur-snippets-alist))))
+ (candidates . (helm-yas-get-candidates helm-yas-cur-snippets-alist))
+ (candidate-transformer . (lambda (candidates)
+ (helm-yas-get-transformed-list helm-yas-cur-snippets-alist helm-yas-initial-input)))
+ (action . (("Insert snippet" . (lambda (template)
+ (yas-expand-snippet template helm-yas-point-start helm-yas-point-end)
+ (when helm-yas-display-msg-after-complete
+ (message "this snippet is bound to [ %s ]"
+ (helm-yas-get-key-by-template template helm-yas-cur-snippets-alist)))))
+ ("Open snippet file" . (lambda (template)
+ (helm-yas-find-file-snippet-by-template template)))
+ ("Open snippet file other window" . (lambda (template)
+ (helm-yas-find-file-snippet-by-template template t)))
+ ("Create new snippet on region" . (lambda (template)
+ (helm-yas-create-new-snippet helm-yas-selected-text)))
+ ("Reload All Snippts" . (lambda (template)
+ (yas-reload-all)
+ (message "Reload All Snippts done")))
+ ("Rename snippet file" . (lambda (template)
+ (let* ((path (or (helm-yas-get-path-by-template template) ""))
+ (dir (file-name-directory path))
+ (filename (file-name-nondirectory path))
+ (rename-to (read-string (concat "rename [" filename "] to: "))))
+ (rename-file path (concat dir rename-to))
+ (yas-reload-all))))
+ ("Delete snippet file" . (lambda (template)
+ (let ((path (or (helm-yas-get-path-by-template template) "")))
+ (when (y-or-n-p "really delete?")
+ (delete-file path)
+ (yas-reload-all)))))))
+ (persistent-action . (lambda (template)
+ (helm-yas-find-file-snippet-by-template template)))
+ (match . (helm-yas-match))))
+
+
+;;; visit template
+(defun helm-yas-all-templates ()
+ (let ((tables (yas--get-snippet-tables)))
+ (cl-loop for table in tables
+ append (yas--table-templates table))))
+
+(defun helm-yas-snippet-files-candidates ()
+ "called in `helm-source-yasnippet-snippet-files' candidates"
+ (let ((yas-choose-keys-first nil)
+ (yas-choose-tables-first nil)
+ (yas-buffer-local-condition 'always))
+ (with-current-buffer helm-current-buffer
+ (cl-mapcar 'yas--template-load-file
+ (mapcar 'cdr
+ (helm-yas-all-templates))))))
+
+(defun helm-yas--visit-files-transformer (candidate)
+ (file-name-nondirectory candidate))
+
+;; (helm 'helm-source-yasnippet-snippet-files)
+(defvar helm-source-yasnippet-snippet-files
+ (helm-build-sync-source "yasnippet snippet files"
+ :candidates #'helm-yas-snippet-files-candidates
+ :real-to-display #'helm-yas--visit-files-transformer
+ :action (helm-actions-from-type-file)))
+
+\f
+;;; Commands
+
+;;;###autoload
+(defun helm-yas-complete ()
+ "List of yasnippet snippets using `helm' interface."
+ (interactive)
+ (helm 'helm-source-yasnippet))
+
+;;;###autoload
+(defun helm-yas-visit-snippet-file ()
+ "List of yasnippet snippet files"
+ (interactive)
+ (helm 'helm-source-yasnippet-snippet-files))
+
+;;;###autoload
+(defun helm-yas-create-snippet-on-region (&optional start end file-name)
+ "Create a snippet from region."
+ (interactive "r")
+ (let ((str (buffer-substring-no-properties start end)))
+ (helm-yas-create-new-snippet str file-name)))
+;; (helm-yas-create-snippet-on-region (region-beginning) (region-end) "aaaa")
+
+
+(define-obsolete-variable-alias 'helm-c-yas-not-display-dups 'helm-yas-not-display-dups "0.6.4")
+(define-obsolete-variable-alias 'helm-c-yas-display-msg-after-complete 'helm-yas-display-msg-after-complete "0.6.4")
+(define-obsolete-variable-alias 'helm-c-yas-space-match-any-greedy 'helm-yas-space-match-any-greedy "0.6.4")
+(define-obsolete-variable-alias 'helm-c-yas-display-key-on-candidate 'helm-yas-display-key-on-candidate "0.6.4")
+(define-obsolete-variable-alias 'helm-c-yas-cur-snippets-alist 'helm-yas-cur-snippets-alist "0.6.4")
+(define-obsolete-variable-alias 'helm-c-yas-initial-input 'helm-yas-initial-input "0.6.4")
+(define-obsolete-variable-alias 'helm-c-yas-point-start 'helm-yas-point-start "0.6.4")
+(define-obsolete-variable-alias 'helm-c-yas-point-end 'helm-yas-point-end "0.6.4")
+(define-obsolete-variable-alias 'helm-c-yas-selected-text 'helm-yas-selected-text "0.6.4")
+(define-obsolete-variable-alias 'helm-c-source-yasnippet 'helm-source-yasnippet "0.6.4")
+(define-obsolete-variable-alias 'helm-c-source-yasnippet-snippet-files 'helm-source-yasnippet-snippet-files "0.6.4")
+
+(define-obsolete-function-alias 'helm-c-yas-create-new-snippet 'helm-yas-create-new-snippet "0.6.4")
+(define-obsolete-function-alias 'helm-c-yas-find-recursively 'helm-yas-find-recursively "0.6.4")
+(define-obsolete-function-alias 'helm-c-yas-build-cur-snippets-alist 'helm-yas-build-cur-snippets-alist "0.6.4")
+(define-obsolete-function-alias 'helm-c-yas-get-cmp-context 'helm-yas-get-cmp-context "0.6.4")
+(define-obsolete-function-alias 'helm-c-yas-get-key-by-template 'helm-yas-get-key-by-template "0.6.4")
+(define-obsolete-function-alias 'helm-c-yas-get-candidates 'helm-yas-get-candidates "0.6.4")
+(define-obsolete-function-alias 'helm-c-yas-get-transformed-list 'helm-yas-get-transformed-list "0.6.4")
+(define-obsolete-function-alias 'helm-c-yas-find-file-snippet-by-template 'helm-yas-find-file-snippet-by-template "0.6.4")
+(define-obsolete-function-alias 'helm-c-yas-get-path-by-template 'helm-yas-get-path-by-template "0.6.4")
+(define-obsolete-function-alias 'helm-c-yas-match 'helm-yas-match "0.6.4")
+(define-obsolete-function-alias 'helm-c-yas-all-templates 'helm-yas-all-templates "0.6.4")
+(define-obsolete-function-alias 'helm-c-yas-snippet-files-candidates 'helm-yas-snippet-files-candidates "0.6.4")
+(define-obsolete-function-alias 'helm-c-yas-complete 'helm-yas-complete "0.6.4")
+(define-obsolete-function-alias 'helm-c-yas-visit-snippet-file 'helm-yas-visit-snippet-file "0.6.4")
+(define-obsolete-function-alias 'helm-c-yas-create-snippet-on-region 'helm-yas-create-snippet-on-region "0.6.4")
+
+(provide 'helm-c-yasnippet)
+;;; helm-c-yasnippet.el ends here
+++ /dev/null
-Actions: Insert snippet, Open snippet file, Open snippet file other window
-C-z: execute-persistent-action
+++ /dev/null
-;;; helm-core-autoloads.el --- automatically extracted autoloads
-;;
-;;; Code:
-(add-to-list 'load-path (or (file-name-directory #$) (car load-path)))
-\f
-;;;### (autoloads nil "helm" "helm.el" (22156 56341 0 0))
-;;; Generated autoloads from helm.el
-
-(autoload 'helm-define-multi-key "helm" "\
-In KEYMAP, define key sequence KEY for function list FUNCTIONS.
-Each function run sequentially each time the key KEY is pressed.
-If DELAY is specified switch back to initial function of FUNCTIONS list
-after DELAY seconds.
-The functions in FUNCTIONS list are functions with no args.
-e.g
- (defun foo ()
- (message \"Run foo\"))
- (defun bar ()
- (message \"Run bar\"))
- (defun baz ()
- (message \"Run baz\"))
-
-\(helm-define-multi-key global-map \"<f5> q\" '(foo bar baz) 2)
-
-Each time \"<f5> q\" is pressed the next function is executed, if you wait
-More than 2 seconds, next hit will run again the first function and so on.
-
-\(fn KEYMAP KEY FUNCTIONS &optional DELAY)" nil nil)
-
-(autoload 'helm-multi-key-defun "helm" "\
-Define NAME as a multi-key command running FUNS.
-After DELAY seconds the FUNS list is reinitialised.
-See `helm-define-multi-key'.
-
-\(fn NAME DOCSTRING FUNS &optional DELAY)" nil t)
-
-(put 'helm-multi-key-defun 'lisp-indent-function '2)
-
-(autoload 'helm-define-key-with-subkeys "helm" "\
-Allow defining in MAP a KEY and SUBKEY to COMMAND.
-
-This allow typing KEY to call COMMAND the first time and
-type only SUBKEY on subsequent calls.
-
-Arg MAP is the keymap to use, SUBKEY is the initial short keybinding to
-call COMMAND.
-
-Arg OTHER-SUBKEYS is an alist specifying other short keybindings
-to use once started.
-e.g:
-
-\(helm-define-key-with-subkeys global-map
- (kbd \"C-x v n\") ?n 'git-gutter:next-hunk '((?p . git-gutter:previous-hunk)))
-
-
-In this example, `C-x v n' will run `git-gutter:next-hunk'
-subsequent hits on \"n\" will run this command again
-and subsequent hits on \"p\" will run `git-gutter:previous-hunk'.
-
-Arg MENU is a string to display in minibuffer
-to describe SUBKEY and OTHER-SUBKEYS.
-Arg EXIT-FN specify a function to run on exit.
-
-Any other keys pressed run their assigned command defined in MAP
-and exit the loop running EXIT-FN if specified.
-
-NOTE: SUBKEY and OTHER-SUBKEYS bindings support
-only char syntax actually (e.g ?n)
-so don't use strings, vectors or whatever to define them.
-
-\(fn MAP KEY SUBKEY COMMAND &optional OTHER-SUBKEYS MENU EXIT-FN)" nil nil)
-
-(put 'helm-define-key-with-subkeys 'lisp-indent-function '1)
-
-(autoload 'helm-debug-open-last-log "helm" "\
-Open helm log file of last helm session.
-If `helm-last-log-file' is nil, switch to `helm-debug-buffer' .
-
-\(fn)" t nil)
-
-(autoload 'helm "helm" "\
-Main function to execute helm sources.
-
-Keywords supported:
-:sources :input :prompt :resume :preselect
-:buffer :keymap :default :history :allow-nest
-
-Extra LOCAL-VARS keywords are supported, see below.
-
-PLIST is a list like (:key1 val1 :key2 val2 ...) or
-\(&optional sources input prompt resume
- preselect buffer keymap default history).
-
-Basic keywords are the following:
-
-:sources
-
-A list of sources used for this session. It also accepts a
-symbol, interpreted as a variable of a helm source
-i.e (a symbol can be passed instead of a list of sources).
-It also accepts an alist representing a helm source, which is
-detected by (assq 'name ANY-SOURCES).
-NOTE: In this case the source is embedded in the helm command and
-have no symbol name, so it is not reachable from outside.
-It will be referenced in `helm-sources' as a whole alist.
-
-:input
-
-Temporary value of `helm-pattern', ie. initial input of minibuffer.
-
-:prompt
-
-Prompt other than \"pattern: \".
-
-:resume
-
-If t, Resurrect previously instance of `helm'. Skip the initialization.
-If 'noresume, this instance of `helm' cannot be resumed.
-
-:preselect
-
-Initially selected candidate. Specified by exact candidate or a regexp.
-
-:buffer
-
-`helm-buffer' instead of *helm*.
-
-:keymap
-
-`helm-map' for current `helm' session.
-
-:default
-
-A default argument that will be inserted in minibuffer with \\<minibuffer-local-map>\\[next-history-element].
-When nil or not present `thing-at-point' will be used instead.
-If `helm--maybe-use-default-as-input' is non--nil display will be
-updated using :default arg as input unless :input is specified,
-which in this case will take precedence on :default
-This is a string or a list, in this case the car of the list will
-be used as initial default input, but you will be able to cycle in this
-list with \\<minibuffer-local-map>\\[next-history-element].
-
-:history
-
-By default all minibuffer input is pushed to `minibuffer-history',
-if an argument HISTORY is provided, input will be pushed to HISTORY.
-History element should be a symbol.
-
-:allow-nest
-
-Allow running this helm command within a running helm session.
-
-Of course, conventional arguments are supported, the two are same.
-
-\(helm :sources sources :input input :prompt prompt :resume resume
- :preselect preselect :buffer buffer :keymap keymap :default default
- :history history)
-
-and
-
-\(helm sources input prompt resume preselect buffer keymap default history)
-
-are the same.
-
-However the use of non keyword args is deprecated and should not be used.
-
-Other keywords are interpreted as local variables of this helm session.
-The `helm-' prefix can be omitted. For example,
-
-\(helm :sources 'helm-source-buffers-list
- :buffer \"*buffers*\" :candidate-number-limit 10)
-
-means starting helm session with `helm-source-buffers'
-source in *buffers* buffer and set variable `helm-candidate-number-limit'
-to 10 as session local variable.
-
-\(fn &key SOURCES INPUT PROMPT RESUME PRESELECT BUFFER KEYMAP DEFAULT HISTORY ALLOW-NEST OTHER-LOCAL-VARS)" nil nil)
-
-(autoload 'helm-other-buffer "helm" "\
-Simplified interface of `helm' with other `helm-buffer'.
-Call `helm' with only ANY-SOURCES and ANY-BUFFER as args.
-
-\(fn ANY-SOURCES ANY-BUFFER)" nil nil)
-
-(autoload 'helm-debug-toggle "helm" "\
-Enable/disable helm debug from outside of helm session.
-
-\(fn)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil nil ("helm-core-pkg.el" "helm-lib.el" "helm-multi-match.el"
-;;;;;; "helm-source.el") (22156 56341 612132 0))
-
-;;;***
-\f
-;; Local Variables:
-;; version-control: never
-;; no-byte-compile: t
-;; no-update-autoloads: t
-;; End:
-;;; helm-core-autoloads.el ends here
+++ /dev/null
-(define-package "helm-core" "20160105.2046" "Development files for Helm"
- '((emacs "24")
- (cl-lib "0.5")
- (async "1.6"))
- :url "https://emacs-helm.github.io/helm/")
-;; Local Variables:
-;; no-byte-compile: t
-;; End:
+++ /dev/null
-;;; helm-lib.el --- Helm routines. -*- lexical-binding: t -*-
-
-;; Copyright (C) 2015 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; Author: Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-;; URL: http://github.com/emacs-helm/helm
-
-;; 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/>.
-
-;;; Commentary:
-;; All helm functions that don't require specific helm code should go here.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'dired)
-
-\f
-;;; User vars.
-;;
-(defcustom helm-file-globstar t
- "Same as globstar bash shopt option.
-When non--nil a pattern beginning with two stars will expand recursively.
-Directories expansion is not supported yet."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-yank-text-at-point-function nil
- "The function used to forward point with `helm-yank-text-at-point'.
-With a nil value, fallback to default `forward-word'.
-The function should take one arg, an integer like `forward-word'.
-NOTE: Using `forward-symbol' here is not very useful as it is already
-provided by \\<helm-map>\\[next-history-element]."
- :type 'function
- :group 'helm)
-
-(defcustom helm-scroll-amount nil
- "Scroll amount when scrolling other window in a helm session.
-It is used by `helm-scroll-other-window'
-and `helm-scroll-other-window-down'.
-
-If you prefer scrolling line by line, set this value to 1."
- :group 'helm
- :type 'integer)
-
-\f
-;;; Internal vars
-;;
-(defvar helm-yank-point nil)
-(defvar helm-pattern ""
- "The input pattern used to update the helm buffer.")
-(defvar helm-buffer "*helm*"
- "Buffer showing completions.")
-(defvar helm-current-buffer nil
- "Current buffer when `helm' is invoked.")
-(defvar helm-suspend-update-flag nil)
-(defvar helm-action-buffer "*helm action*"
- "Buffer showing actions.")
-\f
-;;; Macros helper.
-;;
-(defmacro helm-with-gensyms (symbols &rest body)
- "Bind the SYMBOLS to fresh uninterned symbols and eval BODY."
- (declare (indent 1))
- `(let ,(mapcar (lambda (s)
- ;; Use cl-gensym here instead of make-symbol
- ;; to ensure a symbol that have a live that go
- ;; beyond the live of its macro have different name.
- ;; i.e symbols created with `with-helm-temp-hook'
- ;; should have random names.
- `(,s (cl-gensym (symbol-name ',s))))
- symbols)
- ,@body))
-\f
-;;; Iterators
-;;
-(defun helm-iter-list (seq)
- "Return an iterator object from SEQ."
- (let ((lis seq))
- (lambda ()
- (let ((elm (car lis)))
- (setq lis (cdr lis))
- elm))))
-
-(defun helm-iter-next (iterator)
- "Return next elm of ITERATOR."
- (funcall iterator))
-
-(defun helm-make-actions (&rest args)
- "Build an alist with (NAME . ACTION) elements with each pairs in ARGS.
-Where NAME is a string or a function returning a string or nil and ACTION
-a function.
-If NAME returns nil the pair is skipped.
-
-\(fn NAME ACTION ...)"
- (cl-loop for i on args by #'cddr
- for name = (car i)
- when (functionp name)
- do (setq name (funcall name))
- when name
- collect (cons name (cadr i))))
-
-(defmacro helm-aif (test-form then-form &rest else-forms)
- "Like `if' but set the result of TEST-FORM in a temprary variable called `it'.
-THEN-FORM and ELSE-FORMS are then excuted just like in `if'."
- (declare (indent 2) (debug t))
- `(let ((it ,test-form))
- (if it ,then-form ,@else-forms)))
-
-(defun helm-current-line-contents ()
- "Current line string without properties."
- (buffer-substring-no-properties (point-at-bol) (point-at-eol)))
-\f
-;;; Fuzzy matching routines
-;;
-(defsubst helm--mapconcat-pattern (pattern)
- "Transform string PATTERN in regexp for further fuzzy matching.
-e.g helm.el$
- => \"[^h]*h[^e]*e[^l]*l[^m]*m[^.]*[.][^e]*e[^l]*l$\"
- ^helm.el$
- => \"helm[.]el$\"."
- (let ((ls (split-string-and-unquote pattern "")))
- (if (string= "^" (car ls))
- ;; Exact match.
- (mapconcat (lambda (c)
- (if (and (string= c "$")
- (string-match "$\\'" pattern))
- c (regexp-quote c)))
- (cdr ls) "")
- ;; Fuzzy match.
- (mapconcat (lambda (c)
- (if (and (string= c "$")
- (string-match "$\\'" pattern))
- c (format "[^%s]*%s" c (regexp-quote c))))
- ls ""))))
-
-(defsubst helm--collect-pairs-in-string (string)
- (cl-loop for str on (split-string string "" t) by 'cdr
- when (cdr str)
- collect (list (car str) (cadr str))))
-\f
-;;; Help routines.
-;;
-(defun helm-help-internal (bufname insert-content-fn)
- "Show long message during `helm' session in BUFNAME.
-INSERT-CONTENT-FN is the function that insert
-text to be displayed in BUFNAME."
- (let ((winconf (current-frame-configuration)))
- (unwind-protect
- (progn
- (setq helm-suspend-update-flag t)
- (set-buffer (get-buffer-create bufname))
- (switch-to-buffer bufname)
- (delete-other-windows)
- (delete-region (point-min) (point-max))
- (org-mode)
- (save-excursion
- (funcall insert-content-fn))
- (setq cursor-type nil)
- (buffer-disable-undo)
- (helm-help-event-loop))
- (setq helm-suspend-update-flag nil)
- (set-frame-configuration winconf))))
-
-(defun helm-help-scroll-up (amount)
- (condition-case _err
- (scroll-up-command amount)
- (beginning-of-buffer nil)
- (end-of-buffer nil)))
-
-(defun helm-help-scroll-down (amount)
- (condition-case _err
- (scroll-down-command amount)
- (beginning-of-buffer nil)
- (end-of-buffer nil)))
-
-(defun helm-help-event-loop ()
- (let ((prompt (propertize
- "[SPC,C-v,down,next:NextPage b,M-v,up,prior:PrevPage C-s/r:Isearch q:Quit]"
- 'face 'helm-helper))
- scroll-error-top-bottom)
- (cl-loop for event = (read-key prompt) do
- (cl-case event
- ((?\C-v ? down next) (helm-help-scroll-up helm-scroll-amount))
- ((?\M-v ?b up prior) (helm-help-scroll-down helm-scroll-amount))
- (?\C-s (isearch-forward))
- (?\C-r (isearch-backward))
- (?q (cl-return))
- (t (ignore))))))
-
-\f
-;;; List processing
-;;
-(defun helm-flatten-list (seq &optional omit-nulls)
- "Return a list of all single elements of sublists in SEQ."
- (let (result)
- (cl-labels ((flatten (seq)
- (cl-loop
- for elm in seq
- if (and (or elm
- (null omit-nulls))
- (or (atom elm)
- (functionp elm)
- (and (consp elm)
- (cdr elm)
- (atom (cdr elm)))))
- do (push elm result)
- else do (flatten elm))))
- (flatten seq))
- (nreverse result)))
-
-(defun helm-mklist (obj)
- "If OBJ is a list \(but not lambda\), return itself.
-Otherwise make a list with one element."
- (if (and (listp obj) (not (functionp obj)))
- obj
- (list obj)))
-
-(cl-defmacro helm-position (item seq &key (test 'eq) all)
- "A simple and faster replacement of CL `position'.
-Return position of first occurence of ITEM found in SEQ.
-Argument SEQ can be a string, in this case ITEM have to be a char.
-Argument ALL, if non--nil specify to return a list of positions of
-all ITEM found in SEQ."
- (let ((key (if (stringp seq) 'across 'in)))
- `(cl-loop for c ,key ,seq
- for index from 0
- when (funcall ,test c ,item)
- if ,all collect index into ls
- else return index
- finally return ls)))
-
-(cl-defun helm-fast-remove-dups (seq &key (test 'eq))
- "Remove duplicates elements in list SEQ.
-This is same as `remove-duplicates' but with memoisation.
-It is much faster, especially in large lists.
-A test function can be provided with TEST argument key.
-Default is `eq'."
- (cl-loop with cont = (make-hash-table :test test)
- for elm in seq
- unless (gethash elm cont)
- do (puthash elm elm cont)
- finally return
- (cl-loop for i being the hash-values in cont collect i)))
-
-(defun helm-skip-entries (seq black-regexp-list &optional white-regexp-list)
- "Remove entries which matches one of REGEXP-LIST from SEQ."
- (cl-loop for i in seq
- unless (and (cl-loop for re in black-regexp-list
- thereis (and (stringp i)
- (string-match-p re i)))
- (null
- (cl-loop for re in white-regexp-list
- thereis (and (stringp i)
- (string-match-p re i)))))
- collect i))
-
-(defun helm-shadow-entries (seq regexp-list)
- "Put shadow property on entries in SEQ matching a regexp in REGEXP-LIST."
- (let ((face 'italic))
- (cl-loop for i in seq
- if (cl-loop for regexp in regexp-list
- thereis (and (stringp i)
- (string-match regexp i)))
- collect (propertize i 'face face)
- else collect i)))
-
-(defun helm-remove-if-not-match (regexp seq)
- "Remove all elements of SEQ that don't match REGEXP."
- (cl-loop for s in seq
- for str = (cond ((symbolp s)
- (symbol-name s))
- ((consp s)
- (car s))
- (t s))
- when (string-match-p regexp str)
- collect s))
-
-(defun helm-remove-if-match (regexp seq)
- "Remove all elements of SEQ that match REGEXP."
- (cl-loop for s in seq
- for str = (cond ((symbolp s)
- (symbol-name s))
- ((consp s)
- (car s))
- (t s))
- unless (string-match-p regexp str)
- collect s))
-
-(defun helm-transform-mapcar (function args)
- "`mapcar' for candidate-transformer.
-
-ARGS is (cand1 cand2 ...) or ((disp1 . real1) (disp2 . real2) ...)
-
-\(helm-transform-mapcar 'upcase '(\"foo\" \"bar\"))
-=> (\"FOO\" \"BAR\")
-\(helm-transform-mapcar 'upcase '((\"1st\" . \"foo\") (\"2nd\" . \"bar\")))
-=> ((\"1st\" . \"FOO\") (\"2nd\" . \"BAR\"))
-"
- (cl-loop for arg in args
- if (consp arg)
- collect (cons (car arg) (funcall function (cdr arg)))
- else
- collect (funcall function arg)))
-\f
-;;; Strings processing.
-;;
-(defun helm-stringify (str-or-sym)
- "Get string of STR-OR-SYM."
- (if (stringp str-or-sym)
- str-or-sym
- (symbol-name str-or-sym)))
-
-(defun helm-substring (str width)
- "Return the substring of string STR from 0 to WIDTH.
-Handle multibyte characters by moving by columns."
- (with-temp-buffer
- (save-excursion
- (insert str))
- (move-to-column width)
- (buffer-substring (point-at-bol) (point))))
-
-(defun helm-substring-by-width (str width &optional endstr)
- "Truncate string STR to end at column WIDTH.
-Similar to `truncate-string-to-width'.
-Add ENDSTR at end of truncated STR.
-Add spaces at end if needed to reach WIDTH when STR is shorter than WIDTH."
- (cl-loop for ini-str = str
- then (substring ini-str 0 (1- (length ini-str)))
- for sw = (string-width ini-str)
- when (<= sw width) return
- (concat ini-str endstr (make-string (- width sw) ? ))))
-
-(defun helm-string-multibyte-p (str)
- "Check if string STR contains multibyte characters."
- (cl-loop for c across str
- thereis (> (char-width c) 1)))
-
-(defun helm-get-pid-from-process-name (process-name)
- "Get pid from running process PROCESS-NAME."
- (cl-loop with process-list = (list-system-processes)
- for pid in process-list
- for process = (assoc-default 'comm (process-attributes pid))
- when (and process (string-match process-name process))
- return pid))
-
-(defun helm-ff-find-printers ()
- "Return a list of available printers on Unix systems."
- (when (executable-find "lpstat")
- (let ((printer-list (with-temp-buffer
- (call-process "lpstat" nil t nil "-a")
- (split-string (buffer-string) "\n"))))
- (cl-loop for p in printer-list
- for printer = (car (split-string p))
- when printer
- collect printer))))
-
-(defun helm-region-active-p ()
- (and transient-mark-mode mark-active (/= (mark) (point))))
-
-(defun helm-quote-whitespace (candidate)
- "Quote whitespace, if some, in string CANDIDATE."
- (replace-regexp-in-string " " "\\\\ " candidate))
-
-\f
-;;; Symbols routines
-;;
-(defun helm-symbolify (str-or-sym)
- "Get symbol of STR-OR-SYM."
- (if (symbolp str-or-sym)
- str-or-sym
- (intern str-or-sym)))
-
-(defun helm-symbol-name (obj)
- (if (or (consp obj) (byte-code-function-p obj))
- "Anonymous"
- (symbol-name obj)))
-
-(defun helm-describe-function (func)
- "FUNC is symbol or string."
- (describe-function (helm-symbolify func))
- (message nil))
-
-(defun helm-describe-variable (var)
- "VAR is symbol or string."
- (describe-variable (helm-symbolify var))
- (message nil))
-
-(defun helm-describe-face (face)
- "VAR is symbol or string."
- (describe-face (helm-symbolify face))
- (message nil))
-
-(defun helm-find-function (func)
- "FUNC is symbol or string."
- (find-function (helm-symbolify func)))
-
-(defun helm-find-variable (var)
- "VAR is symbol or string."
- (find-variable (helm-symbolify var)))
-
-(defun helm-find-face-definition (face)
- "FACE is symbol or string."
- (find-face-definition (helm-symbolify face)))
-
-(defun helm-kill-new (candidate &optional replace)
- "CANDIDATE is symbol or string.
-See `kill-new' for argument REPLACE."
- (kill-new (helm-stringify candidate) replace))
-\f
-;;; Files routines
-;;
-(defun helm-basename (fname &optional ext)
- "Print FNAME with any leading directory components removed.
-If specified, also remove filename extension EXT."
- (let ((non-essential t))
- (if (and ext (or (string= (file-name-extension fname) ext)
- (string= (file-name-extension fname t) ext))
- (not (file-directory-p fname)))
- (file-name-sans-extension (file-name-nondirectory fname))
- (file-name-nondirectory (directory-file-name fname)))))
-
-(defun helm-basedir (fname)
- "Return the base directory of filename ending by a slash."
- (helm-aif (and fname
- (or (and (string= fname "~") "~")
- (file-name-directory fname)))
- (file-name-as-directory it)))
-
-(defun helm-current-directory ()
- "Return current-directory name at point.
-Useful in dired buffers when there is inserted subdirs."
- (expand-file-name
- (if (eq major-mode 'dired-mode)
- (dired-current-directory)
- default-directory)))
-
-(defun helm-w32-prepare-filename (file)
- "Convert filename FILE to something usable by external w32 executables."
- (replace-regexp-in-string ; For UNC paths
- "/" "\\"
- (replace-regexp-in-string ; Strip cygdrive paths
- "/cygdrive/\\(.\\)" "\\1:"
- file nil nil) nil t))
-
-(defun helm-w32-shell-execute-open-file (file)
- (interactive "fOpen file:")
- (with-no-warnings
- (w32-shell-execute "open" (helm-w32-prepare-filename file))))
-
-;; Same as `vc-directory-exclusion-list'.
-(defvar helm-walk-ignore-directories
- '("SCCS" "RCS" "CVS" "MCVS" ".svn" ".git" ".hg" ".bzr"
- "_MTN" "_darcs" "{arch}" ".gvfs"))
-
-(cl-defun helm-walk-directory (directory &key (path 'basename)
- (directories t)
- match skip-subdirs)
- "Walk through DIRECTORY tree.
-Argument PATH can be one of basename, relative, full, or a function
-called on file name, default to basename.
-Argument DIRECTORIES when non--nil (default) return also directories names,
-otherwise skip directories names.
-Argument MATCH can be a predicate or a regexp.
-Argument SKIP-SUBDIRS when non--nil will skip `helm-walk-ignore-directories'
-unless it is given as a list of directories, in this case this list will be used
-instead of `helm-walk-ignore-directories'."
- (let* ((result '())
- (fn (cl-case path
- (basename 'file-name-nondirectory)
- (relative 'file-relative-name)
- (full 'identity)
- (t path))))
- (cl-labels ((ls-rec (dir)
- (unless (and skip-subdirs
- (member (helm-basename dir)
- (if (listp skip-subdirs)
- skip-subdirs
- helm-walk-ignore-directories)))
- (cl-loop with ls = (sort (file-name-all-completions "" dir)
- 'string-lessp)
- for f in ls
- ;; Use `directory-file-name' to remove the final slash.
- ;; Needed to avoid infloop on symlinks symlinking
- ;; a directory inside it [1].
- for file = (directory-file-name
- (expand-file-name f dir))
- unless (member f '("./" "../"))
- ;; A directory.
- if (char-equal (aref f (1- (length f))) ?/)
- do (progn (when directories
- (push (funcall fn file) result))
- ;; Don't recurse in symlinks.
- ;; `file-symlink-p' have to be called
- ;; on the directory with its final
- ;; slash removed [1].
- (and (not (file-symlink-p file))
- (ls-rec file)))
- else do
- (if match
- (and (if (functionp match)
- (funcall match f)
- (and (stringp match)
- (string-match match f)))
- (push (funcall fn file) result))
- (push (funcall fn file) result))))))
- (ls-rec directory)
- (nreverse result))))
-
-(defun helm-file-expand-wildcards (pattern &optional full)
- "Same as `file-expand-wildcards' but allow recursion.
-Recursion happen when PATTERN starts with two stars.
-Directories expansion is not supported."
- (let ((bn (helm-basename pattern)))
- (if (and helm-file-globstar
- (string-match "\\`\\*\\{2\\}\\(.*\\)" bn))
- (helm-walk-directory (helm-basedir pattern)
- :path (cl-case full
- (full 'full)
- (relative 'relative)
- ((basename nil) 'basename)
- (t 'full))
- :directories nil
- :match (wildcard-to-regexp bn)
- :skip-subdirs t)
- (file-expand-wildcards pattern full))))
-\f
-;;; helm internals
-;;
-(defun helm-set-pattern (pattern &optional noupdate)
- "Set minibuffer contents to PATTERN.
-if optional NOUPDATE is non-nil, helm buffer is not changed."
- (with-selected-window (or (active-minibuffer-window) (minibuffer-window))
- (delete-minibuffer-contents)
- (insert pattern))
- (when noupdate
- (setq helm-pattern pattern)))
-
-(defun helm-minibuffer-completion-contents ()
- "Return the user input in a minibuffer before point as a string.
-That is what completion commands operate on."
- (buffer-substring (field-beginning) (point)))
-
-(defmacro with-helm-buffer (&rest body)
- "Eval BODY inside `helm-buffer'."
- (declare (indent 0) (debug t))
- `(with-current-buffer (helm-buffer-get)
- ,@body))
-
-(defmacro with-helm-current-buffer (&rest body)
- "Eval BODY inside `helm-current-buffer'."
- (declare (indent 0) (debug t))
- `(with-current-buffer (or (and (buffer-live-p helm-current-buffer)
- helm-current-buffer)
- (setq helm-current-buffer
- (current-buffer)))
- ,@body))
-
-(defun helm-buffer-get ()
- "Return `helm-action-buffer' if shown otherwise `helm-buffer'."
- (if (helm-action-window)
- helm-action-buffer
- helm-buffer))
-
-(defun helm-window ()
- "Window of `helm-buffer'."
- (get-buffer-window (helm-buffer-get) 0))
-
-(defun helm-action-window ()
- "Window of `helm-action-buffer'."
- (get-buffer-window helm-action-buffer 'visible))
-
-(defmacro with-helm-window (&rest body)
- "Be sure BODY is excuted in the helm window."
- (declare (indent 0) (debug t))
- `(with-selected-window (helm-window)
- ,@body))
-
-\f
-;; Yank text at point.
-;;
-;;
-(defun helm-yank-text-at-point ()
- "Yank text at point in `helm-current-buffer' into minibuffer."
- (interactive)
- (with-helm-current-buffer
- (let ((fwd-fn (or helm-yank-text-at-point-function #'forward-word)))
- ;; Start to initial point if C-w have never been hit.
- (unless helm-yank-point (setq helm-yank-point (point)))
- (save-excursion
- (goto-char helm-yank-point)
- (funcall fwd-fn 1)
- (helm-set-pattern
- (concat
- helm-pattern (replace-regexp-in-string
- "\\`\n" ""
- (buffer-substring-no-properties
- helm-yank-point (point)))))
- (setq helm-yank-point (point))))))
-
-(defun helm-reset-yank-point ()
- (setq helm-yank-point nil))
-
-(add-hook 'helm-cleanup-hook 'helm-reset-yank-point)
-(add-hook 'helm-after-initialize-hook 'helm-reset-yank-point)
-
-;;; Ansi
-;;
-;;
-(defvar helm--ansi-color-regexp
- "\033\\[\\(K\\|[0-9;]*m\\)")
-(defvar helm--ansi-color-drop-regexp
- "\033\\[\\([ABCDsuK]\\|[12][JK]\\|=[0-9]+[hI]\\|[0-9;]*[Hf]\\)")
-(defun helm--ansi-color-apply (string)
- "A version of `ansi-color-apply' immune to upstream changes.
-
-Similar to the emacs-24.5 version without support to `ansi-color-context'
-which is buggy in emacs.
-
-Modify also `ansi-color-regexp' by using own variable `helm--ansi-color-regexp'
-that match whole STRING.
-
-This is needed to provide compatibility for both emacs-25 and emacs-24.5
-as emacs-25 version of `ansi-color-apply' is partially broken."
- (let ((start 0)
- codes end escape-sequence
- result colorized-substring)
- ;; Find the next escape sequence.
- (while (setq end (string-match helm--ansi-color-regexp string start))
- (setq escape-sequence (match-string 1 string))
- ;; Colorize the old block from start to end using old face.
- (when codes
- (put-text-property
- start end 'font-lock-face (ansi-color--find-face codes) string))
- (setq colorized-substring (substring string start end)
- start (match-end 0))
- ;; Eliminate unrecognized ANSI sequences.
- (while (string-match helm--ansi-color-drop-regexp colorized-substring)
- (setq colorized-substring
- (replace-match "" nil nil colorized-substring)))
- (push colorized-substring result)
- ;; Create new face, by applying escape sequence parameters.
- (setq codes (ansi-color-apply-sequence escape-sequence codes)))
- ;; If the rest of the string should have a face, put it there.
- (when codes
- (put-text-property
- start (length string)
- 'font-lock-face (ansi-color--find-face codes) string))
- ;; Save the remainder of the string to the result.
- (if (string-match "\033" string start)
- (push (substring string start (match-beginning 0)) result)
- (push (substring string start) result))
- (apply 'concat (nreverse result))))
-
-(provide 'helm-lib)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-lib ends here
+++ /dev/null
-;;; helm-multi-match.el --- Multiple regexp matching methods for helm -*- lexical-binding: t -*-
-
-;; Original Author: rubikitch
-
-;; Copyright (C) 2008 ~ 2011 rubikitch
-;; Copyright (C) 2011 ~ 2015 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; Author: Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-;; URL: http://github.com/emacs-helm/helm
-
-;; 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/>.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'helm-lib)
-
-\f
-(defgroup helm-multi-match nil
- "Helm multi match."
- :group 'helm)
-
-(defcustom helm-mm-matching-method 'multi3
- "Matching method for helm match plugin.
-You can set here different methods to match candidates in helm.
-Here are the possible value of this symbol and their meaning:
-- multi1: Respect order, prefix of pattern must match.
-- multi2: Same but with partial match.
-- multi3: The best, multiple regexp match, allow negation.
-- multi3p: Same but prefix must match.
-
-Default is multi3, you should keep this for a better experience.
-
-Note that multi1 and multi3p are incompatible with fuzzy matching
-in file completion and by the way fuzzy matching will be disabled there
-when these options are used."
- :type '(radio :tag "Matching methods for helm"
- (const :tag "Multiple regexp 1 ordered with prefix match" multi1)
- (const :tag "Multiple regexp 2 ordered with partial match" multi2)
- (const :tag "Multiple regexp 3 matching no order, partial, best." multi3)
- (const :tag "Multiple regexp 3p matching with prefix match" multi3p))
- :group 'helm-multi-match)
-
-\f
-;; Internal
-(defconst helm-mm-default-match-functions
- '(helm-mm-exact-match helm-mm-match))
-(defconst helm-mm-default-search-functions
- '(helm-mm-exact-search helm-mm-search))
-
-\f
-;;; Build regexps
-;;
-;;
-(defvar helm-mm-space-regexp "[\\ ] "
- "Regexp to represent space itself in multiple regexp match.")
-
-(defun helm-mm-split-pattern (pattern)
- "Split PATTERN if it contain spaces and return resulting list.
-If spaces in PATTERN are escaped, don't split at this place.
-i.e \"foo bar\"=> (\"foo\" \"bar\")
-but \"foo\ bar\"=> (\"foobar\")."
- (if (string= pattern "")
- '("")
- (cl-loop for s in (split-string
- (replace-regexp-in-string helm-mm-space-regexp
- "\000\000" pattern)
- " " t)
- collect (replace-regexp-in-string "\000\000" " " s))))
-
-(defun helm-mm-1-make-regexp (pattern)
- "Replace spaces in PATTERN with \"\.*\"."
- (mapconcat 'identity (helm-mm-split-pattern pattern) ".*"))
-
-\f
-;;; Exact match.
-;;
-;;
-;; Internal.
-(defvar helm-mm-exact-pattern-str nil)
-(defvar helm-mm-exact-pattern-real nil)
-
-(defun helm-mm-exact-get-pattern (pattern)
- (unless (equal pattern helm-mm-exact-pattern-str)
- (setq helm-mm-exact-pattern-str pattern
- helm-mm-exact-pattern-real (concat "\n" pattern "\n")))
- helm-mm-exact-pattern-real)
-
-
-(cl-defun helm-mm-exact-match (str &optional (pattern helm-pattern))
- (if case-fold-search
- (progn
- (setq str (downcase str)
- pattern (downcase pattern))
- (string= str pattern))
- (string= str pattern)))
-
-(defun helm-mm-exact-search (pattern &rest _ignore)
- (and (search-forward (helm-mm-exact-get-pattern pattern) nil t)
- (forward-line -1)))
-
-\f
-;;; Prefix match
-;;
-;;
-;; Internal
-(defvar helm-mm-prefix-pattern-str nil)
-(defvar helm-mm-prefix-pattern-real nil)
-
-(defun helm-mm-prefix-get-pattern (pattern)
- (unless (equal pattern helm-mm-prefix-pattern-str)
- (setq helm-mm-prefix-pattern-str pattern
- helm-mm-prefix-pattern-real (concat "\n" pattern)))
- helm-mm-prefix-pattern-real)
-
-(defun helm-mm-prefix-match (str &optional pattern)
- ;; In filename completion basename and basedir may be
- ;; quoted, unquote them for string comparison (Issue #1283).
- (setq pattern (replace-regexp-in-string
- "\\\\" "" (or pattern helm-pattern)))
- (let ((len (length pattern)))
- (and (<= len (length str))
- (string= (substring str 0 len) pattern ))))
-
-(defun helm-mm-prefix-search (pattern &rest _ignore)
- (search-forward (helm-mm-prefix-get-pattern pattern) nil t))
-
-\f
-;;; Multiple regexp patterns 1 (order is preserved / prefix).
-;;
-;;
-;; Internal
-(defvar helm-mm-1-pattern-str nil)
-(defvar helm-mm-1-pattern-real nil)
-
-(defun helm-mm-1-get-pattern (pattern)
- (unless (equal pattern helm-mm-1-pattern-str)
- (setq helm-mm-1-pattern-str pattern
- helm-mm-1-pattern-real
- (concat "^" (helm-mm-1-make-regexp pattern))))
- helm-mm-1-pattern-real)
-
-(cl-defun helm-mm-1-match (str &optional (pattern helm-pattern))
- (string-match (helm-mm-1-get-pattern pattern) str))
-
-(defun helm-mm-1-search (pattern &rest _ignore)
- (re-search-forward (helm-mm-1-get-pattern pattern) nil t))
-
-\f
-;;; Multiple regexp patterns 2 (order is preserved / partial).
-;;
-;;
-;; Internal
-(defvar helm-mm-2-pattern-str nil)
-(defvar helm-mm-2-pattern-real nil)
-
-(defun helm-mm-2-get-pattern (pattern)
- (unless (equal pattern helm-mm-2-pattern-str)
- (setq helm-mm-2-pattern-str pattern
- helm-mm-2-pattern-real
- (concat "^.*" (helm-mm-1-make-regexp pattern))))
- helm-mm-2-pattern-real)
-
-(cl-defun helm-mm-2-match (str &optional (pattern helm-pattern))
- (string-match (helm-mm-2-get-pattern pattern) str))
-
-(defun helm-mm-2-search (pattern &rest _ignore)
- (re-search-forward (helm-mm-2-get-pattern pattern) nil t))
-
-\f
-;;; Multiple regexp patterns 3 (permutation).
-;;
-;;
-;; Internal
-(defvar helm-mm-3-pattern-str nil)
-(defvar helm-mm-3-pattern-list nil)
-
-(defun helm-mm-3-get-patterns (pattern)
- "Return `helm-mm-3-pattern-list', a list of predicate/regexp cons cells.
-e.g ((identity . \"foo\") (identity . \"bar\")).
-This is done only if `helm-mm-3-pattern-str' is same as PATTERN."
- (unless (equal pattern helm-mm-3-pattern-str)
- (setq helm-mm-3-pattern-str pattern
- helm-mm-3-pattern-list
- (helm-mm-3-get-patterns-internal pattern)))
- helm-mm-3-pattern-list)
-
-(defun helm-mm-3-get-patterns-internal (pattern)
- "Return a list of predicate/regexp cons cells.
-e.g ((identity . \"foo\") (identity . \"bar\"))."
- (unless (string= pattern "")
- (cl-loop for pat in (helm-mm-split-pattern pattern)
- collect (if (string= "!" (substring pat 0 1))
- (cons 'not (substring pat 1))
- (cons 'identity pat)))))
-
-(cl-defun helm-mm-3-match (str &optional (pattern helm-pattern))
- "Check if PATTERN match STR.
-When PATTERN contain a space, it is splitted and matching is done
-with the several resulting regexps against STR.
-e.g \"bar foo\" will match \"foobar\" and \"barfoo\".
-Argument PATTERN, a string, is transformed in a list of
-cons cell with `helm-mm-3-get-patterns' if it contain a space.
-e.g \"foo bar\"=>((identity . \"foo\") (identity . \"bar\")).
-Then each predicate of cons cell(s) is called with regexp of same
-cons cell against STR (a candidate).
-i.e (identity (string-match \"foo\" \"foo bar\")) => t."
- (let ((pat (helm-mm-3-get-patterns pattern)))
- (cl-loop for (predicate . regexp) in pat
- always (funcall predicate
- (condition-case _err
- ;; FIXME: Probably do nothing when
- ;; using fuzzy leaving the job
- ;; to the fuzzy fn.
- (string-match regexp str)
- (invalid-regexp nil))))))
-
-(defun helm-mm-3-search-base (pattern searchfn1 searchfn2)
- "Try to find PATTERN in `helm-buffer' with SEARCHFN1 and SEARCHFN2.
-This is the search function for `candidates-in-buffer' enabled sources.
-Use the same method as `helm-mm-3-match' except it search in buffer
-instead of matching on a string.
-i.e (identity (re-search-forward \"foo\" (point-at-eol) t)) => t."
- (cl-loop with pat = (if (stringp pattern)
- (helm-mm-3-get-patterns pattern)
- pattern)
- when (eq (caar pat) 'not) return
- ;; Pass the job to `helm-search-match-part'.
- (prog1 (list (point-at-bol) (point-at-eol))
- (forward-line 1))
- while (condition-case _err
- (funcall searchfn1 (or (cdar pat) "") nil t)
- (invalid-regexp nil))
- for bol = (point-at-bol)
- for eol = (point-at-eol)
- if (cl-loop for (pred . str) in (cdr pat) always
- (progn (goto-char bol)
- (funcall pred (condition-case _err
- (funcall searchfn2 str eol t)
- (invalid-regexp nil)))))
- do (goto-char eol) and return t
- else do (goto-char eol)
- finally return nil))
-
-(defun helm-mm-3-search (pattern &rest _ignore)
- (when (stringp pattern)
- (setq pattern (helm-mm-3-get-patterns pattern)))
- (helm-mm-3-search-base
- pattern 're-search-forward 're-search-forward))
-\f
-;;; mp-3 with migemo
-;;
-;;
-(defvar helm-mm--previous-migemo-info nil
- "[Internal] Cache previous migemo query.")
-(make-local-variable 'helm-mm--previous-migemo-info)
-
-(declare-function migemo-get-pattern "ext:migemo.el")
-(declare-function migemo-search-pattern-get "ext:migemo.el")
-
-(define-minor-mode helm-migemo-mode
- "Enable migemo in helm.
-It will be available in the sources handling it,
-i.e the sources which have the slot :migemo with non--nil value."
- :lighter " Hmio"
- :group 'helm
- :global t
- (cl-assert (featurep 'migemo)
- nil "No feature called migemo found, install migemo.el."))
-
-(defun helm-mm-migemo-get-pattern (pattern)
- (let ((regex (migemo-get-pattern pattern)))
- (if (ignore-errors (string-match regex "") t)
- (concat regex "\\|" pattern) pattern)))
-
-(defun helm-mm-migemo-search-pattern-get (pattern)
- (let ((regex (migemo-search-pattern-get pattern)))
- (if (ignore-errors (string-match regex "") t)
- (concat regex "\\|" pattern) pattern)))
-
-(defun helm-mm-migemo-string-match (pattern str)
- "Migemo version of `string-match'."
- (unless (assoc pattern helm-mm--previous-migemo-info)
- (with-helm-buffer
- (setq helm-mm--previous-migemo-info
- (push (cons pattern (helm-mm-migemo-get-pattern pattern))
- helm-mm--previous-migemo-info))))
- (string-match (assoc-default pattern helm-mm--previous-migemo-info) str))
-
-(cl-defun helm-mm-3-migemo-match (str &optional (pattern helm-pattern))
- (and helm-migemo-mode
- (cl-loop for (pred . re) in (helm-mm-3-get-patterns pattern)
- always (funcall pred (helm-mm-migemo-string-match re str)))))
-
-(defun helm-mm-migemo-forward (word &optional bound noerror count)
- (with-helm-buffer
- (unless (assoc word helm-mm--previous-migemo-info)
- (setq helm-mm--previous-migemo-info
- (push (cons word (if (delq 'ascii (find-charset-string word))
- word
- (helm-mm-migemo-search-pattern-get word)))
- helm-mm--previous-migemo-info))))
- (re-search-forward
- (assoc-default word helm-mm--previous-migemo-info) bound noerror count))
-
-(defun helm-mm-3-migemo-search (pattern &rest _ignore)
- (and helm-migemo-mode
- (helm-mm-3-search-base
- pattern 'helm-mm-migemo-forward 'helm-mm-migemo-forward)))
-
-\f
-;;; mp-3p- (multiple regexp pattern 3 with prefix search)
-;;
-;;
-(defun helm-mm-3p-match (str &optional pattern)
- "Check if PATTERN match STR.
-Same as `helm-mm-3-match' but more strict, matching against prefix also.
-e.g \"bar foo\" will match \"barfoo\" but not \"foobar\" contrarily to
-`helm-mm-3-match'."
- (let* ((pat (helm-mm-3-get-patterns (or pattern helm-pattern)))
- (first (car pat)))
- (and (funcall (car first) (helm-mm-prefix-match str (cdr first)))
- (cl-loop for (predicate . regexp) in (cdr pat)
- always (funcall predicate (string-match regexp str))))))
-
-(defun helm-mm-3p-search (pattern &rest _ignore)
- (when (stringp pattern)
- (setq pattern (helm-mm-3-get-patterns pattern)))
- (helm-mm-3-search-base
- pattern 'helm-mm-prefix-search 're-search-forward))
-
-\f
-;;; Generic multi-match/search functions
-;;
-;;
-(cl-defun helm-mm-match (str &optional (pattern helm-pattern))
- (let ((fun (cl-ecase helm-mm-matching-method
- (multi1 #'helm-mm-1-match)
- (multi2 #'helm-mm-2-match)
- (multi3 #'helm-mm-3-match)
- (multi3p #'helm-mm-3p-match))))
- (funcall fun str pattern)))
-
-(defun helm-mm-search (pattern &rest _ignore)
- (let ((fun (cl-ecase helm-mm-matching-method
- (multi1 #'helm-mm-1-search)
- (multi2 #'helm-mm-2-search)
- (multi3 #'helm-mm-3-search)
- (multi3p #'helm-mm-3p-search))))
- (funcall fun pattern)))
-
-
-(provide 'helm-multi-match)
-
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-multi-match.el ends here
+++ /dev/null
-;;; helm-source.el --- Helm source creation. -*- lexical-binding: t -*-
-
-;; Copyright (C) 2015 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; Author: Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-;; URL: http://github.com/emacs-helm/helm
-
-;; 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/>.
-
-;;; Commentary:
-
-;; Interface to create helm sources easily.
-;; Actually the eieo objects are transformed in alist for compatibility.
-;; In the future this package should allow creating source as eieo objects
-;; without conversion to alist, teaching helm to read such a structure.
-;; The compatibility with alists would be kept.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'eieio)
-(require 'helm-lib)
-
-(defvar helm-fuzzy-sort-fn)
-(defvar helm-fuzzy-match-fn)
-(defvar helm-fuzzy-search-fn)
-
-(declare-function helm-init-candidates-in-buffer "helm.el")
-(declare-function helm-interpret-value "helm.el")
-(declare-function helm-fuzzy-highlight-matches "helm.el")
-
-\f
-(defgeneric helm--setup-source (source)
- "Prepare slots and handle slot errors before creating a helm source.")
-
-(defgeneric helm-setup-user-source (source)
- "Allow users modifying slots in SOURCE just before creation.")
-
-\f
-;;; Classes for sources
-;;
-;;
-(defclass helm-source ()
- ((name
- :initarg :name
- :initform nil
- :custom string
- :documentation
- " The name of the source.
- A string which is also the heading which appears
- above the list of matches from the source. Must be unique.")
-
- (header-name
- :initarg :header-name
- :initform nil
- :custom function
- :documentation
- " A function returning the display string of the header.
- Its argument is the name of the source. This attribute is useful to
- add an additional information with the source name.
- It doesn't modify the name of the source.")
-
- (init
- :initarg :init
- :initform nil
- :custom function
- :documentation
- " Function called with no parameters when helm is started.
- It is useful for collecting current state information which can be
- used to create the list of candidates later.
- Initialization of `candidates-in-buffer' is done here
- with `helm-init-candidates-in-buffer'.")
-
- (candidates
- :initarg :candidates
- :initform nil
- :custom (choice function list)
- :documentation
- " Specifies how to retrieve candidates from the source.
- It can either be a variable name, a function called with no parameters
- or the actual list of candidates.
-
- The list must be a list whose members are strings, symbols
- or (DISPLAY . REAL) pairs.
-
- In case of (DISPLAY . REAL) pairs, the DISPLAY string is shown
- in the Helm buffer, but the REAL one is used as action
- argument when the candidate is selected. This allows a more
- readable presentation for candidates which would otherwise be,
- for example, too long or have a common part shared with other
- candidates which can be safely replaced with an abbreviated
- string for display purposes.
-
- Note that if the (DISPLAY . REAL) form is used then pattern
- matching is done on the displayed string, not on the real
- value.")
-
- (update
- :initarg :update
- :initform nil
- :custom function
- :documentation
- " Function called with no parameters at before \"init\" function
- when `helm-force-update' is called.")
-
- (cleanup
- :initarg :cleanup
- :initform nil
- :custom function
- :documentation
- " Function called with no parameters when *helm* buffer is
- closed. It is useful for killing unneeded candidates buffer.
-
- Note that the function is executed BEFORE performing action.")
-
- (delayed
- :initarg :delayed
- :initform nil
- :custom (choice null integer)
- :documentation
- " Candidates from the source are shown only if the user stops
- typing and is idle for `helm-idle-delay' seconds.
- If a value is given to delayed attr, this value is used instead only
- if it is > to `helm-idle-delay'.")
-
- (keymap
- :initarg :keymap
- :initform nil
- :custom sexp
- :documentation
- " Specific keymap for this source.
- It is useful to have a keymap per source when using more than
- one source. Otherwise, a keymap can be set per command with
- `helm' argument KEYMAP. NOTE: when a source have `helm-map' as
- keymap attr, the global value of `helm-map' will override the
- actual local one.")
-
- (action
- :initarg :action
- :initform 'identity
- :custom (alist :key-type string
- :value-type function)
- :documentation
- " An alist of (DISPLAY . FUNCTION) pairs, a variable name or a function.
- FUNCTION is called with one parameter: the selected candidate.
-
- An action other than the default can be chosen from this list
- of actions for the currently selected candidate (by default
- with TAB). The DISPLAY string is shown in the completions
- buffer and the FUNCTION is invoked when an action is
- selected. The first action of the list is the default.
-
- You should use `helm-make-actions' to build this alist easily.")
-
- (persistent-action
- :initarg :persistent-action
- :initform nil
- :custom function
- :documentation
- " Can be a either a Function called with one parameter (the
- selected candidate) or a cons cell where first element is this
- same function and second element a symbol (e.g never-split)
- that inform `helm-execute-persistent-action'to not split his
- window to execute this persistent action.")
-
- (persistent-help
- :initarg :persistent-help
- :initform nil
- :custom string
- :documentation
- " A string to explain persistent-action of this source. It also
- accepts a function or a variable name.
- It will be displayed in `header-line'.
- Have no effect when `helm-echo-input-in-header-line' is non--nil.")
-
- (help-message
- :initarg :help-message
- :initform nil
- :custom (choice string function)
- :documentation
- " Help message for this source.
- If not present, `helm-help-message' value will be used.")
-
- (multiline
- :initarg :multiline
- :initform nil
- :custom boolean
- :documentation
- " Enable to selection multiline candidates.")
-
- (requires-pattern
- :initarg :requires-pattern
- :initform nil
- :custom integer
- :documentation
- " If present matches from the source are shown only if the
- pattern is not empty. Optionally, it can have an integer
- parameter specifying the required length of input which is
- useful in case of sources with lots of candidates.")
-
- (candidate-transformer
- :initarg :candidate-transformer
- :initform nil
- :custom (choice function list)
- :documentation
- " It's a function or a list of functions called with one argument
- when the completion list from the source is built. The argument
- is the list of candidates retrieved from the source. The
- function should return a transformed list of candidates which
- will be used for the actual completion. If it is a list of
- functions, it calls each function sequentially.
-
- This can be used to transform or remove items from the list of
- candidates.
-
- Note that `candidates' is run already, so the given transformer
- function should also be able to handle candidates with (DISPLAY
- . REAL) format.")
-
- (filtered-candidate-transformer
- :initarg :filtered-candidate-transformer
- :initform nil
- :custom (choice function list)
- :documentation
- " It has the same format as `candidate-transformer', except the
- function is called with two parameters: the candidate list and
- the source.
-
- This transformer is run on the candidate list which is already
- filtered by the current pattern. While `candidate-transformer'
- is run only once, it is run every time the input pattern is
- changed.
-
- It can be used to transform the candidate list dynamically, for
- example, based on the current pattern.
-
- In some cases it may also be more efficent to perform candidate
- transformation here, instead of with `candidate-transformer'
- even if this transformation is done every time the pattern is
- changed. For example, if a candidate set is very large then
- `candidate-transformer' transforms every candidate while only
- some of them will actually be displayed due to the limit
- imposed by `helm-candidate-number-limit'.
-
- Note that `candidates' and `candidate-transformer' is run
- already, so the given transformer function should also be able
- to handle candidates with (DISPLAY . REAL) format.")
-
- (filter-one-by-one
- :initarg :filter-one-by-one
- :initform nil
- :custom (choice function list)
- :documentation
- " A transformer function that treat candidates one by one.
- It is called with one arg the candidate.
- It is faster than `filtered-candidate-transformer' or
- `candidates-transformer', but should be used only in sources
- that recompute constantly their candidates, e.g `helm-source-find-files'.
- Filtering happen early and candidates are treated
- one by one instead of re-looping on the whole list.
- If used with `filtered-candidate-transformer' or `candidates-transformer'
- these functions should treat the candidates transformed by the
- `filter-one-by-one' function in consequence.")
-
- (display-to-real
- :initarg :display-to-real
- :initform nil
- :custom function
- :documentation
- " Function called with one parameter; the selected candidate.
-
- The function transforms the selected candidate, and the result
- is passed to the action function. The display-to-real
- attribute provides another way to pass to action other string than
- the one shown in Helm buffer.
-
- Traditionally, it is possible to make candidates,
- candidate-transformer or filtered-candidate-transformer
- function return a list with (DISPLAY . REAL) pairs. But if REAL
- can be generated from DISPLAY, display-to-real is more
- convenient and faster.
-
- NOTE: This is deprecated and you have better time using `filter-one-by-one'.")
-
- (real-to-display
- :initarg :real-to-display
- :initform nil
- :custom function
- :documentation
- " Function called with one parameter; the selected candidate.
- The real value of candidates will be shown in display.
- See `display-to-real'.")
-
- (action-transformer
- :initarg :action-transformer
- :initform nil
- :custom (choice function list)
- :documentation
- " It's a function or a list of functions called with two
- arguments when the action list from the source is
- assembled. The first argument is the list of actions, the
- second is the current selection. If it is a list of functions,
- it calls each function sequentially.
-
- The function should return a transformed action list.
-
- This can be used to customize the list of actions based on the
- currently selected candidate.")
-
- (pattern-transformer
- :initarg :pattern-transformer
- :initform nil
- :custom (choice function list)
- :documentation
- " It's a function or a list of functions called with one argument
- before computing matches. Its argument is `helm-pattern'.
- Functions should return transformed `helm-pattern'.
-
- It is useful to change interpretation of `helm-pattern'.")
-
- (candidate-number-limit
- :initarg :candidate-number-limit
- :initform nil
- :custom integer
- :documentation
- " Override `helm-candidate-number-limit' only for this source.")
-
- (volatile
- :initarg :volatile
- :initform nil
- :custom boolean
- :documentation
- " Indicates the source assembles the candidate list dynamically,
- so it shouldn't be cached within a single Helm
- invocation. It is only applicable to synchronous sources,
- because asynchronous sources are not cached.")
-
- (match
- :initarg :match
- :initform nil
- :custom (choice function list)
- :documentation
- " List of functions called with one parameter: a candidate. The
- function should return non-nil if the candidate matches the
- current pattern (see variable `helm-pattern').
-
- When using `candidates-in-buffer' its default value is `identity' and
- don't have to be changed, use the `search' slot instead.
-
- This attribute allows the source to override the default
- pattern matching based on `string-match'. It can be used, for
- example, to implement a source for file names and do the
- pattern matching on the basename of files, since it's more
- likely one is typing part of the basename when searching for a
- file, instead of some string anywhere else in its path.
-
- If the list contains more than one function then the list of
- matching candidates from the source is constructed by appending
- the results after invoking the first function on all the
- potential candidates, then the next function, and so on. The
- matching candidates supplied by the first function appear first
- in the list of results and then results from the other
- functions, respectively.
-
- This attribute has no effect for asynchronous sources (see
- attribute `candidates'), since they perform pattern matching
- themselves.
-
- Note that FUZZY-MATCH slot will overhide value of this slot.")
-
- (fuzzy-match
- :initarg :fuzzy-match
- :initform nil
- :custom boolean
- :documentation
- " Enable fuzzy matching in this source.
- This will overwrite settings in MATCH slot, and for
- sources built with child class `helm-source-in-buffer' the SEARCH slot.
- This is an easy way of enabling fuzzy matching, but you can use the MATCH
- or SEARCH slots yourself if you want something more elaborated, mixing
- different type of match (See `helm-source-buffers' class for example).")
-
- (nomark
- :initarg :nomark
- :initform nil
- :custom boolean
- :documentation
- " Don't allow marking candidates when this attribute is present.")
-
- (nohighlight
- :initarg :nohighlight
- :initform nil
- :custom boolean
- :documentation
- " Disable highlighting matches in this source.
- This will disable generic highlighting of matches,
- but some specialized highlighting can be done from elsewhere,
- i.e from `filtered-candidate-transformer' or `filter-one-by-one' slots.
- So use this to either disable completely highlighting in your source,
- or to disable highlighting and use a specialized highlighting matches
- function for this source.
- Remember that this function should run AFTER all filter functions if those
- filter functions are modifying face properties, though it is possible to
- avoid this by using new `add-face-text-property' in your filter functions.")
-
- (allow-dups
- :initarg :allow-dups
- :initform nil
- :custom boolean
- :documentation
- " Allow helm collecting duplicates candidates.")
-
- (history
- :initarg :history
- :initform nil
- :custom symbol
- :documentation
- " Allow passing history variable to helm from source.
- It should be a quoted symbol.")
-
- (coerce
- :initarg :coerce
- :initform nil
- :custom function
- :documentation
- " It's a function called with one argument: the selected candidate.
- This function is intended for type convertion. In normal case,
- the selected candidate (string) is passed to action
- function. If coerce function is specified, it is called just
- before action function.
-
- Example: converting string to symbol
- (coerce . intern)")
-
- (mode-line
- :initarg :mode-line
- :initform nil
- :custom (choice string sexp)
- :documentation
- " Source local `helm-mode-line-string' (included in
- `mode-line-format'). It accepts also variable/function name.")
-
- (header-line
- :initarg :header-line
- :initform nil
- :custom (choice string function)
- :documentation
- " Source local `header-line-format'.
- Have no effect when `helm-echo-input-in-header-line' is non--nil.
- It accepts also variable/function name.")
-
- (resume
- :initarg :resume
- :initform nil
- :custom function
- :documentation
- " Function called with no parameters at end of initialization
- when `helm-resume' is started.
- If this function try to do something against `helm-buffer', \(e.g updating,
- searching etc...\) probably you should run it in a timer to ensure
- `helm-buffer' is ready.")
-
- (follow
- :initarg :follow
- :initform nil
- :custom integer
- :documentation
- " Enable `helm-follow-mode' for this source only.
- You must give it a value of 1 or -1, though giving a -1 value
- is surely not what you want, e.g: (follow . 1)
-
- See `helm-follow-mode' for more infos.")
-
- (follow-delay
- :initarg :follow-delay
- :initform nil
- :custom integer
- :documentation
- " `helm-follow-mode' will execute persistent-action after this delay.
- Otherwise value of `helm-follow-input-idle-delay' is used if non--nil,
- If none of these are found fallback to `helm-input-idle-delay'.")
-
- (dont-plug
- :initarg :dont-plug
- :initform '(helm-compile-source--persistent-help)
- :custom list
- :documentation
- " A list of compile functions plugin to ignore.")
-
- (matchplugin
- :initarg :matchplugin
- :initform t
- :custom boolean)
-
- (match-part
- :initarg :match-part
- :initform nil
- :custom function
- :documentation
- " Allow matching only one part of candidate.
- If source contain match-part attribute, match is computed only
- on part of candidate returned by the call of function provided
- by this attribute. The function should have one arg, candidate,
- and return only a specific part of candidate.")
-
- (before-init-hook
- :initarg :before-init-hook
- :initform nil
- :custom symbol
- :documentation
- " A local hook that run at beginning of initilization of this source.
- i.e Before the creation of `helm-buffer'.")
-
- (after-init-hook
- :initarg :after-init-hook
- :initform nil
- :custom symbol
- :documentation
- " A local hook that run at end of initilization of this source.
- i.e After the creation of `helm-buffer'."))
-
- "Main interface to define helm sources."
- :abstract t)
-
-(defclass helm-source-sync (helm-source)
- ((candidates
- :initform '("ERROR: You must specify the `candidates' slot, either with a list or a function"))
-
- (dont-plug
- :initform '(helm-compile-source--multi-match
- helm-compile-source--persistent-help
- ;; Ensure this will not be plugged
- ;; if user have somewhere old helm-migemo.el.
- helm-compile-source--migemo))
-
- (migemo
- :initarg :migemo
- :initform nil
- :custom boolean
- :documentation
- " Enable migemo.
- When multimatch is disabled, you can give the symbol 'nomultimatch as value
- to force not using generic migemo matching function.
- In this case you have to provide your own migemo matching funtion
- that kick in when `helm-migemo-mode' is enabled.
- Otherwise it will be available for this source once `helm-migemo-mode'
- is enabled when non-nil.")
-
- (match-strict
- :initarg :match-strict
- :initform nil
- :custom function
- :documentation
- " When specifying a match function within a source and
- helm-multi-match is enabled, the result of all matching
- functions will be concatened, which in some cases is not what
- is wanted. When using `match-strict' only this or these
- functions will be used. You can specify those functions as a
- list of functions or a single symbol function.
-
- NOTE: This have the same effect as using :MATCHPLUGIN nil."))
-
- "Use this class to make helm sources using a list of candidates.
-This list should be given as a normal list, a variable handling a list
-or a function returning a list.
-Matching is done basically with `string-match' against each candidate.")
-
-(defclass helm-source-async (helm-source)
- ((candidates-process
- :initarg :candidates-process
- :initform nil
- :custom function
- :documentation
- " This attribute is used to define a process as candidate.
- The value must be a process.
-
- NOTE:
- When building the source at runtime you can give directly a process
- as value, otherwise wrap the process call into a function.
- The process buffer should be nil, otherwise, if you use
- `helm-buffer' give to the process a sentinel.")
-
- (matchplugin :initform nil)
- (dont-plug :initform '(helm-compile-source--multi-match
- helm-compile-source--persistent-help)))
-
- "Use this class to define a helm source calling an external process.
-The :candidates slot is not allowed even if described because this class
-inherit from `helm-source'.")
-
-(defclass helm-source-in-buffer (helm-source)
- ((init
- :initform 'helm-default-init-source-in-buffer-function)
-
- (data
- :initarg :data
- :initform nil
- :custom (choice list string)
- :documentation
- " A string or a list that will be used to feed the `helm-candidates-buffer'.
- This data will be passed in a function added to the init slot and
- the buffer will be build with `helm-init-candidates-in-buffer'.
- This is an easy and fast method to build a `candidates-in-buffer' source.")
-
- (dont-plug
- :initform '(helm-compile-source--candidates-in-buffer
- helm-compile-source--multi-match
- helm-compile-source--persistent-help
- helm-compile-source--migemo))
-
- (migemo
- :initarg :migemo
- :initform nil
- :custom boolean
- :documentation
- " Enable migemo.
- When multimatch is disabled, you can give the symbol 'nomultimatch as value
- to force not using generic migemo matching function.
- In this case you have to provide your own migemo matching funtion
- that kick in when `helm-migemo-mode' is enabled.
- Otherwise it will be available for this source once `helm-migemo-mode'
- is enabled when non-nil.")
-
- (candidates
- :initform 'helm-candidates-in-buffer)
-
- (volatile
- :initform t)
-
- (match
- :initform '(identity))
-
- (get-line
- :initarg :get-line
- :initform 'buffer-substring-no-properties
- :custom function
- :documentation
- " A function like `buffer-substring-no-properties' or `buffer-substring'.
- This function converts point of line-beginning and point of line-end,
- which represents a candidate computed by `helm-candidates-in-buffer'.
- By default, `helm-candidates-in-buffer' uses
- `buffer-substring-no-properties'.")
-
- (search
- :initarg :search
- :initform '(helm-candidates-in-buffer-search-default-fn)
- :custom (choice function list)
- :documentation
- " List of functions like `re-search-forward' or `search-forward'.
- Buffer search function used by `helm-candidates-in-buffer'.
- By default, `helm-candidates-in-buffer' uses `re-search-forward'.
- The function should take one arg PATTERN.
- If your search function needs to handle negation like matchplugin,
- this function should returns in such case a cons cell of two integers defining
- the beg and end positions to match in the line previously matched by
- `re-search-forward' or similar, and move point to next line
- (See how the `helm-mm-3-search-base' and `helm-fuzzy-search' functions are working).
-
- NOTE: FUZZY-MATCH slot will overhide value of this slot.")
-
- (search-strict
- :initarg :search-strict
- :initform nil
- :custom function
- :documentation
- " When specifying a search function within a source and
- helm-multi-match is enabled, the result of all searching
- functions will be concatened, which in some cases is not what
- is wanted. When using `search-strict' only this or these
- functions will be used. You can specify those functions as a
- list of functions or a single symbol function.
-
- NOTE: This have the same effect as using a nil value for
- :MATCHPLUGIN slot."))
-
- "Use this source to make helm sources storing candidates inside a buffer.
-Contrarily to `helm-source-sync' candidates are matched using a function
-like `re-search-forward', see below documentation of :search slot.")
-
-(defclass helm-source-dummy (helm-source)
- ((candidates
- :initform '("dummy"))
-
- (filtered-candidate-transformer
- :initform 'helm-dummy-candidate)
-
- (matchplugin
- :initform nil)
-
- (accept-empty
- :initarg :accept-empty
- :initform t
- :custom boolean
- :documentation
- " Allow exiting with an empty string.
- You should keep the default value.")
-
- (match
- :initform 'identity)
-
- (volatile
- :initform t)))
-
-(defclass helm-source-in-file (helm-source-in-buffer)
- ((init :initform (lambda ()
- (let ((file (helm-attr 'candidates-file)))
- (with-current-buffer (helm-candidate-buffer 'global)
- (insert-file-contents file)))))
- (candidates-file
- :initarg :candidates-file
- :initform nil
- :custom string
- :documentation "A filename."))
-
- "The contents of the file will be used as candidates in buffer.")
-
-\f
-;;; Error functions
-;;
-;;
-(defun helm-default-init-source-in-buffer-function ()
- (helm-init-candidates-in-buffer 'global
- '("ERROR: No buffer handling your data, use either the `init' slot or the `data' slot.")))
-
-\f
-;;; Internal Builder functions.
-;;
-;;
-(defun helm--create-source (object)
- "[INTERNAL] Build a helm source from OBJECT.
-Where OBJECT is an instance of an eieio class."
- (cl-loop for s in (object-slots object)
- for slot-val = (slot-value object s)
- when slot-val
- collect (cons s (unless (eq t slot-val) slot-val))))
-
-(defun helm-make-source (name class &rest args)
- "Build a `helm' source named NAME with ARGS for CLASS.
-Argument NAME is a string which define the source name, so no need to use
-the keyword :name in your source, NAME will be used instead.
-Argument CLASS is an eieio class object.
-Arguments ARGS are keyword value pairs as defined in CLASS."
- (declare (indent 2))
- (let ((source (apply #'make-instance class name args)))
- (set-slot-value source 'name name)
- (helm--setup-source source)
- (helm-setup-user-source source)
- (helm--create-source source)))
-
-(defun helm-make-type (class &rest args)
- (let ((source (apply #'make-instance class args)))
- (set-slot-value source 'name nil)
- (helm--setup-source source)
- (helm--create-source source)))
-
-(defvar helm-mm-default-search-functions)
-(defvar helm-mm-default-match-functions)
-
-(defun helm-source-mm-get-search-or-match-fns (source method)
- (let ((defmatch (helm-aif (slot-value source 'match)
- (helm-mklist it)))
- (defmatch-strict (helm-aif (and (eq method 'match)
- (slot-value source 'match-strict))
- (helm-mklist it)))
- (defsearch (helm-aif (and (eq method 'search)
- (slot-value source 'search))
- (helm-mklist it)))
- (defsearch-strict (helm-aif (and (eq method 'search-strict)
- (slot-value source 'search-strict))
- (helm-mklist it)))
- (migemo (slot-value source 'migemo)))
- (cl-case method
- (match (cond (defmatch-strict)
- (migemo
- (append helm-mm-default-match-functions
- defmatch '(helm-mm-3-migemo-match)))
- (defmatch
- (append helm-mm-default-match-functions defmatch))
- (t helm-mm-default-match-functions)))
- (search (cond (defsearch-strict)
- (migemo
- (append helm-mm-default-search-functions
- defsearch '(helm-mm-3-migemo-search)))
- (defsearch
- (append helm-mm-default-search-functions defsearch))
- (t helm-mm-default-search-functions))))))
-
-\f
-;;; Modifiers
-;;
-(cl-defun helm-source-add-action-to-source-if (name fn source predicate
- &optional (index 4))
- "Same as `helm-add-action-to-source-if' but for SOURCE defined as eieio object.
-You can use this inside a `helm--setup-source' method for a SOURCE defined as
-an eieio class."
- (let* ((actions (slot-value source 'action))
- (action-transformers (slot-value source 'action-transformer))
- (new-action (list (cons name fn)))
- (transformer `(lambda (actions candidate)
- (cond ((funcall (quote ,predicate) candidate)
- (helm-append-at-nth
- actions (quote ,new-action) ,index))
- (t actions)))))
- (if (functionp actions)
- (set-slot-value source 'action (list (cons "Default action" actions)))
- (set-slot-value source 'action (helm-interpret-value actions source)))
- (when (or (symbolp action-transformers) (functionp action-transformers))
- (setq action-transformers (list action-transformers)))
- (set-slot-value
- source
- 'action-transformer
- (delq nil (append (list transformer) action-transformers)))))
-
-\f
-;;; Methods to build sources.
-;;
-;;
-(defun helm-source--persistent-help-string (string source)
- (substitute-command-keys
- (concat "\\<helm-map>\\[helm-execute-persistent-action]: "
- (or (format "%s (keeping session)" string)
- (slot-value source 'header-line)))))
-
-(defun helm-source--header-line (source)
- (substitute-command-keys
- (concat "\\<helm-map>\\[helm-execute-persistent-action]: "
- (helm-aif (or (slot-value source 'persistent-action)
- (slot-value source 'action))
- (cond ((and (symbolp it)
- (functionp it)
- (eq it 'identity))
- "Do Nothing")
- ((and (symbolp it)
- (boundp it)
- (listp (symbol-value it))
- (stringp (caar (symbol-value it))))
- (caar (symbol-value it)))
- ((or (symbolp it) (functionp it))
- (helm-symbol-name it))
- ((listp it)
- (let ((action (car it)))
- ;; It comes from :action ("foo" . function).
- (if (stringp (car action))
- (car action)
- ;; It comes from :persistent-action
- ;; (function . 'nosplit) Fix Issue #788.
- (if (or (symbolp action)
- (functionp action))
- (helm-symbol-name action)))))
- (t ""))
- "")
- " (keeping session)")))
-
-(defmethod helm--setup-source :primary ((_source helm-source)))
-
-(defmethod helm--setup-source :before ((source helm-source))
- (helm-aif (slot-value source 'keymap)
- (and (symbolp it) (set-slot-value source 'keymap (symbol-value it))))
- (helm-aif (slot-value source 'persistent-help)
- (set-slot-value source 'header-line
- (helm-source--persistent-help-string it source))
- (set-slot-value source 'header-line (helm-source--header-line source)))
- (helm-aif (slot-value source 'candidate-number-limit)
- (and (symbolp it) (set-slot-value
- source 'candidate-number-limit (symbol-value it))))
- (when (and (slot-value source 'fuzzy-match) helm-fuzzy-sort-fn)
- (set-slot-value source 'filtered-candidate-transformer
- (helm-aif (slot-value source 'filtered-candidate-transformer)
- (append (helm-mklist it)
- (list helm-fuzzy-sort-fn))
- (list helm-fuzzy-sort-fn))))
- (unless (slot-value source 'nohighlight)
- (set-slot-value source 'filtered-candidate-transformer
- (helm-aif (slot-value source 'filtered-candidate-transformer)
- (append (helm-mklist it)
- (list #'helm-fuzzy-highlight-matches))
- (list #'helm-fuzzy-highlight-matches)))))
-
-(defmethod helm-setup-user-source ((_source helm-source)))
-
-(defmethod helm--setup-source ((source helm-source-sync))
- (when (slot-value source 'fuzzy-match)
- (helm-aif (slot-value source 'match)
- (set-slot-value source 'match (append (helm-mklist it)
- (list helm-fuzzy-match-fn)))
- (set-slot-value source 'match helm-fuzzy-match-fn)))
- (when (slot-value source 'matchplugin)
- (set-slot-value source 'match
- (helm-source-mm-get-search-or-match-fns source 'match)))
- (helm-aif (and (null (slot-value source 'matchplugin))
- (slot-value source 'migemo))
- (unless (eq it 'nomultimatch) ; Use own migemo fn.
- (set-slot-value source 'match
- (append (helm-mklist (slot-value source 'match))
- '(helm-mm-3-migemo-match))))))
-
-(defmethod helm--setup-source ((source helm-source-in-buffer))
- (let ((cur-init (slot-value source 'init)))
- (helm-aif (slot-value source 'data)
- (set-slot-value
- source
- 'init (delq
- nil
- (list
- (and (null (eq 'helm-default-init-source-in-buffer-function
- cur-init))
- cur-init)
- (lambda ()
- (helm-init-candidates-in-buffer
- 'global
- (if (functionp it) (funcall it) it))))))))
- (when (slot-value source 'fuzzy-match)
- (helm-aif (slot-value source 'search)
- (set-slot-value source 'search (append (helm-mklist it)
- (list helm-fuzzy-search-fn)))
- (set-slot-value source 'search (list helm-fuzzy-search-fn))))
- (when (slot-value source 'matchplugin)
- (set-slot-value
- source 'search (helm-source-mm-get-search-or-match-fns source 'search)))
- (helm-aif (and (null (slot-value source 'matchplugin))
- (slot-value source 'migemo))
- (unless (eq it 'nomultimatch)
- (set-slot-value source 'search
- (append (helm-mklist (slot-value source 'search))
- '(helm-mm-3-migemo-search)))))
- (let ((mtc (slot-value source 'match)))
- (cl-assert (or (equal '(identity) mtc)
- (eq 'identity mtc))
- nil "Invalid slot value for `match'")
- (cl-assert (eq (slot-value source 'volatile) t)
- nil "Invalid slot value for `volatile'")))
-
-(defmethod helm--setup-source ((source helm-source-async))
- (cl-assert (null (slot-value source 'candidates))
- nil "Incorrect use of `candidates' use `candidates-process' instead")
- (cl-assert (null (slot-value source 'matchplugin))
- nil "`matchplugin' not allowed in async sources."))
-
-(defmethod helm--setup-source ((source helm-source-dummy))
- (let ((mtc (slot-value source 'match)))
- (cl-assert (or (equal '(identity) mtc)
- (eq 'identity mtc))
- nil "Invalid slot value for `match'")
- (cl-assert (eq (slot-value source 'volatile) t)
- nil "Invalid slot value for `volatile'")
- (cl-assert (equal (slot-value source 'candidates) '("dummy"))
- nil "Invalid slot value for `candidates'")
- (cl-assert (eq (slot-value source 'accept-empty) t)
- nil "Invalid slot value for `accept-empty'")))
-
-\f
-;;; User functions
-;;
-;; Sources
-(defmacro helm-build-sync-source (name &rest args)
- "Build a synchronous helm source with name NAME.
-Args ARGS are keywords provided by `helm-source-sync'."
- (declare (indent 1))
- `(helm-make-source ,name 'helm-source-sync ,@args))
-
-(defmacro helm-build-async-source (name &rest args)
- "Build a asynchronous helm source with name NAME.
-Args ARGS are keywords provided by `helm-source-async'."
- (declare (indent 1))
- `(helm-make-source ,name 'helm-source-async ,@args))
-
-(defmacro helm-build-in-buffer-source (name &rest args)
- "Build a helm source with name NAME using `candidates-in-buffer' method.
-Args ARGS are keywords provided by `helm-source-in-buffer'."
- (declare (indent 1))
- `(helm-make-source ,name 'helm-source-in-buffer ,@args))
-
-(defmacro helm-build-dummy-source (name &rest args)
- "Build a helm source with name NAME using `dummy' method.
-Args ARGS are keywords provided by `helm-source-dummy'."
- (declare (indent 1))
- `(helm-make-source ,name 'helm-source-dummy ,@args))
-
-(defmacro helm-build-in-file-source (name file &rest args)
- "Build a helm source with NAME name using `candidates-in-files' method.
-Arg FILE is a filename, the contents of this file will be
-used as candidates in buffer.
-Args ARGS are keywords provided by `helm-source-in-file'."
- (declare (indent 1))
- `(helm-make-source ,name 'helm-source-in-file
- :candidates-file ,file ,@args))
-
-
-(provide 'helm-source)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-source ends here
+++ /dev/null
-;;; helm.el --- Emacs incremental and narrowing framework -*- lexical-binding: t -*-
-
-;; Copyright (C) 2007 Tamas Patrovics
-;; 2008 ~ 2011 rubikitch <rubikitchNOSPAMruby-lang.org>
-;; 2011 ~ 2015 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; This is a fork of anything.el wrote by Tamas Patrovics.
-
-;; Authors of anything.el: Tamas Patrovics
-;; rubikitch <rubikitchNOSPAMruby-lang.org>
-;; Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; Author: Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-;; URL: http://github.com/emacs-helm/helm
-
-;; 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/>.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'advice) ; Shutup byte compiler about ad-deactivate.
-(require 'helm-lib)
-(require 'helm-multi-match)
-(require 'helm-source)
-
-\f
-;;; Multi keys
-;;
-;;
-;;;###autoload
-(defun helm-define-multi-key (keymap key functions &optional delay)
- "In KEYMAP, define key sequence KEY for function list FUNCTIONS.
-Each function run sequentially each time the key KEY is pressed.
-If DELAY is specified switch back to initial function of FUNCTIONS list
-after DELAY seconds.
-The functions in FUNCTIONS list are functions with no args.
-e.g
- \(defun foo ()
- (message \"Run foo\"))
- \(defun bar ()
- (message \"Run bar\"))
- \(defun baz ()
- (message \"Run baz\"))
-
-\(helm-define-multi-key global-map \"<f5> q\" '(foo bar baz) 2)
-
-Each time \"<f5> q\" is pressed the next function is executed, if you wait
-More than 2 seconds, next hit will run again the first function and so on."
- (define-key keymap key (helm-make-multi-command functions delay)))
-
-;;;###autoload
-(defmacro helm-multi-key-defun (name docstring funs &optional delay)
- "Define NAME as a multi-key command running FUNS.
-After DELAY seconds the FUNS list is reinitialised.
-See `helm-define-multi-key'."
- (declare (indent 2))
- (setq docstring (if docstring (concat docstring "\n\n")
- "This is a helmish multi-key command."))
- `(defalias (quote ,name) (helm-make-multi-command ,funs ,delay) ,docstring))
-
-(defun helm-make-multi-command (functions &optional delay)
- "Return an anonymous multi-key command running FUNCTIONS.
-Run each function of FUNCTIONS list in turn when called within DELAY seconds."
- (declare (indent 1))
- (let ((funs functions)
- (iter (cl-gensym "helm-iter-key"))
- (timeout delay))
- (eval (list 'defvar iter nil))
- (lambda () (interactive) (helm-run-multi-key-command funs iter timeout))))
-
-(defun helm-run-multi-key-command (functions iterator delay)
- (let ((fn (lambda ()
- (cl-loop for count from 1 to (length functions)
- collect count)))
- next)
- (unless (and (symbol-value iterator)
- ;; Reset iterator when another key is pressed.
- (eq this-command real-last-command))
- (set iterator (helm-iter-list (funcall fn))))
- (setq next (helm-iter-next (symbol-value iterator)))
- (unless next
- (set iterator (helm-iter-list (funcall fn)))
- (setq next (helm-iter-next (symbol-value iterator))))
- (and next (symbol-value iterator) (call-interactively (nth (1- next) functions)))
- (when delay (run-with-idle-timer delay nil `(lambda ()
- (setq ,iterator nil))))))
-
-(helm-multi-key-defun helm-toggle-resplit-and-swap-windows
- "Multi key command to resplit and swap helm window.
-First call run `helm-toggle-resplit-window',
-second call within 0.5s run `helm-swap-windows'."
- '(helm-toggle-resplit-window helm-swap-windows) 1)
-
-;;;###autoload
-(defun helm-define-key-with-subkeys (map key subkey command
- &optional other-subkeys menu exit-fn)
- "Allow defining in MAP a KEY and SUBKEY to COMMAND.
-
-This allow typing KEY to call COMMAND the first time and
-type only SUBKEY on subsequent calls.
-
-Arg MAP is the keymap to use, SUBKEY is the initial short keybinding to
-call COMMAND.
-
-Arg OTHER-SUBKEYS is an alist specifying other short keybindings
-to use once started.
-e.g:
-
-\(helm-define-key-with-subkeys global-map
- \(kbd \"C-x v n\") ?n 'git-gutter:next-hunk '((?p . git-gutter:previous-hunk))\)
-
-
-In this example, `C-x v n' will run `git-gutter:next-hunk'
-subsequent hits on \"n\" will run this command again
-and subsequent hits on \"p\" will run `git-gutter:previous-hunk'.
-
-Arg MENU is a string to display in minibuffer
-to describe SUBKEY and OTHER-SUBKEYS.
-Arg EXIT-FN specify a function to run on exit.
-
-Any other keys pressed run their assigned command defined in MAP
-and exit the loop running EXIT-FN if specified.
-
-NOTE: SUBKEY and OTHER-SUBKEYS bindings support
-only char syntax actually (e.g ?n)
-so don't use strings, vectors or whatever to define them."
- (declare (indent 1))
- (define-key map key
- (lambda ()
- (interactive)
- (unwind-protect
- (progn
- (call-interactively command)
- (while (let ((input (read-key menu)) other kb com)
- (setq last-command-event input)
- (cond
- ((eq input subkey)
- (call-interactively command)
- t)
- ((setq other (assoc input other-subkeys))
- (call-interactively (cdr other))
- t)
- (t
- (setq kb (vector last-command-event))
- (setq com (lookup-key map kb))
- (if (commandp com)
- (call-interactively com)
- (setq unread-command-events
- (nconc (mapcar 'identity kb)
- unread-command-events)))
- nil)))))
- (and exit-fn (funcall exit-fn))))))
-
-\f
-;;; Keymap
-;;
-;;
-(defvar helm-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map minibuffer-local-map)
- (define-key map (kbd "<down>") 'helm-next-line)
- (define-key map (kbd "<up>") 'helm-previous-line)
- (define-key map (kbd "C-n") 'helm-next-line)
- (define-key map (kbd "C-p") 'helm-previous-line)
- (define-key map (kbd "<C-down>") 'helm-follow-action-forward)
- (define-key map (kbd "<C-up>") 'helm-follow-action-backward)
- (define-key map (kbd "<prior>") 'helm-previous-page)
- (define-key map (kbd "<next>") 'helm-next-page)
- (define-key map (kbd "M-v") 'helm-previous-page)
- (define-key map (kbd "C-v") 'helm-next-page)
- (define-key map (kbd "M-<") 'helm-beginning-of-buffer)
- (define-key map (kbd "M->") 'helm-end-of-buffer)
- (define-key map (kbd "C-g") 'helm-keyboard-quit)
- (define-key map (kbd "<right>") 'helm-next-source)
- (define-key map (kbd "<left>") 'helm-previous-source)
- (define-key map (kbd "<RET>") 'helm-maybe-exit-minibuffer)
- (define-key map (kbd "C-i") 'helm-select-action)
- (define-key map (kbd "C-z") 'helm-execute-persistent-action)
- (define-key map (kbd "C-j") 'helm-execute-persistent-action)
- (define-key map (kbd "C-o") 'helm-next-source)
- (define-key map (kbd "C-l") 'helm-recenter-top-bottom-other-window)
- (define-key map (kbd "M-C-l") 'helm-reposition-window-other-window)
- (define-key map (kbd "C-M-v") 'helm-scroll-other-window)
- (define-key map (kbd "M-<next>") 'helm-scroll-other-window)
- (define-key map (kbd "C-M-y") 'helm-scroll-other-window-down)
- (define-key map (kbd "C-M-S-v") 'helm-scroll-other-window-down)
- (define-key map (kbd "M-<prior>") 'helm-scroll-other-window-down)
- (define-key map (kbd "<C-M-down>") 'helm-scroll-other-window)
- (define-key map (kbd "<C-M-up>") 'helm-scroll-other-window-down)
- (define-key map (kbd "C-@") 'helm-toggle-visible-mark)
- (define-key map (kbd "C-SPC") 'helm-toggle-visible-mark)
- (define-key map (kbd "M-SPC") 'helm-toggle-visible-mark)
- (define-key map (kbd "M-[") nil)
- (define-key map (kbd "M-(") 'helm-prev-visible-mark)
- (define-key map (kbd "M-)") 'helm-next-visible-mark)
- (define-key map (kbd "C-k") 'helm-delete-minibuffer-contents)
- (define-key map (kbd "C-x C-f") 'helm-quit-and-find-file)
- (define-key map (kbd "M-m") 'helm-toggle-all-marks)
- (define-key map (kbd "M-a") 'helm-mark-all)
- (define-key map (kbd "M-U") 'helm-unmark-all)
- (define-key map (kbd "C-w") 'helm-yank-text-at-point)
- (define-key map (kbd "C-M-a") 'helm-show-all-in-this-source-only)
- (define-key map (kbd "C-M-e") 'helm-display-all-sources)
- (define-key map (kbd "C-r") 'undefined)
- (define-key map (kbd "C-s") 'undefined)
- (define-key map (kbd "M-s") 'undefined)
- (define-key map (kbd "C-}") 'helm-narrow-window)
- (define-key map (kbd "C-{") 'helm-enlarge-window)
- (define-key map (kbd "C-c -") 'helm-swap-windows)
- (define-key map (kbd "C-c C-d") 'helm-delete-current-selection)
- (define-key map (kbd "C-c C-y") 'helm-yank-selection)
- (define-key map (kbd "C-c C-k") 'helm-kill-selection-and-quit)
- (define-key map (kbd "C-c C-i") 'helm-copy-to-buffer)
- (define-key map (kbd "C-c C-f") 'helm-follow-mode)
- (define-key map (kbd "C-c C-u") 'helm-refresh)
- (define-key map (kbd "C-c >") 'helm-toggle-truncate-line)
- (define-key map (kbd "M-p") 'previous-history-element)
- (define-key map (kbd "M-n") 'next-history-element)
- (define-key map (kbd "C-!") 'helm-toggle-suspend-update)
- (define-key map (kbd "C-x b") 'helm-resume-previous-session-after-quit)
- (define-key map (kbd "C-x C-b") 'helm-resume-list-buffers-after-quit)
- ;; Disable `file-cache-minibuffer-complete'.
- (define-key map (kbd "<C-tab>") 'undefined)
- ;; Multi keys
- (define-key map (kbd "C-t") 'helm-toggle-resplit-and-swap-windows)
- ;; Debugging command
- (define-key map (kbd "C-h C-d") 'undefined)
- (define-key map (kbd "C-h C-d") 'helm-enable-or-switch-to-debug)
- ;; Allow to eval keymap without errors.
- (define-key map [f1] nil)
- (define-key map (kbd "C-h C-h") 'undefined)
- (define-key map (kbd "C-h h") 'undefined)
- ;; Use `describe-mode' key in `global-map'.
- (cl-dolist (k (where-is-internal 'describe-mode global-map))
- (define-key map k 'helm-help))
- (define-key map (kbd "C-c ?") 'helm-help)
- ;; Bind all actions from 1 to 12 to their corresponding nth index+1.
- (cl-loop for n from 0 to 12 do
- (define-key map (kbd (format "<f%s>" (1+ n)))
- `(lambda ()
- (interactive)
- (helm-select-nth-action ,n))))
- ;; Bind keys to allow executing default action
- ;; on first 9 candidates before and after selection.
- (cl-loop for n from 1 to 9
- for key = (format "C-c %d" n)
- for key- = (format "C-x %d" n)
- for fn = `(lambda ()
- (interactive)
- (helm-execute-selection-action-at-nth ,n))
- for fn- = `(lambda ()
- (interactive)
- (helm-execute-selection-action-at-nth ,(- n)))
- do (progn
- (define-key map (kbd key) fn)
- (define-key map (kbd key-) fn-)))
- map)
- "Keymap for helm.")
-
-\f
-(defgroup helm nil
- "Open helm."
- :prefix "helm-" :group 'convenience)
-
-(defcustom helm-completion-window-scroll-margin 5
- " `scroll-margin' to use for helm completion window.
-Which see. Set to 0 to disable.
-NOTE: This have no effect when `helm-display-source-at-screen-top'
-id non--nil."
- :group 'helm
- :type 'integer)
-
-(defcustom helm-display-source-at-screen-top t
- "Display candidates at the top of screen.
-This happen when using `helm-next-source' and `helm-previous-source'.
-NOTE: When non--nil (default) disable `helm-completion-window-scroll-margin'."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-candidate-number-limit 100
- "Limit candidate number globally.
-Do not show more candidates than this limit from individual sources.
-It is usually pointless to show hundreds of matches
-when the pattern is empty, because it is much simpler to type a
-few characters to narrow down the list of potential candidates.
-
-Set it to nil if you don't want this limit."
- :group 'helm
- :type '(choice (const :tag "Disabled" nil) integer))
-
-(defcustom helm-idle-delay 0.01
- "Be idle for this many seconds, before updating in delayed sources.
-This is useful for sources involving heavy operations
-\(like launching external programs\), so that candidates
-from the source are not retrieved unnecessarily if the user keeps typing.
-
-It also can be used to declutter the results helm displays,
-so that results from certain sources are not shown with every
-character typed, only if the user hesitates a bit.
-Be sure to know what you are doing when modifying this."
- :group 'helm
- :type 'float)
-
-(defcustom helm-input-idle-delay 0.01
- "Be idle for this many seconds, before updating.
-
-Unlike `helm-idle-delay', it is also effective for non-delayed sources.
-If nil, candidates are collected immediately.
-
-Note: If this value is too low compared to `helm-idle-delay',
-you may have duplicated sources when using multiples sources.
-Safe value is always >= `helm-idle-delay'.
-Default settings are equal value for both.
-Be sure to know what you are doing when modifying this."
- :group 'helm
- :type 'float)
-
-(defcustom helm-exit-idle-delay 0
- "Be idle for this many seconds before exiting minibuffer while helm is updating.
-Note that this does nothing when helm-buffer is up to date
-\(i.e exit without delay in this condition\)."
- :group 'helm
- :type 'float)
-
-(defcustom helm-full-frame nil
- "Use current window to show the candidates.
-If t then Helm doesn't pop up a new window."
- :group 'helm
- :type 'boolean)
-
-(defvaralias 'helm-samewindow 'helm-full-frame)
-(make-obsolete-variable 'helm-samewindow 'helm-full-frame "1.4.8.1")
-
-(defcustom helm-quick-update nil
- "If non-nil, suppress displaying sources which are out of screen at first.
-They are treated as delayed sources at this input.
-This flag makes `helm' a bit faster with many sources."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-candidate-separator
- "--------------------"
- "Candidates separator of `multiline' source."
- :group 'helm
- :type 'string)
-
-(defcustom helm-save-configuration-functions
- '(set-window-configuration . current-window-configuration)
- "The functions used to restore/save window or frame configurations.
-It is a pair where the car is the function to restore window or frame config,
-and the cdr is the function to save the window or frame config.
-
-If you want to save and restore frame configuration, set this variable to
- '\(set-frame-configuration . current-frame-configuration\)
-NOTE: This may not work properly with own-frame minibuffer settings.
-Older version saves/restores frame configuration, but the default is changed now
-because flickering can occur in some environment."
- :group 'helm
- :type 'sexp)
-
-(defcustom helm-persistent-action-use-special-display nil
- "If non-nil, use `special-display-function' in persistent action."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-display-function 'helm-default-display-buffer
- "Function to display *helm* buffer.
-It is `helm-default-display-buffer' by default,
-which affects `helm-full-frame'."
- :group 'helm
- :type 'symbol)
-
-(defcustom helm-case-fold-search 'smart
- "Add 'smart' option to `case-fold-search'.
-When smart is enabled, ignore case in the search strings
-if pattern contains no uppercase characters.
-Otherwise, with a nil or t value, the behavior is same as
-`case-fold-search'.
-Default value is smart, other possible values are nil and t.
-NOTE: This have no effect in asynchronous sources, you will
-have to implement a similar feature directly in the process.
-See in helm-grep.el how it is implemented."
- :group 'helm
- :type '(choice (const :tag "Ignore case" t)
- (const :tag "Respect case" nil)
- (other :tag "Smart" 'smart)))
-
-(defcustom helm-file-name-case-fold-search
- (if (memq system-type
- '(cygwin windows-nt ms-dos darwin))
- t
- helm-case-fold-search)
- "Local setting of `helm-case-fold-search' for reading filenames.
-
-See `helm-case-fold-search' for more info."
- :group 'helm
- :type 'symbol)
-
-(defcustom helm-reuse-last-window-split-state nil
- "Reuse the last state of window split, vertical or horizontal.
-That is when you use `helm-toggle-resplit-window' the next helm session
-will reuse the same window scheme than the one of last session unless
-`helm-split-window-default-side' is 'same or 'other."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-split-window-preferred-function 'helm-split-window-default-fn
- "Default function used for splitting window."
- :group 'helm
- :type 'function)
-
-(defcustom helm-split-window-default-side 'below
- "The default side to display `helm-buffer'.
-Must be one acceptable arg for `split-window' SIDE,
-that is `below', `above', `left' or `right'.
-
-Other acceptable values are `same' which always display `helm-buffer'
-in current window and `other' that display `helm-buffer' below if only one
-window or in `other-window-for-scrolling' if available.
-
-A nil value as same effect as `below'.
-If `helm-full-frame' is non--nil, it take precedence on this.
-
-See also `helm-split-window-in-side-p' and `helm-always-two-windows' that
-take precedence on this.
-
-NOTE: this have no effect if `helm-split-window-preferred-function' is not
-`helm-split-window-default-fn' unless this new function handle this."
- :group 'helm
- :type 'symbol)
-
-(defcustom helm-split-window-in-side-p nil
- "Force splitting inside selected window when non--nil.
-See also `helm-split-window-default-side'.
-
-NOTE: this have no effect if `helm-split-window-preferred-function' is not
-`helm-split-window-default-fn' unless this new function handle this."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-always-two-windows nil
- "When non--nil helm will use two windows in this frame.
-That is one window to display `helm-buffer' and one to display
-`helm-current-buffer'.
-
-Note: this have no effect when `helm-split-window-in-side-p' is non--nil,
-or when `helm-split-window-default-side' is set to 'same.
-
-When `helm-autoresize-mode' is enabled, setting this to nil
-will have no effect.
-
-Also when non-nil it overhides the effect of `helm-split-window-default-side'
-set to `other'."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-sources-using-default-as-input '(helm-source-imenu
- helm-source-imenu-all
- helm-source-info-elisp
- helm-source-etags-select
- helm-source-man-pages
- helm-source-occur
- helm-source-moccur)
- "List of helm sources that need to use `helm--maybe-use-default-as-input'.
-When a source is member of this list, default `thing-at-point'
-will be used as input."
- :group 'helm
- :type '(repeat (choice symbol)))
-
-(defcustom helm-delete-minibuffer-contents-from-point t
- "When non--nil, `helm-delete-minibuffer-contents' delete region from `point'.
-Otherwise delete `minibuffer-contents'.
-See documentation of `helm-delete-minibuffer-contents'."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-follow-mode-persistent nil
- "Retrieve last state of `helm-follow-mode' in next helm session when non--nil.
-This will not make it persistent through emacs sessions though,
-you will have to set explicitely the `follow' attribute in the source where
-you want this mode enabled definitely."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-prevent-escaping-from-minibuffer t
- "Prevent escaping from minibuffer during helm session."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-move-to-line-cycle-in-source nil
- "Move to end or beginning of source when reaching top or bottom of source.
-This happen when using `helm-next/previous-line'."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-fuzzy-match-fn 'helm-fuzzy-match
- "The function for fuzzy matching in `helm-source-sync' based sources."
- :group 'helm
- :type 'function)
-
-(defcustom helm-fuzzy-search-fn 'helm-fuzzy-search
- "The function for fuzzy matching in `helm-source-in-buffer' based sources."
- :group 'helm
- :type 'function)
-
-(defcustom helm-fuzzy-sort-fn 'helm-fuzzy-matching-default-sort-fn
- "The sort transformer function used in fuzzy matching.
-When nil no sorting will be done."
- :group 'helm
- :type 'function)
-
-(defcustom helm-fuzzy-matching-highlight-fn 'helm-fuzzy-default-highlight-match
- "The function to highlight matches in fuzzy matching.
-When nil no highlighting will be done."
- :group 'helm
- :type 'function)
-
-(defcustom helm-autoresize-max-height 40
- "Specifies a maximum height and defaults to the height of helm window's frame in percentage.
-
-See `fit-window-to-buffer' for more infos."
- :group 'helm
- :type 'integer)
-
-(defcustom helm-autoresize-min-height 10
- "Specifies a minimum height and defaults to the height of helm window's frame in percentage.
-
-If nil the default of `window-min-height' is used
-See `fit-window-to-buffer' for more infos."
- :group 'helm
- :type 'integer)
-
-(defcustom helm-input-method-verbose-flag nil
- "The default value of `input-method-verbose-flag' to use in helm minibuffer.
-It is nil by default to allow helm updating and exiting without turning off
-the input method when complex methods are in use, if you set it to any other
-value allowed by `input-method-verbose-flag' you will have at each time you want
-to exit or helm update to disable the `current-input-method' with `C-\\'."
- :group 'helm
- :type '(radio :tag "A flag to control extra guidance given by input methods in helm."
- (const :tag "Never provide guidance" nil)
- (const :tag "Always provide guidance" t)
- (const :tag "Provide guidance only in complex methods" complex-only)))
-
-(defcustom helm-display-header-line t
- "Display header-line when non nil."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-inherit-input-method t
- "Inherit `current-input-method' from `current-buffer' when non--nil.
-The default is to enable this by default, the user can toggle the current
-input method with `toggle-input-method'."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-echo-input-in-header-line nil
- "Send current input in header-line."
- :group 'helm
- :type 'boolean)
-
-\f
-;;; Faces
-;;
-;;
-(defgroup helm-faces nil
- "Customize the appearance of helm."
- :prefix "helm-"
- :group 'faces
- :group 'helm)
-
-(defface helm-source-header
- '((((background dark))
- :background "#22083397778B"
- :foreground "white"
- :weight bold :height 1.3 :family "Sans Serif")
- (((background light))
- :background "#abd7f0"
- :foreground "black"
- :weight bold :height 1.3 :family "Sans Serif"))
- "Face for source header in the helm buffer."
- :group 'helm-faces)
-
-(defface helm-visible-mark
- '((((min-colors 88) (background dark))
- (:background "green1" :foreground "black"))
- (((background dark))
- (:background "green" :foreground "black"))
- (((background light)) :background "#d1f5ea")
- (((min-colors 88))
- (:background "green1"))
- (t (:background "green")))
- "Face for visible mark."
- :group 'helm-faces)
-
-(defface helm-header
- '((t (:inherit header-line)))
- "Face for header lines in the helm buffer."
- :group 'helm-faces)
-
-(defface helm-candidate-number
- '((((background dark)) :background "Yellow" :foreground "black")
- (((background light)) :background "#faffb5" :foreground "black"))
- "Face for candidate number in mode-line." :group 'helm-faces)
-
-(defface helm-selection
- '((((background dark)) :background "ForestGreen"
- :distant-foreground "black")
- (((background light)) :background "#b5ffd1"
- :distant-foreground "black"))
- "Face for currently selected item in the helm buffer."
- :group 'helm-faces)
-
-(defface helm-separator
- '((((background dark)) :foreground "red")
- (((background light)) :foreground "#ffbfb5"))
- "Face for multiline source separator."
- :group 'helm-faces)
-
-(defface helm-action
- '((t (:underline t)))
- "Face for action lines in the helm action buffer."
- :group 'helm-faces)
-
-(defface helm-prefarg
- '((((background dark)) :foreground "green")
- (((background light)) :foreground "red"))
- "Face for showing prefix arg in mode-line."
- :group 'helm-faces)
-
-(defface helm-match
- '((((background light)) :foreground "#b00000")
- (((background dark)) :foreground "gold1"))
- "Face used to highlight matches."
- :group 'helm-faces)
-
-(defface helm-header-line-left-margin
- '((t (:foreground "black" :background "yellow")))
- "Face used to highlight helm-header sign in left-margin."
- :group 'helm-faces)
-
-\f
-;;; Variables.
-;;
-;;
-(defvar helm-type-attributes nil
- "It's a list of \(TYPE ATTRIBUTES ...\).
-ATTRIBUTES are the same as attributes for `helm-sources'.
-TYPE connects the value to the appropriate sources.
-Don't set this directly, use instead `define-helm-type-attribute'.
-
-This allows specifying common attributes for several sources.
-For example, sources which provide files can specify
-common attributes with a `file' type.")
-
-(defvar helm-source-filter nil
- "A list of source names to be displayed.
-Other sources won't appear in the search results.
-If nil then there is no filtering.
-See also `helm-set-source-filter'.")
-
-(defvar helm-selection-overlay nil
- "Overlay used to highlight the currently selected item.")
-
-(defvar helm-async-processes nil
- "List of information about asynchronous processes managed by helm.")
-
-(defvar helm-before-initialize-hook nil
- "Run before helm initialization.
-This hook is run before init functions in `helm-sources',
-that is before creation of `helm-buffer'.
-Local variables for `helm-buffer' that need a value from `current-buffer'
-can be set here with `helm-set-local-variable'.")
-
-(defvar helm-after-initialize-hook nil
- "Run after helm initialization.
-This hook run after `helm-buffer' is created but not from `helm-buffer'
-so the hook have to specify in which buffer it should run.")
-
-(defvar helm-update-hook nil
- "Run after the helm buffer was updated according the new input pattern.
-This hook is run at the beginning of buffer.
-The first candidate is selected after running this hook.
-See also `helm-after-update-hook'.")
-
-(defvar helm-after-update-hook nil
- "Run after the helm buffer was updated according the new input pattern.
-This is very similar to `helm-update-hook' but selection is not moved.
-It is useful to select a particular object instead of the first one.")
-
-(defvar helm-cleanup-hook nil
- "Run after helm minibuffer is closed.
-IOW this hook is executed BEFORE performing action.")
-
-(defvar helm-select-action-hook nil
- "Run when opening the action buffer.")
-
-(defvar helm-before-action-hook nil
- "Run before executing action.
-Contrarily to `helm-cleanup-hook',
-this hook run before helm minibuffer is closed
-and before performing action.")
-
-(defvar helm-after-action-hook nil
- "Run after executing action.")
-
-(defvar helm-exit-minibuffer-hook nil
- "Run just before exiting minibuffer.")
-
-(defvar helm-after-persistent-action-hook nil
- "Run after executing persistent action.")
-
-(defvar helm-move-selection-before-hook nil
- "Run before moving selection in `helm-buffer'.")
-
-(defvar helm-move-selection-after-hook nil
- "Run after moving selection in `helm-buffer'.")
-
-(defvar helm-after-preselection-hook nil
- "Run after preselection in `helm-buffer'.")
-
-(defvar helm-window-configuration-hook nil
- "Run when switching to and back from action buffer.")
-
-(defconst helm-restored-variables
- '(helm-candidate-number-limit
- helm-source-filter
- helm-source-in-each-line-flag
- helm-map
- helm-sources)
- "Variables which are restored after `helm' invocation.")
-
-(defvar helm-execute-action-at-once-if-one nil
- "Execute default action and exit when only one candidate is remaining.
-It can be also a function called with no args returning a boolean value.")
-
-(defvar helm-quit-if-no-candidate nil
- "Quit when there is no candidates when non--nil.
-This variable accepts a function, which is executed if no candidate.")
-
-(defvar helm-source-in-each-line-flag nil
- "Non-nil means add helm-source text-property in each candidate.
-experimental feature.")
-
-(defvar helm-debug-variables nil
- "A list of helm variables to show in `helm-debug-output'.
-Otherwise all variables started with `helm-' are shown.")
-
-(defvar helm-debug-buffer "*Debug Helm Log*")
-
-(defvar helm-debug nil
- "If non-nil, write log message into `helm-debug-buffer' buffer.
-It is disabled by default because `helm-debug-buffer' grows quickly.")
-
-(defvar helm-compile-source-functions
- '(helm-compile-source--type
- helm-compile-source--dummy
- helm-compile-source--candidates-in-buffer)
- "Functions to compile elements of `helm-sources' (plug-in).")
-
-(defvar helm-mode-line-string "\
-\\<helm-map>\
-\\[helm-help]:Help \
-\\[helm-select-action]:Act \
-\\[helm-maybe-exit-minibuffer]/\
-f1/f2/f-n:NthAct \
-\\[helm-toggle-suspend-update]:Tog.suspend"
- "Help string displayed in mode-line in `helm'.
-It can be a string or a list of two args, in this case,
-first arg is a string that will be used as name for candidates number,
-second arg any string to display in mode line.
-If nil, use default `mode-line-format'.")
-
-(defvar helm-minibuffer-set-up-hook nil
- "Hook that run at initialization of minibuffer.
-Useful for modifying the settings of minibuffer in helm.
-
-Here an example to hide minibuffer when using
-`helm-echo-input-in-header-line':
-
- (add-hook 'helm-minibuffer-set-up-hook #'helm-hide-minibuffer-maybe)
-
-Note that we check `helm-echo-input-in-header-line' value
-from `helm-buffer' which allow detecting possible local
-value of this var.")
-
-(defvar helm-help-message
- "* Helm Generic Help
-
-\\<helm-map>`helm' is an Emacs incremental completion and selection narrowing framework.
-
-Narrow the list by typing some pattern,
-Multiple patterns are allowed by separating with a space.
-Select with natural Emacs operations, choose with RET.
-
-** Help
-
-C-h m\t\tRun this generic help for helm.
-
-** Basic Operations
-
-These are the default key bindings:
-
-| Key | Alternative Keys | Command |
-|---------+------------------+-----------------------------------------------------------|
-| C-p | Up | Previous Line |
-| C-n | Down | Next Line |
-| M-v | PageUp | Previous Page |
-| C-v | PageDown | Next Page |
-| Enter | | Execute first (default) action / Select |
-| M-< | | First Line |
-| M-> | | Last Line |
-| C-M-S-v | M-PageUp, C-M-y | Previous Page (other-window) |
-| C-M-v | M-PageDown | Next Page (other-window) |
-| Tab | C-i | Show action list |
-| Left | | Previous Source |
-| Right | C-o | Next Source |
-| C-k | | Delete pattern (with prefix arg delete from point to end) |
-| C-j | C-z | Persistent Action (Execute and keep helm session) |
-
-** Shortcuts For nth Action
-
-f1-12: Execute nth 1 to 12 Action(s).
-
-** Shortcuts for executing Default Action on nth candidate
-
-C-x <n> => execute default action on number <n> candidate before selection.
-C-c <n> => execute default action on number <n> candidate after selection.
-
-Of course this works only on the 9 first and previous candidates.
-
-Helm provides nothing to visualize candidates numbers, up to you to install
-linum-relative package and enable linum-relative in helm..
-
-** Visible Marks
-
-Visible marks store candidate. Some actions uses marked candidates.
-
-** Miscellaneous Commands
-
-\\[helm-toggle-resplit-and-swap-windows]\t\tToggle vertical/horizontal split on first hit and swap helm window on second hit.
-\\[helm-quit-and-find-file]\t\tDrop into `helm-find-files'.
-\\[helm-delete-current-selection]\t\tDelete selected item (visually).
-\\[helm-kill-selection-and-quit]\t\tKill display value of candidate and quit (with prefix arg kill the real value).
-\\[helm-yank-selection]\t\tYank selection into pattern.
-\\[helm-follow-mode]\t\tToggle automatical execution of persistent action.
-\\[helm-follow-action-forward]\tRun persistent action and goto next line.
-\\[helm-follow-action-backward]\t\tRun persistent action and goto previous line.
-\\[helm-refresh]\t\tRecalculate and redisplay candidates.
-\\[helm-toggle-suspend-update]\t\tSuspend/reenable update.
-
-** Global Commands
-
-\\<global-map>\\[helm-resume] revives last `helm' session.
-It is very useful, so you should bind any key.
-
-** Helm Map
-\\{helm-map}"
- "Detailed help message string for `helm'.
-It also accepts function or variable symbol.")
-
-(defvar helm-autoresize-mode) ;; Undefined in `helm-default-display-buffer'.
-
-\f
-;;; Internal Variables
-;;
-;;
-(defvar helm-current-prefix-arg nil
- "Record `current-prefix-arg' when exiting minibuffer.")
-(defvar helm-saved-action nil
- "Saved value of the currently selected action by key.")
-(defvar helm-saved-current-source nil
- "Value of the current source when the action list is shown.")
-(defvar helm-compiled-sources nil
- "Compiled version of `helm-sources'.")
-(defvar helm-in-persistent-action nil
- "Flag whether in persistent-action or not.")
-(defvar helm-last-buffer nil
- "`helm-buffer' of previously `helm' session.")
-(defvar helm-saved-selection nil
- "Value of the currently selected object when the action list is shown.")
-(defvar helm-sources nil
- "[INTERNAL] Value of current sources in use, a list.")
-(defvar helm-buffer-file-name nil
- "Variable `buffer-file-name' when `helm' is invoked.")
-(defvar helm-candidate-cache (make-hash-table :test 'equal)
- "Holds the available candidate within a single helm invocation.")
-(defvar helm-input ""
- "The input typed in the candidates panel.")
-(defvar helm-input-local nil
- "Internal, store locally `helm-pattern' value for later use in `helm-resume'.")
-(defvar helm-source-name nil)
-(defvar helm-current-source nil)
-(defvar helm-candidate-buffer-alist nil)
-(defvar helm-match-hash (make-hash-table :test 'equal))
-(defvar helm-cib-hash (make-hash-table :test 'equal))
-(defvar helm-tick-hash (make-hash-table :test 'equal))
-(defvar helm-issued-errors nil)
-(defvar helm-debug-root-directory nil
- "When non--nil, save helm log to `helm-last-log-file'.
-Be aware that if you set that, you will end up with a huge directory
-of log files, so use that only for debugging purpose.
-See `helm-log-save-maybe' for more info.")
-(defvar helm-last-log-file nil
- "The name of the last helm session log file.")
-(defvar helm-follow-mode nil)
-(defvar helm--local-variables nil)
-(defvar helm-split-window-state nil)
-(defvar helm--window-side-state nil)
-(defvar helm-selection-point nil)
-(defvar helm-alive-p nil)
-(defvar helm-visible-mark-overlays nil)
-(defvar helm-update-blacklist-regexps '("^" "^ *" "$" "!" " " "\\b"
- "\\<" "\\>" "\\_<" "\\_>" ".*"))
-(defvar helm-force-updating-p nil)
-(defvar helm-exit-status 0
- "Flag to inform whether helm have exited or quitted.
-Exit with 0 mean helm have exited executing an action.
-Exit with 1 mean helm have quitted with \\[keyboard-quit]
-It is useful for example to restore a window config if helm abort
-in special cases.
-See `helm-exit-minibuffer' and `helm-keyboard-quit'.")
-(defvar helm-minibuffer-confirm-state nil)
-(defvar helm-quit nil)
-(defvar helm-attributes nil "List of all `helm' attributes.")
-(defvar helm-buffers nil
- "All of `helm-buffer' in most recently used order.")
-(defvar helm-current-position nil
- "Cons of \(point . window-start\) when `helm' is invoked.
-It is needed to restore position in `helm-current-buffer'
-when `helm' is keyboard-quitted.")
-(defvar helm-last-frame-or-window-configuration nil
- "Used to store window or frame configuration when helm start.")
-(defvar helm-onewindow-p nil)
-(defvar helm-types nil)
-(defvar helm--mode-line-string-real nil) ; The string to display in mode-line.
-(defvar helm-persistent-action-display-window nil)
-(defvar helm-marked-candidates nil
- "Marked candadates. List of \(source . real\) pair.")
-(defvar helm--mode-line-display-prefarg nil)
-(defvar helm--temp-follow-flag nil
- "[INTERNAL] A simple flag to notify persistent action we are following.")
-(defvar helm--reading-passwd-or-string nil)
-(defvar helm--in-update nil)
-(defvar helm--in-fuzzy nil)
-(defvar helm--maybe-use-default-as-input nil
- "Flag to notify the use of use-default-as-input.
-Use only in let-bindings.
-Use :default arg of `helm' as input to update display.
-Note that if also :input is specified as `helm' arg, it will take
-precedence on :default.")
-(defvar helm--temp-hooks nil
- "Store temporary hooks added by `with-helm-temp-hook'.")
-(defvar helm-truncate-lines nil
- "[Internal] Don't set this globally, it is used as a local var.")
-(defvar helm--prompt nil)
-(defvar helm--file-completion-sources
- '("Find Files" "Read File Name" "Read File Name History")
- "Sources that use the *find-files mechanism can be added here.
-Sources generated by `helm-mode' don't need to be added here, it will
-be done automatically.
-You should not modify this yourself unless you know what you do.")
-;; Same as `ffap-url-regexp' but keep it here to ensure `ffap-url-regexp' is not nil.
-(defvar helm--url-regexp "\\(news\\(post\\)?:\\|mailto:\\|file:\\|\\(ftp\\|https?\\|telnet\\|gopher\\|www\\|wais\\)://\\)")
-\f
-;; Utility: logging
-(defun helm-log (format-string &rest args)
- "Log message `helm-debug' is non-nil.
-Messages are written to the `helm-debug-buffer' buffer.
-
-Argument FORMAT-STRING is a string to use with `format'.
-Use optional arguments ARGS like in `format'."
- (when helm-debug
- (with-current-buffer (get-buffer-create helm-debug-buffer)
- (outline-mode)
- (buffer-disable-undo)
- (set (make-local-variable 'inhibit-read-only) t)
- (goto-char (point-max))
- (insert (let ((tm (current-time)))
- (format (concat (if (string-match "Start session" format-string)
- "* " "** ")
- "%s.%06d (%s)\n %s\n")
- (format-time-string "%H:%M:%S" tm)
- (nth 2 tm)
- (helm-log-get-current-function)
- (apply #'format (cons format-string args))))))))
-
-(defun helm-log-run-hook (hook)
- "Run HOOK like `run-hooks' but write these actions to helm log buffer."
- (helm-log "Executing %s with value = %S" hook (symbol-value hook))
- (helm-log "Executing %s with global value = %S" hook (default-value hook))
- (run-hooks hook)
- (helm-log "executed %s" hook))
-
-(defun helm-log-get-current-function ()
- "Get function name calling `helm-log'.
-The original idea is from `tramp-debug-message'."
- (cl-loop with exclude-func-re = "^helm-\\(?:interpret\\|log\\|.*funcall\\)"
- for btn from 1 to 40
- for btf = (cl-second (backtrace-frame btn))
- for fn = (if (symbolp btf) (symbol-name btf) "")
- if (and (string-match "^helm" fn)
- (not (string-match exclude-func-re fn)))
- return fn))
-
-(defun helm-log-error (&rest args)
- "Accumulate error messages into `helm-issued-errors'.
-ARGS are args given to `format'.
-e.g (helm-log-error \"Error %s: %s\" (car err) (cdr err))."
- (apply 'helm-log (concat "ERROR: " (car args)) (cdr args))
- (let ((msg (apply 'format args)))
- (unless (member msg helm-issued-errors)
- (add-to-list 'helm-issued-errors msg))))
-
-(defun helm-log-save-maybe ()
- "May be save log buffer to `helm-last-log-file'.
-If `helm-debug-root-directory' is non--nil and a valid directory,
-a directory named 'helm-debug-<date of today>'
-will be created there and the log recorded in a file named
-at the date and time of today in this directory."
- (when (and (stringp helm-debug-root-directory)
- (file-directory-p helm-debug-root-directory)
- helm-debug)
- (let ((logdir (expand-file-name (concat "helm-debug-"
- (format-time-string "%Y%m%d"))
- helm-debug-root-directory)))
- (make-directory logdir t)
- (with-current-buffer (get-buffer-create helm-debug-buffer)
- (write-region (point-min) (point-max)
- (setq helm-last-log-file
- (expand-file-name
- (format-time-string "%Y%m%d-%H%M%S")
- logdir))
- nil 'silent)
- (kill-buffer)))))
-
-;;;###autoload
-(defun helm-debug-open-last-log ()
- "Open helm log file of last helm session.
-If `helm-last-log-file' is nil, switch to `helm-debug-buffer' ."
- (interactive)
- (if helm-last-log-file
- (view-file helm-last-log-file)
- (switch-to-buffer helm-debug-buffer)
- (view-mode 1) (visual-line-mode 1)))
-
-(defun helm-print-error-messages ()
- "Print error messages in `helm-issued-errors'."
- (and helm-issued-errors
- (message "Helm issued errors: %s"
- (mapconcat 'identity (reverse helm-issued-errors) "\n"))))
-
-\f
-;; Programming Tools
-
-(defun helm-this-command ()
- "Return the actual command in action.
-Like `this-command' but return the real command,
-not `exit-minibuffer' or unwanted functions."
- (cl-loop with bl = '(helm-maybe-exit-minibuffer
- helm-confirm-and-exit-minibuffer
- helm-exit-minibuffer
- exit-minibuffer)
- for count from 1 to 50
- for btf = (backtrace-frame count)
- for fn = (cl-second btf)
- if (and
- ;; In some case we may have in the way an
- ;; advice compiled resulting in byte-code,
- ;; ignore it (Issue #691).
- (symbolp fn)
- (commandp fn)
- (not (memq fn bl)))
- return fn
- else
- if (and (eq fn 'call-interactively)
- (> (length btf) 2))
- return (cadr (cdr btf))))
-
-\f
-;; Test tools
-(defmacro with-helm-time-after-update (&rest body)
- (helm-with-gensyms (start-time time-elapsed)
- `(let ((,start-time (float-time)) ,time-elapsed)
- (add-hook 'helm-after-update-hook
- (lambda ()
- (setq ,time-elapsed (- (float-time) ,start-time))
- (keyboard-quit)))
- (unwind-protect ,@body
- (remove-hook 'helm-after-update-hook
- (lambda ()
- (setq ,time-elapsed (- (float-time) ,start-time))
- (keyboard-quit))))
- ,time-elapsed)))
-
-\f
-;; Helm API
-
-(defmacro with-helm-restore-variables (&rest body)
- "Restore `helm-restored-variables' after executing BODY."
- (declare (indent 0) (debug t))
- (helm-with-gensyms (orig-vars)
- `(let ((,orig-vars (mapcar (lambda (v)
- (cons v (symbol-value v)))
- helm-restored-variables)))
- (unwind-protect (progn ,@body)
- (cl-loop for (var . value) in ,orig-vars
- do (set var value))
- (helm-log "restore variables")))))
-
-(defmacro with-helm-default-directory (directory &rest body)
- (declare (indent 2) (debug t))
- `(let ((default-directory (or (and ,directory
- (file-name-as-directory ,directory))
- default-directory)))
- ,@body))
-
-(defun helm-default-directory ()
- "Return the local value of `default-directory' in `helm-buffer'."
- (buffer-local-value 'default-directory (get-buffer helm-buffer)))
-
-(defmacro with-helm-temp-hook (hook &rest body)
- "Execute temporarily BODY as a function for HOOK."
- (declare (indent 1) (debug t))
- (helm-with-gensyms (helm--hook)
- `(progn
- (defun ,helm--hook ()
- (unwind-protect
- (progn ,@body)
- (remove-hook ,hook (quote ,helm--hook))
- (fmakunbound (quote ,helm--hook))))
- (push (cons ',helm--hook ,hook) helm--temp-hooks)
- (add-hook ,hook (quote ,helm--hook)))))
-
-(defmacro with-helm-after-update-hook (&rest body)
- "Execute BODY at end of `helm-update'."
- (declare (indent 0) (debug t))
- `(with-helm-temp-hook 'helm-after-update-hook ,@body))
-
-(defmacro with-helm-alive-p (&rest body)
- "Return error when BODY run outside helm context."
- (declare (indent 0) (debug t))
- `(progn
- (if helm-alive-p
- (progn ,@body)
- (error "Running helm command outside of context"))))
-
-(defun helm-attr (attribute-name &optional source compute)
- "Get the value of ATTRIBUTE-NAME of SRC.
-If SRC is omitted, use current source.
-If COMPUTE is non--nil compute value of ATTRIBUTE-NAME
-with `helm-interpret-value'. COMPUTE can have also 'ignorefn as
-value, in this case `helm-interpret-value' will return a function
-as value inchanged, but will eval a symbol which is bound
-(i.e a variable)."
- (let ((src (or source (helm-get-current-source))))
- (helm-aif (or (assq attribute-name src)
- (helm-get-attribute-from-source-type attribute-name src))
- (if compute
- (helm-interpret-value (cdr it) src compute)
- (cdr it)))))
-
-(cl-defun helm-attr-defined (attribute-name
- &optional (src (helm-get-current-source)))
- "Return non-nil if ATTRIBUTE-NAME of SRC is defined.
-if SRC is omitted, use current source."
- (and (helm-attr attribute-name src) t))
-
-(cl-defun helm-attrset (attribute-name value
- &optional
- (src (helm-get-current-source))
- alter-type)
- "Set the value of ATTRIBUTE-NAME of source SRC to VALUE.
-If ATTRIBUTE-NAME doesn't exists in source it is created with value VALUE.
-If ALTER-TYPE is non--nil alter the value of ATTRIBUTE-NAME in `helm-attributes'
-if it exists.
-If SRC is omitted, use current source.
-If operation succeed, return value, otherwise nil."
- (let ((from-type (helm-get-attribute-from-source-type attribute-name src))
- done)
- (helm-aif (or (assq attribute-name src)
- (and alter-type from-type))
- (prog1 (setcdr it value) (setq done t))
- (unless from-type
- (setcdr src (cons (cons attribute-name value) (cdr src)))
- (setq done t)))
- (and done value)))
-
-(defun helm-get-attribute-from-source-type (attribute source)
- "Get ATTRIBUTE from type attribute of SOURCE."
- (when (assq 'type source)
- (assq attribute
- (assq (cdr (assq 'type source))
- helm-type-attributes))))
-
-(defun helm-get-attribute-from-type (attribute type)
- "Get ATTRIBUTE from TYPE.
-arg TYPE is an existing type defined in `helm-type-attributes'."
- (assq attribute (assq type helm-type-attributes)))
-
-(defun helm-get-actions-from-type (source)
- "Get actions list from type attribute of SOURCE."
- (when (assq 'type source)
- (helm-get-attribute-from-source-type 'action source)))
-
-(defun helm-inherit-attribute-from-source (attribute source)
- "Get the ATTRIBUTE of SOURCE."
- (helm-aif (assq attribute source)
- it
- (helm-get-attribute-from-source-type attribute source)))
-
-(defun helm-append-at-nth (seq elm index)
- "Append ELM at INDEX in SEQ."
- (let ((len (length seq)))
- (cond ((> index len) (setq index len))
- ((< index 0) (setq index 0)))
- (if (zerop index)
- (append elm seq)
- (cl-loop for i in seq
- for count from 1 collect i
- when (= count index)
- if (listp elm) append elm
- else collect elm))))
-
-(defun helm-add-action-to-source (name fn source &optional index)
- "Add new action NAME linked to function FN to SOURCE.
-Function FN should be a valid function that take one arg i.e candidate,
-argument NAME is a string that will appear in action menu
-and SOURCE should be an existing helm source already loaded.
-If INDEX is specified, action is added in action list at INDEX,
-otherwise it is added at end.
-This allow user to add a specific action to an existing source
-without modifying source code."
- (let ((actions (helm-attr 'action source 'ignorefn))
- (new-action (list (cons name fn))))
- (when (functionp actions)
- (setq actions (list (cons "Default action" actions))))
- (helm-attrset 'action
- (if index
- (helm-append-at-nth actions new-action index)
- (append actions new-action))
- source)))
-
-(defun helm-delete-action-from-source (action-or-name source)
- "Delete ACTION-OR-NAME from SOURCE.
-ACTION-OR-NAME can either be the name of action or the symbol function
-associated to name."
- (let* ((actions (helm-attr 'action source 'ignorefn))
- (del-action (if (symbolp action-or-name)
- (rassoc action-or-name actions)
- (assoc action-or-name actions))))
- (helm-attrset 'action (delete del-action actions) source)))
-
-(cl-defun helm-add-action-to-source-if (name fn source predicate
- &optional (index 4) test-only)
- "Add new action NAME linked to function FN to SOURCE.
-Action NAME will be available when the current candidate matches PREDICATE.
-This function add an entry in the `action-transformer' attribute
-of SOURCE (or create one if not found).
-Function PREDICATE should take one arg candidate.
-Function FN should be a valid function that take one arg i.e candidate,
-argument NAME is a string that will appear in action menu
-and SOURCE should be an existing helm source already loaded.
-If INDEX is specified, action is added in action list at INDEX.
-Value of INDEX should be always >=1, default to 4.
-This allow user to add a specific `action-tranformer'
-to an existing source without modifying source code.
-E.g
-Add the action \"Byte compile file async\" linked to
-function 'async-byte-compile-file to source `helm-source-find-files'
-only when predicate helm-ff-candidates-lisp-p return non--nil:
-
-\(helm-add-action-to-source-if \"Byte compile file async\"
- 'async-byte-compile-file
- helm-source-find-files
- 'helm-ff-candidates-lisp-p\)."
- (let* ((actions (helm-attr 'action source 'ignorefn))
- (action-transformers (helm-attr 'action-transformer source))
- (new-action (list (cons name fn)))
- (transformer `(lambda (actions candidate)
- (cond ((funcall (quote ,predicate) candidate)
- (helm-append-at-nth
- actions (quote ,new-action) ,index))
- (t actions)))))
- (when (functionp actions)
- (helm-attrset 'action (list (cons "Default action" actions)) source))
- (when (or (symbolp action-transformers) (functionp action-transformers))
- (setq action-transformers (list action-transformers)))
- (if test-only ; debug
- (delq nil (append (list transformer) action-transformers))
- (helm-attrset 'action-transformer
- (helm-fast-remove-dups
- (delq nil (append (list transformer) action-transformers))
- :test 'equal)
- source))))
-
-(defun helm-set-source-filter (sources)
- "Set the value of `helm-source-filter' to SOURCES and update.
-
-This function sets a filter for helm sources and it may be
-called while helm is running. It can be used to toggle
-displaying of sources dynamically. For example, additional keys
-can be bound into `helm-map' to display only the file-related
-results if there are too many matches from other sources and
-you're after files only:
-
-Shift+F shows only file results from some sources:
-
-\(define-key helm-map \"F\" 'helm-my-show-files-only)
-
-\(defun helm-my-show-files-only ()
- (interactive)
- (helm-set-source-filter '(\"File Name History\"
- \"Files from Current Directory\")))
-
-Shift+A shows all results:
-
-\(define-key helm-map \"A\" 'helm-my-show-all)
-
-\(defun helm-my-show-all ()
- (interactive)
- (helm-set-source-filter nil))
-
-The -my- part is added to avoid collisions with
-existing Helm function names."
- (let ((cur-disp-sel (with-current-buffer helm-buffer
- (helm-get-selection nil t))))
- (setq helm-source-filter (helm--normalize-filter-sources sources))
- (helm-log "helm-source-filter = %S" helm-source-filter)
- ;; Use force-update to run init/update functions.
- (helm-force-update (and (stringp cur-disp-sel)
- (regexp-quote cur-disp-sel)))))
-
-(defun helm--normalize-filter-sources (sources)
- (cl-loop for s in sources collect
- (cond ((symbolp s)
- (assoc-default 'name (symbol-value s)))
- ((listp s)
- (assoc-default 'name s))
- ((stringp s) s))))
-
-(defun helm-set-sources (sources &optional no-init no-update)
- "Set SOURCES during `helm' invocation.
-If NO-INIT is non-nil, skip executing init functions of SOURCES.
-If NO-UPDATE is non-nil, skip executing `helm-update'."
- (with-current-buffer helm-buffer
- (setq helm-compiled-sources nil
- helm-sources sources)
- (helm-log "helm-compiled-sources = %S" helm-compiled-sources)
- (helm-log "helm-sources = %S" helm-sources))
- (unless no-init (helm-funcall-foreach 'init))
- (unless no-update (helm-update)))
-
-(defun helm-get-sources ()
- "Return compiled `helm-sources', which is memoized.
-
-Attributes:
-
-- type
- `helm-type-attributes' are merged in.
-- candidates-buffer
- candidates, volatile and match attribute are created."
- (cond
- ;; action
- ((helm-action-window)
- helm-sources)
- ;; memoized
- (helm-compiled-sources)
- ;; first time
- (t
- (prog1
- (setq helm-compiled-sources
- (helm-compile-sources
- helm-sources helm-compile-source-functions))
- (helm-log "helm-compiled-sources = %S" helm-compiled-sources)))))
-
-(cl-defun helm-get-selection (&optional (buffer nil buffer-s)
- force-display-part)
- "Return the currently selected item or nil.
-if BUFFER is nil or unspecified, use helm-buffer as default value.
-If FORCE-DISPLAY-PART is non-nil, return the display string.
-If FORCE-DISPLAY-PART value is 'withprop the display string is returned
-with its properties."
- (setq buffer (if (and buffer buffer-s) buffer helm-buffer))
- (unless (helm-empty-buffer-p buffer)
- (with-current-buffer buffer
- (let* ((disp-fn (if (eq force-display-part 'withprop)
- 'buffer-substring
- 'buffer-substring-no-properties))
- (selection
- (or (and (not force-display-part)
- (get-text-property (overlay-start
- helm-selection-overlay)
- 'helm-realvalue))
- ;; It is needed to return properties of DISP in some case,
- ;; e.g for `helm-confirm-and-exit-minibuffer',
- ;; so use `buffer-substring' here when 'withprop is specified.
- (let ((disp (funcall
- disp-fn
- (overlay-start helm-selection-overlay)
- (1- (overlay-end helm-selection-overlay))))
- (source (helm-get-current-source)))
- (helm-aif (and (not force-display-part)
- (assoc-default 'display-to-real source))
- (helm-funcall-with-source source it disp)
- disp)))))
- (unless (equal selection "")
- (helm-log "selection = %S" selection)
- selection)))))
-
-(defun helm-get-actions-from-current-source ()
- "Return the associated action for the selected candidate.
-It is a function symbol \(sole action\) or list
-of \(action-display . function\)."
- (unless (helm-empty-buffer-p (helm-buffer-get))
- (helm-aif (helm-attr 'action-transformer)
- (helm-composed-funcall-with-source
- (helm-get-current-source) it
- (helm-attr 'action nil 'ignorefn)
- ;; Check if the first given transformer
- ;; returns the same set of actions for each
- ;; candidate in marked candidates.
- ;; If so use the car of marked to determine
- ;; the set of actions, otherwise use the selection.
- (if (cl-loop with marked = (helm-marked-candidates)
- with act = (car (helm-mklist it))
- with acts = (funcall act nil (car marked))
- for c in marked
- always (equal (funcall act nil c) acts))
- (car (helm-marked-candidates))
- (helm-get-selection)))
- (helm-attr 'action nil 'ignorefn))))
-
-(defun helm-get-current-source ()
- "Return the source for the current selection.
-Allow also checking if helm-buffer contain candidates."
- (or helm-current-source
- (with-current-buffer (helm-buffer-get)
- (or
- ;; This happen only when `helm-source-in-each-line-flag'
- ;; is non--nil and there is candidates in buffer.
- (get-text-property (point) 'helm-source)
- ;; Return nil when no--candidates.
- (cl-block exit
- ;; This goto-char shouldn't be necessary, but point is moved to
- ;; point-min somewhere else which shouldn't happen.
- (goto-char (overlay-start helm-selection-overlay))
- (let* ((header-pos (or (helm-get-previous-header-pos)
- (helm-get-next-header-pos)))
- (source-name
- (save-excursion
- (unless header-pos
- (cl-return-from exit nil))
- (goto-char header-pos)
- (helm-current-line-contents))))
- (cl-loop for source in (helm-get-sources) thereis
- (and (equal (assoc-default 'name source) source-name)
- source))))))))
-
-(defun helm-buffer-is-modified (buffer)
- "Return non-nil when BUFFER is modified since `helm' was invoked."
- (let* ((b (get-buffer buffer))
- (key (concat (buffer-name b) "/" (helm-attr 'name)))
- (source-tick (or (gethash key helm-tick-hash) 0))
- (buffer-tick (buffer-chars-modified-tick b))
- (modifiedp (/= source-tick buffer-tick)))
- (puthash key buffer-tick helm-tick-hash)
- (helm-log "buffer = %S" buffer)
- (helm-log "modifiedp = %S" modifiedp)
- modifiedp))
-
-(defun helm-current-buffer-is-modified ()
- "Check if `helm-current-buffer' is modified since `helm' was invoked."
- (helm-buffer-is-modified helm-current-buffer))
-
-(defun helm-run-after-exit (function &rest args)
- "Exectute FUNCTION with ARGS after exiting `helm'.
-The action is to call FUNCTION with arguments ARGS.
-Contrarily to `helm-exit-and-execute-action' this can be used
-to call non--actions functions with any ARGS or no ARGS at all.
-
-Use this on commands invoked from keybindings, but not
-on action functions invoked as action from the action menu,
-i.e functions called with RET."
- (helm-kill-async-processes)
- (helm-log "function = %S" function)
- (helm-log "args = %S" args)
- (helm-exit-and-execute-action
- (lambda (_candidate)
- (apply function args))))
-
-(defun helm-exit-and-execute-action (action)
- "Exit current helm session and execute ACTION.
-Argument ACTION is a function called with one arg (candidate)
-and part of the actions of current source.
-
-Use this on commands invoked from keybindings, but not
-on action functions invoked as action from the action menu,
-i.e functions called with RET."
- (setq helm-saved-action action)
- (setq helm-saved-selection (helm-get-selection))
- (helm-exit-minibuffer))
-
-(defalias 'helm-run-after-quit 'helm-run-after-exit)
-(make-obsolete 'helm-run-after-quit 'helm-run-after-exit "1.7.7")
-(defalias 'helm-quit-and-execute-action 'helm-exit-and-execute-action)
-(make-obsolete 'helm-quit-and-execute-action 'helm-exit-and-execute-action "1.7.7")
-
-(defun helm-interpret-value (value &optional source compute)
- "Interpret VALUE as variable, function or literal and return it.
-If VALUE is a function, call it with no arguments and return the value
-unless COMPUTE value is 'ignorefn.
-If SOURCE compute VALUE for this source.
-If VALUE is a variable, return the value.
-If VALUE is a symbol, but it is not a function or a variable, cause an error.
-Otherwise, return VALUE itself."
- (cond ((and source (functionp value) (not (eq compute 'ignorefn)))
- (helm-funcall-with-source source value))
- ((and (functionp value) (not (eq compute 'ignorefn)))
- (funcall value))
- ((and (symbolp value) (boundp value))
- (symbol-value value))
- ((and (symbolp value) (not (functionp value)))
- (error
- "helm-interpret-value: Symbol must be a function or a variable"))
- (t
- value)))
-
-(defun helm-set-local-variable (&rest args)
- "Bind each pair in ARGS locally to `helm-buffer'.
-
-Use this to set local vars before calling helm.
-
-When used from an init or update function
-(i.e when `helm-force-update' is running) the variables are set
-using `make-local-variable' within the `helm-buffer'.
-
-Usage: helm-set-local-variable ([VAR VALUE]...)
-Just like `setq' except that the vars are not set sequentially.
-IOW Don't use VALUE of previous VAR to set the VALUE of next VAR.
-
-\(fn VAR VALUE ...)"
- (if helm-force-updating-p
- (with-helm-buffer
- (cl-loop for i on args by #'cddr
- do (set (make-local-variable (car i)) (cadr i))))
- (setq helm--local-variables
- (append (cl-loop for i on args by #'cddr
- collect (cons (car i) (cadr i)))
- helm--local-variables))))
-
-\f
-;; Core: API helper
-(cl-defun helm-empty-buffer-p (&optional (buffer helm-buffer))
- "Check if BUFFER have candidates.
-Default value for BUFFER is `helm-buffer'."
- (zerop (buffer-size (and buffer (get-buffer buffer)))))
-
-(defun helm-empty-source-p ()
- "Check if current source contains candidates.
-This happen only in certains cases when e.g the last element
-of a source is deleted without updating the source."
- (with-helm-window
- (or (helm-empty-buffer-p)
- (and (helm-end-of-source-p)
- (eq (point-at-bol) (point-at-eol))
- (or
- (save-excursion
- (forward-line -1)
- (helm-pos-header-line-p))
- (bobp))))))
-
-\f
-;; Core: tools
-
-(defun helm-funcall-with-source (source functions &rest args)
- "Call from SOURCE FUNCTIONS list or single function FUNCTIONS with ARGS.
-FUNCTIONS can be a symbol or a list of functions.
-Return the result of last function call."
- (let ((helm-source-name (assoc-default 'name source))
- (helm-current-source source)
- (funs (if (functionp functions) (list functions) functions)))
- (helm-log "helm-source-name = %S" helm-source-name)
- (helm-log "functions = %S" functions)
- (helm-log "args = %S" args)
- (cl-loop with result for fn in funs
- do (setq result (apply fn args))
- finally return result)))
-
-(defun helm-funcall-foreach (sym &optional sources)
- "Call the associated function to SYM for each source if any."
- (let ((sources (or sources (helm-get-sources))))
- (cl-dolist (source sources)
- (helm-aif (assoc-default sym source)
- (helm-funcall-with-source source it)))))
-
-(defun helm-normalize-sources (sources)
- "If SOURCES is only one source, make a list of one element."
- (cond ((or (and sources
- (symbolp sources))
- (and (listp sources) (assq 'name sources)))
- (list sources))
- (sources)
- (t helm-sources)))
-
-(defun helm-get-candidate-number (&optional in-current-source)
- "Return candidates number in `helm-buffer'.
-If IN-CURRENT-SOURCE is provided return number of candidates
-in the source where point is."
- (with-current-buffer (helm-buffer-get)
- (if (or (helm-empty-buffer-p)
- (helm-empty-source-p))
- 0
- (save-excursion
- (if in-current-source
- (goto-char (helm-get-previous-header-pos))
- (goto-char (point-min)))
- (forward-line 1)
- (if (helm-pos-multiline-p)
- (save-excursion
- (cl-loop with count-multi = 1
- while (and (not (if in-current-source
- (save-excursion
- (forward-line 2)
- (or (helm-pos-header-line-p) (eobp)))
- (eobp)))
- (search-forward helm-candidate-separator nil t))
- do (cl-incf count-multi)
- finally return count-multi))
- (save-excursion
- (cl-loop with ln = 0
- while (not (if in-current-source
- (or (helm-pos-header-line-p) (eobp))
- (eobp)))
- unless (helm-pos-header-line-p)
- do (cl-incf ln)
- do (forward-line 1) finally return ln)))))))
-
-(defmacro with-helm-quittable (&rest body)
- "If an error occur in execution of BODY, quit helm safely."
- (declare (indent 0) (debug t))
- `(condition-case _v
- (let (inhibit-quit)
- ,@body)
- (quit (setq quit-flag t)
- (setq helm-quit t)
- (exit-minibuffer)
- (keyboard-quit)
- ;; See comment about this in `with-local-quit'.
- (eval '(ignore nil)))))
-
-(defun helm-compose (arg-lst func-lst)
- "Apply arguments specified in ARG-LST with each function of FUNC-LST.
-The result of each function will be the new `car' of ARG-LST.
-Each function in FUNC-LST must accept (length ARG-LST) arguments
-\(See examples below) .
-This function allows easy sequencing of transformer functions.
-Where generally, ARG-LST is '(candidates-list source) and FUNC-LST a
-list of transformer functions that take one or two arguments depending
-we are using 'filtered-candidate-transformer' or 'candidate-transformer'.
-e.g
-filtered-candidate-transformer:
-\(helm-compose '((1 2 3 4 5 6 7)
- '((name . \"A helm source\") (candidates . (a b c))))
- '((lambda (candidates _source)
- (cl-loop for i in candidates
- when (cl-oddp i) collect i))
- (lambda (candidates _source)
- (cl-loop for i in candidates collect (1+ i)))))
-=>(2 4 6 8)
-
-candidate-transformer:
-\(helm-compose '((1 2 3 4 5 6 7))
- '((lambda (candidates)
- (cl-loop for i in candidates
- when (cl-oddp i) collect i))
- (lambda (candidates)
- (cl-loop for i in candidates collect (1+ i)))))
-=> (2 4 6 8)."
- (cl-dolist (func func-lst)
- (setcar arg-lst (apply func arg-lst)))
- (car arg-lst))
-
-(defun helm-composed-funcall-with-source (source funcs &rest args)
- "With SOURCE apply `helm-funcall-with-source' with each FUNCS and ARGS.
-This is used in transformers to modify candidates list."
- (if (functionp funcs)
- (apply 'helm-funcall-with-source source funcs args)
- (apply 'helm-funcall-with-source source
- (lambda (&rest oargs) (helm-compose oargs funcs))
- args)))
-
-\f
-;; Core: entry point
-;; `:allow-nest' is not in this list because it is treated before.
-(defconst helm-argument-keys
- '(:sources :input :prompt :resume
- :preselect :buffer :keymap :default :history))
-
-;;;###autoload
-(defun helm (&rest plist)
- "Main function to execute helm sources.
-
-Keywords supported:
-:sources :input :prompt :resume :preselect
-:buffer :keymap :default :history :allow-nest
-
-Extra LOCAL-VARS keywords are supported, see below.
-
-PLIST is a list like \(:key1 val1 :key2 val2 ...\) or
-\(&optional sources input prompt resume
- preselect buffer keymap default history\).
-
-Basic keywords are the following:
-
-\:sources
-
-A list of sources used for this session. It also accepts a
-symbol, interpreted as a variable of a helm source
-i.e (a symbol can be passed instead of a list of sources).
-It also accepts an alist representing a helm source, which is
-detected by \(assq 'name ANY-SOURCES\).
-NOTE: In this case the source is embedded in the helm command and
-have no symbol name, so it is not reachable from outside.
-It will be referenced in `helm-sources' as a whole alist.
-
-\:input
-
-Temporary value of `helm-pattern', ie. initial input of minibuffer.
-
-\:prompt
-
-Prompt other than \"pattern: \".
-
-\:resume
-
-If t, Resurrect previously instance of `helm'. Skip the initialization.
-If 'noresume, this instance of `helm' cannot be resumed.
-
-\:preselect
-
-Initially selected candidate. Specified by exact candidate or a regexp.
-
-\:buffer
-
-`helm-buffer' instead of *helm*.
-
-\:keymap
-
-`helm-map' for current `helm' session.
-
-\:default
-
-A default argument that will be inserted in minibuffer \
-with \\<minibuffer-local-map>\\[next-history-element].
-When nil or not present `thing-at-point' will be used instead.
-If `helm--maybe-use-default-as-input' is non--nil display will be
-updated using :default arg as input unless :input is specified,
-which in this case will take precedence on :default
-This is a string or a list, in this case the car of the list will
-be used as initial default input, but you will be able to cycle in this
-list with \\<minibuffer-local-map>\\[next-history-element].
-
-\:history
-
-By default all minibuffer input is pushed to `minibuffer-history',
-if an argument HISTORY is provided, input will be pushed to HISTORY.
-History element should be a symbol.
-
-\:allow-nest
-
-Allow running this helm command within a running helm session.
-
-Of course, conventional arguments are supported, the two are same.
-
-\(helm :sources sources :input input :prompt prompt :resume resume
- :preselect preselect :buffer buffer :keymap keymap :default default
- :history history\)
-
-and
-
-\(helm sources input prompt resume preselect buffer keymap default history\)
-
-are the same.
-
-However the use of non keyword args is deprecated and should not be used.
-
-Other keywords are interpreted as local variables of this helm session.
-The `helm-' prefix can be omitted. For example,
-
-\(helm :sources 'helm-source-buffers-list
- :buffer \"*buffers*\" :candidate-number-limit 10\)
-
-means starting helm session with `helm-source-buffers'
-source in *buffers* buffer and set variable `helm-candidate-number-limit'
-to 10 as session local variable.
-
-\(fn &key SOURCES INPUT PROMPT RESUME PRESELECT BUFFER KEYMAP DEFAULT HISTORY ALLOW-NEST OTHER-LOCAL-VARS)"
- (let ((fn (cond ((or (and helm-alive-p (plist-get plist :allow-nest))
- (and helm-alive-p (memq 'allow-nest plist)))
- #'helm-nest)
- ((keywordp (car plist))
- #'helm)
- (t #'helm-internal))))
- (if (and helm-alive-p (eq fn #'helm))
- (if (helm-alive-p)
- ;; A helm session is normally running.
- (error "Error: Trying to run helm within a running helm session")
- ;; A helm session is already running and user jump somewhere else
- ;; without desactivating it.
- (with-helm-buffer
- (prog1
- (message "Aborting an helm session running in background")
- ;; `helm-alive-p' will be reset in unwind-protect forms.
- (helm-keyboard-quit))))
- (if (keywordp (car plist))
- ;; Parse `plist' and move not regular `helm-argument-keys'
- ;; to `helm--local-variables', then calling helm on itself
- ;; with normal arguments (the non--arguments-keys removed)
- ;; will end up in [1].
- (progn
- (setq helm--local-variables
- (append helm--local-variables
- ;; Vars passed by keyword on helm call
- ;; take precedence on same vars
- ;; that may have been passed before helm call.
- (helm-parse-keys plist)))
- (apply fn (mapcar (lambda (key) (plist-get plist key))
- helm-argument-keys)))
- (apply fn plist))))) ; [1] fn == helm-internal.
-
-(defun helm-alive-p ()
- "Check if `helm' is alive.
-An `helm' session is considered alive if `helm-alive-p' is non--nil,
-the `helm-buffer' is visible, and cursor is in minibuffer."
- (and helm-alive-p
- (get-buffer-window helm-buffer 'visible)
- (minibuffer-window-active-p (minibuffer-window))
- (minibufferp (current-buffer))))
-
-(defun helm-parse-keys (keys)
- "Parse the KEYS arguments of `helm'.
-Return only the keys that are not in `helm-argument-keys',
-prefix them with \"helm\" and convert them to alist.
-This allow to add arguments that are not part of `helm-argument-keys',
-but are valid helm variables.
-e.g :candidate-number-limit will be bound to `helm-candidate-number-limit'
-in source.
-
- (helm-parse-keys '(:sources ((name . \"test\")
- (candidates . (a b c)))
- :buffer \"toto\"
- :candidate-number-limit 4))
- ==> ((helm-candidate-number-limit . 4))."
-
- (cl-loop for (key value) on keys by #'cddr
- for symname = (substring (symbol-name key) 1)
- for sym = (intern (if (string-match "^helm-" symname)
- symname
- (concat "helm-" symname)))
- unless (memq key helm-argument-keys)
- collect (cons sym value)))
-
-;;; Core: entry point helper
-(defun helm-internal (&optional
- any-sources any-input
- any-prompt any-resume
- any-preselect any-buffer
- any-keymap any-default any-history)
- "The internal helm function called by `helm'.
-For ANY-SOURCES ANY-INPUT ANY-PROMPT ANY-RESUME ANY-PRESELECT ANY-BUFFER and
-ANY-KEYMAP ANY-DEFAULT ANY-HISTORY See `helm'."
- ;; Activate the advice for `tramp-read-passwd'.
- (if (fboundp 'advice-add)
- (progn
- (advice-add 'tramp-read-passwd :around #'helm--advice-tramp-read-passwd)
- (advice-add 'ange-ftp-get-passwd :around #'helm--advice-ange-ftp-get-passwd))
- (ad-activate 'tramp-read-passwd)
- (ad-activate 'ange-ftp-get-passwd))
- (helm-log (concat "[Start session] " (make-string 41 ?+)))
- (helm-log "any-prompt = %S" any-prompt)
- (helm-log "any-preselect = %S" any-preselect)
- (helm-log "any-buffer = %S" any-buffer)
- (helm-log "any-keymap = %S" any-keymap)
- (helm-log "any-default = %S" any-default)
- (helm-log "any-history = %S" any-history)
- (setq helm--prompt (or any-prompt "pattern: "))
- (let ((non-essential t)
- (input-method-verbose-flag helm-input-method-verbose-flag)
- (old--cua cua-mode)
- (helm--maybe-use-default-as-input
- (and (null any-input)
- (or helm--maybe-use-default-as-input ; it is let-bounded so use it.
- (cl-loop for s in (helm-normalize-sources any-sources)
- thereis (memq s helm-sources-using-default-as-input))))))
- ;; cua-mode overhide local helm bindings.
- ;; disable this stupid thing if enabled.
- (and cua-mode (cua-mode -1))
- (unwind-protect
- (condition-case-unless-debug _v
- (let ( ;; `helm-source-name' is non-nil
- ;; when `helm' is invoked by action, reset it.
- helm-source-name
- helm-current-source
- helm-in-persistent-action
- helm-quit
- (helm-buffer (or any-buffer helm-buffer)))
- (with-helm-restore-variables
- (helm-initialize
- any-resume any-input any-default any-sources)
- (helm-display-buffer helm-buffer)
- ;; We are now in helm-buffer.
- (when helm-prevent-escaping-from-minibuffer
- (helm--remap-mouse-mode 1)) ; Disable mouse bindings.
- (add-hook 'post-command-hook 'helm--maybe-update-keymap)
- (add-hook 'post-command-hook 'helm--update-header-line)
- (helm-log "show prompt")
- (unwind-protect
- (helm-read-pattern-maybe
- any-prompt any-input any-preselect
- any-resume any-keymap any-default any-history)
- (helm-cleanup)))
- (prog1
- (unless helm-quit (helm-execute-selection-action))
- (helm-log (concat "[End session] " (make-string 41 ?-)))))
- (quit
- (helm-restore-position-on-quit)
- (helm-log (concat "[End session (quit)] " (make-string 34 ?-)))
- nil))
- (if (fboundp 'advice-add)
- (progn
- (advice-remove 'tramp-read-passwd
- #'helm--advice-tramp-read-passwd)
- (advice-remove 'ange-ftp-get-passwd
- #'helm--advice-ange-ftp-get-passwd))
- (ad-deactivate 'tramp-read-passwd)
- (ad-deactivate 'ange-ftp-get-passwd))
- (helm-log "helm-alive-p = %S" (setq helm-alive-p nil))
- (helm--remap-mouse-mode -1) ; Reenable mouse bindings.
- (setq helm-alive-p nil)
- ;; Reset helm-pattern so that lambda's using it
- ;; before running helm will not start with its old value.
- (setq helm-pattern "")
- (and old--cua (cua-mode 1))
- (helm-log-save-maybe))))
-
-\f
-;;; Helm resume
-;;
-;;
-(defun helm-resume (arg)
- "Resurrect previously invoked `helm'.
-Called with a prefix arg, allow choosing among all existing
-helm buffers. i.e choose among various helm sessions.
-Called from lisp, you can specify a buffer-name as a string with ARG."
- (interactive "P")
- (let (any-buffer helm-full-frame cur-dir)
- (if arg
- (if (and (stringp arg) (bufferp (get-buffer arg)))
- (setq any-buffer arg)
- (setq any-buffer (helm-resume-select-buffer)))
- (setq any-buffer helm-last-buffer))
- (cl-assert any-buffer nil
- "helm-resume: No helm buffers found to resume")
- ;; Reset `cursor-type' to nil as it have been set to t
- ;; when quitting previous session.
- (with-current-buffer any-buffer (setq cursor-type nil))
- (setq helm-full-frame (buffer-local-value
- 'helm-full-frame (get-buffer any-buffer)))
- (setq helm-compiled-sources nil)
- (setq cur-dir (buffer-local-value
- 'default-directory (get-buffer any-buffer)))
- (setq helm-saved-selection nil
- helm-saved-action nil)
- (unless (buffer-live-p helm-current-buffer)
- ;; `helm-current-buffer' may have been killed.
- (setq helm-current-buffer (current-buffer)))
- ;; Restart with same `default-directory' value this session
- ;; was initially started with.
- (with-helm-default-directory cur-dir
- (helm
- :sources (buffer-local-value
- 'helm-sources (get-buffer any-buffer))
- :input (buffer-local-value 'helm-input-local (get-buffer any-buffer))
- :resume t
- :buffer any-buffer))))
-
-(defun helm-resume-previous-session-after-quit (arg)
- "Resume previous helm session within running helm."
- (interactive "p")
- (if (and helm-alive-p (> (length helm-buffers) arg))
- (helm-run-after-exit `(lambda () (helm-resume (nth ,arg helm-buffers))))
- (message "No previous helm sessions to resume yet!")))
-
-(defun helm-resume-list-buffers-after-quit ()
- "List resumable helm buffers within running helm."
- (interactive)
- (if (and helm-alive-p (> (length helm-buffers) 0))
- (helm-run-after-exit (lambda () (helm-resume t)))
- (message "No previous helm sessions to resume yet!")))
-
-(defun helm-resume-p (any-resume)
- "Whether current helm session is resumed or not."
- (eq any-resume t))
-
-(defun helm-resume-select-buffer ()
- "Select an `helm-buffer' in `helm-buffers' list to resume a helm session.
-Return nil if no `helm-buffer' found."
- (when helm-buffers
- (or (helm :sources '(((name . "Resume helm buffer")
- (candidates . helm-buffers)
- (action . identity)))
- :resume 'noresume
- :buffer "*helm resume*")
- (keyboard-quit))))
-
-\f
-;;;###autoload
-(defun helm-other-buffer (any-sources any-buffer)
- "Simplified interface of `helm' with other `helm-buffer'.
-Call `helm' with only ANY-SOURCES and ANY-BUFFER as args."
- (helm :sources any-sources :buffer any-buffer))
-
-(defun helm-nest (&rest same-as-helm)
- "Allow calling `helm' whithin a running helm session.
-Arguments SAME-AS-HELM are the same as `helm', which see."
- (with-helm-window
- (let ((orig-helm-current-buffer helm-current-buffer)
- (orig-helm-buffer helm-buffer)
- (orig-helm--prompt helm--prompt)
- (orig-helm--in-fuzzy helm--in-fuzzy)
- (orig-helm-last-frame-or-window-configuration
- helm-last-frame-or-window-configuration)
- (orig-one-window-p helm-onewindow-p))
- (unwind-protect
- (let (helm-current-position
- helm-current-buffer
- helm-pattern
- (helm-buffer (or (cl-getf same-as-helm :buffer)
- (nth 5 same-as-helm)
- "*Helm*"))
- helm-sources
- helm-compiled-sources
- (helm-full-frame t)
- (enable-recursive-minibuffers t))
- (apply #'helm same-as-helm))
- (with-current-buffer orig-helm-buffer
- (setq helm-alive-p t) ; Nested session set this to nil on exit.
- (setq helm-buffer orig-helm-buffer)
- (setq helm--prompt orig-helm--prompt)
- (setq helm--in-fuzzy orig-helm--in-fuzzy)
- (helm-initialize-overlays helm-buffer)
- (unless (helm-empty-buffer-p) (helm-mark-current-line t))
- (setq helm-last-frame-or-window-configuration
- orig-helm-last-frame-or-window-configuration)
- (setq cursor-type nil)
- (setq helm-current-buffer orig-helm-current-buffer)
- (setq helm-onewindow-p orig-one-window-p)
- ;; Be sure advices, hooks, and local modes keep running.
- (if (fboundp 'advice-add)
- (progn
- (advice-add 'tramp-read-passwd
- :around #'helm--advice-tramp-read-passwd)
- (advice-add 'ange-ftp-get-passwd
- :around #'helm--advice-ange-ftp-get-passwd))
- (ad-activate 'tramp-read-passwd)
- (ad-activate 'ange-ftp-get-passwd))
- (when helm-prevent-escaping-from-minibuffer
- (helm--remap-mouse-mode 1))
- (unless (cl-loop for h in post-command-hook
- thereis (memq h '(helm--maybe-update-keymap
- helm--update-header-line)))
- (add-hook 'post-command-hook 'helm--maybe-update-keymap)
- (add-hook 'post-command-hook 'helm--update-header-line))
- (helm-display-mode-line (helm-get-current-source)))))))
-
-\f
-;;; Core: Accessors
-;;
-(defun helm-current-position (save-or-restore)
- "Restore or save current position in `helm-current-buffer'.
-Argument SAVE-OR-RESTORE is one of save or restore."
- (cl-case save-or-restore
- (save
- (helm-log "Save position at %S" (cons (point) (window-start)))
- (setq helm-current-position (cons (point) (window-start))))
- (restore
- ;; Maybe `helm-current-buffer' have been deleted
- ;; during helm session so check if it is here
- ;; otherwise position in underlaying buffer will be lost.
- (when (get-buffer-window helm-current-buffer 'visible)
- (helm-log "Restore position at %S in buffer %s"
- helm-current-position
- (buffer-name (current-buffer)))
- (goto-char (car helm-current-position))
- ;; Fix this position with the NOFORCE arg of `set-window-start'
- ;; otherwise, if there is some other buffer than `helm-current-buffer'
- ;; one, position will be lost.
- (set-window-start (selected-window) (cdr helm-current-position) t)))))
-
-
-(defun helm-frame-or-window-configuration (save-or-restore)
- "Save or restore last frame or window configuration.
-Possible value of SAVE-OR-RESTORE are 'save and 'restore.
-window or frame configuration is saved/restored according to values of
-`helm-save-configuration-functions'."
- (helm-log "helm-save-configuration-functions = %S"
- helm-save-configuration-functions)
- (let ((window-persistent-parameters (append '((no-other-window . t))
- window-persistent-parameters)))
- (cl-case save-or-restore
- (save (setq helm-last-frame-or-window-configuration
- (funcall (cdr helm-save-configuration-functions))))
- (restore (funcall (car helm-save-configuration-functions)
- helm-last-frame-or-window-configuration)
- ;; Restore frame focus.
- ;; This is needed for minibuffer own-frame config
- ;; when recursive minibuffers are in use.
- ;; e.g M-: + helm-minibuffer-history.
- (let ((frame (if (minibufferp helm-current-buffer)
- (selected-frame)
- (last-nonminibuffer-frame))))
- (select-frame-set-input-focus frame))))))
-
-(defun helm-split-window-default-fn (window)
- (let (split-width-threshold)
- (if (and (fboundp 'window-in-direction)
- ;; Don't try to split when starting in a minibuffer
- ;; e.g M-: and try to use helm-show-kill-ring.
- (not (minibufferp helm-current-buffer)))
- (if (or (one-window-p t)
- helm-split-window-in-side-p)
- (split-window
- (selected-window) nil (if (eq helm-split-window-default-side 'other)
- 'below helm-split-window-default-side))
- ;; If more than one window reuse one of them.
- (cl-case helm-split-window-default-side
- (left (or (helm-window-in-direction 'left)
- (helm-window-in-direction 'above)
- (selected-window)))
- (above (or (helm-window-in-direction 'above)
- (helm-window-in-direction 'left)
- (selected-window)))
- (right (or (helm-window-in-direction 'right)
- (helm-window-in-direction 'below)
- (selected-window)))
- (below (or (helm-window-in-direction 'below)
- (helm-window-in-direction 'right)
- (selected-window)))
- (same (selected-window))
- (other (other-window-for-scrolling))
- (t (or (window-next-sibling) (selected-window)))))
- (split-window-sensibly window))))
-
-(defun helm-window-in-direction (direction)
- "Same as `window-in-direction' but check if window is dedicated."
- (helm-aif (window-in-direction direction)
- (and (not (window-dedicated-p it)) it)))
-
-\f
-;;; Display helm buffer
-;;
-;;
-(defun helm-display-buffer (buffer)
- "Display BUFFER.
-The function used to display `helm-buffer'."
- (let (pop-up-frames
- (split-window-preferred-function
- helm-split-window-preferred-function)
- (helm-split-window-default-side
- (if (and (not helm-full-frame)
- helm-reuse-last-window-split-state)
- (cond ((eq helm-split-window-default-side 'same) 'same)
- ((eq helm-split-window-default-side 'other) 'other)
- (helm--window-side-state)
- (t helm-split-window-default-side))
- helm-split-window-default-side)))
- (prog1
- (funcall (with-current-buffer buffer helm-display-function) buffer)
- (setq helm-onewindow-p (one-window-p t))
- ;; Don't allow other-window and friends switching out of minibuffer.
- (when helm-prevent-escaping-from-minibuffer
- (helm-prevent-switching-other-window)))))
-
-(cl-defun helm-prevent-switching-other-window (&key (enabled t))
- "Allow setting `no-other-window' window parameter in all windows.
-Arg ENABLE will be the value of the `no-other-window' window property."
- (walk-windows
- (lambda (w)
- (unless (window-dedicated-p w)
- (set-window-parameter w 'no-other-window enabled)))
- 0))
-
-(defun helm-default-display-buffer (buffer)
- "Default function to display `helm-buffer' BUFFER.
-It uses `switch-to-buffer' or `display-buffer' depending of value
-of `helm-full-frame' and/or `helm-split-window-default-side'."
- (if (or (buffer-local-value 'helm-full-frame (get-buffer buffer))
- (and (eq helm-split-window-default-side 'same)
- (one-window-p t)))
- (progn (delete-other-windows) (switch-to-buffer buffer))
- (when (and (or helm-always-two-windows helm-autoresize-mode
- (and (not helm-split-window-in-side-p)
- (eq (save-selected-window
- (funcall helm-split-window-preferred-function
- (selected-window)))
- (get-buffer-window helm-current-buffer))))
- (not (eq helm-split-window-default-side 'same))
- (not (minibufferp helm-current-buffer))
- (not helm-split-window-in-side-p))
- (delete-other-windows))
- (display-buffer buffer)))
-
-\f
-;;; Core: initialize
-;;
-(defun helm-initialize (any-resume any-input any-default any-sources)
- "Start initialization of `helm' session.
-For ANY-RESUME ANY-INPUT ANY-DEFAULT and ANY-SOURCES See `helm'."
- (helm-log "start initialization: any-resume=%S any-input=%S"
- any-resume any-input)
- (helm-frame-or-window-configuration 'save)
- (setq helm-sources (helm-normalize-sources any-sources))
- (setq helm--in-fuzzy
- (cl-loop for s in helm-sources
- for matchfns = (helm-match-functions
- (if (symbolp s) (symbol-value s) s))
- for searchfns = (helm-search-functions
- (if (symbolp s) (symbol-value s) s))
- when (or (member 'helm-fuzzy-match matchfns)
- (member 'helm-fuzzy-search searchfns))
- return t))
- (helm-log "sources = %S" helm-sources)
- (helm-current-position 'save)
- (if (helm-resume-p any-resume)
- (helm-initialize-overlays (helm-buffer-get))
- (helm-initial-setup any-default))
- (setq helm-alive-p t)
- (unless (eq any-resume 'noresume)
- (helm-recent-push helm-buffer 'helm-buffers)
- (setq helm-last-buffer helm-buffer))
- (when any-input
- (setq helm-input any-input
- helm-pattern any-input)
- (helm--fuzzy-match-maybe-set-pattern))
- ;; If a `resume' attribute is present `helm-funcall-foreach'
- ;; will run its function.
- (when (helm-resume-p any-resume)
- (helm-funcall-foreach 'resume))
- (helm-log "end initialization"))
-
-(defun helm-initialize-overlays (buffer)
- "Initialize helm overlays in BUFFER."
- (helm-log "overlay setup")
- (if helm-selection-overlay
- ;; make sure the overlay belongs to the helm buffer if
- ;; it's newly created
- (move-overlay helm-selection-overlay (point-min) (point-min)
- (get-buffer buffer))
-
- (setq helm-selection-overlay
- (make-overlay (point-min) (point-min) (get-buffer buffer)))
- (overlay-put helm-selection-overlay 'face 'helm-selection)
- (overlay-put helm-selection-overlay 'priority 1)))
-
-(defun helm-restore-position-on-quit ()
- "Restore position in `helm-current-buffer' when quitting."
- (helm-current-position 'restore))
-
-(defun helm-recent-push (elt list-var)
- "Add ELT to the value of LIST-VAR as most recently used value."
- (let ((m (member elt (symbol-value list-var))))
- (and m (set list-var (delq (car m) (symbol-value list-var))))
- (push elt (symbol-value list-var))))
-
-(defun helm--current-buffer ()
- "[internal] Return `current-buffer' BEFORE `helm-buffer' is initialized.
-Note that this will return the minibuffer in use after helm have started,
-so to get the buffer where helm started while in a helm session,
-use `helm-current-buffer'.
-It is intended to use this only in `helm-initial-setup'."
- (if (minibuffer-window-active-p (minibuffer-window))
- ;; If minibuffer is active be sure to use it's buffer
- ;; as `helm-current-buffer', this allow to use helm
- ;; from an already active minibuffer (M-: etc...)
- (window-buffer (active-minibuffer-window))
- ;; Fix Issue #456
- ;; Use this instead of `current-buffer' to ensure
- ;; helm session started in helm-mode from a completing-read
- ;; Use really the buffer where we started and not the one
- ;; where the completing-read is wrapped. i.e
- ;; (with-current-buffer SOME-OTHER-BUFFER (completing-read [...])
- (window-buffer (with-selected-window (minibuffer-window)
- (minibuffer-selected-window)))))
-
-
-(defun helm-initial-setup (any-default)
- "Initialize helm settings and set up the helm buffer."
- (helm-log-run-hook 'helm-before-initialize-hook)
- (cl-loop for s in (helm-get-sources)
- for hook = (assoc-default 'before-init-hook s)
- when hook do (helm-log-run-hook hook))
- ;; For initialization of helm locals vars that need
- ;; a value from current buffer, it is here.
- (helm-set-local-variable 'current-input-method current-input-method)
- (setq helm-current-prefix-arg nil
- helm-saved-action nil
- helm-saved-selection nil
- helm-suspend-update-flag nil
- helm-current-buffer (helm--current-buffer)
- helm-buffer-file-name buffer-file-name
- helm-issued-errors nil
- helm-compiled-sources nil
- helm-saved-current-source nil)
- (unless (and (or helm-split-window-state
- helm--window-side-state)
- helm-reuse-last-window-split-state)
- (setq helm-split-window-state
- (if (or (null split-width-threshold)
- (and (integerp split-width-threshold)
- (>= split-width-threshold (+ (frame-width) 4))))
- 'vertical 'horizontal))
- (setq helm--window-side-state
- (or helm-split-window-default-side 'below)))
- ;; Call the init function for sources where appropriate
- (helm-funcall-foreach
- 'init (and helm-source-filter
- (cl-remove-if-not (lambda (s)
- (member (assoc-default 'name s)
- helm-source-filter))
- (helm-get-sources))))
- (setq helm-pattern (or (and helm--maybe-use-default-as-input
- (or (if (listp any-default)
- (car any-default) any-default)
- (with-helm-current-buffer
- (thing-at-point 'symbol))))
- ""))
- (setq helm-input "")
- (clrhash helm-candidate-cache)
- (helm-create-helm-buffer)
- (helm-clear-visible-mark)
- (helm-log-run-hook 'helm-after-initialize-hook)
- (cl-loop for s in (helm-get-sources)
- for hook = (assoc-default 'after-init-hook s)
- when hook do (helm-log-run-hook hook)))
-
-(defun helm-create-helm-buffer ()
- "Create and setup `helm-buffer'."
- (let ((root-dir default-directory))
- (with-current-buffer (get-buffer-create helm-buffer)
- (helm-log "kill local variables: %S" (buffer-local-variables))
- (kill-all-local-variables)
- (set (make-local-variable 'inhibit-read-only) t)
- (buffer-disable-undo)
- (erase-buffer)
- (set (make-local-variable 'helm-map) helm-map)
- (make-local-variable 'helm-sources)
- (set (make-local-variable 'helm-follow-mode) nil)
- (set (make-local-variable 'helm-display-function) helm-display-function)
- (set (make-local-variable 'helm-selection-point) nil)
- (set (make-local-variable 'scroll-margin)
- (if helm-display-source-at-screen-top
- 0 helm-completion-window-scroll-margin))
- (set (make-local-variable 'default-directory) root-dir)
- (set (make-local-variable 'helm-marked-candidates) nil)
- (helm-initialize-persistent-action)
- (helm-log "helm-display-function = %S" helm-display-function)
- (helm-log "helm--local-variables = %S" helm--local-variables)
- (cl-loop for (var . val) in helm--local-variables
- do (set (make-local-variable var) val)
- finally (setq helm--local-variables nil))
- (setq truncate-lines helm-truncate-lines) ; already local.
- (setq cursor-type nil)
- (setq mode-name "Helm"))
- (helm-initialize-overlays helm-buffer)
- (get-buffer helm-buffer)))
-
-(define-minor-mode helm--minor-mode
- "[INTERNAL] Enable keymap in helm minibuffer.
-This mode have no effect when run outside of helm context.
-Please don't use it.
-
-\\{helm-map}"
- :group 'helm
- :keymap (and helm-alive-p helm-map)
- (unless helm-alive-p (setq helm--minor-mode nil)))
-
-(defun helm--reset-default-pattern ()
- (setq helm-pattern "")
- (setq helm--maybe-use-default-as-input nil))
-
-(defun helm-read-pattern-maybe (any-prompt any-input
- any-preselect any-resume any-keymap
- any-default any-history)
- "Read pattern with prompt ANY-PROMPT and initial input ANY-INPUT.
-For ANY-PRESELECT ANY-RESUME ANY-KEYMAP ANY-DEFAULT ANY-HISTORY, See `helm'."
- (if (and (helm-resume-p any-resume)
- ;; When no source, helm-buffer is empty
- ;; or contain non--candidate lines (e.g grep exit status)
- (helm-get-current-source))
- (helm-mark-current-line t)
- (helm-update any-preselect))
- (with-current-buffer (helm-buffer-get)
- (let* ((src (helm-get-current-source))
- (src-keymap (assoc-default 'keymap src))
- (hist (or (and any-history (symbolp any-history) any-history)
- ;; Needed for resuming.
- (assoc-default 'history src)))
- (timer nil)
- blink-matching-paren
- (resize-mini-windows (and (null helm-echo-input-in-header-line)
- resize-mini-windows))
- (first-src (car helm-sources))
- (first-src-val (if (symbolp first-src)
- (symbol-value first-src)
- first-src))
- (source-process-p (or (assq 'candidates-process src)
- (assq 'candidates-process first-src-val)))
- (source-delayed-p (or (assq 'delayed src)
- (assq 'delayed first-src-val))))
- (helm-log "helm-get-candidate-number => %S"
- (helm-get-candidate-number))
- (helm-log "helm-execute-action-at-once-if-one = %S"
- helm-execute-action-at-once-if-one)
- (helm-log "helm-quit-if-no-candidate = %S" helm-quit-if-no-candidate)
- ;; If source is delayed `helm-execute-action-at-once-if-one'
- ;; and `helm-quit-if-no-candidate' are handled after update finish.
- (when source-delayed-p
- ;; Note that we quickly add the hook now when `helm-update'
- ;; is already started, but because source is delayed the hook
- ;; should have the time to be passed !!!
- ;; the hook will remove itself once done.
- (with-helm-after-update-hook (helm-exit-or-quit-maybe)))
- ;; Reset `helm-pattern' for non--delayed sources and update
- ;; display if no result found with precedent value of `helm-pattern'
- ;; unless `helm-quit-if-no-candidate' is non--nil, in this case
- ;; Don't force update with an empty pattern.
- ;; Reset also `helm--maybe-use-default-as-input' as this checking
- ;; happen only on startup.
- (when helm--maybe-use-default-as-input
- ;; Store value of `default' temporarily here waiting next update
- ;; to allow actions like helm-moccur-action matching pattern
- ;; at the place it jump to.
- (setq helm-input helm-pattern)
- (if (or source-delayed-p source-process-p)
- ;; Reset pattern to next update.
- (with-helm-after-update-hook
- (helm--reset-default-pattern))
- ;; Reset pattern right now.
- (helm--reset-default-pattern))
- ;; Ensure force-update when no candidates
- ;; when we start with an empty pattern.
- (and (helm-empty-buffer-p)
- (null helm-quit-if-no-candidate)
- (helm-force-update)))
- ;; Handle `helm-execute-action-at-once-if-one' and
- ;; `helm-quit-if-no-candidate' now only for not--delayed sources.
- (cond ((and (if (functionp helm-execute-action-at-once-if-one)
- (funcall helm-execute-action-at-once-if-one)
- helm-execute-action-at-once-if-one)
- (not source-delayed-p)
- (= (helm-get-candidate-number) 1))
- (ignore)) ; Don't enter the minibuffer loop.
- ((and helm-quit-if-no-candidate
- (not source-delayed-p)
- (= (helm-get-candidate-number) 0))
- (setq helm-quit t)
- (and (functionp helm-quit-if-no-candidate)
- (funcall helm-quit-if-no-candidate)))
- (t ; Enter now minibuffer and wait for input.
- (let ((tap (or any-default
- (with-helm-current-buffer
- (thing-at-point 'symbol)))))
- (unwind-protect
- (minibuffer-with-setup-hook
- (lambda ()
- ;; Start minor-mode with global value of helm-map.
- (helm--minor-mode 1)
- ;; Now overhide the global value of `helm-map' with
- ;; the local one which is in this order:
- ;; - The keymap of current source.
- ;; - The value passed in ANY-KEYMAP
- ;; which will become buffer local.
- ;; - Or fallback to the global value of helm-map.
- (helm--maybe-update-keymap
- (or src-keymap any-keymap helm-map))
- (helm-log-run-hook 'helm-minibuffer-set-up-hook)
- (setq timer
- (run-with-idle-timer
- (max helm-input-idle-delay 0.001) 'repeat
- (lambda ()
- ;; Stop updating in persistent action
- ;; or when `helm-suspend-update-flag'
- ;; is non--nil.
- (unless (or helm-in-persistent-action
- helm-suspend-update-flag)
- (save-selected-window
- (helm-check-minibuffer-input)
- (helm-print-error-messages))))))
- (helm--update-header-line)) ; minibuffer has already been filled here
- (read-from-minibuffer (or any-prompt "pattern: ")
- any-input helm-map
- nil hist tap
- helm-inherit-input-method))
- (when timer (cancel-timer timer) (setq timer nil)))))))))
-
-(defun helm-exit-or-quit-maybe ()
- "Exit and run default action if only one candidate, quit if no candidates.
-This function is handling `helm-execute-action-at-once-if-one' and
-`helm-quit-if-no-candidate' in delayed sources."
- (with-helm-window
- (cond ((and (if (functionp helm-execute-action-at-once-if-one)
- (funcall helm-execute-action-at-once-if-one)
- helm-execute-action-at-once-if-one)
- (= (helm-get-candidate-number) 1))
- (helm-exit-minibuffer))
- ((and helm-quit-if-no-candidate
- (= (helm-get-candidate-number) 0))
- (setq helm-quit t)
- (and (functionp helm-quit-if-no-candidate)
- (funcall helm-quit-if-no-candidate))
- (keyboard-quit)))))
-
-(defun helm-toggle-suspend-update ()
- "Enable or disable update of display in helm.
-This can be useful for e.g writing quietly a complex regexp."
- (interactive)
- (when (setq helm-suspend-update-flag (not helm-suspend-update-flag))
- (helm-kill-async-processes)
- (setq helm-pattern ""))
- (message (if helm-suspend-update-flag
- "Helm update suspended!"
- "Helm update reenabled!")))
-
-(defadvice tramp-read-passwd (around disable-helm-update)
- ;; Suspend update when prompting for a tramp password.
- (setq helm-suspend-update-flag t)
- (setq overriding-terminal-local-map nil)
- (setq helm--reading-passwd-or-string t)
- (let (stimers)
- (unwind-protect
- (progn
- (setq stimers (with-timeout-suspend))
- ad-do-it)
- (with-timeout-unsuspend stimers)
- (setq helm--reading-passwd-or-string nil)
- (setq helm-suspend-update-flag nil))))
-
-(defun helm--advice-tramp-read-passwd (old--fn &rest args)
- ;; Suspend update when prompting for a tramp password.
- (setq helm-suspend-update-flag t)
- (setq overriding-terminal-local-map nil)
- (setq helm--reading-passwd-or-string t)
- (unwind-protect
- ;; No need to suspend timer in emacs-24.4
- ;; it is fixed upstream.
- (apply old--fn args)
- (setq helm--reading-passwd-or-string nil)
- (setq helm-suspend-update-flag nil)))
-
-(defun helm--advice-ange-ftp-get-passwd (old--fn &rest args)
- ;; Suspend update when prompting for a ange password.
- (setq helm-suspend-update-flag t)
- (setq overriding-terminal-local-map nil)
- (setq helm--reading-passwd-or-string t)
- (unwind-protect
- (apply old--fn args)
- (setq helm--reading-passwd-or-string nil)
- (setq helm-suspend-update-flag nil)))
-
-(defadvice ange-ftp-get-passwd (around disable-helm-update)
- ;; Suspend update when prompting for a ange password.
- (setq helm-suspend-update-flag t)
- (setq overriding-terminal-local-map nil)
- (setq helm--reading-passwd-or-string t)
- (unwind-protect
- ad-do-it
- (setq helm--reading-passwd-or-string nil)
- (setq helm-suspend-update-flag nil)))
-
-(defun helm--maybe-update-keymap (&optional map)
- "Handle differents keymaps in multiples sources.
-
-It will override `helm-map' with the local map of current source.
-If no map is found in current source do nothing (keep previous map)."
- (with-helm-buffer
- (helm-aif (or map (assoc-default 'keymap (helm-get-current-source)))
- ;; We used a timer in the past to leave
- ;; enough time to helm to setup its keymap
- ;; when changing source from a recursive minibuffer.
- ;; e.g C-x C-f M-y C-g
- ;; => *find-files have now the bindings of *kill-ring.
- ;; It is no more true now we are using `minor-mode-overriding-map-alist'
- ;; and `helm--minor-mode' thus it fix issue #1076 for emacs-24.3
- ;; where concurrent timers are not supported.
- ;; i.e update keymap+check input.
- (with-current-buffer (window-buffer (minibuffer-window))
- (setq minor-mode-overriding-map-alist `((helm--minor-mode . ,it)))))))
-
-;;; Prevent loosing focus when using mouse.
-;;
-(defvar helm--remap-mouse-mode-map
- (let ((map (make-sparse-keymap)))
- (cl-loop for k in '([mouse-1] [mouse-2] [mouse-3]
- [down-mouse-1] [down-mouse-2] [down-mouse-3]
- [drag-mouse-1] [drag-mouse-2] [drag-mouse-3]
- [double-mouse-1] [double-mouse-2] [double-mouse-3]
- [triple-mouse-1] [triple-mouse-2] [triple-mouse-3])
- do (define-key map k 'undefined))
- map))
-
-(define-minor-mode helm--remap-mouse-mode
- "[INTERNAL] Prevent escaping helm minibuffer with mouse clicks.
-Do nothing when used outside of helm context.
-
-WARNING: Do not use this mode yourself, it is internal to helm."
- :group 'helm
- :global t
- :keymap helm--remap-mouse-mode-map
- (unless helm-alive-p
- (setq helm--remap-mouse-mode-map nil)))
-\f
-;; Core: clean up
-
-(defun helm-cleanup ()
- "Clean up the mess when helm exit or quit."
- (helm-log "start cleanup")
- (with-current-buffer helm-buffer
- ;; bury-buffer from this window.
- (bury-buffer) ;[1]
- (remove-hook 'post-command-hook 'helm--maybe-update-keymap)
- (remove-hook 'post-command-hook 'helm--update-header-line)
- ;; Be sure we call this from helm-buffer.
- (helm-funcall-foreach 'cleanup))
- (helm-kill-async-processes)
- ;; Remove the temporary hooks added
- ;; by `with-helm-temp-hook' that
- ;; may not have been consumed.
- (when helm--temp-hooks
- (cl-loop for (fn . hook) in helm--temp-hooks
- do (set hook (delete fn (symbol-value hook)))))
- ;; When running helm from a dedicated frame
- ;; with no minibuffer, helm will run in the main frame
- ;; which have a minibuffer, so be sure to disable
- ;; the `no-other-window' prop there.
- (helm-prevent-switching-other-window :enabled nil)
- (helm-log-run-hook 'helm-cleanup-hook)
- (helm-frame-or-window-configuration 'restore)
- ;; [1] now bury-buffer from underlying windows otherwise,
- ;; if this window is killed the underlying buffer will
- ;; be a helm buffer.
- (replace-buffer-in-windows helm-buffer)
- (setq helm-alive-p nil)
- (setq helm-debug nil)
- ;; This is needed in some cases where last input
- ;; is yielded infinitely in minibuffer after helm session.
- (helm-clean-up-minibuffer))
-
-(defun helm-clean-up-minibuffer ()
- "Remove contents of minibuffer."
- (let ((miniwin (minibuffer-window)))
- ;; Clean only current minibuffer used by helm.
- ;; i.e The precedent one is active.
- (unless (minibuffer-window-active-p miniwin)
- (with-current-buffer (window-buffer miniwin)
- (delete-minibuffer-contents)))))
-
-\f
-;;; Core: input handling
-;;
-;;
-(defun helm-check-minibuffer-input ()
- "Check minibuffer content."
- (with-helm-quittable
- (with-selected-window (or (active-minibuffer-window)
- (minibuffer-window))
- (helm-check-new-input (minibuffer-contents)))))
-
-(defun helm-check-new-input (input)
- "Check INPUT string and update the helm buffer if necessary."
- ;; First time minibuffer is entered
- ;; we check value of `helm-pattern' that have been set
- ;; in `helm-initial-setup' when `helm--maybe-use-default-as-input'
- ;; is non--nil. After this initial check, reset
- ;; `helm--maybe-use-default-as-input' and ignore this.
- ;; This happen only when source is `delayed'.
- (when helm--maybe-use-default-as-input ; nil when non--delayed.
- (setq input helm-pattern))
- (unless (equal input helm-pattern)
- (setq helm-pattern input)
- (unless (helm-action-window)
- (setq helm-input helm-pattern))
- (helm-log "helm-pattern = %S" helm-pattern)
- (helm-log "helm-input = %S" helm-input)
- (setq helm--in-update t)
- (helm-update)))
-
-(defun helm--reset-update-flag ()
- (run-with-idle-timer
- helm-exit-idle-delay nil
- (lambda () (setq helm--in-update nil))))
-
-(add-hook 'helm-after-update-hook #'helm--reset-update-flag)
-
-\f
-;;; Core: source compiler
-;;
-;;
-(defun helm-compile-sources (sources funcs)
- "Compile SOURCES with FUNCS.
-See `helm-compile-source-functions'.
-Helm plug-ins are realized by this function."
- (mapcar
- (lambda (source)
- (cl-loop with src = (if (listp source) source (symbol-value source))
- for noplug = (assoc 'dont-plug src)
- for f in funcs
- unless (and noplug (memq f (cdr noplug)))
- do (setq src (funcall f src))
- finally (cl-return src)))
- sources))
-
-\f
-;; Core: all candidates
-
-(defun helm-get-candidates (source)
- "Retrieve and return the list of candidates from SOURCE."
- (let* (inhibit-quit
- (candidate-fn (assoc-default 'candidates source))
- (candidate-proc (assoc-default 'candidates-process source))
- (type-error (lambda ()
- (error
- "`%s' must either be a function, a variable or a list"
- (or candidate-fn candidate-proc))))
- (candidates (condition-case-unless-debug err
- ;; Process candidates-(process) function
- ;; It may return a process or a list of candidates.
- (if candidate-proc
- ;; Calling `helm-interpret-value' with no
- ;; SOURCE arg force the use of `funcall'
- ;; and not `helm-funcall-with-source'.
- (helm-interpret-value candidate-proc)
- (helm-interpret-value candidate-fn source))
- (error (helm-log "Error: %S" err) nil))))
- (when (and (processp candidates) (not candidate-proc))
- (warn "Candidates function `%s' should be called in a `candidates-process' attribute"
- candidate-fn))
- (cond ((processp candidates)
- ;; Candidates will be filtered later in process filter.
- candidates)
- ((or (null candidates)
- ;; Can happen when the output of a process
- ;; is empty, and the candidates function call
- ;; something like (split-string (buffer-string) "\n")
- ;; which result in a list of one empty string (Issue #938).
- ;; e.g (completing-read "test: " '(""))
- (equal candidates '("")))
- nil)
- ((listp candidates)
- ;; Transform candidates with `candidate-transformer' functions if
- ;; some, otherwise return candidates.
- (helm-transform-candidates candidates source))
- (t (funcall type-error)))))
-
-(defmacro helm-while-no-input (&rest body)
- "Same as `while-no-input' but without testing with `input-pending-p'."
- (declare (debug t) (indent 0))
- (let ((catch-sym (make-symbol "input"))
- inhibit-quit)
- `(with-local-quit
- (catch ',catch-sym
- (let ((throw-on-input ',catch-sym))
- ,@body)))))
-
-(defun helm-get-cached-candidates (source)
- "Return the cached value of candidates for SOURCE.
-Cache the candidates if there is not yet a cached value."
- (let* ((name (assoc-default 'name source))
- (candidate-cache (gethash name helm-candidate-cache)))
- (helm-aif candidate-cache
- (prog1 it (helm-log "Use cached candidates"))
- (helm-log "No cached candidates, calculate candidates")
- (let ((candidates (helm-get-candidates source)))
- (cond ((processp candidates)
- (push (cons candidates
- (append source
- (list (cons 'item-count 0)
- (cons 'incomplete-line ""))))
- helm-async-processes)
- (set-process-filter candidates 'helm-output-filter)
- (setq candidates nil))
- ((not (assoc 'volatile source))
- (puthash name candidates helm-candidate-cache)))
- candidates))))
-
-\f
-;;; Core: candidate transformers
-
-(defun helm-process-candidate-transformer (candidates source)
- "Execute `candidate-transformer' function(s) on CANDIDATES in SOURCE."
- (helm-aif (assoc-default 'candidate-transformer source)
- (helm-composed-funcall-with-source source it candidates)
- candidates))
-
-(defun helm-process-filtered-candidate-transformer (candidates source)
- "Execute `filtered-candidate-transformer' function(s) on CANDIDATES in SOURCE."
- (helm-aif (assoc-default 'filtered-candidate-transformer source)
- (helm-composed-funcall-with-source source it candidates source)
- candidates))
-
-(defmacro helm--maybe-process-filter-one-by-one-candidate (candidate source)
- "Execute `filter-one-by-one' function(s) on CANDIDATE in SOURCE."
- `(helm-aif (assoc-default 'filter-one-by-one ,source)
- (if (and (listp it)
- (not (functionp it))) ;; Don't treat lambda's as list.
- (cl-loop for f in it
- do (setq ,candidate (funcall f ,candidate))
- finally return ,candidate)
- (setq ,candidate (funcall it ,candidate)))
- ,candidate))
-
-(defun helm--initialize-one-by-one-candidates (candidates source)
- "Process the CANDIDATES with the `filter-one-by-one' function in SOURCE.
-Return CANDIDATES when pattern is empty."
- (helm-aif (and (string= helm-pattern "")
- (assoc-default 'filter-one-by-one source))
- (cl-loop for cand in candidates collect
- (helm--maybe-process-filter-one-by-one-candidate cand source))
- candidates))
-
-(defun helm-process-filtered-candidate-transformer-maybe
- (candidates source process-p)
- "Execute `filtered-candidate-transformer' function(s) on CANDIDATES in SOURCE.
-When PROCESS-P is non-nil execute `filtered-candidate-transformer'
-functions if some, otherwise return CANDIDATES."
- (if process-p
- ;; When no filter return CANDIDATES unmodified.
- (helm-process-filtered-candidate-transformer candidates source)
- candidates))
-
-(defun helm-process-real-to-display (candidates source)
- "Execute real-to-display function on all CANDIDATES of SOURCE."
- (helm-aif (assoc-default 'real-to-display source)
- (setq candidates (helm-funcall-with-source
- source 'mapcar
- (lambda (cand_)
- (if (consp cand_)
- ;; override DISPLAY from candidate-transformer
- (cons (funcall it (cdr cand_)) (cdr cand_))
- (cons (funcall it cand_) cand_)))
- candidates))
- candidates))
-
-(defun helm-transform-candidates (candidates source &optional process-p)
- "Transform CANDIDATES of SOURCE according to candidate transformers.
-When PROCESS-P is non-nil execute the `filtered-candidate-transformer' functions
-otherwise only the `candidate-transformer' functions are processed.
-When attribute `real-to-display' is present, execute its function on all maybe
-filtered CANDIDATES."
- (helm-process-real-to-display
- (helm-process-filtered-candidate-transformer-maybe
- (helm-process-candidate-transformer
- (helm--initialize-one-by-one-candidates candidates source) source)
- source process-p)
- source))
-
-\f
-;; Core: narrowing candidates
-(defun helm-candidate-number-limit (source)
- "Apply candidate-number-limit attribute value.
-This overhide variable `helm-candidate-number-limit'.
-
-e.g:
-If \(candidate-number-limit\) is in SOURCE, show all candidates in SOURCE.
-If \(candidate-number-limit . 123\) is in SOURCE limit candidate to 123."
- (helm-aif (assq 'candidate-number-limit source)
- (or (cdr it) 99999999)
- (or helm-candidate-number-limit 99999999)))
-
-(defun helm-candidate-get-display (candidate)
- "Get searched display part from CANDIDATE.
-CANDIDATE is a string, a symbol, or \(DISPLAY . REAL\) cons cell."
- (cond ((car-safe candidate))
- ((symbolp candidate)
- (symbol-name candidate))
- ((numberp candidate)
- (number-to-string candidate))
- (t candidate)))
-
-(defun helm-process-pattern-transformer (pattern source)
- "Execute pattern-transformer attribute PATTERN function in SOURCE."
- (helm-aif (assoc-default 'pattern-transformer source)
- (helm-composed-funcall-with-source source it pattern)
- pattern))
-
-(defun helm-default-match-function (candidate)
- "Check if `helm-pattern' match CANDIDATE.
-Default function to match candidates according to `helm-pattern'."
- (string-match helm-pattern candidate))
-
-\f
-;;; Fuzzy matching
-;;
-;;
-(defvar helm--fuzzy-regexp-cache (make-hash-table :test 'eq))
-(defun helm--fuzzy-match-maybe-set-pattern ()
- ;; Computing helm-pattern with helm--mapconcat-pattern
- ;; is costly, so cache it once time for all and reuse it
- ;; until pattern change.
- (when helm--in-fuzzy
- (let ((fun (if (string-match "\\`\\^" helm-pattern)
- #'identity
- #'helm--mapconcat-pattern)))
- (clrhash helm--fuzzy-regexp-cache)
- ;; FIXME: Splitted part are not handled here,
- ;; I must compute them in `helm-search-match-part'
- ;; when negation and in-buffer are used.
- (if (string-match "\\`!" helm-pattern)
- (puthash 'helm-pattern
- (if (> (length helm-pattern) 1)
- (list (funcall fun (substring helm-pattern 1 2))
- (funcall fun (substring helm-pattern 1)))
- '("" ""))
- helm--fuzzy-regexp-cache)
- (puthash 'helm-pattern
- (if (> (length helm-pattern) 0)
- (list (funcall fun (substring helm-pattern 0 1))
- (funcall fun helm-pattern))
- '("" ""))
- helm--fuzzy-regexp-cache)))))
-
-(defun helm-fuzzy-match (candidate)
- "Check if `helm-pattern' fuzzy match CANDIDATE.
-This function is used with sources build with `helm-source-sync'."
- (unless (string-match " " helm-pattern)
- ;; When pattern have one or more spaces, let
- ;; multi-match doing the job with no fuzzy matching.[1]
- (let ((regexp (cadr (gethash 'helm-pattern helm--fuzzy-regexp-cache))))
- (if (string-match "\\`!" helm-pattern)
- (not (string-match regexp candidate))
- (string-match regexp candidate)))))
-
-(defun helm-fuzzy-search (pattern)
- "Same as `helm-fuzzy-match' but for sources build with `helm-source-in-buffer'."
- (unless (string-match " " helm-pattern)
- ;; Same as in `helm-fuzzy-match' ref[1].
- (let* ((regexps (gethash 'helm-pattern helm--fuzzy-regexp-cache))
- (partial-regexp (car regexps))
- (regexp (cadr regexps)))
- (if (string-match "\\`!" pattern)
- ;; Don't try to search here, just return
- ;; the position of line and go ahead,
- ;; letting `helm-search-match-part' checking if
- ;; pattern match against this line.
- (prog1 (list (point-at-bol) (point-at-eol))
- (forward-line 1))
- ;; We could use here directly `re-search-forward'
- ;; on the regexp produced by `helm--mapconcat-pattern',
- ;; but it is very slow because emacs have to do an incredible
- ;; amount of loops to match e.g "[^f]*o[^o]..." in the whole buffer,
- ;; more the regexp is long more the amount of loops grow.
- ;; (Probably leading to a max-lisp-eval-depth error if both
- ;; regexp and buffer are too big)
- ;; So just search the first bit of pattern e.g "[^f]*f", and
- ;; then search the corresponding line with the whole regexp,
- ;; which increase dramatically the speed of the search.
- (cl-loop while (re-search-forward partial-regexp nil t)
- for bol = (point-at-bol)
- for eol = (point-at-eol)
- if (progn (goto-char bol)
- (re-search-forward regexp eol t))
- do (goto-char eol) and return t
- else do (goto-char eol)
- finally return nil)))))
-
-(defun helm-score-candidate-for-pattern (candidate pattern)
- "Give a score to CANDIDATE according to PATTERN.
-Score is calculated against number of contiguous matches found with PATTERN.
-If PATTERN is fully matched in CANDIDATE a maximal score (100) is given.
-A bonus of one point is given when PATTERN prefix match CANDIDATE.
-Contiguous matches have a coefficient of 2."
- (let* ((cand (if (stringp candidate)
- candidate (helm-stringify candidate)))
- (pat-lookup (helm--collect-pairs-in-string pattern))
- (str-lookup (helm--collect-pairs-in-string cand))
- (bonus (if (equal (car pat-lookup) (car str-lookup)) 1 0))
- (bonus1 (and (string-match (concat "\\<" (regexp-quote pattern) "\\>")
- cand)
- 100)))
- (+ bonus (or bonus1
- ;; Give a coefficient of 2 for contiguous matches.
- ;; That's mean that "wiaaaki" will not take precedence
- ;; on "aaawiki" when matching on "wiki" even if "wiaaaki"
- ;; starts by "wi".
- (* (length (cl-nintersection
- pat-lookup str-lookup :test 'equal))
- 2)))))
-
-(defun helm-fuzzy-matching-default-sort-fn (candidates _source &optional use-real)
- "The transformer for sorting candidates in fuzzy matching.
-It is sorting on the display part of by default.
-
-Sort CANDIDATES according to their score calculated by
-`helm-score-candidate-for-pattern'. When two candidates have the
-same score sort is made by length. Set USE-REAL to non-nil to
-sort on the real part."
- (if (string= helm-pattern "")
- candidates
- (let ((table-scr (make-hash-table :test 'equal)))
- (sort candidates
- (lambda (s1 s2)
- ;; Score and measure the length on real or display part of candidate
- ;; according to `use-real'.
- (let* ((real-or-disp-fn (if use-real #'cdr #'car))
- (cand1 (if (consp s1)
- (funcall real-or-disp-fn s1)
- s1))
- (cand2 (if (consp s2)
- (funcall real-or-disp-fn s2)
- s2))
- (data1 (or (gethash cand1 table-scr)
- (puthash cand1
- (list (helm-score-candidate-for-pattern
- cand1 helm-pattern)
- (length (helm-stringify cand1)))
- table-scr)))
- (data2 (or (gethash cand2 table-scr)
- (puthash cand2
- (list (helm-score-candidate-for-pattern
- cand2 helm-pattern)
- (length (helm-stringify cand2)))
- table-scr)))
- (len1 (cadr data1))
- (len2 (cadr data2))
- (scr1 (car data1))
- (scr2 (car data2)))
- (cond ((= scr1 scr2)
- (< len1 len2))
- ((> scr1 scr2)))))))))
-
-(defun helm-fuzzy-default-highlight-match (candidate)
- "The default function to highlight matches in fuzzy matching.
-It is meant to use with `filter-one-by-one' slot."
- (let* ((pair (and (consp candidate) candidate))
- (display (helm-stringify (if pair (car pair) candidate)))
- (real (cdr pair))
- (regex (helm-aif (and helm-migemo-mode
- (assoc helm-pattern
- helm-mm--previous-migemo-info))
- (cdr it)
- helm-pattern))
- (mp (helm-aif (helm-attr 'match-part (helm-get-current-source))
- (funcall it display))))
- (with-temp-buffer
- (insert (propertize display 'read-only nil)) ; Fix (#1176)
- (goto-char (point-min))
- (when mp
- ;; FIXME the first part of display may contain an occurence of mp.
- ;; e.g "helm-adaptive.el:27:(defgroup helm-adapt"
- (search-forward mp nil t)
- (goto-char (match-beginning 0)))
- (if (re-search-forward regex (and mp (+ (point) (length mp))) t)
- (add-text-properties
- (match-beginning 0) (match-end 0) '(face helm-match))
- (cl-loop with multi-match
- with patterns = (if (string-match-p " " helm-pattern)
- (prog1 (split-string helm-pattern)
- (setq multi-match t))
- (split-string helm-pattern "" t))
- for p in patterns
- for re = (or (and helm-migemo-mode
- (assoc-default
- p helm-mm--previous-migemo-info))
- p)
- do
- (when (re-search-forward re nil t)
- (add-text-properties
- (match-beginning 0) (match-end 0)
- '(face helm-match)))
- (when multi-match (goto-char (point-min)))))
- (setq display (buffer-string)))
- (if real (cons display real) display)))
-
-(defun helm-fuzzy-highlight-matches (candidates _source)
- "The filtered-candidate-transformer function to highlight matches in fuzzy.
-See `helm-fuzzy-default-highlight-match'."
- (cl-loop for c in candidates
- collect (funcall helm-fuzzy-matching-highlight-fn c)))
-
-(defun helm-match-functions (source)
- (let ((matchfns (or (assoc-default 'match source)
- (assoc-default 'match-strict source)
- #'helm-default-match-function)))
- (if (and (listp matchfns) (not (functionp matchfns)))
- matchfns (list matchfns))))
-
-(defun helm-search-functions (source)
- (let ((searchfns (assoc-default 'search source)))
- (if (and (listp searchfns) (not (functionp searchfns)))
- searchfns (list searchfns))))
-
-(defmacro helm--accumulate-candidates (candidate newmatches
- hash item-count limit source)
- "Add CAND into NEWMATCHES and use HASH to uniq NEWMATCHES.
-Argument ITEM-COUNT count the matches.
-if ITEM-COUNT reaches LIMIT, exit from inner loop."
- `(unless (gethash ,candidate ,hash)
- (unless (assq 'allow-dups ,source)
- (puthash ,candidate t ,hash))
- (helm--maybe-process-filter-one-by-one-candidate ,candidate ,source)
- (push ,candidate ,newmatches)
- (cl-incf ,item-count)
- (when (= ,item-count ,limit) (cl-return))))
-
-(defun helm-take-first-elements (seq n)
- "Return the N first element of SEQ if SEQ is longer than N.
-It is used to narrow down list of candidates to `helm-candidate-number-limit'."
- (if (> (length seq) n) (cl-subseq seq 0 n) seq))
-
-(cl-defun helm-set-case-fold-search (&optional (pattern helm-pattern))
- "Used to set the value of `case-fold-search' in helm.
-Return t or nil depending of value of `helm-case-fold-search'
-and `helm-pattern'."
- (let ((helm-case-fold-search
- (helm-aif (assq 'case-fold-search (helm-get-current-source))
- (cdr it)
- helm-case-fold-search))
- ;; Only parse basename for filenames
- ;; to avoid setting case sensitivity
- ;; when expanded directories contains upcase
- ;; characters.
- (bn-or-pattern (if (string-match "[~/]*" pattern)
- ;; `helm-basename' is not available yet.
- (file-name-nondirectory
- (directory-file-name pattern))
- pattern)))
- (helm-set-case-fold-search-1 bn-or-pattern)))
-
-(defun helm-set-case-fold-search-1 (pattern)
- (cl-case helm-case-fold-search
- (smart (let ((case-fold-search nil))
- (if (string-match "[[:upper:]]" pattern) nil t)))
- (t helm-case-fold-search)))
-
-(defun helm-match-from-candidates (cands matchfns match-part-fn limit source)
- (let (matches)
- (condition-case-unless-debug err
- (let ((item-count 0)
- (case-fold-search (helm-set-case-fold-search)))
- (clrhash helm-match-hash)
- (cl-dolist (match matchfns)
- (when (< item-count limit)
- (let (newmatches)
- (cl-dolist (candidate cands)
- (unless (gethash candidate helm-match-hash)
- (let ((target (helm-candidate-get-display candidate)))
- (when (funcall match
- (if match-part-fn
- (funcall match-part-fn target) target))
- (helm--accumulate-candidates
- candidate newmatches
- helm-match-hash item-count limit source)))))
- ;; filter-one-by-one may return nil candidates, so delq them if some.
- (setq matches (nconc matches (nreverse (delq nil newmatches))))))))
- (error (unless (eq (car err) 'invalid-regexp) ; Always ignore regexps errors.
- (helm-log-error "helm-match-from-candidates in source `%s': %s %s"
- (assoc-default 'name source) (car err) (cdr err)))
- (setq matches nil)))
- matches))
-
-(defun helm-compute-matches (source)
- "Start computing candidates in SOURCE."
- (save-current-buffer
- (let ((matchfns (helm-match-functions source))
- (matchpartfn (assoc-default 'match-part source))
- (helm-source-name (assoc-default 'name source))
- (helm-current-source source)
- (limit (helm-candidate-number-limit source))
- (helm-pattern (helm-process-pattern-transformer
- helm-pattern source)))
- (helm--fuzzy-match-maybe-set-pattern)
- ;; If source have a `filtered-candidate-transformer' attr
- ;; Filter candidates with this func, otherwise just compute
- ;; candidates.
- (helm-process-filtered-candidate-transformer
- (if (or (equal helm-pattern "")
- (equal matchfns '(identity)))
- ;; Compute all candidates up to LIMIT.
- (helm-take-first-elements
- (helm-get-cached-candidates source) limit)
- ;; Compute candidates according to pattern with their match fns.
- (helm-match-from-candidates
- ;; FIXME: What when volatile is used, and the display expected
- ;; comes from the filtered-candidate-transformer fn ?
- ;; In this case match function try to match on real which is maybe not
- ;; a string.
- (helm-get-cached-candidates source) matchfns matchpartfn limit source))
- source))))
-
-(defun helm-render-source (source matches)
- "Display MATCHES from SOURCE according to its settings."
- (helm-log "Source name = %S" (assoc-default 'name source))
- (when matches
- (helm-insert-header-from-source source)
- (if (not (assq 'multiline source))
- (cl-loop for m in matches
- for count from 1
- do (helm-insert-match m 'insert source count))
- (let ((start (point))
- (count 0)
- separate)
- (cl-dolist (match matches)
- (cl-incf count)
- (if separate
- (helm-insert-candidate-separator)
- (setq separate t))
- (helm-insert-match match 'insert source count))
- (put-text-property start (point) 'helm-multiline t)))))
-
-(defmacro helm--maybe-use-while-no-input (&rest body)
- "Wrap BODY in `helm-while-no-input' unless initializing a remote connection."
- `(progn
- (if (and (file-remote-p helm-pattern)
- (not (file-remote-p helm-pattern nil t)))
- ;; Tramp will ask for passwd, don't use `helm-while-no-input'.
- ,@body
- (helm-log "Using here `helm-while-no-input'")
- (helm-while-no-input ,@body))))
-
-(defun helm--collect-matches (src-list)
- (let ((matches (helm--maybe-use-while-no-input
- (cl-loop for src in src-list
- collect (helm-compute-matches src)))))
- (unless (eq matches t) matches)))
-
-(defun helm--compute-sources (src-list)
- (cl-loop with matches = (helm--collect-matches src-list)
- for src in src-list
- for mtc in matches
- do (helm-render-source src mtc)))
-
-(cl-defun helm-process-delayed-sources (delayed-sources &optional preselect source)
- "Process helm DELAYED-SOURCES.
-Move selection to string or regexp PRESELECT if non--nil.
-This function is called in `helm-process-delayed-sources-timer'
-when emacs is idle for `helm-idle-delay'."
- (with-helm-quittable
- (helm-log "Delayed sources = %S"
- (mapcar (lambda (s)
- (assoc-default 'name s))
- delayed-sources))
- (with-current-buffer (helm-buffer-get)
- (save-excursion
- (goto-char (point-max))
- (helm--compute-sources delayed-sources)
- (when (and (not (helm-empty-buffer-p))
- ;; No selection yet.
- (= (overlay-start helm-selection-overlay)
- (overlay-end helm-selection-overlay)))
- (helm-update-move-first-line 'without-hook)))
- (save-excursion
- (goto-char (point-min))
- (helm-log-run-hook 'helm-update-hook))
- (setq helm-force-updating-p nil)
- (unless (assoc 'candidates-process source)
- (helm-display-mode-line (helm-get-current-source))
- (helm-log-run-hook 'helm-after-update-hook))
- (when preselect (helm-preselect preselect source)))))
-
-\f
-;;; Core: helm-update
-;;
-(defun helm-update (&optional preselect source)
- "Update candidates list in `helm-buffer' according to `helm-pattern'.
-Argument PRESELECT is a string or regexp used to move selection to a particular
-place once updating is done. It should be used on single source because search
-is done on whole `helm-buffer' and not on current source."
- (helm-log "Start updating")
- (helm-kill-async-processes)
- ;; When persistent action have been called
- ;; we have two windows even with `helm-full-frame'.
- ;; So go back to one window when updating if `helm-full-frame'
- ;; is non--nil.
- (with-helm-window
- (when helm-onewindow-p (delete-other-windows)))
- (with-current-buffer (helm-buffer-get)
- (set (make-local-variable 'helm-input-local) helm-pattern)
- (let (normal-sources
- delayed-sources
- matches)
- (unwind-protect
- (progn
- ;; Iterate over all the sources
- (cl-loop for source in (cl-remove-if-not
- 'helm-update-source-p (helm-get-sources))
- if (helm-delayed-source-p source)
- ;; Delayed sources just get collected for later
- ;; processing
- collect source into ds
- else
- ;; Collect the normal sources
- collect source into ns
- ;; Export the variables from cl-loop
- finally (setq delayed-sources ds
- normal-sources ns))
- ;; When no normal-sources erase buffer
- ;; for the next possible delayed source
- ;; or the already computed normal-source
- ;; that is no more "updateable" (requires-pattern).
- (unless normal-sources (erase-buffer))
- ;; Compute matches without rendering the sources.
- (helm-log "Matches: %S"
- (setq matches (helm--collect-matches normal-sources)))
- ;; If computing matches finished and is not interrupted
- ;; erase the helm-buffer and render results (Fix #1157).
- (when matches
- (erase-buffer)
- (cl-loop for src in normal-sources
- for mtc in matches
- do (helm-render-source src mtc))))
- (helm-log "Delayed sources = %S"
- (mapcar (lambda (s) (assoc-default 'name s))
- delayed-sources))
- (cond ((and preselect delayed-sources normal-sources)
- ;; Preselection run here when there is
- ;; normal AND delayed sources.
- (helm-log "Update preselect candidate %s" preselect)
- (helm-preselect preselect source))
- (delayed-sources ; Preselection and hooks will run later.
- (helm-update-move-first-line 'without-hook))
- (t ; No delayed sources, run the hooks now.
- (helm-update-move-first-line)
- (unless (assoc 'candidates-process source)
- (helm-display-mode-line (helm-get-current-source))
- (helm-log-run-hook 'helm-after-update-hook))
- (when preselect
- (helm-log "Update preselect candidate %s" preselect)
- (helm-preselect preselect source))
- (setq helm-force-updating-p nil)))
- (when delayed-sources
- ;; Allow giving a value to `delayed' attr from inside source.
- ;; Retain the biggest value (the slower) found in DELAYED-SOURCES.
- (let ((helm-idle-delay (cl-loop with delay = helm-idle-delay
- for s in delayed-sources
- for d = (assoc-default 'delayed s)
- when d do (setq delay (max delay d))
- finally return delay)))
- (run-with-idle-timer
- ;; Be sure helm-idle-delay is >
- ;; to helm-input-idle-delay
- ;; otherwise use value of helm-input-idle-delay
- ;; or 0.01 if == to 0.
- (max helm-idle-delay helm-input-idle-delay 0.001) nil
- 'helm-process-delayed-sources delayed-sources preselect source)))
- (helm-log "end update")))))
-
-;; Update keymap after updating.
-;; Now we run this in post-command-hook, it is
-;; probably no more needed in helm-after-update-hook.
-;; Leave it commented as a reminder for now.
-;; (add-hook 'helm-after-update-hook 'helm--maybe-update-keymap)
-
-(defun helm-update-source-p (source)
- "Whether SOURCE need updating or not."
- (let ((len (string-width
- (if (or (assoc 'matchplugin source)
- (null (assoc 'no-matchplugin source)))
- ;; Don't count spaces entered when using
- ;; multi-match.
- (replace-regexp-in-string " " "" helm-pattern)
- helm-pattern))))
- (and (or (not helm-source-filter)
- (member (assoc-default 'name source) helm-source-filter))
- (>= len
- (helm-aif (assoc 'requires-pattern source) (or (cdr it) 1) 0))
- ;; These incomplete regexps hang helm forever
- ;; so defer update. Maybe replace spaces quoted when using
- ;; multi-match.
- (not (member (replace-regexp-in-string "\\s\\ " " " helm-pattern)
- helm-update-blacklist-regexps)))))
-
-(defun helm-delayed-source-p (source)
- "Wheter SOURCE is a delayed source or not."
- (or (assoc 'delayed source)
- (and helm-quick-update
- (> (length helm-sources) 1)
- (< (window-height (get-buffer-window (current-buffer)))
- (line-number-at-pos (point-max))))))
-
-(defun helm-update-move-first-line (&optional without-hook)
- "Goto first line of `helm-buffer'."
- (goto-char (point-min))
- (unless without-hook
- (save-excursion (helm-log-run-hook 'helm-update-hook)))
- (helm-next-line))
-
-(defun helm-force-update (&optional preselect)
- "Force recalculation and update of candidates.
-
-The difference with `helm-update' is this function is reevaling
-the `init' and `update' attributes functions when present
-before running `helm-update', also `helm-candidate-cache',
-if some (async candidates are not cached)
-is not reinitialized so that candidates are not recomputed
-unless pattern have changed.
-
-Selection is preserved to current candidate or moved to PRESELECT
-if specified."
- (let ((source (helm-get-current-source))
- (selection (helm-get-selection nil t))
- ;; `helm-goto-source' need to have all sources displayed
- ;; So disable `helm-quick-update'.
- helm-quick-update)
- (setq helm-force-updating-p t)
- (when source
- (mapc 'helm-force-update--reinit
- (helm-get-sources)))
- (helm-update (or preselect selection) source)
- (with-helm-window (recenter))))
-
-(defun helm-refresh ()
- "Force recalculation and update of candidates."
- (interactive)
- (with-helm-alive-p
- (helm-force-update)))
-
-(defun helm-force-update--reinit (source)
- "Reinit SOURCE by calling his update and/or init functions."
- (helm-aif (helm-funcall-with-source
- source 'helm-candidate-buffer)
- (kill-buffer it))
- (cl-dolist (attr '(update init))
- (helm-aif (assoc-default attr source)
- (helm-funcall-with-source source it)))
- (helm-remove-candidate-cache source))
-
-(defun helm-remove-candidate-cache (source)
- "Remove SOURCE from `helm-candidate-cache'."
- (remhash (assoc-default 'name source) helm-candidate-cache))
-
-(defun helm-insert-match (match insert-function source &optional num)
- "Insert MATCH into `helm-buffer' with INSERT-FUNCTION for SOURCE.
-If MATCH is a list then insert the string intended to appear on the display
-and store the real value in a text property."
- (let ((start (point-at-bol (point)))
- (dispvalue (helm-candidate-get-display match))
- (realvalue (cdr-safe match)))
- (when (and (stringp dispvalue)
- (not (zerop (length dispvalue))))
- (funcall insert-function dispvalue)
- ;; Some sources with candidates-in-buffer have already added
- ;; 'helm-realvalue property when creating candidate buffer.
- (unless (get-text-property start 'helm-realvalue)
- (and realvalue
- (put-text-property start (point-at-eol)
- 'helm-realvalue realvalue)))
- (when num
- (put-text-property start (point-at-eol) 'helm-cand-num num))
- (when helm-source-in-each-line-flag
- (put-text-property start (point-at-eol) 'helm-source source))
- (funcall insert-function "\n"))))
-
-(defun helm-insert-header-from-source (source)
- "Insert SOURCE name in `helm-buffer' header.
-Maybe insert by overlay additional info after source name if SOURCE have
-header-name attribute."
- (let ((name (assoc-default 'name source)))
- (helm-insert-header
- name
- (helm-aif (assoc-default 'header-name source)
- (helm-funcall-with-source source it name)))))
-
-(defun helm-insert-header (name &optional display-string)
- "Insert header of source NAME into the helm buffer.
-If DISPLAY-STRING is non--nil and a string, display this additional info
-after the source name by overlay."
- (unless (bobp)
- (let ((start (point)))
- (insert "\n")
- (put-text-property start (point) 'helm-header-separator t)))
- (let ((start (point)))
- (insert name)
- (put-text-property (point-at-bol)
- (point-at-eol) 'helm-header t)
- (when display-string
- (overlay-put (make-overlay (point-at-bol) (point-at-eol))
- 'display display-string))
- (insert "\n")
- (put-text-property start (point) 'face 'helm-source-header)))
-
-(defun helm-insert-candidate-separator ()
- "Insert separator of candidates into the helm buffer."
- (insert (propertize helm-candidate-separator 'face 'helm-separator))
- (put-text-property (point-at-bol)
- (point-at-eol) 'helm-candidate-separator t)
- (insert "\n"))
-
-\f
-;;; Core: async process
-;;
-(defun helm-output-filter (process output-string)
- "The `process-filter' function for helm async sources."
- (with-helm-quittable
- (helm-output-filter-1 (assoc process helm-async-processes) output-string)))
-
-(defun helm-output-filter-1 (process-assoc output-string)
- (helm-log "output-string = %S" output-string)
- (with-current-buffer helm-buffer
- (let ((source (cdr process-assoc)))
- (save-excursion
- (helm-aif (assoc-default 'insertion-marker source)
- (goto-char it)
- (goto-char (point-max))
- (helm-insert-header-from-source source)
- (setcdr process-assoc
- (append source `((insertion-marker . ,(point-marker))))))
- (helm-output-filter--process-source
- (car process-assoc) output-string source
- (helm-candidate-number-limit source))))
- (helm-output-filter--post-process)))
-
-(defun helm-output-filter--process-source (process output-string source limit)
- (cl-dolist (candidate (helm-transform-candidates
- (helm-output-filter--collect-candidates
- (split-string output-string "\n")
- (assoc 'incomplete-line source))
- source t))
- (setq candidate
- (helm--maybe-process-filter-one-by-one-candidate candidate source))
- (if (assq 'multiline source)
- (let ((start (point)))
- (helm-insert-candidate-separator)
- (helm-insert-match candidate 'insert-before-markers source
- (1+ (cdr (assoc 'item-count source))))
- (put-text-property start (point) 'helm-multiline t))
- (helm-insert-match candidate 'insert-before-markers source
- (1+ (cdr (assoc 'item-count source)))))
- (cl-incf (cdr (assoc 'item-count source)))
- (when (>= (assoc-default 'item-count source) limit)
- (helm-kill-async-process process)
- (cl-return))))
-
-(defun helm-output-filter--collect-candidates (lines incomplete-line-info)
- "Collect LINES maybe completing the truncated first and last lines."
- ;; The output of process may come in chunks of any size,
- ;; so the last line of LINES come truncated, this truncated line is
- ;; stored in INCOMPLETE-LINE-INFO and will be concated with the first
- ;; incomplete line of next chunk arriving.
- ;; INCOMPLETE-LINE-INFO is an attribute of source which is created
- ;; with an empty string when the source is computed => (incomplete-line . "")
- (helm-log "incomplete-line-info = %S" (cdr incomplete-line-info))
- (butlast
- (cl-loop for line in lines
- ;; On start `incomplete-line-info' value is empty string.
- for newline = (helm-aif (cdr incomplete-line-info)
- (prog1
- (concat it line)
- (setcdr incomplete-line-info nil))
- line)
- collect newline
- ;; Store last incomplete line (last chunk truncated)
- ;; until new output arrives.
- ;; Previously we were storing 'line' in incomplete-line-info
- ;; assuming output is truncated in only two chunks,
- ;; which may be wrong if output is very large and is truncated
- ;; in more than two chunks, so store now 'newline' which
- ;; contain the previous chunks (Issue #1187).
- finally do (setcdr incomplete-line-info newline))))
-
-(defun helm-output-filter--post-process ()
- (let ((src (helm-get-current-source)))
- (helm-log-run-hook 'helm-update-hook)
- (helm-aif (get-buffer-window helm-buffer 'visible)
- (with-selected-window it
- (helm-skip-noncandidate-line 'next)
- (helm-mark-current-line)
- (helm-display-mode-line src)
- (helm-log-run-hook 'helm-after-update-hook)))))
-
-(defun helm-process-deferred-sentinel-hook (process event file)
- "Defer remote processes in sentinels.
-Meant to be called at beginning of a sentinel process function."
- (when (and (string= event "finished\n")
- (or (file-remote-p file)
- ;; `helm-suspend-update-flag'
- ;; is non--nil here only during a
- ;; running process, this will never be called
- ;; when user set it explicitely with `C-!'.
- helm-suspend-update-flag))
- (setq helm-suspend-update-flag t)
- ;; Kill the process but don't delete entry in
- ;; `helm-async-processes'.
- (helm-kill-async-process process)
- ;; When tramp tries to open the same connection twice in a
- ;; short time frame (less than 5s) it throw 'suppress which
- ;; call the real-handler on the main "Emacs", so we wait
- ;; 5s before updating to avoid this [1], but allowing user to
- ;; enter input during this delay.
- ;; [1] On last Emacs versions, this is fixed and tramp return
- ;; nil in this situation.
- ;; Note: It is difficult to have a value < to 5 for
- ;; `tramp-connection-min-time-diff', because the process die
- ;; when calling too quickly same process.
- (run-at-time (or (and (boundp 'tramp-connection-min-time-diff)
- tramp-connection-min-time-diff)
- 5)
- nil (lambda ()
- (when helm-alive-p ; Don't run timer fn after quit.
- (setq helm-suspend-update-flag nil)
- (helm-check-minibuffer-input))))))
-
-(defun helm-kill-async-processes ()
- "Kill all asynchronous processes registered in `helm-async-processes'."
- (while helm-async-processes
- (helm-kill-async-process (caar helm-async-processes))
- (setq helm-async-processes (cdr helm-async-processes))))
-
-(defun helm-kill-async-process (process)
- "Stop output from `helm-output-filter' and kill associated PROCESS."
- (set-process-filter process nil)
- (delete-process process))
-
-\f
-;;; Core: action
-;;
-(defun helm-execute-selection-action ()
- "Execute current action and kill the action buffer if present."
- (helm-log-run-hook 'helm-before-action-hook)
- ;; Position can be different when `helm-current-buffer'
- ;; is splitted, so jump to this position before executing action.
- (helm-current-position 'restore)
- (unwind-protect
- (helm-execute-selection-action-1)
- (helm-aif (get-buffer helm-action-buffer)
- (kill-buffer it))
- (helm-log-run-hook 'helm-after-action-hook)))
-
-(defun helm-execute-selection-action-1 (&optional
- selection action
- preserve-saved-action)
- "Execute ACTION on current SELECTION.
-If PRESERVE-SAVED-ACTION is non--nil save action."
- (helm-log "executing action")
- (setq action (helm-get-default-action
- (or action
- helm-saved-action
- (if (get-buffer helm-action-buffer)
- (helm-get-selection helm-action-buffer)
- (helm-get-actions-from-current-source)))))
- (let ((source (or helm-saved-current-source
- (helm-get-current-source)))
- non-essential)
- (setq selection (helm-coerce-selection
- (or selection
- helm-saved-selection
- (helm-get-selection)
- (and (assoc 'accept-empty source) ""))
- source))
- (unless preserve-saved-action (setq helm-saved-action nil))
- (when (and selection action) (funcall action selection))))
-
-(defun helm-coerce-selection (selection source)
- "Apply coerce attribute function to SELECTION in SOURCE.
-Coerce source with coerce function."
- (helm-aif (assoc-default 'coerce source)
- (helm-funcall-with-source source it selection)
- selection))
-
-(defun helm-get-default-action (action)
- "Get the first ACTION value of action list in source."
- (if (and (listp action) (not (functionp action)))
- (cdar action)
- action))
-
-(defun helm-select-action ()
- "Select an action for the currently selected candidate.
-If action buffer is selected, back to the helm buffer."
- (interactive)
- (helm-log-run-hook 'helm-select-action-hook)
- (setq helm-saved-selection (helm-get-selection))
- (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)
- (helm-set-pattern helm-input 'noupdate))
- (helm-saved-selection
- (setq helm-saved-current-source (helm-get-current-source))
- (let ((actions (helm-get-actions-from-current-source)))
- (if (functionp actions)
- (message "Sole action: %s" 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-display-mode-line (helm-get-current-source))
- (run-hooks 'helm-window-configuration-hook))))
-
-(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 (make-local-variable 'helm-sources)
- (list
- (helm-build-sync-source "Actions"
- :volatile t
- :nomark t
- :keymap 'helm-map
- :candidates actions
- :mode-line '("Action(s)" "TAB:BackToCands RET/f1/f2/fn:NthAct")
- :candidate-transformer
- (lambda (candidates)
- (cl-loop for (i . j) in candidates
- for count from 1
- collect
- (cons (concat (cond ((> count 12)
- " ")
- ((< count 10)
- (format "[f%s] " count))
- (t (format "[f%s] " count)))
- (propertize i 'face 'helm-action))
- j)))
- :candidate-number-limit nil)))
- (set (make-local-variable 'helm-source-filter) nil)
- (set (make-local-variable 'helm-selection-overlay) nil)
- (helm-initialize-overlays helm-action-buffer)))
-
-\f
-;; Core: selection
-
-(defun helm-display-source-at-screen-top-maybe (unit)
- "Display source at top of screen when UNIT value is 'source.
-With any other value of UNIT return nil."
- (when (and helm-display-source-at-screen-top (eq unit 'source))
- (set-window-start (selected-window)
- (save-excursion (forward-line -1) (point)))))
-
-(defun helm-skip-noncandidate-line (direction)
- "Skip source header or candidates separator when going in DIRECTION.
-Possible value of DIRECTION are 'next or 'previous.
-Same as `helm-skip-header-and-separator-line' but ensure
-point is moved to the right place when at bop or eob."
- (helm-skip-header-and-separator-line direction)
- (and (bobp) (forward-line 1)) ; Skip first header.
- (and (eobp) (forward-line -1))) ; Avoid last empty line.
-
-(defun helm-skip-header-and-separator-line (direction)
- "Skip source header or candidate separator when going to next/previous line.
-Possible value of DIRECTION are 'next or 'previous."
- (let ((fn (cl-ecase direction
- (next 'eobp)
- (previous 'bobp))))
- (while (and (not (funcall fn))
- (or (helm-pos-header-line-p)
- (helm-pos-candidate-separator-p)))
- (forward-line (if (and (eq direction 'previous)
- (not (eq (point-at-bol) (point-min))))
- -1 1)))))
-
-(defun helm-display-mode-line (source &optional force)
- "Setup mode-line and header-line for `helm-buffer'."
- (set (make-local-variable 'helm-mode-line-string)
- (helm-interpret-value (or (and (listp source) ; Check if source is empty.
- (assoc-default 'mode-line source))
- (default-value 'helm-mode-line-string))
- source))
- (let ((follow (and (eq (cdr (assq 'follow source)) 1) " (HF)"))
- (marked (and helm-marked-candidates
- (cl-loop with cur-name = (assoc-default 'name source)
- for c in helm-marked-candidates
- for name = (assoc-default 'name (car c))
- when (string= name cur-name)
- collect c))))
- ;; Setup mode-line.
- (if helm-mode-line-string
- (setq mode-line-format
- `(" " mode-line-buffer-identification " "
- (:eval (format "L%-3d" (helm-candidate-number-at-point)))
- ,follow
- (:eval ,(and marked
- (concat
- " "
- (propertize
- (format "M%d" (length marked))
- 'face 'helm-visible-mark))))
- (:eval (when ,helm--mode-line-display-prefarg
- (let ((arg (prefix-numeric-value
- (or prefix-arg current-prefix-arg))))
- (unless (= arg 1)
- (propertize (format " [prefarg:%s]" arg)
- 'face 'helm-prefarg)))))
- " "
- (:eval (helm-show-candidate-number
- (car-safe helm-mode-line-string)))
- " " helm--mode-line-string-real " " mode-line-end-spaces)
- helm--mode-line-string-real
- (substitute-command-keys (if (listp helm-mode-line-string)
- (cadr helm-mode-line-string)
- helm-mode-line-string)))
- (setq mode-line-format (default-value 'mode-line-format)))
- ;; Setup header-line.
- (cond (helm-echo-input-in-header-line
- (setq force t)
- (helm--set-header-line))
- (helm-display-header-line
- (let ((hlstr (helm-interpret-value
- (and (listp source)
- (assoc-default 'header-line source))
- source))
- (endstr (make-string (window-width) ? )))
- (setq header-line-format
- (propertize (concat " " hlstr endstr)
- 'face 'helm-header))))))
- (when force (force-mode-line-update)))
-
-(defun helm--set-header-line (&optional update)
- (with-selected-window (minibuffer-window)
- (let* ((beg (save-excursion (vertical-motion 0 (helm-window)) (point)))
- (end (save-excursion (end-of-visual-line) (point)))
- ;; The visual line where the cursor is.
- (cont (buffer-substring beg end))
- (pref (propertize
- " "
- 'display (if (string-match-p (regexp-quote helm--prompt) cont)
- '(space :width left-fringe)
- (propertize
- "->"
- 'face 'helm-header-line-left-margin))))
- (pos (- (point) beg)))
- (with-helm-buffer
- (setq header-line-format (concat pref cont " "))
- (put-text-property
- ;; Increment pos to handle the space before prompt (i.e `pref').
- (1+ pos) (+ 2 pos)
- 'face ;don't just use 'cursor; this can hide the current character
- (list :inverse-video t
- :foreground (face-background 'cursor)
- :background (face-background 'default))
- header-line-format)
- (when update (force-mode-line-update))))))
-
-(defun helm--update-header-line ()
- ;; This should be used in `post-command-hook',
- ;; nowhere else.
- (when (with-helm-buffer helm-echo-input-in-header-line)
- (helm--set-header-line t)))
-
-(defun helm-hide-minibuffer-maybe ()
- "Hide minibuffer contents in a Helm session.
-This function should normally go to `helm-minibuffer-set-up-hook'.
-It has no effect if `helm-echo-input-in-header-line' is nil."
- (when (with-helm-buffer helm-echo-input-in-header-line)
- (let ((ov (make-overlay (point-min) (point-max) nil nil t)))
- (overlay-put ov 'window (selected-window))
- (overlay-put ov 'face (let ((bg-color (face-background 'default nil)))
- `(:background ,bg-color :foreground ,bg-color)))
- (setq cursor-type nil))))
-
-(defun helm-show-candidate-number (&optional name)
- "Used to display candidate number in mode-line.
-You can specify NAME of candidates e.g \"Buffers\" otherwise
-it is \"Candidate\(s\)\" by default."
- (when helm-alive-p
- (unless (helm-empty-source-p)
- ;; Build a fixed width string when candidate-number < 1000
- (let* ((cand-name (or name "Candidate(s)"))
- (width (length (format "[999 %s]" cand-name))))
- (propertize
- (format (concat "%-" (number-to-string width) "s")
- (format "[%s %s]"
- (helm-get-candidate-number 'in-current-source)
- cand-name))
- 'face 'helm-candidate-number)))))
-
-(cl-defun helm-move-selection-common (&key where direction)
- "Move the selection marker to a new position.
-Position is determined by WHERE and DIRECTION.
-Key arg WHERE can be one of:
- - line
- - page
- - edge
- - source
-Key arg DIRECTION can be one of:
- - previous
- - next
- - A source or a source name when used with :WHERE 'source."
- (let ((move-func (cl-case where
- (line (cl-ecase direction
- (previous 'helm-move--previous-line-fn)
- (next 'helm-move--next-line-fn)))
- (page (cl-ecase direction
- (previous 'helm-move--previous-page-fn)
- (next 'helm-move--next-page-fn)))
- (edge (cl-ecase direction
- (previous 'helm-move--beginning-of-buffer-fn)
- (next 'helm-move--end-of-buffer-fn)))
- (source (cl-case direction
- (previous 'helm-move--previous-source-fn)
- (next 'helm-move--next-source-fn)
- (t (lambda () ; A source is passed as DIRECTION arg.
- (helm-move--goto-source-fn direction))))))))
- (unless (or (helm-empty-buffer-p (helm-buffer-get))
- (not (helm-window)))
- (with-helm-window
- (helm-log-run-hook 'helm-move-selection-before-hook)
- (funcall move-func)
- (and (memq direction '(next previous))
- (helm-skip-noncandidate-line direction))
- (when (helm-pos-multiline-p)
- (helm-move--beginning-of-multiline-candidate))
- (helm-display-source-at-screen-top-maybe where)
- (when (helm-get-previous-header-pos)
- (helm-mark-current-line))
- (helm-display-mode-line (helm-get-current-source))
- (helm-log-run-hook 'helm-move-selection-after-hook)))))
-
-(defun helm-move--beginning-of-multiline-candidate ()
- (let ((header-pos (helm-get-previous-header-pos))
- (separator-pos (helm-get-previous-candidate-separator-pos)))
- (when header-pos
- (goto-char (if (or (null separator-pos)
- (< separator-pos header-pos))
- header-pos
- separator-pos))
- (forward-line 1))))
-
-(defun helm-move--previous-multi-line-fn ()
- (forward-line -1)
- (unless (helm-pos-header-line-p)
- (helm-skip-header-and-separator-line 'previous)
- (helm-move--beginning-of-multiline-candidate)))
-
-(defun helm-move--previous-line-fn ()
- (if (not (helm-pos-multiline-p))
- (forward-line -1)
- (helm-move--previous-multi-line-fn))
- (when (and helm-move-to-line-cycle-in-source
- (helm-pos-header-line-p))
- (forward-line 1)
- (helm-move--end-of-source)
- ;; We are at end of helm-buffer
- ;; check if last candidate is a multiline candidate
- ;; and jump to it
- (when (and (eobp)
- (save-excursion (forward-line -1) (helm-pos-multiline-p)))
- (helm-move--previous-multi-line-fn))))
-
-(defun helm-move--next-multi-line-fn ()
- (let ((header-pos (helm-get-next-header-pos))
- (separator-pos (helm-get-next-candidate-separator-pos)))
- (cond ((and separator-pos
- (or (null header-pos) (< separator-pos header-pos)))
- (goto-char separator-pos))
- (header-pos
- (goto-char header-pos)))))
-
-(defun helm-move--next-line-fn ()
- (if (not (helm-pos-multiline-p))
- (forward-line 1)
- (helm-move--next-multi-line-fn))
- (when (and helm-move-to-line-cycle-in-source
- (or (save-excursion (and (helm-pos-multiline-p)
- (goto-char (overlay-end
- helm-selection-overlay))
- (helm-end-of-source-p t)))
- (helm-end-of-source-p t)))
- (helm-move--beginning-of-source)))
-
-(defun helm-move--previous-page-fn ()
- (condition-case nil
- (scroll-down)
- (beginning-of-buffer (goto-char (point-min)))))
-
-(defun helm-move--next-page-fn ()
- (condition-case nil
- (scroll-up)
- (end-of-buffer (goto-char (point-max)))))
-
-(defun helm-move--beginning-of-buffer-fn ()
- (goto-char (point-min)))
-
-(defun helm-move--end-of-buffer-fn ()
- (goto-char (point-max)))
-
-(defun helm-move--end-of-source ()
- (goto-char (or (helm-get-next-header-pos) (point-max)))
- (when (helm-pos-header-line-p) (forward-line -2)))
-
-(defun helm-move--beginning-of-source ()
- (goto-char (helm-get-previous-header-pos))
- (forward-line 1))
-
-(defun helm-move--previous-source-fn ()
- (forward-line -1)
- (if (bobp)
- (goto-char (point-max))
- (helm-skip-header-and-separator-line 'previous))
- (goto-char (helm-get-previous-header-pos))
- (forward-line 1))
-
-(defun helm-move--next-source-fn ()
- (goto-char (or (and (not (save-excursion
- (forward-line 1) (eobp)))
- ;; Empty source at eob are just
- ;; not displayed unless they are dummy.
- ;; Issue #1117.
- (helm-get-next-header-pos))
- (point-min))))
-
-(defun helm-move--goto-source-fn (source-or-name)
- (goto-char (point-min))
- (let ((name (if (stringp source-or-name) source-or-name
- (assoc-default 'name source-or-name))))
- (condition-case err
- (while (not (string= name (helm-current-line-contents)))
- (goto-char (helm-get-next-header-pos)))
- (error (helm-log "%S" err)))))
-
-(defun helm-candidate-number-at-point ()
- (with-helm-buffer
- (or (get-text-property (point) 'helm-cand-num) 1)))
-
-(defun helm--next-or-previous-line (direction &optional arg)
- ;; Be sure to not use this in non--interactives calls.
- (let ((helm-move-to-line-cycle-in-source
- (and helm-move-to-line-cycle-in-source arg)))
- (if (and arg (> arg 1))
- (cl-loop with pos = (helm-candidate-number-at-point)
- with cand-num = (helm-get-candidate-number t)
- with iter = (min arg (if (eq direction 'next)
- (- cand-num pos)
- (min arg (1- pos))))
- for count from 1
- while (<= count iter)
- do
- (helm-move-selection-common :where 'line :direction direction))
- (helm-move-selection-common :where 'line :direction direction))))
-
-(defun helm-previous-line (&optional arg)
- "Move selection to the ARG previous line(s).
-Same behavior than `helm-next-line' when called with a numeric prefix arg."
- (interactive "p")
- (helm--next-or-previous-line 'previous arg))
-
-(defun helm-next-line (&optional arg)
- "Move selection to the next ARG line(s).
-When a numeric prefix arg is given and this numeric arg
-is > to the number of candidates, move to last candidate of
-current source (i.e don't move to next source if some)."
- (interactive "p")
- (helm--next-or-previous-line 'next arg))
-
-(defun helm-previous-page ()
- "Move selection back with a pageful."
- (interactive)
- (helm-move-selection-common :where 'page :direction 'previous))
-
-(defun helm-next-page ()
- "Move selection forward with a pageful."
- (interactive)
- (helm-move-selection-common :where 'page :direction 'next))
-
-(defun helm-beginning-of-buffer ()
- "Move selection at the top."
- (interactive)
- (helm-move-selection-common :where 'edge :direction 'previous))
-
-(defun helm-end-of-buffer ()
- "Move selection at the bottom."
- (interactive)
- (helm-move-selection-common :where 'edge :direction 'next))
-
-(defun helm-previous-source ()
- "Move selection to the previous source."
- (interactive)
- (helm-move-selection-common :where 'source :direction 'previous))
-
-(defun helm-next-source ()
- "Move selection to the next source."
- (interactive)
- (helm-move-selection-common :where 'source :direction 'next))
-
-(defun helm-goto-source (source-or-name)
- "Move the selection to the source SOURCE-OR-NAME."
- (helm-move-selection-common :where 'source :direction source-or-name))
-
-(defun helm--follow-action (arg)
- (let ((helm--temp-follow-flag t))
- (when (or (eq last-command 'helm-follow-action-forward)
- (eq last-command 'helm-follow-action-backward)
- (eq last-command 'helm-execute-persistent-action))
- (if (> arg 0)
- (helm-next-line 1)
- (helm-previous-line 1)))
- (helm-execute-persistent-action)))
-
-(defun helm-follow-action-forward ()
- "Go to next line and execute persistent action."
- (interactive)
- (helm--follow-action 1))
-
-(defun helm-follow-action-backward ()
- "Go to previous line and execute persistent action."
- (interactive)
- (helm--follow-action -1))
-
-(defun helm-mark-current-line (&optional resumep)
- "Move `helm-selection-overlay' to current line.
-Note that this is not related with visibles marks, which are used
-to mark candidates."
- (with-helm-window
- (when resumep
- (goto-char helm-selection-point))
- (move-overlay
- helm-selection-overlay (point-at-bol)
- (if (helm-pos-multiline-p)
- (let ((header-pos (helm-get-next-header-pos))
- (separator-pos (helm-get-next-candidate-separator-pos)))
- (or (and (null header-pos) separator-pos)
- (and header-pos separator-pos
- (< separator-pos header-pos)
- separator-pos)
- header-pos
- (point-max)))
- (1+ (point-at-eol))))
- (setq helm-selection-point (overlay-start helm-selection-overlay)))
- (helm-follow-execute-persistent-action-maybe))
-
-(defun helm-confirm-and-exit-minibuffer ()
- "Maybe ask for confirmation when exiting helm.
-It is similar to `minibuffer-complete-and-exit' adapted to helm.
-If `minibuffer-completion-confirm' value is 'confirm,
-send in minibuffer confirm message and exit on next hit.
-If `minibuffer-completion-confirm' value is t,
-don't exit and send message 'no match'."
- (interactive)
- (if (and (helm--updating-p)
- (null helm--reading-passwd-or-string))
- (progn (message "[Display not ready]")
- (sit-for 0.5) (message nil))
- (let* ((empty-buffer-p (with-current-buffer helm-buffer
- (eq (point-min) (point-max))))
- (sel (helm-get-selection))
- (unknown (and (not empty-buffer-p)
- (string= (get-text-property
- 0 'display
- (helm-get-selection nil 'withprop))
- "[?]"))))
- (cond ((and (or empty-buffer-p unknown)
- (eq minibuffer-completion-confirm 'confirm))
- (setq helm-minibuffer-confirm-state
- 'confirm)
- (setq minibuffer-completion-confirm nil)
- (minibuffer-message " [confirm]"))
- ((and (or empty-buffer-p
- (unless (if minibuffer-completing-file-name
- (and minibuffer-completion-predicate
- (funcall minibuffer-completion-predicate sel))
- (and (stringp sel)
- ;; SEL may be a cons cell when helm-comp-read
- ;; is called directly with a collection composed
- ;; of (display . real) and real is a cons cell.
- (try-completion sel minibuffer-completion-table
- minibuffer-completion-predicate)))
- unknown))
- (eq minibuffer-completion-confirm t))
- (minibuffer-message " [No match]"))
- (t
- (setq helm-minibuffer-confirm-state nil)
- (helm-exit-minibuffer))))))
-(add-hook 'helm-after-update-hook 'helm-confirm-and-exit-hook)
-
-(defun helm-confirm-and-exit-hook ()
- "Restore `minibuffer-completion-confirm' when helm update."
- (unless (or (eq minibuffer-completion-confirm t)
- (not helm-minibuffer-confirm-state))
- (setq minibuffer-completion-confirm
- helm-minibuffer-confirm-state)))
-
-(defun helm-read-string (prompt &optional initial-input history
- default-value inherit-input-method)
- "Same as `read-string' but for reading string from a helm session."
- (let ((helm--reading-passwd-or-string t))
- (read-string
- prompt initial-input history default-value inherit-input-method)))
-
-(defun helm--updating-p ()
- ;; helm timer is between two cycles.
- ;; IOW `helm-check-minibuffer-input' haven't yet compared input
- ;; and `helm-pattern'.
- (or (not (equal (minibuffer-contents) helm-pattern))
- ;; `helm-check-minibuffer-input' have launched `helm-update'.
- helm--in-update))
-
-(defun helm-maybe-exit-minibuffer ()
- (interactive)
- (if (and (helm--updating-p)
- (null helm--reading-passwd-or-string))
- (progn (message "[Display not ready]")
- (sit-for 0.5) (message nil))
- (helm-exit-minibuffer)))
-
-(defun helm-exit-minibuffer ()
- "Select the current candidate by exiting the minibuffer."
- (unless helm-current-prefix-arg
- (setq helm-current-prefix-arg current-prefix-arg))
- (setq helm-exit-status 0)
- (helm-log-run-hook 'helm-exit-minibuffer-hook)
- (exit-minibuffer))
-
-(defun helm-keyboard-quit ()
- "Quit minibuffer in helm.
-If action buffer is displayed, kill it."
- (interactive)
- (when (get-buffer-window helm-action-buffer 'visible)
- (kill-buffer helm-action-buffer))
- (setq helm-exit-status 1)
- (abort-recursive-edit))
-
-(defun helm-get-next-header-pos ()
- "Return the position of the next header from point."
- (next-single-property-change (point) 'helm-header))
-
-(defun helm-get-previous-header-pos ()
- "Return the position of the previous header from point."
- (previous-single-property-change (point) 'helm-header))
-
-(defun helm-pos-multiline-p ()
- "Return non-nil if the current position is in the multiline source region."
- (get-text-property (point) 'helm-multiline))
-
-(defun helm-get-next-candidate-separator-pos ()
- "Return the position of the next candidate separator from point."
- (let ((hp (helm-get-next-header-pos)))
- (helm-aif (next-single-property-change (point) 'helm-candidate-separator)
- (or
- ;; Be sure we don't catch
- ;; the separator of next source.
- (and hp (< it hp) it)
- ;; The separator found is in next source
- ;; we are at last cand, so use the header pos.
- (and hp (< hp it) hp)
- ;; A single source, just try next separator.
- it))))
-
-(defun helm-get-previous-candidate-separator-pos ()
- "Return the position of the previous candidate separator from point."
- (previous-single-property-change (point) 'helm-candidate-separator))
-
-(defun helm-pos-header-line-p ()
- "Return t if the current line is a header line."
- (or (get-text-property (point-at-bol) 'helm-header)
- (get-text-property (point-at-bol) 'helm-header-separator)))
-
-(defun helm-pos-candidate-separator-p ()
- "Return t if the current line is a candidate separator."
- (get-text-property (point-at-bol) 'helm-candidate-separator))
-
-\f
-;;; Debugging
-;;
-;;
-(defun helm-debug-output ()
- "Show all helm-related variables at this time."
- (interactive)
- (helm-help-internal " *Helm Debug*" 'helm-debug-output-function))
-
-(defun helm-debug-output-function (&optional vars)
- (message "Calculating all helm-related values...")
- (insert "If you debug some variables or forms, set `helm-debug-variables'
-to a list of forms.\n\n")
- (cl-dolist (v (or vars
- helm-debug-variables
- (apropos-internal "^helm-" 'boundp)))
- (insert "** "
- (pp-to-string v) "\n"
- (pp-to-string (with-current-buffer helm-buffer (eval v))) "\n"))
- (message "Calculating all helm-related values...Done"))
-
-;;;###autoload
-(defun helm-debug-toggle ()
- "Enable/disable helm debug from outside of helm session."
- (interactive)
- (setq helm-debug (not helm-debug))
- (message "Helm Debug is now %s"
- (if helm-debug "Enabled" "Disabled")))
-
-(defun helm-enable-or-switch-to-debug ()
- "First hit enable helm debugging, second hit switch to debug buffer."
- (interactive)
- (with-helm-alive-p
- (if helm-debug
- (helm-run-after-exit
- #'helm-debug-open-last-log)
- (setq helm-debug t)
- (message "Debugging enabled"))))
-
-\f
-;; Core: misc
-(defun helm-kill-buffer-hook ()
- "Remove tick entry from `helm-tick-hash' and remove buffer from
-`helm-buffers' when killing a buffer."
- (cl-loop for key being the hash-keys in helm-tick-hash
- if (string-match (format "^%s/" (regexp-quote (buffer-name))) key)
- do (remhash key helm-tick-hash))
- (setq helm-buffers (remove (buffer-name) helm-buffers)))
-(add-hook 'kill-buffer-hook 'helm-kill-buffer-hook)
-
-(defun helm-preselect (candidate-or-regexp &optional source)
- "Move `helm-selection-overlay' to CANDIDATE-OR-REGEXP on startup.
-Arg CANDIDATE-OR-REGEXP can be a string or a cons cell of two strings.
-When it is a cons cell helm will try to jump first to first element of cons cell
-and then to second, allowing a finer preselection when possible duplicates are
-before the candidate we want to preselect."
- (with-helm-window
- (when candidate-or-regexp
- (if (and helm-force-updating-p source)
- (helm-goto-source source)
- (goto-char (point-min))
- (forward-line 1))
- (let ((start (point)))
- (or
- (if (consp candidate-or-regexp)
- (and (re-search-forward (car candidate-or-regexp) nil t)
- (re-search-forward (cdr candidate-or-regexp) nil t))
- (re-search-forward candidate-or-regexp nil t))
- (goto-char start))))
- (forward-line 0) ; Avoid scrolling right on long lines.
- (when (helm-pos-multiline-p)
- (helm-move--beginning-of-multiline-candidate))
- (when (helm-pos-header-line-p) (forward-line 1))
- (helm-mark-current-line)
- (helm-display-mode-line (helm-get-current-source))
- (helm-log-run-hook 'helm-after-preselection-hook)))
-
-(defun helm-delete-current-selection ()
- "Delete the currently selected item."
- (interactive)
- (with-helm-window
- (cond ((helm-pos-multiline-p)
- (helm-aif (helm-get-next-candidate-separator-pos)
- (delete-region (point-at-bol)
- (1+ (progn (goto-char it) (point-at-eol))))
- ;; last candidate
- (goto-char (helm-get-previous-candidate-separator-pos))
- (delete-region (point-at-bol) (point-max)))
- (when (helm-end-of-source-p)
- (goto-char (or (helm-get-previous-candidate-separator-pos)
- (point-min)))
- (forward-line 1)))
- (t
- (delete-region (point-at-bol) (1+ (point-at-eol)))
- (when (helm-end-of-source-p t)
- (let ((headp (save-excursion
- (forward-line -1)
- (not (helm-pos-header-line-p)))))
- (and headp (forward-line -1))))))
- (unless (helm-end-of-source-p t)
- (helm-mark-current-line))))
-
-(defun helm-end-of-source-p (&optional at-point)
- "Return non--nil if we are at eob or end of source."
- (save-excursion
- (if (and (helm-pos-multiline-p) (null at-point))
- (null (helm-get-next-candidate-separator-pos))
- (forward-line (if at-point 0 1))
- (or (eq (point-at-bol) (point-at-eol))
- (helm-pos-header-line-p)
- (eobp)))))
-
-(defun helm-beginning-of-source-p (&optional at-point)
- "Return non--nil if we are at bob or beginning of source."
- (save-excursion
- (if (and (helm-pos-multiline-p) (null at-point))
- (null (helm-get-previous-candidate-separator-pos))
- (forward-line (if at-point 0 -1))
- (or (eq (point-at-bol) (point-at-eol))
- (helm-pos-header-line-p)
- (bobp)))))
-
-(defun helm-edit-current-selection-internal (func)
- (with-helm-window
- (forward-line 0)
- (let ((realvalue (get-text-property (point) 'helm-realvalue))
- (multiline (get-text-property (point) 'helm-multiline)))
- (funcall func)
- (forward-line 0)
- (and realvalue
- (put-text-property (point) (point-at-eol)
- 'helm-realvalue realvalue))
- (and multiline
- (put-text-property (point) (point-at-eol)
- 'helm-multiline multiline))
- (helm-mark-current-line))))
-
-(defmacro helm-edit-current-selection (&rest forms)
- "Evaluate FORMS at current selection in the helm buffer.
-Used generally to modify current selection."
- (declare (indent 0) (debug t))
- `(helm-edit-current-selection-internal
- (lambda () ,@forms)))
-
-(defun helm--delete-minibuffer-contents-from (from-str)
- ;; Giving an empty string value to FROM-STR delete all.
- (let ((input (minibuffer-contents)))
- (helm-reset-yank-point)
- (if (> (length input) 0)
- ;; minibuffer is not empty, delete contents from end
- ;; of FROM-STR and update.
- (helm-set-pattern from-str)
- ;; minibuffer is already empty, force update.
- (helm-force-update))))
-
-(defun helm-delete-minibuffer-contents (&optional arg)
- "Delete minibuffer contents.
-When `helm-delete-minibuffer-contents-from-point' is non--nil,
-delete minibuffer contents from point instead of deleting all.
-Giving a prefix arg reverse this behavior.
-When at end of minibuffer delete all."
- (interactive "P")
- (let ((str (if helm-delete-minibuffer-contents-from-point
- (if (or arg (eobp))
- "" (helm-minibuffer-completion-contents))
- (if (and arg (not (eobp)))
- (helm-minibuffer-completion-contents) ""))))
- (helm--delete-minibuffer-contents-from str)))
-
-\f
-;;; Plugins (Deprecated in favor of helm-types)
-;;
-;; i.e Inherit instead of helm-type-* classes in your own classes.
-
-;; [DEPRECATED] Enable multi-match by default in old sources.
-;; This is deprecated and will not run in sources
-;; created by helm-source.
-;; Keep it for backward compatibility with old sources.
-(defun helm-compile-source--multi-match (source)
- (if (assoc 'no-matchplugin source)
- source
- (let* ((searchers helm-mm-default-search-functions)
- (defmatch (helm-aif (assoc-default 'match source)
- (helm-mklist it)))
- (defmatch-strict (helm-aif (assoc-default 'match-strict source)
- (helm-mklist it)))
- (defsearch (helm-aif (assoc-default 'search source)
- (helm-mklist it)))
- (defsearch-strict (helm-aif (assoc-default 'search-strict source)
- (helm-mklist it)))
- (matchfns (cond (defmatch-strict)
- (defmatch
- (append helm-mm-default-match-functions defmatch))
- (t helm-mm-default-match-functions)))
- (searchfns (cond (defsearch-strict)
- (defsearch
- (append searchers defsearch))
- (t searchers))))
- `(,(if (assoc 'candidates-in-buffer source)
- `(search ,@searchfns) `(match ,@matchfns))
- ,@source))))
-
-(add-to-list 'helm-compile-source-functions 'helm-compile-source--multi-match)
-
-(defun helm-compile-source--type (source)
- (helm-aif (assoc-default 'type source)
- (append source (assoc-default it helm-type-attributes) nil)
- source))
-
-(defun define-helm-type-attribute (type definition &optional doc)
- "Register type attribute of TYPE as DEFINITION with DOC.
-DOC is displayed in `helm-type-attributes' docstring.
-
-Use this function is better than setting `helm-type-attributes' directly."
- (cl-loop for i in definition do
- ;; without `ignore-errors', error at emacs22
- (ignore-errors (setf i (delete nil i))))
- (helm-add-type-attribute type definition)
- (and doc (helm-document-type-attribute type doc))
- nil)
-
-(defun helm-document-attribute (attribute short-doc &optional long-doc)
- "Register ATTRIBUTE documentation introduced by plug-in.
-SHORT-DOC is displayed beside attribute name.
-LONG-DOC is displayed below attribute name and short documentation."
- (declare (indent 2))
- (if long-doc
- (setq short-doc (concat "(" short-doc ")"))
- (setq long-doc short-doc
- short-doc ""))
- (add-to-list 'helm-attributes attribute t)
- (put attribute 'helm-attrdoc
- (concat "- " (symbol-name attribute)
- " " short-doc "\n\n" long-doc "\n")))
-
-(defun helm-add-type-attribute (type definition)
- (helm-aif (assq type helm-type-attributes)
- (setq helm-type-attributes (delete it helm-type-attributes)))
- (push (cons type definition) helm-type-attributes))
-
-(defun helm-document-type-attribute (type doc)
- (add-to-list 'helm-types type t)
- (put type 'helm-typeattrdoc
- (concat "- " (symbol-name type) "\n\n" doc "\n")))
-
-;; Built-in plug-in: dummy
-(defun helm-dummy-candidate (_candidate _source)
- "Use `helm-pattern' as CANDIDATE in SOURCE."
- ;; `source' is defined in filtered-candidate-transformer
- (list helm-pattern))
-
-(defun helm-compile-source--dummy (source)
- (if (assoc 'dummy source)
- (progn
- (unless (helm-attr-defined
- 'filtered-candidate-transformer source)
- (helm-attrset 'filtered-candidate-transformer
- 'helm-dummy-candidate source))
- (append source
- '((candidates "dummy")
- (accept-empty)
- (match identity)
- (volatile))))
- source))
-
-;; Built-in plug-in: candidates-in-buffer
-(defun helm-candidates-in-buffer (&optional source)
- "The top level function used to store candidates in `helm-source-in-buffer'.
-
-Candidates are stored in a buffer generated internally by the function
-`helm-candidate-buffer'. Each candidate must be placed in one line.
-This function is meant to be used in candidates-in-buffer or candidates
-attribute of an helm source. Especially fast for many (1000+) candidates.
-
-The buffer is created and feeded in the init attribute function of helm.
-
-e.g:
-
- (helm-build-in-buffer-source \"test\"
- :init (lambda ()
- (helm-init-candidates-in-buffer
- 'global '(foo foa fob bar baz))))
-
-A shortcut can be used to simplify:
-
- (helm-build-in-buffer-source \"test\"
- :data '(foo foa fob bar baz))
-
-The usage of the `candidates-in-buffer' is deprecated in favor
-of `helm-source-in-buffer' class.
-
-It is anyway described below and provided for backward compatibility.
-
-By default, `helm' makes candidates by evaluating the
-candidates function, then narrows them by `string-match' for each
-candidate.
-
-But this way is very slow for many candidates. The new way is
-storing all candidates in a buffer and narrowing them by
-`re-search-forward'. Search function is customizable by search
-attribute. The important point is that buffer processing is MUCH
-FASTER than string list processing and is the Emacs way.
-
-The init function writes all candidates to a newly-created
-candidate buffer. The candidates buffer is created or specified
-by `helm-candidate-buffer'. Candidates are stored in a line.
-
-The candidates function narrows all candidates, IOW creates a
-subset of candidates dynamically. It is the task of
-`helm-candidates-in-buffer'. As long as
-`helm-candidate-buffer' is used,`(candidates-in-buffer)' is
-sufficient in most cases.
-
-Note that `(candidates-in-buffer)' is shortcut of three attributes:
- (candidates . helm-candidates-in-buffer)
- (volatile)
- (match identity)
-And `(candidates-in-buffer . func)' is shortcut of three attributes:
- (candidates . func)
- (volatile)
- (match identity)
-The expansion is performed in `helm-get-sources'.
-
-The `candidates-in-buffer' attribute implies the volatile attribute.
-The volatile attribute is needed because `helm-candidates-in-buffer'
-creates candidates dynamically and need to be called everytime
-`helm-pattern' changes.
-
-Because `helm-candidates-in-buffer' plays the role of `match' attribute
-function, specifying `(match identity)' makes the source slightly faster.
-
-However if source contain `match-part' attribute, match is computed only
-on part of candidate returned by the call of function provided by this attribute.
-The function should have one arg, candidate, and return only
-a specific part of candidate.
-
-To customize `helm-candidates-in-buffer' behavior, use `search',
-`get-line' and `match-part' attributes."
- (let ((src (or source (helm-get-current-source))))
- (helm-candidates-in-buffer-1
- (helm-candidate-buffer)
- helm-pattern
- (or (assoc-default 'get-line src)
- #'buffer-substring-no-properties)
- (or (assoc-default 'search src)
- '(helm-candidates-in-buffer-search-default-fn))
- (helm-candidate-number-limit src)
- (helm-attr 'match-part)
- src)))
-
-(defun helm-candidates-in-buffer-search-default-fn (pattern)
- "Search PATTERN with `re-search-forward' with bound and noerror args."
- (condition-case _err
- (re-search-forward pattern nil t)
- (invalid-regexp nil)))
-
-(defun helm-candidates-in-buffer-1 (buffer pattern get-line-fn
- search-fns limit
- match-part-fn source)
- "Return the list of candidates inserted in BUFFER matching PATTERN."
- ;; buffer == nil when candidates buffer does not exist.
- (when buffer
- (with-current-buffer buffer
- (let ((inhibit-point-motion-hooks t)
- (start-point (1- (point-min))))
- (goto-char start-point)
- (if (string= pattern "")
- (helm-initial-candidates-from-candidate-buffer
- get-line-fn limit)
- (helm-search-from-candidate-buffer
- pattern get-line-fn search-fns limit
- start-point match-part-fn source))))))
-
-(defun helm-search-from-candidate-buffer (pattern get-line-fn search-fns
- limit start-point match-part-fn source)
- (let (buffer-read-only
- matches
- newmatches
- (item-count 0)
- (case-fold-search (helm-set-case-fold-search)))
- (helm--search-from-candidate-buffer-1
- (lambda ()
- (clrhash helm-cib-hash)
- (cl-dolist (searcher search-fns)
- (goto-char start-point)
- (forward-line 1) ; >>>[1]
- (setq newmatches nil)
- (cl-loop with pos-lst
- while (and (setq pos-lst (funcall searcher pattern))
- (not (eobp)))
- for cand = (apply get-line-fn
- (if (and pos-lst (listp pos-lst))
- pos-lst
- (list (point-at-bol) (point-at-eol))))
- when (and (not (gethash cand helm-cib-hash))
- (or
- ;; Always collect when cand is matched
- ;; by searcher funcs and match-part attr
- ;; is not present.
- (and (not match-part-fn)
- (not (consp pos-lst)))
- ;; If match-part attr is present, or if SEARCHER fn
- ;; returns a cons cell, collect PATTERN only if it
- ;; match the part of CAND specified by
- ;; the match-part func.
- (helm-search-match-part
- cand pattern (or match-part-fn #'identity))))
- do (helm--accumulate-candidates
- cand newmatches helm-cib-hash item-count limit source))
- (setq matches (append matches (nreverse newmatches))))
- (delq nil matches)))))
-
-(defun helm-search-match-part (candidate pattern match-part-fn)
- "Match PATTERN only on part of CANDIDATE returned by MATCH-PART-FN.
-Because `helm-search-match-part' maybe called even if unspecified
-in source (negation), MATCH-PART-FN default to `identity'
-to match whole candidate.
-When using fuzzy matching and negation (i.e \"!\"),
-this function is always called."
- (let ((part (funcall match-part-fn candidate))
- (fuzzy-regexp (cadr (gethash 'helm-pattern helm--fuzzy-regexp-cache)))
- (matchfn (if helm-migemo-mode
- 'helm-mm-migemo-string-match 'string-match)))
- (if (string-match " " pattern)
- (cl-loop for i in (split-string pattern) always
- (if (string-match "\\`!" i)
- (not (funcall matchfn (substring i 1) part))
- (funcall matchfn i part)))
- (if (string-match "\\`!" pattern)
- (if helm--in-fuzzy
- ;; Fuzzy regexp have already been
- ;; computed with substring 1.
- (not (string-match fuzzy-regexp part))
- (not (funcall matchfn (substring pattern 1) part)))
- (funcall matchfn (if helm--in-fuzzy fuzzy-regexp pattern) part)))))
-
-(defun helm-initial-candidates-from-candidate-buffer (get-line-fn limit)
- (delq nil (cl-loop for i from 1 to limit
- until (eobp)
- collect (funcall get-line-fn
- (point-at-bol) (point-at-eol))
- do (forward-line 1))))
-
-(defun helm--search-from-candidate-buffer-1 (search-fn)
- ;; We are adding a newline at bob and at eol
- ;; and removing these newlines afterward.
- ;; This is a bad hack that should be removed.
- ;; To avoid matching the empty line at first line
- ;; when searching with e.g occur and "^$" just
- ;; forward-line before searching (See >>>[1] above).
- (goto-char (point-min))
- (insert "\n")
- (goto-char (point-max))
- (insert "\n")
- (unwind-protect
- (funcall search-fn)
- (goto-char (point-min))
- (delete-char 1)
- (goto-char (1- (point-max)))
- (delete-char 1)
- (set-buffer-modified-p nil)))
-
-(defun helm-candidate-buffer (&optional create-or-buffer)
- "Register and return a buffer containing candidates of current source.
-`helm-candidate-buffer' searches buffer-local candidates buffer first,
-then global candidates buffer.
-
-Acceptable values of CREATE-OR-BUFFER:
-
-- nil (omit)
- Only return the candidates buffer.
-- a buffer
- Register a buffer as a candidates buffer.
-- 'global
- Create a new global candidates buffer,
- named \" *helm candidates:SOURCE*\".
-- other non-nil value
- Create a new local candidates buffer,
- named \" *helm candidates:SOURCE*HELM-CURRENT-BUFFER\"."
- (let* ((global-bname (format " *helm candidates:%s*"
- helm-source-name))
- (local-bname (format " *helm candidates:%s*%s"
- helm-source-name
- (buffer-name helm-current-buffer)))
- (register-func
- (lambda ()
- (setq helm-candidate-buffer-alist
- (cons (cons helm-source-name create-or-buffer)
- (delete (assoc helm-source-name
- helm-candidate-buffer-alist)
- helm-candidate-buffer-alist)))))
- (kill-buffers-func
- (lambda ()
- (cl-loop for b in (buffer-list)
- if (string-match (format "^%s" (regexp-quote global-bname))
- (buffer-name b))
- do (kill-buffer b))))
- (create-func
- (lambda ()
- (with-current-buffer
- (get-buffer-create (if (eq create-or-buffer 'global)
- global-bname
- local-bname))
- (set (make-local-variable 'inhibit-read-only) t) ; Fix (#1176)
- (buffer-disable-undo)
- (erase-buffer)
- (font-lock-mode -1))))
- (return-func
- (lambda ()
- (or (get-buffer local-bname)
- (get-buffer global-bname)
- (helm-aif (assoc-default helm-source-name
- helm-candidate-buffer-alist)
- (and (buffer-live-p it) it))))))
- (when create-or-buffer
- (funcall register-func)
- (unless (bufferp create-or-buffer)
- (and (eq create-or-buffer 'global) (funcall kill-buffers-func))
- (funcall create-func)))
- (funcall return-func)))
-
-(defun helm-init-candidates-in-buffer (buffer data)
- "Register BUFFER with DATA for a helm candidates-in-buffer session.
-Arg BUFFER can be a string, a buffer object (bufferp), or a symbol,
-either 'local or 'global which is passed to `helm-candidate-buffer'.
-Arg DATA can be either a list or a plain string.
-Returns the resulting buffer."
- (declare (indent 1))
- (let ((buf (helm-candidate-buffer
- (if (or (stringp buffer)
- (bufferp buffer))
- (get-buffer-create buffer)
- buffer)))) ; a symbol.
- (with-current-buffer buf
- (erase-buffer)
- (if (listp data)
- (insert (mapconcat (lambda (i)
- (cond ((symbolp i) (symbol-name i))
- ((numberp i) (number-to-string i))
- (t i)))
- data "\n"))
- (and (stringp data) (insert data))))
- buf))
-
-(defun helm-compile-source--candidates-in-buffer (source)
- (helm-aif (assoc 'candidates-in-buffer source)
- (append source
- `((candidates . ,(or (cdr it)
- (lambda ()
- (helm-candidates-in-buffer source))))
- (volatile) (match identity)))
- source))
-
-\f
-;;; Resplit helm window
-;;
-;;
-(defun helm-toggle-resplit-window ()
- "Toggle resplit helm window, vertically or horizontally."
- (interactive)
- (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))))
-
-;; Utility: Resize helm window.
-(defun helm-enlarge-window-1 (n)
- "Enlarge or narrow helm window.
-If N is positive enlarge, if negative narrow."
- (unless helm-full-frame
- (let ((horizontal-p (eq helm-split-window-state 'horizontal)))
- (with-helm-window
- (enlarge-window n horizontal-p)))))
-
-(defun helm-narrow-window ()
- "Narrow helm window."
- (interactive)
- (helm-enlarge-window-1 -1))
-
-(defun helm-enlarge-window ()
- "Enlarge helm window."
- (interactive)
- (helm-enlarge-window-1 1))
-
-(defun helm-swap-windows ()
- "Swap window holding `helm-buffer' with other window."
- (interactive)
- (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)))))
-
-(defun helm--get-window-side-state ()
- "Return the position of `helm-window' from `helm-current-buffer'.
-Possible values are 'left 'right 'below or 'above."
- (let ((side-list '(left right below above)))
- (cl-loop for side in side-list
- thereis (and (equal (helm-window)
- (window-in-direction
- side (get-buffer-window helm-current-buffer t)
- t))
- side))))
-
-(defun helm-replace-buffer-in-window (window buffer1 buffer2)
- "Replace BUFFER1 by BUFFER2 in WINDOW registering BUFFER1."
- (when (get-buffer-window buffer1)
- (unrecord-window-buffer window buffer1)
- (set-window-buffer window buffer2)))
-
-;; Utility: select another action by key
-(defun helm-select-nth-action (n)
- "Select the N nth action for the currently selected candidate."
- (setq helm-saved-selection (helm-get-selection))
- (unless helm-saved-selection
- (error "Nothing is selected"))
- (setq helm-saved-action
- (helm-get-nth-action
- n
- (if (get-buffer-window helm-action-buffer 'visible)
- (assoc-default 'candidates (helm-get-current-source))
- (helm-get-actions-from-current-source))))
- (helm-maybe-exit-minibuffer))
-
-(defun helm-get-nth-action (n action)
- (cond ((and (zerop n) (functionp action))
- action)
- ((listp action)
- (or (cdr (elt action n))
- (error "No such action")))
- ((and (functionp action) (< 0 n))
- (error "Sole action"))
- (t
- (error "Error in `helm-select-nth-action'"))))
-
-(defun helm-execute-selection-action-at-nth (linum)
- "Allow to execute default action on candidate at LINUM."
- (let ((prefarg current-prefix-arg))
- (if (>= linum 0)
- (helm-next-line linum)
- (helm-previous-line (lognot (1- linum))))
- (setq current-prefix-arg prefarg)
- (helm-exit-minibuffer)))
-
-;; Utility: Persistent Action
-(defmacro with-helm-display-same-window (&rest body)
- "Execute BODY in the window used for persistent action.
-Make `pop-to-buffer' and `display-buffer' display in the same window."
- (declare (indent 0) (debug t))
- `(let ((display-buffer-function 'helm-persistent-action-display-buffer))
- ,@body))
-
-(defun helm-initialize-persistent-action ()
- (set (make-local-variable 'helm-persistent-action-display-window) nil))
-
-(cl-defun helm-execute-persistent-action
- (&optional (attr 'persistent-action) split-onewindow)
- "Perform the associated action ATTR without quitting helm.
-ATTR default is 'persistent-action', but it can be anything else.
-In this case you have to add this new attribute to your source.
-
-When `helm-full-frame' or SPLIT-ONEWINDOW are non--nil,
-and `helm-buffer' is displayed in only one window,
-the helm window is splitted to display
-`helm-select-persistent-action-window' in other window
-and keep its visibility."
- (interactive)
- (helm-log "executing persistent-action")
- (let* ((attr-val (assoc-default attr (helm-get-current-source)))
- ;; If attr value is a cons, use its car as persistent function
- ;; and its car to decide if helm window should be splitted.
- (fn (if (and (consp attr-val)
- ;; maybe a lambda.
- (not (functionp attr-val)))
- (car attr-val) attr-val))
- (no-split (and (consp attr-val)
- (not (functionp attr-val))
- (cdr attr-val))))
- (with-helm-window
- (save-selected-window
- (if no-split
- (helm-select-persistent-action-window)
- (helm-select-persistent-action-window
- (or split-onewindow helm-onewindow-p)))
- (helm-log "current-buffer = %S" (current-buffer))
- (let ((helm-in-persistent-action t))
- (with-helm-display-same-window
- (helm-execute-selection-action-1
- nil (or fn (helm-get-actions-from-current-source)) t)
- (helm-log-run-hook 'helm-after-persistent-action-hook))
- ;; A typical case is when a persistent action delete
- ;; the buffer already displayed in
- ;; `helm-persistent-action-display-window' and `helm-full-frame'
- ;; is enabled, we end up with the `helm-buffer'
- ;; displayed in two windows.
- (when (and helm-onewindow-p
- (> (length (window-list)) 1)
- (equal (buffer-name
- (window-buffer
- helm-persistent-action-display-window))
- (helm-buffer-get)))
- (delete-other-windows)))))))
-
-(defun helm-persistent-action-display-window (&optional split-onewindow)
- "Return the window that will be used for persistent action.
-If SPLIT-ONEWINDOW is non--nil window will be splitted in persistent action."
- (with-helm-window
- (setq helm-persistent-action-display-window
- (cond ((and (window-live-p helm-persistent-action-display-window)
- (not (member helm-persistent-action-display-window
- (get-buffer-window-list helm-buffer))))
- helm-persistent-action-display-window)
- (split-onewindow (split-window))
- ((get-buffer-window helm-current-buffer))
- (t (next-window (selected-window) 1))))))
-
-(defun helm-select-persistent-action-window (&optional split-onewindow)
- "Select the window that will be used for persistent action.
-See `helm-persistent-action-display-window' for how to use SPLIT-ONEWINDOW."
- (select-window (get-buffer-window (helm-buffer-get)))
- (select-window
- (setq minibuffer-scroll-window
- (helm-persistent-action-display-window split-onewindow))))
-
-(defun helm-persistent-action-display-buffer (buf &optional action)
- "Make `pop-to-buffer' and `display-buffer' display in the same window.
-If `helm-persistent-action-use-special-display' is non-nil and
-BUF is to be displayed by `special-display-function', use it.
-Otherwise ignores `special-display-buffer-names' and `special-display-regexps'.
-Argument ACTION if present will be used as second argument of `display-buffer'."
- (let* ((name (buffer-name buf))
- display-buffer-function pop-up-windows pop-up-frames
- ;; Disable `special-display-regexps' and `special-display-buffer-names'
- ;; unless `helm-persistent-action-use-special-display' is non--nil.
- (special-display-buffer-names
- (and helm-persistent-action-use-special-display
- special-display-buffer-names))
- (special-display-regexps
- (and helm-persistent-action-use-special-display
- special-display-regexps))
- (same-window-regexps
- (unless (and helm-persistent-action-use-special-display
- (or (member name
- (mapcar (lambda (x) (or (car-safe x) x))
- special-display-buffer-names))
- (cl-loop for x in special-display-regexps
- thereis (string-match (or (car-safe x) x)
- name))))
- '("."))))
- ;; Don't loose minibuffer when displaying persistent window in
- ;; another frame.
- ;; This happen when the displayed persistent buffer-name is one of
- ;; `special-display-buffer-names' or match `special-display-regexps'
- ;; and `helm-persistent-action-use-special-display' is enabled.
- (with-selected-window (if (or special-display-regexps
- special-display-buffer-names)
- (minibuffer-window)
- (selected-window))
- ;; Be sure window of BUF is not dedicated.
- (set-window-dedicated-p (get-buffer-window buf) nil)
- (display-buffer buf action))))
-
-;; scroll-other-window(-down)? for persistent-action
-(defun helm-other-window-base (command &optional scroll-amount)
- (setq scroll-amount (unless (eq scroll-amount 'noscroll)
- helm-scroll-amount))
- (with-selected-window (helm-persistent-action-display-window)
- (funcall command scroll-amount)))
-
-(defun helm-scroll-other-window ()
- "Scroll other window (not *Helm* window) upward."
- (interactive)
- (helm-other-window-base 'scroll-up))
-
-(defun helm-scroll-other-window-down ()
- "Scroll other window (not *Helm* window) downward."
- (interactive)
- (helm-other-window-base 'scroll-down))
-
-(defun helm-recenter-top-bottom-other-window ()
- "`recenter-top-bottom' in other window (not *Helm* window)."
- (interactive)
- (helm-other-window-base 'recenter-top-bottom 'noscroll))
-
-(defun helm-reposition-window-other-window ()
- "`helm-reposition-window' in other window (not *Helm* window)."
- (interactive)
- (helm-other-window-base 'reposition-window 'noscroll))
-
-
-\f
-;; Utility: Visible Mark
-
-(defun helm-clear-visible-mark ()
- (with-current-buffer (helm-buffer-get)
- (mapc 'delete-overlay helm-visible-mark-overlays)
- (set (make-local-variable 'helm-visible-mark-overlays) nil)))
-
-(defun helm-this-visible-mark ()
- (cl-loop for o in helm-visible-mark-overlays
- when (equal (point-at-bol) (overlay-start o))
- return o))
-
-(defun helm-delete-visible-mark (overlay)
- (setq helm-marked-candidates
- (remove
- (cons (helm-get-current-source) (helm-get-selection))
- helm-marked-candidates))
- (delete-overlay overlay)
- (setq helm-visible-mark-overlays
- (delq overlay helm-visible-mark-overlays)))
-
-(defun helm-make-visible-mark ()
- (let ((o (make-overlay (point-at-bol)
- (if (helm-pos-multiline-p)
- (or (helm-get-next-candidate-separator-pos)
- (point-max))
- (1+ (point-at-eol))))))
- (overlay-put o 'priority 0)
- (overlay-put o 'face 'helm-visible-mark)
- (overlay-put o 'source (assoc-default 'name (helm-get-current-source)))
- (overlay-put o 'string (buffer-substring (overlay-start o) (overlay-end o)))
- (overlay-put o 'real (helm-get-selection))
- (add-to-list 'helm-visible-mark-overlays o))
- (push (cons (helm-get-current-source) (helm-get-selection))
- helm-marked-candidates))
-
-(defun helm-toggle-visible-mark ()
- "Toggle helm visible mark at point."
- (interactive)
- (with-helm-window
- (let ((nomark (assq 'nomark (helm-get-current-source))))
- (if nomark
- (message "Marking not allowed in this source")
- (helm-aif (helm-this-visible-mark)
- (helm-delete-visible-mark it)
- (helm-make-visible-mark))
- (if (helm-end-of-source-p)
- (helm-display-mode-line (helm-get-current-source))
- (helm-next-line))))))
-
-(defun helm-file-completion-source-p ()
- "Return non--nil if current source is a file completion source."
- (or minibuffer-completing-file-name
- (let ((cur-source (cdr (assoc 'name (helm-get-current-source)))))
- (cl-loop for i in helm--file-completion-sources
- thereis (string= cur-source i)))))
-
-(defun helm-mark-all ()
- "Mark all visible unmarked candidates in current source."
- (interactive)
- (with-helm-window
- (let ((nomark (assq 'nomark (helm-get-current-source)))
- (follow (if helm-follow-mode 1 -1)))
- (helm-follow-mode -1)
- (unwind-protect
- (if nomark
- (message "Marking not allowed in this source")
- (save-excursion
- (goto-char (helm-get-previous-header-pos))
- (helm-next-line)
- (let* ((next-head (helm-get-next-header-pos))
- (end (and next-head
- (save-excursion
- (goto-char next-head)
- (forward-line -1)
- (point))))
- (maxpoint (or end (point-max))))
- (while (< (point) maxpoint)
- (helm-mark-current-line)
- (let* ((prefix (get-text-property (point-at-bol) 'display))
- (cand (helm-get-selection))
- (bn (and (helm-file-completion-source-p)
- (helm-basename cand)))
- (src-name (assoc-default 'name
- (helm-get-current-source))))
- (when (and (not (helm-this-visible-mark))
- (not (or (string= prefix "[?]")
- (string= prefix "[@]"))))
- ;; Don't mark possibles directories ending with . or ..
- ;; autosave files/links and non--existent file.
- (unless
- (and (or (helm-file-completion-source-p)
- (string=
- src-name "Files from Current Directory"))
- (or (string-match
- "^[.]?#.*#?$\\|[^#]*[.]\\{1,2\\}$" bn)
- ;; We need to test here when not using
- ;; a transformer that tag prefix
- ;; (i.e on tramp).
- (not (file-exists-p cand))))
- (helm-make-visible-mark))))
- (if (helm-pos-multiline-p)
- (progn
- (goto-char
- (or (helm-get-next-candidate-separator-pos)
- (point-max)))
- (forward-line 1))
- (forward-line 1))
- (end-of-line))))
- (helm-mark-current-line)
- (message "%s candidates marked" (length helm-marked-candidates)))
- (helm-follow-mode follow) (message nil)))))
-
-(defun helm-unmark-all ()
- "Unmark all candidates in all sources of current helm session."
- (interactive)
- (with-helm-window
- (let ((len (length helm-marked-candidates)))
- (save-excursion
- (helm-clear-visible-mark))
- (setq helm-marked-candidates nil)
- (helm-mark-current-line)
- (helm-display-mode-line (helm-get-current-source))
- (message "%s candidates unmarked" len))))
-
-(defun helm-toggle-all-marks ()
- "Toggle all marks.
-Mark all visible candidates of current source or unmark all candidates
-visible or invisible in all sources of current helm session"
- (interactive)
- (let ((marked (helm-marked-candidates)))
- (if (and (>= (length marked) 1)
- (with-helm-window helm-visible-mark-overlays))
- (helm-unmark-all)
- (helm-mark-all))))
-
-(defun helm--compute-marked (real source wildcard)
- (let* ((coerced (helm-coerce-selection real source))
- (wilds (and wildcard
- (condition-case nil
- (helm-file-expand-wildcards coerced t)
- (error nil)))))
- ;; Avoid returning a not expanded wilcard fname.
- ;; e.g assuming "/tmp" doesn't contain "*.el"
- ;; return nil when coerced is "/tmp/*.el".
- (unless (or wilds (null wildcard)
- (string-match-p helm--url-regexp coerced)
- (file-exists-p coerced)
- (and (stringp coerced)
- (null (string-match-p "[[*?]" coerced))))
- (setq coerced nil))
- (or wilds (and coerced (list coerced)))))
-
-(cl-defun helm-marked-candidates (&key with-wildcard)
- "Return marked candidates of current source if any.
-Otherwise one element list of current selection.
-When key WITH-WILDCARD is specified try to expand a wilcard if some."
- (with-current-buffer helm-buffer
- (let ((candidates
- (cl-loop with current-src = (helm-get-current-source)
- for (source . real) in (reverse helm-marked-candidates)
- when (equal (assq 'name source) (assq 'name current-src))
- append (helm--compute-marked real source with-wildcard)
- into cands
- finally return (or cands
- (append
- (helm--compute-marked
- (helm-get-selection) current-src
- with-wildcard)
- cands)))))
- (helm-log "Marked candidates = %S" candidates)
- candidates)))
-
-(defun helm-current-source-name= (name)
- (save-excursion
- (goto-char (helm-get-previous-header-pos))
- (equal name (helm-current-line-contents))))
-
-(defun helm-revive-visible-mark ()
- "Restore marked candidates when helm update display."
- (with-current-buffer helm-buffer
- (save-excursion
- (cl-dolist (o helm-visible-mark-overlays)
- (goto-char (point-min))
- (while (and (search-forward (overlay-get o 'string) nil t)
- (helm-current-source-name= (overlay-get o 'source)))
- ;; Calculate real value of candidate.
- ;; It can be nil if candidate have only a display value.
- (let ((real (get-text-property (point-at-bol 0) 'helm-realvalue)))
- (if real
- ;; Check if real value of current candidate is the same
- ;; than the one stored in overlay.
- ;; This is needed when some cands have same display names.
- ;; Using equal allow testing any type of value for real cand.
- ;; Issue (#706).
- (and (equal (overlay-get o 'real) real)
- (move-overlay o (point-at-bol 0) (1+ (point-at-eol 0))))
- (move-overlay o (point-at-bol 0) (1+ (point-at-eol 0))))))))))
-(add-hook 'helm-update-hook 'helm-revive-visible-mark)
-
-(defun helm-next-point-in-list (curpos points &optional prev)
- (cond
- ;; rule out special cases.
- ((null points) curpos)
- ((and prev (<= curpos (car points)))
- (nth (1- (length points)) points))
- ((< (car (last points)) curpos)
- (if prev (car (last points)) (nth 0 points)))
- ((and (not prev) (>= curpos (car (last points))))
- (nth 0 points))
- (t
- (nth (if prev
- (cl-loop for pt in points
- for i from 0
- if (<= curpos pt) return (1- i))
- (cl-loop for pt in points
- for i from 0
- if (< curpos pt) return i))
- points))))
-
-(defun helm-next-visible-mark (&optional prev)
- "Move next helm visible mark.
-If PREV is non-nil move to precedent."
- (interactive)
- (with-helm-window
- (ignore-errors
- (goto-char (helm-next-point-in-list
- (point)
- (sort (mapcar 'overlay-start helm-visible-mark-overlays) '<)
- prev)))
- (helm-mark-current-line)))
-
-(defun helm-prev-visible-mark ()
- "Move previous helm visible mark."
- (interactive)
- (helm-next-visible-mark t))
-
-;;; Utility: Selection Paste
-;;
-(defun helm-yank-selection (arg)
- "Set minibuffer contents to current display selection.
-With a prefix arg set to real value of current selection."
- (interactive "P")
- (let ((str (helm-get-selection nil (not arg))))
- (kill-new str)
- (helm-set-pattern str)))
-
-(defun helm-kill-selection-and-quit (arg)
- "Store display value of current selection to kill ring.
-With a prefix arg set to real value of current selection.
-Display value is what you see in `helm-buffer' and real value
-is what is used to perform actions."
- (interactive "P")
- (helm-run-after-exit
- (lambda (sel)
- (kill-new sel)
- ;; Return nil to force `helm-mode--keyboard-quit'
- ;; in `helm-comp-read' otherwise the value "Saved to kill-ring: foo"
- ;; is used as exit value for `helm-comp-read'.
- (prog1 nil (message "Saved to kill-ring: %s" sel) (sit-for 1)))
- (helm-get-selection nil (not arg))))
-
-(defun helm-copy-to-buffer ()
- "Copy selection or marked candidates to `helm-current-buffer'."
- (interactive)
- (with-helm-buffer
- (cl-loop for cand in (helm-marked-candidates)
- do (with-helm-current-buffer
- (insert (format "%s\n" cand))))))
-
-\f
-;;; Follow-mode: Automatical execution of persistent-action
-;;
-;;
-(defun helm-follow-mode (&optional arg)
- "Execute persistent action everytime the cursor is moved when enabled.
-The mode is enabled for the current source only, you will have to turn it
-on again when you go to next source if you want it there also.
-This mode can be enabled or disabled interactively at anytime during
-helm session or enabled specifically by source by adding the `follow'
-attribute to this source.
-Even when the attribute `follow' exists in source, it is still possible
-to disable/enable this mode interactively.
-Note that when you disable it interactively and `follow' attribute exists,
-`helm-follow-mode' will be disabled on next helm session even if `follow'
-attribute is specified in source. To avoid this set your `follow' attribute
-in source in `helm-before-initialize-hook'.
-
-e.g:
-
-\(add-hook 'helm-before-initialize-hook
- (lambda () (helm-attrset 'follow 1 helm-source-buffers-list)))
-
-This will enable `helm-follow-mode' automatically in `helm-source-buffers-list'."
- (interactive "p")
- (with-current-buffer helm-buffer
- (let* ((src (helm-get-current-source))
- (name (assoc-default 'name src))
- (sym (cl-loop for s in helm-sources
- for sname = (and (symbolp s)
- (assoc-default
- 'name (symbol-value s)))
- thereis (and sname (string= sname name) s)))
- (fol-attr (assq 'follow src))
- (enabled (or
- ;; If `helm-follow-mode' is called with a negative
- ;; ARG, assume follow is already enabled.
- ;; i.e turn it off now.
- (< arg 0)
- (eq (cdr fol-attr) 1)
- helm-follow-mode)))
- (if src
- (progn
- (if (eq (cdr fol-attr) 'never)
- (message "helm-follow-mode not allowed in this source")
- ;; Make follow attr persistent for this emacs session.
- (helm-attrset 'follow (if enabled -1 1) src)
- (setq helm-follow-mode (not enabled))
- (message "helm-follow-mode is %s"
- (if helm-follow-mode
- "enabled" "disabled"))
- (helm-display-mode-line src t))
- (unless helm-follow-mode-persistent
- (and sym (set sym (remove (assq 'follow src) src)))))
- (message "Not enough candidates for helm-follow-mode")))))
-
-(defvar helm-follow-input-idle-delay nil
- "`helm-follow-mode' will execute its persistent action after this delay.
-Note that if the `follow-delay' attr is present in source,
-it will take precedence on this.")
-(defun helm-follow-execute-persistent-action-maybe ()
- "Execute persistent action in mode `helm-follow-mode'.
-This happen after `helm-input-idle-delay' secs."
- (let ((src (helm-get-current-source)))
- (and (not (get-buffer-window helm-action-buffer 'visible))
- (eq (assoc-default 'follow src) 1)
- (sit-for (or (assoc-default 'follow-delay src)
- helm-follow-input-idle-delay
- (and helm-input-idle-delay
- (max helm-input-idle-delay 0.01))))
- (helm-window)
- (helm-get-selection)
- (save-excursion
- (helm-execute-persistent-action)))))
-
-\f
-;;; Auto-resize mode
-;;
-(defun helm--autoresize-hook (&optional max-height min-height)
- (with-helm-window
- (fit-window-to-buffer nil
- (/ (* (frame-height)
- (or max-height helm-autoresize-max-height))
- 100)
- (/ (* (frame-height)
- (or min-height helm-autoresize-min-height))
- 100))))
-
-(define-minor-mode helm-autoresize-mode
- "Auto resize helm window when enabled.
-Helm window is resized according to values of `helm-autoresize-max-height'
-and `helm-autoresize-min-height'.
-Note that when this mode is enabled, helm behave like when
-`helm-always-two-windows' is enabled.
-
-See `fit-window-to-buffer' for more infos."
- :group 'helm
- :global t
- (if helm-autoresize-mode
- (progn (add-hook 'helm-after-update-hook 'helm--autoresize-hook)
- (add-hook 'helm-window-configuration-hook 'helm--autoresize-hook))
- (remove-hook 'helm-after-update-hook 'helm--autoresize-hook)
- (remove-hook 'helm-window-configuration-hook 'helm--autoresize-hook)))
-
-(defun helm-help ()
- "Help of `helm'."
- (interactive)
- (with-helm-alive-p
- (save-selected-window
- (helm-help-internal
- "*Helm Help*"
- (lambda ()
- (helm-aif (assoc-default 'help-message (helm-get-current-source))
- (insert (substitute-command-keys
- (helm-interpret-value it)))
- (insert "* No specific help for this source at this time.\n
-It may appear after first results popup in helm buffer."))
- (insert "\n\n"
- (substitute-command-keys
- (helm-interpret-value helm-help-message))))))))
-
-(defun helm-toggle-truncate-line ()
- "Toggle `truncate-lines' value in `helm-buffer'"
- (interactive)
- (with-helm-alive-p
- (with-helm-buffer
- (setq truncate-lines (not truncate-lines))
- (helm-update (regexp-quote (helm-get-selection nil t))))))
-
-(provide 'helm)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm.el ends here
+++ /dev/null
-;;; helm-core-autoloads.el --- automatically extracted autoloads
-;;
-;;; Code:
-(add-to-list 'load-path (or (file-name-directory #$) (car load-path)))
-\f
-;;;### (autoloads nil "helm" "helm.el" (22215 7773 0 0))
-;;; Generated autoloads from helm.el
-
-(autoload 'helm-define-multi-key "helm" "\
-In KEYMAP, define key sequence KEY for function list FUNCTIONS.
-Each function run sequentially each time the key KEY is pressed.
-If DELAY is specified switch back to initial function of FUNCTIONS list
-after DELAY seconds.
-The functions in FUNCTIONS list are functions with no args.
-e.g
- (defun foo ()
- (message \"Run foo\"))
- (defun bar ()
- (message \"Run bar\"))
- (defun baz ()
- (message \"Run baz\"))
-
-\(helm-define-multi-key global-map \"<f5> q\" '(foo bar baz) 2)
-
-Each time \"<f5> q\" is pressed the next function is executed, if you wait
-More than 2 seconds, next hit will run again the first function and so on.
-
-\(fn KEYMAP KEY FUNCTIONS &optional DELAY)" nil nil)
-
-(autoload 'helm-multi-key-defun "helm" "\
-Define NAME as a multi-key command running FUNS.
-After DELAY seconds the FUNS list is reinitialised.
-See `helm-define-multi-key'.
-
-\(fn NAME DOCSTRING FUNS &optional DELAY)" nil t)
-
-(put 'helm-multi-key-defun 'lisp-indent-function '2)
-
-(autoload 'helm-define-key-with-subkeys "helm" "\
-Allow defining in MAP a KEY and SUBKEY to COMMAND.
-
-This allow typing KEY to call COMMAND the first time and
-type only SUBKEY on subsequent calls.
-
-Arg MAP is the keymap to use, SUBKEY is the initial short keybinding to
-call COMMAND.
-
-Arg OTHER-SUBKEYS is an alist specifying other short keybindings
-to use once started.
-e.g:
-
-\(helm-define-key-with-subkeys global-map
- (kbd \"C-x v n\") ?n 'git-gutter:next-hunk '((?p . git-gutter:previous-hunk)))
-
-
-In this example, `C-x v n' will run `git-gutter:next-hunk'
-subsequent hits on \"n\" will run this command again
-and subsequent hits on \"p\" will run `git-gutter:previous-hunk'.
-
-Arg MENU is a string to display in minibuffer
-to describe SUBKEY and OTHER-SUBKEYS.
-Arg EXIT-FN specify a function to run on exit.
-
-Any other keys pressed run their assigned command defined in MAP
-and exit the loop running EXIT-FN if specified.
-
-NOTE: SUBKEY and OTHER-SUBKEYS bindings support
-only char syntax actually (e.g ?n)
-so don't use strings, vectors or whatever to define them.
-
-\(fn MAP KEY SUBKEY COMMAND &optional OTHER-SUBKEYS MENU EXIT-FN)" nil nil)
-
-(put 'helm-define-key-with-subkeys 'lisp-indent-function '1)
-
-(autoload 'helm-debug-open-last-log "helm" "\
-Open helm log file of last helm session.
-If `helm-last-log-file' is nil, switch to `helm-debug-buffer' .
-
-\(fn)" t nil)
-
-(autoload 'helm "helm" "\
-Main function to execute helm sources.
-
-Keywords supported:
-:sources :input :prompt :resume :preselect
-:buffer :keymap :default :history :allow-nest
-
-Extra LOCAL-VARS keywords are supported, see below.
-
-PLIST is a list like (:key1 val1 :key2 val2 ...) or
-\(&optional sources input prompt resume
- preselect buffer keymap default history).
-
-Basic keywords are the following:
-
-:sources
-
-A list of sources used for this session. It also accepts a
-symbol, interpreted as a variable of a helm source
-i.e (a symbol can be passed instead of a list of sources).
-It also accepts an alist representing a helm source, which is
-detected by (assq 'name ANY-SOURCES).
-NOTE: In this case the source is embedded in the helm command and
-have no symbol name, so it is not reachable from outside.
-It will be referenced in `helm-sources' as a whole alist.
-
-:input
-
-Temporary value of `helm-pattern', ie. initial input of minibuffer.
-
-:prompt
-
-Prompt other than \"pattern: \".
-
-:resume
-
-If t, Resurrect previously instance of `helm'. Skip the initialization.
-If 'noresume, this instance of `helm' cannot be resumed.
-
-:preselect
-
-Initially selected candidate. Specified by exact candidate or a regexp.
-
-:buffer
-
-`helm-buffer' instead of *helm*.
-
-:keymap
-
-`helm-map' for current `helm' session.
-
-:default
-
-A default argument that will be inserted in minibuffer with \\<minibuffer-local-map>\\[next-history-element].
-When nil or not present `thing-at-point' will be used instead.
-If `helm--maybe-use-default-as-input' is non--nil display will be
-updated using :default arg as input unless :input is specified,
-which in this case will take precedence on :default
-This is a string or a list, in this case the car of the list will
-be used as initial default input, but you will be able to cycle in this
-list with \\<minibuffer-local-map>\\[next-history-element].
-
-:history
-
-By default all minibuffer input is pushed to `minibuffer-history',
-if an argument HISTORY is provided, input will be pushed to HISTORY.
-History element should be a symbol.
-
-:allow-nest
-
-Allow running this helm command within a running helm session.
-
-Of course, conventional arguments are supported, the two are same.
-
-\(helm :sources sources :input input :prompt prompt :resume resume
- :preselect preselect :buffer buffer :keymap keymap :default default
- :history history)
-
-and
-
-\(helm sources input prompt resume preselect buffer keymap default history)
-
-are the same.
-
-However the use of non keyword args is deprecated and should not be used.
-
-Other keywords are interpreted as local variables of this helm session.
-The `helm-' prefix can be omitted. For example,
-
-\(helm :sources 'helm-source-buffers-list
- :buffer \"*buffers*\" :candidate-number-limit 10)
-
-means starting helm session with `helm-source-buffers'
-source in *buffers* buffer and set variable `helm-candidate-number-limit'
-to 10 as session local variable.
-
-\(fn &key SOURCES INPUT PROMPT RESUME PRESELECT BUFFER KEYMAP DEFAULT HISTORY ALLOW-NEST OTHER-LOCAL-VARS)" nil nil)
-
-(autoload 'helm-other-buffer "helm" "\
-Simplified interface of `helm' with other `helm-buffer'.
-Call `helm' with only ANY-SOURCES and ANY-BUFFER as args.
-
-\(fn ANY-SOURCES ANY-BUFFER)" nil nil)
-
-(autoload 'helm-debug-toggle "helm" "\
-Enable/disable helm debug from outside of helm session.
-
-\(fn)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil nil ("helm-core-pkg.el" "helm-lib.el" "helm-multi-match.el"
-;;;;;; "helm-source.el") (22215 7773 270790 0))
-
-;;;***
-\f
-;; Local Variables:
-;; version-control: never
-;; no-byte-compile: t
-;; no-update-autoloads: t
-;; End:
-;;; helm-core-autoloads.el ends here
+++ /dev/null
-(define-package "helm-core" "20160217.958" "Development files for Helm"
- '((emacs "24.3")
- (async "1.6"))
- :url "https://emacs-helm.github.io/helm/")
-;; Local Variables:
-;; no-byte-compile: t
-;; End:
+++ /dev/null
-;;; helm-lib.el --- Helm routines. -*- lexical-binding: t -*-
-
-;; Copyright (C) 2015 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; Author: Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-;; URL: http://github.com/emacs-helm/helm
-
-;; 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/>.
-
-;;; Commentary:
-;; All helm functions that don't require specific helm code should go here.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'dired)
-
-\f
-;;; User vars.
-;;
-(defcustom helm-file-globstar t
- "Same as globstar bash shopt option.
-When non--nil a pattern beginning with two stars will expand recursively.
-Directories expansion is not supported yet."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-yank-text-at-point-function nil
- "The function used to forward point with `helm-yank-text-at-point'.
-With a nil value, fallback to default `forward-word'.
-The function should take one arg, an integer like `forward-word'.
-NOTE: Using `forward-symbol' here is not very useful as it is already
-provided by \\<helm-map>\\[next-history-element]."
- :type 'function
- :group 'helm)
-
-(defcustom helm-scroll-amount nil
- "Scroll amount when scrolling other window in a helm session.
-It is used by `helm-scroll-other-window'
-and `helm-scroll-other-window-down'.
-
-If you prefer scrolling line by line, set this value to 1."
- :group 'helm
- :type 'integer)
-
-\f
-;;; Internal vars
-;;
-(defvar helm-yank-point nil)
-(defvar helm-pattern ""
- "The input pattern used to update the helm buffer.")
-(defvar helm-buffer "*helm*"
- "Buffer showing completions.")
-(defvar helm-current-buffer nil
- "Current buffer when `helm' is invoked.")
-(defvar helm-suspend-update-flag nil)
-(defvar helm-action-buffer "*helm action*"
- "Buffer showing actions.")
-\f
-;;; Macros helper.
-;;
-(defmacro helm-with-gensyms (symbols &rest body)
- "Bind the SYMBOLS to fresh uninterned symbols and eval BODY."
- (declare (indent 1))
- `(let ,(mapcar (lambda (s)
- ;; Use cl-gensym here instead of make-symbol
- ;; to ensure a symbol that have a live that go
- ;; beyond the live of its macro have different name.
- ;; i.e symbols created with `with-helm-temp-hook'
- ;; should have random names.
- `(,s (cl-gensym (symbol-name ',s))))
- symbols)
- ,@body))
-\f
-;;; Iterators
-;;
-(defun helm-iter-list (seq)
- "Return an iterator object from SEQ."
- (let ((lis seq))
- (lambda ()
- (let ((elm (car lis)))
- (setq lis (cdr lis))
- elm))))
-
-(defun helm-iter-next (iterator)
- "Return next elm of ITERATOR."
- (funcall iterator))
-
-(defun helm-make-actions (&rest args)
- "Build an alist with (NAME . ACTION) elements with each pairs in ARGS.
-Where NAME is a string or a function returning a string or nil and ACTION
-a function.
-If NAME returns nil the pair is skipped.
-
-\(fn NAME ACTION ...)"
- (cl-loop for i on args by #'cddr
- for name = (car i)
- when (functionp name)
- do (setq name (funcall name))
- when name
- collect (cons name (cadr i))))
-
-(defmacro helm-aif (test-form then-form &rest else-forms)
- "Like `if' but set the result of TEST-FORM in a temprary variable called `it'.
-THEN-FORM and ELSE-FORMS are then excuted just like in `if'."
- (declare (indent 2) (debug t))
- `(let ((it ,test-form))
- (if it ,then-form ,@else-forms)))
-
-(defun helm-current-line-contents ()
- "Current line string without properties."
- (buffer-substring-no-properties (point-at-bol) (point-at-eol)))
-\f
-;;; Fuzzy matching routines
-;;
-(defsubst helm--mapconcat-pattern (pattern)
- "Transform string PATTERN in regexp for further fuzzy matching.
-e.g helm.el$
- => \"[^h]*h[^e]*e[^l]*l[^m]*m[^.]*[.][^e]*e[^l]*l$\"
- ^helm.el$
- => \"helm[.]el$\"."
- (let ((ls (split-string-and-unquote pattern "")))
- (if (string= "^" (car ls))
- ;; Exact match.
- (mapconcat (lambda (c)
- (if (and (string= c "$")
- (string-match "$\\'" pattern))
- c (regexp-quote c)))
- (cdr ls) "")
- ;; Fuzzy match.
- (mapconcat (lambda (c)
- (if (and (string= c "$")
- (string-match "$\\'" pattern))
- c (format "[^%s]*%s" c (regexp-quote c))))
- ls ""))))
-
-(defsubst helm--collect-pairs-in-string (string)
- (cl-loop for str on (split-string string "" t) by 'cdr
- when (cdr str)
- collect (list (car str) (cadr str))))
-\f
-;;; Help routines.
-;;
-(defun helm-help-internal (bufname insert-content-fn)
- "Show long message during `helm' session in BUFNAME.
-INSERT-CONTENT-FN is the function that insert
-text to be displayed in BUFNAME."
- (let ((winconf (current-frame-configuration)))
- (unwind-protect
- (progn
- (setq helm-suspend-update-flag t)
- (set-buffer (get-buffer-create bufname))
- (switch-to-buffer bufname)
- (delete-other-windows)
- (delete-region (point-min) (point-max))
- (org-mode)
- (save-excursion
- (funcall insert-content-fn))
- (buffer-disable-undo)
- (helm-help-event-loop))
- (setq helm-suspend-update-flag nil)
- (set-frame-configuration winconf))))
-
-(defun helm-help-scroll-up (amount)
- (condition-case _err
- (scroll-up-command amount)
- (beginning-of-buffer nil)
- (end-of-buffer nil)))
-
-(defun helm-help-scroll-down (amount)
- (condition-case _err
- (scroll-down-command amount)
- (beginning-of-buffer nil)
- (end-of-buffer nil)))
-
-(defun helm-help-next-line ()
- (condition-case _err
- (call-interactively #'next-line)
- (beginning-of-buffer nil)
- (end-of-buffer nil)))
-
-(defun helm-help-previous-line ()
- (condition-case _err
- (call-interactively #'previous-line)
- (beginning-of-buffer nil)
- (end-of-buffer nil)))
-
-(defun helm-help-toggle-mark ()
- (if (region-active-p)
- (deactivate-mark)
- (push-mark nil nil t)))
-
-;; For movement of cursor in help buffer we need to call interactively
-;; commands for impaired people using a synthetizer (#1347).
-(defun helm-help-event-loop ()
- (let ((prompt (propertize
- "[SPC,C-v,down,next:NextPage b,M-v,up,prior:PrevPage C-s/r:Isearch q:Quit]"
- 'face 'helm-helper))
- scroll-error-top-bottom)
- (cl-loop for event = (read-key prompt) do
- (cl-case event
- ((?\C-v ? down next) (helm-help-scroll-up helm-scroll-amount))
- ((?\M-v ?b up prior) (helm-help-scroll-down helm-scroll-amount))
- (?\C-s (isearch-forward))
- (?\C-r (isearch-backward))
- (?\C-a (call-interactively #'move-beginning-of-line))
- (?\C-e (call-interactively #'move-end-of-line))
- (?\C-f (call-interactively #'forward-char))
- (?\C-b (call-interactively #'backward-char))
- (?\C-n (helm-help-next-line))
- (?\C-p (helm-help-previous-line))
- (?\M-a (call-interactively #'backward-sentence))
- (?\M-e (call-interactively #'forward-sentence))
- (?\M-f (call-interactively #'forward-word))
- (?\M-b (call-interactively #'backward-word))
- (?\C- (helm-help-toggle-mark))
- (?\M-w (copy-region-as-kill
- (region-beginning) (region-end))
- (deactivate-mark))
- (?q (cl-return))
- (t (ignore))))))
-
-\f
-;;; List processing
-;;
-(defun helm-flatten-list (seq &optional omit-nulls)
- "Return a list of all single elements of sublists in SEQ."
- (let (result)
- (cl-labels ((flatten (seq)
- (cl-loop
- for elm in seq
- if (and (or elm
- (null omit-nulls))
- (or (atom elm)
- (functionp elm)
- (and (consp elm)
- (cdr elm)
- (atom (cdr elm)))))
- do (push elm result)
- else do (flatten elm))))
- (flatten seq))
- (nreverse result)))
-
-(defun helm-mklist (obj)
- "If OBJ is a list \(but not lambda\), return itself.
-Otherwise make a list with one element."
- (if (and (listp obj) (not (functionp obj)))
- obj
- (list obj)))
-
-(cl-defmacro helm-position (item seq &key (test 'eq) all)
- "A simple and faster replacement of CL `position'.
-Return position of first occurence of ITEM found in SEQ.
-Argument SEQ can be a string, in this case ITEM have to be a char.
-Argument ALL, if non--nil specify to return a list of positions of
-all ITEM found in SEQ."
- (let ((key (if (stringp seq) 'across 'in)))
- `(cl-loop for c ,key ,seq
- for index from 0
- when (funcall ,test c ,item)
- if ,all collect index into ls
- else return index
- finally return ls)))
-
-(cl-defun helm-fast-remove-dups (seq &key (test 'eq))
- "Remove duplicates elements in list SEQ.
-This is same as `remove-duplicates' but with memoisation.
-It is much faster, especially in large lists.
-A test function can be provided with TEST argument key.
-Default is `eq'."
- (cl-loop with cont = (make-hash-table :test test)
- for elm in seq
- unless (gethash elm cont)
- do (puthash elm elm cont)
- finally return
- (cl-loop for i being the hash-values in cont collect i)))
-
-(defun helm-skip-entries (seq black-regexp-list &optional white-regexp-list)
- "Remove entries which matches one of REGEXP-LIST from SEQ."
- (cl-loop for i in seq
- unless (and (cl-loop for re in black-regexp-list
- thereis (and (stringp i)
- (string-match-p re i)))
- (null
- (cl-loop for re in white-regexp-list
- thereis (and (stringp i)
- (string-match-p re i)))))
- collect i))
-
-(defun helm-shadow-entries (seq regexp-list)
- "Put shadow property on entries in SEQ matching a regexp in REGEXP-LIST."
- (let ((face 'italic))
- (cl-loop for i in seq
- if (cl-loop for regexp in regexp-list
- thereis (and (stringp i)
- (string-match regexp i)))
- collect (propertize i 'face face)
- else collect i)))
-
-(defun helm-remove-if-not-match (regexp seq)
- "Remove all elements of SEQ that don't match REGEXP."
- (cl-loop for s in seq
- for str = (cond ((symbolp s)
- (symbol-name s))
- ((consp s)
- (car s))
- (t s))
- when (string-match-p regexp str)
- collect s))
-
-(defun helm-remove-if-match (regexp seq)
- "Remove all elements of SEQ that match REGEXP."
- (cl-loop for s in seq
- for str = (cond ((symbolp s)
- (symbol-name s))
- ((consp s)
- (car s))
- (t s))
- unless (string-match-p regexp str)
- collect s))
-
-(defun helm-transform-mapcar (function args)
- "`mapcar' for candidate-transformer.
-
-ARGS is (cand1 cand2 ...) or ((disp1 . real1) (disp2 . real2) ...)
-
-\(helm-transform-mapcar 'upcase '(\"foo\" \"bar\"))
-=> (\"FOO\" \"BAR\")
-\(helm-transform-mapcar 'upcase '((\"1st\" . \"foo\") (\"2nd\" . \"bar\")))
-=> ((\"1st\" . \"FOO\") (\"2nd\" . \"BAR\"))
-"
- (cl-loop for arg in args
- if (consp arg)
- collect (cons (car arg) (funcall function (cdr arg)))
- else
- collect (funcall function arg)))
-\f
-;;; Strings processing.
-;;
-(defun helm-stringify (str-or-sym)
- "Get string of STR-OR-SYM."
- (if (stringp str-or-sym)
- str-or-sym
- (symbol-name str-or-sym)))
-
-(defun helm-substring (str width)
- "Return the substring of string STR from 0 to WIDTH.
-Handle multibyte characters by moving by columns."
- (with-temp-buffer
- (save-excursion
- (insert str))
- (move-to-column width)
- (buffer-substring (point-at-bol) (point))))
-
-(defun helm-substring-by-width (str width &optional endstr)
- "Truncate string STR to end at column WIDTH.
-Similar to `truncate-string-to-width'.
-Add ENDSTR at end of truncated STR.
-Add spaces at end if needed to reach WIDTH when STR is shorter than WIDTH."
- (cl-loop for ini-str = str
- then (substring ini-str 0 (1- (length ini-str)))
- for sw = (string-width ini-str)
- when (<= sw width) return
- (concat ini-str endstr (make-string (- width sw) ? ))))
-
-(defun helm-string-multibyte-p (str)
- "Check if string STR contains multibyte characters."
- (cl-loop for c across str
- thereis (> (char-width c) 1)))
-
-(defun helm-get-pid-from-process-name (process-name)
- "Get pid from running process PROCESS-NAME."
- (cl-loop with process-list = (list-system-processes)
- for pid in process-list
- for process = (assoc-default 'comm (process-attributes pid))
- when (and process (string-match process-name process))
- return pid))
-
-(defun helm-ff-find-printers ()
- "Return a list of available printers on Unix systems."
- (when (executable-find "lpstat")
- (let ((printer-list (with-temp-buffer
- (call-process "lpstat" nil t nil "-a")
- (split-string (buffer-string) "\n"))))
- (cl-loop for p in printer-list
- for printer = (car (split-string p))
- when printer
- collect printer))))
-
-(defun helm-region-active-p ()
- (and transient-mark-mode mark-active (/= (mark) (point))))
-
-(defun helm-quote-whitespace (candidate)
- "Quote whitespace, if some, in string CANDIDATE."
- (replace-regexp-in-string " " "\\\\ " candidate))
-
-\f
-;;; Symbols routines
-;;
-(defun helm-symbolify (str-or-sym)
- "Get symbol of STR-OR-SYM."
- (if (symbolp str-or-sym)
- str-or-sym
- (intern str-or-sym)))
-
-(defun helm-symbol-name (obj)
- (if (or (consp obj) (byte-code-function-p obj))
- "Anonymous"
- (symbol-name obj)))
-
-(defun helm-describe-function (func)
- "FUNC is symbol or string."
- (describe-function (helm-symbolify func))
- (message nil))
-
-(defun helm-describe-variable (var)
- "VAR is symbol or string."
- (describe-variable (helm-symbolify var))
- (message nil))
-
-(defun helm-describe-face (face)
- "VAR is symbol or string."
- (describe-face (helm-symbolify face))
- (message nil))
-
-(defun helm-find-function (func)
- "FUNC is symbol or string."
- (find-function (helm-symbolify func)))
-
-(defun helm-find-variable (var)
- "VAR is symbol or string."
- (find-variable (helm-symbolify var)))
-
-(defun helm-find-face-definition (face)
- "FACE is symbol or string."
- (find-face-definition (helm-symbolify face)))
-
-(defun helm-kill-new (candidate &optional replace)
- "CANDIDATE is symbol or string.
-See `kill-new' for argument REPLACE."
- (kill-new (helm-stringify candidate) replace))
-\f
-;;; Files routines
-;;
-(defun helm-file-name-sans-extension (filename)
- "Same as `file-name-sans-extension' but remove all extensions."
- (helm-aif (file-name-sans-extension filename)
- ;; Start searching at index 1 for files beginning with a dot (#1335).
- (if (string-match "\\." (helm-basename it) 1)
- (helm-file-name-sans-extension it)
- it)))
-
-(defun helm-basename (fname &optional ext)
- "Print FNAME with any leading directory components removed.
-If specified, also remove filename extension EXT.
-Arg EXT can be specified as a string with or without dot."
- (let ((non-essential t))
- (if (and ext (or (string= (file-name-extension fname) ext)
- (string= (file-name-extension fname t) ext))
- (not (file-directory-p fname)))
- (file-name-sans-extension (file-name-nondirectory fname))
- (file-name-nondirectory (directory-file-name fname)))))
-
-(defun helm-basedir (fname)
- "Return the base directory of filename ending by a slash."
- (helm-aif (and fname
- (or (and (string= fname "~") "~")
- (file-name-directory fname)))
- (file-name-as-directory it)))
-
-(defun helm-current-directory ()
- "Return current-directory name at point.
-Useful in dired buffers when there is inserted subdirs."
- (expand-file-name
- (if (eq major-mode 'dired-mode)
- (dired-current-directory)
- default-directory)))
-
-(defun helm-w32-prepare-filename (file)
- "Convert filename FILE to something usable by external w32 executables."
- (replace-regexp-in-string ; For UNC paths
- "/" "\\"
- (replace-regexp-in-string ; Strip cygdrive paths
- "/cygdrive/\\(.\\)" "\\1:"
- file nil nil) nil t))
-
-(defun helm-w32-shell-execute-open-file (file)
- (with-no-warnings
- (w32-shell-execute "open" (helm-w32-prepare-filename file))))
-
-;; Same as `vc-directory-exclusion-list'.
-(defvar helm-walk-ignore-directories
- '("SCCS" "RCS" "CVS" "MCVS" ".svn" ".git" ".hg" ".bzr"
- "_MTN" "_darcs" "{arch}" ".gvfs"))
-
-(cl-defun helm-walk-directory (directory &key (path 'basename)
- (directories t)
- match skip-subdirs)
- "Walk through DIRECTORY tree.
-Argument PATH can be one of basename, relative, full, or a function
-called on file name, default to basename.
-Argument DIRECTORIES when non--nil (default) return also directories names,
-otherwise skip directories names.
-Argument MATCH can be a predicate or a regexp.
-Argument SKIP-SUBDIRS when non--nil will skip `helm-walk-ignore-directories'
-unless it is given as a list of directories, in this case this list will be used
-instead of `helm-walk-ignore-directories'."
- (let* ((result '())
- (fn (cl-case path
- (basename 'file-name-nondirectory)
- (relative 'file-relative-name)
- (full 'identity)
- (t path))))
- (cl-labels ((ls-rec (dir)
- (unless (and skip-subdirs
- (member (helm-basename dir)
- (if (listp skip-subdirs)
- skip-subdirs
- helm-walk-ignore-directories)))
- (cl-loop with ls = (sort (file-name-all-completions "" dir)
- 'string-lessp)
- for f in ls
- ;; Use `directory-file-name' to remove the final slash.
- ;; Needed to avoid infloop on symlinks symlinking
- ;; a directory inside it [1].
- for file = (directory-file-name
- (expand-file-name f dir))
- unless (member f '("./" "../"))
- ;; A directory.
- if (char-equal (aref f (1- (length f))) ?/)
- do (progn (when directories
- (push (funcall fn file) result))
- ;; Don't recurse in symlinks.
- ;; `file-symlink-p' have to be called
- ;; on the directory with its final
- ;; slash removed [1].
- (and (not (file-symlink-p file))
- (ls-rec file)))
- else do
- (if match
- (and (if (functionp match)
- (funcall match f)
- (and (stringp match)
- (string-match match f)))
- (push (funcall fn file) result))
- (push (funcall fn file) result))))))
- (ls-rec directory)
- (nreverse result))))
-
-(defun helm-file-expand-wildcards (pattern &optional full)
- "Same as `file-expand-wildcards' but allow recursion.
-Recursion happen when PATTERN starts with two stars.
-Directories expansion is not supported."
- (let ((bn (helm-basename pattern)))
- (if (and helm-file-globstar
- (string-match "\\`\\*\\{2\\}\\(.*\\)" bn))
- (helm-walk-directory (helm-basedir pattern)
- :path (cl-case full
- (full 'full)
- (relative 'relative)
- ((basename nil) 'basename)
- (t 'full))
- :directories nil
- :match (wildcard-to-regexp bn)
- :skip-subdirs t)
- (file-expand-wildcards pattern full))))
-\f
-;;; helm internals
-;;
-(defun helm-set-pattern (pattern &optional noupdate)
- "Set minibuffer contents to PATTERN.
-if optional NOUPDATE is non-nil, helm buffer is not changed."
- (with-selected-window (or (active-minibuffer-window) (minibuffer-window))
- (delete-minibuffer-contents)
- (insert pattern))
- (when noupdate
- (setq helm-pattern pattern)))
-
-(defun helm-minibuffer-completion-contents ()
- "Return the user input in a minibuffer before point as a string.
-That is what completion commands operate on."
- (buffer-substring (field-beginning) (point)))
-
-(defmacro with-helm-buffer (&rest body)
- "Eval BODY inside `helm-buffer'."
- (declare (indent 0) (debug t))
- `(with-current-buffer (helm-buffer-get)
- ,@body))
-
-(defmacro with-helm-current-buffer (&rest body)
- "Eval BODY inside `helm-current-buffer'."
- (declare (indent 0) (debug t))
- `(with-current-buffer (or (and (buffer-live-p helm-current-buffer)
- helm-current-buffer)
- (setq helm-current-buffer
- (current-buffer)))
- ,@body))
-
-(defun helm-buffer-get ()
- "Return `helm-action-buffer' if shown otherwise `helm-buffer'."
- (if (helm-action-window)
- helm-action-buffer
- helm-buffer))
-
-(defun helm-window ()
- "Window of `helm-buffer'."
- (get-buffer-window (helm-buffer-get) 0))
-
-(defun helm-action-window ()
- "Window of `helm-action-buffer'."
- (get-buffer-window helm-action-buffer 'visible))
-
-(defmacro with-helm-window (&rest body)
- "Be sure BODY is excuted in the helm window."
- (declare (indent 0) (debug t))
- `(with-selected-window (helm-window)
- ,@body))
-
-\f
-;; Yank text at point.
-;;
-;;
-(defun helm-yank-text-at-point ()
- "Yank text at point in `helm-current-buffer' into minibuffer."
- (interactive)
- (with-helm-current-buffer
- (let ((fwd-fn (or helm-yank-text-at-point-function #'forward-word)))
- ;; Start to initial point if C-w have never been hit.
- (unless helm-yank-point (setq helm-yank-point (point)))
- (save-excursion
- (goto-char helm-yank-point)
- (funcall fwd-fn 1)
- (helm-set-pattern
- (concat
- helm-pattern (replace-regexp-in-string
- "\\`\n" ""
- (buffer-substring-no-properties
- helm-yank-point (point)))))
- (setq helm-yank-point (point))))))
-
-(defun helm-reset-yank-point ()
- (setq helm-yank-point nil))
-
-(add-hook 'helm-cleanup-hook 'helm-reset-yank-point)
-(add-hook 'helm-after-initialize-hook 'helm-reset-yank-point)
-
-;;; Ansi
-;;
-;;
-(defvar helm--ansi-color-regexp
- "\033\\[\\(K\\|[0-9;]*m\\)")
-(defvar helm--ansi-color-drop-regexp
- "\033\\[\\([ABCDsuK]\\|[12][JK]\\|=[0-9]+[hI]\\|[0-9;]*[Hf]\\)")
-(defun helm--ansi-color-apply (string)
- "A version of `ansi-color-apply' immune to upstream changes.
-
-Similar to the emacs-24.5 version without support to `ansi-color-context'
-which is buggy in emacs.
-
-Modify also `ansi-color-regexp' by using own variable `helm--ansi-color-regexp'
-that match whole STRING.
-
-This is needed to provide compatibility for both emacs-25 and emacs-24.5
-as emacs-25 version of `ansi-color-apply' is partially broken."
- (let ((start 0)
- codes end escape-sequence
- result colorized-substring)
- ;; Find the next escape sequence.
- (while (setq end (string-match helm--ansi-color-regexp string start))
- (setq escape-sequence (match-string 1 string))
- ;; Colorize the old block from start to end using old face.
- (when codes
- (put-text-property
- start end 'font-lock-face (ansi-color--find-face codes) string))
- (setq colorized-substring (substring string start end)
- start (match-end 0))
- ;; Eliminate unrecognized ANSI sequences.
- (while (string-match helm--ansi-color-drop-regexp colorized-substring)
- (setq colorized-substring
- (replace-match "" nil nil colorized-substring)))
- (push colorized-substring result)
- ;; Create new face, by applying escape sequence parameters.
- (setq codes (ansi-color-apply-sequence escape-sequence codes)))
- ;; If the rest of the string should have a face, put it there.
- (when codes
- (put-text-property
- start (length string)
- 'font-lock-face (ansi-color--find-face codes) string))
- ;; Save the remainder of the string to the result.
- (if (string-match "\033" string start)
- (push (substring string start (match-beginning 0)) result)
- (push (substring string start) result))
- (apply 'concat (nreverse result))))
-
-(provide 'helm-lib)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-lib ends here
+++ /dev/null
-;;; helm-multi-match.el --- Multiple regexp matching methods for helm -*- lexical-binding: t -*-
-
-;; Original Author: rubikitch
-
-;; Copyright (C) 2008 ~ 2011 rubikitch
-;; Copyright (C) 2011 ~ 2015 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; Author: Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-;; URL: http://github.com/emacs-helm/helm
-
-;; 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/>.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'helm-lib)
-
-\f
-(defgroup helm-multi-match nil
- "Helm multi match."
- :group 'helm)
-
-(defcustom helm-mm-matching-method 'multi3
- "Matching method for helm match plugin.
-You can set here different methods to match candidates in helm.
-Here are the possible value of this symbol and their meaning:
-- multi1: Respect order, prefix of pattern must match.
-- multi2: Same but with partial match.
-- multi3: The best, multiple regexp match, allow negation.
-- multi3p: Same but prefix must match.
-
-Default is multi3, you should keep this for a better experience.
-
-Note that multi1 and multi3p are incompatible with fuzzy matching
-in file completion and by the way fuzzy matching will be disabled there
-when these options are used."
- :type '(radio :tag "Matching methods for helm"
- (const :tag "Multiple regexp 1 ordered with prefix match" multi1)
- (const :tag "Multiple regexp 2 ordered with partial match" multi2)
- (const :tag "Multiple regexp 3 matching no order, partial, best." multi3)
- (const :tag "Multiple regexp 3p matching with prefix match" multi3p))
- :group 'helm-multi-match)
-
-\f
-;; Internal
-(defconst helm-mm-default-match-functions
- '(helm-mm-exact-match helm-mm-match))
-(defconst helm-mm-default-search-functions
- '(helm-mm-exact-search helm-mm-search))
-
-\f
-;;; Build regexps
-;;
-;;
-(defvar helm-mm-space-regexp "[\\ ] "
- "Regexp to represent space itself in multiple regexp match.")
-
-(defun helm-mm-split-pattern (pattern)
- "Split PATTERN if it contain spaces and return resulting list.
-If spaces in PATTERN are escaped, don't split at this place.
-i.e \"foo bar\"=> (\"foo\" \"bar\")
-but \"foo\ bar\"=> (\"foobar\")."
- (if (string= pattern "")
- '("")
- (cl-loop for s in (split-string
- (replace-regexp-in-string helm-mm-space-regexp
- "\000\000" pattern)
- " " t)
- collect (replace-regexp-in-string "\000\000" " " s))))
-
-(defun helm-mm-1-make-regexp (pattern)
- "Replace spaces in PATTERN with \"\.*\"."
- (mapconcat 'identity (helm-mm-split-pattern pattern) ".*"))
-
-\f
-;;; Exact match.
-;;
-;;
-;; Internal.
-(defvar helm-mm-exact-pattern-str nil)
-(defvar helm-mm-exact-pattern-real nil)
-
-(defun helm-mm-exact-get-pattern (pattern)
- (unless (equal pattern helm-mm-exact-pattern-str)
- (setq helm-mm-exact-pattern-str pattern
- helm-mm-exact-pattern-real (concat "\n" pattern "\n")))
- helm-mm-exact-pattern-real)
-
-
-(cl-defun helm-mm-exact-match (str &optional (pattern helm-pattern))
- (if case-fold-search
- (progn
- (setq str (downcase str)
- pattern (downcase pattern))
- (string= str pattern))
- (string= str pattern)))
-
-(defun helm-mm-exact-search (pattern &rest _ignore)
- (and (search-forward (helm-mm-exact-get-pattern pattern) nil t)
- (forward-line -1)))
-
-\f
-;;; Prefix match
-;;
-;;
-;; Internal
-(defvar helm-mm-prefix-pattern-str nil)
-(defvar helm-mm-prefix-pattern-real nil)
-
-(defun helm-mm-prefix-get-pattern (pattern)
- (unless (equal pattern helm-mm-prefix-pattern-str)
- (setq helm-mm-prefix-pattern-str pattern
- helm-mm-prefix-pattern-real (concat "\n" pattern)))
- helm-mm-prefix-pattern-real)
-
-(defun helm-mm-prefix-match (str &optional pattern)
- ;; In filename completion basename and basedir may be
- ;; quoted, unquote them for string comparison (Issue #1283).
- (setq pattern (replace-regexp-in-string
- "\\\\" "" (or pattern helm-pattern)))
- (let ((len (length pattern)))
- (and (<= len (length str))
- (string= (substring str 0 len) pattern ))))
-
-(defun helm-mm-prefix-search (pattern &rest _ignore)
- (search-forward (helm-mm-prefix-get-pattern pattern) nil t))
-
-\f
-;;; Multiple regexp patterns 1 (order is preserved / prefix).
-;;
-;;
-;; Internal
-(defvar helm-mm-1-pattern-str nil)
-(defvar helm-mm-1-pattern-real nil)
-
-(defun helm-mm-1-get-pattern (pattern)
- (unless (equal pattern helm-mm-1-pattern-str)
- (setq helm-mm-1-pattern-str pattern
- helm-mm-1-pattern-real
- (concat "^" (helm-mm-1-make-regexp pattern))))
- helm-mm-1-pattern-real)
-
-(cl-defun helm-mm-1-match (str &optional (pattern helm-pattern))
- (string-match (helm-mm-1-get-pattern pattern) str))
-
-(defun helm-mm-1-search (pattern &rest _ignore)
- (re-search-forward (helm-mm-1-get-pattern pattern) nil t))
-
-\f
-;;; Multiple regexp patterns 2 (order is preserved / partial).
-;;
-;;
-;; Internal
-(defvar helm-mm-2-pattern-str nil)
-(defvar helm-mm-2-pattern-real nil)
-
-(defun helm-mm-2-get-pattern (pattern)
- (unless (equal pattern helm-mm-2-pattern-str)
- (setq helm-mm-2-pattern-str pattern
- helm-mm-2-pattern-real
- (concat "^.*" (helm-mm-1-make-regexp pattern))))
- helm-mm-2-pattern-real)
-
-(cl-defun helm-mm-2-match (str &optional (pattern helm-pattern))
- (string-match (helm-mm-2-get-pattern pattern) str))
-
-(defun helm-mm-2-search (pattern &rest _ignore)
- (re-search-forward (helm-mm-2-get-pattern pattern) nil t))
-
-\f
-;;; Multiple regexp patterns 3 (permutation).
-;;
-;;
-;; Internal
-(defvar helm-mm-3-pattern-str nil)
-(defvar helm-mm-3-pattern-list nil)
-
-(defun helm-mm-3-get-patterns (pattern)
- "Return `helm-mm-3-pattern-list', a list of predicate/regexp cons cells.
-e.g ((identity . \"foo\") (identity . \"bar\")).
-This is done only if `helm-mm-3-pattern-str' is same as PATTERN."
- (unless (equal pattern helm-mm-3-pattern-str)
- (setq helm-mm-3-pattern-str pattern
- helm-mm-3-pattern-list
- (helm-mm-3-get-patterns-internal pattern)))
- helm-mm-3-pattern-list)
-
-(defun helm-mm-3-get-patterns-internal (pattern)
- "Return a list of predicate/regexp cons cells.
-e.g ((identity . \"foo\") (identity . \"bar\"))."
- (unless (string= pattern "")
- (cl-loop for pat in (helm-mm-split-pattern pattern)
- collect (if (string= "!" (substring pat 0 1))
- (cons 'not (substring pat 1))
- (cons 'identity pat)))))
-
-(cl-defun helm-mm-3-match (str &optional (pattern helm-pattern))
- "Check if PATTERN match STR.
-When PATTERN contain a space, it is splitted and matching is done
-with the several resulting regexps against STR.
-e.g \"bar foo\" will match \"foobar\" and \"barfoo\".
-Argument PATTERN, a string, is transformed in a list of
-cons cell with `helm-mm-3-get-patterns' if it contain a space.
-e.g \"foo bar\"=>((identity . \"foo\") (identity . \"bar\")).
-Then each predicate of cons cell(s) is called with regexp of same
-cons cell against STR (a candidate).
-i.e (identity (string-match \"foo\" \"foo bar\")) => t."
- (let ((pat (helm-mm-3-get-patterns pattern)))
- (cl-loop for (predicate . regexp) in pat
- always (funcall predicate
- (condition-case _err
- ;; FIXME: Probably do nothing when
- ;; using fuzzy leaving the job
- ;; to the fuzzy fn.
- (string-match regexp str)
- (invalid-regexp nil))))))
-
-(defun helm-mm-3-search-base (pattern searchfn1 searchfn2)
- "Try to find PATTERN in `helm-buffer' with SEARCHFN1 and SEARCHFN2.
-This is the search function for `candidates-in-buffer' enabled sources.
-Use the same method as `helm-mm-3-match' except it search in buffer
-instead of matching on a string.
-i.e (identity (re-search-forward \"foo\" (point-at-eol) t)) => t."
- (cl-loop with pat = (if (stringp pattern)
- (helm-mm-3-get-patterns pattern)
- pattern)
- when (eq (caar pat) 'not) return
- ;; Pass the job to `helm-search-match-part'.
- (prog1 (list (point-at-bol) (point-at-eol))
- (forward-line 1))
- while (condition-case _err
- (funcall searchfn1 (or (cdar pat) "") nil t)
- (invalid-regexp nil))
- for bol = (point-at-bol)
- for eol = (point-at-eol)
- if (cl-loop for (pred . str) in (cdr pat) always
- (progn (goto-char bol)
- (funcall pred (condition-case _err
- (funcall searchfn2 str eol t)
- (invalid-regexp nil)))))
- do (goto-char eol) and return t
- else do (goto-char eol)
- finally return nil))
-
-(defun helm-mm-3-search (pattern &rest _ignore)
- (when (stringp pattern)
- (setq pattern (helm-mm-3-get-patterns pattern)))
- (helm-mm-3-search-base
- pattern 're-search-forward 're-search-forward))
-\f
-;;; mp-3 with migemo
-;;
-;;
-(defvar helm-mm--previous-migemo-info nil
- "[Internal] Cache previous migemo query.")
-(make-local-variable 'helm-mm--previous-migemo-info)
-
-(declare-function migemo-get-pattern "ext:migemo.el")
-(declare-function migemo-search-pattern-get "ext:migemo.el")
-
-(define-minor-mode helm-migemo-mode
- "Enable migemo in helm.
-It will be available in the sources handling it,
-i.e the sources which have the slot :migemo with non--nil value."
- :lighter " Hmio"
- :group 'helm
- :global t
- (cl-assert (featurep 'migemo)
- nil "No feature called migemo found, install migemo.el."))
-
-(defun helm-mm-migemo-get-pattern (pattern)
- (let ((regex (migemo-get-pattern pattern)))
- (if (ignore-errors (string-match regex "") t)
- (concat regex "\\|" pattern) pattern)))
-
-(defun helm-mm-migemo-search-pattern-get (pattern)
- (let ((regex (migemo-search-pattern-get pattern)))
- (if (ignore-errors (string-match regex "") t)
- (concat regex "\\|" pattern) pattern)))
-
-(defun helm-mm-migemo-string-match (pattern str)
- "Migemo version of `string-match'."
- (unless (assoc pattern helm-mm--previous-migemo-info)
- (with-helm-buffer
- (setq helm-mm--previous-migemo-info
- (push (cons pattern (helm-mm-migemo-get-pattern pattern))
- helm-mm--previous-migemo-info))))
- (string-match (assoc-default pattern helm-mm--previous-migemo-info) str))
-
-(cl-defun helm-mm-3-migemo-match (str &optional (pattern helm-pattern))
- (and helm-migemo-mode
- (cl-loop for (pred . re) in (helm-mm-3-get-patterns pattern)
- always (funcall pred (helm-mm-migemo-string-match re str)))))
-
-(defun helm-mm-migemo-forward (word &optional bound noerror count)
- (with-helm-buffer
- (unless (assoc word helm-mm--previous-migemo-info)
- (setq helm-mm--previous-migemo-info
- (push (cons word (if (delq 'ascii (find-charset-string word))
- word
- (helm-mm-migemo-search-pattern-get word)))
- helm-mm--previous-migemo-info))))
- (re-search-forward
- (assoc-default word helm-mm--previous-migemo-info) bound noerror count))
-
-(defun helm-mm-3-migemo-search (pattern &rest _ignore)
- (and helm-migemo-mode
- (helm-mm-3-search-base
- pattern 'helm-mm-migemo-forward 'helm-mm-migemo-forward)))
-
-\f
-;;; mp-3p- (multiple regexp pattern 3 with prefix search)
-;;
-;;
-(defun helm-mm-3p-match (str &optional pattern)
- "Check if PATTERN match STR.
-Same as `helm-mm-3-match' but more strict, matching against prefix also.
-e.g \"bar foo\" will match \"barfoo\" but not \"foobar\" contrarily to
-`helm-mm-3-match'."
- (let* ((pat (helm-mm-3-get-patterns (or pattern helm-pattern)))
- (first (car pat)))
- (and (funcall (car first) (helm-mm-prefix-match str (cdr first)))
- (cl-loop for (predicate . regexp) in (cdr pat)
- always (funcall predicate (string-match regexp str))))))
-
-(defun helm-mm-3p-search (pattern &rest _ignore)
- (when (stringp pattern)
- (setq pattern (helm-mm-3-get-patterns pattern)))
- (helm-mm-3-search-base
- pattern 'helm-mm-prefix-search 're-search-forward))
-
-\f
-;;; Generic multi-match/search functions
-;;
-;;
-(cl-defun helm-mm-match (str &optional (pattern helm-pattern))
- (let ((fun (cl-ecase helm-mm-matching-method
- (multi1 #'helm-mm-1-match)
- (multi2 #'helm-mm-2-match)
- (multi3 #'helm-mm-3-match)
- (multi3p #'helm-mm-3p-match))))
- (funcall fun str pattern)))
-
-(defun helm-mm-search (pattern &rest _ignore)
- (let ((fun (cl-ecase helm-mm-matching-method
- (multi1 #'helm-mm-1-search)
- (multi2 #'helm-mm-2-search)
- (multi3 #'helm-mm-3-search)
- (multi3p #'helm-mm-3p-search))))
- (funcall fun pattern)))
-
-
-(provide 'helm-multi-match)
-
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-multi-match.el ends here
+++ /dev/null
-;;; helm-source.el --- Helm source creation. -*- lexical-binding: t -*-
-
-;; Copyright (C) 2015 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; Author: Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-;; URL: http://github.com/emacs-helm/helm
-
-;; 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/>.
-
-;;; Commentary:
-
-;; Interface to create helm sources easily.
-;; Actually the eieo objects are transformed in alist for compatibility.
-;; In the future this package should allow creating source as eieo objects
-;; without conversion to alist, teaching helm to read such a structure.
-;; The compatibility with alists would be kept.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'eieio)
-(require 'helm-lib)
-
-(defvar helm-fuzzy-sort-fn)
-(defvar helm-fuzzy-match-fn)
-(defvar helm-fuzzy-search-fn)
-
-(declare-function helm-init-candidates-in-buffer "helm.el")
-(declare-function helm-interpret-value "helm.el")
-(declare-function helm-fuzzy-highlight-matches "helm.el")
-
-\f
-(defgeneric helm--setup-source (source)
- "Prepare slots and handle slot errors before creating a helm source.")
-
-(defgeneric helm-setup-user-source (source)
- "Allow users modifying slots in SOURCE just before creation.")
-
-\f
-;;; Classes for sources
-;;
-;;
-(defclass helm-source ()
- ((name
- :initarg :name
- :initform nil
- :custom string
- :documentation
- " The name of the source.
- A string which is also the heading which appears
- above the list of matches from the source. Must be unique.")
-
- (header-name
- :initarg :header-name
- :initform nil
- :custom function
- :documentation
- " A function returning the display string of the header.
- Its argument is the name of the source. This attribute is useful to
- add an additional information with the source name.
- It doesn't modify the name of the source.")
-
- (init
- :initarg :init
- :initform nil
- :custom function
- :documentation
- " Function called with no parameters when helm is started.
- It is useful for collecting current state information which can be
- used to create the list of candidates later.
- Initialization of `candidates-in-buffer' is done here
- with `helm-init-candidates-in-buffer'.")
-
- (candidates
- :initarg :candidates
- :initform nil
- :custom (choice function list)
- :documentation
- " Specifies how to retrieve candidates from the source.
- It can either be a variable name, a function called with no parameters
- or the actual list of candidates.
-
- The list must be a list whose members are strings, symbols
- or (DISPLAY . REAL) pairs.
-
- In case of (DISPLAY . REAL) pairs, the DISPLAY string is shown
- in the Helm buffer, but the REAL one is used as action
- argument when the candidate is selected. This allows a more
- readable presentation for candidates which would otherwise be,
- for example, too long or have a common part shared with other
- candidates which can be safely replaced with an abbreviated
- string for display purposes.
-
- Note that if the (DISPLAY . REAL) form is used then pattern
- matching is done on the displayed string, not on the real
- value.")
-
- (update
- :initarg :update
- :initform nil
- :custom function
- :documentation
- " Function called with no parameters at before \"init\" function
- when `helm-force-update' is called.")
-
- (cleanup
- :initarg :cleanup
- :initform nil
- :custom function
- :documentation
- " Function called with no parameters when *helm* buffer is
- closed. It is useful for killing unneeded candidates buffer.
-
- Note that the function is executed BEFORE performing action.")
-
- (delayed
- :initarg :delayed
- :initform nil
- :custom (choice null integer)
- :documentation
- " Candidates from the source are shown only if the user stops
- typing and is idle for `helm-idle-delay' seconds.
- If a value is given to delayed attr, this value is used instead only
- if it is > to `helm-idle-delay'.")
-
- (keymap
- :initarg :keymap
- :initform nil
- :custom sexp
- :documentation
- " Specific keymap for this source.
- It is useful to have a keymap per source when using more than
- one source. Otherwise, a keymap can be set per command with
- `helm' argument KEYMAP. NOTE: when a source have `helm-map' as
- keymap attr, the global value of `helm-map' will override the
- actual local one.")
-
- (action
- :initarg :action
- :initform 'identity
- :custom (alist :key-type string
- :value-type function)
- :documentation
- " An alist of (DISPLAY . FUNCTION) pairs, a variable name or a function.
- FUNCTION is called with one parameter: the selected candidate.
-
- An action other than the default can be chosen from this list
- of actions for the currently selected candidate (by default
- with TAB). The DISPLAY string is shown in the completions
- buffer and the FUNCTION is invoked when an action is
- selected. The first action of the list is the default.
-
- You should use `helm-make-actions' to build this alist easily.")
-
- (persistent-action
- :initarg :persistent-action
- :initform nil
- :custom function
- :documentation
- " Can be a either a Function called with one parameter (the
- selected candidate) or a cons cell where first element is this
- same function and second element a symbol (e.g never-split)
- that inform `helm-execute-persistent-action'to not split his
- window to execute this persistent action.")
-
- (persistent-help
- :initarg :persistent-help
- :initform nil
- :custom string
- :documentation
- " A string to explain persistent-action of this source. It also
- accepts a function or a variable name.
- It will be displayed in `header-line'.
- Have no effect when `helm-echo-input-in-header-line' is non--nil.")
-
- (help-message
- :initarg :help-message
- :initform nil
- :custom (choice string function)
- :documentation
- " Help message for this source.
- If not present, `helm-help-message' value will be used.")
-
- (multiline
- :initarg :multiline
- :initform nil
- :custom boolean
- :documentation
- " Enable to selection multiline candidates.")
-
- (requires-pattern
- :initarg :requires-pattern
- :initform nil
- :custom integer
- :documentation
- " If present matches from the source are shown only if the
- pattern is not empty. Optionally, it can have an integer
- parameter specifying the required length of input which is
- useful in case of sources with lots of candidates.")
-
- (candidate-transformer
- :initarg :candidate-transformer
- :initform nil
- :custom (choice function list)
- :documentation
- " It's a function or a list of functions called with one argument
- when the completion list from the source is built. The argument
- is the list of candidates retrieved from the source. The
- function should return a transformed list of candidates which
- will be used for the actual completion. If it is a list of
- functions, it calls each function sequentially.
-
- This can be used to transform or remove items from the list of
- candidates.
-
- Note that `candidates' is run already, so the given transformer
- function should also be able to handle candidates with (DISPLAY
- . REAL) format.")
-
- (filtered-candidate-transformer
- :initarg :filtered-candidate-transformer
- :initform nil
- :custom (choice function list)
- :documentation
- " It has the same format as `candidate-transformer', except the
- function is called with two parameters: the candidate list and
- the source.
-
- This transformer is run on the candidate list which is already
- filtered by the current pattern. While `candidate-transformer'
- is run only once, it is run every time the input pattern is
- changed.
-
- It can be used to transform the candidate list dynamically, for
- example, based on the current pattern.
-
- In some cases it may also be more efficent to perform candidate
- transformation here, instead of with `candidate-transformer'
- even if this transformation is done every time the pattern is
- changed. For example, if a candidate set is very large then
- `candidate-transformer' transforms every candidate while only
- some of them will actually be displayed due to the limit
- imposed by `helm-candidate-number-limit'.
-
- Note that `candidates' and `candidate-transformer' is run
- already, so the given transformer function should also be able
- to handle candidates with (DISPLAY . REAL) format.")
-
- (filter-one-by-one
- :initarg :filter-one-by-one
- :initform nil
- :custom (choice function list)
- :documentation
- " A transformer function that treat candidates one by one.
- It is called with one arg the candidate.
- It is faster than `filtered-candidate-transformer' or
- `candidates-transformer', but should be used only in sources
- that recompute constantly their candidates, e.g `helm-source-find-files'.
- Filtering happen early and candidates are treated
- one by one instead of re-looping on the whole list.
- If used with `filtered-candidate-transformer' or `candidates-transformer'
- these functions should treat the candidates transformed by the
- `filter-one-by-one' function in consequence.")
-
- (display-to-real
- :initarg :display-to-real
- :initform nil
- :custom function
- :documentation
- " Function called with one parameter; the selected candidate.
-
- The function transforms the selected candidate, and the result
- is passed to the action function. The display-to-real
- attribute provides another way to pass to action other string than
- the one shown in Helm buffer.
-
- Traditionally, it is possible to make candidates,
- candidate-transformer or filtered-candidate-transformer
- function return a list with (DISPLAY . REAL) pairs. But if REAL
- can be generated from DISPLAY, display-to-real is more
- convenient and faster.
-
- NOTE: This is deprecated and you have better time using `filter-one-by-one'.")
-
- (real-to-display
- :initarg :real-to-display
- :initform nil
- :custom function
- :documentation
- " Function called with one parameter; the selected candidate.
- The real value of candidates will be shown in display.
- See `display-to-real'.")
-
- (action-transformer
- :initarg :action-transformer
- :initform nil
- :custom (choice function list)
- :documentation
- " It's a function or a list of functions called with two
- arguments when the action list from the source is
- assembled. The first argument is the list of actions, the
- second is the current selection. If it is a list of functions,
- it calls each function sequentially.
-
- The function should return a transformed action list.
-
- This can be used to customize the list of actions based on the
- currently selected candidate.")
-
- (pattern-transformer
- :initarg :pattern-transformer
- :initform nil
- :custom (choice function list)
- :documentation
- " It's a function or a list of functions called with one argument
- before computing matches. Its argument is `helm-pattern'.
- Functions should return transformed `helm-pattern'.
-
- It is useful to change interpretation of `helm-pattern'.")
-
- (candidate-number-limit
- :initarg :candidate-number-limit
- :initform nil
- :custom integer
- :documentation
- " Override `helm-candidate-number-limit' only for this source.")
-
- (volatile
- :initarg :volatile
- :initform nil
- :custom boolean
- :documentation
- " Indicates the source assembles the candidate list dynamically,
- so it shouldn't be cached within a single Helm
- invocation. It is only applicable to synchronous sources,
- because asynchronous sources are not cached.")
-
- (match
- :initarg :match
- :initform nil
- :custom (choice function list)
- :documentation
- " List of functions called with one parameter: a candidate. The
- function should return non-nil if the candidate matches the
- current pattern (see variable `helm-pattern').
-
- When using `candidates-in-buffer' its default value is `identity' and
- don't have to be changed, use the `search' slot instead.
-
- This attribute allows the source to override the default
- pattern matching based on `string-match'. It can be used, for
- example, to implement a source for file names and do the
- pattern matching on the basename of files, since it's more
- likely one is typing part of the basename when searching for a
- file, instead of some string anywhere else in its path.
-
- If the list contains more than one function then the list of
- matching candidates from the source is constructed by appending
- the results after invoking the first function on all the
- potential candidates, then the next function, and so on. The
- matching candidates supplied by the first function appear first
- in the list of results and then results from the other
- functions, respectively.
-
- This attribute has no effect for asynchronous sources (see
- attribute `candidates'), since they perform pattern matching
- themselves.
-
- Note that FUZZY-MATCH slot will overhide value of this slot.")
-
- (fuzzy-match
- :initarg :fuzzy-match
- :initform nil
- :custom boolean
- :documentation
- " Enable fuzzy matching in this source.
- This will overwrite settings in MATCH slot, and for
- sources built with child class `helm-source-in-buffer' the SEARCH slot.
- This is an easy way of enabling fuzzy matching, but you can use the MATCH
- or SEARCH slots yourself if you want something more elaborated, mixing
- different type of match (See `helm-source-buffers' class for example).")
-
- (nomark
- :initarg :nomark
- :initform nil
- :custom boolean
- :documentation
- " Don't allow marking candidates when this attribute is present.")
-
- (nohighlight
- :initarg :nohighlight
- :initform nil
- :custom boolean
- :documentation
- " Disable highlighting matches in this source.
- This will disable generic highlighting of matches,
- but some specialized highlighting can be done from elsewhere,
- i.e from `filtered-candidate-transformer' or `filter-one-by-one' slots.
- So use this to either disable completely highlighting in your source,
- or to disable highlighting and use a specialized highlighting matches
- function for this source.
- Remember that this function should run AFTER all filter functions if those
- filter functions are modifying face properties, though it is possible to
- avoid this by using new `add-face-text-property' in your filter functions.")
-
- (allow-dups
- :initarg :allow-dups
- :initform nil
- :custom boolean
- :documentation
- " Allow helm collecting duplicates candidates.")
-
- (history
- :initarg :history
- :initform nil
- :custom symbol
- :documentation
- " Allow passing history variable to helm from source.
- It should be a quoted symbol.")
-
- (coerce
- :initarg :coerce
- :initform nil
- :custom function
- :documentation
- " It's a function called with one argument: the selected candidate.
- This function is intended for type convertion. In normal case,
- the selected candidate (string) is passed to action
- function. If coerce function is specified, it is called just
- before action function.
-
- Example: converting string to symbol
- (coerce . intern)")
-
- (mode-line
- :initarg :mode-line
- :initform nil
- :custom (choice string sexp)
- :documentation
- " Source local `helm-mode-line-string' (included in
- `mode-line-format'). It accepts also variable/function name.")
-
- (header-line
- :initarg :header-line
- :initform nil
- :custom (choice string function)
- :documentation
- " Source local `header-line-format'.
- Have no effect when `helm-echo-input-in-header-line' is non--nil.
- It accepts also variable/function name.")
-
- (resume
- :initarg :resume
- :initform nil
- :custom function
- :documentation
- " Function called with no parameters at end of initialization
- when `helm-resume' is started.
- If this function try to do something against `helm-buffer', \(e.g updating,
- searching etc...\) probably you should run it in a timer to ensure
- `helm-buffer' is ready.")
-
- (follow
- :initarg :follow
- :initform nil
- :custom integer
- :documentation
- " Enable `helm-follow-mode' for this source only.
- You must give it a value of 1 or -1, though giving a -1 value
- is surely not what you want, e.g: (follow . 1)
-
- See `helm-follow-mode' for more infos.")
-
- (follow-delay
- :initarg :follow-delay
- :initform nil
- :custom integer
- :documentation
- " `helm-follow-mode' will execute persistent-action after this delay.
- Otherwise value of `helm-follow-input-idle-delay' is used if non--nil,
- If none of these are found fallback to `helm-input-idle-delay'.")
-
- (dont-plug
- :initarg :dont-plug
- :initform '(helm-compile-source--persistent-help)
- :custom list
- :documentation
- " A list of compile functions plugin to ignore.")
-
- (matchplugin
- :initarg :matchplugin
- :initform t
- :custom boolean)
-
- (match-part
- :initarg :match-part
- :initform nil
- :custom function
- :documentation
- " Allow matching only one part of candidate.
- If source contain match-part attribute, match is computed only
- on part of candidate returned by the call of function provided
- by this attribute. The function should have one arg, candidate,
- and return only a specific part of candidate.")
-
- (before-init-hook
- :initarg :before-init-hook
- :initform nil
- :custom symbol
- :documentation
- " A local hook that run at beginning of initilization of this source.
- i.e Before the creation of `helm-buffer'.
-
- Should be a variable (defined with defvar).
- Can be also an anonymous function or a list of functions
- directly added to slot, this is not recommended though.")
-
- (after-init-hook
- :initarg :after-init-hook
- :initform nil
- :custom symbol
- :documentation
- " A local hook that run at end of initilization of this source.
- i.e After the creation of `helm-buffer'.
-
- Should be a variable.
- Can be also an anonymous function or a list of functions
- directly added to slot, this is not recommended though."))
-
- "Main interface to define helm sources."
- :abstract t)
-
-(defclass helm-source-sync (helm-source)
- ((candidates
- :initform '("ERROR: You must specify the `candidates' slot, either with a list or a function"))
-
- (dont-plug
- :initform '(helm-compile-source--multi-match
- helm-compile-source--persistent-help
- ;; Ensure this will not be plugged
- ;; if user have somewhere old helm-migemo.el.
- helm-compile-source--migemo))
-
- (migemo
- :initarg :migemo
- :initform nil
- :custom boolean
- :documentation
- " Enable migemo.
- When multimatch is disabled, you can give the symbol 'nomultimatch as value
- to force not using generic migemo matching function.
- In this case you have to provide your own migemo matching funtion
- that kick in when `helm-migemo-mode' is enabled.
- Otherwise it will be available for this source once `helm-migemo-mode'
- is enabled when non-nil.")
-
- (match-strict
- :initarg :match-strict
- :initform nil
- :custom function
- :documentation
- " When specifying a match function within a source and
- helm-multi-match is enabled, the result of all matching
- functions will be concatened, which in some cases is not what
- is wanted. When using `match-strict' only this or these
- functions will be used. You can specify those functions as a
- list of functions or a single symbol function.
-
- NOTE: This have the same effect as using :MATCHPLUGIN nil."))
-
- "Use this class to make helm sources using a list of candidates.
-This list should be given as a normal list, a variable handling a list
-or a function returning a list.
-Matching is done basically with `string-match' against each candidate.")
-
-(defclass helm-source-async (helm-source)
- ((candidates-process
- :initarg :candidates-process
- :initform nil
- :custom function
- :documentation
- " This attribute is used to define a process as candidate.
- The value must be a process.
-
- NOTE:
- When building the source at runtime you can give directly a process
- as value, otherwise wrap the process call into a function.
- The process buffer should be nil, otherwise, if you use
- `helm-buffer' give to the process a sentinel.")
-
- (matchplugin :initform nil)
- (dont-plug :initform '(helm-compile-source--multi-match
- helm-compile-source--persistent-help)))
-
- "Use this class to define a helm source calling an external process.
-The :candidates slot is not allowed even if described because this class
-inherit from `helm-source'.")
-
-(defclass helm-source-in-buffer (helm-source)
- ((init
- :initform 'helm-default-init-source-in-buffer-function)
-
- (data
- :initarg :data
- :initform nil
- :custom (choice list string)
- :documentation
- " A string or a list that will be used to feed the `helm-candidates-buffer'.
- This data will be passed in a function added to the init slot and
- the buffer will be build with `helm-init-candidates-in-buffer'.
- This is an easy and fast method to build a `candidates-in-buffer' source.")
-
- (dont-plug
- :initform '(helm-compile-source--candidates-in-buffer
- helm-compile-source--multi-match
- helm-compile-source--persistent-help
- helm-compile-source--migemo))
-
- (migemo
- :initarg :migemo
- :initform nil
- :custom boolean
- :documentation
- " Enable migemo.
- When multimatch is disabled, you can give the symbol 'nomultimatch as value
- to force not using generic migemo matching function.
- In this case you have to provide your own migemo matching funtion
- that kick in when `helm-migemo-mode' is enabled.
- Otherwise it will be available for this source once `helm-migemo-mode'
- is enabled when non-nil.")
-
- (candidates
- :initform 'helm-candidates-in-buffer)
-
- (volatile
- :initform t)
-
- (match
- :initform '(identity))
-
- (get-line
- :initarg :get-line
- :initform 'buffer-substring-no-properties
- :custom function
- :documentation
- " A function like `buffer-substring-no-properties' or `buffer-substring'.
- This function converts point of line-beginning and point of line-end,
- which represents a candidate computed by `helm-candidates-in-buffer'.
- By default, `helm-candidates-in-buffer' uses
- `buffer-substring-no-properties'.")
-
- (search
- :initarg :search
- :initform '(helm-candidates-in-buffer-search-default-fn)
- :custom (choice function list)
- :documentation
- " List of functions like `re-search-forward' or `search-forward'.
- Buffer search function used by `helm-candidates-in-buffer'.
- By default, `helm-candidates-in-buffer' uses `re-search-forward'.
- The function should take one arg PATTERN.
- If your search function needs to handle negation like matchplugin,
- this function should returns in such case a cons cell of two integers defining
- the beg and end positions to match in the line previously matched by
- `re-search-forward' or similar, and move point to next line
- (See how the `helm-mm-3-search-base' and `helm-fuzzy-search' functions are working).
-
- NOTE: FUZZY-MATCH slot will overhide value of this slot.")
-
- (search-strict
- :initarg :search-strict
- :initform nil
- :custom function
- :documentation
- " When specifying a search function within a source and
- helm-multi-match is enabled, the result of all searching
- functions will be concatened, which in some cases is not what
- is wanted. When using `search-strict' only this or these
- functions will be used. You can specify those functions as a
- list of functions or a single symbol function.
-
- NOTE: This have the same effect as using a nil value for
- :MATCHPLUGIN slot."))
-
- "Use this source to make helm sources storing candidates inside a buffer.
-Contrarily to `helm-source-sync' candidates are matched using a function
-like `re-search-forward', see below documentation of :search slot.")
-
-(defclass helm-source-dummy (helm-source)
- ((candidates
- :initform '("dummy"))
-
- (filtered-candidate-transformer
- :initform 'helm-dummy-candidate)
-
- (matchplugin
- :initform nil)
-
- (accept-empty
- :initarg :accept-empty
- :initform t
- :custom boolean
- :documentation
- " Allow exiting with an empty string.
- You should keep the default value.")
-
- (match
- :initform 'identity)
-
- (volatile
- :initform t)))
-
-(defclass helm-source-in-file (helm-source-in-buffer)
- ((init :initform (lambda ()
- (let ((file (helm-attr 'candidates-file)))
- (with-current-buffer (helm-candidate-buffer 'global)
- (insert-file-contents file)))))
- (candidates-file
- :initarg :candidates-file
- :initform nil
- :custom string
- :documentation "A filename."))
-
- "The contents of the file will be used as candidates in buffer.")
-
-\f
-;;; Error functions
-;;
-;;
-(defun helm-default-init-source-in-buffer-function ()
- (helm-init-candidates-in-buffer 'global
- '("ERROR: No buffer handling your data, use either the `init' slot or the `data' slot.")))
-
-\f
-;;; Internal Builder functions.
-;;
-;;
-(defun helm--create-source (object)
- "[INTERNAL] Build a helm source from OBJECT.
-Where OBJECT is an instance of an eieio class."
- (cl-loop for s in (object-slots object)
- for slot-val = (slot-value object s)
- when slot-val
- collect (cons s (unless (eq t slot-val) slot-val))))
-
-(defun helm-make-source (name class &rest args)
- "Build a `helm' source named NAME with ARGS for CLASS.
-Argument NAME is a string which define the source name, so no need to use
-the keyword :name in your source, NAME will be used instead.
-Argument CLASS is an eieio class object.
-Arguments ARGS are keyword value pairs as defined in CLASS."
- (declare (indent 2))
- (let ((source (apply #'make-instance class name args)))
- (set-slot-value source 'name name)
- (helm--setup-source source)
- (helm-setup-user-source source)
- (helm--create-source source)))
-
-(defun helm-make-type (class &rest args)
- (let ((source (apply #'make-instance class args)))
- (set-slot-value source 'name nil)
- (helm--setup-source source)
- (helm--create-source source)))
-
-(defvar helm-mm-default-search-functions)
-(defvar helm-mm-default-match-functions)
-
-(defun helm-source-mm-get-search-or-match-fns (source method)
- (let ((defmatch (helm-aif (slot-value source 'match)
- (helm-mklist it)))
- (defmatch-strict (helm-aif (and (eq method 'match)
- (slot-value source 'match-strict))
- (helm-mklist it)))
- (defsearch (helm-aif (and (eq method 'search)
- (slot-value source 'search))
- (helm-mklist it)))
- (defsearch-strict (helm-aif (and (eq method 'search-strict)
- (slot-value source 'search-strict))
- (helm-mklist it)))
- (migemo (slot-value source 'migemo)))
- (cl-case method
- (match (cond (defmatch-strict)
- (migemo
- (append helm-mm-default-match-functions
- defmatch '(helm-mm-3-migemo-match)))
- (defmatch
- (append helm-mm-default-match-functions defmatch))
- (t helm-mm-default-match-functions)))
- (search (cond (defsearch-strict)
- (migemo
- (append helm-mm-default-search-functions
- defsearch '(helm-mm-3-migemo-search)))
- (defsearch
- (append helm-mm-default-search-functions defsearch))
- (t helm-mm-default-search-functions))))))
-
-\f
-;;; Modifiers
-;;
-(cl-defun helm-source-add-action-to-source-if (name fn source predicate
- &optional (index 4))
- "Same as `helm-add-action-to-source-if' but for SOURCE defined as eieio object.
-You can use this inside a `helm--setup-source' method for a SOURCE defined as
-an eieio class."
- (let* ((actions (slot-value source 'action))
- (action-transformers (slot-value source 'action-transformer))
- (new-action (list (cons name fn)))
- (transformer `(lambda (actions candidate)
- (cond ((funcall (quote ,predicate) candidate)
- (helm-append-at-nth
- actions (quote ,new-action) ,index))
- (t actions)))))
- (if (functionp actions)
- (set-slot-value source 'action (list (cons "Default action" actions)))
- (set-slot-value source 'action (helm-interpret-value actions source)))
- (when (or (symbolp action-transformers) (functionp action-transformers))
- (setq action-transformers (list action-transformers)))
- (set-slot-value
- source
- 'action-transformer
- (delq nil (append (list transformer) action-transformers)))))
-
-\f
-;;; Methods to build sources.
-;;
-;;
-(defun helm-source--persistent-help-string (string source)
- (substitute-command-keys
- (concat "\\<helm-map>\\[helm-execute-persistent-action]: "
- (or (format "%s (keeping session)" string)
- (slot-value source 'header-line)))))
-
-(defun helm-source--header-line (source)
- (substitute-command-keys
- (concat "\\<helm-map>\\[helm-execute-persistent-action]: "
- (helm-aif (or (slot-value source 'persistent-action)
- (slot-value source 'action))
- (cond ((and (symbolp it)
- (functionp it)
- (eq it 'identity))
- "Do Nothing")
- ((and (symbolp it)
- (boundp it)
- (listp (symbol-value it))
- (stringp (caar (symbol-value it))))
- (caar (symbol-value it)))
- ((or (symbolp it) (functionp it))
- (helm-symbol-name it))
- ((listp it)
- (let ((action (car it)))
- ;; It comes from :action ("foo" . function).
- (if (stringp (car action))
- (car action)
- ;; It comes from :persistent-action
- ;; (function . 'nosplit) Fix Issue #788.
- (if (or (symbolp action)
- (functionp action))
- (helm-symbol-name action)))))
- (t ""))
- "")
- " (keeping session)")))
-
-(defmethod helm--setup-source :primary ((_source helm-source)))
-
-(defmethod helm--setup-source :before ((source helm-source))
- (helm-aif (slot-value source 'keymap)
- (and (symbolp it) (set-slot-value source 'keymap (symbol-value it))))
- (helm-aif (slot-value source 'persistent-help)
- (set-slot-value source 'header-line
- (helm-source--persistent-help-string it source))
- (set-slot-value source 'header-line (helm-source--header-line source)))
- (helm-aif (slot-value source 'candidate-number-limit)
- (and (symbolp it) (set-slot-value
- source 'candidate-number-limit (symbol-value it))))
- (when (and (slot-value source 'fuzzy-match) helm-fuzzy-sort-fn)
- (set-slot-value source 'filtered-candidate-transformer
- (helm-aif (slot-value source 'filtered-candidate-transformer)
- (append (helm-mklist it)
- (list helm-fuzzy-sort-fn))
- (list helm-fuzzy-sort-fn))))
- (unless (slot-value source 'nohighlight)
- (set-slot-value source 'filtered-candidate-transformer
- (helm-aif (slot-value source 'filtered-candidate-transformer)
- (append (helm-mklist it)
- (list #'helm-fuzzy-highlight-matches))
- (list #'helm-fuzzy-highlight-matches)))))
-
-(defmethod helm-setup-user-source ((_source helm-source)))
-
-(defmethod helm--setup-source ((source helm-source-sync))
- (when (slot-value source 'fuzzy-match)
- (helm-aif (slot-value source 'match)
- (set-slot-value source 'match (append (helm-mklist it)
- (list helm-fuzzy-match-fn)))
- (set-slot-value source 'match helm-fuzzy-match-fn)))
- (when (slot-value source 'matchplugin)
- (set-slot-value source 'match
- (helm-source-mm-get-search-or-match-fns source 'match)))
- (helm-aif (and (null (slot-value source 'matchplugin))
- (slot-value source 'migemo))
- (unless (eq it 'nomultimatch) ; Use own migemo fn.
- (set-slot-value source 'match
- (append (helm-mklist (slot-value source 'match))
- '(helm-mm-3-migemo-match))))))
-
-(defmethod helm--setup-source ((source helm-source-in-buffer))
- (let ((cur-init (slot-value source 'init)))
- (helm-aif (slot-value source 'data)
- (set-slot-value
- source
- 'init (delq
- nil
- (list
- (and (null (eq 'helm-default-init-source-in-buffer-function
- cur-init))
- cur-init)
- (lambda ()
- (helm-init-candidates-in-buffer
- 'global
- (if (functionp it) (funcall it) it))))))))
- (when (slot-value source 'fuzzy-match)
- (helm-aif (slot-value source 'search)
- (set-slot-value source 'search (append (helm-mklist it)
- (list helm-fuzzy-search-fn)))
- (set-slot-value source 'search (list helm-fuzzy-search-fn))))
- (when (slot-value source 'matchplugin)
- (set-slot-value
- source 'search (helm-source-mm-get-search-or-match-fns source 'search)))
- (helm-aif (and (null (slot-value source 'matchplugin))
- (slot-value source 'migemo))
- (unless (eq it 'nomultimatch)
- (set-slot-value source 'search
- (append (helm-mklist (slot-value source 'search))
- '(helm-mm-3-migemo-search)))))
- (let ((mtc (slot-value source 'match)))
- (cl-assert (or (equal '(identity) mtc)
- (eq 'identity mtc))
- nil "Invalid slot value for `match'")
- (cl-assert (eq (slot-value source 'volatile) t)
- nil "Invalid slot value for `volatile'")))
-
-(defmethod helm--setup-source ((source helm-source-async))
- (cl-assert (null (slot-value source 'candidates))
- nil "Incorrect use of `candidates' use `candidates-process' instead")
- (cl-assert (null (slot-value source 'matchplugin))
- nil "`matchplugin' not allowed in async sources."))
-
-(defmethod helm--setup-source ((source helm-source-dummy))
- (let ((mtc (slot-value source 'match)))
- (cl-assert (or (equal '(identity) mtc)
- (eq 'identity mtc))
- nil "Invalid slot value for `match'")
- (cl-assert (eq (slot-value source 'volatile) t)
- nil "Invalid slot value for `volatile'")
- (cl-assert (equal (slot-value source 'candidates) '("dummy"))
- nil "Invalid slot value for `candidates'")
- (cl-assert (eq (slot-value source 'accept-empty) t)
- nil "Invalid slot value for `accept-empty'")))
-
-\f
-;;; User functions
-;;
-;; Sources
-(defmacro helm-build-sync-source (name &rest args)
- "Build a synchronous helm source with name NAME.
-Args ARGS are keywords provided by `helm-source-sync'."
- (declare (indent 1))
- `(helm-make-source ,name 'helm-source-sync ,@args))
-
-(defmacro helm-build-async-source (name &rest args)
- "Build a asynchronous helm source with name NAME.
-Args ARGS are keywords provided by `helm-source-async'."
- (declare (indent 1))
- `(helm-make-source ,name 'helm-source-async ,@args))
-
-(defmacro helm-build-in-buffer-source (name &rest args)
- "Build a helm source with name NAME using `candidates-in-buffer' method.
-Args ARGS are keywords provided by `helm-source-in-buffer'."
- (declare (indent 1))
- `(helm-make-source ,name 'helm-source-in-buffer ,@args))
-
-(defmacro helm-build-dummy-source (name &rest args)
- "Build a helm source with name NAME using `dummy' method.
-Args ARGS are keywords provided by `helm-source-dummy'."
- (declare (indent 1))
- `(helm-make-source ,name 'helm-source-dummy ,@args))
-
-(defmacro helm-build-in-file-source (name file &rest args)
- "Build a helm source with NAME name using `candidates-in-files' method.
-Arg FILE is a filename, the contents of this file will be
-used as candidates in buffer.
-Args ARGS are keywords provided by `helm-source-in-file'."
- (declare (indent 1))
- `(helm-make-source ,name 'helm-source-in-file
- :candidates-file ,file ,@args))
-
-
-(provide 'helm-source)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-source ends here
+++ /dev/null
-;;; helm.el --- Emacs incremental and narrowing framework -*- lexical-binding: t -*-
-
-;; Copyright (C) 2007 Tamas Patrovics
-;; 2008 ~ 2011 rubikitch <rubikitchNOSPAMruby-lang.org>
-;; 2011 ~ 2015 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; This is a fork of anything.el wrote by Tamas Patrovics.
-
-;; Authors of anything.el: Tamas Patrovics
-;; rubikitch <rubikitchNOSPAMruby-lang.org>
-;; Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; Author: Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-;; URL: http://github.com/emacs-helm/helm
-
-;; 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/>.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'advice) ; Shutup byte compiler about ad-deactivate.
-(require 'helm-lib)
-(require 'helm-multi-match)
-(require 'helm-source)
-
-\f
-;;; Multi keys
-;;
-;;
-;;;###autoload
-(defun helm-define-multi-key (keymap key functions &optional delay)
- "In KEYMAP, define key sequence KEY for function list FUNCTIONS.
-Each function run sequentially each time the key KEY is pressed.
-If DELAY is specified switch back to initial function of FUNCTIONS list
-after DELAY seconds.
-The functions in FUNCTIONS list are functions with no args.
-e.g
- \(defun foo ()
- (message \"Run foo\"))
- \(defun bar ()
- (message \"Run bar\"))
- \(defun baz ()
- (message \"Run baz\"))
-
-\(helm-define-multi-key global-map \"<f5> q\" '(foo bar baz) 2)
-
-Each time \"<f5> q\" is pressed the next function is executed, if you wait
-More than 2 seconds, next hit will run again the first function and so on."
- (define-key keymap key (helm-make-multi-command functions delay)))
-
-;;;###autoload
-(defmacro helm-multi-key-defun (name docstring funs &optional delay)
- "Define NAME as a multi-key command running FUNS.
-After DELAY seconds the FUNS list is reinitialised.
-See `helm-define-multi-key'."
- (declare (indent 2))
- (setq docstring (if docstring (concat docstring "\n\n")
- "This is a helmish multi-key command."))
- `(defalias (quote ,name) (helm-make-multi-command ,funs ,delay) ,docstring))
-
-(defun helm-make-multi-command (functions &optional delay)
- "Return an anonymous multi-key command running FUNCTIONS.
-Run each function of FUNCTIONS list in turn when called within DELAY seconds."
- (declare (indent 1))
- (let ((funs functions)
- (iter (cl-gensym "helm-iter-key"))
- (timeout delay))
- (eval (list 'defvar iter nil))
- (lambda () (interactive) (helm-run-multi-key-command funs iter timeout))))
-
-(defun helm-run-multi-key-command (functions iterator delay)
- (let ((fn (lambda ()
- (cl-loop for count from 1 to (length functions)
- collect count)))
- next)
- (unless (and (symbol-value iterator)
- ;; Reset iterator when another key is pressed.
- (eq this-command real-last-command))
- (set iterator (helm-iter-list (funcall fn))))
- (setq next (helm-iter-next (symbol-value iterator)))
- (unless next
- (set iterator (helm-iter-list (funcall fn)))
- (setq next (helm-iter-next (symbol-value iterator))))
- (and next (symbol-value iterator) (call-interactively (nth (1- next) functions)))
- (when delay (run-with-idle-timer delay nil `(lambda ()
- (setq ,iterator nil))))))
-
-(helm-multi-key-defun helm-toggle-resplit-and-swap-windows
- "Multi key command to resplit and swap helm window.
-First call run `helm-toggle-resplit-window',
-second call within 0.5s run `helm-swap-windows'."
- '(helm-toggle-resplit-window helm-swap-windows) 1)
-(put 'helm-toggle-resplit-and-swap-windows 'helm-only t)
-
-;;;###autoload
-(defun helm-define-key-with-subkeys (map key subkey command
- &optional other-subkeys menu exit-fn)
- "Allow defining in MAP a KEY and SUBKEY to COMMAND.
-
-This allow typing KEY to call COMMAND the first time and
-type only SUBKEY on subsequent calls.
-
-Arg MAP is the keymap to use, SUBKEY is the initial short keybinding to
-call COMMAND.
-
-Arg OTHER-SUBKEYS is an alist specifying other short keybindings
-to use once started.
-e.g:
-
-\(helm-define-key-with-subkeys global-map
- \(kbd \"C-x v n\") ?n 'git-gutter:next-hunk '((?p . git-gutter:previous-hunk))\)
-
-
-In this example, `C-x v n' will run `git-gutter:next-hunk'
-subsequent hits on \"n\" will run this command again
-and subsequent hits on \"p\" will run `git-gutter:previous-hunk'.
-
-Arg MENU is a string to display in minibuffer
-to describe SUBKEY and OTHER-SUBKEYS.
-Arg EXIT-FN specify a function to run on exit.
-
-Any other keys pressed run their assigned command defined in MAP
-and exit the loop running EXIT-FN if specified.
-
-NOTE: SUBKEY and OTHER-SUBKEYS bindings support
-only char syntax actually (e.g ?n)
-so don't use strings, vectors or whatever to define them."
- (declare (indent 1))
- (define-key map key
- (lambda ()
- (interactive)
- (unwind-protect
- (progn
- (call-interactively command)
- (while (let ((input (read-key menu)) other kb com)
- (setq last-command-event input)
- (cond
- ((eq input subkey)
- (call-interactively command)
- t)
- ((setq other (assoc input other-subkeys))
- (call-interactively (cdr other))
- t)
- (t
- (setq kb (vector last-command-event))
- (setq com (lookup-key map kb))
- (if (commandp com)
- (call-interactively com)
- (setq unread-command-events
- (nconc (mapcar 'identity kb)
- unread-command-events)))
- nil)))))
- (and exit-fn (funcall exit-fn))))))
-
-\f
-;;; Keymap
-;;
-;;
-(defvar helm-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map minibuffer-local-map)
- (define-key map (kbd "<down>") 'helm-next-line)
- (define-key map (kbd "<up>") 'helm-previous-line)
- (define-key map (kbd "C-n") 'helm-next-line)
- (define-key map (kbd "C-p") 'helm-previous-line)
- (define-key map (kbd "<C-down>") 'helm-follow-action-forward)
- (define-key map (kbd "<C-up>") 'helm-follow-action-backward)
- (define-key map (kbd "<prior>") 'helm-previous-page)
- (define-key map (kbd "<next>") 'helm-next-page)
- (define-key map (kbd "M-v") 'helm-previous-page)
- (define-key map (kbd "C-v") 'helm-next-page)
- (define-key map (kbd "M-<") 'helm-beginning-of-buffer)
- (define-key map (kbd "M->") 'helm-end-of-buffer)
- (define-key map (kbd "C-g") 'helm-keyboard-quit)
- (define-key map (kbd "<right>") 'helm-next-source)
- (define-key map (kbd "<left>") 'helm-previous-source)
- (define-key map (kbd "<RET>") 'helm-maybe-exit-minibuffer)
- (define-key map (kbd "C-i") 'helm-select-action)
- (define-key map (kbd "C-z") 'helm-execute-persistent-action)
- (define-key map (kbd "C-j") 'helm-execute-persistent-action)
- (define-key map (kbd "C-o") 'helm-next-source)
- (define-key map (kbd "C-l") 'helm-recenter-top-bottom-other-window)
- (define-key map (kbd "M-C-l") 'helm-reposition-window-other-window)
- (define-key map (kbd "C-M-v") 'helm-scroll-other-window)
- (define-key map (kbd "M-<next>") 'helm-scroll-other-window)
- (define-key map (kbd "C-M-y") 'helm-scroll-other-window-down)
- (define-key map (kbd "C-M-S-v") 'helm-scroll-other-window-down)
- (define-key map (kbd "M-<prior>") 'helm-scroll-other-window-down)
- (define-key map (kbd "<C-M-down>") 'helm-scroll-other-window)
- (define-key map (kbd "<C-M-up>") 'helm-scroll-other-window-down)
- (define-key map (kbd "C-@") 'helm-toggle-visible-mark)
- (define-key map (kbd "C-SPC") 'helm-toggle-visible-mark)
- (define-key map (kbd "M-SPC") 'helm-toggle-visible-mark)
- (define-key map (kbd "M-[") nil)
- (define-key map (kbd "M-(") 'helm-prev-visible-mark)
- (define-key map (kbd "M-)") 'helm-next-visible-mark)
- (define-key map (kbd "C-k") 'helm-delete-minibuffer-contents)
- (define-key map (kbd "C-x C-f") 'helm-quit-and-find-file)
- (define-key map (kbd "M-m") 'helm-toggle-all-marks)
- (define-key map (kbd "M-a") 'helm-mark-all)
- (define-key map (kbd "M-U") 'helm-unmark-all)
- (define-key map (kbd "C-w") 'helm-yank-text-at-point)
- (define-key map (kbd "C-M-a") 'helm-show-all-in-this-source-only)
- (define-key map (kbd "C-M-e") 'helm-display-all-sources)
- (define-key map (kbd "C-r") 'undefined)
- (define-key map (kbd "C-s") 'undefined)
- (define-key map (kbd "M-s") 'undefined)
- (define-key map (kbd "C-}") 'helm-narrow-window)
- (define-key map (kbd "C-{") 'helm-enlarge-window)
- (define-key map (kbd "C-c -") 'helm-swap-windows)
- (define-key map (kbd "C-c C-y") 'helm-yank-selection)
- (define-key map (kbd "C-c C-k") 'helm-kill-selection-and-quit)
- (define-key map (kbd "C-c C-i") 'helm-copy-to-buffer)
- (define-key map (kbd "C-c C-f") 'helm-follow-mode)
- (define-key map (kbd "C-c C-u") 'helm-refresh)
- (define-key map (kbd "C-c >") 'helm-toggle-truncate-line)
- (define-key map (kbd "M-p") 'previous-history-element)
- (define-key map (kbd "M-n") 'next-history-element)
- (define-key map (kbd "C-!") 'helm-toggle-suspend-update)
- (define-key map (kbd "C-x b") 'helm-resume-previous-session-after-quit)
- (define-key map (kbd "C-x C-b") 'helm-resume-list-buffers-after-quit)
- ;; Disable `file-cache-minibuffer-complete'.
- (define-key map (kbd "<C-tab>") 'undefined)
- ;; Multi keys
- (define-key map (kbd "C-t") 'helm-toggle-resplit-and-swap-windows)
- ;; Debugging command
- (define-key map (kbd "C-h C-d") 'undefined)
- (define-key map (kbd "C-h C-d") 'helm-enable-or-switch-to-debug)
- ;; Allow to eval keymap without errors.
- (define-key map [f1] nil)
- (define-key map (kbd "C-h C-h") 'undefined)
- (define-key map (kbd "C-h h") 'undefined)
- ;; Use `describe-mode' key in `global-map'.
- (cl-dolist (k (where-is-internal 'describe-mode global-map))
- (define-key map k 'helm-help))
- (define-key map (kbd "C-c ?") 'helm-help)
- ;; Bind all actions from 1 to 12 to their corresponding nth index+1.
- (cl-loop for n from 0 to 12 do
- (define-key map (kbd (format "<f%s>" (1+ n)))
- `(lambda ()
- (interactive)
- (helm-select-nth-action ,n))))
- ;; Bind keys to allow executing default action
- ;; on first 9 candidates before and after selection.
- (cl-loop for n from 1 to 9
- for key = (format "C-c %d" n)
- for key- = (format "C-x %d" n)
- for fn = `(lambda ()
- (interactive)
- (helm-execute-selection-action-at-nth ,n))
- for fn- = `(lambda ()
- (interactive)
- (helm-execute-selection-action-at-nth ,(- n)))
- do (progn
- (define-key map (kbd key) fn)
- (define-key map (kbd key-) fn-)))
- map)
- "Keymap for helm.")
-
-\f
-(defgroup helm nil
- "Open helm."
- :prefix "helm-" :group 'convenience)
-
-(defcustom helm-completion-window-scroll-margin 5
- " `scroll-margin' to use for helm completion window.
-Which see. Set to 0 to disable.
-NOTE: This have no effect when `helm-display-source-at-screen-top'
-id non--nil."
- :group 'helm
- :type 'integer)
-
-(defcustom helm-display-source-at-screen-top t
- "Display candidates at the top of screen.
-This happen when using `helm-next-source' and `helm-previous-source'.
-NOTE: When non--nil (default) disable `helm-completion-window-scroll-margin'."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-candidate-number-limit 100
- "Limit candidate number globally.
-Do not show more candidates than this limit from individual sources.
-It is usually pointless to show hundreds of matches
-when the pattern is empty, because it is much simpler to type a
-few characters to narrow down the list of potential candidates.
-
-Set it to nil if you don't want this limit."
- :group 'helm
- :type '(choice (const :tag "Disabled" nil) integer))
-
-(defcustom helm-idle-delay 0.01
- "Be idle for this many seconds, before updating in delayed sources.
-This is useful for sources involving heavy operations
-\(like launching external programs\), so that candidates
-from the source are not retrieved unnecessarily if the user keeps typing.
-
-It also can be used to declutter the results helm displays,
-so that results from certain sources are not shown with every
-character typed, only if the user hesitates a bit.
-Be sure to know what you are doing when modifying this."
- :group 'helm
- :type 'float)
-
-(defcustom helm-input-idle-delay 0.01
- "Be idle for this many seconds, before updating.
-
-Unlike `helm-idle-delay', it is also effective for non-delayed sources.
-If nil, candidates are collected immediately.
-
-Note: If this value is too low compared to `helm-idle-delay',
-you may have duplicated sources when using multiples sources.
-Safe value is always >= `helm-idle-delay'.
-Default settings are equal value for both.
-Be sure to know what you are doing when modifying this."
- :group 'helm
- :type 'float)
-
-(defcustom helm-exit-idle-delay 0
- "Be idle for this many seconds before exiting minibuffer while helm is updating.
-Note that this does nothing when helm-buffer is up to date
-\(i.e exit without delay in this condition\)."
- :group 'helm
- :type 'float)
-
-(defcustom helm-full-frame nil
- "Use current window to show the candidates.
-If t then Helm doesn't pop up a new window."
- :group 'helm
- :type 'boolean)
-
-(defvaralias 'helm-samewindow 'helm-full-frame)
-(make-obsolete-variable 'helm-samewindow 'helm-full-frame "1.4.8.1")
-
-(defcustom helm-quick-update nil
- "If non-nil, suppress displaying sources which are out of screen at first.
-They are treated as delayed sources at this input.
-This flag makes `helm' a bit faster with many sources."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-candidate-separator
- "--------------------"
- "Candidates separator of `multiline' source."
- :group 'helm
- :type 'string)
-
-(defcustom helm-save-configuration-functions
- '(set-window-configuration . current-window-configuration)
- "The functions used to restore/save window or frame configurations.
-It is a pair where the car is the function to restore window or frame config,
-and the cdr is the function to save the window or frame config.
-
-If you want to save and restore frame configuration, set this variable to
- '\(set-frame-configuration . current-frame-configuration\)
-NOTE: This may not work properly with own-frame minibuffer settings.
-Older version saves/restores frame configuration, but the default is changed now
-because flickering can occur in some environment."
- :group 'helm
- :type 'sexp)
-
-(defcustom helm-persistent-action-use-special-display nil
- "If non-nil, use `special-display-function' in persistent action."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-display-function 'helm-default-display-buffer
- "Function to display *helm* buffer.
-It is `helm-default-display-buffer' by default,
-which affects `helm-full-frame'."
- :group 'helm
- :type 'symbol)
-
-(defcustom helm-case-fold-search 'smart
- "Add 'smart' option to `case-fold-search'.
-When smart is enabled, ignore case in the search strings
-if pattern contains no uppercase characters.
-Otherwise, with a nil or t value, the behavior is same as
-`case-fold-search'.
-Default value is smart, other possible values are nil and t.
-NOTE: This have no effect in asynchronous sources, you will
-have to implement a similar feature directly in the process.
-See in helm-grep.el how it is implemented."
- :group 'helm
- :type '(choice (const :tag "Ignore case" t)
- (const :tag "Respect case" nil)
- (other :tag "Smart" 'smart)))
-
-(defcustom helm-file-name-case-fold-search
- (if (memq system-type
- '(cygwin windows-nt ms-dos darwin))
- t
- helm-case-fold-search)
- "Local setting of `helm-case-fold-search' for reading filenames.
-
-See `helm-case-fold-search' for more info."
- :group 'helm
- :type 'symbol)
-
-(defcustom helm-reuse-last-window-split-state nil
- "Reuse the last state of window split, vertical or horizontal.
-That is when you use `helm-toggle-resplit-window' the next helm session
-will reuse the same window scheme than the one of last session unless
-`helm-split-window-default-side' is 'same or 'other."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-split-window-preferred-function 'helm-split-window-default-fn
- "Default function used for splitting window."
- :group 'helm
- :type 'function)
-
-(defcustom helm-split-window-default-side 'below
- "The default side to display `helm-buffer'.
-Must be one acceptable arg for `split-window' SIDE,
-that is `below', `above', `left' or `right'.
-
-Other acceptable values are `same' which always display `helm-buffer'
-in current window and `other' that display `helm-buffer' below if only one
-window or in `other-window-for-scrolling' if available.
-
-A nil value as same effect as `below'.
-If `helm-full-frame' is non--nil, it take precedence on this.
-
-See also `helm-split-window-in-side-p' and `helm-always-two-windows' that
-take precedence on this.
-
-NOTE: this have no effect if `helm-split-window-preferred-function' is not
-`helm-split-window-default-fn' unless this new function handle this."
- :group 'helm
- :type 'symbol)
-
-(defcustom helm-display-buffer-default-size nil
- "Initial height of `helm-buffer', an integer or a function.
-If a function, it should take one arg the window and it is in charge of
-resizing the window, its return value is ignored.
-See `display-buffer' for more info."
- :group 'helm
- :type '(choice integer function))
-
-(defcustom helm-split-window-in-side-p nil
- "Force splitting inside selected window when non--nil.
-See also `helm-split-window-default-side'.
-
-NOTE: this have no effect if `helm-split-window-preferred-function' is not
-`helm-split-window-default-fn' unless this new function handle this."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-always-two-windows nil
- "When non--nil helm will use two windows in this frame.
-That is one window to display `helm-buffer' and one to display
-`helm-current-buffer'.
-
-Note: this have no effect when `helm-split-window-in-side-p' is non--nil,
-or when `helm-split-window-default-side' is set to 'same.
-
-When `helm-autoresize-mode' is enabled, setting this to nil
-will have no effect.
-
-Also when non-nil it overhides the effect of `helm-split-window-default-side'
-set to `other'."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-sources-using-default-as-input '(helm-source-imenu
- helm-source-imenu-all
- helm-source-info-elisp
- helm-source-etags-select
- helm-source-man-pages
- helm-source-occur
- helm-source-moccur)
- "List of helm sources that need to use `helm--maybe-use-default-as-input'.
-When a source is member of this list, default `thing-at-point'
-will be used as input."
- :group 'helm
- :type '(repeat (choice symbol)))
-
-(defcustom helm-delete-minibuffer-contents-from-point t
- "When non--nil, `helm-delete-minibuffer-contents' delete region from `point'.
-Otherwise delete `minibuffer-contents'.
-See documentation of `helm-delete-minibuffer-contents'."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-follow-mode-persistent nil
- "Retrieve last state of `helm-follow-mode' in next helm session when non--nil.
-This will not make it persistent through emacs sessions though,
-you will have to set explicitely the `follow' attribute in the source where
-you want this mode enabled definitely."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-prevent-escaping-from-minibuffer t
- "Prevent escaping from minibuffer during helm session."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-move-to-line-cycle-in-source nil
- "Move to end or beginning of source when reaching top or bottom of source.
-This happen when using `helm-next/previous-line'."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-fuzzy-match-fn 'helm-fuzzy-match
- "The function for fuzzy matching in `helm-source-sync' based sources."
- :group 'helm
- :type 'function)
-
-(defcustom helm-fuzzy-search-fn 'helm-fuzzy-search
- "The function for fuzzy matching in `helm-source-in-buffer' based sources."
- :group 'helm
- :type 'function)
-
-(defcustom helm-fuzzy-sort-fn 'helm-fuzzy-matching-default-sort-fn
- "The sort transformer function used in fuzzy matching.
-When nil no sorting will be done."
- :group 'helm
- :type 'function)
-
-(defcustom helm-fuzzy-matching-highlight-fn 'helm-fuzzy-default-highlight-match
- "The function to highlight matches in fuzzy matching.
-When nil no highlighting will be done."
- :group 'helm
- :type 'function)
-
-(defcustom helm-autoresize-max-height 40
- "Specifies a maximum height and defaults to the height of helm window's frame in percentage.
-
-See `fit-window-to-buffer' for more infos."
- :group 'helm
- :type 'integer)
-
-(defcustom helm-autoresize-min-height 10
- "Specifies a minimum height and defaults to the height of helm window's frame in percentage.
-
-If nil the default of `window-min-height' is used
-See `fit-window-to-buffer' for more infos."
- :group 'helm
- :type 'integer)
-
-(defcustom helm-input-method-verbose-flag nil
- "The default value of `input-method-verbose-flag' to use in helm minibuffer.
-It is nil by default to allow helm updating and exiting without turning off
-the input method when complex methods are in use, if you set it to any other
-value allowed by `input-method-verbose-flag' you will have at each time you want
-to exit or helm update to disable the `current-input-method' with `C-\\'."
- :group 'helm
- :type '(radio :tag "A flag to control extra guidance given by input methods in helm."
- (const :tag "Never provide guidance" nil)
- (const :tag "Always provide guidance" t)
- (const :tag "Provide guidance only in complex methods" complex-only)))
-
-(defcustom helm-display-header-line t
- "Display header-line when non nil."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-inherit-input-method t
- "Inherit `current-input-method' from `current-buffer' when non--nil.
-The default is to enable this by default, the user can toggle the current
-input method with `toggle-input-method'."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-echo-input-in-header-line nil
- "Send current input in header-line."
- :group 'helm
- :type 'boolean)
-
-\f
-;;; Faces
-;;
-;;
-(defgroup helm-faces nil
- "Customize the appearance of helm."
- :prefix "helm-"
- :group 'faces
- :group 'helm)
-
-(defface helm-source-header
- '((((background dark))
- :background "#22083397778B"
- :foreground "white"
- :weight bold :height 1.3 :family "Sans Serif")
- (((background light))
- :background "#abd7f0"
- :foreground "black"
- :weight bold :height 1.3 :family "Sans Serif"))
- "Face for source header in the helm buffer."
- :group 'helm-faces)
-
-(defface helm-visible-mark
- '((((min-colors 88) (background dark))
- (:background "green1" :foreground "black"))
- (((background dark))
- (:background "green" :foreground "black"))
- (((background light)) :background "#d1f5ea")
- (((min-colors 88))
- (:background "green1"))
- (t (:background "green")))
- "Face for visible mark."
- :group 'helm-faces)
-
-(defface helm-header
- '((t (:inherit header-line)))
- "Face for header lines in the helm buffer."
- :group 'helm-faces)
-
-(defface helm-candidate-number
- '((((background dark)) :background "Yellow" :foreground "black")
- (((background light)) :background "#faffb5" :foreground "black"))
- "Face for candidate number in mode-line." :group 'helm-faces)
-
-(defface helm-selection
- '((((background dark)) :background "ForestGreen"
- :distant-foreground "black")
- (((background light)) :background "#b5ffd1"
- :distant-foreground "black"))
- "Face for currently selected item in the helm buffer."
- :group 'helm-faces)
-
-(defface helm-separator
- '((((background dark)) :foreground "red")
- (((background light)) :foreground "#ffbfb5"))
- "Face for multiline source separator."
- :group 'helm-faces)
-
-(defface helm-action
- '((t (:underline t)))
- "Face for action lines in the helm action buffer."
- :group 'helm-faces)
-
-(defface helm-prefarg
- '((((background dark)) :foreground "green")
- (((background light)) :foreground "red"))
- "Face for showing prefix arg in mode-line."
- :group 'helm-faces)
-
-(defface helm-match
- '((((background light)) :foreground "#b00000")
- (((background dark)) :foreground "gold1"))
- "Face used to highlight matches."
- :group 'helm-faces)
-
-(defface helm-header-line-left-margin
- '((t (:foreground "black" :background "yellow")))
- "Face used to highlight helm-header sign in left-margin."
- :group 'helm-faces)
-
-\f
-;;; Variables.
-;;
-;;
-(defvar helm-type-attributes nil
- "It's a list of \(TYPE ATTRIBUTES ...\).
-ATTRIBUTES are the same as attributes for `helm-sources'.
-TYPE connects the value to the appropriate sources.
-Don't set this directly, use instead `define-helm-type-attribute'.
-
-This allows specifying common attributes for several sources.
-For example, sources which provide files can specify
-common attributes with a `file' type.")
-
-(defvar helm-source-filter nil
- "A list of source names to be displayed.
-Other sources won't appear in the search results.
-If nil then there is no filtering.
-See also `helm-set-source-filter'.")
-
-(defvar helm-selection-overlay nil
- "Overlay used to highlight the currently selected item.")
-
-(defvar helm-async-processes nil
- "List of information about asynchronous processes managed by helm.")
-
-(defvar helm-before-initialize-hook nil
- "Run before helm initialization.
-This hook is run before init functions in `helm-sources',
-that is before creation of `helm-buffer'.
-Local variables for `helm-buffer' that need a value from `current-buffer'
-can be set here with `helm-set-local-variable'.")
-
-(defvar helm-after-initialize-hook nil
- "Run after helm initialization.
-This hook run after `helm-buffer' is created but not from `helm-buffer'
-so the hook have to specify in which buffer it should run.")
-
-(defvar helm-update-hook nil
- "Run after the helm buffer was updated according the new input pattern.
-This hook is run at the beginning of buffer.
-The first candidate is selected after running this hook.
-See also `helm-after-update-hook'.")
-
-(defvar helm-after-update-hook nil
- "Run after the helm buffer was updated according the new input pattern.
-This is very similar to `helm-update-hook' but selection is not moved.
-It is useful to select a particular object instead of the first one.")
-
-(defvar helm-cleanup-hook nil
- "Run after exiting the minibuffer and before performing an
-action.
-
-This hook is run even if the minibuffer is exited
-abnormally (e.g. via `helm-keyboard-quit`).")
-
-(defvar helm-select-action-hook nil
- "Run when opening the action buffer.")
-
-(defvar helm-before-action-hook nil
- "Run before executing action.
-Contrarily to `helm-cleanup-hook',
-this hook run before helm minibuffer is closed
-and before performing action.")
-
-(defvar helm-after-action-hook nil
- "Run after executing action.")
-
-(defvar helm-exit-minibuffer-hook nil
- "Run just before exiting the minibuffer.
-
-This hook is run if the minibuffer is exited normally (e.g. via
-candidate selection). It is NOT run if the minibuffer is exited
-abnormally (e.g. via `helm-keyboard-quit`).")
-
-(defvar helm-after-persistent-action-hook nil
- "Run after executing persistent action.")
-
-(defvar helm-move-selection-before-hook nil
- "Run before moving selection in `helm-buffer'.")
-
-(defvar helm-move-selection-after-hook nil
- "Run after moving selection in `helm-buffer'.")
-
-(defvar helm-after-preselection-hook nil
- "Run after preselection in `helm-buffer'.")
-
-(defvar helm-window-configuration-hook nil
- "Run when switching to and back from action buffer.")
-
-(defconst helm-restored-variables
- '(helm-candidate-number-limit
- helm-source-filter
- helm-source-in-each-line-flag
- helm-map
- helm-sources)
- "Variables which are restored after `helm' invocation.")
-
-(defvar helm-execute-action-at-once-if-one nil
- "Execute default action and exit when only one candidate is remaining.
-It can be also a function called with no args returning a boolean value.")
-
-(defvar helm-quit-if-no-candidate nil
- "Quit when there is no candidates when non--nil.
-This variable accepts a function, which is executed if no candidate.")
-
-(defvar helm-source-in-each-line-flag nil
- "Non-nil means add helm-source text-property in each candidate.
-experimental feature.")
-
-(defvar helm-debug-variables nil
- "A list of helm variables to show in `helm-debug-output'.
-Otherwise all variables started with `helm-' are shown.")
-
-(defvar helm-debug-buffer "*Debug Helm Log*")
-
-(defvar helm-debug nil
- "If non-nil, write log message into `helm-debug-buffer' buffer.
-It is disabled by default because `helm-debug-buffer' grows quickly.")
-
-(defvar helm-compile-source-functions
- '(helm-compile-source--type
- helm-compile-source--dummy
- helm-compile-source--candidates-in-buffer)
- "Functions to compile elements of `helm-sources' (plug-in).")
-
-(defvar helm-mode-line-string "\
-\\<helm-map>\
-\\[helm-help]:Help \
-\\[helm-select-action]:Act \
-\\[helm-maybe-exit-minibuffer]/\
-f1/f2/f-n:NthAct \
-\\[helm-toggle-suspend-update]:Tog.suspend"
- "Help string displayed in mode-line in `helm'.
-It can be a string or a list of two args, in this case,
-first arg is a string that will be used as name for candidates number,
-second arg any string to display in mode line.
-If nil, use default `mode-line-format'.")
-
-(defvar helm-minibuffer-set-up-hook nil
- "Hook that run at initialization of minibuffer.
-Useful for modifying the settings of minibuffer in helm.
-
-Here an example to hide minibuffer when using
-`helm-echo-input-in-header-line':
-
- (add-hook 'helm-minibuffer-set-up-hook #'helm-hide-minibuffer-maybe)
-
-Note that we check `helm-echo-input-in-header-line' value
-from `helm-buffer' which allow detecting possible local
-value of this var.")
-
-(defvar helm-help-message
- "* Helm Generic Help
-
-\\<helm-map>`helm' is an Emacs incremental completion and selection narrowing framework.
-
-Narrow the list by typing some pattern,
-Multiple patterns are allowed by separating with a space.
-Select with natural Emacs operations, choose with RET.
-
-** Help
-
-C-h m\t\tRun this generic help for helm.
-
-** Basic Operations
-
-These are the default key bindings:
-
-| Key | Alternative Keys | Command |
-|---------+------------------+-----------------------------------------------------------|
-| C-p | Up | Previous Line |
-| C-n | Down | Next Line |
-| M-v | PageUp | Previous Page |
-| C-v | PageDown | Next Page |
-| Enter | | Execute first (default) action / Select |
-| M-< | | First Line |
-| M-> | | Last Line |
-| C-M-S-v | M-PageUp, C-M-y | Previous Page (other-window) |
-| C-M-v | M-PageDown | Next Page (other-window) |
-| Tab | C-i | Show action list |
-| Left | | Previous Source |
-| Right | C-o | Next Source |
-| C-k | | Delete pattern (with prefix arg delete from point to end) |
-| C-j | C-z | Persistent Action (Execute and keep helm session) |
-
-** Shortcuts For nth Action
-
-f1-12: Execute nth 1 to 12 Action(s).
-
-** Shortcuts for executing Default Action on nth candidate
-
-C-x <n> => execute default action on number <n> candidate before selection.
-C-c <n> => execute default action on number <n> candidate after selection.
-
-Of course this works only on the 9 first and previous candidates.
-
-Helm provides nothing to visualize candidates numbers, up to you to install
-linum-relative package and enable linum-relative in helm..
-
-** Visible Marks
-
-Visible marks store candidate. Some actions uses marked candidates.
-
-** Miscellaneous Commands
-
-\\[helm-toggle-resplit-and-swap-windows]\t\tToggle vertical/horizontal split on first hit and swap helm window on second hit.
-\\[helm-quit-and-find-file]\t\tDrop into `helm-find-files'.
-\\[helm-kill-selection-and-quit]\t\tKill display value of candidate and quit (with prefix arg kill the real value).
-\\[helm-yank-selection]\t\tYank selection into pattern.
-\\[helm-follow-mode]\t\tToggle automatical execution of persistent action.
-\\[helm-follow-action-forward]\tRun persistent action and goto next line.
-\\[helm-follow-action-backward]\t\tRun persistent action and goto previous line.
-\\[helm-refresh]\t\tRecalculate and redisplay candidates.
-\\[helm-toggle-suspend-update]\t\tSuspend/reenable update.
-
-** Global Commands
-
-\\<global-map>\\[helm-resume] revives last `helm' session.
-It is very useful, so you should bind any key.
-
-** Helm Map
-\\{helm-map}"
- "Detailed help message string for `helm'.
-It also accepts function or variable symbol.")
-
-(defvar helm-autoresize-mode) ;; Undefined in `helm-default-display-buffer'.
-
-\f
-;;; Internal Variables
-;;
-;;
-(defvar helm-current-prefix-arg nil
- "Record `current-prefix-arg' when exiting minibuffer.")
-(defvar helm-saved-action nil
- "Saved value of the currently selected action by key.")
-(defvar helm-saved-current-source nil
- "Value of the current source when the action list is shown.")
-(defvar helm-compiled-sources nil
- "Compiled version of `helm-sources'.")
-(defvar helm-in-persistent-action nil
- "Flag whether in persistent-action or not.")
-(defvar helm-last-buffer nil
- "`helm-buffer' of previously `helm' session.")
-(defvar helm-saved-selection nil
- "Value of the currently selected object when the action list is shown.")
-(defvar helm-sources nil
- "[INTERNAL] Value of current sources in use, a list.")
-(defvar helm-buffer-file-name nil
- "Variable `buffer-file-name' when `helm' is invoked.")
-(defvar helm-candidate-cache (make-hash-table :test 'equal)
- "Holds the available candidate within a single helm invocation.")
-(defvar helm-input ""
- "The input typed in the candidates panel.")
-(defvar helm-input-local nil
- "Internal, store locally `helm-pattern' value for later use in `helm-resume'.")
-(defvar helm-source-name nil)
-(defvar helm-current-source nil)
-(defvar helm-candidate-buffer-alist nil)
-(defvar helm-tick-hash (make-hash-table :test 'equal))
-(defvar helm-issued-errors nil)
-(defvar helm-debug-root-directory nil
- "When non--nil, save helm log to `helm-last-log-file'.
-Be aware that if you set that, you will end up with a huge directory
-of log files, so use that only for debugging purpose.
-See `helm-log-save-maybe' for more info.")
-(defvar helm-last-log-file nil
- "The name of the last helm session log file.")
-(defvar helm-follow-mode nil)
-(defvar helm--local-variables nil)
-(defvar helm-split-window-state nil)
-(defvar helm--window-side-state nil)
-(defvar helm-selection-point nil)
-(defvar helm-alive-p nil)
-(defvar helm-visible-mark-overlays nil)
-(defvar helm-update-blacklist-regexps '("^" "^ *" "$" "!" " " "\\b"
- "\\<" "\\>" "\\_<" "\\_>" ".*"))
-(defvar helm-force-updating-p nil)
-(defvar helm-exit-status 0
- "Flag to inform whether helm have exited or quitted.
-Exit with 0 mean helm have exited executing an action.
-Exit with 1 mean helm have quitted with \\[keyboard-quit]
-It is useful for example to restore a window config if helm abort
-in special cases.
-See `helm-exit-minibuffer' and `helm-keyboard-quit'.")
-(defvar helm-minibuffer-confirm-state nil)
-(defvar helm-quit nil)
-(defvar helm-attributes nil "List of all `helm' attributes.")
-(defvar helm-buffers nil
- "All of `helm-buffer' in most recently used order.")
-(defvar helm-current-position nil
- "Cons of \(point . window-start\) when `helm' is invoked.
-It is needed to restore position in `helm-current-buffer'
-when `helm' is keyboard-quitted.")
-(defvar helm-last-frame-or-window-configuration nil
- "Used to store window or frame configuration when helm start.")
-(defvar helm-onewindow-p nil)
-(defvar helm-types nil)
-(defvar helm--mode-line-string-real nil) ; The string to display in mode-line.
-(defvar helm-persistent-action-display-window nil)
-(defvar helm-marked-candidates nil
- "Marked candadates. List of \(source . real\) pair.")
-(defvar helm--mode-line-display-prefarg nil)
-(defvar helm--temp-follow-flag nil
- "[INTERNAL] A simple flag to notify persistent action we are following.")
-(defvar helm--reading-passwd-or-string nil)
-(defvar helm--in-update nil)
-(defvar helm--in-fuzzy nil)
-(defvar helm--maybe-use-default-as-input nil
- "Flag to notify the use of use-default-as-input.
-Use only in let-bindings.
-Use :default arg of `helm' as input to update display.
-Note that if also :input is specified as `helm' arg, it will take
-precedence on :default.")
-(defvar helm--temp-hooks nil
- "Store temporary hooks added by `with-helm-temp-hook'.")
-(defvar helm-truncate-lines nil
- "[Internal] Don't set this globally, it is used as a local var.")
-(defvar helm--prompt nil)
-(defvar helm--file-completion-sources
- '("Find Files" "Read File Name" "Read File Name History")
- "Sources that use the *find-files mechanism can be added here.
-Sources generated by `helm-mode' don't need to be added here, it will
-be done automatically.
-You should not modify this yourself unless you know what you do.")
-;; Same as `ffap-url-regexp' but keep it here to ensure `ffap-url-regexp' is not nil.
-(defvar helm--url-regexp "\\(news\\(post\\)?:\\|mailto:\\|file:\\|\\(ftp\\|https?\\|telnet\\|gopher\\|www\\|wais\\)://\\)")
-\f
-;; Utility: logging
-(defun helm-log (format-string &rest args)
- "Log message `helm-debug' is non-nil.
-Messages are written to the `helm-debug-buffer' buffer.
-
-Argument FORMAT-STRING is a string to use with `format'.
-Use optional arguments ARGS like in `format'."
- (when helm-debug
- (with-current-buffer (get-buffer-create helm-debug-buffer)
- (outline-mode)
- (buffer-disable-undo)
- (set (make-local-variable 'inhibit-read-only) t)
- (goto-char (point-max))
- (insert (let ((tm (current-time)))
- (format (concat (if (string-match "Start session" format-string)
- "* " "** ")
- "%s.%06d (%s)\n %s\n")
- (format-time-string "%H:%M:%S" tm)
- (nth 2 tm)
- (helm-log-get-current-function)
- (apply #'format (cons format-string args))))))))
-
-(defun helm-log-run-hook (hook)
- "Run HOOK like `run-hooks' but write these actions to helm log buffer."
- (helm-log "Executing %s with value = %S" hook (symbol-value hook))
- (helm-log "Executing %s with global value = %S" hook (default-value hook))
- (run-hooks hook)
- (helm-log "executed %s" hook))
-
-(defun helm-log-get-current-function ()
- "Get function name calling `helm-log'.
-The original idea is from `tramp-debug-message'."
- (cl-loop with exclude-func-re = "^helm-\\(?:interpret\\|log\\|.*funcall\\)"
- for btn from 1 to 40
- for btf = (cl-second (backtrace-frame btn))
- for fn = (if (symbolp btf) (symbol-name btf) "")
- if (and (string-match "^helm" fn)
- (not (string-match exclude-func-re fn)))
- return fn))
-
-(defun helm-log-error (&rest args)
- "Accumulate error messages into `helm-issued-errors'.
-ARGS are args given to `format'.
-e.g (helm-log-error \"Error %s: %s\" (car err) (cdr err))."
- (apply 'helm-log (concat "ERROR: " (car args)) (cdr args))
- (let ((msg (apply 'format args)))
- (unless (member msg helm-issued-errors)
- (add-to-list 'helm-issued-errors msg))))
-
-(defun helm-log-save-maybe ()
- "May be save log buffer to `helm-last-log-file'.
-If `helm-debug-root-directory' is non--nil and a valid directory,
-a directory named 'helm-debug-<date of today>'
-will be created there and the log recorded in a file named
-at the date and time of today in this directory."
- (when (and (stringp helm-debug-root-directory)
- (file-directory-p helm-debug-root-directory)
- helm-debug)
- (let ((logdir (expand-file-name (concat "helm-debug-"
- (format-time-string "%Y%m%d"))
- helm-debug-root-directory)))
- (make-directory logdir t)
- (with-current-buffer (get-buffer-create helm-debug-buffer)
- (write-region (point-min) (point-max)
- (setq helm-last-log-file
- (expand-file-name
- (format-time-string "%Y%m%d-%H%M%S")
- logdir))
- nil 'silent)
- (kill-buffer)))))
-
-;;;###autoload
-(defun helm-debug-open-last-log ()
- "Open helm log file of last helm session.
-If `helm-last-log-file' is nil, switch to `helm-debug-buffer' ."
- (interactive)
- (if helm-last-log-file
- (view-file helm-last-log-file)
- (switch-to-buffer helm-debug-buffer)
- (view-mode 1) (visual-line-mode 1)))
-
-(defun helm-print-error-messages ()
- "Print error messages in `helm-issued-errors'."
- (and helm-issued-errors
- (message "Helm issued errors: %s"
- (mapconcat 'identity (reverse helm-issued-errors) "\n"))))
-
-\f
-;; Programming Tools
-
-(defun helm-this-command ()
- "Return the actual command in action.
-Like `this-command' but return the real command,
-not `exit-minibuffer' or unwanted functions."
- (cl-loop with bl = '(helm-maybe-exit-minibuffer
- helm-confirm-and-exit-minibuffer
- helm-exit-minibuffer
- exit-minibuffer)
- for count from 1 to 50
- for btf = (backtrace-frame count)
- for fn = (cl-second btf)
- if (and
- ;; In some case we may have in the way an
- ;; advice compiled resulting in byte-code,
- ;; ignore it (Issue #691).
- (symbolp fn)
- (commandp fn)
- (not (memq fn bl)))
- return fn
- else
- if (and (eq fn 'call-interactively)
- (> (length btf) 2))
- return (cadr (cdr btf))))
-
-\f
-;; Test tools
-(defmacro with-helm-time-after-update (&rest body)
- (helm-with-gensyms (start-time time-elapsed)
- `(let ((,start-time (float-time)) ,time-elapsed)
- (add-hook 'helm-after-update-hook
- (lambda ()
- (setq ,time-elapsed (- (float-time) ,start-time))
- (keyboard-quit)))
- (unwind-protect ,@body
- (remove-hook 'helm-after-update-hook
- (lambda ()
- (setq ,time-elapsed (- (float-time) ,start-time))
- (keyboard-quit))))
- ,time-elapsed)))
-
-\f
-;; Helm API
-
-(defmacro with-helm-restore-variables (&rest body)
- "Restore `helm-restored-variables' after executing BODY."
- (declare (indent 0) (debug t))
- (helm-with-gensyms (orig-vars)
- `(let ((,orig-vars (mapcar (lambda (v)
- (cons v (symbol-value v)))
- helm-restored-variables)))
- (unwind-protect (progn ,@body)
- (cl-loop for (var . value) in ,orig-vars
- do (set var value))
- (helm-log "restore variables")))))
-
-(defmacro with-helm-default-directory (directory &rest body)
- (declare (indent 2) (debug t))
- `(let ((default-directory (or (and ,directory
- (file-name-as-directory ,directory))
- default-directory)))
- ,@body))
-
-(defun helm-default-directory ()
- "Return the local value of `default-directory' in `helm-buffer'."
- (buffer-local-value 'default-directory (get-buffer helm-buffer)))
-
-(defmacro with-helm-temp-hook (hook &rest body)
- "Execute temporarily BODY as a function for HOOK."
- (declare (indent 1) (debug t))
- (helm-with-gensyms (helm--hook)
- `(progn
- (defun ,helm--hook ()
- (unwind-protect
- (progn ,@body)
- (remove-hook ,hook (quote ,helm--hook))
- (fmakunbound (quote ,helm--hook))))
- (push (cons ',helm--hook ,hook) helm--temp-hooks)
- (add-hook ,hook (quote ,helm--hook)))))
-
-(defmacro with-helm-after-update-hook (&rest body)
- "Execute BODY at end of `helm-update'."
- (declare (indent 0) (debug t))
- `(with-helm-temp-hook 'helm-after-update-hook ,@body))
-
-(defmacro with-helm-alive-p (&rest body)
- "Return error when BODY run outside helm context."
- (declare (indent 0) (debug t))
- `(progn
- (if helm-alive-p
- (progn ,@body)
- (error "Running helm command outside of context"))))
-
-(defun helm-attr (attribute-name &optional source compute)
- "Get the value of ATTRIBUTE-NAME of SRC.
-If SRC is omitted, use current source.
-If COMPUTE is non--nil compute value of ATTRIBUTE-NAME
-with `helm-interpret-value'. COMPUTE can have also 'ignorefn as
-value, in this case `helm-interpret-value' will return a function
-as value inchanged, but will eval a symbol which is bound
-(i.e a variable)."
- (let ((src (or source (helm-get-current-source))))
- (helm-aif (or (assq attribute-name src)
- (helm-get-attribute-from-source-type attribute-name src))
- (if compute
- (helm-interpret-value (cdr it) src compute)
- (cdr it)))))
-
-(cl-defun helm-attr-defined (attribute-name
- &optional (src (helm-get-current-source)))
- "Return non-nil if ATTRIBUTE-NAME of SRC is defined.
-if SRC is omitted, use current source."
- (and (helm-attr attribute-name src) t))
-
-(cl-defun helm-attrset (attribute-name value
- &optional
- (src (helm-get-current-source))
- alter-type)
- "Set the value of ATTRIBUTE-NAME of source SRC to VALUE.
-If ATTRIBUTE-NAME doesn't exists in source it is created with value VALUE.
-If ALTER-TYPE is non--nil alter the value of ATTRIBUTE-NAME in `helm-attributes'
-if it exists.
-If SRC is omitted, use current source.
-If operation succeed, return value, otherwise nil."
- (let ((from-type (helm-get-attribute-from-source-type attribute-name src))
- done)
- (helm-aif (or (assq attribute-name src)
- (and alter-type from-type))
- (prog1 (setcdr it value) (setq done t))
- (unless from-type
- (setcdr src (cons (cons attribute-name value) (cdr src)))
- (setq done t)))
- (and done value)))
-
-(defun helm-get-attribute-from-source-type (attribute source)
- "Get ATTRIBUTE from type attribute of SOURCE."
- (when (assq 'type source)
- (assq attribute
- (assq (cdr (assq 'type source))
- helm-type-attributes))))
-
-(defun helm-get-attribute-from-type (attribute type)
- "Get ATTRIBUTE from TYPE.
-arg TYPE is an existing type defined in `helm-type-attributes'."
- (assq attribute (assq type helm-type-attributes)))
-
-(defun helm-get-actions-from-type (source)
- "Get actions list from type attribute of SOURCE."
- (when (assq 'type source)
- (helm-get-attribute-from-source-type 'action source)))
-
-(defun helm-inherit-attribute-from-source (attribute source)
- "Get the ATTRIBUTE of SOURCE."
- (helm-aif (assq attribute source)
- it
- (helm-get-attribute-from-source-type attribute source)))
-
-(defun helm-append-at-nth (seq elm index)
- "Append ELM at INDEX in SEQ."
- (let ((len (length seq)))
- (cond ((> index len) (setq index len))
- ((< index 0) (setq index 0)))
- (if (zerop index)
- (append elm seq)
- (cl-loop for i in seq
- for count from 1 collect i
- when (= count index)
- if (listp elm) append elm
- else collect elm))))
-
-(defun helm-add-action-to-source (name fn source &optional index)
- "Add new action NAME linked to function FN to SOURCE.
-Function FN should be a valid function that take one arg i.e candidate,
-argument NAME is a string that will appear in action menu
-and SOURCE should be an existing helm source already loaded.
-If INDEX is specified, action is added in action list at INDEX,
-otherwise it is added at end.
-This allow user to add a specific action to an existing source
-without modifying source code."
- (let ((actions (helm-attr 'action source 'ignorefn))
- (new-action (list (cons name fn))))
- (when (functionp actions)
- (setq actions (list (cons "Default action" actions))))
- (helm-attrset 'action
- (if index
- (helm-append-at-nth actions new-action index)
- (append actions new-action))
- source)))
-
-(defun helm-delete-action-from-source (action-or-name source)
- "Delete ACTION-OR-NAME from SOURCE.
-ACTION-OR-NAME can either be the name of action or the symbol function
-associated to name."
- (let* ((actions (helm-attr 'action source 'ignorefn))
- (del-action (if (symbolp action-or-name)
- (rassoc action-or-name actions)
- (assoc action-or-name actions))))
- (helm-attrset 'action (delete del-action actions) source)))
-
-(cl-defun helm-add-action-to-source-if (name fn source predicate
- &optional (index 4) test-only)
- "Add new action NAME linked to function FN to SOURCE.
-Action NAME will be available when the current candidate matches PREDICATE.
-This function add an entry in the `action-transformer' attribute
-of SOURCE (or create one if not found).
-Function PREDICATE should take one arg candidate.
-Function FN should be a valid function that take one arg i.e candidate,
-argument NAME is a string that will appear in action menu
-and SOURCE should be an existing helm source already loaded.
-If INDEX is specified, action is added in action list at INDEX.
-Value of INDEX should be always >=1, default to 4.
-This allow user to add a specific `action-tranformer'
-to an existing source without modifying source code.
-E.g
-Add the action \"Byte compile file async\" linked to
-function 'async-byte-compile-file to source `helm-source-find-files'
-only when predicate helm-ff-candidates-lisp-p return non--nil:
-
-\(helm-add-action-to-source-if \"Byte compile file async\"
- 'async-byte-compile-file
- helm-source-find-files
- 'helm-ff-candidates-lisp-p\)."
- (let* ((actions (helm-attr 'action source 'ignorefn))
- (action-transformers (helm-attr 'action-transformer source))
- (new-action (list (cons name fn)))
- (transformer `(lambda (actions candidate)
- (cond ((funcall (quote ,predicate) candidate)
- (helm-append-at-nth
- actions (quote ,new-action) ,index))
- (t actions)))))
- (when (functionp actions)
- (helm-attrset 'action (list (cons "Default action" actions)) source))
- (when (or (symbolp action-transformers) (functionp action-transformers))
- (setq action-transformers (list action-transformers)))
- (if test-only ; debug
- (delq nil (append (list transformer) action-transformers))
- (helm-attrset 'action-transformer
- (helm-fast-remove-dups
- (delq nil (append (list transformer) action-transformers))
- :test 'equal)
- source))))
-
-(defun helm-set-source-filter (sources)
- "Set the value of `helm-source-filter' to SOURCES and update.
-
-This function sets a filter for helm sources and it may be
-called while helm is running. It can be used to toggle
-displaying of sources dynamically. For example, additional keys
-can be bound into `helm-map' to display only the file-related
-results if there are too many matches from other sources and
-you're after files only:
-
-Shift+F shows only file results from some sources:
-
-\(define-key helm-map \"F\" 'helm-my-show-files-only)
-
-\(defun helm-my-show-files-only ()
- (interactive)
- (helm-set-source-filter '(\"File Name History\"
- \"Files from Current Directory\")))
-
-Shift+A shows all results:
-
-\(define-key helm-map \"A\" 'helm-my-show-all)
-
-\(defun helm-my-show-all ()
- (interactive)
- (helm-set-source-filter nil))
-
-The -my- part is added to avoid collisions with
-existing Helm function names."
- (let ((cur-disp-sel (with-current-buffer helm-buffer
- (helm-get-selection nil t))))
- (setq helm-source-filter (helm--normalize-filter-sources sources))
- (helm-log "helm-source-filter = %S" helm-source-filter)
- ;; Use force-update to run init/update functions.
- (helm-force-update (and (stringp cur-disp-sel)
- (regexp-quote cur-disp-sel)))))
-
-(defun helm--normalize-filter-sources (sources)
- (cl-loop for s in sources collect
- (cl-typecase s
- (symbolp (assoc-default 'name (symbol-value s)))
- (listp (assoc-default 'name s))
- (stringp s))))
-
-(defun helm-set-sources (sources &optional no-init no-update)
- "Set SOURCES during `helm' invocation.
-If NO-INIT is non-nil, skip executing init functions of SOURCES.
-If NO-UPDATE is non-nil, skip executing `helm-update'."
- (with-current-buffer helm-buffer
- (setq helm-compiled-sources nil
- helm-sources sources)
- (helm-log "helm-compiled-sources = %S" helm-compiled-sources)
- (helm-log "helm-sources = %S" helm-sources))
- (unless no-init (helm-funcall-foreach 'init))
- (unless no-update (helm-update)))
-
-(defun helm-get-sources ()
- "Return compiled `helm-sources', which is memoized.
-
-Attributes:
-
-- type
- `helm-type-attributes' are merged in.
-- candidates-buffer
- candidates, volatile and match attribute are created."
- (cond
- ;; action
- ((helm-action-window)
- helm-sources)
- ;; memoized
- (helm-compiled-sources)
- ;; first time
- (t
- (prog1
- (setq helm-compiled-sources
- (helm-compile-sources
- helm-sources helm-compile-source-functions))
- (helm-log "helm-compiled-sources = %S" helm-compiled-sources)))))
-
-(cl-defun helm-get-selection (&optional (buffer nil buffer-s)
- force-display-part)
- "Return the currently selected item or nil.
-if BUFFER is nil or unspecified, use helm-buffer as default value.
-If FORCE-DISPLAY-PART is non-nil, return the display string.
-If FORCE-DISPLAY-PART value is 'withprop the display string is returned
-with its properties."
- (setq buffer (if (and buffer buffer-s) buffer helm-buffer))
- (unless (helm-empty-buffer-p buffer)
- (with-current-buffer buffer
- (let* ((disp-fn (if (eq force-display-part 'withprop)
- 'buffer-substring
- 'buffer-substring-no-properties))
- (selection
- (or (and (not force-display-part)
- (get-text-property (overlay-start
- helm-selection-overlay)
- 'helm-realvalue))
- ;; It is needed to return properties of DISP in some case,
- ;; e.g for `helm-confirm-and-exit-minibuffer',
- ;; so use `buffer-substring' here when 'withprop is specified.
- (let ((disp (funcall
- disp-fn
- (overlay-start helm-selection-overlay)
- (1- (overlay-end helm-selection-overlay))))
- (source (helm-get-current-source)))
- (helm-aif (and (not force-display-part)
- (assoc-default 'display-to-real source))
- (helm-funcall-with-source source it disp)
- disp)))))
- (unless (equal selection "")
- (helm-log "selection = %S" selection)
- selection)))))
-
-(defun helm-get-actions-from-current-source ()
- "Return the associated action for the selected candidate.
-It is a function symbol \(sole action\) or list
-of \(action-display . function\)."
- (unless (helm-empty-buffer-p (helm-buffer-get))
- (helm-aif (helm-attr 'action-transformer)
- (helm-composed-funcall-with-source
- (helm-get-current-source) it
- (helm-attr 'action nil 'ignorefn)
- ;; Check if the first given transformer
- ;; returns the same set of actions for each
- ;; candidate in marked candidates.
- ;; If so use the car of marked to determine
- ;; the set of actions, otherwise use the selection.
- (if (cl-loop with marked = (helm-marked-candidates)
- with act = (car (helm-mklist it))
- with acts = (funcall act nil (car marked))
- for c in marked
- always (equal (funcall act nil c) acts))
- (car (helm-marked-candidates))
- (helm-get-selection)))
- (helm-attr 'action nil 'ignorefn))))
-
-(defun helm-get-current-source ()
- "Return the source for the current selection.
-Allow also checking if helm-buffer contain candidates."
- (or helm-current-source
- (with-current-buffer (helm-buffer-get)
- (or
- ;; This happen only when `helm-source-in-each-line-flag'
- ;; is non--nil and there is candidates in buffer.
- (get-text-property (point) 'helm-source)
- ;; Return nil when no--candidates.
- (cl-block exit
- ;; This goto-char shouldn't be necessary, but point is moved to
- ;; point-min somewhere else which shouldn't happen.
- (goto-char (overlay-start helm-selection-overlay))
- (let* ((header-pos (or (helm-get-previous-header-pos)
- (helm-get-next-header-pos)))
- (source-name
- (save-excursion
- (unless header-pos
- (cl-return-from exit nil))
- (goto-char header-pos)
- (helm-current-line-contents))))
- (cl-loop for source in (helm-get-sources) thereis
- (and (equal (assoc-default 'name source) source-name)
- source))))))))
-
-(defun helm-buffer-is-modified (buffer)
- "Return non-nil when BUFFER is modified since `helm' was invoked."
- (let* ((b (get-buffer buffer))
- (key (concat (buffer-name b) "/" (helm-attr 'name)))
- (source-tick (or (gethash key helm-tick-hash) 0))
- (buffer-tick (buffer-chars-modified-tick b))
- (modifiedp (/= source-tick buffer-tick)))
- (puthash key buffer-tick helm-tick-hash)
- (helm-log "buffer = %S" buffer)
- (helm-log "modifiedp = %S" modifiedp)
- modifiedp))
-
-(defun helm-current-buffer-is-modified ()
- "Check if `helm-current-buffer' is modified since `helm' was invoked."
- (helm-buffer-is-modified helm-current-buffer))
-
-(defun helm-run-after-exit (function &rest args)
- "Exectute FUNCTION with ARGS after exiting `helm'.
-The action is to call FUNCTION with arguments ARGS.
-Contrarily to `helm-exit-and-execute-action' this can be used
-to call non--actions functions with any ARGS or no ARGS at all.
-
-Use this on commands invoked from keybindings, but not
-on action functions invoked as action from the action menu,
-i.e functions called with RET."
- (helm-kill-async-processes)
- (helm-log "function = %S" function)
- (helm-log "args = %S" args)
- (helm-exit-and-execute-action
- (lambda (_candidate)
- (apply function args))))
-
-(defun helm-exit-and-execute-action (action)
- "Exit current helm session and execute ACTION.
-Argument ACTION is a function called with one arg (candidate)
-and part of the actions of current source.
-
-Use this on commands invoked from keybindings, but not
-on action functions invoked as action from the action menu,
-i.e functions called with RET."
- (setq helm-saved-action action)
- (setq helm-saved-selection (helm-get-selection))
- (helm-exit-minibuffer))
-
-(defalias 'helm-run-after-quit 'helm-run-after-exit)
-(make-obsolete 'helm-run-after-quit 'helm-run-after-exit "1.7.7")
-(defalias 'helm-quit-and-execute-action 'helm-exit-and-execute-action)
-(make-obsolete 'helm-quit-and-execute-action 'helm-exit-and-execute-action "1.7.7")
-
-(defun helm-interpret-value (value &optional source compute)
- "Interpret VALUE as variable, function or literal and return it.
-If VALUE is a function, call it with no arguments and return the value
-unless COMPUTE value is 'ignorefn.
-If SOURCE compute VALUE for this source.
-If VALUE is a variable, return the value.
-If VALUE is a symbol, but it is not a function or a variable, cause an error.
-Otherwise, return VALUE itself."
- (cond ((and source (functionp value) (not (eq compute 'ignorefn)))
- (helm-funcall-with-source source value))
- ((and (functionp value) (not (eq compute 'ignorefn)))
- (funcall value))
- ((and (symbolp value) (boundp value))
- (symbol-value value))
- ((and (symbolp value) (not (functionp value)))
- (error
- "helm-interpret-value: Symbol must be a function or a variable"))
- (t
- value)))
-
-(defun helm-set-local-variable (&rest args)
- "Bind each pair in ARGS locally to `helm-buffer'.
-
-Use this to set local vars before calling helm.
-
-When used from an init or update function
-(i.e when `helm-force-update' is running) the variables are set
-using `make-local-variable' within the `helm-buffer'.
-
-Usage: helm-set-local-variable ([VAR VALUE]...)
-Just like `setq' except that the vars are not set sequentially.
-IOW Don't use VALUE of previous VAR to set the VALUE of next VAR.
-
-\(fn VAR VALUE ...)"
- (if helm-force-updating-p
- (with-helm-buffer
- (cl-loop for i on args by #'cddr
- do (set (make-local-variable (car i)) (cadr i))))
- (setq helm--local-variables
- (append (cl-loop for i on args by #'cddr
- collect (cons (car i) (cadr i)))
- helm--local-variables))))
-
-\f
-;; Core: API helper
-(cl-defun helm-empty-buffer-p (&optional (buffer helm-buffer))
- "Check if BUFFER have candidates.
-Default value for BUFFER is `helm-buffer'."
- (zerop (buffer-size (and buffer (get-buffer buffer)))))
-
-(defun helm-empty-source-p ()
- "Check if current source contains candidates.
-This happen only in certains cases when e.g the last element
-of a source is deleted without updating the source."
- (with-helm-window
- (or (helm-empty-buffer-p)
- (and (helm-end-of-source-p)
- (eq (point-at-bol) (point-at-eol))
- (or
- (save-excursion
- (forward-line -1)
- (helm-pos-header-line-p))
- (bobp))))))
-
-\f
-;; Core: tools
-
-(defun helm-funcall-with-source (source functions &rest args)
- "Call from SOURCE FUNCTIONS list or single function FUNCTIONS with ARGS.
-FUNCTIONS can be a symbol or a list of functions.
-Return the result of last function call."
- (let ((helm-source-name (assoc-default 'name source))
- (helm-current-source source)
- (funs (if (functionp functions) (list functions) functions)))
- (helm-log "helm-source-name = %S" helm-source-name)
- (helm-log "functions = %S" functions)
- (helm-log "args = %S" args)
- (cl-loop with result for fn in funs
- do (setq result (apply fn args))
- finally return result)))
-
-(defun helm-funcall-foreach (sym &optional sources)
- "Call the associated function to SYM for each source if any."
- (let ((sources (or sources (helm-get-sources))))
- (cl-dolist (source sources)
- (helm-aif (assoc-default sym source)
- (helm-funcall-with-source source it)))))
-
-(defun helm-normalize-sources (sources)
- "If SOURCES is only one source, make a list of one element."
- (cond ((or (and sources
- (symbolp sources))
- (and (listp sources) (assq 'name sources)))
- (list sources))
- (sources)
- (t helm-sources)))
-
-(defun helm-get-candidate-number (&optional in-current-source)
- "Return candidates number in `helm-buffer'.
-If IN-CURRENT-SOURCE is provided return number of candidates
-in the source where point is."
- (with-helm-buffer
- (if (or (helm-empty-buffer-p)
- (helm-empty-source-p))
- 0
- (save-excursion
- (if in-current-source
- (goto-char (helm-get-previous-header-pos))
- (goto-char (point-min)))
- (forward-line 1)
- (if (helm-pos-multiline-p)
- (cl-loop with count-multi = 1
- while (and (not (if in-current-source
- (save-excursion
- (forward-line 2)
- (or (helm-pos-header-line-p) (eobp)))
- (eobp)))
- (search-forward helm-candidate-separator nil t))
- do (cl-incf count-multi)
- finally return count-multi)
- (cl-loop with ln = 0
- while (not (if in-current-source
- (or (helm-pos-header-line-p) (eobp))
- (eobp)))
- ;; Don't count empty lines maybe added by popup (#1370).
- unless (or (eq (point-at-bol) (point-at-eol))
- (helm-pos-header-line-p))
- do (cl-incf ln)
- do (forward-line 1) finally return ln))))))
-
-(defmacro with-helm-quittable (&rest body)
- "If an error occur in execution of BODY, quit helm safely."
- (declare (indent 0) (debug t))
- `(condition-case _v
- (let (inhibit-quit)
- ,@body)
- (quit (setq quit-flag t)
- (setq helm-quit t)
- (exit-minibuffer)
- (keyboard-quit)
- ;; See comment about this in `with-local-quit'.
- (eval '(ignore nil)))))
-
-(defun helm-compose (arg-lst func-lst)
- "Apply arguments specified in ARG-LST with each function of FUNC-LST.
-The result of each function will be the new `car' of ARG-LST.
-Each function in FUNC-LST must accept (length ARG-LST) arguments
-\(See examples below) .
-This function allows easy sequencing of transformer functions.
-Where generally, ARG-LST is '(candidates-list source) and FUNC-LST a
-list of transformer functions that take one or two arguments depending
-we are using 'filtered-candidate-transformer' or 'candidate-transformer'.
-e.g
-filtered-candidate-transformer:
-\(helm-compose '((1 2 3 4 5 6 7)
- '((name . \"A helm source\") (candidates . (a b c))))
- '((lambda (candidates _source)
- (cl-loop for i in candidates
- when (cl-oddp i) collect i))
- (lambda (candidates _source)
- (cl-loop for i in candidates collect (1+ i)))))
-=>(2 4 6 8)
-
-candidate-transformer:
-\(helm-compose '((1 2 3 4 5 6 7))
- '((lambda (candidates)
- (cl-loop for i in candidates
- when (cl-oddp i) collect i))
- (lambda (candidates)
- (cl-loop for i in candidates collect (1+ i)))))
-=> (2 4 6 8)."
- (cl-dolist (func func-lst)
- (setcar arg-lst (apply func arg-lst)))
- (car arg-lst))
-
-(defun helm-composed-funcall-with-source (source funcs &rest args)
- "With SOURCE apply `helm-funcall-with-source' with each FUNCS and ARGS.
-This is used in transformers to modify candidates list."
- (if (functionp funcs)
- (apply 'helm-funcall-with-source source funcs args)
- (apply 'helm-funcall-with-source source
- (lambda (&rest oargs) (helm-compose oargs funcs))
- args)))
-
-\f
-;; Core: entry point
-;; `:allow-nest' is not in this list because it is treated before.
-(defconst helm-argument-keys
- '(:sources :input :prompt :resume
- :preselect :buffer :keymap :default :history))
-
-;;;###autoload
-(defun helm (&rest plist)
- "Main function to execute helm sources.
-
-Keywords supported:
-:sources :input :prompt :resume :preselect
-:buffer :keymap :default :history :allow-nest
-
-Extra LOCAL-VARS keywords are supported, see below.
-
-PLIST is a list like \(:key1 val1 :key2 val2 ...\) or
-\(&optional sources input prompt resume
- preselect buffer keymap default history\).
-
-Basic keywords are the following:
-
-\:sources
-
-A list of sources used for this session. It also accepts a
-symbol, interpreted as a variable of a helm source
-i.e (a symbol can be passed instead of a list of sources).
-It also accepts an alist representing a helm source, which is
-detected by \(assq 'name ANY-SOURCES\).
-NOTE: In this case the source is embedded in the helm command and
-have no symbol name, so it is not reachable from outside.
-It will be referenced in `helm-sources' as a whole alist.
-
-\:input
-
-Temporary value of `helm-pattern', ie. initial input of minibuffer.
-
-\:prompt
-
-Prompt other than \"pattern: \".
-
-\:resume
-
-If t, Resurrect previously instance of `helm'. Skip the initialization.
-If 'noresume, this instance of `helm' cannot be resumed.
-
-\:preselect
-
-Initially selected candidate. Specified by exact candidate or a regexp.
-
-\:buffer
-
-`helm-buffer' instead of *helm*.
-
-\:keymap
-
-`helm-map' for current `helm' session.
-
-\:default
-
-A default argument that will be inserted in minibuffer \
-with \\<minibuffer-local-map>\\[next-history-element].
-When nil or not present `thing-at-point' will be used instead.
-If `helm--maybe-use-default-as-input' is non--nil display will be
-updated using :default arg as input unless :input is specified,
-which in this case will take precedence on :default
-This is a string or a list, in this case the car of the list will
-be used as initial default input, but you will be able to cycle in this
-list with \\<minibuffer-local-map>\\[next-history-element].
-
-\:history
-
-By default all minibuffer input is pushed to `minibuffer-history',
-if an argument HISTORY is provided, input will be pushed to HISTORY.
-History element should be a symbol.
-
-\:allow-nest
-
-Allow running this helm command within a running helm session.
-
-Of course, conventional arguments are supported, the two are same.
-
-\(helm :sources sources :input input :prompt prompt :resume resume
- :preselect preselect :buffer buffer :keymap keymap :default default
- :history history\)
-
-and
-
-\(helm sources input prompt resume preselect buffer keymap default history\)
-
-are the same.
-
-However the use of non keyword args is deprecated and should not be used.
-
-Other keywords are interpreted as local variables of this helm session.
-The `helm-' prefix can be omitted. For example,
-
-\(helm :sources 'helm-source-buffers-list
- :buffer \"*buffers*\" :candidate-number-limit 10\)
-
-means starting helm session with `helm-source-buffers'
-source in *buffers* buffer and set variable `helm-candidate-number-limit'
-to 10 as session local variable.
-
-\(fn &key SOURCES INPUT PROMPT RESUME PRESELECT BUFFER KEYMAP DEFAULT HISTORY ALLOW-NEST OTHER-LOCAL-VARS)"
- (let ((fn (cond ((or (and helm-alive-p (plist-get plist :allow-nest))
- (and helm-alive-p (memq 'allow-nest plist)))
- #'helm-nest)
- ((keywordp (car plist))
- #'helm)
- (t #'helm-internal))))
- (if (and helm-alive-p (eq fn #'helm))
- (if (helm-alive-p)
- ;; A helm session is normally running.
- (error "Error: Trying to run helm within a running helm session")
- ;; A helm session is already running and user jump somewhere else
- ;; without desactivating it.
- (with-helm-buffer
- (prog1
- (message "Aborting an helm session running in background")
- ;; `helm-alive-p' will be reset in unwind-protect forms.
- (helm-keyboard-quit))))
- (if (keywordp (car plist))
- ;; Parse `plist' and move not regular `helm-argument-keys'
- ;; to `helm--local-variables', then calling helm on itself
- ;; with normal arguments (the non--arguments-keys removed)
- ;; will end up in [1].
- (progn
- (setq helm--local-variables
- (append helm--local-variables
- ;; Vars passed by keyword on helm call
- ;; take precedence on same vars
- ;; that may have been passed before helm call.
- (helm-parse-keys plist)))
- (apply fn (mapcar (lambda (key) (plist-get plist key))
- helm-argument-keys)))
- (apply fn plist))))) ; [1] fn == helm-internal.
-
-(defun helm-alive-p ()
- "Check if `helm' is alive.
-An `helm' session is considered alive if `helm-alive-p' is non--nil,
-the `helm-buffer' is visible, and cursor is in minibuffer."
- (and helm-alive-p
- (get-buffer-window helm-buffer 'visible)
- (minibuffer-window-active-p (minibuffer-window))
- (minibufferp (current-buffer))))
-
-(defun helm-parse-keys (keys)
- "Parse the KEYS arguments of `helm'.
-Return only the keys that are not in `helm-argument-keys',
-prefix them with \"helm\" and convert them to alist.
-This allow to add arguments that are not part of `helm-argument-keys',
-but are valid helm variables.
-e.g :candidate-number-limit will be bound to `helm-candidate-number-limit'
-in source.
-
- (helm-parse-keys '(:sources ((name . \"test\")
- (candidates . (a b c)))
- :buffer \"toto\"
- :candidate-number-limit 4))
- ==> ((helm-candidate-number-limit . 4))."
-
- (cl-loop for (key value) on keys by #'cddr
- for symname = (substring (symbol-name key) 1)
- for sym = (intern (if (string-match "^helm-" symname)
- symname
- (concat "helm-" symname)))
- unless (memq key helm-argument-keys)
- collect (cons sym value)))
-
-;;; Core: entry point helper
-(defun helm-internal (&optional
- any-sources any-input
- any-prompt any-resume
- any-preselect any-buffer
- any-keymap any-default any-history)
- "The internal helm function called by `helm'.
-For ANY-SOURCES ANY-INPUT ANY-PROMPT ANY-RESUME ANY-PRESELECT ANY-BUFFER and
-ANY-KEYMAP ANY-DEFAULT ANY-HISTORY See `helm'."
- ;; Activate the advice for `tramp-read-passwd'.
- (if (fboundp 'advice-add)
- (progn
- (advice-add 'tramp-read-passwd :around #'helm--advice-tramp-read-passwd)
- (advice-add 'ange-ftp-get-passwd :around #'helm--advice-ange-ftp-get-passwd))
- (ad-activate 'tramp-read-passwd)
- (ad-activate 'ange-ftp-get-passwd))
- (helm-log (concat "[Start session] " (make-string 41 ?+)))
- (helm-log "any-prompt = %S" any-prompt)
- (helm-log "any-preselect = %S" any-preselect)
- (helm-log "any-buffer = %S" any-buffer)
- (helm-log "any-keymap = %S" any-keymap)
- (helm-log "any-default = %S" any-default)
- (helm-log "any-history = %S" any-history)
- (setq helm--prompt (or any-prompt "pattern: "))
- (let ((non-essential t)
- (input-method-verbose-flag helm-input-method-verbose-flag)
- (old--cua cua-mode)
- (helm--maybe-use-default-as-input
- (and (null any-input)
- (or helm--maybe-use-default-as-input ; it is let-bounded so use it.
- (cl-loop for s in (helm-normalize-sources any-sources)
- thereis (memq s helm-sources-using-default-as-input))))))
- ;; cua-mode overhide local helm bindings.
- ;; disable this stupid thing if enabled.
- (and cua-mode (cua-mode -1))
- (unwind-protect
- (condition-case-unless-debug _v
- (let ( ;; `helm-source-name' is non-nil
- ;; when `helm' is invoked by action, reset it.
- helm-source-name
- helm-current-source
- helm-in-persistent-action
- helm-quit
- (helm-buffer (or any-buffer helm-buffer)))
- (with-helm-restore-variables
- (helm-initialize
- any-resume any-input any-default any-sources)
- (helm-display-buffer helm-buffer)
- ;; We are now in helm-buffer.
- (when helm-prevent-escaping-from-minibuffer
- (helm--remap-mouse-mode 1)) ; Disable mouse bindings.
- (add-hook 'post-command-hook 'helm--maybe-update-keymap)
- (add-hook 'post-command-hook 'helm--update-header-line)
- (helm-log "show prompt")
- (unwind-protect
- (helm-read-pattern-maybe
- any-prompt any-input any-preselect
- any-resume any-keymap any-default any-history)
- (helm-cleanup)))
- (prog1
- (unless helm-quit (helm-execute-selection-action))
- (helm-log (concat "[End session] " (make-string 41 ?-)))))
- (quit
- (helm-restore-position-on-quit)
- (helm-log (concat "[End session (quit)] " (make-string 34 ?-)))
- nil))
- (if (fboundp 'advice-add)
- (progn
- (advice-remove 'tramp-read-passwd
- #'helm--advice-tramp-read-passwd)
- (advice-remove 'ange-ftp-get-passwd
- #'helm--advice-ange-ftp-get-passwd))
- (ad-deactivate 'tramp-read-passwd)
- (ad-deactivate 'ange-ftp-get-passwd))
- (helm-log "helm-alive-p = %S" (setq helm-alive-p nil))
- (helm--remap-mouse-mode -1) ; Reenable mouse bindings.
- (setq helm-alive-p nil)
- ;; Reset helm-pattern so that lambda's using it
- ;; before running helm will not start with its old value.
- (setq helm-pattern "")
- (and old--cua (cua-mode 1))
- (helm-log-save-maybe))))
-
-\f
-;;; Helm resume
-;;
-;;
-(defun helm-resume (arg)
- "Resurrect previously invoked `helm'.
-Called with a prefix arg, allow choosing among all existing
-helm buffers. i.e choose among various helm sessions.
-Called from lisp, you can specify a buffer-name as a string with ARG."
- (interactive "P")
- (let (any-buffer helm-full-frame cur-dir)
- (if arg
- (if (and (stringp arg) (bufferp (get-buffer arg)))
- (setq any-buffer arg)
- (setq any-buffer (helm-resume-select-buffer)))
- (setq any-buffer helm-last-buffer))
- (cl-assert any-buffer nil
- "helm-resume: No helm buffers found to resume")
- ;; Reset `cursor-type' to nil as it have been set to t
- ;; when quitting previous session.
- (with-current-buffer any-buffer (setq cursor-type nil))
- (setq helm-full-frame (buffer-local-value
- 'helm-full-frame (get-buffer any-buffer)))
- (setq helm-compiled-sources nil)
- (setq cur-dir (buffer-local-value
- 'default-directory (get-buffer any-buffer)))
- (setq helm-saved-selection nil
- helm-saved-action nil)
- (unless (buffer-live-p helm-current-buffer)
- ;; `helm-current-buffer' may have been killed.
- (setq helm-current-buffer (current-buffer)))
- ;; Restart with same `default-directory' value this session
- ;; was initially started with.
- (with-helm-default-directory cur-dir
- (helm
- :sources (buffer-local-value
- 'helm-sources (get-buffer any-buffer))
- :input (buffer-local-value 'helm-input-local (get-buffer any-buffer))
- :prompt (buffer-local-value 'helm--prompt (get-buffer any-buffer))
- :resume t
- :buffer any-buffer))))
-
-(defun helm-resume-previous-session-after-quit (arg)
- "Resume previous helm session within running helm."
- (interactive "p")
- (with-helm-alive-p
- (if (> (length helm-buffers) arg)
- (helm-run-after-exit `(lambda () (helm-resume (nth ,arg helm-buffers))))
- (message "No previous helm sessions to resume yet!"))))
-(put 'helm-resume-previous-session-after-quit 'helm-only t)
-
-(defun helm-resume-list-buffers-after-quit ()
- "List resumable helm buffers within running helm."
- (interactive)
- (with-helm-alive-p
- (if (> (length helm-buffers) 0)
- (helm-run-after-exit (lambda () (helm-resume t)))
- (message "No previous helm sessions to resume yet!"))))
-(put 'helm-resume-list-buffers-after-quit 'helm-only t)
-
-(defun helm-resume-p (any-resume)
- "Whether current helm session is resumed or not."
- (eq any-resume t))
-
-(defun helm-resume-select-buffer ()
- "Select an `helm-buffer' in `helm-buffers' list to resume a helm session.
-Return nil if no `helm-buffer' found."
- (when helm-buffers
- (or (helm :sources '(((name . "Resume helm buffer")
- (candidates . helm-buffers)
- (action . identity)))
- :resume 'noresume
- :buffer "*helm resume*")
- (keyboard-quit))))
-
-\f
-;;;###autoload
-(defun helm-other-buffer (any-sources any-buffer)
- "Simplified interface of `helm' with other `helm-buffer'.
-Call `helm' with only ANY-SOURCES and ANY-BUFFER as args."
- (helm :sources any-sources :buffer any-buffer))
-
-(defun helm-nest (&rest same-as-helm)
- "Allow calling `helm' whithin a running helm session.
-Arguments SAME-AS-HELM are the same as `helm', which see."
- (with-helm-window
- (let ((orig-helm-current-buffer helm-current-buffer)
- (orig-helm-buffer helm-buffer)
- (orig-helm--prompt helm--prompt)
- (orig-helm--in-fuzzy helm--in-fuzzy)
- (orig-helm-last-frame-or-window-configuration
- helm-last-frame-or-window-configuration)
- (orig-one-window-p helm-onewindow-p))
- (unwind-protect
- (let (helm-current-position
- helm-current-buffer
- helm-pattern
- (helm-buffer (or (cl-getf same-as-helm :buffer)
- (nth 5 same-as-helm)
- "*Helm*"))
- helm-sources
- helm-compiled-sources
- (helm-full-frame t)
- (enable-recursive-minibuffers t))
- (apply #'helm same-as-helm))
- (with-current-buffer orig-helm-buffer
- (setq helm-alive-p t) ; Nested session set this to nil on exit.
- (setq helm-buffer orig-helm-buffer)
- (setq helm--prompt orig-helm--prompt)
- (setq helm--in-fuzzy orig-helm--in-fuzzy)
- (helm-initialize-overlays helm-buffer)
- (unless (helm-empty-buffer-p) (helm-mark-current-line t))
- (setq helm-last-frame-or-window-configuration
- orig-helm-last-frame-or-window-configuration)
- (setq cursor-type nil)
- (setq helm-current-buffer orig-helm-current-buffer)
- (setq helm-onewindow-p orig-one-window-p)
- ;; Be sure advices, hooks, and local modes keep running.
- (if (fboundp 'advice-add)
- (progn
- (advice-add 'tramp-read-passwd
- :around #'helm--advice-tramp-read-passwd)
- (advice-add 'ange-ftp-get-passwd
- :around #'helm--advice-ange-ftp-get-passwd))
- (ad-activate 'tramp-read-passwd)
- (ad-activate 'ange-ftp-get-passwd))
- (when helm-prevent-escaping-from-minibuffer
- (helm--remap-mouse-mode 1))
- (unless (cl-loop for h in post-command-hook
- thereis (memq h '(helm--maybe-update-keymap
- helm--update-header-line)))
- (add-hook 'post-command-hook 'helm--maybe-update-keymap)
- (add-hook 'post-command-hook 'helm--update-header-line))
- (helm-display-mode-line (helm-get-current-source)))))))
-
-\f
-;;; Core: Accessors
-;;
-(defun helm-current-position (save-or-restore)
- "Restore or save current position in `helm-current-buffer'.
-Argument SAVE-OR-RESTORE is one of save or restore."
- (cl-case save-or-restore
- (save
- (helm-log "Save position at %S" (cons (point) (window-start)))
- (setq helm-current-position (cons (point) (window-start))))
- (restore
- ;; Maybe `helm-current-buffer' have been deleted
- ;; during helm session so check if it is here
- ;; otherwise position in underlaying buffer will be lost.
- (when (get-buffer-window helm-current-buffer 'visible)
- (helm-log "Restore position at %S in buffer %s"
- helm-current-position
- (buffer-name (current-buffer)))
- (goto-char (car helm-current-position))
- ;; Fix this position with the NOFORCE arg of `set-window-start'
- ;; otherwise, if there is some other buffer than `helm-current-buffer'
- ;; one, position will be lost.
- (set-window-start (selected-window) (cdr helm-current-position) t)))))
-
-
-(defun helm-frame-or-window-configuration (save-or-restore)
- "Save or restore last frame or window configuration.
-Possible value of SAVE-OR-RESTORE are 'save and 'restore.
-window or frame configuration is saved/restored according to values of
-`helm-save-configuration-functions'."
- (helm-log "helm-save-configuration-functions = %S"
- helm-save-configuration-functions)
- (let ((window-persistent-parameters (append '((no-other-window . t))
- window-persistent-parameters)))
- (cl-case save-or-restore
- (save (setq helm-last-frame-or-window-configuration
- (funcall (cdr helm-save-configuration-functions))))
- (restore (funcall (car helm-save-configuration-functions)
- helm-last-frame-or-window-configuration)
- ;; Restore frame focus.
- ;; This is needed for minibuffer own-frame config
- ;; when recursive minibuffers are in use.
- ;; e.g M-: + helm-minibuffer-history.
- (let ((frame (if (minibufferp helm-current-buffer)
- (selected-frame)
- (last-nonminibuffer-frame))))
- (select-frame-set-input-focus frame))))))
-
-(defun helm-split-window-default-fn (window)
- (let (split-width-threshold)
- (if (and (fboundp 'window-in-direction)
- ;; Don't try to split when starting in a minibuffer
- ;; e.g M-: and try to use helm-show-kill-ring.
- (not (minibufferp helm-current-buffer)))
- (if (or (one-window-p t)
- helm-split-window-in-side-p)
- (split-window
- (selected-window) nil (if (eq helm-split-window-default-side 'other)
- 'below helm-split-window-default-side))
- ;; If more than one window reuse one of them.
- (cl-case helm-split-window-default-side
- (left (or (helm-window-in-direction 'left)
- (helm-window-in-direction 'above)
- (selected-window)))
- (above (or (helm-window-in-direction 'above)
- (helm-window-in-direction 'left)
- (selected-window)))
- (right (or (helm-window-in-direction 'right)
- (helm-window-in-direction 'below)
- (selected-window)))
- (below (or (helm-window-in-direction 'below)
- (helm-window-in-direction 'right)
- (selected-window)))
- (same (selected-window))
- (other (other-window-for-scrolling))
- (t (or (window-next-sibling) (selected-window)))))
- (split-window-sensibly window))))
-
-(defun helm-window-in-direction (direction)
- "Same as `window-in-direction' but check if window is dedicated."
- (helm-aif (window-in-direction direction)
- (and (not (window-dedicated-p it)) it)))
-
-\f
-;;; Display helm buffer
-;;
-;;
-(defun helm-display-buffer (buffer)
- "Display BUFFER.
-The function used to display `helm-buffer'."
- (let (pop-up-frames
- (split-window-preferred-function
- helm-split-window-preferred-function)
- (helm-split-window-default-side
- (if (and (not helm-full-frame)
- helm-reuse-last-window-split-state)
- (cond ((eq helm-split-window-default-side 'same) 'same)
- ((eq helm-split-window-default-side 'other) 'other)
- (helm--window-side-state)
- (t helm-split-window-default-side))
- helm-split-window-default-side)))
- (prog1
- (funcall (with-current-buffer buffer helm-display-function) buffer)
- (setq helm-onewindow-p (one-window-p t))
- ;; Don't allow other-window and friends switching out of minibuffer.
- (when helm-prevent-escaping-from-minibuffer
- (helm-prevent-switching-other-window)))))
-
-(cl-defun helm-prevent-switching-other-window (&key (enabled t))
- "Allow setting `no-other-window' window parameter in all windows.
-Arg ENABLE will be the value of the `no-other-window' window property."
- (walk-windows
- (lambda (w)
- (unless (window-dedicated-p w)
- (set-window-parameter w 'no-other-window enabled)))
- 0))
-
-(defun helm-default-display-buffer (buffer)
- "Default function to display `helm-buffer' BUFFER.
-It uses `switch-to-buffer' or `display-buffer' depending of value
-of `helm-full-frame' and/or `helm-split-window-default-side'."
- (if (or (buffer-local-value 'helm-full-frame (get-buffer buffer))
- (and (eq helm-split-window-default-side 'same)
- (one-window-p t)))
- (progn (delete-other-windows) (switch-to-buffer buffer))
- (when (and (or helm-always-two-windows helm-autoresize-mode
- (and (not helm-split-window-in-side-p)
- (eq (save-selected-window
- (funcall helm-split-window-preferred-function
- (selected-window)))
- (get-buffer-window helm-current-buffer))))
- (not (eq helm-split-window-default-side 'same))
- (not (minibufferp helm-current-buffer))
- (not helm-split-window-in-side-p))
- (delete-other-windows))
- (display-buffer
- buffer `(nil . ((window-height . ,helm-display-buffer-default-size))))))
-
-\f
-;;; Core: initialize
-;;
-(defun helm-initialize (any-resume any-input any-default any-sources)
- "Start initialization of `helm' session.
-For ANY-RESUME ANY-INPUT ANY-DEFAULT and ANY-SOURCES See `helm'."
- (helm-log "start initialization: any-resume=%S any-input=%S"
- any-resume any-input)
- (helm-frame-or-window-configuration 'save)
- (setq helm-sources (helm-normalize-sources any-sources))
- (setq helm--in-fuzzy
- (cl-loop for s in helm-sources
- for matchfns = (helm-match-functions
- (if (symbolp s) (symbol-value s) s))
- for searchfns = (helm-search-functions
- (if (symbolp s) (symbol-value s) s))
- when (or (member 'helm-fuzzy-match matchfns)
- (member 'helm-fuzzy-search searchfns))
- return t))
- (helm-log "sources = %S" helm-sources)
- (helm-current-position 'save)
- (if (helm-resume-p any-resume)
- (helm-initialize-overlays (helm-buffer-get))
- (helm-initial-setup any-default))
- (setq helm-alive-p t)
- (unless (eq any-resume 'noresume)
- (helm-recent-push helm-buffer 'helm-buffers)
- (setq helm-last-buffer helm-buffer))
- (when any-input
- (setq helm-input any-input
- helm-pattern any-input)
- (helm--fuzzy-match-maybe-set-pattern))
- ;; If a `resume' attribute is present `helm-funcall-foreach'
- ;; will run its function.
- (when (helm-resume-p any-resume)
- (helm-funcall-foreach 'resume))
- (helm-log "end initialization"))
-
-(defun helm-initialize-overlays (buffer)
- "Initialize helm overlays in BUFFER."
- (helm-log "overlay setup")
- (if helm-selection-overlay
- ;; make sure the overlay belongs to the helm buffer if
- ;; it's newly created
- (move-overlay helm-selection-overlay (point-min) (point-min)
- (get-buffer buffer))
-
- (setq helm-selection-overlay
- (make-overlay (point-min) (point-min) (get-buffer buffer)))
- (overlay-put helm-selection-overlay 'face 'helm-selection)
- (overlay-put helm-selection-overlay 'priority 1)))
-
-(defun helm-restore-position-on-quit ()
- "Restore position in `helm-current-buffer' when quitting."
- (helm-current-position 'restore))
-
-(defun helm-recent-push (elt list-var)
- "Add ELT to the value of LIST-VAR as most recently used value."
- (let ((m (member elt (symbol-value list-var))))
- (and m (set list-var (delq (car m) (symbol-value list-var))))
- (push elt (symbol-value list-var))))
-
-(defun helm--current-buffer ()
- "[internal] Return `current-buffer' BEFORE `helm-buffer' is initialized.
-Note that this will return the minibuffer in use after helm have started,
-so to get the buffer where helm started while in a helm session,
-use `helm-current-buffer'.
-It is intended to use this only in `helm-initial-setup'."
- (if (minibuffer-window-active-p (minibuffer-window))
- ;; If minibuffer is active be sure to use it's buffer
- ;; as `helm-current-buffer', this allow to use helm
- ;; from an already active minibuffer (M-: etc...)
- (window-buffer (active-minibuffer-window))
- ;; Fix Issue #456
- ;; Use this instead of `current-buffer' to ensure
- ;; helm session started in helm-mode from a completing-read
- ;; Use really the buffer where we started and not the one
- ;; where the completing-read is wrapped. i.e
- ;; (with-current-buffer SOME-OTHER-BUFFER (completing-read [...])
- (window-buffer (with-selected-window (minibuffer-window)
- (minibuffer-selected-window)))))
-
-(defun helm--run-init-hooks (hook)
- "Run after and before init hooks local to source.
-See :after-init-hook and :before-init-hook in `helm-source'."
- (cl-loop with sname = (cl-ecase hook
- (before-init-hook "h-before-init-hook")
- (after-init-hook "h-after-init-hook"))
- with h = (cl-gensym sname)
- for s in (helm-get-sources)
- for hv = (assoc-default hook s)
- if (and hv (not (symbolp hv)))
- do (set h hv)
- and do (helm-log-run-hook h)
- else do (helm-log-run-hook hv)))
-
-(defun helm-initial-setup (any-default)
- "Initialize helm settings and set up the helm buffer."
- ;; Run global hook.
- (helm-log-run-hook 'helm-before-initialize-hook)
- ;; Run local source hook.
- (helm--run-init-hooks 'before-init-hook)
- ;; For initialization of helm locals vars that need
- ;; a value from current buffer, it is here.
- (helm-set-local-variable 'current-input-method current-input-method)
- (setq helm-current-prefix-arg nil
- helm-saved-action nil
- helm-saved-selection nil
- helm-suspend-update-flag nil
- helm-current-buffer (helm--current-buffer)
- helm-buffer-file-name buffer-file-name
- helm-issued-errors nil
- helm-compiled-sources nil
- helm-saved-current-source nil)
- (unless (and (or helm-split-window-state
- helm--window-side-state)
- helm-reuse-last-window-split-state)
- (setq helm-split-window-state
- (if (or (null split-width-threshold)
- (and (integerp split-width-threshold)
- (>= split-width-threshold (+ (frame-width) 4))))
- 'vertical 'horizontal))
- (setq helm--window-side-state
- (or helm-split-window-default-side 'below)))
- ;; Call the init function for sources where appropriate
- (helm-funcall-foreach
- 'init (and helm-source-filter
- (cl-remove-if-not (lambda (s)
- (member (assoc-default 'name s)
- helm-source-filter))
- (helm-get-sources))))
- (setq helm-pattern (or (and helm--maybe-use-default-as-input
- (or (if (listp any-default)
- (car any-default) any-default)
- (with-helm-current-buffer
- (thing-at-point 'symbol))))
- ""))
- (setq helm-input "")
- (clrhash helm-candidate-cache)
- (helm-create-helm-buffer)
- (helm-clear-visible-mark)
- ;; Run global hook.
- (helm-log-run-hook 'helm-after-initialize-hook)
- ;; Run local source hook.
- (helm--run-init-hooks 'after-init-hook))
-
-(defun helm-create-helm-buffer ()
- "Create and setup `helm-buffer'."
- (let ((root-dir default-directory))
- (with-current-buffer (get-buffer-create helm-buffer)
- (helm-log "kill local variables: %S" (buffer-local-variables))
- (kill-all-local-variables)
- (set (make-local-variable 'inhibit-read-only) t)
- (buffer-disable-undo)
- (erase-buffer)
- (set (make-local-variable 'helm-map) helm-map)
- (make-local-variable 'helm-sources)
- (set (make-local-variable 'helm-follow-mode) nil)
- (set (make-local-variable 'helm-display-function) helm-display-function)
- (set (make-local-variable 'helm-selection-point) nil)
- (set (make-local-variable 'scroll-margin)
- (if helm-display-source-at-screen-top
- 0 helm-completion-window-scroll-margin))
- (set (make-local-variable 'default-directory) root-dir)
- (set (make-local-variable 'helm-marked-candidates) nil)
- (set (make-local-variable 'helm--prompt) helm--prompt)
- (helm-initialize-persistent-action)
- (helm-log "helm-display-function = %S" helm-display-function)
- (helm-log "helm--local-variables = %S" helm--local-variables)
- (cl-loop for (var . val) in helm--local-variables
- do (set (make-local-variable var) val)
- finally (setq helm--local-variables nil))
- (setq truncate-lines helm-truncate-lines) ; already local.
- (setq cursor-type nil)
- (setq mode-name "Helm"))
- (helm-initialize-overlays helm-buffer)
- (get-buffer helm-buffer)))
-
-(define-minor-mode helm--minor-mode
- "[INTERNAL] Enable keymap in helm minibuffer.
-This mode have no effect when run outside of helm context.
-Please don't use it.
-
-\\{helm-map}"
- :group 'helm
- :keymap (and helm-alive-p helm-map)
- (unless helm-alive-p (setq helm--minor-mode nil)))
-
-(defun helm--reset-default-pattern ()
- (setq helm-pattern "")
- (setq helm--maybe-use-default-as-input nil))
-
-(defun helm-read-pattern-maybe (any-prompt any-input
- any-preselect any-resume any-keymap
- any-default any-history)
- "Read pattern with prompt ANY-PROMPT and initial input ANY-INPUT.
-For ANY-PRESELECT ANY-RESUME ANY-KEYMAP ANY-DEFAULT ANY-HISTORY, See `helm'."
- (if (and (helm-resume-p any-resume)
- ;; When no source, helm-buffer is empty
- ;; or contain non--candidate lines (e.g grep exit status)
- (helm-get-current-source))
- (helm-mark-current-line t)
- (helm-update any-preselect))
- (with-current-buffer (helm-buffer-get)
- (let* ((src (helm-get-current-source))
- (src-keymap (assoc-default 'keymap src))
- (hist (or (and any-history (symbolp any-history) any-history)
- ;; Needed for resuming.
- (assoc-default 'history src)))
- (timer nil)
- blink-matching-paren
- (resize-mini-windows (and (null helm-echo-input-in-header-line)
- resize-mini-windows))
- (first-src (car helm-sources))
- (first-src-val (if (symbolp first-src)
- (symbol-value first-src)
- first-src))
- (source-process-p (or (assq 'candidates-process src)
- (assq 'candidates-process first-src-val)))
- (source-delayed-p (or (assq 'delayed src)
- (assq 'delayed first-src-val))))
- (helm-log "helm-get-candidate-number => %S"
- (helm-get-candidate-number))
- (helm-log "helm-execute-action-at-once-if-one = %S"
- helm-execute-action-at-once-if-one)
- (helm-log "helm-quit-if-no-candidate = %S" helm-quit-if-no-candidate)
- ;; If source is delayed `helm-execute-action-at-once-if-one'
- ;; and `helm-quit-if-no-candidate' are handled after update finish.
- (when source-delayed-p
- ;; Note that we quickly add the hook now when `helm-update'
- ;; is already started, but because source is delayed the hook
- ;; should have the time to be passed !!!
- ;; the hook will remove itself once done.
- (with-helm-after-update-hook (helm-exit-or-quit-maybe)))
- ;; Reset `helm-pattern' for non--delayed sources and update
- ;; display if no result found with precedent value of `helm-pattern'
- ;; unless `helm-quit-if-no-candidate' is non--nil, in this case
- ;; Don't force update with an empty pattern.
- ;; Reset also `helm--maybe-use-default-as-input' as this checking
- ;; happen only on startup.
- (when helm--maybe-use-default-as-input
- ;; Store value of `default' temporarily here waiting next update
- ;; to allow actions like helm-moccur-action matching pattern
- ;; at the place it jump to.
- (setq helm-input helm-pattern)
- (if (or source-delayed-p source-process-p)
- ;; Reset pattern to next update.
- (with-helm-after-update-hook
- (helm--reset-default-pattern))
- ;; Reset pattern right now.
- (helm--reset-default-pattern))
- ;; Ensure force-update when no candidates
- ;; when we start with an empty pattern.
- (and (helm-empty-buffer-p)
- (null helm-quit-if-no-candidate)
- (helm-force-update)))
- ;; Handle `helm-execute-action-at-once-if-one' and
- ;; `helm-quit-if-no-candidate' now only for not--delayed sources.
- (cond ((and (if (functionp helm-execute-action-at-once-if-one)
- (funcall helm-execute-action-at-once-if-one)
- helm-execute-action-at-once-if-one)
- (not source-delayed-p)
- (= (helm-get-candidate-number) 1))
- (ignore)) ; Don't enter the minibuffer loop.
- ((and helm-quit-if-no-candidate
- (not source-delayed-p)
- (= (helm-get-candidate-number) 0))
- (setq helm-quit t)
- (and (functionp helm-quit-if-no-candidate)
- (funcall helm-quit-if-no-candidate)))
- (t ; Enter now minibuffer and wait for input.
- (let ((tap (or any-default
- (with-helm-current-buffer
- (thing-at-point 'symbol)))))
- (unwind-protect
- (minibuffer-with-setup-hook
- (lambda ()
- ;; Start minor-mode with global value of helm-map.
- (helm--minor-mode 1)
- ;; Now overhide the global value of `helm-map' with
- ;; the local one which is in this order:
- ;; - The keymap of current source.
- ;; - The value passed in ANY-KEYMAP
- ;; which will become buffer local.
- ;; - Or fallback to the global value of helm-map.
- (helm--maybe-update-keymap
- (or src-keymap any-keymap helm-map))
- (helm-log-run-hook 'helm-minibuffer-set-up-hook)
- (setq timer
- (run-with-idle-timer
- (max helm-input-idle-delay 0.001) 'repeat
- (lambda ()
- ;; Stop updating in persistent action
- ;; or when `helm-suspend-update-flag'
- ;; is non--nil.
- (unless (or helm-in-persistent-action
- helm-suspend-update-flag)
- (save-selected-window
- (helm-check-minibuffer-input)
- (helm-print-error-messages))))))
- (helm--update-header-line)) ; minibuffer has already been filled here
- (read-from-minibuffer (or any-prompt "pattern: ")
- any-input helm-map
- nil hist tap
- helm-inherit-input-method))
- (when timer (cancel-timer timer) (setq timer nil)))))))))
-
-(defun helm-exit-or-quit-maybe ()
- "Exit and run default action if only one candidate, quit if no candidates.
-This function is handling `helm-execute-action-at-once-if-one' and
-`helm-quit-if-no-candidate' in delayed sources."
- (with-helm-window
- (cond ((and (if (functionp helm-execute-action-at-once-if-one)
- (funcall helm-execute-action-at-once-if-one)
- helm-execute-action-at-once-if-one)
- (= (helm-get-candidate-number) 1))
- (helm-exit-minibuffer))
- ((and helm-quit-if-no-candidate
- (= (helm-get-candidate-number) 0))
- (setq helm-quit t)
- (and (functionp helm-quit-if-no-candidate)
- (funcall helm-quit-if-no-candidate))
- (keyboard-quit)))))
-
-(defun helm-toggle-suspend-update ()
- "Enable or disable update of display in helm.
-This can be useful for e.g writing quietly a complex regexp."
- (interactive)
- (with-helm-alive-p
- (when (setq helm-suspend-update-flag (not helm-suspend-update-flag))
- (helm-kill-async-processes)
- (setq helm-pattern ""))
- (message (if helm-suspend-update-flag
- "Helm update suspended!"
- "Helm update reenabled!"))))
-(put 'helm-toggle-suspend-update 'helm-only t)
-
-(defadvice tramp-read-passwd (around disable-helm-update)
- ;; Suspend update when prompting for a tramp password.
- (setq helm-suspend-update-flag t)
- (setq overriding-terminal-local-map nil)
- (setq helm--reading-passwd-or-string t)
- (let (stimers)
- (unwind-protect
- (progn
- (setq stimers (with-timeout-suspend))
- ad-do-it)
- (with-timeout-unsuspend stimers)
- (setq helm--reading-passwd-or-string nil)
- (setq helm-suspend-update-flag nil))))
-
-(defun helm--advice-tramp-read-passwd (old--fn &rest args)
- ;; Suspend update when prompting for a tramp password.
- (setq helm-suspend-update-flag t)
- (setq overriding-terminal-local-map nil)
- (setq helm--reading-passwd-or-string t)
- (unwind-protect
- ;; No need to suspend timer in emacs-24.4
- ;; it is fixed upstream.
- (apply old--fn args)
- (setq helm--reading-passwd-or-string nil)
- (setq helm-suspend-update-flag nil)))
-
-(defun helm--advice-ange-ftp-get-passwd (old--fn &rest args)
- ;; Suspend update when prompting for a ange password.
- (setq helm-suspend-update-flag t)
- (setq overriding-terminal-local-map nil)
- (setq helm--reading-passwd-or-string t)
- (unwind-protect
- (apply old--fn args)
- (setq helm--reading-passwd-or-string nil)
- (setq helm-suspend-update-flag nil)))
-
-(defadvice ange-ftp-get-passwd (around disable-helm-update)
- ;; Suspend update when prompting for a ange password.
- (setq helm-suspend-update-flag t)
- (setq overriding-terminal-local-map nil)
- (setq helm--reading-passwd-or-string t)
- (unwind-protect
- ad-do-it
- (setq helm--reading-passwd-or-string nil)
- (setq helm-suspend-update-flag nil)))
-
-(defun helm--maybe-update-keymap (&optional map)
- "Handle differents keymaps in multiples sources.
-
-It will override `helm-map' with the local map of current source.
-If no map is found in current source do nothing (keep previous map)."
- (with-helm-buffer
- (helm-aif (or map (assoc-default 'keymap (helm-get-current-source)))
- ;; We used a timer in the past to leave
- ;; enough time to helm to setup its keymap
- ;; when changing source from a recursive minibuffer.
- ;; e.g C-x C-f M-y C-g
- ;; => *find-files have now the bindings of *kill-ring.
- ;; It is no more true now we are using `minor-mode-overriding-map-alist'
- ;; and `helm--minor-mode' thus it fix issue #1076 for emacs-24.3
- ;; where concurrent timers are not supported.
- ;; i.e update keymap+check input.
- (with-current-buffer (window-buffer (minibuffer-window))
- (setq minor-mode-overriding-map-alist `((helm--minor-mode . ,it)))))))
-
-;;; Prevent loosing focus when using mouse.
-;;
-(defvar helm--remap-mouse-mode-map
- (let ((map (make-sparse-keymap)))
- (cl-loop for k in '([mouse-1] [mouse-2] [mouse-3]
- [down-mouse-1] [down-mouse-2] [down-mouse-3]
- [drag-mouse-1] [drag-mouse-2] [drag-mouse-3]
- [double-mouse-1] [double-mouse-2] [double-mouse-3]
- [triple-mouse-1] [triple-mouse-2] [triple-mouse-3])
- do (define-key map k 'undefined))
- map))
-
-(define-minor-mode helm--remap-mouse-mode
- "[INTERNAL] Prevent escaping helm minibuffer with mouse clicks.
-Do nothing when used outside of helm context.
-
-WARNING: Do not use this mode yourself, it is internal to helm."
- :group 'helm
- :global t
- :keymap helm--remap-mouse-mode-map
- (unless helm-alive-p
- (setq helm--remap-mouse-mode-map nil)))
-\f
-;; Core: clean up
-
-(defun helm-cleanup ()
- "Clean up the mess when helm exit or quit."
- (helm-log "start cleanup")
- (with-current-buffer helm-buffer
- ;; bury-buffer from this window.
- (bury-buffer) ;[1]
- (remove-hook 'post-command-hook 'helm--maybe-update-keymap)
- (remove-hook 'post-command-hook 'helm--update-header-line)
- ;; Be sure we call this from helm-buffer.
- (helm-funcall-foreach 'cleanup))
- (helm-kill-async-processes)
- ;; Remove the temporary hooks added
- ;; by `with-helm-temp-hook' that
- ;; may not have been consumed.
- (when helm--temp-hooks
- (cl-loop for (fn . hook) in helm--temp-hooks
- do (set hook (delete fn (symbol-value hook)))))
- ;; When running helm from a dedicated frame
- ;; with no minibuffer, helm will run in the main frame
- ;; which have a minibuffer, so be sure to disable
- ;; the `no-other-window' prop there.
- (helm-prevent-switching-other-window :enabled nil)
- (helm-log-run-hook 'helm-cleanup-hook)
- (helm-frame-or-window-configuration 'restore)
- ;; [1] now bury-buffer from underlying windows otherwise,
- ;; if this window is killed the underlying buffer will
- ;; be a helm buffer.
- (replace-buffer-in-windows helm-buffer)
- (setq helm-alive-p nil)
- (setq helm-debug nil)
- ;; This is needed in some cases where last input
- ;; is yielded infinitely in minibuffer after helm session.
- (helm-clean-up-minibuffer))
-
-(defun helm-clean-up-minibuffer ()
- "Remove contents of minibuffer."
- (let ((miniwin (minibuffer-window)))
- ;; Clean only current minibuffer used by helm.
- ;; i.e The precedent one is active.
- (unless (minibuffer-window-active-p miniwin)
- (with-current-buffer (window-buffer miniwin)
- (delete-minibuffer-contents)))))
-
-\f
-;;; Core: input handling
-;;
-;;
-(defun helm-check-minibuffer-input ()
- "Check minibuffer content."
- (with-helm-quittable
- (with-selected-window (or (active-minibuffer-window)
- (minibuffer-window))
- (helm-check-new-input (minibuffer-contents)))))
-
-(defun helm-check-new-input (input)
- "Check INPUT string and update the helm buffer if necessary."
- ;; First time minibuffer is entered
- ;; we check value of `helm-pattern' that have been set
- ;; in `helm-initial-setup' when `helm--maybe-use-default-as-input'
- ;; is non--nil. After this initial check, reset
- ;; `helm--maybe-use-default-as-input' and ignore this.
- ;; This happen only when source is `delayed'.
- (when helm--maybe-use-default-as-input ; nil when non--delayed.
- (setq input helm-pattern))
- (unless (equal input helm-pattern)
- (setq helm-pattern input)
- (unless (helm-action-window)
- (setq helm-input helm-pattern))
- (helm-log "helm-pattern = %S" helm-pattern)
- (helm-log "helm-input = %S" helm-input)
- (setq helm--in-update t)
- (helm-update)))
-
-(defun helm--reset-update-flag ()
- (run-with-idle-timer
- helm-exit-idle-delay nil
- (lambda () (setq helm--in-update nil))))
-
-(add-hook 'helm-after-update-hook #'helm--reset-update-flag)
-
-\f
-;;; Core: source compiler
-;;
-;;
-(defun helm-compile-sources (sources funcs)
- "Compile SOURCES with FUNCS.
-See `helm-compile-source-functions'.
-Helm plug-ins are realized by this function."
- (mapcar
- (lambda (source)
- (cl-loop with src = (if (listp source) source (symbol-value source))
- for noplug = (assoc 'dont-plug src)
- for f in funcs
- unless (and noplug (memq f (cdr noplug)))
- do (setq src (funcall f src))
- finally (cl-return src)))
- sources))
-
-\f
-;; Core: all candidates
-
-(defun helm-get-candidates (source)
- "Retrieve and return the list of candidates from SOURCE."
- (let* (inhibit-quit
- (candidate-fn (assoc-default 'candidates source))
- (candidate-proc (assoc-default 'candidates-process source))
- (type-error (lambda ()
- (error
- "`%s' must either be a function, a variable or a list"
- (or candidate-fn candidate-proc))))
- (candidates (condition-case-unless-debug err
- ;; Process candidates-(process) function
- ;; It may return a process or a list of candidates.
- (if candidate-proc
- ;; Calling `helm-interpret-value' with no
- ;; SOURCE arg force the use of `funcall'
- ;; and not `helm-funcall-with-source'.
- (helm-interpret-value candidate-proc)
- (helm-interpret-value candidate-fn source))
- (error (helm-log "Error: %S" err) nil))))
- (when (and (processp candidates) (not candidate-proc))
- (warn "Candidates function `%s' should be called in a `candidates-process' attribute"
- candidate-fn))
- (cond ((processp candidates)
- ;; Candidates will be filtered later in process filter.
- candidates)
- ((or (null candidates)
- ;; Can happen when the output of a process
- ;; is empty, and the candidates function call
- ;; something like (split-string (buffer-string) "\n")
- ;; which result in a list of one empty string (Issue #938).
- ;; e.g (completing-read "test: " '(""))
- (equal candidates '("")))
- nil)
- ((listp candidates)
- ;; Transform candidates with `candidate-transformer' functions if
- ;; some, otherwise return candidates.
- (helm-transform-candidates candidates source))
- (t (funcall type-error)))))
-
-(defmacro helm-while-no-input (&rest body)
- "Same as `while-no-input' but without testing with `input-pending-p'."
- (declare (debug t) (indent 0))
- (let ((catch-sym (make-symbol "input"))
- inhibit-quit)
- `(with-local-quit
- (catch ',catch-sym
- (let ((throw-on-input ',catch-sym))
- ,@body)))))
-
-(defun helm-get-cached-candidates (source)
- "Return the cached value of candidates for SOURCE.
-Cache the candidates if there is not yet a cached value."
- (let* ((name (assoc-default 'name source))
- (candidate-cache (gethash name helm-candidate-cache)))
- (helm-aif candidate-cache
- (prog1 it (helm-log "Use cached candidates"))
- (helm-log "No cached candidates, calculate candidates")
- (let ((candidates (helm-get-candidates source)))
- (cond ((processp candidates)
- (push (cons candidates
- (append source
- (list (cons 'item-count 0)
- (cons 'incomplete-line ""))))
- helm-async-processes)
- (set-process-filter candidates 'helm-output-filter)
- (setq candidates nil))
- ((not (assoc 'volatile source))
- (puthash name candidates helm-candidate-cache)))
- candidates))))
-
-\f
-;;; Core: candidate transformers
-
-(defun helm-process-candidate-transformer (candidates source)
- "Execute `candidate-transformer' function(s) on CANDIDATES in SOURCE."
- (helm-aif (assoc-default 'candidate-transformer source)
- (helm-composed-funcall-with-source source it candidates)
- candidates))
-
-(defun helm-process-filtered-candidate-transformer (candidates source)
- "Execute `filtered-candidate-transformer' function(s) on CANDIDATES in SOURCE."
- (helm-aif (assoc-default 'filtered-candidate-transformer source)
- (helm-composed-funcall-with-source source it candidates source)
- candidates))
-
-(defmacro helm--maybe-process-filter-one-by-one-candidate (candidate source)
- "Execute `filter-one-by-one' function(s) on CANDIDATE in SOURCE."
- `(helm-aif (assoc-default 'filter-one-by-one ,source)
- (if (and (listp it)
- (not (functionp it))) ;; Don't treat lambda's as list.
- (cl-loop for f in it
- do (setq ,candidate (funcall f ,candidate))
- finally return ,candidate)
- (setq ,candidate (funcall it ,candidate)))
- ,candidate))
-
-(defun helm--initialize-one-by-one-candidates (candidates source)
- "Process the CANDIDATES with the `filter-one-by-one' function in SOURCE.
-Return CANDIDATES when pattern is empty."
- (helm-aif (and (string= helm-pattern "")
- (assoc-default 'filter-one-by-one source))
- (cl-loop for cand in candidates collect
- (helm--maybe-process-filter-one-by-one-candidate cand source))
- candidates))
-
-(defun helm-process-filtered-candidate-transformer-maybe
- (candidates source process-p)
- "Execute `filtered-candidate-transformer' function(s) on CANDIDATES in SOURCE.
-When PROCESS-P is non-nil execute `filtered-candidate-transformer'
-functions if some, otherwise return CANDIDATES."
- (if process-p
- ;; When no filter return CANDIDATES unmodified.
- (helm-process-filtered-candidate-transformer candidates source)
- candidates))
-
-(defun helm-process-real-to-display (candidates source)
- "Execute real-to-display function on all CANDIDATES of SOURCE."
- (helm-aif (assoc-default 'real-to-display source)
- (setq candidates (helm-funcall-with-source
- source 'mapcar
- (lambda (cand_)
- (if (consp cand_)
- ;; override DISPLAY from candidate-transformer
- (cons (funcall it (cdr cand_)) (cdr cand_))
- (cons (funcall it cand_) cand_)))
- candidates))
- candidates))
-
-(defun helm-transform-candidates (candidates source &optional process-p)
- "Transform CANDIDATES of SOURCE according to candidate transformers.
-When PROCESS-P is non-nil execute the `filtered-candidate-transformer' functions
-otherwise only the `candidate-transformer' functions are processed.
-When attribute `real-to-display' is present, execute its function on all maybe
-filtered CANDIDATES."
- (helm-process-real-to-display
- (helm-process-filtered-candidate-transformer-maybe
- (helm-process-candidate-transformer
- (helm--initialize-one-by-one-candidates candidates source) source)
- source process-p)
- source))
-
-\f
-;; Core: narrowing candidates
-(defun helm-candidate-number-limit (source)
- "Apply candidate-number-limit attribute value.
-This overhide variable `helm-candidate-number-limit'.
-
-e.g:
-If \(candidate-number-limit\) is in SOURCE, show all candidates in SOURCE.
-If \(candidate-number-limit . 123\) is in SOURCE limit candidate to 123."
- (helm-aif (assq 'candidate-number-limit source)
- (or (cdr it) 99999999)
- (or helm-candidate-number-limit 99999999)))
-
-(defun helm-candidate-get-display (candidate)
- "Get searched display part from CANDIDATE.
-CANDIDATE is a string, a symbol, or \(DISPLAY . REAL\) cons cell."
- (cond ((car-safe candidate))
- ((symbolp candidate)
- (symbol-name candidate))
- ((numberp candidate)
- (number-to-string candidate))
- (t candidate)))
-
-(defun helm-process-pattern-transformer (pattern source)
- "Execute pattern-transformer attribute PATTERN function in SOURCE."
- (helm-aif (assoc-default 'pattern-transformer source)
- (helm-composed-funcall-with-source source it pattern)
- pattern))
-
-(defun helm-default-match-function (candidate)
- "Check if `helm-pattern' match CANDIDATE.
-Default function to match candidates according to `helm-pattern'."
- (string-match helm-pattern candidate))
-
-\f
-;;; Fuzzy matching
-;;
-;;
-(defvar helm--fuzzy-regexp-cache (make-hash-table :test 'eq))
-(defun helm--fuzzy-match-maybe-set-pattern ()
- ;; Computing helm-pattern with helm--mapconcat-pattern
- ;; is costly, so cache it once time for all and reuse it
- ;; until pattern change.
- (when helm--in-fuzzy
- (let ((fun (if (string-match "\\`\\^" helm-pattern)
- #'identity
- #'helm--mapconcat-pattern)))
- (clrhash helm--fuzzy-regexp-cache)
- ;; FIXME: Splitted part are not handled here,
- ;; I must compute them in `helm-search-match-part'
- ;; when negation and in-buffer are used.
- (if (string-match "\\`!" helm-pattern)
- (puthash 'helm-pattern
- (if (> (length helm-pattern) 1)
- (list (funcall fun (substring helm-pattern 1 2))
- (funcall fun (substring helm-pattern 1)))
- '("" ""))
- helm--fuzzy-regexp-cache)
- (puthash 'helm-pattern
- (if (> (length helm-pattern) 0)
- (list (funcall fun (substring helm-pattern 0 1))
- (funcall fun helm-pattern))
- '("" ""))
- helm--fuzzy-regexp-cache)))))
-
-(defun helm-fuzzy-match (candidate)
- "Check if `helm-pattern' fuzzy match CANDIDATE.
-This function is used with sources build with `helm-source-sync'."
- (unless (string-match " " helm-pattern)
- ;; When pattern have one or more spaces, let
- ;; multi-match doing the job with no fuzzy matching.[1]
- (let ((regexp (cadr (gethash 'helm-pattern helm--fuzzy-regexp-cache))))
- (if (string-match "\\`!" helm-pattern)
- (not (string-match regexp candidate))
- (string-match regexp candidate)))))
-
-(defun helm-fuzzy-search (pattern)
- "Same as `helm-fuzzy-match' but for sources build with `helm-source-in-buffer'."
- (unless (string-match " " helm-pattern)
- ;; Same as in `helm-fuzzy-match' ref[1].
- (let* ((regexps (gethash 'helm-pattern helm--fuzzy-regexp-cache))
- (partial-regexp (car regexps))
- (regexp (cadr regexps)))
- (if (string-match "\\`!" pattern)
- ;; Don't try to search here, just return
- ;; the position of line and go ahead,
- ;; letting `helm-search-match-part' checking if
- ;; pattern match against this line.
- (prog1 (list (point-at-bol) (point-at-eol))
- (forward-line 1))
- ;; We could use here directly `re-search-forward'
- ;; on the regexp produced by `helm--mapconcat-pattern',
- ;; but it is very slow because emacs have to do an incredible
- ;; amount of loops to match e.g "[^f]*o[^o]..." in the whole buffer,
- ;; more the regexp is long more the amount of loops grow.
- ;; (Probably leading to a max-lisp-eval-depth error if both
- ;; regexp and buffer are too big)
- ;; So just search the first bit of pattern e.g "[^f]*f", and
- ;; then search the corresponding line with the whole regexp,
- ;; which increase dramatically the speed of the search.
- (cl-loop while (re-search-forward partial-regexp nil t)
- for bol = (point-at-bol)
- for eol = (point-at-eol)
- if (progn (goto-char bol)
- (re-search-forward regexp eol t))
- do (goto-char eol) and return t
- else do (goto-char eol)
- finally return nil)))))
-
-(defun helm-score-candidate-for-pattern (candidate pattern)
- "Give a score to CANDIDATE according to PATTERN.
-Score is calculated against number of contiguous matches found with PATTERN.
-If PATTERN is fully matched in CANDIDATE a maximal score (100) is given.
-A bonus of one point is given when PATTERN prefix match CANDIDATE.
-Contiguous matches have a coefficient of 2."
- (let* ((cand (if (stringp candidate)
- candidate (helm-stringify candidate)))
- (pat-lookup (helm--collect-pairs-in-string pattern))
- (str-lookup (helm--collect-pairs-in-string cand))
- (bonus (if (equal (car pat-lookup) (car str-lookup)) 1 0))
- (bonus1 (and (string-match (concat "\\<" (regexp-quote pattern) "\\>")
- cand)
- 100)))
- (+ bonus (or bonus1
- ;; Give a coefficient of 2 for contiguous matches.
- ;; That's mean that "wiaaaki" will not take precedence
- ;; on "aaawiki" when matching on "wiki" even if "wiaaaki"
- ;; starts by "wi".
- (* (length (cl-nintersection
- pat-lookup str-lookup :test 'equal))
- 2)))))
-
-(defun helm-fuzzy-matching-default-sort-fn (candidates _source &optional use-real)
- "The transformer for sorting candidates in fuzzy matching.
-It is sorting on the display part of by default.
-
-Sort CANDIDATES according to their score calculated by
-`helm-score-candidate-for-pattern'. When two candidates have the
-same score sort is made by length. Set USE-REAL to non-nil to
-sort on the real part."
- (if (string= helm-pattern "")
- candidates
- (let ((table-scr (make-hash-table :test 'equal)))
- (sort candidates
- (lambda (s1 s2)
- ;; Score and measure the length on real or display part of candidate
- ;; according to `use-real'.
- (let* ((real-or-disp-fn (if use-real #'cdr #'car))
- (cand1 (if (consp s1)
- (funcall real-or-disp-fn s1)
- s1))
- (cand2 (if (consp s2)
- (funcall real-or-disp-fn s2)
- s2))
- (data1 (or (gethash cand1 table-scr)
- (puthash cand1
- (list (helm-score-candidate-for-pattern
- cand1 helm-pattern)
- (length (helm-stringify cand1)))
- table-scr)))
- (data2 (or (gethash cand2 table-scr)
- (puthash cand2
- (list (helm-score-candidate-for-pattern
- cand2 helm-pattern)
- (length (helm-stringify cand2)))
- table-scr)))
- (len1 (cadr data1))
- (len2 (cadr data2))
- (scr1 (car data1))
- (scr2 (car data2)))
- (cond ((= scr1 scr2)
- (< len1 len2))
- ((> scr1 scr2)))))))))
-
-(defun helm-fuzzy-default-highlight-match (candidate)
- "The default function to highlight matches in fuzzy matching.
-It is meant to use with `filter-one-by-one' slot."
- (let* ((pair (and (consp candidate) candidate))
- (display (helm-stringify (if pair (car pair) candidate)))
- (real (cdr pair))
- (regex (helm-aif (and helm-migemo-mode
- (assoc helm-pattern
- helm-mm--previous-migemo-info))
- (cdr it)
- helm-pattern))
- ;; FIXME This is called at each turn, cache it to optimize.
- (mp (helm-aif (helm-attr 'match-part (helm-get-current-source))
- (funcall it display))))
- (with-temp-buffer
- (insert (propertize display 'read-only nil)) ; Fix (#1176)
- (goto-char (point-min))
- (when mp
- ;; FIXME the first part of display may contain an occurence of mp.
- ;; e.g "helm-adaptive.el:27:(defgroup helm-adapt"
- (search-forward mp nil t)
- (goto-char (match-beginning 0)))
- (if (re-search-forward regex (and mp (+ (point) (length mp))) t)
- (add-text-properties
- (match-beginning 0) (match-end 0) '(face helm-match))
- (cl-loop with multi-match
- with patterns = (if (string-match-p " " helm-pattern)
- (prog1 (split-string helm-pattern)
- (setq multi-match t))
- (split-string helm-pattern "" t))
- for p in patterns
- for re = (or (and helm-migemo-mode
- (assoc-default
- p helm-mm--previous-migemo-info))
- p)
- do
- (when (re-search-forward re nil t)
- (add-text-properties
- (match-beginning 0) (match-end 0)
- '(face helm-match)))
- (when multi-match (goto-char (point-min)))))
- (setq display (buffer-string)))
- (if real (cons display real) display)))
-
-(defun helm-fuzzy-highlight-matches (candidates _source)
- "The filtered-candidate-transformer function to highlight matches in fuzzy.
-See `helm-fuzzy-default-highlight-match'."
- (cl-loop for c in candidates
- collect (funcall helm-fuzzy-matching-highlight-fn c)))
-
-(defun helm-match-functions (source)
- (let ((matchfns (or (assoc-default 'match source)
- (assoc-default 'match-strict source)
- #'helm-default-match-function)))
- (if (and (listp matchfns) (not (functionp matchfns)))
- matchfns (list matchfns))))
-
-(defun helm-search-functions (source)
- (let ((searchfns (assoc-default 'search source)))
- (if (and (listp searchfns) (not (functionp searchfns)))
- searchfns (list searchfns))))
-
-(defun helm-take-first-elements (seq n)
- "Return the N first element of SEQ if SEQ is longer than N.
-It is used to narrow down list of candidates to `helm-candidate-number-limit'."
- (if (> (length seq) n) (cl-subseq seq 0 n) seq))
-
-(cl-defun helm-set-case-fold-search (&optional (pattern helm-pattern))
- "Used to set the value of `case-fold-search' in helm.
-Return t or nil depending of value of `helm-case-fold-search'
-and `helm-pattern'."
- (let ((helm-case-fold-search
- (helm-aif (assq 'case-fold-search (helm-get-current-source))
- (cdr it)
- helm-case-fold-search))
- ;; Only parse basename for filenames
- ;; to avoid setting case sensitivity
- ;; when expanded directories contains upcase
- ;; characters.
- (bn-or-pattern (if (string-match "[~/]*" pattern)
- (helm-basename pattern)
- pattern)))
- (helm-set-case-fold-search-1 bn-or-pattern)))
-
-(defun helm-set-case-fold-search-1 (pattern)
- (cl-case helm-case-fold-search
- (smart (let ((case-fold-search nil))
- (if (string-match "[[:upper:]]" pattern) nil t)))
- (t helm-case-fold-search)))
-
-(defun helm-match-from-candidates (cands matchfns match-part-fn limit source)
- (condition-case-unless-debug err
- (cl-loop with hash = (make-hash-table :test 'equal)
- with allow-dups = (assq 'allow-dups source)
- with case-fold-search = (helm-set-case-fold-search)
- with count = 0
- for iter from 1
- for fn in matchfns
- when (< count limit) nconc
- (cl-loop for c in cands
- for dup = (gethash c hash)
- while (and (< count limit)
- ;; When allowing dups check if DUP
- ;; have been already found in previous loop
- ;; by comparing its value with ITER.
- (or (and allow-dups dup (= dup iter))
- (null dup)))
- for target = (helm-candidate-get-display c)
- for part = (if match-part-fn
- (funcall match-part-fn target)
- target)
- when (funcall fn part) do
- (progn
- ;; Modify candidate before pushing it to hash.
- (helm--maybe-process-filter-one-by-one-candidate c source)
- ;; Give as value the iteration number of
- ;; inner loop to be able to check if
- ;; the duplicate have not been found in previous loop.
- (puthash c iter hash)
- (cl-incf count))
- and when c collect c))
- (error (unless (eq (car err) 'invalid-regexp) ; Always ignore regexps errors.
- (helm-log-error "helm-match-from-candidates in source `%s': %s %s"
- (assoc-default 'name source) (car err) (cdr err)))
- nil)))
-
-(defun helm-compute-matches (source)
- "Start computing candidates in SOURCE."
- (save-current-buffer
- (let ((matchfns (helm-match-functions source))
- (matchpartfn (assoc-default 'match-part source))
- (helm-source-name (assoc-default 'name source))
- (helm-current-source source)
- (limit (helm-candidate-number-limit source))
- (helm-pattern (helm-process-pattern-transformer
- helm-pattern source)))
- (helm--fuzzy-match-maybe-set-pattern)
- ;; If source have a `filtered-candidate-transformer' attr
- ;; Filter candidates with this func, otherwise just compute
- ;; candidates.
- (helm-process-filtered-candidate-transformer
- (if (or (equal helm-pattern "")
- (equal matchfns '(identity)))
- ;; Compute all candidates up to LIMIT.
- (helm-take-first-elements
- (helm-get-cached-candidates source) limit)
- ;; Compute candidates according to pattern with their match fns.
- (helm-match-from-candidates
- (helm-get-cached-candidates source) matchfns matchpartfn limit source))
- source))))
-
-(defun helm-render-source (source matches)
- "Display MATCHES from SOURCE according to its settings."
- (helm-log "Source name = %S" (assoc-default 'name source))
- (when matches
- (helm-insert-header-from-source source)
- (if (not (assq 'multiline source))
- (cl-loop for m in matches
- for count from 1
- do (helm-insert-match m 'insert source count))
- (let ((start (point))
- (count 0)
- separate)
- (cl-dolist (match matches)
- (cl-incf count)
- (if separate
- (helm-insert-candidate-separator)
- (setq separate t))
- (helm-insert-match match 'insert source count))
- (put-text-property start (point) 'helm-multiline t)))))
-
-(defmacro helm--maybe-use-while-no-input (&rest body)
- "Wrap BODY in `helm-while-no-input' unless initializing a remote connection."
- `(progn
- (if (and (file-remote-p helm-pattern)
- (not (file-remote-p helm-pattern nil t)))
- ;; Tramp will ask for passwd, don't use `helm-while-no-input'.
- ,@body
- (helm-log "Using here `helm-while-no-input'")
- (helm-while-no-input ,@body))))
-
-(defun helm--collect-matches (src-list)
- (let ((matches (helm--maybe-use-while-no-input
- (cl-loop for src in src-list
- collect (helm-compute-matches src)))))
- (unless (eq matches t) matches)))
-
-(defun helm--compute-sources (src-list)
- (cl-loop with matches = (helm--collect-matches src-list)
- for src in src-list
- for mtc in matches
- do (helm-render-source src mtc)))
-
-(cl-defun helm-process-delayed-sources (delayed-sources &optional preselect source)
- "Process helm DELAYED-SOURCES.
-Move selection to string or regexp PRESELECT if non--nil.
-This function is called in `helm-process-delayed-sources-timer'
-when emacs is idle for `helm-idle-delay'."
- (with-helm-quittable
- (helm-log "Delayed sources = %S"
- (mapcar (lambda (s)
- (assoc-default 'name s))
- delayed-sources))
- (with-current-buffer (helm-buffer-get)
- (save-excursion
- (goto-char (point-max))
- (helm--compute-sources delayed-sources)
- (when (and (not (helm-empty-buffer-p))
- ;; No selection yet.
- (= (overlay-start helm-selection-overlay)
- (overlay-end helm-selection-overlay)))
- (helm-update-move-first-line 'without-hook)))
- (save-excursion
- (goto-char (point-min))
- (helm-log-run-hook 'helm-update-hook))
- (setq helm-force-updating-p nil)
- (unless (assoc 'candidates-process source)
- (helm-display-mode-line (helm-get-current-source))
- (helm-log-run-hook 'helm-after-update-hook))
- (when preselect (helm-preselect preselect source)))))
-
-\f
-;;; Core: helm-update
-;;
-(defun helm-update (&optional preselect source)
- "Update candidates list in `helm-buffer' according to `helm-pattern'.
-Argument PRESELECT is a string or regexp used to move selection to a particular
-place once updating is done. It should be used on single source because search
-is done on whole `helm-buffer' and not on current source."
- (helm-log "Start updating")
- (helm-kill-async-processes)
- ;; When persistent action have been called
- ;; we have two windows even with `helm-full-frame'.
- ;; So go back to one window when updating if `helm-full-frame'
- ;; is non--nil.
- (with-helm-window
- (when helm-onewindow-p (delete-other-windows)))
- (with-current-buffer (helm-buffer-get)
- (set (make-local-variable 'helm-input-local) helm-pattern)
- (let (normal-sources
- delayed-sources
- matches)
- (unwind-protect
- (progn
- ;; Iterate over all the sources
- (cl-loop for source in (cl-remove-if-not
- 'helm-update-source-p (helm-get-sources))
- if (helm-delayed-source-p source)
- ;; Delayed sources just get collected for later
- ;; processing
- collect source into ds
- else
- ;; Collect the normal sources
- collect source into ns
- ;; Export the variables from cl-loop
- finally (setq delayed-sources ds
- normal-sources ns))
- ;; When no normal-sources erase buffer
- ;; for the next possible delayed source
- ;; or the already computed normal-source
- ;; that is no more "updateable" (requires-pattern).
- (unless normal-sources (erase-buffer))
- ;; Compute matches without rendering the sources.
- (helm-log "Matches: %S"
- (setq matches (helm--collect-matches normal-sources)))
- ;; If computing matches finished and is not interrupted
- ;; erase the helm-buffer and render results (Fix #1157).
- (when matches
- (erase-buffer)
- (cl-loop for src in normal-sources
- for mtc in matches
- do (helm-render-source src mtc))))
- (helm-log "Delayed sources = %S"
- (mapcar (lambda (s) (assoc-default 'name s))
- delayed-sources))
- (cond ((and preselect delayed-sources normal-sources)
- ;; Preselection run here when there is
- ;; normal AND delayed sources.
- (helm-log "Update preselect candidate %s" preselect)
- (helm-preselect preselect source))
- (delayed-sources ; Preselection and hooks will run later.
- (helm-update-move-first-line 'without-hook))
- (t ; No delayed sources, run the hooks now.
- (helm-update-move-first-line)
- (unless (assoc 'candidates-process source)
- (helm-display-mode-line (helm-get-current-source))
- (helm-log-run-hook 'helm-after-update-hook))
- (when preselect
- (helm-log "Update preselect candidate %s" preselect)
- (helm-preselect preselect source))
- (setq helm-force-updating-p nil)))
- (when delayed-sources
- ;; Allow giving a value to `delayed' attr from inside source.
- ;; Retain the biggest value (the slower) found in DELAYED-SOURCES.
- (let ((helm-idle-delay (cl-loop with delay = helm-idle-delay
- for s in delayed-sources
- for d = (assoc-default 'delayed s)
- when d do (setq delay (max delay d))
- finally return delay)))
- (run-with-idle-timer
- ;; Be sure helm-idle-delay is >
- ;; to helm-input-idle-delay
- ;; otherwise use value of helm-input-idle-delay
- ;; or 0.01 if == to 0.
- (max helm-idle-delay helm-input-idle-delay 0.001) nil
- 'helm-process-delayed-sources delayed-sources preselect source)))
- (helm-log "end update")))))
-
-;; Update keymap after updating.
-;; Now we run this in post-command-hook, it is
-;; probably no more needed in helm-after-update-hook.
-;; Leave it commented as a reminder for now.
-;; (add-hook 'helm-after-update-hook 'helm--maybe-update-keymap)
-
-(defun helm-update-source-p (source)
- "Whether SOURCE need updating or not."
- (let ((len (string-width
- (if (or (assoc 'matchplugin source)
- (null (assoc 'no-matchplugin source)))
- ;; Don't count spaces entered when using
- ;; multi-match.
- (replace-regexp-in-string " " "" helm-pattern)
- helm-pattern))))
- (and (or (not helm-source-filter)
- (member (assoc-default 'name source) helm-source-filter))
- (>= len
- (helm-aif (assoc 'requires-pattern source) (or (cdr it) 1) 0))
- ;; These incomplete regexps hang helm forever
- ;; so defer update. Maybe replace spaces quoted when using
- ;; multi-match.
- (not (member (replace-regexp-in-string "\\s\\ " " " helm-pattern)
- helm-update-blacklist-regexps)))))
-
-(defun helm-delayed-source-p (source)
- "Wheter SOURCE is a delayed source or not."
- (or (assoc 'delayed source)
- (and helm-quick-update
- (> (length helm-sources) 1)
- (< (window-height (get-buffer-window (current-buffer)))
- (line-number-at-pos (point-max))))))
-
-(defun helm-update-move-first-line (&optional without-hook)
- "Goto first line of `helm-buffer'."
- (goto-char (point-min))
- (unless without-hook
- (save-excursion (helm-log-run-hook 'helm-update-hook)))
- (helm-next-line))
-
-(defun helm-force-update (&optional preselect)
- "Force recalculation and update of candidates.
-
-The difference with `helm-update' is this function is reevaling
-the `init' and `update' attributes functions when present
-before running `helm-update', also `helm-candidate-cache',
-if some (async candidates are not cached)
-is not reinitialized so that candidates are not recomputed
-unless pattern have changed.
-
-Selection is preserved to current candidate or moved to PRESELECT
-if specified."
- (let ((source (helm-get-current-source))
- (selection (helm-get-selection nil t))
- ;; `helm-goto-source' need to have all sources displayed
- ;; So disable `helm-quick-update'.
- helm-quick-update)
- (setq helm-force-updating-p t)
- (when source
- (mapc 'helm-force-update--reinit
- (helm-get-sources)))
- (helm-update (or preselect selection) source)
- (with-helm-window (recenter))))
-
-(defun helm-refresh ()
- "Force recalculation and update of candidates."
- (interactive)
- (with-helm-alive-p
- (helm-force-update)))
-(put 'helm-refresh 'helm-only t)
-
-(defun helm-force-update--reinit (source)
- "Reinit SOURCE by calling his update and/or init functions."
- (helm-aif (helm-funcall-with-source
- source 'helm-candidate-buffer)
- (kill-buffer it))
- (cl-dolist (attr '(update init))
- (helm-aif (assoc-default attr source)
- (helm-funcall-with-source source it)))
- (helm-remove-candidate-cache source))
-
-(defun helm-remove-candidate-cache (source)
- "Remove SOURCE from `helm-candidate-cache'."
- (remhash (assoc-default 'name source) helm-candidate-cache))
-
-(defun helm-insert-match (match insert-function source &optional num)
- "Insert MATCH into `helm-buffer' with INSERT-FUNCTION for SOURCE.
-If MATCH is a list then insert the string intended to appear on the display
-and store the real value in a text property."
- (let ((start (point-at-bol (point)))
- (dispvalue (helm-candidate-get-display match))
- (realvalue (cdr-safe match)))
- (when (and (stringp dispvalue)
- (not (zerop (length dispvalue))))
- (funcall insert-function dispvalue)
- ;; Some sources with candidates-in-buffer have already added
- ;; 'helm-realvalue property when creating candidate buffer.
- (unless (get-text-property start 'helm-realvalue)
- (and realvalue
- (put-text-property start (point-at-eol)
- 'helm-realvalue realvalue)))
- (when num
- (put-text-property start (point-at-eol) 'helm-cand-num num))
- (when helm-source-in-each-line-flag
- (put-text-property start (point-at-eol) 'helm-source source))
- (funcall insert-function "\n"))))
-
-(defun helm-insert-header-from-source (source)
- "Insert SOURCE name in `helm-buffer' header.
-Maybe insert by overlay additional info after source name if SOURCE have
-header-name attribute."
- (let ((name (assoc-default 'name source)))
- (helm-insert-header
- name
- (helm-aif (assoc-default 'header-name source)
- (helm-funcall-with-source source it name)))))
-
-(defun helm-insert-header (name &optional display-string)
- "Insert header of source NAME into the helm buffer.
-If DISPLAY-STRING is non--nil and a string, display this additional info
-after the source name by overlay."
- (unless (bobp)
- (let ((start (point)))
- (insert "\n")
- (put-text-property start (point) 'helm-header-separator t)))
- (let ((start (point)))
- (insert name)
- (put-text-property (point-at-bol)
- (point-at-eol) 'helm-header t)
- (when display-string
- (overlay-put (make-overlay (point-at-bol) (point-at-eol))
- 'display display-string))
- (insert "\n")
- (put-text-property start (point) 'face 'helm-source-header)))
-
-(defun helm-insert-candidate-separator ()
- "Insert separator of candidates into the helm buffer."
- (insert (propertize helm-candidate-separator 'face 'helm-separator))
- (put-text-property (point-at-bol)
- (point-at-eol) 'helm-candidate-separator t)
- (insert "\n"))
-
-\f
-;;; Core: async process
-;;
-(defun helm-output-filter (process output-string)
- "The `process-filter' function for helm async sources."
- (with-helm-quittable
- (helm-output-filter-1 (assoc process helm-async-processes) output-string)))
-
-(defun helm-output-filter-1 (process-assoc output-string)
- (helm-log "output-string = %S" output-string)
- (with-current-buffer helm-buffer
- (let ((source (cdr process-assoc)))
- (save-excursion
- (helm-aif (assoc-default 'insertion-marker source)
- (goto-char it)
- (goto-char (point-max))
- (helm-insert-header-from-source source)
- (setcdr process-assoc
- (append source `((insertion-marker . ,(point-marker))))))
- (helm-output-filter--process-source
- (car process-assoc) output-string source
- (helm-candidate-number-limit source))))
- (helm-output-filter--post-process)))
-
-(defun helm-output-filter--process-source (process output-string source limit)
- (cl-dolist (candidate (helm-transform-candidates
- (helm-output-filter--collect-candidates
- (split-string output-string "\n")
- (assoc 'incomplete-line source))
- source t))
- (setq candidate
- (helm--maybe-process-filter-one-by-one-candidate candidate source))
- (if (assq 'multiline source)
- (let ((start (point)))
- (helm-insert-candidate-separator)
- (helm-insert-match candidate 'insert-before-markers source
- (1+ (cdr (assoc 'item-count source))))
- (put-text-property start (point) 'helm-multiline t))
- (helm-insert-match candidate 'insert-before-markers source
- (1+ (cdr (assoc 'item-count source)))))
- (cl-incf (cdr (assoc 'item-count source)))
- (when (>= (assoc-default 'item-count source) limit)
- (helm-kill-async-process process)
- (cl-return))))
-
-(defun helm-output-filter--collect-candidates (lines incomplete-line-info)
- "Collect LINES maybe completing the truncated first and last lines."
- ;; The output of process may come in chunks of any size,
- ;; so the last line of LINES come truncated, this truncated line is
- ;; stored in INCOMPLETE-LINE-INFO and will be concated with the first
- ;; incomplete line of next chunk arriving.
- ;; INCOMPLETE-LINE-INFO is an attribute of source which is created
- ;; with an empty string when the source is computed => (incomplete-line . "")
- (helm-log "incomplete-line-info = %S" (cdr incomplete-line-info))
- (butlast
- (cl-loop for line in lines
- ;; On start `incomplete-line-info' value is empty string.
- for newline = (helm-aif (cdr incomplete-line-info)
- (prog1
- (concat it line)
- (setcdr incomplete-line-info nil))
- line)
- collect newline
- ;; Store last incomplete line (last chunk truncated)
- ;; until new output arrives.
- ;; Previously we were storing 'line' in incomplete-line-info
- ;; assuming output is truncated in only two chunks,
- ;; which may be wrong if output is very large and is truncated
- ;; in more than two chunks, so store now 'newline' which
- ;; contain the previous chunks (Issue #1187).
- finally do (setcdr incomplete-line-info newline))))
-
-(defun helm-output-filter--post-process ()
- (let ((src (helm-get-current-source)))
- (helm-log-run-hook 'helm-update-hook)
- (helm-aif (get-buffer-window helm-buffer 'visible)
- (with-selected-window it
- (helm-skip-noncandidate-line 'next)
- (helm-mark-current-line)
- (helm-display-mode-line src)
- (helm-log-run-hook 'helm-after-update-hook)))))
-
-(defun helm-process-deferred-sentinel-hook (process event file)
- "Defer remote processes in sentinels.
-Meant to be called at beginning of a sentinel process function."
- (when (and (string= event "finished\n")
- (or (file-remote-p file)
- ;; `helm-suspend-update-flag'
- ;; is non--nil here only during a
- ;; running process, this will never be called
- ;; when user set it explicitely with `C-!'.
- helm-suspend-update-flag))
- (setq helm-suspend-update-flag t)
- ;; Kill the process but don't delete entry in
- ;; `helm-async-processes'.
- (helm-kill-async-process process)
- ;; When tramp tries to open the same connection twice in a
- ;; short time frame (less than 5s) it throw 'suppress which
- ;; call the real-handler on the main "Emacs", so we wait
- ;; 5s before updating to avoid this [1], but allowing user to
- ;; enter input during this delay.
- ;; [1] On last Emacs versions, this is fixed and tramp return
- ;; nil in this situation.
- ;; Note: It is difficult to have a value < to 5 for
- ;; `tramp-connection-min-time-diff', because the process die
- ;; when calling too quickly same process.
- (run-at-time (or (and (boundp 'tramp-connection-min-time-diff)
- tramp-connection-min-time-diff)
- 5)
- nil (lambda ()
- (when helm-alive-p ; Don't run timer fn after quit.
- (setq helm-suspend-update-flag nil)
- (helm-check-minibuffer-input))))))
-
-(defun helm-kill-async-processes ()
- "Kill all asynchronous processes registered in `helm-async-processes'."
- (while helm-async-processes
- (helm-kill-async-process (caar helm-async-processes))
- (setq helm-async-processes (cdr helm-async-processes))))
-
-(defun helm-kill-async-process (process)
- "Stop output from `helm-output-filter' and kill associated PROCESS."
- (set-process-filter process nil)
- (delete-process process))
-
-\f
-;;; Core: action
-;;
-(defun helm-execute-selection-action ()
- "Execute current action and kill the action buffer if present."
- (helm-log-run-hook 'helm-before-action-hook)
- ;; Position can be different when `helm-current-buffer'
- ;; is splitted, so jump to this position before executing action.
- (helm-current-position 'restore)
- (unwind-protect
- (helm-execute-selection-action-1)
- (helm-aif (get-buffer helm-action-buffer)
- (kill-buffer it))
- (helm-log-run-hook 'helm-after-action-hook)))
-
-(defun helm-execute-selection-action-1 (&optional
- selection action
- preserve-saved-action)
- "Execute ACTION on current SELECTION.
-If PRESERVE-SAVED-ACTION is non--nil save action."
- (helm-log "executing action")
- (setq action (helm-get-default-action
- (or action
- helm-saved-action
- (if (get-buffer helm-action-buffer)
- (helm-get-selection helm-action-buffer)
- (helm-get-actions-from-current-source)))))
- (let ((source (or helm-saved-current-source
- (helm-get-current-source)))
- non-essential)
- (setq selection (helm-coerce-selection
- (or selection
- helm-saved-selection
- (helm-get-selection)
- (and (assoc 'accept-empty source) ""))
- source))
- (unless preserve-saved-action (setq helm-saved-action nil))
- (when (and selection action) (funcall action selection))))
-
-(defun helm-coerce-selection (selection source)
- "Apply coerce attribute function to SELECTION in SOURCE.
-Coerce source with coerce function."
- (helm-aif (assoc-default 'coerce source)
- (helm-funcall-with-source source it selection)
- selection))
-
-(defun helm-get-default-action (action)
- "Get the first ACTION value of action list in source."
- (if (and (listp action) (not (functionp action)))
- (cdar action)
- action))
-
-(defun helm-select-action ()
- "Select an action for the currently selected candidate.
-If action buffer is selected, back to the helm buffer."
- (interactive)
- (with-helm-alive-p
- (helm-log-run-hook 'helm-select-action-hook)
- (setq helm-saved-selection (helm-get-selection))
- (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)
- (helm-set-pattern helm-input 'noupdate))
- (helm-saved-selection
- (setq helm-saved-current-source (helm-get-current-source))
- (let ((actions (helm-get-actions-from-current-source)))
- (if (functionp actions)
- (message "Sole action: %s" 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-display-mode-line (helm-get-current-source))
- (run-hooks 'helm-window-configuration-hook)))))
-(put 'helm-select-action 'helm-only t)
-
-(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 (make-local-variable 'helm-sources)
- (list
- (helm-build-sync-source "Actions"
- :volatile t
- :nomark t
- :keymap 'helm-map
- :candidates actions
- :mode-line '("Action(s)" "TAB:BackToCands RET/f1/f2/fn:NthAct")
- :candidate-transformer
- (lambda (candidates)
- (cl-loop for (i . j) in candidates
- for count from 1
- collect
- (cons (concat (cond ((> count 12)
- " ")
- ((< count 10)
- (format "[f%s] " count))
- (t (format "[f%s] " count)))
- (propertize i 'face 'helm-action))
- j)))
- :candidate-number-limit nil)))
- (set (make-local-variable 'helm-source-filter) nil)
- (set (make-local-variable 'helm-selection-overlay) nil)
- (helm-initialize-overlays helm-action-buffer)))
-
-\f
-;; Core: selection
-
-(defun helm-display-source-at-screen-top-maybe (unit)
- "Display source at top of screen when UNIT value is 'source.
-With any other value of UNIT return nil."
- (when (and helm-display-source-at-screen-top (eq unit 'source))
- (set-window-start (selected-window)
- (save-excursion (forward-line -1) (point)))))
-
-(defun helm-skip-noncandidate-line (direction)
- "Skip source header or candidates separator when going in DIRECTION.
-Possible value of DIRECTION are 'next or 'previous.
-Same as `helm-skip-header-and-separator-line' but ensure
-point is moved to the right place when at bop or eob."
- (helm-skip-header-and-separator-line direction)
- (and (bobp) (forward-line 1)) ; Skip first header.
- (and (eobp) (forward-line -1))) ; Avoid last empty line.
-
-(defun helm-skip-header-and-separator-line (direction)
- "Skip source header or candidate separator when going to next/previous line.
-Possible value of DIRECTION are 'next or 'previous."
- (let ((fn (cl-ecase direction
- (next 'eobp)
- (previous 'bobp))))
- (while (and (not (funcall fn))
- (or (helm-pos-header-line-p)
- (helm-pos-candidate-separator-p)))
- (forward-line (if (and (eq direction 'previous)
- (not (eq (point-at-bol) (point-min))))
- -1 1)))))
-
-(defun helm-display-mode-line (source &optional force)
- "Setup mode-line and header-line for `helm-buffer'."
- (set (make-local-variable 'helm-mode-line-string)
- (helm-interpret-value (or (and (listp source) ; Check if source is empty.
- (assoc-default 'mode-line source))
- (default-value 'helm-mode-line-string))
- source))
- (let ((follow (and (eq (cdr (assq 'follow source)) 1) " (HF)"))
- (marked (and helm-marked-candidates
- (cl-loop with cur-name = (assoc-default 'name source)
- for c in helm-marked-candidates
- for name = (assoc-default 'name (car c))
- when (string= name cur-name)
- collect c))))
- ;; Setup mode-line.
- (if helm-mode-line-string
- (setq mode-line-format
- `(" " mode-line-buffer-identification " "
- (:eval (format "L%-3d" (helm-candidate-number-at-point)))
- ,follow
- (:eval ,(and marked
- (concat
- " "
- (propertize
- (format "M%d" (length marked))
- 'face 'helm-visible-mark))))
- (:eval (when ,helm--mode-line-display-prefarg
- (let ((arg (prefix-numeric-value
- (or prefix-arg current-prefix-arg))))
- (unless (= arg 1)
- (propertize (format " [prefarg:%s]" arg)
- 'face 'helm-prefarg)))))
- " "
- (:eval (helm-show-candidate-number
- (car-safe helm-mode-line-string)))
- " " helm--mode-line-string-real " " mode-line-end-spaces)
- helm--mode-line-string-real
- (substitute-command-keys (if (listp helm-mode-line-string)
- (cadr helm-mode-line-string)
- helm-mode-line-string)))
- (setq mode-line-format (default-value 'mode-line-format)))
- ;; Setup header-line.
- (cond (helm-echo-input-in-header-line
- (setq force t)
- (helm--set-header-line))
- (helm-display-header-line
- (let ((hlstr (helm-interpret-value
- (and (listp source)
- (assoc-default 'header-line source))
- source))
- (endstr (make-string (window-width) ? )))
- (setq header-line-format
- (propertize (concat " " hlstr endstr)
- 'face 'helm-header))))))
- (when force (force-mode-line-update)))
-
-(defun helm--set-header-line (&optional update)
- (with-selected-window (minibuffer-window)
- (let* ((beg (save-excursion (vertical-motion 0 (helm-window)) (point)))
- (end (save-excursion (end-of-visual-line) (point)))
- ;; The visual line where the cursor is.
- (cont (buffer-substring beg end))
- (pref (propertize
- " "
- 'display (if (string-match-p (regexp-quote helm--prompt) cont)
- '(space :width left-fringe)
- (propertize
- "->"
- 'face 'helm-header-line-left-margin))))
- (pos (- (point) beg)))
- (with-helm-buffer
- (setq header-line-format (concat pref cont " "))
- (put-text-property
- ;; Increment pos to handle the space before prompt (i.e `pref').
- (1+ pos) (+ 2 pos)
- 'face ;don't just use 'cursor; this can hide the current character
- (list :inverse-video t
- :foreground (face-background 'cursor)
- :background (face-background 'default))
- header-line-format)
- (when update (force-mode-line-update))))))
-
-(defun helm--update-header-line ()
- ;; This should be used in `post-command-hook',
- ;; nowhere else.
- (when (with-helm-buffer helm-echo-input-in-header-line)
- (helm--set-header-line t)))
-
-(defun helm-hide-minibuffer-maybe ()
- "Hide minibuffer contents in a Helm session.
-This function should normally go to `helm-minibuffer-set-up-hook'.
-It has no effect if `helm-echo-input-in-header-line' is nil."
- (when (with-helm-buffer helm-echo-input-in-header-line)
- (let ((ov (make-overlay (point-min) (point-max) nil nil t)))
- (overlay-put ov 'window (selected-window))
- (overlay-put ov 'face (let ((bg-color (face-background 'default nil)))
- `(:background ,bg-color :foreground ,bg-color)))
- (setq cursor-type nil))))
-
-(defun helm-show-candidate-number (&optional name)
- "Used to display candidate number in mode-line.
-You can specify NAME of candidates e.g \"Buffers\" otherwise
-it is \"Candidate\(s\)\" by default."
- (when helm-alive-p
- (unless (helm-empty-source-p)
- ;; Build a fixed width string when candidate-number < 1000
- (let* ((cand-name (or name "Candidate(s)"))
- (width (length (format "[999 %s]" cand-name))))
- (propertize
- (format (concat "%-" (number-to-string width) "s")
- (format "[%s %s]"
- (helm-get-candidate-number 'in-current-source)
- cand-name))
- 'face 'helm-candidate-number)))))
-
-(cl-defun helm-move-selection-common (&key where direction)
- "Move the selection marker to a new position.
-Position is determined by WHERE and DIRECTION.
-Key arg WHERE can be one of:
- - line
- - page
- - edge
- - source
-Key arg DIRECTION can be one of:
- - previous
- - next
- - A source or a source name when used with :WHERE 'source."
- (let ((move-func (cl-case where
- (line (cl-ecase direction
- (previous 'helm-move--previous-line-fn)
- (next 'helm-move--next-line-fn)))
- (page (cl-ecase direction
- (previous 'helm-move--previous-page-fn)
- (next 'helm-move--next-page-fn)))
- (edge (cl-ecase direction
- (previous 'helm-move--beginning-of-buffer-fn)
- (next 'helm-move--end-of-buffer-fn)))
- (source (cl-case direction
- (previous 'helm-move--previous-source-fn)
- (next 'helm-move--next-source-fn)
- (t (lambda () ; A source is passed as DIRECTION arg.
- (helm-move--goto-source-fn direction))))))))
- (unless (or (helm-empty-buffer-p (helm-buffer-get))
- (not (helm-window)))
- (with-helm-window
- (helm-log-run-hook 'helm-move-selection-before-hook)
- (funcall move-func)
- (and (memq direction '(next previous))
- (helm-skip-noncandidate-line direction))
- (when (helm-pos-multiline-p)
- (helm-move--beginning-of-multiline-candidate))
- (helm-display-source-at-screen-top-maybe where)
- (when (helm-get-previous-header-pos)
- (helm-mark-current-line))
- (helm-display-mode-line (helm-get-current-source))
- (helm-log-run-hook 'helm-move-selection-after-hook)))))
-
-(defun helm-move--beginning-of-multiline-candidate ()
- (let ((header-pos (helm-get-previous-header-pos))
- (separator-pos (helm-get-previous-candidate-separator-pos)))
- (when header-pos
- (goto-char (if (or (null separator-pos)
- (< separator-pos header-pos))
- header-pos
- separator-pos))
- (forward-line 1))))
-
-(defun helm-move--previous-multi-line-fn ()
- (forward-line -1)
- (unless (helm-pos-header-line-p)
- (helm-skip-header-and-separator-line 'previous)
- (helm-move--beginning-of-multiline-candidate)))
-
-(defun helm-move--previous-line-fn ()
- (if (not (helm-pos-multiline-p))
- (forward-line -1)
- (helm-move--previous-multi-line-fn))
- (when (and helm-move-to-line-cycle-in-source
- (helm-pos-header-line-p))
- (forward-line 1)
- (helm-move--end-of-source)
- ;; We are at end of helm-buffer
- ;; check if last candidate is a multiline candidate
- ;; and jump to it
- (when (and (eobp)
- (save-excursion (forward-line -1) (helm-pos-multiline-p)))
- (helm-move--previous-multi-line-fn))))
-
-(defun helm-move--next-multi-line-fn ()
- (let ((header-pos (helm-get-next-header-pos))
- (separator-pos (helm-get-next-candidate-separator-pos)))
- (cond ((and separator-pos
- (or (null header-pos) (< separator-pos header-pos)))
- (goto-char separator-pos))
- (header-pos
- (goto-char header-pos)))))
-
-(defun helm-move--next-line-fn ()
- (if (not (helm-pos-multiline-p))
- (forward-line 1)
- (helm-move--next-multi-line-fn))
- (when (and helm-move-to-line-cycle-in-source
- (or (save-excursion (and (helm-pos-multiline-p)
- (goto-char (overlay-end
- helm-selection-overlay))
- (helm-end-of-source-p t)))
- (helm-end-of-source-p t)))
- (helm-move--beginning-of-source)))
-
-(defun helm-move--previous-page-fn ()
- (condition-case nil
- (scroll-down)
- (beginning-of-buffer (goto-char (point-min)))))
-
-(defun helm-move--next-page-fn ()
- (condition-case nil
- (scroll-up)
- (end-of-buffer (goto-char (point-max)))))
-
-(defun helm-move--beginning-of-buffer-fn ()
- (goto-char (point-min)))
-
-(defun helm-move--end-of-buffer-fn ()
- (goto-char (point-max)))
-
-(defun helm-move--end-of-source ()
- (goto-char (or (helm-get-next-header-pos) (point-max)))
- (when (helm-pos-header-line-p) (forward-line -2)))
-
-(defun helm-move--beginning-of-source ()
- (goto-char (helm-get-previous-header-pos))
- (forward-line 1))
-
-(defun helm-move--previous-source-fn ()
- (forward-line -1)
- (if (bobp)
- (goto-char (point-max))
- (helm-skip-header-and-separator-line 'previous))
- (goto-char (helm-get-previous-header-pos))
- (forward-line 1))
-
-(defun helm-move--next-source-fn ()
- (goto-char (or (and (not (save-excursion
- (forward-line 1) (eobp)))
- ;; Empty source at eob are just
- ;; not displayed unless they are dummy.
- ;; Issue #1117.
- (helm-get-next-header-pos))
- (point-min))))
-
-(defun helm-move--goto-source-fn (source-or-name)
- (goto-char (point-min))
- (let ((name (if (stringp source-or-name) source-or-name
- (assoc-default 'name source-or-name))))
- (condition-case err
- (while (not (string= name (helm-current-line-contents)))
- (goto-char (helm-get-next-header-pos)))
- (error (helm-log "%S" err)))))
-
-(defun helm-candidate-number-at-point ()
- (with-helm-buffer
- (or (get-text-property (point) 'helm-cand-num) 1)))
-
-(defun helm--next-or-previous-line (direction &optional arg)
- ;; Be sure to not use this in non--interactives calls.
- (let ((helm-move-to-line-cycle-in-source
- (and helm-move-to-line-cycle-in-source arg)))
- (if (and arg (> arg 1))
- (cl-loop with pos = (helm-candidate-number-at-point)
- with cand-num = (helm-get-candidate-number t)
- with iter = (min arg (if (eq direction 'next)
- (- cand-num pos)
- (min arg (1- pos))))
- for count from 1
- while (<= count iter)
- do
- (helm-move-selection-common :where 'line :direction direction))
- (helm-move-selection-common :where 'line :direction direction))))
-
-(defun helm-previous-line (&optional arg)
- "Move selection to the ARG previous line(s).
-Same behavior than `helm-next-line' when called with a numeric prefix arg."
- (interactive "p")
- (with-helm-alive-p
- (helm--next-or-previous-line 'previous arg)))
-(put 'helm-previous-line 'helm-only t)
-
-(defun helm-next-line (&optional arg)
- "Move selection to the next ARG line(s).
-When a numeric prefix arg is given and this numeric arg
-is > to the number of candidates, move to last candidate of
-current source (i.e don't move to next source if some)."
- (interactive "p")
- (with-helm-alive-p
- (helm--next-or-previous-line 'next arg)))
-(put 'helm-next-line 'helm-only t)
-
-(defun helm-previous-page ()
- "Move selection back with a pageful."
- (interactive)
- (with-helm-alive-p
- (helm-move-selection-common :where 'page :direction 'previous)))
-(put 'helm-previous-page 'helm-only t)
-
-(defun helm-next-page ()
- "Move selection forward with a pageful."
- (interactive)
- (with-helm-alive-p
- (helm-move-selection-common :where 'page :direction 'next)))
-(put 'helm-next-page 'helm-only t)
-
-(defun helm-beginning-of-buffer ()
- "Move selection at the top."
- (interactive)
- (with-helm-alive-p
- (helm-move-selection-common :where 'edge :direction 'previous)))
-(put 'helm-beginning-of-buffer 'helm-only t)
-
-(defun helm-end-of-buffer ()
- "Move selection at the bottom."
- (interactive)
- (with-helm-alive-p
- (helm-move-selection-common :where 'edge :direction 'next)))
-(put 'helm-end-of-buffer 'helm-only t)
-
-(defun helm-previous-source ()
- "Move selection to the previous source."
- (interactive)
- (with-helm-alive-p
- (helm-move-selection-common :where 'source :direction 'previous)))
-(put 'helm-previous-source 'helm-only t)
-
-(defun helm-next-source ()
- "Move selection to the next source."
- (interactive)
- (with-helm-alive-p
- (helm-move-selection-common :where 'source :direction 'next)))
-(put 'helm-next-source 'helm-only t)
-
-(defun helm-goto-source (source-or-name)
- "Move the selection to the source SOURCE-OR-NAME."
- (helm-move-selection-common :where 'source :direction source-or-name))
-
-(defun helm--follow-action (arg)
- (let ((helm--temp-follow-flag t))
- (when (or (eq last-command 'helm-follow-action-forward)
- (eq last-command 'helm-follow-action-backward)
- (eq last-command 'helm-execute-persistent-action))
- (if (> arg 0)
- (helm-next-line 1)
- (helm-previous-line 1)))
- (helm-execute-persistent-action)))
-
-(defun helm-follow-action-forward ()
- "Go to next line and execute persistent action."
- (interactive)
- (with-helm-alive-p (helm--follow-action 1)))
-(put 'helm-follow-action-forward 'helm-only t)
-
-(defun helm-follow-action-backward ()
- "Go to previous line and execute persistent action."
- (interactive)
- (with-helm-alive-p (helm--follow-action -1)))
-(put 'helm-follow-action-backward 'helm-only t)
-
-(defun helm-mark-current-line (&optional resumep)
- "Move `helm-selection-overlay' to current line.
-Note that this is not related with visibles marks, which are used
-to mark candidates."
- (with-helm-window
- (when resumep
- (goto-char helm-selection-point))
- (move-overlay
- helm-selection-overlay (point-at-bol)
- (if (helm-pos-multiline-p)
- (let ((header-pos (helm-get-next-header-pos))
- (separator-pos (helm-get-next-candidate-separator-pos)))
- (or (and (null header-pos) separator-pos)
- (and header-pos separator-pos
- (< separator-pos header-pos)
- separator-pos)
- header-pos
- (point-max)))
- (1+ (point-at-eol))))
- (setq helm-selection-point (overlay-start helm-selection-overlay)))
- (helm-follow-execute-persistent-action-maybe))
-
-(defun helm-confirm-and-exit-minibuffer ()
- "Maybe ask for confirmation when exiting helm.
-It is similar to `minibuffer-complete-and-exit' adapted to helm.
-If `minibuffer-completion-confirm' value is 'confirm,
-send in minibuffer confirm message and exit on next hit.
-If `minibuffer-completion-confirm' value is t,
-don't exit and send message 'no match'."
- (interactive)
- (with-helm-alive-p
- (if (and (helm--updating-p)
- (null helm--reading-passwd-or-string))
- (progn (message "[Display not ready]")
- (sit-for 0.5) (message nil))
- (let* ((empty-buffer-p (with-current-buffer helm-buffer
- (eq (point-min) (point-max))))
- (sel (helm-get-selection))
- (unknown (and (not empty-buffer-p)
- (string= (get-text-property
- 0 'display
- (helm-get-selection nil 'withprop))
- "[?]"))))
- (cond ((and (or empty-buffer-p unknown)
- (eq minibuffer-completion-confirm 'confirm))
- (setq helm-minibuffer-confirm-state
- 'confirm)
- (setq minibuffer-completion-confirm nil)
- (minibuffer-message " [confirm]"))
- ((and (or empty-buffer-p
- (unless (if minibuffer-completing-file-name
- (and minibuffer-completion-predicate
- (funcall minibuffer-completion-predicate sel))
- (and (stringp sel)
- ;; SEL may be a cons cell when helm-comp-read
- ;; is called directly with a collection composed
- ;; of (display . real) and real is a cons cell.
- (try-completion sel minibuffer-completion-table
- minibuffer-completion-predicate)))
- unknown))
- (eq minibuffer-completion-confirm t))
- (minibuffer-message " [No match]"))
- (t
- (setq helm-minibuffer-confirm-state nil)
- (helm-exit-minibuffer)))))))
-(put 'helm-confirm-and-exit-minibuffer 'helm-only t)
-
-(add-hook 'helm-after-update-hook 'helm-confirm-and-exit-hook)
-
-(defun helm-confirm-and-exit-hook ()
- "Restore `minibuffer-completion-confirm' when helm update."
- (unless (or (eq minibuffer-completion-confirm t)
- (not helm-minibuffer-confirm-state))
- (setq minibuffer-completion-confirm
- helm-minibuffer-confirm-state)))
-
-(defun helm-read-string (prompt &optional initial-input history
- default-value inherit-input-method)
- "Same as `read-string' but for reading string from a helm session."
- (let ((helm--reading-passwd-or-string t))
- (read-string
- prompt initial-input history default-value inherit-input-method)))
-
-(defun helm--updating-p ()
- ;; helm timer is between two cycles.
- ;; IOW `helm-check-minibuffer-input' haven't yet compared input
- ;; and `helm-pattern'.
- (or (not (equal (minibuffer-contents) helm-pattern))
- ;; `helm-check-minibuffer-input' have launched `helm-update'.
- helm--in-update))
-
-(defun helm-maybe-exit-minibuffer ()
- (interactive)
- (with-helm-alive-p
- (if (and (helm--updating-p)
- (null helm--reading-passwd-or-string))
- (progn (message "[Display not ready]")
- (sit-for 0.5) (message nil))
- (helm-exit-minibuffer))))
-(put 'helm-maybe-exit-minibuffer 'helm-only t)
-
-(defun helm-exit-minibuffer ()
- "Select the current candidate by exiting the minibuffer."
- (unless helm-current-prefix-arg
- (setq helm-current-prefix-arg current-prefix-arg))
- (setq helm-exit-status 0)
- (helm-log-run-hook 'helm-exit-minibuffer-hook)
- (exit-minibuffer))
-
-(defun helm-keyboard-quit ()
- "Quit minibuffer in helm.
-If action buffer is displayed, kill it."
- (interactive)
- (with-helm-alive-p
- (when (get-buffer-window helm-action-buffer 'visible)
- (kill-buffer helm-action-buffer))
- (setq helm-exit-status 1)
- (abort-recursive-edit)))
-(put 'helm-keyboard-quit 'helm-only t)
-
-(defun helm-get-next-header-pos ()
- "Return the position of the next header from point."
- (next-single-property-change (point) 'helm-header))
-
-(defun helm-get-previous-header-pos ()
- "Return the position of the previous header from point."
- (previous-single-property-change (point) 'helm-header))
-
-(defun helm-pos-multiline-p ()
- "Return non-nil if the current position is in the multiline source region."
- (get-text-property (point) 'helm-multiline))
-
-(defun helm-get-next-candidate-separator-pos ()
- "Return the position of the next candidate separator from point."
- (let ((hp (helm-get-next-header-pos)))
- (helm-aif (next-single-property-change (point) 'helm-candidate-separator)
- (or
- ;; Be sure we don't catch
- ;; the separator of next source.
- (and hp (< it hp) it)
- ;; The separator found is in next source
- ;; we are at last cand, so use the header pos.
- (and hp (< hp it) hp)
- ;; A single source, just try next separator.
- it))))
-
-(defun helm-get-previous-candidate-separator-pos ()
- "Return the position of the previous candidate separator from point."
- (previous-single-property-change (point) 'helm-candidate-separator))
-
-(defun helm-pos-header-line-p ()
- "Return t if the current line is a header line."
- (or (get-text-property (point-at-bol) 'helm-header)
- (get-text-property (point-at-bol) 'helm-header-separator)))
-
-(defun helm-pos-candidate-separator-p ()
- "Return t if the current line is a candidate separator."
- (get-text-property (point-at-bol) 'helm-candidate-separator))
-
-\f
-;;; Debugging
-;;
-;;
-(defun helm-debug-output ()
- "Show all helm-related variables at this time."
- (interactive)
- (with-helm-alive-p
- (helm-help-internal " *Helm Debug*" 'helm-debug-output-function)))
-(put 'helm-debug-output 'helm-only t)
-
-(defun helm-debug-output-function (&optional vars)
- (message "Calculating all helm-related values...")
- (insert "If you debug some variables or forms, set `helm-debug-variables'
-to a list of forms.\n\n")
- (cl-dolist (v (or vars
- helm-debug-variables
- (apropos-internal "^helm-" 'boundp)))
- (insert "** "
- (pp-to-string v) "\n"
- (pp-to-string (with-current-buffer helm-buffer (eval v))) "\n"))
- (message "Calculating all helm-related values...Done"))
-
-;;;###autoload
-(defun helm-debug-toggle ()
- "Enable/disable helm debug from outside of helm session."
- (interactive)
- (setq helm-debug (not helm-debug))
- (message "Helm Debug is now %s"
- (if helm-debug "Enabled" "Disabled")))
-
-(defun helm-enable-or-switch-to-debug ()
- "First hit enable helm debugging, second hit switch to debug buffer."
- (interactive)
- (with-helm-alive-p
- (if helm-debug
- (helm-run-after-exit
- #'helm-debug-open-last-log)
- (setq helm-debug t)
- (message "Debugging enabled"))))
-(put 'helm-enable-or-switch-to-debug 'helm-only t)
-
-\f
-;; Core: misc
-(defun helm-kill-buffer-hook ()
- "Remove tick entry from `helm-tick-hash' and remove buffer from
-`helm-buffers' when killing a buffer."
- (cl-loop for key being the hash-keys in helm-tick-hash
- if (string-match (format "^%s/" (regexp-quote (buffer-name))) key)
- do (remhash key helm-tick-hash))
- (setq helm-buffers (remove (buffer-name) helm-buffers)))
-(add-hook 'kill-buffer-hook 'helm-kill-buffer-hook)
-
-(defun helm-preselect (candidate-or-regexp &optional source)
- "Move `helm-selection-overlay' to CANDIDATE-OR-REGEXP on startup.
-Arg CANDIDATE-OR-REGEXP can be a string or a cons cell of two strings.
-When it is a cons cell helm will try to jump first to first element of cons cell
-and then to second, allowing a finer preselection when possible duplicates are
-before the candidate we want to preselect."
- (with-helm-window
- (when candidate-or-regexp
- (if (and helm-force-updating-p source)
- (helm-goto-source source)
- (goto-char (point-min))
- (forward-line 1))
- (let ((start (point)))
- (or
- (if (consp candidate-or-regexp)
- (and (re-search-forward (car candidate-or-regexp) nil t)
- (re-search-forward (cdr candidate-or-regexp) nil t))
- (re-search-forward candidate-or-regexp nil t))
- (goto-char start))))
- (forward-line 0) ; Avoid scrolling right on long lines.
- (when (helm-pos-multiline-p)
- (helm-move--beginning-of-multiline-candidate))
- (when (helm-pos-header-line-p) (forward-line 1))
- (helm-mark-current-line)
- (helm-display-mode-line (helm-get-current-source))
- (helm-log-run-hook 'helm-after-preselection-hook)))
-
-(defun helm-delete-current-selection ()
- "Delete the currently selected item."
- (with-helm-window
- (cond ((helm-pos-multiline-p)
- (helm-aif (helm-get-next-candidate-separator-pos)
- (delete-region (point-at-bol)
- (1+ (progn (goto-char it) (point-at-eol))))
- ;; last candidate
- (goto-char (helm-get-previous-candidate-separator-pos))
- (delete-region (point-at-bol) (point-max)))
- (when (helm-end-of-source-p)
- (goto-char (or (helm-get-previous-candidate-separator-pos)
- (point-min)))
- (forward-line 1)))
- (t
- (delete-region (point-at-bol) (1+ (point-at-eol)))
- (when (helm-end-of-source-p t)
- (let ((headp (save-excursion
- (forward-line -1)
- (not (helm-pos-header-line-p)))))
- (and headp (forward-line -1))))))
- (unless (helm-end-of-source-p t)
- (helm-mark-current-line))))
-
-(defun helm-end-of-source-p (&optional at-point)
- "Return non--nil if we are at eob or end of source."
- (save-excursion
- (if (and (helm-pos-multiline-p) (null at-point))
- (null (helm-get-next-candidate-separator-pos))
- (forward-line (if at-point 0 1))
- (or (eq (point-at-bol) (point-at-eol))
- (helm-pos-header-line-p)
- (eobp)))))
-
-(defun helm-beginning-of-source-p (&optional at-point)
- "Return non--nil if we are at bob or beginning of source."
- (save-excursion
- (if (and (helm-pos-multiline-p) (null at-point))
- (null (helm-get-previous-candidate-separator-pos))
- (forward-line (if at-point 0 -1))
- (or (eq (point-at-bol) (point-at-eol))
- (helm-pos-header-line-p)
- (bobp)))))
-
-(defun helm-edit-current-selection-internal (func)
- (with-helm-window
- (forward-line 0)
- (let ((realvalue (get-text-property (point) 'helm-realvalue))
- (multiline (get-text-property (point) 'helm-multiline)))
- (funcall func)
- (forward-line 0)
- (and realvalue
- (put-text-property (point) (point-at-eol)
- 'helm-realvalue realvalue))
- (and multiline
- (put-text-property (point) (point-at-eol)
- 'helm-multiline multiline))
- (helm-mark-current-line))))
-
-(defmacro helm-edit-current-selection (&rest forms)
- "Evaluate FORMS at current selection in the helm buffer.
-Used generally to modify current selection."
- (declare (indent 0) (debug t))
- `(helm-edit-current-selection-internal
- (lambda () ,@forms)))
-
-(defun helm--delete-minibuffer-contents-from (from-str)
- ;; Giving an empty string value to FROM-STR delete all.
- (let ((input (minibuffer-contents)))
- (helm-reset-yank-point)
- (if (> (length input) 0)
- ;; minibuffer is not empty, delete contents from end
- ;; of FROM-STR and update.
- (helm-set-pattern from-str)
- ;; minibuffer is already empty, force update.
- (helm-force-update))))
-
-(defun helm-delete-minibuffer-contents (&optional arg)
- "Delete minibuffer contents.
-When `helm-delete-minibuffer-contents-from-point' is non--nil,
-delete minibuffer contents from point instead of deleting all.
-Giving a prefix arg reverse this behavior.
-When at end of minibuffer delete all."
- (interactive "P")
- (let ((str (if helm-delete-minibuffer-contents-from-point
- (if (or arg (eobp))
- "" (helm-minibuffer-completion-contents))
- (if (and arg (not (eobp)))
- (helm-minibuffer-completion-contents) ""))))
- (helm--delete-minibuffer-contents-from str)))
-
-\f
-;;; Plugins (Deprecated in favor of helm-types)
-;;
-;; i.e Inherit instead of helm-type-* classes in your own classes.
-
-;; [DEPRECATED] Enable multi-match by default in old sources.
-;; This is deprecated and will not run in sources
-;; created by helm-source.
-;; Keep it for backward compatibility with old sources.
-(defun helm-compile-source--multi-match (source)
- (if (assoc 'no-matchplugin source)
- source
- (let* ((searchers helm-mm-default-search-functions)
- (defmatch (helm-aif (assoc-default 'match source)
- (helm-mklist it)))
- (defmatch-strict (helm-aif (assoc-default 'match-strict source)
- (helm-mklist it)))
- (defsearch (helm-aif (assoc-default 'search source)
- (helm-mklist it)))
- (defsearch-strict (helm-aif (assoc-default 'search-strict source)
- (helm-mklist it)))
- (matchfns (cond (defmatch-strict)
- (defmatch
- (append helm-mm-default-match-functions defmatch))
- (t helm-mm-default-match-functions)))
- (searchfns (cond (defsearch-strict)
- (defsearch
- (append searchers defsearch))
- (t searchers))))
- `(,(if (assoc 'candidates-in-buffer source)
- `(search ,@searchfns) `(match ,@matchfns))
- ,@source))))
-
-(add-to-list 'helm-compile-source-functions 'helm-compile-source--multi-match)
-
-(defun helm-compile-source--type (source)
- (helm-aif (assoc-default 'type source)
- (append source (assoc-default it helm-type-attributes) nil)
- source))
-
-(defun define-helm-type-attribute (type definition &optional doc)
- "Register type attribute of TYPE as DEFINITION with DOC.
-DOC is displayed in `helm-type-attributes' docstring.
-
-Use this function is better than setting `helm-type-attributes' directly."
- (cl-loop for i in definition do
- ;; without `ignore-errors', error at emacs22
- (ignore-errors (setf i (delete nil i))))
- (helm-add-type-attribute type definition)
- (and doc (helm-document-type-attribute type doc))
- nil)
-
-(defun helm-document-attribute (attribute short-doc &optional long-doc)
- "Register ATTRIBUTE documentation introduced by plug-in.
-SHORT-DOC is displayed beside attribute name.
-LONG-DOC is displayed below attribute name and short documentation."
- (declare (indent 2))
- (if long-doc
- (setq short-doc (concat "(" short-doc ")"))
- (setq long-doc short-doc
- short-doc ""))
- (add-to-list 'helm-attributes attribute t)
- (put attribute 'helm-attrdoc
- (concat "- " (symbol-name attribute)
- " " short-doc "\n\n" long-doc "\n")))
-
-(defun helm-add-type-attribute (type definition)
- (helm-aif (assq type helm-type-attributes)
- (setq helm-type-attributes (delete it helm-type-attributes)))
- (push (cons type definition) helm-type-attributes))
-
-(defun helm-document-type-attribute (type doc)
- (add-to-list 'helm-types type t)
- (put type 'helm-typeattrdoc
- (concat "- " (symbol-name type) "\n\n" doc "\n")))
-
-;; Built-in plug-in: dummy
-(defun helm-dummy-candidate (_candidate _source)
- "Use `helm-pattern' as CANDIDATE in SOURCE."
- ;; `source' is defined in filtered-candidate-transformer
- (list helm-pattern))
-
-(defun helm-compile-source--dummy (source)
- (if (assoc 'dummy source)
- (progn
- (unless (helm-attr-defined
- 'filtered-candidate-transformer source)
- (helm-attrset 'filtered-candidate-transformer
- 'helm-dummy-candidate source))
- (append source
- '((candidates "dummy")
- (accept-empty)
- (match identity)
- (volatile))))
- source))
-
-;; Built-in plug-in: candidates-in-buffer
-(defun helm-candidates-in-buffer (&optional source)
- "The top level function used to store candidates in `helm-source-in-buffer'.
-
-Candidates are stored in a buffer generated internally by the function
-`helm-candidate-buffer'. Each candidate must be placed in one line.
-This function is meant to be used in candidates-in-buffer or candidates
-attribute of an helm source. Especially fast for many (1000+) candidates.
-
-The buffer is created and feeded in the init attribute function of helm.
-
-e.g:
-
- (helm-build-in-buffer-source \"test\"
- :init (lambda ()
- (helm-init-candidates-in-buffer
- 'global '(foo foa fob bar baz))))
-
-A shortcut can be used to simplify:
-
- (helm-build-in-buffer-source \"test\"
- :data '(foo foa fob bar baz))
-
-The usage of the `candidates-in-buffer' is deprecated in favor
-of `helm-source-in-buffer' class.
-
-It is anyway described below and provided for backward compatibility.
-
-By default, `helm' makes candidates by evaluating the
-candidates function, then narrows them by `string-match' for each
-candidate.
-
-But this way is very slow for many candidates. The new way is
-storing all candidates in a buffer and narrowing them by
-`re-search-forward'. Search function is customizable by search
-attribute. The important point is that buffer processing is MUCH
-FASTER than string list processing and is the Emacs way.
-
-The init function writes all candidates to a newly-created
-candidate buffer. The candidates buffer is created or specified
-by `helm-candidate-buffer'. Candidates are stored in a line.
-
-The candidates function narrows all candidates, IOW creates a
-subset of candidates dynamically. It is the task of
-`helm-candidates-in-buffer'. As long as
-`helm-candidate-buffer' is used,`(candidates-in-buffer)' is
-sufficient in most cases.
-
-Note that `(candidates-in-buffer)' is shortcut of three attributes:
- (candidates . helm-candidates-in-buffer)
- (volatile)
- (match identity)
-And `(candidates-in-buffer . func)' is shortcut of three attributes:
- (candidates . func)
- (volatile)
- (match identity)
-The expansion is performed in `helm-get-sources'.
-
-The `candidates-in-buffer' attribute implies the volatile attribute.
-The volatile attribute is needed because `helm-candidates-in-buffer'
-creates candidates dynamically and need to be called everytime
-`helm-pattern' changes.
-
-Because `helm-candidates-in-buffer' plays the role of `match' attribute
-function, specifying `(match identity)' makes the source slightly faster.
-
-However if source contain `match-part' attribute, match is computed only
-on part of candidate returned by the call of function provided by this attribute.
-The function should have one arg, candidate, and return only
-a specific part of candidate.
-
-To customize `helm-candidates-in-buffer' behavior, use `search',
-`get-line' and `match-part' attributes."
- (let ((src (or source (helm-get-current-source))))
- (helm-candidates-in-buffer-1
- (helm-candidate-buffer)
- helm-pattern
- (or (assoc-default 'get-line src)
- #'buffer-substring-no-properties)
- (or (assoc-default 'search src)
- '(helm-candidates-in-buffer-search-default-fn))
- (helm-candidate-number-limit src)
- (helm-attr 'match-part)
- src)))
-
-(defun helm-candidates-in-buffer-search-default-fn (pattern)
- "Search PATTERN with `re-search-forward' with bound and noerror args."
- (condition-case _err
- (re-search-forward pattern nil t)
- (invalid-regexp nil)))
-
-(defun helm-candidates-in-buffer-1 (buffer pattern get-line-fn
- search-fns limit
- match-part-fn source)
- "Return the list of candidates inserted in BUFFER matching PATTERN."
- ;; buffer == nil when candidates buffer does not exist.
- (when buffer
- (with-current-buffer buffer
- (let ((inhibit-point-motion-hooks t)
- (start-point (1- (point-min))))
- (goto-char start-point)
- (if (string= pattern "")
- (helm-initial-candidates-from-candidate-buffer
- get-line-fn limit)
- (helm-search-from-candidate-buffer
- pattern get-line-fn search-fns limit
- start-point match-part-fn source))))))
-
-
-(defun helm-search-from-candidate-buffer (pattern get-line-fn search-fns
- limit start-point match-part-fn source)
- (let (buffer-read-only)
- (helm--search-from-candidate-buffer-1
- (lambda ()
- (cl-loop with hash = (make-hash-table :test 'equal)
- with allow-dups = (assq 'allow-dups source)
- with case-fold-search = (helm-set-case-fold-search)
- with count = 0
- for iter from 1
- for searcher in search-fns
- do (progn
- (goto-char start-point)
- ;; The character at start-point is a newline,
- ;; if pattern match it that's mean we are
- ;; searching for newline in buffer, in this
- ;; case skip this false line.
- ;; See comment >>>[1] in
- ;; `helm--search-from-candidate-buffer-1'.
- (and (looking-at pattern) (forward-line 1)))
- nconc
- (cl-loop with pos-lst
- while (and (setq pos-lst (funcall searcher pattern))
- (not (eobp))
- (< count limit))
- for cand = (apply get-line-fn
- (if (and pos-lst (listp pos-lst))
- pos-lst
- (list (point-at-bol) (point-at-eol))))
- for dup = (gethash cand hash)
- when (and (or (and allow-dups dup (= dup iter))
- (null dup))
- (or
- ;; Always collect when cand is matched
- ;; by searcher funcs and match-part attr
- ;; is not present.
- (and (not match-part-fn)
- (not (consp pos-lst)))
- ;; If match-part attr is present, or if SEARCHER fn
- ;; returns a cons cell, collect PATTERN only if it
- ;; match the part of CAND specified by
- ;; the match-part func.
- (helm-search-match-part
- cand pattern (or match-part-fn #'identity))))
- do (progn
- (puthash cand iter hash)
- (helm--maybe-process-filter-one-by-one-candidate cand source)
- (cl-incf count))
- and collect cand))))))
-
-(defun helm-search-match-part (candidate pattern match-part-fn)
- "Match PATTERN only on part of CANDIDATE returned by MATCH-PART-FN.
-Because `helm-search-match-part' maybe called even if unspecified
-in source (negation), MATCH-PART-FN default to `identity'
-to match whole candidate.
-When using fuzzy matching and negation (i.e \"!\"),
-this function is always called."
- (let ((part (funcall match-part-fn candidate))
- (fuzzy-regexp (cadr (gethash 'helm-pattern helm--fuzzy-regexp-cache)))
- (matchfn (if helm-migemo-mode
- 'helm-mm-migemo-string-match 'string-match)))
- (if (string-match " " pattern)
- (cl-loop for i in (split-string pattern) always
- (if (string-match "\\`!" i)
- (not (funcall matchfn (substring i 1) part))
- (funcall matchfn i part)))
- (if (string-match "\\`!" pattern)
- (if helm--in-fuzzy
- ;; Fuzzy regexp have already been
- ;; computed with substring 1.
- (not (string-match fuzzy-regexp part))
- (not (funcall matchfn (substring pattern 1) part)))
- (funcall matchfn (if helm--in-fuzzy fuzzy-regexp pattern) part)))))
-
-(defun helm-initial-candidates-from-candidate-buffer (get-line-fn limit)
- (delq nil (cl-loop for i from 1 to limit
- until (eobp)
- collect (funcall get-line-fn
- (point-at-bol) (point-at-eol))
- do (forward-line 1))))
-
-(defun helm--search-from-candidate-buffer-1 (search-fn)
- ;; We are adding a newline at bob and at eol
- ;; and removing these newlines afterward.
- ;; This is a bad hack that should be removed.
- ;; To avoid matching the empty line at first line
- ;; when searching with e.g occur and "^$" just
- ;; forward-line before searching (See >>>[1] above).
- (goto-char (point-min))
- (insert "\n")
- (goto-char (point-max))
- (insert "\n")
- (unwind-protect
- (funcall search-fn)
- (goto-char (point-min))
- (delete-char 1)
- (goto-char (1- (point-max)))
- (delete-char 1)
- (set-buffer-modified-p nil)))
-
-(defun helm-candidate-buffer (&optional create-or-buffer)
- "Register and return a buffer containing candidates of current source.
-`helm-candidate-buffer' searches buffer-local candidates buffer first,
-then global candidates buffer.
-
-Acceptable values of CREATE-OR-BUFFER:
-
-- nil (omit)
- Only return the candidates buffer.
-- a buffer
- Register a buffer as a candidates buffer.
-- 'global
- Create a new global candidates buffer,
- named \" *helm candidates:SOURCE*\".
-- other non-nil value
- Create a new local candidates buffer,
- named \" *helm candidates:SOURCE*HELM-CURRENT-BUFFER\"."
- (let* ((global-bname (format " *helm candidates:%s*"
- helm-source-name))
- (local-bname (format " *helm candidates:%s*%s"
- helm-source-name
- (buffer-name helm-current-buffer)))
- (register-func
- (lambda ()
- (setq helm-candidate-buffer-alist
- (cons (cons helm-source-name create-or-buffer)
- (delete (assoc helm-source-name
- helm-candidate-buffer-alist)
- helm-candidate-buffer-alist)))))
- (kill-buffers-func
- (lambda ()
- (cl-loop for b in (buffer-list)
- if (string-match (format "^%s" (regexp-quote global-bname))
- (buffer-name b))
- do (kill-buffer b))))
- (create-func
- (lambda ()
- (with-current-buffer
- (get-buffer-create (if (eq create-or-buffer 'global)
- global-bname
- local-bname))
- (set (make-local-variable 'inhibit-read-only) t) ; Fix (#1176)
- (buffer-disable-undo)
- (erase-buffer)
- (font-lock-mode -1))))
- (return-func
- (lambda ()
- (or (get-buffer local-bname)
- (get-buffer global-bname)
- (helm-aif (assoc-default helm-source-name
- helm-candidate-buffer-alist)
- (and (buffer-live-p it) it))))))
- (when create-or-buffer
- (funcall register-func)
- (unless (bufferp create-or-buffer)
- (and (eq create-or-buffer 'global) (funcall kill-buffers-func))
- (funcall create-func)))
- (funcall return-func)))
-
-(defun helm-init-candidates-in-buffer (buffer data)
- "Register BUFFER with DATA for a helm candidates-in-buffer session.
-Arg BUFFER can be a string, a buffer object (bufferp), or a symbol,
-either 'local or 'global which is passed to `helm-candidate-buffer'.
-Arg DATA can be either a list or a plain string.
-Returns the resulting buffer."
- (declare (indent 1))
- (let ((buf (helm-candidate-buffer
- (if (or (stringp buffer)
- (bufferp buffer))
- (get-buffer-create buffer)
- buffer)))) ; a symbol.
- (with-current-buffer buf
- (erase-buffer)
- (if (listp data)
- (insert (mapconcat (lambda (i)
- (cond ((symbolp i) (symbol-name i))
- ((numberp i) (number-to-string i))
- (t i)))
- data "\n"))
- (and (stringp data) (insert data))))
- buf))
-
-(defun helm-compile-source--candidates-in-buffer (source)
- (helm-aif (assoc 'candidates-in-buffer source)
- (append source
- `((candidates . ,(or (cdr it)
- (lambda ()
- (helm-candidates-in-buffer source))))
- (volatile) (match identity)))
- source))
-
-\f
-;;; Resplit helm window
-;;
-;;
-(defun helm-toggle-resplit-window ()
- "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)))))
-(put 'helm-toggle-resplit-window 'helm-only t)
-
-;; Utility: Resize helm window.
-(defun helm-enlarge-window-1 (n)
- "Enlarge or narrow helm window.
-If N is positive enlarge, if negative narrow."
- (unless helm-full-frame
- (let ((horizontal-p (eq helm-split-window-state 'horizontal)))
- (with-helm-window
- (enlarge-window n horizontal-p)))))
-
-(defun helm-narrow-window ()
- "Narrow helm window."
- (interactive)
- (with-helm-alive-p
- (helm-enlarge-window-1 -1)))
-(put 'helm-narrow-window 'helm-only t)
-
-(defun helm-enlarge-window ()
- "Enlarge helm window."
- (interactive)
- (with-helm-alive-p
- (helm-enlarge-window-1 1)))
-(put 'helm-enlarge-window 'helm-only t)
-
-(defun helm-swap-windows ()
- "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))))))
-(put 'helm-swap-windows 'helm-only t)
-
-(defun helm--get-window-side-state ()
- "Return the position of `helm-window' from `helm-current-buffer'.
-Possible values are 'left 'right 'below or 'above."
- (let ((side-list '(left right below above)))
- (cl-loop for side in side-list
- thereis (and (equal (helm-window)
- (window-in-direction
- side (get-buffer-window helm-current-buffer t)
- t))
- side))))
-
-(defun helm-replace-buffer-in-window (window buffer1 buffer2)
- "Replace BUFFER1 by BUFFER2 in WINDOW registering BUFFER1."
- (when (get-buffer-window buffer1)
- (unrecord-window-buffer window buffer1)
- (set-window-buffer window buffer2)))
-
-;; Utility: select another action by key
-(defun helm-select-nth-action (n)
- "Select the N nth action for the currently selected candidate."
- (setq helm-saved-selection (helm-get-selection))
- (unless helm-saved-selection
- (error "Nothing is selected"))
- (setq helm-saved-action
- (helm-get-nth-action
- n
- (if (get-buffer-window helm-action-buffer 'visible)
- (assoc-default 'candidates (helm-get-current-source))
- (helm-get-actions-from-current-source))))
- (helm-maybe-exit-minibuffer))
-
-(defun helm-get-nth-action (n action)
- (cond ((and (zerop n) (functionp action))
- action)
- ((listp action)
- (or (cdr (elt action n))
- (error "No such action")))
- ((and (functionp action) (< 0 n))
- (error "Sole action"))
- (t
- (error "Error in `helm-select-nth-action'"))))
-
-(defun helm-execute-selection-action-at-nth (linum)
- "Allow to execute default action on candidate at LINUM."
- (let ((prefarg current-prefix-arg))
- (if (>= linum 0)
- (helm-next-line linum)
- (helm-previous-line (lognot (1- linum))))
- (setq current-prefix-arg prefarg)
- (helm-exit-minibuffer)))
-
-;; Utility: Persistent Action
-(defmacro with-helm-display-same-window (&rest body)
- "Execute BODY in the window used for persistent action.
-Make `pop-to-buffer' and `display-buffer' display in the same window."
- (declare (indent 0) (debug t))
- `(let ((display-buffer-function 'helm-persistent-action-display-buffer))
- ,@body))
-
-(defun helm-initialize-persistent-action ()
- (set (make-local-variable 'helm-persistent-action-display-window) nil))
-
-(cl-defun helm-execute-persistent-action
- (&optional (attr 'persistent-action) split-onewindow)
- "Perform the associated action ATTR without quitting helm.
-ATTR default is 'persistent-action', but it can be anything else.
-In this case you have to add this new attribute to your source.
-
-When `helm-full-frame' or SPLIT-ONEWINDOW are non--nil,
-and `helm-buffer' is displayed in only one window,
-the helm window is splitted to display
-`helm-select-persistent-action-window' in other window
-and keep its visibility."
- (interactive)
- (with-helm-alive-p
- (helm-log "executing persistent-action")
- (let* ((attr-val (assoc-default attr (helm-get-current-source)))
- ;; If attr value is a cons, use its car as persistent function
- ;; and its car to decide if helm window should be splitted.
- (fn (if (and (consp attr-val)
- ;; maybe a lambda.
- (not (functionp attr-val)))
- (car attr-val) attr-val))
- (no-split (and (consp attr-val)
- (not (functionp attr-val))
- (cdr attr-val))))
- (with-helm-window
- (save-selected-window
- (if no-split
- (helm-select-persistent-action-window)
- (helm-select-persistent-action-window
- (or split-onewindow helm-onewindow-p)))
- (helm-log "current-buffer = %S" (current-buffer))
- (let ((helm-in-persistent-action t))
- (with-helm-display-same-window
- (helm-execute-selection-action-1
- nil (or fn (helm-get-actions-from-current-source)) t)
- (helm-log-run-hook 'helm-after-persistent-action-hook))
- ;; A typical case is when a persistent action delete
- ;; the buffer already displayed in
- ;; `helm-persistent-action-display-window' and `helm-full-frame'
- ;; is enabled, we end up with the `helm-buffer'
- ;; displayed in two windows.
- (when (and helm-onewindow-p
- (> (length (window-list)) 1)
- (equal (buffer-name
- (window-buffer
- helm-persistent-action-display-window))
- (helm-buffer-get)))
- (delete-other-windows))))))))
-(put 'helm-execute-persistent-action 'helm-only t)
-
-(defun helm-persistent-action-display-window (&optional split-onewindow)
- "Return the window that will be used for persistent action.
-If SPLIT-ONEWINDOW is non--nil window will be splitted in persistent action."
- (with-helm-window
- (setq helm-persistent-action-display-window
- (cond ((and (window-live-p helm-persistent-action-display-window)
- (not (member helm-persistent-action-display-window
- (get-buffer-window-list helm-buffer))))
- helm-persistent-action-display-window)
- (split-onewindow (split-window))
- ((get-buffer-window helm-current-buffer))
- (t (next-window (selected-window) 1))))))
-
-(defun helm-select-persistent-action-window (&optional split-onewindow)
- "Select the window that will be used for persistent action.
-See `helm-persistent-action-display-window' for how to use SPLIT-ONEWINDOW."
- (select-window (get-buffer-window (helm-buffer-get)))
- (select-window
- (setq minibuffer-scroll-window
- (helm-persistent-action-display-window split-onewindow))))
-
-(defun helm-persistent-action-display-buffer (buf &optional action)
- "Make `pop-to-buffer' and `display-buffer' display in the same window.
-If `helm-persistent-action-use-special-display' is non-nil and
-BUF is to be displayed by `special-display-function', use it.
-Otherwise ignores `special-display-buffer-names' and `special-display-regexps'.
-Argument ACTION if present will be used as second argument of `display-buffer'."
- (let* ((name (buffer-name buf))
- display-buffer-function pop-up-windows pop-up-frames
- ;; Disable `special-display-regexps' and `special-display-buffer-names'
- ;; unless `helm-persistent-action-use-special-display' is non--nil.
- (special-display-buffer-names
- (and helm-persistent-action-use-special-display
- special-display-buffer-names))
- (special-display-regexps
- (and helm-persistent-action-use-special-display
- special-display-regexps))
- (same-window-regexps
- (unless (and helm-persistent-action-use-special-display
- (or (member name
- (mapcar (lambda (x) (or (car-safe x) x))
- special-display-buffer-names))
- (cl-loop for x in special-display-regexps
- thereis (string-match (or (car-safe x) x)
- name))))
- '("."))))
- ;; Don't loose minibuffer when displaying persistent window in
- ;; another frame.
- ;; This happen when the displayed persistent buffer-name is one of
- ;; `special-display-buffer-names' or match `special-display-regexps'
- ;; and `helm-persistent-action-use-special-display' is enabled.
- (with-selected-window (if (or special-display-regexps
- special-display-buffer-names)
- (minibuffer-window)
- (selected-window))
- ;; Be sure window of BUF is not dedicated.
- (set-window-dedicated-p (get-buffer-window buf) nil)
- (display-buffer buf action))))
-
-;; scroll-other-window(-down)? for persistent-action
-(defun helm-other-window-base (command &optional scroll-amount)
- (setq scroll-amount (unless (eq scroll-amount 'noscroll)
- helm-scroll-amount))
- (with-selected-window (helm-persistent-action-display-window)
- (funcall command scroll-amount)))
-
-(defun helm-scroll-other-window ()
- "Scroll other window (not *Helm* window) upward."
- (interactive)
- (with-helm-alive-p (helm-other-window-base 'scroll-up)))
-(put 'helm-scroll-other-window 'helm-only t)
-
-(defun helm-scroll-other-window-down ()
- "Scroll other window (not *Helm* window) downward."
- (interactive)
- (with-helm-alive-p (helm-other-window-base 'scroll-down)))
-(put 'helm-scroll-other-window-down 'helm-only t)
-
-(defun helm-recenter-top-bottom-other-window ()
- "`recenter-top-bottom' in other window (not *Helm* window)."
- (interactive)
- (with-helm-alive-p (helm-other-window-base 'recenter-top-bottom 'noscroll)))
-(put 'helm-recenter-top-bottom-other-window 'helm-only t)
-
-(defun helm-reposition-window-other-window ()
- "`helm-reposition-window' in other window (not *Helm* window)."
- (interactive)
- (with-helm-alive-p (helm-other-window-base 'reposition-window 'noscroll)))
-(put 'helm-reposition-window-other-window 'helm-only t)
-
-
-\f
-;; Utility: Visible Mark
-
-(defun helm-clear-visible-mark ()
- (with-current-buffer (helm-buffer-get)
- (mapc 'delete-overlay helm-visible-mark-overlays)
- (set (make-local-variable 'helm-visible-mark-overlays) nil)))
-
-(defun helm-this-visible-mark ()
- (cl-loop for o in helm-visible-mark-overlays
- when (equal (point-at-bol) (overlay-start o))
- return o))
-
-(defun helm-delete-visible-mark (overlay)
- (setq helm-marked-candidates
- (remove
- (cons (helm-get-current-source) (helm-get-selection))
- helm-marked-candidates))
- (delete-overlay overlay)
- (setq helm-visible-mark-overlays
- (delq overlay helm-visible-mark-overlays)))
-
-(defun helm-make-visible-mark ()
- (let ((o (make-overlay (point-at-bol)
- (if (helm-pos-multiline-p)
- (or (helm-get-next-candidate-separator-pos)
- (point-max))
- (1+ (point-at-eol))))))
- (overlay-put o 'priority 0)
- (overlay-put o 'face 'helm-visible-mark)
- (overlay-put o 'source (assoc-default 'name (helm-get-current-source)))
- (overlay-put o 'string (buffer-substring (overlay-start o) (overlay-end o)))
- (overlay-put o 'real (helm-get-selection))
- (add-to-list 'helm-visible-mark-overlays o))
- (push (cons (helm-get-current-source) (helm-get-selection))
- helm-marked-candidates))
-
-(defun helm-toggle-visible-mark ()
- "Toggle helm visible mark at point."
- (interactive)
- (with-helm-alive-p
- (with-helm-window
- (let ((nomark (assq 'nomark (helm-get-current-source))))
- (if nomark
- (message "Marking not allowed in this source")
- (helm-aif (helm-this-visible-mark)
- (helm-delete-visible-mark it)
- (helm-make-visible-mark))
- (if (helm-end-of-source-p)
- (helm-display-mode-line (helm-get-current-source))
- (helm-next-line)))))))
-(put 'helm-toggle-visible-mark 'helm-only t)
-
-(defun helm-file-completion-source-p ()
- "Return non--nil if current source is a file completion source."
- (or minibuffer-completing-file-name
- (let ((cur-source (cdr (assoc 'name (helm-get-current-source)))))
- (cl-loop for i in helm--file-completion-sources
- thereis (string= cur-source i)))))
-
-(defun helm-mark-all ()
- "Mark all visible unmarked candidates in current source."
- (interactive)
- (with-helm-alive-p
- (with-helm-window
- (let ((nomark (assq 'nomark (helm-get-current-source)))
- (follow (if helm-follow-mode 1 -1)))
- (helm-follow-mode -1)
- (unwind-protect
- (if nomark
- (message "Marking not allowed in this source")
- (save-excursion
- (goto-char (helm-get-previous-header-pos))
- (helm-next-line)
- (let* ((next-head (helm-get-next-header-pos))
- (end (and next-head
- (save-excursion
- (goto-char next-head)
- (forward-line -1)
- (point))))
- (maxpoint (or end (point-max))))
- (while (< (point) maxpoint)
- (helm-mark-current-line)
- (let* ((prefix (get-text-property (point-at-bol) 'display))
- (cand (helm-get-selection))
- (bn (and (helm-file-completion-source-p)
- (helm-basename cand)))
- (src-name (assoc-default 'name
- (helm-get-current-source))))
- (when (and (not (helm-this-visible-mark))
- (not (or (string= prefix "[?]")
- (string= prefix "[@]"))))
- ;; Don't mark possibles directories ending with . or ..
- ;; autosave files/links and non--existent file.
- (unless
- (and (or (helm-file-completion-source-p)
- (string=
- src-name "Files from Current Directory"))
- (or (string-match
- "^[.]?#.*#?$\\|[^#]*[.]\\{1,2\\}$" bn)
- ;; We need to test here when not using
- ;; a transformer that tag prefix
- ;; (i.e on tramp).
- (not (file-exists-p cand))))
- (helm-make-visible-mark))))
- (if (helm-pos-multiline-p)
- (progn
- (goto-char
- (or (helm-get-next-candidate-separator-pos)
- (point-max)))
- (forward-line 1))
- (forward-line 1))
- (end-of-line))))
- (helm-mark-current-line))
- (helm-follow-mode follow) (message nil))))))
-(put 'helm-mark-all 'helm-only t)
-
-(defun helm-unmark-all ()
- "Unmark all candidates in all sources of current helm session."
- (interactive)
- (with-helm-alive-p
- (with-helm-window
- (save-excursion
- (helm-clear-visible-mark))
- (setq helm-marked-candidates nil)
- (helm-mark-current-line)
- (helm-display-mode-line (helm-get-current-source)))))
-(put 'helm-unmark-all 'helm-only t)
-
-(defun helm-toggle-all-marks ()
- "Toggle all marks.
-Mark all visible candidates of current source or unmark all candidates
-visible or invisible in all sources of current helm session"
- (interactive)
- (with-helm-alive-p
- (let ((marked (helm-marked-candidates)))
- (if (and (>= (length marked) 1)
- (with-helm-window helm-visible-mark-overlays))
- (helm-unmark-all)
- (helm-mark-all)))))
-(put 'helm-toggle-all-marks 'helm-only t)
-
-(defun helm--compute-marked (real source wildcard)
- (let* ((coerced (helm-coerce-selection real source))
- (wilds (and wildcard
- (condition-case nil
- (helm-file-expand-wildcards coerced t)
- (error nil)))))
- ;; Avoid returning a not expanded wilcard fname.
- ;; e.g assuming "/tmp" doesn't contain "*.el"
- ;; return nil when coerced is "/tmp/*.el".
- (unless (or wilds (null wildcard)
- (string-match-p helm--url-regexp coerced)
- (file-exists-p coerced)
- (and (stringp coerced)
- (null (string-match-p "[[*?]" coerced))))
- (setq coerced nil))
- (or wilds (and coerced (list coerced)))))
-
-(cl-defun helm-marked-candidates (&key with-wildcard)
- "Return marked candidates of current source if any.
-Otherwise one element list of current selection.
-When key WITH-WILDCARD is specified try to expand a wilcard if some."
- (with-current-buffer helm-buffer
- (let ((candidates
- (cl-loop with current-src = (helm-get-current-source)
- for (source . real) in (reverse helm-marked-candidates)
- when (equal (assq 'name source) (assq 'name current-src))
- append (helm--compute-marked real source with-wildcard)
- into cands
- finally return (or cands
- (append
- (helm--compute-marked
- (helm-get-selection) current-src
- with-wildcard)
- cands)))))
- (helm-log "Marked candidates = %S" candidates)
- candidates)))
-
-(defun helm-current-source-name= (name)
- (save-excursion
- (goto-char (helm-get-previous-header-pos))
- (equal name (helm-current-line-contents))))
-
-(defun helm-revive-visible-mark ()
- "Restore marked candidates when helm update display."
- (with-current-buffer helm-buffer
- (save-excursion
- (cl-dolist (o helm-visible-mark-overlays)
- (let ((o-src-str (overlay-get o 'source))
- (o-str (overlay-get o 'string))
- beg end)
- ;; Move point to end of source header line.
- (goto-char (point-min))
- (search-forward o-src-str nil t)
- (while (and (search-forward o-str nil t)
- (not (overlays-at (point-at-bol 0)))
- (helm-current-source-name= o-src-str))
- (setq beg (match-beginning 0)
- end (match-end 0))
- ;; Calculate real value of candidate.
- ;; It can be nil if candidate have only a display value.
- (let ((real (get-text-property (point-at-bol 0) 'helm-realvalue)))
- (if real
- ;; Check if real value of current candidate is the same
- ;; than the one stored in overlay.
- ;; This is needed when some cands have same display names.
- ;; Using equal allow testing any type of value for real cand.
- ;; Issue (#706).
- (and (equal (overlay-get o 'real) real)
- (move-overlay o beg end))
- (and (equal o-str (buffer-substring beg end))
- (move-overlay o beg end))))))))))
-(add-hook 'helm-update-hook 'helm-revive-visible-mark)
-
-(defun helm-next-point-in-list (curpos points &optional prev)
- (cond
- ;; rule out special cases.
- ((null points) curpos)
- ((and prev (<= curpos (car points)))
- (nth (1- (length points)) points))
- ((< (car (last points)) curpos)
- (if prev (car (last points)) (nth 0 points)))
- ((and (not prev) (>= curpos (car (last points))))
- (nth 0 points))
- (t
- (nth (if prev
- (cl-loop for pt in points
- for i from 0
- if (<= curpos pt) return (1- i))
- (cl-loop for pt in points
- for i from 0
- if (< curpos pt) return i))
- points))))
-
-(defun helm-next-visible-mark (&optional prev)
- "Move next helm visible mark.
-If PREV is non-nil move to precedent."
- (interactive)
- (with-helm-alive-p
- (with-helm-window
- (ignore-errors
- (goto-char (helm-next-point-in-list
- (point)
- (sort (mapcar 'overlay-start helm-visible-mark-overlays) '<)
- prev)))
- (helm-mark-current-line))))
-(put 'helm-next-visible-mark 'helm-only t)
-
-(defun helm-prev-visible-mark ()
- "Move previous helm visible mark."
- (interactive)
- (with-helm-alive-p
- (helm-next-visible-mark t)))
-(put 'helm-prev-visible-mark 'helm-only t)
-
-;;; Utility: Selection Paste
-;;
-(defun helm-yank-selection (arg)
- "Set minibuffer contents to current display selection.
-With a prefix arg set to real value of current selection."
- (interactive "P")
- (with-helm-alive-p
- (let ((str (helm-get-selection nil (not arg))))
- (kill-new str)
- (helm-set-pattern str))))
-(put 'helm-yank-selection 'helm-only t)
-
-(defun helm-kill-selection-and-quit (arg)
- "Store display value of current selection to kill ring.
-With a prefix arg set to real value of current selection.
-Display value is what you see in `helm-buffer' and real value
-is what is used to perform actions."
- (interactive "P")
- (with-helm-alive-p
- (helm-run-after-exit
- (lambda (sel)
- (kill-new sel)
- ;; Return nil to force `helm-mode--keyboard-quit'
- ;; in `helm-comp-read' otherwise the value "Saved to kill-ring: foo"
- ;; is used as exit value for `helm-comp-read'.
- (prog1 nil (message "Saved to kill-ring: %s" sel) (sit-for 1)))
- (helm-get-selection nil (not arg)))))
-(put 'helm-kill-selection-and-quit 'helm-only t)
-
-(defun helm-copy-to-buffer ()
- "Copy selection or marked candidates to `helm-current-buffer'."
- (interactive)
- (with-helm-alive-p
- (with-helm-buffer
- (cl-loop for cand in (helm-marked-candidates)
- do (with-helm-current-buffer
- (insert (format "%s\n" cand)))))))
-(put 'helm-copy-to-buffer 'helm-only t)
-
-\f
-;;; Follow-mode: Automatical execution of persistent-action
-;;
-;;
-(defun helm-follow-mode (&optional arg)
- "Execute persistent action everytime the cursor is moved when enabled.
-The mode is enabled for the current source only, you will have to turn it
-on again when you go to next source if you want it there also.
-This mode can be enabled or disabled interactively at anytime during
-helm session or enabled specifically by source by adding the `follow'
-attribute to this source.
-Even when the attribute `follow' exists in source, it is still possible
-to disable/enable this mode interactively.
-Note that when you disable it interactively and `follow' attribute exists,
-`helm-follow-mode' will be disabled on next helm session even if `follow'
-attribute is specified in source. To avoid this set your `follow' attribute
-in source in `helm-before-initialize-hook'.
-
-e.g:
-
-\(add-hook 'helm-before-initialize-hook
- (lambda () (helm-attrset 'follow 1 helm-source-buffers-list)))
-
-This will enable `helm-follow-mode' automatically in `helm-source-buffers-list'."
- (interactive "p")
- (with-helm-alive-p
- (with-current-buffer helm-buffer
- (let* ((src (helm-get-current-source))
- (name (assoc-default 'name src))
- (sym (cl-loop for s in helm-sources
- for sname = (and (symbolp s)
- (assoc-default
- 'name (symbol-value s)))
- thereis (and sname (string= sname name) s)))
- (fol-attr (assq 'follow src))
- (enabled (or
- ;; If `helm-follow-mode' is called with a negative
- ;; ARG, assume follow is already enabled.
- ;; i.e turn it off now.
- (< arg 0)
- (eq (cdr fol-attr) 1)
- helm-follow-mode)))
- (if src
- (progn
- (if (eq (cdr fol-attr) 'never)
- (message "helm-follow-mode not allowed in this source")
- ;; Make follow attr persistent for this emacs session.
- (helm-attrset 'follow (if enabled -1 1) src)
- (setq helm-follow-mode (not enabled))
- (message "helm-follow-mode is %s"
- (if helm-follow-mode
- "enabled" "disabled"))
- (helm-display-mode-line src t))
- (unless helm-follow-mode-persistent
- (and sym (set sym (remove (assq 'follow src) src)))))
- (message "Not enough candidates for helm-follow-mode"))))))
-(put 'helm-follow-mode 'helm-only t)
-
-(defvar helm-follow-input-idle-delay nil
- "`helm-follow-mode' will execute its persistent action after this delay.
-Note that if the `follow-delay' attr is present in source,
-it will take precedence on this.")
-(defun helm-follow-execute-persistent-action-maybe ()
- "Execute persistent action in mode `helm-follow-mode'.
-This happen after `helm-input-idle-delay' secs."
- (let ((src (helm-get-current-source)))
- (and (not (get-buffer-window helm-action-buffer 'visible))
- (eq (assoc-default 'follow src) 1)
- (sit-for (or (assoc-default 'follow-delay src)
- helm-follow-input-idle-delay
- (and helm-input-idle-delay
- (max helm-input-idle-delay 0.01))))
- (helm-window)
- (helm-get-selection)
- (save-excursion
- (helm-execute-persistent-action)))))
-
-\f
-;;; Auto-resize mode
-;;
-(defun helm--autoresize-hook (&optional max-height min-height)
- (with-helm-window
- (fit-window-to-buffer nil
- (/ (* (frame-height)
- (or max-height helm-autoresize-max-height))
- 100)
- (/ (* (frame-height)
- (or min-height helm-autoresize-min-height))
- 100))))
-
-(define-minor-mode helm-autoresize-mode
- "Auto resize helm window when enabled.
-Helm window is resized according to values of `helm-autoresize-max-height'
-and `helm-autoresize-min-height'.
-Note that when this mode is enabled, helm behave like when
-`helm-always-two-windows' is enabled.
-
-See `fit-window-to-buffer' for more infos."
- :group 'helm
- :global t
- (if helm-autoresize-mode
- (progn (add-hook 'helm-after-update-hook 'helm--autoresize-hook)
- (add-hook 'helm-window-configuration-hook 'helm--autoresize-hook))
- (remove-hook 'helm-after-update-hook 'helm--autoresize-hook)
- (remove-hook 'helm-window-configuration-hook 'helm--autoresize-hook)))
-
-(defun helm-help ()
- "Help of `helm'."
- (interactive)
- (with-helm-alive-p
- (save-selected-window
- (helm-help-internal
- "*Helm Help*"
- (lambda ()
- (helm-aif (assoc-default 'help-message (helm-get-current-source))
- (insert (substitute-command-keys
- (helm-interpret-value it)))
- (insert "* No specific help for this source at this time.\n
-It may appear after first results popup in helm buffer."))
- (insert "\n\n"
- (substitute-command-keys
- (helm-interpret-value helm-help-message))))))))
-(put 'helm-help 'helm-only t)
-
-(defun helm-toggle-truncate-line ()
- "Toggle `truncate-lines' value in `helm-buffer'"
- (interactive)
- (with-helm-alive-p
- (with-helm-buffer
- (setq truncate-lines (not truncate-lines))
- (helm-update (regexp-quote (helm-get-selection nil t))))))
-(put 'helm-toggle-truncate-line 'helm-only t)
-
-(provide 'helm)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm.el ends here
+++ /dev/null
-;;; helm-core-autoloads.el --- automatically extracted autoloads
-;;
-;;; Code:
-(add-to-list 'load-path (or (file-name-directory #$) (car load-path)))
-\f
-;;;### (autoloads nil "helm" "helm.el" (22348 36024 0 0))
-;;; Generated autoloads from helm.el
-
-(autoload 'helm-define-multi-key "helm" "\
-In KEYMAP, define key sequence KEY for function list FUNCTIONS.
-Each function runs sequentially for each KEY press.
-If DELAY is specified, switch back to initial function of FUNCTIONS list
-after DELAY seconds.
-The functions in FUNCTIONS list take no args.
-e.g
- (defun foo ()
- (message \"Run foo\"))
- (defun bar ()
- (message \"Run bar\"))
- (defun baz ()
- (message \"Run baz\"))
-
-\(helm-define-multi-key global-map \"<f5> q\" '(foo bar baz) 2)
-
-Each time \"<f5> q\" is pressed, the next function is executed. Waiting
-more than 2 seconds between key presses switches back to executing the first
-function on the next hit.
-
-\(fn KEYMAP KEY FUNCTIONS &optional DELAY)" nil nil)
-
-(autoload 'helm-multi-key-defun "helm" "\
-Define NAME as a multi-key command running FUNS.
-After DELAY seconds, the FUNS list is reinitialized.
-See `helm-define-multi-key'.
-
-\(fn NAME DOCSTRING FUNS &optional DELAY)" nil t)
-
-(put 'helm-multi-key-defun 'lisp-indent-function '2)
-
-(autoload 'helm-define-key-with-subkeys "helm" "\
-Defines in MAP a KEY and SUBKEY to COMMAND.
-
-This allows typing KEY to call COMMAND the first time and
-type only SUBKEY on subsequent calls.
-
-Arg MAP is the keymap to use, SUBKEY is the initial short key-binding to
-call COMMAND.
-
-Arg OTHER-SUBKEYS is an alist specifying other short key-bindings
-to use once started e.g:
-
- (helm-define-key-with-subkeys global-map
- (kbd \"C-x v n\") ?n 'git-gutter:next-hunk '((?p . git-gutter:previous-hunk)))
-
-
-In this example, `C-x v n' will run `git-gutter:next-hunk'
-subsequent \"n\"'s run this command again
-and subsequent \"p\"'s run `git-gutter:previous-hunk'.
-
-Arg MENU is a string displayed in minibuffer that
-describes SUBKEY and OTHER-SUBKEYS.
-Arg EXIT-FN specifies a function to run on exit.
-
-For any other keys pressed, run their assigned command as defined
-in MAP and then exit the loop running EXIT-FN, if specified.
-
-NOTE: SUBKEY and OTHER-SUBKEYS bindings support char syntax only
-\(e.g ?n), so don't use strings or vectors to define them.
-
-\(fn MAP KEY SUBKEY COMMAND &optional OTHER-SUBKEYS MENU EXIT-FN)" nil nil)
-
-(put 'helm-define-key-with-subkeys 'lisp-indent-function '1)
-
-(autoload 'helm-debug-open-last-log "helm" "\
-Open helm log file or buffer of last helm session.
-
-\(fn)" t nil)
-
-(autoload 'helm "helm" "\
-Main function to execute helm sources.
-
-Keywords supported:
-:sources :input :prompt :resume :preselect
-:buffer :keymap :default :history :allow-nest
-
-Extra LOCAL-VARS keywords are supported, see below.
-
-PLIST is a list like (:key1 val1 :key2 val2 ...) or
-\(&optional sources input prompt resume
- preselect buffer keymap default history).
-
-Basic keywords are the following:
-
-:sources
-
-A list of sources used for this session. It also accepts a
-symbol, interpreted as a variable of a helm source
-i.e (a symbol can be passed instead of a list of sources).
-It also accepts an alist representing a helm source, which is
-detected by (assq 'name ANY-SOURCES).
-NOTE: In this case the source is embedded in the helm command and
-have no symbol name, so it is not reachable from outside.
-It will be referenced in `helm-sources' as a whole alist.
-
-:input
-
-Temporary value of `helm-pattern', ie. initial input of minibuffer.
-
-:prompt
-
-Prompt other than \"pattern: \".
-
-:resume
-
-If t, Resurrect previously instance of `helm'. Skip the initialization.
-If 'noresume, this instance of `helm' cannot be resumed.
-
-:preselect
-
-Initially selected candidate. Specified by exact candidate or a regexp.
-
-:buffer
-
-`helm-buffer' instead of *helm*.
-
-:keymap
-
-`helm-map' for current `helm' session.
-
-:default
-
-A default argument that will be inserted in minibuffer with
-\\<minibuffer-local-map>\\[next-history-element]. When nil or not
-present `thing-at-point' will be used instead. If
-`helm--maybe-use-default-as-input' is non-`nil' display will be
-updated using :default arg as input unless :input is specified,
-which in this case will take precedence over :default. This is a
-string or a list. If list, car of the list becomes initial
-default input. \\<minibuffer-local-map>\\[next-history-element]
-cycles through the list items.
-
-:history
-
-Minibuffer input, by default, is pushed to `minibuffer-history'.
-When an argument HISTORY is provided, input is pushed to
-HISTORY. The HISTORY element should be a valid symbol.
-
-:allow-nest
-
-Allow running this helm command in a running helm session.
-
-Standard arguments are supported. These two are the same:
-
-\(helm :sources sources :input input :prompt prompt :resume resume
- :preselect preselect :buffer buffer :keymap keymap :default default
- :history history)
-
-and
-
-\(helm sources input prompt resume preselect buffer keymap default history)
-
-are the same for now. However, the use of non-keyword args is
-deprecated and should not be used.
-
-Other keywords are interpreted as local variables of this helm
-session. The `helm-' prefix can be omitted. For example,
-
-\(helm :sources 'helm-source-buffers-list
- :buffer \"*helm buffers*\" :candidate-number-limit 10)
-
-starts helm session with `helm-source-buffers' source in
-*helm buffers* buffer and sets variable `helm-candidate-number-limit'
-to 10 as a session local variable.
-
-\(fn &key SOURCES INPUT PROMPT RESUME PRESELECT BUFFER KEYMAP DEFAULT HISTORY ALLOW-NEST OTHER-LOCAL-VARS)" nil nil)
-
-(autoload 'helm-other-buffer "helm" "\
-Simplified `helm' interface with other `helm-buffer'.
-Call `helm' only with ANY-SOURCES and ANY-BUFFER as args.
-
-\(fn ANY-SOURCES ANY-BUFFER)" nil nil)
-
-(autoload 'helm-debug-toggle "helm" "\
-Enable/disable helm debugging from outside of helm session.
-
-\(fn)" t nil)
-
-;;;***
-\f
-;;;### (autoloads nil nil ("helm-core-pkg.el" "helm-lib.el" "helm-multi-match.el"
-;;;;;; "helm-source.el") (22348 36024 558133 0))
-
-;;;***
-\f
-;; Local Variables:
-;; version-control: never
-;; no-byte-compile: t
-;; no-update-autoloads: t
-;; End:
-;;; helm-core-autoloads.el ends here
+++ /dev/null
-(define-package "helm-core" "20160530.52" "Development files for Helm"
- '((emacs "24.3")
- (async "1.9"))
- :url "https://emacs-helm.github.io/helm/")
-;; Local Variables:
-;; no-byte-compile: t
-;; End:
+++ /dev/null
-;;; helm-lib.el --- Helm routines. -*- lexical-binding: t -*-
-
-;; Copyright (C) 2015 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; Author: Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-;; URL: http://github.com/emacs-helm/helm
-
-;; 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/>.
-
-;;; Commentary:
-;; All helm functions that don't require specific helm code should go here.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'dired)
-
-\f
-;;; User vars.
-;;
-(defcustom helm-file-globstar t
- "Same as globstar bash shopt option.
-When non--nil a pattern beginning with two stars will expand recursively.
-Directories expansion is not supported yet."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-yank-text-at-point-function nil
- "The function used to forward point with `helm-yank-text-at-point'.
-With a nil value, fallback to default `forward-word'.
-The function should take one arg, an integer like `forward-word'.
-NOTE: Using `forward-symbol' here is not very useful as it is already
-provided by \\<helm-map>\\[next-history-element]."
- :type 'function
- :group 'helm)
-
-(defcustom helm-scroll-amount nil
- "Scroll amount when scrolling other window in a helm session.
-It is used by `helm-scroll-other-window'
-and `helm-scroll-other-window-down'.
-
-If you prefer scrolling line by line, set this value to 1."
- :group 'helm
- :type 'integer)
-
-(defcustom helm-help-full-frame t
- "Display help window in full frame when non nil.
-
-Even when `nil' probably the same result (full frame)
-can be reach by tweaking `display-buffer-alist' but it is
-much more convenient to use a simple boolean value here."
- :type 'boolean
- :group 'helm-help)
-
-\f
-;;; Internal vars
-;;
-(defvar helm-yank-point nil)
-(defvar helm-pattern ""
- "The input pattern used to update the helm buffer.")
-(defvar helm-buffer "*helm*"
- "Buffer showing completions.")
-(defvar helm-current-buffer nil
- "Current buffer when `helm' is invoked.")
-(defvar helm-suspend-update-flag nil)
-(defvar helm-action-buffer "*helm action*"
- "Buffer showing actions.")
-\f
-;;; Macros helper.
-;;
-(defmacro helm-with-gensyms (symbols &rest body)
- "Bind the SYMBOLS to fresh uninterned symbols and eval BODY."
- (declare (indent 1))
- `(let ,(mapcar (lambda (s)
- ;; Use cl-gensym here instead of make-symbol
- ;; to ensure a symbol that have a live that go
- ;; beyond the live of its macro have different name.
- ;; i.e symbols created with `with-helm-temp-hook'
- ;; should have random names.
- `(,s (cl-gensym (symbol-name ',s))))
- symbols)
- ,@body))
-\f
-;;; Iterators
-;;
-(defun helm-iter-list (seq)
- "Return an iterator object from SEQ."
- (let ((lis seq))
- (lambda ()
- (let ((elm (car lis)))
- (setq lis (cdr lis))
- elm))))
-
-(defun helm-iter-next (iterator)
- "Return next elm of ITERATOR."
- (funcall iterator))
-
-(defun helm-make-actions (&rest args)
- "Build an alist with (NAME . ACTION) elements with each pairs in ARGS.
-Where NAME is a string or a function returning a string or nil and ACTION
-a function.
-If NAME returns nil the pair is skipped.
-
-\(fn NAME ACTION ...)"
- (cl-loop for i on args by #'cddr
- for name = (car i)
- when (functionp name)
- do (setq name (funcall name))
- when name
- collect (cons name (cadr i))))
-\f
-;;; Anaphoric macros.
-;;
-(defmacro helm-aif (test-form then-form &rest else-forms)
- "Anaphoric version of `if'.
-Like `if' but set the result of TEST-FORM in a temporary variable called `it'.
-THEN-FORM and ELSE-FORMS are then excuted just like in `if'."
- (declare (indent 2) (debug t))
- `(let ((it ,test-form))
- (if it ,then-form ,@else-forms)))
-
-(defmacro helm-awhile (sexp &rest body)
- "Anaphoric version of `while'.
-Same usage as `while' except that SEXP is bound to
-a temporary variable called `it' at each turn.
-An implicit nil block is bound to the loop so usage
-of `cl-return' is possible to exit the loop."
- (declare (indent 1) (debug t))
- (helm-with-gensyms (flag)
- `(let ((,flag t))
- (cl-block nil
- (while ,flag
- (helm-aif ,sexp
- (progn ,@body)
- (setq ,flag nil)))))))
-
-(defmacro helm-acond (&rest clauses)
- "Anaphoric version of `cond'."
- (unless (null clauses)
- (helm-with-gensyms (sym)
- (let ((clause1 (car clauses)))
- `(let ((,sym ,(car clause1)))
- (helm-aif ,sym
- ,@(cdr clause1)
- (helm-acond ,@(cdr clauses))))))))
-
-(defun helm-current-line-contents ()
- "Current line string without properties."
- (buffer-substring-no-properties (point-at-bol) (point-at-eol)))
-\f
-;;; Fuzzy matching routines
-;;
-(defsubst helm--mapconcat-pattern (pattern)
- "Transform string PATTERN in regexp for further fuzzy matching.
-e.g helm.el$
- => \"[^h]*h[^e]*e[^l]*l[^m]*m[^.]*[.][^e]*e[^l]*l$\"
- ^helm.el$
- => \"helm[.]el$\"."
- (let ((ls (split-string-and-unquote pattern "")))
- (if (string= "^" (car ls))
- ;; Exact match.
- (mapconcat (lambda (c)
- (if (and (string= c "$")
- (string-match "$\\'" pattern))
- c (regexp-quote c)))
- (cdr ls) "")
- ;; Fuzzy match.
- (mapconcat (lambda (c)
- (if (and (string= c "$")
- (string-match "$\\'" pattern))
- c (format "[^%s]*%s" c (regexp-quote c))))
- ls ""))))
-
-(defsubst helm--collect-pairs-in-string (string)
- (cl-loop for str on (split-string string "" t) by 'cdr
- when (cdr str)
- collect (list (car str) (cadr str))))
-\f
-;;; Help routines.
-;;
-(defun helm-help-internal (bufname insert-content-fn)
- "Show long message during `helm' session in BUFNAME.
-INSERT-CONTENT-FN is the function that insert
-text to be displayed in BUFNAME."
- (let ((winconf (current-frame-configuration)))
- (unwind-protect
- (progn
- (setq helm-suspend-update-flag t)
- (set-buffer (get-buffer-create bufname))
- (switch-to-buffer bufname)
- (when helm-help-full-frame (delete-other-windows))
- (delete-region (point-min) (point-max))
- (org-mode)
- (save-excursion
- (funcall insert-content-fn))
- (buffer-disable-undo)
- (helm-help-event-loop))
- (setq helm-suspend-update-flag nil)
- (set-frame-configuration winconf))))
-
-(defun helm-help-scroll-up (amount)
- (condition-case _err
- (scroll-up-command amount)
- (beginning-of-buffer nil)
- (end-of-buffer nil)))
-
-(defun helm-help-scroll-down (amount)
- (condition-case _err
- (scroll-down-command amount)
- (beginning-of-buffer nil)
- (end-of-buffer nil)))
-
-(defun helm-help-next-line ()
- (condition-case _err
- (call-interactively #'next-line)
- (beginning-of-buffer nil)
- (end-of-buffer nil)))
-
-(defun helm-help-previous-line ()
- (condition-case _err
- (call-interactively #'previous-line)
- (beginning-of-buffer nil)
- (end-of-buffer nil)))
-
-(defun helm-help-toggle-mark ()
- (if (region-active-p)
- (deactivate-mark)
- (push-mark nil nil t)))
-
-;; For movement of cursor in help buffer we need to call interactively
-;; commands for impaired people using a synthetizer (#1347).
-(defun helm-help-event-loop ()
- (let ((prompt (propertize
- "[SPC,C-v,down,next:NextPage b,M-v,up,prior:PrevPage C-s/r:Isearch q:Quit]"
- 'face 'helm-helper))
- scroll-error-top-bottom)
- (helm-awhile (read-key prompt)
- (cl-case it
- ((?\C-v ? down next) (helm-help-scroll-up helm-scroll-amount))
- ((?\M-v ?b up prior) (helm-help-scroll-down helm-scroll-amount))
- (?\C-s (isearch-forward))
- (?\C-r (isearch-backward))
- (?\C-a (call-interactively #'move-beginning-of-line))
- (?\C-e (call-interactively #'move-end-of-line))
- (?\C-f (call-interactively #'forward-char))
- (?\C-b (call-interactively #'backward-char))
- (?\C-n (helm-help-next-line))
- (?\C-p (helm-help-previous-line))
- (?\M-a (call-interactively #'backward-sentence))
- (?\M-e (call-interactively #'forward-sentence))
- (?\M-f (call-interactively #'forward-word))
- (?\M-b (call-interactively #'backward-word))
- (?\C- (helm-help-toggle-mark))
- (?\M-w (copy-region-as-kill
- (region-beginning) (region-end))
- (deactivate-mark))
- (?q (cl-return))
- (t (ignore))))))
-
-\f
-;;; List processing
-;;
-(defun helm-flatten-list (seq &optional omit-nulls)
- "Return a list of all single elements of sublists in SEQ."
- (let (result)
- (cl-labels ((flatten (seq)
- (cl-loop
- for elm in seq
- if (and (or elm
- (null omit-nulls))
- (or (atom elm)
- (functionp elm)
- (and (consp elm)
- (cdr elm)
- (atom (cdr elm)))))
- do (push elm result)
- else do (flatten elm))))
- (flatten seq))
- (nreverse result)))
-
-(defun helm-mklist (obj)
- "If OBJ is a list \(but not lambda\), return itself.
-Otherwise make a list with one element."
- (if (and (listp obj) (not (functionp obj)))
- obj
- (list obj)))
-
-(cl-defmacro helm-position (item seq &key (test 'eq) all)
- "A simple and faster replacement of CL `position'.
-Return position of first occurence of ITEM found in SEQ.
-Argument SEQ can be a string, in this case ITEM have to be a char.
-Argument ALL, if non--nil specify to return a list of positions of
-all ITEM found in SEQ."
- (let ((key (if (stringp seq) 'across 'in)))
- `(cl-loop for c ,key ,seq
- for index from 0
- when (funcall ,test c ,item)
- if ,all collect index into ls
- else return index
- finally return ls)))
-
-(cl-defun helm-fast-remove-dups (seq &key (test 'eq))
- "Remove duplicates elements in list SEQ.
-This is same as `remove-duplicates' but with memoisation.
-It is much faster, especially in large lists.
-A test function can be provided with TEST argument key.
-Default is `eq'."
- (cl-loop with cont = (make-hash-table :test test)
- for elm in seq
- unless (gethash elm cont)
- collect (puthash elm elm cont)))
-
-(defun helm-skip-entries (seq black-regexp-list &optional white-regexp-list)
- "Remove entries which matches one of REGEXP-LIST from SEQ."
- (cl-loop for i in seq
- unless (and (cl-loop for re in black-regexp-list
- thereis (and (stringp i)
- (string-match-p re i)))
- (null
- (cl-loop for re in white-regexp-list
- thereis (and (stringp i)
- (string-match-p re i)))))
- collect i))
-
-(defun helm-shadow-entries (seq regexp-list)
- "Put shadow property on entries in SEQ matching a regexp in REGEXP-LIST."
- (let ((face 'italic))
- (cl-loop for i in seq
- if (cl-loop for regexp in regexp-list
- thereis (and (stringp i)
- (string-match regexp i)))
- collect (propertize i 'face face)
- else collect i)))
-
-(defun helm-remove-if-not-match (regexp seq)
- "Remove all elements of SEQ that don't match REGEXP."
- (cl-loop for s in seq
- for str = (cond ((symbolp s)
- (symbol-name s))
- ((consp s)
- (car s))
- (t s))
- when (string-match-p regexp str)
- collect s))
-
-(defun helm-remove-if-match (regexp seq)
- "Remove all elements of SEQ that match REGEXP."
- (cl-loop for s in seq
- for str = (cond ((symbolp s)
- (symbol-name s))
- ((consp s)
- (car s))
- (t s))
- unless (string-match-p regexp str)
- collect s))
-
-(defun helm-transform-mapcar (function args)
- "`mapcar' for candidate-transformer.
-
-ARGS is (cand1 cand2 ...) or ((disp1 . real1) (disp2 . real2) ...)
-
-\(helm-transform-mapcar 'upcase '(\"foo\" \"bar\"))
-=> (\"FOO\" \"BAR\")
-\(helm-transform-mapcar 'upcase '((\"1st\" . \"foo\") (\"2nd\" . \"bar\")))
-=> ((\"1st\" . \"FOO\") (\"2nd\" . \"BAR\"))
-"
- (cl-loop for arg in args
- if (consp arg)
- collect (cons (car arg) (funcall function (cdr arg)))
- else
- collect (funcall function arg)))
-\f
-;;; Strings processing.
-;;
-(defun helm-stringify (elm)
- "Return the representation of ELM as a string.
-ELM can be a string, a number or a symbol."
- (cl-typecase elm
- (string elm)
- (number (number-to-string elm))
- (symbol (symbol-name elm))))
-
-(defun helm-substring (str width)
- "Return the substring of string STR from 0 to WIDTH.
-Handle multibyte characters by moving by columns."
- (with-temp-buffer
- (save-excursion
- (insert str))
- (move-to-column width)
- (buffer-substring (point-at-bol) (point))))
-
-(defun helm-substring-by-width (str width &optional endstr)
- "Truncate string STR to end at column WIDTH.
-Similar to `truncate-string-to-width'.
-Add ENDSTR at end of truncated STR.
-Add spaces at end if needed to reach WIDTH when STR is shorter than WIDTH."
- (cl-loop for ini-str = str
- then (substring ini-str 0 (1- (length ini-str)))
- for sw = (string-width ini-str)
- when (<= sw width) return
- (concat ini-str endstr (make-string (- width sw) ? ))))
-
-(defun helm-string-multibyte-p (str)
- "Check if string STR contains multibyte characters."
- (cl-loop for c across str
- thereis (> (char-width c) 1)))
-
-(defun helm-get-pid-from-process-name (process-name)
- "Get pid from running process PROCESS-NAME."
- (cl-loop with process-list = (list-system-processes)
- for pid in process-list
- for process = (assoc-default 'comm (process-attributes pid))
- when (and process (string-match process-name process))
- return pid))
-
-(defun helm-ff-find-printers ()
- "Return a list of available printers on Unix systems."
- (when (executable-find "lpstat")
- (let ((printer-list (with-temp-buffer
- (call-process "lpstat" nil t nil "-a")
- (split-string (buffer-string) "\n"))))
- (cl-loop for p in printer-list
- for printer = (car (split-string p))
- when printer
- collect printer))))
-
-(defun helm-region-active-p ()
- (and transient-mark-mode mark-active (/= (mark) (point))))
-
-(defun helm-quote-whitespace (candidate)
- "Quote whitespace, if some, in string CANDIDATE."
- (replace-regexp-in-string " " "\\\\ " candidate))
-
-\f
-;;; Symbols routines
-;;
-(defun helm-symbolify (str-or-sym)
- "Get symbol of STR-OR-SYM."
- (if (symbolp str-or-sym)
- str-or-sym
- (intern str-or-sym)))
-
-(defun helm-symbol-name (obj)
- (if (or (and (consp obj) (functionp obj))
- (byte-code-function-p obj))
- "Anonymous"
- (symbol-name obj)))
-
-(defun helm-describe-function (func)
- "FUNC is symbol or string."
- (describe-function (helm-symbolify func))
- (message nil))
-
-(defun helm-describe-variable (var)
- "VAR is symbol or string."
- (describe-variable (helm-symbolify var))
- (message nil))
-
-(defun helm-describe-face (face)
- "VAR is symbol or string."
- (describe-face (helm-symbolify face))
- (message nil))
-
-(defun helm-find-function (func)
- "FUNC is symbol or string."
- (find-function (helm-symbolify func)))
-
-(defun helm-find-variable (var)
- "VAR is symbol or string."
- (find-variable (helm-symbolify var)))
-
-(defun helm-find-face-definition (face)
- "FACE is symbol or string."
- (find-face-definition (helm-symbolify face)))
-
-(defun helm-kill-new (candidate &optional replace)
- "CANDIDATE is symbol or string.
-See `kill-new' for argument REPLACE."
- (kill-new (helm-stringify candidate) replace))
-
-\f
-;;; Modes
-;;
-(defun helm-same-major-mode-p (start-buffer alist)
- "Decide if current-buffer is related to START-BUFFER.
-Argument ALIST is an alist of associated major modes."
- ;; START-BUFFER is the current-buffer where we start searching.
- ;; Determine the major-mode of START-BUFFER as `cur-maj-mode'.
- ;; Each time the loop go in another buffer we try from this buffer
- ;; to determine if its `major-mode' is:
- ;; - same as the `cur-maj-mode'
- ;; - derived from `cur-maj-mode' and from
- ;; START-BUFFER if its mode is derived from the one in START-BUFFER.
- ;; - have an assoc entry (major-mode . cur-maj-mode)
- ;; - have an rassoc entry (cur-maj-mode . major-mode)
- ;; - check if one of these entries inherit from another one in
- ;; `alist'.
- (let* ((cur-maj-mode (with-current-buffer start-buffer major-mode))
- (maj-mode major-mode)
- (c-assoc-mode (assq cur-maj-mode alist))
- (c-rassoc-mode (rassq cur-maj-mode alist))
- (o-assoc-mode (assq major-mode alist))
- (o-rassoc-mode (rassq major-mode alist))
- (cdr-c-assoc-mode (cdr c-assoc-mode))
- (cdr-o-assoc-mode (cdr o-assoc-mode)))
- (or (eq major-mode cur-maj-mode)
- (derived-mode-p cur-maj-mode)
- (with-current-buffer start-buffer
- (derived-mode-p maj-mode))
- (or (eq cdr-c-assoc-mode major-mode)
- (eq (car c-rassoc-mode) major-mode)
- (eq (cdr (assq cdr-c-assoc-mode alist))
- major-mode)
- (eq (car (rassq cdr-c-assoc-mode alist))
- major-mode))
- (or (eq cdr-o-assoc-mode cur-maj-mode)
- (eq (car o-rassoc-mode) cur-maj-mode)
- (eq (cdr (assq cdr-o-assoc-mode alist))
- cur-maj-mode)
- (eq (car (rassq cdr-o-assoc-mode alist))
- cur-maj-mode)))))
-\f
-;;; Files routines
-;;
-(defun helm-file-name-sans-extension (filename)
- "Same as `file-name-sans-extension' but remove all extensions."
- (helm-aif (file-name-sans-extension filename)
- ;; Start searching at index 1 for files beginning with a dot (#1335).
- (if (string-match "\\." (helm-basename it) 1)
- (helm-file-name-sans-extension it)
- it)))
-
-(defun helm-basename (fname &optional ext)
- "Print FNAME with any leading directory components removed.
-If specified, also remove filename extension EXT.
-Arg EXT can be specified as a string with or without dot,
-in this case it should match file-name-extension.
-It can also be non-nil (`t') in this case no checking
-of file-name-extension is done and the extension is removed
-unconditionally."
- (let ((non-essential t))
- (if (and ext (or (string= (file-name-extension fname) ext)
- (string= (file-name-extension fname t) ext)
- (eq ext t))
- (not (file-directory-p fname)))
- (file-name-sans-extension (file-name-nondirectory fname))
- (file-name-nondirectory (directory-file-name fname)))))
-
-(defun helm-basedir (fname)
- "Return the base directory of filename ending by a slash."
- (helm-aif (and fname
- (or (and (string= fname "~") "~")
- (file-name-directory fname)))
- (file-name-as-directory it)))
-
-(defun helm-current-directory ()
- "Return current-directory name at point.
-Useful in dired buffers when there is inserted subdirs."
- (expand-file-name
- (if (eq major-mode 'dired-mode)
- (dired-current-directory)
- default-directory)))
-
-(defun helm-w32-prepare-filename (file)
- "Convert filename FILE to something usable by external w32 executables."
- (replace-regexp-in-string ; For UNC paths
- "/" "\\"
- (replace-regexp-in-string ; Strip cygdrive paths
- "/cygdrive/\\(.\\)" "\\1:"
- file nil nil) nil t))
-
-(defun helm-w32-shell-execute-open-file (file)
- (with-no-warnings
- (w32-shell-execute "open" (helm-w32-prepare-filename file))))
-
-;; Same as `vc-directory-exclusion-list'.
-(defvar helm-walk-ignore-directories
- '("SCCS" "RCS" "CVS" "MCVS" ".svn" ".git" ".hg" ".bzr"
- "_MTN" "_darcs" "{arch}" ".gvfs"))
-
-(cl-defun helm-walk-directory (directory &key (path 'basename)
- directories
- match skip-subdirs)
- "Walk through DIRECTORY tree.
-
-Argument PATH can be one of basename, relative, full, or a function
-called on file name, default to basename.
-
-Argument DIRECTORIES when non--nil (default) return also directories names,
-otherwise skip directories names, with a value of 'only returns
-only subdirectories, i.e files are skipped.
-
-Argument MATCH is a regexp matching files or directories.
-
-Argument SKIP-SUBDIRS when `t' will skip `helm-walk-ignore-directories'
-otherwise if it is given as a list of directories, this list will be used
-instead of `helm-walk-ignore-directories'."
- (let ((fn (cl-case path
- (basename 'file-name-nondirectory)
- (relative 'file-relative-name)
- (full 'identity)
- (t path)))) ; A function.
- (setq skip-subdirs (if (listp skip-subdirs)
- skip-subdirs
- helm-walk-ignore-directories))
- (cl-labels ((ls-rec (dir)
- (unless (file-symlink-p dir)
- (cl-loop for f in (sort (file-name-all-completions "" dir)
- 'string-lessp)
- unless (member f '("./" "../"))
- ;; A directory.
- ;; Use `helm--dir-file-name' to remove the final slash.
- ;; Needed to avoid infloop on directory symlinks.
- if (and (helm--dir-name-p f)
- (helm--dir-file-name f dir))
- nconc
- (unless (member (helm-basename it) skip-subdirs)
- (if directories
- (nconc (and (or (null match)
- (string-match match f))
- (list (concat (funcall fn it) "/")))
- (ls-rec it))
- (ls-rec it)))
- ;; A regular file.
- else nconc
- (when (and (null (eq directories 'only))
- (or (null match) (string-match match f)))
- (list (funcall fn (expand-file-name f dir))))))))
- (ls-rec directory))))
-
-(defsubst helm--dir-file-name (file dir)
- (expand-file-name
- (substring file 0 (1- (length file))) dir))
-
-(defsubst helm--dir-name-p (str)
- (char-equal (aref str (1- (length str))) ?/))
-
-(defun helm-file-expand-wildcards (pattern &optional full)
- "Same as `file-expand-wildcards' but allow recursion.
-Recursion happen when PATTERN starts with two stars.
-Directories expansion is not supported."
- (let ((bn (helm-basename pattern))
- (case-fold-search nil))
- (if (and helm-file-globstar
- (string-match "\\`\\*\\{2\\}\\(.*\\)" bn))
- (helm-walk-directory (helm-basedir pattern)
- :path (cl-case full
- (full 'full)
- (relative 'relative)
- ((basename nil) 'basename)
- (t 'full))
- :directories nil
- :match (wildcard-to-regexp bn)
- :skip-subdirs t)
- (file-expand-wildcards pattern full))))
-\f
-;;; helm internals
-;;
-(defun helm-set-pattern (pattern &optional noupdate)
- "Set minibuffer contents to PATTERN.
-if optional NOUPDATE is non-nil, helm buffer is not changed."
- (with-selected-window (or (active-minibuffer-window) (minibuffer-window))
- (delete-minibuffer-contents)
- (insert pattern))
- (when noupdate
- (setq helm-pattern pattern)))
-
-(defun helm-minibuffer-completion-contents ()
- "Return the user input in a minibuffer before point as a string.
-That is what completion commands operate on."
- (buffer-substring (field-beginning) (point)))
-
-(defmacro with-helm-buffer (&rest body)
- "Eval BODY inside `helm-buffer'."
- (declare (indent 0) (debug t))
- `(with-current-buffer (helm-buffer-get)
- ,@body))
-
-(defmacro with-helm-current-buffer (&rest body)
- "Eval BODY inside `helm-current-buffer'."
- (declare (indent 0) (debug t))
- `(with-current-buffer (or (and (buffer-live-p helm-current-buffer)
- helm-current-buffer)
- (setq helm-current-buffer
- (current-buffer)))
- ,@body))
-
-(defun helm-buffer-get ()
- "Return `helm-action-buffer' if shown otherwise `helm-buffer'."
- (if (helm-action-window)
- helm-action-buffer
- helm-buffer))
-
-(defun helm-window ()
- "Window of `helm-buffer'."
- (get-buffer-window (helm-buffer-get) 0))
-
-(defun helm-action-window ()
- "Window of `helm-action-buffer'."
- (get-buffer-window helm-action-buffer 'visible))
-
-(defmacro with-helm-window (&rest body)
- "Be sure BODY is excuted in the helm window."
- (declare (indent 0) (debug t))
- `(with-selected-window (helm-window)
- ,@body))
-
-\f
-;; Yank text at point.
-;;
-;;
-(defun helm-yank-text-at-point ()
- "Yank text at point in `helm-current-buffer' into minibuffer."
- (interactive)
- (with-helm-current-buffer
- (let ((fwd-fn (or helm-yank-text-at-point-function #'forward-word)))
- ;; Start to initial point if C-w have never been hit.
- (unless helm-yank-point (setq helm-yank-point (point)))
- (save-excursion
- (goto-char helm-yank-point)
- (funcall fwd-fn 1)
- (helm-set-pattern
- (concat
- helm-pattern (replace-regexp-in-string
- "\\`\n" ""
- (buffer-substring-no-properties
- helm-yank-point (point)))))
- (setq helm-yank-point (point))))))
-
-(defun helm-reset-yank-point ()
- (setq helm-yank-point nil))
-
-(add-hook 'helm-cleanup-hook 'helm-reset-yank-point)
-(add-hook 'helm-after-initialize-hook 'helm-reset-yank-point)
-
-;;; Ansi
-;;
-;;
-(defvar helm--ansi-color-regexp
- "\033\\[\\(K\\|[0-9;]*m\\)")
-(defvar helm--ansi-color-drop-regexp
- "\033\\[\\([ABCDsuK]\\|[12][JK]\\|=[0-9]+[hI]\\|[0-9;]*[Hf]\\)")
-(defun helm--ansi-color-apply (string)
- "A version of `ansi-color-apply' immune to upstream changes.
-
-Similar to the emacs-24.5 version without support to `ansi-color-context'
-which is buggy in emacs.
-
-Modify also `ansi-color-regexp' by using own variable `helm--ansi-color-regexp'
-that match whole STRING.
-
-This is needed to provide compatibility for both emacs-25 and emacs-24.5
-as emacs-25 version of `ansi-color-apply' is partially broken."
- (let ((start 0)
- codes end escape-sequence
- result colorized-substring)
- ;; Find the next escape sequence.
- (while (setq end (string-match helm--ansi-color-regexp string start))
- (setq escape-sequence (match-string 1 string))
- ;; Colorize the old block from start to end using old face.
- (when codes
- (put-text-property
- start end 'font-lock-face (ansi-color--find-face codes) string))
- (setq colorized-substring (substring string start end)
- start (match-end 0))
- ;; Eliminate unrecognized ANSI sequences.
- (while (string-match helm--ansi-color-drop-regexp colorized-substring)
- (setq colorized-substring
- (replace-match "" nil nil colorized-substring)))
- (push colorized-substring result)
- ;; Create new face, by applying escape sequence parameters.
- (setq codes (ansi-color-apply-sequence escape-sequence codes)))
- ;; If the rest of the string should have a face, put it there.
- (when codes
- (put-text-property
- start (length string)
- 'font-lock-face (ansi-color--find-face codes) string))
- ;; Save the remainder of the string to the result.
- (if (string-match "\033" string start)
- (push (substring string start (match-beginning 0)) result)
- (push (substring string start) result))
- (apply 'concat (nreverse result))))
-
-(provide 'helm-lib)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-lib ends here
+++ /dev/null
-;;; helm-multi-match.el --- Multiple regexp matching methods for helm -*- lexical-binding: t -*-
-
-;; Original Author: rubikitch
-
-;; Copyright (C) 2008 ~ 2011 rubikitch
-;; Copyright (C) 2011 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; Author: Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-;; URL: http://github.com/emacs-helm/helm
-
-;; 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/>.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'helm-lib)
-
-\f
-(defgroup helm-multi-match nil
- "Helm multi match."
- :group 'helm)
-
-(defcustom helm-mm-matching-method 'multi3
- "Matching method for helm match plugin.
-You can set here different methods to match candidates in helm.
-Here are the possible value of this symbol and their meaning:
-- multi1: Respect order, prefix of pattern must match.
-- multi2: Same but with partial match.
-- multi3: The best, multiple regexp match, allow negation.
-- multi3p: Same but prefix must match.
-
-Default is multi3, you should keep this for a better experience.
-
-Note that multi1 and multi3p are incompatible with fuzzy matching
-in file completion and by the way fuzzy matching will be disabled there
-when these options are used."
- :type '(radio :tag "Matching methods for helm"
- (const :tag "Multiple regexp 1 ordered with prefix match" multi1)
- (const :tag "Multiple regexp 2 ordered with partial match" multi2)
- (const :tag "Multiple regexp 3 matching no order, partial, best." multi3)
- (const :tag "Multiple regexp 3p matching with prefix match" multi3p))
- :group 'helm-multi-match)
-
-\f
-;; Internal
-(defconst helm-mm-default-match-functions
- '(helm-mm-exact-match helm-mm-match))
-(defconst helm-mm-default-search-functions
- '(helm-mm-exact-search helm-mm-search))
-
-\f
-;;; Build regexps
-;;
-;;
-(defvar helm-mm-space-regexp "[\\ ] "
- "Regexp to represent space itself in multiple regexp match.")
-
-(defun helm-mm-split-pattern (pattern)
- "Split PATTERN if it contain spaces and return resulting list.
-If spaces in PATTERN are escaped, don't split at this place.
-i.e \"foo bar\"=> (\"foo\" \"bar\")
-but \"foo\ bar\"=> (\"foobar\")."
- (if (string= pattern "")
- '("")
- (cl-loop for s in (split-string
- (replace-regexp-in-string helm-mm-space-regexp
- "\000\000" pattern)
- " " t)
- collect (replace-regexp-in-string "\000\000" " " s))))
-
-(defun helm-mm-1-make-regexp (pattern)
- "Replace spaces in PATTERN with \"\.*\"."
- (mapconcat 'identity (helm-mm-split-pattern pattern) ".*"))
-
-\f
-;;; Exact match.
-;;
-;;
-;; Internal.
-(defvar helm-mm-exact-pattern-str nil)
-(defvar helm-mm-exact-pattern-real nil)
-
-(defun helm-mm-exact-get-pattern (pattern)
- (unless (equal pattern helm-mm-exact-pattern-str)
- (setq helm-mm-exact-pattern-str pattern
- helm-mm-exact-pattern-real (concat "\n" pattern "\n")))
- helm-mm-exact-pattern-real)
-
-
-(cl-defun helm-mm-exact-match (str &optional (pattern helm-pattern))
- (if case-fold-search
- (progn
- (setq str (downcase str)
- pattern (downcase pattern))
- (string= str pattern))
- (string= str pattern)))
-
-(defun helm-mm-exact-search (pattern &rest _ignore)
- (and (search-forward (helm-mm-exact-get-pattern pattern) nil t)
- (forward-line -1)))
-
-\f
-;;; Prefix match
-;;
-;;
-;; Internal
-(defvar helm-mm-prefix-pattern-str nil)
-(defvar helm-mm-prefix-pattern-real nil)
-
-(defun helm-mm-prefix-get-pattern (pattern)
- (unless (equal pattern helm-mm-prefix-pattern-str)
- (setq helm-mm-prefix-pattern-str pattern
- helm-mm-prefix-pattern-real (concat "\n" pattern)))
- helm-mm-prefix-pattern-real)
-
-(defun helm-mm-prefix-match (str &optional pattern)
- ;; In filename completion basename and basedir may be
- ;; quoted, unquote them for string comparison (Issue #1283).
- (setq pattern (replace-regexp-in-string
- "\\\\" "" (or pattern helm-pattern)))
- (let ((len (length pattern)))
- (and (<= len (length str))
- (string= (substring str 0 len) pattern ))))
-
-(defun helm-mm-prefix-search (pattern &rest _ignore)
- (search-forward (helm-mm-prefix-get-pattern pattern) nil t))
-
-\f
-;;; Multiple regexp patterns 1 (order is preserved / prefix).
-;;
-;;
-;; Internal
-(defvar helm-mm-1-pattern-str nil)
-(defvar helm-mm-1-pattern-real nil)
-
-(defun helm-mm-1-get-pattern (pattern)
- (unless (equal pattern helm-mm-1-pattern-str)
- (setq helm-mm-1-pattern-str pattern
- helm-mm-1-pattern-real
- (concat "^" (helm-mm-1-make-regexp pattern))))
- helm-mm-1-pattern-real)
-
-(cl-defun helm-mm-1-match (str &optional (pattern helm-pattern))
- (string-match (helm-mm-1-get-pattern pattern) str))
-
-(defun helm-mm-1-search (pattern &rest _ignore)
- (re-search-forward (helm-mm-1-get-pattern pattern) nil t))
-
-\f
-;;; Multiple regexp patterns 2 (order is preserved / partial).
-;;
-;;
-;; Internal
-(defvar helm-mm-2-pattern-str nil)
-(defvar helm-mm-2-pattern-real nil)
-
-(defun helm-mm-2-get-pattern (pattern)
- (unless (equal pattern helm-mm-2-pattern-str)
- (setq helm-mm-2-pattern-str pattern
- helm-mm-2-pattern-real
- (concat "^.*" (helm-mm-1-make-regexp pattern))))
- helm-mm-2-pattern-real)
-
-(cl-defun helm-mm-2-match (str &optional (pattern helm-pattern))
- (string-match (helm-mm-2-get-pattern pattern) str))
-
-(defun helm-mm-2-search (pattern &rest _ignore)
- (re-search-forward (helm-mm-2-get-pattern pattern) nil t))
-
-\f
-;;; Multiple regexp patterns 3 (permutation).
-;;
-;;
-;; Internal
-(defvar helm-mm-3-pattern-str nil)
-(defvar helm-mm-3-pattern-list nil)
-
-(defun helm-mm-3-get-patterns (pattern)
- "Return `helm-mm-3-pattern-list', a list of predicate/regexp cons cells.
-e.g ((identity . \"foo\") (identity . \"bar\")).
-This is done only if `helm-mm-3-pattern-str' is same as PATTERN."
- (unless (equal pattern helm-mm-3-pattern-str)
- (setq helm-mm-3-pattern-str pattern
- helm-mm-3-pattern-list
- (helm-mm-3-get-patterns-internal pattern)))
- helm-mm-3-pattern-list)
-
-(defun helm-mm-3-get-patterns-internal (pattern)
- "Return a list of predicate/regexp cons cells.
-e.g ((identity . \"foo\") (identity . \"bar\"))."
- (unless (string= pattern "")
- (cl-loop for pat in (helm-mm-split-pattern pattern)
- collect (if (string= "!" (substring pat 0 1))
- (cons 'not (substring pat 1))
- (cons 'identity pat)))))
-
-(cl-defun helm-mm-3-match (str &optional (pattern helm-pattern))
- "Check if PATTERN match STR.
-When PATTERN contain a space, it is splitted and matching is done
-with the several resulting regexps against STR.
-e.g \"bar foo\" will match \"foobar\" and \"barfoo\".
-Argument PATTERN, a string, is transformed in a list of
-cons cell with `helm-mm-3-get-patterns' if it contain a space.
-e.g \"foo bar\"=>((identity . \"foo\") (identity . \"bar\")).
-Then each predicate of cons cell(s) is called with regexp of same
-cons cell against STR (a candidate).
-i.e (identity (string-match \"foo\" \"foo bar\")) => t."
- (let ((pat (helm-mm-3-get-patterns pattern)))
- (cl-loop for (predicate . regexp) in pat
- always (funcall predicate
- (condition-case _err
- ;; FIXME: Probably do nothing when
- ;; using fuzzy leaving the job
- ;; to the fuzzy fn.
- (string-match regexp str)
- (invalid-regexp nil))))))
-
-(defun helm-mm-3-search-base (pattern searchfn1 searchfn2)
- "Try to find PATTERN in `helm-buffer' with SEARCHFN1 and SEARCHFN2.
-This is the search function for `candidates-in-buffer' enabled sources.
-Use the same method as `helm-mm-3-match' except it search in buffer
-instead of matching on a string.
-i.e (identity (re-search-forward \"foo\" (point-at-eol) t)) => t."
- (cl-loop with pat = (if (stringp pattern)
- (helm-mm-3-get-patterns pattern)
- pattern)
- when (eq (caar pat) 'not) return
- ;; Pass the job to `helm-search-match-part'.
- (prog1 (list (point-at-bol) (point-at-eol))
- (forward-line 1))
- while (condition-case _err
- (funcall searchfn1 (or (cdar pat) "") nil t)
- (invalid-regexp nil))
- for bol = (point-at-bol)
- for eol = (point-at-eol)
- if (cl-loop for (pred . str) in (cdr pat) always
- (progn (goto-char bol)
- (funcall pred (condition-case _err
- (funcall searchfn2 str eol t)
- (invalid-regexp nil)))))
- do (goto-char eol) and return t
- else do (goto-char eol)
- finally return nil))
-
-(defun helm-mm-3-search (pattern &rest _ignore)
- (when (stringp pattern)
- (setq pattern (helm-mm-3-get-patterns pattern)))
- (helm-mm-3-search-base
- pattern 're-search-forward 're-search-forward))
-\f
-;;; mp-3 with migemo
-;;
-;;
-(defvar helm-mm--previous-migemo-info nil
- "[Internal] Cache previous migemo query.")
-(make-local-variable 'helm-mm--previous-migemo-info)
-
-(declare-function migemo-get-pattern "ext:migemo.el")
-(declare-function migemo-search-pattern-get "ext:migemo.el")
-
-(define-minor-mode helm-migemo-mode
- "Enable migemo in helm.
-It will be available in the sources handling it,
-i.e the sources which have the slot :migemo with non--nil value."
- :lighter " Hmio"
- :group 'helm
- :global t
- (cl-assert (featurep 'migemo)
- nil "No feature called migemo found, install migemo.el."))
-
-(defun helm-mm-migemo-get-pattern (pattern)
- (let ((regex (migemo-get-pattern pattern)))
- (if (ignore-errors (string-match regex "") t)
- (concat regex "\\|" pattern) pattern)))
-
-(defun helm-mm-migemo-search-pattern-get (pattern)
- (let ((regex (migemo-search-pattern-get pattern)))
- (if (ignore-errors (string-match regex "") t)
- (concat regex "\\|" pattern) pattern)))
-
-(defun helm-mm-migemo-string-match (pattern str)
- "Migemo version of `string-match'."
- (unless (assoc pattern helm-mm--previous-migemo-info)
- (with-helm-buffer
- (setq helm-mm--previous-migemo-info
- (push (cons pattern (helm-mm-migemo-get-pattern pattern))
- helm-mm--previous-migemo-info))))
- (string-match (assoc-default pattern helm-mm--previous-migemo-info) str))
-
-(cl-defun helm-mm-3-migemo-match (str &optional (pattern helm-pattern))
- (and helm-migemo-mode
- (cl-loop for (pred . re) in (helm-mm-3-get-patterns pattern)
- always (funcall pred (helm-mm-migemo-string-match re str)))))
-
-(defun helm-mm-migemo-forward (word &optional bound noerror count)
- (with-helm-buffer
- (unless (assoc word helm-mm--previous-migemo-info)
- (setq helm-mm--previous-migemo-info
- (push (cons word (if (delq 'ascii (find-charset-string word))
- word
- (helm-mm-migemo-search-pattern-get word)))
- helm-mm--previous-migemo-info))))
- (re-search-forward
- (assoc-default word helm-mm--previous-migemo-info) bound noerror count))
-
-(defun helm-mm-3-migemo-search (pattern &rest _ignore)
- (and helm-migemo-mode
- (helm-mm-3-search-base
- pattern 'helm-mm-migemo-forward 'helm-mm-migemo-forward)))
-
-\f
-;;; mp-3p- (multiple regexp pattern 3 with prefix search)
-;;
-;;
-(defun helm-mm-3p-match (str &optional pattern)
- "Check if PATTERN match STR.
-Same as `helm-mm-3-match' but more strict, matching against prefix also.
-e.g \"bar foo\" will match \"barfoo\" but not \"foobar\" contrarily to
-`helm-mm-3-match'."
- (let* ((pat (helm-mm-3-get-patterns (or pattern helm-pattern)))
- (first (car pat)))
- (and (funcall (car first) (helm-mm-prefix-match str (cdr first)))
- (cl-loop for (predicate . regexp) in (cdr pat)
- always (funcall predicate (string-match regexp str))))))
-
-(defun helm-mm-3p-search (pattern &rest _ignore)
- (when (stringp pattern)
- (setq pattern (helm-mm-3-get-patterns pattern)))
- (helm-mm-3-search-base
- pattern 'helm-mm-prefix-search 're-search-forward))
-
-\f
-;;; Generic multi-match/search functions
-;;
-;;
-(cl-defun helm-mm-match (str &optional (pattern helm-pattern))
- (let ((fun (cl-ecase helm-mm-matching-method
- (multi1 #'helm-mm-1-match)
- (multi2 #'helm-mm-2-match)
- (multi3 #'helm-mm-3-match)
- (multi3p #'helm-mm-3p-match))))
- (funcall fun str pattern)))
-
-(defun helm-mm-search (pattern &rest _ignore)
- (let ((fun (cl-ecase helm-mm-matching-method
- (multi1 #'helm-mm-1-search)
- (multi2 #'helm-mm-2-search)
- (multi3 #'helm-mm-3-search)
- (multi3p #'helm-mm-3p-search))))
- (funcall fun pattern)))
-
-
-(provide 'helm-multi-match)
-
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-multi-match.el ends here
+++ /dev/null
-;;; helm-source.el --- Helm source creation. -*- lexical-binding: t -*-
-
-;; Copyright (C) 2015 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; Author: Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-;; URL: http://github.com/emacs-helm/helm
-
-;; 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/>.
-
-;;; Commentary:
-
-;; Interface to create helm sources easily.
-;; Actually the eieo objects are transformed in alist for compatibility.
-;; In the future this package should allow creating source as eieo objects
-;; without conversion to alist, teaching helm to read such a structure.
-;; The compatibility with alists would be kept.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'eieio)
-(require 'helm-lib)
-
-(defvar helm-fuzzy-sort-fn)
-(defvar helm-fuzzy-match-fn)
-(defvar helm-fuzzy-search-fn)
-
-(declare-function helm-init-candidates-in-buffer "helm.el")
-(declare-function helm-interpret-value "helm.el")
-(declare-function helm-fuzzy-highlight-matches "helm.el")
-
-\f
-(defgeneric helm--setup-source (source)
- "Prepare slots and handle slot errors before creating a helm source.")
-
-(defgeneric helm-setup-user-source (source)
- "Allow users modifying slots in SOURCE just before creation.")
-
-\f
-;;; Classes for sources
-;;
-;;
-(defclass helm-source ()
- ((name
- :initarg :name
- :initform nil
- :custom string
- :documentation
- " The name of the source.
- A string which is also the heading which appears
- above the list of matches from the source. Must be unique.")
-
- (header-name
- :initarg :header-name
- :initform nil
- :custom function
- :documentation
- " A function returning the display string of the header.
- Its argument is the name of the source. This attribute is useful to
- add an additional information with the source name.
- It doesn't modify the name of the source.")
-
- (init
- :initarg :init
- :initform nil
- :custom function
- :documentation
- " Function called with no parameters when helm is started.
- It is useful for collecting current state information which can be
- used to create the list of candidates later.
- Initialization of `candidates-in-buffer' is done here
- with `helm-init-candidates-in-buffer'.")
-
- (candidates
- :initarg :candidates
- :initform nil
- :custom (choice function list)
- :documentation
- " Specifies how to retrieve candidates from the source.
- It can either be a variable name, a function called with no parameters
- or the actual list of candidates.
-
- The list must be a list whose members are strings, symbols
- or (DISPLAY . REAL) pairs.
-
- In case of (DISPLAY . REAL) pairs, the DISPLAY string is shown
- in the Helm buffer, but the REAL one is used as action
- argument when the candidate is selected. This allows a more
- readable presentation for candidates which would otherwise be,
- for example, too long or have a common part shared with other
- candidates which can be safely replaced with an abbreviated
- string for display purposes.
-
- Note that if the (DISPLAY . REAL) form is used then pattern
- matching is done on the displayed string, not on the real
- value.")
-
- (update
- :initarg :update
- :initform nil
- :custom function
- :documentation
- " Function called with no parameters at before \"init\" function
- when `helm-force-update' is called.")
-
- (cleanup
- :initarg :cleanup
- :initform nil
- :custom function
- :documentation
- " Function called with no parameters when *helm* buffer is
- closed. It is useful for killing unneeded candidates buffer.
-
- Note that the function is executed BEFORE performing action.")
-
- (keymap
- :initarg :keymap
- :initform nil
- :custom sexp
- :documentation
- " Specific keymap for this source.
- It is useful to have a keymap per source when using more than
- one source. Otherwise, a keymap can be set per command with
- `helm' argument KEYMAP. NOTE: when a source have `helm-map' as
- keymap attr, the global value of `helm-map' will override the
- actual local one.")
-
- (action
- :initarg :action
- :initform 'identity
- :custom (alist :key-type string
- :value-type function)
- :documentation
- " An alist of (DISPLAY . FUNCTION) pairs, a variable name or a function.
- FUNCTION is called with one parameter: the selected candidate.
-
- An action other than the default can be chosen from this list
- of actions for the currently selected candidate (by default
- with TAB). The DISPLAY string is shown in the completions
- buffer and the FUNCTION is invoked when an action is
- selected. The first action of the list is the default.
-
- You should use `helm-make-actions' to build this alist easily.")
-
- (persistent-action
- :initarg :persistent-action
- :initform nil
- :custom function
- :documentation
- " Can be a either a Function called with one parameter (the
- selected candidate) or a cons cell where first element is this
- same function and second element a symbol (e.g never-split)
- that inform `helm-execute-persistent-action'to not split his
- window to execute this persistent action.")
-
- (persistent-help
- :initarg :persistent-help
- :initform nil
- :custom string
- :documentation
- " A string to explain persistent-action of this source. It also
- accepts a function or a variable name.
- It will be displayed in `header-line'.
- Have no effect when `helm-echo-input-in-header-line' is non--nil.")
-
- (help-message
- :initarg :help-message
- :initform nil
- :custom (choice string function)
- :documentation
- " Help message for this source.
- If not present, `helm-help-message' value will be used.")
-
- (multiline
- :initarg :multiline
- :initform nil
- :custom boolean
- :documentation
- " Enable to selection multiline candidates.")
-
- (requires-pattern
- :initarg :requires-pattern
- :initform nil
- :custom integer
- :documentation
- " If present matches from the source are shown only if the
- pattern is not empty. Optionally, it can have an integer
- parameter specifying the required length of input which is
- useful in case of sources with lots of candidates.")
-
- (candidate-transformer
- :initarg :candidate-transformer
- :initform nil
- :custom (choice function list)
- :documentation
- " It's a function or a list of functions called with one argument
- when the completion list from the source is built. The argument
- is the list of candidates retrieved from the source. The
- function should return a transformed list of candidates which
- will be used for the actual completion. If it is a list of
- functions, it calls each function sequentially.
-
- This can be used to transform or remove items from the list of
- candidates.
-
- Note that `candidates' is run already, so the given transformer
- function should also be able to handle candidates with (DISPLAY
- . REAL) format.")
-
- (filtered-candidate-transformer
- :initarg :filtered-candidate-transformer
- :initform nil
- :custom (choice function list)
- :documentation
- " It has the same format as `candidate-transformer', except the
- function is called with two parameters: the candidate list and
- the source.
-
- This transformer is run on the candidate list which is already
- filtered by the current pattern. While `candidate-transformer'
- is run only once, it is run every time the input pattern is
- changed.
-
- It can be used to transform the candidate list dynamically, for
- example, based on the current pattern.
-
- In some cases it may also be more efficent to perform candidate
- transformation here, instead of with `candidate-transformer'
- even if this transformation is done every time the pattern is
- changed. For example, if a candidate set is very large then
- `candidate-transformer' transforms every candidate while only
- some of them will actually be displayed due to the limit
- imposed by `helm-candidate-number-limit'.
-
- Note that `candidates' and `candidate-transformer' is run
- already, so the given transformer function should also be able
- to handle candidates with (DISPLAY . REAL) format.")
-
- (filter-one-by-one
- :initarg :filter-one-by-one
- :initform nil
- :custom (choice function list)
- :documentation
- " A transformer function that treat candidates one by one.
- It is called with one arg the candidate.
- It is faster than `filtered-candidate-transformer' or
- `candidates-transformer', but should be used only in sources
- that recompute constantly their candidates, e.g `helm-source-find-files'.
- Filtering happen early and candidates are treated
- one by one instead of re-looping on the whole list.
- If used with `filtered-candidate-transformer' or `candidates-transformer'
- these functions should treat the candidates transformed by the
- `filter-one-by-one' function in consequence.")
-
- (display-to-real
- :initarg :display-to-real
- :initform nil
- :custom function
- :documentation
- " Function called with one parameter; the selected candidate.
-
- The function transforms the selected candidate, and the result
- is passed to the action function. The display-to-real
- attribute provides another way to pass to action other string than
- the one shown in Helm buffer.
-
- Traditionally, it is possible to make candidates,
- candidate-transformer or filtered-candidate-transformer
- function return a list with (DISPLAY . REAL) pairs. But if REAL
- can be generated from DISPLAY, display-to-real is more
- convenient and faster.
-
- NOTE: This is deprecated and you have better time using `filter-one-by-one'.")
-
- (real-to-display
- :initarg :real-to-display
- :initform nil
- :custom function
- :documentation
- " Function called with one parameter; the selected candidate.
- The real value of candidates will be shown in display.
- See `display-to-real'.")
-
- (action-transformer
- :initarg :action-transformer
- :initform nil
- :custom (choice function list)
- :documentation
- " It's a function or a list of functions called with two
- arguments when the action list from the source is
- assembled. The first argument is the list of actions, the
- second is the current selection. If it is a list of functions,
- it calls each function sequentially.
-
- The function should return a transformed action list.
-
- This can be used to customize the list of actions based on the
- currently selected candidate.")
-
- (pattern-transformer
- :initarg :pattern-transformer
- :initform nil
- :custom (choice function list)
- :documentation
- " It's a function or a list of functions called with one argument
- before computing matches. Its argument is `helm-pattern'.
- Functions should return transformed `helm-pattern'.
-
- It is useful to change interpretation of `helm-pattern'.")
-
- (candidate-number-limit
- :initarg :candidate-number-limit
- :initform nil
- :custom integer
- :documentation
- " Override `helm-candidate-number-limit' only for this source.")
-
- (volatile
- :initarg :volatile
- :initform nil
- :custom boolean
- :documentation
- " Indicates the source assembles the candidate list dynamically,
- so it shouldn't be cached within a single Helm
- invocation. It is only applicable to synchronous sources,
- because asynchronous sources are not cached.")
-
- (match
- :initarg :match
- :initform nil
- :custom (choice function list)
- :documentation
- " List of functions called with one parameter: a candidate. The
- function should return non-nil if the candidate matches the
- current pattern (see variable `helm-pattern').
-
- When using `candidates-in-buffer' its default value is `identity' and
- don't have to be changed, use the `search' slot instead.
-
- This attribute allows the source to override the default
- pattern matching based on `string-match'. It can be used, for
- example, to implement a source for file names and do the
- pattern matching on the basename of files, since it's more
- likely one is typing part of the basename when searching for a
- file, instead of some string anywhere else in its path.
-
- If the list contains more than one function then the list of
- matching candidates from the source is constructed by appending
- the results after invoking the first function on all the
- potential candidates, then the next function, and so on. The
- matching candidates supplied by the first function appear first
- in the list of results and then results from the other
- functions, respectively.
-
- This attribute has no effect for asynchronous sources (see
- attribute `candidates'), since they perform pattern matching
- themselves.
-
- Note that FUZZY-MATCH slot will overhide value of this slot.")
-
- (fuzzy-match
- :initarg :fuzzy-match
- :initform nil
- :custom boolean
- :documentation
- " Enable fuzzy matching in this source.
- This will overwrite settings in MATCH slot, and for
- sources built with child class `helm-source-in-buffer' the SEARCH slot.
- This is an easy way of enabling fuzzy matching, but you can use the MATCH
- or SEARCH slots yourself if you want something more elaborated, mixing
- different type of match (See `helm-source-buffers' class for example).")
-
- (nomark
- :initarg :nomark
- :initform nil
- :custom boolean
- :documentation
- " Don't allow marking candidates when this attribute is present.")
-
- (nohighlight
- :initarg :nohighlight
- :initform nil
- :custom boolean
- :documentation
- " Disable highlighting matches in this source.
- This will disable generic highlighting of matches,
- but some specialized highlighting can be done from elsewhere,
- i.e from `filtered-candidate-transformer' or `filter-one-by-one' slots.
- So use this to either disable completely highlighting in your source,
- or to disable highlighting and use a specialized highlighting matches
- function for this source.
- Remember that this function should run AFTER all filter functions if those
- filter functions are modifying face properties, though it is possible to
- avoid this by using new `add-face-text-property' in your filter functions.")
-
- (allow-dups
- :initarg :allow-dups
- :initform nil
- :custom boolean
- :documentation
- " Allow helm collecting duplicates candidates.")
-
- (history
- :initarg :history
- :initform nil
- :custom symbol
- :documentation
- " Allow passing history variable to helm from source.
- It should be a quoted symbol.")
-
- (coerce
- :initarg :coerce
- :initform nil
- :custom function
- :documentation
- " It's a function called with one argument: the selected candidate.
- This function is intended for type convertion. In normal case,
- the selected candidate (string) is passed to action
- function. If coerce function is specified, it is called just
- before action function.
-
- Example: converting string to symbol
- (coerce . intern)")
-
- (mode-line
- :initarg :mode-line
- :initform nil
- :custom (choice string sexp)
- :documentation
- " Source local `helm-mode-line-string' (included in
- `mode-line-format'). It accepts also variable/function name.")
-
- (header-line
- :initarg :header-line
- :initform nil
- :custom (choice string function)
- :documentation
- " Source local `header-line-format'.
- Have no effect when `helm-echo-input-in-header-line' is non--nil.
- It accepts also variable/function name.")
-
- (resume
- :initarg :resume
- :initform nil
- :custom function
- :documentation
- " Function called with no parameters at end of initialization
- when `helm-resume' is started.
- If this function try to do something against `helm-buffer', \(e.g updating,
- searching etc...\) probably you should run it in a timer to ensure
- `helm-buffer' is ready.")
-
- (follow
- :initarg :follow
- :initform nil
- :custom integer
- :documentation
- " Enable `helm-follow-mode' for this source only.
- You must give it a value of 1 or -1, though giving a -1 value
- is surely not what you want, e.g: (follow . 1)
-
- See `helm-follow-mode' for more infos.")
-
- (follow-delay
- :initarg :follow-delay
- :initform nil
- :custom integer
- :documentation
- " `helm-follow-mode' will execute persistent-action after this delay.
- Otherwise value of `helm-follow-input-idle-delay' is used if non--nil,
- If none of these are found fallback to `helm-input-idle-delay'.")
-
- (dont-plug
- :initarg :dont-plug
- :initform '(helm-compile-source--persistent-help)
- :custom list
- :documentation
- " A list of compile functions plugin to ignore.")
-
- (matchplugin
- :initarg :matchplugin
- :initform t
- :custom boolean)
-
- (match-part
- :initarg :match-part
- :initform nil
- :custom function
- :documentation
- " Allow matching only one part of candidate.
- If source contain match-part attribute, match is computed only
- on part of candidate returned by the call of function provided
- by this attribute. The function should have one arg, candidate,
- and return only a specific part of candidate.")
-
- (before-init-hook
- :initarg :before-init-hook
- :initform nil
- :custom symbol
- :documentation
- " A local hook that run at beginning of initilization of this source.
- i.e Before the creation of `helm-buffer'.
-
- Should be a variable (defined with defvar).
- Can be also an anonymous function or a list of functions
- directly added to slot, this is not recommended though.")
-
- (after-init-hook
- :initarg :after-init-hook
- :initform nil
- :custom symbol
- :documentation
- " A local hook that run at end of initilization of this source.
- i.e After the creation of `helm-buffer'.
-
- Should be a variable.
- Can be also an anonymous function or a list of functions
- directly added to slot, this is not recommended though.")
-
- (delayed
- :initarg :delayed
- :initform nil
- :custom (choice null integer)
- :documentation
- " This slot have no more effect and is just kept for backward compatibility.
- Please don't use it."))
-
- "Main interface to define helm sources."
- :abstract t)
-
-(defclass helm-source-sync (helm-source)
- ((candidates
- :initform '("ERROR: You must specify the `candidates' slot, either with a list or a function"))
-
- (dont-plug
- :initform '(helm-compile-source--multi-match
- helm-compile-source--persistent-help
- ;; Ensure this will not be plugged
- ;; if user have somewhere old helm-migemo.el.
- helm-compile-source--migemo))
-
- (migemo
- :initarg :migemo
- :initform nil
- :custom boolean
- :documentation
- " Enable migemo.
- When multimatch is disabled, you can give the symbol 'nomultimatch as value
- to force not using generic migemo matching function.
- In this case you have to provide your own migemo matching funtion
- that kick in when `helm-migemo-mode' is enabled.
- Otherwise it will be available for this source once `helm-migemo-mode'
- is enabled when non-nil.")
-
- (match-strict
- :initarg :match-strict
- :initform nil
- :custom function
- :documentation
- " When specifying a match function within a source and
- helm-multi-match is enabled, the result of all matching
- functions will be concatened, which in some cases is not what
- is wanted. When using `match-strict' only this or these
- functions will be used. You can specify those functions as a
- list of functions or a single symbol function.
-
- NOTE: This have the same effect as using :MATCHPLUGIN nil."))
-
- "Use this class to make helm sources using a list of candidates.
-This list should be given as a normal list, a variable handling a list
-or a function returning a list.
-Matching is done basically with `string-match' against each candidate.")
-
-(defclass helm-source-async (helm-source)
- ((candidates-process
- :initarg :candidates-process
- :initform nil
- :custom function
- :documentation
- " This attribute is used to define a process as candidate.
- The value must be a process.
-
- NOTE:
- When building the source at runtime you can give directly a process
- as value, otherwise wrap the process call into a function.
- The process buffer should be nil, otherwise, if you use
- `helm-buffer' give to the process a sentinel.")
-
- (matchplugin :initform nil)
- (dont-plug :initform '(helm-compile-source--multi-match
- helm-compile-source--persistent-help)))
-
- "Use this class to define a helm source calling an external process.
-The :candidates slot is not allowed even if described because this class
-inherit from `helm-source'.")
-
-(defclass helm-source-in-buffer (helm-source)
- ((init
- :initform 'helm-default-init-source-in-buffer-function)
-
- (data
- :initarg :data
- :initform nil
- :custom (choice list string)
- :documentation
- " A string or a list that will be used to feed the `helm-candidates-buffer'.
- This data will be passed in a function added to the init slot and
- the buffer will be build with `helm-init-candidates-in-buffer'.
- This is an easy and fast method to build a `candidates-in-buffer' source.")
-
- (dont-plug
- :initform '(helm-compile-source--candidates-in-buffer
- helm-compile-source--multi-match
- helm-compile-source--persistent-help
- helm-compile-source--migemo))
-
- (migemo
- :initarg :migemo
- :initform nil
- :custom boolean
- :documentation
- " Enable migemo.
- When multimatch is disabled, you can give the symbol 'nomultimatch as value
- to force not using generic migemo matching function.
- In this case you have to provide your own migemo matching funtion
- that kick in when `helm-migemo-mode' is enabled.
- Otherwise it will be available for this source once `helm-migemo-mode'
- is enabled when non-nil.")
-
- (candidates
- :initform 'helm-candidates-in-buffer)
-
- (volatile
- :initform t)
-
- (match
- :initform '(identity))
-
- (get-line
- :initarg :get-line
- :initform 'buffer-substring-no-properties
- :custom function
- :documentation
- " A function like `buffer-substring-no-properties' or `buffer-substring'.
- This function converts point of line-beginning and point of line-end,
- which represents a candidate computed by `helm-candidates-in-buffer'.
- By default, `helm-candidates-in-buffer' uses
- `buffer-substring-no-properties'.")
-
- (search
- :initarg :search
- :initform '(helm-candidates-in-buffer-search-default-fn)
- :custom (choice function list)
- :documentation
- " List of functions like `re-search-forward' or `search-forward'.
- Buffer search function used by `helm-candidates-in-buffer'.
- By default, `helm-candidates-in-buffer' uses `re-search-forward'.
- The function should take one arg PATTERN.
- If your search function needs to handle negation like matchplugin,
- this function should returns in such case a cons cell of two integers defining
- the beg and end positions to match in the line previously matched by
- `re-search-forward' or similar, and move point to next line
- (See how the `helm-mm-3-search-base' and `helm-fuzzy-search' functions are working).
-
- NOTE: FUZZY-MATCH slot will overhide value of this slot.")
-
- (search-strict
- :initarg :search-strict
- :initform nil
- :custom function
- :documentation
- " When specifying a search function within a source and
- helm-multi-match is enabled, the result of all searching
- functions will be concatened, which in some cases is not what
- is wanted. When using `search-strict' only this or these
- functions will be used. You can specify those functions as a
- list of functions or a single symbol function.
-
- NOTE: This have the same effect as using a nil value for
- :MATCHPLUGIN slot."))
-
- "Use this source to make helm sources storing candidates inside a buffer.
-Contrarily to `helm-source-sync' candidates are matched using a function
-like `re-search-forward', see below documentation of :search slot.")
-
-(defclass helm-source-dummy (helm-source)
- ((candidates
- :initform '("dummy"))
-
- (filtered-candidate-transformer
- :initform 'helm-dummy-candidate)
-
- (matchplugin
- :initform nil)
-
- (accept-empty
- :initarg :accept-empty
- :initform t
- :custom boolean
- :documentation
- " Allow exiting with an empty string.
- You should keep the default value.")
-
- (match
- :initform 'identity)
-
- (volatile
- :initform t)))
-
-(defclass helm-source-in-file (helm-source-in-buffer)
- ((init :initform (lambda ()
- (let ((file (helm-attr 'candidates-file)))
- (with-current-buffer (helm-candidate-buffer 'global)
- (insert-file-contents file)))))
- (candidates-file
- :initarg :candidates-file
- :initform nil
- :custom string
- :documentation "A filename."))
-
- "The contents of the file will be used as candidates in buffer.")
-
-\f
-;;; Error functions
-;;
-;;
-(defun helm-default-init-source-in-buffer-function ()
- (helm-init-candidates-in-buffer 'global
- '("ERROR: No buffer handling your data, use either the `init' slot or the `data' slot.")))
-
-\f
-;;; Internal Builder functions.
-;;
-;;
-(defun helm--create-source (object)
- "[INTERNAL] Build a helm source from OBJECT.
-Where OBJECT is an instance of an eieio class."
- (cl-loop for s in (object-slots object)
- for slot-val = (slot-value object s)
- when slot-val
- collect (cons s (unless (eq t slot-val) slot-val))))
-
-(defun helm-make-source (name class &rest args)
- "Build a `helm' source named NAME with ARGS for CLASS.
-Argument NAME is a string which define the source name, so no need to use
-the keyword :name in your source, NAME will be used instead.
-Argument CLASS is an eieio class object.
-Arguments ARGS are keyword value pairs as defined in CLASS."
- (declare (indent 2))
- (let ((source (apply #'make-instance class name args)))
- (setf (slot-value source 'name) name)
- (helm--setup-source source)
- (helm-setup-user-source source)
- (helm--create-source source)))
-
-(defun helm-make-type (class &rest args)
- (let ((source (apply #'make-instance class args)))
- (setf (slot-value source 'name) nil)
- (helm--setup-source source)
- (helm--create-source source)))
-
-(defvar helm-mm-default-search-functions)
-(defvar helm-mm-default-match-functions)
-
-(defun helm-source-mm-get-search-or-match-fns (source method)
- (let ((defmatch (helm-aif (slot-value source 'match)
- (helm-mklist it)))
- (defmatch-strict (helm-aif (and (eq method 'match)
- (slot-value source 'match-strict))
- (helm-mklist it)))
- (defsearch (helm-aif (and (eq method 'search)
- (slot-value source 'search))
- (helm-mklist it)))
- (defsearch-strict (helm-aif (and (eq method 'search-strict)
- (slot-value source 'search-strict))
- (helm-mklist it)))
- (migemo (slot-value source 'migemo)))
- (cl-case method
- (match (cond (defmatch-strict)
- (migemo
- (append helm-mm-default-match-functions
- defmatch '(helm-mm-3-migemo-match)))
- (defmatch
- (append helm-mm-default-match-functions defmatch))
- (t helm-mm-default-match-functions)))
- (search (cond (defsearch-strict)
- (migemo
- (append helm-mm-default-search-functions
- defsearch '(helm-mm-3-migemo-search)))
- (defsearch
- (append helm-mm-default-search-functions defsearch))
- (t helm-mm-default-search-functions))))))
-
-\f
-;;; Modifiers
-;;
-(cl-defun helm-source-add-action-to-source-if (name fn source predicate
- &optional (index 4))
- "Same as `helm-add-action-to-source-if' but for SOURCE defined as eieio object.
-You can use this inside a `helm--setup-source' method for a SOURCE defined as
-an eieio class."
- (let* ((actions (slot-value source 'action))
- (action-transformers (slot-value source 'action-transformer))
- (new-action (list (cons name fn)))
- (transformer `(lambda (actions candidate)
- (cond ((funcall (quote ,predicate) candidate)
- (helm-append-at-nth
- actions (quote ,new-action) ,index))
- (t actions)))))
- (if (functionp actions)
- (setf (slot-value source 'action) (list (cons "Default action" actions)))
- (setf (slot-value source 'action) (helm-interpret-value actions source)))
- (when (or (symbolp action-transformers) (functionp action-transformers))
- (setq action-transformers (list action-transformers)))
- (setf (slot-value source 'action-transformer)
- (delq nil (append (list transformer) action-transformers)))))
-
-\f
-;;; Methods to build sources.
-;;
-;;
-(defun helm-source--persistent-help-string (string source)
- (substitute-command-keys
- (concat "\\<helm-map>\\[helm-execute-persistent-action]: "
- (or (format "%s (keeping session)" string)
- (slot-value source 'header-line)))))
-
-(defun helm-source--header-line (source)
- (substitute-command-keys
- (concat "\\<helm-map>\\[helm-execute-persistent-action]: "
- (helm-aif (or (slot-value source 'persistent-action)
- (slot-value source 'action))
- (cond ((and (symbolp it)
- (functionp it)
- (eq it 'identity))
- "Do Nothing")
- ((and (symbolp it)
- (boundp it)
- (listp (symbol-value it))
- (stringp (caar (symbol-value it))))
- (caar (symbol-value it)))
- ((or (symbolp it) (functionp it))
- (helm-symbol-name it))
- ((listp it)
- (let ((action (car it)))
- ;; It comes from :action ("foo" . function).
- (if (stringp (car action))
- (car action)
- ;; It comes from :persistent-action
- ;; (function . 'nosplit) Fix Issue #788.
- (if (or (symbolp action)
- (functionp action))
- (helm-symbol-name action)))))
- (t ""))
- "")
- " (keeping session)")))
-
-(defmethod helm--setup-source :primary ((_source helm-source)))
-
-(defmethod helm--setup-source :before ((source helm-source))
- (when (slot-value source 'delayed)
- (warn "Deprecated usage of helm `delayed' slot in `%s'"
- (slot-value source 'name)))
- (helm-aif (slot-value source 'keymap)
- (and (symbolp it) (setf (slot-value source 'keymap) (symbol-value it))))
- (helm-aif (slot-value source 'persistent-help)
- (setf (slot-value source 'header-line)
- (helm-source--persistent-help-string it source))
- (setf (slot-value source 'header-line) (helm-source--header-line source)))
- (helm-aif (slot-value source 'candidate-number-limit)
- (and (symbolp it) (setf (slot-value source 'candidate-number-limit)
- (symbol-value it))))
- (when (and (slot-value source 'fuzzy-match) helm-fuzzy-sort-fn)
- (setf (slot-value source 'filtered-candidate-transformer)
- (helm-aif (slot-value source 'filtered-candidate-transformer)
- (append (helm-mklist it)
- (list helm-fuzzy-sort-fn))
- (list helm-fuzzy-sort-fn))))
- (unless (slot-value source 'nohighlight)
- (setf (slot-value source 'filtered-candidate-transformer)
- (helm-aif (slot-value source 'filtered-candidate-transformer)
- (append (helm-mklist it)
- (list #'helm-fuzzy-highlight-matches))
- (list #'helm-fuzzy-highlight-matches)))))
-
-(defmethod helm-setup-user-source ((_source helm-source)))
-
-(defmethod helm--setup-source ((source helm-source-sync))
- (when (slot-value source 'fuzzy-match)
- (helm-aif (slot-value source 'match)
- (setf (slot-value source 'match)
- (append (helm-mklist it)
- (list helm-fuzzy-match-fn)))
- (setf (slot-value source 'match) helm-fuzzy-match-fn)))
- (when (slot-value source 'matchplugin)
- (setf (slot-value source 'match)
- (helm-source-mm-get-search-or-match-fns source 'match)))
- (helm-aif (and (null (slot-value source 'matchplugin))
- (slot-value source 'migemo))
- (unless (eq it 'nomultimatch) ; Use own migemo fn.
- (setf (slot-value source 'match)
- (append (helm-mklist (slot-value source 'match))
- '(helm-mm-3-migemo-match))))))
-
-(defmethod helm--setup-source ((source helm-source-in-buffer))
- (let ((cur-init (slot-value source 'init)))
- (helm-aif (slot-value source 'data)
- (setf (slot-value source 'init)
- (delq
- nil
- (list
- (and (null (eq 'helm-default-init-source-in-buffer-function
- cur-init))
- cur-init)
- (lambda ()
- (helm-init-candidates-in-buffer
- 'global
- (if (functionp it) (funcall it) it))))))))
- (when (slot-value source 'fuzzy-match)
- (helm-aif (slot-value source 'search)
- (setf (slot-value source 'search)
- (append (helm-mklist it)
- (list helm-fuzzy-search-fn)))
- (setf (slot-value source 'search) (list helm-fuzzy-search-fn))))
- (when (slot-value source 'matchplugin)
- (setf (slot-value source 'search)
- (helm-source-mm-get-search-or-match-fns source 'search)))
- (helm-aif (and (null (slot-value source 'matchplugin))
- (slot-value source 'migemo))
- (unless (eq it 'nomultimatch)
- (setf (slot-value source 'search)
- (append (helm-mklist (slot-value source 'search))
- '(helm-mm-3-migemo-search)))))
- (let ((mtc (slot-value source 'match)))
- (cl-assert (or (equal '(identity) mtc)
- (eq 'identity mtc))
- nil "Invalid slot value for `match'")
- (cl-assert (eq (slot-value source 'volatile) t)
- nil "Invalid slot value for `volatile'")))
-
-(defmethod helm--setup-source ((source helm-source-async))
- (cl-assert (null (slot-value source 'candidates))
- nil "Incorrect use of `candidates' use `candidates-process' instead")
- (cl-assert (null (slot-value source 'matchplugin))
- nil "`matchplugin' not allowed in async sources."))
-
-(defmethod helm--setup-source ((source helm-source-dummy))
- (let ((mtc (slot-value source 'match)))
- (cl-assert (or (equal '(identity) mtc)
- (eq 'identity mtc))
- nil "Invalid slot value for `match'")
- (cl-assert (eq (slot-value source 'volatile) t)
- nil "Invalid slot value for `volatile'")
- (cl-assert (equal (slot-value source 'candidates) '("dummy"))
- nil "Invalid slot value for `candidates'")
- (cl-assert (eq (slot-value source 'accept-empty) t)
- nil "Invalid slot value for `accept-empty'")))
-
-\f
-;;; User functions
-;;
-;; Sources
-(defmacro helm-build-sync-source (name &rest args)
- "Build a synchronous helm source with name NAME.
-Args ARGS are keywords provided by `helm-source-sync'."
- (declare (indent 1))
- `(helm-make-source ,name 'helm-source-sync ,@args))
-
-(defmacro helm-build-async-source (name &rest args)
- "Build a asynchronous helm source with name NAME.
-Args ARGS are keywords provided by `helm-source-async'."
- (declare (indent 1))
- `(helm-make-source ,name 'helm-source-async ,@args))
-
-(defmacro helm-build-in-buffer-source (name &rest args)
- "Build a helm source with name NAME using `candidates-in-buffer' method.
-Args ARGS are keywords provided by `helm-source-in-buffer'."
- (declare (indent 1))
- `(helm-make-source ,name 'helm-source-in-buffer ,@args))
-
-(defmacro helm-build-dummy-source (name &rest args)
- "Build a helm source with name NAME using `dummy' method.
-Args ARGS are keywords provided by `helm-source-dummy'."
- (declare (indent 1))
- `(helm-make-source ,name 'helm-source-dummy ,@args))
-
-(defmacro helm-build-in-file-source (name file &rest args)
- "Build a helm source with NAME name using `candidates-in-files' method.
-Arg FILE is a filename, the contents of this file will be
-used as candidates in buffer.
-Args ARGS are keywords provided by `helm-source-in-file'."
- (declare (indent 1))
- `(helm-make-source ,name 'helm-source-in-file
- :candidates-file ,file ,@args))
-
-
-(provide 'helm-source)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-source ends here
+++ /dev/null
-;;; helm.el --- Emacs incremental and narrowing framework -*- lexical-binding: t -*-
-
-;; Copyright (C) 2007 Tamas Patrovics
-;; 2008 ~ 2011 rubikitch <rubikitchNOSPAMruby-lang.org>
-;; 2011 ~ 2016 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; This is a fork of anything.el wrote by Tamas Patrovics.
-
-;; Authors of anything.el: Tamas Patrovics
-;; rubikitch <rubikitchNOSPAMruby-lang.org>
-;; Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-
-;; Author: Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
-;; URL: http://github.com/emacs-helm/helm
-
-;; 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/>.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'advice) ; Shutup byte compiler about ad-deactivate.
-(require 'helm-lib)
-(require 'helm-multi-match)
-(require 'helm-source)
-
-\f
-;;; Multi keys
-;;
-;;
-;;;###autoload
-(defun helm-define-multi-key (keymap key functions &optional delay)
- "In KEYMAP, define key sequence KEY for function list FUNCTIONS.
-Each function runs sequentially for each KEY press.
-If DELAY is specified, switch back to initial function of FUNCTIONS list
-after DELAY seconds.
-The functions in FUNCTIONS list take no args.
-e.g
- \(defun foo ()
- (message \"Run foo\"))
- \(defun bar ()
- (message \"Run bar\"))
- \(defun baz ()
- (message \"Run baz\"))
-
-\(helm-define-multi-key global-map \"<f5> q\" '(foo bar baz) 2)
-
-Each time \"<f5> q\" is pressed, the next function is executed. Waiting
-more than 2 seconds between key presses switches back to executing the first
-function on the next hit."
- (define-key keymap key (helm-make-multi-command functions delay)))
-
-;;;###autoload
-(defmacro helm-multi-key-defun (name docstring funs &optional delay)
- "Define NAME as a multi-key command running FUNS.
-After DELAY seconds, the FUNS list is reinitialized.
-See `helm-define-multi-key'."
- (declare (indent 2))
- (setq docstring (if docstring (concat docstring "\n\n")
- "This is a helm-ish multi-key command."))
- `(defalias (quote ,name) (helm-make-multi-command ,funs ,delay) ,docstring))
-
-(defun helm-make-multi-command (functions &optional delay)
- "Return an anonymous multi-key command running FUNCTIONS.
-Run each function in the FUNCTIONS list in turn when called within DELAY seconds."
- (declare (indent 1))
- (let ((funs functions)
- (iter (cl-gensym "helm-iter-key"))
- (timeout delay))
- (eval (list 'defvar iter nil))
- (lambda () (interactive) (helm-run-multi-key-command funs iter timeout))))
-
-(defun helm-run-multi-key-command (functions iterator delay)
- (let ((fn (lambda ()
- (cl-loop for count from 1 to (length functions)
- collect count)))
- next)
- (unless (and (symbol-value iterator)
- ;; Reset iterator when another key is pressed.
- (eq this-command real-last-command))
- (set iterator (helm-iter-list (funcall fn))))
- (setq next (helm-iter-next (symbol-value iterator)))
- (unless next
- (set iterator (helm-iter-list (funcall fn)))
- (setq next (helm-iter-next (symbol-value iterator))))
- (and next (symbol-value iterator) (call-interactively (nth (1- next) functions)))
- (when delay (run-with-idle-timer delay nil `(lambda ()
- (setq ,iterator nil))))))
-
-(helm-multi-key-defun helm-toggle-resplit-and-swap-windows
- "Multi key command to re-split and swap helm window.
-First call runs `helm-toggle-resplit-window',
-and second call within 0.5s runs `helm-swap-windows'."
- '(helm-toggle-resplit-window helm-swap-windows) 1)
-(put 'helm-toggle-resplit-and-swap-windows 'helm-only t)
-
-;;;###autoload
-(defun helm-define-key-with-subkeys (map key subkey command
- &optional other-subkeys menu exit-fn)
- "Defines in MAP a KEY and SUBKEY to COMMAND.
-
-This allows typing KEY to call COMMAND the first time and
-type only SUBKEY on subsequent calls.
-
-Arg MAP is the keymap to use, SUBKEY is the initial short key-binding to
-call COMMAND.
-
-Arg OTHER-SUBKEYS is an alist specifying other short key-bindings
-to use once started e.g:
-
- \(helm-define-key-with-subkeys global-map
- \(kbd \"C-x v n\") ?n 'git-gutter:next-hunk '((?p . git-gutter:previous-hunk))\)
-
-
-In this example, `C-x v n' will run `git-gutter:next-hunk'
-subsequent \"n\"'s run this command again
-and subsequent \"p\"'s run `git-gutter:previous-hunk'.
-
-Arg MENU is a string displayed in minibuffer that
-describes SUBKEY and OTHER-SUBKEYS.
-Arg EXIT-FN specifies a function to run on exit.
-
-For any other keys pressed, run their assigned command as defined
-in MAP and then exit the loop running EXIT-FN, if specified.
-
-NOTE: SUBKEY and OTHER-SUBKEYS bindings support char syntax only
-\(e.g ?n), so don't use strings or vectors to define them."
- (declare (indent 1))
- (define-key map key
- (lambda ()
- (interactive)
- (unwind-protect
- (progn
- (call-interactively command)
- (while (let ((input (read-key menu)) other kb com)
- (setq last-command-event input)
- (cond
- ((eq input subkey)
- (call-interactively command)
- t)
- ((setq other (assoc input other-subkeys))
- (call-interactively (cdr other))
- t)
- (t
- (setq kb (vector last-command-event))
- (setq com (lookup-key map kb))
- (if (commandp com)
- (call-interactively com)
- (setq unread-command-events
- (nconc (mapcar 'identity kb)
- unread-command-events)))
- nil)))))
- (and exit-fn (funcall exit-fn))))))
-\f
-;;; Keymap
-;;
-;;
-(defvar helm-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map minibuffer-local-map)
- (define-key map (kbd "<down>") 'helm-next-line)
- (define-key map (kbd "<up>") 'helm-previous-line)
- (define-key map (kbd "C-n") 'helm-next-line)
- (define-key map (kbd "C-p") 'helm-previous-line)
- (define-key map (kbd "<C-down>") 'helm-follow-action-forward)
- (define-key map (kbd "<C-up>") 'helm-follow-action-backward)
- (define-key map (kbd "<prior>") 'helm-previous-page)
- (define-key map (kbd "<next>") 'helm-next-page)
- (define-key map (kbd "M-v") 'helm-previous-page)
- (define-key map (kbd "C-v") 'helm-next-page)
- (define-key map (kbd "M-<") 'helm-beginning-of-buffer)
- (define-key map (kbd "M->") 'helm-end-of-buffer)
- (define-key map (kbd "C-g") 'helm-keyboard-quit)
- (define-key map (kbd "<right>") 'helm-next-source)
- (define-key map (kbd "<left>") 'helm-previous-source)
- (define-key map (kbd "<RET>") 'helm-maybe-exit-minibuffer)
- (define-key map (kbd "C-i") 'helm-select-action)
- (define-key map (kbd "C-z") 'helm-execute-persistent-action)
- (define-key map (kbd "C-j") 'helm-execute-persistent-action)
- (define-key map (kbd "C-o") 'helm-next-source)
- (define-key map (kbd "C-l") 'helm-recenter-top-bottom-other-window)
- (define-key map (kbd "M-C-l") 'helm-reposition-window-other-window)
- (define-key map (kbd "C-M-v") 'helm-scroll-other-window)
- (define-key map (kbd "M-<next>") 'helm-scroll-other-window)
- (define-key map (kbd "C-M-y") 'helm-scroll-other-window-down)
- (define-key map (kbd "C-M-S-v") 'helm-scroll-other-window-down)
- (define-key map (kbd "M-<prior>") 'helm-scroll-other-window-down)
- (define-key map (kbd "<C-M-down>") 'helm-scroll-other-window)
- (define-key map (kbd "<C-M-up>") 'helm-scroll-other-window-down)
- (define-key map (kbd "C-@") 'helm-toggle-visible-mark)
- (define-key map (kbd "C-SPC") 'helm-toggle-visible-mark)
- (define-key map (kbd "M-SPC") 'helm-toggle-visible-mark)
- (define-key map (kbd "M-[") nil)
- (define-key map (kbd "M-(") 'helm-prev-visible-mark)
- (define-key map (kbd "M-)") 'helm-next-visible-mark)
- (define-key map (kbd "C-k") 'helm-delete-minibuffer-contents)
- (define-key map (kbd "C-x C-f") 'helm-quit-and-find-file)
- (define-key map (kbd "M-m") 'helm-toggle-all-marks)
- (define-key map (kbd "M-a") 'helm-mark-all)
- (define-key map (kbd "M-U") 'helm-unmark-all)
- (define-key map (kbd "C-w") 'helm-yank-text-at-point)
- (define-key map (kbd "C-M-a") 'helm-show-all-in-this-source-only)
- (define-key map (kbd "C-M-e") 'helm-display-all-sources)
- (define-key map (kbd "C-r") 'undefined)
- (define-key map (kbd "C-s") 'undefined)
- (define-key map (kbd "M-s") 'undefined)
- (define-key map (kbd "C-}") 'helm-narrow-window)
- (define-key map (kbd "C-{") 'helm-enlarge-window)
- (define-key map (kbd "C-c -") 'helm-swap-windows)
- (define-key map (kbd "C-c C-y") 'helm-yank-selection)
- (define-key map (kbd "C-c C-k") 'helm-kill-selection-and-quit)
- (define-key map (kbd "C-c C-i") 'helm-copy-to-buffer)
- (define-key map (kbd "C-c C-f") 'helm-follow-mode)
- (define-key map (kbd "C-c C-u") 'helm-refresh)
- (define-key map (kbd "C-c >") 'helm-toggle-truncate-line)
- (define-key map (kbd "M-p") 'previous-history-element)
- (define-key map (kbd "M-n") 'next-history-element)
- (define-key map (kbd "C-!") 'helm-toggle-suspend-update)
- (define-key map (kbd "C-x b") 'helm-resume-previous-session-after-quit)
- (define-key map (kbd "C-x C-b") 'helm-resume-list-buffers-after-quit)
- ;; Disable `file-cache-minibuffer-complete'.
- (define-key map (kbd "<C-tab>") 'undefined)
- ;; Multi keys
- (define-key map (kbd "C-t") 'helm-toggle-resplit-and-swap-windows)
- ;; Debugging command
- (define-key map (kbd "C-h C-d") 'undefined)
- (define-key map (kbd "C-h C-d") 'helm-enable-or-switch-to-debug)
- ;; Allow to eval keymap without errors.
- (define-key map [f1] nil)
- (define-key map (kbd "C-h C-h") 'undefined)
- (define-key map (kbd "C-h h") 'undefined)
- ;; Use `describe-mode' key in `global-map'.
- (cl-dolist (k (where-is-internal 'describe-mode global-map))
- (define-key map k 'helm-help))
- (define-key map (kbd "C-c ?") 'helm-help)
- ;; Bind all actions from 1 to 12 to their corresponding nth index+1.
- (cl-loop for n from 0 to 12 do
- (define-key map (kbd (format "<f%s>" (1+ n)))
- `(lambda ()
- (interactive)
- (helm-select-nth-action ,n))))
- ;; Bind keys to allow executing default action
- ;; on first 9 candidates before and after selection.
- (cl-loop for n from 1 to 9
- for key = (format "C-c %d" n)
- for key- = (format "C-x %d" n)
- for fn = `(lambda ()
- (interactive)
- (helm-execute-selection-action-at-nth ,n))
- for fn- = `(lambda ()
- (interactive)
- (helm-execute-selection-action-at-nth ,(- n)))
- do (progn
- (define-key map (kbd key) fn)
- (define-key map (kbd key-) fn-)))
- map)
- "Keymap for helm.")
-
-\f
-(defgroup helm nil
- "Open helm."
- :prefix "helm-" :group 'convenience)
-
-(defcustom helm-completion-window-scroll-margin 5
- " `scroll-margin' to use for helm completion window.
-Set to 0 to disable.
-NOTE: This has no effect when `helm-display-source-at-screen-top'
-id is non-`nil'."
- :group 'helm
- :type 'integer)
-
-(defcustom helm-display-source-at-screen-top t
- "Display candidates at the top of screen.
-This happens with `helm-next-source' and `helm-previous-source'.
-NOTE: When non-`nil' (default), disable `helm-completion-window-scroll-margin'."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-candidate-number-limit 100
- "Global limit for number of candidates displayed.
-When the pattern is empty, the number of candidates shown will be
-as set here instead of the entire list, which may be hundreds or
-thousands. Since narrowing and filtering rapidly reduces
-available candidates, having a small list will keep the interface
-responsive.
-
-Set this value to nil for no limit."
- :group 'helm
- :type '(choice (const :tag "Disabled" nil) integer))
-
-(defcustom helm-input-idle-delay 0.01
- "Idle time before updating, specified in seconds."
- :group 'helm
- :type 'float)
-
-(defcustom helm-exit-idle-delay 0
- "Idle time before exiting minibuffer while helm is updating.
-Has no affect when helm-buffer is up to date \(i.e exit without
-delay in this condition\)."
- :group 'helm
- :type 'float)
-
-(defcustom helm-full-frame nil
- "Use current window for showing candidates.
-If t, then Helm does not pop-up new window."
- :group 'helm
- :type 'boolean)
-
-(defvaralias 'helm-samewindow 'helm-full-frame)
-(make-obsolete-variable 'helm-samewindow 'helm-full-frame "1.4.8.1")
-
-(defcustom helm-candidate-separator
- "--------------------"
- "Candidates separator of `multiline' source."
- :group 'helm
- :type 'string)
-
-(defcustom helm-save-configuration-functions
- '(set-window-configuration . current-window-configuration)
- "Functions used to restore or save configurations for frames and windows.
-Specified as a pair of functions, where car is the restore function and cdr
-is the save function.
-
-To save and restore frame configuration, set this variable to
-'\(set-frame-configuration . current-frame-configuration\)
-
-NOTE: This may not work properly with own-frame minibuffer
-settings. Older versions saves/restores frame configuration, but
-the default has changed now to avoid flickering."
- :group 'helm
- :type 'sexp)
-
-(defcustom helm-persistent-action-use-special-display nil
- "If non-`nil', use `special-display-function' in persistent action."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-display-function 'helm-default-display-buffer
- "Function to display *helm* buffer.
-By default, it is `helm-default-display-buffer', which affects
-`helm-full-frame'."
- :group 'helm
- :type 'symbol)
-
-(defcustom helm-case-fold-search 'smart
- "Adds 'smart' option to `case-fold-search'.
-Smart option ignores case for searches as long as there are no
-upper case characters in the pattern.
-
-Use nil or t to turn off smart behavior and use
-`case-fold-search' behavior.
-
-Default is smart.
-
-NOTE: Case fold search has no effect when searching asynchronous
-sources, which rely on customized features implemented directly
-into their execution process. See helm-grep.el for an example."
- :group 'helm
- :type '(choice (const :tag "Ignore case" t)
- (const :tag "Respect case" nil)
- (other :tag "Smart" 'smart)))
-
-(defcustom helm-file-name-case-fold-search
- (if (memq system-type
- '(cygwin windows-nt ms-dos darwin))
- t
- helm-case-fold-search)
- "Local setting of `helm-case-fold-search' for reading filenames.
-
-See `helm-case-fold-search' for more info."
- :group 'helm
- :type 'symbol)
-
-(defcustom helm-reuse-last-window-split-state nil
- "Use the same state of window split, vertical or horizontal.
-`helm-toggle-resplit-window' for the next helm session will use
-the same window scheme as the previous session unless
-`helm-split-window-default-side' is 'same or 'other."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-split-window-preferred-function 'helm-split-window-default-fn
- "Default function used for splitting window."
- :group 'helm
- :type 'function)
-
-(defcustom helm-split-window-default-side 'below
- "The default side to display `helm-buffer'.
-Must be one acceptable arg for `split-window' SIDE,
-that is `below', `above', `left' or `right'.
-
-Other acceptable values are `same' which always display
-`helm-buffer' in current window and `other' that display
-`helm-buffer' below if only one window or in
-`other-window-for-scrolling' when available.
-
-A nil value has same effect as `below'.
-If `helm-full-frame' is non-`nil', it take precedence over this setting.
-
-See also `helm-split-window-in-side-p' and `helm-always-two-windows' that
-take precedence over this.
-
-NOTE: this have no effect if `helm-split-window-preferred-function' is not
-`helm-split-window-default-fn' unless this new function can handle this."
- :group 'helm
- :type 'symbol)
-
-(defcustom helm-display-buffer-default-size nil
- "Initial height of `helm-buffer', specified as an integer or a function.
-The function should take one arg and the responsibility for
-re-sizing the window; function's return value is ignored. See
-`display-buffer' for more info."
- :group 'helm
- :type '(choice integer function))
-
-(defcustom helm-split-window-in-side-p nil
- "Forces split inside selected window when non-`nil'.
-See also `helm-split-window-default-side'.
-
-NOTE: this has no effect if
-`helm-split-window-preferred-function' is not
-`helm-split-window-default-fn' unless this new function can
-handle this."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-always-two-windows nil
- "When non-`nil' helm uses two windows in this frame.
-To display `helm-buffer' in one window and `helm-current-buffer'
-in the other.
-
-Note: this has no effect when `helm-split-window-in-side-p' is non-`nil',
-or when `helm-split-window-default-side' is set to 'same.
-
-When `helm-autoresize-mode' is enabled, setting this to nil
-will have no effect.
-
-Also when non-`nil' it overrides the effect of `helm-split-window-default-side'
-set to `other'."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-sources-using-default-as-input '(helm-source-imenu
- helm-source-imenu-all
- helm-source-info-elisp
- helm-source-etags-select
- helm-source-man-pages
- helm-source-occur
- helm-source-moccur)
- "List of helm sources that need to use `helm--maybe-use-default-as-input'.
-When a source is a member of this list, default `thing-at-point'
-will be used as input."
- :group 'helm
- :type '(repeat (choice symbol)))
-
-(defcustom helm-delete-minibuffer-contents-from-point t
- "When non-`nil', `helm-delete-minibuffer-contents' delete region from `point'.
-Otherwise delete `minibuffer-contents'.
-See documentation for `helm-delete-minibuffer-contents'."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-follow-mode-persistent nil
- "When non-`nil', use last state of `helm-follow-mode' for the next helm session.
-To make this behavior persistent across emacs sessions, set the
-`follow' attribute explicitly in the source."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-prevent-escaping-from-minibuffer t
- "Prevent escape from minibuffer during the helm session."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-move-to-line-cycle-in-source nil
- "Cycle to the beginning or end of the list after reaching the bottom or top.
-This applies when using `helm-next/previous-line'."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-fuzzy-match-fn 'helm-fuzzy-match
- "The function for fuzzy matching in `helm-source-sync' based sources."
- :group 'helm
- :type 'function)
-
-(defcustom helm-fuzzy-search-fn 'helm-fuzzy-search
- "The function for fuzzy matching in `helm-source-in-buffer' based sources."
- :group 'helm
- :type 'function)
-
-(defcustom helm-fuzzy-sort-fn 'helm-fuzzy-matching-default-sort-fn
- "The sort transformer function used in fuzzy matching.
-When nil, sorting is not done."
- :group 'helm
- :type 'function)
-
-(defcustom helm-fuzzy-matching-highlight-fn 'helm-fuzzy-default-highlight-match
- "The function to highlight fuzzy matches.
-When nil, no highlighting is done."
- :group 'helm
- :type 'function)
-
-(defcustom helm-autoresize-max-height 40
- "Specifies maximum height and defaults to percent of helm window's frame height.
-
-See `fit-window-to-buffer' for more infos."
- :group 'helm
- :type 'integer)
-
-(defcustom helm-autoresize-min-height 10
- "Specifies minimum height and defaults to percent of helm window's frame height.
-
-If nil, `window-min-height' is used.
-See `fit-window-to-buffer' for details."
- :group 'helm
- :type 'integer)
-
-(defcustom helm-input-method-verbose-flag nil
- "The default value for `input-method-verbose-flag' used in helm minibuffer.
-It is nil by default, which does not turn off input method. Helm
-updates and exits without interruption -- necessary for complex methods.
-
-If set to any other value as per `input-method-verbose-flag',
-then use `C-\\' to disable the `current-input-method' to exit or update helm"
- :group 'helm
- :type '(radio :tag "A flag to control extra guidance for input methods in helm."
- (const :tag "Never provide guidance" nil)
- (const :tag "Always provide guidance" t)
- (const :tag "Provide guidance only for complex methods" complex-only)))
-
-(defcustom helm-display-header-line t
- "Display header-line when non nil."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-inherit-input-method t
- "Inherit `current-input-method' from `current-buffer' when non-`nil'.
-The default is to enable this by default and then toggle
-`toggle-input-method'."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-echo-input-in-header-line nil
- "Send current input in header-line."
- :group 'helm
- :type 'boolean)
-
-(defcustom helm-tramp-connection-min-time-diff 5
- "Value of `tramp-connection-min-time-diff' for helm remote processes.
-If set to zero helm remote processes are not delayed.
-Setting this to a value less than 5 or disabling it with a zero value
-is risky, however on emacs versions starting at 24.5 it seems
-it is now possible to disable it.
-Anyway at any time in helm you can suspend your processes while typing
-by hitting \\<helm-map> `\\[helm-toggle-suspend-update]'.
-Only async sources than use a sentinel calling
-`helm-process-deferred-sentinel-hook' are affected by this."
- :type 'integer
- :group 'helm)
-
-(defcustom helm-debug-root-directory nil
- "When non-`nil', saves helm log messages to a file in this directory.
-When `nil' log messages are saved to a buffer instead.
-Log message are saved only when `helm-debug' is non-nil, so setting this
-doesn't enable debugging by itself.
-
-See `helm-log-save-maybe' for more info."
- :type 'string
- :group 'helm)
-
-\f
-;;; Faces
-;;
-;;
-(defgroup helm-faces nil
- "Customize the appearance of helm."
- :prefix "helm-"
- :group 'faces
- :group 'helm)
-
-(defface helm-source-header
- '((((background dark))
- :background "#22083397778B"
- :foreground "white"
- :weight bold :height 1.3 :family "Sans Serif")
- (((background light))
- :background "#abd7f0"
- :foreground "black"
- :weight bold :height 1.3 :family "Sans Serif"))
- "Face for source header in the helm buffer."
- :group 'helm-faces)
-
-(defface helm-visible-mark
- '((((min-colors 88) (background dark))
- (:background "green1" :foreground "black"))
- (((background dark))
- (:background "green" :foreground "black"))
- (((background light)) :background "#d1f5ea")
- (((min-colors 88))
- (:background "green1"))
- (t (:background "green")))
- "Face for visible mark."
- :group 'helm-faces)
-
-(defface helm-header
- '((t (:inherit header-line)))
- "Face for header lines in the helm buffer."
- :group 'helm-faces)
-
-(defface helm-candidate-number
- '((((background dark)) :background "Yellow" :foreground "black")
- (((background light)) :background "#faffb5" :foreground "black"))
- "Face for candidate number in mode-line." :group 'helm-faces)
-
-(defface helm-selection
- '((((background dark)) :background "ForestGreen"
- :distant-foreground "black")
- (((background light)) :background "#b5ffd1"
- :distant-foreground "black"))
- "Face for currently selected item in the helm buffer."
- :group 'helm-faces)
-
-(defface helm-separator
- '((((background dark)) :foreground "red")
- (((background light)) :foreground "#ffbfb5"))
- "Face for multiline source separator."
- :group 'helm-faces)
-
-(defface helm-action
- '((t (:underline t)))
- "Face for action lines in the helm action buffer."
- :group 'helm-faces)
-
-(defface helm-prefarg
- '((((background dark)) :foreground "green")
- (((background light)) :foreground "red"))
- "Face for showing prefix arg in mode-line."
- :group 'helm-faces)
-
-(defface helm-match
- '((((background light)) :foreground "#b00000")
- (((background dark)) :foreground "gold1"))
- "Face used to highlight matches."
- :group 'helm-faces)
-
-(defface helm-header-line-left-margin
- '((t (:foreground "black" :background "yellow")))
- "Face used to highlight helm-header sign in left-margin."
- :group 'helm-faces)
-
-\f
-;;; Variables.
-;;
-;;
-(defvar helm-type-attributes nil
- "It's a list of \(TYPE ATTRIBUTES ...\).
-ATTRIBUTES are the same as attributes for `helm-sources'. TYPE
-connects the value to the appropriate sources. Don't set this
-directly, use `define-helm-type-attribute' instead.
-
-This alist is for specifying common attributes for multiple
-sources. For example, sources which provide files can specify
-common attributes with a `file' type.")
-
-(defvar helm-source-filter nil
- "A list of source names to be displayed.
-Other sources won't appear in the search results.
-If nil, no filtering is done.
-See also `helm-set-source-filter'.")
-
-(defvar helm-selection-overlay nil
- "Overlay used to highlight the currently selected item.")
-
-(defvar helm-async-processes nil
- "List of information about asynchronous processes managed by helm.")
-
-(defvar helm-before-initialize-hook nil
- "Runs before helm initialization.
-This hook runs before init functions in `helm-sources', which is
-before creation of `helm-buffer'. Set local variables for
-`helm-buffer' that need a value from `current-buffer' with
-`helm-set-local-variable'.")
-
-(defvar helm-after-initialize-hook nil
- "Runs after helm initialization.
-This hook runs after `helm-buffer' is created but not from
-`helm-buffer'. The hook needs to specify in which buffer to run.")
-
-(defvar helm-update-hook nil
- "Run after the helm buffer is updated.
-This hook runs at the beginning of buffer. The first candidate is
-selected after running this hook. See also
-`helm-after-update-hook'.")
-
-(defvar helm-after-update-hook nil
- "Runs after updating the helm buffer with the new input pattern.
-This is very similar to `helm-update-hook' except the selection
-is not moved. Hook is useful for selecting a particular object
-instead of the first one.")
-
-(defvar helm-cleanup-hook nil
- "Runs after exiting the minibuffer and before performing an
-action.
-
-This hook runs even if helm exits the minibuffer abnormally (e.g.
-via `helm-keyboard-quit').")
-
-(defvar helm-select-action-hook nil
- "Runs when opening the action buffer.")
-
-(defvar helm-before-action-hook nil
- "Runs before executing action.
-Unlike `helm-cleanup-hook', this hook runs before helm closes the
-minibuffer and also before performing an action.")
-
-(defvar helm-after-action-hook nil
- "Runs after executing action.")
-
-(defvar helm-exit-minibuffer-hook nil
- "Runs just before exiting the minibuffer.
-
-This hook runs when helm exits the minibuffer normally (e.g. via
-candidate selection), but does NOT run if helm exits the
-minibuffer abnormally (e.g. via `helm-keyboard-quit').")
-
-(defvar helm-after-persistent-action-hook nil
- "Runs after executing persistent action.")
-
-(defvar helm-move-selection-before-hook nil
- "Runs before moving selection in `helm-buffer'.")
-
-(defvar helm-move-selection-after-hook nil
- "Runs after moving selection in `helm-buffer'.")
-
-(defvar helm-after-preselection-hook nil
- "Runs after pre-selection in `helm-buffer'.")
-
-(defvar helm-window-configuration-hook nil
- "Runs when switching to and from the action buffer.")
-
-(defconst helm-restored-variables
- '(helm-candidate-number-limit
- helm-source-filter
- helm-map
- helm-sources)
- "Variables restored after an `helm' invocation.")
-
-(defvar helm-execute-action-at-once-if-one nil
- "With the only remaining candidate, executes the default action and then exits.
-This variable accepts a function with no args and returns a boolean
-value.")
-
-(defvar helm-quit-if-no-candidate nil
- "When non-`nil', quits if there are no candidates.
-This variable accepts a function.")
-
-(defvar helm-debug-variables nil
- "A list of helm variables that `helm-debug-output' displays.
-If `nil', `helm-debug-output' includes only variables with
-`helm-' prefixes.")
-
-(defvar helm-debug-buffer "*Debug Helm Log*")
-
-(defvar helm-debug nil
- "If non-`nil', write log message to `helm-debug-buffer'.
-Default is `nil', which disables writing log messages because the
-size of `helm-debug-buffer' grows quickly.")
-
-(defvar helm-compile-source-functions
- '(helm-compile-source--type
- helm-compile-source--dummy
- helm-compile-source--candidates-in-buffer)
- "Functions to compile elements of `helm-sources' (plug-in).")
-
-(defvar helm-mode-line-string "\
-\\<helm-map>\
-\\[helm-help]:Help \
-\\[helm-select-action]:Act \
-\\[helm-maybe-exit-minibuffer]/\
-f1/f2/f-n:NthAct \
-\\[helm-toggle-suspend-update]:Tog.suspend"
- "Help string displayed by helm in the mode-line.
-It is either a string or a list of two string arguments where the
-first string is the name and the second string is displayed in
-the mode-line. When `nil', uses default `mode-line-format'.")
-
-(defvar helm-minibuffer-set-up-hook nil
- "Hook that runs at minibuffer initialization.
-A hook useful for modifying minibuffer settings in helm.
-
-An example that hides the minibuffer when using
-`helm-echo-input-in-header-line':
-
- (add-hook 'helm-minibuffer-set-up-hook #'helm-hide-minibuffer-maybe)
-
-Note that we check `helm-echo-input-in-header-line' value
-from `helm-buffer' which allow detecting possible local
-value of this var.")
-
-(defvar helm-help-message
- "* Helm Generic Help
-
-\\<helm-map>`helm' is an Emacs framework for incremental
-completions and narrowing selections.
-
-Helm narrows the list of candidates as the pattern is typed and
-updates the list in a live feedback. Helm accepts multiple
-patterns (entered with a space between patterns). Helm uses
-familiar Emacs navigation keys to move up and down the list.
-`RET' selects the candidate from the list.
-
-** Helm Help
-
-C-h m\t\tShows this generic Helm help.
-
-** Helm's Basic Operations and Default Key Bindings
-
-| Key | Alternative Keys | Command |
-|---------+------------------+-----------------------------------------------------------|
-| C-p | Up | Previous Line |
-| C-n | Down | Next Line |
-| M-v | PageUp | Previous Page |
-| C-v | PageDown | Next Page |
-| Enter | | Execute first (default) action / Select |
-| M-< | | First Line |
-| M-> | | Last Line |
-| C-M-S-v | M-PageUp, C-M-y | Previous Page (other-window) |
-| C-M-v | M-PageDown | Next Page (other-window) |
-| Tab | C-i | Show action list |
-| Left | | Previous Source |
-| Right | C-o | Next Source |
-| C-k | | Delete pattern (with prefix arg delete from point to end) |
-| C-j | C-z | Persistent Action (Execute and keep helm session) |
-
-** Shortcuts For nth Action
-
-f1-12: Execute nth Action where n is 1 to 12.
-
-** Shortcuts for executing Default Action on the nth candidate
-
-C-x <n> => executes default action on number <n> candidate before currently selected candidate.
-
-C-c <n> => executes default action on number <n> candidate after current selected candidate.
-
-n is limited only to 1 through 9. For larger jumps use other
-navigation keys. Also note that Helm candidates list by default
-do not display line numbers. Line numbers can be enabled with the
-linum-relative package.
-
-** Visible Marks
-
-Visible marks are displayed next to selected candidates, if any.
-Some Helm actions operate on marked candidates.
-
-** Frequently Used Commands
-
-\\[helm-toggle-resplit-and-swap-windows]\t\tToggle vertical/horizontal split on first hit and swap helm window on second hit.
-\\[helm-quit-and-find-file]\t\tDrop into `helm-find-files'.
-\\[helm-kill-selection-and-quit]\t\tKill display value of candidate and quit (with prefix arg, kill the real value).
-\\[helm-yank-selection]\t\tYank current selection into pattern.
-\\[helm-follow-mode]\t\tToggle automatic execution of persistent action.
-\\[helm-follow-action-forward]\tRun persistent action and then select next line.
-\\[helm-follow-action-backward]\t\tRun persistent action and then select previous line.
-\\[helm-refresh]\t\tRecalculate and redisplay candidates.
-\\[helm-toggle-suspend-update]\t\tSuspend/reenable updates to candidates list.
-
-** Global Commands
-
-\\<global-map>\\[helm-resume] revives the last `helm' session.
-Very useful for resuming previous Helm. Binding a key to this
-command will greatly improve `helm' interactivity especially
-after an accidental exit.
-
-** Debugging helm
-
-helm have a special variable called `helm-debug', setting it to non-nil
-will allow helm logging in a special outline-mode buffer.
-Helm is resetting the variable to nil at end of each session.
-
-A convenient command is bound to \\<helm-map>\\[helm-enable-or-switch-to-debug]
-and allow turning debugging to this session only.
-To avoid accumulating log while you are typing your pattern, you can use
-\\<helm-map>\\[helm-toggle-suspend-update] to turn off updating, then when you
-are ready turn it on again to start updating.
-
-Once you exit your helm session you can access the debug buffer with `helm-debug-open-last-log'.
-It is possible to save logs to dated files when `helm-debug-root-directory'
-is set to a valid directory.
-
-NOTE: Be aware that helm log buffers grow really fast, so use `helm-debug' only when needed.
-
-** Helm Map
-\\{helm-map}"
- "Message string containing detailed help for `helm'.
-It also accepts function or variable symbol.")
-
-(defvar helm-autoresize-mode) ;; Undefined in `helm-default-display-buffer'.
-
-\f
-;;; Internal Variables
-;;
-;;
-(defvar helm-current-prefix-arg nil
- "Record `current-prefix-arg' when exiting minibuffer.")
-(defvar helm-saved-action nil
- "Saved value of the currently selected action by key.")
-(defvar helm-saved-current-source nil
- "Value of the current source when the action list is shown.")
-(defvar helm-compiled-sources nil
- "Compiled version of `helm-sources'.")
-(defvar helm-in-persistent-action nil
- "Flag whether in persistent-action or not.")
-(defvar helm-last-buffer nil
- "`helm-buffer' of previously `helm' session.")
-(defvar helm-saved-selection nil
- "Value of the currently selected object when the action list is shown.")
-(defvar helm-sources nil
- "[INTERNAL] Value of current sources in use, a list.")
-(defvar helm-buffer-file-name nil
- "Variable `buffer-file-name' when `helm' is invoked.")
-(defvar helm-candidate-cache (make-hash-table :test 'equal)
- "Holds the available candidate within a single helm invocation.")
-(defvar helm-input ""
- "The input typed in the candidates panel.")
-(defvar helm-input-local nil
- "Internal, store locally `helm-pattern' value for later use in `helm-resume'.")
-(defvar helm-source-name nil)
-(defvar helm-current-source nil)
-(defvar helm-candidate-buffer-alist nil)
-(defvar helm-tick-hash (make-hash-table :test 'equal))
-(defvar helm-issued-errors nil)
-(defvar helm--last-log-file nil
- "The name of the log file of the last helm session.")
-(defvar helm-follow-mode nil)
-(defvar helm--local-variables nil)
-(defvar helm-split-window-state nil)
-(defvar helm--window-side-state nil)
-(defvar helm-selection-point nil)
-(defvar helm-alive-p nil)
-(defvar helm-visible-mark-overlays nil)
-(defvar helm-update-blacklist-regexps '("^" "^ *" "$" "!" " " "\\b"
- "\\<" "\\>" "\\_<" "\\_>" ".*"))
-(defvar helm-force-updating-p nil)
-(defvar helm-exit-status 0
- "Flag to inform if helm did exit or quit.
-0 means helm did exit when executing an action.
-1 means helm did quit with \\[keyboard-quit]
-Knowing this exit-status could help restore a window config when helm aborts
-in some special circumstances.
-See `helm-exit-minibuffer' and `helm-keyboard-quit'.")
-(defvar helm-minibuffer-confirm-state nil)
-(defvar helm-quit nil)
-(defvar helm-attributes nil "List of all `helm' attributes.")
-(defvar helm-buffers nil
- "Helm buffers listed in order of most recently used.")
-(defvar helm-current-position nil
- "Cons of \(point . window-start\) when `helm' is invoked.
-`helm-current-buffer' uses this to restore position after
-`helm-keyboard-quit'")
-(defvar helm-last-frame-or-window-configuration nil
- "Used to store window or frame configuration at helm start.")
-(defvar helm-onewindow-p nil)
-(defvar helm-types nil)
-(defvar helm--mode-line-string-real nil) ; The string to display in mode-line.
-(defvar helm-persistent-action-display-window nil)
-(defvar helm-marked-candidates nil
- "Marked candadates. List of \(source . real\) pair.")
-(defvar helm--mode-line-display-prefarg nil)
-(defvar helm--temp-follow-flag nil
- "[INTERNAL] A simple flag to notify persistent action we are following.")
-(defvar helm--reading-passwd-or-string nil)
-(defvar helm--in-update nil)
-(defvar helm--in-fuzzy nil)
-(defvar helm--maybe-use-default-as-input nil
- "Flag to notify the use of use-default-as-input.
-Use only in let-bindings.
-Use :default arg of `helm' as input to update display.
-Note that if also :input is specified as `helm' arg, it will take
-precedence on :default.")
-(defvar helm--temp-hooks nil
- "Store temporary hooks added by `with-helm-temp-hook'.")
-(defvar helm-truncate-lines nil
- "[Internal] Don't set this globally, it is used as a local var.")
-(defvar helm--prompt nil)
-(defvar helm--file-completion-sources
- '("Find Files" "Read File Name" "Read File Name History")
- "Sources that use the *find-files mechanism can be added here.
-Sources generated by `helm-mode' don't need to be added here
-because they are automatically added.
-
-You should not modify this yourself unless you know what you are doing.")
-;; Same as `ffap-url-regexp' but keep it here to ensure `ffap-url-regexp' is not nil.
-(defvar helm--url-regexp "\\(news\\(post\\)?:\\|mailto:\\|file:\\|\\(ftp\\|https?\\|telnet\\|gopher\\|www\\|wais\\)://\\)")
-\f
-;; Utility: logging
-(defun helm-log (format-string &rest args)
- "Log message `helm-debug' is non-`nil'.
-Messages are written to the `helm-debug-buffer' buffer.
-
-Argument FORMAT-STRING is a string to use with `format'.
-Use optional arguments ARGS like in `format'."
- (when helm-debug
- (with-current-buffer (get-buffer-create helm-debug-buffer)
- (outline-mode)
- (buffer-disable-undo)
- (set (make-local-variable 'inhibit-read-only) t)
- (goto-char (point-max))
- (insert (let ((tm (current-time)))
- (format (concat (if (string-match "Start session" format-string)
- "* " "** ")
- "%s.%06d (%s)\n %s\n")
- (format-time-string "%H:%M:%S" tm)
- (nth 2 tm)
- (helm-log-get-current-function)
- (apply #'format (cons format-string args))))))))
-
-(defun helm-log-run-hook (hook)
- "Run HOOK like `run-hooks' but write these actions to helm log buffer."
- (helm-log "Executing %s with value = %S" hook (symbol-value hook))
- (helm-log "Executing %s with global value = %S" hook (default-value hook))
- (run-hooks hook)
- (helm-log "executed %s" hook))
-
-(defun helm-log-get-current-function ()
- "Get name of function that is calling `helm-log'.
-The original idea is from `tramp-debug-message'."
- (cl-loop with exclude-func-re = "^helm-\\(?:interpret\\|log\\|.*funcall\\)"
- for btn from 1 to 40
- for btf = (cl-second (backtrace-frame btn))
- for fn = (if (symbolp btf) (symbol-name btf) "")
- if (and (string-match "^helm" fn)
- (not (string-match exclude-func-re fn)))
- return fn))
-
-(defun helm-log-error (&rest args)
- "Accumulate error messages into `helm-issued-errors'.
-ARGS are args given to `format'.
-e.g (helm-log-error \"Error %s: %s\" (car err) (cdr err))."
- (apply 'helm-log (concat "ERROR: " (car args)) (cdr args))
- (let ((msg (apply 'format args)))
- (unless (member msg helm-issued-errors)
- (add-to-list 'helm-issued-errors msg))))
-
-(defun helm-log-save-maybe ()
- "Save log buffer if `helm-debug-root-directory' is set to a valid directory.
-Messages are logged to a file named with todays date and time in this directory."
- (when (and (stringp helm-debug-root-directory)
- (file-directory-p helm-debug-root-directory)
- helm-debug)
- (let ((logdir (expand-file-name (concat "helm-debug-"
- (format-time-string "%Y%m%d"))
- helm-debug-root-directory)))
- (make-directory logdir t)
- (with-current-buffer (get-buffer-create helm-debug-buffer)
- (write-region (point-min) (point-max)
- (setq helm--last-log-file
- (expand-file-name
- (format-time-string "%Y%m%d-%H%M%S")
- logdir))
- nil 'silent)
- (kill-buffer))))
- (setq helm-debug nil))
-
-;;;###autoload
-(defun helm-debug-open-last-log ()
- "Open helm log file or buffer of last helm session."
- (interactive)
- (if helm--last-log-file
- (progn
- (find-file helm--last-log-file)
- (outline-mode) (view-mode 1) (visual-line-mode 1))
- (switch-to-buffer helm-debug-buffer)
- (view-mode 1) (visual-line-mode 1)))
-
-(defun helm-print-error-messages ()
- "Print error messages in `helm-issued-errors'."
- (and helm-issued-errors
- (message "Helm issued errors: %s"
- (mapconcat 'identity (reverse helm-issued-errors) "\n"))))
-
-\f
-;; Programming Tools
-
-(defun helm-this-command ()
- "Returns the actual command in action.
-Like `this-command' but return the real command,
-and not `exit-minibuffer' or other unwanted functions."
- (cl-loop with bl = '(helm-maybe-exit-minibuffer
- helm-confirm-and-exit-minibuffer
- helm-exit-minibuffer
- exit-minibuffer)
- for count from 1 to 50
- for btf = (backtrace-frame count)
- for fn = (cl-second btf)
- if (and
- ;; In some case we may have in the way an
- ;; advice compiled resulting in byte-code,
- ;; ignore it (Issue #691).
- (symbolp fn)
- (commandp fn)
- (not (memq fn bl)))
- return fn
- else
- if (and (eq fn 'call-interactively)
- (> (length btf) 2))
- return (cadr (cdr btf))))
-
-\f
-;; Test tools
-(defmacro with-helm-time-after-update (&rest body)
- (helm-with-gensyms (start-time time-elapsed)
- `(let ((,start-time (float-time)) ,time-elapsed)
- (add-hook 'helm-after-update-hook
- (lambda ()
- (setq ,time-elapsed (- (float-time) ,start-time))
- (keyboard-quit)))
- (unwind-protect ,@body
- (remove-hook 'helm-after-update-hook
- (lambda ()
- (setq ,time-elapsed (- (float-time) ,start-time))
- (keyboard-quit))))
- ,time-elapsed)))
-
-\f
-;; Helm API
-
-(defmacro with-helm-restore-variables (&rest body)
- "Restore `helm-restored-variables' after executing BODY."
- (declare (indent 0) (debug t))
- (helm-with-gensyms (orig-vars)
- `(let ((,orig-vars (mapcar (lambda (v)
- (cons v (symbol-value v)))
- helm-restored-variables)))
- (unwind-protect (progn ,@body)
- (cl-loop for (var . value) in ,orig-vars
- do (set var value))
- (helm-log "restore variables")))))
-
-(defmacro with-helm-default-directory (directory &rest body)
- (declare (indent 2) (debug t))
- `(let ((default-directory (or (and ,directory
- (file-name-as-directory ,directory))
- default-directory)))
- ,@body))
-
-(defun helm-default-directory ()
- "Return the local value of `default-directory' in `helm-buffer'."
- (buffer-local-value 'default-directory (get-buffer helm-buffer)))
-
-(defmacro with-helm-temp-hook (hook &rest body)
- "Execute temporarily BODY as a function for HOOK."
- (declare (indent 1) (debug t))
- (helm-with-gensyms (helm--hook)
- `(progn
- (defun ,helm--hook ()
- (unwind-protect
- (progn ,@body)
- (remove-hook ,hook (quote ,helm--hook))
- (fmakunbound (quote ,helm--hook))))
- (push (cons ',helm--hook ,hook) helm--temp-hooks)
- (add-hook ,hook (quote ,helm--hook)))))
-
-(defmacro with-helm-after-update-hook (&rest body)
- "Execute BODY at end of `helm-update'."
- (declare (indent 0) (debug t))
- `(with-helm-temp-hook 'helm-after-update-hook ,@body))
-
-(defmacro with-helm-alive-p (&rest body)
- "Return error when BODY run outside helm context."
- (declare (indent 0) (debug t))
- `(progn
- (if helm-alive-p
- (progn ,@body)
- (error "Running helm command outside of context"))))
-
-(defun helm-attr (attribute-name &optional source compute)
- "Get the value of ATTRIBUTE-NAME of SRC.
-If SRC is omitted, use current source.
-If COMPUTE is non-`nil' compute value of ATTRIBUTE-NAME
-with `helm-interpret-value'. COMPUTE can have also 'ignorefn as
-value, in this case `helm-interpret-value' will return a function
-as value unchanged, but will eval a symbol which is bound
-(i.e a variable)."
- (let ((src (or source (helm-get-current-source))))
- (helm-aif (or (assq attribute-name src)
- (helm-get-attribute-from-source-type attribute-name src))
- (if compute
- (helm-interpret-value (cdr it) src compute)
- (cdr it)))))
-
-(cl-defun helm-attr-defined (attribute-name
- &optional (src (helm-get-current-source)))
- "Return non-`nil' if ATTRIBUTE-NAME of SRC is defined.
-if SRC is omitted, use current source."
- (and (helm-attr attribute-name src) t))
-
-(cl-defun helm-attrset (attribute-name value
- &optional
- (src (helm-get-current-source))
- alter-type)
- "Set the value of ATTRIBUTE-NAME of source SRC to VALUE.
-If ATTRIBUTE-NAME doesn't exists in source it is created with value VALUE.
-If ALTER-TYPE is non-`nil' alter the value of ATTRIBUTE-NAME in `helm-attributes'
-if it exists.
-If SRC is omitted, use current source.
-If operation succeed, return value, otherwise nil."
- (let ((from-type (helm-get-attribute-from-source-type attribute-name src))
- done)
- (helm-aif (or (assq attribute-name src)
- (and alter-type from-type))
- (prog1 (setcdr it value) (setq done t))
- (unless from-type
- (setcdr src (cons (cons attribute-name value) (cdr src)))
- (setq done t)))
- (and done value)))
-
-(defun helm-get-attribute-from-source-type (attribute source)
- "Get ATTRIBUTE from type attribute of SOURCE."
- (when (assq 'type source)
- (assq attribute
- (assq (cdr (assq 'type source))
- helm-type-attributes))))
-
-(defun helm-get-attribute-from-type (attribute type)
- "Get ATTRIBUTE from TYPE.
-arg TYPE is an existing type defined in `helm-type-attributes'."
- (assq attribute (assq type helm-type-attributes)))
-
-(defun helm-get-actions-from-type (source)
- "Get actions list from type attribute of SOURCE."
- (when (assq 'type source)
- (helm-get-attribute-from-source-type 'action source)))
-
-(defun helm-inherit-attribute-from-source (attribute source)
- "Get the ATTRIBUTE of SOURCE."
- (helm-aif (assq attribute source)
- it
- (helm-get-attribute-from-source-type attribute source)))
-
-(defun helm-append-at-nth (seq elm index)
- "Append ELM at INDEX in SEQ."
- (let ((len (length seq)))
- (cond ((> index len) (setq index len))
- ((< index 0) (setq index 0)))
- (if (zerop index)
- (append elm seq)
- (cl-loop for i in seq
- for count from 1 collect i
- when (= count index)
- if (listp elm) append elm
- else collect elm))))
-
-(defun helm-add-action-to-source (name fn source &optional index)
- "Add new action NAME linked to function FN to SOURCE.
-Function FN should be a valid function that takes one arg i.e candidate,
-argument NAME is a string that will appear in action menu
-and SOURCE should be an existing helm source already loaded.
-If INDEX is specified, action is added to the action list at INDEX,
-otherwise added at end.
-This allows users to add specific actions to an existing source
-without modifying source code."
- (let ((actions (helm-attr 'action source 'ignorefn))
- (new-action (list (cons name fn))))
- (when (functionp actions)
- (setq actions (list (cons "Default action" actions))))
- (helm-attrset 'action
- (if index
- (helm-append-at-nth actions new-action index)
- (append actions new-action))
- source)))
-
-(defun helm-delete-action-from-source (action-or-name source)
- "Delete ACTION-OR-NAME from SOURCE.
-ACTION-OR-NAME can either be the name of action or the symbol function
-associated to name."
- (let* ((actions (helm-attr 'action source 'ignorefn))
- (del-action (if (symbolp action-or-name)
- (rassoc action-or-name actions)
- (assoc action-or-name actions))))
- (helm-attrset 'action (delete del-action actions) source)))
-
-(cl-defun helm-add-action-to-source-if (name fn source predicate
- &optional (index 4) test-only)
- "Add new action NAME linked to function FN to SOURCE.
-Action NAME will be available when the current candidate matches PREDICATE.
-This function adds an entry in the `action-transformer' attribute
-of SOURCE (or creates one if not found).
-Function PREDICATE must take one candidate as arg.
-Function FN should be a valid function that takes one arg i.e. candidate,
-argument NAME is a string that will appear in action menu
-and SOURCE should be an existing helm source already loaded.
-If INDEX is specified, action is added in action list at INDEX.
-Value of INDEX should be always >=1, default to 4.
-This allow user to add a specific `action-transformer'
-to an existing source without modifying source code.
-E.g
-Add the action \"Byte compile file async\" linked to
-function 'async-byte-compile-file to source `helm-source-find-files'
-only when predicate helm-ff-candidates-lisp-p return non-`nil':
-
-\(helm-add-action-to-source-if \"Byte compile file async\"
- 'async-byte-compile-file
- helm-source-find-files
- 'helm-ff-candidates-lisp-p\)."
- (let* ((actions (helm-attr 'action source 'ignorefn))
- (action-transformers (helm-attr 'action-transformer source))
- (new-action (list (cons name fn)))
- (transformer `(lambda (actions candidate)
- (cond ((funcall (quote ,predicate) candidate)
- (helm-append-at-nth
- actions (quote ,new-action) ,index))
- (t actions)))))
- (when (functionp actions)
- (helm-attrset 'action (list (cons "Default action" actions)) source))
- (when (or (symbolp action-transformers) (functionp action-transformers))
- (setq action-transformers (list action-transformers)))
- (if test-only ; debug
- (delq nil (append (list transformer) action-transformers))
- (helm-attrset 'action-transformer
- (helm-fast-remove-dups
- (delq nil (append (list transformer) action-transformers))
- :test 'equal)
- source))))
-
-(defun helm-set-source-filter (sources)
- "Set the value of `helm-source-filter' to SOURCES and update.
-
-This function sets a filter for helm sources and it may be
-called while helm is running. It can be used to toggle
-displaying of sources dynamically. For example, additional keys
-can be bound into `helm-map' to display only the file-related
-results if there are too many matches from other sources and
-you're after files only:
-
-Shift+F shows only file results from some sources:
-
-\(define-key helm-map \"F\" 'helm-my-show-files-only)
-
-\(defun helm-my-show-files-only ()
- (interactive)
- (helm-set-source-filter '(\"File Name History\"
- \"Files from Current Directory\")))
-
-Shift+A shows all results:
-
-\(define-key helm-map \"A\" 'helm-my-show-all)
-
-\(defun helm-my-show-all ()
- (interactive)
- (helm-set-source-filter nil))
-
-The -my- part is added to avoid collisions with
-existing Helm function names."
- (let ((cur-disp-sel (with-current-buffer helm-buffer
- (helm-get-selection nil t))))
- (setq helm-source-filter (helm--normalize-filter-sources sources))
- (helm-log "helm-source-filter = %S" helm-source-filter)
- ;; Use force-update to run init/update functions.
- (helm-force-update (and (stringp cur-disp-sel)
- (regexp-quote cur-disp-sel)))))
-
-(defun helm--normalize-filter-sources (sources)
- (cl-loop for s in sources collect
- (cl-typecase s
- (symbol (assoc-default 'name (symbol-value s)))
- (list (assoc-default 'name s))
- (string s))))
-
-(defun helm-set-sources (sources &optional no-init no-update)
- "Set SOURCES during `helm' invocation.
-If NO-INIT is non-`nil', skip executing init functions of SOURCES.
-If NO-UPDATE is non-`nil', skip executing `helm-update'."
- (with-current-buffer helm-buffer
- (setq helm-compiled-sources nil
- helm-sources sources)
- (helm-log "helm-compiled-sources = %S" helm-compiled-sources)
- (helm-log "helm-sources = %S" helm-sources))
- (unless no-init (helm-funcall-foreach 'init))
- (unless no-update (helm-update)))
-
-(defun helm-get-sources ()
- "Return compiled `helm-sources', which is memoized.
-
-Attributes:
-
-- type
- `helm-type-attributes' are merged in.
-- candidates-buffer
- candidates, volatile and match attribute are created."
- (cond
- ;; action
- ((helm-action-window)
- helm-sources)
- ;; memoized
- (helm-compiled-sources)
- ;; first time
- (t
- (prog1
- (setq helm-compiled-sources
- (helm-compile-sources
- helm-sources helm-compile-source-functions))
- (helm-log "helm-compiled-sources = %S" helm-compiled-sources)))))
-
-(defun helm-get-selection (&optional buffer force-display-part)
- "Return the currently selected item or nil.
-if BUFFER is nil or unspecified, use helm-buffer as default value.
-If FORCE-DISPLAY-PART is non-`nil', return the display string.
-If FORCE-DISPLAY-PART value is 'withprop the display string is returned
-with its properties."
- (setq buffer (or buffer helm-buffer))
- (unless (helm-empty-buffer-p buffer)
- (with-current-buffer buffer
- (let* ((disp-fn (if (eq force-display-part 'withprop)
- 'buffer-substring
- 'buffer-substring-no-properties))
- (selection
- (or (and (not force-display-part)
- (get-text-property (overlay-start
- helm-selection-overlay)
- 'helm-realvalue))
- ;; It is needed to return properties of DISP in some case,
- ;; e.g for `helm-confirm-and-exit-minibuffer',
- ;; so use `buffer-substring' here when 'withprop is specified.
- (let ((disp (funcall
- disp-fn
- (overlay-start helm-selection-overlay)
- (1- (overlay-end helm-selection-overlay))))
- (source (helm-get-current-source)))
- (helm-aif (and (not force-display-part)
- (assoc-default 'display-to-real source))
- (helm-funcall-with-source source it disp)
- disp)))))
- (unless (equal selection "")
- (helm-log "selection = %S" selection)
- selection)))))
-
-(defun helm-get-actions-from-current-source ()
- "Return the associated action for the selected candidate.
-It is a function symbol \(sole action\) or list
-of \(action-display . function\)."
- (unless (helm-empty-buffer-p (helm-buffer-get))
- (helm-aif (helm-attr 'action-transformer)
- (helm-funcall-with-source
- (helm-get-current-source) it
- (helm-attr 'action nil 'ignorefn)
- ;; Check if the first given transformer
- ;; returns the same set of actions for each
- ;; candidate in marked candidates.
- ;; If so use the car of marked to determine
- ;; the set of actions, otherwise use the selection.
- (if (cl-loop with marked = (helm-marked-candidates)
- with act = (car (helm-mklist it))
- with acts = (funcall act nil (car marked))
- for c in marked
- always (equal (funcall act nil c) acts))
- (car (helm-marked-candidates))
- (helm-get-selection)))
- (helm-attr 'action nil 'ignorefn))))
-
-(defun helm-get-current-source ()
- "Return the source for the current selection.
-Allow also checking if helm-buffer contain candidates."
- (or helm-current-source
- (with-helm-buffer
- ;; Return nil when no--candidates.
- (cl-block exit
- ;; This goto-char shouldn't be necessary, but point is moved to
- ;; point-min somewhere else which shouldn't happen.
- (goto-char (overlay-start helm-selection-overlay))
- (let* ((header-pos (or (helm-get-previous-header-pos)
- (helm-get-next-header-pos)))
- (source-name
- (save-excursion
- (unless header-pos
- (cl-return-from exit nil))
- (goto-char header-pos)
- (helm-current-line-contents))))
- (cl-loop for source in (helm-get-sources) thereis
- (and (equal (assoc-default 'name source) source-name)
- source)))))))
-
-(defun helm-buffer-is-modified (buffer)
- "Return non-`nil' when BUFFER is modified since `helm' was invoked."
- (let* ((b (get-buffer buffer))
- (key (concat (buffer-name b) "/" (helm-attr 'name)))
- (source-tick (or (gethash key helm-tick-hash) 0))
- (buffer-tick (buffer-chars-modified-tick b))
- (modifiedp (/= source-tick buffer-tick)))
- (puthash key buffer-tick helm-tick-hash)
- (helm-log "buffer = %S" buffer)
- (helm-log "modifiedp = %S" modifiedp)
- modifiedp))
-
-(defun helm-current-buffer-is-modified ()
- "Check if `helm-current-buffer' is modified since `helm' was invoked."
- (helm-buffer-is-modified helm-current-buffer))
-
-(defun helm-run-after-exit (function &rest args)
- "Execute FUNCTION with ARGS after exiting `helm'.
-The action is to call FUNCTION with arguments ARGS.
-Unlike `helm-exit-and-execute-action', this can be used
-to call non--actions functions with any ARGS or no ARGS at all.
-
-Use this on commands invoked from key-bindings, but not
-on action functions invoked as action from the action menu,
-i.e. functions called with RET."
- (helm-kill-async-processes)
- (helm-log "function = %S" function)
- (helm-log "args = %S" args)
- (helm-exit-and-execute-action
- (lambda (_candidate)
- (apply function args))))
-
-(defun helm-exit-and-execute-action (action)
- "Exit current helm session and execute ACTION.
-Argument ACTION is a function called with one arg (candidate)
-and part of the actions of current source.
-
-Use this on commands invoked from key-bindings, but not
-on action functions invoked as action from the action menu,
-i.e functions called with RET."
- (setq helm-saved-action action)
- (setq helm-saved-selection (helm-get-selection))
- (helm-exit-minibuffer))
-
-(defalias 'helm-run-after-quit 'helm-run-after-exit)
-(make-obsolete 'helm-run-after-quit 'helm-run-after-exit "1.7.7")
-(defalias 'helm-quit-and-execute-action 'helm-exit-and-execute-action)
-(make-obsolete 'helm-quit-and-execute-action 'helm-exit-and-execute-action "1.7.7")
-
-(defun helm-interpret-value (value &optional source compute)
- "Interpret VALUE as variable, function or literal and return it.
-If VALUE is a function, call it with no arguments and return the value
-unless COMPUTE value is 'ignorefn.
-If SOURCE compute VALUE for this source.
-If VALUE is a variable, return the value.
-If VALUE is a symbol, but it is not a function or a variable, cause an error.
-Otherwise, return VALUE itself."
- (cond ((and source (functionp value) (not (eq compute 'ignorefn)))
- (helm-funcall-with-source source value))
- ((and (functionp value) (not (eq compute 'ignorefn)))
- (funcall value))
- ((and (symbolp value) (boundp value))
- (symbol-value value))
- ((and (symbolp value) (not (functionp value)))
- (error
- "helm-interpret-value: Symbol must be a function or a variable"))
- (t
- value)))
-
-(defun helm-set-local-variable (&rest args)
- "Bind each pair in ARGS locally to `helm-buffer'.
-
-Use this to set local vars before calling helm.
-
-When used from an init or update function
-(i.e when `helm-force-update' is running) the variables are set
-using `make-local-variable' within the `helm-buffer'.
-
-Usage: helm-set-local-variable ([VAR VALUE]...)
-Just like `setq' except that the vars are not set sequentially.
-IOW Don't use VALUE of previous VAR to set the VALUE of next VAR.
-
-\(fn VAR VALUE ...)"
- (if helm-force-updating-p
- (with-helm-buffer
- (cl-loop for i on args by #'cddr
- do (set (make-local-variable (car i)) (cadr i))))
- (setq helm--local-variables
- (append (cl-loop for i on args by #'cddr
- collect (cons (car i) (cadr i)))
- helm--local-variables))))
-
-\f
-;; Core: API helper
-(cl-defun helm-empty-buffer-p (&optional (buffer helm-buffer))
- "Check if BUFFER have candidates.
-Default value for BUFFER is `helm-buffer'."
- (zerop (buffer-size (and buffer (get-buffer buffer)))))
-
-(defun helm-empty-source-p ()
- "Check if current source contains candidates.
-This could happen when for example the last element of a source
-was deleted and the candidates list not updated."
- (with-helm-window
- (or (helm-empty-buffer-p)
- (and (helm-end-of-source-p)
- (eq (point-at-bol) (point-at-eol))
- (or
- (save-excursion
- (forward-line -1)
- (helm-pos-header-line-p))
- (bobp))))))
-
-\f
-;; Core: tools
-;;
-(defun helm-funcall-with-source (source functions &rest args)
- "Call from SOURCE FUNCTIONS list or single function FUNCTIONS with ARGS.
-FUNCTIONS is either a symbol or a list of functions.
-Return the result of last function call."
- (let ((helm-source-name (assoc-default 'name source))
- (helm-current-source source)
- (funs (if (functionp functions) (list functions) functions)))
- (helm-log "helm-source-name = %S" helm-source-name)
- (helm-log "functions = %S" functions)
- (helm-log "args = %S" args)
- (cl-loop with result
- for fn in funs
- do (setq result (apply fn args))
- when (and args (cdr funs))
- ;; In filter functions, ARGS is a list of one or two elements where
- ;; the first element is the list of candidates and the second
- ;; a list containing the source.
- ;; When more than one fn, set the candidates list to what returns
- ;; this fn to compute the modified candidates with the next fn
- ;; and so on.
- do (setcar args result)
- finally return result)))
-
-(defun helm-funcall-foreach (sym &optional sources)
- "Call the associated function(s) to SYM for each source if any."
- (let ((sources (or sources (helm-get-sources))))
- (cl-dolist (source sources)
- (helm-aif (assoc-default sym source)
- (helm-funcall-with-source source it)))))
-
-(defun helm-normalize-sources (sources)
- "If SOURCES is only one source, make a list of one element."
- (cond ((or (and sources (symbolp sources))
- (and (listp sources) (assq 'name sources)))
- (list sources))
- (sources)
- (t helm-sources)))
-
-(defun helm-get-candidate-number (&optional in-current-source)
- "Return candidates number in `helm-buffer'.
-If IN-CURRENT-SOURCE is provided return number of candidates of current source
-only."
- (with-helm-buffer
- (if (or (helm-empty-buffer-p)
- (helm-empty-source-p))
- 0
- (save-excursion
- (if in-current-source
- (goto-char (helm-get-previous-header-pos))
- (goto-char (point-min)))
- (forward-line 1)
- (if (helm-pos-multiline-p)
- (cl-loop with count-multi = 1
- while (and (not (if in-current-source
- (save-excursion
- (forward-line 2)
- (or (helm-pos-header-line-p) (eobp)))
- (eobp)))
- (search-forward helm-candidate-separator nil t))
- do (cl-incf count-multi)
- finally return count-multi)
- (cl-loop with ln = 0
- while (not (if in-current-source
- (or (helm-pos-header-line-p) (eobp))
- (eobp)))
- ;; Don't count empty lines maybe added by popup (#1370).
- unless (or (eq (point-at-bol) (point-at-eol))
- (helm-pos-header-line-p))
- do (cl-incf ln)
- do (forward-line 1) finally return ln))))))
-
-(defmacro with-helm-quittable (&rest body)
- "If an error occurs in execution of BODY, safely quit helm."
- (declare (indent 0) (debug t))
- `(condition-case _v
- (let (inhibit-quit)
- ,@body)
- (quit (setq quit-flag t)
- (setq helm-quit t)
- (exit-minibuffer)
- (keyboard-quit)
- ;; See comment about this in `with-local-quit'.
- (eval '(ignore nil)))))
-\f
-;; Core: entry point
-;; `:allow-nest' is not in this list because it is treated before.
-(defconst helm-argument-keys
- '(:sources :input :prompt :resume
- :preselect :buffer :keymap :default :history))
-
-;;;###autoload
-(defun helm (&rest plist)
- "Main function to execute helm sources.
-
-Keywords supported:
-:sources :input :prompt :resume :preselect
-:buffer :keymap :default :history :allow-nest
-
-Extra LOCAL-VARS keywords are supported, see below.
-
-PLIST is a list like \(:key1 val1 :key2 val2 ...\) or
-\(&optional sources input prompt resume
- preselect buffer keymap default history\).
-
-Basic keywords are the following:
-
-\:sources
-
-A list of sources used for this session. It also accepts a
-symbol, interpreted as a variable of a helm source
-i.e (a symbol can be passed instead of a list of sources).
-It also accepts an alist representing a helm source, which is
-detected by \(assq 'name ANY-SOURCES\).
-NOTE: In this case the source is embedded in the helm command and
-have no symbol name, so it is not reachable from outside.
-It will be referenced in `helm-sources' as a whole alist.
-
-\:input
-
-Temporary value of `helm-pattern', ie. initial input of minibuffer.
-
-\:prompt
-
-Prompt other than \"pattern: \".
-
-\:resume
-
-If t, Resurrect previously instance of `helm'. Skip the initialization.
-If 'noresume, this instance of `helm' cannot be resumed.
-
-\:preselect
-
-Initially selected candidate. Specified by exact candidate or a regexp.
-
-\:buffer
-
-`helm-buffer' instead of *helm*.
-
-\:keymap
-
-`helm-map' for current `helm' session.
-
-\:default
-
-A default argument that will be inserted in minibuffer \ with
-\\<minibuffer-local-map>\\[next-history-element]. When nil or not
-present `thing-at-point' will be used instead. If
-`helm--maybe-use-default-as-input' is non-`nil' display will be
-updated using :default arg as input unless :input is specified,
-which in this case will take precedence over :default. This is a
-string or a list. If list, car of the list becomes initial
-default input. \\<minibuffer-local-map>\\[next-history-element]
-cycles through the list items.
-
-\:history
-
-Minibuffer input, by default, is pushed to `minibuffer-history'.
-When an argument HISTORY is provided, input is pushed to
-HISTORY. The HISTORY element should be a valid symbol.
-
-\:allow-nest
-
-Allow running this helm command in a running helm session.
-
-Standard arguments are supported. These two are the same:
-
-\(helm :sources sources :input input :prompt prompt :resume resume
- :preselect preselect :buffer buffer :keymap keymap :default default
- :history history\)
-
-and
-
-\(helm sources input prompt resume preselect buffer keymap default history\)
-
-are the same for now. However, the use of non-keyword args is
-deprecated and should not be used.
-
-Other keywords are interpreted as local variables of this helm
-session. The `helm-' prefix can be omitted. For example,
-
-\(helm :sources 'helm-source-buffers-list
- :buffer \"*helm buffers*\" :candidate-number-limit 10\)
-
-starts helm session with `helm-source-buffers' source in
-*helm buffers* buffer and sets variable `helm-candidate-number-limit'
-to 10 as a session local variable.
-
-\(fn &key SOURCES INPUT PROMPT RESUME PRESELECT BUFFER KEYMAP DEFAULT HISTORY ALLOW-NEST OTHER-LOCAL-VARS)"
- (let ((fn (cond ((or (and helm-alive-p (plist-get plist :allow-nest))
- (and helm-alive-p (memq 'allow-nest plist)))
- #'helm-nest)
- ((keywordp (car plist))
- #'helm)
- (t #'helm-internal))))
- (if (and helm-alive-p (eq fn #'helm))
- (if (helm-alive-p)
- ;; A helm session is normally running.
- (error "Error: Trying to run helm within a running helm session")
- ;; A helm session is already running and user jump somewhere else
- ;; without deactivating it.
- (with-helm-buffer
- (prog1
- (message "Aborting an helm session running in background")
- ;; `helm-alive-p' will be reset in unwind-protect forms.
- (helm-keyboard-quit))))
- (if (keywordp (car plist))
- ;; Parse `plist' and move not regular `helm-argument-keys'
- ;; to `helm--local-variables', then calling helm on itself
- ;; with normal arguments (the non--arguments-keys removed)
- ;; will end up in [1].
- (progn
- (setq helm--local-variables
- (append helm--local-variables
- ;; Vars passed by keyword on helm call
- ;; take precedence on same vars
- ;; that may have been passed before helm call.
- (helm-parse-keys plist)))
- (apply fn (mapcar (lambda (key) (plist-get plist key))
- helm-argument-keys)))
- (apply fn plist))))) ; [1] fn == helm-internal.
-
-(defun helm-alive-p ()
- "Check if `helm' is alive.
-An `helm' session is considered alive if `helm-alive-p' returns
-non-`nil', the `helm-buffer' is visible, and cursor is in the
-minibuffer."
- (and helm-alive-p
- (get-buffer-window helm-buffer 'visible)
- (minibuffer-window-active-p (minibuffer-window))
- (minibufferp (current-buffer))))
-
-(defun helm-parse-keys (keys)
- "Parse the KEYS arguments of `helm'.
-Return only those keys not in `helm-argument-keys', prefix them
-with \"helm\", and then convert them to an alist. This allows
-adding arguments that are not part of `helm-argument-keys', but
-are valid helm variables nevertheless. For
-example, :candidate-number-limit is bound to
-`helm-candidate-number-limit' in the source.
-
- (helm-parse-keys '(:sources ((name . \"test\")
- (candidates . (a b c)))
- :buffer \"toto\"
- :candidate-number-limit 4))
- ==> ((helm-candidate-number-limit . 4))."
-
- (cl-loop for (key value) on keys by #'cddr
- for symname = (substring (symbol-name key) 1)
- for sym = (intern (if (string-match "^helm-" symname)
- symname
- (concat "helm-" symname)))
- unless (memq key helm-argument-keys)
- collect (cons sym value)))
-
-;;; Core: entry point helper
-(defun helm-internal (&optional
- any-sources any-input
- any-prompt any-resume
- any-preselect any-buffer
- any-keymap any-default any-history)
- "The internal helm function called by `helm'.
-For ANY-SOURCES ANY-INPUT ANY-PROMPT ANY-RESUME ANY-PRESELECT ANY-BUFFER and
-ANY-KEYMAP ANY-DEFAULT ANY-HISTORY See `helm'."
- ;; Activate the advice for `tramp-read-passwd'.
- (if (fboundp 'advice-add)
- (progn
- (advice-add 'tramp-read-passwd :around #'helm--advice-tramp-read-passwd)
- (advice-add 'ange-ftp-get-passwd :around #'helm--advice-ange-ftp-get-passwd))
- (ad-activate 'tramp-read-passwd)
- (ad-activate 'ange-ftp-get-passwd))
- (helm-log (concat "[Start session] " (make-string 41 ?+)))
- (helm-log "any-prompt = %S" any-prompt)
- (helm-log "any-preselect = %S" any-preselect)
- (helm-log "any-buffer = %S" any-buffer)
- (helm-log "any-keymap = %S" any-keymap)
- (helm-log "any-default = %S" any-default)
- (helm-log "any-history = %S" any-history)
- (setq helm--prompt (or any-prompt "pattern: "))
- (let ((non-essential t)
- mode-line-in-non-selected-windows
- (input-method-verbose-flag helm-input-method-verbose-flag)
- (old--cua cua-mode)
- (helm--maybe-use-default-as-input
- (and (null any-input)
- (or helm--maybe-use-default-as-input ; it is let-bounded so use it.
- (cl-loop for s in (helm-normalize-sources any-sources)
- thereis (memq s helm-sources-using-default-as-input))))))
- ;; cua-mode override local helm bindings.
- ;; disable this stupid thing if enabled.
- (and cua-mode (cua-mode -1))
- (unwind-protect
- (condition-case-unless-debug _v
- (let ( ;; `helm-source-name' is non-`nil'
- ;; when `helm' is invoked by action, reset it.
- helm-source-name
- helm-current-source
- helm-in-persistent-action
- helm-quit
- (helm-buffer (or any-buffer helm-buffer)))
- (with-helm-restore-variables
- (helm-initialize
- any-resume any-input any-default any-sources)
- (helm-display-buffer helm-buffer)
- ;; We are now in helm-buffer.
- (when helm-prevent-escaping-from-minibuffer
- (helm--remap-mouse-mode 1)) ; Disable mouse bindings.
- (add-hook 'post-command-hook 'helm--maybe-update-keymap)
- (add-hook 'post-command-hook 'helm--update-header-line)
- (helm-log "show prompt")
- (unwind-protect
- (helm-read-pattern-maybe
- any-prompt any-input any-preselect
- any-resume any-keymap any-default any-history)
- (helm-cleanup)))
- (prog1
- (unless helm-quit (helm-execute-selection-action))
- (helm-log (concat "[End session] " (make-string 41 ?-)))))
- (quit
- (helm-restore-position-on-quit)
- (helm-log (concat "[End session (quit)] " (make-string 34 ?-)))
- nil))
- (if (fboundp 'advice-add)
- (progn
- (advice-remove 'tramp-read-passwd
- #'helm--advice-tramp-read-passwd)
- (advice-remove 'ange-ftp-get-passwd
- #'helm--advice-ange-ftp-get-passwd))
- (ad-deactivate 'tramp-read-passwd)
- (ad-deactivate 'ange-ftp-get-passwd))
- (helm-log "helm-alive-p = %S" (setq helm-alive-p nil))
- (helm--remap-mouse-mode -1) ; Reenable mouse bindings.
- (setq helm-alive-p nil)
- ;; Reset helm-pattern so that lambda's using it
- ;; before running helm will not start with its old value.
- (setq helm-pattern "")
- (and old--cua (cua-mode 1))
- (helm-log-save-maybe))))
-
-\f
-;;; Helm resume
-;;
-;;
-(defun helm-resume (arg)
- "Resume a previous `helm' session.
-Call with a prefix arg to choose among existing helm
-buffers (sessions). When calling from lisp, specify a buffer-name
-as a string with ARG."
- (interactive "P")
- (let (any-buffer helm-full-frame cur-dir)
- (if arg
- (if (and (stringp arg) (bufferp (get-buffer arg)))
- (setq any-buffer arg)
- (setq any-buffer (helm-resume-select-buffer)))
- (setq any-buffer helm-last-buffer))
- (cl-assert any-buffer nil
- "helm-resume: No helm buffers found to resume")
- ;; Reset `cursor-type' to nil as it have been set to t
- ;; when quitting previous session.
- (with-current-buffer any-buffer (setq cursor-type nil))
- (setq helm-full-frame (buffer-local-value
- 'helm-full-frame (get-buffer any-buffer)))
- (setq helm-compiled-sources nil)
- (setq cur-dir (buffer-local-value
- 'default-directory (get-buffer any-buffer)))
- (setq helm-saved-selection nil
- helm-saved-action nil)
- (unless (buffer-live-p helm-current-buffer)
- ;; `helm-current-buffer' may have been killed.
- (setq helm-current-buffer (current-buffer)))
- ;; Restart with same `default-directory' value this session
- ;; was initially started with.
- (with-helm-default-directory cur-dir
- (helm
- :sources (buffer-local-value
- 'helm-sources (get-buffer any-buffer))
- :input (buffer-local-value 'helm-input-local (get-buffer any-buffer))
- :prompt (buffer-local-value 'helm--prompt (get-buffer any-buffer))
- :resume t
- :buffer any-buffer))))
-
-(defun helm-resume-previous-session-after-quit (arg)
- "Resume previous helm session within a running helm."
- (interactive "p")
- (with-helm-alive-p
- (if (> (length helm-buffers) arg)
- (helm-run-after-exit `(lambda () (helm-resume (nth ,arg helm-buffers))))
- (message "No previous helm sessions available for resuming!"))))
-(put 'helm-resume-previous-session-after-quit 'helm-only t)
-
-(defun helm-resume-list-buffers-after-quit ()
- "List resumable helm buffers within running helm."
- (interactive)
- (with-helm-alive-p
- (if (> (length helm-buffers) 0)
- (helm-run-after-exit (lambda () (helm-resume t)))
- (message "No previous helm sessions available for resuming!"))))
-(put 'helm-resume-list-buffers-after-quit 'helm-only t)
-
-(defun helm-resume-p (any-resume)
- "Whether current helm session is resumed or not."
- (eq any-resume t))
-
-(defun helm-resume-select-buffer ()
- "Select an `helm-buffer' in `helm-buffers' list to resume a helm session.
-Return nil if no `helm-buffer' found."
- (when helm-buffers
- (or (helm :sources (helm-build-sync-source "Resume helm buffer"
- :candidates helm-buffers)
- :resume 'noresume
- :buffer "*helm resume*")
- (keyboard-quit))))
-
-\f
-;;;###autoload
-(defun helm-other-buffer (any-sources any-buffer)
- "Simplified `helm' interface with other `helm-buffer'.
-Call `helm' only with ANY-SOURCES and ANY-BUFFER as args."
- (helm :sources any-sources :buffer any-buffer))
-
-(defun helm-nest (&rest same-as-helm)
- "Allows calling `helm' within a running helm session.
-Arguments SAME-AS-HELM are the same as `helm'"
- (with-helm-window
- (let ((orig-helm-current-buffer helm-current-buffer)
- (orig-helm-buffer helm-buffer)
- (orig-helm--prompt helm--prompt)
- (orig-helm--in-fuzzy helm--in-fuzzy)
- (orig-helm-last-frame-or-window-configuration
- helm-last-frame-or-window-configuration)
- (orig-one-window-p helm-onewindow-p))
- (unwind-protect
- (let (helm-current-position
- helm-current-buffer
- helm-pattern
- (helm-buffer (or (cl-getf same-as-helm :buffer)
- (nth 5 same-as-helm)
- "*Helm*"))
- helm-sources
- helm-compiled-sources
- (helm-full-frame t)
- (enable-recursive-minibuffers t))
- (apply #'helm same-as-helm))
- (with-current-buffer orig-helm-buffer
- (setq helm-alive-p t) ; Nested session set this to nil on exit.
- (setq helm-buffer orig-helm-buffer)
- (setq helm--prompt orig-helm--prompt)
- (setq helm--in-fuzzy orig-helm--in-fuzzy)
- (helm-initialize-overlays helm-buffer)
- (unless (helm-empty-buffer-p) (helm-mark-current-line t))
- (setq helm-last-frame-or-window-configuration
- orig-helm-last-frame-or-window-configuration)
- (setq cursor-type nil)
- (setq helm-current-buffer orig-helm-current-buffer)
- (setq helm-onewindow-p orig-one-window-p)
- ;; Be sure advices, hooks, and local modes keep running.
- (if (fboundp 'advice-add)
- (progn
- (advice-add 'tramp-read-passwd
- :around #'helm--advice-tramp-read-passwd)
- (advice-add 'ange-ftp-get-passwd
- :around #'helm--advice-ange-ftp-get-passwd))
- (ad-activate 'tramp-read-passwd)
- (ad-activate 'ange-ftp-get-passwd))
- (when helm-prevent-escaping-from-minibuffer
- (helm--remap-mouse-mode 1))
- (unless (cl-loop for h in post-command-hook
- thereis (memq h '(helm--maybe-update-keymap
- helm--update-header-line)))
- (add-hook 'post-command-hook 'helm--maybe-update-keymap)
- (add-hook 'post-command-hook 'helm--update-header-line))
- (helm-display-mode-line (helm-get-current-source)))))))
-
-\f
-;;; Core: Accessors
-;;
-(defun helm-current-position (save-or-restore)
- "Save or restore current position in `helm-current-buffer'.
-Argument SAVE-OR-RESTORE is either save or restore."
- (cl-case save-or-restore
- (save
- (helm-log "Save position at %S" (cons (point) (window-start)))
- (setq helm-current-position (cons (point) (window-start))))
- (restore
- ;; Maybe `helm-current-buffer' have been deleted
- ;; during helm session so check if it is here
- ;; otherwise position in underlying buffer will be lost.
- (when (get-buffer-window helm-current-buffer 'visible)
- (helm-log "Restore position at %S in buffer %s"
- helm-current-position
- (buffer-name (current-buffer)))
- (goto-char (car helm-current-position))
- ;; Fix this position with the NOFORCE arg of `set-window-start'
- ;; otherwise, if there is some other buffer than `helm-current-buffer'
- ;; one, position will be lost.
- (set-window-start (selected-window) (cdr helm-current-position) t)))))
-
-
-(defun helm-frame-or-window-configuration (save-or-restore)
- "Save or restore last frame or window configuration.
-Argument SAVE-OR-RESTORE is either save or restore of window or
-frame configuration as per `helm-save-configuration-functions'."
- (helm-log "helm-save-configuration-functions = %S"
- helm-save-configuration-functions)
- (let ((window-persistent-parameters (append '((no-other-window . t))
- window-persistent-parameters)))
- (cl-case save-or-restore
- (save (setq helm-last-frame-or-window-configuration
- (funcall (cdr helm-save-configuration-functions))))
- (restore (funcall (car helm-save-configuration-functions)
- helm-last-frame-or-window-configuration)
- ;; Restore frame focus.
- ;; This is needed for minibuffer own-frame config
- ;; when recursive minibuffers are in use.
- ;; e.g M-: + helm-minibuffer-history.
- (let ((frame (if (minibufferp helm-current-buffer)
- (selected-frame)
- (last-nonminibuffer-frame))))
- (select-frame-set-input-focus frame))))))
-
-(defun helm-split-window-default-fn (window)
- (let (split-width-threshold)
- (if (and (fboundp 'window-in-direction)
- ;; Don't try to split when starting in a minibuffer
- ;; e.g M-: and try to use helm-show-kill-ring.
- (not (minibufferp helm-current-buffer)))
- (if (or (one-window-p t)
- helm-split-window-in-side-p)
- (split-window
- (selected-window) nil (if (eq helm-split-window-default-side 'other)
- 'below helm-split-window-default-side))
- ;; If more than one window reuse one of them.
- (cl-case helm-split-window-default-side
- (left (or (helm-window-in-direction 'left)
- (helm-window-in-direction 'above)
- (selected-window)))
- (above (or (helm-window-in-direction 'above)
- (helm-window-in-direction 'left)
- (selected-window)))
- (right (or (helm-window-in-direction 'right)
- (helm-window-in-direction 'below)
- (selected-window)))
- (below (or (helm-window-in-direction 'below)
- (helm-window-in-direction 'right)
- (selected-window)))
- (same (selected-window))
- (other (other-window-for-scrolling))
- (t (or (window-next-sibling) (selected-window)))))
- (split-window-sensibly window))))
-
-(defun helm-window-in-direction (direction)
- "Same as `window-in-direction' but check if window is dedicated."
- (helm-aif (window-in-direction direction)
- (and (not (window-dedicated-p it)) it)))
-
-\f
-;;; Display helm buffer
-;;
-;;
-(defun helm-display-buffer (buffer)
- "Display BUFFER.
-The function to display `helm-buffer'."
- (let (pop-up-frames
- (split-window-preferred-function
- helm-split-window-preferred-function)
- (helm-split-window-default-side
- (if (and (not helm-full-frame)
- helm-reuse-last-window-split-state)
- (cond ((eq helm-split-window-default-side 'same) 'same)
- ((eq helm-split-window-default-side 'other) 'other)
- (helm--window-side-state)
- (t helm-split-window-default-side))
- helm-split-window-default-side)))
- (prog1
- (funcall (with-current-buffer buffer helm-display-function) buffer)
- (setq helm-onewindow-p (one-window-p t))
- ;; Don't allow other-window and friends switching out of minibuffer.
- (when helm-prevent-escaping-from-minibuffer
- (helm-prevent-switching-other-window)))))
-
-(cl-defun helm-prevent-switching-other-window (&key (enabled t))
- "Allow setting `no-other-window' parameter for all windows.
-Arg ENABLE is the value of `no-other-window' window property."
- (walk-windows
- (lambda (w)
- (unless (window-dedicated-p w)
- (set-window-parameter w 'no-other-window enabled)))
- 0))
-
-(defun helm-default-display-buffer (buffer)
- "Default function to display `helm-buffer' BUFFER.
-It uses `switch-to-buffer' or `display-buffer' depending on the
-value of `helm-full-frame' or `helm-split-window-default-side'."
- (if (or (buffer-local-value 'helm-full-frame (get-buffer buffer))
- (and (eq helm-split-window-default-side 'same)
- (one-window-p t)))
- (progn (and (not (minibufferp helm-current-buffer))
- (delete-other-windows))
- (switch-to-buffer buffer))
- (when (and (or helm-always-two-windows helm-autoresize-mode
- (and (not helm-split-window-in-side-p)
- (eq (save-selected-window
- (funcall helm-split-window-preferred-function
- (selected-window)))
- (get-buffer-window helm-current-buffer))))
- (not (eq helm-split-window-default-side 'same))
- (not (minibufferp helm-current-buffer))
- (not helm-split-window-in-side-p))
- (delete-other-windows))
- (display-buffer
- buffer `(nil . ((window-height . ,helm-display-buffer-default-size))))))
-
-\f
-;;; Core: initialize
-;;
-(defun helm-initialize (any-resume any-input any-default any-sources)
- "Start initialization of `helm' session.
-For ANY-RESUME ANY-INPUT ANY-DEFAULT and ANY-SOURCES See `helm'."
- (helm-log "start initialization: any-resume=%S any-input=%S"
- any-resume any-input)
- (helm-frame-or-window-configuration 'save)
- (setq helm-sources (helm-normalize-sources any-sources))
- (setq helm--in-fuzzy
- (cl-loop for s in helm-sources
- for matchfns = (helm-match-functions
- (if (symbolp s) (symbol-value s) s))
- for searchfns = (helm-search-functions
- (if (symbolp s) (symbol-value s) s))
- when (or (member 'helm-fuzzy-match matchfns)
- (member 'helm-fuzzy-search searchfns))
- return t))
- (helm-log "sources = %S" helm-sources)
- (helm-current-position 'save)
- (if (helm-resume-p any-resume)
- (helm-initialize-overlays (helm-buffer-get))
- (helm-initial-setup any-default))
- (setq helm-alive-p t)
- (unless (eq any-resume 'noresume)
- (helm--recent-push helm-buffer 'helm-buffers)
- (setq helm-last-buffer helm-buffer))
- (when any-input
- (setq helm-input any-input
- helm-pattern any-input)
- (helm--fuzzy-match-maybe-set-pattern))
- ;; If a `resume' attribute is present `helm-funcall-foreach'
- ;; will run its function.
- (when (helm-resume-p any-resume)
- (helm-funcall-foreach 'resume))
- (helm-log "end initialization"))
-
-(defun helm-initialize-overlays (buffer)
- "Initialize helm overlays in BUFFER."
- (helm-log "overlay setup")
- (if helm-selection-overlay
- ;; make sure the overlay belongs to the helm buffer if
- ;; it's newly created
- (move-overlay helm-selection-overlay (point-min) (point-min)
- (get-buffer buffer))
-
- (setq helm-selection-overlay
- (make-overlay (point-min) (point-min) (get-buffer buffer)))
- (overlay-put helm-selection-overlay 'face 'helm-selection)
- (overlay-put helm-selection-overlay 'priority 1)))
-
-(defun helm-restore-position-on-quit ()
- "Restore position in `helm-current-buffer' when quitting."
- (helm-current-position 'restore))
-
-(defun helm--recent-push (elm sym)
- "Move ELM of SYM value on top and set SYM to this new value."
- (pcase (symbol-value sym)
- ((and (pred (member elm)) l)
- (set sym (delete elm l))))
- (push elm (symbol-value sym)))
-
-(defun helm--current-buffer ()
- "[internal] Return `current-buffer' BEFORE `helm-buffer' is initialized.
-Note that it returns the minibuffer in use after helm has started
-and is intended for `helm-initial-setup'. To get the buffer where
-helm was started, use `helm-current-buffer' instead."
- (if (minibuffer-window-active-p (minibuffer-window))
- ;; If minibuffer is active be sure to use it's buffer
- ;; as `helm-current-buffer', this allow to use helm
- ;; from an already active minibuffer (M-: etc...)
- (window-buffer (active-minibuffer-window))
- ;; Fix Issue #456
- ;; Use this instead of `current-buffer' to ensure
- ;; helm session started in helm-mode from a completing-read
- ;; Use really the buffer where we started and not the one
- ;; where the completing-read is wrapped. i.e
- ;; (with-current-buffer SOME-OTHER-BUFFER (completing-read [...])
- (window-buffer (with-selected-window (minibuffer-window)
- (minibuffer-selected-window)))))
-
-(defun helm--run-init-hooks (hook)
- "Run after and before init hooks local to source.
-See :after-init-hook and :before-init-hook in `helm-source'."
- (cl-loop with sname = (cl-ecase hook
- (before-init-hook "h-before-init-hook")
- (after-init-hook "h-after-init-hook"))
- with h = (cl-gensym sname)
- for s in (helm-get-sources)
- for hv = (assoc-default hook s)
- if (and hv (not (symbolp hv)))
- do (set h hv)
- and do (helm-log-run-hook h)
- else do (helm-log-run-hook hv)))
-
-(defun helm-initial-setup (any-default)
- "Initialize helm settings and set up the helm buffer."
- ;; Run global hook.
- (helm-log-run-hook 'helm-before-initialize-hook)
- ;; Run local source hook.
- (helm--run-init-hooks 'before-init-hook)
- ;; For initialization of helm locals vars that need
- ;; a value from current buffer, it is here.
- (helm-set-local-variable 'current-input-method current-input-method)
- (setq helm-current-prefix-arg nil
- helm-saved-action nil
- helm-saved-selection nil
- helm-suspend-update-flag nil
- helm-current-buffer (helm--current-buffer)
- helm-buffer-file-name buffer-file-name
- helm-issued-errors nil
- helm-compiled-sources nil
- helm-saved-current-source nil)
- (unless (and (or helm-split-window-state
- helm--window-side-state)
- helm-reuse-last-window-split-state)
- (setq helm-split-window-state
- (if (or (null split-width-threshold)
- (and (integerp split-width-threshold)
- (>= split-width-threshold (+ (frame-width) 4))))
- 'vertical 'horizontal))
- (setq helm--window-side-state
- (or helm-split-window-default-side 'below)))
- ;; Call the init function for sources where appropriate
- (helm-funcall-foreach
- 'init (and helm-source-filter
- (cl-remove-if-not (lambda (s)
- (member (assoc-default 'name s)
- helm-source-filter))
- (helm-get-sources))))
- (setq helm-pattern (or (and helm--maybe-use-default-as-input
- (or (if (listp any-default)
- (car any-default) any-default)
- (with-helm-current-buffer
- (thing-at-point 'symbol))))
- ""))
- (setq helm-input "")
- (clrhash helm-candidate-cache)
- (helm-create-helm-buffer)
- (helm-clear-visible-mark)
- ;; Run global hook.
- (helm-log-run-hook 'helm-after-initialize-hook)
- ;; Run local source hook.
- (helm--run-init-hooks 'after-init-hook))
-
-(define-derived-mode helm-major-mode
- fundamental-mode "Hmm"
- "[Internal] Provide major-mode name in helm buffers.
-Unuseful when used outside helm, don't use it.")
-(put 'helm-major-mode 'mode-class 'special)
-(put 'helm-major-mode 'helm-only t)
-
-(defun helm-create-helm-buffer ()
- "Create and setup `helm-buffer'."
- (let ((root-dir default-directory))
- (with-current-buffer (get-buffer-create helm-buffer)
- (helm-log "Enabling major-mode %S" major-mode)
- (helm-log "kill local variables: %S" (buffer-local-variables))
- (kill-all-local-variables)
- (helm-major-mode)
- (set (make-local-variable 'inhibit-read-only) t)
- (buffer-disable-undo)
- (erase-buffer)
- (set (make-local-variable 'helm-map) helm-map)
- (make-local-variable 'helm-sources)
- (set (make-local-variable 'helm-follow-mode) nil)
- (set (make-local-variable 'helm-display-function) helm-display-function)
- (set (make-local-variable 'helm-selection-point) nil)
- (set (make-local-variable 'scroll-margin)
- (if helm-display-source-at-screen-top
- 0 helm-completion-window-scroll-margin))
- (set (make-local-variable 'default-directory) root-dir)
- (set (make-local-variable 'helm-marked-candidates) nil)
- (set (make-local-variable 'helm--prompt) helm--prompt)
- (helm-initialize-persistent-action)
- (helm-log "helm-display-function = %S" helm-display-function)
- (helm-log "helm--local-variables = %S" helm--local-variables)
- (cl-loop for (var . val) in helm--local-variables
- do (set (make-local-variable var) val)
- finally (setq helm--local-variables nil))
- (setq truncate-lines helm-truncate-lines) ; already local.
- (setq cursor-type nil))
- (helm-initialize-overlays helm-buffer)
- (get-buffer helm-buffer)))
-
-(define-minor-mode helm--minor-mode
- "[INTERNAL] Enable keymap in helm minibuffer.
-Since this mode has no effect when run outside of helm context,
-please don't use it outside helm.
-
-\\{helm-map}"
- :group 'helm
- :keymap (and helm-alive-p helm-map)
- (unless helm-alive-p (setq helm--minor-mode nil)))
-(put 'helm--minor-mode 'helm-only t)
-
-(defun helm--reset-default-pattern ()
- (setq helm-pattern "")
- (setq helm--maybe-use-default-as-input nil))
-
-(defun helm-read-pattern-maybe (any-prompt any-input
- any-preselect any-resume any-keymap
- any-default any-history)
- "Read pattern with prompt ANY-PROMPT and initial input ANY-INPUT.
-For ANY-PRESELECT ANY-RESUME ANY-KEYMAP ANY-DEFAULT ANY-HISTORY, See `helm'."
- (if (and (helm-resume-p any-resume)
- ;; When no source, helm-buffer is empty
- ;; or contain non--candidate lines (e.g grep exit status)
- (helm-get-current-source))
- (helm-mark-current-line t)
- (helm-update any-preselect))
- (with-current-buffer (helm-buffer-get)
- (let* ((src (helm-get-current-source))
- (src-keymap (assoc-default 'keymap src))
- (hist (or (and any-history (symbolp any-history) any-history)
- ;; Needed for resuming.
- (assoc-default 'history src)))
- (timer nil)
- blink-matching-paren
- (resize-mini-windows (and (null helm-echo-input-in-header-line)
- resize-mini-windows))
- (first-src (car helm-sources))
- (first-src-val (if (symbolp first-src)
- (symbol-value first-src)
- first-src))
- (source-process-p (or (assq 'candidates-process src)
- (assq 'candidates-process first-src-val))))
- (helm-log "helm-get-candidate-number => %S"
- (helm-get-candidate-number))
- (helm-log "helm-execute-action-at-once-if-one = %S"
- helm-execute-action-at-once-if-one)
- (helm-log "helm-quit-if-no-candidate = %S" helm-quit-if-no-candidate)
- ;; Reset `helm-pattern' and update
- ;; display if no result found with precedent value of `helm-pattern'
- ;; unless `helm-quit-if-no-candidate' is non-`nil', in this case
- ;; Don't force update with an empty pattern.
- ;; Reset also `helm--maybe-use-default-as-input' as this checking
- ;; happen only on startup.
- (when helm--maybe-use-default-as-input
- ;; Store value of `default' temporarily here waiting next update
- ;; to allow actions like helm-moccur-action matching pattern
- ;; at the place it jump to.
- (setq helm-input helm-pattern)
- (if source-process-p
- ;; Reset pattern to next update.
- (with-helm-after-update-hook
- (helm--reset-default-pattern))
- ;; Reset pattern right now.
- (helm--reset-default-pattern))
- ;; Ensure force-update when no candidates
- ;; when we start with an empty pattern.
- (and (helm-empty-buffer-p)
- (null helm-quit-if-no-candidate)
- (helm-force-update)))
- ;; Handle `helm-execute-action-at-once-if-one' and
- ;; `helm-quit-if-no-candidate' now.
- (cond ((and (if (functionp helm-execute-action-at-once-if-one)
- (funcall helm-execute-action-at-once-if-one)
- helm-execute-action-at-once-if-one)
- (= (helm-get-candidate-number) 1))
- (ignore)) ; Don't enter the minibuffer loop.
- ((and helm-quit-if-no-candidate
- (= (helm-get-candidate-number) 0))
- (setq helm-quit t)
- (and (functionp helm-quit-if-no-candidate)
- (funcall helm-quit-if-no-candidate)))
- (t ; Enter now minibuffer and wait for input.
- (let ((tap (or any-default
- (with-helm-current-buffer
- (thing-at-point 'symbol)))))
- (unwind-protect
- (minibuffer-with-setup-hook
- (lambda ()
- ;; Start minor-mode with global value of helm-map.
- (helm--minor-mode 1)
- ;; Now override the global value of `helm-map' with
- ;; the local one which is in this order:
- ;; - The keymap of current source.
- ;; - The value passed in ANY-KEYMAP
- ;; which will become buffer local.
- ;; - Or fallback to the global value of helm-map.
- (helm--maybe-update-keymap
- (or src-keymap any-keymap helm-map))
- (helm-log-run-hook 'helm-minibuffer-set-up-hook)
- (setq timer
- (run-with-idle-timer
- (max (with-helm-buffer helm-input-idle-delay)
- 0.001)
- 'repeat
- (lambda ()
- ;; Stop updating in persistent action
- ;; or when `helm-suspend-update-flag'
- ;; is non-`nil'.
- (unless (or helm-in-persistent-action
- helm-suspend-update-flag)
- (save-selected-window
- (helm-check-minibuffer-input)
- (helm-print-error-messages))))))
- (helm--update-header-line)) ; minibuffer has already been filled here
- (read-from-minibuffer (or any-prompt "pattern: ")
- any-input helm-map
- nil hist tap
- helm-inherit-input-method))
- (when timer (cancel-timer timer) (setq timer nil)))))))))
-
-(defun helm-toggle-suspend-update ()
- "Enable or disable update of display in helm.
-This can be useful for example for quietly writing a complex regexp."
- (interactive)
- (with-helm-alive-p
- (when (setq helm-suspend-update-flag (not helm-suspend-update-flag))
- (helm-kill-async-processes)
- (setq helm-pattern ""))
- (message (if helm-suspend-update-flag
- "Helm update suspended!"
- "Helm update re-enabled!"))))
-(put 'helm-toggle-suspend-update 'helm-only t)
-
-(defadvice tramp-read-passwd (around disable-helm-update)
- ;; Suspend update when prompting for a tramp password.
- (setq helm-suspend-update-flag t)
- (setq overriding-terminal-local-map nil)
- (setq helm--reading-passwd-or-string t)
- (let (stimers)
- (unwind-protect
- (progn
- (setq stimers (with-timeout-suspend))
- ad-do-it)
- (with-timeout-unsuspend stimers)
- (setq helm--reading-passwd-or-string nil)
- (setq helm-suspend-update-flag nil))))
-
-(defun helm--advice-tramp-read-passwd (old--fn &rest args)
- ;; Suspend update when prompting for a tramp password.
- (setq helm-suspend-update-flag t)
- (setq overriding-terminal-local-map nil)
- (setq helm--reading-passwd-or-string t)
- (unwind-protect
- ;; No need to suspend timer in emacs-24.4
- ;; it is fixed upstream.
- (apply old--fn args)
- (setq helm--reading-passwd-or-string nil)
- (setq helm-suspend-update-flag nil)))
-
-(defun helm--advice-ange-ftp-get-passwd (old--fn &rest args)
- ;; Suspend update when prompting for a ange password.
- (setq helm-suspend-update-flag t)
- (setq overriding-terminal-local-map nil)
- (setq helm--reading-passwd-or-string t)
- (unwind-protect
- (apply old--fn args)
- (setq helm--reading-passwd-or-string nil)
- (setq helm-suspend-update-flag nil)))
-
-(defadvice ange-ftp-get-passwd (around disable-helm-update)
- ;; Suspend update when prompting for a ange password.
- (setq helm-suspend-update-flag t)
- (setq overriding-terminal-local-map nil)
- (setq helm--reading-passwd-or-string t)
- (unwind-protect
- ad-do-it
- (setq helm--reading-passwd-or-string nil)
- (setq helm-suspend-update-flag nil)))
-
-(defun helm--maybe-update-keymap (&optional map)
- "Handle different keymaps in multiples sources.
-
-Overrides `helm-map' with the local map of current source. If no
-map is found in current source, does nothing (keeps previous
-map)."
- (with-helm-buffer
- (helm-aif (or map (assoc-default 'keymap (helm-get-current-source)))
- ;; We used a timer in the past to leave
- ;; enough time to helm to setup its keymap
- ;; when changing source from a recursive minibuffer.
- ;; e.g C-x C-f M-y C-g
- ;; => *find-files have now the bindings of *kill-ring.
- ;; It is no more true now we are using `minor-mode-overriding-map-alist'
- ;; and `helm--minor-mode' thus it fix issue #1076 for emacs-24.3
- ;; where concurrent timers are not supported.
- ;; i.e update keymap+check input.
- (with-current-buffer (window-buffer (minibuffer-window))
- (setq minor-mode-overriding-map-alist `((helm--minor-mode . ,it)))))))
-
-;;; Prevent loosing focus when using mouse.
-;;
-(defvar helm--remap-mouse-mode-map
- (let ((map (make-sparse-keymap)))
- (cl-loop for k in '([mouse-1] [mouse-2] [mouse-3]
- [down-mouse-1] [down-mouse-2] [down-mouse-3]
- [drag-mouse-1] [drag-mouse-2] [drag-mouse-3]
- [double-mouse-1] [double-mouse-2] [double-mouse-3]
- [triple-mouse-1] [triple-mouse-2] [triple-mouse-3])
- do (define-key map k 'undefined))
- map))
-
-(define-minor-mode helm--remap-mouse-mode
- "[INTERNAL] Prevent escaping helm minibuffer with mouse clicks.
-Do nothing when used outside of helm context.
-
-WARNING: Do not use this mode yourself, it is internal to helm."
- :group 'helm
- :global t
- :keymap helm--remap-mouse-mode-map
- (unless helm-alive-p
- (setq helm--remap-mouse-mode-map nil)))
-(put 'helm--remap-mouse-mode 'helm-only t)
-\f
-;; Core: clean up
-
-(defun helm-cleanup ()
- "Clean up the mess when helm exit or quit."
- (helm-log "start cleanup")
- (with-current-buffer helm-buffer
- (setq cursor-type t)
- ;; bury-buffer from this window.
- (bury-buffer) ;[1]
- (remove-hook 'post-command-hook 'helm--maybe-update-keymap)
- (remove-hook 'post-command-hook 'helm--update-header-line)
- ;; Be sure we call this from helm-buffer.
- (helm-funcall-foreach 'cleanup))
- (helm-kill-async-processes)
- ;; Remove the temporary hooks added
- ;; by `with-helm-temp-hook' that
- ;; may not have been consumed.
- (when helm--temp-hooks
- (cl-loop for (fn . hook) in helm--temp-hooks
- do (set hook (delete fn (symbol-value hook)))))
- ;; When running helm from a dedicated frame
- ;; with no minibuffer, helm will run in the main frame
- ;; which have a minibuffer, so be sure to disable
- ;; the `no-other-window' prop there.
- (helm-prevent-switching-other-window :enabled nil)
- (helm-log-run-hook 'helm-cleanup-hook)
- (helm-frame-or-window-configuration 'restore)
- ;; [1] now bury-buffer from underlying windows otherwise,
- ;; if this window is killed the underlying buffer will
- ;; be a helm buffer.
- (replace-buffer-in-windows helm-buffer)
- (setq helm-alive-p nil)
- ;; This is needed in some cases where last input
- ;; is yielded infinitely in minibuffer after helm session.
- (helm-clean-up-minibuffer))
-
-(defun helm-clean-up-minibuffer ()
- "Remove contents of minibuffer."
- (let ((miniwin (minibuffer-window)))
- ;; Clean only current minibuffer used by helm.
- ;; i.e The precedent one is active.
- (unless (minibuffer-window-active-p miniwin)
- (with-current-buffer (window-buffer miniwin)
- (delete-minibuffer-contents)))))
-
-\f
-;;; Core: input handling
-;;
-;;
-(defun helm-check-minibuffer-input ()
- "Check minibuffer content."
- (with-helm-quittable
- (with-selected-window (or (active-minibuffer-window)
- (minibuffer-window))
- (helm-check-new-input (minibuffer-contents)))))
-
-(defun helm-check-new-input (input)
- "Check INPUT string and update the helm buffer if necessary."
- (unless (equal input helm-pattern)
- (setq helm-pattern input)
- (unless (helm-action-window)
- (setq helm-input helm-pattern))
- (helm-log "helm-pattern = %S" helm-pattern)
- (helm-log "helm-input = %S" helm-input)
- (setq helm--in-update t)
- (helm-update)))
-
-(defun helm--reset-update-flag ()
- (run-with-idle-timer
- helm-exit-idle-delay nil
- (lambda () (setq helm--in-update nil))))
-
-(add-hook 'helm-after-update-hook #'helm--reset-update-flag)
-
-\f
-;;; Core: source compiler
-;;
-;;
-(defun helm-compile-sources (sources funcs)
- "Compile SOURCES with FUNCS.
-See `helm-compile-source-functions'.
-Helm plug-ins are realized by this function."
- (mapcar
- (lambda (source)
- (cl-loop with src = (if (listp source) source (symbol-value source))
- for noplug = (assoc 'dont-plug src)
- for f in funcs
- unless (and noplug (memq f (cdr noplug)))
- do (setq src (funcall f src))
- finally (cl-return src)))
- sources))
-
-\f
-;; Core: all candidates
-
-(defun helm-get-candidates (source)
- "Retrieve and return the list of candidates from SOURCE."
- (let* (inhibit-quit
- (candidate-fn (assoc-default 'candidates source))
- (candidate-proc (assoc-default 'candidates-process source))
- cfn-error
- (notify-error
- (lambda (&optional e)
- (error
- "In `%s' source: `%s' %s %s"
- (assoc-default 'name source)
- (or candidate-fn candidate-proc)
- (if e "\n" "must be a list, a symbol bound to a list, or a function returning a list")
- (if e (prin1-to-string e) ""))))
- (candidates (condition-case-unless-debug err
- ;; Process candidates-(process) function
- ;; It may return a process or a list of candidates.
- (if candidate-proc
- ;; Calling `helm-interpret-value' with no
- ;; SOURCE arg force the use of `funcall'
- ;; and not `helm-funcall-with-source'.
- (helm-interpret-value candidate-proc)
- (helm-interpret-value candidate-fn source))
- (error (helm-log "Error: %S" (setq cfn-error err)) nil))))
- (when (and (processp candidates) (not candidate-proc))
- (warn "Candidates function `%s' should be called in a `candidates-process' attribute"
- candidate-fn))
- (cond ((processp candidates)
- ;; Candidates will be filtered later in process filter.
- candidates)
- ;; An error occured in candidates function.
- (cfn-error (funcall notify-error cfn-error))
- ;; Candidates function returns no candidates.
- ((or (null candidates)
- ;; Can happen when the output of a process
- ;; is empty, and the candidates function call
- ;; something like (split-string (buffer-string) "\n")
- ;; which result in a list of one empty string (Issue #938).
- ;; e.g (completing-read "test: " '(""))
- (equal candidates '("")))
- nil)
- ((listp candidates)
- ;; Transform candidates with `candidate-transformer' functions if
- ;; some, otherwise return candidates.
- (helm-transform-candidates candidates source))
- (t (funcall notify-error)))))
-
-(defmacro helm-while-no-input (&rest body)
- "Same as `while-no-input' but without the `input-pending-p' test."
- (declare (debug t) (indent 0))
- (let ((catch-sym (make-symbol "input"))
- inhibit-quit)
- `(with-local-quit
- (catch ',catch-sym
- (let ((throw-on-input ',catch-sym))
- ,@body)))))
-
-(defun helm-get-cached-candidates (source)
- "Return the cached value of candidates for SOURCE.
-Cache the candidates if there is no cached value yet."
- (let* ((name (assoc-default 'name source))
- (candidate-cache (gethash name helm-candidate-cache)))
- (helm-aif candidate-cache
- (prog1 it (helm-log "Use cached candidates"))
- (helm-log "No cached candidates, calculate candidates")
- (let ((candidates (helm-get-candidates source)))
- (cond ((processp candidates)
- (push (cons candidates
- (append source
- (list (cons 'item-count 0)
- (cons 'incomplete-line ""))))
- helm-async-processes)
- (set-process-filter candidates 'helm-output-filter)
- (setq candidates nil))
- ((not (assoc 'volatile source))
- (puthash name candidates helm-candidate-cache)))
- candidates))))
-
-\f
-;;; Core: candidate transformers
-
-(defun helm-process-candidate-transformer (candidates source)
- "Execute `candidate-transformer' function(s) on CANDIDATES in SOURCE."
- (helm-aif (assoc-default 'candidate-transformer source)
- (helm-funcall-with-source source it candidates)
- candidates))
-
-(defun helm-process-filtered-candidate-transformer (candidates source)
- "Execute `filtered-candidate-transformer' function(s) on CANDIDATES in SOURCE."
- (helm-aif (assoc-default 'filtered-candidate-transformer source)
- (helm-funcall-with-source source it candidates source)
- candidates))
-
-(defmacro helm--maybe-process-filter-one-by-one-candidate (candidate source)
- "Execute `filter-one-by-one' function(s) on CANDIDATE in SOURCE."
- `(helm-aif (assoc-default 'filter-one-by-one ,source)
- (if (and (listp it)
- (not (functionp it))) ;; Don't treat lambda's as list.
- (cl-loop for f in it
- do (setq ,candidate (funcall f ,candidate))
- finally return ,candidate)
- (setq ,candidate (funcall it ,candidate)))
- ,candidate))
-
-(defun helm--initialize-one-by-one-candidates (candidates source)
- "Process the CANDIDATES with the `filter-one-by-one' function in SOURCE.
-Return CANDIDATES when pattern is empty."
- (helm-aif (and (string= helm-pattern "")
- (assoc-default 'filter-one-by-one source))
- (cl-loop for cand in candidates collect
- (helm--maybe-process-filter-one-by-one-candidate cand source))
- candidates))
-
-(defun helm-process-filtered-candidate-transformer-maybe
- (candidates source process-p)
- "Execute `filtered-candidate-transformer' function(s) on CANDIDATES in SOURCE.
-When PROCESS-P is non-`nil' execute `filtered-candidate-transformer'
-functions if some, otherwise return CANDIDATES."
- (if process-p
- ;; When no filter return CANDIDATES unmodified.
- (helm-process-filtered-candidate-transformer candidates source)
- candidates))
-
-(defun helm-process-real-to-display (candidates source)
- "Execute real-to-display function on all CANDIDATES of SOURCE."
- (helm-aif (assoc-default 'real-to-display source)
- (setq candidates (helm-funcall-with-source
- source 'mapcar
- (lambda (cand_)
- (if (consp cand_)
- ;; override DISPLAY from candidate-transformer
- (cons (funcall it (cdr cand_)) (cdr cand_))
- (cons (funcall it cand_) cand_)))
- candidates))
- candidates))
-
-(defun helm-transform-candidates (candidates source &optional process-p)
- "Transform CANDIDATES from SOURCE according to candidate transformers.
-When PROCESS-P is non-`nil' executes the
-`filtered-candidate-transformer' functions, otherwise processes
-`candidate-transformer' functions only. When `real-to-display'
-attribute is present, execute its function on all maybe filtered
-CANDIDATES."
- (helm-process-real-to-display
- (helm-process-filtered-candidate-transformer-maybe
- (helm-process-candidate-transformer
- (helm--initialize-one-by-one-candidates candidates source) source)
- source process-p)
- source))
-
-\f
-;; Core: narrowing candidates
-(defun helm-candidate-number-limit (source)
- "Apply candidate-number-limit attribute value.
-This overrides `helm-candidate-number-limit' variable.
-
-e.g:
-If \(candidate-number-limit\) is in SOURCE, show all candidates in SOURCE.
-If \(candidate-number-limit . 123\) is in SOURCE limit candidate to 123."
- (helm-aif (assq 'candidate-number-limit source)
- (or (cdr it) 99999999)
- (or helm-candidate-number-limit 99999999)))
-
-(defun helm-candidate-get-display (candidate)
- "Get searched display part from CANDIDATE.
-CANDIDATE is either a string, a symbol, or a \(DISPLAY . REAL\)
-cons cell."
- (cond ((car-safe candidate))
- ((symbolp candidate)
- (symbol-name candidate))
- ((numberp candidate)
- (number-to-string candidate))
- (t candidate)))
-
-(defun helm-process-pattern-transformer (pattern source)
- "Execute pattern-transformer attribute function(s) on PATTERN in SOURCE."
- (helm-aif (assoc-default 'pattern-transformer source)
- (helm-funcall-with-source source it pattern)
- pattern))
-
-(defun helm-default-match-function (candidate)
- "Check if `helm-pattern' match CANDIDATE.
-Default function to match candidates according to `helm-pattern'."
- (string-match helm-pattern candidate))
-
-\f
-;;; Fuzzy matching
-;;
-;;
-(defvar helm--fuzzy-regexp-cache (make-hash-table :test 'eq))
-(defun helm--fuzzy-match-maybe-set-pattern ()
- ;; Computing helm-pattern with helm--mapconcat-pattern
- ;; is costly, so cache it once time for all and reuse it
- ;; until pattern change.
- (when helm--in-fuzzy
- (let ((fun (if (string-match "\\`\\^" helm-pattern)
- #'identity
- #'helm--mapconcat-pattern)))
- (clrhash helm--fuzzy-regexp-cache)
- ;; FIXME: Splitted part are not handled here,
- ;; I must compute them in `helm-search-match-part'
- ;; when negation and in-buffer are used.
- (if (string-match "\\`!" helm-pattern)
- (puthash 'helm-pattern
- (if (> (length helm-pattern) 1)
- (list (funcall fun (substring helm-pattern 1 2))
- (funcall fun (substring helm-pattern 1)))
- '("" ""))
- helm--fuzzy-regexp-cache)
- (puthash 'helm-pattern
- (if (> (length helm-pattern) 0)
- (list (funcall fun (substring helm-pattern 0 1))
- (funcall fun helm-pattern))
- '("" ""))
- helm--fuzzy-regexp-cache)))))
-
-(defun helm-fuzzy-match (candidate)
- "Check if `helm-pattern' fuzzy matches CANDIDATE.
-This function is used with sources built with `helm-source-sync'."
- (unless (string-match " " helm-pattern)
- ;; When pattern have one or more spaces, let
- ;; multi-match doing the job with no fuzzy matching.[1]
- (let ((regexp (cadr (gethash 'helm-pattern helm--fuzzy-regexp-cache))))
- (if (string-match "\\`!" helm-pattern)
- (not (string-match regexp candidate))
- (string-match regexp candidate)))))
-
-(defun helm-fuzzy-search (pattern)
- "Same as `helm-fuzzy-match' but for sources built with
-`helm-source-in-buffer'."
- (unless (string-match " " helm-pattern)
- ;; Same as in `helm-fuzzy-match' ref[1].
- (let* ((regexps (gethash 'helm-pattern helm--fuzzy-regexp-cache))
- (partial-regexp (car regexps))
- (regexp (cadr regexps)))
- (if (string-match "\\`!" pattern)
- ;; Don't try to search here, just return
- ;; the position of line and go ahead,
- ;; letting `helm-search-match-part' checking if
- ;; pattern match against this line.
- (prog1 (list (point-at-bol) (point-at-eol))
- (forward-line 1))
- ;; We could use here directly `re-search-forward'
- ;; on the regexp produced by `helm--mapconcat-pattern',
- ;; but it is very slow because emacs have to do an incredible
- ;; amount of loops to match e.g "[^f]*o[^o]..." in the whole buffer,
- ;; more the regexp is long more the amount of loops grow.
- ;; (Probably leading to a max-lisp-eval-depth error if both
- ;; regexp and buffer are too big)
- ;; So just search the first bit of pattern e.g "[^f]*f", and
- ;; then search the corresponding line with the whole regexp,
- ;; which increase dramatically the speed of the search.
- (cl-loop while (re-search-forward partial-regexp nil t)
- for bol = (point-at-bol)
- for eol = (point-at-eol)
- if (progn (goto-char bol)
- (re-search-forward regexp eol t))
- do (goto-char eol) and return t
- else do (goto-char eol)
- finally return nil)))))
-
-(defun helm-score-candidate-for-pattern (candidate pattern)
- "Assign score to CANDIDATE according to PATTERN.
-Score is calculated for contiguous matches found with PATTERN.
-Score is 100 (maximum) if PATTERN is fully matched in CANDIDATE.
-One point bonus is added to score when PATTERN prefix matches
-CANDIDATE. Contiguous matches get a coefficient of 2."
- (let* ((cand (if (stringp candidate)
- candidate (helm-stringify candidate)))
- (pat-lookup (helm--collect-pairs-in-string pattern))
- (str-lookup (helm--collect-pairs-in-string cand))
- (bonus (if (equal (car pat-lookup) (car str-lookup)) 1 0))
- (bonus1 (and (string-match (concat "\\<" (regexp-quote pattern) "\\>")
- cand)
- 100)))
- (+ bonus (or bonus1
- ;; Give a coefficient of 2 for contiguous matches.
- ;; That's mean that "wiaaaki" will not take precedence
- ;; on "aaawiki" when matching on "wiki" even if "wiaaaki"
- ;; starts by "wi".
- (* (length (cl-nintersection
- pat-lookup str-lookup :test 'equal))
- 2)))))
-
-(defun helm-fuzzy-matching-default-sort-fn (candidates _source &optional use-real)
- "The transformer for sorting candidates in fuzzy matching.
-It sorts on the display part by default.
-
-Sorts CANDIDATES by their scores as calculated by
-`helm-score-candidate-for-pattern'. Ties in scores are sorted by
-length of the candidates. Set USE-REAL to non-`nil' to sort on the
-real part."
- (if (string= helm-pattern "")
- candidates
- (let ((table-scr (make-hash-table :test 'equal)))
- (sort candidates
- (lambda (s1 s2)
- ;; Score and measure the length on real or display part of candidate
- ;; according to `use-real'.
- (let* ((real-or-disp-fn (if use-real #'cdr #'car))
- (cand1 (if (consp s1)
- (funcall real-or-disp-fn s1)
- s1))
- (cand2 (if (consp s2)
- (funcall real-or-disp-fn s2)
- s2))
- (data1 (or (gethash cand1 table-scr)
- (puthash cand1
- (list (helm-score-candidate-for-pattern
- cand1 helm-pattern)
- (length (helm-stringify cand1)))
- table-scr)))
- (data2 (or (gethash cand2 table-scr)
- (puthash cand2
- (list (helm-score-candidate-for-pattern
- cand2 helm-pattern)
- (length (helm-stringify cand2)))
- table-scr)))
- (len1 (cadr data1))
- (len2 (cadr data2))
- (scr1 (car data1))
- (scr2 (car data2)))
- (cond ((= scr1 scr2)
- (< len1 len2))
- ((> scr1 scr2)))))))))
-
-(defun helm--maybe-get-migemo-pattern (pattern)
- (or (and helm-migemo-mode
- (assoc-default pattern helm-mm--previous-migemo-info))
- pattern))
-
-(defun helm-fuzzy-default-highlight-match (candidate)
- "The default function to highlight matches in fuzzy matching.
-Highlight elements in CANDIDATE matching `helm-pattern' according
-to the matching method in use."
- (if (string= helm-pattern "")
- ;; Empty pattern, do nothing.
- candidate
- ;; Else start highlighting.
- (let* ((pair (and (consp candidate) candidate))
- (display (helm-stringify (if pair (car pair) candidate)))
- (real (cdr pair))
- (regex (helm--maybe-get-migemo-pattern helm-pattern))
- (mp (pcase (get-text-property 0 'match-part display)
- ((pred (string= display)) nil)
- (str str)))
- (count 0)
- beg-str end-str)
- ;; Extract all parts of display keeping original properties.
- (when (and mp (string-match (regexp-quote mp) display))
- (setq beg-str (substring display 0 (match-beginning 0))
- end-str (substring display (match-end 0) (length display))
- mp (substring display (match-beginning 0) (match-end 0))))
- (with-temp-buffer
- ;; Insert the whole display part and remove non--match-part
- ;; to keep their original face properties.
- (insert (propertize (or mp display) 'read-only nil)) ; Fix (#1176)
- (goto-char (point-min))
- (condition-case nil
- (progn
- ;; Try first matching against whole pattern.
- (while (re-search-forward regex nil t)
- (cl-incf count)
- (add-text-properties
- (match-beginning 0) (match-end 0) '(face helm-match)))
- ;; If no matches start matching against multiples or fuzzy matches.
- (when (zerop count)
- (cl-loop with multi-match = (string-match-p " " helm-pattern)
- with patterns = (if multi-match
- (mapcar #'helm--maybe-get-migemo-pattern
- (split-string helm-pattern))
- (split-string helm-pattern "" t))
- for p in patterns
- ;; Multi matches (regexps patterns).
- if multi-match do
- (progn
- (while (re-search-forward p nil t)
- (add-text-properties
- (match-beginning 0) (match-end 0)
- '(face helm-match)))
- (goto-char (point-min)))
- ;; Fuzzy matches (literal patterns).
- else do
- (when (search-forward p nil t)
- (add-text-properties
- (match-beginning 0) (match-end 0)
- '(face helm-match))))))
- (invalid-regexp nil))
- ;; Now replace the original match-part with the part
- ;; with face properties added.
- (setq display (if mp (concat beg-str (buffer-string) end-str) (buffer-string))))
- (if real (cons display real) display))))
-
-(defun helm-fuzzy-highlight-matches (candidates _source)
- "The filtered-candidate-transformer function to highlight fuzzy matches.
-See `helm-fuzzy-default-highlight-match'."
- (cl-loop for c in candidates
- collect (funcall helm-fuzzy-matching-highlight-fn c)))
-
-(defun helm-match-functions (source)
- (let ((matchfns (or (assoc-default 'match source)
- (assoc-default 'match-strict source)
- #'helm-default-match-function)))
- (if (and (listp matchfns) (not (functionp matchfns)))
- matchfns (list matchfns))))
-
-(defun helm-search-functions (source)
- (let ((searchfns (assoc-default 'search source)))
- (if (and (listp searchfns) (not (functionp searchfns)))
- searchfns (list searchfns))))
-
-(defun helm-take-first-elements (seq n)
- "Return the first N elements of SEQ if SEQ is longer than N.
-It is used for narrowing list of candidates to the
-`helm-candidate-number-limit'."
- (if (> (length seq) n) (cl-subseq seq 0 n) seq))
-
-(cl-defun helm-set-case-fold-search (&optional (pattern helm-pattern))
- "Used to set the value of `case-fold-search' in helm.
-Return t or nil depending on the value of `helm-case-fold-search'
-and `helm-pattern'."
- (let ((helm-case-fold-search
- (helm-aif (assq 'case-fold-search (helm-get-current-source))
- (cdr it)
- helm-case-fold-search))
- ;; Only parse basename for filenames
- ;; to avoid setting case sensitivity
- ;; when expanded directories contains upcase
- ;; characters.
- (bn-or-pattern (if (string-match "[~/]*" pattern)
- (helm-basename pattern)
- pattern)))
- (helm-set-case-fold-search-1 bn-or-pattern)))
-
-(defun helm-set-case-fold-search-1 (pattern)
- (cl-case helm-case-fold-search
- (smart (let ((case-fold-search nil))
- (if (string-match "[[:upper:]]" pattern) nil t)))
- (t helm-case-fold-search)))
-
-(defun helm-match-from-candidates (cands matchfns match-part-fn limit source)
- (condition-case-unless-debug err
- (cl-loop with hash = (make-hash-table :test 'equal)
- with allow-dups = (assq 'allow-dups source)
- with case-fold-search = (helm-set-case-fold-search)
- with count = 0
- for iter from 1
- for fn in matchfns
- when (< count limit) nconc
- (cl-loop for c in cands
- for dup = (gethash c hash)
- while (< count limit)
- for target = (helm-candidate-get-display c)
- for prop-part = (get-text-property 0 'match-part target)
- for part = (and match-part-fn
- (or prop-part
- (funcall match-part-fn target)))
- ;; When allowing dups check if DUP
- ;; have been already found in previous loop
- ;; by comparing its value with ITER.
- when (and (or (and allow-dups dup (= dup iter))
- (null dup))
- (condition-case nil
- (funcall fn (or part target))
- (invalid-regexp nil)))
- do
- (progn
- ;; Give as value the iteration number of
- ;; inner loop to be able to check if
- ;; the duplicate have not been found in previous loop.
- (puthash c iter hash)
- (helm--maybe-process-filter-one-by-one-candidate c source)
- (cl-incf count))
- ;; Filter out nil candidates maybe returned by
- ;; `helm--maybe-process-filter-one-by-one-candidate'.
- and when c collect
- (if (and part (not prop-part))
- (if (consp c)
- (cons (propertize target 'match-part part) (cdr c))
- (propertize c 'match-part part))
- c)))
- (error (unless (eq (car err) 'invalid-regexp) ; Always ignore regexps errors.
- (helm-log-error "helm-match-from-candidates in source `%s': %s %s"
- (assoc-default 'name source) (car err) (cdr err)))
- nil)))
-
-(defun helm-compute-matches (source)
- "Start computing candidates in SOURCE."
- (save-current-buffer
- (let ((matchfns (helm-match-functions source))
- (matchpartfn (assoc-default 'match-part source))
- (helm-source-name (assoc-default 'name source))
- (helm-current-source source)
- (limit (helm-candidate-number-limit source))
- (helm-pattern (helm-process-pattern-transformer
- helm-pattern source)))
- (helm--fuzzy-match-maybe-set-pattern)
- ;; If source have a `filtered-candidate-transformer' attr
- ;; Filter candidates with this func, otherwise just compute
- ;; candidates.
- (helm-process-filtered-candidate-transformer
- ;; ; Using in-buffer method or helm-pattern is empty
- ;; in this case compute all candidates.
- (if (or (equal helm-pattern "")
- (helm--candidates-in-buffer-p matchfns))
- ;; Compute all candidates up to LIMIT.
- (helm-take-first-elements
- (helm-get-cached-candidates source) limit)
- ;; Compute candidates according to pattern with their match fns.
- (helm-match-from-candidates
- (helm-get-cached-candidates source) matchfns matchpartfn limit source))
- source))))
-
-(defun helm--candidates-in-buffer-p (matchfns)
- (equal matchfns '(identity)))
-
-(defun helm-render-source (source matches)
- "Display MATCHES from SOURCE according to its settings."
- (helm-log "Source name = %S" (assoc-default 'name source))
- (when matches
- (helm-insert-header-from-source source)
- (if (not (assq 'multiline source))
- (cl-loop for m in matches
- for count from 1
- do (helm-insert-match m 'insert count))
- (let ((start (point))
- (count 0)
- separate)
- (cl-dolist (match matches)
- (cl-incf count)
- (if separate
- (helm-insert-candidate-separator)
- (setq separate t))
- (helm-insert-match match 'insert count))
- (put-text-property start (point) 'helm-multiline t)))))
-
-(defmacro helm--maybe-use-while-no-input (&rest body)
- "Wrap BODY in `helm-while-no-input' unless initializing a remote connection."
- `(progn
- (if (and (file-remote-p helm-pattern)
- (not (file-remote-p helm-pattern nil t)))
- ;; Tramp will ask for passwd, don't use `helm-while-no-input'.
- ,@body
- (helm-log "Using here `helm-while-no-input'")
- (helm-while-no-input ,@body))))
-
-(defun helm--collect-matches (src-list)
- (let ((matches (helm--maybe-use-while-no-input
- (cl-loop for src in src-list
- collect (helm-compute-matches src)))))
- (unless (eq matches t) matches)))
-
-\f
-;;; Core: helm-update
-;;
-(defun helm-update (&optional preselect source)
- "Update candidates list in `helm-buffer' based on `helm-pattern'.
-Argument PRESELECT is a string or regexp used to move selection
-to a particular place after finishing update."
- (helm-log "Start updating")
- (helm-kill-async-processes)
- ;; When persistent action have been called
- ;; we have two windows even with `helm-full-frame'.
- ;; So go back to one window when updating if `helm-full-frame'
- ;; is non-`nil'.
- (with-helm-window
- (when helm-onewindow-p (delete-other-windows)))
- (with-current-buffer (helm-buffer-get)
- (set (make-local-variable 'helm-input-local) helm-pattern)
- (unwind-protect
- (let (sources matches)
- ;; Collect sources ready to be updated.
- (setq sources
- (cl-loop for src in (helm-get-sources)
- when (helm-update-source-p src)
- collect src))
- ;; When no sources to update erase buffer
- ;; to avoid duplication of header and candidates
- ;; when next chunk of update will arrive,
- ;; otherwise the buffer is erased AFTER [1] the results
- ;; are computed.
- (unless sources (erase-buffer))
- ;; Compute matches without rendering the sources.
- (helm-log "Matches: %S"
- (setq matches (helm--collect-matches sources)))
- ;; If computing matches finished and is not interrupted
- ;; erase the helm-buffer and render results (Fix #1157).
- (when matches
- (erase-buffer) ; [1]
- (cl-loop for src in sources
- for mtc in matches
- do (helm-render-source src mtc))))
- (helm-update-move-first-line)
- (unless (assoc 'candidates-process source)
- (helm-display-mode-line (helm-get-current-source))
- (helm-log-run-hook 'helm-after-update-hook))
- (when preselect
- (helm-log "Update preselect candidate %s" preselect)
- (helm-preselect preselect source))
- (setq helm-force-updating-p nil))
- (helm-log "end update")))
-
-(defun helm-update-source-p (source)
- "Whether SOURCE need updating or not."
- (let ((len (string-width
- (if (or (assoc 'matchplugin source)
- (null (assoc 'no-matchplugin source)))
- ;; Don't count spaces entered when using
- ;; multi-match.
- (replace-regexp-in-string " " "" helm-pattern)
- helm-pattern))))
- (and (or (not helm-source-filter)
- (member (assoc-default 'name source) helm-source-filter))
- (>= len
- (helm-aif (assoc 'requires-pattern source) (or (cdr it) 1) 0))
- ;; These incomplete regexps hang helm forever
- ;; so defer update. Maybe replace spaces quoted when using
- ;; multi-match.
- (not (member (replace-regexp-in-string "\\s\\ " " " helm-pattern)
- helm-update-blacklist-regexps)))))
-
-(defun helm-update-move-first-line (&optional without-hook)
- "Goto first line of `helm-buffer'."
- (goto-char (point-min))
- (unless without-hook
- (save-excursion (helm-log-run-hook 'helm-update-hook)))
- (helm-next-line))
-
-(defun helm-force-update (&optional preselect)
- "Force recalculation and update of candidates.
-
-Unlike `helm-update', this function re-evaluates `init' and
-`update' attributes when present; also `helm-candidate-cache' is
-not reinitialized, meaning candidates are not recomputed unless
-pattern has changed.
-
-Selection is preserved to current candidate or moved to
-PRESELECT, if specified."
- (let ((source (helm-get-current-source))
- (selection (helm-aif (helm-get-selection nil t)
- (regexp-quote it)
- it)))
- (setq helm-force-updating-p t)
- (when source
- (mapc 'helm-force-update--reinit
- (helm-get-sources)))
- (helm-update (or preselect selection) source)
- (with-helm-window (recenter))))
-
-(defun helm-refresh ()
- "Force recalculation and update of candidates."
- (interactive)
- (with-helm-alive-p
- (helm-force-update)))
-(put 'helm-refresh 'helm-only t)
-
-(defun helm-force-update--reinit (source)
- "Reinit SOURCE by calling its update and init functions."
- (helm-aif (helm-funcall-with-source
- source 'helm-candidate-buffer)
- (kill-buffer it))
- (cl-dolist (attr '(update init))
- (helm-aif (assoc-default attr source)
- (helm-funcall-with-source source it)))
- (helm-remove-candidate-cache source))
-
-(defun helm-remove-candidate-cache (source)
- "Remove SOURCE from `helm-candidate-cache'."
- (remhash (assoc-default 'name source) helm-candidate-cache))
-
-(defun helm-insert-match (match insert-function &optional num)
- "Insert MATCH into `helm-buffer' with INSERT-FUNCTION for SOURCE.
-If MATCH is a list then insert the string to display and store
-the real value in a text property."
- (let ((start (point-at-bol (point)))
- (dispvalue (helm-candidate-get-display match))
- (realvalue (cdr-safe match)))
- (when (and (stringp dispvalue)
- (not (zerop (length dispvalue))))
- (funcall insert-function dispvalue)
- ;; Some sources with candidates-in-buffer have already added
- ;; 'helm-realvalue property when creating candidate buffer.
- (unless (get-text-property start 'helm-realvalue)
- (and realvalue
- (put-text-property start (point-at-eol)
- 'helm-realvalue realvalue)))
- (when num
- (put-text-property start (point-at-eol) 'helm-cand-num num))
- (funcall insert-function "\n"))))
-
-(defun helm-insert-header-from-source (source)
- "Insert SOURCE name in `helm-buffer' header.
-Maybe insert, by overlay, additional info after the source name
-if SOURCE has header-name attribute."
- (let ((name (assoc-default 'name source)))
- (helm-insert-header
- name
- (helm-aif (assoc-default 'header-name source)
- (helm-funcall-with-source source it name)))))
-
-(defun helm-insert-header (name &optional display-string)
- "Insert header of source NAME into the helm buffer.
-If DISPLAY-STRING is non-`nil' and a string value then display
-this additional info after the source name by overlay."
- (unless (bobp)
- (let ((start (point)))
- (insert "\n")
- (put-text-property start (point) 'helm-header-separator t)))
- (let ((start (point)))
- (insert name)
- (put-text-property (point-at-bol)
- (point-at-eol) 'helm-header t)
- (when display-string
- (overlay-put (make-overlay (point-at-bol) (point-at-eol))
- 'display display-string))
- (insert "\n")
- (put-text-property start (point) 'face 'helm-source-header)))
-
-(defun helm-insert-candidate-separator ()
- "Insert separator of candidates into the helm buffer."
- (insert (propertize helm-candidate-separator 'face 'helm-separator))
- (put-text-property (point-at-bol)
- (point-at-eol) 'helm-candidate-separator t)
- (insert "\n"))
-
-\f
-;;; Core: async process
-;;
-(defun helm-output-filter (process output-string)
- "The `process-filter' function for helm async sources."
- (with-helm-quittable
- (helm-output-filter-1 (assoc process helm-async-processes) output-string)))
-
-(defun helm-output-filter-1 (process-assoc output-string)
- (helm-log "output-string = %S" output-string)
- (with-current-buffer helm-buffer
- (let ((source (cdr process-assoc)))
- (save-excursion
- (helm-aif (assoc-default 'insertion-marker source)
- (goto-char it)
- (goto-char (point-max))
- (helm-insert-header-from-source source)
- (setcdr process-assoc
- (append source `((insertion-marker . ,(point-marker))))))
- (helm-output-filter--process-source
- (car process-assoc) output-string source
- (helm-candidate-number-limit source))))
- (helm-output-filter--post-process)))
-
-(defun helm-output-filter--process-source (process output-string source limit)
- (cl-dolist (candidate (helm-transform-candidates
- (helm-output-filter--collect-candidates
- (split-string output-string "\n")
- (assoc 'incomplete-line source))
- source t))
- (setq candidate
- (helm--maybe-process-filter-one-by-one-candidate candidate source))
- (if (assq 'multiline source)
- (let ((start (point)))
- (helm-insert-candidate-separator)
- (helm-insert-match candidate 'insert-before-markers
- (1+ (cdr (assoc 'item-count source))))
- (put-text-property start (point) 'helm-multiline t))
- (helm-insert-match candidate 'insert-before-markers
- (1+ (cdr (assoc 'item-count source)))))
- (cl-incf (cdr (assoc 'item-count source)))
- (when (>= (assoc-default 'item-count source) limit)
- (helm-kill-async-process process)
- (cl-return))))
-
-(defun helm-output-filter--collect-candidates (lines incomplete-line-info)
- "Collect LINES maybe completing the truncated first and last lines."
- ;; The output of process may come in chunks of any size, so the last
- ;; line of LINES could be truncated, this truncated line is stored
- ;; in INCOMPLETE-LINE-INFO to be concatenated with the first
- ;; incomplete line of the next arriving chunk. INCOMPLETE-LINE-INFO
- ;; is an attribute of source; it is created with an empty string
- ;; when the source is computed => (incomplete-line . "")
- (helm-log "incomplete-line-info = %S" (cdr incomplete-line-info))
- (butlast
- (cl-loop for line in lines
- ;; On start `incomplete-line-info' value is empty string.
- for newline = (helm-aif (cdr incomplete-line-info)
- (prog1
- (concat it line)
- (setcdr incomplete-line-info nil))
- line)
- collect newline
- ;; Store last incomplete line (last chunk truncated) until
- ;; new output arrives. Previously storing 'line' in
- ;; incomplete-line-info assumed output was truncated in
- ;; only two chunks. But output could be large and
- ;; truncated in more than two chunks. Therefore store
- ;; 'newline' to contain the previous chunks (Issue #1187).
- finally do (setcdr incomplete-line-info newline))))
-
-(defun helm-output-filter--post-process ()
- (let ((src (helm-get-current-source)))
- (helm-log-run-hook 'helm-update-hook)
- (helm-aif (get-buffer-window helm-buffer 'visible)
- (with-selected-window it
- (helm-skip-noncandidate-line 'next)
- (helm-mark-current-line)
- (helm-display-mode-line src)
- (helm-log-run-hook 'helm-after-update-hook)))))
-
-(defun helm-process-deferred-sentinel-hook (process event file)
- "Defer remote processes in sentinels.
-Meant to be called at the beginning of a sentinel process
-function."
- (when (and (not (zerop helm-tramp-connection-min-time-diff))
- (string= event "finished\n")
- (or (file-remote-p file)
- ;; `helm-suspend-update-flag'
- ;; is non-`nil' here only during a
- ;; running process, this will never be called
- ;; when user set it explicitly with `C-!'.
- helm-suspend-update-flag))
- (setq helm-suspend-update-flag t)
- ;; Kill the process but don't delete entry in
- ;; `helm-async-processes'.
- (helm-kill-async-process process)
- ;; When tramp opens the same connection twice in less than 5
- ;; seconds, it throws 'suppress, which calls the real-handler on
- ;; the main "Emacs". To avoid this [1] helm waits for 5 seconds
- ;; before updates yet allows user input during this delay. [1] In
- ;; recent Emacs versions, this has been fixed so tramp returns nil
- ;; in such conditions. Note: `tramp-connection-min-time-diff' cannot
- ;; have values less than 5 seconds otherwise the process dies.
- (run-at-time helm-tramp-connection-min-time-diff
- nil (lambda ()
- (when helm-alive-p ; Don't run timer fn after quit.
- (setq helm-suspend-update-flag nil)
- (helm-check-minibuffer-input))))))
-
-(defun helm-kill-async-processes ()
- "Kill all asynchronous processes registered in `helm-async-processes'."
- (while helm-async-processes
- (helm-kill-async-process (caar helm-async-processes))
- (setq helm-async-processes (cdr helm-async-processes))))
-
-(defun helm-kill-async-process (process)
- "Stop output from `helm-output-filter' and kill associated PROCESS."
- (set-process-filter process nil)
- (delete-process process))
-
-\f
-;;; Core: action
-;;
-(defun helm-execute-selection-action ()
- "Execute current action."
- (helm-log-run-hook 'helm-before-action-hook)
- ;; Position can be change when `helm-current-buffer'
- ;; is split, so jump to this position before executing action.
- (helm-current-position 'restore)
- (prog1 (helm-execute-selection-action-1)
- (helm-log-run-hook 'helm-after-action-hook)))
-
-(defun helm-execute-selection-action-1 (&optional
- selection action
- preserve-saved-action)
- "Execute ACTION on current SELECTION.
-If PRESERVE-SAVED-ACTION is non-`nil', then save the action."
- (helm-log "executing action")
- (setq action (helm-get-default-action
- (or action
- helm-saved-action
- (if (get-buffer helm-action-buffer)
- (helm-get-selection helm-action-buffer)
- (helm-get-actions-from-current-source)))))
- (helm-aif (get-buffer helm-action-buffer)
- (kill-buffer it))
- (let ((source (or helm-saved-current-source
- (helm-get-current-source)))
- non-essential)
- (setq selection (helm-coerce-selection
- (or selection
- helm-saved-selection
- (helm-get-selection)
- (and (assoc 'accept-empty source) ""))
- source))
- (unless preserve-saved-action (setq helm-saved-action nil))
- (when (and selection action) (funcall action selection))))
-
-(defun helm-coerce-selection (selection source)
- "Apply coerce attribute function to SELECTION in SOURCE.
-Coerce source with coerce function."
- (helm-aif (assoc-default 'coerce source)
- (helm-funcall-with-source source it selection)
- selection))
-
-(defun helm-get-default-action (action)
- "Get the first ACTION value of action list in source."
- (if (and (listp action) (not (functionp action)))
- (cdar action)
- action))
-
-(defun helm-select-action ()
- "Select an action for the currently selected candidate.
-If action buffer is selected, back to the helm buffer."
- (interactive)
- (with-helm-alive-p
- (helm-log-run-hook 'helm-select-action-hook)
- (setq helm-saved-selection (helm-get-selection))
- (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 (helm-get-current-source))
- (let ((actions (helm-get-actions-from-current-source)))
- (if (functionp actions)
- (message "Sole action: %s" 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-display-mode-line (helm-get-current-source))
- (run-hooks 'helm-window-configuration-hook)))))
-(put 'helm-select-action 'helm-only t)
-
-(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 (make-local-variable 'helm-sources)
- (list
- (helm-build-sync-source "Actions"
- :volatile t
- :nomark t
- :keymap 'helm-map
- :candidates actions
- :mode-line '("Action(s)" "TAB:BackToCands RET/f1/f2/fn:NthAct")
- :candidate-transformer
- (lambda (candidates)
- (cl-loop for (i . j) in candidates
- for count from 1
- collect
- (cons (concat (cond ((> count 12)
- " ")
- ((< count 10)
- (format "[f%s] " count))
- (t (format "[f%s] " count)))
- (propertize i 'face 'helm-action))
- j)))
- :candidate-number-limit nil)))
- (set (make-local-variable 'helm-source-filter) nil)
- (set (make-local-variable 'helm-selection-overlay) nil)
- (helm-initialize-overlays helm-action-buffer)))
-
-\f
-;; Core: selection
-
-(defun helm-display-source-at-screen-top-maybe (unit)
- "Display source at the top of screen when UNIT value is 'source.
-Returns nil for any other value of UNIT."
- (when (and helm-display-source-at-screen-top (eq unit 'source))
- (set-window-start (selected-window)
- (save-excursion (forward-line -1) (point)))))
-
-(defun helm-skip-noncandidate-line (direction)
- "Skip source header or candidates separator when going in DIRECTION.
-DIRECTION is either 'next or 'previous.
-Same as `helm-skip-header-and-separator-line' but ensure
-point is moved to the right place when at bop or eob."
- (helm-skip-header-and-separator-line direction)
- (and (bobp) (forward-line 1)) ; Skip first header.
- (and (eobp) (forward-line -1))) ; Avoid last empty line.
-
-(defun helm-skip-header-and-separator-line (direction)
- "Skip source header or candidate separator when going to next/previous line.
-DIRECTION is either 'next or 'previous."
- (let ((fn (cl-ecase direction
- (next 'eobp)
- (previous 'bobp))))
- (while (and (not (funcall fn))
- (or (helm-pos-header-line-p)
- (helm-pos-candidate-separator-p)))
- (forward-line (if (and (eq direction 'previous)
- (not (eq (point-at-bol) (point-min))))
- -1 1)))))
-
-(defun helm-display-mode-line (source &optional force)
- "Setup mode-line and header-line for `helm-buffer'."
- (set (make-local-variable 'helm-mode-line-string)
- (helm-interpret-value (or (and (listp source) ; Check if source is empty.
- (assoc-default 'mode-line source))
- (default-value 'helm-mode-line-string))
- source))
- (let ((follow (and (eq (cdr (assq 'follow source)) 1) " (HF)"))
- (marked (and helm-marked-candidates
- (cl-loop with cur-name = (assoc-default 'name source)
- for c in helm-marked-candidates
- for name = (assoc-default 'name (car c))
- when (string= name cur-name)
- collect c))))
- ;; Setup mode-line.
- (if helm-mode-line-string
- (setq mode-line-format
- `(" " mode-line-buffer-identification " "
- (:eval (format "L%-3d" (helm-candidate-number-at-point)))
- ,follow
- (:eval ,(and marked
- (concat
- " "
- (propertize
- (format "M%d" (length marked))
- 'face 'helm-visible-mark))))
- (:eval (when ,helm--mode-line-display-prefarg
- (let ((arg (prefix-numeric-value
- (or prefix-arg current-prefix-arg))))
- (unless (= arg 1)
- (propertize (format " [prefarg:%s]" arg)
- 'face 'helm-prefarg)))))
- " "
- (:eval (helm-show-candidate-number
- (car-safe helm-mode-line-string)))
- " " helm--mode-line-string-real " " mode-line-end-spaces)
- helm--mode-line-string-real
- (substitute-command-keys (if (listp helm-mode-line-string)
- (cadr helm-mode-line-string)
- helm-mode-line-string)))
- (setq mode-line-format (default-value 'mode-line-format)))
- ;; Setup header-line.
- (cond (helm-echo-input-in-header-line
- (setq force t)
- (helm--set-header-line))
- (helm-display-header-line
- (let ((hlstr (helm-interpret-value
- (and (listp source)
- (assoc-default 'header-line source))
- source))
- (endstr (make-string (window-width) ? )))
- (setq header-line-format
- (propertize (concat " " hlstr endstr)
- 'face 'helm-header))))))
- (when force (force-mode-line-update)))
-
-(defun helm--set-header-line (&optional update)
- (with-selected-window (minibuffer-window)
- (let* ((beg (save-excursion (vertical-motion 0 (helm-window)) (point)))
- (end (save-excursion (end-of-visual-line) (point)))
- ;; The visual line where the cursor is.
- (cont (buffer-substring beg end))
- (pref (propertize
- " "
- 'display (if (string-match-p (regexp-quote helm--prompt) cont)
- '(space :width left-fringe)
- (propertize
- "->"
- 'face 'helm-header-line-left-margin))))
- (pos (- (point) beg)))
- (with-helm-buffer
- (setq header-line-format (concat pref cont " "))
- (put-text-property
- ;; Increment pos to handle the space before prompt (i.e `pref').
- (1+ pos) (+ 2 pos)
- 'face ;don't just use 'cursor; this can hide the current character
- (list :inverse-video t
- :foreground (face-background 'cursor)
- :background (face-background 'default))
- header-line-format)
- (when update (force-mode-line-update))))))
-
-(defun helm--update-header-line ()
- ;; This should be used in `post-command-hook',
- ;; nowhere else.
- (when (with-helm-buffer helm-echo-input-in-header-line)
- (helm--set-header-line t)))
-
-(defun helm-hide-minibuffer-maybe ()
- "Hide minibuffer contents in a Helm session.
-This function should normally go to `helm-minibuffer-set-up-hook'.
-It has no effect if `helm-echo-input-in-header-line' is nil."
- (when (with-helm-buffer helm-echo-input-in-header-line)
- (let ((ov (make-overlay (point-min) (point-max) nil nil t)))
- (overlay-put ov 'window (selected-window))
- (overlay-put ov 'face (let ((bg-color (face-background 'default nil)))
- `(:background ,bg-color :foreground ,bg-color)))
- (setq cursor-type nil))))
-
-(defun helm-show-candidate-number (&optional name)
- "Used to display candidate number in mode-line.
-You can specify NAME of candidates e.g \"Buffers\" otherwise
-it is \"Candidate\(s\)\" by default."
- (when helm-alive-p
- (unless (helm-empty-source-p)
- ;; Build a fixed width string when candidate-number < 1000
- (let* ((cand-name (or name "Candidate(s)"))
- (width (length (format "[999 %s]" cand-name))))
- (propertize
- (format (concat "%-" (number-to-string width) "s")
- (format "[%s %s]"
- (helm-get-candidate-number 'in-current-source)
- cand-name))
- 'face 'helm-candidate-number)))))
-
-(cl-defun helm-move-selection-common (&key where direction)
- "Move the selection marker to a new position.
-Position is determined by WHERE and DIRECTION.
-Key arg WHERE can be one of:
- - line
- - page
- - edge
- - source
-Key arg DIRECTION can be one of:
- - previous
- - next
- - A source or a source name when used with :WHERE 'source."
- (let ((move-func (cl-case where
- (line (cl-ecase direction
- (previous 'helm-move--previous-line-fn)
- (next 'helm-move--next-line-fn)))
- (page (cl-ecase direction
- (previous 'helm-move--previous-page-fn)
- (next 'helm-move--next-page-fn)))
- (edge (cl-ecase direction
- (previous 'helm-move--beginning-of-buffer-fn)
- (next 'helm-move--end-of-buffer-fn)))
- (source (cl-case direction
- (previous 'helm-move--previous-source-fn)
- (next 'helm-move--next-source-fn)
- (t (lambda () ; A source is passed as DIRECTION arg.
- (helm-move--goto-source-fn direction))))))))
- (unless (or (helm-empty-buffer-p (helm-buffer-get))
- (not (helm-window)))
- (with-helm-window
- (helm-log-run-hook 'helm-move-selection-before-hook)
- (funcall move-func)
- (and (memq direction '(next previous))
- (helm-skip-noncandidate-line direction))
- (when (helm-pos-multiline-p)
- (helm-move--beginning-of-multiline-candidate))
- (helm-display-source-at-screen-top-maybe where)
- (when (helm-get-previous-header-pos)
- (helm-mark-current-line))
- (helm-display-mode-line (helm-get-current-source))
- (helm-log-run-hook 'helm-move-selection-after-hook)))))
-
-(defun helm-move--beginning-of-multiline-candidate ()
- (let ((header-pos (helm-get-previous-header-pos))
- (separator-pos (helm-get-previous-candidate-separator-pos)))
- (when header-pos
- (goto-char (if (or (null separator-pos)
- (< separator-pos header-pos))
- header-pos
- separator-pos))
- (forward-line 1))))
-
-(defun helm-move--previous-multi-line-fn ()
- (forward-line -1)
- (unless (helm-pos-header-line-p)
- (helm-skip-header-and-separator-line 'previous)
- (helm-move--beginning-of-multiline-candidate)))
-
-(defun helm-move--previous-line-fn ()
- (if (not (helm-pos-multiline-p))
- (forward-line -1)
- (helm-move--previous-multi-line-fn))
- (when (and helm-move-to-line-cycle-in-source
- (helm-pos-header-line-p))
- (forward-line 1)
- (helm-move--end-of-source)
- ;; We are at end of helm-buffer
- ;; check if last candidate is a multiline candidate
- ;; and jump to it
- (when (and (eobp)
- (save-excursion (forward-line -1) (helm-pos-multiline-p)))
- (helm-move--previous-multi-line-fn))))
-
-(defun helm-move--next-multi-line-fn ()
- (let ((header-pos (helm-get-next-header-pos))
- (separator-pos (helm-get-next-candidate-separator-pos)))
- (cond ((and separator-pos
- (or (null header-pos) (< separator-pos header-pos)))
- (goto-char separator-pos))
- (header-pos
- (goto-char header-pos)))))
-
-(defun helm-move--next-line-fn ()
- (if (not (helm-pos-multiline-p))
- (forward-line 1)
- (helm-move--next-multi-line-fn))
- (when (and helm-move-to-line-cycle-in-source
- (or (save-excursion (and (helm-pos-multiline-p)
- (goto-char (overlay-end
- helm-selection-overlay))
- (helm-end-of-source-p t)))
- (helm-end-of-source-p t)))
- (helm-move--beginning-of-source)))
-
-(defun helm-move--previous-page-fn ()
- (condition-case nil
- (scroll-down)
- (beginning-of-buffer (goto-char (point-min)))))
-
-(defun helm-move--next-page-fn ()
- (condition-case nil
- (scroll-up)
- (end-of-buffer (goto-char (point-max)))))
-
-(defun helm-move--beginning-of-buffer-fn ()
- (goto-char (point-min)))
-
-(defun helm-move--end-of-buffer-fn ()
- (goto-char (point-max)))
-
-(defun helm-move--end-of-source ()
- (goto-char (or (helm-get-next-header-pos) (point-max)))
- (when (helm-pos-header-line-p) (forward-line -2)))
-
-(defun helm-move--beginning-of-source ()
- (goto-char (helm-get-previous-header-pos))
- (forward-line 1))
-
-(defun helm-move--previous-source-fn ()
- (forward-line -1)
- (if (bobp)
- (goto-char (point-max))
- (helm-skip-header-and-separator-line 'previous))
- (goto-char (helm-get-previous-header-pos))
- (forward-line 1))
-
-(defun helm-move--next-source-fn ()
- (goto-char (or (and (not (save-excursion
- (forward-line 1) (eobp)))
- ;; Empty source at eob are just
- ;; not displayed unless they are dummy.
- ;; Issue #1117.
- (helm-get-next-header-pos))
- (point-min))))
-
-(defun helm-move--goto-source-fn (source-or-name)
- (goto-char (point-min))
- (let ((name (if (stringp source-or-name) source-or-name
- (assoc-default 'name source-or-name))))
- (condition-case err
- (while (not (string= name (helm-current-line-contents)))
- (goto-char (helm-get-next-header-pos)))
- (error (helm-log "%S" err)))))
-
-(defun helm-candidate-number-at-point ()
- (if helm-alive-p
- (with-helm-buffer
- (or (get-text-property (point) 'helm-cand-num) 1))
- (or (get-text-property (point) 'helm-cand-num) 1)))
-
-(defun helm--next-or-previous-line (direction &optional arg)
- ;; Be sure to not use this in non--interactives calls.
- (let ((helm-move-to-line-cycle-in-source
- (and helm-move-to-line-cycle-in-source arg)))
- (if (and arg (> arg 1))
- (cl-loop with pos = (helm-candidate-number-at-point)
- with cand-num = (helm-get-candidate-number t)
- with iter = (min arg (if (eq direction 'next)
- (- cand-num pos)
- (min arg (1- pos))))
- for count from 1
- while (<= count iter)
- do
- (helm-move-selection-common :where 'line :direction direction))
- (helm-move-selection-common :where 'line :direction direction))))
-
-(defun helm-previous-line (&optional arg)
- "Move selection to the ARG previous line(s).
-Same behavior as `helm-next-line' when called with a numeric prefix arg."
- (interactive "p")
- (with-helm-alive-p
- (helm--next-or-previous-line 'previous arg)))
-(put 'helm-previous-line 'helm-only t)
-
-(defun helm-next-line (&optional arg)
- "Move selection to the next ARG line(s).
-When numeric prefix arg is > than the number of candidates, then
-move to the last candidate of current source (i.e. don't move to
-next source)."
- (interactive "p")
- (with-helm-alive-p
- (helm--next-or-previous-line 'next arg)))
-(put 'helm-next-line 'helm-only t)
-
-(defun helm-previous-page ()
- "Move selection back with a pageful."
- (interactive)
- (with-helm-alive-p
- (helm-move-selection-common :where 'page :direction 'previous)))
-(put 'helm-previous-page 'helm-only t)
-
-(defun helm-next-page ()
- "Move selection forward with a pageful."
- (interactive)
- (with-helm-alive-p
- (helm-move-selection-common :where 'page :direction 'next)))
-(put 'helm-next-page 'helm-only t)
-
-(defun helm-beginning-of-buffer ()
- "Move selection at the top."
- (interactive)
- (with-helm-alive-p
- (helm-move-selection-common :where 'edge :direction 'previous)))
-(put 'helm-beginning-of-buffer 'helm-only t)
-
-(defun helm-end-of-buffer ()
- "Move selection at the bottom."
- (interactive)
- (with-helm-alive-p
- (helm-move-selection-common :where 'edge :direction 'next)))
-(put 'helm-end-of-buffer 'helm-only t)
-
-(defun helm-previous-source ()
- "Move selection to the previous source."
- (interactive)
- (with-helm-alive-p
- (helm-move-selection-common :where 'source :direction 'previous)))
-(put 'helm-previous-source 'helm-only t)
-
-(defun helm-next-source ()
- "Move selection to the next source."
- (interactive)
- (with-helm-alive-p
- (helm-move-selection-common :where 'source :direction 'next)))
-(put 'helm-next-source 'helm-only t)
-
-(defun helm-goto-source (source-or-name)
- "Move the selection to the source SOURCE-OR-NAME."
- (helm-move-selection-common :where 'source :direction source-or-name))
-
-(defun helm--follow-action (arg)
- (let ((helm--temp-follow-flag t))
- (when (or (eq last-command 'helm-follow-action-forward)
- (eq last-command 'helm-follow-action-backward)
- (eq last-command 'helm-execute-persistent-action))
- (if (> arg 0)
- (helm-next-line 1)
- (helm-previous-line 1)))
- (helm-execute-persistent-action)))
-
-(defun helm-follow-action-forward ()
- "Go to next line and execute persistent action."
- (interactive)
- (with-helm-alive-p (helm--follow-action 1)))
-(put 'helm-follow-action-forward 'helm-only t)
-
-(defun helm-follow-action-backward ()
- "Go to previous line and execute persistent action."
- (interactive)
- (with-helm-alive-p (helm--follow-action -1)))
-(put 'helm-follow-action-backward 'helm-only t)
-
-(defun helm-mark-current-line (&optional resumep)
- "Move `helm-selection-overlay' to current line.
-Note that this is unrelated to visible marks used for marking
-candidates."
- (with-helm-window
- (when resumep
- (goto-char helm-selection-point))
- (move-overlay
- helm-selection-overlay (point-at-bol)
- (if (helm-pos-multiline-p)
- (let ((header-pos (helm-get-next-header-pos))
- (separator-pos (helm-get-next-candidate-separator-pos)))
- (or (and (null header-pos) separator-pos)
- (and header-pos separator-pos
- (< separator-pos header-pos)
- separator-pos)
- header-pos
- (point-max)))
- (1+ (point-at-eol))))
- (setq helm-selection-point (overlay-start helm-selection-overlay)))
- (helm-follow-execute-persistent-action-maybe))
-
-(defun helm-confirm-and-exit-minibuffer ()
- "Maybe ask for confirmation when exiting helm.
-It is similar to `minibuffer-complete-and-exit' adapted to helm.
-If `minibuffer-completion-confirm' value is 'confirm,
-send minibuffer confirm message and exit on next hit.
-If `minibuffer-completion-confirm' value is t,
-don't exit and send message 'no match'."
- (interactive)
- (with-helm-alive-p
- (if (and (helm--updating-p)
- (null helm--reading-passwd-or-string))
- (progn (message "[Display not ready]")
- (sit-for 0.5) (message nil))
- (let* ((empty-buffer-p (with-current-buffer helm-buffer
- (eq (point-min) (point-max))))
- (sel (helm-get-selection))
- (unknown (and (not empty-buffer-p)
- (string= (get-text-property
- 0 'display
- (helm-get-selection nil 'withprop))
- "[?]"))))
- (cond ((and (or empty-buffer-p unknown)
- (eq minibuffer-completion-confirm 'confirm))
- (setq helm-minibuffer-confirm-state
- 'confirm)
- (setq minibuffer-completion-confirm nil)
- (minibuffer-message " [confirm]"))
- ((and (or empty-buffer-p
- (unless (if minibuffer-completing-file-name
- (and minibuffer-completion-predicate
- (funcall minibuffer-completion-predicate sel))
- (and (stringp sel)
- ;; SEL may be a cons cell when helm-comp-read
- ;; is called directly with a collection composed
- ;; of (display . real) and real is a cons cell.
- (try-completion sel minibuffer-completion-table
- minibuffer-completion-predicate)))
- unknown))
- (eq minibuffer-completion-confirm t))
- (minibuffer-message " [No match]"))
- (t
- (setq helm-minibuffer-confirm-state nil)
- (helm-exit-minibuffer)))))))
-(put 'helm-confirm-and-exit-minibuffer 'helm-only t)
-
-(add-hook 'helm-after-update-hook 'helm-confirm-and-exit-hook)
-
-(defun helm-confirm-and-exit-hook ()
- "Restore `minibuffer-completion-confirm' when helm update."
- (unless (or (eq minibuffer-completion-confirm t)
- (not helm-minibuffer-confirm-state))
- (setq minibuffer-completion-confirm
- helm-minibuffer-confirm-state)))
-
-(defun helm-read-string (prompt &optional initial-input history
- default-value inherit-input-method)
- "Same as `read-string' but for reading string from a helm session."
- (let ((helm--reading-passwd-or-string t))
- (read-string
- prompt initial-input history default-value inherit-input-method)))
-
-(defun helm--updating-p ()
- ;; helm timer is between two cycles.
- ;; IOW `helm-check-minibuffer-input' haven't yet compared input
- ;; and `helm-pattern'.
- (or (not (equal (minibuffer-contents) helm-pattern))
- ;; `helm-check-minibuffer-input' have launched `helm-update'.
- helm--in-update))
-
-(defun helm-maybe-exit-minibuffer ()
- (interactive)
- (with-helm-alive-p
- (if (and (helm--updating-p)
- (null helm--reading-passwd-or-string))
- (progn (message "[Display not ready]")
- (sit-for 0.5) (message nil))
- (helm-exit-minibuffer))))
-(put 'helm-maybe-exit-minibuffer 'helm-only t)
-
-(defun helm-exit-minibuffer ()
- "Select the current candidate by exiting the minibuffer."
- (unless helm-current-prefix-arg
- (setq helm-current-prefix-arg current-prefix-arg))
- (setq helm-exit-status 0)
- (helm-log-run-hook 'helm-exit-minibuffer-hook)
- (exit-minibuffer))
-
-(defun helm-keyboard-quit ()
- "Quit minibuffer in helm.
-If action buffer is displayed, kill it."
- (interactive)
- (with-helm-alive-p
- (when (get-buffer-window helm-action-buffer 'visible)
- (kill-buffer helm-action-buffer))
- (setq helm-exit-status 1)
- (abort-recursive-edit)))
-(put 'helm-keyboard-quit 'helm-only t)
-
-(defun helm-get-next-header-pos ()
- "Return the position of the next header from point."
- (next-single-property-change (point) 'helm-header))
-
-(defun helm-get-previous-header-pos ()
- "Return the position of the previous header from point."
- (previous-single-property-change (point) 'helm-header))
-
-(defun helm-pos-multiline-p ()
- "Return non-`nil' if the current position is in the multiline source region."
- (get-text-property (point) 'helm-multiline))
-
-(defun helm-get-next-candidate-separator-pos ()
- "Return the position of the next candidate separator from point."
- (let ((hp (helm-get-next-header-pos)))
- (helm-aif (next-single-property-change (point) 'helm-candidate-separator)
- (or
- ;; Be sure we don't catch
- ;; the separator of next source.
- (and hp (< it hp) it)
- ;; The separator found is in next source
- ;; we are at last cand, so use the header pos.
- (and hp (< hp it) hp)
- ;; A single source, just try next separator.
- it))))
-
-(defun helm-get-previous-candidate-separator-pos ()
- "Return the position of the previous candidate separator from point."
- (previous-single-property-change (point) 'helm-candidate-separator))
-
-(defun helm-pos-header-line-p ()
- "Return t if the current line is a header line."
- (or (get-text-property (point-at-bol) 'helm-header)
- (get-text-property (point-at-bol) 'helm-header-separator)))
-
-(defun helm-pos-candidate-separator-p ()
- "Return t if the current line is a candidate separator."
- (get-text-property (point-at-bol) 'helm-candidate-separator))
-
-\f
-;;; Debugging
-;;
-;;
-(defun helm-debug-output ()
- "Show all helm-related variables at this time."
- (interactive)
- (with-helm-alive-p
- (helm-help-internal " *Helm Debug*" 'helm-debug-output-function)))
-(put 'helm-debug-output 'helm-only t)
-
-(defun helm-debug-output-function (&optional vars)
- (message "Calculating all helm-related values...")
- (insert "If you debug some variables or forms, set `helm-debug-variables'
-to a list of forms.\n\n")
- (cl-dolist (v (or vars
- helm-debug-variables
- (apropos-internal "^helm-" 'boundp)))
- (insert "** "
- (pp-to-string v) "\n"
- (pp-to-string (with-current-buffer helm-buffer (eval v))) "\n"))
- (message "Calculating all helm-related values...Done"))
-
-;;;###autoload
-(defun helm-debug-toggle ()
- "Enable/disable helm debugging from outside of helm session."
- (interactive)
- (setq helm-debug (not helm-debug))
- (message "Helm Debug is now %s"
- (if helm-debug "Enabled" "Disabled")))
-
-(defun helm-enable-or-switch-to-debug ()
- "First hit enable helm debugging, second hit switch to debug buffer."
- (interactive)
- (with-helm-alive-p
- (if helm-debug
- (helm-run-after-exit
- #'helm-debug-open-last-log)
- (setq helm-debug t)
- (with-helm-buffer (setq truncate-lines nil))
- (message "Debugging enabled"))))
-(put 'helm-enable-or-switch-to-debug 'helm-only t)
-
-\f
-;; Core: misc
-(defun helm-kill-buffer-hook ()
- "Remove tick entry from `helm-tick-hash' and remove buffer from
-`helm-buffers' when killing a buffer."
- (cl-loop for key being the hash-keys in helm-tick-hash
- if (string-match (format "^%s/" (regexp-quote (buffer-name))) key)
- do (remhash key helm-tick-hash))
- (setq helm-buffers (remove (buffer-name) helm-buffers)))
-(add-hook 'kill-buffer-hook 'helm-kill-buffer-hook)
-
-(defun helm-preselect (candidate-or-regexp &optional source)
- "Move `helm-selection-overlay' to CANDIDATE-OR-REGEXP on startup.
-Arg CANDIDATE-OR-REGEXP can be a string or a cons cell of two
-strings. When cons cell, helm tries jumping to first element of
-cons cell and then to the second, and so on. This allows finer
-preselection if there are duplicates before the candidate we
-want to preselect."
- (with-helm-window
- (when candidate-or-regexp
- (if (and helm-force-updating-p source)
- (helm-goto-source source)
- (goto-char (point-min))
- (forward-line 1))
- (if (functionp candidate-or-regexp)
- (funcall candidate-or-regexp)
- (let ((start (point)) mp)
- (helm-awhile (if (consp candidate-or-regexp)
- (and (re-search-forward (car candidate-or-regexp) nil t)
- (re-search-forward (cdr candidate-or-regexp) nil t))
- (re-search-forward candidate-or-regexp nil t))
- ;; If search fall on an header line continue loop
- ;; until it match or fail (Issue #1509).
- (unless (helm-pos-header-line-p) (cl-return (setq mp it))))
- (goto-char (or mp start)))))
- (forward-line 0) ; Avoid scrolling right on long lines.
- (when (helm-pos-multiline-p)
- (helm-move--beginning-of-multiline-candidate))
- (when (helm-pos-header-line-p) (forward-line 1))
- (helm-mark-current-line)
- (helm-display-mode-line (helm-get-current-source))
- (helm-log-run-hook 'helm-after-preselection-hook)))
-
-(defun helm-delete-current-selection ()
- "Delete the currently selected item."
- (with-helm-window
- (cond ((helm-pos-multiline-p)
- (helm-aif (helm-get-next-candidate-separator-pos)
- (delete-region (point-at-bol)
- (1+ (progn (goto-char it) (point-at-eol))))
- ;; last candidate
- (goto-char (helm-get-previous-candidate-separator-pos))
- (delete-region (point-at-bol) (point-max)))
- (when (helm-end-of-source-p)
- (goto-char (or (helm-get-previous-candidate-separator-pos)
- (point-min)))
- (forward-line 1)))
- (t
- (delete-region (point-at-bol) (1+ (point-at-eol)))
- (when (helm-end-of-source-p t)
- (let ((headp (save-excursion
- (forward-line -1)
- (not (helm-pos-header-line-p)))))
- (and headp (forward-line -1))))))
- (unless (helm-end-of-source-p t)
- (helm-mark-current-line))))
-
-(defun helm-end-of-source-p (&optional at-point)
- "Return non-`nil' if we are at eob or end of source."
- (save-excursion
- (if (and (helm-pos-multiline-p) (null at-point))
- (null (helm-get-next-candidate-separator-pos))
- (forward-line (if at-point 0 1))
- (or (eq (point-at-bol) (point-at-eol))
- (helm-pos-header-line-p)
- (eobp)))))
-
-(defun helm-beginning-of-source-p (&optional at-point)
- "Return non-`nil' if we are at bob or beginning of source."
- (save-excursion
- (if (and (helm-pos-multiline-p) (null at-point))
- (null (helm-get-previous-candidate-separator-pos))
- (forward-line (if at-point 0 -1))
- (or (eq (point-at-bol) (point-at-eol))
- (helm-pos-header-line-p)
- (bobp)))))
-
-(defun helm-edit-current-selection-internal (func)
- (with-helm-window
- (forward-line 0)
- (let ((realvalue (get-text-property (point) 'helm-realvalue))
- (multiline (get-text-property (point) 'helm-multiline)))
- (funcall func)
- (forward-line 0)
- (and realvalue
- (put-text-property (point) (point-at-eol)
- 'helm-realvalue realvalue))
- (and multiline
- (put-text-property (point) (point-at-eol)
- 'helm-multiline multiline))
- (helm-mark-current-line))))
-
-(defmacro helm-edit-current-selection (&rest forms)
- "Evaluate FORMS at current selection in the helm buffer.
-Used generally to modify current selection."
- (declare (indent 0) (debug t))
- `(helm-edit-current-selection-internal
- (lambda () ,@forms)))
-
-(defun helm--delete-minibuffer-contents-from (from-str)
- ;; Giving an empty string value to FROM-STR delete all.
- (let ((input (minibuffer-contents)))
- (helm-reset-yank-point)
- (if (> (length input) 0)
- ;; minibuffer is not empty, delete contents from end
- ;; of FROM-STR and update.
- (helm-set-pattern from-str)
- ;; minibuffer is already empty, force update.
- (helm-force-update))))
-
-(defun helm-delete-minibuffer-contents (&optional arg)
- "Delete minibuffer contents.
-When `helm-delete-minibuffer-contents-from-point' is non-`nil',
-delete minibuffer contents from point instead of deleting all.
-Giving a prefix arg reverses this behavior.
-When at the end of minibuffer, deletes all."
- (interactive "P")
- (let ((str (if helm-delete-minibuffer-contents-from-point
- (if (or arg (eobp))
- "" (helm-minibuffer-completion-contents))
- (if (and arg (not (eobp)))
- (helm-minibuffer-completion-contents) ""))))
- (helm--delete-minibuffer-contents-from str)))
-
-\f
-;;; Plugins (Deprecated in favor of helm-types)
-;;
-;; i.e Inherit instead of helm-type-* classes in your own classes.
-
-;; [DEPRECATED] Enable multi-match by default in old sources.
-;; This is deprecated and will not run in sources
-;; created by helm-source.
-;; Keep it for backward compatibility with old sources.
-(defun helm-compile-source--multi-match (source)
- (if (assoc 'no-matchplugin source)
- source
- (let* ((searchers helm-mm-default-search-functions)
- (defmatch (helm-aif (assoc-default 'match source)
- (helm-mklist it)))
- (defmatch-strict (helm-aif (assoc-default 'match-strict source)
- (helm-mklist it)))
- (defsearch (helm-aif (assoc-default 'search source)
- (helm-mklist it)))
- (defsearch-strict (helm-aif (assoc-default 'search-strict source)
- (helm-mklist it)))
- (matchfns (cond (defmatch-strict)
- (defmatch
- (append helm-mm-default-match-functions defmatch))
- (t helm-mm-default-match-functions)))
- (searchfns (cond (defsearch-strict)
- (defsearch
- (append searchers defsearch))
- (t searchers))))
- `(,(if (assoc 'candidates-in-buffer source)
- `(search ,@searchfns) `(match ,@matchfns))
- ,@source))))
-
-(add-to-list 'helm-compile-source-functions 'helm-compile-source--multi-match)
-
-(defun helm-compile-source--type (source)
- (helm-aif (assoc-default 'type source)
- (append source (assoc-default it helm-type-attributes) nil)
- source))
-
-(defun define-helm-type-attribute (type definition &optional doc)
- "Register type attribute of TYPE as DEFINITION with DOC.
-DOC is displayed in `helm-type-attributes' docstring.
-
-Using this function is better than setting `helm-type-attributes'
-directly."
- (cl-loop for i in definition do
- ;; without `ignore-errors', error at emacs22
- (ignore-errors (setf i (delete nil i))))
- (helm-add-type-attribute type definition)
- (and doc (helm-document-type-attribute type doc))
- nil)
-
-(defun helm-document-attribute (attribute short-doc &optional long-doc)
- "Register ATTRIBUTE documentation introduced by plug-in.
-SHORT-DOC is displayed beside attribute name.
-LONG-DOC is displayed below attribute name and short documentation."
- (declare (indent 2))
- (if long-doc
- (setq short-doc (concat "(" short-doc ")"))
- (setq long-doc short-doc
- short-doc ""))
- (add-to-list 'helm-attributes attribute t)
- (put attribute 'helm-attrdoc
- (concat "- " (symbol-name attribute)
- " " short-doc "\n\n" long-doc "\n")))
-
-(defun helm-add-type-attribute (type definition)
- (helm-aif (assq type helm-type-attributes)
- (setq helm-type-attributes (delete it helm-type-attributes)))
- (push (cons type definition) helm-type-attributes))
-
-(defun helm-document-type-attribute (type doc)
- (add-to-list 'helm-types type t)
- (put type 'helm-typeattrdoc
- (concat "- " (symbol-name type) "\n\n" doc "\n")))
-
-;; Built-in plug-in: dummy
-(defun helm-dummy-candidate (_candidate _source)
- "Use `helm-pattern' as CANDIDATE in SOURCE."
- ;; `source' is defined in filtered-candidate-transformer
- (list helm-pattern))
-
-(defun helm-compile-source--dummy (source)
- (if (assoc 'dummy source)
- (progn
- (unless (helm-attr-defined
- 'filtered-candidate-transformer source)
- (helm-attrset 'filtered-candidate-transformer
- 'helm-dummy-candidate source))
- (append source
- '((candidates "dummy")
- (accept-empty)
- (match identity)
- (volatile))))
- source))
-
-;; Built-in plug-in: candidates-in-buffer
-(defun helm-candidates-in-buffer (&optional source)
- "The top level function used to store candidates in `helm-source-in-buffer'.
-
-Candidates are stored in a buffer generated internally by
-`helm-candidate-buffer' function. Each candidate must be placed
-in one line. This function is meant to be used in
-candidates-in-buffer or candidates attribute of an helm source.
-It is especially fast for many (1000+) candidates.
-
-The buffer is created and fed in the init attribute function of helm.
-
-e.g:
-
- (helm-build-in-buffer-source \"test\"
- :init (lambda ()
- (helm-init-candidates-in-buffer
- 'global '(foo foa fob bar baz))))
-
-A shortcut can be used to simplify:
-
- (helm-build-in-buffer-source \"test\"
- :data '(foo foa fob bar baz))
-
-`candidates-in-buffer' is now deprecated in favor of
-`helm-source-in-buffer' class.
-
-Description provided here for backward compatibility.
-
-By default, `helm' makes candidates by evaluating the
-candidates function, then narrows them by `string-match' for each
-candidate.
-
-But this is slow for large number of candidates. The new way is
-to store all candidates in a buffer and then narrow with
-`re-search-forward'. Search function is customizable by search
-attribute. The important point is that buffer processing is MUCH
-FASTER than string list processing and is the Emacs way.
-
-The init function writes all candidates to a newly-created
-candidate buffer. The candidates buffer is created or specified
-by `helm-candidate-buffer'. Candidates are stored in a line.
-
-The candidates function narrows all candidates, IOW creates a
-subset of candidates dynamically. It is the task of
-`helm-candidates-in-buffer'. As long as
-`helm-candidate-buffer' is used,`(candidates-in-buffer)' is
-sufficient in most cases.
-
-Note that `(candidates-in-buffer)' is shortcut of three attributes:
- (candidates . helm-candidates-in-buffer)
- (volatile)
- (match identity)
-And `(candidates-in-buffer . func)' is shortcut of three attributes:
- (candidates . func)
- (volatile)
- (match identity)
-The expansion is performed in `helm-get-sources'.
-
-The `candidates-in-buffer' attribute implies the volatile attribute.
-The volatile attribute is needed because `helm-candidates-in-buffer'
-creates candidates dynamically and need to be called every time
-`helm-pattern' changes.
-
-Because `helm-candidates-in-buffer' plays the role of `match' attribute
-function, specifying `(match identity)' makes the source slightly faster.
-
-However if source contains `match-part' attribute, match is computed only
-on part of candidate returned by the call of function provided by this attribute.
-The function should have one arg, candidate, and return only
-a specific part of candidate.
-
-To customize `helm-candidates-in-buffer' behavior, use `search',
-`get-line' and `match-part' attributes."
- (let ((src (or source (helm-get-current-source))))
- (helm-candidates-in-buffer-1
- (helm-candidate-buffer)
- helm-pattern
- (or (assoc-default 'get-line src)
- #'buffer-substring-no-properties)
- (or (assoc-default 'search src)
- '(helm-candidates-in-buffer-search-default-fn))
- (helm-candidate-number-limit src)
- (helm-attr 'match-part)
- src)))
-
-(defun helm-candidates-in-buffer-search-default-fn (pattern)
- "Search PATTERN with `re-search-forward' with bound and noerror args."
- (condition-case _err
- (re-search-forward pattern nil t)
- (invalid-regexp nil)))
-
-(defun helm-candidates-in-buffer-1 (buffer pattern get-line-fn
- search-fns limit
- match-part-fn source)
- "Return the list of candidates inserted in BUFFER matching PATTERN."
- ;; buffer == nil when candidates buffer does not exist.
- (when buffer
- (with-current-buffer buffer
- (let ((inhibit-point-motion-hooks t)
- (start-point (1- (point-min))))
- (goto-char start-point)
- (if (string= pattern "")
- (helm-initial-candidates-from-candidate-buffer
- get-line-fn limit)
- (helm-search-from-candidate-buffer
- pattern get-line-fn search-fns limit
- start-point match-part-fn source))))))
-
-
-(defun helm-search-from-candidate-buffer (pattern get-line-fn search-fns
- limit start-point match-part-fn source)
- (let (buffer-read-only)
- (helm--search-from-candidate-buffer-1
- (lambda ()
- (cl-loop with hash = (make-hash-table :test 'equal)
- with allow-dups = (assq 'allow-dups source)
- with case-fold-search = (helm-set-case-fold-search)
- with count = 0
- for iter from 1
- for searcher in search-fns
- do (progn
- (goto-char start-point)
- ;; The character at start-point is a newline,
- ;; if pattern match it that's mean we are
- ;; searching for newline in buffer, in this
- ;; case skip this false line.
- ;; See comment >>>[1] in
- ;; `helm--search-from-candidate-buffer-1'.
- (and (condition-case nil
- (looking-at pattern)
- (invalid-regexp nil))
- (forward-line 1)))
- nconc
- (cl-loop with pos-lst
- while (and (setq pos-lst (funcall searcher pattern))
- (not (eobp))
- (< count limit))
- for cand = (apply get-line-fn
- (if (and pos-lst (listp pos-lst))
- pos-lst
- (list (point-at-bol) (point-at-eol))))
- when (and match-part-fn
- (not (get-text-property 0 'match-part cand)))
- do (setq cand
- (propertize cand 'match-part (funcall match-part-fn cand)))
- for dup = (gethash cand hash)
- when (and (or (and allow-dups dup (= dup iter))
- (null dup))
- (or
- ;; Always collect when cand is matched
- ;; by searcher funcs and match-part attr
- ;; is not present.
- (and (not match-part-fn)
- (not (consp pos-lst)))
- ;; If match-part attr is present, or if SEARCHER fn
- ;; returns a cons cell, collect PATTERN only if it
- ;; match the part of CAND specified by
- ;; the match-part func.
- (helm-search-match-part cand pattern)))
- do (progn
- (puthash cand iter hash)
- (helm--maybe-process-filter-one-by-one-candidate cand source)
- (cl-incf count))
- and collect cand))))))
-
-(defun helm-search-match-part (candidate pattern)
- "Match PATTERN only on part of CANDIDATE returned by MATCH-PART-FN.
-Because `helm-search-match-part' maybe called even if unspecified
-in source (negation), MATCH-PART-FN default to `identity'
-to match whole candidate.
-When using fuzzy matching and negation (i.e \"!\"),
-this function is always called."
- (let ((part (get-text-property 0 'match-part candidate))
- (fuzzy-regexp (cadr (gethash 'helm-pattern helm--fuzzy-regexp-cache)))
- (matchfn (if helm-migemo-mode
- 'helm-mm-migemo-string-match 'string-match)))
- (if (string-match " " pattern)
- (cl-loop for i in (split-string pattern) always
- (if (string-match "\\`!" i)
- (not (funcall matchfn (substring i 1) part))
- (funcall matchfn i part)))
- (if (string-match "\\`!" pattern)
- (if helm--in-fuzzy
- ;; Fuzzy regexp have already been
- ;; computed with substring 1.
- (not (string-match fuzzy-regexp part))
- (not (funcall matchfn (substring pattern 1) part)))
- (funcall matchfn (if helm--in-fuzzy fuzzy-regexp pattern) part)))))
-
-(defun helm-initial-candidates-from-candidate-buffer (get-line-fn limit)
- (delq nil (cl-loop for i from 1 to limit
- until (eobp)
- collect (funcall get-line-fn
- (point-at-bol) (point-at-eol))
- do (forward-line 1))))
-
-(defun helm--search-from-candidate-buffer-1 (search-fn)
- ;; We are adding a newline at bob and at eol
- ;; and removing these newlines afterward.
- ;; This is a bad hack that should be removed.
- ;; To avoid matching the empty line at first line
- ;; when searching with e.g occur and "^$" just
- ;; forward-line before searching (See >>>[1] above).
- (goto-char (point-min))
- (insert "\n")
- (goto-char (point-max))
- (insert "\n")
- (unwind-protect
- (funcall search-fn)
- (goto-char (point-min))
- (delete-char 1)
- (goto-char (1- (point-max)))
- (delete-char 1)
- (set-buffer-modified-p nil)))
-
-(defun helm-candidate-buffer (&optional create-or-buffer)
- "Register and return a buffer containing candidates of current source.
-`helm-candidate-buffer' searches buffer-local candidates buffer first,
-then global candidates buffer.
-
-Acceptable values of CREATE-OR-BUFFER:
-
-- nil (omit)
- Only return the candidates buffer.
-- a buffer
- Register a buffer as a candidates buffer.
-- 'global
- Create a new global candidates buffer,
- named \" *helm candidates:SOURCE*\".
-- other non-`nil' value
- Create a new local candidates buffer,
- named \" *helm candidates:SOURCE*HELM-CURRENT-BUFFER\"."
- (let* ((global-bname (format " *helm candidates:%s*"
- helm-source-name))
- (local-bname (format " *helm candidates:%s*%s"
- helm-source-name
- (buffer-name helm-current-buffer)))
- (register-func
- (lambda ()
- (setq helm-candidate-buffer-alist
- (cons (cons helm-source-name create-or-buffer)
- (delete (assoc helm-source-name
- helm-candidate-buffer-alist)
- helm-candidate-buffer-alist)))))
- (kill-buffers-func
- (lambda ()
- (cl-loop for b in (buffer-list)
- if (string-match (format "^%s" (regexp-quote global-bname))
- (buffer-name b))
- do (kill-buffer b))))
- (create-func
- (lambda ()
- (with-current-buffer
- (get-buffer-create (if (eq create-or-buffer 'global)
- global-bname
- local-bname))
- (set (make-local-variable 'inhibit-read-only) t) ; Fix (#1176)
- (buffer-disable-undo)
- (erase-buffer)
- (font-lock-mode -1))))
- (return-func
- (lambda ()
- (or (get-buffer local-bname)
- (get-buffer global-bname)
- (helm-aif (assoc-default helm-source-name
- helm-candidate-buffer-alist)
- (and (buffer-live-p it) it))))))
- (when create-or-buffer
- (funcall register-func)
- (unless (bufferp create-or-buffer)
- (and (eq create-or-buffer 'global) (funcall kill-buffers-func))
- (funcall create-func)))
- (funcall return-func)))
-
-(defun helm-init-candidates-in-buffer (buffer data)
- "Register BUFFER with DATA for a helm candidates-in-buffer session.
-Arg BUFFER can be a string, a buffer object (bufferp), or a symbol,
-either 'local or 'global which is passed to `helm-candidate-buffer'.
-Arg DATA can be either a list or a plain string.
-Returns the resulting buffer."
- (declare (indent 1))
- (let ((buf (helm-candidate-buffer
- (if (or (stringp buffer)
- (bufferp buffer))
- (get-buffer-create buffer)
- buffer)))) ; a symbol.
- (with-current-buffer buf
- (erase-buffer)
- (if (listp data)
- (insert (mapconcat (lambda (i)
- (cond ((symbolp i) (symbol-name i))
- ((numberp i) (number-to-string i))
- (t i)))
- data "\n"))
- (and (stringp data) (insert data))))
- buf))
-
-(defun helm-compile-source--candidates-in-buffer (source)
- (helm-aif (assoc 'candidates-in-buffer source)
- (append source
- `((candidates . ,(or (cdr it)
- (lambda ()
- (helm-candidates-in-buffer source))))
- (volatile) (match identity)))
- source))
-
-\f
-;;; Resplit helm window
-;;
-;;
-(defun helm-toggle-resplit-window ()
- "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)))))
-(put 'helm-toggle-resplit-window 'helm-only t)
-
-;; Utility: Resize helm window.
-(defun helm-enlarge-window-1 (n)
- "Enlarge or narrow helm window.
-If N is positive enlarge, if negative narrow."
- (unless helm-full-frame
- (let ((horizontal-p (eq helm-split-window-state 'horizontal)))
- (with-helm-window
- (enlarge-window n horizontal-p)))))
-
-(defun helm-narrow-window ()
- "Narrow helm window."
- (interactive)
- (with-helm-alive-p
- (helm-enlarge-window-1 -1)))
-(put 'helm-narrow-window 'helm-only t)
-
-(defun helm-enlarge-window ()
- "Enlarge helm window."
- (interactive)
- (with-helm-alive-p
- (helm-enlarge-window-1 1)))
-(put 'helm-enlarge-window 'helm-only t)
-
-(defun helm-swap-windows ()
- "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))))))
-(put 'helm-swap-windows 'helm-only t)
-
-(defun helm--get-window-side-state ()
- "Return the position of `helm-window' from `helm-current-buffer'.
-Possible values are 'left 'right 'below or 'above."
- (let ((side-list '(left right below above)))
- (cl-loop for side in side-list
- thereis (and (equal (helm-window)
- (window-in-direction
- side (get-buffer-window helm-current-buffer t)
- t))
- side))))
-
-(defun helm-replace-buffer-in-window (window buffer1 buffer2)
- "Replace BUFFER1 by BUFFER2 in WINDOW registering BUFFER1."
- (when (get-buffer-window buffer1)
- (unrecord-window-buffer window buffer1)
- (set-window-buffer window buffer2)))
-
-;; Utility: select another action by key
-(defun helm-select-nth-action (n)
- "Select the N nth action for the currently selected candidate."
- (setq helm-saved-selection (helm-get-selection))
- (unless helm-saved-selection
- (error "Nothing is selected"))
- (setq helm-saved-action
- (helm-get-nth-action
- n
- (if (get-buffer-window helm-action-buffer 'visible)
- (assoc-default 'candidates (helm-get-current-source))
- (helm-get-actions-from-current-source))))
- (helm-maybe-exit-minibuffer))
-
-(defun helm-get-nth-action (n action)
- (cond ((and (zerop n) (functionp action))
- action)
- ((listp action)
- (or (cdr (elt action n))
- (error "No such action")))
- ((and (functionp action) (< 0 n))
- (error "Sole action"))
- (t
- (error "Error in `helm-select-nth-action'"))))
-
-(defun helm-execute-selection-action-at-nth (linum)
- "Allow to execute default action on candidate at LINUM."
- (let ((prefarg current-prefix-arg))
- (if (>= linum 0)
- (helm-next-line linum)
- (helm-previous-line (lognot (1- linum))))
- (setq current-prefix-arg prefarg)
- (helm-exit-minibuffer)))
-
-;; Utility: Persistent Action
-(defmacro with-helm-display-same-window (&rest body)
- "Execute BODY in the window used for persistent action.
-Make `pop-to-buffer' and `display-buffer' display in the same window."
- (declare (indent 0) (debug t))
- `(let ((display-buffer-function 'helm-persistent-action-display-buffer))
- ,@body))
-
-(defun helm-initialize-persistent-action ()
- (set (make-local-variable 'helm-persistent-action-display-window) nil))
-
-(cl-defun helm-execute-persistent-action
- (&optional (attr 'persistent-action) split-onewindow)
- "Perform the associated action ATTR without quitting helm.
-ATTR default is 'persistent-action', but it can be anything else.
-In this case you have to add this new attribute to your source.
-
-When `helm-full-frame' or SPLIT-ONEWINDOW are non-`nil', and
-`helm-buffer' is displayed in only one window, the helm window is
-split to display `helm-select-persistent-action-window' in other
-window to maintain visibility."
- (interactive)
- (with-helm-alive-p
- (helm-log "executing persistent-action")
- (let* ((attr-val (assoc-default attr (helm-get-current-source)))
- ;; If attr value is a cons, use its car as persistent function
- ;; and its car to decide if helm window should be splitted.
- (fn (if (and (consp attr-val)
- ;; maybe a lambda.
- (not (functionp attr-val)))
- (car attr-val) attr-val))
- (no-split (and (consp attr-val)
- (not (functionp attr-val))
- (cdr attr-val))))
- (with-helm-window
- (save-selected-window
- (if no-split
- (helm-select-persistent-action-window)
- (helm-select-persistent-action-window
- (or split-onewindow helm-onewindow-p)))
- (helm-log "current-buffer = %S" (current-buffer))
- (let ((helm-in-persistent-action t))
- (with-helm-display-same-window
- (helm-execute-selection-action-1
- nil (or fn (helm-get-actions-from-current-source)) t)
- (helm-log-run-hook 'helm-after-persistent-action-hook))
- ;; A typical case is when a persistent action delete
- ;; the buffer already displayed in
- ;; `helm-persistent-action-display-window' and `helm-full-frame'
- ;; is enabled, we end up with the `helm-buffer'
- ;; displayed in two windows.
- (when (and helm-onewindow-p
- (> (length (window-list)) 1)
- (equal (buffer-name
- (window-buffer
- helm-persistent-action-display-window))
- (helm-buffer-get)))
- (delete-other-windows))))))))
-(put 'helm-execute-persistent-action 'helm-only t)
-
-(defun helm-persistent-action-display-window (&optional split-onewindow)
- "Return the window that will be used for persistent action.
-If SPLIT-ONEWINDOW is non-`nil' window is split in persistent action."
- (with-helm-window
- (setq helm-persistent-action-display-window
- (cond ((and (window-live-p helm-persistent-action-display-window)
- (not (member helm-persistent-action-display-window
- (get-buffer-window-list helm-buffer))))
- helm-persistent-action-display-window)
- (split-onewindow (split-window))
- ((get-buffer-window helm-current-buffer))
- (t (next-window (selected-window) 1))))))
-
-(defun helm-select-persistent-action-window (&optional split-onewindow)
- "Select the window that will be used for persistent action.
-See `helm-persistent-action-display-window' for how to use SPLIT-ONEWINDOW."
- (select-window (get-buffer-window (helm-buffer-get)))
- (select-window
- (setq minibuffer-scroll-window
- (helm-persistent-action-display-window split-onewindow))))
-
-(defun helm-persistent-action-display-buffer (buf &optional action)
- "Make `pop-to-buffer' and `display-buffer' display in the same window.
-If `helm-persistent-action-use-special-display' is non-`nil' and
-BUF is to be displayed by `special-display-function', use it.
-Otherwise ignore `special-display-buffer-names' and `special-display-regexps'.
-Argument ACTION, when present, is used as second argument of `display-buffer'."
- (let* ((name (buffer-name buf))
- display-buffer-function pop-up-windows pop-up-frames
- ;; Disable `special-display-regexps' and `special-display-buffer-names'
- ;; unless `helm-persistent-action-use-special-display' is non-`nil'.
- (special-display-buffer-names
- (and helm-persistent-action-use-special-display
- special-display-buffer-names))
- (special-display-regexps
- (and helm-persistent-action-use-special-display
- special-display-regexps))
- (same-window-regexps
- (unless (and helm-persistent-action-use-special-display
- (or (member name
- (mapcar (lambda (x) (or (car-safe x) x))
- special-display-buffer-names))
- (cl-loop for x in special-display-regexps
- thereis (string-match (or (car-safe x) x)
- name))))
- '("."))))
- ;; Don't loose minibuffer when displaying persistent window in
- ;; another frame.
- ;; This happen when the displayed persistent buffer-name is one of
- ;; `special-display-buffer-names' or match `special-display-regexps'
- ;; and `helm-persistent-action-use-special-display' is enabled.
- (with-selected-window (if (or special-display-regexps
- special-display-buffer-names)
- (minibuffer-window)
- (selected-window))
- ;; Be sure window of BUF is not dedicated.
- (set-window-dedicated-p (get-buffer-window buf) nil)
- (display-buffer buf action))))
-
-;; scroll-other-window(-down)? for persistent-action
-(defun helm-other-window-base (command &optional scroll-amount)
- (setq scroll-amount (unless (eq scroll-amount 'noscroll)
- helm-scroll-amount))
- (with-selected-window (helm-persistent-action-display-window)
- (funcall command scroll-amount)))
-
-(defun helm-scroll-other-window ()
- "Scroll other window (not *Helm* window) upward."
- (interactive)
- (with-helm-alive-p (helm-other-window-base 'scroll-up)))
-(put 'helm-scroll-other-window 'helm-only t)
-
-(defun helm-scroll-other-window-down ()
- "Scroll other window (not *Helm* window) downward."
- (interactive)
- (with-helm-alive-p (helm-other-window-base 'scroll-down)))
-(put 'helm-scroll-other-window-down 'helm-only t)
-
-(defun helm-recenter-top-bottom-other-window ()
- "`recenter-top-bottom' in other window (not *Helm* window)."
- (interactive)
- (with-helm-alive-p (helm-other-window-base 'recenter-top-bottom 'noscroll)))
-(put 'helm-recenter-top-bottom-other-window 'helm-only t)
-
-(defun helm-reposition-window-other-window ()
- "`helm-reposition-window' in other window (not *Helm* window)."
- (interactive)
- (with-helm-alive-p (helm-other-window-base 'reposition-window 'noscroll)))
-(put 'helm-reposition-window-other-window 'helm-only t)
-
-
-\f
-;; Utility: Visible Mark
-
-(defun helm-clear-visible-mark ()
- (with-current-buffer (helm-buffer-get)
- (mapc 'delete-overlay helm-visible-mark-overlays)
- (set (make-local-variable 'helm-visible-mark-overlays) nil)))
-
-(defun helm-this-visible-mark ()
- (cl-loop for o in helm-visible-mark-overlays
- when (equal (point-at-bol) (overlay-start o))
- return o))
-
-(defun helm-delete-visible-mark (overlay)
- (setq helm-marked-candidates
- (remove
- (cons (helm-get-current-source) (helm-get-selection))
- helm-marked-candidates))
- (delete-overlay overlay)
- (setq helm-visible-mark-overlays
- (delq overlay helm-visible-mark-overlays)))
-
-(defun helm-make-visible-mark ()
- (let ((o (make-overlay (point-at-bol)
- (if (helm-pos-multiline-p)
- (or (helm-get-next-candidate-separator-pos)
- (point-max))
- (1+ (point-at-eol))))))
- (overlay-put o 'priority 0)
- (overlay-put o 'face 'helm-visible-mark)
- (overlay-put o 'source (assoc-default 'name (helm-get-current-source)))
- (overlay-put o 'string (buffer-substring (overlay-start o) (overlay-end o)))
- (overlay-put o 'real (helm-get-selection))
- (add-to-list 'helm-visible-mark-overlays o))
- (push (cons (helm-get-current-source) (helm-get-selection))
- helm-marked-candidates))
-
-(defun helm-toggle-visible-mark ()
- "Toggle helm visible mark at point."
- (interactive)
- (with-helm-alive-p
- (with-helm-window
- (let ((nomark (assq 'nomark (helm-get-current-source))))
- (if nomark
- (message "Marking not allowed in this source")
- (helm-aif (helm-this-visible-mark)
- (helm-delete-visible-mark it)
- (helm-make-visible-mark))
- (if (helm-end-of-source-p)
- (helm-display-mode-line (helm-get-current-source))
- (helm-next-line)))))))
-(put 'helm-toggle-visible-mark 'helm-only t)
-
-(defun helm-file-completion-source-p ()
- "Return non-`nil' if current source is a file completion source."
- (or minibuffer-completing-file-name
- (let ((cur-source (cdr (assoc 'name (helm-get-current-source)))))
- (cl-loop for i in helm--file-completion-sources
- thereis (string= cur-source i)))))
-
-(defun helm-mark-all ()
- "Mark all visible unmarked candidates in current source."
- (interactive)
- (with-helm-alive-p
- (with-helm-window
- (let ((nomark (assq 'nomark (helm-get-current-source)))
- (follow (if helm-follow-mode 1 -1)))
- (helm-follow-mode -1)
- (unwind-protect
- (if nomark
- (message "Marking not allowed in this source")
- (save-excursion
- (goto-char (helm-get-previous-header-pos))
- (helm-next-line)
- (let* ((next-head (helm-get-next-header-pos))
- (end (and next-head
- (save-excursion
- (goto-char next-head)
- (forward-line -1)
- (point))))
- (maxpoint (or end (point-max))))
- (while (< (point) maxpoint)
- (helm-mark-current-line)
- (let* ((prefix (get-text-property (point-at-bol) 'display))
- (cand (helm-get-selection))
- (bn (and (helm-file-completion-source-p)
- (helm-basename cand)))
- (src-name (assoc-default 'name
- (helm-get-current-source))))
- (when (and (not (helm-this-visible-mark))
- (not (or (string= prefix "[?]")
- (string= prefix "[@]"))))
- ;; Don't mark possibles directories ending with . or ..
- ;; autosave files/links and non--existent file.
- (unless
- (and (or (helm-file-completion-source-p)
- (string=
- src-name "Files from Current Directory"))
- (or (string-match
- "^[.]?#.*#?$\\|[^#]*[.]\\{1,2\\}$" bn)
- ;; We need to test here when not using
- ;; a transformer that tag prefix
- ;; (i.e on tramp).
- (not (file-exists-p cand))))
- (helm-make-visible-mark))))
- (if (helm-pos-multiline-p)
- (progn
- (goto-char
- (or (helm-get-next-candidate-separator-pos)
- (point-max)))
- (forward-line 1))
- (forward-line 1))
- (end-of-line))))
- (helm-mark-current-line))
- (helm-follow-mode follow) (message nil))))))
-(put 'helm-mark-all 'helm-only t)
-
-(defun helm-unmark-all ()
- "Unmark all candidates in all sources of current helm session."
- (interactive)
- (with-helm-alive-p
- (with-helm-window
- (save-excursion
- (helm-clear-visible-mark))
- (setq helm-marked-candidates nil)
- (helm-mark-current-line)
- (helm-display-mode-line (helm-get-current-source)))))
-(put 'helm-unmark-all 'helm-only t)
-
-(defun helm-toggle-all-marks ()
- "Toggle all marks.
-Mark all visible candidates of current source or unmark all candidates
-visible or invisible in all sources of current helm session"
- (interactive)
- (with-helm-alive-p
- (let ((marked (helm-marked-candidates)))
- (if (and (>= (length marked) 1)
- (with-helm-window helm-visible-mark-overlays))
- (helm-unmark-all)
- (helm-mark-all)))))
-(put 'helm-toggle-all-marks 'helm-only t)
-
-(defun helm--compute-marked (real source wildcard)
- (let* ((coerced (helm-coerce-selection real source))
- (wilds (and wildcard
- (condition-case nil
- (helm-file-expand-wildcards
- coerced t)
- (error nil)))))
- ;; Avoid returning a not expanded wilcard fname.
- ;; e.g assuming "/tmp" doesn't contain "*.el"
- ;; return nil when coerced is "/tmp/*.el".
- (unless (or wilds (null wildcard)
- (string-match-p helm--url-regexp coerced)
- (file-exists-p coerced)
- (and (stringp coerced)
- (null (string-match-p "[[*?]" coerced))))
- (setq coerced nil))
- (or wilds (and coerced (list coerced)))))
-
-(cl-defun helm-marked-candidates (&key with-wildcard)
- "Return marked candidates of current source, if any.
-Otherwise return one element list consisting of the current
-selection. When key WITH-WILDCARD is specified, expand it."
- (with-current-buffer helm-buffer
- (let ((candidates
- (cl-loop with current-src = (helm-get-current-source)
- for (source . real) in (reverse helm-marked-candidates)
- when (equal (assq 'name source) (assq 'name current-src))
- append (helm--compute-marked real source with-wildcard)
- into cands
- finally return (or cands
- (append
- (helm--compute-marked
- (helm-get-selection) current-src
- with-wildcard)
- cands)))))
- (helm-log "Marked candidates = %S" candidates)
- candidates)))
-
-(defun helm-current-source-name= (name)
- (save-excursion
- (goto-char (helm-get-previous-header-pos))
- (equal name (helm-current-line-contents))))
-
-(defun helm-revive-visible-mark ()
- "Restore marked candidates when helm updates display."
- (with-current-buffer helm-buffer
- (save-excursion
- (cl-dolist (o helm-visible-mark-overlays)
- (let ((o-src-str (overlay-get o 'source))
- (o-str (overlay-get o 'string))
- beg end)
- ;; Move point to end of source header line.
- (goto-char (point-min))
- (search-forward o-src-str nil t)
- (while (and (search-forward o-str nil t)
- (not (overlays-at (point-at-bol 0)))
- (helm-current-source-name= o-src-str))
- (setq beg (match-beginning 0)
- end (match-end 0))
- ;; Calculate real value of candidate.
- ;; It can be nil if candidate have only a display value.
- (let ((real (get-text-property (point-at-bol 0) 'helm-realvalue)))
- (if real
- ;; Check if real value of current candidate is the same
- ;; than the one stored in overlay.
- ;; This is needed when some cands have same display names.
- ;; Using equal allow testing any type of value for real cand.
- ;; Issue (#706).
- (and (equal (overlay-get o 'real) real)
- (move-overlay o beg end))
- (and (equal o-str (buffer-substring beg end))
- (move-overlay o beg end))))))))))
-(add-hook 'helm-update-hook 'helm-revive-visible-mark)
-
-(defun helm-next-point-in-list (curpos points &optional prev)
- (cond
- ;; rule out special cases.
- ((null points) curpos)
- ((and prev (<= curpos (car points)))
- (nth (1- (length points)) points))
- ((< (car (last points)) curpos)
- (if prev (car (last points)) (nth 0 points)))
- ((and (not prev) (>= curpos (car (last points))))
- (nth 0 points))
- (t
- (nth (if prev
- (cl-loop for pt in points
- for i from 0
- if (<= curpos pt) return (1- i))
- (cl-loop for pt in points
- for i from 0
- if (< curpos pt) return i))
- points))))
-
-(defun helm-next-visible-mark (&optional prev)
- "Move next helm visible mark.
-If PREV is non-`nil' move to precedent."
- (interactive)
- (with-helm-alive-p
- (with-helm-window
- (ignore-errors
- (goto-char (helm-next-point-in-list
- (point)
- (sort (mapcar 'overlay-start helm-visible-mark-overlays) '<)
- prev)))
- (helm-mark-current-line))))
-(put 'helm-next-visible-mark 'helm-only t)
-
-(defun helm-prev-visible-mark ()
- "Move previous helm visible mark."
- (interactive)
- (with-helm-alive-p
- (helm-next-visible-mark t)))
-(put 'helm-prev-visible-mark 'helm-only t)
-
-;;; Utility: Selection Paste
-;;
-(defun helm-yank-selection (arg)
- "Set minibuffer contents to current display selection.
-With a prefix arg set to real value of current selection."
- (interactive "P")
- (with-helm-alive-p
- (let ((str (format "%s" (helm-get-selection nil (not arg)))))
- (kill-new str)
- (helm-set-pattern str))))
-(put 'helm-yank-selection 'helm-only t)
-
-(defun helm-kill-selection-and-quit (arg)
- "Store display value of current selection to kill ring.
-With a prefix arg use real value of current selection.
-Display value is shown in `helm-buffer' and real value
-is used to perform actions."
- (interactive "P")
- (with-helm-alive-p
- (helm-run-after-exit
- (lambda (sel)
- (kill-new sel)
- ;; Return nil to force `helm-mode--keyboard-quit'
- ;; in `helm-comp-read' otherwise the value "Saved to kill-ring: foo"
- ;; is used as exit value for `helm-comp-read'.
- (prog1 nil (message "Saved to kill-ring: %s" sel) (sit-for 1)))
- (format "%s" (helm-get-selection nil (not arg))))))
-(put 'helm-kill-selection-and-quit 'helm-only t)
-
-(defun helm-copy-to-buffer ()
- "Copy selection or marked candidates to `helm-current-buffer'.
-Note that the real values of candidates are copied and not the
-display values."
- (interactive)
- (with-helm-alive-p
- (helm-run-after-exit
- (lambda (cands)
- (with-helm-current-buffer
- (insert (mapconcat (lambda (c)
- (format "%s" c))
- cands "\n"))))
- (helm-marked-candidates))))
-(put 'helm-copy-to-buffer 'helm-only t)
-
-\f
-;;; Follow-mode: Automatic execution of persistent-action
-;;
-;;
-(defun helm-follow-mode (&optional arg)
- "Execute persistent action every time the cursor is moved.
-
-This mode is source local, i.e It apply on current source only.
-\\<helm-map>
-This mode can be enabled or disabled interactively at anytime during
-a helm session with \\[helm-follow-mode].
-
-It can also be enabled specifically for a source by adding the
-`follow' attribute to the source.
-Value of this attribute can be -1, 1, or 'never.
-If the source is defined with its own class,
-you can use `helm-setup-user-source' e.g:
-
- (defmethod helm-setup-user-source ((source helm-grep-class))
- (setf (slot-value source 'follow) 1))
-
-Otherwise, use `helm-attrset' to setup the `follow' attribute of the existing source,
-which see.
-
-Even with `follow' attribute, a source can be interactively disabled or enabled
-unless `follow' attribute value is 'never.
-When enabling interactively `helm-follow-mode' in a source, you can keep it enabled
-for next helm sessions by setting `helm-follow-mode-persistent' to a non-nil value.
-
-Note that you can use instead of this mode the commands `helm-follow-action-forward'
-and `helm-follow-action-backward' at anytime in all helm sessions.
-
-They are bound by default to \\[helm-follow-action-forward] and \\[helm-follow-action-backward]."
- (interactive "p")
- (with-helm-alive-p
- (with-current-buffer helm-buffer
- (let* ((src (helm-get-current-source))
- (name (assoc-default 'name src))
- (sym (cl-loop for s in helm-sources
- for sname = (and (symbolp s)
- (assoc-default
- 'name (symbol-value s)))
- thereis (and sname (string= sname name) s)))
- (fol-attr (assq 'follow src))
- (enabled (or
- ;; If `helm-follow-mode' is called with a negative
- ;; ARG, assume follow is already enabled.
- ;; i.e turn it off now.
- (< arg 0)
- (eq (cdr fol-attr) 1)
- helm-follow-mode)))
- (if src
- (progn
- (if (eq (cdr fol-attr) 'never)
- (message "helm-follow-mode not allowed in this source")
- ;; Make follow attr persistent for this emacs session.
- (helm-attrset 'follow (if enabled -1 1) src)
- (setq helm-follow-mode (not enabled))
- (message "helm-follow-mode is %s"
- (if helm-follow-mode
- "enabled" "disabled"))
- (helm-display-mode-line src t))
- (unless helm-follow-mode-persistent
- (and sym (set sym (remove (assq 'follow src) src)))))
- (message "Not enough candidates for helm-follow-mode"))))))
-(put 'helm-follow-mode 'helm-only t)
-
-(defvar helm-follow-input-idle-delay nil
- "`helm-follow-mode' will execute its persistent action after this delay.
-Note that if the `follow-delay' attr is present in source,
-it will take precedence over this.")
-(defun helm-follow-execute-persistent-action-maybe ()
- "Execute persistent action in mode `helm-follow-mode'.
-This happen after `helm-input-idle-delay' secs."
- (let ((src (helm-get-current-source)))
- (and (not (get-buffer-window helm-action-buffer 'visible))
- (eq (assoc-default 'follow src) 1)
- (sit-for (or (assoc-default 'follow-delay src)
- helm-follow-input-idle-delay
- (and helm-input-idle-delay
- (max helm-input-idle-delay 0.01))))
- (helm-window)
- (helm-get-selection)
- (save-excursion
- (helm-execute-persistent-action)))))
-
-\f
-;;; Auto-resize mode
-;;
-(defun helm--autoresize-hook (&optional max-height min-height)
- (with-helm-window
- (fit-window-to-buffer nil
- (/ (* (frame-height)
- (or max-height helm-autoresize-max-height))
- 100)
- (/ (* (frame-height)
- (or min-height helm-autoresize-min-height))
- 100))))
-
-(define-minor-mode helm-autoresize-mode
- "Auto resize helm window when enabled.
-Helm window is re-sized according to `helm-autoresize-max-height'
-and `helm-autoresize-min-height'. Note that when this mode is
-enabled, helm behaves as if `helm-always-two-windows' is
-enabled.
-
-See `fit-window-to-buffer' for more infos."
- :group 'helm
- :global t
- (if helm-autoresize-mode
- (progn (add-hook 'helm-after-update-hook 'helm--autoresize-hook)
- (add-hook 'helm-window-configuration-hook 'helm--autoresize-hook))
- (remove-hook 'helm-after-update-hook 'helm--autoresize-hook)
- (remove-hook 'helm-window-configuration-hook 'helm--autoresize-hook)))
-
-(defun helm-help ()
- "Help of `helm'."
- (interactive)
- (with-helm-alive-p
- (save-selected-window
- (helm-help-internal
- "*Helm Help*"
- (lambda ()
- (helm-aif (assoc-default 'help-message (helm-get-current-source))
- (insert (substitute-command-keys
- (helm-interpret-value it)))
- (insert "* No specific help for this source at this time.\n
-It may appear after first results popup in helm buffer."))
- (insert "\n\n"
- (substitute-command-keys
- (helm-interpret-value helm-help-message))))))))
-(put 'helm-help 'helm-only t)
-
-(defun helm-toggle-truncate-line ()
- "Toggle `truncate-lines' value in `helm-buffer'"
- (interactive)
- (with-helm-alive-p
- (with-helm-buffer
- (setq truncate-lines (not truncate-lines))
- (helm-update (regexp-quote (helm-get-selection nil t))))))
-(put 'helm-toggle-truncate-line 'helm-only t)
-
-(provide 'helm)
-
-;; Local Variables:
-;; byte-compile-warnings: (not cl-functions obsolete)
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm.el ends here
--- /dev/null
+;;; helm-core-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+
+(add-to-list 'load-path (directory-file-name
+ (or (file-name-directory #$) (car load-path))))
+
+\f
+;;;### (autoloads nil "helm" "helm.el" (0 0 0 0))
+;;; Generated autoloads from helm.el
+
+(autoload 'helm-define-multi-key "helm" "\
+In KEYMAP, define key sequence KEY for function list FUNCTIONS.
+Each function runs sequentially for each KEY press.
+If DELAY is specified, switch back to initial function of FUNCTIONS list
+after DELAY seconds.
+The functions in FUNCTIONS list take no args.
+e.g
+ (defun foo ()
+ (interactive)
+ (message \"Run foo\"))
+ (defun bar ()
+ (interactive)
+ (message \"Run bar\"))
+ (defun baz ()
+ (interactive)
+ (message \"Run baz\"))
+
+\(helm-define-multi-key global-map (kbd \"<f5> q\") '(foo bar baz) 2)
+
+Each time \"<f5> q\" is pressed, the next function is executed. Waiting
+more than 2 seconds between key presses switches back to executing the first
+function on the next hit.
+
+\(fn KEYMAP KEY FUNCTIONS &optional DELAY)" nil nil)
+
+(autoload 'helm-multi-key-defun "helm" "\
+Define NAME as a multi-key command running FUNS.
+After DELAY seconds, the FUNS list is reinitialized.
+See `helm-define-multi-key'.
+
+\(fn NAME DOCSTRING FUNS &optional DELAY)" nil t)
+
+(function-put 'helm-multi-key-defun 'lisp-indent-function '2)
+
+(autoload 'helm-define-key-with-subkeys "helm" "\
+Defines in MAP a KEY and SUBKEY to COMMAND.
+
+This allows typing KEY to call COMMAND the first time and
+type only SUBKEY on subsequent calls.
+
+Arg MAP is the keymap to use, SUBKEY is the initial short key-binding to
+call COMMAND.
+
+Arg OTHER-SUBKEYS is an alist specifying other short key-bindings
+to use once started e.g:
+
+ (helm-define-key-with-subkeys global-map
+ (kbd \"C-x v n\") ?n 'git-gutter:next-hunk '((?p . git-gutter:previous-hunk)))
+
+
+In this example, `C-x v n' will run `git-gutter:next-hunk'
+subsequent \"n\"'s run this command again
+and subsequent \"p\"'s run `git-gutter:previous-hunk'.
+
+If specified PROMPT can be displayed in minibuffer to
+describe SUBKEY and OTHER-SUBKEYS.
+Arg EXIT-FN specifies a function to run on exit.
+
+For any other keys pressed, run their assigned command as defined
+in MAP and then exit the loop running EXIT-FN, if specified.
+
+NOTE: SUBKEY and OTHER-SUBKEYS bindings support only char syntax and
+vectors, so don't use strings to define them.
+
+\(fn MAP KEY SUBKEY COMMAND &optional OTHER-SUBKEYS PROMPT EXIT-FN)" nil nil)
+
+(function-put 'helm-define-key-with-subkeys 'lisp-indent-function '1)
+
+(autoload 'helm-debug-open-last-log "helm" "\
+Open helm log file or buffer of last helm session.
+
+\(fn)" t nil)
+
+(autoload 'helm "helm" "\
+Main function to execute helm sources.
+
+PLIST is a list like
+
+\(:key1 val1 :key2 val2 ...)
+
+ or
+
+\(&optional sources input prompt resume preselect
+ buffer keymap default history allow-nest).
+
+** Keywords
+
+Keywords supported:
+
+- :sources
+- :input
+- :prompt
+- :resume
+- :preselect
+- :buffer
+- :keymap
+- :default
+- :history
+- :allow-nest
+
+Extra LOCAL-VARS keywords are supported, see the \"** Other
+keywords\" section below.
+
+Basic keywords are the following:
+
+*** :sources
+
+One of the following:
+
+- List of sources
+- Symbol whose value is a list of sources
+- Alist representing a Helm source.
+ - In this case the source has no name and is referenced in
+ `helm-sources' as a whole alist.
+
+*** :input
+
+Initial input of minibuffer (temporary value of `helm-pattern')
+
+*** :prompt
+
+Minibuffer prompt. Default value is `helm--prompt'.
+
+*** :resume
+
+If t, allow resumption of the previous session of this Helm
+command, skipping initialization.
+
+If 'noresume, this instance of `helm' cannot be resumed.
+
+*** :preselect
+
+Initially selected candidate (string or regexp).
+
+*** :buffer
+
+Buffer name for this Helm session. `helm-buffer' will take this value.
+
+*** :keymap
+
+\[Obsolete]
+
+Keymap used at the start of this Helm session.
+
+It is overridden by keymaps specified in sources, and is kept
+only for backward compatibility.
+
+Keymaps should be specified in sources using the :keymap slot
+instead. See `helm-source'.
+
+This keymap is not restored by `helm-resume'.
+
+*** :default
+
+Default value inserted into the minibuffer with
+\\<minibuffer-local-map>\\[next-history-element].
+
+It can be a string or a list of strings, in this case
+\\<minibuffer-local-map>\\[next-history-element] cycles through
+the list items, starting with the first.
+
+If nil, `thing-at-point' is used.
+
+If `helm--maybe-use-default-as-input' is non-`nil', display is
+updated using this value, unless :input is specified, in which
+case that value is used instead.
+
+*** :history
+
+Minibuffer input, by default, is pushed to `minibuffer-history'.
+
+When an argument HISTORY is provided, input is pushed to
+HISTORY. HISTORY should be a valid symbol.
+
+*** :allow-nest
+
+Allow running this Helm command in a running Helm session.
+
+** Other keywords
+
+Other keywords are interpreted as local variables of this Helm
+session. The `helm-' prefix can be omitted. For example,
+
+\(helm :sources 'helm-source-buffers-list
+ :buffer \"*helm buffers*\"
+ :candidate-number-limit 10)
+
+starts a Helm session with the variable
+`helm-candidate-number-limit' set to 10.
+
+** Backward compatibility
+
+For backward compatibility, positional parameters are
+supported:
+
+\(helm sources input prompt resume preselect
+ buffer keymap default history allow-nest)
+
+However, the use of non-keyword args is deprecated.
+
+\(fn &key SOURCES INPUT PROMPT RESUME PRESELECT BUFFER KEYMAP DEFAULT HISTORY ALLOW-NEST OTHER-LOCAL-VARS)" nil nil)
+
+(autoload 'helm-cycle-resume "helm" "\
+Cycle in `helm-buffers' list and resume when waiting more than 1.2s.
+
+\(fn)" t nil)
+
+(autoload 'helm-other-buffer "helm" "\
+Simplified `helm' interface with other `helm-buffer'.
+Call `helm' only with ANY-SOURCES and ANY-BUFFER as args.
+
+\(fn ANY-SOURCES ANY-BUFFER)" nil nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm" '("helm-" "with-helm-")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-lib" "helm-lib.el" (0 0 0 0))
+;;; Generated autoloads from helm-lib.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-lib" '("helm-" "with-helm-")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-multi-match" "helm-multi-match.el" (0
+;;;;;; 0 0 0))
+;;; Generated autoloads from helm-multi-match.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-multi-match" '("helm-m")))
+
+;;;***
+\f
+;;;### (autoloads nil "helm-source" "helm-source.el" (0 0 0 0))
+;;; Generated autoloads from helm-source.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-source" '("helm-")))
+
+;;;***
+\f
+;;;### (autoloads nil nil ("helm-core-pkg.el") (0 0 0 0))
+
+;;;***
+\f
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; coding: utf-8
+;; End:
+;;; helm-core-autoloads.el ends here
--- /dev/null
+(define-package "helm-core" "20181110.1635" "Development files for Helm"
+ '((emacs "24.4")
+ (async "1.9.3"))
+ :url "https://emacs-helm.github.io/helm/")
+;; Local Variables:
+;; no-byte-compile: t
+;; End:
--- /dev/null
+;;; helm-lib.el --- Helm routines. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2015 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; Author: Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+;; URL: http://github.com/emacs-helm/helm
+
+;; 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/>.
+
+;;; Commentary:
+;; All helm functions that don't require specific helm code should go here.
+
+;;; Code:
+
+(require 'cl-lib)
+(eval-when-compile (require 'wdired))
+
+(declare-function helm-get-sources "helm.el")
+(declare-function helm-marked-candidates "helm.el")
+(declare-function helm-follow-mode-p "helm.el")
+(declare-function helm-attr "helm.el")
+(declare-function helm-attrset "helm.el")
+(declare-function org-open-at-point "org.el")
+(declare-function org-content "org.el")
+(declare-function org-mark-ring-goto "org.el")
+(declare-function org-mark-ring-push "org.el")
+(declare-function helm-interpret-value "helm.el")
+(declare-function helm-get-current-source "helm.el")
+(defvar helm-sources)
+(defvar helm-initial-frame)
+(defvar helm-current-position)
+(defvar wdired-old-marks)
+(defvar helm-persistent-action-display-window)
+\f
+;;; User vars.
+;;
+(defcustom helm-file-globstar t
+ "Same as globstar bash shopt option.
+When non--nil a pattern beginning with two stars will expand recursively.
+Directories expansion is not supported yet."
+ :group 'helm
+ :type 'boolean)
+
+(defcustom helm-yank-text-at-point-function nil
+ "The function used to forward point with `helm-yank-text-at-point'.
+With a nil value, fallback to default `forward-word'.
+The function should take one arg, an integer like `forward-word'.
+NOTE: Using `forward-symbol' here is not very useful as it is already
+provided by \\<helm-map>\\[next-history-element]."
+ :type 'function
+ :group 'helm)
+
+(defcustom helm-scroll-amount nil
+ "Scroll amount when scrolling other window in a helm session.
+It is used by `helm-scroll-other-window'
+and `helm-scroll-other-window-down'.
+
+If you prefer scrolling line by line, set this value to 1."
+ :group 'helm
+ :type 'integer)
+
+(defcustom helm-help-full-frame t
+ "Display help window in full frame when non nil.
+
+Even when `nil' probably the same result (full frame)
+can be reach by tweaking `display-buffer-alist' but it is
+much more convenient to use a simple boolean value here."
+ :type 'boolean
+ :group 'helm-help)
+
+(defvar helm-ff--boring-regexp nil)
+(defun helm-ff--setup-boring-regex (var val)
+ (set var val)
+ (setq helm-ff--boring-regexp
+ (cl-loop with last = (car (last val))
+ for r in (butlast val)
+ if (string-match "\\$\\'" r)
+ concat (concat r "\\|") into result
+ else concat (concat r "$\\|") into result
+ finally return
+ (concat result last
+ (if (string-match "\\$\\'" last) "" "$")))))
+
+(defcustom helm-boring-file-regexp-list
+ (mapcar (lambda (f)
+ (let ((rgx (regexp-quote f)))
+ (if (string-match-p "[^/]$" f)
+ ;; files: e.g .o => \\.o$
+ (concat rgx "$")
+ ;; directories: e.g .git/ => \.git\\(/\\|$\\)
+ (concat (substring rgx 0 -1) "\\(/\\|$\\)"))))
+ completion-ignored-extensions)
+ "A list of regexps matching boring files.
+
+This list is build by default on `completion-ignored-extensions'.
+The directory names should end with \"/?\" e.g. \"\\.git/?\" and the
+file names should end with \"$\" e.g. \"\\.o$\".
+
+These regexps may be used to match the entire path, not just the file
+name, so for example to ignore files with a prefix \".bak.\", use
+\"\\.bak\\..*$\" as the regexp.
+
+NOTE: When modifying this, be sure to use customize interface or the
+customize functions e.g. `customize-set-variable' and NOT `setq'."
+ :group 'helm-files
+ :type '(repeat (choice regexp))
+ :set 'helm-ff--setup-boring-regex)
+
+\f
+;;; Internal vars
+;;
+(defvar helm-yank-point nil)
+(defvar helm-pattern ""
+ "The input pattern used to update the helm buffer.")
+(defvar helm-buffer "*helm*"
+ "Buffer showing completions.")
+(defvar helm-current-buffer nil
+ "Current buffer when `helm' is invoked.")
+(defvar helm-suspend-update-flag nil)
+(defvar helm-action-buffer "*helm action*"
+ "Buffer showing actions.")
+
+\f
+;;; Compatibility
+;;
+(defun helm-add-face-text-properties (beg end face &optional append object)
+ "Add the face property to the text from START to END.
+It is a compatibility function which behave exactly like
+`add-face-text-property' if available otherwise like `add-text-properties'.
+When only `add-text-properties' is available APPEND is ignored."
+ (if (fboundp 'add-face-text-property)
+ (add-face-text-property beg end face append object)
+ (add-text-properties beg end `(face ,face) object)))
+
+;; Override `wdired-finish-edit'.
+;; Fix emacs bug in `wdired-finish-edit' where
+;; Wdired is not handling the case where `dired-directory' is a cons
+;; cell instead of a string.
+(defun helm--advice-wdired-finish-edit ()
+ (interactive)
+ (wdired-change-to-dired-mode)
+ (let ((changes nil)
+ (errors 0)
+ files-deleted
+ files-renamed
+ some-file-names-unchanged
+ file-old file-new tmp-value)
+ (save-excursion
+ (when (and wdired-allow-to-redirect-links
+ (fboundp 'make-symbolic-link))
+ (setq tmp-value (wdired-do-symlink-changes))
+ (setq errors (cdr tmp-value))
+ (setq changes (car tmp-value)))
+ (when (and wdired-allow-to-change-permissions
+ (boundp 'wdired-col-perm)) ; could have been changed
+ (setq tmp-value (wdired-do-perm-changes))
+ (setq errors (+ errors (cdr tmp-value)))
+ (setq changes (or changes (car tmp-value))))
+ (goto-char (point-max))
+ (while (not (bobp))
+ (setq file-old (wdired-get-filename nil t))
+ (when file-old
+ (setq file-new (wdired-get-filename))
+ (if (equal file-new file-old)
+ (setq some-file-names-unchanged t)
+ (setq changes t)
+ (if (not file-new) ;empty filename!
+ (push file-old files-deleted)
+ (when wdired-keep-marker-rename
+ (let ((mark (cond ((integerp wdired-keep-marker-rename)
+ wdired-keep-marker-rename)
+ (wdired-keep-marker-rename
+ (cdr (assoc file-old wdired-old-marks)))
+ (t nil))))
+ (when mark
+ (push (cons (substitute-in-file-name file-new) mark)
+ wdired-old-marks))))
+ (push (cons file-old (substitute-in-file-name file-new))
+ files-renamed))))
+ (forward-line -1)))
+ (when files-renamed
+ (setq errors (+ errors (wdired-do-renames files-renamed))))
+ (if changes
+ (progn
+ ;; If we are displaying a single file (rather than the
+ ;; contents of a directory), change dired-directory if that
+ ;; file was renamed. (This ought to be generalized to
+ ;; handle the multiple files case, but that's less trivial)
+ ;; fixit [1].
+ (cond ((and (stringp dired-directory)
+ (not (file-directory-p dired-directory))
+ (null some-file-names-unchanged)
+ (= (length files-renamed) 1))
+ (setq dired-directory (cdr (car files-renamed))))
+ ;; Fix [1] i.e dired buffers created with
+ ;; (dired '(foo f1 f2 f3)).
+ ((and (consp dired-directory)
+ (cdr dired-directory)
+ files-renamed)
+ (setcdr dired-directory
+ ;; Replace in `dired-directory' files that have
+ ;; been modified with their new name keeping
+ ;; the ones that are unmodified at the same place.
+ (cl-loop with old-to-rename = (mapcar 'car files-renamed)
+ for f in (cdr dired-directory)
+ if (member f old-to-rename)
+ collect (assoc-default f files-renamed)
+ else collect f))))
+ ;; Re-sort the buffer if all went well.
+ (unless (> errors 0) (revert-buffer))
+ (let ((inhibit-read-only t))
+ (dired-mark-remembered wdired-old-marks)))
+ (let ((inhibit-read-only t))
+ (remove-text-properties (point-min) (point-max)
+ '(old-name nil end-name nil old-link nil
+ end-link nil end-perm nil
+ old-perm nil perm-changed nil))
+ (message "(No changes to be performed)")))
+ (when files-deleted
+ (wdired-flag-for-deletion files-deleted))
+ (when (> errors 0)
+ (dired-log-summary (format "%d rename actions failed" errors) nil)))
+ (set-buffer-modified-p nil)
+ (setq buffer-undo-list nil))
+
+;; Override `wdired-get-filename'.
+;; Fix emacs bug in `wdired-get-filename' which returns the current
+;; directory concatened with the filename i.e
+;; "/home/you//home/you/foo" when filename is absolute in dired
+;; buffer.
+;; In consequence Wdired try to rename files even when buffer have
+;; been modified and corrected, e.g delete one char and replace it so
+;; that no change to file is done.
+;; This also lead to ask confirmation for every files even when not
+;; modified and when `wdired-use-interactive-rename' is nil.
+(defun helm--advice-wdired-get-filename (&optional no-dir old)
+ ;; FIXME: Use dired-get-filename's new properties.
+ (let (beg end file)
+ (save-excursion
+ (setq end (line-end-position))
+ (beginning-of-line)
+ (setq beg (next-single-property-change (point) 'old-name nil end))
+ (unless (eq beg end)
+ (if old
+ (setq file (get-text-property beg 'old-name))
+ ;; In the following form changed `(1+ beg)' to `beg' so that
+ ;; the filename end is found even when the filename is empty.
+ ;; Fixes error and spurious newlines when marking files for
+ ;; deletion.
+ (setq end (next-single-property-change beg 'end-name))
+ (setq file (buffer-substring-no-properties (1+ beg) end)))
+ ;; Don't unquote the old name, it wasn't quoted in the first place
+ (and file (setq file (condition-case _err
+ ;; emacs-25+
+ (apply #'wdired-normalize-filename
+ (list file (not old)))
+ (wrong-number-of-arguments
+ ;; emacs-24
+ (wdired-normalize-filename file))))))
+ (if (or no-dir old (and file (file-name-absolute-p file)))
+ file
+ (and file (> (length file) 0)
+ (expand-file-name file (dired-current-directory)))))))
+
+;;; Override `push-mark'
+;;
+;; Fix duplicates in `mark-ring' and `global-mark-ring' and update
+;; buffers in `global-mark-ring' to recentest mark.
+(defun helm--advice-push-mark (&optional location nomsg activate)
+ (unless (null (mark t))
+ (let ((marker (copy-marker (mark-marker))))
+ (setq mark-ring (cons marker (delete marker mark-ring))))
+ (when (> (length mark-ring) mark-ring-max)
+ ;; Move marker to nowhere.
+ (set-marker (car (nthcdr mark-ring-max mark-ring)) nil)
+ (setcdr (nthcdr (1- mark-ring-max) mark-ring) nil)))
+ (set-marker (mark-marker) (or location (point)) (current-buffer))
+ ;; Now push the mark on the global mark ring.
+ (setq global-mark-ring (cons (copy-marker (mark-marker))
+ ;; Avoid having multiple entries
+ ;; for same buffer in `global-mark-ring'.
+ (cl-loop with mb = (current-buffer)
+ for m in global-mark-ring
+ for nmb = (marker-buffer m)
+ unless (eq mb nmb)
+ collect m)))
+ (when (> (length global-mark-ring) global-mark-ring-max)
+ (set-marker (car (nthcdr global-mark-ring-max global-mark-ring)) nil)
+ (setcdr (nthcdr (1- global-mark-ring-max) global-mark-ring) nil))
+ (or nomsg executing-kbd-macro (> (minibuffer-depth) 0)
+ (message "Mark set"))
+ (when (or activate (not transient-mark-mode))
+ (set-mark (mark t)))
+ nil)
+
+(defcustom helm-advice-push-mark t
+ "Override `push-mark' with a version avoiding duplicates when non nil."
+ :group 'helm
+ :type 'boolean
+ :set (lambda (var val)
+ (set var val)
+ (if val
+ (advice-add 'push-mark :override #'helm--advice-push-mark)
+ (advice-remove 'push-mark #'helm--advice-push-mark))))
+\f
+;;; Macros helper.
+;;
+(defmacro helm-with-gensyms (symbols &rest body)
+ "Bind the SYMBOLS to fresh uninterned symbols and eval BODY."
+ (declare (indent 1))
+ `(let ,(mapcar (lambda (s)
+ ;; Use cl-gensym here instead of make-symbol
+ ;; to ensure a symbol that have a live that go
+ ;; beyond the live of its macro have different name.
+ ;; i.e symbols created with `with-helm-temp-hook'
+ ;; should have random names.
+ `(,s (cl-gensym (symbol-name ',s))))
+ symbols)
+ ,@body))
+\f
+;;; Command loop helper
+;;
+(defun helm-this-command ()
+ "Returns the actual command in action.
+Like `this-command' but return the real command,
+and not `exit-minibuffer' or other unwanted functions."
+ (cl-loop with bl = '(helm-maybe-exit-minibuffer
+ helm-confirm-and-exit-minibuffer
+ helm-exit-minibuffer
+ exit-minibuffer)
+ for count from 1 to 50
+ for btf = (backtrace-frame count)
+ for fn = (cl-second btf)
+ if (and
+ ;; In some case we may have in the way an
+ ;; advice compiled resulting in byte-code,
+ ;; ignore it (Issue #691).
+ (symbolp fn)
+ (commandp fn)
+ (not (memq fn bl)))
+ return fn
+ else
+ if (and (eq fn 'call-interactively)
+ (> (length btf) 2))
+ return (cadr (cdr btf))))
+
+\f
+;;; Iterators
+;;
+(cl-defmacro helm-position (item seq &key test all)
+ "A simple and faster replacement of CL `position'.
+
+Returns ITEM first occurence position found in SEQ.
+When SEQ is a string, ITEM have to be specified as a char.
+Argument TEST when unspecified default to `eq'.
+When argument ALL is non--nil return a list of all ITEM positions
+found in SEQ."
+ (let ((key (if (stringp seq) 'across 'in)))
+ `(cl-loop with deftest = 'eq
+ for c ,key ,seq
+ for index from 0
+ when (funcall (or ,test deftest) c ,item)
+ if ,all collect index into ls
+ else return index
+ finally return ls)))
+
+(defun helm-iter-list (seq)
+ "Return an iterator object from SEQ."
+ (let ((lis seq))
+ (lambda ()
+ (let ((elm (car lis)))
+ (setq lis (cdr lis))
+ elm))))
+
+(defun helm-iter-circular (seq)
+ "Infinite iteration on SEQ."
+ (let ((lis seq))
+ (lambda ()
+ (let ((elm (car lis)))
+ (setq lis (pcase lis (`(,_ . ,ll) (or ll seq))))
+ elm))))
+
+(cl-defun helm-iter-sub-next-circular (seq elm &key (test 'eq))
+ "Infinite iteration of SEQ starting at ELM."
+ (let* ((pos (1+ (helm-position elm seq :test test)))
+ (sub (append (nthcdr pos seq) (cl-subseq seq 0 pos)))
+ (iterator (helm-iter-circular sub)))
+ (lambda ()
+ (helm-iter-next iterator))))
+
+(defun helm-iter-next (iterator)
+ "Return next elm of ITERATOR."
+ (and iterator (funcall iterator)))
+
+\f
+;;; Anaphoric macros.
+;;
+(defmacro helm-aif (test-form then-form &rest else-forms)
+ "Anaphoric version of `if'.
+Like `if' but set the result of TEST-FORM in a temporary variable called `it'.
+THEN-FORM and ELSE-FORMS are then excuted just like in `if'."
+ (declare (indent 2) (debug t))
+ `(let ((it ,test-form))
+ (if it ,then-form ,@else-forms)))
+
+(defmacro helm-awhile (sexp &rest body)
+ "Anaphoric version of `while'.
+Same usage as `while' except that SEXP is bound to
+a temporary variable called `it' at each turn.
+An implicit nil block is bound to the loop so usage
+of `cl-return' is possible to exit the loop."
+ (declare (indent 1) (debug t))
+ (helm-with-gensyms (flag)
+ `(let ((,flag t))
+ (cl-block nil
+ (while ,flag
+ (helm-aif ,sexp
+ (progn ,@body)
+ (setq ,flag nil)))))))
+
+(defmacro helm-acond (&rest clauses)
+ "Anaphoric version of `cond'.
+In each clause of CLAUSES, the result of the car of clause
+is stored in a temporary variable called `it' and usable in the cdr
+of this same clause. Each `it' variable is independent of its clause.
+The usage is the same as `cond'."
+ (declare (debug cond))
+ (unless (null clauses)
+ (helm-with-gensyms (sym)
+ (let ((clause1 (car clauses)))
+ `(let ((,sym ,(car clause1)))
+ (helm-aif ,sym
+ (if (cdr ',clause1)
+ (progn ,@(cdr clause1))
+ it)
+ (helm-acond ,@(cdr clauses))))))))
+
+(defmacro helm-aand (&rest conditions)
+ "Anaphoric version of `and'.
+Each condition is bound to a temporary variable called `it' which is
+usable in next condition."
+ (declare (debug (&rest form)))
+ (cond ((null conditions) t)
+ ((null (cdr conditions)) (car conditions))
+ (t `(helm-aif ,(car conditions)
+ (helm-aand ,@(cdr conditions))))))
+
+(defmacro helm-acase (expr &rest clauses)
+ "A simple anaphoric `cl-case' implementation handling strings.
+EXPR is bound to a temporary variable called `it' which is usable in
+CLAUSES to refer to EXPR.
+NOTE: Duplicate keys in CLAUSES are deliberately not handled."
+ (declare (indent 1) (debug t))
+ (unless (null clauses)
+ (let ((clause1 (car clauses)))
+ `(let ((key ',(car clause1))
+ (it ,expr))
+ (if (or (equal it key)
+ (eq key t)
+ (and (listp key) (member it key)))
+ (progn ,@(cdr clause1))
+ (helm-acase it ,@(cdr clauses)))))))
+\f
+;;; Fuzzy matching routines
+;;
+(defsubst helm--mapconcat-pattern (pattern)
+ "Transform string PATTERN in regexp for further fuzzy matching.
+e.g helm.el$
+ => \"[^h]*h[^e]*e[^l]*l[^m]*m[^.]*[.][^e]*e[^l]*l$\"
+ ^helm.el$
+ => \"helm[.]el$\"."
+ (let ((ls (split-string-and-unquote pattern "")))
+ (if (string= "^" (car ls))
+ ;; Exact match.
+ (mapconcat (lambda (c)
+ (if (and (string= c "$")
+ (string-match "$\\'" pattern))
+ c (regexp-quote c)))
+ (cdr ls) "")
+ ;; Fuzzy match.
+ (mapconcat (lambda (c)
+ (if (and (string= c "$")
+ (string-match "$\\'" pattern))
+ c (format "[^%s]*%s" c (regexp-quote c))))
+ ls ""))))
+
+(defsubst helm--collect-pairs-in-string (string)
+ (cl-loop for str on (split-string string "" t) by 'cdr
+ when (cdr str)
+ collect (list (car str) (cadr str))))
+\f
+;;; Help routines.
+;;
+(defun helm-help-internal (bufname insert-content-fn)
+ "Show long message during `helm' session in BUFNAME.
+INSERT-CONTENT-FN is the function that insert
+text to be displayed in BUFNAME."
+ (let ((winconf (current-frame-configuration))
+ (hframe (selected-frame)))
+ (with-selected-frame helm-initial-frame
+ (select-frame-set-input-focus helm-initial-frame)
+ (unwind-protect
+ (progn
+ (setq helm-suspend-update-flag t)
+ (set-buffer (get-buffer-create bufname))
+ (switch-to-buffer bufname)
+ (when helm-help-full-frame (delete-other-windows))
+ (delete-region (point-min) (point-max))
+ (org-mode)
+ (org-mark-ring-push) ; Put mark at bob
+ (save-excursion
+ (funcall insert-content-fn))
+ (buffer-disable-undo)
+ (helm-help-event-loop))
+ (raise-frame hframe)
+ (setq helm-suspend-update-flag nil)
+ (set-frame-configuration winconf)))))
+
+(defun helm-help-scroll-up (amount)
+ (condition-case _err
+ (scroll-up-command amount)
+ (beginning-of-buffer nil)
+ (end-of-buffer nil)))
+
+(defun helm-help-scroll-down (amount)
+ (condition-case _err
+ (scroll-down-command amount)
+ (beginning-of-buffer nil)
+ (end-of-buffer nil)))
+
+(defun helm-help-next-line ()
+ (condition-case _err
+ (call-interactively #'next-line)
+ (beginning-of-buffer nil)
+ (end-of-buffer nil)))
+
+(defun helm-help-previous-line ()
+ (condition-case _err
+ (call-interactively #'previous-line)
+ (beginning-of-buffer nil)
+ (end-of-buffer nil)))
+
+(defun helm-help-toggle-mark ()
+ (if (region-active-p)
+ (deactivate-mark)
+ (push-mark nil nil t)))
+
+;; For movement of cursor in help buffer we need to call interactively
+;; commands for impaired people using a synthetizer (#1347).
+(defun helm-help-event-loop ()
+ (let ((prompt (propertize
+ "[SPC,C-v,next:ScrollUp b,M-v,prior:ScrollDown TAB:Cycle M-TAB:All C-s/r:Isearch q:Quit]"
+ 'face 'helm-helper))
+ scroll-error-top-bottom
+ (iter-org-state (helm-iter-circular '(1 (16) (64)))))
+ (helm-awhile (read-key prompt)
+ (cl-case it
+ ((?\C-v ? next) (helm-help-scroll-up helm-scroll-amount))
+ ((?\M-v ?b prior) (helm-help-scroll-down helm-scroll-amount))
+ (?\C-s (isearch-forward))
+ (?\C-r (isearch-backward))
+ (?\C-a (call-interactively #'move-beginning-of-line))
+ (?\C-e (call-interactively #'move-end-of-line))
+ ((?\C-f right) (call-interactively #'forward-char))
+ ((?\C-b left) (call-interactively #'backward-char))
+ ((?\C-n down) (helm-help-next-line))
+ ((?\C-p up) (helm-help-previous-line))
+ (?\M-a (call-interactively #'backward-sentence))
+ (?\M-e (call-interactively #'forward-sentence))
+ (?\M-f (call-interactively #'forward-word))
+ (?\M-b (call-interactively #'backward-word))
+ (?\M-> (call-interactively #'end-of-buffer))
+ (?\M-< (call-interactively #'beginning-of-buffer))
+ (?\C- (helm-help-toggle-mark))
+ (?\t (org-cycle))
+ (?\C-m (ignore-errors (call-interactively #'org-open-at-point)))
+ (?\C-& (ignore-errors (call-interactively #'org-mark-ring-goto)))
+ (?\C-% (call-interactively #'org-mark-ring-push))
+ (?\M-\t (pcase (helm-iter-next iter-org-state)
+ ((pred numberp) (org-content))
+ ((and state) (org-cycle state))))
+ (?\M-w (copy-region-as-kill
+ (region-beginning) (region-end))
+ (deactivate-mark))
+ (?q (cl-return))
+ (t (ignore))))))
+
+\f
+;;; Multiline transformer
+;;
+(defun helm-multiline-transformer (candidates _source)
+ (cl-loop with offset = (helm-interpret-value
+ (assoc-default 'multiline (helm-get-current-source)))
+ for i in candidates
+ if (numberp offset)
+ collect (cons (helm--multiline-get-truncated-candidate i offset) i)
+ else collect i))
+
+(defun helm--multiline-get-truncated-candidate (candidate offset)
+ "Truncate CANDIDATE when its length is > than OFFSET."
+ (with-temp-buffer
+ (insert candidate)
+ (goto-char (point-min))
+ (if (and offset
+ (> (buffer-size) offset))
+ (let ((end-str "[...]"))
+ (concat
+ (buffer-substring
+ (point)
+ (save-excursion
+ (forward-char offset)
+ (setq end-str (if (looking-at "\n")
+ end-str (concat "\n" end-str)))
+ (point)))
+ end-str))
+ (buffer-string))))
+\f
+;;; List processing
+;;
+(defun helm-flatten-list (seq &optional omit-nulls)
+ "Return a list of all single elements of sublists in SEQ."
+ (let (result)
+ (cl-labels ((flatten (seq)
+ (cl-loop
+ for elm in seq
+ if (and (or elm
+ (null omit-nulls))
+ (or (atom elm)
+ (functionp elm)
+ (and (consp elm)
+ (cdr elm)
+ (atom (cdr elm)))))
+ do (push elm result)
+ else do (flatten elm))))
+ (flatten seq))
+ (nreverse result)))
+
+(defun helm-mklist (obj)
+ "If OBJ is a list \(but not lambda\), return itself.
+Otherwise make a list with one element."
+ (if (and (listp obj) (not (functionp obj)))
+ obj
+ (list obj)))
+
+(cl-defun helm-fast-remove-dups (seq &key (test 'eq))
+ "Remove duplicates elements in list SEQ.
+
+This is same as `remove-duplicates' but with memoisation.
+It is much faster, especially in large lists.
+A test function can be provided with TEST argument key.
+Default is `eq'.
+NOTE: Comparison of special elisp objects (e.g. markers etc...) fails
+because their printed representations which are stored in hash-table
+can't be compared with with the real object in SEQ.
+This is a bug in `puthash' which store the printable representation of
+object instead of storing the object itself, this to provide at the
+end a printable representation of hashtable itself."
+ (cl-loop with cont = (make-hash-table :test test)
+ for elm in seq
+ unless (gethash elm cont)
+ collect (puthash elm elm cont)))
+
+(defsubst helm--string-join (strings &optional separator)
+ "Join all STRINGS using SEPARATOR."
+ (mapconcat 'identity strings separator))
+
+(defun helm--concat-regexps (regexp-list)
+ "Return a regexp which matches any of the regexps in REGEXP-LIST."
+ (if regexp-list
+ (concat "\\(?:" (helm--string-join regexp-list "\\)\\|\\(?:") "\\)")
+ "\\<\\>")) ; Match nothing
+
+(defun helm-skip-entries (seq black-regexp-list &optional white-regexp-list)
+ "Remove entries which matches one of REGEXP-LIST from SEQ."
+ (let ((black-regexp (helm--concat-regexps black-regexp-list))
+ (white-regexp (helm--concat-regexps white-regexp-list)))
+ (cl-loop for i in seq
+ unless (and (stringp i)
+ (string-match-p black-regexp i)
+ (null
+ (string-match-p white-regexp i)))
+ collect i)))
+
+(defun helm-boring-directory-p (directory black-list)
+ "Check if one regexp in BLACK-LIST match DIRECTORY."
+ (helm-awhile (helm-basedir (directory-file-name
+ (expand-file-name directory)))
+ (when (string= it "/") (cl-return nil))
+ (when (cl-loop for r in black-list
+ thereis (string-match-p
+ r (directory-file-name directory)))
+ (cl-return t))
+ (setq directory it)))
+
+(defun helm-shadow-entries (seq regexp-list)
+ "Put shadow property on entries in SEQ matching a regexp in REGEXP-LIST."
+ (let ((face 'italic))
+ (cl-loop for i in seq
+ if (cl-loop for regexp in regexp-list
+ thereis (and (stringp i)
+ (string-match regexp i)))
+ collect (propertize i 'face face)
+ else collect i)))
+
+(defun helm-remove-if-not-match (regexp seq)
+ "Remove all elements of SEQ that don't match REGEXP."
+ (cl-loop for s in seq
+ for str = (cond ((symbolp s)
+ (symbol-name s))
+ ((consp s)
+ (car s))
+ (t s))
+ when (string-match-p regexp str)
+ collect s))
+
+(defun helm-remove-if-match (regexp seq)
+ "Remove all elements of SEQ that match REGEXP."
+ (cl-loop for s in seq
+ for str = (cond ((symbolp s)
+ (symbol-name s))
+ ((consp s)
+ (car s))
+ (t s))
+ unless (string-match-p regexp str)
+ collect s))
+
+(defun helm-transform-mapcar (function args)
+ "`mapcar' for candidate-transformer.
+
+ARGS is (cand1 cand2 ...) or ((disp1 . real1) (disp2 . real2) ...)
+
+\(helm-transform-mapcar 'upcase '(\"foo\" \"bar\"))
+=> (\"FOO\" \"BAR\")
+\(helm-transform-mapcar 'upcase '((\"1st\" . \"foo\") (\"2nd\" . \"bar\")))
+=> ((\"1st\" . \"FOO\") (\"2nd\" . \"BAR\"))
+"
+ (cl-loop for arg in args
+ if (consp arg)
+ collect (cons (car arg) (funcall function (cdr arg)))
+ else
+ collect (funcall function arg)))
+
+(defun helm-append-at-nth (seq elm index)
+ "Append ELM at INDEX in SEQ."
+ (let ((len (length seq)))
+ (cond ((> index len) (setq index len))
+ ((< index 0) (setq index 0)))
+ (if (zerop index)
+ (append elm seq)
+ (cl-loop for i in seq
+ for count from 1 collect i
+ when (= count index)
+ if (listp elm) append elm
+ else collect elm))))
+
+(defun helm-source-by-name (name &optional sources)
+ "Get a Helm source in SOURCES by NAME.
+
+Optional argument SOURCES is a list of Helm sources which default to
+`helm-sources'."
+ (cl-loop with src-list = (if sources
+ (cl-loop for src in sources
+ collect (if (listp src)
+ src
+ (symbol-value src)))
+ helm-sources)
+ for source in src-list
+ thereis (and (string= name (assoc-default 'name source)) source)))
+
+(defun helm-make-actions (&rest args)
+ "Build an alist with (NAME . ACTION) elements with each pairs in ARGS.
+Where NAME is a string or a function returning a string or nil and ACTION
+a function.
+If NAME returns nil the pair is skipped.
+
+\(fn NAME ACTION ...)"
+ (cl-loop for (name fn) on args by #'cddr
+ when (functionp name)
+ do (setq name (funcall name))
+ when name
+ collect (cons name fn)))
+\f
+;;; Strings processing.
+;;
+(defun helm-stringify (elm)
+ "Return the representation of ELM as a string.
+ELM can be a string, a number or a symbol."
+ (cl-typecase elm
+ (string elm)
+ (number (number-to-string elm))
+ (symbol (symbol-name elm))))
+
+(defun helm-substring (str width)
+ "Return the substring of string STR from 0 to WIDTH.
+Handle multibyte characters by moving by columns."
+ (with-temp-buffer
+ (save-excursion
+ (insert str))
+ (move-to-column width)
+ (buffer-substring (point-at-bol) (point))))
+
+(defun helm-substring-by-width (str width &optional endstr)
+ "Truncate string STR to end at column WIDTH.
+Similar to `truncate-string-to-width'.
+Add ENDSTR at end of truncated STR.
+Add spaces at end if needed to reach WIDTH when STR is shorter than WIDTH."
+ (cl-loop for ini-str = str
+ then (substring ini-str 0 (1- (length ini-str)))
+ for sw = (string-width ini-str)
+ when (<= sw width) return
+ (concat ini-str endstr (make-string (- width sw) ? ))))
+
+(defun helm-string-multibyte-p (str)
+ "Check if string STR contains multibyte characters."
+ (cl-loop for c across str
+ thereis (> (char-width c) 1)))
+
+(defun helm-get-pid-from-process-name (process-name)
+ "Get pid from running process PROCESS-NAME."
+ (cl-loop with process-list = (list-system-processes)
+ for pid in process-list
+ for process = (assoc-default 'comm (process-attributes pid))
+ when (and process (string-match process-name process))
+ return pid))
+
+(defun helm-ff-find-printers ()
+ "Return a list of available printers on Unix systems."
+ (when (executable-find "lpstat")
+ (let ((printer-list (with-temp-buffer
+ (call-process "lpstat" nil t nil "-a")
+ (split-string (buffer-string) "\n"))))
+ (cl-loop for p in printer-list
+ for printer = (car (split-string p))
+ when printer
+ collect printer))))
+
+(defun helm-region-active-p ()
+ (and transient-mark-mode mark-active (/= (mark) (point))))
+
+(defun helm-quote-whitespace (candidate)
+ "Quote whitespace, if some, in string CANDIDATE."
+ (replace-regexp-in-string " " "\\\\ " candidate))
+
+(defun helm-current-line-contents ()
+ "Current line string without properties."
+ (buffer-substring-no-properties (point-at-bol) (point-at-eol)))
+
+(defun helm--replace-regexp-in-buffer-string (regexp rep str &optional fixedcase literal subexp start)
+ "Replace REGEXP by REP in string STR.
+
+Same as `replace-regexp-in-string' but handle properly REP as
+function with SUBEXP specified.
+
+e.g
+
+ (helm--replace-regexp-in-buffer-string \"e\\\\(m\\\\)acs\" 'upcase \"emacs\" t nil 1)
+ => \"eMacs\"
+
+ (replace-regexp-in-string \"e\\\\(m\\\\)acs\" 'upcase \"emacs\" t nil 1)
+ => \"eEMACSacs\"
+
+Also START argument behave as expected unlike
+`replace-regexp-in-string'.
+
+e.g
+
+ (helm--replace-regexp-in-buffer-string \"f\" \"r\" \"foofoo\" t nil nil 3)
+ => \"fooroo\"
+
+ (replace-regexp-in-string \"f\" \"r\" \"foofoo\" t nil nil 3)
+ => \"roo\"
+
+Unlike `replace-regexp-in-string' this function is buffer-based
+implemented i.e replacement is computed inside a temp buffer, so
+REGEXP should be used differently than with
+`replace-regexp-in-string'.
+
+NOTE: This function is used internally for
+`helm-ff-query-replace-on-filenames' and builded for this.
+You should use `replace-regexp-in-string' instead unless the behavior
+of this function is really needed."
+ (with-temp-buffer
+ (insert str)
+ (goto-char (or start (point-min)))
+ (while (re-search-forward regexp nil t)
+ (replace-match (cond ((and (functionp rep) subexp)
+ (funcall rep (match-string subexp)))
+ ((functionp rep)
+ (funcall rep str))
+ (t rep))
+ fixedcase literal nil subexp))
+ (buffer-string)))
+
+(defun helm-url-unhex-string (str)
+ "Same as `url-unhex-string' but ensure STR is completely decoded."
+ (setq str (or str ""))
+ (with-temp-buffer
+ (save-excursion (insert str))
+ (while (re-search-forward "%[A-Za-z0-9]\\{2\\}" nil t)
+ (replace-match (byte-to-string (string-to-number
+ (substring (match-string 0) 1)
+ 16))
+ t t)
+ ;; Restart from beginning until string is completely decoded.
+ (goto-char (point-min)))
+ (decode-coding-string (buffer-string) 'utf-8)))
+
+(defun helm-read-answer (prompt answer-list)
+ "Prompt user for an answer.
+Arg PROMPT is the prompt to present user the different possible
+answers, ANSWER-LIST is a list of strings.
+If user enter an answer which is one of ANSWER-LIST return this
+answer, otherwise keep prompting for a valid answer.
+Note that answer should be a single char, only short answer are
+accepted.
+
+Example:
+
+ (let ((answer (helm-read-answer
+ \"answer [y,n,!,q]: \"
+ '(\"y\" \"n\" \"!\" \"q\"))))
+ (pcase answer
+ (\"y\" \"yes\")
+ (\"n\" \"no\")
+ (\"!\" \"all\")
+ (\"q\" \"quit\")))
+
+"
+ (helm-awhile (string
+ (read-key (propertize prompt 'face 'minibuffer-prompt)))
+ (if (member it answer-list)
+ (cl-return it)
+ (message "Please answer by %s" (mapconcat 'identity answer-list ", "))
+ (sit-for 1))))
+\f
+;;; Symbols routines
+;;
+(defun helm-symbolify (str-or-sym)
+ "Get symbol of STR-OR-SYM."
+ (if (symbolp str-or-sym)
+ str-or-sym
+ (intern str-or-sym)))
+
+(defun helm-symbol-name (obj)
+ (if (or (and (consp obj) (functionp obj))
+ (byte-code-function-p obj))
+ "Anonymous"
+ (symbol-name obj)))
+
+(defun helm-describe-function (func)
+ "FUNC is symbol or string."
+ (cl-letf (((symbol-function 'message) #'ignore))
+ (describe-function (helm-symbolify func))))
+
+(defun helm-describe-variable (var)
+ "VAR is symbol or string."
+ (cl-letf (((symbol-function 'message) #'ignore))
+ (describe-variable (helm-symbolify var))))
+
+(defun helm-describe-face (face)
+ "FACE is symbol or string."
+ (let ((faces (helm-marked-candidates)))
+ (cl-letf (((symbol-function 'message) #'ignore))
+ (describe-face (if (cdr faces)
+ (mapcar 'helm-symbolify faces)
+ (helm-symbolify face))))))
+
+(defun helm-elisp--persistent-help (candidate fun &optional name)
+ "Used to build persistent actions describing CANDIDATE with FUN.
+Argument NAME is used internally to know which command to use when
+symbol CANDIDATE refers at the same time to variable and a function.
+See `helm-elisp-show-help'."
+ (let ((hbuf (get-buffer (help-buffer))))
+ (cond ((helm-follow-mode-p)
+ (if name
+ (funcall fun candidate name)
+ (funcall fun candidate)))
+ ((or (and (helm-attr 'help-running-p)
+ (string= candidate (helm-attr 'help-current-symbol))))
+ (progn
+ ;; When started from a help buffer,
+ ;; Don't kill this buffer as it is helm-current-buffer.
+ (unless (equal hbuf helm-current-buffer)
+ (set-window-buffer (get-buffer-window hbuf)
+ helm-current-buffer)
+ (kill-buffer hbuf))
+ (helm-attrset 'help-running-p nil)))
+ (t
+ (if name
+ (funcall fun candidate name)
+ (funcall fun candidate))
+ (helm-attrset 'help-running-p t)))
+ (helm-attrset 'help-current-symbol candidate)))
+
+(defun helm-find-function (func)
+ "FUNC is symbol or string."
+ (find-function (helm-symbolify func)))
+
+(defun helm-find-variable (var)
+ "VAR is symbol or string."
+ (find-variable (helm-symbolify var)))
+
+(defun helm-find-face-definition (face)
+ "FACE is symbol or string."
+ (find-face-definition (helm-symbolify face)))
+
+(defun helm-kill-new (candidate &optional replace)
+ "CANDIDATE is symbol or string.
+See `kill-new' for argument REPLACE."
+ (kill-new (helm-stringify candidate) replace))
+
+\f
+;;; Modes
+;;
+(defun helm-same-major-mode-p (start-buffer alist)
+ "Decide if current-buffer is related to START-BUFFER.
+Argument ALIST is an alist of associated major modes."
+ ;; START-BUFFER is the current-buffer where we start searching.
+ ;; Determine the major-mode of START-BUFFER as `cur-maj-mode'.
+ ;; Each time the loop go in another buffer we try from this buffer
+ ;; to determine if its `major-mode' is:
+ ;; - same as the `cur-maj-mode'
+ ;; - derived from `cur-maj-mode' and from
+ ;; START-BUFFER if its mode is derived from the one in START-BUFFER.
+ ;; - have an assoc entry (major-mode . cur-maj-mode)
+ ;; - have an rassoc entry (cur-maj-mode . major-mode)
+ ;; - check if one of these entries inherit from another one in
+ ;; `alist'.
+ (let* ((cur-maj-mode (with-current-buffer start-buffer major-mode))
+ (maj-mode major-mode)
+ (c-assoc-mode (assq cur-maj-mode alist))
+ (c-rassoc-mode (rassq cur-maj-mode alist))
+ (o-assoc-mode (assq major-mode alist))
+ (o-rassoc-mode (rassq major-mode alist))
+ (cdr-c-assoc-mode (cdr c-assoc-mode))
+ (cdr-o-assoc-mode (cdr o-assoc-mode)))
+ (or (eq major-mode cur-maj-mode)
+ (derived-mode-p cur-maj-mode)
+ (with-current-buffer start-buffer
+ (derived-mode-p maj-mode))
+ (or (eq cdr-c-assoc-mode major-mode)
+ (eq (car c-rassoc-mode) major-mode)
+ (eq (cdr (assq cdr-c-assoc-mode alist))
+ major-mode)
+ (eq (car (rassq cdr-c-assoc-mode alist))
+ major-mode))
+ (or (eq cdr-o-assoc-mode cur-maj-mode)
+ (eq (car o-rassoc-mode) cur-maj-mode)
+ (eq (cdr (assq cdr-o-assoc-mode alist))
+ cur-maj-mode)
+ (eq (car (rassq cdr-o-assoc-mode alist))
+ cur-maj-mode)))))
+\f
+;;; Files routines
+;;
+(defun helm-file-name-sans-extension (filename)
+ "Same as `file-name-sans-extension' but remove all extensions."
+ (helm-aif (file-name-sans-extension filename)
+ ;; Start searching at index 1 for files beginning with a dot (#1335).
+ (if (string-match "\\." (helm-basename it) 1)
+ (helm-file-name-sans-extension it)
+ it)))
+
+(defun helm-basename (fname &optional ext)
+ "Print FNAME with any leading directory components removed.
+If specified, also remove filename extension EXT.
+Arg EXT can be specified as a string with or without dot,
+in this case it should match file-name-extension.
+It can also be non-nil (`t') in this case no checking
+of file-name-extension is done and the extension is removed
+unconditionally."
+ (let ((non-essential t))
+ (if (and ext (or (string= (file-name-extension fname) ext)
+ (string= (file-name-extension fname t) ext)
+ (eq ext t))
+ (not (file-directory-p fname)))
+ (file-name-sans-extension (file-name-nondirectory fname))
+ (file-name-nondirectory (directory-file-name fname)))))
+
+(defun helm-basedir (fname)
+ "Return the base directory of filename ending by a slash."
+ (helm-aif (and fname
+ (or (and (string= fname "~") "~")
+ (file-name-directory fname)))
+ (file-name-as-directory it)))
+
+(defun helm-current-directory ()
+ "Return current-directory name at point.
+Useful in dired buffers when there is inserted subdirs."
+ (expand-file-name
+ (if (eq major-mode 'dired-mode)
+ (dired-current-directory)
+ default-directory)))
+
+(defun helm-shadow-boring-files (files)
+ "Files matching `helm-boring-file-regexp' will be
+displayed with the `file-name-shadow' face if available."
+ (helm-shadow-entries files helm-boring-file-regexp-list))
+
+(defun helm-skip-boring-files (files)
+ "Files matching `helm-boring-file-regexp' will be skipped."
+ (helm-skip-entries files helm-boring-file-regexp-list))
+
+(defun helm-skip-current-file (files)
+ "Current file will be skipped."
+ (remove (buffer-file-name helm-current-buffer) files))
+
+(defun helm-w32-pathname-transformer (args)
+ "Change undesirable features of windows pathnames to ones more acceptable to
+other candidate transformers."
+ (if (eq system-type 'windows-nt)
+ (helm-transform-mapcar
+ (lambda (x)
+ (replace-regexp-in-string
+ "/cygdrive/\\(.\\)" "\\1:"
+ (replace-regexp-in-string "\\\\" "/" x)))
+ args)
+ args))
+
+(defun helm-w32-prepare-filename (file)
+ "Convert filename FILE to something usable by external w32 executables."
+ (replace-regexp-in-string ; For UNC paths
+ "/" "\\"
+ (replace-regexp-in-string ; Strip cygdrive paths
+ "/cygdrive/\\(.\\)" "\\1:"
+ file nil nil) nil t))
+
+(defun helm-w32-shell-execute-open-file (file)
+ (with-no-warnings
+ (w32-shell-execute "open" (helm-w32-prepare-filename file))))
+
+;; Same as `vc-directory-exclusion-list'.
+(defvar helm-walk-ignore-directories
+ '("SCCS/" "RCS/" "CVS/" "MCVS/" ".svn/" ".git/" ".hg/" ".bzr/"
+ "_MTN/" "_darcs/" "{arch}/" ".gvfs/"))
+
+(defsubst helm--dir-file-name (file dir)
+ (expand-file-name
+ (substring file 0 (1- (length file))) dir))
+
+(defsubst helm--dir-name-p (str)
+ (char-equal (aref str (1- (length str))) ?/))
+
+(cl-defun helm-walk-directory (directory &key (path 'basename)
+ directories
+ match skip-subdirs)
+ "Walk through DIRECTORY tree.
+
+Argument PATH can be one of basename, relative, full, or a function
+called on file name, default to basename.
+
+Argument DIRECTORIES when non--nil (default) return also directories names,
+otherwise skip directories names, with a value of 'only returns
+only subdirectories, i.e files are skipped.
+
+Argument MATCH is a regexp matching files or directories.
+
+Argument SKIP-SUBDIRS when `t' will skip `helm-walk-ignore-directories'
+otherwise if it is given as a list of directories, this list will be used
+instead of `helm-walk-ignore-directories'."
+ (let ((fn (cl-case path
+ (basename 'file-name-nondirectory)
+ (relative 'file-relative-name)
+ (full 'identity)
+ (t path)))) ; A function.
+ (setq skip-subdirs (if (listp skip-subdirs)
+ skip-subdirs
+ helm-walk-ignore-directories))
+ (cl-labels ((ls-rec (dir)
+ (unless (file-symlink-p dir)
+ (cl-loop for f in (sort (file-name-all-completions "" dir)
+ 'string-lessp)
+ unless (member f '("./" "../"))
+ ;; A directory.
+ ;; Use `helm--dir-file-name' to remove the final slash.
+ ;; Needed to avoid infloop on directory symlinks.
+ if (and (helm--dir-name-p f)
+ (helm--dir-file-name f dir))
+ nconc
+ (unless (member f skip-subdirs)
+ (if (and directories
+ (or (null match)
+ (string-match match f)))
+ (nconc (list (concat (funcall fn it) "/"))
+ (ls-rec it))
+ (ls-rec it)))
+ ;; A regular file.
+ else nconc
+ (when (and (null (eq directories 'only))
+ (or (null match) (string-match match f)))
+ (list (funcall fn (expand-file-name f dir))))))))
+ (ls-rec directory))))
+
+(defun helm-file-expand-wildcards (pattern &optional full)
+ "Same as `file-expand-wildcards' but allow recursion.
+Recursion happen when PATTERN starts with two stars.
+Directories expansion is not supported."
+ (let ((bn (helm-basename pattern))
+ (case-fold-search nil))
+ (if (and helm-file-globstar
+ (string-match "\\`\\*\\{2\\}\\(.*\\)" bn))
+ (helm-walk-directory (helm-basedir pattern)
+ :path (cl-case full
+ (full 'full)
+ (relative 'relative)
+ ((basename nil) 'basename)
+ (t 'full))
+ :directories nil
+ :match (wildcard-to-regexp bn)
+ :skip-subdirs t)
+ (file-expand-wildcards pattern full))))
+\f
+;;; helm internals
+;;
+(defun helm-set-pattern (pattern &optional noupdate)
+ "Set minibuffer contents to PATTERN.
+if optional NOUPDATE is non-nil, helm buffer is not changed."
+ (with-selected-window (or (active-minibuffer-window) (minibuffer-window))
+ (delete-minibuffer-contents)
+ (insert pattern))
+ (when noupdate
+ (setq helm-pattern pattern)))
+
+(defun helm-minibuffer-completion-contents ()
+ "Return the user input in a minibuffer before point as a string.
+That is what completion commands operate on."
+ (buffer-substring (field-beginning) (point)))
+
+(defmacro with-helm-buffer (&rest body)
+ "Eval BODY inside `helm-buffer'."
+ (declare (indent 0) (debug t))
+ `(with-current-buffer (helm-buffer-get)
+ ,@body))
+
+(defmacro with-helm-current-buffer (&rest body)
+ "Eval BODY inside `helm-current-buffer'."
+ (declare (indent 0) (debug t))
+ `(with-current-buffer (or (and (buffer-live-p helm-current-buffer)
+ helm-current-buffer)
+ (setq helm-current-buffer
+ (current-buffer)))
+ ,@body))
+
+(defun helm-buffer-get ()
+ "Return `helm-action-buffer' if shown otherwise `helm-buffer'."
+ (if (helm-action-window)
+ helm-action-buffer
+ helm-buffer))
+
+(defun helm-window ()
+ "Window of `helm-buffer'."
+ (get-buffer-window (helm-buffer-get) 0))
+
+(defun helm-action-window ()
+ "Window of `helm-action-buffer'."
+ (get-buffer-window helm-action-buffer 'visible))
+
+(defmacro with-helm-window (&rest body)
+ "Be sure BODY is excuted in the helm window."
+ (declare (indent 0) (debug t))
+ `(with-selected-window (helm-window)
+ ,@body))
+
+\f
+;; Yank text at point.
+;;
+;;
+(defun helm-yank-text-at-point (arg)
+ "Yank text at point in `helm-current-buffer' into minibuffer."
+ (interactive "p")
+ (with-helm-current-buffer
+ (let ((fwd-fn (or helm-yank-text-at-point-function #'forward-word))
+ diff)
+ ;; Start to initial point if C-w have never been hit.
+ (unless helm-yank-point
+ (setq helm-yank-point (car helm-current-position)))
+ (save-excursion
+ (goto-char helm-yank-point)
+ (helm-set-pattern
+ (if (< arg 0)
+ (with-temp-buffer
+ (insert helm-pattern)
+ (let ((end (point-max)))
+ (goto-char end)
+ (funcall fwd-fn -1)
+ (setq diff (- end (point)))
+ (delete-region (point) end)
+ (buffer-string)))
+ (funcall fwd-fn arg)
+ (concat
+ ;; Allow yankink beyond eol allow inserting e.g long
+ ;; urls in mail buffers.
+ helm-pattern (replace-regexp-in-string
+ "\\`\n" ""
+ (buffer-substring-no-properties
+ helm-yank-point (point))))))
+ (setq helm-yank-point (if diff (- (point) diff) (point)))))))
+(put 'helm-yank-text-at-point 'helm-only t)
+
+(defun helm-undo-yank-text-at-point ()
+ "Undo last entry added by `helm-yank-text-at-point'."
+ (interactive)
+ (helm-yank-text-at-point -1))
+(put 'helm-undo-yank-text-at-point 'helm-only t)
+
+(defun helm-reset-yank-point ()
+ (setq helm-yank-point nil))
+
+(add-hook 'helm-cleanup-hook 'helm-reset-yank-point)
+(add-hook 'helm-after-initialize-hook 'helm-reset-yank-point)
+
+;;; Ansi
+;;
+;;
+(defvar helm--ansi-color-regexp
+ "\033\\[\\(K\\|[0-9;]*m\\)")
+(defvar helm--ansi-color-drop-regexp
+ "\033\\[\\([ABCDsuK]\\|[12][JK]\\|=[0-9]+[hI]\\|[0-9;]*[Hf]\\)")
+(defun helm--ansi-color-apply (string)
+ "A version of `ansi-color-apply' immune to upstream changes.
+
+Similar to the emacs-24.5 version without support to `ansi-color-context'
+which is buggy in emacs.
+
+Modify also `ansi-color-regexp' by using own variable `helm--ansi-color-regexp'
+that match whole STRING.
+
+This is needed to provide compatibility for both emacs-25 and emacs-24.5
+as emacs-25 version of `ansi-color-apply' is partially broken."
+ (let ((start 0)
+ codes end escape-sequence
+ result colorized-substring)
+ ;; Find the next escape sequence.
+ (while (setq end (string-match helm--ansi-color-regexp string start))
+ (setq escape-sequence (match-string 1 string))
+ ;; Colorize the old block from start to end using old face.
+ (when codes
+ (put-text-property
+ start end 'font-lock-face (ansi-color--find-face codes) string))
+ (setq colorized-substring (substring string start end)
+ start (match-end 0))
+ ;; Eliminate unrecognized ANSI sequences.
+ (while (string-match helm--ansi-color-drop-regexp colorized-substring)
+ (setq colorized-substring
+ (replace-match "" nil nil colorized-substring)))
+ (push colorized-substring result)
+ ;; Create new face, by applying escape sequence parameters.
+ (setq codes (ansi-color-apply-sequence escape-sequence codes)))
+ ;; If the rest of the string should have a face, put it there.
+ (when codes
+ (put-text-property
+ start (length string)
+ 'font-lock-face (ansi-color--find-face codes) string))
+ ;; Save the remainder of the string to the result.
+ (if (string-match "\033" string start)
+ (push (substring string start (match-beginning 0)) result)
+ (push (substring string start) result))
+ (apply 'concat (nreverse result))))
+
+(provide 'helm-lib)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-lib ends here
--- /dev/null
+;;; helm-multi-match.el --- Multiple regexp matching methods for helm -*- lexical-binding: t -*-
+
+;; Original Author: rubikitch
+
+;; Copyright (C) 2008 ~ 2011 rubikitch
+;; Copyright (C) 2011 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; Author: Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+;; URL: http://github.com/emacs-helm/helm
+
+;; 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/>.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'helm-lib)
+
+\f
+(defgroup helm-multi-match nil
+ "Helm multi match."
+ :group 'helm)
+
+(defcustom helm-mm-matching-method 'multi3
+ "Matching method for helm match plugin.
+You can set here different methods to match candidates in helm.
+Here are the possible value of this symbol and their meaning:
+- multi1: Respect order, prefix of pattern must match.
+- multi2: Same but with partial match.
+- multi3: The best, multiple regexp match, allow negation.
+- multi3p: Same but prefix must match.
+
+Default is multi3, you should keep this for a better experience.
+
+Note that multi1 and multi3p are incompatible with fuzzy matching
+in file completion and by the way fuzzy matching will be disabled there
+when these options are used."
+ :type '(radio :tag "Matching methods for helm"
+ (const :tag "Multiple regexp 1 ordered with prefix match" multi1)
+ (const :tag "Multiple regexp 2 ordered with partial match" multi2)
+ (const :tag "Multiple regexp 3 matching no order, partial, best." multi3)
+ (const :tag "Multiple regexp 3p matching with prefix match" multi3p))
+ :group 'helm-multi-match)
+
+\f
+;; Internal
+(defvar helm-mm-default-match-functions
+ '(helm-mm-exact-match helm-mm-match))
+(defvar helm-mm-default-search-functions
+ '(helm-mm-exact-search helm-mm-search))
+
+\f
+;;; Build regexps
+;;
+;;
+(defconst helm-mm-space-regexp "\\s\\\\s-"
+ "Regexp to represent space itself in multiple regexp match.")
+
+(defun helm-mm-split-pattern (pattern &optional grep-space)
+ "Split PATTERN if it contain spaces and return resulting list.
+If spaces in PATTERN are escaped, don't split at this place.
+i.e \"foo bar baz\"=> (\"foo\" \"bar\" \"baz\")
+but \"foo\\ bar baz\"=> (\"foo\\s-bar\" \"baz\").
+If GREP-SPACE is used translate escaped space to \"\\s\" instead of \"\\s-\"."
+ (split-string
+ ;; Match spaces litteraly because candidate buffer syntax-table
+ ;; doesn't understand "\s-" properly.
+ (replace-regexp-in-string
+ helm-mm-space-regexp
+ (if grep-space "\\s" "\\s-") pattern nil t)))
+
+(defun helm-mm-1-make-regexp (pattern)
+ "Replace spaces in PATTERN with \"\.*\"."
+ (mapconcat 'identity (helm-mm-split-pattern pattern) ".*"))
+
+\f
+;;; Exact match.
+;;
+;;
+;; Internal.
+(defvar helm-mm-exact-pattern-str nil)
+(defvar helm-mm-exact-pattern-real nil)
+
+(defun helm-mm-exact-get-pattern (pattern)
+ (unless (equal pattern helm-mm-exact-pattern-str)
+ (setq helm-mm-exact-pattern-str pattern
+ helm-mm-exact-pattern-real (concat "\n" pattern "\n")))
+ helm-mm-exact-pattern-real)
+
+
+(cl-defun helm-mm-exact-match (str &optional (pattern helm-pattern))
+ (if case-fold-search
+ (progn
+ (setq str (downcase str)
+ pattern (downcase pattern))
+ (string= str pattern))
+ (string= str pattern)))
+
+(defun helm-mm-exact-search (pattern &rest _ignore)
+ (and (search-forward (helm-mm-exact-get-pattern pattern) nil t)
+ (forward-line -1)))
+
+\f
+;;; Prefix match
+;;
+;;
+;; Internal
+(defvar helm-mm-prefix-pattern-str nil)
+(defvar helm-mm-prefix-pattern-real nil)
+
+(defun helm-mm-prefix-get-pattern (pattern)
+ (unless (equal pattern helm-mm-prefix-pattern-str)
+ (setq helm-mm-prefix-pattern-str pattern
+ helm-mm-prefix-pattern-real (concat "\n" pattern)))
+ helm-mm-prefix-pattern-real)
+
+(defun helm-mm-prefix-match (str &optional pattern)
+ ;; In filename completion basename and basedir may be
+ ;; quoted, unquote them for string comparison (Issue #1283).
+ (setq pattern (replace-regexp-in-string
+ "\\\\" "" (or pattern helm-pattern)))
+ (let ((len (length pattern)))
+ (and (<= len (length str))
+ (string= (substring str 0 len) pattern ))))
+
+(defun helm-mm-prefix-search (pattern &rest _ignore)
+ (search-forward (helm-mm-prefix-get-pattern pattern) nil t))
+
+\f
+;;; Multiple regexp patterns 1 (order is preserved / prefix).
+;;
+;;
+;; Internal
+(defvar helm-mm-1-pattern-str nil)
+(defvar helm-mm-1-pattern-real nil)
+
+(defun helm-mm-1-get-pattern (pattern)
+ (unless (equal pattern helm-mm-1-pattern-str)
+ (setq helm-mm-1-pattern-str pattern
+ helm-mm-1-pattern-real
+ (concat "^" (helm-mm-1-make-regexp pattern))))
+ helm-mm-1-pattern-real)
+
+(cl-defun helm-mm-1-match (str &optional (pattern helm-pattern))
+ (string-match (helm-mm-1-get-pattern pattern) str))
+
+(defun helm-mm-1-search (pattern &rest _ignore)
+ (re-search-forward (helm-mm-1-get-pattern pattern) nil t))
+
+\f
+;;; Multiple regexp patterns 2 (order is preserved / partial).
+;;
+;;
+;; Internal
+(defvar helm-mm-2-pattern-str nil)
+(defvar helm-mm-2-pattern-real nil)
+
+(defun helm-mm-2-get-pattern (pattern)
+ (unless (equal pattern helm-mm-2-pattern-str)
+ (setq helm-mm-2-pattern-str pattern
+ helm-mm-2-pattern-real
+ (concat "^.*" (helm-mm-1-make-regexp pattern))))
+ helm-mm-2-pattern-real)
+
+(cl-defun helm-mm-2-match (str &optional (pattern helm-pattern))
+ (string-match (helm-mm-2-get-pattern pattern) str))
+
+(defun helm-mm-2-search (pattern &rest _ignore)
+ (re-search-forward (helm-mm-2-get-pattern pattern) nil t))
+
+\f
+;;; Multiple regexp patterns 3 (permutation).
+;;
+;;
+;; Internal
+(defvar helm-mm-3-pattern-str nil)
+(defvar helm-mm-3-pattern-list nil)
+
+(defun helm-mm-3-get-patterns (pattern)
+ "Return `helm-mm-3-pattern-list', a list of predicate/regexp cons cells.
+e.g ((identity . \"foo\") (identity . \"bar\")).
+This is done only if `helm-mm-3-pattern-str' is same as PATTERN."
+ (unless (equal pattern helm-mm-3-pattern-str)
+ (setq helm-mm-3-pattern-str pattern
+ helm-mm-3-pattern-list
+ (helm-mm-3-get-patterns-internal pattern)))
+ helm-mm-3-pattern-list)
+
+(defun helm-mm-3-get-patterns-internal (pattern)
+ "Return a list of predicate/regexp cons cells.
+e.g ((identity . \"foo\") (identity . \"bar\"))."
+ (unless (string= pattern "")
+ (cl-loop for pat in (helm-mm-split-pattern pattern)
+ collect (if (string= "!" (substring pat 0 1))
+ (cons 'not (substring pat 1))
+ (cons 'identity pat)))))
+
+(cl-defun helm-mm-3-match (str &optional (pattern helm-pattern))
+ "Check if PATTERN match STR.
+When PATTERN contain a space, it is splitted and matching is done
+with the several resulting regexps against STR.
+e.g \"bar foo\" will match \"foobar\" and \"barfoo\".
+Argument PATTERN, a string, is transformed in a list of
+cons cell with `helm-mm-3-get-patterns' if it contain a space.
+e.g \"foo bar\"=>((identity . \"foo\") (identity . \"bar\")).
+Then each predicate of cons cell(s) is called with regexp of same
+cons cell against STR (a candidate).
+i.e (identity (string-match \"foo\" \"foo bar\")) => t."
+ (let ((pat (helm-mm-3-get-patterns pattern)))
+ (cl-loop for (predicate . regexp) in pat
+ always (funcall predicate
+ (condition-case _err
+ ;; FIXME: Probably do nothing when
+ ;; using fuzzy leaving the job
+ ;; to the fuzzy fn.
+ (string-match regexp str)
+ (invalid-regexp nil))))))
+
+(defun helm-mm-3-search-base (pattern searchfn1 searchfn2)
+ "Try to find PATTERN in `helm-buffer' with SEARCHFN1 and SEARCHFN2.
+This is the search function for `candidates-in-buffer' enabled sources.
+Use the same method as `helm-mm-3-match' except it search in buffer
+instead of matching on a string.
+i.e (identity (re-search-forward \"foo\" (point-at-eol) t)) => t."
+ (cl-loop with pat = (if (stringp pattern)
+ (helm-mm-3-get-patterns pattern)
+ pattern)
+ when (eq (caar pat) 'not) return
+ ;; Pass the job to `helm-search-match-part'.
+ (prog1 (list (point-at-bol) (point-at-eol))
+ (forward-line 1))
+ while (condition-case _err
+ (funcall searchfn1 (or (cdar pat) "") nil t)
+ (invalid-regexp nil))
+ for bol = (point-at-bol)
+ for eol = (point-at-eol)
+ if (cl-loop for (pred . str) in (cdr pat) always
+ (progn (goto-char bol)
+ (funcall pred (condition-case _err
+ (funcall searchfn2 str eol t)
+ (invalid-regexp nil)))))
+ do (goto-char eol) and return t
+ else do (goto-char eol)
+ finally return nil))
+
+(defun helm-mm-3-search (pattern &rest _ignore)
+ (when (stringp pattern)
+ (setq pattern (helm-mm-3-get-patterns pattern)))
+ (helm-mm-3-search-base
+ pattern 're-search-forward 're-search-forward))
+\f
+;;; mp-3 with migemo
+;;
+;;
+(defvar helm-mm--previous-migemo-info nil
+ "[Internal] Cache previous migemo query.")
+(make-local-variable 'helm-mm--previous-migemo-info)
+
+(declare-function migemo-get-pattern "ext:migemo.el")
+(declare-function migemo-search-pattern-get "ext:migemo.el")
+
+(define-minor-mode helm-migemo-mode
+ "Enable migemo in helm.
+It will be available in the sources handling it,
+i.e the sources which have the slot :migemo with non--nil value."
+ :lighter " Hmio"
+ :group 'helm
+ :global t
+ (cl-assert (featurep 'migemo)
+ nil "No feature called migemo found, install migemo.el."))
+
+(defun helm-mm-migemo-get-pattern (pattern)
+ (let ((regex (migemo-get-pattern pattern)))
+ (if (ignore-errors (string-match regex "") t)
+ (concat regex "\\|" pattern) pattern)))
+
+(defun helm-mm-migemo-search-pattern-get (pattern)
+ (let ((regex (migemo-search-pattern-get pattern)))
+ (if (ignore-errors (string-match regex "") t)
+ (concat regex "\\|" pattern) pattern)))
+
+(defun helm-mm-migemo-string-match (pattern str)
+ "Migemo version of `string-match'."
+ (unless (assoc pattern helm-mm--previous-migemo-info)
+ (with-helm-buffer
+ (setq helm-mm--previous-migemo-info
+ (push (cons pattern (helm-mm-migemo-get-pattern pattern))
+ helm-mm--previous-migemo-info))))
+ (string-match (assoc-default pattern helm-mm--previous-migemo-info) str))
+
+(cl-defun helm-mm-3-migemo-match (str &optional (pattern helm-pattern))
+ (and helm-migemo-mode
+ (cl-loop for (pred . re) in (helm-mm-3-get-patterns pattern)
+ always (funcall pred (helm-mm-migemo-string-match re str)))))
+
+(defun helm-mm-migemo-forward (word &optional bound noerror count)
+ (with-helm-buffer
+ (unless (assoc word helm-mm--previous-migemo-info)
+ (setq helm-mm--previous-migemo-info
+ (push (cons word (if (delq 'ascii (find-charset-string word))
+ word
+ (helm-mm-migemo-search-pattern-get word)))
+ helm-mm--previous-migemo-info))))
+ (re-search-forward
+ (assoc-default word helm-mm--previous-migemo-info) bound noerror count))
+
+(defun helm-mm-3-migemo-search (pattern &rest _ignore)
+ (and helm-migemo-mode
+ (helm-mm-3-search-base
+ pattern 'helm-mm-migemo-forward 'helm-mm-migemo-forward)))
+
+\f
+;;; mp-3p- (multiple regexp pattern 3 with prefix search)
+;;
+;;
+(defun helm-mm-3p-match (str &optional pattern)
+ "Check if PATTERN match STR.
+Same as `helm-mm-3-match' but more strict, matching against prefix also.
+e.g \"bar foo\" will match \"barfoo\" but not \"foobar\" contrarily to
+`helm-mm-3-match'."
+ (let* ((pat (helm-mm-3-get-patterns (or pattern helm-pattern)))
+ (first (car pat)))
+ (and (funcall (car first) (helm-mm-prefix-match str (cdr first)))
+ (cl-loop for (predicate . regexp) in (cdr pat)
+ always (funcall predicate (string-match regexp str))))))
+
+(defun helm-mm-3p-search (pattern &rest _ignore)
+ (when (stringp pattern)
+ (setq pattern (helm-mm-3-get-patterns pattern)))
+ (helm-mm-3-search-base
+ pattern 'helm-mm-prefix-search 're-search-forward))
+
+\f
+;;; Generic multi-match/search functions
+;;
+;;
+(cl-defun helm-mm-match (str &optional (pattern helm-pattern))
+ (let ((fun (cl-ecase helm-mm-matching-method
+ (multi1 #'helm-mm-1-match)
+ (multi2 #'helm-mm-2-match)
+ (multi3 #'helm-mm-3-match)
+ (multi3p #'helm-mm-3p-match))))
+ (funcall fun str pattern)))
+
+(defun helm-mm-search (pattern &rest _ignore)
+ (let ((fun (cl-ecase helm-mm-matching-method
+ (multi1 #'helm-mm-1-search)
+ (multi2 #'helm-mm-2-search)
+ (multi3 #'helm-mm-3-search)
+ (multi3p #'helm-mm-3p-search))))
+ (funcall fun pattern)))
+
+
+(provide 'helm-multi-match)
+
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-multi-match.el ends here
--- /dev/null
+;;; helm-source.el --- Helm source creation. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2015 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; Author: Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+;; URL: http://github.com/emacs-helm/helm
+
+;; 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/>.
+
+;;; Commentary:
+
+;; Interface to create helm sources easily.
+;; Actually the eieo objects are transformed in alist for compatibility.
+;; In the future this package should allow creating source as eieo objects
+;; without conversion to alist, teaching helm to read such a structure.
+;; The compatibility with alists would be kept.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'eieio)
+(require 'helm-lib)
+
+(defvar helm-fuzzy-sort-fn)
+(defvar helm-fuzzy-match-fn)
+(defvar helm-fuzzy-search-fn)
+
+(declare-function helm-init-candidates-in-buffer "helm.el")
+(declare-function helm-interpret-value "helm.el")
+(declare-function helm-fuzzy-highlight-matches "helm.el")
+
+\f
+(defgeneric helm--setup-source (source)
+ "Prepare slots and handle slot errors before creating a helm source.")
+
+(defgeneric helm-setup-user-source (source)
+ "Allow users modifying slots in SOURCE just before creation.")
+
+\f
+;;; Classes for sources
+;;
+;;
+(defclass helm-source ()
+ ((name
+ :initarg :name
+ :initform nil
+ :custom string
+ :documentation
+ " The name of the source.
+ A string which is also the heading which appears
+ above the list of matches from the source. Must be unique.")
+
+ (header-name
+ :initarg :header-name
+ :initform nil
+ :custom function
+ :documentation
+ " A function returning the display string of the header.
+ Its argument is the name of the source. This attribute is useful to
+ add an additional information with the source name.
+ It doesn't modify the name of the source.")
+
+ (init
+ :initarg :init
+ :initform nil
+ :custom function
+ :documentation
+ " Function called with no parameters when helm is started.
+ It is useful for collecting current state information which can be
+ used to create the list of candidates later.
+ Initialization of `candidates-in-buffer' is done here
+ with `helm-init-candidates-in-buffer'.")
+
+ (candidates
+ :initarg :candidates
+ :initform nil
+ :custom (choice function list)
+ :documentation
+ " Specifies how to retrieve candidates from the source.
+ It can either be a variable name, a function called with no parameters
+ or the actual list of candidates.
+
+ The list must be a list whose members are strings, symbols
+ or (DISPLAY . REAL) pairs.
+
+ In case of (DISPLAY . REAL) pairs, the DISPLAY string is shown
+ in the Helm buffer, but the REAL one is used as action
+ argument when the candidate is selected. This allows a more
+ readable presentation for candidates which would otherwise be,
+ for example, too long or have a common part shared with other
+ candidates which can be safely replaced with an abbreviated
+ string for display purposes.
+
+ Note that if the (DISPLAY . REAL) form is used then pattern
+ matching is done on the displayed string, not on the real
+ value.")
+
+ (update
+ :initarg :update
+ :initform nil
+ :custom function
+ :documentation
+ " Function called with no parameters at before \"init\" function
+ when `helm-force-update' is called.")
+
+ (cleanup
+ :initarg :cleanup
+ :initform nil
+ :custom function
+ :documentation
+ " Function called with no parameters when *helm* buffer is
+ closed. It is useful for killing unneeded candidates buffer.
+
+ Note that the function is executed BEFORE performing action.")
+
+ (keymap
+ :initarg :keymap
+ :initform helm-map
+ :custom sexp
+ :documentation
+ " Specific keymap for this source.
+ default value is `helm-map'.")
+
+ (action
+ :initarg :action
+ :initform 'identity
+ :custom (alist :key-type string
+ :value-type function)
+ :documentation
+ " An alist of (DISPLAY . FUNCTION) pairs, a variable name or a function.
+ FUNCTION is called with one parameter: the selected candidate.
+
+ An action other than the default can be chosen from this list
+ of actions for the currently selected candidate (by default
+ with TAB). The DISPLAY string is shown in the completions
+ buffer and the FUNCTION is invoked when an action is
+ selected. The first action of the list is the default.
+
+ You should use `helm-make-actions' to build this alist easily.")
+
+ (persistent-action
+ :initarg :persistent-action
+ :initform nil
+ :custom function
+ :documentation
+ " Can be a either a Function called with one parameter (the
+ selected candidate) or a cons cell where first element is this
+ same function and second element a symbol (e.g never-split)
+ that inform `helm-execute-persistent-action' to not split his
+ window to execute this persistent action.
+ Example:
+
+ (defun foo-persistent-action (candidate)
+ (do-something candidate))
+
+ :persistent-action '(foo-persistent-action . never-split) ; Don't split
+ or
+ :persistent-action 'foo-persistent-action ; Split
+
+ When specifying :persistent-action by slot directly, foo-persistent-action
+ will be executed without quitting helm when hitting `C-j'.
+
+ Note that other persistent actions can be defined using other
+ bindings than `C-j' by simply defining an interactive function bound
+ to a key in the keymap source.
+ The function should create a new attribute in source before calling
+ `helm-execute-persistent-action' on this attribute.
+ Example:
+
+ (defun helm-ff-persistent-delete ()
+ \"Delete current candidate without quitting.\"
+ (interactive)
+ (with-helm-alive-p
+ (helm-attrset 'quick-delete '(helm-ff-quick-delete . never-split))
+ (helm-execute-persistent-action 'quick-delete)))
+
+ This function is then bound in `helm-find-files-map'.")
+
+ (persistent-action-if
+ :initarg :persistent-action-if
+ :initform nil
+ :custom function
+ :documentation
+ " Similar from persistent action but it is a function that should
+ return an object suitable for persistent action when called , i.e. a
+ function or a cons cell.
+ Example:
+
+ (defun foo-persistent-action (candidate)
+ (cond (something
+ ;; Don't split helm-window.
+ (cons (lambda (_ignore)
+ (do-something candidate))
+ 'no-split))
+ ;; Split helm-window.
+ (something-else
+ (lambda (_ignore)
+ (do-something-else candidate)))))
+
+ :persistent-action-if 'foo-persistent-action
+
+ Here when hitting `C-j' one of the lambda's will be executed
+ depending on something or something-else condition, splitting or not
+ splitting as needed.
+ See `helm-find-files-persistent-action-if' definition as another example.")
+
+ (persistent-help
+ :initarg :persistent-help
+ :initform nil
+ :custom string
+ :documentation
+ " A string to explain persistent-action of this source. It also
+ accepts a function or a variable name.
+ It will be displayed in `header-line' or in `minibuffer' depending
+ of value of `helm-echo-input-in-header-line' and `helm-display-header-line'.")
+
+ (help-message
+ :initarg :help-message
+ :initform nil
+ :custom (choice string function)
+ :documentation
+ " Help message for this source.
+ If not present, `helm-help-message' value will be used.")
+
+ (multiline
+ :initarg :multiline
+ :initform nil
+ :custom (choice boolean integer)
+ :documentation
+ " Allow multiline candidates.
+ When non-nil candidates will be separated by `helm-candidate-separator'.
+ You can customize the color of this separator with `helm-separator' face.
+ Value of multiline can be an integer which specify the maximum size of the
+ multiline string to display, if multiline string is longer than this value
+ it will be truncated.")
+
+ (requires-pattern
+ :initarg :requires-pattern
+ :initform nil
+ :custom integer
+ :documentation
+ " If present matches from the source are shown only if the
+ pattern is not empty. Optionally, it can have an integer
+ parameter specifying the required length of input which is
+ useful in case of sources with lots of candidates.")
+
+ (candidate-transformer
+ :initarg :candidate-transformer
+ :initform nil
+ :custom (choice function list)
+ :documentation
+ " It's a function or a list of functions called with one argument
+ when the completion list from the source is built. The argument
+ is the list of candidates retrieved from the source. The
+ function should return a transformed list of candidates which
+ will be used for the actual completion. If it is a list of
+ functions, it calls each function sequentially.
+
+ This can be used to transform or remove items from the list of
+ candidates.
+
+ Note that `candidates' is run already, so the given transformer
+ function should also be able to handle candidates with (DISPLAY
+ . REAL) format.")
+
+ (filtered-candidate-transformer
+ :initarg :filtered-candidate-transformer
+ :initform nil
+ :custom (choice function list)
+ :documentation
+ " It has the same format as `candidate-transformer', except the
+ function is called with two parameters: the candidate list and
+ the source.
+
+ This transformer is run on the candidate list which is already
+ filtered by the current pattern. While `candidate-transformer'
+ is run only once, it is run every time the input pattern is
+ changed.
+
+ It can be used to transform the candidate list dynamically, for
+ example, based on the current pattern.
+
+ In some cases it may also be more efficent to perform candidate
+ transformation here, instead of with `candidate-transformer'
+ even if this transformation is done every time the pattern is
+ changed. For example, if a candidate set is very large then
+ `candidate-transformer' transforms every candidate while only
+ some of them will actually be displayed due to the limit
+ imposed by `helm-candidate-number-limit'.
+
+ Note that `candidates' and `candidate-transformer' is run
+ already, so the given transformer function should also be able
+ to handle candidates with (DISPLAY . REAL) format.")
+
+ (filter-one-by-one
+ :initarg :filter-one-by-one
+ :initform nil
+ :custom (choice function list)
+ :documentation
+ " A transformer function that treat candidates one by one.
+ It is called with one arg the candidate.
+ It is faster than `filtered-candidate-transformer' or
+ `candidate-transformer', but should be used only in sources
+ that recompute constantly their candidates, e.g `helm-source-find-files'.
+ Filtering happen early and candidates are treated
+ one by one instead of re-looping on the whole list.
+ If used with `filtered-candidate-transformer' or `candidate-transformer'
+ these functions should treat the candidates transformed by the
+ `filter-one-by-one' function in consequence.")
+
+ (display-to-real
+ :initarg :display-to-real
+ :initform nil
+ :custom function
+ :documentation
+ " Transform the selected candidate when passing it to action.
+
+ Function called with one parameter, the selected candidate.
+
+ Avoid recomputing all candidates with candidate-transformer
+ or filtered-candidate-transformer to give a new value to REAL,
+ instead the selected candidate is transformed only when passing it
+ to action.
+
+ Note that this is NOT a transformer,
+ so the display will not be modified by this function.")
+
+ (real-to-display
+ :initarg :real-to-display
+ :initform nil
+ :custom function
+ :documentation
+ " Recompute all candidates computed previously with other transformers.
+
+ Function called with one parameter, the selected candidate.
+
+ The real value of candidates will be shown in display.
+ Note: This have nothing to do with display-to-real.
+ It is unuseful as the same can be performed by using more than
+ one function in transformers, it is kept only for backward compatibility.")
+
+ (marked-with-props
+ :initarg :marked-with-props
+ :initform nil
+ :custom (choice boolean symbol)
+ :documentation
+ " Get candidates with their properties in `helm-marked-candidates'.
+ Allow using the FORCE-DISPLAY-PART of `helm-get-selection' in marked
+ candidates, use t or 'withprop to pass it to `helm-get-selection'.")
+
+ (action-transformer
+ :initarg :action-transformer
+ :initform nil
+ :custom (choice function list)
+ :documentation
+ " It's a function or a list of functions called with two
+ arguments when the action list from the source is
+ assembled. The first argument is the list of actions, the
+ second is the current selection. If it is a list of functions,
+ it calls each function sequentially.
+
+ The function should return a transformed action list.
+
+ This can be used to customize the list of actions based on the
+ currently selected candidate.")
+
+ (pattern-transformer
+ :initarg :pattern-transformer
+ :initform nil
+ :custom (choice function list)
+ :documentation
+ " It's a function or a list of functions called with one argument
+ before computing matches. Its argument is `helm-pattern'.
+ Functions should return transformed `helm-pattern'.
+
+ It is useful to change interpretation of `helm-pattern'.")
+
+ (candidate-number-limit
+ :initarg :candidate-number-limit
+ :initform nil
+ :custom integer
+ :documentation
+ " Override `helm-candidate-number-limit' only for this source.")
+
+ (volatile
+ :initarg :volatile
+ :initform nil
+ :custom boolean
+ :documentation
+ " Indicates the source assembles the candidate list dynamically,
+ so it shouldn't be cached within a single Helm
+ invocation. It is only applicable to synchronous sources,
+ because asynchronous sources are not cached.")
+
+ (match
+ :initarg :match
+ :initform nil
+ :custom (choice function list)
+ :documentation
+ " List of functions called with one parameter: a candidate. The
+ function should return non-nil if the candidate matches the
+ current pattern (see variable `helm-pattern').
+
+ When using `candidates-in-buffer' its default value is `identity' and
+ don't have to be changed, use the `search' slot instead.
+
+ This attribute allows the source to override the default
+ pattern matching based on `string-match'. It can be used, for
+ example, to implement a source for file names and do the
+ pattern matching on the basename of files, since it's more
+ likely one is typing part of the basename when searching for a
+ file, instead of some string anywhere else in its path.
+
+ If the list contains more than one function then the list of
+ matching candidates from the source is constructed by appending
+ the results after invoking the first function on all the
+ potential candidates, then the next function, and so on. The
+ matching candidates supplied by the first function appear first
+ in the list of results and then results from the other
+ functions, respectively.
+
+ This attribute has no effect for asynchronous sources (see
+ attribute `candidates'), since they perform pattern matching
+ themselves.
+
+ Note that FUZZY-MATCH slot will overhide value of this slot.")
+
+ (fuzzy-match
+ :initarg :fuzzy-match
+ :initform nil
+ :custom boolean
+ :documentation
+ " Enable fuzzy matching in this source.
+ This will overwrite settings in MATCH slot, and for
+ sources built with child class `helm-source-in-buffer' the SEARCH slot.
+ This is an easy way of enabling fuzzy matching, but you can use the MATCH
+ or SEARCH slots yourself if you want something more elaborated, mixing
+ different type of match (See `helm-source-buffers' class for example).
+
+ This attribute is not supported for asynchronous sources
+ since they perform pattern matching themselves.")
+
+ (redisplay
+ :initarg :redisplay
+ :initform 'identity
+ :custom (choice list function)
+ :documentation
+ " A function or a list of functions to apply to current list
+ of candidates when redisplaying buffer with `helm-redisplay-buffer'.
+ This is only interesting for modifying and redisplaying the whole list
+ of candidates in async sources.
+ It uses `identity' by default for when async sources are mixed with
+ normal sources, in this case these normal sources are not modified and
+ redisplayed as they are.")
+
+ (nomark
+ :initarg :nomark
+ :initform nil
+ :custom boolean
+ :documentation
+ " Don't allow marking candidates when this attribute is present.")
+
+ (nohighlight
+ :initarg :nohighlight
+ :initform nil
+ :custom boolean
+ :documentation
+ " Disable highlighting matches in this source.
+ This will disable generic highlighting of matches,
+ but some specialized highlighting can be done from elsewhere,
+ i.e from `filtered-candidate-transformer' or `filter-one-by-one' slots.
+ So use this to either disable completely highlighting in your source,
+ or to disable highlighting and use a specialized highlighting matches
+ function for this source.
+ Remember that this function should run AFTER all filter functions if those
+ filter functions are modifying face properties, though it is possible to
+ avoid this by using new `add-face-text-property' in your filter functions.")
+
+ (allow-dups
+ :initarg :allow-dups
+ :initform nil
+ :custom boolean
+ :documentation
+ " Allow helm collecting duplicates candidates.")
+
+ (history
+ :initarg :history
+ :initform nil
+ :custom symbol
+ :documentation
+ " Allow passing history variable to helm from source.
+ It should be a quoted symbol.
+ Passing the history variable here have no effect
+ so add it also in the `helm' call with the :history keyword.
+ The main point of adding the variable here
+ is to make it available when resuming.")
+
+ (coerce
+ :initarg :coerce
+ :initform nil
+ :custom function
+ :documentation
+ " It's a function called with one argument: the selected candidate.
+ This function is intended for type convertion. In normal case,
+ the selected candidate (string) is passed to action
+ function. If coerce function is specified, it is called just
+ before action function.
+
+ Example: converting string to symbol
+ (coerce . intern)")
+
+ (mode-line
+ :initarg :mode-line
+ :initform nil
+ :custom (choice string sexp)
+ :documentation
+ " Source local `helm-mode-line-string' (included in
+ `mode-line-format'). It accepts also variable/function name.")
+
+ (header-line
+ :initarg :header-line
+ :initform nil
+ :custom (choice string function)
+ :documentation
+ " Source local `header-line-format'.
+ It will be displayed in `header-line' or in `minibuffer' depending
+ of value of `helm-echo-input-in-header-line' and `helm-display-header-line'.
+ It accepts also variable/function name.")
+
+ (resume
+ :initarg :resume
+ :initform nil
+ :custom function
+ :documentation
+ " Function called with no parameters at end of initialization
+ when `helm-resume' is started.
+ If this function try to do something against `helm-buffer', \(e.g updating,
+ searching etc...\) probably you should run it in a timer to ensure
+ `helm-buffer' is ready.")
+
+ (follow
+ :initarg :follow
+ :initform nil
+ :custom integer
+ :documentation
+ " Enable `helm-follow-mode' for this source only.
+With a value of 1 enable, a value of -1 or nil disable the mode.
+ See `helm-follow-mode' for more infos.")
+
+ (follow-delay
+ :initarg :follow-delay
+ :initform nil
+ :custom integer
+ :documentation
+ " `helm-follow-mode' will execute persistent-action after this delay.
+ Otherwise value of `helm-follow-input-idle-delay' is used if non--nil,
+ If none of these are found fallback to `helm-input-idle-delay'.")
+
+ (multimatch
+ :initarg :multimatch
+ :initform t
+ :custom boolean
+ :documentation
+ " Use the multi-match algorithm when non-nil.
+ I.e Allow specifying multiple patterns separated by spaces.
+ When a pattern is prefixed by \"!\" the negation of this pattern is used,
+ i.e match anything but this pattern.
+ It is the standard way of matching in helm and is enabled by default.
+ It can be used with fuzzy-matching enabled, but as soon helm detect a space,
+ each pattern will match by regexp and will not be fuzzy.")
+
+ (match-part
+ :initarg :match-part
+ :initform nil
+ :custom function
+ :documentation
+ " Allow matching only one part of candidate.
+ If source contain match-part attribute, match is computed only
+ on part of candidate returned by the call of function provided
+ by this attribute. The function should have one arg, candidate,
+ and return only a specific part of candidate.
+ On async sources, as matching is done by the backend, this have
+ no effect apart for highlighting matches.")
+
+ (before-init-hook
+ :initarg :before-init-hook
+ :initform nil
+ :custom symbol
+ :documentation
+ " A local hook that run at beginning of initilization of this source.
+ i.e Before the creation of `helm-buffer'.
+
+ Should be a variable (defined with defvar).
+ Can be also an anonymous function or a list of functions
+ directly added to slot, this is not recommended though.")
+
+ (after-init-hook
+ :initarg :after-init-hook
+ :initform nil
+ :custom symbol
+ :documentation
+ " A local hook that run at end of initilization of this source.
+ i.e After the creation of `helm-buffer'.
+
+ Should be a variable.
+ Can be also an anonymous function or a list of functions
+ directly added to slot, this is not recommended though.")
+
+ (delayed
+ :initarg :delayed
+ :initform nil
+ :custom (choice null integer)
+ :documentation
+ " This slot have no more effect and is just kept for backward compatibility.
+ Please don't use it.")
+
+ (group
+ :initarg :group
+ :initform helm
+ :custom symbol
+ :documentation
+ " The current source group, default to `helm' when not specified."))
+
+ "Main interface to define helm sources."
+ :abstract t)
+
+(defclass helm-source-sync (helm-source)
+ ((candidates
+ :initform '("ERROR: You must specify the `candidates' slot, either with a list or a function"))
+
+ (migemo
+ :initarg :migemo
+ :initform nil
+ :custom boolean
+ :documentation
+ " Enable migemo.
+ When multimatch is disabled, you can give the symbol 'nomultimatch as value
+ to force not using generic migemo matching function.
+ In this case you have to provide your own migemo matching funtion
+ that kick in when `helm-migemo-mode' is enabled.
+ Otherwise it will be available for this source once `helm-migemo-mode'
+ is enabled when non-nil.")
+
+ (match-strict
+ :initarg :match-strict
+ :initform nil
+ :custom function
+ :documentation
+ " When specifying a match function within a source and
+ helm-multi-match is enabled, the result of all matching
+ functions will be concatened, which in some cases is not what
+ is wanted. When using `match-strict' only this or these
+ functions will be used. You can specify those functions as a
+ list of functions or a single symbol function.
+
+ NOTE: This have the same effect as using :MULTIMATCH nil."))
+
+ "Use this class to make helm sources using a list of candidates.
+This list should be given as a normal list, a variable handling a list
+or a function returning a list.
+Matching is done basically with `string-match' against each candidate.")
+
+(defclass helm-source-async (helm-source)
+ ((candidates-process
+ :initarg :candidates-process
+ :initform nil
+ :custom function
+ :documentation
+ " This attribute is used to define a process as candidate.
+ The value must be a process.
+
+ NOTE:
+ When building the source at runtime you can give directly a process
+ as value, otherwise wrap the process call into a function.
+ The process buffer should be nil, otherwise, if you use
+ `helm-buffer' give to the process a sentinel.")
+
+ (multimatch :initform nil))
+
+ "Use this class to define a helm source calling an external process.
+The :candidates slot is not allowed even if described because this class
+inherit from `helm-source'.")
+
+(defclass helm-source-in-buffer (helm-source)
+ ((init
+ :initform 'helm-default-init-source-in-buffer-function)
+
+ (data
+ :initarg :data
+ :initform nil
+ :custom (choice list string)
+ :documentation
+ " A string, a list or a buffer that will be used to feed the `helm-candidates-buffer'.
+ This data will be passed in a function added to the init slot and
+ the buffer will be build with `helm-init-candidates-in-buffer' or directly
+ with `helm-candidates-buffer' if data is a buffer.
+ This is an easy and fast method to build a `candidates-in-buffer' source.")
+
+ (migemo
+ :initarg :migemo
+ :initform nil
+ :custom boolean
+ :documentation
+ " Enable migemo.
+ When multimatch is disabled, you can give the symbol 'nomultimatch as value
+ to force not using generic migemo matching function.
+ In this case you have to provide your own migemo matching funtion
+ that kick in when `helm-migemo-mode' is enabled.
+ Otherwise it will be available for this source once `helm-migemo-mode'
+ is enabled when non-nil.")
+
+ (candidates
+ :initform 'helm-candidates-in-buffer)
+
+ (volatile
+ :initform t)
+
+ (match
+ :initform '(identity))
+
+ (get-line
+ :initarg :get-line
+ :initform 'buffer-substring-no-properties
+ :custom function
+ :documentation
+ " A function like `buffer-substring-no-properties' or `buffer-substring'.
+ This function converts region from point at line-beginning and point
+ at line-end in the `helm-candidate-buffer' to a string which will be displayed
+ in the `helm-buffer', it takes two args BEG and END.
+ By default, `helm-candidates-in-buffer' uses
+ `buffer-substring-no-properties' which does no conversion and doesn't carry
+ text properties.")
+
+ (search
+ :initarg :search
+ :initform '(helm-candidates-in-buffer-search-default-fn)
+ :custom (choice function list)
+ :documentation
+ " List of functions like `re-search-forward' or `search-forward'.
+ Buffer search function used by `helm-candidates-in-buffer'.
+ By default, `helm-candidates-in-buffer' uses `re-search-forward'.
+ The function should take one arg PATTERN.
+ If your search function needs to handle negation like multimatch,
+ this function should returns in such case a cons cell of two integers defining
+ the beg and end positions to match in the line previously matched by
+ `re-search-forward' or similar, and move point to next line
+ (See how the `helm-mm-3-search-base' and `helm-fuzzy-search' functions are working).
+
+ NOTE: FUZZY-MATCH slot will overhide value of this slot.")
+
+ (search-strict
+ :initarg :search-strict
+ :initform nil
+ :custom function
+ :documentation
+ " When specifying a search function within a source and
+ helm-multi-match is enabled, the result of all searching
+ functions will be concatened, which in some cases is not what
+ is wanted. When using `search-strict' only this or these
+ functions will be used. You can specify those functions as a
+ list of functions or a single symbol function.
+
+ NOTE: This have the same effect as using a nil value for
+ :MULTIMATCH slot."))
+
+ "Use this source to make helm sources storing candidates inside a buffer.
+
+The buffer storing candidates is generated by `helm-candidate-buffer' function
+and all search are done in this buffer, results are transfered to the `helm-buffer'
+when done.
+Contrarily to `helm-source-sync' candidates are matched using a function
+like `re-search-forward' (see below documentation of `:search' slot) which makes
+the search much faster than matching candidates one by one.
+If you want to add search functions to your sources, don't use `:match' which
+will raise an error, but `:search'.
+See `helm-candidates-in-buffer' for more infos.")
+
+(defclass helm-source-dummy (helm-source)
+ ((candidates
+ :initform '("dummy"))
+
+ (filtered-candidate-transformer
+ :initform (lambda (_candidates _source) (list helm-pattern)))
+
+ (multimatch
+ :initform nil)
+
+ (accept-empty
+ :initarg :accept-empty
+ :initform t
+ :custom boolean
+ :documentation
+ " Allow exiting with an empty string.
+ You should keep the default value.")
+
+ (match
+ :initform 'identity)
+
+ (volatile
+ :initform t)))
+
+(defclass helm-source-in-file (helm-source-in-buffer)
+ ((init :initform (lambda ()
+ (let ((file (helm-attr 'candidates-file))
+ (count 1))
+ (with-current-buffer (helm-candidate-buffer 'global)
+ (insert-file-contents file)
+ (goto-char (point-min))
+ (while (not (eobp))
+ (add-text-properties
+ (point-at-bol) (point-at-eol)
+ `(helm-linum ,count))
+ (cl-incf count)
+ (forward-line 1))))))
+ (get-line :initform #'buffer-substring)
+ (candidates-file
+ :initarg :candidates-file
+ :initform nil
+ :custom string
+ :documentation
+ " A filename.
+ Each line number of FILE is accessible with helm-linum property
+ from candidate display part."))
+
+ "The contents of the FILE will be used as candidates in buffer.")
+
+\f
+;;; Error functions
+;;
+;;
+(defun helm-default-init-source-in-buffer-function ()
+ (helm-init-candidates-in-buffer 'global
+ '("ERROR: No buffer handling your data, use either the `init' slot or the `data' slot.")))
+
+\f
+;;; Internal Builder functions.
+;;
+;;
+(defun helm--create-source (object)
+ "[INTERNAL] Build a helm source from OBJECT.
+Where OBJECT is an instance of an eieio class."
+ (cl-loop for s in (object-slots object)
+ for slot-val = (slot-value object s)
+ when slot-val
+ collect (cons s (unless (eq t slot-val) slot-val))))
+
+(defun helm-make-source (name class &rest args)
+ "Build a `helm' source named NAME with ARGS for CLASS.
+Argument NAME is a string which define the source name, so no need to use
+the keyword :name in your source, NAME will be used instead.
+Argument CLASS is an eieio class object.
+Arguments ARGS are keyword value pairs as defined in CLASS."
+ (declare (indent 2))
+ (let ((source (apply #'make-instance class name args)))
+ (setf (slot-value source 'name) name)
+ (helm--setup-source source)
+ (helm-setup-user-source source)
+ (helm--create-source source)))
+
+(defun helm-make-type (class &rest args)
+ (let ((source (apply #'make-instance class args)))
+ (setf (slot-value source 'name) nil)
+ (helm--setup-source source)
+ (helm--create-source source)))
+
+(defvar helm-mm-default-search-functions)
+(defvar helm-mm-default-match-functions)
+
+(defun helm-source-mm-get-search-or-match-fns (source method)
+ (let ((defmatch (helm-aif (slot-value source 'match)
+ (helm-mklist it)))
+ (defmatch-strict (helm-aif (and (eq method 'match)
+ (slot-value source 'match-strict))
+ (helm-mklist it)))
+ (defsearch (helm-aif (and (eq method 'search)
+ (slot-value source 'search))
+ (helm-mklist it)))
+ (defsearch-strict (helm-aif (and (eq method 'search-strict)
+ (slot-value source 'search-strict))
+ (helm-mklist it)))
+ (migemo (slot-value source 'migemo)))
+ (cl-case method
+ (match (cond (defmatch-strict)
+ (migemo
+ (append helm-mm-default-match-functions
+ defmatch '(helm-mm-3-migemo-match)))
+ (defmatch
+ (append helm-mm-default-match-functions defmatch))
+ (t helm-mm-default-match-functions)))
+ (search (cond (defsearch-strict)
+ (migemo
+ (append helm-mm-default-search-functions
+ defsearch '(helm-mm-3-migemo-search)))
+ (defsearch
+ (append helm-mm-default-search-functions defsearch))
+ (t helm-mm-default-search-functions))))))
+
+\f
+;;; Modifiers
+;;
+(cl-defun helm-source-add-action-to-source-if (name fn source predicate
+ &optional (index 4))
+ "Same as `helm-add-action-to-source-if' but for SOURCE defined as eieio object.
+You can use this inside a `helm--setup-source' method for a SOURCE defined as
+an eieio class."
+ (let* ((actions (slot-value source 'action))
+ (action-transformers (slot-value source 'action-transformer))
+ (new-action (list (cons name fn)))
+ (transformer (lambda (actions candidate)
+ (cond ((funcall predicate candidate)
+ (helm-append-at-nth
+ actions new-action index))
+ (t actions)))))
+ (cond ((functionp actions)
+ (setf (slot-value source 'action) (list (cons "Default action" actions))))
+ ((listp actions)
+ (setf (slot-value source 'action) (helm-interpret-value actions source))))
+ (when (or (symbolp action-transformers) (functionp action-transformers))
+ (setq action-transformers (list action-transformers)))
+ (setf (slot-value source 'action-transformer)
+ (delq nil (append (list transformer) action-transformers)))))
+
+\f
+;;; Methods to build sources.
+;;
+;;
+(defun helm-source--persistent-help-string (string source)
+ (substitute-command-keys
+ (concat "\\<helm-map>\\[helm-execute-persistent-action]: "
+ (or (format "%s (keeping session)" string)
+ (slot-value source 'header-line)))))
+
+(defun helm-source--header-line (source)
+ (substitute-command-keys
+ (concat "\\<helm-map>\\[helm-execute-persistent-action]: "
+ (helm-aif (or (slot-value source 'persistent-action)
+ (slot-value source 'action))
+ (cond ((and (symbolp it)
+ (functionp it)
+ (eq it 'identity))
+ "Do Nothing")
+ ((and (symbolp it)
+ (boundp it)
+ (listp (symbol-value it))
+ (stringp (caar (symbol-value it))))
+ (caar (symbol-value it)))
+ ((or (symbolp it) (functionp it))
+ (helm-symbol-name it))
+ ((listp it)
+ (let ((action (car it)))
+ ;; It comes from :action ("foo" . function).
+ (if (stringp (car action))
+ (car action)
+ ;; It comes from :persistent-action
+ ;; (function . 'nosplit) Fix Issue #788.
+ (if (or (symbolp action)
+ (functionp action))
+ (helm-symbol-name action)))))
+ (t ""))
+ "")
+ " (keeping session)")))
+
+(defmethod helm--setup-source :primary ((_source helm-source)))
+
+(defmethod helm--setup-source :before ((source helm-source))
+ (when (slot-value source 'delayed)
+ (warn "Deprecated usage of helm `delayed' slot in `%s'"
+ (slot-value source 'name)))
+ (helm-aif (slot-value source 'keymap)
+ (and (symbolp it) (setf (slot-value source 'keymap) (symbol-value it))))
+ (helm-aif (slot-value source 'persistent-help)
+ (setf (slot-value source 'header-line)
+ (helm-source--persistent-help-string it source))
+ (setf (slot-value source 'header-line) (helm-source--header-line source)))
+ (when (and (slot-value source 'fuzzy-match) helm-fuzzy-sort-fn)
+ (setf (slot-value source 'filtered-candidate-transformer)
+ (helm-aif (slot-value source 'filtered-candidate-transformer)
+ (append (helm-mklist it)
+ (list helm-fuzzy-sort-fn))
+ (list helm-fuzzy-sort-fn))))
+ (unless (slot-value source 'nohighlight)
+ (setf (slot-value source 'filtered-candidate-transformer)
+ (helm-aif (slot-value source 'filtered-candidate-transformer)
+ (append (helm-mklist it)
+ (list #'helm-fuzzy-highlight-matches))
+ (list #'helm-fuzzy-highlight-matches))))
+ (when (numberp (helm-interpret-value (slot-value source 'multiline)))
+ (setf (slot-value source 'filtered-candidate-transformer)
+ (helm-aif (slot-value source 'filtered-candidate-transformer)
+ (append (helm-mklist it)
+ (list #'helm-multiline-transformer))
+ (list #'helm-multiline-transformer)))))
+
+(defmethod helm-setup-user-source ((_source helm-source)))
+
+(defmethod helm--setup-source ((source helm-source-sync))
+ (when (slot-value source 'fuzzy-match)
+ (helm-aif (slot-value source 'match)
+ (setf (slot-value source 'match)
+ (append (helm-mklist it)
+ (list helm-fuzzy-match-fn)))
+ (setf (slot-value source 'match) helm-fuzzy-match-fn)))
+ (when (slot-value source 'multimatch)
+ (setf (slot-value source 'match)
+ (helm-source-mm-get-search-or-match-fns source 'match)))
+ (helm-aif (and (null (slot-value source 'multimatch))
+ (slot-value source 'migemo))
+ (unless (eq it 'nomultimatch) ; Use own migemo fn.
+ (setf (slot-value source 'match)
+ (append (helm-mklist (slot-value source 'match))
+ '(helm-mm-3-migemo-match))))))
+
+(defmethod helm--setup-source ((source helm-source-in-buffer))
+ (let ((cur-init (slot-value source 'init)))
+ (helm-aif (slot-value source 'data)
+ (setf (slot-value source 'init)
+ (delq
+ nil
+ (list
+ (and (null (eq 'helm-default-init-source-in-buffer-function
+ cur-init))
+ cur-init)
+ (lambda ()
+ (helm-init-candidates-in-buffer
+ 'global
+ (cond ((functionp it) (funcall it))
+ ((and (bufferp it) (buffer-live-p it))
+ (with-current-buffer it (buffer-string)))
+ (t it)))))))))
+ (when (slot-value source 'fuzzy-match)
+ (helm-aif (slot-value source 'search)
+ (setf (slot-value source 'search)
+ (append (helm-mklist it)
+ (list helm-fuzzy-search-fn)))
+ (setf (slot-value source 'search) (list helm-fuzzy-search-fn))))
+ (when (slot-value source 'multimatch)
+ (setf (slot-value source 'search)
+ (helm-source-mm-get-search-or-match-fns source 'search)))
+ (helm-aif (and (null (slot-value source 'multimatch))
+ (slot-value source 'migemo))
+ (unless (eq it 'nomultimatch)
+ (setf (slot-value source 'search)
+ (append (helm-mklist (slot-value source 'search))
+ '(helm-mm-3-migemo-search)))))
+ (let ((mtc (slot-value source 'match)))
+ (cl-assert (or (equal '(identity) mtc)
+ (eq 'identity mtc))
+ nil "Invalid slot value for `match'")
+ (cl-assert (eq (slot-value source 'volatile) t)
+ nil "Invalid slot value for `volatile'")))
+
+(defmethod helm--setup-source ((source helm-source-async))
+ (cl-assert (null (slot-value source 'candidates))
+ nil "Incorrect use of `candidates' use `candidates-process' instead")
+ (cl-assert (null (slot-value source 'multimatch))
+ nil "`multimatch' not allowed in async sources.")
+ (cl-assert (null (slot-value source 'fuzzy-match))
+ nil "`fuzzy-match' not supported in async sources."))
+
+(defmethod helm--setup-source ((source helm-source-dummy))
+ (let ((mtc (slot-value source 'match)))
+ (cl-assert (or (equal '(identity) mtc)
+ (eq 'identity mtc))
+ nil "Invalid slot value for `match'")
+ (cl-assert (eq (slot-value source 'volatile) t)
+ nil "Invalid slot value for `volatile'")
+ (cl-assert (equal (slot-value source 'candidates) '("dummy"))
+ nil "Invalid slot value for `candidates'")
+ (cl-assert (eq (slot-value source 'accept-empty) t)
+ nil "Invalid slot value for `accept-empty'")))
+
+\f
+;;; User functions
+;;
+;; Sources
+(defmacro helm-build-sync-source (name &rest args)
+ "Build a synchronous helm source with name NAME.
+Args ARGS are keywords provided by `helm-source-sync'."
+ (declare (indent 1))
+ `(helm-make-source ,name 'helm-source-sync ,@args))
+
+(defmacro helm-build-async-source (name &rest args)
+ "Build a asynchronous helm source with name NAME.
+Args ARGS are keywords provided by `helm-source-async'."
+ (declare (indent 1))
+ `(helm-make-source ,name 'helm-source-async ,@args))
+
+(defmacro helm-build-in-buffer-source (name &rest args)
+ "Build a helm source with name NAME using `candidates-in-buffer' method.
+Args ARGS are keywords provided by `helm-source-in-buffer'."
+ (declare (indent 1))
+ `(helm-make-source ,name 'helm-source-in-buffer ,@args))
+
+(defmacro helm-build-dummy-source (name &rest args)
+ "Build a helm source with name NAME using `dummy' method.
+Args ARGS are keywords provided by `helm-source-dummy'."
+ (declare (indent 1))
+ `(helm-make-source ,name 'helm-source-dummy ,@args))
+
+(defmacro helm-build-in-file-source (name file &rest args)
+ "Build a helm source with NAME name using `candidates-in-files' method.
+Arg FILE is a filename, the contents of this file will be
+used as candidates in buffer.
+Args ARGS are keywords provided by `helm-source-in-file'."
+ (declare (indent 1))
+ `(helm-make-source ,name 'helm-source-in-file
+ :candidates-file ,file ,@args))
+
+
+(provide 'helm-source)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-source ends here
--- /dev/null
+;;; helm.el --- Emacs incremental and narrowing framework -*- lexical-binding: t -*-
+
+;; Copyright (C) 2007 Tamas Patrovics
+;; 2008 ~ 2011 rubikitch <rubikitchNOSPAMruby-lang.org>
+;; 2011 ~ 2018 Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; This is a fork of anything.el wrote by Tamas Patrovics.
+
+;; Authors of anything.el: Tamas Patrovics
+;; rubikitch <rubikitchNOSPAMruby-lang.org>
+;; Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+
+;; Author: Thierry Volpiatto <thierry.volpiattoNOSPAMgmail.com>
+;; URL: http://github.com/emacs-helm/helm
+
+;; 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/>.
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'async)
+(require 'advice) ; Shutup byte compiler about ad-deactivate.
+(require 'helm-lib)
+(require 'helm-multi-match)
+(require 'helm-source)
+
+\f
+;;; Multi keys
+;;
+;;
+;;;###autoload
+(defun helm-define-multi-key (keymap key functions &optional delay)
+ "In KEYMAP, define key sequence KEY for function list FUNCTIONS.
+Each function runs sequentially for each KEY press.
+If DELAY is specified, switch back to initial function of FUNCTIONS list
+after DELAY seconds.
+The functions in FUNCTIONS list take no args.
+e.g
+ (defun foo ()
+ (interactive)
+ (message \"Run foo\"))
+ (defun bar ()
+ (interactive)
+ (message \"Run bar\"))
+ (defun baz ()
+ (interactive)
+ (message \"Run baz\"))
+
+\(helm-define-multi-key global-map (kbd \"<f5> q\") '(foo bar baz) 2)
+
+Each time \"<f5> q\" is pressed, the next function is executed. Waiting
+more than 2 seconds between key presses switches back to executing the first
+function on the next hit."
+ (define-key keymap key (helm-make-multi-command functions delay)))
+
+;;;###autoload
+(defmacro helm-multi-key-defun (name docstring funs &optional delay)
+ "Define NAME as a multi-key command running FUNS.
+After DELAY seconds, the FUNS list is reinitialized.
+See `helm-define-multi-key'."
+ (declare (indent 2))
+ (setq docstring (if docstring (concat docstring "\n\n")
+ "This is a helm-ish multi-key command."))
+ `(defalias (quote ,name) (helm-make-multi-command ,funs ,delay) ,docstring))
+
+(defun helm-make-multi-command (functions &optional delay)
+ "Return an anonymous multi-key command running FUNCTIONS.
+Run each function in the FUNCTIONS list in turn when called within DELAY seconds."
+ (declare (indent 1))
+ (let ((funs functions)
+ (iter (cl-gensym "helm-iter-key"))
+ (timeout delay))
+ (eval (list 'defvar iter nil))
+ (lambda ()
+ (interactive)
+ (helm-run-multi-key-command funs iter timeout))))
+
+(defun helm-run-multi-key-command (functions iterator delay)
+ (let ((fn (lambda ()
+ (cl-loop for count from 1 to (length functions)
+ collect count)))
+ next)
+ (unless (and (symbol-value iterator)
+ ;; Reset iterator when another key is pressed.
+ (eq this-command real-last-command))
+ (set iterator (helm-iter-list (funcall fn))))
+ (setq next (helm-iter-next (symbol-value iterator)))
+ (unless next
+ (set iterator (helm-iter-list (funcall fn)))
+ (setq next (helm-iter-next (symbol-value iterator))))
+ (and next (symbol-value iterator)
+ (call-interactively (nth (1- next) functions)))
+ (when delay (run-with-idle-timer
+ delay nil (lambda ()
+ (set iterator nil))))))
+
+(helm-multi-key-defun helm-toggle-resplit-and-swap-windows
+ "Multi key command to re-split and swap helm window.
+First call runs `helm-toggle-resplit-window',
+and second call within 0.5s runs `helm-swap-windows'."
+ '(helm-toggle-resplit-window helm-swap-windows) 1)
+(put 'helm-toggle-resplit-and-swap-windows 'helm-only t)
+
+;;;###autoload
+(defun helm-define-key-with-subkeys (map key subkey command
+ &optional other-subkeys prompt exit-fn)
+ "Defines in MAP a KEY and SUBKEY to COMMAND.
+
+This allows typing KEY to call COMMAND the first time and
+type only SUBKEY on subsequent calls.
+
+Arg MAP is the keymap to use, SUBKEY is the initial short key-binding to
+call COMMAND.
+
+Arg OTHER-SUBKEYS is an alist specifying other short key-bindings
+to use once started e.g:
+
+ \(helm-define-key-with-subkeys global-map
+ \(kbd \"C-x v n\") ?n 'git-gutter:next-hunk '((?p . git-gutter:previous-hunk))\)
+
+
+In this example, `C-x v n' will run `git-gutter:next-hunk'
+subsequent \"n\"'s run this command again
+and subsequent \"p\"'s run `git-gutter:previous-hunk'.
+
+If specified PROMPT can be displayed in minibuffer to
+describe SUBKEY and OTHER-SUBKEYS.
+Arg EXIT-FN specifies a function to run on exit.
+
+For any other keys pressed, run their assigned command as defined
+in MAP and then exit the loop running EXIT-FN, if specified.
+
+NOTE: SUBKEY and OTHER-SUBKEYS bindings support only char syntax and
+vectors, so don't use strings to define them."
+ (declare (indent 1))
+ (define-key map key
+ (lambda ()
+ (interactive)
+ (unwind-protect
+ (progn
+ (call-interactively command)
+ (while (let ((input (read-key prompt)) other kb com)
+ (setq last-command-event input)
+ (cond
+ ((eq input subkey)
+ (call-interactively command)
+ t)
+ ((setq other (assoc input other-subkeys))
+ (call-interactively (cdr other))
+ t)
+ (t
+ (setq kb (vector last-command-event))
+ (setq com (lookup-key map kb))
+ (if (commandp com)
+ (call-interactively com)
+ (setq unread-command-events
+ (nconc (mapcar 'identity kb)
+ unread-command-events)))
+ nil)))))
+ (and exit-fn (funcall exit-fn))))))
+\f
+;;; Keymap
+;;
+;;
+(defvar helm-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map minibuffer-local-map)
+ (define-key map (kbd "<down>") 'helm-next-line)
+ (define-key map (kbd "<up>") 'helm-previous-line)
+ (define-key map (kbd "C-n") 'helm-next-line)
+ (define-key map (kbd "C-p") 'helm-previous-line)
+ (define-key map (kbd "<C-down>") 'helm-follow-action-forward)
+ (define-key map (kbd "<C-up>") 'helm-follow-action-backward)
+ (define-key map (kbd "<prior>") 'helm-previous-page)
+ (define-key map (kbd "<next>") 'helm-next-page)
+ (define-key map (kbd "M-v") 'helm-previous-page)
+ (define-key map (kbd "C-v") 'helm-next-page)
+ (define-key map (kbd "M-<") 'helm-beginning-of-buffer)
+ (define-key map (kbd "M->") 'helm-end-of-buffer)
+ (define-key map (kbd "C-g") 'helm-keyboard-quit)
+ (define-key map (kbd "<right>") 'helm-next-source)
+ (define-key map (kbd "<left>") 'helm-previous-source)
+ (define-key map (kbd "<RET>") 'helm-maybe-exit-minibuffer)
+ (define-key map (kbd "C-i") 'helm-select-action)
+ (define-key map (kbd "C-z") 'helm-execute-persistent-action)
+ (define-key map (kbd "C-j") 'helm-execute-persistent-action)
+ (define-key map (kbd "C-o") 'helm-next-source)
+ (define-key map (kbd "M-o") 'helm-previous-source)
+ (define-key map (kbd "C-l") 'helm-recenter-top-bottom-other-window)
+ (define-key map (kbd "M-C-l") 'helm-reposition-window-other-window)
+ (define-key map (kbd "C-M-v") 'helm-scroll-other-window)
+ (define-key map (kbd "M-<next>") 'helm-scroll-other-window)
+ (define-key map (kbd "C-M-y") 'helm-scroll-other-window-down)
+ (define-key map (kbd "C-M-S-v") 'helm-scroll-other-window-down)
+ (define-key map (kbd "M-<prior>") 'helm-scroll-other-window-down)
+ (define-key map (kbd "<C-M-down>") 'helm-scroll-other-window)
+ (define-key map (kbd "<C-M-up>") 'helm-scroll-other-window-down)
+ (define-key map (kbd "C-@") 'helm-toggle-visible-mark)
+ (define-key map (kbd "C-SPC") 'helm-toggle-visible-mark)
+ (define-key map (kbd "M-SPC") 'helm-toggle-visible-mark)
+ (define-key map (kbd "M-[") nil)
+ (define-key map (kbd "M-(") 'helm-prev-visible-mark)
+ (define-key map (kbd "M-)") 'helm-next-visible-mark)
+ (define-key map (kbd "C-k") 'helm-delete-minibuffer-contents)
+ (define-key map (kbd "C-x C-f") 'helm-quit-and-find-file)
+ (define-key map (kbd "M-m") 'helm-toggle-all-marks)
+ (define-key map (kbd "M-a") 'helm-mark-all)
+ (define-key map (kbd "M-U") 'helm-unmark-all)
+ (define-key map (kbd "C-M-a") 'helm-show-all-in-this-source-only)
+ (define-key map (kbd "C-M-e") 'helm-display-all-sources)
+ (define-key map (kbd "C-s") 'undefined)
+ (define-key map (kbd "M-s") 'undefined)
+ (define-key map (kbd "C-}") 'helm-narrow-window)
+ (define-key map (kbd "C-{") 'helm-enlarge-window)
+ (define-key map (kbd "C-c -") 'helm-swap-windows)
+ (define-key map (kbd "C-c _") 'helm-toggle-full-frame)
+ (define-key map (kbd "C-c %") 'helm-exchange-minibuffer-and-header-line)
+ (define-key map (kbd "C-c C-y") 'helm-yank-selection)
+ (define-key map (kbd "C-c C-k") 'helm-kill-selection-and-quit)
+ (define-key map (kbd "C-c C-i") 'helm-copy-to-buffer)
+ (define-key map (kbd "C-c C-f") 'helm-follow-mode)
+ (define-key map (kbd "C-c C-u") 'helm-refresh)
+ (define-key map (kbd "C-c >") 'helm-toggle-truncate-line)
+ (define-key map (kbd "M-p") 'previous-history-element)
+ (define-key map (kbd "M-n") 'next-history-element)
+ (define-key map (kbd "C-!") 'helm-toggle-suspend-update)
+ (define-key map (kbd "C-x b") 'helm-resume-previous-session-after-quit)
+ (define-key map (kbd "C-x C-b") 'helm-resume-list-buffers-after-quit)
+ (helm-define-key-with-subkeys map (kbd "C-c n") ?n 'helm-run-cycle-resume)
+ ;; Disable `file-cache-minibuffer-complete'.
+ (define-key map (kbd "<C-tab>") 'undefined)
+ ;; Multi keys
+ (define-key map (kbd "C-t") 'helm-toggle-resplit-and-swap-windows)
+ ;; Debugging command
+ (define-key map (kbd "C-h C-d") 'undefined)
+ (define-key map (kbd "C-h C-d") 'helm-enable-or-switch-to-debug)
+ (define-key map (kbd "C-h c") 'helm-customize-group)
+ ;; Allow to eval keymap without errors.
+ (define-key map [f1] nil)
+ (define-key map (kbd "C-h C-h") 'undefined)
+ (define-key map (kbd "C-h h") 'undefined)
+ (helm-define-key-with-subkeys map
+ (kbd "C-w") ?\C-w 'helm-yank-text-at-point
+ '((?\C-_ . helm-undo-yank-text-at-point)))
+ ;; Use `describe-mode' key in `global-map'.
+ (cl-dolist (k (where-is-internal 'describe-mode global-map))
+ (define-key map k 'helm-help))
+ (define-key map (kbd "C-c ?") 'helm-help)
+ ;; Bind all actions from 1 to 12 to their corresponding nth index+1.
+ (cl-loop for n from 0 to 12 do
+ (define-key map (kbd (format "<f%s>" (1+ n)))
+ `(lambda ()
+ (interactive)
+ (helm-select-nth-action ,n))))
+ map)
+ "Keymap for helm.")
+
+(defun helm-customize-group ()
+ "Jump to customization group of current source.
+
+Default to `helm' when group is not defined in source."
+ (interactive)
+ (helm-run-after-exit 'customize-group (helm-attr 'group)))
+(put 'helm-customize-group 'helm-only t)
+
+(defun helm--action-at-nth-set-fn-1 (value &optional negative)
+ (cl-loop for n from 1 to 9
+ for key = (format value n)
+ for sym = (make-symbol (format "helm-execute-selection-action-at-nth-+%d" n))
+ for fn = `(lambda ()
+ (interactive)
+ (helm-execute-selection-action-at-nth ,(if negative (- n) n)))
+ do (progn
+ (defalias sym fn)
+ (define-key helm-map (kbd key) sym))))
+
+(defun helm--action-at-nth-set-fn- (var val)
+ (set var val)
+ (helm--action-at-nth-set-fn-1 val 'negative))
+
+(defun helm--action-at-nth-set-fn+ (var val)
+ (set var val)
+ (helm--action-at-nth-set-fn-1 val))
+
+(defcustom helm-action-at-nth-negative-prefix-key "C-x %d"
+ "The prefix key to execute default action on nth <-n> candidate.
+
+This is a format spec where %d will be replaced by the candidate
+number.
+
+NOTE: `setq' have no effect until you restart emacs, use customize for
+immediate effect."
+ :group 'helm
+ :type 'string
+ :set #'helm--action-at-nth-set-fn-)
+
+(defcustom helm-action-at-nth-positive-prefix-key "C-c %d"
+ "The prefix key to execute default action on nth <+n> candidate.
+
+This is a format spec where %d will be replaced by the candidate
+number.
+
+NOTE: `setq' have no effect until you restart emacs, use customize for
+immediate effect."
+ :group 'helm
+ :type 'string
+ :set #'helm--action-at-nth-set-fn+)
+
+\f
+(defgroup helm nil
+ "Open helm."
+ :prefix "helm-" :group 'convenience)
+
+(defcustom helm-completion-window-scroll-margin 5
+ " `scroll-margin' to use for helm completion window.
+Set to 0 to disable.
+NOTE: This has no effect when `helm-display-source-at-screen-top'
+id is non-`nil'."
+ :group 'helm
+ :type 'integer)
+
+(defcustom helm-display-source-at-screen-top t
+ "Display candidates at the top of screen.
+This happens with `helm-next-source' and `helm-previous-source'.
+NOTE: When non-`nil' (default), disable `helm-completion-window-scroll-margin'."
+ :group 'helm
+ :type 'boolean)
+
+(defcustom helm-candidate-number-limit 100
+ "Global limit for number of candidates displayed.
+When the pattern is empty, the number of candidates shown will be
+as set here instead of the entire list, which may be hundreds or
+thousands. Since narrowing and filtering rapidly reduces
+available candidates, having a small list will keep the interface
+responsive.
+
+Set this value to nil for no limit."
+ :group 'helm
+ :type '(choice (const :tag "Disabled" nil) integer))
+
+(defcustom helm-input-idle-delay 0.01
+ "Idle time before updating, specified in seconds."
+ :group 'helm
+ :type 'float)
+
+(defcustom helm-exit-idle-delay 0
+ "Idle time before exiting minibuffer while helm is updating.
+Has no affect when helm-buffer is up to date \(i.e exit without
+delay in this condition\)."
+ :group 'helm
+ :type 'float)
+
+(defvaralias 'helm-samewindow 'helm-full-frame)
+(make-obsolete-variable 'helm-samewindow 'helm-full-frame "1.4.8.1")
+(defcustom helm-full-frame nil
+ "Use current window for showing candidates.
+If t, then Helm does not pop-up new window."
+ :group 'helm
+ :type 'boolean)
+
+(defcustom helm-candidate-separator
+ "--------------------"
+ "Candidates separator of `multiline' source."
+ :group 'helm
+ :type 'string)
+
+(defcustom helm-save-configuration-functions
+ '(set-window-configuration . current-window-configuration)
+ "Functions used to restore or save configurations for frames and windows.
+Specified as a pair of functions, where car is the restore function and cdr
+is the save function.
+
+To save and restore frame configuration, set this variable to
+'\(set-frame-configuration . current-frame-configuration\)
+
+NOTE: This may not work properly with own-frame minibuffer
+settings. Older versions saves/restores frame configuration, but
+the default has changed now to avoid flickering."
+ :group 'helm
+ :type 'sexp)
+
+(defcustom helm-display-function 'helm-default-display-buffer
+ "Function used to display `helm-buffer'.
+
+Local value in `helm-buffer' will take precedence on this default
+value. Commands that are in `helm-commands-using-frame' will have
+`helm-buffer' displayed in frame, `helm-display-function' being
+ignored.
+If no local value found and current command is not one of
+`helm-commands-using-frame' use this default value.
+Function in charge of deciding which value use is
+`helm-resolve-display-function'.
+
+To set it locally to `helm-buffer' in helm sources use
+`helm-set-local-variable' in init function or use
+:display-function slot in `helm' call."
+ :group 'helm
+ :type 'symbol)
+
+(defcustom helm-case-fold-search 'smart
+ "Adds 'smart' option to `case-fold-search'.
+Smart option ignores case for searches as long as there are no
+upper case characters in the pattern.
+
+Use nil or t to turn off smart behavior and use
+`case-fold-search' behavior.
+
+Default is smart.
+
+NOTE: Case fold search has no effect when searching asynchronous
+sources, which rely on customized features implemented directly
+into their execution process. See helm-grep.el for an example."
+ :group 'helm
+ :type '(choice (const :tag "Ignore case" t)
+ (const :tag "Respect case" nil)
+ (other :tag "Smart" 'smart)))
+
+(defcustom helm-file-name-case-fold-search
+ (if (memq system-type
+ '(cygwin windows-nt ms-dos darwin))
+ t
+ helm-case-fold-search)
+ "Local setting of `helm-case-fold-search' for reading filenames.
+
+See `helm-case-fold-search' for more info."
+ :group 'helm
+ :type 'symbol)
+
+(defcustom helm-reuse-last-window-split-state nil
+ "Use the same state of window split, vertical or horizontal.
+`helm-toggle-resplit-window' for the next helm session will use
+the same window scheme as the previous session unless
+`helm-split-window-default-side' is 'same or 'other."
+ :group 'helm
+ :type 'boolean)
+
+(defcustom helm-split-window-preferred-function 'helm-split-window-default-fn
+ "Default function used for splitting window."
+ :group 'helm
+ :type 'function)
+
+(defcustom helm-split-window-default-side 'below
+ "The default side to display `helm-buffer'.
+Must be one acceptable arg for `split-window' SIDE,
+that is `below', `above', `left' or `right'.
+
+Other acceptable values are `same' which always display
+`helm-buffer' in current window and `other' that display
+`helm-buffer' below if only one window or in
+`other-window-for-scrolling' when available.
+
+A nil value has same effect as `below'.
+If `helm-full-frame' is non-`nil', it take precedence over this setting.
+
+See also `helm-split-window-inside-p' and `helm-always-two-windows' that
+take precedence over this.
+
+NOTE: this have no effect if `helm-split-window-preferred-function' is not
+`helm-split-window-default-fn' unless this new function can handle this."
+ :group 'helm
+ :type 'symbol)
+
+(defcustom helm-display-buffer-default-height nil
+ "Initial height of `helm-buffer', specified as an integer or a function.
+
+The function should take one arg and the responsibility for
+re-sizing the window; function's return value is ignored.
+Note that this have no effect when the split is vertical.
+See `display-buffer' for more info."
+ :group 'helm
+ :type '(choice integer function))
+
+(defcustom helm-display-buffer-default-width nil
+ "Initial width of `helm-buffer', specified as an integer or a function.
+
+The function should take one arg and the responsibility for
+re-sizing the window; function's return value is ignored.
+Note that this have no effect when the split is horizontal.
+See `display-buffer' for more info."
+ :group 'helm
+ :type '(choice integer function))
+
+(defvaralias 'helm-split-window-in-side-p 'helm-split-window-inside-p)
+(make-obsolete-variable 'helm-split-window-in-side-p 'helm-split-window-inside-p "2.8.6")
+(defcustom helm-split-window-inside-p nil
+ "Forces split inside selected window when non-`nil'.
+See also `helm-split-window-default-side'.
+
+NOTE: this has no effect if
+`helm-split-window-preferred-function' is not
+`helm-split-window-default-fn' unless this new function can
+handle this."
+ :group 'helm
+ :type 'boolean)
+
+(defcustom helm-always-two-windows nil
+ "When non-`nil' helm uses two windows in this frame.
+To display `helm-buffer' in one window and `helm-current-buffer'
+in the other.
+
+Note: this has no effect when `helm-split-window-inside-p' is non-`nil',
+or when `helm-split-window-default-side' is set to 'same.
+
+When `helm-autoresize-mode' is enabled, setting this to nil
+will have no effect.
+
+Also when non-`nil' it overrides the effect of `helm-split-window-default-side'
+set to `other'."
+ :group 'helm
+ :type 'boolean)
+
+(defcustom helm-display-buffer-width 72
+ "Frame width when displaying helm-buffer in own frame."
+ :group 'helm
+ :type 'integer)
+
+(defcustom helm-display-buffer-height 20
+ "Frame height when displaying helm-buffer in own frame."
+ :group 'helm
+ :type 'integer)
+
+(defcustom helm-default-display-buffer-functions nil
+ "Action functions to pass to `display-buffer'.
+See (info \"(elisp) Display Action Functions\").
+
+Have no effect when `helm-always-two-windows' is non-nil and may
+override other settings like `helm-split-window-inside-p'."
+ :group 'helm
+ :type '(repeat symbol))
+
+(defcustom helm-default-display-buffer-alist nil
+ "Additional alist to pass to `display-buffer' action.
+See (info \"(elisp) Display Action Functions\").
+
+Have no effect when `helm-always-two-windows' is non-nil and may
+override other settings like `helm-split-window-inside-p'.
+Note that window-height and window-width have to be configured in
+`helm-display-buffer-height' and `helm-display-buffer-width'."
+ :group 'helm
+ :type '(alist :key-type symbol :value-type sexp))
+
+(defcustom helm-sources-using-default-as-input '(helm-source-imenu
+ helm-source-imenu-all
+ helm-source-info-elisp
+ helm-source-etags-select
+ helm-source-man-pages
+ helm-source-occur
+ helm-source-moccur
+ helm-source-grep-ag
+ helm-source-grep-git
+ helm-source-grep)
+ "List of helm sources that need to use `helm--maybe-use-default-as-input'.
+When a source is a member of this list, default `thing-at-point'
+will be used as input."
+ :group 'helm
+ :type '(repeat (choice symbol)))
+
+(defcustom helm-delete-minibuffer-contents-from-point t
+ "When non-`nil', `helm-delete-minibuffer-contents' delete region from `point'.
+Otherwise delete `minibuffer-contents'.
+See documentation for `helm-delete-minibuffer-contents'."
+ :group 'helm
+ :type 'boolean)
+
+(defcustom helm-follow-mode-persistent nil
+ "When non-`nil', save last state of `helm-follow-mode' for the next emacs sessions.
+
+Each time you turn on or off `helm-follow-mode', the current source name will be stored
+or removed from `helm-source-names-using-follow'.
+
+Note that this may be disabled in some places where it is unsafe to use
+because persistent action is changing according to context."
+ :group 'helm
+ :type 'boolean)
+
+(defcustom helm-source-names-using-follow nil
+ "A list of source names to have follow enabled.
+This list of source names will be used only
+when `helm-follow-mode-persistent' is non-nil.
+
+You don't have to customize this yourself unless you really want and
+know what you are doing, instead just set
+`helm-follow-mode-persistent' to non-nil and as soon you turn on or
+off `helm-follow-mode' (C-c C-f) in a source, helm will save or remove
+source name in this variable."
+ :group 'helm
+ :type '(repeat (choice string)))
+
+(defcustom helm-prevent-escaping-from-minibuffer t
+ "Prevent escaping from minibuffer with `other-window' during the helm session."
+ :group 'helm
+ :type 'boolean)
+
+(defcustom helm-allow-mouse nil
+ "Allow mouse usage during the helm session when non-nil.
+
+Note that this also allow moving out of minibuffer when clicking
+outside of `helm-buffer', up to you to get back to helm by clicking
+back in `helm-buffer' of minibuffer."
+ :group 'helm
+ :type 'boolean)
+
+(defcustom helm-move-to-line-cycle-in-source nil
+ "Cycle to the beginning or end of the list after reaching the bottom or top.
+This applies when using `helm-next/previous-line'."
+ :group 'helm
+ :type 'boolean)
+
+(defcustom helm-fuzzy-match-fn 'helm-fuzzy-match
+ "The function for fuzzy matching in `helm-source-sync' based sources."
+ :group 'helm
+ :type 'function)
+
+(defcustom helm-fuzzy-search-fn 'helm-fuzzy-search
+ "The function for fuzzy matching in `helm-source-in-buffer' based sources."
+ :group 'helm
+ :type 'function)
+
+(defcustom helm-fuzzy-sort-fn 'helm-fuzzy-matching-default-sort-fn
+ "The sort transformer function used in fuzzy matching.
+When nil, sorting is not done."
+ :group 'helm
+ :type 'function)
+
+(defcustom helm-fuzzy-matching-highlight-fn 'helm-fuzzy-default-highlight-match
+ "The function to highlight fuzzy matches.
+When nil, no highlighting is done."
+ :group 'helm
+ :type 'function)
+
+(defcustom helm-autoresize-max-height 40
+ "Specifies maximum height and defaults to percent of helm window's frame height.
+
+See `fit-window-to-buffer' for more infos."
+ :group 'helm
+ :type 'integer)
+
+(defcustom helm-autoresize-min-height 10
+ "Specifies minimum height and defaults to percent of helm window's frame height.
+
+If nil, `window-min-height' is used.
+See `fit-window-to-buffer' for details."
+ :group 'helm
+ :type 'integer)
+
+(defcustom helm-input-method-verbose-flag nil
+ "The default value for `input-method-verbose-flag' used in helm minibuffer.
+It is nil by default, which does not turn off input method. Helm
+updates and exits without interruption -- necessary for complex methods.
+
+If set to any other value as per `input-method-verbose-flag',
+then use `C-\\' to disable the `current-input-method' to exit or update helm"
+ :group 'helm
+ :type '(radio :tag "A flag to control extra guidance for input methods in helm."
+ (const :tag "Never provide guidance" nil)
+ (const :tag "Always provide guidance" t)
+ (const :tag "Provide guidance only for complex methods" complex-only)))
+
+(defcustom helm-display-header-line t
+ "Display header-line when non nil."
+ :group 'helm
+ :type 'boolean)
+
+(defcustom helm-inherit-input-method t
+ "Inherit `current-input-method' from `current-buffer' when non-`nil'.
+The default is to enable this by default and then toggle
+`toggle-input-method'."
+ :group 'helm
+ :type 'boolean)
+
+(defcustom helm-echo-input-in-header-line nil
+ "Send current input in header-line when non-nil."
+ :group 'helm
+ :type 'boolean)
+
+(defcustom helm-header-line-space-before-prompt 'left-fringe
+ "Specify the space before prompt in header-line.
+
+This will be used when `helm-echo-input-in-header-line' is non-nil.
+
+Value can be one of the symbols 'left-fringe or 'left-margin or an
+integer specifying the number of spaces before prompt.
+Note that on input longer that `window-width' the continuation string
+will be shown on left side of window without taking care of this."
+ :group 'helm
+ :type '(choice
+ (symbol
+ (const :tag "Fringe" 'left-fringe)
+ (const :tag "Margin" 'left-margin))
+ integer))
+
+(defcustom helm-tramp-connection-min-time-diff 5
+ "Value of `tramp-connection-min-time-diff' for helm remote processes.
+If set to zero helm remote processes are not delayed.
+Setting this to a value less than 5 or disabling it with a zero value
+is risky, however on emacs versions starting at 24.5 it seems
+it is now possible to disable it.
+Anyway at any time in helm you can suspend your processes while typing
+by hitting \\<helm-map> `\\[helm-toggle-suspend-update]'.
+Only async sources than use a sentinel calling
+`helm-process-deferred-sentinel-hook' are affected by this."
+ :type 'integer
+ :group 'helm)
+
+(defcustom helm-debug-root-directory nil
+ "When non-`nil', saves helm log messages to a file in this directory.
+When `nil' log messages are saved to a buffer instead.
+Log message are saved only when `helm-debug' is non-nil, so setting this
+doesn't enable debugging by itself.
+
+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.
+
+If nil don't split and replace helm-buffer by the action buffer
+in same window.
+If left display the action buffer at the left of helm-buffer.
+If right or any other value, split at right.
+
+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 '(choice
+ (const :tag "Split at left" left)
+ (const :tag "Don't split" nil)
+ (other :tag "Split at right" right)))
+
+(defcustom helm-cycle-resume-delay 1.0
+ "Delay used before resuming in `helm-run-cycle-resume'."
+ :type 'float
+ :group 'helm)
+
+(defcustom helm-display-buffer-reuse-frame nil
+ "When non nil helm frame is not deleted and reused in next sessions.
+
+This was used to workaround a bug in emacs where frames where
+popping up slowly, now that the bug have been fixed upstream probably
+you don't want to use this anymore."
+ :group 'helm
+ :type 'boolean)
+
+(defcustom helm-commands-using-frame nil
+ "A list of commands where `helm-buffer' is displayed in a frame."
+ :group 'helm
+ :type '(repeat symbol))
+
+(defcustom helm-actions-inherit-frame-settings t
+ "Actions inherit helm frame settings of initial command when non nil."
+ :group 'helm
+ :type 'boolean)
+
+(defcustom helm-use-undecorated-frame-option nil
+ "Display helm frame undecorated when non nil.
+
+This option have no effect with emacs versions lower than 26."
+ :group 'helm
+ :type 'boolean)
+
+(defcustom helm-use-frame-when-more-than-two-windows nil
+ "Display helm buffer in frame when more than two windows."
+ :group 'helm
+ :type 'boolean)
+
+(defcustom helm-default-prompt-display-function
+ #'helm-set-default-prompt-display
+ "The function to use to set face of fake cursor in header-line."
+ :group 'helm
+ :type 'function)
+\f
+;;; Faces
+;;
+;;
+(defgroup helm-faces nil
+ "Customize the appearance of helm."
+ :prefix "helm-"
+ :group 'faces
+ :group 'helm)
+
+(defface helm-source-header
+ '((((background dark))
+ :background "#22083397778B"
+ :foreground "white"
+ :weight bold :height 1.3 :family "Sans Serif")
+ (((background light))
+ :background "#abd7f0"
+ :foreground "black"
+ :weight bold :height 1.3 :family "Sans Serif"))
+ "Face for source header in the helm buffer."
+ :group 'helm-faces)
+
+(defface helm-visible-mark
+ '((((min-colors 88) (background dark))
+ (:background "green1" :foreground "black"))
+ (((background dark))
+ (:background "green" :foreground "black"))
+ (((background light)) :background "#d1f5ea")
+ (((min-colors 88))
+ (:background "green1"))
+ (t (:background "green")))
+ "Face for visible mark."
+ :group 'helm-faces)
+
+(defface helm-header
+ '((t (:inherit header-line)))
+ "Face for header lines in the helm buffer."
+ :group 'helm-faces)
+
+(defface helm-candidate-number
+ '((((background dark)) :background "Yellow" :foreground "black")
+ (((background light)) :background "#faffb5" :foreground "black"))
+ "Face for candidate number in mode-line."
+ :group 'helm-faces)
+
+(defface helm-candidate-number-suspended
+ '((t (:inherit helm-candidate-number :inverse-video t)))
+ "Face for candidate number in mode-line when helm is suspended."
+ :group 'helm-faces)
+
+(defface helm-selection
+ '((((background dark)) :background "ForestGreen"
+ :distant-foreground "black")
+ (((background light)) :background "#b5ffd1"
+ :distant-foreground "black"))
+ "Face for currently selected item in the helm buffer."
+ :group 'helm-faces)
+
+(defface helm-separator
+ '((((background dark)) :foreground "red")
+ (((background light)) :foreground "#ffbfb5"))
+ "Face for multiline source separator."
+ :group 'helm-faces)
+
+(defface helm-action
+ '((t (:underline t)))
+ "Face for action lines in the helm action buffer."
+ :group 'helm-faces)
+
+(defface helm-prefarg
+ '((((background dark)) :foreground "green")
+ (((background light)) :foreground "red"))
+ "Face for showing prefix arg in mode-line."
+ :group 'helm-faces)
+
+(defface helm-match
+ '((((background light)) :foreground "#b00000")
+ (((background dark)) :foreground "gold1"))
+ "Face used to highlight matches."
+ :group 'helm-faces)
+
+(defface helm-header-line-left-margin
+ '((t (:foreground "black" :background "yellow")))
+ "Face used to highlight helm-header sign in left-margin."
+ :group 'helm-faces)
+
+(defface helm-minibuffer-prompt
+ '((t (:inherit minibuffer-prompt)))
+ "Face used for the minibuffer/headline prompt (such as Pattern:) in helm."
+ :group 'helm-faces)
+
+\f
+;;; Variables.
+;;
+;;
+(defvar helm-selection-overlay nil
+ "Overlay used to highlight the currently selected item.")
+
+(defvar helm-async-processes nil
+ "List of information about asynchronous processes managed by helm.")
+
+(defvar helm-before-initialize-hook nil
+ "Runs before helm initialization.
+This hook runs before init functions in `helm-sources', which is
+before creation of `helm-buffer'. Set local variables for
+`helm-buffer' that need a value from `current-buffer' with
+`helm-set-local-variable'.")
+
+(defvar helm-after-initialize-hook nil
+ "Runs after helm initialization.
+This hook runs after `helm-buffer' is created but not from
+`helm-buffer'. The hook needs to specify in which buffer to run.")
+
+(defvaralias 'helm-update-hook 'helm-after-update-hook)
+(make-obsolete-variable 'helm-update-hook 'helm-after-update-hook "1.9.9")
+
+(defvar helm-after-update-hook nil
+ "Runs after updating the helm buffer with the new input pattern.")
+
+(defvar helm-cleanup-hook nil
+ "Runs after exiting the minibuffer and before performing an
+action.
+
+This hook runs even if helm exits the minibuffer abnormally (e.g.
+via `helm-keyboard-quit').")
+
+(defvar helm-select-action-hook nil
+ "Runs when opening the action buffer.")
+
+(defvar helm-before-action-hook nil
+ "Runs before executing action.
+Unlike `helm-cleanup-hook', this hook runs before helm closes the
+minibuffer and also before performing an action.")
+
+(defvar helm-after-action-hook nil
+ "Runs after executing action.")
+
+(defvar helm-exit-minibuffer-hook nil
+ "Runs just before exiting the minibuffer.
+
+This hook runs when helm exits the minibuffer normally (e.g. via
+candidate selection), but does NOT run if helm exits the
+minibuffer abnormally (e.g. via `helm-keyboard-quit').")
+
+(defvar helm-after-persistent-action-hook nil
+ "Runs after executing persistent action.")
+
+(defvar helm-move-selection-before-hook nil
+ "Runs before moving selection in `helm-buffer'.")
+
+(defvar helm-move-selection-after-hook nil
+ "Runs after moving selection in `helm-buffer'.")
+
+(defvar helm-after-preselection-hook nil
+ "Runs after pre-selection in `helm-buffer'.")
+
+(defvar helm-window-configuration-hook nil
+ "Runs when switching to and from the action buffer.")
+
+(defvar helm-execute-action-at-once-if-one nil
+ "When non--nil executes the default action and then exits if only one candidate.
+If symbol 'current-source is given as value exit if only one candidate
+in current source.
+This variable accepts a function with no args that should returns a boolean
+value or 'current-source.")
+
+(defvar helm-quit-if-no-candidate nil
+ "When non-`nil', quits if there are no candidates.
+This variable accepts a function.")
+
+(defvar helm-debug-variables nil
+ "A list of helm variables that `helm-debug-output' displays.
+If `nil', `helm-debug-output' includes only variables with
+`helm-' prefixes.")
+
+(defvar helm-debug-buffer "*Debug Helm Log*")
+
+(defvar helm-debug nil
+ "If non-`nil', write log message to `helm-debug-buffer'.
+Default is `nil', which disables writing log messages because the
+size of `helm-debug-buffer' grows quickly.")
+
+(defvar helm-mode-line-string "\
+\\<helm-map>\
+\\[helm-help]:Help \
+\\[helm-select-action]:Act \
+\\[helm-maybe-exit-minibuffer]/\
+f1/f2/f-n:NthAct \
+\\[helm-toggle-suspend-update]:Tog.suspend"
+ "Help string displayed by helm in the mode-line.
+It is either a string or a list of two string arguments where the
+first string is the name and the second string is displayed in
+the mode-line. When `nil', uses default `mode-line-format'.")
+
+(defvar helm-minibuffer-set-up-hook nil
+ "Hook that runs at minibuffer initialization.
+A hook useful for modifying minibuffer settings in helm.
+
+An example that hides the minibuffer when using
+`helm-echo-input-in-header-line':
+
+ (add-hook 'helm-minibuffer-set-up-hook #'helm-hide-minibuffer-maybe)
+
+Note that we check `helm-echo-input-in-header-line' value
+from `helm-buffer' which allow detecting possible local
+value of this var.")
+
+(defvar helm-help-message
+ "* Helm Generic Help
+** Basics
+
+Helm narrows down the list of candidates as you type a filter pattern.
+
+Helm accepts multiple space-separated patterns, each pattern can be negated with \"!\".
+
+Helm also supports fuzzy matching in some places when specified, you will find
+several variables to enable fuzzy matching in diverse sources,
+see [[https://github.com/emacs-helm/helm/wiki/Fuzzy-matching][fuzzy-matching]] in helm-wiki for more infos.
+
+Helm generally uses familiar Emacs keys to navigate the list.
+Here follow some of the less obvious bindings:
+
+- `\\[helm-maybe-exit-minibuffer]' selects the candidate from the list, executes the default action
+upon exiting the Helm session.
+
+- `\\[helm-execute-persistent-action]' executes the default action but without exiting the Helm session.
+Not all sources support this.
+
+- `\\[helm-select-action]' displays a list of actions available on current candidate or all marked candidates.
+The default binding <tab> is ordinarily used for completion, but that would be
+redundant since Helm completes upon every character entered in the prompt.
+See [[https://github.com/emacs-helm/helm/wiki#helm-completion-vs-emacs-completion][Helm wiki]].
+
+Note: In addition to the default actions list, additional actions appear
+depending of the type of the selected candidate(s). They are called filtered
+actions.
+
+** Helm mode
+
+`helm-mode' toggles Helm completion in native Emacs functions,
+so when you turn `helm-mode' on, commands like `switch-to-buffer' will use
+Helm completion instead of the usual Emacs completion buffer.
+
+*** What gets or does not get \"helmized\" when `helm-mode' is enabled?
+
+Helm provides generic completion on all Emacs functions using `completing-read',
+`completion-in-region' and their derivatives, e.g. `read-file-name'. Helm
+exposes a user variable to control which function to use for a specific Emacs
+command: `helm-completing-read-handlers-alist'. If the function for a specific
+command is nil, it turns off Helm completion. See the variable documentation
+for more infos.
+
+*** Helm functions vs helmized Emacs functions
+
+While there are Helm functions that perform the same completion as other
+helmized Emacs functions, e.g. `switch-to-buffer' and `helm-buffers-list', the
+native Helm functions like `helm-buffers-list' can receive new features, the
+allow marking candidates, they have several actions, etc. Whereas the helmized
+Emacs functions only have Helm completion, one action and no more then Emacs can
+provide for this function. This is the intended behavior.
+
+Generally you are better off using the native Helm command
+than the helmized Emacs equivalent.
+
+** Helm help
+
+\\[helm-documentation]: Show all helm documentations concatenated in one org file.
+
+From a Helm session, just hit \\<helm-map>\\[helm-help] to have the
+documentation for the current source followed by the global Helm documentation.
+
+While in the help buffer, most of the regular keybindings are available in an
+Emacs buffers; the most important ones are shown in minibuffer. However due to
+the implementation restrictions, no regular Emacs keymap is used (it runs in a
+loop when reading the help buffer) they are hardcoded and not modifiable.
+
+The hard-coded documentation bindings are:
+
+| Key | Alternative keys | Command |
+|-----------+------------------+---------------------|
+| C-v | Space next | Scroll up |
+| M-v | b prior | Scroll down |
+| C-s | | Isearch forward |
+| C-r | | Isearch backward |
+| C-a | | Beginning of line |
+| C-e | | End of line |
+| C-f | right | Forward char |
+| C-b | left | Backward char |
+| C-n | down | Next line |
+| C-p | up | Previous line |
+| M-a | | Backward sentence |
+| M-e | | Forward sentence |
+| M-f | | Forward word |
+| M-b | | Backward word |
+| M-> | | End of buffer |
+| M-< | | Beginning of buffer |
+| C-<SPACE> | | Toggle mark |
+| RET | | Follow org link |
+| C-% | | Push org mark |
+| C-& | | Goto org mark-ring |
+| TAB | | Org cycle |
+| M-<TAB> | | Toggle visibility |
+| M-w | | Copy region |
+| q | | Quit |
+
+** Customize Helm
+
+Helm provides a lot of user variables for extensive customization.
+From any Helm session, type \\<helm-map>\\[helm-customize-group] to jump to the current source `custom' group.
+Helm also has a special group for faces you can access via `M-x customize-group RET helm-faces'.
+
+Note: Some sources may not have their group set and default to the `helm' group.
+
+** Helm's basic operations and default key bindings
+
+| Key | Alternative Keys | Command |
+|---------+------------------+----------------------------------------------------------------------|
+| C-p | Up | Previous line |
+| C-n | Down | Next line |
+| M-v | prior | Previous page |
+| C-v | next | Next page |
+| Enter | | Execute first (default) action / Select |
+| M-< | | First line |
+| M-> | | Last line |
+| C-M-S-v | M-prior, C-M-y | Previous page (other-window) |
+| C-M-v | M-next | Next page (other-window) |
+| Tab | C-i | Show action list |
+| Left | | Previous source |
+| Right | C-o | Next source |
+| C-k | | Delete pattern (with prefix arg delete from point to end or all [1]) |
+| C-j | C-z | Persistent action (Execute and keep Helm session) |
+
+\[1] Delete from point to end or all depending on the value of
+`helm-delete-minibuffer-contents-from-point'.
+
+** Shortcuts for n-th action
+
+f1-f12: Execute n-th action where n is 1 to 12.
+
+** Shortcuts for executing the default action on the n-th candidate
+
+C-x <n>: Execute default action on the n-th candidate before currently selected candidate.
+
+C-c <n>: Execute default action on the n-th candidate after current selected candidate.
+
+\"n\" is limited to 1-9. For larger jumps use other navigation keys. Helm does
+not display line numbers by default: enable them with the
+\[[https://github.com/coldnew/linum-relative][linum-relative]] package and
+`helm-linum-relative-mode'.
+If you are using Emacs-26+ version you can use `global-display-line-numbers-mode'
+which seems even better (don't forget to customize `display-line-numbers-type' to relative).
+
+** Mouse control in Helm
+
+A basic support for the mouse is provided when the user sets `helm-allow-mouse' to non-nil.
+
+- mouse-1 selects the candidate.
+- mouse-2 executes the default action on selected candidate.
+- mouse-3 pops up the action menu.
+
+Note: When mouse control is enabled in Helm, it also lets you click around and lose
+the minibuffer focus: you'll have to click on the Helm buffer or the minibuffer
+to retrieve control of your Helm session.
+
+** Marked candidates
+
+You can mark candidates to execute an action on all of them instead of the
+current selected candidate only. (See bindings below.) Most Helm actions
+operate on marked candidates unless candidate-marking is explicitely forbidden
+for a specific source.
+
+- To mark/unmark a candidate, use \\[helm-toggle-visible-mark]. (See bindings below.)
+With a numeric prefix arg mark ARG candidates forward, if ARG is negative
+mark ARG candidates backward.
+
+- To mark all visible unmarked candidates at once in current source use \\[helm-mark-all].
+With a prefix argument, mark all candidates in all sources.
+
+- To unmark all visible marked candidates at once use \\[helm-unmark-all].
+
+- To mark/unmark all candidates at once use \\[helm-toggle-all-marks].
+With a prefix argument, mark/unmark all candidates in all sources.
+
+Note: When multiple candidates are selected across different sources, only the
+candidates of the current source will be used when executing most actions (as
+different sources can have different actions). Some actions support
+multi-source marking however.
+
+** Follow candidates
+
+When `helm-follow-mode' is on (\\<helm-map>\\[helm-follow-mode] to toggle it),
+moving up and down the Helm session or updating the list of candidates will
+automatically execute the persistent-action as specified for the current source.
+
+If `helm-follow-mode-persistent' is non-nil, the state of the mode will be
+restored for the following Helm sessions.
+
+If you just want to follow candidates occasionally without enabling
+`helm-follow-mode', you can use \\<helm-map>\\[helm-follow-action-forward] or \\[helm-follow-action-backward] instead.
+Conversely, when `helm-follow-mode' is enabled, those commands
+go to previous/next line without executing the persistent action.
+
+** Frequently Used Commands
+
+\\[helm-toggle-resplit-and-swap-windows]\t\tToggle vertical/horizontal split on first hit and swap Helm window on second hit.
+\\[helm-quit-and-find-file]\t\tDrop into `helm-find-files'.
+\\[helm-kill-selection-and-quit]\t\tKill display value of candidate and quit (with prefix arg, kill the real value).
+\\[helm-yank-selection]\t\tYank current selection into pattern.
+\\[helm-copy-to-buffer]\t\tCopy selected candidate at point in current buffer.
+\\[helm-follow-mode]\t\tToggle automatic execution of persistent action.
+\\[helm-follow-action-forward]\tRun persistent action then select next line.
+\\[helm-follow-action-backward]\t\tRun persistent action then select previous line.
+\\[helm-refresh]\t\tRecalculate and redisplay candidates.
+\\[helm-toggle-suspend-update]\t\tToggle candidate updates.
+
+** Special yes, no or yes for all answers
+
+You may be prompted in the minibuffer to answer by [y,n,!,q] in some places
+for confirmation.
+
+- y mean yes
+- no mean no
+- ! mean yes for all
+- q mean quit or abort current operation.
+
+When using ! you will not be prompted anymore for the same thing in current operation
+e.g. file deletion, file copy etc...
+
+** Moving in `helm-buffer'
+
+You can move in `helm-buffer' with the usual commands used in Emacs:
+\(\\<helm-map>\\[helm-next-line], \\<helm-map>\\[helm-previous-line], etc. See above basic commands.
+When `helm-buffer' contains more than one source, change source with \\<helm-map>\\[helm-next-source].
+
+Note: When reaching the end of a source, \\<helm-map>\\[helm-next-line] will *not* go to the next source unless
+variable `helm-move-to-line-cycle-in-source' is non-nil, so you will have to use \\<helm-map>\\[helm-next-source].
+
+** Resume previous session from current Helm session
+
+You can use `C-c n' (`helm-run-cycle-resume') to cycle in resumables sources.
+`C-c n' is a special key set with `helm-define-key-with-subkeys' which, after pressing it, allows you
+to keep cycling with further `n'.
+
+Tip: You can bound the same key in `global-map' to `helm-cycle-resume'
+ with `helm-define-key-with-subkeys' to let you transparently cycle
+ sessions, Helm fired up or not.
+ You can also bind the cycling commands to single key presses (e.g. `S-<f1>') this time
+ with a simple `define-key'. (Note that `S-<f1>' is not available in terminals.)
+
+Note: `helm-define-key-with-subkeys' is available only once Helm is loaded.
+
+You can also use \\<helm-map>\\[helm-resume-previous-session-after-quit] to resume
+the previous session, or \\<helm-map>\\[helm-resume-list-buffers-after-quit]
+to have completion on all resumable buffers.
+
+** Global commands
+
+*** Resume Helm session from outside Helm
+
+\\<global-map>\\[helm-resume] revives the last `helm' session. Binding a key to
+this command will greatly improve `helm' interactivity, e.g. when quitting Helm
+accidentally.
+
+You can call \\<global-map>\\[helm-resume] with a prefix argument to choose
+\(with completion!) which session you'd like to resume. You can also cycle in
+these sources with `helm-cycle-resume' (see above).
+
+** Debugging Helm
+
+Helm exposes the special variable `helm-debug': setting it to non-nil
+will enable Helm logging in a special outline-mode buffer.
+Helm resets the variable to nil at the end of each session.
+
+For convenience, \\<helm-map>\\[helm-enable-or-switch-to-debug]
+allows you to turn on debugging for this session only.
+To avoid accumulating log entries while you are typing patterns, you can use
+\\<helm-map>\\[helm-toggle-suspend-update] to turn off updating. When you
+are ready turn it on again to resume logging.
+
+Once you exit your Helm session you can access the debug buffer with
+`helm-debug-open-last-log'. It is possible to save logs to dated files when
+`helm-debug-root-directory' is set to a valid directory.
+
+Note: Be aware that Helm log buffers grow really fast, so use `helm-debug' only
+when needed.
+
+** Writing your own Helm sources
+
+Writing simple sources for your own usage is easy. When calling the `helm'
+function, the sources are added the :sources slot which can be a symbol or a
+list of sources. Sources can be built with different EIEIO classes depending
+what you want to do. To simplify this, several `helm-build-*' macros are
+provided. Below, simple examples to start with.
+
+We will not go further here, see [[https://github.com/emacs-helm/helm/wiki/Developing][Helm wiki]] and the source
+code for more information and more complex exapmles.
+
+#+begin_src elisp
+
+ ;; Candidates are stored in a list.
+ (helm :sources (helm-build-sync-source \"test\"
+ ;; A function can be used as well
+ ;; to provide candidates.
+ :candidates '(\"foo\" \"bar\" \"baz\"))
+ :buffer \"*helm test*\")
+
+ ;; Candidates are stored in a buffer.
+ ;; Generally faster but doesn't allow a dynamic updating
+ ;; of the candidates list i.e the list is fixed on start.
+ (helm :sources (helm-build-in-buffer-source \"test\"
+ :data '(\"foo\" \"bar\" \"baz\"))
+ :buffer \"*helm test*\")
+
+#+end_src
+
+** Helm Map
+\\{helm-map}"
+ "Message string containing detailed help for `helm'.
+It also accepts function or variable symbol.")
+
+(defvar helm-autoresize-mode) ;; Undefined in `helm-default-display-buffer'.
+
+(defvar helm-async-outer-limit-hook nil
+ "A hook that run in async sources when process output comes out of `candidate-number-limit'.
+Should be set locally to `helm-buffer' with `helm-set-local-variable'.")
+
+(defvar helm-quit-hook nil
+ "A hook that run when quitting helm.")
+
+(defvar helm-resume-after-hook nil
+ "A hook that run after resuming a helm session.
+The hook should take one arg SOURCES.")
+\f
+;;; Internal Variables
+;;
+;;
+(defvar helm-source-filter nil
+ "A list of source names to be displayed.
+Other sources won't appear in the search results.
+If nil, no filtering is done.
+Don't set this directly, use `helm-set-source-filter' during helm session
+to modify it.")
+(defvar helm-current-prefix-arg nil
+ "Record `current-prefix-arg' when exiting minibuffer.")
+(defvar helm-saved-action nil
+ "Saved value of the currently selected action by key.")
+(defvar helm-saved-current-source nil
+ "Value of the current source when the action list is shown.")
+(defvar helm-in-persistent-action nil
+ "Flag whether in persistent-action or not.")
+(defvar helm-last-buffer nil
+ "`helm-buffer' of previously `helm' session.")
+(defvar helm-saved-selection nil
+ "Value of the currently selected object when the action list is shown.")
+(defvar helm-sources nil
+ "[INTERNAL] Value of current sources in use, a list.")
+(defvar helm-buffer-file-name nil
+ "Variable `buffer-file-name' when `helm' is invoked.")
+(defvar helm-candidate-cache (make-hash-table :test 'equal)
+ "Holds the available candidate within a single helm invocation.")
+(defvar helm--candidate-buffer-alist nil)
+(defvar helm-input ""
+ "The input typed in the candidates panel.")
+(defvar helm-input-local nil
+ "Internal, store locally `helm-pattern' value for later use in `helm-resume'.")
+(defvar helm--source-name nil)
+(defvar helm-current-source nil)
+(defvar helm-tick-hash (make-hash-table :test 'equal))
+(defvar helm-issued-errors nil)
+(defvar helm--last-log-file nil
+ "The name of the log file of the last helm session.")
+(defvar helm--local-variables nil)
+(defvar helm-split-window-state nil)
+(defvar helm--window-side-state nil)
+(defvar helm-selection-point nil)
+(defvar helm-alive-p nil)
+(defvar helm-visible-mark-overlays nil)
+(defvar helm-update-blacklist-regexps '("^" "^ *" "$" "!" " " "\\b"
+ "\\<" "\\>" "\\_<" "\\_>" ".*"
+ "??" "?*" "*?" "?"))
+(defvar helm--force-updating-p nil
+ "[INTERNAL] Don't use this in your programs.")
+(defvar helm-exit-status 0
+ "Flag to inform if helm did exit or quit.
+0 means helm did exit when executing an action.
+1 means helm did quit with \\[keyboard-quit]
+Knowing this exit-status could help restore a window config when helm aborts
+in some special circumstances.
+See `helm-exit-minibuffer' and `helm-keyboard-quit'.")
+(defvar helm-minibuffer-confirm-state nil)
+(defvar helm-quit nil)
+(defvar helm-buffers nil
+ "Helm buffers listed in order of most recently used.")
+(defvar helm-current-position nil
+ "Cons of \(point . window-start\) when `helm' is invoked.
+`helm-current-buffer' uses this to restore position after
+`helm-keyboard-quit'")
+(defvar helm-last-frame-or-window-configuration nil
+ "Used to store window or frame configuration at helm start.")
+(defvar helm-onewindow-p nil)
+(defvar helm-types nil)
+(defvar helm--mode-line-string-real nil) ; The string to display in mode-line.
+(defvar helm-persistent-action-display-window nil)
+(defvar helm-marked-candidates nil
+ "Marked candidates. List of \(source . real\) pair.")
+(defvar helm--mode-line-display-prefarg nil)
+(defvar helm--temp-follow-flag nil
+ "[INTERNAL] A simple flag to notify persistent action we are following.")
+(defvar helm--reading-passwd-or-string nil)
+(defvar helm--in-update nil)
+(defvar helm--in-fuzzy nil)
+(defvar helm--maybe-use-default-as-input nil
+ "Flag to notify the use of use-default-as-input.
+Use only in let-bindings.
+Use :default arg of `helm' as input to update display.
+Note that if also :input is specified as `helm' arg, it will take
+precedence on :default.")
+(defvar helm--temp-hooks nil
+ "Store temporary hooks added by `with-helm-temp-hook'.")
+(defvar helm-truncate-lines nil
+ "[Internal] Don't set this globally, it is used as a local var.")
+(defvar helm--prompt nil)
+(defvar helm--file-completion-sources
+ '("Find Files" "Read File Name")
+ "Sources that use the *find-files mechanism can be added here.
+Sources generated by `helm-mode' don't need to be added here
+because they are automatically added.
+
+You should not modify this yourself unless you know what you are doing.")
+(defvar helm--completing-file-name nil
+ "Non nil when `helm-read-file-name' is running.
+Used for `helm-file-completion-source-p'.")
+;; Same as `ffap-url-regexp' but keep it here to ensure `ffap-url-regexp' is not nil.
+(defvar helm--url-regexp "\\`\\(news\\(post\\)?:\\|mailto:\\|file:\\|\\(ftp\\|https?\\|telnet\\|gopher\\|www\\|wais\\)://\\)")
+(defvar helm--ignore-errors nil
+ "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: ")
+(defvar helm--cycle-resume-iterator nil)
+(defvar helm--buffer-in-new-frame-p nil)
+(defvar helm-initial-frame nil
+ "[INTERNAL] The selected frame before starting helm.
+Helm use this internally to know in which frame it started, don't
+modify this yourself.")
+(defvar helm-popup-frame nil
+ "The frame where helm is displayed.
+
+This is only used when helm is using
+`helm-display-buffer-in-own-frame' as `helm-display-function' and
+`helm-display-buffer-reuse-frame' is non nil.")
+(defvar helm--nested nil)
+(defconst helm--frame-default-attributes
+ '(width height tool-bar-lines left top
+ title undecorated vertical-scroll-bars
+ visibility fullscreen menu-bar-lines undecorated)
+ "Frame parameters to save in `helm--last-frame-parameters'.")
+(defvar helm--last-frame-parameters nil
+ "Frame parameters to save for later resuming.
+Local to `helm-buffer'.")
+(defvar helm--executing-helm-action nil
+ "Non nil when action is triggering a new helm-session.
+This may be let bounded in other places to notify the display function
+to reuse the same frame parameters as the previous helm session just
+like resume would do.")
+(defvar helm--current-buffer-narrowed nil)
+\f
+;; Utility: logging
+(defun helm-log (format-string &rest args)
+ "Log message `helm-debug' is non-`nil'.
+Messages are written to the `helm-debug-buffer' buffer.
+
+Argument FORMAT-STRING is a string to use with `format'.
+Use optional arguments ARGS like in `format'."
+ (when helm-debug
+ (with-current-buffer (get-buffer-create helm-debug-buffer)
+ (outline-mode)
+ (buffer-disable-undo)
+ (let ((inhibit-read-only t))
+ (goto-char (point-max))
+ (insert (let ((tm (current-time)))
+ (format (concat (if (string-match "Start session" format-string)
+ "* " "** ")
+ "%s.%06d (%s)\n %s\n")
+ (format-time-string "%H:%M:%S" tm)
+ (nth 2 tm)
+ (helm-log-get-current-function)
+ (apply #'format (cons format-string args)))))))))
+
+(defun helm-log-run-hook (hook)
+ "Run HOOK like `run-hooks' but write these actions to helm log buffer."
+ (helm-log "Executing %s with value = %S" hook (symbol-value hook))
+ (helm-log "Executing %s with global value = %S" hook (default-value hook))
+ (run-hooks hook)
+ (helm-log "executed %s" hook))
+
+(defun helm-log-get-current-function ()
+ "Get name of function that is calling `helm-log'.
+The original idea is from `tramp-debug-message'."
+ (cl-loop with exclude-func-re = "^helm-\\(?:interpret\\|log\\|.*funcall\\)"
+ for btn from 1 to 40
+ for btf = (cl-second (backtrace-frame btn))
+ for fn = (if (symbolp btf) (symbol-name btf) "")
+ if (and (string-match "^helm" fn)
+ (not (string-match exclude-func-re fn)))
+ return fn))
+
+(defun helm-log-error (&rest args)
+ "Accumulate error messages into `helm-issued-errors'.
+ARGS are args given to `format'.
+e.g (helm-log-error \"Error %s: %s\" (car err) (cdr err))."
+ (apply 'helm-log (concat "ERROR: " (car args)) (cdr args))
+ (let ((msg (apply 'format args)))
+ (unless (member msg helm-issued-errors)
+ (cl-pushnew msg helm-issued-errors :test 'equal))))
+
+(defun helm-log-save-maybe ()
+ "Save log buffer when `helm-debug-root-directory' is non nil.
+Create `helm-debug-root-directory' directory if necessary.
+Messages are logged to a file named with todays date and time in this directory."
+ (when (and (stringp helm-debug-root-directory)
+ (not (file-directory-p helm-debug-root-directory)))
+ (make-directory helm-debug-root-directory t))
+ (when helm-debug
+ (let ((logdir (expand-file-name (concat "helm-debug-"
+ (format-time-string "%Y%m%d"))
+ helm-debug-root-directory)))
+ (make-directory logdir t)
+ (with-current-buffer (get-buffer-create helm-debug-buffer)
+ (write-region (point-min) (point-max)
+ (setq helm--last-log-file
+ (expand-file-name
+ (format-time-string "%Y%m%d-%H%M%S")
+ logdir))
+ nil 'silent)
+ (kill-buffer))))
+ (setq helm-debug nil))
+
+;;;###autoload
+(defun helm-debug-open-last-log ()
+ "Open helm log file or buffer of last helm session."
+ (interactive)
+ (if helm--last-log-file
+ (progn
+ (find-file helm--last-log-file)
+ (outline-mode) (view-mode 1) (visual-line-mode 1))
+ (switch-to-buffer helm-debug-buffer)
+ (view-mode 1) (visual-line-mode 1)))
+
+(defun helm-print-error-messages ()
+ "Print error messages in `helm-issued-errors'."
+ (and helm-issued-errors
+ (message "Helm issued errors: %s"
+ (mapconcat 'identity (reverse helm-issued-errors) "\n"))))
+
+\f
+;; Test tools
+(defmacro with-helm-time-after-update (&rest body)
+ (helm-with-gensyms (start-time time-elapsed)
+ `(let ((,start-time (float-time)) ,time-elapsed)
+ (add-hook 'helm-after-update-hook
+ (lambda ()
+ (setq ,time-elapsed (- (float-time) ,start-time))
+ (keyboard-quit)))
+ (unwind-protect ,@body
+ (remove-hook 'helm-after-update-hook
+ (lambda ()
+ (setq ,time-elapsed (- (float-time) ,start-time))
+ (keyboard-quit))))
+ ,time-elapsed)))
+
+\f
+;; Helm API
+(defmacro with-helm-default-directory (directory &rest body)
+ (declare (indent 2) (debug t))
+ `(let ((default-directory (or (and ,directory
+ (file-name-as-directory ,directory))
+ default-directory)))
+ ,@body))
+
+(defun helm-default-directory ()
+ "Return the local value of `default-directory' in `helm-buffer'."
+ (buffer-local-value 'default-directory (get-buffer helm-buffer)))
+
+(defmacro with-helm-temp-hook (hook &rest body)
+ "Execute temporarily BODY as a function for HOOK."
+ (declare (indent 1) (debug t))
+ (helm-with-gensyms (helm--hook)
+ `(progn
+ (defun ,helm--hook ()
+ (unwind-protect
+ (progn ,@body)
+ (remove-hook ,hook (quote ,helm--hook))
+ (fmakunbound (quote ,helm--hook))))
+ (push (cons ',helm--hook ,hook) helm--temp-hooks)
+ (add-hook ,hook (quote ,helm--hook)))))
+
+(defmacro with-helm-after-update-hook (&rest body)
+ "Execute BODY at end of `helm-update'."
+ (declare (indent 0) (debug t))
+ `(with-helm-temp-hook 'helm-after-update-hook ,@body))
+
+(defmacro with-helm-alive-p (&rest body)
+ "Return error when BODY run outside helm context."
+ (declare (indent 0) (debug t))
+ `(progn
+ (if helm-alive-p
+ (progn ,@body)
+ (error "Running helm command outside of context"))))
+
+(defmacro with-helm-in-frame (&rest body)
+ "Execute helm function in BODY displaying `helm-buffer' in separate frame."
+ (declare (debug t) (indent 0))
+ `(progn
+ (helm-set-local-variable
+ 'helm-display-function 'helm-display-buffer-in-own-frame)
+ ,@body))
+\f
+;;; helm-attributes
+;;
+(defun helm-attr (attribute-name &optional source compute)
+ "Get the value of ATTRIBUTE-NAME of SRC.
+
+If SRC is omitted, use current source.
+
+If COMPUTE is non-`nil' compute value of ATTRIBUTE-NAME with
+`helm-interpret-value'. COMPUTE can have also 'ignorefn as value, in
+this case `helm-interpret-value' will return a function as value
+unchanged, but will eval a symbol which is bound.
+
+You can use `setf' to modify value of ATTRIBUTE-NAME unless COMPUTE is
+specified, if attribute ATTRIBUTE-NAME is not found in SOURCE `setf'
+will create new attribute ATTRIBUTE-NAME with specified value.
+You can also use `helm-attrset' to modify ATTRIBUTE-NAME."
+ (declare (gv-setter
+ (lambda (val)
+ `(let* ((src (or ,source (helm-get-current-source)))
+ (attr (assq ,attribute-name src)))
+ (cl-assert (null ,compute) nil
+ "`setf' can't set the computed value of attribute `%s'"
+ ,attribute-name)
+ (if attr
+ (setcdr attr ,val)
+ (and (setcdr src (cons (cons ,attribute-name ,val)
+ (cdr src)))
+ ,val))))))
+ (let ((src (or source (helm-get-current-source))))
+ (helm-aif (assq attribute-name src)
+ (if compute
+ (helm-interpret-value (cdr it) src compute)
+ (cdr it)))))
+
+(cl-defun helm-attrset (attribute-name value
+ &optional
+ (src (helm-get-current-source)))
+ "Set the value of ATTRIBUTE-NAME of source SRC to VALUE.
+
+If ATTRIBUTE-NAME doesn't exists in source it is created with value VALUE..
+If SRC is omitted, use current source.
+If operation succeed, return value, otherwise nil.
+
+Note that `setf' on `helm-attr' can be used instead of this function."
+ (setf (helm-attr attribute-name src) value))
+
+(defun helm-add-action-to-source (name fn source &optional index)
+ "Add new action NAME linked to function FN to SOURCE.
+Function FN should be a valid function that takes one arg i.e candidate,
+argument NAME is a string that will appear in action menu
+and SOURCE should be an existing helm source already loaded.
+If INDEX is specified, action is added to the action list at INDEX,
+otherwise added at end.
+This allows users to add specific actions to an existing source
+without modifying source code."
+ (let ((actions (helm-attr 'action source 'ignorefn))
+ (new-action (list (cons name fn))))
+ (when (functionp actions)
+ (setq actions (list (cons "Default action" actions))))
+ (helm-attrset 'action
+ (if index
+ (helm-append-at-nth actions new-action index)
+ (append actions new-action))
+ source)))
+
+(defun helm-delete-action-from-source (action-or-name source)
+ "Delete ACTION-OR-NAME from SOURCE.
+ACTION-OR-NAME can either be the name of action or the symbol function
+associated to name."
+ (let* ((actions (helm-attr 'action source 'ignorefn))
+ (del-action (if (symbolp action-or-name)
+ (rassoc action-or-name actions)
+ (assoc action-or-name actions))))
+ (helm-attrset 'action (delete del-action actions) source)))
+
+(cl-defun helm-add-action-to-source-if (name fn source predicate
+ &optional (index 4) test-only)
+ "Add new action NAME linked to function FN to SOURCE.
+Action NAME will be available when the current candidate matches PREDICATE.
+This function adds an entry in the `action-transformer' attribute
+of SOURCE (or creates one if not found).
+Function PREDICATE must take one candidate as arg.
+Function FN should be a valid function that takes one arg i.e. candidate,
+argument NAME is a string that will appear in action menu
+and SOURCE should be an existing helm source already loaded.
+If INDEX is specified, action is added in action list at INDEX.
+Value of INDEX should be always >=1, default to 4.
+This allow user to add a specific `action-transformer'
+to an existing source without modifying source code.
+E.g
+Add the action \"Byte compile file async\" linked to
+function 'async-byte-compile-file to source `helm-source-find-files'
+only when predicate helm-ff-candidates-lisp-p return non-`nil':
+
+\(helm-add-action-to-source-if \"Byte compile file async\"
+ 'async-byte-compile-file
+ helm-source-find-files
+ 'helm-ff-candidates-lisp-p\)."
+ (let* ((actions (helm-attr 'action source 'ignorefn))
+ (action-transformers (helm-attr 'action-transformer source))
+ (new-action (list (cons name fn)))
+ (transformer (lambda (actions candidate)
+ (cond ((funcall predicate candidate)
+ (helm-append-at-nth
+ actions new-action index))
+ (t actions)))))
+ (when (functionp actions)
+ (helm-attrset 'action (list (cons "Default action" actions)) source))
+ (when (or (symbolp action-transformers) (functionp action-transformers))
+ (setq action-transformers (list action-transformers)))
+ (if test-only ; debug
+ (delq nil (append (list transformer) action-transformers))
+ (helm-attrset 'action-transformer
+ (helm-fast-remove-dups
+ (delq nil (append (list transformer) action-transformers))
+ :test 'equal)
+ source))))
+
+\f
+;;; Source filter
+;;
+(defun helm-set-source-filter (sources)
+ "Set the value of `helm-source-filter' to SOURCES and update.
+
+This function sets a filter for helm sources and it may be
+called while helm is running. It can be used to toggle
+displaying of sources dynamically. For example, additional keys
+can be bound into `helm-map' to display only the file-related
+results if there are too many matches from other sources and
+you're after files only:
+
+Shift+F shows only file results from some sources:
+
+\(define-key helm-map \"F\" 'helm-my-show-files-only)
+
+\(defun helm-my-show-files-only ()
+ (interactive)
+ (helm-set-source-filter '(\"File Name History\"
+ \"Files from Current Directory\")))
+
+Shift+A shows all results:
+
+\(define-key helm-map \"A\" 'helm-my-show-all)
+
+\(defun helm-my-show-all ()
+ (interactive)
+ (helm-set-source-filter nil))
+
+The -my- part is added to avoid collisions with
+existing Helm function names."
+ (with-helm-buffer
+ (let ((cur-disp-sel (helm-get-selection nil t)))
+ (set (make-local-variable 'helm-source-filter)
+ (helm--normalize-filter-sources sources))
+ (helm-log "helm-source-filter = %S" helm-source-filter)
+ ;; Use force-update to run init/update functions.
+ (helm-force-update (and (stringp cur-disp-sel)
+ (regexp-quote cur-disp-sel))))))
+
+(defun helm--normalize-filter-sources (sources)
+ (cl-loop for s in sources collect
+ (cl-typecase s
+ (symbol (assoc-default 'name (symbol-value s)))
+ (list (assoc-default 'name s))
+ (string s))))
+
+(defun helm-set-sources (sources &optional no-init no-update)
+ "Set SOURCES during `helm' invocation.
+If NO-INIT is non-`nil', skip executing init functions of SOURCES.
+If NO-UPDATE is non-`nil', skip executing `helm-update'."
+ (with-current-buffer helm-buffer
+ (setq helm-sources (helm-get-sources sources))
+ (helm-log "helm-sources = %S" helm-sources))
+ (unless no-init (helm-compute-attr-in-sources 'init))
+ (unless no-update (helm-update)))
+
+(defun helm-get-selection (&optional buffer force-display-part source)
+ "Return the currently selected item or nil.
+
+if BUFFER is nil or unspecified, use helm-buffer as default value.
+If FORCE-DISPLAY-PART is non-`nil', return the display string.
+If FORCE-DISPLAY-PART value is `withprop' the display string is returned
+with its properties."
+ (setq buffer (or buffer helm-buffer))
+ (unless (or (helm-empty-buffer-p buffer)
+ (helm-pos-header-line-p))
+ (with-current-buffer buffer
+ (let* ((disp-fn (if (eq force-display-part 'withprop)
+ 'buffer-substring
+ 'buffer-substring-no-properties))
+ (selection
+ (or (and (not force-display-part)
+ (get-text-property (overlay-start
+ helm-selection-overlay)
+ 'helm-realvalue))
+ ;; It is needed to return properties of DISP in some case,
+ ;; e.g for `helm-confirm-and-exit-minibuffer',
+ ;; so use `buffer-substring' here when 'withprop is specified.
+ (let* ((beg (overlay-start helm-selection-overlay))
+ (end (overlay-end helm-selection-overlay))
+ ;; If there is no selection at point, the
+ ;; overlay is at its initial pos, (point-min)
+ ;; (point-min), that's mean the helm-buffer
+ ;; is not empty but have no selection yet,
+ ;; this happen with grep sentinel sending an
+ ;; error message in helm-buffer when no matches.
+ (disp (unless (= beg end) (funcall disp-fn beg (1- end))))
+ (src (or source (helm-get-current-source))))
+ (helm-aif (and src disp
+ (not force-display-part)
+ (assoc-default 'display-to-real src))
+ (helm-apply-functions-from-source source it disp)
+ disp)))))
+ (unless (equal selection "")
+ (helm-log "selection = %S" selection)
+ selection)))))
+
+(defun helm-get-actions-from-current-source (&optional source)
+ "Return the associated action for the selected candidate.
+It is a function symbol (sole action) or list
+of (action-display . function)."
+ (unless (helm-empty-buffer-p (helm-buffer-get))
+ (let ((src (helm-get-current-source)))
+ (helm-aif (helm-attr 'action-transformer)
+ (helm-apply-functions-from-source
+ (or source src) it
+ (helm-attr 'action nil 'ignorefn)
+ ;; Check if the first given transformer
+ ;; returns the same set of actions for each
+ ;; candidate in marked candidates.
+ ;; If so use the car of marked to determine
+ ;; the set of actions, otherwise use the selection.
+ (if (cl-loop with marked = (helm-marked-candidates)
+ with act = (car (helm-mklist it))
+ with acts = (funcall act nil (car marked))
+ for c in marked
+ always (equal (funcall act nil c) acts))
+ (car (helm-marked-candidates))
+ (helm-get-selection nil nil src)))
+ (helm-attr 'action nil 'ignorefn)))))
+
+(defun helm-get-current-source ()
+ "Return the source for the current selection.
+Return nil when `helm-buffer' is empty."
+ (or helm-current-source
+ (with-helm-buffer
+ (or (get-text-property (point) 'helm-cur-source)
+ (progn
+ ;; This is needed to not loose selection.
+ (goto-char (overlay-start helm-selection-overlay))
+ (let ((header-pos (or (helm-get-previous-header-pos)
+ (helm-get-next-header-pos))))
+ ;; Return nil when no--candidates.
+ (when header-pos
+ (cl-loop with source-name = (save-excursion
+ (goto-char header-pos)
+ (helm-current-line-contents))
+ for source in helm-sources thereis
+ (and (equal (assoc-default 'name source) source-name)
+ source)))))))))
+
+(defun helm-buffer-is-modified (buffer)
+ "Return non-`nil' when BUFFER is modified since `helm' was invoked."
+ (let* ((buf (get-buffer buffer))
+ (key (concat (buffer-name buf) "/" (helm-attr 'name)))
+ (source-tick (or (gethash key helm-tick-hash) 0))
+ (buffer-tick (buffer-chars-modified-tick buf))
+ (modifiedp (/= source-tick buffer-tick)))
+ (puthash key buffer-tick helm-tick-hash)
+ (helm-log "buffer = %S" buffer)
+ (helm-log "modifiedp = %S" modifiedp)
+ modifiedp))
+
+(defun helm-current-buffer-is-modified ()
+ "Check if `helm-current-buffer' is modified since `helm' was invoked."
+ (helm-buffer-is-modified helm-current-buffer))
+
+(defun helm-run-after-exit (function &rest args)
+ "Execute FUNCTION with ARGS after exiting `helm'.
+The action is to call FUNCTION with arguments ARGS.
+Unlike `helm-exit-and-execute-action', this can be used
+to call non--actions functions with any ARGS or no ARGS at all.
+
+Use this on commands invoked from key-bindings, but not
+on action functions invoked as action from the action menu,
+i.e. functions called with RET."
+ (helm-kill-async-processes)
+ (helm-log "function = %S" function)
+ (helm-log "args = %S" args)
+ (helm-exit-and-execute-action
+ (lambda (_candidate)
+ (apply function args))))
+
+(defun helm-exit-and-execute-action (action)
+ "Exit current helm session and execute ACTION.
+Argument ACTION is a function called with one arg (candidate)
+and part of the actions of current source.
+
+Use this on commands invoked from key-bindings, but not
+on action functions invoked as action from the action menu,
+i.e functions called with RET."
+ ;; If ACTION is not an action available in source 'action attribute,
+ ;; return an error. This allow to remove unneeded actions from
+ ;; source that inherit actions from type, note that ACTION have to
+ ;; be bound to a symbol and not to be an anonymous action
+ ;; i.e. lambda or byte-code.
+ (let ((actions (helm-attr 'action nil t)))
+ (when actions
+ (cl-assert (or (eq action actions)
+ (rassq action actions)
+ ;; Compiled lambda
+ (byte-code-function-p action)
+ ;; Lambdas
+ (and (listp action) (functionp action)))
+ nil "No such action `%s' for this source" action)))
+ (setq helm-saved-action action)
+ (setq helm-saved-selection (or (helm-get-selection) ""))
+ (setq helm--executing-helm-action t)
+ ;; When toggling minibuffer and header-line, we want next action
+ ;; inherit this setting.
+ (helm-set-local-variable 'helm-echo-input-in-header-line
+ (with-helm-buffer helm-echo-input-in-header-line))
+ ;; Ensure next action use same display function as initial helm-buffer when
+ ;; helm-actions-inherit-frame-settings is non nil.
+ (when (and helm-actions-inherit-frame-settings
+ helm--buffer-in-new-frame-p)
+ (helm-set-local-variable 'helm-display-function
+ (with-helm-buffer helm-display-function)
+ 'helm--last-frame-parameters
+ (with-helm-buffer
+ (helm--get-frame-parameters)))
+ ;; The helm-buffer keeps `helm-display-function' and
+ ;; `helm--get-frame-parameters' values during 0.5 seconds, just
+ ;; the time to execute the possible helm action with those values.
+ ;; If no helm based action run within 0.5 seconds, the next helm
+ ;; session will have to resolve again those variable values.
+ (run-with-idle-timer 0.5 nil
+ (lambda () (helm-set-local-variable 'helm-display-function nil
+ 'helm--last-frame-parameters nil))))
+ (helm-exit-minibuffer))
+
+(defun helm--get-frame-parameters (&optional frame)
+ (cl-loop with params = (frame-parameters frame)
+ for p in helm--frame-default-attributes
+ when (assq p params) collect it))
+
+(defalias 'helm-run-after-quit 'helm-run-after-exit)
+(make-obsolete 'helm-run-after-quit 'helm-run-after-exit "1.7.7")
+(defalias 'helm-quit-and-execute-action 'helm-exit-and-execute-action)
+(make-obsolete 'helm-quit-and-execute-action 'helm-exit-and-execute-action "1.7.7")
+
+(defun helm-interpret-value (value &optional source compute)
+ "Interpret VALUE as variable, function or literal and return it.
+If VALUE is a function, call it with no arguments and return the value
+unless COMPUTE value is 'ignorefn.
+If SOURCE compute VALUE for this source.
+If VALUE is a variable, return the value.
+If VALUE is a symbol, but it is not a function or a variable, cause an error.
+Otherwise, return VALUE itself."
+ (cond ((and source (functionp value) (not (eq compute 'ignorefn)))
+ (helm-apply-functions-from-source source value))
+ ((and (functionp value) (not (eq compute 'ignorefn)))
+ (funcall value))
+ ((and (symbolp value) (boundp value))
+ (symbol-value value))
+ ((and (symbolp value) (not (functionp value)))
+ (error
+ "helm-interpret-value: Symbol must be a function or a variable"))
+ (t
+ value)))
+
+(defun helm-set-local-variable (&rest args)
+ "Bind each pair in ARGS locally to `helm-buffer'.
+
+Use this to set local vars before calling helm.
+
+When used from an init or update function
+(i.e when `helm-force-update' is running) the variables are set
+using `make-local-variable' within the `helm-buffer'.
+
+Usage: helm-set-local-variable ([VAR VALUE]...)
+Just like `setq' except that the vars are not set sequentially.
+IOW Don't use VALUE of previous VAR to set the VALUE of next VAR.
+
+\(fn VAR VALUE ...)"
+ (if helm--force-updating-p
+ (with-helm-buffer
+ (cl-loop for i on args by #'cddr
+ do (set (make-local-variable (car i)) (cadr i))))
+ (setq helm--local-variables
+ (append (cl-loop for i on args by #'cddr
+ collect (cons (car i) (cadr i)))
+ helm--local-variables))))
+
+(defun helm--set-local-variables-internal ()
+ (cl-loop for (var . val) in helm--local-variables
+ ;; If `helm-set-local-variable' is called twice or more
+ ;; on same variable use the last value entered which is
+ ;; the first on stack e.g.
+ ;; (helm-set-local-variable 'helm-foo 1)
+ ;; (helm-set-local-variable 'helm-foo 2)
+ ;; helm--local-variables =>
+ ;; '((helm-foo . 2) (helm-foo. 1))
+ ;; (helm-foo . 2) is retained and (helm-foo . 1)
+ ;; ignored.
+ unless (memq var computed)
+ do (set (make-local-variable var) val)
+ collect var into computed
+ finally (setq helm--local-variables nil)))
+
+\f
+;; API helper
+(cl-defun helm-empty-buffer-p (&optional (buffer helm-buffer))
+ "Check if BUFFER have candidates.
+Default value for BUFFER is `helm-buffer'."
+ (zerop (buffer-size (and buffer (get-buffer buffer)))))
+
+(defun helm-empty-source-p ()
+ "Check if current source contains candidates.
+This could happen when for example the last element of a source
+was deleted and the candidates list not updated."
+ (when (helm-window)
+ (with-helm-window
+ (or (helm-empty-buffer-p)
+ (and (helm-end-of-source-p)
+ (eq (point-at-bol) (point-at-eol))
+ (or
+ (save-excursion
+ (forward-line -1)
+ (helm-pos-header-line-p))
+ (bobp)))))))
+
+\f
+;; Tools
+;;
+(defun helm-apply-functions-from-source (source functions &rest args)
+ "From SOURCE apply FUNCTIONS on ARGS.
+
+This function is used to process filter functions, when filter is a
+\`filtered-candidate-transformer', we pass to ARGS candidates+source
+whereas when the filter is `candidate-transformer' we pass to ARGS
+candidates only.
+This function is used also to process functions called with no args,
+e.g. init functions, in this case it is called without ARGS.
+See `helm-process-filtered-candidate-transformer'
+\`helm-compute-attr-in-sources' and
+\`helm-process-candidate-transformer'.
+
+Arg FUNCTIONS is either a symbol or a list of functions, each function being
+applied on ARGS and called on the result of the precedent function.
+Return the result of last function call."
+ (let ((helm--source-name (assoc-default 'name source))
+ (helm-current-source source)
+ (funs (if (functionp functions) (list functions) functions)))
+ (helm-log "helm--source-name = %S" helm--source-name)
+ (helm-log "functions = %S" functions)
+ (helm-log "args = %S" args)
+ (cl-loop with result
+ for fn in funs
+ do (setq result (apply fn args))
+ when (and args (cdr funs))
+ ;; In filter functions, ARGS is a list of one or two elements where
+ ;; the first element is the list of candidates and the second
+ ;; a list containing the source.
+ ;; When more than one fn, set the candidates list to what returns
+ ;; this fn to compute the modified candidates with the next fn
+ ;; and so on.
+ do (setcar args result)
+ finally return result)))
+
+(defalias 'helm-funcall-with-source 'helm-apply-functions-from-source)
+(make-obsolete 'helm-funcall-with-source 'helm-apply-functions-from-source "2.9.7")
+
+(defun helm-compute-attr-in-sources (attr &optional sources)
+ "Call the associated function(s) to ATTR for each source if any."
+ (let ((sources (or (helm-get-sources sources)
+ ;; Fix error no buffer named *helm... by checking
+ ;; if helm-buffer exists.
+ (and (buffer-live-p (get-buffer (helm-buffer-get)))
+ ;; `helm-sources' are local to helm-buffer.
+ (with-helm-buffer helm-sources)))))
+ (when sources
+ (cl-dolist (source sources)
+ (helm-aif (assoc-default attr source)
+ (helm-apply-functions-from-source source it))))))
+
+(defalias 'helm-funcall-foreach 'helm-compute-attr-in-sources)
+(make-obsolete 'helm-funcall-foreach 'helm-compute-attr-in-sources "2.9.7")
+
+(defun helm-normalize-sources (sources)
+ "If SOURCES is only one source, make a list of one element."
+ (if (or (and sources (symbolp sources))
+ (and (listp sources) (assq 'name sources)))
+ (list sources)
+ sources))
+
+(defun helm-get-candidate-number (&optional in-current-source)
+ "Return candidates number in `helm-buffer'.
+If IN-CURRENT-SOURCE is provided return number of candidates of current source
+only."
+ (with-helm-buffer
+ (if (or (helm-empty-buffer-p)
+ (helm-empty-source-p))
+ 0
+ (save-excursion
+ (helm-aif (and in-current-source (helm-get-previous-header-pos))
+ (goto-char it)
+ (goto-char (point-min)))
+ (forward-line 1)
+ (if (helm-pos-multiline-p)
+ (cl-loop with count-multi = 1
+ while (and (not (if in-current-source
+ (save-excursion
+ (forward-line 2)
+ (or (helm-pos-header-line-p) (eobp)))
+ (eobp)))
+ (search-forward helm-candidate-separator nil t))
+ do (cl-incf count-multi)
+ finally return count-multi)
+ (cl-loop with ln = 0
+ while (not (if in-current-source
+ (or (helm-pos-header-line-p) (eobp))
+ (eobp)))
+ ;; Don't count empty lines maybe added by popup (#1370).
+ unless (or (eq (point-at-bol) (point-at-eol))
+ (helm-pos-header-line-p))
+ do (cl-incf ln)
+ do (forward-line 1) finally return ln))))))
+
+(defmacro with-helm-quittable (&rest body)
+ "If an error occurs in execution of BODY, safely quit helm."
+ (declare (indent 0) (debug t))
+ `(condition-case _v
+ (let (inhibit-quit)
+ ,@body)
+ (quit (setq quit-flag t)
+ (setq helm-quit t)
+ (exit-minibuffer)
+ (keyboard-quit)
+ ;; See comment about this in `with-local-quit'.
+ (eval '(ignore nil)))))
+\f
+;; Entry point
+;; `:allow-nest' is not in this list because it is treated before.
+(defconst helm-argument-keys
+ '(:sources :input :prompt :resume
+ :preselect :buffer :keymap :default :history))
+
+;;;###autoload
+(defun helm (&rest plist)
+ "Main function to execute helm sources.
+
+PLIST is a list like
+
+\(:key1 val1 :key2 val2 ...\)
+
+ or
+
+\(&optional sources input prompt resume preselect
+ buffer keymap default history allow-nest\).
+
+** Keywords
+
+Keywords supported:
+
+- :sources
+- :input
+- :prompt
+- :resume
+- :preselect
+- :buffer
+- :keymap
+- :default
+- :history
+- :allow-nest
+
+Extra LOCAL-VARS keywords are supported, see the \"** Other
+keywords\" section below.
+
+Basic keywords are the following:
+
+*** :sources
+
+One of the following:
+
+- List of sources
+- Symbol whose value is a list of sources
+- Alist representing a Helm source.
+ - In this case the source has no name and is referenced in
+ `helm-sources' as a whole alist.
+
+*** :input
+
+Initial input of minibuffer (temporary value of `helm-pattern')
+
+*** :prompt
+
+Minibuffer prompt. Default value is `helm--prompt'.
+
+*** :resume
+
+If t, allow resumption of the previous session of this Helm
+command, skipping initialization.
+
+If 'noresume, this instance of `helm' cannot be resumed.
+
+*** :preselect
+
+Initially selected candidate (string or regexp).
+
+*** :buffer
+
+Buffer name for this Helm session. `helm-buffer' will take this value.
+
+*** :keymap
+
+\[Obsolete]
+
+Keymap used at the start of this Helm session.
+
+It is overridden by keymaps specified in sources, and is kept
+only for backward compatibility.
+
+Keymaps should be specified in sources using the :keymap slot
+instead. See `helm-source'.
+
+This keymap is not restored by `helm-resume'.
+
+*** :default
+
+Default value inserted into the minibuffer \ with
+\\<minibuffer-local-map>\\[next-history-element].
+
+It can be a string or a list of strings, in this case
+\\<minibuffer-local-map>\\[next-history-element] cycles through
+the list items, starting with the first.
+
+If nil, `thing-at-point' is used.
+
+If `helm--maybe-use-default-as-input' is non-`nil', display is
+updated using this value, unless :input is specified, in which
+case that value is used instead.
+
+*** :history
+
+Minibuffer input, by default, is pushed to `minibuffer-history'.
+
+When an argument HISTORY is provided, input is pushed to
+HISTORY. HISTORY should be a valid symbol.
+
+*** :allow-nest
+
+Allow running this Helm command in a running Helm session.
+
+** Other keywords
+
+Other keywords are interpreted as local variables of this Helm
+session. The `helm-' prefix can be omitted. For example,
+
+\(helm :sources 'helm-source-buffers-list
+ :buffer \"*helm buffers*\"
+ :candidate-number-limit 10\)
+
+starts a Helm session with the variable
+`helm-candidate-number-limit' set to 10.
+
+** Backward compatibility
+
+For backward compatibility, positional parameters are
+supported:
+
+\(helm sources input prompt resume preselect
+ buffer keymap default history allow-nest\)
+
+However, the use of non-keyword args is deprecated.
+
+\(fn &key SOURCES INPUT PROMPT RESUME PRESELECT BUFFER KEYMAP DEFAULT HISTORY ALLOW-NEST OTHER-LOCAL-VARS)"
+ (let ((fn (cond ((or (and helm-alive-p (plist-get plist :allow-nest))
+ (and helm-alive-p (memq 'allow-nest plist)))
+ #'helm--nest)
+ ((keywordp (car plist))
+ #'helm)
+ (t #'helm-internal))))
+ (if (and helm-alive-p (eq fn #'helm))
+ (if (helm--alive-p)
+ ;; A helm session is normally running.
+ (error "Error: Trying to run helm within a running helm session")
+ ;; A helm session is already running and user jump somewhere else
+ ;; without deactivating it.
+ (with-helm-buffer
+ (prog1
+ (message "Aborting an helm session running in background")
+ ;; `helm-alive-p' will be reset in unwind-protect forms.
+ (helm-keyboard-quit))))
+ (if (keywordp (car plist))
+ ;; Parse `plist' and move not regular `helm-argument-keys'
+ ;; to `helm--local-variables', then calling helm on itself
+ ;; with normal arguments (the non--arguments-keys removed)
+ ;; will end up in [1].
+ (progn
+ (setq helm--local-variables
+ (append helm--local-variables
+ ;; Vars passed by keyword on helm call
+ ;; take precedence on same vars
+ ;; that may have been passed before helm call.
+ (helm-parse-keys plist)))
+ (apply fn (mapcar (lambda (key) (plist-get plist key))
+ helm-argument-keys)))
+ (apply fn plist))))) ; [1] fn == helm-internal.
+
+(defun helm--alive-p ()
+ "[Internal] Check if `helm' is alive.
+An `helm' session is considered alive if `helm-alive-p' value is
+non-`nil', the `helm-buffer' is visible, and cursor is in the
+minibuffer."
+ (and helm-alive-p
+ (get-buffer-window (helm-buffer-get) 'visible)
+ (minibuffer-window-active-p (minibuffer-window))
+ (minibufferp (current-buffer))))
+
+(defun helm-parse-keys (keys)
+ "Parse the KEYS arguments of `helm'.
+Return only those keys not in `helm-argument-keys', prefix them
+with \"helm\", and then convert them to an alist. This allows
+adding arguments that are not part of `helm-argument-keys', but
+are valid helm variables nevertheless. For
+example, :candidate-number-limit is bound to
+`helm-candidate-number-limit' in the source.
+
+ (helm-parse-keys '(:sources ((name . \"test\")
+ (candidates . (a b c)))
+ :buffer \"toto\"
+ :candidate-number-limit 4))
+ ==> ((helm-candidate-number-limit . 4))."
+
+ (cl-loop for (key value) on keys by #'cddr
+ for symname = (substring (symbol-name key) 1)
+ for sym = (intern (if (string-match "^helm-" symname)
+ symname
+ (concat "helm-" symname)))
+ unless (memq key helm-argument-keys)
+ collect (cons sym value)))
+
+;;; Entry point helper
+(defun helm-internal (&optional
+ any-sources any-input
+ any-prompt any-resume
+ any-preselect any-buffer
+ any-keymap any-default any-history)
+ "The internal helm function called by `helm'.
+For ANY-SOURCES ANY-INPUT ANY-PROMPT ANY-RESUME ANY-PRESELECT ANY-BUFFER and
+ANY-KEYMAP ANY-DEFAULT ANY-HISTORY See `helm'."
+ (unless helm--nested (setq helm-initial-frame (selected-frame)))
+ ;; Activate the advices.
+ ;; Advices will be available only in >=emacs-24.4, but
+ ;; allow compiling without errors on lower emacs.
+ (when (fboundp 'advice-add)
+ (advice-add 'tramp-read-passwd :around #'helm--suspend-read-passwd)
+ (advice-add 'ange-ftp-get-passwd :around #'helm--suspend-read-passwd)
+ (advice-add 'epa-passphrase-callback-function
+ :around #'helm--suspend-read-passwd)
+ ;; Ensure linum-mode is disabled in Helm buffers to preserve
+ ;; performances (Issue #1894).
+ (advice-add 'linum-on :override #'helm--advice-linum-on))
+ (helm-log (concat "[Start session] " (make-string 41 ?+)))
+ (helm-log "any-prompt = %S" any-prompt)
+ (helm-log "any-preselect = %S" any-preselect)
+ (helm-log "any-buffer = %S" any-buffer)
+ (helm-log "any-keymap = %S" any-keymap)
+ (helm-log "any-default = %S" any-default)
+ (helm-log "any-history = %S" any-history)
+ (setq helm--prompt (or any-prompt "pattern: "))
+ (let ((non-essential t)
+ ;; Prevent mouse jumping to the upper-right
+ ;; hand corner of the frame (#1538).
+ mouse-autoselect-window
+ focus-follows-mouse
+ mode-line-in-non-selected-windows
+ (input-method-verbose-flag helm-input-method-verbose-flag)
+ (helm--maybe-use-default-as-input
+ (and (null any-input)
+ (or helm--maybe-use-default-as-input ; it is let-bounded so use it.
+ (cl-loop for s in (helm-normalize-sources any-sources)
+ thereis (memq s helm-sources-using-default-as-input))))))
+ (unwind-protect
+ (condition-case-unless-debug _v
+ (let ( ;; `helm--source-name' is non-`nil'
+ ;; when `helm' is invoked by action, reset it.
+ helm--source-name
+ helm-current-source
+ helm-in-persistent-action
+ helm-quit
+ (helm-buffer (or any-buffer helm-buffer)))
+ (helm-initialize
+ any-resume any-input any-default any-sources)
+ ;; We don't display helm-buffer here to avoid popping
+ ;; up a window or a frame when exiting immediately when
+ ;; only one candidate (this avoid having the helm frame
+ ;; flashing), lets first compute candidates and if more
+ ;; than one display helm-buffer (this is done later in
+ ;; helm-read-pattern-maybe).
+ (unless helm-execute-action-at-once-if-one
+ (helm-display-buffer helm-buffer any-resume)
+ (select-window (helm-window)))
+ ;; We are now in helm-buffer.
+ (unless helm-allow-mouse
+ (helm--remap-mouse-mode 1)) ; Disable mouse bindings.
+ (add-hook 'post-command-hook 'helm--maybe-update-keymap)
+ ;; Add also to update hook otherwise keymap is not updated
+ ;; until a key is hitted (Issue #1670).
+ (add-hook 'helm-after-update-hook 'helm--maybe-update-keymap)
+ (add-hook 'post-command-hook 'helm--update-header-line)
+ (helm-log "show prompt")
+ (unwind-protect
+ (helm-read-pattern-maybe
+ any-prompt any-input any-preselect
+ any-resume any-keymap any-default any-history)
+ (helm-cleanup))
+ (prog1
+ (unless helm-quit (helm-execute-selection-action))
+ (helm-log (concat "[End session] " (make-string 41 ?-)))))
+ (quit
+ (helm-restore-position-on-quit)
+ (helm-log-run-hook 'helm-quit-hook)
+ (helm-log (concat "[End session (quit)] " (make-string 34 ?-)))
+ nil))
+ (when (fboundp 'advice-remove)
+ (advice-remove 'tramp-read-passwd #'helm--suspend-read-passwd)
+ (advice-remove 'ange-ftp-get-passwd #'helm--suspend-read-passwd)
+ (advice-remove 'epa-passphrase-callback-function #'helm--suspend-read-passwd)
+ (advice-remove 'linum-on #'helm--advice-linum-on))
+ (helm-log "helm-alive-p = %S" (setq helm-alive-p nil))
+ (helm--remap-mouse-mode -1) ; Reenable mouse bindings.
+ (setq helm-alive-p nil)
+ ;; Prevent error "No buffer named *helm*" triggered by
+ ;; `helm-set-local-variable'.
+ (setq helm--force-updating-p nil)
+ (setq helm--buffer-in-new-frame-p nil)
+ ;; Reset helm-pattern so that lambda's using it
+ ;; before running helm will not start with its old value.
+ (setq helm-pattern "")
+ (setq helm--ignore-errors nil)
+ (helm-log-save-maybe))))
+
+(defun helm--advice-linum-on ()
+ (unless (or (minibufferp)
+ (string-match "\\`\\*helm" (buffer-name))
+ (and (daemonp) (null (frame-parameter nil 'client))))
+ (linum-mode 1)))
+\f
+;;; Helm resume
+;;
+;;
+(defun helm-resume (arg)
+ "Resume a previous `helm' session.
+Call with a prefix arg to choose among existing helm
+buffers (sessions). When calling from lisp, specify a buffer-name
+as a string with ARG."
+ (interactive "P")
+ (let (any-buffer
+ cur-dir
+ narrow-pos
+ (helm-full-frame (default-value 'helm-full-frame))
+ sources)
+ (if arg
+ (if (and (stringp arg) (bufferp (get-buffer arg)))
+ (setq any-buffer arg)
+ (setq any-buffer (helm-resume-select-buffer)))
+ (setq any-buffer helm-last-buffer))
+ (cl-assert any-buffer nil
+ "helm-resume: No helm buffers found to resume")
+ (setq sources (buffer-local-value
+ 'helm-sources (get-buffer any-buffer)))
+ ;; Reset `cursor-type' to nil as it have been set to t
+ ;; when quitting previous session.
+ (with-current-buffer any-buffer (setq cursor-type nil))
+ (setq helm-full-frame (buffer-local-value
+ 'helm-full-frame (get-buffer any-buffer)))
+ (setq cur-dir (buffer-local-value
+ 'default-directory (get-buffer any-buffer)))
+ (setq helm-saved-selection nil
+ helm-saved-action nil)
+ (unless (buffer-live-p helm-current-buffer)
+ ;; `helm-current-buffer' may have been killed.
+ (setq helm-current-buffer (current-buffer)))
+ (helm-aif (with-current-buffer any-buffer
+ helm--current-buffer-narrowed)
+ (progn
+ (set-buffer (car it))
+ (setq narrow-pos (cdr it))))
+ (save-restriction
+ (when narrow-pos (apply #'narrow-to-region narrow-pos))
+ ;; Restart with same `default-directory' value this session
+ ;; was initially started with.
+ (with-helm-default-directory cur-dir
+ (unwind-protect
+ (helm
+ :sources sources
+ :input (buffer-local-value 'helm-input-local (get-buffer any-buffer))
+ :prompt (buffer-local-value 'helm--prompt (get-buffer any-buffer))
+ :resume t
+ :buffer any-buffer)
+ (run-hook-with-args 'helm-resume-after-hook sources))))))
+
+(defun helm-resume-previous-session-after-quit (arg)
+ "Resume previous helm session within a running helm."
+ (interactive "p")
+ (with-helm-alive-p
+ (if (> (length helm-buffers) arg)
+ (helm-run-after-exit (lambda () (helm-resume (nth arg helm-buffers))))
+ (message "No previous helm sessions available for resuming!"))))
+(put 'helm-resume-previous-session-after-quit 'helm-only t)
+
+(defun helm-resume-list-buffers-after-quit ()
+ "List resumable helm buffers within running helm."
+ (interactive)
+ (with-helm-alive-p
+ (if (> (length helm-buffers) 0)
+ (helm-run-after-exit (lambda () (helm-resume t)))
+ (message "No previous helm sessions available for resuming!"))))
+(put 'helm-resume-list-buffers-after-quit 'helm-only t)
+
+(defun helm-resume-p (any-resume)
+ "Whether current helm session is resumed or not."
+ (eq any-resume t))
+
+(defun helm-resume-select-buffer ()
+ "Select an `helm-buffer' in `helm-buffers' list to resume a helm session.
+Return nil if no `helm-buffer' found."
+ (when helm-buffers
+ (or (helm :sources (helm-build-sync-source "Resume helm buffer"
+ :candidates helm-buffers)
+ :resume 'noresume
+ :buffer "*helm resume*")
+ (keyboard-quit))))
+
+;;;###autoload
+(defun helm-cycle-resume ()
+ "Cycle in `helm-buffers' list and resume when waiting more than 1.2s."
+ (interactive)
+ (cl-assert (and helm-buffers helm-last-buffer)
+ nil "No helm buffers to resume")
+ ;; Setup a new iterator only on first hit on
+ ;; `helm-run-cycle-resume', subsequents hits should reuse same
+ ;; iterator.
+ (unless (and (eq last-command 'helm-cycle-resume)
+ helm--cycle-resume-iterator)
+ (setq helm--cycle-resume-iterator
+ (helm-iter-sub-next-circular
+ helm-buffers helm-last-buffer :test 'equal)))
+ (helm--resume-or-iter))
+
+(defun helm--resume-or-iter (&optional from-helm)
+ (message "Resuming helm buffer `%s'" helm-last-buffer)
+ (if (sit-for helm-cycle-resume-delay)
+ ;; Delay expire, run helm-resume.
+ (if from-helm
+ (helm-run-after-exit (lambda () (helm-resume helm-last-buffer)))
+ (helm-resume helm-last-buffer))
+ ;; key pressed before delay, cycle.
+ (unless from-helm ; cycling to next item already done.
+ (message "Resuming helm buffer `%s'"
+ (setq helm-last-buffer
+ (helm-iter-next helm--cycle-resume-iterator))))))
+
+(defun helm-run-cycle-resume ()
+ "Same as `helm-cycle-resume' but intended to be called only from helm."
+ (interactive)
+ (when (cdr helm-buffers) ; only one session registered.
+ ;; Setup a new iterator only on first hit on
+ ;; `helm-run-cycle-resume', subsequents hits should reuse same
+ ;; iterator.
+ (unless (and (eq last-command 'helm-run-cycle-resume)
+ helm--cycle-resume-iterator)
+ (setq helm--cycle-resume-iterator
+ (helm-iter-sub-next-circular
+ helm-buffers helm-last-buffer :test 'equal)))
+ ;; start at next buffer as we already are at `helm-last-buffer'.
+ (setq helm-last-buffer
+ (helm-iter-next helm--cycle-resume-iterator))
+ (helm--resume-or-iter 'from-helm)))
+(put 'helm-run-cycle-resume 'helm-only t)
+
+\f
+;;;###autoload
+(defun helm-other-buffer (any-sources any-buffer)
+ "Simplified `helm' interface with other `helm-buffer'.
+Call `helm' only with ANY-SOURCES and ANY-BUFFER as args."
+ (helm :sources any-sources :buffer any-buffer))
+
+;;; Nested sessions
+;;
+;;
+(defun helm--nest (&rest same-as-helm)
+ "[internal]Allows calling `helm' within a running helm session.
+
+Arguments SAME-AS-HELM are the same as `helm'.
+
+Don't use this directly, use instead `helm' with the keyword
+:allow-nest.
+
+\(fn &key SOURCES INPUT PROMPT RESUME PRESELECT BUFFER KEYMAP DEFAULT HISTORY OTHER-LOCAL-VARS)"
+ (with-helm-window
+ (let ((orig-helm-current-buffer helm-current-buffer)
+ (orig-helm-buffer helm-buffer)
+ (orig-helm--prompt helm--prompt)
+ (orig-helm-sources helm-sources)
+ (orig-helm--in-fuzzy helm--in-fuzzy)
+ (orig-helm--display-frame helm--buffer-in-new-frame-p)
+ (orig-helm-last-frame-or-window-configuration
+ helm-last-frame-or-window-configuration)
+ (orig-one-window-p helm-onewindow-p)
+ (helm--nested t))
+ ;; FIXME Using helm-full-frame here allow showing the new
+ ;; helm-buffer in the same window as old helm-buffer, why?
+ (helm-set-local-variable 'helm-full-frame t)
+ (unwind-protect
+ (let (helm-current-position
+ helm-current-buffer
+ helm-pattern
+ (helm-buffer (or (cl-getf same-as-helm :buffer)
+ (nth 5 same-as-helm)
+ "*Helm*"))
+ (enable-recursive-minibuffers t))
+ (setq helm-sources nil)
+ (apply #'helm same-as-helm))
+ (with-current-buffer orig-helm-buffer
+ (setq helm-sources orig-helm-sources)
+ (setq helm--nested nil)
+ (setq helm--buffer-in-new-frame-p orig-helm--display-frame)
+ (setq helm-alive-p t) ; Nested session set this to nil on exit.
+ (setq helm-buffer orig-helm-buffer)
+ (setq helm-full-frame nil)
+ (setq helm--prompt orig-helm--prompt)
+ (setq helm--in-fuzzy orig-helm--in-fuzzy)
+ (helm-initialize-overlays helm-buffer)
+ (unless (helm-empty-buffer-p) (helm-mark-current-line t))
+ (setq helm-last-frame-or-window-configuration
+ orig-helm-last-frame-or-window-configuration)
+ (setq cursor-type nil)
+ (setq helm-current-buffer orig-helm-current-buffer)
+ (setq helm-onewindow-p orig-one-window-p)
+ ;; Be sure advices, hooks, and local modes keep running.
+ (if (fboundp 'advice-add)
+ (progn
+ (advice-add 'tramp-read-passwd
+ :around #'helm--suspend-read-passwd)
+ (advice-add 'ange-ftp-get-passwd
+ :around #'helm--suspend-read-passwd)
+ (advice-add 'epa-passphrase-callback-function
+ :around #'helm--suspend-read-passwd))
+ (ad-activate 'tramp-read-passwd)
+ (ad-activate 'ange-ftp-get-passwd))
+ (unless helm-allow-mouse
+ (helm--remap-mouse-mode 1))
+ (unless (cl-loop for h in post-command-hook
+ thereis (memq h '(helm--maybe-update-keymap
+ helm--update-header-line)))
+ (add-hook 'post-command-hook 'helm--maybe-update-keymap)
+ (add-hook 'post-command-hook 'helm--update-header-line))
+ (helm-display-mode-line (helm-get-current-source)))))))
+
+\f
+;;; Accessors
+;;
+(defun helm-current-position (save-or-restore)
+ "Save or restore current position in `helm-current-buffer'.
+Argument SAVE-OR-RESTORE is either save or restore."
+ (cl-case save-or-restore
+ (save
+ (helm-log "Save position at %S" (cons (point) (window-start)))
+ (setq helm-current-position (cons (point) (window-start))))
+ (restore
+ ;; Maybe `helm-current-buffer' have been deleted
+ ;; during helm session so check if it is here
+ ;; otherwise position in underlying buffer will be lost.
+ (when (get-buffer-window helm-current-buffer 'visible)
+ (helm-log "Restore position at %S in buffer %s"
+ helm-current-position
+ (buffer-name (current-buffer)))
+ (goto-char (car helm-current-position))
+ ;; Fix this position with the NOFORCE arg of `set-window-start'
+ ;; otherwise, if there is some other buffer than `helm-current-buffer'
+ ;; one, position will be lost.
+ (set-window-start (selected-window) (cdr helm-current-position) t)))))
+
+
+(defun helm-frame-or-window-configuration (save-or-restore)
+ "Save or restore last frame or window configuration.
+Argument SAVE-OR-RESTORE is either save or restore of window or
+frame configuration as per `helm-save-configuration-functions'."
+ (helm-log "helm-save-configuration-functions = %S"
+ helm-save-configuration-functions)
+ (let ((window-persistent-parameters (append '((no-other-window . t))
+ window-persistent-parameters)))
+ (cl-case save-or-restore
+ (save (setq helm-last-frame-or-window-configuration
+ (funcall (cdr helm-save-configuration-functions))))
+ (restore (funcall (car helm-save-configuration-functions)
+ helm-last-frame-or-window-configuration)
+ ;; Restore frame focus.
+ ;; This is needed for minibuffer own-frame config
+ ;; when recursive minibuffers are in use.
+ ;; e.g M-: + helm-minibuffer-history.
+ (cl-letf ((frame (if (minibufferp helm-current-buffer)
+ (selected-frame)
+ (last-nonminibuffer-frame)))
+ ;; This is a workaround, because the i3 window
+ ;; manager developers are refusing to fix their
+ ;; broken timestamp and event handling.
+ ;;
+ ;; We basically just disable the part of
+ ;; select-frame-set-input-focus that would call
+ ;; XSetInputFocus in Xlib (x-focus-frame), that
+ ;; resets a timestamp in the xserver which the i3
+ ;; developers fail to notice.
+ ;;
+ ;; Since they don't know about the new timestamp,
+ ;; their keyboard handling can break after a helm
+ ;; user quits emacs, as reported in #1641.
+ ;;
+ ;; Fortunately for us, we really don't need this
+ ;; XSetInputFocus call, since we already have focus
+ ;; for Emacs, the user is just using helm! We call
+ ;; select-frame-set-input-focus for the other
+ ;; side-effects, not for x-focus-frame.
+ ((symbol-function 'x-focus-frame) #'ignore))
+ (select-frame-set-input-focus frame))))))
+
+(defun helm-split-window-default-fn (window)
+ "Default function to split windows before displaying `helm-buffer'.
+
+It is used as default value for
+`helm-split-window-preferred-function' which is then the let-bounded
+value of `split-window-preferred-function' in `helm-display-buffer'.
+When `helm-display-function' which default to
+`helm-default-display-buffer' is called from `helm-display-buffer' the
+value of `split-window-preferred-function' will be used by `display-buffer'."
+ (let (split-width-threshold)
+ (if (and (fboundp 'window-in-direction)
+ ;; Don't try to split when starting in a minibuffer
+ ;; e.g M-: and try to use helm-show-kill-ring.
+ (not (minibufferp helm-current-buffer)))
+ (if (or (one-window-p t)
+ helm-split-window-inside-p)
+ (split-window
+ (selected-window) nil (if (eq helm-split-window-default-side 'other)
+ 'below helm-split-window-default-side))
+ ;; If more than one window reuse one of them.
+ (cl-case helm-split-window-default-side
+ (left (or (helm-window-in-direction 'left)
+ (helm-window-in-direction 'above)
+ (selected-window)))
+ (above (or (helm-window-in-direction 'above)
+ (helm-window-in-direction 'left)
+ (selected-window)))
+ (right (or (helm-window-in-direction 'right)
+ (helm-window-in-direction 'below)
+ (selected-window)))
+ (below (or (helm-window-in-direction 'below)
+ (helm-window-in-direction 'right)
+ (selected-window)))
+ (same (selected-window))
+ (other (other-window-for-scrolling))
+ (t (or (window-next-sibling) (selected-window)))))
+ (split-window-sensibly window))))
+
+(defun helm-window-in-direction (direction)
+ "Same as `window-in-direction' but check if window is dedicated."
+ (helm-aif (window-in-direction direction)
+ (and (not (window-dedicated-p it)) it)))
+
+\f
+;;; Display helm buffer
+;;
+;;
+(defun helm-resolve-display-function (com)
+ "Decide which display function use according to `helm-commands-using-frame'.
+
+The `helm-display-function' buffer local value takes precedence on
+`helm-commands-using-frame'.
+If `helm-initial-frame' has no minibuffer, use
+`helm-display-buffer-in-own-frame' function.
+Fallback to global value of `helm-display-function' when no local
+value found and current command is not in `helm-commands-using-frame'."
+ (or (with-helm-buffer helm-display-function)
+ (and (or (memq com helm-commands-using-frame)
+ (and helm-use-frame-when-more-than-two-windows
+ (null helm--nested)
+ (> (length (window-list)) 2))
+ ;; Frame parameter is unreliable for minibuffer on emacs-26.
+ (null (member helm-initial-frame (minibuffer-frame-list))))
+ #'helm-display-buffer-in-own-frame)
+ (default-value 'helm-display-function)))
+
+(defun helm-display-buffer (buffer &optional resume)
+ "Display BUFFER.
+
+The function used to display `helm-buffer' by calling
+`helm-display-function' which split window with
+`helm-split-window-preferred-function'."
+ (let ((split-window-preferred-function
+ helm-split-window-preferred-function)
+ (helm-split-window-default-side
+ (if (and (not helm-full-frame)
+ helm-reuse-last-window-split-state)
+ (cond ((eq helm-split-window-default-side 'same) 'same)
+ ((eq helm-split-window-default-side 'other) 'other)
+ (helm--window-side-state)
+ (t helm-split-window-default-side))
+ helm-split-window-default-side))
+ (disp-fn (with-current-buffer buffer
+ (helm-resolve-display-function
+ (if helm-actions-inherit-frame-settings
+ (helm-this-command) this-command)))))
+ (prog1
+ (funcall disp-fn buffer (or (helm-resume-p resume)
+ (and helm-actions-inherit-frame-settings
+ helm--executing-helm-action)))
+ (with-helm-buffer (setq-local helm-display-function disp-fn))
+ (setq helm-onewindow-p (one-window-p t))
+ ;; Don't allow other-window and friends switching out of minibuffer.
+ (when helm-prevent-escaping-from-minibuffer
+ (helm-prevent-switching-other-window)))))
+
+(cl-defun helm-prevent-switching-other-window (&key (enabled t))
+ "Allow setting `no-other-window' parameter for all windows.
+Arg ENABLE is the value of `no-other-window' window property."
+ (walk-windows
+ (lambda (w)
+ (unless (window-dedicated-p w)
+ (set-window-parameter w 'no-other-window enabled)))
+ 0))
+
+(defun helm-default-display-buffer (buffer &optional _resume)
+ "Default function to display `helm-buffer' BUFFER.
+
+It is the default value of `helm-display-function'
+It uses `switch-to-buffer' or `display-buffer' depending on the
+value of `helm-full-frame' or `helm-split-window-default-side'."
+ (let (pop-up-frames)
+ (if (or (buffer-local-value 'helm-full-frame (get-buffer buffer))
+ (and (eq helm-split-window-default-side 'same)
+ (one-window-p t)))
+ (progn (and (not (minibufferp helm-current-buffer))
+ (delete-other-windows))
+ (switch-to-buffer buffer))
+ (when (and (or helm-always-two-windows helm-autoresize-mode)
+ (not (eq helm-split-window-default-side 'same))
+ (not (minibufferp helm-current-buffer))
+ (not helm-split-window-inside-p))
+ (delete-other-windows))
+ (display-buffer
+ buffer `(,helm-default-display-buffer-functions
+ . ,(append helm-default-display-buffer-alist
+ `((window-height . ,helm-display-buffer-default-height)
+ (window-width . ,helm-display-buffer-default-width)))))
+ (helm-log-run-hook 'helm-window-configuration-hook))))
+
+(defun helm-display-buffer-in-own-frame (buffer &optional resume)
+ "Display helm buffer BUFFER in a separate frame.
+
+Function suitable for `helm-display-function',
+`helm-completion-in-region-display-function'
+and/or `helm-show-completion-default-display-function'.
+
+See `helm-display-buffer-height' and `helm-display-buffer-width' to
+configure frame size.
+
+Note that this feature is available only with emacs-25+."
+ (cl-assert (and (fboundp 'window-absolute-pixel-edges)
+ (fboundp 'frame-geometry))
+ nil "Helm buffer in own frame is only available starting at emacs-25+")
+ (if (not (display-graphic-p))
+ ;; Fallback to default when frames are not usable.
+ (helm-default-display-buffer buffer)
+ (setq helm--buffer-in-new-frame-p t)
+ (let* ((pos (window-absolute-pixel-position))
+ (half-screen-size (/ (display-pixel-height x-display-name) 2))
+ (frame-info (frame-geometry))
+ (prmt-size (length helm--prompt))
+ (line-height (frame-char-height))
+ (default-frame-alist
+ (if resume
+ (buffer-local-value 'helm--last-frame-parameters
+ (get-buffer buffer))
+ `((width . ,helm-display-buffer-width)
+ (height . ,helm-display-buffer-height)
+ (tool-bar-lines . 0)
+ (left . ,(- (car pos)
+ (* (frame-char-width)
+ (if (< (- (point) (point-at-bol)) prmt-size)
+ (- (point) (point-at-bol))
+ prmt-size))))
+ ;; Try to put frame at the best possible place.
+ ;; Frame should be below point if enough
+ ;; place, otherwise above point and
+ ;; current line should not be hidden
+ ;; by helm frame.
+ (top . ,(if (> (cdr pos) half-screen-size)
+ ;; Above point
+ (- (cdr pos)
+ ;; add 2 lines to make sure there is always a gap
+ (* (+ helm-display-buffer-height 2) line-height)
+ ;; account for title bar height too
+ (cddr (assq 'title-bar-size frame-info)))
+ ;; Below point
+ (+ (cdr pos) line-height)))
+ (title . "Helm")
+ (undecorated . ,helm-use-undecorated-frame-option)
+ (vertical-scroll-bars . nil)
+ (menu-bar-lines . 0)
+ (fullscreen . nil)
+ (visibility . ,(null helm-display-buffer-reuse-frame))
+ (minibuffer . t))))
+ display-buffer-alist)
+ ;; Display minibuffer above or below only in initial session,
+ ;; not on a session triggered by action, this way if user have
+ ;; toggled minibuffer and header-line manually she keeps this
+ ;; setting in next action.
+ (unless (or helm--executing-helm-action resume)
+ ;; Add the hook inconditionally, if
+ ;; helm-echo-input-in-header-line is nil helm-hide-minibuffer-maybe
+ ;; will have anyway no effect so no need to remove the hook.
+ (add-hook 'helm-minibuffer-set-up-hook 'helm-hide-minibuffer-maybe)
+ (with-helm-buffer
+ (setq-local helm-echo-input-in-header-line
+ (not (> (cdr pos) half-screen-size)))))
+ (helm-display-buffer-popup-frame buffer default-frame-alist)
+ ;; When frame size have been modified manually by user restore
+ ;; it to default value unless resuming or not using
+ ;; `helm-display-buffer-reuse-frame'.
+ ;; This have to be done AFTER raising the frame otherwise
+ ;; minibuffer visibility is lost until next session.
+ (unless (or resume (not helm-display-buffer-reuse-frame))
+ (set-frame-size helm-popup-frame
+ helm-display-buffer-width
+ helm-display-buffer-height)))
+ (helm-log-run-hook 'helm-window-configuration-hook)))
+
+(defun helm-display-buffer-popup-frame (buffer frame-alist)
+ (if helm-display-buffer-reuse-frame
+ (let* ((x (cdr (assoc 'left frame-alist)))
+ (y (cdr (assoc 'top frame-alist))))
+ (unless (and helm-popup-frame
+ (frame-live-p helm-popup-frame))
+ (setq helm-popup-frame (make-frame frame-alist)))
+ (select-frame helm-popup-frame)
+ (set-frame-position helm-popup-frame x y)
+ (switch-to-buffer buffer)
+ (select-frame-set-input-focus helm-popup-frame t))
+ ;; If user have changed `helm-display-buffer-reuse-frame' to nil
+ ;; maybe kill the frame.
+ (when (and helm-popup-frame
+ (frame-live-p helm-popup-frame))
+ (delete-frame helm-popup-frame))
+ (display-buffer
+ buffer '(display-buffer-pop-up-frame . nil))))
+
+;; Ensure to quit helm when user delete helm frame manually.
+;; If user deletes another frame keep session running.
+(defun helm--delete-frame-function (frame)
+ (when (and helm-alive-p
+ ;; FRAME is handling helm-buffer
+ (get-buffer-window helm-buffer frame))
+ (helm-keyboard-quit)))
+(add-hook 'delete-frame-functions 'helm--delete-frame-function)
+\f
+;;; Initialize
+;;
+(defun helm-get-sources (sources)
+ "Transform each element of SOURCES in alist.
+Returns the resulting list."
+ (when sources
+ (mapcar (lambda (source)
+ (if (listp source)
+ source (symbol-value source)))
+ (helm-normalize-sources sources))))
+
+(defun helm-initialize (any-resume any-input any-default any-sources)
+ "Start initialization of `helm' session.
+For ANY-RESUME ANY-INPUT ANY-DEFAULT and ANY-SOURCES See `helm'."
+ (helm-log "start initialization: any-resume=%S any-input=%S"
+ any-resume any-input)
+ (helm-frame-or-window-configuration 'save)
+ (let ((sources (helm-get-sources any-sources)))
+ (setq helm--in-fuzzy
+ (cl-loop for s in sources
+ for matchfns = (helm-match-functions s)
+ for searchfns = (helm-search-functions s)
+ when (or (memq 'helm-fuzzy-match matchfns)
+ (memq 'helm-fuzzy-search searchfns))
+ return t))
+ (helm-log "sources = %S" sources)
+ (helm-set-local-variable 'helm-sources sources)
+ ;; Once `helm-buffer' is created `helm-sources' will be a local
+ ;; variable which value is a list of alists.
+ (helm-current-position 'save)
+ (if (helm-resume-p any-resume)
+ (helm-initialize-overlays (helm-buffer-get))
+ (helm-initial-setup any-default sources))
+ (setq helm-alive-p t)
+ (unless (eq any-resume 'noresume)
+ (helm--push-and-remove-dups helm-buffer 'helm-buffers)
+ (setq helm-last-buffer helm-buffer))
+ (when any-input
+ (setq helm-input any-input
+ helm-pattern any-input)
+ (helm--fuzzy-match-maybe-set-pattern))
+ ;; If a `resume' attribute is present `helm-compute-attr-in-sources'
+ ;; will run its function.
+ (when (helm-resume-p any-resume)
+ (helm-compute-attr-in-sources 'resume))
+ (helm-log "end initialization")))
+
+(defun helm-initialize-overlays (buffer)
+ "Initialize helm overlays in BUFFER."
+ (helm-log "overlay setup")
+ (if helm-selection-overlay
+ ;; make sure the overlay belongs to the helm buffer if
+ ;; it's newly created
+ (move-overlay helm-selection-overlay (point-min) (point-min)
+ (get-buffer buffer))
+
+ (setq helm-selection-overlay
+ (make-overlay (point-min) (point-min) (get-buffer buffer)))
+ (overlay-put helm-selection-overlay 'face 'helm-selection)
+ (overlay-put helm-selection-overlay 'priority 1)))
+
+(defun helm-restore-position-on-quit ()
+ "Restore position in `helm-current-buffer' when quitting."
+ (helm-current-position 'restore))
+
+(defun helm--push-and-remove-dups (elm sym)
+ "Move ELM of SYM value on top and set SYM to this new value."
+ (set sym (cons elm (delete elm (symbol-value sym)))))
+
+(defun helm--current-buffer ()
+ "[internal] Return `current-buffer' BEFORE `helm-buffer' is initialized.
+Note that it returns the minibuffer in use after helm has started
+and is intended for `helm-initial-setup'. To get the buffer where
+helm was started, use `helm-current-buffer' instead."
+ (if (minibuffer-window-active-p (minibuffer-window))
+ ;; If minibuffer is active be sure to use it's buffer
+ ;; as `helm-current-buffer', this allow to use helm
+ ;; from an already active minibuffer (M-: etc...)
+ (window-buffer (active-minibuffer-window))
+ ;; Fix Issue #456
+ ;; Use this instead of `current-buffer' to ensure
+ ;; helm session started in helm-mode from a completing-read
+ ;; Use really the buffer where we started and not the one
+ ;; where the completing-read is wrapped. i.e
+ ;; (with-current-buffer SOME-OTHER-BUFFER (completing-read [...])
+ (window-buffer (with-selected-window (minibuffer-window)
+ (minibuffer-selected-window)))))
+
+(defun helm--run-init-hooks (hook sources)
+ "Run after and before init hooks local to source.
+See :after-init-hook and :before-init-hook in `helm-source'."
+ (cl-loop with sname = (cl-ecase hook
+ (before-init-hook "h-before-init-hook")
+ (after-init-hook "h-after-init-hook"))
+ with h = (cl-gensym sname)
+ for s in sources
+ for hv = (assoc-default hook s)
+ if (and hv (not (symbolp hv)))
+ do (set h hv)
+ and do (helm-log-run-hook h)
+ else do (helm-log-run-hook hv)))
+
+(defun helm-initial-setup (any-default sources)
+ "Initialize helm settings and set up the helm buffer."
+ ;; Run global hook.
+ (helm-log-run-hook 'helm-before-initialize-hook)
+ ;; Run local source hook.
+ (helm--run-init-hooks 'before-init-hook sources)
+ ;; For initialization of helm locals vars that need
+ ;; a value from current buffer, it is here.
+ (helm-set-local-variable 'current-input-method current-input-method)
+ (setq helm-current-prefix-arg nil
+ helm-saved-action nil
+ helm-saved-selection nil
+ helm-suspend-update-flag nil
+ ;; Ensure this is called BEFORE selecting helm-window.
+ helm-current-buffer (helm--current-buffer)
+ helm-buffer-file-name buffer-file-name
+ helm-issued-errors nil
+ helm-saved-current-source nil)
+ (when (and (with-helm-current-buffer
+ (and (buffer-narrowed-p)
+ (use-region-p)))
+ (not helm--nested))
+ (helm-set-local-variable 'helm--current-buffer-narrowed
+ (list (current-buffer)
+ (region-beginning) (region-end))))
+ (unless (and (or helm-split-window-state
+ helm--window-side-state)
+ helm-reuse-last-window-split-state)
+ (setq helm-split-window-state
+ (if (or (null split-width-threshold)
+ (and (integerp split-width-threshold)
+ (>= split-width-threshold (+ (frame-width) 4))))
+ 'vertical 'horizontal))
+ (setq helm--window-side-state
+ (or helm-split-window-default-side 'below)))
+ ;; Call the init function for sources where appropriate
+ (helm-compute-attr-in-sources 'init sources)
+ (setq helm-pattern (or (and helm--maybe-use-default-as-input
+ (or (if (listp any-default)
+ (car any-default) any-default)
+ (with-helm-current-buffer
+ (thing-at-point 'symbol))))
+ ""))
+ (setq helm-input "")
+ (clrhash helm-candidate-cache)
+ (helm-create-helm-buffer)
+ (helm-clear-visible-mark)
+ ;; Run global hook.
+ (helm-log-run-hook 'helm-after-initialize-hook)
+ ;; Run local source hook.
+ (helm--run-init-hooks 'after-init-hook sources))
+
+(define-derived-mode helm-major-mode
+ fundamental-mode "Hmm"
+ "[Internal] Provide major-mode name in helm buffers.
+Unuseful when used outside helm, don't use it.")
+(put 'helm-major-mode 'mode-class 'special)
+(put 'helm-major-mode 'helm-only t)
+
+(defun helm-create-helm-buffer ()
+ "Create and setup `helm-buffer'."
+ (let ((root-dir default-directory)
+ (inhibit-read-only t))
+ (with-current-buffer (get-buffer-create helm-buffer)
+ (helm-log "Enabling major-mode %S" major-mode)
+ (helm-log "kill local variables: %S" (buffer-local-variables))
+ (kill-all-local-variables)
+ (helm-major-mode)
+ (set (make-local-variable 'buffer-read-only) nil)
+ (buffer-disable-undo)
+ (erase-buffer)
+ (set (make-local-variable 'helm-map) helm-map)
+ (set (make-local-variable 'helm-source-filter) nil)
+ (make-local-variable 'helm-sources)
+ (set (make-local-variable 'helm-display-function) nil)
+ (set (make-local-variable 'helm-selection-point) nil)
+ (set (make-local-variable 'scroll-margin)
+ (if helm-display-source-at-screen-top
+ 0 helm-completion-window-scroll-margin))
+ (set (make-local-variable 'default-directory) root-dir)
+ (set (make-local-variable 'helm-marked-candidates) nil)
+ (set (make-local-variable 'helm--prompt) helm--prompt)
+ (helm-initialize-persistent-action)
+ (helm-log "helm-display-function = %S" helm-display-function)
+ (helm-log "helm--local-variables = %S" helm--local-variables)
+ (helm--set-local-variables-internal)
+ (setq truncate-lines helm-truncate-lines) ; already local.
+ (setq cursor-type nil))
+ (helm-initialize-overlays helm-buffer)
+ (get-buffer helm-buffer)))
+
+(define-minor-mode helm--minor-mode
+ "[INTERNAL] Enable keymap in helm minibuffer.
+Since this mode has no effect when run outside of helm context,
+please don't use it outside helm.
+
+\\{helm-map}"
+ :group 'helm
+ :keymap (and helm-alive-p helm-map)
+ (unless helm-alive-p (setq helm--minor-mode nil)))
+(put 'helm--minor-mode 'helm-only t)
+
+(defun helm--reset-default-pattern ()
+ (setq helm-pattern "")
+ (setq helm--maybe-use-default-as-input nil))
+
+(defun helm-read-pattern-maybe (any-prompt any-input
+ any-preselect any-resume any-keymap
+ any-default any-history)
+ "Read pattern with prompt ANY-PROMPT and initial input ANY-INPUT.
+For ANY-PRESELECT ANY-RESUME ANY-KEYMAP ANY-DEFAULT ANY-HISTORY, See `helm'."
+ (with-helm-buffer
+ (if (and (helm-resume-p any-resume)
+ ;; When no source, helm-buffer is empty
+ ;; or contain non--candidate lines (e.g grep exit status)
+ (helm-get-current-source))
+ (helm-mark-current-line t)
+ (helm-update any-preselect))
+ (let* ((src (helm-get-current-source))
+ (src-keymap (assoc-default 'keymap src))
+ (hist (or (and any-history (symbolp any-history) any-history)
+ ;; Needed for resuming.
+ (assoc-default 'history src)))
+ (timer nil)
+ blink-matching-paren
+ (resize-mini-windows (and (null helm-echo-input-in-header-line)
+ resize-mini-windows))
+ (first-src (car helm-sources))
+ (source-process-p (or (assq 'candidates-process src)
+ (assq 'candidates-process first-src))))
+ (helm-log "helm-get-candidate-number => %S"
+ (helm-get-candidate-number))
+ (helm-log "helm-execute-action-at-once-if-one = %S"
+ helm-execute-action-at-once-if-one)
+ (helm-log "helm-quit-if-no-candidate = %S" helm-quit-if-no-candidate)
+ (when (and src (helm-resume-p any-resume))
+ (helm-display-mode-line src))
+ ;; Reset `helm-pattern' and update
+ ;; display if no result found with precedent value of `helm-pattern'
+ ;; unless `helm-quit-if-no-candidate' is non-`nil', in this case
+ ;; Don't force update with an empty pattern.
+ ;; Reset also `helm--maybe-use-default-as-input' as this checking
+ ;; happen only on startup.
+ (when helm--maybe-use-default-as-input
+ ;; Store value of `default' temporarily here waiting next update
+ ;; to allow actions like helm-moccur-action matching pattern
+ ;; at the place it jump to.
+ (setq helm-input helm-pattern)
+ (if source-process-p
+ ;; Reset pattern to next update.
+ (with-helm-after-update-hook
+ (helm--reset-default-pattern))
+ ;; Reset pattern right now.
+ (helm--reset-default-pattern))
+ ;; Ensure force-update when no candidates
+ ;; when we start with an empty pattern.
+ (and (helm-empty-buffer-p)
+ (null helm-quit-if-no-candidate)
+ (helm-force-update)))
+ ;; Handle `helm-execute-action-at-once-if-one' and
+ ;; `helm-quit-if-no-candidate' now.
+ (cond ((and (if (functionp helm-execute-action-at-once-if-one)
+ (funcall helm-execute-action-at-once-if-one)
+ helm-execute-action-at-once-if-one)
+ (= (helm-get-candidate-number
+ (eq helm-execute-action-at-once-if-one 'current-source))
+ 1))
+ (ignore)) ; Don't enter the minibuffer loop.
+ ((and helm-quit-if-no-candidate
+ (= (helm-get-candidate-number) 0))
+ (setq helm-quit t)
+ (and (functionp helm-quit-if-no-candidate)
+ (funcall helm-quit-if-no-candidate)))
+ (t ; Enter now minibuffer and wait for input.
+ (let ((tap (or any-default
+ (with-helm-current-buffer
+ (thing-at-point 'symbol)))))
+ (when helm-execute-action-at-once-if-one
+ (helm-display-buffer helm-buffer any-resume)
+ (select-window (helm-window)))
+ (unwind-protect
+ (minibuffer-with-setup-hook
+ (lambda ()
+ ;; Start minor-mode with global value of helm-map.
+ (helm--minor-mode 1)
+ ;; Now override the global value of `helm-map' with
+ ;; the local one which is in this order:
+ ;; - The keymap of current source.
+ ;; - The value passed in ANY-KEYMAP
+ ;; - Or fallback to the global value of helm-map.
+ (helm--maybe-update-keymap
+ (or src-keymap any-keymap helm-map))
+ (helm-log-run-hook 'helm-minibuffer-set-up-hook)
+ (setq timer
+ (run-with-idle-timer
+ (max (with-helm-buffer helm-input-idle-delay)
+ 0.001)
+ 'repeat
+ (lambda ()
+ ;; Stop updating in persistent action
+ ;; or when `helm-suspend-update-flag'
+ ;; is non-`nil'.
+ (unless (or helm-in-persistent-action
+ helm-suspend-update-flag)
+ (save-selected-window
+ (helm-check-minibuffer-input)
+ (helm-print-error-messages))))))
+ ;; minibuffer has already been filled here.
+ (helm--update-header-line))
+ (read-from-minibuffer (propertize (or any-prompt "pattern: ")
+ 'face 'helm-minibuffer-prompt)
+ any-input helm-map
+ nil hist tap
+ helm-inherit-input-method))
+ (when timer (cancel-timer timer) (setq timer nil)))))))))
+
+(defun helm-toggle-suspend-update ()
+ "Enable or disable update of display in helm.
+This can be useful for example for quietly writing a complex regexp
+without helm constantly updating."
+ (interactive)
+ (with-helm-alive-p
+ (when (setq helm-suspend-update-flag (not helm-suspend-update-flag))
+ (helm-kill-async-processes)
+ (setq helm-pattern ""))
+ (message (if helm-suspend-update-flag
+ "Helm update suspended!"
+ "Helm update re-enabled!"))
+ (helm-aif (helm-get-current-source)
+ (with-helm-buffer (helm-display-mode-line it t)))))
+(put 'helm-toggle-suspend-update 'helm-only t)
+
+(defun helm--suspend-read-passwd (old--fn &rest args)
+ "Suspend helm while reading password.
+This is used to advice `tramp-read-passwd', `ange-ftp-get-passwd' and
+`epa-passphrase-callback-function'."
+ ;; Suspend update when prompting for a tramp password.
+ (setq helm-suspend-update-flag t)
+ (setq overriding-terminal-local-map nil)
+ (setq helm--reading-passwd-or-string t)
+ (unwind-protect
+ ;; No need to suspend timer in emacs-24.4
+ ;; it is fixed upstream.
+ (apply old--fn args)
+ (setq helm--reading-passwd-or-string nil)
+ (setq helm-suspend-update-flag nil)))
+
+(defun helm--maybe-update-keymap (&optional map)
+ "Handle different keymaps in multiples sources.
+
+Overrides `helm-map' with the local map of current source. If no
+map is found in current source, does nothing (keeps previous
+map)."
+ (with-helm-buffer
+ (helm-aif (or map (assoc-default 'keymap (helm-get-current-source)))
+ ;; We used a timer in the past to leave
+ ;; enough time to helm to setup its keymap
+ ;; when changing source from a recursive minibuffer.
+ ;; e.g C-x C-f M-y C-g
+ ;; => *find-files have now the bindings of *kill-ring.
+ ;; It is no more true now we are using `minor-mode-overriding-map-alist'
+ ;; and `helm--minor-mode' thus it fix issue #1076 for emacs-24.3
+ ;; where concurrent timers are not supported.
+ ;; i.e update keymap+check input.
+ (with-current-buffer (window-buffer (minibuffer-window))
+ (setq minor-mode-overriding-map-alist `((helm--minor-mode . ,it)))))))
+
+;;; Prevent loosing focus when using mouse.
+;;
+(defvar helm--remap-mouse-mode-map
+ (let ((map (make-sparse-keymap)))
+ (cl-loop for k in '([mouse-1] [mouse-2] [mouse-3]
+ [down-mouse-1] [down-mouse-2] [down-mouse-3]
+ [drag-mouse-1] [drag-mouse-2] [drag-mouse-3]
+ [double-mouse-1] [double-mouse-2] [double-mouse-3]
+ [triple-mouse-1] [triple-mouse-2] [triple-mouse-3])
+ do (define-key map k 'ignore))
+ map))
+
+(define-minor-mode helm--remap-mouse-mode
+ "[INTERNAL] Prevent escaping helm minibuffer with mouse clicks.
+Do nothing when used outside of helm context.
+
+WARNING: Do not use this mode yourself, it is internal to helm."
+ :group 'helm
+ :global t
+ :keymap helm--remap-mouse-mode-map
+ (unless helm-alive-p
+ (setq helm--remap-mouse-mode-map nil)))
+(put 'helm--remap-mouse-mode 'helm-only t)
+\f
+;; Clean up
+
+(defun helm-cleanup ()
+ "Clean up the mess when helm exit or quit."
+ (helm-log "start cleanup")
+ (with-current-buffer helm-buffer
+ (let ((frame (selected-frame)))
+ (setq cursor-type t)
+ (remove-hook 'post-command-hook 'helm--maybe-update-keymap)
+ (remove-hook 'post-command-hook 'helm--update-header-line)
+ ;; Be sure we call cleanup functions from helm-buffer.
+ (helm-compute-attr-in-sources 'cleanup)
+ ;; Delete or make invisible helm frame.
+ (if (and helm--buffer-in-new-frame-p (null helm--nested))
+ (progn
+ (setq-local helm--last-frame-parameters
+ (helm--get-frame-parameters))
+ (bury-buffer)
+ (if helm-display-buffer-reuse-frame
+ (make-frame-invisible frame) (delete-frame frame)))
+ ;; bury-buffer from this window [1].
+ ;; Do it at end to make sure buffer is still current.
+ (bury-buffer))))
+ (helm-kill-async-processes)
+ ;; Remove the temporary hooks added
+ ;; by `with-helm-temp-hook' that
+ ;; may not have been consumed.
+ (when helm--temp-hooks
+ (cl-loop for (fn . hook) in helm--temp-hooks
+ do (set hook (delete fn (symbol-value hook)))))
+ ;; When running helm from a dedicated frame
+ ;; with no minibuffer, helm will run in the main frame
+ ;; which have a minibuffer, so be sure to disable
+ ;; the `no-other-window' prop there.
+ (helm-prevent-switching-other-window :enabled nil)
+ (helm-log-run-hook 'helm-cleanup-hook)
+ (helm-frame-or-window-configuration 'restore)
+ ;; [1] now bury-buffer from underlying windows otherwise,
+ ;; if this window is killed the underlying buffer will
+ ;; be a helm buffer.
+ (replace-buffer-in-windows helm-buffer)
+ (setq helm-alive-p nil)
+ ;; Prevent error "No buffer named *helm*" triggered by
+ ;; `helm-set-local-variable'.
+ (setq helm--force-updating-p nil)
+ (setq helm--buffer-in-new-frame-p nil)
+ ;; This is needed in some cases where last input
+ ;; is yielded infinitely in minibuffer after helm session.
+ (helm-clean-up-minibuffer))
+
+(defun helm-clean-up-minibuffer ()
+ "Remove contents of minibuffer."
+ (let ((miniwin (minibuffer-window)))
+ ;; Clean only current minibuffer used by helm.
+ ;; i.e The precedent one is active.
+ (unless (minibuffer-window-active-p miniwin)
+ (with-current-buffer (window-buffer miniwin)
+ (delete-minibuffer-contents)))))
+
+\f
+;;; Input handling
+;;
+;;
+(defun helm-check-minibuffer-input ()
+ "Check minibuffer content."
+ (with-helm-quittable
+ (with-selected-window (or (active-minibuffer-window)
+ (minibuffer-window))
+ (helm-check-new-input (minibuffer-contents)))))
+
+(defun helm-check-new-input (input)
+ "Check INPUT string and update the helm buffer if necessary."
+ (unless (equal input helm-pattern)
+ (setq helm-pattern input)
+ (unless (helm-action-window)
+ (setq helm-input helm-pattern))
+ (helm-log "helm-pattern = %S" helm-pattern)
+ (helm-log "helm-input = %S" helm-input)
+ (setq helm--in-update t)
+ (helm-update)))
+
+(defun helm--reset-update-flag ()
+ (run-with-idle-timer
+ helm-exit-idle-delay nil
+ (lambda () (setq helm--in-update nil))))
+
+;; (add-hook 'helm-after-update-hook #'helm--reset-update-flag)
+
+\f
+;; All candidates
+
+(defun helm-get-candidates (source)
+ "Retrieve and return the list of candidates from SOURCE."
+ (let* (inhibit-quit
+ (candidate-fn (assoc-default 'candidates source))
+ (candidate-proc (assoc-default 'candidates-process source))
+ cfn-error
+ (notify-error
+ (lambda (&optional e)
+ (error
+ "In `%s' source: `%s' %s %s"
+ (assoc-default 'name source)
+ (or candidate-fn candidate-proc)
+ (if e "\n" "must be a list, a symbol bound to a list, or a function returning a list")
+ (if e (prin1-to-string e) ""))))
+ (candidates (condition-case-unless-debug err
+ ;; Process candidates-(process) function
+ ;; It may return a process or a list of candidates.
+ (if candidate-proc
+ ;; Calling `helm-interpret-value' with no
+ ;; SOURCE arg force the use of `funcall'
+ ;; and not `helm-apply-functions-from-source'.
+ (helm-interpret-value candidate-proc)
+ (helm-interpret-value candidate-fn source))
+ (error (helm-log "Error: %S" (setq cfn-error err)) nil))))
+ (cond ((and (processp candidates) (not candidate-proc))
+ (warn "Candidates function `%s' should be called in a `candidates-process' attribute"
+ candidate-fn))
+ ((and candidate-proc (not (processp candidates)))
+ (error "Candidates function `%s' should run a process" candidate-proc)))
+ (cond ((processp candidates)
+ ;; Candidates will be filtered later in process filter.
+ candidates)
+ ;; An error occured in candidates function.
+ (cfn-error (unless helm--ignore-errors
+ (funcall notify-error cfn-error)))
+ ;; Candidates function returns no candidates.
+ ((or (null candidates)
+ ;; Can happen when the output of a process
+ ;; is empty, and the candidates function call
+ ;; something like (split-string (buffer-string) "\n")
+ ;; which result in a list of one empty string (Issue #938).
+ ;; e.g (completing-read "test: " '(""))
+ (equal candidates '("")))
+ nil)
+ ((listp candidates)
+ ;; Transform candidates with `candidate-transformer' functions or
+ ;; `real-to-display' functions if those are found,
+ ;; otherwise return candidates unmodified.
+ ;; `filtered-candidate-transformer' is NOT called here.
+ (helm-transform-candidates candidates source))
+ (t (funcall notify-error)))))
+
+(defmacro helm-while-no-input (&rest body)
+ "Same as `while-no-input' but without the `input-pending-p' test."
+ (declare (debug t) (indent 0))
+ (let ((catch-sym (make-symbol "input")))
+ `(with-local-quit
+ (catch ',catch-sym
+ (let ((throw-on-input ',catch-sym))
+ ,@body)))))
+
+(defun helm-get-cached-candidates (source)
+ "Return the cached value of candidates for SOURCE.
+Cache the candidates if there is no cached value yet."
+ (let* ((name (assoc-default 'name source))
+ (candidate-cache (gethash name helm-candidate-cache)))
+ (helm-aif candidate-cache
+ (prog1 it (helm-log "Use cached candidates"))
+ (helm-log "No cached candidates, calculate candidates")
+ (let ((candidates (helm-get-candidates source)))
+ (cond ((processp candidates)
+ (push (cons candidates
+ (append source
+ (list (cons 'item-count 0)
+ (cons 'incomplete-line ""))))
+ helm-async-processes)
+ (set-process-filter candidates 'helm-output-filter)
+ (setq candidates nil))
+ ((not (assq 'volatile source))
+ (puthash name candidates helm-candidate-cache)))
+ candidates))))
+
+\f
+;;; Candidate transformers
+
+(defun helm-process-candidate-transformer (candidates source)
+ "Execute `candidate-transformer' function(s) on CANDIDATES in SOURCE."
+ (helm-aif (assoc-default 'candidate-transformer source)
+ (helm-apply-functions-from-source source it candidates)
+ candidates))
+
+(defun helm-process-filtered-candidate-transformer (candidates source)
+ "Execute `filtered-candidate-transformer' function(s) on CANDIDATES in SOURCE."
+ (helm-aif (assoc-default 'filtered-candidate-transformer source)
+ (helm-apply-functions-from-source source it candidates source)
+ candidates))
+
+(defmacro helm--maybe-process-filter-one-by-one-candidate (candidate source)
+ "Execute `filter-one-by-one' function(s) on real value of CANDIDATE in SOURCE."
+ `(helm-aif (assoc-default 'filter-one-by-one ,source)
+ (let ((real (if (consp ,candidate)
+ (cdr ,candidate)
+ ,candidate)))
+ (if (and (listp it)
+ (not (functionp it))) ;; Don't treat lambda's as list.
+ (cl-loop for f in it
+ do (setq ,candidate (funcall f real))
+ finally return ,candidate)
+ (setq ,candidate (funcall it real))))
+ ,candidate))
+
+(defun helm--initialize-one-by-one-candidates (candidates source)
+ "Process the CANDIDATES with the `filter-one-by-one' function in SOURCE.
+Return CANDIDATES unchanged when pattern is not empty."
+ (helm-aif (and (string= helm-pattern "")
+ (assoc-default 'filter-one-by-one source))
+ (cl-loop for cand in candidates collect
+ (helm--maybe-process-filter-one-by-one-candidate cand source))
+ candidates))
+
+(defun helm-process-filtered-candidate-transformer-maybe
+ (candidates source process-p)
+ "Execute `filtered-candidate-transformer' function(s) on CANDIDATES in SOURCE.
+When PROCESS-P is non-`nil' execute `filtered-candidate-transformer'
+functions if some, otherwise return CANDIDATES."
+ (if process-p
+ ;; When no filter return CANDIDATES unmodified.
+ (helm-process-filtered-candidate-transformer candidates source)
+ candidates))
+
+(defun helm-process-real-to-display (candidates source)
+ "Execute real-to-display function on all CANDIDATES of SOURCE."
+ (helm-aif (assoc-default 'real-to-display source)
+ (setq candidates (helm-apply-functions-from-source
+ source 'mapcar
+ (lambda (cand)
+ (if (consp cand)
+ ;; override DISPLAY from candidate-transformer
+ (cons (funcall it (cdr cand)) (cdr cand))
+ (cons (funcall it cand) cand)))
+ candidates))
+ candidates))
+
+(defun helm-transform-candidates (candidates source &optional process-p)
+ "Transform CANDIDATES from SOURCE according to candidate transformers.
+
+When PROCESS-P is non-`nil' executes the
+`filtered-candidate-transformer' functions, otherwise processes
+`candidate-transformer' functions only,
+`filtered-candidate-transformer' functions being processed later,
+after the candidates have been narrowed by
+`helm-candidate-number-limit', see `helm-compute-matches'. When
+`real-to-display' attribute is present, execute its functions on all
+maybe filtered CANDIDATES."
+ (helm-process-real-to-display
+ (helm-process-filtered-candidate-transformer-maybe
+ (helm-process-candidate-transformer
+ candidates source)
+ source process-p)
+ source))
+
+\f
+;; Narrowing candidates
+(defun helm-candidate-number-limit (source)
+ "Apply candidate-number-limit attribute value.
+This overrides `helm-candidate-number-limit' variable.
+
+e.g:
+If \(candidate-number-limit\) is in SOURCE, show all candidates in SOURCE.
+If \(candidate-number-limit . 123\) is in SOURCE limit candidate to 123."
+ (helm-aif (assq 'candidate-number-limit source)
+ ;; When assoc value is nil use by default 99999999 otherwise use
+ ;; the assoc value, when it is a symbol interpret its value (#1831).
+ (or (helm-aand (cdr it) (helm-interpret-value it)) 99999999)
+ (or helm-candidate-number-limit 99999999)))
+
+(defun helm-candidate-get-display (candidate)
+ "Get searched display part from CANDIDATE.
+CANDIDATE is either a string, a symbol, or a \(DISPLAY . REAL\)
+cons cell."
+ (cond ((car-safe candidate))
+ ((symbolp candidate)
+ (symbol-name candidate))
+ ((numberp candidate)
+ (number-to-string candidate))
+ (t candidate)))
+
+(defun helm-process-pattern-transformer (pattern source)
+ "Execute pattern-transformer attribute function(s) on PATTERN in SOURCE."
+ (helm-aif (assoc-default 'pattern-transformer source)
+ (helm-apply-functions-from-source source it pattern)
+ pattern))
+
+(defun helm-default-match-function (candidate)
+ "Check if `helm-pattern' match CANDIDATE.
+Default function to match candidates according to `helm-pattern'."
+ (string-match helm-pattern candidate))
+
+\f
+;;; Fuzzy matching
+;;
+;;
+(defvar helm--fuzzy-regexp-cache (make-hash-table :test 'eq))
+(defun helm--fuzzy-match-maybe-set-pattern ()
+ ;; Computing helm-pattern with helm--mapconcat-pattern
+ ;; is costly, so cache it once time for all and reuse it
+ ;; until pattern change.
+ (when helm--in-fuzzy
+ (let ((fun (if (string-match "\\`\\^" helm-pattern)
+ #'identity
+ #'helm--mapconcat-pattern)))
+ (clrhash helm--fuzzy-regexp-cache)
+ ;; FIXME: Splitted part are not handled here,
+ ;; I must compute them in `helm-search-match-part'
+ ;; when negation and in-buffer are used.
+ (if (string-match "\\`!" helm-pattern)
+ (puthash 'helm-pattern
+ (if (> (length helm-pattern) 1)
+ (list (funcall fun (substring helm-pattern 1 2))
+ (funcall fun (substring helm-pattern 1)))
+ '("" ""))
+ helm--fuzzy-regexp-cache)
+ (puthash 'helm-pattern
+ (if (> (length helm-pattern) 0)
+ (list (funcall fun (substring helm-pattern 0 1))
+ (funcall fun helm-pattern))
+ '("" ""))
+ helm--fuzzy-regexp-cache)))))
+
+(defun helm-fuzzy-match (candidate)
+ "Check if `helm-pattern' fuzzy matches CANDIDATE.
+This function is used with sources built with `helm-source-sync'."
+ (unless (string-match " " helm-pattern)
+ ;; When pattern have one or more spaces, let
+ ;; multi-match doing the job with no fuzzy matching.[1]
+ (let ((regexp (cadr (gethash 'helm-pattern helm--fuzzy-regexp-cache))))
+ (if (string-match "\\`!" helm-pattern)
+ (not (string-match regexp candidate))
+ (string-match regexp candidate)))))
+
+(defun helm-fuzzy-search (pattern)
+ "Same as `helm-fuzzy-match' but for sources built with
+`helm-source-in-buffer'."
+ (unless (string-match " " helm-pattern)
+ ;; Same as in `helm-fuzzy-match' ref[1].
+ (let* ((regexps (gethash 'helm-pattern helm--fuzzy-regexp-cache))
+ (partial-regexp (car regexps))
+ (regexp (cadr regexps)))
+ (if (string-match "\\`!" pattern)
+ ;; Don't try to search here, just return
+ ;; the position of line and go ahead,
+ ;; letting `helm-search-match-part' checking if
+ ;; pattern match against this line.
+ (prog1 (list (point-at-bol) (point-at-eol))
+ (forward-line 1))
+ ;; We could use here directly `re-search-forward'
+ ;; on the regexp produced by `helm--mapconcat-pattern',
+ ;; but it is very slow because emacs have to do an incredible
+ ;; amount of loops to match e.g "[^f]*f[^o]*o..." in the whole buffer,
+ ;; more the regexp is long more the amount of loops grow.
+ ;; (Probably leading to a max-lisp-eval-depth error if both
+ ;; regexp and buffer are too big)
+ ;; So just search the first bit of pattern e.g "[^f]*f", and
+ ;; then search the corresponding line with the whole regexp,
+ ;; which increase dramatically the speed of the search.
+ (cl-loop while (re-search-forward partial-regexp nil t)
+ for bol = (point-at-bol)
+ for eol = (point-at-eol)
+ if (progn (goto-char bol)
+ (re-search-forward regexp eol t))
+ do (goto-char eol) and return t
+ else do (goto-char eol)
+ finally return nil)))))
+
+(defun helm-score-candidate-for-pattern (candidate pattern)
+ "Assign score to CANDIDATE according to PATTERN.
+Score is calculated for contiguous matches found with PATTERN.
+Score is 100 (maximum) if PATTERN is fully matched in CANDIDATE.
+One point bonus is added to score when PATTERN prefix matches
+CANDIDATE. Contiguous matches get a coefficient of 2."
+ (let* ((cand (if (stringp candidate)
+ candidate (helm-stringify candidate)))
+ (pat-lookup (helm--collect-pairs-in-string pattern))
+ (str-lookup (helm--collect-pairs-in-string cand))
+ (bonus (cond ((equal (car pat-lookup) (car str-lookup))
+ 1)
+ ((and (null pat-lookup) ; length = 1
+ (string= pattern (substring cand 0 1)))
+ 150)
+ (t 0)))
+ (bonus1 (and (string-match (concat "\\<" (regexp-quote pattern) "\\>")
+ cand)
+ 100)))
+ (+ bonus (or bonus1
+ ;; Give a coefficient of 2 for contiguous matches.
+ ;; That's mean that "wiaaaki" will not take precedence
+ ;; on "aaawiki" when matching on "wiki" even if "wiaaaki"
+ ;; starts by "wi".
+ (* (length (cl-nintersection
+ pat-lookup str-lookup :test 'equal))
+ 2)))))
+
+(defun helm-fuzzy-matching-default-sort-fn-1 (candidates &optional use-real basename preserve-tie-order)
+ "The transformer for sorting candidates in fuzzy matching.
+It sorts on the display part by default.
+
+Sorts CANDIDATES by their scores as calculated by
+`helm-score-candidate-for-pattern'. Set USE-REAL to non-`nil' to
+sort on the real part. If BASENAME is non-nil assume we are
+completing filenames and sort on basename of candidates. If
+PRESERVE-TIE-ORDER is nil, ties in scores are sorted by length of
+the candidates."
+ (if (string= helm-pattern "")
+ candidates
+ (let ((table-scr (make-hash-table :test 'equal)))
+ (sort candidates
+ (lambda (s1 s2)
+ ;; Score and measure the length on real or display part of candidate
+ ;; according to `use-real'.
+ (let* ((real-or-disp-fn (if use-real #'cdr #'car))
+ (cand1 (cond ((and basename (consp s1))
+ (helm-basename (funcall real-or-disp-fn s1)))
+ ((consp s1) (funcall real-or-disp-fn s1))
+ (basename (helm-basename s1))
+ (t s1)))
+ (cand2 (cond ((and basename (consp s2))
+ (helm-basename (funcall real-or-disp-fn s2)))
+ ((consp s2) (funcall real-or-disp-fn s2))
+ (basename (helm-basename s2))
+ (t s2)))
+ (data1 (or (gethash cand1 table-scr)
+ (puthash cand1
+ (list (helm-score-candidate-for-pattern
+ cand1 helm-pattern)
+ (length (helm-stringify cand1)))
+ table-scr)))
+ (data2 (or (gethash cand2 table-scr)
+ (puthash cand2
+ (list (helm-score-candidate-for-pattern
+ cand2 helm-pattern)
+ (length (helm-stringify cand2)))
+ table-scr)))
+ (len1 (cadr data1))
+ (len2 (cadr data2))
+ (scr1 (car data1))
+ (scr2 (car data2)))
+ (cond ((= scr1 scr2)
+ (unless preserve-tie-order
+ (< len1 len2)))
+ ((> scr1 scr2)))))))))
+
+(defun helm-fuzzy-matching-default-sort-fn (candidates _source)
+ "Default `filtered-candidate-transformer' to sort candidates in fuzzy matching."
+ (helm-fuzzy-matching-default-sort-fn-1 candidates))
+
+(defun helm-fuzzy-matching-sort-fn-preserve-ties-order (candidates _source)
+ "`filtered-candidate-transformer' to sort candidates in fuzzy matching, preserving order of ties.
+The default function, `helm-fuzzy-matching-default-sort-fn',
+sorts ties by length, shortest first. This function may be more
+useful when the order of the candidates is meaningful, e.g. with
+`recentf-list'."
+ (helm-fuzzy-matching-default-sort-fn-1 candidates nil t))
+
+(defun helm--maybe-get-migemo-pattern (pattern)
+ (or (and helm-migemo-mode
+ (assoc-default pattern helm-mm--previous-migemo-info))
+ pattern))
+
+(defun helm-fuzzy-default-highlight-match (candidate)
+ "The default function to highlight matches in fuzzy matching.
+Highlight elements in CANDIDATE matching `helm-pattern' according
+to the matching method in use."
+ (if (string= helm-pattern "")
+ ;; Empty pattern, do nothing.
+ candidate
+ ;; Else start highlighting.
+ (let* ((pair (and (consp candidate) candidate))
+ (display (helm-stringify (if pair (car pair) candidate)))
+ (real (cdr pair))
+ (regex (helm--maybe-get-migemo-pattern helm-pattern))
+ (mp (pcase (get-text-property 0 'match-part display)
+ ((pred (string= display)) nil)
+ (str str)))
+ (count 0)
+ beg-str end-str)
+ ;; Extract all parts of display keeping original properties.
+ (when (and mp (string-match (regexp-quote mp) display))
+ (setq beg-str (substring display 0 (match-beginning 0))
+ end-str (substring display (match-end 0) (length display))
+ mp (substring display (match-beginning 0) (match-end 0))))
+ (with-temp-buffer
+ ;; Insert the whole display part and remove non--match-part
+ ;; to keep their original face properties.
+ (insert (propertize (or mp display) 'read-only nil)) ; Fix (#1176)
+ (goto-char (point-min))
+ (condition-case nil
+ (progn
+ ;; Try first matching against whole pattern.
+ (while (re-search-forward regex nil t)
+ (cl-incf count)
+ (helm-add-face-text-properties
+ (match-beginning 0) (match-end 0) 'helm-match))
+ ;; If no matches start matching against multiples or fuzzy matches.
+ (when (zerop count)
+ (cl-loop with multi-match = (string-match-p " " helm-pattern)
+ with patterns = (if multi-match
+ (mapcar #'helm--maybe-get-migemo-pattern
+ (helm-mm-split-pattern helm-pattern))
+ (split-string helm-pattern "" t))
+ for p in patterns
+ ;; Multi matches (regexps patterns).
+ if multi-match do
+ (progn
+ (while (re-search-forward p nil t)
+ (helm-add-face-text-properties
+ (match-beginning 0) (match-end 0)
+ 'helm-match))
+ (goto-char (point-min)))
+ ;; Fuzzy matches (literal patterns).
+ else do
+ (when (search-forward p nil t)
+ (helm-add-face-text-properties
+ (match-beginning 0) (match-end 0)
+ 'helm-match)))))
+ (invalid-regexp nil))
+ ;; Now replace the original match-part with the part
+ ;; with face properties added.
+ (setq display (if mp (concat beg-str (buffer-string) end-str) (buffer-string))))
+ (if real (cons display real) display))))
+
+(defun helm-fuzzy-highlight-matches (candidates _source)
+ "The filtered-candidate-transformer function to highlight fuzzy matches.
+See `helm-fuzzy-default-highlight-match'."
+ (cl-loop for c in candidates
+ collect (funcall helm-fuzzy-matching-highlight-fn c)))
+
+\f
+;;; Matching candidates
+;;
+;;
+(defun helm-match-functions (source)
+ (let ((matchfns (or (assoc-default 'match source)
+ (assoc-default 'match-strict source)
+ #'helm-default-match-function)))
+ (if (and (listp matchfns) (not (functionp matchfns)))
+ matchfns (list matchfns))))
+
+(defun helm-search-functions (source)
+ (let ((searchfns (assoc-default 'search source)))
+ (if (and (listp searchfns) (not (functionp searchfns)))
+ searchfns (list searchfns))))
+
+(defun helm-take-first-elements (seq n)
+ "Return the first N elements of SEQ if SEQ is longer than N.
+It is used for narrowing list of candidates to the
+`helm-candidate-number-limit'."
+ (if (> (length seq) n) (cl-subseq seq 0 n) seq))
+
+(defun helm-match-from-candidates (cands matchfns match-part-fn limit source)
+ (condition-case-unless-debug err
+ (cl-loop with hash = (make-hash-table :test 'equal)
+ with allow-dups = (assq 'allow-dups source)
+ with case-fold-search = (helm-set-case-fold-search)
+ with count = 0
+ for iter from 1
+ for fn in matchfns
+ when (< count limit) nconc
+ (cl-loop for c in cands
+ for dup = (gethash c hash)
+ while (< count limit)
+ for target = (helm-candidate-get-display c)
+ for prop-part = (get-text-property 0 'match-part target)
+ for part = (and match-part-fn
+ (or prop-part
+ (funcall match-part-fn target)))
+ ;; When allowing dups check if DUP
+ ;; have been already found in previous loop
+ ;; by comparing its value with ITER.
+ when (and (or (and allow-dups dup (= dup iter))
+ (null dup))
+ (condition-case nil
+ (funcall fn (or part target))
+ (invalid-regexp nil)))
+ do
+ (progn
+ ;; Give as value the iteration number of
+ ;; inner loop to be able to check if
+ ;; the duplicate have not been found in previous loop.
+ (puthash c iter hash)
+ (helm--maybe-process-filter-one-by-one-candidate c source)
+ (cl-incf count))
+ ;; Filter out nil candidates maybe returned by
+ ;; `helm--maybe-process-filter-one-by-one-candidate'.
+ and when c collect
+ (if (and part (not prop-part))
+ (if (consp c)
+ (cons (propertize target 'match-part part) (cdr c))
+ (propertize c 'match-part part))
+ c)))
+ (error (unless (eq (car err) 'invalid-regexp) ; Always ignore regexps errors.
+ (helm-log-error "helm-match-from-candidates in source `%s': %s %s"
+ (assoc-default 'name source) (car err) (cdr err)))
+ nil)))
+
+(defun helm-compute-matches (source)
+ "Start computing candidates in SOURCE."
+ (save-current-buffer
+ (let ((matchfns (helm-match-functions source))
+ (matchpartfn (assoc-default 'match-part source))
+ (helm--source-name (assoc-default 'name source))
+ (helm-current-source source)
+ (limit (helm-candidate-number-limit source))
+ (helm-pattern (helm-process-pattern-transformer
+ helm-pattern source)))
+ (helm--fuzzy-match-maybe-set-pattern)
+ ;; If source have a `filtered-candidate-transformer' attr
+ ;; Filter candidates with this func, otherwise just compute
+ ;; candidates.
+ ;; NOTE that this next block of code is returning nil on async sources,
+ ;; the candidates being processed directly in `helm-output-filter'
+ ;; process-filter.
+ (helm-process-filtered-candidate-transformer
+ ;; Using in-buffer method or helm-pattern is empty
+ ;; in this case compute all candidates.
+ (if (or (equal helm-pattern "")
+ (helm--candidates-in-buffer-p matchfns))
+ ;; Compute all candidates up to LIMIT.
+ ;; one-by-one are computed here only for sources that
+ ;; display a list of candidates even with an empty
+ ;; pattern.
+ (helm--initialize-one-by-one-candidates
+ (helm-take-first-elements
+ (helm-get-cached-candidates source) limit)
+ source)
+ ;; Compute candidates according to pattern with their match
+ ;; fns.
+ ;; one-by-one filtered candidates are computed during the
+ ;; execution of next loop in `helm-match-from-candidates'.
+ (helm-match-from-candidates
+ (helm-get-cached-candidates source) matchfns matchpartfn limit source))
+ source))))
+
+(defun helm--candidates-in-buffer-p (matchfns)
+ (equal matchfns '(identity)))
+
+(defun helm-render-source (source matches)
+ "Display MATCHES from SOURCE according to its settings."
+ (helm-log "Source name = %S" (assoc-default 'name source))
+ (when matches
+ (helm-insert-header-from-source source)
+ (cl-loop with separate = nil
+ with start = (point)
+ with singleline = (null (assq 'multiline source))
+ for m in matches
+ for count from 1
+ if singleline
+ do (helm-insert-match m 'insert count source)
+ else
+ do (progn
+ (if separate
+ (helm-insert-candidate-separator)
+ (setq separate t))
+ (helm-insert-match m 'insert count source))
+ finally (and (null singleline)
+ (put-text-property start (point)
+ 'helm-multiline t)))))
+
+(defmacro helm--maybe-use-while-no-input (&rest body)
+ "Wrap BODY in `helm-while-no-input' unless initializing a remote connection."
+ `(progn
+ (if (and (file-remote-p helm-pattern)
+ (not (file-remote-p helm-pattern nil t)))
+ ;; Tramp will ask for passwd, don't use `helm-while-no-input'.
+ ,@body
+ (helm-log "Using here `helm-while-no-input'")
+ (helm-while-no-input ,@body))))
+
+(defun helm--collect-matches (src-list)
+ "Returns a list of matches for each source in SRC-LIST.
+
+The resulting value is a list of lists, e.g ((a b c) (c d) (e f)) or
+\(nil nil nil) for three sources when no matches found, however this
+function can be interrupted by new input and in this case returns a
+plain `nil' i.e not (nil), in this case `helm-update' is not rendering
+the source, keeping previous candidates in display."
+ (let ((matches (helm--maybe-use-while-no-input
+ (cl-loop for src in src-list
+ collect (helm-compute-matches src)))))
+ (unless (eq matches t) matches)))
+
+\f
+;;; Case fold search
+;;
+;;
+(cl-defun helm-set-case-fold-search (&optional (pattern helm-pattern))
+ "Used to set the value of `case-fold-search' in helm.
+Return t or nil depending on the value of `helm-case-fold-search'
+and `helm-pattern'."
+ (let ((helm-case-fold-search
+ (helm-aif (assq 'case-fold-search (helm-get-current-source))
+ (cdr it)
+ helm-case-fold-search))
+ ;; Only parse basename for filenames
+ ;; to avoid setting case sensitivity
+ ;; when expanded directories contains upcase
+ ;; characters.
+ (bn-or-pattern (if (string-match "[~/]*" pattern)
+ (helm-basename pattern)
+ pattern)))
+ (helm-set-case-fold-search-1 bn-or-pattern)))
+
+(defun helm-set-case-fold-search-1 (pattern)
+ (cl-case helm-case-fold-search
+ (smart (let ((case-fold-search nil))
+ (if (string-match "[[:upper:]]" pattern) nil t)))
+ (t helm-case-fold-search)))
+
+\f
+;;; Helm update
+;;
+(defun helm-update (&optional preselect source candidates)
+ "Update candidates list in `helm-buffer' based on `helm-pattern'.
+Argument PRESELECT is a string or regexp used to move selection
+to a particular place after finishing update.
+When SOURCE is provided update mode-line for this source, otherwise
+the current source will be used.
+Argument CANDIDATES when provided is used to redisplay these candidates
+without recomputing them, it should be a list of lists."
+ (helm-log "Start updating")
+ (helm-kill-async-processes)
+ ;; When persistent action have been called
+ ;; we have two windows even with `helm-full-frame'.
+ ;; So go back to one window when updating if `helm-full-frame'
+ ;; is non-`nil'.
+ (when (with-helm-buffer
+ (and helm-onewindow-p
+ ;; We are not displaying helm-buffer in a frame and
+ ;; helm-window is already displayed.
+ (not helm--buffer-in-new-frame-p)
+ (helm-window)
+ (not (helm-action-window))))
+ (with-helm-window (delete-other-windows)))
+ (with-current-buffer (helm-buffer-get)
+ (set (make-local-variable 'helm-input-local) helm-pattern)
+ (unwind-protect
+ (let (sources matches)
+ ;; Collect sources ready to be updated.
+ (setq sources
+ (cl-loop for src in helm-sources
+ when (helm-update-source-p src)
+ collect src))
+ ;; When no sources to update erase buffer
+ ;; to avoid duplication of header and candidates
+ ;; when next chunk of update will arrive,
+ ;; otherwise the buffer is erased AFTER [1] the results
+ ;; are computed.
+ (unless sources (erase-buffer))
+ ;; Compute matches without rendering the sources.
+ ;; This prevent the helm-buffer flickering when constantly
+ ;; updating.
+ (helm-log "Matches: %S"
+ (setq matches (or candidates (helm--collect-matches sources))))
+ ;; If computing matches finished and is not interrupted
+ ;; erase the helm-buffer and render results (Fix #1157).
+ (when matches ;; nil only when interrupted by helm-while-no-input.
+ (erase-buffer) ; [1]
+ (cl-loop for src in sources
+ for mtc in matches
+ do (helm-render-source src mtc))
+ ;; Move to first line only when there is matches
+ ;; to avoid cursor moving upside down (issue #1703).
+ (helm--update-move-first-line)
+ (helm--reset-update-flag)))
+ ;; When there is only one async source, update mode-line and run
+ ;; `helm-after-update-hook' in `helm-output-filter--post-process',
+ ;; when there is more than one source, update mode-line and run
+ ;; `helm-after-update-hook' now even if an async source is
+ ;; present and running in BG.
+ (let ((src (or source (helm-get-current-source))))
+ (unless (assq 'candidates-process src)
+ (and src (helm-display-mode-line src 'force))
+ (helm-log-run-hook 'helm-after-update-hook)))
+ (when preselect
+ (helm-log "Update preselect candidate %s" preselect)
+ (if (helm-window)
+ (with-helm-window (helm-preselect preselect source))
+ (helm-preselect preselect source)))
+ (setq helm--force-updating-p nil))
+ (helm-log "end update")))
+
+(defun helm-update-source-p (source)
+ "Whether SOURCE needs updating or not."
+ (let ((len (string-width
+ (if (assq 'multimatch source)
+ ;; Don't count spaces entered when using
+ ;; multi-match.
+ (replace-regexp-in-string " " "" helm-pattern)
+ helm-pattern))))
+ (and (or (not helm-source-filter)
+ (member (assoc-default 'name source) helm-source-filter))
+ (>= len
+ (helm-aif (assq 'requires-pattern source) (or (cdr it) 1) 0))
+ ;; Entering repeatedly these strings (*, ?) takes 100% CPU
+ ;; and hang emacs on MacOs preventing deleting backward those
+ ;; characters (issue #1802).
+ (not (string-match-p "\\`[*]+\\'" helm-pattern))
+ ;; These incomplete regexps hang helm forever
+ ;; so defer update. Maybe replace spaces quoted when using
+ ;; multi-match.
+ (not (member (replace-regexp-in-string "\\s\\ " " " helm-pattern)
+ helm-update-blacklist-regexps)))))
+
+(defun helm--update-move-first-line ()
+ "Goto first line of `helm-buffer'."
+ (goto-char (point-min))
+ (if (helm-window)
+ (helm-move-selection-common :where 'line
+ :direction 'next
+ :follow t)
+ (forward-line 1)
+ (helm-mark-current-line)
+ (helm-follow-execute-persistent-action-maybe)))
+
+(cl-defun helm-force-update (&optional preselect (recenter t))
+ "Force recalculation and update of candidates.
+
+Unlike `helm-update', this function re-evaluates `init' and
+`update' attributes when present; also `helm-candidate-cache' is
+not reinitialized, meaning candidates are not recomputed unless
+pattern has changed.
+
+Selection is preserved to current candidate if it still exists after
+update or moved to PRESELECT, if specified.
+The helm-window is recentered at the end when RECENTER is `t'
+which is the default, RECENTER can be also a number in this case it is
+passed as argument to `recenter'."
+ (with-helm-buffer
+ (let* ((source (helm-get-current-source))
+ (selection (helm-aif (helm-get-selection nil t source)
+ (regexp-quote it))))
+ (setq helm--force-updating-p t)
+ (mapc 'helm-force-update--reinit helm-sources)
+ (helm-update (or preselect selection) source)
+ (when (and (helm-window) recenter)
+ (with-helm-window
+ (recenter (and (numberp recenter) recenter)))))))
+
+(defun helm-refresh ()
+ "Force recalculation and update of candidates."
+ (interactive)
+ (with-helm-alive-p
+ (helm-force-update)))
+(put 'helm-refresh 'helm-only t)
+
+(defun helm-force-update--reinit (source)
+ "Reinit SOURCE by calling its update and init functions."
+ ;; When using a specific buffer as cache, don't kill it.
+ (helm-aif (and (null (bufferp (assoc-default
+ (helm-attr 'name source)
+ helm--candidate-buffer-alist)))
+ (helm-apply-functions-from-source
+ source 'helm-candidate-buffer))
+ (kill-buffer it))
+ (cl-dolist (attr '(update init))
+ (helm-aif (assoc-default attr source)
+ (helm-apply-functions-from-source source it)))
+ (helm-remove-candidate-cache source))
+
+(defun helm-redisplay-buffer ()
+ "Redisplay candidates in `helm-buffer'.
+
+Candidates are not recomputed, only redisplayed after modifying the
+whole list of candidates in each source with functions found in
+`redisplay' attribute of current source. Note that candidates are
+redisplayed with their display part with all properties included only.
+This function is used in async sources to transform the whole list of
+candidates from the sentinel functions (i.e when all candidates have
+been computed) because other filters like `candidate-transformer' are
+modifying only each chunk of candidates from process-filter as they
+come in and not the whole list. Use this for e.g sorting the whole
+list of async candidates once computed.
+Note: To ensure redisplay is done in async sources after helm
+reached `candidate-number-limit' you will have also to redisplay your
+candidates from `helm-async-outer-limit-hook'."
+ (with-helm-buffer
+ (let ((get-cands (lambda (source)
+ (let ((fns (assoc-default 'redisplay source))
+ candidates
+ helm-move-to-line-cycle-in-source
+ helm-allow-mouse)
+ (helm-goto-source source)
+ (helm-next-line)
+ (helm-awhile (condition-case-unless-debug nil
+ (and (not (helm-pos-header-line-p))
+ (helm-get-selection
+ nil 'withprop source))
+ (error nil))
+ (push it candidates)
+ (when (save-excursion
+ (forward-line 1) (helm-end-of-source-p t))
+ (cl-return nil))
+ (helm-next-line))
+ (helm-apply-functions-from-source
+ source fns (nreverse candidates)))))
+ (get-sources (lambda ()
+ (let (sources helm-move-to-line-cycle-in-source)
+ (helm-awhile (helm-get-current-source)
+ (push it sources)
+ (when (save-excursion
+ (helm-move--end-of-source)
+ (forward-line 1) (eobp))
+ (cl-return nil))
+ (helm-next-source))
+ (nreverse sources)))))
+ (goto-char (point-min))
+ (helm-update nil (helm-get-current-source)
+ (cl-loop with sources = (funcall get-sources)
+ for s in helm-sources
+ for name = (assoc-default 'name s) collect
+ (when (cl-loop for src in sources thereis
+ (string= name
+ (assoc-default 'name src)))
+ (funcall get-cands s)))))))
+
+(defun helm-remove-candidate-cache (source)
+ "Remove SOURCE from `helm-candidate-cache'."
+ (remhash (assoc-default 'name source) helm-candidate-cache))
+
+(defun helm-insert-match (match insert-function &optional num source)
+ "Insert MATCH into `helm-buffer' with INSERT-FUNCTION.
+If MATCH is a cons cell then insert the car as display with
+the cdr stored as real value in a `helm-realvalue' text property.
+Args NUM and SOURCE are also stored as text property when specified as
+respectively `helm-cand-num' and `helm-cur-source'."
+ (let ((start (point-at-bol (point)))
+ (dispvalue (helm-candidate-get-display match))
+ (realvalue (cdr-safe match))
+ (map (when helm-allow-mouse (make-sparse-keymap)))
+ (inhibit-read-only t)
+ end)
+ (when (and (stringp dispvalue)
+ (not (zerop (length dispvalue))))
+ (funcall insert-function dispvalue)
+ (setq end (point-at-eol))
+ ;; Some strings may handle another keymap prop.
+ (remove-text-properties start end '(keymap nil))
+ (put-text-property start end 'read-only nil)
+ ;; Some sources with candidates-in-buffer have already added
+ ;; 'helm-realvalue property when creating candidate buffer.
+ (unless (get-text-property start 'helm-realvalue)
+ (and realvalue
+ (put-text-property start end
+ 'helm-realvalue realvalue)))
+ (when map
+ (define-key map [mouse-1] 'helm-mouse-select-candidate)
+ (define-key map [mouse-2] 'ignore)
+ (define-key map [mouse-3] 'helm-select-action)
+ (add-text-properties
+ start end
+ `(mouse-face highlight
+ keymap ,map
+ help-echo ,(pcase (get-text-property start 'help-echo)
+ ((and it (pred stringp))
+ (concat it "\nmouse-1: select candidate\nmouse-3: menu actions"))
+ (_ "mouse-1: select candidate\nmouse-3: menu actions")))))
+ (when num
+ (put-text-property start end 'helm-cand-num num))
+ (when source
+ (put-text-property start end 'helm-cur-source source))
+ (funcall insert-function "\n"))))
+
+(defun helm--mouse-reset-selection-help-echo ()
+ (let* ((inhibit-read-only t)
+ (start (overlay-start helm-selection-overlay))
+ (end (overlay-end helm-selection-overlay))
+ (help-echo (get-text-property start 'help-echo)))
+ (when (and (stringp help-echo)
+ (string-match "mouse-2: execute action" help-echo))
+ (put-text-property
+ start end
+ 'help-echo (replace-match "mouse-1: select candidate"
+ t t help-echo)))))
+
+(defun helm--bind-mouse-for-selection (pos)
+ (let ((inhibit-read-only t)
+ (map (get-text-property pos 'keymap)))
+ (when map
+ (define-key map [mouse-2] 'helm-maybe-exit-minibuffer)
+ (put-text-property
+ helm-selection-point
+ (overlay-end helm-selection-overlay)
+ 'help-echo (helm-aif (get-text-property pos 'help-echo)
+ (if (and (stringp it)
+ (string-match "mouse-1: select candidate" it))
+ (replace-match "mouse-2: execute action" t t it)
+ "mouse-2: execute action\nmouse-3: menu actions")
+ "mouse-2: execute action\nmouse-3: menu actions")))))
+
+(defun helm-mouse-select-candidate (event)
+ (interactive "e")
+ (let* ((window (posn-window (event-end event)))
+ (pos (posn-point (event-end event))))
+ (unwind-protect
+ (with-current-buffer (window-buffer window)
+ (if (and (helm-action-window)
+ (eql window (get-buffer-window helm-buffer)))
+ (user-error "selection in helm-window not available while selecting action")
+ (helm--mouse-reset-selection-help-echo)
+ (goto-char pos)
+ (when (helm-pos-multiline-p)
+ (goto-char (or (helm-get-previous-candidate-separator-pos)
+ (helm-get-previous-header-pos)))
+ (forward-line 1)))
+ (helm-mark-current-line)
+ (helm-follow-execute-persistent-action-maybe))
+ (select-window (minibuffer-window))
+ (set-buffer (window-buffer window)))))
+(put 'helm-mouse-select-candidate 'helm-only t)
+
+(defun helm-insert-header-from-source (source)
+ "Insert SOURCE name in `helm-buffer' header.
+Maybe insert, by overlay, additional info after the source name
+if SOURCE has header-name attribute."
+ (let ((name (assoc-default 'name source)))
+ (helm-insert-header
+ name
+ (helm-aif (assoc-default 'header-name source)
+ (helm-apply-functions-from-source source it name)))))
+
+(defun helm-insert-header (name &optional display-string)
+ "Insert header of source NAME into the helm buffer.
+If DISPLAY-STRING is non-`nil' and a string value then display
+this additional info after the source name by overlay."
+ (unless (bobp)
+ (let ((start (point)))
+ (insert "\n")
+ (put-text-property start (point) 'helm-header-separator t)))
+ (let ((start (point)))
+ (insert name)
+ (put-text-property (point-at-bol)
+ (point-at-eol) 'helm-header t)
+ (when display-string
+ (overlay-put (make-overlay (point-at-bol) (point-at-eol))
+ 'display display-string))
+ (insert "\n")
+ (put-text-property start (point) 'face 'helm-source-header)))
+
+(defun helm-insert-candidate-separator ()
+ "Insert separator of candidates into the helm buffer."
+ (insert (propertize helm-candidate-separator 'face 'helm-separator))
+ (put-text-property (point-at-bol)
+ (point-at-eol) 'helm-candidate-separator t)
+ (insert "\n"))
+
+\f
+;;; Async process
+;;
+(defun helm-output-filter (process output-string)
+ "The `process-filter' function for helm async sources."
+ (with-helm-quittable
+ (helm-output-filter-1 (assoc process helm-async-processes) output-string)))
+
+(defun helm-output-filter-1 (process-assoc output-string)
+ (helm-log "output-string = %S" output-string)
+ (with-current-buffer helm-buffer
+ (let ((source (cdr process-assoc)))
+ (save-excursion
+ (helm-aif (assoc-default 'insertion-marker source)
+ (goto-char it)
+ (goto-char (point-max))
+ (helm-insert-header-from-source source)
+ (setcdr process-assoc
+ (append source `((insertion-marker . ,(point-marker))))))
+ (helm-output-filter--process-source
+ (car process-assoc) output-string source
+ (helm-candidate-number-limit source))))
+ (helm-output-filter--post-process)))
+
+(defun helm-output-filter--process-source (process output-string source limit)
+ (cl-dolist (candidate (helm-transform-candidates
+ (helm-output-filter--collect-candidates
+ (split-string output-string "\n")
+ (assq 'incomplete-line source))
+ source t))
+ (setq candidate
+ (helm--maybe-process-filter-one-by-one-candidate candidate source))
+ (if (assq 'multiline source)
+ (let ((start (point)))
+ (helm-insert-candidate-separator)
+ (helm-insert-match candidate 'insert-before-markers
+ (1+ (cdr (assq 'item-count source)))
+ source)
+ (put-text-property start (point) 'helm-multiline t))
+ (helm-insert-match candidate 'insert-before-markers
+ (1+ (cdr (assq 'item-count source)))
+ source))
+ (cl-incf (cdr (assq 'item-count source)))
+ (when (>= (assoc-default 'item-count source) limit)
+ (helm-kill-async-process process)
+ (helm-log-run-hook 'helm-async-outer-limit-hook)
+ (cl-return))))
+
+(defun helm-output-filter--collect-candidates (lines incomplete-line-info)
+ "Collect LINES maybe completing the truncated first and last lines."
+ ;; The output of process may come in chunks of any size, so the last
+ ;; line of LINES could be truncated, this truncated line is stored
+ ;; in INCOMPLETE-LINE-INFO to be concatenated with the first
+ ;; incomplete line of the next arriving chunk. INCOMPLETE-LINE-INFO
+ ;; is an attribute of source; it is created with an empty string
+ ;; when the source is computed => (incomplete-line . "")
+ (helm-log "incomplete-line-info = %S" (cdr incomplete-line-info))
+ (butlast
+ (cl-loop for line in lines
+ ;; On start `incomplete-line-info' value is empty string.
+ for newline = (helm-aif (cdr incomplete-line-info)
+ (prog1
+ (concat it line)
+ (setcdr incomplete-line-info nil))
+ line)
+ collect newline
+ ;; Store last incomplete line (last chunk truncated) until
+ ;; new output arrives. Previously storing 'line' in
+ ;; incomplete-line-info assumed output was truncated in
+ ;; only two chunks. But output could be large and
+ ;; truncated in more than two chunks. Therefore store
+ ;; 'newline' to contain the previous chunks (Issue #1187).
+ finally do (setcdr incomplete-line-info newline))))
+
+(defun helm-output-filter--post-process ()
+ (helm-aif (get-buffer-window helm-buffer 'visible)
+ (with-selected-window it
+ (helm-skip-noncandidate-line 'next)
+ (helm-mark-current-line nil 'nomouse)
+ ;; FIXME Don't hardcode follow delay.
+ (helm-follow-execute-persistent-action-maybe 0.5)
+ (helm-display-mode-line (helm-get-current-source))
+ (helm-log-run-hook 'helm-after-update-hook)
+ (helm--reset-update-flag))))
+
+(defun helm-process-deferred-sentinel-hook (process event file)
+ "Defer remote processes in sentinels.
+Meant to be called at the beginning of a sentinel process
+function."
+ (when (and (not (zerop helm-tramp-connection-min-time-diff))
+ (string= event "finished\n")
+ (or (file-remote-p file)
+ ;; `helm-suspend-update-flag'
+ ;; is non-`nil' here only during a
+ ;; running process, this will never be called
+ ;; when user set it explicitly with `C-!'.
+ helm-suspend-update-flag))
+ (setq helm-suspend-update-flag t)
+ ;; Kill the process but don't delete entry in
+ ;; `helm-async-processes'.
+ (helm-kill-async-process process)
+ ;; When tramp opens the same connection twice in less than 5
+ ;; seconds, it throws 'suppress, which calls the real-handler on
+ ;; the main "Emacs". To avoid this [1] helm waits for 5 seconds
+ ;; before updates yet allows user input during this delay. [1] In
+ ;; recent Emacs versions, this has been fixed so tramp returns nil
+ ;; in such conditions. Note: `tramp-connection-min-time-diff' cannot
+ ;; have values less than 5 seconds otherwise the process dies.
+ (run-at-time helm-tramp-connection-min-time-diff
+ nil (lambda ()
+ (when helm-alive-p ; Don't run timer fn after quit.
+ (setq helm-suspend-update-flag nil)
+ (helm-check-minibuffer-input))))))
+
+(defun helm-kill-async-processes ()
+ "Kill all asynchronous processes registered in `helm-async-processes'."
+ (while helm-async-processes
+ (helm-kill-async-process (caar helm-async-processes))
+ (setq helm-async-processes (cdr helm-async-processes))))
+
+(defun helm-kill-async-process (process)
+ "Stop output from `helm-output-filter' and kill associated PROCESS."
+ (set-process-filter process nil)
+ (delete-process process))
+
+\f
+;;; Actions
+;;
+(defun helm-execute-selection-action ()
+ "Execute current action."
+ (helm-log-run-hook 'helm-before-action-hook)
+ ;; Position can be change when `helm-current-buffer'
+ ;; is split, so jump to this position before executing action.
+ (helm-current-position 'restore)
+ (unwind-protect
+ (prog1 (helm-execute-selection-action-1)
+ (helm-log-run-hook 'helm-after-action-hook))
+ (setq helm--executing-helm-action nil)))
+
+(defun helm-execute-selection-action-1 (&optional
+ selection action
+ preserve-saved-action)
+ "Execute ACTION on current SELECTION.
+If PRESERVE-SAVED-ACTION is non-`nil', then save the action."
+ (helm-log "executing action")
+ (setq action (helm-get-default-action
+ (or action
+ helm-saved-action
+ (if (get-buffer helm-action-buffer)
+ (helm-get-selection helm-action-buffer)
+ (helm-get-actions-from-current-source)))))
+ (helm-aif (and (not helm-in-persistent-action)
+ (get-buffer helm-action-buffer))
+ (kill-buffer it))
+ (let ((source (or helm-saved-current-source
+ (helm-get-current-source)))
+ non-essential)
+ (setq selection (helm-coerce-selection
+ (or selection
+ helm-saved-selection
+ (helm-get-selection nil nil source)
+ (and (assq 'accept-empty source) ""))
+ source))
+ (unless preserve-saved-action (setq helm-saved-action nil))
+ (when (and selection action) (funcall action selection))))
+
+(defun helm-coerce-selection (selection source)
+ "Apply coerce attribute function to SELECTION in SOURCE.
+Coerce source with coerce function."
+ (helm-aif (assoc-default 'coerce source)
+ (helm-apply-functions-from-source source it selection)
+ selection))
+
+(defun helm-get-default-action (action)
+ "Get the first ACTION value of action list in source."
+ (if (and (listp action) (not (functionp action)))
+ (cdar action)
+ action))
+
+(defun helm--show-action-window-other-window-p ()
+ (and helm-show-action-window-other-window
+ (or helm-always-two-windows
+ helm--buffer-in-new-frame-p)
+ (eq helm-split-window-state 'vertical)))
+
+(defun helm-select-action ()
+ "Select an action for the currently selected candidate.
+If action buffer is selected, back to the helm buffer."
+ (interactive)
+ (with-helm-alive-p
+ (let ((src (helm-get-current-source)))
+ (helm-log-run-hook 'helm-select-action-hook)
+ (setq helm-saved-selection (helm-get-selection nil nil src))
+ (with-selected-frame (with-helm-window (selected-frame))
+ (prog1
+ (helm-acond ((get-buffer-window helm-action-buffer 'visible)
+ (set-window-buffer it helm-buffer)
+ (helm--set-action-prompt 'restore)
+ (when (helm--show-action-window-other-window-p)
+ (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)
+ (setq cursor-type nil)
+ (set-window-buffer (if (helm--show-action-window-other-window-p)
+ (split-window (get-buffer-window helm-buffer)
+ nil helm-show-action-window-other-window)
+ (get-buffer-window helm-buffer))
+ helm-action-buffer)
+ (set (make-local-variable 'helm-sources)
+ (list
+ (helm-build-sync-source "Actions"
+ :volatile t
+ :nomark t
+ :persistent-action #'ignore
+ :persistent-help "DoNothing"
+ :keymap 'helm-map
+ :candidates actions
+ :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
+ for count from 1
+ collect
+ (cons (concat (cond ((> count 12)
+ " ")
+ ((< count 10)
+ (format "[f%s] " count))
+ (t (format "[f%s] " count)))
+ (propertize i 'face 'helm-action))
+ j)))
+ :candidate-number-limit nil)))
+ (set (make-local-variable 'helm-source-filter) nil)
+ (set (make-local-variable 'helm-selection-overlay) nil)
+ (helm-initialize-overlays helm-action-buffer)))
+
+\f
+;; Selection of candidates
+
+(defun helm-display-source-at-screen-top-maybe (unit)
+ "Display source at the top of screen when UNIT value is 'source.
+Returns nil for any other value of UNIT."
+ (when (and helm-display-source-at-screen-top (eq unit 'source))
+ (set-window-start (selected-window)
+ (save-excursion (forward-line -1) (point)))))
+
+(defun helm-skip-noncandidate-line (direction)
+ "Skip source header or candidates separator when going in DIRECTION.
+DIRECTION is either 'next or 'previous.
+Same as `helm-skip-header-and-separator-line' but ensure
+point is moved to the right place when at bob or eob."
+ (helm-skip-header-and-separator-line direction)
+ (and (bobp) (forward-line 1)) ; Skip first header.
+ (and (eobp) (forward-line -1))) ; Avoid last empty line.
+
+(defun helm-skip-header-and-separator-line (direction)
+ "Skip source header or candidate separator when going to next/previous line.
+DIRECTION is either 'next or 'previous."
+ (let ((fn (cl-ecase direction
+ (next 'eobp)
+ (previous 'bobp))))
+ (while (and (not (funcall fn))
+ (or (helm-pos-header-line-p)
+ (helm-pos-candidate-separator-p)))
+ (forward-line (if (and (eq direction 'previous)
+ (not (eq (point-at-bol) (point-min))))
+ -1 1)))))
+
+(defun helm-display-mode-line (source &optional force)
+ "Set up mode line and header line for `helm-buffer'.
+
+SOURCE is a Helm source object.
+
+Optional argument FORCE forces redisplay of the Helm buffer's
+mode and header lines."
+ (set (make-local-variable 'helm-mode-line-string)
+ (helm-interpret-value (or (and (listp source) ; Check if source is empty.
+ (assoc-default 'mode-line source))
+ (default-value 'helm-mode-line-string))
+ source))
+ (let ((follow (and (or (helm-follow-mode-p source)
+ (and helm-follow-mode-persistent
+ (member (assoc-default 'name source)
+ helm-source-names-using-follow)))
+ " (HF)"))
+ (marked (and helm-marked-candidates
+ (cl-loop with cur-name = (assoc-default 'name source)
+ for c in helm-marked-candidates
+ for name = (assoc-default 'name (car c))
+ when (string= name cur-name)
+ collect c))))
+ ;; Setup mode-line.
+ (if helm-mode-line-string
+ (setq mode-line-format
+ `(:propertize
+ (" " mode-line-buffer-identification " "
+ (:eval (format "L%-3d" (helm-candidate-number-at-point)))
+ ,follow
+ " "
+ (:eval ,(and marked
+ (propertize
+ (format "M%d" (length marked))
+ 'face 'helm-visible-mark)))
+ (:eval (when ,helm--mode-line-display-prefarg
+ (let ((arg (prefix-numeric-value
+ (or prefix-arg current-prefix-arg))))
+ (unless (= arg 1)
+ (propertize (format " [prefarg:%s]" arg)
+ 'face 'helm-prefarg)))))
+ " "
+ (: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
+ (mouse-1 . ignore)
+ (down-mouse-1 . ignore)
+ (drag-mouse-1 . ignore)
+ (mouse-2 . ignore)
+ (down-mouse-2 . ignore)
+ (drag-mouse-2 . ignore)
+ (mouse-3 . ignore)
+ (down-mouse-3 . ignore)
+ (drag-mouse-3 . ignore))))
+ helm--mode-line-string-real
+ (substitute-command-keys (if (listp helm-mode-line-string)
+ (cadr helm-mode-line-string)
+ helm-mode-line-string)))
+ (setq mode-line-format (default-value 'mode-line-format)))
+ ;; Setup header-line.
+ (cond (helm-echo-input-in-header-line
+ (setq force t)
+ (helm--set-header-line))
+ (helm-display-header-line
+ (let ((hlstr (helm-interpret-value
+ (and (listp source)
+ (assoc-default 'header-line source))
+ source))
+ (endstr (make-string (window-width) ? )))
+ (setq header-line-format
+ (propertize (concat " " hlstr endstr)
+ 'face 'helm-header))))))
+ (when force (force-mode-line-update)))
+
+(defun helm--set-header-line (&optional update)
+ (with-selected-window (minibuffer-window)
+ (when helm-display-header-line
+ ;; Prevent cursor movement over the overlay displaying
+ ;; persistent-help in minibuffer (issue #2108).
+ (setq-local disable-point-adjustment t))
+ (let* ((beg (save-excursion (vertical-motion 0 (helm-window)) (point)))
+ (end (save-excursion (end-of-visual-line) (point)))
+ ;; The visual line where the cursor is.
+ (cont (buffer-substring beg end))
+ (pref (propertize
+ " "
+ 'display (if (string-match-p (regexp-opt `(,helm--prompt
+ ,helm--action-prompt))
+ cont)
+ `(space :width ,helm-header-line-space-before-prompt)
+ (propertize
+ "->"
+ 'face 'helm-header-line-left-margin))))
+ (pos (- (point) beg)))
+ ;; Increment pos each time we find a "%" up to current-pos (#1648).
+ (cl-loop for c across (buffer-substring-no-properties beg (point))
+ when (eql c ?%) do (cl-incf pos))
+ ;; Increment pos when cursor is on a "%" to make it visible in header-line
+ ;; i.e "%%|" and not "%|%" (#1649).
+ (when (eql (char-after) ?%) (setq pos (1+ pos)))
+ (setq cont (replace-regexp-in-string "%" "%%" cont))
+ (with-helm-buffer
+ (setq header-line-format (concat pref cont " "))
+ (funcall helm-default-prompt-display-function pos)
+ (when update (force-mode-line-update))))))
+
+(defun helm-set-default-prompt-display (pos)
+ (put-text-property
+ ;; Increment pos to handle the space before prompt (i.e `pref').
+ (+ 1 pos) (+ 2 pos)
+ 'face
+ ;; Don't just use cursor face, this can hide the current character.
+ (list :inverse-video t
+ :foreground (face-background 'cursor)
+ :background (face-background 'default))
+ header-line-format))
+
+(defun helm-exchange-minibuffer-and-header-line ()
+ "Display minibuffer in header-line and vice versa for current helm session.
+
+This is a toggle command."
+ (interactive)
+ (with-helm-window
+ (add-hook 'helm-minibuffer-set-up-hook 'helm-hide-minibuffer-maybe)
+ (setq-local helm-echo-input-in-header-line
+ (not helm-echo-input-in-header-line))
+ (with-selected-window (minibuffer-window)
+ (if (with-helm-buffer helm-echo-input-in-header-line)
+ (helm-hide-minibuffer-maybe)
+ (remove-overlays)
+ (setq cursor-type t)))
+ (helm-display-mode-line (helm-get-current-source) t)))
+(put 'helm-exchange-minibuffer-and-header-line 'helm-only t)
+
+(defun helm--update-header-line ()
+ ;; This should be used in `post-command-hook',
+ ;; nowhere else.
+ (when (with-helm-buffer helm-echo-input-in-header-line)
+ (helm--set-header-line t)))
+
+(defun helm-hide-minibuffer-maybe ()
+ "Hide minibuffer contents in a Helm session.
+This function should normally go to `helm-minibuffer-set-up-hook'.
+It has no effect if `helm-echo-input-in-header-line' is nil."
+ (when (with-helm-buffer helm-echo-input-in-header-line)
+ (let ((ov (make-overlay (point-min) (point-max) nil nil t)))
+ (overlay-put ov 'window (selected-window))
+ (helm-aif (and helm-display-header-line
+ (helm-attr 'persistent-help))
+ (progn
+ (overlay-put ov 'display
+ (truncate-string-to-width
+ (substitute-command-keys
+ (concat "\\<helm-map>\\[helm-execute-persistent-action]: "
+ (format "%s (keeping session)" it)))
+ (- (window-width) 1)))
+ (overlay-put ov 'face 'helm-header))
+ (overlay-put ov 'face (let ((bg-color (face-background 'default nil)))
+ `(:background ,bg-color :foreground ,bg-color))))
+
+ (setq cursor-type nil))))
+
+(defun helm-show-candidate-number (&optional name)
+ "Used to display candidate number in mode-line.
+You can specify NAME of candidates e.g \"Buffers\" otherwise
+it is \"Candidate\(s\)\" by default."
+ (when helm-alive-p
+ (unless (helm-empty-source-p)
+ ;; Build a fixed width string when candidate-number < 1000
+ (let* ((cand-name (or name "Candidate(s)"))
+ (width (length (format "[999 %s]" cand-name))))
+ (propertize
+ (format (concat "%-" (number-to-string width) "s")
+ (format "[%s %s]"
+ (helm-get-candidate-number 'in-current-source)
+ cand-name))
+ 'face (if helm-suspend-update-flag
+ 'helm-candidate-number-suspended
+ 'helm-candidate-number))))))
+
+(cl-defun helm-move-selection-common (&key where direction (follow t))
+ "Move the selection marker to a new position.
+Position is determined by WHERE and DIRECTION.
+Key arg WHERE can be one of:
+ - line
+ - page
+ - edge
+ - source
+Key arg DIRECTION can be one of:
+ - previous
+ - next
+ - A source or a source name when used with :WHERE 'source."
+ (let ((move-func (cl-case where
+ (line (cl-ecase direction
+ (previous 'helm-move--previous-line-fn)
+ (next 'helm-move--next-line-fn)))
+ (page (cl-ecase direction
+ (previous 'helm-move--previous-page-fn)
+ (next 'helm-move--next-page-fn)))
+ (edge (cl-ecase direction
+ (previous 'helm-move--beginning-of-buffer-fn)
+ (next 'helm-move--end-of-buffer-fn)))
+ (source (cl-case direction
+ (previous 'helm-move--previous-source-fn)
+ (next 'helm-move--next-source-fn)
+ (t (lambda () ; A source is passed as DIRECTION arg.
+ (helm-move--goto-source-fn direction))))))))
+ (unless (or (helm-empty-buffer-p (helm-buffer-get))
+ (not (helm-window)))
+ (with-helm-window
+ (when helm-allow-mouse
+ (helm--mouse-reset-selection-help-echo))
+ (helm-log-run-hook 'helm-move-selection-before-hook)
+ (funcall move-func)
+ (and (memq direction '(next previous))
+ (helm-skip-noncandidate-line direction))
+ (when (helm-pos-multiline-p)
+ (helm-move--beginning-of-multiline-candidate))
+ (helm-display-source-at-screen-top-maybe where)
+ (helm-mark-current-line)
+ (when follow
+ (helm-follow-execute-persistent-action-maybe))
+ (helm-display-mode-line (helm-get-current-source))
+ (helm-log-run-hook 'helm-move-selection-after-hook)))))
+
+(defun helm-move--beginning-of-multiline-candidate ()
+ (let ((header-pos (helm-get-previous-header-pos))
+ (separator-pos (helm-get-previous-candidate-separator-pos)))
+ (when header-pos
+ (goto-char (if (or (null separator-pos)
+ (< separator-pos header-pos))
+ header-pos
+ separator-pos))
+ (forward-line 1))))
+
+(defun helm-move--previous-multi-line-fn ()
+ (forward-line -1)
+ (unless (helm-pos-header-line-p)
+ (helm-skip-header-and-separator-line 'previous)
+ (helm-move--beginning-of-multiline-candidate)))
+
+(defun helm-move--previous-line-fn ()
+ (if (not (helm-pos-multiline-p))
+ (forward-line -1)
+ (helm-move--previous-multi-line-fn))
+ (when (and helm-move-to-line-cycle-in-source
+ (helm-pos-header-line-p))
+ (forward-line 1)
+ (helm-move--end-of-source)
+ ;; We are at end of helm-buffer
+ ;; check if last candidate is a multiline candidate
+ ;; and jump to it
+ (when (and (eobp)
+ (save-excursion (forward-line -1) (helm-pos-multiline-p)))
+ (helm-move--previous-multi-line-fn))))
+
+(defun helm-move--next-multi-line-fn ()
+ (let ((header-pos (helm-get-next-header-pos))
+ (separator-pos (helm-get-next-candidate-separator-pos)))
+ (cond ((and separator-pos
+ (or (null header-pos) (< separator-pos header-pos)))
+ (goto-char separator-pos))
+ (header-pos
+ (goto-char header-pos)))))
+
+(defun helm-move--next-line-fn ()
+ (if (not (helm-pos-multiline-p))
+ (forward-line 1)
+ (helm-move--next-multi-line-fn))
+ (when (and helm-move-to-line-cycle-in-source
+ (or (save-excursion (and (helm-pos-multiline-p)
+ (goto-char (overlay-end
+ helm-selection-overlay))
+ (helm-end-of-source-p t)))
+ (helm-end-of-source-p t)))
+ (helm-move--beginning-of-source)))
+
+(defun helm-move--previous-page-fn ()
+ (condition-case nil
+ (scroll-down)
+ (beginning-of-buffer (goto-char (point-min)))))
+
+(defun helm-move--next-page-fn ()
+ (condition-case nil
+ (scroll-up)
+ (end-of-buffer (goto-char (point-max)))))
+
+(defun helm-move--beginning-of-buffer-fn ()
+ (goto-char (point-min)))
+
+(defun helm-move--end-of-buffer-fn ()
+ (goto-char (point-max)))
+
+(defun helm-move--end-of-source ()
+ (helm-aif (helm-get-next-header-pos)
+ (progn (goto-char it) (forward-line -2))
+ (goto-char (point-max))))
+
+(defun helm-move--beginning-of-source ()
+ (helm-aif (helm-get-previous-header-pos)
+ (progn (goto-char it)
+ (forward-line 1))
+ (goto-char (point-min))))
+
+(defun helm-move--previous-source-fn ()
+ (forward-line -1)
+ (if (bobp)
+ (goto-char (point-max))
+ (helm-skip-header-and-separator-line 'previous))
+ (goto-char (helm-get-previous-header-pos))
+ (forward-line 1))
+
+(defun helm-move--next-source-fn ()
+ (goto-char (or (and (not (save-excursion
+ (forward-line 1) (eobp)))
+ ;; Empty source at eob are just
+ ;; not displayed unless they are dummy.
+ ;; Issue #1117.
+ (helm-get-next-header-pos))
+ (point-min))))
+
+(defun helm-move--goto-source-fn (source-or-name)
+ (goto-char (point-min))
+ (let ((name (if (stringp source-or-name)
+ source-or-name
+ (assoc-default 'name source-or-name))))
+ (if (or (null name) (string= name ""))
+ (forward-line 1)
+ (condition-case err
+ (while (not (string= name (helm-current-line-contents)))
+ (goto-char (helm-get-next-header-pos)))
+ (error (helm-log "%S" err))))))
+
+(defun helm-candidate-number-at-point ()
+ (if helm-alive-p
+ (with-helm-buffer
+ (or (get-text-property (point) 'helm-cand-num) 1))
+ (or (get-text-property (point) 'helm-cand-num) 1)))
+
+(defun helm--next-or-previous-line (direction &optional arg)
+ ;; Be sure to not use this in non--interactives calls.
+ (let ((helm-move-to-line-cycle-in-source
+ (and helm-move-to-line-cycle-in-source arg)))
+ (if (and arg (> arg 1))
+ (cl-loop with pos = (helm-candidate-number-at-point)
+ with cand-num = (helm-get-candidate-number t)
+ with iter = (min arg (if (eq direction 'next)
+ (- cand-num pos)
+ (min arg (1- pos))))
+ for count from 1
+ while (<= count iter)
+ do
+ (helm-move-selection-common :where 'line :direction direction))
+ (helm-move-selection-common :where 'line :direction direction))))
+
+(defun helm-previous-line (&optional arg)
+ "Move selection to the ARG previous line(s).
+Same behavior as `helm-next-line' when called with a numeric prefix arg."
+ (interactive "p")
+ (with-helm-alive-p
+ (helm--next-or-previous-line 'previous arg)))
+(put 'helm-previous-line 'helm-only t)
+
+(defun helm-next-line (&optional arg)
+ "Move selection to the next ARG line(s).
+When numeric prefix arg is > than the number of candidates, then
+move to the last candidate of current source (i.e. don't move to
+next source)."
+ (interactive "p")
+ (with-helm-alive-p
+ (helm--next-or-previous-line 'next arg)))
+(put 'helm-next-line 'helm-only t)
+
+(defun helm-previous-page ()
+ "Move selection back with a pageful."
+ (interactive)
+ (with-helm-alive-p
+ (helm-move-selection-common :where 'page :direction 'previous)))
+(put 'helm-previous-page 'helm-only t)
+
+(defun helm-next-page ()
+ "Move selection forward with a pageful."
+ (interactive)
+ (with-helm-alive-p
+ (helm-move-selection-common :where 'page :direction 'next)))
+(put 'helm-next-page 'helm-only t)
+
+(defun helm-beginning-of-buffer ()
+ "Move selection at the top."
+ (interactive)
+ (with-helm-alive-p
+ (helm-move-selection-common :where 'edge :direction 'previous)))
+(put 'helm-beginning-of-buffer 'helm-only t)
+
+(defun helm-end-of-buffer ()
+ "Move selection at the bottom."
+ (interactive)
+ (with-helm-alive-p
+ (helm-move-selection-common :where 'edge :direction 'next)))
+(put 'helm-end-of-buffer 'helm-only t)
+
+(defun helm-previous-source ()
+ "Move selection to the previous source."
+ (interactive)
+ (with-helm-alive-p
+ (helm-move-selection-common :where 'source :direction 'previous)))
+(put 'helm-previous-source 'helm-only t)
+
+(defun helm-next-source ()
+ "Move selection to the next source."
+ (interactive)
+ (with-helm-alive-p
+ (helm-move-selection-common :where 'source :direction 'next)))
+(put 'helm-next-source 'helm-only t)
+
+(defun helm-goto-source (&optional source-or-name)
+ "Move the selection to the source named SOURCE-OR-NAME.
+
+If SOURCE-OR-NAME is empty string or nil go to the first candidate of
+first source."
+ (helm-move-selection-common :where 'source :direction source-or-name))
+
+(defun helm--follow-action (arg)
+ (let ((helm--temp-follow-flag t) ; Needed in HFF.
+ (in-follow-mode (helm-follow-mode-p)))
+ ;; When follow-mode is already enabled, just go to next or
+ ;; previous line.
+ (when (or (eq last-command 'helm-follow-action-forward)
+ (eq last-command 'helm-follow-action-backward)
+ (eq last-command 'helm-execute-persistent-action)
+ in-follow-mode)
+ (if (> arg 0)
+ (helm-move-selection-common :where 'line
+ :direction 'next
+ :follow nil)
+ (helm-move-selection-common :where 'line
+ :direction 'previous
+ :follow nil)))
+ (unless in-follow-mode
+ (helm-execute-persistent-action))))
+
+(defun helm-follow-action-forward ()
+ "Go to next line and execute persistent action."
+ (interactive)
+ (with-helm-alive-p (helm--follow-action 1)))
+(put 'helm-follow-action-forward 'helm-only t)
+
+(defun helm-follow-action-backward ()
+ "Go to previous line and execute persistent action."
+ (interactive)
+ (with-helm-alive-p (helm--follow-action -1)))
+(put 'helm-follow-action-backward 'helm-only t)
+
+(defun helm-mark-current-line (&optional resumep nomouse)
+ "Move `helm-selection-overlay' to current line.
+When RESUMEP is non nil move overlay to `helm-selection-point'.
+When NOMOUSE is specified do not set mouse bindings.
+
+Note that selection is unrelated to visible marks used for marking
+candidates."
+ (with-helm-buffer
+ (when resumep
+ (goto-char helm-selection-point))
+ (move-overlay
+ helm-selection-overlay (point-at-bol)
+ (if (helm-pos-multiline-p)
+ (let ((header-pos (helm-get-next-header-pos))
+ (separator-pos (helm-get-next-candidate-separator-pos)))
+ (or (and (null header-pos) separator-pos)
+ (and header-pos separator-pos
+ (< separator-pos header-pos)
+ separator-pos)
+ header-pos
+ (point-max)))
+ (1+ (point-at-eol))))
+ (setq helm-selection-point (overlay-start helm-selection-overlay))
+ (when (and helm-allow-mouse (null nomouse))
+ (helm--bind-mouse-for-selection helm-selection-point))))
+
+(defun helm-confirm-and-exit-minibuffer ()
+ "Maybe ask for confirmation when exiting helm.
+It is similar to `minibuffer-complete-and-exit' adapted to helm.
+If `minibuffer-completion-confirm' value is 'confirm,
+send minibuffer confirm message and exit on next hit.
+If `minibuffer-completion-confirm' value is t,
+don't exit and send message 'no match'."
+ (interactive)
+ (with-helm-alive-p
+ (if (and (helm--updating-p)
+ (null helm--reading-passwd-or-string))
+ (progn (message "[Display not ready]")
+ (sit-for 0.5) (message nil))
+ (let* ((src (helm-get-current-source))
+ (empty-buffer-p (with-current-buffer helm-buffer
+ (eq (point-min) (point-max))))
+ (sel (helm-get-selection nil nil src))
+ (unknown (and (not empty-buffer-p)
+ (string= (get-text-property
+ 0 'display
+ (helm-get-selection nil 'withprop src))
+ "[?]"))))
+ (cond ((and (or empty-buffer-p unknown)
+ (eq minibuffer-completion-confirm 'confirm))
+ (setq helm-minibuffer-confirm-state
+ 'confirm)
+ (setq minibuffer-completion-confirm nil)
+ (minibuffer-message " [confirm]"))
+ ((and (or empty-buffer-p
+ (unless (if minibuffer-completing-file-name
+ (and minibuffer-completion-predicate
+ (funcall minibuffer-completion-predicate sel))
+ (and (stringp sel)
+ ;; SEL may be a cons cell when helm-comp-read
+ ;; is called directly with a collection composed
+ ;; of (display . real) and real is a cons cell.
+ (try-completion sel minibuffer-completion-table
+ minibuffer-completion-predicate)))
+ unknown))
+ (eq minibuffer-completion-confirm t))
+ (minibuffer-message " [No match]"))
+ (t
+ (setq helm-minibuffer-confirm-state nil)
+ (helm-exit-minibuffer)))))))
+(put 'helm-confirm-and-exit-minibuffer 'helm-only t)
+
+(add-hook 'helm-after-update-hook 'helm-confirm-and-exit-hook)
+
+(defun helm-confirm-and-exit-hook ()
+ "Restore `minibuffer-completion-confirm' when helm update."
+ (unless (or (eq minibuffer-completion-confirm t)
+ (not helm-minibuffer-confirm-state))
+ (setq minibuffer-completion-confirm
+ helm-minibuffer-confirm-state)))
+
+(defun helm-read-string (prompt &optional initial-input history
+ default-value inherit-input-method)
+ "Same as `read-string' but for reading string from a helm session."
+ (let ((helm--reading-passwd-or-string t))
+ (read-string
+ prompt initial-input history default-value inherit-input-method)))
+
+(defun helm--updating-p ()
+ ;; helm timer is between two cycles.
+ ;; IOW `helm-check-minibuffer-input' haven't yet compared input
+ ;; and `helm-pattern'.
+ (or (not (equal (minibuffer-contents) helm-pattern))
+ ;; `helm-check-minibuffer-input' have launched `helm-update'.
+ helm--in-update))
+
+(defun helm-maybe-exit-minibuffer ()
+ (interactive)
+ (with-helm-alive-p
+ (if (and (helm--updating-p)
+ (null helm--reading-passwd-or-string))
+ (progn
+ (message "[Display not ready]")
+ (sit-for 0.5) (message nil)
+ (helm-update))
+ (helm-exit-minibuffer))))
+(put 'helm-maybe-exit-minibuffer 'helm-only t)
+
+(defun helm-exit-minibuffer ()
+ "Select the current candidate by exiting the minibuffer."
+ (unless helm-current-prefix-arg
+ (setq helm-current-prefix-arg current-prefix-arg))
+ (setq helm-exit-status 0)
+ (helm-log-run-hook 'helm-exit-minibuffer-hook)
+ (exit-minibuffer))
+
+(defun helm-keyboard-quit ()
+ "Quit minibuffer in helm.
+If action buffer is displayed, kill it."
+ (interactive)
+ (with-helm-alive-p
+ (when (get-buffer-window helm-action-buffer 'visible)
+ (kill-buffer helm-action-buffer))
+ (setq helm-exit-status 1)
+ (abort-recursive-edit)))
+(put 'helm-keyboard-quit 'helm-only t)
+
+(defun helm-get-next-header-pos ()
+ "Return the position of the next header from point."
+ (next-single-property-change (point) 'helm-header))
+
+(defun helm-get-previous-header-pos ()
+ "Return the position of the previous header from point."
+ (previous-single-property-change (point) 'helm-header))
+
+(defun helm-pos-multiline-p ()
+ "Return non-`nil' if the current position is in the multiline source region."
+ (get-text-property (point) 'helm-multiline))
+
+(defun helm-get-next-candidate-separator-pos ()
+ "Return the position of the next candidate separator from point."
+ (let ((hp (helm-get-next-header-pos)))
+ (helm-aif (next-single-property-change (point) 'helm-candidate-separator)
+ (or
+ ;; Be sure we don't catch
+ ;; the separator of next source.
+ (and hp (< it hp) it)
+ ;; The separator found is in next source
+ ;; we are at last cand, so use the header pos.
+ (and hp (< hp it) hp)
+ ;; A single source, just try next separator.
+ it))))
+
+(defun helm-get-previous-candidate-separator-pos ()
+ "Return the position of the previous candidate separator from point."
+ (previous-single-property-change (point) 'helm-candidate-separator))
+
+(defun helm-pos-header-line-p ()
+ "Return t if the current line is a header line."
+ (or (get-text-property (point-at-bol) 'helm-header)
+ (get-text-property (point-at-bol) 'helm-header-separator)))
+
+(defun helm-pos-candidate-separator-p ()
+ "Return t if the current line is a candidate separator."
+ (get-text-property (point-at-bol) 'helm-candidate-separator))
+
+\f
+;;; Debugging
+;;
+;;
+(defun helm-debug-output ()
+ "Show all helm-related variables at this time."
+ (interactive)
+ (with-helm-alive-p
+ (helm-help-internal " *Helm Debug*" 'helm-debug-output-function)))
+(put 'helm-debug-output 'helm-only t)
+
+(defun helm-debug-output-function (&optional vars)
+ (message "Calculating all helm-related values...")
+ (insert "If you debug some variables or forms, set `helm-debug-variables'
+to a list of forms.\n\n")
+ (cl-dolist (v (or vars
+ helm-debug-variables
+ (apropos-internal "^helm-" 'boundp)))
+ (insert "** "
+ (pp-to-string v) "\n"
+ (pp-to-string (with-current-buffer helm-buffer (eval v))) "\n"))
+ (message "Calculating all helm-related values...Done"))
+
+(defun helm-enable-or-switch-to-debug ()
+ "First hit enable helm debugging, second hit switch to debug buffer."
+ (interactive)
+ (with-helm-alive-p
+ (if helm-debug
+ (helm-run-after-exit
+ #'helm-debug-open-last-log)
+ (setq helm-debug t)
+ (with-helm-buffer (setq truncate-lines nil))
+ (message "Debugging enabled"))))
+(put 'helm-enable-or-switch-to-debug 'helm-only t)
+
+\f
+;; Misc
+(defun helm-kill-buffer-hook ()
+ "Remove tick entry from `helm-tick-hash' and remove buffer from
+`helm-buffers' when killing a buffer."
+ (cl-loop for key being the hash-keys in helm-tick-hash
+ if (string-match (format "^%s/" (regexp-quote (buffer-name))) key)
+ do (remhash key helm-tick-hash))
+ (setq helm-buffers (remove (buffer-name) helm-buffers)))
+(add-hook 'kill-buffer-hook 'helm-kill-buffer-hook)
+
+(defun helm-preselect (candidate-or-regexp &optional source)
+ "Move selection to CANDIDATE-OR-REGEXP on Helm start.
+
+CANDIDATE-OR-REGEXP can be a:
+
+- String
+- Cons cell of two strings
+- Nullary function, which moves to a candidate
+
+When CANDIDATE-OR-REGEXP is a cons cell, tries moving to first
+element of the cons cell, then the second, and so on. This allows
+selection of duplicate candidates after the first.
+
+Optional argument SOURCE is a Helm source object."
+ (with-helm-buffer
+ (when candidate-or-regexp
+ (if source
+ (helm-goto-source source)
+ (goto-char (point-min))
+ (forward-line 1))
+ (if (functionp candidate-or-regexp)
+ (funcall candidate-or-regexp)
+ (let ((start (point)) mp)
+ (helm-awhile (if (consp candidate-or-regexp)
+ (and (re-search-forward (car candidate-or-regexp) nil t)
+ (re-search-forward (cdr candidate-or-regexp) nil t))
+ (re-search-forward candidate-or-regexp nil t))
+ ;; If search fall on an header line continue loop
+ ;; until it match or fail (Issue #1509).
+ (unless (helm-pos-header-line-p) (cl-return (setq mp it))))
+ (goto-char (or mp start)))))
+ (forward-line 0) ; Avoid scrolling right on long lines.
+ (when (helm-pos-multiline-p)
+ (helm-move--beginning-of-multiline-candidate))
+ (when (helm-pos-header-line-p) (forward-line 1))
+ (when helm-allow-mouse
+ (helm--mouse-reset-selection-help-echo))
+ (helm-mark-current-line)
+ (helm-display-mode-line (or source (helm-get-current-source)))
+ (helm-log-run-hook 'helm-after-preselection-hook)))
+
+(defun helm-delete-current-selection ()
+ "Delete the currently selected item."
+ (with-helm-window
+ (cond ((helm-pos-multiline-p)
+ (helm-aif (helm-get-next-candidate-separator-pos)
+ (delete-region (point-at-bol)
+ (1+ (progn (goto-char it) (point-at-eol))))
+ ;; last candidate
+ (goto-char (helm-get-previous-candidate-separator-pos))
+ (delete-region (point-at-bol) (point-max)))
+ (when (helm-end-of-source-p)
+ (goto-char (or (helm-get-previous-candidate-separator-pos)
+ (point-min)))
+ (forward-line 1)))
+ (t
+ (delete-region (point-at-bol) (1+ (point-at-eol)))
+ (when (helm-end-of-source-p t)
+ (let ((headp (save-excursion
+ (forward-line -1)
+ (not (helm-pos-header-line-p)))))
+ (and headp (forward-line -1))))))
+ (unless (helm-end-of-source-p t)
+ (helm-mark-current-line))))
+
+(defun helm-end-of-source-1 (n at-point)
+ (save-excursion
+ (if (and (helm-pos-multiline-p) (null at-point))
+ (null (helm-get-next-candidate-separator-pos))
+ (forward-line (if at-point 0 n))
+ (or (eq (point-at-bol) (point-at-eol))
+ (helm-pos-header-line-p)
+ (if (< n 0) (bobp) (eobp))))))
+
+(defun helm-end-of-source-p (&optional at-point)
+ "Return non-`nil' if we are at eob or end of source."
+ (helm-end-of-source-1 1 at-point))
+
+(defun helm-beginning-of-source-p (&optional at-point)
+ "Return non-`nil' if we are at bob or beginning of source."
+ (helm-end-of-source-1 -1 at-point))
+
+(defun helm--edit-current-selection-internal (func)
+ (with-helm-window
+ (forward-line 0)
+ (let ((realvalue (get-text-property (point) 'helm-realvalue))
+ (multiline (get-text-property (point) 'helm-multiline)))
+ (funcall func)
+ (forward-line 0)
+ (and realvalue
+ (put-text-property (point) (point-at-eol)
+ 'helm-realvalue realvalue))
+ (and multiline
+ (put-text-property (point)
+ (or (helm-get-next-candidate-separator-pos)
+ (point-max))
+ 'helm-multiline multiline))
+ (helm-mark-current-line))))
+
+(defmacro helm-edit-current-selection (&rest forms)
+ "Evaluate FORMS at current selection in the helm buffer.
+Used generally to modify current selection."
+ (declare (indent 0) (debug t))
+ `(helm--edit-current-selection-internal
+ (lambda () ,@forms)))
+
+(defun helm--delete-minibuffer-contents-from (from-str)
+ ;; Giving an empty string value to FROM-STR delete all.
+ (let ((input (minibuffer-contents)))
+ (helm-reset-yank-point)
+ (if (> (length input) 0)
+ ;; minibuffer is not empty, delete contents from end
+ ;; of FROM-STR and update.
+ (helm-set-pattern from-str)
+ ;; minibuffer is already empty, force update.
+ (helm-force-update))))
+
+(defun helm-delete-minibuffer-contents (&optional arg)
+ "Delete minibuffer contents.
+When `helm-delete-minibuffer-contents-from-point' is non-`nil',
+delete minibuffer contents from point instead of deleting all.
+Giving a prefix arg reverses this behavior.
+When at the end of minibuffer, deletes all."
+ (interactive "P")
+ (let ((str (if helm-delete-minibuffer-contents-from-point
+ (if (or arg (eobp))
+ "" (helm-minibuffer-completion-contents))
+ (if (and arg (not (eobp)))
+ (helm-minibuffer-completion-contents) ""))))
+ (helm--delete-minibuffer-contents-from str)))
+
+\f
+;;; helm-source-in-buffer.
+;;
+(defun helm-candidates-in-buffer (&optional source)
+ "The top level function used to store candidates with `helm-source-in-buffer'.
+
+Candidates are stored in a buffer generated internally
+by `helm-candidate-buffer' function.
+Each candidate must be placed in one line.
+
+The buffer is created and fed in the init attribute function of helm.
+
+e.g:
+
+ (helm-build-in-buffer-source \"test\"
+ :init (lambda ()
+ (helm-init-candidates-in-buffer
+ 'global '(foo foa fob bar baz))))
+
+A shortcut can be used to simplify:
+
+ (helm-build-in-buffer-source \"test\"
+ :data '(foo foa fob bar baz))
+
+By default, `helm' makes candidates by evaluating the
+candidates function, then narrows them by `string-match' for each
+candidate.
+
+But this is slow for large number of candidates. The new way is
+to store all candidates in a buffer and then narrow
+with `re-search-forward'. Search function is customizable by search
+attribute. The important point is that buffer processing is MUCH
+FASTER than string list processing and is the Emacs way.
+
+The init function writes all candidates to a newly-created
+candidate buffer. The candidates buffer is created or specified
+by `helm-candidate-buffer'. Candidates are stored in a line.
+
+The candidates function narrows all candidates, IOW creates a
+subset of candidates dynamically.
+
+Class `helm-source-in-buffer' is implemented with three attributes:
+
+ (candidates . helm-candidates-in-buffer)
+ (volatile)
+ (match identity)
+
+The volatile attribute is needed because `helm-candidates-in-buffer'
+creates candidates dynamically and need to be called every
+time `helm-pattern' changes.
+
+Because `helm-candidates-in-buffer' plays the role of `match' attribute
+function, specifying `(match identity)' makes the source slightly faster.
+
+However if source contains `match-part' attribute, match is computed only
+on part of candidate returned by the call of function provided by this attribute.
+The function should have one arg, candidate, and return only
+a specific part of candidate.
+
+To customize `helm-candidates-in-buffer' behavior,
+use `search', `get-line' and `match-part' attributes."
+ (let ((src (or source (helm-get-current-source))))
+ (helm-candidates-in-buffer-1
+ (helm-candidate-buffer)
+ helm-pattern
+ (or (assoc-default 'get-line src)
+ #'buffer-substring-no-properties)
+ (or (assoc-default 'search src)
+ '(helm-candidates-in-buffer-search-default-fn))
+ (helm-candidate-number-limit src)
+ (helm-attr 'match-part)
+ src)))
+
+(defun helm-candidates-in-buffer-search-default-fn (pattern)
+ "Search PATTERN with `re-search-forward' with bound and noerror args."
+ (condition-case _err
+ (re-search-forward pattern nil t)
+ (invalid-regexp nil)))
+
+(defun helm-candidates-in-buffer-1 (buffer pattern get-line-fn
+ search-fns limit
+ match-part-fn source)
+ "Return the list of candidates inserted in BUFFER matching PATTERN."
+ ;; buffer == nil when candidates buffer does not exist.
+ (when buffer
+ (with-current-buffer buffer
+ (let ((inhibit-point-motion-hooks t)
+ (start-point (1- (point-min))))
+ (goto-char start-point)
+ (if (string= pattern "")
+ (helm-initial-candidates-from-candidate-buffer
+ get-line-fn limit)
+ (helm-search-from-candidate-buffer
+ pattern get-line-fn search-fns limit
+ start-point match-part-fn source))))))
+
+
+(defun helm-search-from-candidate-buffer (pattern get-line-fn search-fns
+ limit start-point match-part-fn source)
+ (let ((inhibit-read-only t))
+ (helm--search-from-candidate-buffer-1
+ (lambda ()
+ (cl-loop with hash = (make-hash-table :test 'equal)
+ with allow-dups = (assq 'allow-dups source)
+ with case-fold-search = (helm-set-case-fold-search)
+ with count = 0
+ for iter from 1
+ for searcher in search-fns
+ do (progn
+ (goto-char start-point)
+ ;; The character at start-point is a newline,
+ ;; if pattern match it that's mean we are
+ ;; searching for newline in buffer, in this
+ ;; case skip this false line.
+ ;; See comment >>>[1] in
+ ;; `helm--search-from-candidate-buffer-1'.
+ (and (condition-case nil
+ (looking-at pattern)
+ (invalid-regexp nil))
+ (forward-line 1)))
+ nconc
+ (cl-loop with pos-lst
+ while (and (setq pos-lst (funcall searcher pattern))
+ (not (eobp))
+ (< count limit))
+ for cand = (apply get-line-fn
+ (if (and pos-lst (listp pos-lst))
+ pos-lst
+ (list (point-at-bol) (point-at-eol))))
+ when (and match-part-fn
+ (not (get-text-property 0 'match-part cand)))
+ do (setq cand
+ (propertize cand 'match-part (funcall match-part-fn cand)))
+ for dup = (gethash cand hash)
+ when (and (or (and allow-dups dup (= dup iter))
+ (null dup))
+ (or
+ ;; Always collect when cand is matched
+ ;; by searcher funcs and match-part attr
+ ;; is not present.
+ (and (not match-part-fn)
+ (not (consp pos-lst)))
+ ;; If match-part attr is present, or if SEARCHER fn
+ ;; returns a cons cell, collect PATTERN only if it
+ ;; match the part of CAND specified by
+ ;; the match-part func.
+ (helm-search-match-part cand pattern)))
+ do (progn
+ (puthash cand iter hash)
+ (helm--maybe-process-filter-one-by-one-candidate cand source)
+ (cl-incf count))
+ and collect cand))))))
+
+(defun helm-search-match-part (candidate pattern)
+ "Match PATTERN only on match-part property value of CANDIDATE.
+
+Because `helm-search-match-part' maybe called even if unspecified
+in source (negation or fuzzy), the part to match fallback to the whole
+candidate even if match-part haven't been computed by match-part-fn
+and stored in the match-part property."
+ (let ((part (or (get-text-property 0 'match-part candidate)
+ candidate))
+ (fuzzy-regexp (cadr (gethash 'helm-pattern helm--fuzzy-regexp-cache)))
+ (matchfn (if helm-migemo-mode
+ 'helm-mm-migemo-string-match 'string-match)))
+ (if (string-match " " pattern)
+ (cl-loop for i in (helm-mm-split-pattern pattern) always
+ (if (string-match "\\`!" i)
+ (not (funcall matchfn (substring i 1) part))
+ (funcall matchfn i part)))
+ (if (string-match "\\`!" pattern)
+ (if helm--in-fuzzy
+ ;; Fuzzy regexp have already been
+ ;; computed with substring 1.
+ (not (string-match fuzzy-regexp part))
+ (not (funcall matchfn (substring pattern 1) part)))
+ (funcall matchfn (if helm--in-fuzzy fuzzy-regexp pattern) part)))))
+
+(defun helm-initial-candidates-from-candidate-buffer (get-line-fn limit)
+ (delq nil (cl-loop for i from 1 to limit
+ until (eobp)
+ collect (funcall get-line-fn
+ (point-at-bol) (point-at-eol))
+ do (forward-line 1))))
+
+(defun helm--search-from-candidate-buffer-1 (search-fn)
+ ;; We are adding a newline at bob and at eol
+ ;; and removing these newlines afterward.
+ ;; This is a bad hack that should be removed.
+ ;; To avoid matching the empty line at first line
+ ;; when searching with e.g occur and "^$" just
+ ;; forward-line before searching (See >>>[1] above).
+ (goto-char (point-min))
+ (insert "\n")
+ (goto-char (point-max))
+ (insert "\n")
+ (unwind-protect
+ (funcall search-fn)
+ (goto-char (point-min))
+ (delete-char 1)
+ (goto-char (1- (point-max)))
+ (delete-char 1)
+ (set-buffer-modified-p nil)))
+
+(defun helm-candidate-buffer (&optional buffer-spec)
+ "Register and return a buffer storing candidates of current source.
+
+This is used to initialize a buffer for storing candidates for a
+candidates-in-buffer source, candidates will be searched in this
+buffer and displayed in `helm-buffer'.
+This should be used only in init functions, don't relay on this in
+other places unless you know what you are doing.
+
+This function is still in public API only for backward compatibility,
+you should use instead `helm-init-candidates-in-buffer' for
+initializing your sources.
+
+Internally, this function is called without argument and returns the
+buffer corresponding to current source i.e `helm--source-name' which
+is available in only some places.
+
+Acceptable values of BUFFER-SPEC:
+
+- global (a symbol)
+ Create a new global candidates buffer,
+ named \" *helm candidates:SOURCE*\".
+ This is used by `helm-init-candidates-in-buffer' and it is
+ the most common usage of BUFFER-SPEC.
+ The buffer will be killed and recreated at each new helm-session.
+
+- local (a symbol)
+ Create a new local candidates buffer,
+ named \" *helm candidates:SOURCE*HELM-CURRENT-BUFFER\".
+ You may want to use this when you want to have a different buffer
+ each time source is used from a different `helm-current-buffer'.
+ The buffer is erased and refilled at each new session but not killed.
+ You probably don't want to use this value for BUFFER-SPEC.
+
+- nil (omit)
+ Only return the candidates buffer of current source if found.
+
+- A buffer
+ Register a buffer as a candidates buffer.
+ The buffer needs to exists, it is not created.
+ This allow you to use the buffer as a cache, it is faster because
+ the buffer is already drawn, but be careful when using this as you
+ may mangle your buffer depending what you write in your init(s)
+ function, IOW don't modify the contents of the buffer in init(s)
+ function but in a transformer.
+ The buffer is not erased nor deleted.
+ Generally it is safer to use a copy of buffer inserted
+ in a global or local buffer.
+
+If for some reasons a global buffer and a local buffer exist and are
+belonging to the same source, the local buffer takes precedence on the
+global one and is used instead.
+
+When forcing update only the global and local buffers are killed
+before running again the init function."
+ (let ((global-bname (format " *helm candidates:%s*"
+ helm--source-name))
+ (local-bname (format " *helm candidates:%s*%s"
+ helm--source-name
+ (buffer-name helm-current-buffer))))
+ (when buffer-spec
+ ;; Register buffer in `helm--candidate-buffer-alist'.
+ ;; This is used only to retrieve buffer associated to current source
+ ;; when using named buffer as value of BUFFER-SPEC.
+ (setq helm--candidate-buffer-alist
+ (cons (cons helm--source-name buffer-spec)
+ (delete (assoc helm--source-name
+ helm--candidate-buffer-alist)
+ helm--candidate-buffer-alist)))
+ ;; When using global or local as value of CREATE-OR-BUFFER
+ ;; create the buffer global-bname or local-bname, otherwise
+ ;; reuse the named buffer.
+ (unless (bufferp buffer-spec)
+ ;; Global buffers are killed and recreated.
+ (and (eq buffer-spec 'global)
+ (buffer-live-p (get-buffer global-bname))
+ (kill-buffer global-bname))
+ ;; Create global or local buffer.
+ ;; Local buffer, once created are reused and a new one
+ ;; is created when `helm-current-buffer' change across sessions.
+ (with-current-buffer (get-buffer-create
+ (cl-ecase buffer-spec
+ (global global-bname)
+ (local local-bname)))
+ ;; We need a buffer not read-only to perhaps insert later
+ ;; text coming from read-only buffers (issue #1176).
+ (set (make-local-variable 'buffer-read-only) nil)
+ ;; Undo is automatically disabled in buffer names starting
+ ;; with a space, so no need to disable it.
+ (erase-buffer)
+ (font-lock-mode -1))))
+ ;; Finally return the candidates buffer.
+ (helm-acond ((get-buffer local-bname))
+ ((get-buffer global-bname))
+ ((assoc-default helm--source-name helm--candidate-buffer-alist)
+ (and (or (stringp it) (bufferp it))
+ (buffer-live-p (get-buffer it))
+ it)))))
+
+(defun helm-init-candidates-in-buffer (buffer-spec data)
+ "Register BUFFER-SPEC with DATA for a helm candidates-in-buffer session.
+
+Arg BUFFER-SPEC can be a buffer-name (stringp), a buffer-spec object
+\(bufferp), or a symbol, either 'local or 'global which is passed to
+`helm-candidate-buffer'.
+The most common usage of BUFFER-SPEC is 'global.
+
+Arg DATA can be either a list or a plain string.
+Returns the resulting buffer.
+
+Use this in your init function to register a buffer for a
+`helm-source-in-buffer' session and feed it with DATA.
+You probably don't want to bother with this and use the :data slot
+when initializing a source with `helm-source-in-buffer' class."
+ (declare (indent 1))
+ (let ((caching (and (or (stringp buffer-spec)
+ (bufferp buffer-spec))
+ (buffer-live-p (get-buffer buffer-spec))))
+ (buf (helm-candidate-buffer
+ (if (or (stringp buffer-spec)
+ (bufferp buffer-spec))
+ (get-buffer-create buffer-spec)
+ buffer-spec)))) ; a symbol 'global or 'local.
+ (unless caching
+ (with-current-buffer buf
+ (erase-buffer)
+ (cond ((listp data)
+ (insert (mapconcat (lambda (i)
+ (cond ((symbolp i) (symbol-name i))
+ ((numberp i) (number-to-string i))
+ (t i)))
+ data "\n")))
+ ((stringp data) (insert data))))
+ buf)))
+
+\f
+;;; Resplit helm window
+;;
+;;
+(defun helm-toggle-resplit-window ()
+ "Toggle resplit helm window, vertically or horizontally."
+ (interactive)
+ (with-helm-alive-p
+ (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)))
+ (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))))
+ (error "current window configuration not suitable for splitting"))))
+(put 'helm-toggle-resplit-window 'helm-only t)
+
+;; Utility: Resize helm window.
+(defun helm-enlarge-window-1 (n)
+ "Enlarge or narrow helm window.
+If N is positive enlarge, if negative narrow."
+ (unless helm-full-frame
+ (let ((horizontal-p (eq helm-split-window-state 'horizontal)))
+ (with-helm-window
+ (enlarge-window n horizontal-p)))))
+
+(defun helm-narrow-window ()
+ "Narrow helm window."
+ (interactive)
+ (with-helm-alive-p
+ (helm-enlarge-window-1 -1)))
+(put 'helm-narrow-window 'helm-only t)
+
+(defun helm-enlarge-window ()
+ "Enlarge helm window."
+ (interactive)
+ (with-helm-alive-p
+ (helm-enlarge-window-1 1)))
+(put 'helm-enlarge-window 'helm-only t)
+
+(defun helm-toggle-full-frame (&optional arg)
+ "Toggle helm-buffer full-frame view."
+ (interactive "p")
+ (cl-assert (null (helm-action-window))
+ nil "Unable to toggle full frame from action window")
+ (when arg ; Called interactively
+ (cl-assert (null helm--buffer-in-new-frame-p)
+ nil "Can't toggle full frame when using helm own frame"))
+ (if (or helm-onewindow-p
+ (buffer-local-value 'helm-full-frame (get-buffer helm-buffer)))
+ (with-helm-window
+ (setq-local helm-full-frame nil)
+ (setq helm-onewindow-p nil)
+ (let ((split-window-preferred-function
+ helm-split-window-preferred-function))
+ (switch-to-buffer helm-current-buffer)
+ (helm-display-buffer helm-buffer)
+ (select-window (minibuffer-window))))
+ (with-helm-window
+ (delete-other-windows)
+ (setq-local helm-full-frame t)
+ (setq helm-onewindow-p t))))
+(put 'helm-toggle-full-frame 'helm-only t)
+
+(defun helm-swap-windows ()
+ "Swap window holding `helm-buffer' with other window."
+ (interactive)
+ (with-helm-alive-p
+ (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))
+ (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)))))
+ (error "current window configuration not suitable for splitting"))))
+(put 'helm-swap-windows 'helm-only t)
+
+(defun helm--get-window-side-state ()
+ "Return the position of `helm-window' from `helm-current-buffer'.
+Possible values are 'left 'right 'below or 'above."
+ (let ((side-list '(left right below above)))
+ (cl-loop for side in side-list
+ thereis (and (equal (helm-window)
+ (window-in-direction
+ side (get-buffer-window helm-current-buffer t)
+ t))
+ side))))
+
+(defun helm-replace-buffer-in-window (window buffer1 buffer2)
+ "Replace BUFFER1 by BUFFER2 in WINDOW registering BUFFER1."
+ (when (get-buffer-window buffer1)
+ (unrecord-window-buffer window buffer1)
+ (set-window-buffer window buffer2)))
+
+;; Utility: select another action by key
+(defun helm-select-nth-action (n)
+ "Select the N nth action for the currently selected candidate."
+ (let ((src (helm-get-current-source)))
+ (setq helm-saved-selection (helm-get-selection nil nil src))
+ (unless helm-saved-selection
+ (error "Nothing is selected"))
+ (setq helm-saved-action
+ (helm-get-nth-action
+ n
+ (if (get-buffer-window helm-action-buffer 'visible)
+ (assoc-default 'candidates src)
+ (helm-get-actions-from-current-source src))))
+ (helm-maybe-exit-minibuffer)))
+
+(defun helm-get-nth-action (n action)
+ (cond ((and (zerop n) (functionp action))
+ action)
+ ((listp action)
+ (or (cdr (elt action n))
+ (error "No such action")))
+ ((and (functionp action) (< 0 n))
+ (error "Sole action"))
+ (t
+ (error "Error in `helm-select-nth-action'"))))
+
+(defun helm-execute-selection-action-at-nth (linum)
+ "Execute default action on candidate at LINUM lines from selection."
+ (let ((prefarg current-prefix-arg))
+ (if (>= linum 0)
+ (helm-next-line linum)
+ (helm-previous-line (lognot (1- linum))))
+ (setq current-prefix-arg prefarg)
+ (helm-exit-minibuffer)))
+\f
+;;; Persistent Action
+;;
+(defun helm-initialize-persistent-action ()
+ (set (make-local-variable 'helm-persistent-action-display-window) nil))
+
+(cl-defun helm-execute-persistent-action (&optional attr split-onewindow)
+ "Perform the associated action ATTR without quitting helm.
+Arg ATTR default will be `persistent-action' or `persistent-action-if'
+if unspecified depending on what's found in source, but it can be
+anything else.
+In this case you have to add this new attribute to your source.
+See `persistent-action' and `persistent-action-if' slot documentation
+in `helm-source'.
+
+When `helm-full-frame' or SPLIT-ONEWINDOW are non-`nil', and
+`helm-buffer' is displayed in only one window, the helm window is
+split to display `helm-select-persistent-action-window' in other
+window to maintain visibility."
+ (interactive)
+ (with-helm-alive-p
+ (let ((source (helm-get-current-source)))
+ (unless attr
+ (setq attr (or (car (assq 'persistent-action source))
+ (car (assq 'persistent-action-if source)))))
+ (helm-log "executing persistent-action")
+ (let* ((selection (and source (helm-get-selection nil nil source)))
+ (attr-val (if (eq attr 'persistent-action-if)
+ (funcall (assoc-default attr source) selection)
+ (assoc-default attr source)))
+ ;; If attr value is a cons, use its car as persistent function
+ ;; and its car to decide if helm window should be splitted.
+ (fn (if (and (consp attr-val)
+ ;; maybe a lambda.
+ (not (functionp attr-val)))
+ (car attr-val) attr-val))
+ (no-split (and (consp attr-val)
+ (not (functionp attr-val))
+ (cdr attr-val)))
+ (cursor-in-echo-area t)
+ mode-line-in-non-selected-windows)
+ (progn
+ (when (and helm-onewindow-p (null no-split)
+ (null helm--buffer-in-new-frame-p))
+ (helm-toggle-full-frame))
+ (when (eq fn 'ignore)
+ (cl-return-from helm-execute-persistent-action nil))
+ (when source
+ (with-helm-window
+ (save-selected-window
+ (if no-split
+ (helm-select-persistent-action-window)
+ (helm-select-persistent-action-window
+ (or split-onewindow helm-onewindow-p)))
+ (helm-log "current-buffer = %S" (current-buffer))
+ (let ((helm-in-persistent-action t)
+ (same-window-regexps '("."))
+ display-buffer-function pop-up-windows pop-up-frames
+ special-display-regexps special-display-buffer-names)
+ (helm-execute-selection-action-1
+ selection (or fn (helm-get-actions-from-current-source source)) t)
+ (unless (helm-action-window)
+ (helm-log-run-hook 'helm-after-persistent-action-hook)))
+ ;; A typical case is when a persistent action delete
+ ;; the buffer already displayed in
+ ;; `helm-persistent-action-display-window' and `helm-full-frame'
+ ;; is enabled, we end up with the `helm-buffer'
+ ;; displayed in two windows.
+ (when (and helm-onewindow-p
+ (> (length (window-list)) 1)
+ (equal (buffer-name
+ (window-buffer
+ helm-persistent-action-display-window))
+ (helm-buffer-get)))
+ (delete-other-windows))))))))))
+(put 'helm-execute-persistent-action 'helm-only t)
+
+(defun helm-persistent-action-display-window (&optional split-onewindow)
+ "Return the window that will be used for persistent action.
+If SPLIT-ONEWINDOW is non-`nil' window is split in persistent action."
+ (with-helm-window
+ (let (next-win cur-win)
+ (setq helm-persistent-action-display-window
+ (cond ((and (window-live-p helm-persistent-action-display-window)
+ (not (member helm-persistent-action-display-window
+ (get-buffer-window-list helm-buffer))))
+ helm-persistent-action-display-window)
+ ((and helm--buffer-in-new-frame-p helm-initial-frame)
+ (with-selected-frame helm-initial-frame (selected-window)))
+ (split-onewindow (split-window))
+ ;; Fix Issue #2050 with dedicated window.
+ ((window-dedicated-p
+ (setq next-win (next-window (selected-window) 1)))
+ (with-helm-after-update-hook
+ (and (window-live-p helm-persistent-action-display-window)
+ (delete-window helm-persistent-action-display-window)))
+ (split-window))
+ ((window-dedicated-p
+ (setq cur-win (get-buffer-window helm-current-buffer)))
+ (split-window))
+ (cur-win)
+ (t next-win))))))
+
+(defun helm-select-persistent-action-window (&optional split-onewindow)
+ "Select the window that will be used for persistent action.
+See `helm-persistent-action-display-window' for how to use SPLIT-ONEWINDOW."
+ (select-window (get-buffer-window (helm-buffer-get)))
+ (prog1
+ (select-window
+ (setq minibuffer-scroll-window
+ (helm-persistent-action-display-window split-onewindow)))
+ (helm-log "Selected window is %S" minibuffer-scroll-window)))
+\f
+;;; Scrolling - recentering
+;;
+;;
+(defun helm-other-window-base (command &optional arg)
+ (let ((minibuffer-scroll-window
+ (helm-persistent-action-display-window)))
+ (funcall command (or arg helm-scroll-amount))))
+
+(defun helm-scroll-other-window (&optional arg)
+ "Scroll other window upward ARG many lines.
+When arg is not provided scroll `helm-scroll-amount' lines.
+See `scroll-other-window'."
+ (interactive "P")
+ (with-helm-alive-p (helm-other-window-base 'scroll-other-window arg)))
+(put 'helm-scroll-other-window 'helm-only t)
+
+(defun helm-scroll-other-window-down (&optional arg)
+ "Scroll other window downward ARG many lines.
+When arg is not provided scroll `helm-scroll-amount' lines.
+See `scroll-other-window-down'."
+ (interactive "P")
+ (with-helm-alive-p (helm-other-window-base 'scroll-other-window-down arg)))
+(put 'helm-scroll-other-window-down 'helm-only t)
+
+(defun helm-recenter-top-bottom-other-window (&optional arg)
+ "Run `recenter-top-bottom' in other window.
+Meaning of prefix ARG is the same as in `recenter-top-bottom'."
+ (interactive "P")
+ (with-helm-alive-p
+ (with-helm-window
+ (with-selected-window (helm-persistent-action-display-window)
+ (recenter-top-bottom arg)))))
+(put 'helm-recenter-top-bottom-other-window 'helm-only t)
+
+(defun helm-reposition-window-other-window (&optional arg)
+ "Run `reposition-window' in other window.
+Meaning of prefix ARG is the same as in `reposition-window'."
+ (interactive "P")
+ (with-helm-alive-p
+ (with-helm-window
+ (with-selected-window (helm-persistent-action-display-window)
+ (reposition-window arg)))))
+(put 'helm-reposition-window-other-window 'helm-only t)
+
+\f
+;; Utility: Visible Mark
+
+(defun helm-clear-visible-mark ()
+ (with-current-buffer (helm-buffer-get)
+ (mapc 'delete-overlay helm-visible-mark-overlays)
+ (set (make-local-variable 'helm-visible-mark-overlays) nil)))
+
+(defun helm-this-visible-mark ()
+ (cl-loop for o in (overlays-at (point))
+ when (overlay-get o 'visible-mark)
+ return o))
+
+(defun helm-delete-visible-mark (overlay)
+ (let ((src (helm-get-current-source)))
+ (setq helm-marked-candidates
+ (remove
+ (cons src (helm-get-selection nil nil src))
+ helm-marked-candidates))
+ (delete-overlay overlay)
+ (setq helm-visible-mark-overlays
+ (delq overlay helm-visible-mark-overlays))))
+
+(defun helm-make-visible-mark (&optional src selection)
+ (let* ((source (or src (helm-get-current-source)))
+ (sel (or selection (helm-get-selection
+ nil (helm-attr 'marked-with-props source)
+ source)))
+ (selection-end (if (helm-pos-multiline-p)
+ ;; Stays within source
+ (or (helm-get-next-candidate-separator-pos)
+ (helm-get-next-header-pos)
+ (point-max))
+ ;; Not multiline
+ (1+ (point-at-eol))))
+ (o (make-overlay (point-at-bol) selection-end)))
+ (overlay-put o 'priority 0)
+ (overlay-put o 'face 'helm-visible-mark)
+ (overlay-put o 'source (assoc-default 'name source))
+ (overlay-put o 'string (buffer-substring (overlay-start o) (overlay-end o)))
+ (overlay-put o 'real sel)
+ (overlay-put o 'visible-mark t)
+ (cl-pushnew o helm-visible-mark-overlays)
+ (push (cons source sel) helm-marked-candidates)))
+
+(defun helm-toggle-visible-mark (arg)
+ "Toggle helm visible mark at point ARG times.
+If ARG is negative toggle backward."
+ (interactive "p")
+ (with-helm-alive-p
+ (with-helm-window
+ (let ((nomark (assq 'nomark (helm-get-current-source)))
+ (next-fns (if (< arg 0)
+ '(helm-beginning-of-source-p . helm-previous-line)
+ '(helm-end-of-source-p . helm-next-line))))
+ (if nomark
+ (message "Marking not allowed in this source")
+ (cl-loop with n = (if (< arg 0) (* arg -1) arg)
+ repeat n do
+ (progn
+ (helm-aif (helm-this-visible-mark)
+ (helm-delete-visible-mark it)
+ (helm-make-visible-mark))
+ (if (funcall (car next-fns))
+ (progn
+ (helm-display-mode-line (helm-get-current-source))
+ (cl-return nil))
+ (funcall (cdr next-fns))))))))))
+(put 'helm-toggle-visible-mark 'helm-only t)
+
+(defun helm-file-completion-source-p (&optional source)
+ "Return non-`nil' if current source is a file completion source."
+ (or helm--completing-file-name ; helm-read-file-name
+ (let ((cur-source (cdr (assq 'name
+ (or source (helm-get-current-source))))))
+ (cl-loop for i in helm--file-completion-sources
+ thereis (string= cur-source i)))))
+
+(defun helm-mark-all (&optional all)
+ "Mark all visible unmarked candidates in current source.
+
+With a prefix arg mark all visible unmarked candidates in all sources."
+ (interactive "P")
+ (with-helm-alive-p
+ (with-helm-window ; Using `with-helm-buffer' for some unknow reasons infloop.
+ (if (null all)
+ (helm-mark-all-1 t)
+ (let ((pos (point)))
+ (goto-char (point-min))
+ (helm-awhile (helm-get-next-header-pos)
+ (goto-char it)
+ (forward-line 1)
+ (helm-mark-current-line)
+ (helm-mark-all-1))
+ ;; `save-excursion' seems confused if used in addition of
+ ;; the one used in `helm-mark-all-1', so save POS and back
+ ;; to it when loop is finished.
+ (goto-char pos)
+ (helm-mark-current-line)
+ (helm-display-mode-line (helm-get-current-source) t))))))
+(put 'helm-mark-all 'helm-only t)
+
+(defun helm-mark-all-1 (&optional ensure-beg-of-source)
+ "Mark all visible unmarked candidates in current source.
+Need to be wrapped in `with-helm-window'.
+Arg ENSURE-BEG-OF-SOURCE ensure we are at beginning of source when
+starting to mark candidates, if handled elsewhere before starting it
+is not needed."
+ (let* ((src (helm-get-current-source))
+ (follow (if (helm-follow-mode-p src) 1 -1))
+ (nomark (assq 'nomark src))
+ (src-name (assoc-default 'name src))
+ (filecomp-p (or (helm-file-completion-source-p src)
+ (string= src-name "Files from Current Directory")))
+ (remote-p (and filecomp-p (file-remote-p helm-pattern))))
+ ;; Note that `cl-letf' prevents edebug working properly.
+ (cl-letf (((symbol-function 'message) #'ignore))
+ (helm-follow-mode -1)
+ (unwind-protect
+ (if nomark
+ (message "Marking not allowed in this source")
+ (save-excursion
+ (when ensure-beg-of-source
+ (goto-char (helm-get-previous-header-pos))
+ (forward-line 1))
+ (let* ((next-head (helm-get-next-header-pos))
+ (end (and next-head
+ (save-excursion
+ (goto-char next-head)
+ (forward-line -1)
+ (point))))
+ (maxpoint (or end (point-max))))
+ (while (< (point) maxpoint)
+ (helm-mark-current-line)
+ (let* ((prefix (get-text-property (point-at-bol) 'display))
+ (cand (helm-get-selection nil nil src))
+ (bn (and filecomp-p (helm-basename cand))))
+ ;; Don't mark possibles directories ending with . or ..
+ ;; autosave files/links and non--existent files.
+ (unless
+ (or (helm-this-visible-mark)
+ (string= prefix "[?]") ; doesn't match
+ (and filecomp-p
+ (or
+ ;; autosave files
+ (string-match-p "^[.]?#.*#?$" bn)
+ ;; dot files
+ (member bn '("." ".."))
+ ;; We need to test here when not using
+ ;; a transformer that put a prefix tag
+ ;; before candidate.
+ ;; (i.e no [?] prefix on tramp).
+ (and remote-p (not (file-exists-p cand))))))
+ (helm-make-visible-mark src cand)))
+ (when (helm-pos-multiline-p)
+ (goto-char
+ (or (helm-get-next-candidate-separator-pos)
+ (point-max))))
+ (forward-line 1))))
+ (helm-mark-current-line))
+ (helm-follow-mode follow)))))
+
+(defun helm-unmark-all ()
+ "Unmark all candidates in all sources of current helm session."
+ (interactive)
+ (with-helm-alive-p
+ (with-helm-window
+ (save-excursion
+ (helm-clear-visible-mark))
+ (setq helm-marked-candidates nil)
+ (helm-mark-current-line)
+ (helm-display-mode-line (helm-get-current-source)))))
+(put 'helm-unmark-all 'helm-only t)
+
+(defun helm-toggle-all-marks (&optional all)
+ "Toggle all marks.
+
+Mark all visible candidates of current source or unmark all candidates
+visible or invisible in all sources of current helm session.
+
+With a prefix argument mark all candidates in all sources."
+ (interactive "P")
+ (with-helm-alive-p
+ (let ((marked (helm-marked-candidates)))
+ (if (and (>= (length marked) 1)
+ (with-helm-window helm-visible-mark-overlays))
+ (helm-unmark-all)
+ (helm-mark-all all)))))
+(put 'helm-toggle-all-marks 'helm-only t)
+
+(defun helm--compute-marked (real source &optional wildcard)
+ (let* ((coerced (helm-coerce-selection real source))
+ (wilds (and wildcard
+ (condition-case nil
+ (helm-file-expand-wildcards
+ coerced t)
+ (error nil)))))
+ ;; Avoid returning a not expanded wilcard fname.
+ ;; e.g assuming "/tmp" doesn't contain "*.el"
+ ;; return nil when coerced is "/tmp/*.el".
+ (unless (or wilds (null wildcard)
+ (string-match-p helm--url-regexp coerced)
+ (file-exists-p coerced)
+ (and (stringp coerced)
+ (null (string-match-p "[[*?]" coerced))))
+ (setq coerced nil))
+ (or wilds (and coerced (list coerced)))))
+
+(cl-defun helm-marked-candidates (&key with-wildcard all-sources)
+ "Return marked candidates of current source, if any.
+
+Otherwise return one element list consisting of the current
+selection. When key WITH-WILDCARD is specified, expand it.
+When ALL-SOURCES key value is non-nil returns marked candidates of all
+sources."
+ (with-current-buffer helm-buffer
+ (let* ((current-src (helm-get-current-source))
+ (candidates
+ (cl-loop for (source . real) in (reverse helm-marked-candidates)
+ for use-wc = (and with-wildcard
+ (string-match-p "\\*" real)
+ (null (file-exists-p real)))
+ when (or all-sources
+ (equal (assq 'name source)
+ (assq 'name current-src)))
+ append (helm--compute-marked real source use-wc)))
+ sel)
+ (unless candidates
+ (setq sel (helm-get-selection
+ nil (helm-attr 'marked-with-props
+ current-src)
+ current-src))
+ (setq candidates
+ (helm--compute-marked
+ sel current-src
+ (and with-wildcard (null (file-exists-p sel))))))
+ (helm-log "Marked candidates = %S" candidates)
+ candidates)))
+
+(defun helm--remove-marked-and-update-mode-line (elm)
+ (with-helm-buffer
+ (setq helm-marked-candidates
+ (delete (rassoc elm helm-marked-candidates)
+ helm-marked-candidates))
+ (helm-display-mode-line (helm-get-current-source))))
+
+(defun helm-current-source-name= (name)
+ (save-excursion
+ (goto-char (helm-get-previous-header-pos))
+ (equal name (helm-current-line-contents))))
+
+(defun helm-revive-visible-mark ()
+ "Restore marked candidates when helm updates display."
+ (with-current-buffer helm-buffer
+ (save-excursion
+ (cl-dolist (o helm-visible-mark-overlays)
+ (let ((o-src-str (overlay-get o 'source))
+ (o-str (overlay-get o 'string))
+ beg end)
+ ;; Move point to end of source header line.
+ (goto-char (point-min))
+ (search-forward o-src-str nil t)
+ (while (and (search-forward o-str nil t)
+ (cl-loop for ov in (overlays-at (point-at-bol 0))
+ never (overlay-get ov 'visible-mark))
+ (helm-current-source-name= o-src-str))
+ (setq beg (match-beginning 0)
+ end (match-end 0))
+ ;; Calculate real value of candidate.
+ ;; It can be nil if candidate have only a display value.
+ (let ((real (get-text-property (point-at-bol 0) 'helm-realvalue)))
+ (if real
+ ;; Check if real value of current candidate is the same
+ ;; than the one stored in overlay.
+ ;; This is needed when some cands have same display names.
+ ;; Using equal allow testing any type of value for real cand.
+ ;; Issue (#706).
+ (and (equal (overlay-get o 'real) real)
+ (move-overlay o beg end))
+ (and (equal o-str (buffer-substring beg end))
+ (move-overlay o beg end))))))))))
+(add-hook 'helm-after-update-hook 'helm-revive-visible-mark)
+
+(defun helm-next-point-in-list (curpos points &optional prev)
+ (cond
+ ;; rule out special cases.
+ ((null points) curpos)
+ ((and prev (<= curpos (car points)))
+ (nth (1- (length points)) points))
+ ((< (car (last points)) curpos)
+ (if prev (car (last points)) (nth 0 points)))
+ ((and (not prev) (>= curpos (car (last points))))
+ (nth 0 points))
+ (t
+ (nth (if prev
+ (cl-loop for pt in points
+ for i from 0
+ if (<= curpos pt) return (1- i))
+ (cl-loop for pt in points
+ for i from 0
+ if (< curpos pt) return i))
+ points))))
+
+(defun helm-next-visible-mark (&optional prev)
+ "Move next helm visible mark.
+If PREV is non-`nil' move to precedent."
+ (interactive)
+ (with-helm-alive-p
+ (with-helm-window
+ (ignore-errors
+ (goto-char (helm-next-point-in-list
+ (point)
+ (sort (mapcar 'overlay-start helm-visible-mark-overlays) '<)
+ prev)))
+ (helm-mark-current-line))))
+(put 'helm-next-visible-mark 'helm-only t)
+
+(defun helm-prev-visible-mark ()
+ "Move previous helm visible mark."
+ (interactive)
+ (with-helm-alive-p
+ (helm-next-visible-mark t)))
+(put 'helm-prev-visible-mark 'helm-only t)
+
+;;; Utility: Selection Paste
+;;
+(defun helm-yank-selection (arg)
+ "Set minibuffer contents to current display selection.
+With a prefix arg set to real value of current selection."
+ (interactive "P")
+ (with-helm-alive-p
+ (let ((str (format "%s" (helm-get-selection nil (not arg)))))
+ (kill-new str)
+ (helm-set-pattern str))))
+(put 'helm-yank-selection 'helm-only t)
+
+(defun helm-kill-selection-and-quit (arg)
+ "Store display value of current selection to kill ring.
+With a prefix arg use real value of current selection.
+Display value is shown in `helm-buffer' and real value
+is used to perform actions."
+ (interactive "P")
+ (with-helm-alive-p
+ (helm-run-after-exit
+ (lambda (sel)
+ (kill-new sel)
+ ;; Return nil to force `helm-mode--keyboard-quit'
+ ;; in `helm-comp-read' otherwise the value "Saved to kill-ring: foo"
+ ;; is used as exit value for `helm-comp-read'.
+ (prog1 nil (message "Saved to kill-ring: %s" sel) (sit-for 1)))
+ (format "%s" (helm-get-selection nil (not arg))))))
+(put 'helm-kill-selection-and-quit 'helm-only t)
+
+(defun helm-copy-to-buffer ()
+ "Copy selection or marked candidates to `helm-current-buffer'.
+Note that the real values of candidates are copied and not the
+display values."
+ (interactive)
+ (with-helm-alive-p
+ (helm-run-after-exit
+ (lambda (cands)
+ (with-helm-current-buffer
+ (insert (mapconcat (lambda (c)
+ (format "%s" c))
+ cands "\n"))))
+ (helm-marked-candidates))))
+(put 'helm-copy-to-buffer 'helm-only t)
+
+\f
+;;; Follow-mode: Automatic execution of persistent-action
+;;
+;;
+(defvar helm-follow-input-idle-delay nil
+ "`helm-follow-mode' will execute its persistent action after this delay.
+Note that if the `follow-delay' attr is present in source,
+it will take precedence over this.")
+
+(defun helm-follow-mode (&optional arg)
+ "Execute persistent action every time the cursor is moved.
+
+This mode is source local, i.e It apply on current source only.
+\\<helm-map>
+This mode can be enabled or disabled interactively at anytime during
+a helm session with \\[helm-follow-mode].
+
+When enabling interactively `helm-follow-mode' in a source, you can keep it enabled
+for next emacs sessions by setting `helm-follow-mode-persistent' to a non-nil value.
+
+When `helm-follow-mode' is called with a prefix arg and `helm-follow-mode-persistent'
+is non-nil `helm-follow-mode' will be persistent only for this emacs session,
+but not for next emacs sessions, i.e the current source will not be saved
+to `helm-source-names-using-follow'.
+A prefix arg with `helm-follow-mode' already enabled will have no effect.
+
+Note that you can use instead of this mode the commands `helm-follow-action-forward'
+and `helm-follow-action-backward' at anytime in all helm sessions.
+
+They are bound by default to \\[helm-follow-action-forward] and \\[helm-follow-action-backward]."
+ (interactive (list (helm-aif (and current-prefix-arg
+ (prefix-numeric-value current-prefix-arg))
+ (unless (helm-follow-mode-p) it))))
+ (with-helm-alive-p
+ (with-current-buffer helm-buffer
+ (let* ((src (helm-get-current-source))
+ (name (assoc-default 'name src))
+ (fol-attr (assq 'follow src))
+ (enabled (or (helm-follow-mode-p src)
+ (and helm-follow-mode-persistent
+ (member (assoc-default 'name src)
+ helm-source-names-using-follow)))))
+ (if src
+ (progn
+ (if (eq (cdr fol-attr) 'never)
+ (message "helm-follow-mode not allowed in this source")
+ ;; Make follow attr persistent for this emacs session.
+ (helm-follow-mode-set-source
+ (if (or enabled (and (numberp arg) (< arg 0))) -1 1)
+ src)
+ ;; When arg is nil assume the call is interactive.
+ ;; However if user call helm-follow-mode with a prefix arg,
+ ;; the call will be considered non--interactive and
+ ;; src-name will NOT be saved to helm-source-names-using-follow.
+ ;; When called from lisp (non--interactive) src-name
+ ;; will never be saved.
+ (when (and helm-follow-mode-persistent (null arg))
+ (if (null enabled)
+ (unless (member name helm-source-names-using-follow)
+ (push name helm-source-names-using-follow)
+ (customize-save-variable 'helm-source-names-using-follow
+ helm-source-names-using-follow))
+ (when (member name helm-source-names-using-follow)
+ (setq helm-source-names-using-follow
+ (delete name helm-source-names-using-follow))
+ (customize-save-variable 'helm-source-names-using-follow
+ helm-source-names-using-follow))))
+ (message "helm-follow-mode is %s"
+ (if (helm-follow-mode-p src)
+ "enabled" "disabled"))
+ (helm-display-mode-line src t)))
+ (message "Not enough candidates for helm-follow-mode"))))))
+(put 'helm-follow-mode 'helm-only t)
+
+(defun helm-follow-execute-persistent-action-maybe (&optional delay)
+ "Execute persistent action in mode `helm-follow-mode'.
+
+This happen after: DELAY or the 'follow-attr value of current source
+or `helm-follow-input-idle-delay' or `helm-input-idle-delay' secs."
+ (let* ((src (helm-get-current-source))
+ (at (or delay
+ (assoc-default 'follow-delay src)
+ helm-follow-input-idle-delay
+ (or (and helm-input-idle-delay
+ (max helm-input-idle-delay 0.01))
+ 0.01))))
+ (when (and (not (get-buffer-window helm-action-buffer 'visible))
+ (not (helm-pos-header-line-p))
+ (or (helm-follow-mode-p src)
+ (and helm-follow-mode-persistent
+ (member (assoc-default 'name src)
+ helm-source-names-using-follow)))
+ (null (eq (assoc-default 'follow src) 'never))
+ (helm-get-selection nil nil src))
+ (helm-follow-mode-set-source 1 src)
+ (run-with-idle-timer at nil (lambda ()
+ (when helm-alive-p
+ (helm-execute-persistent-action)))))))
+
+(defun helm-follow-mode-p (&optional source)
+ (with-helm-buffer
+ (eq (helm-attr 'follow (or source (helm-get-current-source))) 1)))
+
+(defun helm-follow-mode-set-source (value &optional source)
+ (with-helm-buffer
+ (helm-attrset 'follow value (or source (helm-get-current-source)))))
+\f
+;;; Auto-resize mode
+;;
+(defun helm--autoresize-hook (&optional max-height min-height)
+ (when (helm-window)
+ (with-helm-window
+ (fit-window-to-buffer nil
+ (/ (* (frame-height)
+ (or max-height helm-autoresize-max-height))
+ 100)
+ (/ (* (frame-height)
+ (or min-height helm-autoresize-min-height))
+ 100)))))
+
+(define-minor-mode helm-autoresize-mode
+ "Auto resize helm window when enabled.
+Helm window is re-sized according to `helm-autoresize-max-height'
+and `helm-autoresize-min-height'. Note that when this mode is
+enabled, helm behaves as if `helm-always-two-windows' is
+enabled.
+
+See `fit-window-to-buffer' for more infos."
+ :group 'helm
+ :global t
+ (if helm-autoresize-mode
+ (progn (add-hook 'helm-after-update-hook 'helm--autoresize-hook)
+ (add-hook 'helm-window-configuration-hook 'helm--autoresize-hook))
+ (remove-hook 'helm-after-update-hook 'helm--autoresize-hook)
+ (remove-hook 'helm-window-configuration-hook 'helm--autoresize-hook)))
+
+(defun helm-help ()
+ "Generate helm's help according to `help-message' attribute.
+
+If source is not available yet or doesn't have any `help-message'
+attribute, a generic message explaining this is added instead. The
+global `helm-help-message' is always added after this local help."
+ (interactive)
+ (with-helm-alive-p
+ (save-selected-window
+ (helm-help-internal
+ "*Helm Help*"
+ (lambda ()
+ (helm-aif (assoc-default 'help-message (helm-get-current-source))
+ (insert (substitute-command-keys
+ (helm-interpret-value it)))
+ (insert "* No specific help for this source at this time.\n
+It may appear after first results popup in helm buffer."))
+ (insert "\n\n"
+ (substitute-command-keys
+ (helm-interpret-value helm-help-message))))))))
+(put 'helm-help 'helm-only t)
+
+(defun helm-toggle-truncate-line ()
+ "Toggle `truncate-lines' value in `helm-buffer'"
+ (interactive)
+ (with-helm-alive-p
+ (with-helm-buffer
+ (setq truncate-lines (not truncate-lines))
+ (when (helm-get-previous-header-pos)
+ (helm-update (regexp-quote (helm-get-selection nil t)))))))
+(put 'helm-toggle-truncate-line 'helm-only t)
+
+(provide 'helm)
+
+;; Local Variables:
+;; byte-compile-warnings: (not obsolete)
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm.el ends here
+++ /dev/null
-;;; helm-descbinds-autoloads.el --- automatically extracted autoloads
-;;
-;;; Code:
-(add-to-list 'load-path (or (file-name-directory #$) (car load-path)))
-\f
-;;;### (autoloads nil "helm-descbinds" "helm-descbinds.el" (22081
-;;;;;; 57649 0 0))
-;;; Generated autoloads from helm-descbinds.el
-
-(defvar helm-descbinds-mode nil "\
-Non-nil if Helm-Descbinds mode is enabled.
-See the command `helm-descbinds-mode' for a description of this minor mode.
-Setting this variable directly does not take effect;
-either customize it (see the info node `Easy Customization')
-or call the function `helm-descbinds-mode'.")
-
-(custom-autoload 'helm-descbinds-mode "helm-descbinds" nil)
-
-(autoload 'helm-descbinds-mode "helm-descbinds" "\
-Use `helm' for `describe-bindings'
-
-\(fn &optional ARG)" t nil)
-
-(autoload 'helm-descbinds-install "helm-descbinds" "\
-Use `helm-descbinds' as a replacement of `describe-bindings'.
-
-\(fn)" t nil)
-
-(autoload 'helm-descbinds-uninstall "helm-descbinds" "\
-Restore original `describe-bindings'.
-
-\(fn)" t nil)
-
-(autoload 'helm-descbinds "helm-descbinds" "\
-Yet Another `describe-bindings' with `helm'.
-
-\(fn &optional PREFIX BUFFER)" t nil)
-
-;;;***
-\f
-;; Local Variables:
-;; version-control: never
-;; no-byte-compile: t
-;; no-update-autoloads: t
-;; End:
-;;; helm-descbinds-autoloads.el ends here
+++ /dev/null
-(define-package "helm-descbinds" "20151019.230" "Yet Another `describe-bindings' with `helm'." '((helm "1.5")) :url "https://github.com/emacs-helm/helm-descbinds" :keywords '("helm" "help"))
+++ /dev/null
-;;; helm-descbinds.el --- Yet Another `describe-bindings' with `helm'.
-
-;; Copyright (C) 2008, 2009, 2010 Taiki SUGAWARA <buzz.taikiNOSPAMgmail.com>
-;; Copyright (C) 2012, 2013 Michael Markert <markert.michaelNOSPAMgooglemail.com>
-;; Copyright (C) 2013 Daniel Hackney <danNOSPAMhaxney.org>
-
-;; Author: Taiki SUGAWARA <buzz.taikiNOSPAMgmail.com>
-;; URL: https://github.com/emacs-helm/helm-descbinds
-;; Package-Version: 20151019.230
-;; Keywords: helm, help
-;; Version: 1.08
-;; Package-Requires: ((helm "1.5"))
-
-;; 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 file 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 GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
-
-;;; Commentary:
-;; This package is a replacement of `describe-bindings'.
-
-;;; Usage:
-;; Add followings on your .emacs.
-;;
-;; (require 'helm-descbinds)
-;; (helm-descbinds-mode)
-;;
-;; or use customize to set `helm-descbinds-mode' to t.
-;;
-;; Now, `describe-bindings' is replaced to `helm-descbinds'. Type
-;; `C-h b', `C-x C-h' these run `helm-descbinds'.
-;;
-;; In the Helm buffer, you can select key-binds with helm interface.
-;;
-;; - When type RET, selected candidate command is executed.
-;;
-;; - When type TAB, You can "Execute", "Describe Function" or "Find
-;; Function" by the menu.
-;;
-;; - When type C-z, selected command is described without quiting.
-
-;;; History:
-;; 2013-02-23 Michael Markert <markert.michaelNOSPAMgooglemail.com>
-;; * helm-descbinds.el: Version 1.08
-;; Merge Daniel Hackney's helm-descbinds minor mode.
-;; Several bugfixes.
-;;
-;; 2012-03-18 Michael Markert <markert.michaelNOSPAMgooglemail.com>
-;; * helm-descbinds.el: Version 1.07
-;; make strings bound to keys insertable
-;;
-;; 2012-03-18 Michael Markert <markert.michaelNOSPAMgooglemail.com>
-;; * helm-descbinds.el: Version 1.06
-;; port to helm
-;;
-;; 2010-02-05 Taiki SUGAWARA <sugawara_tNOSPAMariel-networks.com>
-;;
-;; * descbinds-anything.el: Version 1.05
-;; bug fix.
-;;
-;; 2010-02-02 UTC Taiki SUGAWARA <buzz.taikiNOSPAMgmail.com>
-;;
-;; * descbinds-anything.el: Version 1.04
-;; add sorting feature.
-;; separete sorce creation function.
-;; add persistent action.
-;;
-;; 2009-03-29 UTC Taiki SUGAWARA <buzz.taikiNOSPAMgmail.com>
-;;
-;; * descbinds-anything.el: Version 1.03
-;; fix typo.
-;;
-;; 2008-11-16 UTC Taiki SUGAWARA <buzz.taikiNOSPAMgmail.com>
-;;
-;; * descbinds-anything.el: Version 1.02
-;; bound `indent-tabs-mode` to t for nil environment.
-;;
-;; 2008-11-16 UTC Taiki SUGAWARA <buzz.taikiNOSPAMgmail.com>
-;;
-;; * descbinds-anything.el: fix infinitive-loop when binding-line
-;; has not tab.
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'helm)
-
-(defgroup helm-descbinds nil
- "Yet Another `describe-bindings' with `helm'."
- :prefix "helm-descbinds-"
- :group 'helm)
-
-(defcustom helm-descbinds-actions
- '(("Execute" . helm-descbinds-action:execute)
- ("Describe Function" . helm-descbinds-action:describe)
- ("Find Function" . helm-descbinds-action:find-func))
- "Actions of selected candidate."
- :type '(repeat
- (cons
- :tag "Action"
- (string :tag "Name")
- (function :tag "Function")))
- :group 'helm-descbinds)
-
-(defcustom helm-descbinds-strings-to-ignore
- '("Keyboard Macro" "Prefix Command")
- "Strings to ignore as a possible string candidate."
- :type '(repeat string))
-
-(defcustom helm-descbinds-candidate-formatter
- 'helm-descbinds-default-candidate-formatter
- "Candidate formatter function.
-This function called two argument KEY and BINDING."
- :type 'function
- :group 'helm-descbinds)
-
-(defcustom helm-descbinds-window-style 'one-window
- "Window splitting style."
- :type '(choice
- (const :tag "One Window" one-window)
- (const :tag "Same Window" same-window)
- (const :tag "Split Window" split-window))
- :group 'helm-descbinds)
-
-(defcustom helm-descbinds-section-order
- '("Major Mode Bindings" "Minor Mode Bindings" "Global Bindings")
- "A list of section order by name regexp."
- :type '(repeat (regexp :tag "Regexp"))
- :group 'helm-descbinds)
-
-(defcustom helm-descbinds-source-template
- `((candidate-transformer . helm-descbinds-transform-candidates)
- (filtered-candidate-transformer . helm-fuzzy-highlight-matches)
- (persistent-action . helm-descbinds-action:describe)
- (action . ,helm-descbinds-actions))
- "A template of `helm-descbinds' source."
- :type 'sexp
- :group 'helm-descbinds)
-
-(defvar helm-descbinds-Orig-describe-bindings (symbol-function 'describe-bindings))
-(defvar helm-descbind--initial-full-frame helm-full-frame)
-
-;;;###autoload
-(define-minor-mode helm-descbinds-mode
- "Use `helm' for `describe-bindings'"
- :group 'helm-descbinds
- :global t
- (if helm-descbinds-mode
- (fset 'describe-bindings #'helm-descbinds)
- (fset 'describe-bindings helm-descbinds-Orig-describe-bindings)))
-
-;;;###autoload
-(defun helm-descbinds-install ()
- "Use `helm-descbinds' as a replacement of `describe-bindings'."
- (interactive)
- (helm-descbinds-mode 1))
-(make-obsolete 'helm-descbinds-install 'helm-descbinds-mode "1.08")
-
-;;;###autoload
-(defun helm-descbinds-uninstall ()
- "Restore original `describe-bindings'."
- (interactive)
- (helm-descbinds-mode -1))
-(make-obsolete 'helm-descbinds-uninstall 'helm-descbinds-mode "1.08")
-
-(defun helm-descbinds-all-sections (buffer &optional prefix menus)
- (with-temp-buffer
- (let ((indent-tabs-mode t))
- (describe-buffer-bindings buffer prefix menus))
- (goto-char (point-min))
- (let ((header-p (not (= (char-after) ?\f)))
- sections header section)
- (while (not (eobp))
- (cond
- (header-p
- (setq header (buffer-substring-no-properties
- (point)
- (line-end-position)))
- (setq header-p nil)
- (forward-line 3))
- ((= (char-after) ?\f)
- (push (cons header (nreverse section)) sections)
- (setq section nil)
- (setq header-p t))
- ((looking-at "^[ \t]*$")
- ;; ignore
- )
- (t
- (let ((binding-start (save-excursion
- (and (re-search-forward "\t+" nil t)
- (match-end 0))))
- key binding)
- (when binding-start
- (setq key (buffer-substring-no-properties (point) binding-start)
- key (replace-regexp-in-string"^[ \t\n]+" "" key)
- key (replace-regexp-in-string"[ \t\n]+$" "" key))
- (goto-char binding-start)
- (setq binding (buffer-substring-no-properties
- binding-start
- (line-end-position)))
- (unless (member binding '("self-insert-command"))
- (push (cons key binding) section))))))
- (forward-line))
- (push (cons header (nreverse section)) sections)
- (nreverse sections))))
-
-(defun helm-descbinds-action:execute (candidate)
- "An action that execute selected CANDIDATE command."
- (let ((x (cdr candidate))
- (helm-full-frame helm-descbind--initial-full-frame))
- (cond
- ((stringp x)
- (insert x))
- ((commandp x)
- (run-at-time 0.01 nil (lambda (command) (call-interactively command)) x)))))
-
-(defun helm-descbinds-action:describe (candidate)
- "An action that describe selected CANDIDATE function."
- (describe-function (cdr candidate)))
-
-(defun helm-descbinds-action:find-func (candidate)
- "An action that find selected CANDIDATE function."
- (find-function (cdr candidate)))
-
-(defun helm-descbinds-default-candidate-formatter (key binding)
- "Default candidate formatter."
- (format "%-10s\t%s" key binding))
-
-(defun helm-descbinds-order-section (section)
- (cl-loop for n = 0 then (1+ n)
- for regexp in helm-descbinds-section-order
- if (and (car section) (string-match regexp (car section)))
- return n
- finally
- return n))
-
-(defun helm-descbinds-transform-candidates (candidates)
- (mapcar
- (lambda (pair)
- (let ((key (car pair))
- (command (cdr pair)))
- (cons (funcall helm-descbinds-candidate-formatter key command)
- (cons key (or (intern-soft command)
- (unless (member command helm-descbinds-strings-to-ignore)
- command))))))
- candidates))
-
-(defun helm-descbinds-sources (buffer &optional prefix menus)
- (mapcar
- (lambda (section)
- (helm-descbinds-source (car section) (cdr section)))
- (sort
- (helm-descbinds-all-sections buffer prefix menus)
- (lambda (a b)
- (< (helm-descbinds-order-section a)
- (helm-descbinds-order-section b))))))
-
-(defun helm-descbinds-source (name candidates)
- `((name . ,name)
- (candidates . ,candidates)
- ,@helm-descbinds-source-template))
-
-;;;###autoload
-(defun helm-descbinds (&optional prefix buffer)
- "Yet Another `describe-bindings' with `helm'."
- (interactive)
- (let ((old-helm-full-frame helm-full-frame)
- (helm-full-frame (and (not (minibufferp))
- (memq helm-descbinds-window-style
- '(same-window one-window))))
- (helm-before-initialize-hook (if (and (not (minibufferp))
- (eq helm-descbinds-window-style
- 'one-window))
- (cons 'delete-other-windows
- helm-before-initialize-hook)
- helm-before-initialize-hook))
- (enable-recursive-minibuffers t))
- (setq helm-descbind--initial-full-frame old-helm-full-frame)
- (helm :sources (helm-descbinds-sources
- (or buffer (current-buffer)) prefix)
- :buffer "*helm-descbinds*"
- :resume 'noresume
- :allow-nest t)))
-
-(provide 'helm-descbinds)
-
-;;; helm-descbinds.el ends here
+++ /dev/null
-;;; helm-descbinds-autoloads.el --- automatically extracted autoloads
-;;
-;;; Code:
-(add-to-list 'load-path (or (file-name-directory #$) (car load-path)))
-\f
-;;;### (autoloads nil "helm-descbinds" "helm-descbinds.el" (22215
-;;;;;; 7793 0 0))
-;;; Generated autoloads from helm-descbinds.el
-
-(defvar helm-descbinds-mode nil "\
-Non-nil if Helm-Descbinds mode is enabled.
-See the command `helm-descbinds-mode' for a description of this minor mode.
-Setting this variable directly does not take effect;
-either customize it (see the info node `Easy Customization')
-or call the function `helm-descbinds-mode'.")
-
-(custom-autoload 'helm-descbinds-mode "helm-descbinds" nil)
-
-(autoload 'helm-descbinds-mode "helm-descbinds" "\
-Use `helm' for `describe-bindings'.
-
-\(fn &optional ARG)" t nil)
-
-(autoload 'helm-descbinds-install "helm-descbinds" "\
-Use `helm-descbinds' as a replacement of `describe-bindings'.
-
-\(fn)" t nil)
-
-(autoload 'helm-descbinds-uninstall "helm-descbinds" "\
-Restore original `describe-bindings'.
-
-\(fn)" t nil)
-
-(autoload 'helm-descbinds "helm-descbinds" "\
-A convenient helm version of `describe-bindings'.
-
-Turning on `helm-descbinds-mode' is the recommended way to
-install this command to replace `describe-bindings'.
-
-You complete against a list of keys + command pairs presented in
-a similar way as `describe-bindings' does, split into sections
-defined by the types of the key bindings (minor and major modes,
-global bindings, etc).
-
-The default action executes a command as if the binding had been
-entered, or narrows the commands according to a prefix key,
-respectively.
-
-The persistent action pops up a help buffer for the selected
-command without quitting.
-
-For key translation maps, the default actions are not very
-useful, yet they are listed for completeness.
-
-\(fn &optional PREFIX BUFFER)" t nil)
-
-;;;***
-\f
-;; Local Variables:
-;; version-control: never
-;; no-byte-compile: t
-;; no-update-autoloads: t
-;; End:
-;;; helm-descbinds-autoloads.el ends here
+++ /dev/null
-(define-package "helm-descbinds" "20160108.1947" "A convenient `describe-bindings' with `helm'" '((helm "1.5")) :url "https://github.com/emacs-helm/helm-descbinds" :keywords '("helm" "help"))
+++ /dev/null
-;;; helm-descbinds.el --- A convenient `describe-bindings' with `helm' -*- lexical-binding: t -*-
-
-;; Copyright (C) 2008, 2009, 2010 Taiki SUGAWARA <buzz.taikiNOSPAMgmail.com>
-;; Copyright (C) 2012, 2013 Michael Markert <markert.michaelNOSPAMgooglemail.com>
-;; Copyright (C) 2013 Daniel Hackney <danNOSPAMhaxney.org>
-;; Copyright (C) 2015 Michael Heerdegen <michael_heerdegenNOSPAMweb.de>
-
-;; Author: Taiki SUGAWARA <buzz.taikiNOSPAMgmail.com>
-;; URL: https://github.com/emacs-helm/helm-descbinds
-;; Package-Version: 20160108.1947
-;; Keywords: helm, help
-;; Version: 1.10
-;; Package-Requires: ((helm "1.5"))
-
-;; 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 file 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 GNU Emacs; see the file COPYING. If not, write to
-;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
-
-
-;;; Commentary:
-;; This package is a replacement of `describe-bindings' for Helm.
-
-;; Usage:
-;;
-;; You can use this package independently from Helm - in particular,
-;; you don't need to turn on `helm-mode' to be able to use this. Helm
-;; just needs to be installed.
-;;
-;; Add followings on your .emacs.
-;;
-;; (require 'helm-descbinds)
-;; (helm-descbinds-mode)
-;;
-;; or use customize to set `helm-descbinds-mode' to t.
-;;
-;; Now, `describe-bindings' is replaced with `helm-descbinds'. As
-;; usual, type `C-h b', or any incomplete key sequence plus C-h , to
-;; run `helm-descbinds'. The bindings are presented in a similar way
-;; as `describe-bindings ' does, but you can use completion to find
-;; the command you searched for and execute it, or view it's
-;; documentation.
-;;
-;; In the Helm completions buffer, you match key bindings with the
-;; Helm interface:
-;;
-;; - When you type RET, the selected candidate command is executed.
-;;
-;; - When you hit RET on a prefix key, the candidates are narrowed to
-;; this prefix
-;;
-;; - When you type TAB, you can select "Execute", "Describe" or "Find
-;; Function" by the menu (i.e. these are the available "actions"
-;; and are of course also available via their usual shortcuts).
-;;
-;; - When you type C-z (aka "persistent action"), the selected
-;; command is described without quitting Helm.
-
-
-
-;;; Code:
-
-(eval-when-compile (require 'cl-lib)) ;cl-loop
-(require 'helm)
-
-(defgroup helm-descbinds nil
- "A convenient `describe-bindings' with `helm'."
- :prefix "helm-descbinds-"
- :group 'helm)
-
-(defcustom helm-descbinds-actions
- '(("Execute" . helm-descbinds-action:execute)
- ("Describe" . helm-descbinds-action:describe)
- ("Find Function" . helm-descbinds-action:find-func))
- "Actions of selected candidate."
- :type '(repeat
- (cons
- :tag "Action"
- (string :tag "Name")
- (function :tag "Function"))))
-
-(defcustom helm-descbinds-candidate-formatter
- #'helm-descbinds-default-candidate-formatter
- "Candidate formatter function.
-This function will be called with two arguments KEY and BINDING."
- :type 'function)
-
-(defcustom helm-descbinds-window-style 'one-window
- "Window splitting style."
- :type '(choice
- (const :tag "One Window" one-window)
- (const :tag "Same Window" same-window)
- (const :tag "Split Window" split-window)))
-
-(defcustom helm-descbinds-section-order
- '("Major Mode Bindings" "Minor Mode Bindings" "Global Bindings")
- "A list of section order by name regexp."
- :type '(repeat (regexp :tag "Regexp")))
-
-(defcustom helm-descbinds-source-template
- `((candidate-transformer . helm-descbinds-transform-candidates)
- (filtered-candidate-transformer . helm-fuzzy-highlight-matches)
- (persistent-action . helm-descbinds-action:describe)
- (action-transformer . helm-descbinds-action-transformer)
- (action . ,helm-descbinds-actions))
- "A template of `helm-descbinds' source."
- :type 'sexp)
-
-(defvar helm-descbinds-Orig-describe-bindings (symbol-function 'describe-bindings))
-(defvar helm-descbind--initial-full-frame helm-full-frame)
-
-;;;###autoload
-(define-minor-mode helm-descbinds-mode
- "Use `helm' for `describe-bindings'."
- :group 'helm-descbinds
- :global t
- (if helm-descbinds-mode
- (fset 'describe-bindings #'helm-descbinds) ;FIXME: why don't we just use an :override advice?
- (fset 'describe-bindings helm-descbinds-Orig-describe-bindings)))
-
-;;;###autoload
-(defun helm-descbinds-install ()
- "Use `helm-descbinds' as a replacement of `describe-bindings'."
- (interactive)
- (helm-descbinds-mode 1))
-(make-obsolete 'helm-descbinds-install 'helm-descbinds-mode "1.08")
-
-;;;###autoload
-(defun helm-descbinds-uninstall ()
- "Restore original `describe-bindings'."
- (interactive)
- (helm-descbinds-mode -1))
-(make-obsolete 'helm-descbinds-uninstall 'helm-descbinds-mode "1.08")
-
-(defun helm-descbinds-all-sections (buffer &optional prefix menus)
- (with-temp-buffer
- (let ((indent-tabs-mode t))
- (describe-buffer-bindings buffer prefix menus))
- (goto-char (point-min))
- (let ((header-p (not (= (char-after) ?\f)))
- sections header section)
- (while (not (eobp))
- (cond
- (header-p
- (setq header (buffer-substring-no-properties
- (point)
- (line-end-position)))
- (setq header-p nil)
- (forward-line 3))
- ((= (char-after) ?\f)
- (push (cons header (nreverse section)) sections)
- (setq section nil)
- (setq header-p t))
- ((looking-at "^[ \t]*$")
- ;; ignore
- )
- (t
- (let ((binding-start (save-excursion
- (and (re-search-forward "\t+" nil t)
- (match-end 0))))
- key binding)
- (when binding-start
- (setq key (buffer-substring-no-properties (point) binding-start)
- key (replace-regexp-in-string"^[ \t\n]+" "" key)
- key (replace-regexp-in-string"[ \t\n]+$" "" key))
- (goto-char binding-start)
- (setq binding (buffer-substring-no-properties
- binding-start
- (line-end-position)))
- (unless (member binding '("self-insert-command"))
- (push (cons key binding) section))))))
- (forward-line))
- (push (cons header (nreverse section)) sections)
- (nreverse sections))))
-
-(defun helm-descbinds-action:execute (candidate)
- "An action that execute selected CANDIDATE command."
- (let ((x (cdr candidate))
- (helm-full-frame helm-descbind--initial-full-frame))
- (cond
- ((equal x "Keyboard Macro")
- (command-execute (kbd (car candidate))))
- ((stringp x)
- (insert x))
- ((commandp x)
- (run-at-time 0.01 nil (lambda (command) (call-interactively command)) x)))))
-
-(defun helm-descbinds-action:describe (candidate)
- "An action that describe selected CANDIDATE function."
- (let ((name (cdr candidate)))
- (if (equal name "Keyboard Macro")
- (describe-key (kbd (car candidate)))
- (describe-function name))))
-
-(defun helm-descbinds-action:find-func (candidate)
- "An action that find selected CANDIDATE function."
- (find-function (cdr candidate)))
-
-(defun helm-descbinds-default-candidate-formatter (key binding)
- "Default candidate formatter."
- (format "%-10s\t%s" key binding))
-
-(defun helm-descbinds-order-section (section)
- (cl-loop for n = 0 then (1+ n)
- for regexp in helm-descbinds-section-order
- if (and (car section) (string-match regexp (car section)))
- return n
- finally
- return n))
-
-(defun helm-descbinds-transform-candidates (candidates)
- (mapcar
- (lambda (pair)
- (let ((key (car pair))
- (command (cdr pair)))
- (cons (funcall helm-descbinds-candidate-formatter key command)
- (cons key (or (intern-soft command) command)))))
- candidates))
-
-(defun helm-descbinds-action-transformer (actions cand)
- "Default action transformer for `helm-descbinds'.
-Provide a useful behavior for prefix commands."
- (if (equal (cdr-safe cand) "Prefix Command")
- `(("helm-descbinds this prefix" . ,(lambda (cand) (interactive)
- (run-with-timer
- 0 nil
- #'describe-bindings (kbd (car cand))))))
- actions))
-
-(defun helm-descbinds-sources (buffer &optional prefix menus)
- (mapcar
- (lambda (section)
- (helm-descbinds-source (car section) (cdr section)))
- (sort
- (helm-descbinds-all-sections buffer prefix menus)
- (lambda (a b)
- (< (helm-descbinds-order-section a)
- (helm-descbinds-order-section b))))))
-
-(defun helm-descbinds-source (name candidates)
- `((name . ,name)
- (candidates . ,candidates)
- ,@helm-descbinds-source-template))
-
-;;;###autoload
-(defun helm-descbinds (&optional prefix buffer)
- "A convenient helm version of `describe-bindings'.
-
-Turning on `helm-descbinds-mode' is the recommended way to
-install this command to replace `describe-bindings'.
-
-You complete against a list of keys + command pairs presented in
-a similar way as `describe-bindings' does, split into sections
-defined by the types of the key bindings (minor and major modes,
-global bindings, etc).
-
-The default action executes a command as if the binding had been
-entered, or narrows the commands according to a prefix key,
-respectively.
-
-The persistent action pops up a help buffer for the selected
-command without quitting.
-
-For key translation maps, the default actions are not very
-useful, yet they are listed for completeness."
- (interactive)
- (let ((old-helm-full-frame helm-full-frame)
- (helm-full-frame (and (not (minibufferp))
- (memq helm-descbinds-window-style
- '(same-window one-window))))
- (helm-before-initialize-hook (if (and (not (minibufferp))
- (eq helm-descbinds-window-style
- 'one-window))
- (cons 'delete-other-windows
- helm-before-initialize-hook)
- helm-before-initialize-hook))
- (enable-recursive-minibuffers t))
- (setq helm-descbind--initial-full-frame old-helm-full-frame)
- (helm :sources (helm-descbinds-sources
- (or buffer (current-buffer)) prefix)
- :buffer "*helm-descbinds*"
- :resume 'noresume
- :allow-nest t)))
-
-(provide 'helm-descbinds)
-
-;;; helm-descbinds.el ends here
--- /dev/null
+;;; helm-descbinds-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+
+(add-to-list 'load-path (directory-file-name
+ (or (file-name-directory #$) (car load-path))))
+
+\f
+;;;### (autoloads nil "helm-descbinds" "helm-descbinds.el" (0 0 0
+;;;;;; 0))
+;;; Generated autoloads from helm-descbinds.el
+
+(defvar helm-descbinds-mode nil "\
+Non-nil if Helm-Descbinds mode is enabled.
+See the `helm-descbinds-mode' command
+for a description of this minor mode.
+Setting this variable directly does not take effect;
+either customize it (see the info node `Easy Customization')
+or call the function `helm-descbinds-mode'.")
+
+(custom-autoload 'helm-descbinds-mode "helm-descbinds" nil)
+
+(autoload 'helm-descbinds-mode "helm-descbinds" "\
+Use `helm' for `describe-bindings'.
+
+\(fn &optional ARG)" t nil)
+
+(autoload 'helm-descbinds-install "helm-descbinds" "\
+Use `helm-descbinds' as a replacement of `describe-bindings'.
+
+\(fn)" t nil)
+
+(autoload 'helm-descbinds-uninstall "helm-descbinds" "\
+Restore original `describe-bindings'.
+
+\(fn)" t nil)
+
+(autoload 'helm-descbinds "helm-descbinds" "\
+A convenient helm version of `describe-bindings'.
+
+Turning on `helm-descbinds-mode' is the recommended way to
+install this command to replace `describe-bindings'.
+
+You complete against a list of keys + command pairs presented in
+a similar way as `describe-bindings' does, split into sections
+defined by the types of the key bindings (minor and major modes,
+global bindings, etc).
+
+The default action executes a command as if the binding had been
+entered, or narrows the commands according to a prefix key,
+respectively.
+
+The persistent action pops up a help buffer for the selected
+command without quitting.
+
+For key translation maps, the default actions are not very
+useful, yet they are listed for completeness.
+
+\(fn &optional PREFIX BUFFER)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-descbinds" '("helm-descbind")))
+
+;;;***
+\f
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; coding: utf-8
+;; End:
+;;; helm-descbinds-autoloads.el ends here
--- /dev/null
+;;; -*- no-byte-compile: t -*-
+(define-package "helm-descbinds" "20180429.1456" "A convenient `describe-bindings' with `helm'" '((helm "1.5")) :commit "033be73f21778633813264ce1634a6e1ad873d8e" :keywords '("helm" "help") :authors '(("Taiki SUGAWARA" . "buzz.taikiNOSPAMgmail.com")) :maintainer '("Taiki SUGAWARA" . "buzz.taiki@gmail.com") :url "https://github.com/emacs-helm/helm-descbinds")
--- /dev/null
+;;; helm-descbinds.el --- A convenient `describe-bindings' with `helm' -*- lexical-binding: t -*-
+
+;; Copyright (C) 2008, 2009, 2010 Taiki SUGAWARA <buzz.taikiNOSPAMgmail.com>
+;; Copyright (C) 2012, 2013 Michael Markert <markert.michaelNOSPAMgooglemail.com>
+;; Copyright (C) 2013 Daniel Hackney <danNOSPAMhaxney.org>
+;; Copyright (C) 2015, 2016 Michael Heerdegen <michael_heerdegenNOSPAMweb.de>
+
+;; Author: Taiki SUGAWARA <buzz.taikiNOSPAMgmail.com>
+;; URL: https://github.com/emacs-helm/helm-descbinds
+;; Package-Version: 20180429.1456
+;; Keywords: helm, help
+;; Version: 1.12
+;; Package-Requires: ((helm "1.5"))
+
+;; 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 file 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 GNU Emacs; see the file COPYING. If not, write to
+;; the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+
+;;; Commentary:
+;; This package is a replacement of `describe-bindings' for Helm.
+
+;; Usage:
+;;
+;; You can use this package independently from Helm - in particular,
+;; you don't need to turn on `helm-mode' to be able to use this. Helm
+;; just needs to be installed.
+;;
+;; Add followings on your .emacs.
+;;
+;; (require 'helm-descbinds)
+;; (helm-descbinds-mode)
+;;
+;; or use customize to set `helm-descbinds-mode' to t.
+;;
+;; Now, `describe-bindings' is replaced with `helm-descbinds'. As
+;; usual, type `C-h b', or any incomplete key sequence plus C-h , to
+;; run `helm-descbinds'. The bindings are presented in a similar way
+;; as `describe-bindings ' does, but you can use completion to find
+;; the command you searched for and execute it, or view it's
+;; documentation.
+;;
+;; In the Helm completions buffer, you match key bindings with the
+;; Helm interface:
+;;
+;; - When you type RET, the selected candidate command is executed.
+;;
+;; - When you hit RET on a prefix key, the candidates are narrowed to
+;; this prefix
+;;
+;; - When you type TAB, you can select "Execute", "Describe" or "Find
+;; Function" by the menu (i.e. these are the available "actions"
+;; and are of course also available via their usual shortcuts).
+;;
+;; - When you type C-z (aka "persistent action"), the selected
+;; command is described without quitting Helm.
+
+
+
+;;; Code:
+
+(eval-when-compile (require 'cl-lib)) ;cl-loop
+(require 'helm)
+
+(defgroup helm-descbinds nil
+ "A convenient `describe-bindings' with `helm'."
+ :prefix "helm-descbinds-"
+ :group 'helm)
+
+(defcustom helm-descbinds-actions
+ '(("Execute" . helm-descbinds-action:execute)
+ ("Describe" . helm-descbinds-action:describe)
+ ("Find Function" . helm-descbinds-action:find-func))
+ "Actions of selected candidate."
+ :type '(repeat
+ (cons
+ :tag "Action"
+ (string :tag "Name")
+ (function :tag "Function"))))
+
+(defcustom helm-descbinds-candidate-formatter
+ #'helm-descbinds-default-candidate-formatter
+ "Candidate formatter function.
+This function will be called with two arguments KEY and BINDING."
+ :type 'function)
+
+(defcustom helm-descbinds-window-style 'one-window
+ "Window splitting style."
+ :type '(choice
+ (const :tag "One Window" one-window)
+ (const :tag "Same Window" same-window)
+ (const :tag "Split Window" split-window)))
+
+(defcustom helm-descbinds-section-order
+ '("Major Mode Bindings" "Minor Mode Bindings" "Global Bindings")
+ "A list of section order by name regexp."
+ :type '(repeat (regexp :tag "Regexp")))
+
+(defvar helm-descbinds-Orig-describe-bindings (symbol-function 'describe-bindings))
+(defvar helm-descbind--initial-full-frame helm-full-frame)
+
+;;;###autoload
+(define-minor-mode helm-descbinds-mode
+ "Use `helm' for `describe-bindings'."
+ :group 'helm-descbinds
+ :global t
+ (if helm-descbinds-mode
+ (progn
+ (advice-add 'describe-bindings :override #'helm-descbinds)
+ (global-unset-key (kbd "<help> C-h")))
+ (advice-remove 'describe-bindings #'helm-descbinds)
+ (global-set-key (kbd "<help> C-h") 'help-for-help)))
+
+;;;###autoload
+(defun helm-descbinds-install ()
+ "Use `helm-descbinds' as a replacement of `describe-bindings'."
+ (interactive)
+ (helm-descbinds-mode 1))
+(make-obsolete 'helm-descbinds-install 'helm-descbinds-mode "1.08")
+
+;;;###autoload
+(defun helm-descbinds-uninstall ()
+ "Restore original `describe-bindings'."
+ (interactive)
+ (helm-descbinds-mode -1))
+(make-obsolete 'helm-descbinds-uninstall 'helm-descbinds-mode "1.08")
+
+(defun helm-descbinds-all-sections (buffer &optional prefix menus)
+ (with-temp-buffer
+ (let ((indent-tabs-mode t))
+ (describe-buffer-bindings buffer prefix menus))
+ (goto-char (point-min))
+ (let ((header-p (not (= (char-after) ?\f)))
+ sections header section)
+ (while (not (eobp))
+ (cond
+ (header-p
+ (setq header (buffer-substring-no-properties
+ (point)
+ (line-end-position)))
+ (setq header-p nil)
+ (forward-line 3))
+ ((= (char-after) ?\f)
+ (push (cons header (nreverse section)) sections)
+ (setq section nil)
+ (setq header-p t))
+ ((looking-at "^[ \t]*$")
+ ;; ignore
+ )
+ (t
+ (let ((binding-start (save-excursion
+ (and (re-search-forward "\t+" nil t)
+ (match-end 0))))
+ key binding)
+ (when binding-start
+ (setq key (buffer-substring-no-properties (point) binding-start)
+ key (replace-regexp-in-string"^[ \t\n]+" "" key)
+ key (replace-regexp-in-string"[ \t\n]+$" "" key))
+ (goto-char binding-start)
+ (setq binding (buffer-substring-no-properties
+ binding-start
+ (line-end-position)))
+ (unless (member binding '("self-insert-command"))
+ (push (cons key binding) section))))))
+ (forward-line))
+ (push (cons header (nreverse section)) sections)
+ (nreverse sections))))
+
+(defun helm-descbinds-action:execute (candidate)
+ "An action that execute selected CANDIDATE command."
+ (let ((x (cdr candidate))
+ (helm-full-frame helm-descbind--initial-full-frame))
+ (cond
+ ((equal x "Keyboard Macro")
+ (command-execute (kbd (car candidate))))
+ ((stringp x)
+ (insert x))
+ ((commandp x)
+ ;; Using a timer here trigger a timer error with help-for-help
+ ;; (and perhaps others that use a timer themselves), so use
+ ;; directly `call-interactively'.
+ (call-interactively x)))))
+
+(defun helm-descbinds-action:describe (candidate)
+ "An action that describe selected CANDIDATE function."
+ (let ((name (cdr candidate)))
+ (if (equal name "Keyboard Macro")
+ (describe-key (kbd (car candidate)))
+ (describe-function name))))
+
+(defun helm-descbinds-action:find-func (candidate)
+ "An action that find selected CANDIDATE function."
+ (find-function (cdr candidate)))
+
+(defun helm-descbinds-default-candidate-formatter (key binding)
+ "Default candidate formatter."
+ (format "%-10s\t%s" key binding))
+
+(defun helm-descbinds-order-section (section)
+ (cl-loop for n = 0 then (1+ n)
+ for regexp in helm-descbinds-section-order
+ if (and (car section) (string-match regexp (car section)))
+ return n
+ finally
+ return n))
+
+(defun helm-descbinds-transform-candidates (candidates)
+ (cl-loop for (key . command) in candidates
+ for sym = (intern-soft command)
+ collect
+ (cons (funcall helm-descbinds-candidate-formatter key command)
+ (cons key (if (commandp sym) sym command)))))
+
+(defun helm-descbinds-action-transformer (actions cand)
+ "Default action transformer for `helm-descbinds'.
+Provide a useful behavior for prefix commands."
+ (if (stringp (cdr cand))
+ (helm-make-actions
+ "helm-descbinds this prefix"
+ (lambda (cand)
+ (describe-bindings (kbd (car cand)))))
+ actions))
+
+(defun helm-descbinds-sources (buffer &optional prefix menus)
+ (mapcar
+ (lambda (section)
+ (helm-descbinds-source (car section) (cdr section)))
+ (sort
+ (helm-descbinds-all-sections buffer prefix menus)
+ (lambda (a b)
+ (< (helm-descbinds-order-section a)
+ (helm-descbinds-order-section b))))))
+
+(defclass helm-descbinds-source-class (helm-source-sync) ())
+
+(defun helm-descbinds-source (name candidates)
+ (when (and name candidates)
+ (helm-make-source name 'helm-descbinds-source-class
+ :candidates candidates
+ :candidate-transformer #'helm-descbinds-transform-candidates
+ :filtered-candidate-transformer #'helm-fuzzy-highlight-matches
+ :persistent-action #'helm-descbinds-action:describe
+ :action-transformer #'helm-descbinds-action-transformer
+ :action 'helm-descbinds-actions)))
+
+;;;###autoload
+(defun helm-descbinds (&optional prefix buffer)
+ "A convenient helm version of `describe-bindings'.
+
+Turning on `helm-descbinds-mode' is the recommended way to
+install this command to replace `describe-bindings'.
+
+You complete against a list of keys + command pairs presented in
+a similar way as `describe-bindings' does, split into sections
+defined by the types of the key bindings (minor and major modes,
+global bindings, etc).
+
+The default action executes a command as if the binding had been
+entered, or narrows the commands according to a prefix key,
+respectively.
+
+The persistent action pops up a help buffer for the selected
+command without quitting.
+
+For key translation maps, the default actions are not very
+useful, yet they are listed for completeness."
+ (interactive)
+ (let ((old-helm-full-frame helm-full-frame)
+ (helm-full-frame (and (not (minibufferp))
+ (memq helm-descbinds-window-style
+ '(same-window one-window))))
+ (helm-before-initialize-hook (if (and (not (minibufferp))
+ (eq helm-descbinds-window-style
+ 'one-window))
+ (cons 'delete-other-windows
+ helm-before-initialize-hook)
+ helm-before-initialize-hook))
+ (enable-recursive-minibuffers t))
+ (setq helm-descbind--initial-full-frame old-helm-full-frame)
+ (helm :sources (helm-descbinds-sources
+ (or buffer (current-buffer)) prefix)
+ :buffer "*helm-descbinds*"
+ :resume 'noresume
+ :allow-nest t)))
+
+(provide 'helm-descbinds)
+
+;;; helm-descbinds.el ends here
+++ /dev/null
-;;; helm-git-autoloads.el --- automatically extracted autoloads
-;;
-;;; Code:
-
-\f
-;;;### (autoloads nil nil ("helm-git-pkg.el" "helm-git.el") (21792
-;;;;;; 6079 675972 0))
-
-;;;***
-\f
-(provide 'helm-git-autoloads)
-;; Local Variables:
-;; version-control: never
-;; no-byte-compile: t
-;; no-update-autoloads: t
-;; coding: utf-8
-;; End:
-;;; helm-git-autoloads.el ends here
+++ /dev/null
-(define-package "helm-git" "20120630.1403" "Helm extension for Git." (quote nil))
+++ /dev/null
-;;; helm-git.el --- Helm extension for Git.
-
-;; Copyright (C) 2012 Marian Schubert
-
-;; Author : Marian Schubert <marian.schubertNOSPAMgmail.com>
-;; URL : https://github.com/maio/helm-git
-;; Package-Version: 20120630.1403
-;; Version : 1.1
-;; Keywords : helm, git
-
-;; This file is NOT part of GNU Emacs.
-
-;;; License:
-
-;; 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, 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 GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
-
-;;; Commentary:
-;;
-;; Helm Git extension makes opening files from current Git repository
-;; fast and easy. It uses Git binary (using magit) to get list of
-;; project files so it's prety fast even for large projects with
-;; thousands of files. It also takes into account .gitignore file so
-;; that you only get real project files. Magit should also make it
-;; usable on wide variety of OS.
-;;
-;;; Code:
-
-(require 'helm-locate)
-(require 'magit)
-
-(defun helm-git-file-name-localname (path)
- (if (file-remote-p path)
- (tramp-file-name-localname (tramp-dissect-file-name path))
- path))
-
-(defun helm-git-git-dir ()
- "This function is required because magit-git-dir doesn't always return tramp path."
- (if (file-remote-p default-directory)
- (let ((path (tramp-dissect-file-name default-directory)))
- (tramp-make-tramp-file-name
- (tramp-file-name-method path)
- (tramp-file-name-user path)
- (tramp-file-name-host path)
- (helm-git-file-name-localname (magit-git-dir))))
- (magit-git-dir)))
-
-(defun helm-git-root-dir ()
- (expand-file-name ".." (helm-git-git-dir)))
-
-(defun helm-git-root-p (candidate)
- (setq candidate (expand-file-name candidate))
- (let ((default-directory (if (file-directory-p candidate)
- (file-name-as-directory candidate)
- (file-name-as-directory
- helm-ff-default-directory))))
- (stringp (condition-case nil
- (helm-git-root-dir)
- (error nil)))))
-
-(defun helm-git-file-full-path (name)
- (expand-file-name name (helm-git-root-dir)))
-
-(defun helm-git-find-file (name)
- (find-file (helm-git-file-full-path name)))
-
-(defun helm-c-git-files ()
- (magit-git-lines "ls-files" "--full-name"
- "--" (helm-git-file-name-localname (helm-git-root-dir))))
-
-;; [NOTE] When value is changed need to restart emacs.
-(defvar helm-git-ff-action-index 4
- "Add list git files action in `helm-c-source-find-files' at this index.")
-
-(defun helm-ff-git-find-files (candidate)
- (let ((default-directory (file-name-as-directory
- (if (file-directory-p candidate)
- (expand-file-name candidate)
- (file-name-directory candidate)))))
- (helm-run-after-quit
- #'(lambda (d)
- (let ((default-directory d))
- (helm-git-find-files)))
- default-directory)))
-
-(when (require 'helm-files)
- (helm-add-action-to-source-if
- "List git files"
- 'helm-ff-git-find-files
- helm-c-source-find-files
- 'helm-git-root-p
- helm-git-ff-action-index))
-
-(defvar helm-c-source-git-files
- `((name . "Git files list")
- (init . (lambda ()
- (helm-init-candidates-in-buffer
- "*helm git*" (helm-c-git-files))))
- (candidates-in-buffer)
- (keymap . ,helm-generic-files-map)
- (help-message . helm-generic-file-help-message)
- (mode-line . helm-generic-file-mode-line-string)
- (match helm-c-match-on-basename)
- (type . file)
- (action . (lambda (candidate)
- (helm-git-find-file candidate))))
- "Helm Git files source definition")
-
-(defun helm-git-find-files ()
- (interactive)
- (helm :sources '(helm-c-source-git-files)))
-
-(provide 'helm-git)
-
-;;; helm-git.el ends here
--- /dev/null
+;;; helm-git-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+
+(add-to-list 'load-path (directory-file-name
+ (or (file-name-directory #$) (car load-path))))
+
+\f
+;;;### (autoloads nil "helm-git" "helm-git.el" (0 0 0 0))
+;;; Generated autoloads from helm-git.el
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-git" '("helm-")))
+
+;;;***
+\f
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; coding: utf-8
+;; End:
+;;; helm-git-autoloads.el ends here
--- /dev/null
+;;; -*- no-byte-compile: t -*-
+(define-package "helm-git" "20120630.2103" "Helm extension for Git." 'nil :commit "cb96a52b5aecadd3c27aba7749d14e43ab128d55" :keywords '("helm" "git") :authors '(("Marian Schubert" . "marian.schubertNOSPAMgmail.com")) :maintainer '("Marian Schubert" . "marian.schubertNOSPAMgmail.com") :url "https://github.com/maio/helm-git")
--- /dev/null
+;;; helm-git.el --- Helm extension for Git.
+
+;; Copyright (C) 2012 Marian Schubert
+
+;; Author : Marian Schubert <marian.schubertNOSPAMgmail.com>
+;; URL : https://github.com/maio/helm-git
+;; Package-Version: 20120630.2103
+;; Version : 1.1
+;; Keywords : helm, git
+
+;; This file is NOT part of GNU Emacs.
+
+;;; License:
+
+;; 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, 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 GNU Emacs; see the file COPYING. If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+;;
+;; Helm Git extension makes opening files from current Git repository
+;; fast and easy. It uses Git binary (using magit) to get list of
+;; project files so it's prety fast even for large projects with
+;; thousands of files. It also takes into account .gitignore file so
+;; that you only get real project files. Magit should also make it
+;; usable on wide variety of OS.
+;;
+;;; Code:
+
+(require 'helm-locate)
+(require 'magit)
+
+(defun helm-git-file-name-localname (path)
+ (if (file-remote-p path)
+ (tramp-file-name-localname (tramp-dissect-file-name path))
+ path))
+
+(defun helm-git-git-dir ()
+ "This function is required because magit-git-dir doesn't always return tramp path."
+ (if (file-remote-p default-directory)
+ (let ((path (tramp-dissect-file-name default-directory)))
+ (tramp-make-tramp-file-name
+ (tramp-file-name-method path)
+ (tramp-file-name-user path)
+ (tramp-file-name-host path)
+ (helm-git-file-name-localname (magit-git-dir))))
+ (magit-git-dir)))
+
+(defun helm-git-root-dir ()
+ (expand-file-name ".." (helm-git-git-dir)))
+
+(defun helm-git-root-p (candidate)
+ (setq candidate (expand-file-name candidate))
+ (let ((default-directory (if (file-directory-p candidate)
+ (file-name-as-directory candidate)
+ (file-name-as-directory
+ helm-ff-default-directory))))
+ (stringp (condition-case nil
+ (helm-git-root-dir)
+ (error nil)))))
+
+(defun helm-git-file-full-path (name)
+ (expand-file-name name (helm-git-root-dir)))
+
+(defun helm-git-find-file (name)
+ (find-file (helm-git-file-full-path name)))
+
+(defun helm-c-git-files ()
+ (magit-git-lines "ls-files" "--full-name"
+ "--" (helm-git-file-name-localname (helm-git-root-dir))))
+
+;; [NOTE] When value is changed need to restart emacs.
+(defvar helm-git-ff-action-index 4
+ "Add list git files action in `helm-c-source-find-files' at this index.")
+
+(defun helm-ff-git-find-files (candidate)
+ (let ((default-directory (file-name-as-directory
+ (if (file-directory-p candidate)
+ (expand-file-name candidate)
+ (file-name-directory candidate)))))
+ (helm-run-after-quit
+ #'(lambda (d)
+ (let ((default-directory d))
+ (helm-git-find-files)))
+ default-directory)))
+
+(when (require 'helm-files)
+ (helm-add-action-to-source-if
+ "List git files"
+ 'helm-ff-git-find-files
+ helm-c-source-find-files
+ 'helm-git-root-p
+ helm-git-ff-action-index))
+
+(defvar helm-c-source-git-files
+ `((name . "Git files list")
+ (init . (lambda ()
+ (helm-init-candidates-in-buffer
+ "*helm git*" (helm-c-git-files))))
+ (candidates-in-buffer)
+ (keymap . ,helm-generic-files-map)
+ (help-message . helm-generic-file-help-message)
+ (mode-line . helm-generic-file-mode-line-string)
+ (match helm-c-match-on-basename)
+ (type . file)
+ (action . (lambda (candidate)
+ (helm-git-find-file candidate))))
+ "Helm Git files source definition")
+
+(defun helm-git-find-files ()
+ (interactive)
+ (helm :sources '(helm-c-source-git-files)))
+
+(provide 'helm-git)
+
+;;; helm-git.el ends here
+++ /dev/null
-Helm Git extension makes opening files from current Git repository
-fast and easy. It uses Git binary (using magit) to get list of
-project files so it's prety fast even for large projects with
-thousands of files. It also takes into account .gitignore file so
-that you only get real project files. Magit should also make it
-usable on wide variety of OS.
+++ /dev/null
-;;; helm-gtags-autoloads.el --- automatically extracted autoloads
-;;
-;;; Code:
-(add-to-list 'load-path (or (file-name-directory #$) (car load-path)))
-\f
-;;;### (autoloads nil "helm-gtags" "helm-gtags.el" (22215 7814 0
-;;;;;; 0))
-;;; Generated autoloads from helm-gtags.el
-
-(autoload 'helm-gtags-clear-all-cache "helm-gtags" "\
-
-
-\(fn)" t nil)
-
-(autoload 'helm-gtags-clear-cache "helm-gtags" "\
-
-
-\(fn)" t nil)
-
-(autoload 'helm-gtags-next-history "helm-gtags" "\
-Jump to next position on context stack
-
-\(fn)" t nil)
-
-(autoload 'helm-gtags-previous-history "helm-gtags" "\
-Jump to previous position on context stack
-
-\(fn)" t nil)
-
-(autoload 'helm-gtags-select "helm-gtags" "\
-
-
-\(fn)" t nil)
-
-(autoload 'helm-gtags-select-path "helm-gtags" "\
-
-
-\(fn)" t nil)
-
-(autoload 'helm-gtags-tags-in-this-function "helm-gtags" "\
-Show tagnames which are referenced in this function and jump to it.
-
-\(fn)" t nil)
-
-(autoload 'helm-gtags-create-tags "helm-gtags" "\
-
-
-\(fn DIR LABEL)" t nil)
-
-(autoload 'helm-gtags-find-tag "helm-gtags" "\
-Jump to definition
-
-\(fn TAG)" t nil)
-
-(autoload 'helm-gtags-find-tag-other-window "helm-gtags" "\
-Jump to definition in other window.
-
-\(fn TAG)" t nil)
-
-(autoload 'helm-gtags-find-rtag "helm-gtags" "\
-Jump to referenced point
-
-\(fn TAG)" t nil)
-
-(autoload 'helm-gtags-find-symbol "helm-gtags" "\
-Jump to the symbol location
-
-\(fn TAG)" t nil)
-
-(autoload 'helm-gtags-find-pattern "helm-gtags" "\
-Grep and jump by gtags tag files.
-
-\(fn PATTERN)" t nil)
-
-(autoload 'helm-gtags-find-files "helm-gtags" "\
-Find file from tagged with gnu global.
-
-\(fn FILE)" t nil)
-
-(autoload 'helm-gtags-find-tag-from-here "helm-gtags" "\
-Jump point by current point information.
-Jump to definition point if cursor is on its reference.
-Jump to reference point if curosr is on its definition
-
-\(fn)" t nil)
-
-(autoload 'helm-gtags-dwim "helm-gtags" "\
-Find by context. Here is
-- on include statement then jump to included file
-- on symbol definition then jump to its references
-- on reference point then jump to its definition.
-
-\(fn)" t nil)
-
-(autoload 'helm-gtags-parse-file "helm-gtags" "\
-Parse current file with gnu global. This is similar to `imenu'.
-You can jump definitions of functions, symbols in this file.
-
-\(fn)" t nil)
-
-(autoload 'helm-gtags-pop-stack "helm-gtags" "\
-Jump to previous point on the context stack and pop it from stack.
-
-\(fn)" t nil)
-
-(autoload 'helm-gtags-show-stack "helm-gtags" "\
-Show current context stack.
-
-\(fn)" t nil)
-
-(autoload 'helm-gtags-clear-stack "helm-gtags" "\
-Clear current context stack.
-
-\(fn)" t nil)
-
-(autoload 'helm-gtags-clear-all-stacks "helm-gtags" "\
-Clear all context stacks.
-
-\(fn)" t nil)
-
-(autoload 'helm-gtags-update-tags "helm-gtags" "\
-Update TAG file. Update All files with `C-u' prefix.
-Generate new TAG file in selected directory with `C-u C-u'
-
-\(fn)" t nil)
-
-(autoload 'helm-gtags-resume "helm-gtags" "\
-Resurrect previously invoked `helm-gtags` command.
-
-\(fn)" t nil)
-
-(autoload 'helm-gtags-mode "helm-gtags" "\
-Toggle Helm-Gtags mode on or off.
-With a prefix argument ARG, enable Helm-Gtags mode if ARG is
-positive, and disable it otherwise. If called from Lisp, enable
-the mode if ARG is omitted or nil, and toggle it if ARG is `toggle'.
-\\{helm-gtags-mode-map}
-
-\(fn &optional ARG)" t nil)
-
-;;;***
-\f
-;; Local Variables:
-;; version-control: never
-;; no-byte-compile: t
-;; no-update-autoloads: t
-;; End:
-;;; helm-gtags-autoloads.el ends here
+++ /dev/null
-(define-package "helm-gtags" "20160202.503" "GNU GLOBAL helm interface" '((emacs "24.3") (helm "1.7.7")) :url "https://github.com/syohex/emacs-helm-gtags")
+++ /dev/null
-;;; helm-gtags.el --- GNU GLOBAL helm interface -*- lexical-binding: t; -*-
-
-;; Copyright (C) 2016 by Syohei YOSHIDA
-
-;; Author: Syohei YOSHIDA <syohexNOSPAMgmail.com>
-;; URL: https://github.com/syohex/emacs-helm-gtags
-;; Package-Version: 20160202.503
-;; Version: 1.5.4
-;; Package-Requires: ((emacs "24.3") (helm "1.7.7"))
-
-;; 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/>.
-
-;;; Commentary:
-
-;; `helm-gtags.el' is a `helm' interface of GNU Global.
-;; `helm-gtags.el' is not compatible `anything-gtags.el', but `helm-gtags.el'
-;; is designed for fast search.
-
-;;
-;; To use this package, add these lines to your init.el or .emacs file:
-;;
-;; ;; Enable helm-gtags-mode
-;; (add-hook 'c-mode-hook 'helm-gtags-mode)
-;; (add-hook 'c++-mode-hook 'helm-gtags-mode)
-;; (add-hook 'asm-mode-hook 'helm-gtags-mode)
-;;
-;; ;; Set key bindings
-;; (eval-after-load "helm-gtags"
-;; '(progn
-;; (define-key helm-gtags-mode-map (kbd "M-t") 'helm-gtags-find-tag)
-;; (define-key helm-gtags-mode-map (kbd "M-r") 'helm-gtags-find-rtag)
-;; (define-key helm-gtags-mode-map (kbd "M-s") 'helm-gtags-find-symbol)
-;; (define-key helm-gtags-mode-map (kbd "M-g M-p") 'helm-gtags-parse-file)
-;; (define-key helm-gtags-mode-map (kbd "C-c <") 'helm-gtags-previous-history)
-;; (define-key helm-gtags-mode-map (kbd "C-c >") 'helm-gtags-next-history)
-;; (define-key helm-gtags-mode-map (kbd "M-,") 'helm-gtags-pop-stack)))
-;;
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'helm)
-(require 'helm-files)
-(require 'which-func)
-(require 'pulse)
-
-(declare-function helm-comp-read "helm-mode")
-(declare-function cygwin-convert-file-name-from-windows "cygw32.c")
-(declare-function cygwin-convert-file-name-to-windows "cygw32.c")
-
-(defgroup helm-gtags nil
- "GNU GLOBAL for helm."
- :group 'helm)
-
-(defcustom helm-gtags-path-style 'root
- "Style of file path"
- :type '(choice (const :tag "Root of the current project" root)
- (const :tag "Relative from the current directory" relative)
- (const :tag "Absolute Path" absolute)))
-
-(defcustom helm-gtags-ignore-case nil
- "Ignore case in each search."
- :type 'boolean)
-
-(defcustom helm-gtags-read-only nil
- "Gtags read only mode."
- :type 'boolean)
-
-(defcustom helm-gtags-auto-update nil
- "*If non-nil, tag files are updated whenever a file is saved."
- :type 'boolean)
-
-(defcustom helm-gtags-pulse-at-cursor t
- "If non-nil, pulse at point after jumping"
- :type 'boolean)
-
-(defcustom helm-gtags-cache-select-result nil
- "*If non-nil, results of helm-gtags-select and helm-gtags-select-path are cached."
- :type 'boolean)
-
-(defcustom helm-gtags-cache-max-result-size (* 10 1024 1024) ;10M
- "Max size(bytes) to cache for each select result."
- :type 'integer)
-
-(defcustom helm-gtags-update-interval-second 60
- "Tags are updated in `after-save-hook' if this seconds is passed from last update.
-Always update if value of this variable is nil."
- :type '(choice (integer :tag "Update interval seconds")
- (boolean :tag "Update every time" nil)))
-
-(defcustom helm-gtags-highlight-candidate t
- "Highlight candidate or not"
- :type 'boolean)
-
-(defcustom helm-gtags-use-input-at-cursor nil
- "Use input at cursor"
- :type 'boolean)
-
-(defcustom helm-gtags-prefix-key "\C-c"
- "If non-nil, it is used for the prefix key of gtags-xxx command."
- :type 'string)
-
-(defcustom helm-gtags-suggested-key-mapping nil
- "If non-nil, suggested key mapping is enabled."
- :type 'boolean)
-
-(defcustom helm-gtags-preselect nil
- "If non-nil, preselect current file and line."
- :type 'boolean)
-
-(defcustom helm-gtags-display-style nil
- "Style of display result."
- :type '(choice (const :tag "Show in detail" detail)
- (const :tag "Normal style" nil)))
-
-(defcustom helm-gtags-fuzzy-match nil
- "Enable fuzzy match"
- :type 'boolean)
-
-(defcustom helm-gtags-maximum-candidates (if helm-gtags-fuzzy-match 100 9999)
- "Maximum number of helm candidates"
- :type 'integer)
-
-(defcustom helm-gtags-direct-helm-completing nil
- "Use helm mode directly."
- :type 'boolean)
-
-(defface helm-gtags-file
- '((t :inherit font-lock-keyword-face))
- "Face for line numbers in the error list.")
-
-(defface helm-gtags-lineno
- '((t :inherit font-lock-doc-face))
- "Face for line numbers in the error list.")
-
-(defface helm-gtags-match
- '((t :inherit helm-match))
- "Face for word matched against tagname")
-
-(defvar helm-gtags--tag-location nil)
-(defvar helm-gtags--last-update-time 0)
-(defvar helm-gtags--completing-history nil)
-(defvar helm-gtags--context-stack (make-hash-table :test 'equal))
-(defvar helm-gtags--result-cache (make-hash-table :test 'equal))
-(defvar helm-gtags--saved-context nil)
-(defvar helm-gtags--use-otherwin nil)
-(defvar helm-gtags--local-directory nil)
-(defvar helm-gtags--parsed-file nil)
-(defvar helm-gtags--current-position nil)
-(defvar helm-gtags--real-tag-location nil)
-(defvar helm-gtags--last-input nil)
-(defvar helm-gtags--query nil)
-(defvar helm-gtags--last-default-directory nil)
-
-(defconst helm-gtags--buffer "*helm gtags*")
-
-(defconst helm-gtags--include-regexp
- "\\`\\s-*#\\(?:include\\|import\\)\\s-*[\"<]\\(?:[./]*\\)?\\(.*?\\)[\">]")
-
-(defmacro helm-declare-obsolete-variable (old new version)
- `(progn
- (defvaralias ,old ,new)
- (make-obsolete-variable ,old ,new ,version)))
-
-(helm-declare-obsolete-variable
- 'helm-c-gtags-path-style 'helm-gtags-path-style "0.8")
-(helm-declare-obsolete-variable
- 'helm-c-gtags-ignore-case 'helm-gtags-ignore-case "0.8")
-(helm-declare-obsolete-variable
- 'helm-c-gtags-read-only 'helm-gtags-read-only "0.8")
-
-;; completsion function for completing-read.
-(defun helm-gtags--completing-gtags (string predicate code)
- (helm-gtags--complete 'tag string predicate code))
-(defun helm-gtags--completing-pattern (string predicate code)
- (helm-gtags--complete 'pattern string predicate code))
-(defun helm-gtags--completing-grtags (string predicate code)
- (helm-gtags--complete 'rtag string predicate code))
-(defun helm-gtags--completing-gsyms (string predicate code)
- (helm-gtags--complete 'symbol string predicate code))
-(defun helm-gtags--completing-files (string predicate code)
- (helm-gtags--complete 'find-file string predicate code))
-
-(defconst helm-gtags-comp-func-alist
- '((tag . helm-gtags--completing-gtags)
- (pattern . helm-gtags--completing-pattern)
- (rtag . helm-gtags--completing-grtags)
- (symbol . helm-gtags--completing-gsyms)
- (find-file . helm-gtags--completing-files)))
-
-(defconst helm-gtags--search-option-alist
- '((pattern . "-g")
- (rtag . "-r")
- (symbol . "-s")
- (find-file . "-Poa")))
-
-(defsubst helm-gtags--windows-p ()
- (memq system-type '(windows-nt ms-dos)))
-
-(defun helm-gtags--remove-carrige-returns ()
- (when (helm-gtags--windows-p)
- (save-excursion
- (goto-char (point-min))
- (while (re-search-forward "\xd" nil t)
- (replace-match "")))))
-
-;; Work around for GNU global Windows issue
-(defsubst helm-gtags--use-abs-path-p (gtagslibpath)
- (and (helm-gtags--windows-p) gtagslibpath))
-
-(defun helm-gtags--construct-options (type completion)
- (let ((find-file-p (eq type 'find-file))
- (gtagslibpath (getenv "GTAGSLIBPATH"))
- options)
- (unless find-file-p
- (push "--result=grep" options))
- (when completion
- (push "-c" options))
- (helm-aif (assoc-default type helm-gtags--search-option-alist)
- (push it options))
- (when (or (eq helm-gtags-path-style 'absolute)
- (helm-gtags--use-abs-path-p gtagslibpath))
- (push "-a" options))
- (when helm-gtags-ignore-case
- (push "-i" options))
- (when (and current-prefix-arg (not find-file-p))
- (push "-l" options))
- (when gtagslibpath
- (push "-T" options))
- options))
-
-(defun helm-gtags--complete (type string predicate code)
- (let* ((options (helm-gtags--construct-options type t))
- (args (reverse (cons string options)))
- candidates)
- (with-temp-buffer
- (apply #'process-file "global" nil t nil args)
- (goto-char (point-min))
- (while (re-search-forward "^\\(.+\\)$" nil t)
- (push (match-string-no-properties 1) candidates)))
- (if (not code)
- (try-completion string candidates predicate)
- (all-completions string candidates predicate))))
-
-(defun helm-gtags--token-at-point (type)
- (if (not (eq type 'find-file))
- (thing-at-point 'symbol)
- (let ((line (helm-current-line-contents)))
- (when (string-match helm-gtags--include-regexp line)
- (match-string-no-properties 1 line)))))
-
-(defconst helm-gtags--prompt-alist
- '((tag . "Find Definition: ")
- (pattern . "Find Pattern: ")
- (rtag . "Find Reference: ")
- (symbol . "Find Symbol: ")
- (find-file . "Find File: ")))
-
-(defun helm-gtags--read-tagname (type &optional default-tagname)
- (let ((tagname (helm-gtags--token-at-point type))
- (prompt (assoc-default type helm-gtags--prompt-alist))
- (comp-func (assoc-default type helm-gtags-comp-func-alist)))
- (if (and tagname helm-gtags-use-input-at-cursor)
- tagname
- (when (and (not tagname) default-tagname)
- (setq tagname default-tagname))
- (when tagname
- (setq prompt (format "%s(default \"%s\") " prompt tagname)))
- (let ((completion-ignore-case helm-gtags-ignore-case)
- (completing-read-function 'completing-read-default))
- (if (and helm-gtags-direct-helm-completing (memq type '(tag rtag symbol find-file)))
- (helm-comp-read prompt comp-func
- :history 'helm-gtags--completing-history
- :exec-when-only-one t
- :default tagname)
- (completing-read prompt comp-func nil nil nil
- 'helm-gtags--completing-history tagname))))))
-
-(defun helm-gtags--path-libpath-p (tagroot)
- (helm-aif (getenv "GTAGSLIBPATH")
- (cl-loop for path in (parse-colon-path it)
- for libpath = (file-name-as-directory (expand-file-name path))
- thereis (string= tagroot libpath))))
-
-(defun helm-gtags--tag-directory ()
- (with-temp-buffer
- (helm-aif (getenv "GTAGSROOT")
- it
- (unless (zerop (process-file "global" nil t nil "-p"))
- (error "GTAGS not found"))
- (goto-char (point-min))
- (when (looking-at "^\\([^\r\n]+\\)")
- (let ((tag-path (match-string-no-properties 1)))
- (file-name-as-directory
- (if (eq system-type 'cygwin)
- (cygwin-convert-file-name-from-windows tag-path)
- tag-path)))))))
-
-(defun helm-gtags--find-tag-directory ()
- (setq helm-gtags--real-tag-location nil)
- (let ((tagroot (helm-gtags--tag-directory)))
- (if (and (helm-gtags--path-libpath-p tagroot) helm-gtags--tag-location)
- (progn
- (setq helm-gtags--real-tag-location tagroot)
- helm-gtags--tag-location)
- (setq helm-gtags--tag-location tagroot))))
-
-(defun helm-gtags--base-directory ()
- (let ((dir (or helm-gtags--last-default-directory
- helm-gtags--local-directory
- (cl-case helm-gtags-path-style
- (root (or helm-gtags--real-tag-location
- helm-gtags--tag-location))
- (otherwise default-directory))))
- (remote (file-remote-p default-directory)))
- (if (and remote (not (file-remote-p dir)))
- (concat remote dir)
- dir)))
-
-(defsubst helm-gtags--new-context-info (index stack)
- (list :index index :stack stack))
-
-(defun helm-gtags--put-context-stack (tag-location index stack)
- (puthash tag-location (helm-gtags--new-context-info index stack)
- helm-gtags--context-stack))
-
-(defsubst helm-gtags--current-context ()
- (let ((file (buffer-file-name (current-buffer))))
- (list :file file :position (point) :readonly buffer-file-read-only)))
-
-(defsubst helm-gtags--save-current-context ()
- (setq helm-gtags--saved-context (helm-gtags--current-context)))
-
-(defun helm-gtags--open-file (file readonly)
- (if readonly
- (find-file-read-only file)
- (find-file file)))
-
-(defun helm-gtags--open-file-other-window (file readonly)
- (setq helm-gtags--use-otherwin nil)
- (if readonly
- (find-file-read-only-other-window file)
- (find-file-other-window file)))
-
-(defun helm-gtags--get-context-info ()
- (let* ((tag-location (helm-gtags--find-tag-directory))
- (context-info (gethash tag-location helm-gtags--context-stack))
- (context-stack (plist-get context-info :stack)))
- (if (null context-stack)
- (error "Context stack is empty(TAG at %s)" tag-location)
- context-info)))
-
-(defun helm-gtags--get-or-create-context-info ()
- (or (gethash helm-gtags--tag-location helm-gtags--context-stack)
- (helm-gtags--new-context-info -1 nil)))
-
-;;;###autoload
-(defun helm-gtags-clear-all-cache ()
- (interactive)
- (clrhash helm-gtags--result-cache))
-
-;;;###autoload
-(defun helm-gtags-clear-cache ()
- (interactive)
- (helm-gtags--find-tag-directory)
- (let* ((tag-location (or helm-gtags--real-tag-location
- helm-gtags--tag-location))
- (gtags-path (concat tag-location "GTAGS"))
- (gpath-path (concat tag-location "GPATH")))
- (remhash gtags-path helm-gtags--result-cache)
- (remhash gpath-path helm-gtags--result-cache)))
-
-(defun helm-gtags--move-to-context (context)
- (let ((file (plist-get context :file))
- (curpoint (plist-get context :position))
- (readonly (plist-get context :readonly)))
- (helm-gtags--open-file file readonly)
- (goto-char curpoint)
- (recenter)))
-
-;;;###autoload
-(defun helm-gtags-next-history ()
- "Jump to next position on context stack"
- (interactive)
- (let* ((context-info (helm-gtags--get-context-info))
- (current-index (plist-get context-info :index))
- (context-stack (plist-get context-info :stack))
- context)
- (when (<= current-index -1)
- (error "This context is latest in context stack"))
- (setf (nth current-index context-stack) (helm-gtags--current-context))
- (cl-decf current-index)
- (if (= current-index -1)
- (setq context helm-gtags--current-position
- helm-gtags--current-position nil)
- (setq context (nth current-index context-stack)))
- (helm-gtags--put-context-stack helm-gtags--tag-location
- current-index context-stack)
- (helm-gtags--move-to-context context)))
-
-;;;###autoload
-(defun helm-gtags-previous-history ()
- "Jump to previous position on context stack"
- (interactive)
- (let* ((context-info (helm-gtags--get-context-info))
- (current-index (plist-get context-info :index))
- (context-stack (plist-get context-info :stack))
- (context-length (length context-stack)))
- (cl-incf current-index)
- (when (>= current-index context-length)
- (error "This context is last in context stack"))
- (if (= current-index 0)
- (setq helm-gtags--current-position (helm-gtags--current-context))
- (setf (nth (- current-index 1) context-stack) (helm-gtags--current-context)))
- (let ((prev-context (nth current-index context-stack)))
- (helm-gtags--move-to-context prev-context))
- (helm-gtags--put-context-stack helm-gtags--tag-location
- current-index context-stack)))
-
-(defun helm-gtags--get-result-cache (file)
- (helm-gtags--find-tag-directory)
- (let* ((file-path (concat (or helm-gtags--real-tag-location
- helm-gtags--tag-location)
- file))
- (file-mtime (nth 5 (file-attributes file-path)))
- (hash-value (gethash file-path helm-gtags--result-cache))
- (cached-file-mtime (nth 0 hash-value)))
- (if (and cached-file-mtime (equal cached-file-mtime file-mtime))
- (nth 1 hash-value)
- nil)))
-
-(defun helm-gtags--put-result-cache (file cache)
- (helm-gtags--find-tag-directory)
- (let* ((file-path (concat (or helm-gtags--real-tag-location
- helm-gtags--tag-location)
- file))
- (file-mtime (nth 5 (file-attributes file-path)))
- (hash-value (list file-mtime cache)))
- (puthash file-path hash-value helm-gtags--result-cache)))
-
-(defun helm-gtags--referer-function (file ref-line)
- (let ((is-opened (cl-loop with path = (concat default-directory file)
- for buf in (buffer-list)
- when (string= (buffer-file-name buf) path)
- return it))
- retval)
- (with-current-buffer (find-file-noselect file)
- (goto-char (point-min))
- (forward-line (1- ref-line))
- (unless (zerop (current-indentation))
- (setq retval (which-function)))
- (unless is-opened
- (kill-buffer (current-buffer)))
- retval)))
-
-(defun helm-gtags--show-detail ()
- (goto-char (point-min))
- (while (not (eobp))
- (let ((line (helm-current-line-contents)))
- (let* ((file-and-line (helm-gtags--extract-file-and-line line))
- (file (car file-and-line))
- (ref-line (cdr file-and-line))
- (ref-func (helm-gtags--referer-function file ref-line)))
- (when ref-func
- (search-forward ":" nil nil 2)
- (insert " " ref-func "|"))
- (forward-line 1)))))
-
-(defun helm-gtags--print-path-in-gtagslibpath (args)
- (let ((libpath (getenv "GTAGSLIBPATH")))
- (when libpath
- (dolist (path (parse-colon-path libpath))
- (let ((default-directory (file-name-as-directory path)))
- (apply #'process-file "global" nil t nil "-Poa" args))))))
-
-(defun helm-gtags--exec-global-command (type input &optional detail)
- (let ((args (helm-gtags--construct-command type input)))
- (helm-gtags--find-tag-directory)
- (helm-gtags--save-current-context)
- (let ((buf-coding buffer-file-coding-system))
- (with-current-buffer (helm-candidate-buffer 'global)
- (let ((default-directory (helm-gtags--base-directory))
- (input (car (last args)))
- (coding-system-for-read buf-coding)
- (coding-system-for-write buf-coding))
- (unless (zerop (apply #'process-file "global" nil '(t nil) nil args))
- (error (format "%s: not found" input)))
- ;; --path options does not support searching under GTAGSLIBPATH
- (when (eq type 'find-file)
- (helm-gtags--print-path-in-gtagslibpath args))
- (helm-gtags--remove-carrige-returns)
- (when detail
- (helm-gtags--show-detail)))))))
-
-(defun helm-gtags--construct-command (type &optional in)
- (setq helm-gtags--local-directory nil)
- (let ((dir (helm-attr 'helm-gtags-base-directory (helm-get-current-source))))
- (when (and dir (not (eq type 'find-file)))
- (setq helm-gtags--local-directory dir)))
- (let ((input (or in helm-gtags--query))
- (options (helm-gtags--construct-options type nil)))
- (when (string= input "")
- (error "Input is empty!!"))
- (setq helm-gtags--last-input input)
- (reverse (cons input options))))
-
-(defun helm-gtags--tags-init (&optional input)
- (helm-gtags--exec-global-command 'tag input))
-
-(defun helm-gtags--pattern-init (&optional input)
- (helm-gtags--exec-global-command 'pattern input helm-gtags-display-style))
-
-(defun helm-gtags--rtags-init (&optional input)
- (helm-gtags--exec-global-command 'rtag input helm-gtags-display-style))
-
-(defun helm-gtags--gsyms-init ()
- (helm-gtags--exec-global-command 'symbol nil helm-gtags-display-style))
-
-(defun helm-gtags--files-init ()
- (helm-gtags--exec-global-command 'find-file nil))
-
-(defun helm-gtags--real-file-name ()
- (let ((buffile (buffer-file-name)))
- (unless buffile
- (error "This buffer is not related to file."))
- (if (file-remote-p buffile)
- (tramp-file-name-localname (tramp-dissect-file-name buffile))
- (file-truename buffile))))
-
-(defun helm-gtags--find-tag-from-here-init ()
- (helm-gtags--find-tag-directory)
- (helm-gtags--save-current-context)
- (let ((token (helm-gtags--token-at-point 'from-here)))
- (unless token
- (error "Cursor is not on symbol."))
- (let* ((filename (helm-gtags--real-file-name))
- (from-here-opt (format "--from-here=%d:%s"
- (line-number-at-pos)
- (if (eq system-type 'cygwin)
- (cygwin-convert-file-name-to-windows filename)
- filename))))
- (setq helm-gtags--last-input token)
- (with-current-buffer (helm-candidate-buffer 'global)
- (let* ((default-directory (helm-gtags--base-directory))
- (status (process-file "global" nil '(t nil) nil
- "--result=grep" from-here-opt token)))
- (helm-gtags--remove-carrige-returns)
- (unless (zerop status)
- (cond ((= status 1)
- (error "Error: %s%s" (buffer-string) filename))
- ((= status 3)
- (error "Error: %s" (buffer-string)))
- (t (error "%s: not found" token)))))))))
-
-(defun helm-gtags--parse-file-init ()
- (with-current-buffer (helm-candidate-buffer 'global)
- (unless (zerop (process-file "global" nil t nil
- "--result=cscope" "-f" helm-gtags--parsed-file))
- (error "Failed: 'global --result=cscope -f %s" helm-gtags--parsed-file))
- (helm-gtags--remove-carrige-returns)))
-
-(defun helm-gtags--push-context (context)
- (let* ((context-info (helm-gtags--get-or-create-context-info))
- (current-index (plist-get context-info :index))
- (context-stack (plist-get context-info :stack)))
- (unless (= current-index -1)
- (setq context-stack (nthcdr (1+ current-index) context-stack)))
- (setq helm-gtags--current-position nil)
- (push context context-stack)
- (helm-gtags--put-context-stack helm-gtags--tag-location -1 context-stack)))
-
-(defsubst helm-gtags--select-find-file-func ()
- (if helm-gtags--use-otherwin
- #'helm-gtags--open-file-other-window
- #'helm-gtags--open-file))
-
-(defun helm-gtags--do-open-file (open-func file line)
- (funcall open-func file helm-gtags-read-only)
- (goto-char (point-min))
- (forward-line (1- line))
- (back-to-indentation)
- (recenter)
- (helm-gtags--push-context helm-gtags--saved-context)
- (when helm-gtags-pulse-at-cursor
- (pulse-momentary-highlight-one-line (point))))
-
-(defun helm-gtags--find-line-number (cand)
- (if (string-match "\\s-+\\([1-9][0-9]+\\)\\s-+" cand)
- (string-to-number (match-string-no-properties 1 cand))
- (error "Can't find line number in %s" cand)))
-
-(defun helm-gtags--parse-file-action (cand)
- (let ((line (helm-gtags--find-line-number cand))
- (open-func (helm-gtags--select-find-file-func)))
- (helm-gtags--do-open-file open-func helm-gtags--parsed-file line)))
-
-(defsubst helm-gtags--has-drive-letter-p (path)
- (string-match-p "\\`[a-zA-Z]:" path))
-
-(defun helm-gtags--extract-file-and-line (cand)
- (if (and (helm-gtags--windows-p) (helm-gtags--has-drive-letter-p cand))
- (when (string-match "\\(\\`[a-zA-Z]:[^:]+\\):\\([^:]+\\)" cand)
- (cons (match-string-no-properties 1 cand)
- (string-to-number (match-string-no-properties 2 cand))))
- (let ((elems (split-string cand ":")))
- (cons (cl-first elems) (string-to-number (cl-second elems))))))
-
-(defun helm-gtags--action-openfile (cand)
- (let* ((file-and-line (helm-gtags--extract-file-and-line cand))
- (filename (car file-and-line))
- (line (cdr file-and-line))
- (open-func (helm-gtags--select-find-file-func))
- (default-directory (helm-gtags--base-directory)))
- (helm-gtags--do-open-file open-func filename line)))
-
-(defun helm-gtags--action-openfile-other-window (cand)
- (let ((helm-gtags--use-otherwin t))
- (helm-gtags--action-openfile cand)))
-
-(defun helm-gtags--file-content-at-pos (file pos)
- (with-current-buffer (find-file-noselect file)
- (save-excursion
- (goto-char pos)
- (format "%s:%d:%s:%s"
- file (line-number-at-pos)
- (helm-aif (which-function) (format "[%s]" it) "")
- (helm-current-line-contents)))))
-
-(defun helm-gtags--files-candidate-transformer (file)
- (if (eq helm-gtags-path-style 'absolute)
- file
- (let ((removed-regexp (concat "\\`" helm-gtags--tag-location)))
- (replace-regexp-in-string removed-regexp "" file))))
-
-(defun helm-gtags--show-stack-init ()
- (cl-loop with context-stack = (plist-get (helm-gtags--get-context-info) :stack)
- with stack-length = (length context-stack)
- for context in (reverse context-stack)
- for file = (plist-get context :file)
- for pos = (plist-get context :position)
- for index = (1- stack-length) then (1- index)
- for line = (helm-gtags--file-content-at-pos file pos)
- for cand = (helm-gtags--files-candidate-transformer line)
- collect (cons cand (propertize cand 'index index))))
-
-(defun helm-gtags--persistent-action (cand)
- (let* ((file-and-line (helm-gtags--extract-file-and-line cand))
- (filename (car file-and-line))
- (line (cdr file-and-line))
- (default-directory (helm-gtags--base-directory)))
- (when (eq helm-gtags-path-style 'relative)
- (setq helm-gtags--last-default-directory default-directory))
- (find-file filename)
- (goto-char (point-min))
- (forward-line (1- line))
- (helm-highlight-current-line)))
-
-(defun helm-gtags--file-persistent-action (cand)
- (let ((default-directory (with-helm-current-buffer
- default-directory)))
- (helm-ff-kill-or-find-buffer-fname cand)))
-
-(defvar helm-gtags--find-file-action
- (helm-make-actions
- "Open file" #'helm-gtags--action-openfile
- "Open file other window" #'helm-gtags--action-openfile-other-window))
-
-(defvar helm-source-gtags-tags
- (helm-build-in-buffer-source "Jump to definitions"
- :init 'helm-gtags--tags-init
- :candidate-number-limit helm-gtags-maximum-candidates
- :real-to-display 'helm-gtags--candidate-transformer
- :persistent-action 'helm-gtags--persistent-action
- :fuzzy-match helm-gtags-fuzzy-match
- :action helm-gtags--find-file-action))
-
-(defvar helm-source-gtags-pattern
- (helm-build-in-buffer-source "Find pattern"
- :init 'helm-gtags--pattern-init
- :candidate-number-limit helm-gtags-maximum-candidates
- :real-to-display 'helm-gtags--candidate-transformer
- :persistent-action 'helm-gtags--persistent-action
- :fuzzy-match helm-gtags-fuzzy-match
- :action helm-gtags--find-file-action))
-
-(defvar helm-source-gtags-rtags
- (helm-build-in-buffer-source "Jump to references"
- :init 'helm-gtags--rtags-init
- :candidate-number-limit helm-gtags-maximum-candidates
- :real-to-display 'helm-gtags--candidate-transformer
- :persistent-action 'helm-gtags--persistent-action
- :fuzzy-match helm-gtags-fuzzy-match
- :action helm-gtags--find-file-action))
-
-(defvar helm-source-gtags-gsyms
- (helm-build-in-buffer-source "Jump to symbols"
- :init 'helm-gtags--gsyms-init
- :candidate-number-limit helm-gtags-maximum-candidates
- :real-to-display 'helm-gtags--candidate-transformer
- :persistent-action 'helm-gtags--persistent-action
- :fuzzy-match helm-gtags-fuzzy-match
- :action helm-gtags--find-file-action))
-
-(defun helm-gtags--highlight-candidate (candidate)
- (let ((regexp (concat "\\_<" helm-gtags--last-input "\\_>"))
- (limit (1- (length candidate)))
- (last-pos 0)
- (case-fold-search nil))
- (while (and (< last-pos limit)
- (string-match regexp candidate last-pos))
- (put-text-property (match-beginning 0) (match-end 0)
- 'face 'helm-gtags-match
- candidate)
- (setq last-pos (1+ (match-end 0))))
- candidate))
-
-(defun helm-gtags--transformer-regexp (candidate)
- (if (and (helm-gtags--windows-p) (helm-gtags--has-drive-letter-p candidate))
- "\\`\\([a-zA-Z]:[^:]+\\):\\([^:]+\\):\\(.*\\)"
- "\\`\\([^:]+\\):\\([^:]+\\):\\(.*\\)"))
-
-(defun helm-gtags--candidate-transformer (candidate)
- (if (not helm-gtags-highlight-candidate)
- candidate
- (let ((regexp (helm-gtags--transformer-regexp candidate)))
- (when (string-match regexp candidate)
- (format "%s:%s:%s"
- (propertize (match-string 1 candidate) 'face 'helm-gtags-file)
- (propertize (match-string 2 candidate) 'face 'helm-gtags-lineno)
- (helm-gtags--highlight-candidate (match-string 3 candidate)))))))
-
-(defun helm-gtags--parse-file-candidate-transformer (file)
- (let ((removed-file (replace-regexp-in-string "\\`\\S-+ " "" file)))
- (when (string-match "\\`\\(\\S-+\\) \\(\\S-+\\) \\(.+\\)\\'" removed-file)
- (format "%-25s %-5s %s"
- (match-string-no-properties 1 removed-file)
- (match-string-no-properties 2 removed-file)
- (match-string-no-properties 3 removed-file)))))
-
-(defvar helm-source-gtags-files
- (helm-build-in-buffer-source "Find files"
- :init 'helm-gtags--files-init
- :candidate-number-limit helm-gtags-maximum-candidates
- :real-to-display 'helm-gtags--files-candidate-transformer
- :persistent-action 'helm-gtags--persistent-action
- :fuzzy-match helm-gtags-fuzzy-match
- :action (helm-actions-from-type-file)))
-
-(defvar helm-source-gtags-find-tag-from-here
- (helm-build-in-buffer-source "Find tag from here"
- :init 'helm-gtags--find-tag-from-here-init
- :candidate-number-limit helm-gtags-maximum-candidates
- :real-to-display 'helm-gtags--candidate-transformer
- :persistent-action 'helm-gtags--persistent-action
- :fuzzy-match helm-gtags-fuzzy-match
- :action helm-gtags--find-file-action))
-
-(defvar helm-source-gtags-parse-file
- (helm-build-in-buffer-source "Parse file"
- :init 'helm-gtags--parse-file-init
- :candidate-number-limit helm-gtags-maximum-candidates
- :real-to-display 'helm-gtags--parse-file-candidate-transformer
- :fuzzy-match helm-gtags-fuzzy-match
- :action 'helm-gtags--parse-file-action))
-
-(defun helm-gtags--show-stack-action (cand)
- (let* ((index (get-text-property 0 'index cand))
- (context-info (helm-gtags--get-context-info))
- (context-stack (plist-get context-info :stack)))
- (helm-gtags--put-context-stack helm-gtags--tag-location
- index context-stack)
- (helm-gtags--move-to-context (nth index context-stack))))
-
-(defvar helm-source-gtags-show-stack
- (helm-build-sync-source "Show Context Stack"
- :candidates 'helm-gtags--show-stack-init
- :volatile t
- :candidate-number-limit helm-gtags-maximum-candidates
- :persistent-action 'helm-gtags--persistent-action
- :fuzzy-match helm-gtags-fuzzy-match
- :action 'helm-gtags--show-stack-action))
-
-;;;###autoload
-(defun helm-gtags-select ()
- (interactive)
- (helm-gtags--common '(helm-source-gtags-select) nil))
-
-;;;###autoload
-(defun helm-gtags-select-path ()
- (interactive)
- (helm-gtags--common '(helm-source-gtags-select-path) nil))
-
-(defsubst helm-gtags--beginning-of-defun ()
- (cl-case major-mode
- ((c-mode c++-mode java-mode) 'c-beginning-of-defun)
- (php-mode 'php-beginning-of-defun)
- (otherwise #'beginning-of-defun)))
-
-(defsubst helm-gtags--end-of-defun ()
- (cl-case major-mode
- ((c-mode c++-mode java-mode malabar-mode) 'c-end-of-defun)
- (php-mode 'php-end-of-defun)
- (otherwise #'end-of-defun)))
-
-(defun helm-gtags--current-funcion-bound ()
- (save-excursion
- (let (start)
- (funcall (helm-gtags--beginning-of-defun))
- (setq start (line-number-at-pos))
- (funcall (helm-gtags--end-of-defun))
- (cons start (line-number-at-pos)))))
-
-(defun helm-gtags--tags-refered-from-this-function ()
- (let* ((file (helm-gtags--real-file-name))
- (bound (helm-gtags--current-funcion-bound))
- (start-line (car bound))
- (end-line (cdr bound)))
- (with-temp-buffer
- (unless (process-file "global" nil t nil "-f" "-r" file)
- (error "Failed: global -f -r %s" file))
- (goto-char (point-min))
- (let (tagnames finish)
- (while (and (not finish) (not (eobp)))
- (let* ((cols (split-string (helm-current-line-contents) nil t))
- (lineno (string-to-number (cl-second cols))))
- (if (and (> lineno start-line) (< lineno end-line))
- (let* ((tag (cl-first cols))
- (elm (cl-find tag tagnames :test 'equal)))
- (unless elm
- (push tag tagnames)))
- (when (>= lineno end-line)
- (setq finish t)))
- (forward-line 1)))
- (reverse tagnames)))))
-
-(defun helm-gtags--tag-in-function-persistent-action (cand)
- (let* ((bound (helm-gtags--current-funcion-bound))
- (limit (save-excursion
- (goto-char (point-min))
- (forward-line (cdr bound))
- (goto-char (line-end-position))
- (point))))
- (when (search-forward cand nil limit)
- (helm-highlight-current-line))))
-
-;;;###autoload
-(defun helm-gtags-tags-in-this-function ()
- "Show tagnames which are referenced in this function and jump to it."
- (interactive)
- (let ((tags (helm-gtags--tags-refered-from-this-function)))
- (unless tags
- (error "There are no tags which are refered from this function."))
- (let* ((name (format "Tags in [%s]" (which-function)))
- (tag (helm-comp-read
- "Tagnames: " tags
- :must-match t :name name
- :persistent-action 'helm-gtags--tag-in-function-persistent-action)))
- (helm-gtags-find-tag tag))))
-
-(defun helm-gtags--source-select-tag (candidate)
- (helm-build-in-buffer-source "Select Tag"
- :init (lambda () (helm-gtags--tags-init candidate))
- :candidate-number-limit helm-gtags-maximum-candidates
- :persistent-action 'helm-gtags--persistent-action
- :fuzzy-match helm-gtags-fuzzy-match
- :action helm-gtags--find-file-action))
-
-(defun helm-gtags--source-select-rtag (candidate)
- (helm-build-in-buffer-source "Select Rtag"
- :init (lambda () (helm-gtags--rtags-init candidate))
- :candidate-number-limit helm-gtags-maximum-candidates
- :persistent-action 'helm-gtags--persistent-action
- :fuzzy-match helm-gtags-fuzzy-match
- :action helm-gtags--find-file-action))
-
-(defsubst helm-gtags--action-by-timer (src)
- (run-with-timer 0.1 nil (lambda () (helm-gtags--common (list src) nil))))
-
-(defun helm-gtags--select-tag-action (c)
- (helm-gtags--action-by-timer (helm-gtags--source-select-tag c)))
-
-(defun helm-gtags--select-rtag-action (c)
- (helm-gtags--action-by-timer (helm-gtags--source-select-rtag c)))
-
-(defun helm-gtags--select-cache-init-common (args tagfile)
- (let ((cache (helm-gtags--get-result-cache tagfile)))
- (if cache
- (insert cache)
- (apply #'process-file "global" nil t nil args)
- (let* ((cache (buffer-string))
- (cache-size (length cache)))
- (when (<= cache-size helm-gtags-cache-max-result-size)
- (helm-gtags--put-result-cache tagfile cache))))))
-
-(defun helm-gtags--source-select-init ()
- (with-current-buffer (helm-candidate-buffer 'global)
- (if (not helm-gtags-cache-select-result)
- (progn
- (process-file "global" nil t nil "-c")
- (helm-gtags--remove-carrige-returns))
- (helm-gtags--select-cache-init-common '("-c") "GTAGS"))))
-
-(defvar helm-source-gtags-select
- (helm-build-in-buffer-source "Find tag from here"
- :init 'helm-gtags--source-select-init
- :candidate-number-limit helm-gtags-maximum-candidates
- :persistent-action #'ignore
- :fuzzy-match helm-gtags-fuzzy-match
- :action (helm-make-actions
- "Goto the location" #'helm-gtags--select-tag-action
- "Goto the location(other buffer)"
- (lambda (c)
- (setq helm-gtags--use-otherwin t)
- (helm-gtags--select-tag-action c))
- "Move to the referenced point" #'helm-gtags--select-rtag-action)))
-
-(defun helm-gtags--select-path-init ()
- (helm-gtags--find-tag-directory)
- (with-current-buffer (helm-candidate-buffer 'global)
- (let ((options (if (eq helm-gtags-path-style 'relative) "-Po" "-Poa")))
- (if (not helm-gtags-cache-select-result)
- (progn
- (process-file "global" nil t nil options)
- (helm-gtags--remove-carrige-returns))
- (helm-gtags--select-cache-init-common options "GPATH")))))
-
-(defvar helm-source-gtags-select-path
- (helm-build-in-buffer-source "Select path"
- :init 'helm-gtags--select-path-init
- :candidate-number-limit helm-gtags-maximum-candidates
- :real-to-display 'helm-gtags--files-candidate-transformer
- :persistent-action #'helm-gtags--file-persistent-action
- :fuzzy-match helm-gtags-fuzzy-match
- :action (helm-actions-from-type-file)))
-
-(defun helm-gtags--searched-directory ()
- (cl-case (prefix-numeric-value current-prefix-arg)
- (4 (let ((dir (read-directory-name "Input Directory: ")))
- (setq helm-gtags--local-directory (file-name-as-directory dir))))
- (16 (file-name-directory (buffer-file-name)))))
-
-(defsubst helm-gtags--using-other-window-p ()
- (< (prefix-numeric-value current-prefix-arg) 0))
-
-(defun helm-gtags--make-gtags-sentinel (action)
- (lambda (process _event)
- (when (eq (process-status process) 'exit)
- (if (zerop (process-exit-status process))
- (message "Success: %s TAGS" action)
- (message "Failed: %s TAGS(%d)" action (process-exit-status process))))))
-
-(defsubst helm-gtags--read-gtagslabel ()
- (let ((labels '("default" "native" "ctags" "pygments")))
- (completing-read "GTAGSLABEL(Default: default): " labels nil t nil nil "default")))
-
-(defsubst helm-gtags--label-option (label)
- (concat "--gtagslabel=" label))
-
-;;;###autoload
-(defun helm-gtags-create-tags (dir label)
- (interactive
- (list (read-directory-name "Root Directory: ")
- (helm-gtags--read-gtagslabel)))
- (let ((default-directory dir)
- (proc-buf (get-buffer-create " *helm-gtags-create*")))
- (let ((proc (start-file-process "helm-gtags-create" proc-buf
- "gtags" "-q" (helm-gtags--label-option label))))
- (set-process-sentinel proc (helm-gtags--make-gtags-sentinel 'create)))))
-
-(defun helm-gtags--find-tag-simple ()
- (or (getenv "GTAGSROOT")
- (locate-dominating-file default-directory "GTAGS")
- (if (not (yes-or-no-p "File GTAGS not found. Run 'gtags'? "))
- (user-error "Abort")
- (let* ((tagroot (read-directory-name "Root Directory: "))
- (label (helm-gtags--read-gtagslabel))
- (default-directory tagroot))
- (message "gtags is generating tags....")
- (unless (zerop (process-file "gtags" nil nil nil
- "-q" (helm-gtags--label-option label)))
- (error "Faild: 'gtags -q'"))
- tagroot))))
-
-(defun helm-gtags--current-file-and-line ()
- (let* ((buffile (buffer-file-name))
- (path (cl-case helm-gtags-path-style
- (absolute buffile)
- (root
- (file-relative-name buffile (helm-gtags--find-tag-directory)))
- (relative
- (file-relative-name buffile (helm-gtags--base-directory))))))
- (format "%s:%d" path (line-number-at-pos))))
-
-(defsubst helm-gtags--clear-variables ()
- (setq helm-gtags--last-default-directory nil))
-
-(defun helm-gtags--common (srcs tagname)
- (helm-gtags--clear-variables)
- (let ((helm-quit-if-no-candidate t)
- (helm-execute-action-at-once-if-one t)
- (dir (helm-gtags--searched-directory))
- (src (car srcs))
- (preselect-regexp (when helm-gtags-preselect
- (regexp-quote (helm-gtags--current-file-and-line)))))
- (when (symbolp src)
- (setq src (symbol-value src)))
- (unless helm-gtags--use-otherwin
- (setq helm-gtags--use-otherwin (helm-gtags--using-other-window-p)))
- (when tagname
- (setq helm-gtags--query tagname))
- (let ((tagroot (helm-gtags--find-tag-simple)))
- (helm-attrset 'helm-gtags-base-directory dir src)
- (helm-attrset 'name (format "%s in %s" tagname (or dir tagroot)) src)
- (helm :sources srcs :buffer helm-gtags--buffer
- :preselect preselect-regexp))))
-
-;;;###autoload
-(defun helm-gtags-find-tag (tag)
- "Jump to definition"
- (interactive
- (list (helm-gtags--read-tagname 'tag)))
- (helm-gtags--common '(helm-source-gtags-tags) tag))
-
-;;;###autoload
-(defun helm-gtags-find-tag-other-window (tag)
- "Jump to definition in other window."
- (interactive
- (list (helm-gtags--read-tagname 'tag)))
- (setq helm-gtags--use-otherwin t)
- (helm-gtags-find-tag tag))
-
-;;;###autoload
-(defun helm-gtags-find-rtag (tag)
- "Jump to referenced point"
- (interactive
- (list (helm-gtags--read-tagname 'rtag (which-function))))
- (helm-gtags--common '(helm-source-gtags-rtags) tag))
-
-;;;###autoload
-(defun helm-gtags-find-symbol (tag)
- "Jump to the symbol location"
- (interactive
- (list (helm-gtags--read-tagname 'symbol)))
- (helm-gtags--common '(helm-source-gtags-gsyms) tag))
-
-;;;###autoload
-(defun helm-gtags-find-pattern (pattern)
- "Grep and jump by gtags tag files."
- (interactive
- (list (helm-gtags--read-tagname 'pattern)))
- (helm-gtags--common '(helm-source-gtags-pattern) pattern))
-
-(defun helm-gtags--find-file-after-hook ()
- (helm-gtags--push-context helm-gtags--saved-context))
-
-;;;###autoload
-(defun helm-gtags-find-files (file)
- "Find file from tagged with gnu global."
- (interactive
- (list (helm-gtags--read-tagname 'find-file)))
- (add-hook 'helm-after-action-hook 'helm-gtags--find-file-after-hook)
- (unwind-protect
- (helm-gtags--common '(helm-source-gtags-files) file)
- (remove-hook 'helm-after-action-hook 'helm-gtags--find-file-after-hook)))
-
-;;;###autoload
-(defun helm-gtags-find-tag-from-here ()
- "Jump point by current point information.
-Jump to definition point if cursor is on its reference.
-Jump to reference point if curosr is on its definition"
- (interactive)
- (helm-gtags--common '(helm-source-gtags-find-tag-from-here) nil))
-
-;;;###autoload
-(defun helm-gtags-dwim ()
- "Find by context. Here is
-- on include statement then jump to included file
-- on symbol definition then jump to its references
-- on reference point then jump to its definition."
- (interactive)
- (let ((line (helm-current-line-contents)))
- (if (string-match helm-gtags--include-regexp line)
- (let ((helm-gtags-use-input-at-cursor t))
- (helm-gtags-find-files (match-string-no-properties 1 line)))
- (if (and (buffer-file-name) (thing-at-point 'symbol))
- (helm-gtags-find-tag-from-here)
- (call-interactively 'helm-gtags-find-tag)))))
-
-(defun helm-gtags--set-parsed-file ()
- (let* ((this-file (file-name-nondirectory (buffer-file-name)))
- (file (if current-prefix-arg
- (read-file-name "Parsed File: " nil this-file)
- this-file)))
- (setq helm-gtags--parsed-file (expand-file-name file))))
-
-(defun helm-gtags--find-preselect-line ()
- (let ((defun-bound (bounds-of-thing-at-point 'defun)))
- (if (not defun-bound)
- (line-number-at-pos)
- (let ((defun-begin-line (line-number-at-pos (car defun-bound)))
- (filename (helm-gtags--real-file-name)))
- (with-temp-buffer
- (unless (zerop (process-file "global" nil t nil "-f" filename))
- (error "Failed: global -f"))
- (goto-char (point-min))
- (let (start-line)
- (while (and (not start-line)
- (re-search-forward "^\\S-+\\s-+\\([1-9][0-9]*\\)" nil t))
- (let ((line (string-to-number (match-string-no-properties 1))))
- (when (>= line defun-begin-line)
- (setq start-line line))))
- (or start-line (line-number-at-pos))))))))
-
-;;;###autoload
-(defun helm-gtags-parse-file ()
- "Parse current file with gnu global. This is similar to `imenu'.
-You can jump definitions of functions, symbols in this file."
- (interactive)
- (helm-gtags--find-tag-directory)
- (helm-gtags--save-current-context)
- (setq helm-gtags--use-otherwin (helm-gtags--using-other-window-p))
- (helm-gtags--set-parsed-file)
- (helm-attrset 'name
- (format "Parsed File: %s"
- (file-relative-name helm-gtags--parsed-file
- helm-gtags--tag-location))
- helm-source-gtags-parse-file)
- (let ((presel (when helm-gtags-preselect
- (format "^\\S-+\\s-+%d\\s-+" (helm-gtags--find-preselect-line)))))
- (helm :sources '(helm-source-gtags-parse-file)
- :buffer helm-gtags--buffer :preselect presel)))
-
-;;;###autoload
-(defun helm-gtags-pop-stack ()
- "Jump to previous point on the context stack and pop it from stack."
- (interactive)
- (let* ((context-info (helm-gtags--get-context-info))
- (context-stack (plist-get context-info :stack))
- (context (pop context-stack)))
- (helm-gtags--put-context-stack helm-gtags--tag-location -1 context-stack)
- (helm-gtags--move-to-context context)))
-
-;;;###autoload
-(defun helm-gtags-show-stack ()
- "Show current context stack."
- (interactive)
- (helm-other-buffer 'helm-source-gtags-show-stack
- (get-buffer-create helm-gtags--buffer)))
-
-;;;###autoload
-(defun helm-gtags-clear-stack ()
- "Clear current context stack."
- (interactive)
- (let ((tag-location (helm-gtags--find-tag-directory)))
- (message "Clear '%s' context stack." tag-location)
- (remhash tag-location helm-gtags--context-stack)))
-
-;;;###autoload
-(defun helm-gtags-clear-all-stacks ()
- "Clear all context stacks."
- (interactive)
- (message "Clear all context statks.")
- (setq helm-gtags--context-stack (make-hash-table :test 'equal)))
-
-(defun helm-gtags--read-tag-directory ()
- (let ((dir (read-directory-name "Directory tag generated: " nil nil t)))
- ;; On Windows, "gtags d:/tmp" work, but "gtags d:/tmp/" doesn't
- (directory-file-name (expand-file-name dir))))
-
-(defsubst helm-gtags--how-to-update-tags ()
- (cl-case (prefix-numeric-value current-prefix-arg)
- (4 'entire-update)
- (16 'generate-other-directory)
- (otherwise 'single-update)))
-
-(defun helm-gtags--update-tags-command (how-to)
- (cl-case how-to
- (entire-update '("global" "-u"))
- (generate-other-directory (list "gtags" (helm-gtags--read-tag-directory)))
- (single-update (list "global" "--single-update" (helm-gtags--real-file-name)))))
-
-(defun helm-gtags--update-tags-p (how-to interactive-p current-time)
- (or interactive-p
- (and (eq how-to 'single-update)
- (buffer-file-name)
- (or (not helm-gtags-update-interval-second)
- (>= (- current-time helm-gtags--last-update-time)
- helm-gtags-update-interval-second)))))
-
-;;;###autoload
-(defun helm-gtags-update-tags ()
- "Update TAG file. Update All files with `C-u' prefix.
-Generate new TAG file in selected directory with `C-u C-u'"
- (interactive)
- (let ((how-to (helm-gtags--how-to-update-tags))
- (interactive-p (called-interactively-p 'interactive))
- (current-time (float-time (current-time))))
- (when (helm-gtags--update-tags-p how-to interactive-p current-time)
- (let* ((cmds (helm-gtags--update-tags-command how-to))
- (proc (apply #'start-file-process "helm-gtags-update-tag" nil cmds)))
- (if (not proc)
- (message "Failed: %s" (mapconcat 'identity cmds " "))
- (set-process-sentinel proc (helm-gtags--make-gtags-sentinel 'update))
- (setq helm-gtags--last-update-time current-time))))))
-
-;;;###autoload
-(defun helm-gtags-resume ()
- "Resurrect previously invoked `helm-gtags` command."
- (interactive)
- (unless (get-buffer helm-gtags--buffer)
- (error "Error: helm-gtags buffer is not existed."))
- (helm-resume helm-gtags--buffer))
-
-(defsubst helm-gtags--check-browser-installed (browser)
- (let ((used-browser (or browser "mozilla")))
- (unless (executable-find used-browser)
- (error "Not found browser '%s'" used-browser))))
-
-(defun helm-gtags-display-browser ()
- "Display current screen on hypertext browser.
-`browse-url-generic-program' is used as browser if its value is non-nil.
-`mozilla' is used in other case."
- (interactive)
- (let ((file (buffer-file-name)))
- (if (not file)
- (error "This buffer is not related to file.")
- (let* ((lineopt (concat "+" (number-to-string (line-number-at-pos))))
- (browser (symbol-value 'browse-url-generic-program))
- (args (list lineopt file)))
- (helm-gtags--check-browser-installed browser)
- (when browser
- (setq args (append (list "-b" browser) args)))
- ;; `gozilla' commend never returns error status if command is failed.
- (apply #'process-file "gozilla" nil nil nil args)))))
-
-(defvar helm-gtags-mode-name " HelmGtags")
-(defvar helm-gtags-mode-map (make-sparse-keymap))
-
-;;;###autoload
-(define-minor-mode helm-gtags-mode ()
- "Enable helm-gtags"
- :init-value nil
- :global nil
- :keymap helm-gtags-mode-map
- :lighter helm-gtags-mode-name
- (if helm-gtags-mode
- (when helm-gtags-auto-update
- (add-hook 'after-save-hook 'helm-gtags-update-tags nil t))
- (when helm-gtags-auto-update
- (remove-hook 'after-save-hook 'helm-gtags-update-tags t))))
-
-;; Key mapping of gtags-mode.
-(when helm-gtags-suggested-key-mapping
- ;; Current key mapping.
- (let ((prefix helm-gtags-prefix-key))
- (define-key helm-gtags-mode-map (concat prefix "h") 'helm-gtags-display-browser)
- (define-key helm-gtags-mode-map "\C-]" 'helm-gtags-find-tag-from-here)
- (define-key helm-gtags-mode-map "\C-t" 'helm-gtags-pop-stack)
- (define-key helm-gtags-mode-map (concat prefix "P") 'helm-gtags-find-files)
- (define-key helm-gtags-mode-map (concat prefix "f") 'helm-gtags-parse-file)
- (define-key helm-gtags-mode-map (concat prefix "g") 'helm-gtags-find-pattern)
- (define-key helm-gtags-mode-map (concat prefix "s") 'helm-gtags-find-symbol)
- (define-key helm-gtags-mode-map (concat prefix "r") 'helm-gtags-find-rtag)
- (define-key helm-gtags-mode-map (concat prefix "t") 'helm-gtags-find-tag)
- (define-key helm-gtags-mode-map (concat prefix "d") 'helm-gtags-find-tag)
-
- ;; common
- (define-key helm-gtags-mode-map "\e*" 'helm-gtags-pop-stack)
- (define-key helm-gtags-mode-map "\e." 'helm-gtags-find-tag)
- (define-key helm-gtags-mode-map "\C-x4." 'helm-gtags-find-tag-other-window)))
-
-(provide 'helm-gtags)
-
-;; Local Variables:
-;; coding: utf-8
-;; indent-tabs-mode: nil
-;; End:
-
-;;; helm-gtags.el ends here
--- /dev/null
+;;; helm-gtags-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+
+(add-to-list 'load-path (directory-file-name
+ (or (file-name-directory #$) (car load-path))))
+
+\f
+;;;### (autoloads nil "helm-gtags" "helm-gtags.el" (0 0 0 0))
+;;; Generated autoloads from helm-gtags.el
+
+(autoload 'helm-gtags-clear-all-cache "helm-gtags" "\
+
+
+\(fn)" t nil)
+
+(autoload 'helm-gtags-clear-cache "helm-gtags" "\
+
+
+\(fn)" t nil)
+
+(autoload 'helm-gtags-next-history "helm-gtags" "\
+Jump to next position on context stack
+
+\(fn)" t nil)
+
+(autoload 'helm-gtags-previous-history "helm-gtags" "\
+Jump to previous position on context stack
+
+\(fn)" t nil)
+
+(autoload 'helm-gtags-select "helm-gtags" "\
+
+
+\(fn)" t nil)
+
+(autoload 'helm-gtags-select-path "helm-gtags" "\
+
+
+\(fn)" t nil)
+
+(autoload 'helm-gtags-tags-in-this-function "helm-gtags" "\
+Show tagnames which are referenced in this function and jump to it.
+
+\(fn)" t nil)
+
+(autoload 'helm-gtags-create-tags "helm-gtags" "\
+
+
+\(fn DIR LABEL)" t nil)
+
+(autoload 'helm-gtags-delete-tags "helm-gtags" "\
+Delete file GTAGS, GRTAGS, GPATH, ID etc. generated by gtags.
+
+\(fn)" t nil)
+
+(autoload 'helm-gtags-find-tag "helm-gtags" "\
+Jump to definition
+
+\(fn TAG)" t nil)
+
+(autoload 'helm-gtags-find-tag-other-window "helm-gtags" "\
+Jump to definition in other window.
+
+\(fn TAG)" t nil)
+
+(autoload 'helm-gtags-find-rtag "helm-gtags" "\
+Jump to referenced point
+
+\(fn TAG)" t nil)
+
+(autoload 'helm-gtags-find-symbol "helm-gtags" "\
+Jump to the symbol location
+
+\(fn TAG)" t nil)
+
+(autoload 'helm-gtags-find-pattern "helm-gtags" "\
+Grep and jump by gtags tag files.
+
+\(fn PATTERN)" t nil)
+
+(autoload 'helm-gtags-find-files "helm-gtags" "\
+Find file from tagged with gnu global.
+
+\(fn FILE)" t nil)
+
+(autoload 'helm-gtags-find-tag-from-here "helm-gtags" "\
+Jump point by current point information.
+Jump to definition point if cursor is on its reference.
+Jump to reference point if curosr is on its definition
+
+\(fn)" t nil)
+
+(autoload 'helm-gtags-dwim "helm-gtags" "\
+Find by context. Here is
+- on include statement then jump to included file
+- on symbol definition then jump to its references
+- on reference point then jump to its definition.
+
+\(fn)" t nil)
+
+(autoload 'helm-gtags-parse-file "helm-gtags" "\
+Parse current file with gnu global. This is similar to `imenu'.
+You can jump definitions of functions, symbols in this file.
+
+\(fn)" t nil)
+
+(autoload 'helm-gtags-pop-stack "helm-gtags" "\
+Jump to previous point on the context stack and pop it from stack.
+
+\(fn)" t nil)
+
+(autoload 'helm-gtags-show-stack "helm-gtags" "\
+Show current context stack.
+
+\(fn)" t nil)
+
+(autoload 'helm-gtags-clear-stack "helm-gtags" "\
+Clear current context stack.
+
+\(fn)" t nil)
+
+(autoload 'helm-gtags-clear-all-stacks "helm-gtags" "\
+Clear all context stacks.
+
+\(fn)" t nil)
+
+(autoload 'helm-gtags-update-tags "helm-gtags" "\
+Update TAG file. Update All files with `C-u' prefix.
+Generate new TAG file in selected directory with `C-u C-u'
+
+\(fn)" t nil)
+
+(autoload 'helm-gtags-resume "helm-gtags" "\
+Resurrect previously invoked `helm-gtags` command.
+
+\(fn)" t nil)
+
+(autoload 'helm-gtags-mode "helm-gtags" "\
+Toggle Helm-Gtags mode on or off.
+With a prefix argument ARG, enable Helm-Gtags mode if ARG is
+positive, and disable it otherwise. If called from Lisp, enable
+the mode if ARG is omitted or nil, and toggle it if ARG is `toggle'.
+\\{helm-gtags-mode-map}
+
+\(fn &optional ARG)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-gtags" '("helm-")))
+
+;;;***
+\f
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; coding: utf-8
+;; End:
+;;; helm-gtags-autoloads.el ends here
--- /dev/null
+;;; -*- no-byte-compile: t -*-
+(define-package "helm-gtags" "20170116.529" "GNU GLOBAL helm interface" '((emacs "24.4") (helm "2.0")) :commit "108e93d0d099ebb7b98847388f368311cf177033" :authors '(("Syohei YOSHIDA" . "syohexNOSPAMgmail.com")) :maintainer '("Syohei YOSHIDA" . "syohex@gmail.com") :url "https://github.com/syohex/emacs-helm-gtags")
--- /dev/null
+;;; helm-gtags.el --- GNU GLOBAL helm interface -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2016 by Syohei YOSHIDA
+
+;; Author: Syohei YOSHIDA <syohexNOSPAMgmail.com>
+;; URL: https://github.com/syohex/emacs-helm-gtags
+;; Package-Version: 20170116.529
+;; Version: 1.5.6
+;; Package-Requires: ((emacs "24.4") (helm "2.0"))
+
+;; 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/>.
+
+;;; Commentary:
+
+;; `helm-gtags.el' is a `helm' interface of GNU Global.
+;; `helm-gtags.el' is not compatible `anything-gtags.el', but `helm-gtags.el'
+;; is designed for fast search.
+
+;;
+;; To use this package, add these lines to your init.el or .emacs file:
+;;
+;; ;; Enable helm-gtags-mode
+;; (add-hook 'c-mode-hook 'helm-gtags-mode)
+;; (add-hook 'c++-mode-hook 'helm-gtags-mode)
+;; (add-hook 'asm-mode-hook 'helm-gtags-mode)
+;;
+;; ;; Set key bindings
+;; (eval-after-load "helm-gtags"
+;; '(progn
+;; (define-key helm-gtags-mode-map (kbd "M-t") 'helm-gtags-find-tag)
+;; (define-key helm-gtags-mode-map (kbd "M-r") 'helm-gtags-find-rtag)
+;; (define-key helm-gtags-mode-map (kbd "M-s") 'helm-gtags-find-symbol)
+;; (define-key helm-gtags-mode-map (kbd "M-g M-p") 'helm-gtags-parse-file)
+;; (define-key helm-gtags-mode-map (kbd "C-c <") 'helm-gtags-previous-history)
+;; (define-key helm-gtags-mode-map (kbd "C-c >") 'helm-gtags-next-history)
+;; (define-key helm-gtags-mode-map (kbd "M-,") 'helm-gtags-pop-stack)))
+;;
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'helm)
+(require 'helm-files)
+(require 'which-func)
+(require 'pulse)
+(require 'subr-x)
+
+(declare-function helm-comp-read "helm-mode")
+(declare-function cygwin-convert-file-name-from-windows "cygw32.c")
+(declare-function cygwin-convert-file-name-to-windows "cygw32.c")
+
+(defgroup helm-gtags nil
+ "GNU GLOBAL for helm."
+ :group 'helm)
+
+(defcustom helm-gtags-path-style 'root
+ "Style of file path"
+ :type '(choice (const :tag "Root of the current project" root)
+ (const :tag "Relative from the current directory" relative)
+ (const :tag "Absolute Path" absolute)))
+
+(defcustom helm-gtags-ignore-case nil
+ "Ignore case in each search."
+ :type 'boolean)
+
+(defcustom helm-gtags-cygwin-use-global-w32-port t
+ "Use the GNU global win32 port in Cygwin."
+ :type 'boolean)
+
+(defcustom helm-gtags-read-only nil
+ "Gtags read only mode."
+ :type 'boolean)
+
+(defcustom helm-gtags-auto-update nil
+ "*If non-nil, tag files are updated whenever a file is saved."
+ :type 'boolean)
+
+(defcustom helm-gtags-pulse-at-cursor t
+ "If non-nil, pulse at point after jumping"
+ :type 'boolean)
+
+(defcustom helm-gtags-cache-select-result nil
+ "*If non-nil, results of helm-gtags-select and helm-gtags-select-path are cached."
+ :type 'boolean)
+
+(defcustom helm-gtags-cache-max-result-size (* 10 1024 1024) ;10M
+ "Max size(bytes) to cache for each select result."
+ :type 'integer)
+
+(defcustom helm-gtags-update-interval-second 60
+ "Tags are updated in `after-save-hook' if this seconds is passed from last update.
+Always update if value of this variable is nil."
+ :type '(choice (integer :tag "Update interval seconds")
+ (boolean :tag "Update every time" nil)))
+
+(defcustom helm-gtags-highlight-candidate t
+ "Highlight candidate or not"
+ :type 'boolean)
+
+(defcustom helm-gtags-use-input-at-cursor nil
+ "Use input at cursor"
+ :type 'boolean)
+
+(defcustom helm-gtags-prefix-key "\C-c"
+ "If non-nil, it is used for the prefix key of gtags-xxx command."
+ :type 'string)
+
+(defcustom helm-gtags-suggested-key-mapping nil
+ "If non-nil, suggested key mapping is enabled."
+ :type 'boolean)
+
+(defcustom helm-gtags-preselect nil
+ "If non-nil, preselect current file and line."
+ :type 'boolean)
+
+(defcustom helm-gtags-display-style nil
+ "Style of display result."
+ :type '(choice (const :tag "Show in detail" detail)
+ (const :tag "Normal style" nil)))
+
+(defcustom helm-gtags-fuzzy-match nil
+ "Enable fuzzy match"
+ :type 'boolean)
+
+(defcustom helm-gtags-maximum-candidates (if helm-gtags-fuzzy-match 100 9999)
+ "Maximum number of helm candidates"
+ :type 'integer)
+
+(defcustom helm-gtags-direct-helm-completing nil
+ "Use helm mode directly."
+ :type 'boolean)
+
+(defface helm-gtags-file
+ '((t :inherit font-lock-keyword-face))
+ "Face for line numbers in the error list.")
+
+(defface helm-gtags-lineno
+ '((t :inherit font-lock-doc-face))
+ "Face for line numbers in the error list.")
+
+(defface helm-gtags-match
+ '((t :inherit helm-match))
+ "Face for word matched against tagname")
+
+(defvar helm-gtags--tag-location nil)
+(defvar helm-gtags--last-update-time 0)
+(defvar helm-gtags--completing-history nil)
+(defvar helm-gtags--context-stack (make-hash-table :test 'equal))
+(defvar helm-gtags--result-cache (make-hash-table :test 'equal))
+(defvar helm-gtags--saved-context nil)
+(defvar helm-gtags--use-otherwin nil)
+(defvar helm-gtags--local-directory nil)
+(defvar helm-gtags--parsed-file nil)
+(defvar helm-gtags--current-position nil)
+(defvar helm-gtags--real-tag-location nil)
+(defvar helm-gtags--last-input nil)
+(defvar helm-gtags--query nil)
+(defvar helm-gtags--last-default-directory nil)
+
+(defconst helm-gtags--buffer "*helm gtags*")
+
+(defconst helm-gtags--include-regexp
+ "\\`\\s-*#\\(?:include\\|import\\)\\s-*[\"<]\\(?:[./]*\\)?\\(.*?\\)[\">]")
+
+(defmacro helm-declare-obsolete-variable (old new version)
+ `(progn
+ (defvaralias ,old ,new)
+ (make-obsolete-variable ,old ,new ,version)))
+
+(helm-declare-obsolete-variable
+ 'helm-c-gtags-path-style 'helm-gtags-path-style "0.8")
+(helm-declare-obsolete-variable
+ 'helm-c-gtags-ignore-case 'helm-gtags-ignore-case "0.8")
+(helm-declare-obsolete-variable
+ 'helm-c-gtags-read-only 'helm-gtags-read-only "0.8")
+
+;; completsion function for completing-read.
+(defun helm-gtags--completing-gtags (string predicate code)
+ (helm-gtags--complete 'tag string predicate code))
+(defun helm-gtags--completing-pattern (string predicate code)
+ (helm-gtags--complete 'pattern string predicate code))
+(defun helm-gtags--completing-grtags (string predicate code)
+ (helm-gtags--complete 'rtag string predicate code))
+(defun helm-gtags--completing-gsyms (string predicate code)
+ (helm-gtags--complete 'symbol string predicate code))
+(defun helm-gtags--completing-files (string predicate code)
+ (helm-gtags--complete 'find-file string predicate code))
+
+(defconst helm-gtags-comp-func-alist
+ '((tag . helm-gtags--completing-gtags)
+ (pattern . helm-gtags--completing-pattern)
+ (rtag . helm-gtags--completing-grtags)
+ (symbol . helm-gtags--completing-gsyms)
+ (find-file . helm-gtags--completing-files)))
+
+(defconst helm-gtags--search-option-alist
+ '((pattern . "-g")
+ (rtag . "-r")
+ (symbol . "-s")
+ (find-file . "-Poa")))
+
+(defsubst helm-gtags--windows-p ()
+ (memq system-type '(windows-nt ms-dos)))
+
+(defun helm-gtags--remove-carrige-returns ()
+ (when (helm-gtags--windows-p)
+ (save-excursion
+ (goto-char (point-min))
+ (while (re-search-forward "\xd" nil t)
+ (replace-match "")))))
+
+;; Work around for GNU global Windows issue
+(defsubst helm-gtags--use-abs-path-p (gtagslibpath)
+ (and (helm-gtags--windows-p) gtagslibpath))
+
+(defun helm-gtags--construct-options (type completion)
+ (let ((find-file-p (eq type 'find-file))
+ (gtagslibpath (getenv "GTAGSLIBPATH"))
+ options)
+ (unless find-file-p
+ (push "--result=grep" options))
+ (when completion
+ (push "-c" options))
+ (helm-aif (assoc-default type helm-gtags--search-option-alist)
+ (push it options))
+ (when (or (eq helm-gtags-path-style 'absolute)
+ (helm-gtags--use-abs-path-p gtagslibpath))
+ (push "-a" options))
+ (when helm-gtags-ignore-case
+ (push "-i" options))
+ (when (and current-prefix-arg (not find-file-p))
+ (push "-l" options))
+ (when gtagslibpath
+ (push "-T" options))
+ options))
+
+(defun helm-gtags--complete (type string predicate code)
+ (let* ((options (helm-gtags--construct-options type t))
+ (args (reverse (cons string options)))
+ candidates)
+ (with-temp-buffer
+ (apply #'process-file "global" nil t nil args)
+ (goto-char (point-min))
+ (while (re-search-forward "^\\(.+\\)$" nil t)
+ (push (match-string-no-properties 1) candidates)))
+ (if (not code)
+ (try-completion string candidates predicate)
+ (all-completions string candidates predicate))))
+
+(defun helm-gtags--token-at-point (type)
+ (if (not (eq type 'find-file))
+ (thing-at-point 'symbol)
+ (let ((line (helm-current-line-contents)))
+ (when (string-match helm-gtags--include-regexp line)
+ (match-string-no-properties 1 line)))))
+
+(defconst helm-gtags--prompt-alist
+ '((tag . "Find Definition: ")
+ (pattern . "Find Pattern: ")
+ (rtag . "Find Reference: ")
+ (symbol . "Find Symbol: ")
+ (find-file . "Find File: ")))
+
+(defun helm-gtags--read-tagname (type &optional default-tagname)
+ (let ((tagname (helm-gtags--token-at-point type))
+ (prompt (assoc-default type helm-gtags--prompt-alist))
+ (comp-func (assoc-default type helm-gtags-comp-func-alist)))
+ (if (and tagname helm-gtags-use-input-at-cursor)
+ tagname
+ (when (and (not tagname) default-tagname)
+ (setq tagname default-tagname))
+ (when tagname
+ (setq prompt (format "%s(default \"%s\") " prompt tagname)))
+ (let ((completion-ignore-case helm-gtags-ignore-case)
+ (completing-read-function 'completing-read-default))
+ (if (and helm-gtags-direct-helm-completing (memq type '(tag rtag symbol find-file)))
+ (helm-comp-read prompt comp-func
+ :history 'helm-gtags--completing-history
+ :exec-when-only-one t
+ :default tagname)
+ (completing-read prompt comp-func nil nil nil
+ 'helm-gtags--completing-history tagname))))))
+
+(defun helm-gtags--path-libpath-p (tagroot)
+ (helm-aif (getenv "GTAGSLIBPATH")
+ (cl-loop for path in (parse-colon-path it)
+ for libpath = (file-name-as-directory (expand-file-name path))
+ thereis (string= tagroot libpath))))
+
+(defsubst helm-gtags--convert-cygwin-windows-file-name-p ()
+ (and (eq system-type 'cygwin) helm-gtags-cygwin-use-global-w32-port))
+
+(defun helm-gtags--tag-directory ()
+ (with-temp-buffer
+ (helm-aif (getenv "GTAGSROOT")
+ it
+ (unless (zerop (process-file "global" nil t nil "-p"))
+ (error "GTAGS not found"))
+ (goto-char (point-min))
+ (when (looking-at "^\\([^\r\n]+\\)")
+ (let ((tag-path (match-string-no-properties 1)))
+ (file-name-as-directory
+ (if (helm-gtags--convert-cygwin-windows-file-name-p)
+ (cygwin-convert-file-name-from-windows tag-path)
+ tag-path)))))))
+
+(defun helm-gtags--find-tag-directory ()
+ (setq helm-gtags--real-tag-location nil)
+ (let ((tagroot (helm-gtags--tag-directory)))
+ (if (and (helm-gtags--path-libpath-p tagroot) helm-gtags--tag-location)
+ (progn
+ (setq helm-gtags--real-tag-location tagroot)
+ helm-gtags--tag-location)
+ (setq helm-gtags--tag-location tagroot))))
+
+(defun helm-gtags--base-directory ()
+ (let ((dir (or helm-gtags--last-default-directory
+ helm-gtags--local-directory
+ (cl-case helm-gtags-path-style
+ (root (or helm-gtags--real-tag-location
+ helm-gtags--tag-location))
+ (otherwise default-directory))))
+ (remote (file-remote-p default-directory)))
+ (if (and remote (not (file-remote-p dir)))
+ (concat remote dir)
+ dir)))
+
+(defsubst helm-gtags--new-context-info (index stack)
+ (list :index index :stack stack))
+
+(defun helm-gtags--put-context-stack (tag-location index stack)
+ (puthash tag-location (helm-gtags--new-context-info index stack)
+ helm-gtags--context-stack))
+
+(defsubst helm-gtags--current-context ()
+ (let ((file (buffer-file-name (current-buffer))))
+ (list :file file :position (point) :readonly buffer-file-read-only)))
+
+(defsubst helm-gtags--save-current-context ()
+ (setq helm-gtags--saved-context (helm-gtags--current-context)))
+
+(defun helm-gtags--open-file (file readonly)
+ (if readonly
+ (find-file-read-only file)
+ (find-file file)))
+
+(defun helm-gtags--open-file-other-window (file readonly)
+ (setq helm-gtags--use-otherwin nil)
+ (if readonly
+ (find-file-read-only-other-window file)
+ (find-file-other-window file)))
+
+(defun helm-gtags--get-context-info ()
+ (let* ((tag-location (helm-gtags--find-tag-directory))
+ (context-info (gethash tag-location helm-gtags--context-stack))
+ (context-stack (plist-get context-info :stack)))
+ (if (null context-stack)
+ (error "Context stack is empty(TAG at %s)" tag-location)
+ context-info)))
+
+(defun helm-gtags--get-or-create-context-info ()
+ (or (gethash helm-gtags--tag-location helm-gtags--context-stack)
+ (helm-gtags--new-context-info -1 nil)))
+
+;;;###autoload
+(defun helm-gtags-clear-all-cache ()
+ (interactive)
+ (clrhash helm-gtags--result-cache))
+
+;;;###autoload
+(defun helm-gtags-clear-cache ()
+ (interactive)
+ (helm-gtags--find-tag-directory)
+ (let* ((tag-location (or helm-gtags--real-tag-location
+ helm-gtags--tag-location))
+ (gtags-path (concat tag-location "GTAGS"))
+ (gpath-path (concat tag-location "GPATH")))
+ (remhash gtags-path helm-gtags--result-cache)
+ (remhash gpath-path helm-gtags--result-cache)))
+
+(defun helm-gtags--move-to-context (context)
+ (let ((file (plist-get context :file))
+ (curpoint (plist-get context :position))
+ (readonly (plist-get context :readonly)))
+ (helm-gtags--open-file file readonly)
+ (goto-char curpoint)
+ (recenter)))
+
+;;;###autoload
+(defun helm-gtags-next-history ()
+ "Jump to next position on context stack"
+ (interactive)
+ (let* ((context-info (helm-gtags--get-context-info))
+ (current-index (plist-get context-info :index))
+ (context-stack (plist-get context-info :stack))
+ context)
+ (when (<= current-index -1)
+ (error "This context is latest in context stack"))
+ (setf (nth current-index context-stack) (helm-gtags--current-context))
+ (cl-decf current-index)
+ (if (= current-index -1)
+ (setq context helm-gtags--current-position
+ helm-gtags--current-position nil)
+ (setq context (nth current-index context-stack)))
+ (helm-gtags--put-context-stack helm-gtags--tag-location
+ current-index context-stack)
+ (helm-gtags--move-to-context context)))
+
+;;;###autoload
+(defun helm-gtags-previous-history ()
+ "Jump to previous position on context stack"
+ (interactive)
+ (let* ((context-info (helm-gtags--get-context-info))
+ (current-index (plist-get context-info :index))
+ (context-stack (plist-get context-info :stack))
+ (context-length (length context-stack)))
+ (cl-incf current-index)
+ (when (>= current-index context-length)
+ (error "This context is last in context stack"))
+ (if (= current-index 0)
+ (setq helm-gtags--current-position (helm-gtags--current-context))
+ (setf (nth (- current-index 1) context-stack) (helm-gtags--current-context)))
+ (let ((prev-context (nth current-index context-stack)))
+ (helm-gtags--move-to-context prev-context))
+ (helm-gtags--put-context-stack helm-gtags--tag-location
+ current-index context-stack)))
+
+(defun helm-gtags--get-result-cache (file)
+ (helm-gtags--find-tag-directory)
+ (let* ((file-path (concat (or helm-gtags--real-tag-location
+ helm-gtags--tag-location)
+ file))
+ (file-mtime (nth 5 (file-attributes file-path)))
+ (hash-value (gethash file-path helm-gtags--result-cache))
+ (cached-file-mtime (nth 0 hash-value)))
+ (if (and cached-file-mtime (equal cached-file-mtime file-mtime))
+ (nth 1 hash-value)
+ nil)))
+
+(defun helm-gtags--put-result-cache (file cache)
+ (helm-gtags--find-tag-directory)
+ (let* ((file-path (concat (or helm-gtags--real-tag-location
+ helm-gtags--tag-location)
+ file))
+ (file-mtime (nth 5 (file-attributes file-path)))
+ (hash-value (list file-mtime cache)))
+ (puthash file-path hash-value helm-gtags--result-cache)))
+
+(defun helm-gtags--referer-function (file ref-line)
+ (let ((is-opened (cl-loop with path = (concat default-directory file)
+ for buf in (buffer-list)
+ when (string= (buffer-file-name buf) path)
+ return it))
+ retval)
+ (with-current-buffer (find-file-noselect file)
+ (goto-char (point-min))
+ (forward-line (1- ref-line))
+ (unless (zerop (current-indentation))
+ (setq retval (which-function)))
+ (unless is-opened
+ (kill-buffer (current-buffer)))
+ retval)))
+
+(defun helm-gtags--show-detail ()
+ (goto-char (point-min))
+ (while (not (eobp))
+ (let ((line (helm-current-line-contents)))
+ (let* ((file-and-line (helm-gtags--extract-file-and-line line))
+ (file (car file-and-line))
+ (ref-line (cdr file-and-line))
+ (ref-func (helm-gtags--referer-function file ref-line)))
+ (when ref-func
+ (search-forward ":" nil nil 2)
+ (insert " " ref-func "|"))
+ (forward-line 1)))))
+
+(defun helm-gtags--print-path-in-gtagslibpath (args)
+ (let ((libpath (getenv "GTAGSLIBPATH")))
+ (when libpath
+ (dolist (path (parse-colon-path libpath))
+ (let ((default-directory (file-name-as-directory path)))
+ (apply #'process-file "global" nil t nil "-Poa" args))))))
+
+(defun helm-gtags--exec-global-command (type input &optional detail)
+ (let ((args (helm-gtags--construct-command type input)))
+ (helm-gtags--find-tag-directory)
+ (helm-gtags--save-current-context)
+ (let ((buf-coding buffer-file-coding-system))
+ (with-current-buffer (helm-candidate-buffer 'global)
+ (let ((default-directory (helm-gtags--base-directory))
+ (input (car (last args)))
+ (coding-system-for-read buf-coding)
+ (coding-system-for-write buf-coding))
+ (unless (zerop (apply #'process-file "global" nil '(t nil) nil args))
+ (error (format "%s: not found" input)))
+ ;; --path options does not support searching under GTAGSLIBPATH
+ (when (eq type 'find-file)
+ (helm-gtags--print-path-in-gtagslibpath args))
+ (helm-gtags--remove-carrige-returns)
+ (when detail
+ (helm-gtags--show-detail)))))))
+
+(defun helm-gtags--construct-command (type &optional in)
+ (setq helm-gtags--local-directory nil)
+ (let ((dir (helm-attr 'helm-gtags-base-directory (helm-get-current-source))))
+ (when (and dir (not (eq type 'find-file)))
+ (setq helm-gtags--local-directory dir)))
+ (let ((input (or in helm-gtags--query))
+ (options (helm-gtags--construct-options type nil)))
+ (when (string-empty-p input)
+ (error "Input is empty!!"))
+ (setq helm-gtags--last-input input)
+ (reverse (cons input options))))
+
+(defun helm-gtags--tags-init (&optional input)
+ (helm-gtags--exec-global-command 'tag input))
+
+(defun helm-gtags--pattern-init (&optional input)
+ (helm-gtags--exec-global-command 'pattern input helm-gtags-display-style))
+
+(defun helm-gtags--rtags-init (&optional input)
+ (helm-gtags--exec-global-command 'rtag input helm-gtags-display-style))
+
+(defun helm-gtags--gsyms-init ()
+ (helm-gtags--exec-global-command 'symbol nil helm-gtags-display-style))
+
+(defun helm-gtags--files-init ()
+ (helm-gtags--exec-global-command 'find-file nil))
+
+(defun helm-gtags--real-file-name ()
+ (let ((buffile (buffer-file-name)))
+ (unless buffile
+ (error "This buffer is not related to file."))
+ (if (file-remote-p buffile)
+ (tramp-file-name-localname (tramp-dissect-file-name buffile))
+ (file-truename buffile))))
+
+(defun helm-gtags--find-tag-from-here-init ()
+ (helm-gtags--find-tag-directory)
+ (helm-gtags--save-current-context)
+ (let ((token (helm-gtags--token-at-point 'from-here)))
+ (unless token
+ (error "Cursor is not on symbol."))
+ (let* ((filename (helm-gtags--real-file-name))
+ (from-here-opt (format "--from-here=%d:%s"
+ (line-number-at-pos)
+ (if (helm-gtags--convert-cygwin-windows-file-name-p)
+ (cygwin-convert-file-name-to-windows filename)
+ filename))))
+ (setq helm-gtags--last-input token)
+ (with-current-buffer (helm-candidate-buffer 'global)
+ (let* ((default-directory (helm-gtags--base-directory))
+ (status (process-file "global" nil '(t nil) nil
+ "--result=grep" from-here-opt token)))
+ (helm-gtags--remove-carrige-returns)
+ (unless (zerop status)
+ (cond ((= status 1)
+ (error "Error: %s%s" (buffer-string) filename))
+ ((= status 3)
+ (error "Error: %s" (buffer-string)))
+ (t (error "%s: not found" token)))))))))
+
+(defun helm-gtags--parse-file-init ()
+ (with-current-buffer (helm-candidate-buffer 'global)
+ (unless (zerop (process-file "global" nil t nil
+ "--result=cscope" "-f" helm-gtags--parsed-file))
+ (error "Failed: 'global --result=cscope -f %s" helm-gtags--parsed-file))
+ (helm-gtags--remove-carrige-returns)))
+
+(defun helm-gtags--push-context (context)
+ (let* ((context-info (helm-gtags--get-or-create-context-info))
+ (current-index (plist-get context-info :index))
+ (context-stack (plist-get context-info :stack)))
+ (unless (= current-index -1)
+ (setq context-stack (nthcdr (1+ current-index) context-stack)))
+ (setq helm-gtags--current-position nil)
+ (push context context-stack)
+ (helm-gtags--put-context-stack helm-gtags--tag-location -1 context-stack)))
+
+(defsubst helm-gtags--select-find-file-func ()
+ (if helm-gtags--use-otherwin
+ #'helm-gtags--open-file-other-window
+ #'helm-gtags--open-file))
+
+(defun helm-gtags--do-open-file (open-func file line)
+ (funcall open-func file helm-gtags-read-only)
+ (goto-char (point-min))
+ (forward-line (1- line))
+ (back-to-indentation)
+ (recenter)
+ (helm-gtags--push-context helm-gtags--saved-context)
+ (when helm-gtags-pulse-at-cursor
+ (pulse-momentary-highlight-one-line (point))))
+
+(defun helm-gtags--find-line-number (cand)
+ (if (string-match "\\s-+\\([1-9][0-9]+\\)\\s-+" cand)
+ (string-to-number (match-string-no-properties 1 cand))
+ (error "Can't find line number in %s" cand)))
+
+(defun helm-gtags--parse-file-action (cand)
+ (let ((line (helm-gtags--find-line-number cand))
+ (open-func (helm-gtags--select-find-file-func)))
+ (helm-gtags--do-open-file open-func helm-gtags--parsed-file line)))
+
+(defsubst helm-gtags--has-drive-letter-p (path)
+ (string-match-p "\\`[a-zA-Z]:" path))
+
+(defun helm-gtags--extract-file-and-line (cand)
+ (if (and (helm-gtags--windows-p) (helm-gtags--has-drive-letter-p cand))
+ (when (string-match "\\(\\`[a-zA-Z]:[^:]+\\):\\([^:]+\\)" cand)
+ (cons (match-string-no-properties 1 cand)
+ (string-to-number (match-string-no-properties 2 cand))))
+ (let ((elems (split-string cand ":")))
+ (cons (cl-first elems) (string-to-number (cl-second elems))))))
+
+(defun helm-gtags--action-openfile (cand)
+ (let* ((file-and-line (helm-gtags--extract-file-and-line cand))
+ (filename (car file-and-line))
+ (line (cdr file-and-line))
+ (open-func (helm-gtags--select-find-file-func))
+ (default-directory (helm-gtags--base-directory)))
+ (helm-gtags--do-open-file open-func filename line)))
+
+(defun helm-gtags--action-openfile-other-window (cand)
+ (let ((helm-gtags--use-otherwin t))
+ (helm-gtags--action-openfile cand)))
+
+(defun helm-gtags--file-content-at-pos (file pos)
+ (with-current-buffer (find-file-noselect file)
+ (save-excursion
+ (goto-char pos)
+ (format "%s:%d:%s:%s"
+ file (line-number-at-pos)
+ (helm-aif (which-function) (format "[%s]" it) "")
+ (helm-current-line-contents)))))
+
+(defun helm-gtags--files-candidate-transformer (file)
+ (if (eq helm-gtags-path-style 'absolute)
+ file
+ (let ((removed-regexp (concat "\\`" helm-gtags--tag-location)))
+ (replace-regexp-in-string removed-regexp "" file))))
+
+(defun helm-gtags--show-stack-init ()
+ (cl-loop with context-stack = (plist-get (helm-gtags--get-context-info) :stack)
+ with stack-length = (length context-stack)
+ for context in (reverse context-stack)
+ for file = (plist-get context :file)
+ for pos = (plist-get context :position)
+ for index = (1- stack-length) then (1- index)
+ for line = (helm-gtags--file-content-at-pos file pos)
+ for cand = (helm-gtags--files-candidate-transformer line)
+ collect (cons cand (propertize cand 'index index))))
+
+(defun helm-gtags--persistent-action (cand)
+ (let* ((file-and-line (helm-gtags--extract-file-and-line cand))
+ (filename (car file-and-line))
+ (line (cdr file-and-line))
+ (default-directory (helm-gtags--base-directory)))
+ (when (eq helm-gtags-path-style 'relative)
+ (setq helm-gtags--last-default-directory default-directory))
+ (find-file filename)
+ (goto-char (point-min))
+ (forward-line (1- line))
+ (helm-highlight-current-line)))
+
+(defvar helm-gtags--find-file-action
+ (helm-make-actions
+ "Open file" #'helm-gtags--action-openfile
+ "Open file other window" #'helm-gtags--action-openfile-other-window))
+
+(defvar helm-source-gtags-tags
+ (helm-build-in-buffer-source "Jump to definitions"
+ :init 'helm-gtags--tags-init
+ :candidate-number-limit helm-gtags-maximum-candidates
+ :real-to-display 'helm-gtags--candidate-transformer
+ :persistent-action 'helm-gtags--persistent-action
+ :fuzzy-match helm-gtags-fuzzy-match
+ :action helm-gtags--find-file-action))
+
+(defvar helm-source-gtags-pattern
+ (helm-build-in-buffer-source "Find pattern"
+ :init 'helm-gtags--pattern-init
+ :candidate-number-limit helm-gtags-maximum-candidates
+ :real-to-display 'helm-gtags--candidate-transformer
+ :persistent-action 'helm-gtags--persistent-action
+ :fuzzy-match helm-gtags-fuzzy-match
+ :action helm-gtags--find-file-action))
+
+(defvar helm-source-gtags-rtags
+ (helm-build-in-buffer-source "Jump to references"
+ :init 'helm-gtags--rtags-init
+ :candidate-number-limit helm-gtags-maximum-candidates
+ :real-to-display 'helm-gtags--candidate-transformer
+ :persistent-action 'helm-gtags--persistent-action
+ :fuzzy-match helm-gtags-fuzzy-match
+ :action helm-gtags--find-file-action))
+
+(defvar helm-source-gtags-gsyms
+ (helm-build-in-buffer-source "Jump to symbols"
+ :init 'helm-gtags--gsyms-init
+ :candidate-number-limit helm-gtags-maximum-candidates
+ :real-to-display 'helm-gtags--candidate-transformer
+ :persistent-action 'helm-gtags--persistent-action
+ :fuzzy-match helm-gtags-fuzzy-match
+ :action helm-gtags--find-file-action))
+
+(defun helm-gtags--highlight-candidate (candidate)
+ (let ((regexp (concat "\\_<" helm-gtags--last-input "\\_>"))
+ (limit (1- (length candidate)))
+ (last-pos 0)
+ (case-fold-search nil))
+ (while (and (< last-pos limit)
+ (string-match regexp candidate last-pos))
+ (put-text-property (match-beginning 0) (match-end 0)
+ 'face 'helm-gtags-match
+ candidate)
+ (setq last-pos (1+ (match-end 0))))
+ candidate))
+
+(defun helm-gtags--transformer-regexp (candidate)
+ (if (and (helm-gtags--windows-p) (helm-gtags--has-drive-letter-p candidate))
+ "\\`\\([a-zA-Z]:[^:]+\\):\\([^:]+\\):\\(.*\\)"
+ "\\`\\([^:]+\\):\\([^:]+\\):\\(.*\\)"))
+
+(defun helm-gtags--candidate-transformer (candidate)
+ (if (not helm-gtags-highlight-candidate)
+ candidate
+ (let ((regexp (helm-gtags--transformer-regexp candidate)))
+ (when (string-match regexp candidate)
+ (format "%s:%s:%s"
+ (propertize (match-string 1 candidate) 'face 'helm-gtags-file)
+ (propertize (match-string 2 candidate) 'face 'helm-gtags-lineno)
+ (helm-gtags--highlight-candidate (match-string 3 candidate)))))))
+
+(defun helm-gtags--parse-file-candidate-transformer (file)
+ (let ((removed-file (replace-regexp-in-string "\\`\\S-+ " "" file)))
+ (when (string-match "\\`\\(\\S-+\\) \\(\\S-+\\) \\(.+\\)\\'" removed-file)
+ (format "%-25s %-5s %s"
+ (match-string-no-properties 1 removed-file)
+ (match-string-no-properties 2 removed-file)
+ (match-string-no-properties 3 removed-file)))))
+
+(defvar helm-source-gtags-find-tag-from-here
+ (helm-build-in-buffer-source "Find tag from here"
+ :init 'helm-gtags--find-tag-from-here-init
+ :candidate-number-limit helm-gtags-maximum-candidates
+ :real-to-display 'helm-gtags--candidate-transformer
+ :persistent-action 'helm-gtags--persistent-action
+ :fuzzy-match helm-gtags-fuzzy-match
+ :action helm-gtags--find-file-action))
+
+(defvar helm-source-gtags-parse-file
+ (helm-build-in-buffer-source "Parse file"
+ :init 'helm-gtags--parse-file-init
+ :candidate-number-limit helm-gtags-maximum-candidates
+ :real-to-display 'helm-gtags--parse-file-candidate-transformer
+ :fuzzy-match helm-gtags-fuzzy-match
+ :action 'helm-gtags--parse-file-action))
+
+(defun helm-gtags--show-stack-action (cand)
+ (let* ((index (get-text-property 0 'index cand))
+ (context-info (helm-gtags--get-context-info))
+ (context-stack (plist-get context-info :stack)))
+ (helm-gtags--put-context-stack helm-gtags--tag-location
+ index context-stack)
+ (helm-gtags--move-to-context (nth index context-stack))))
+
+(defvar helm-source-gtags-show-stack
+ (helm-build-sync-source "Show Context Stack"
+ :candidates 'helm-gtags--show-stack-init
+ :volatile t
+ :candidate-number-limit helm-gtags-maximum-candidates
+ :persistent-action 'helm-gtags--persistent-action
+ :fuzzy-match helm-gtags-fuzzy-match
+ :action 'helm-gtags--show-stack-action))
+
+;;;###autoload
+(defun helm-gtags-select ()
+ (interactive)
+ (helm-gtags--common '(helm-source-gtags-select) nil))
+
+;;;###autoload
+(defun helm-gtags-select-path ()
+ (interactive)
+ (helm-gtags--common '(helm-source-gtags-select-path) nil))
+
+(defsubst helm-gtags--beginning-of-defun ()
+ (cl-case major-mode
+ ((c-mode c++-mode java-mode) 'c-beginning-of-defun)
+ (php-mode 'php-beginning-of-defun)
+ (otherwise #'beginning-of-defun)))
+
+(defsubst helm-gtags--end-of-defun ()
+ (cl-case major-mode
+ ((c-mode c++-mode java-mode malabar-mode) 'c-end-of-defun)
+ (php-mode 'php-end-of-defun)
+ (otherwise #'end-of-defun)))
+
+(defun helm-gtags--current-funcion-bound ()
+ (save-excursion
+ (let (start)
+ (funcall (helm-gtags--beginning-of-defun))
+ (setq start (line-number-at-pos))
+ (funcall (helm-gtags--end-of-defun))
+ (cons start (line-number-at-pos)))))
+
+(defun helm-gtags--tags-refered-from-this-function ()
+ (let* ((file (helm-gtags--real-file-name))
+ (bound (helm-gtags--current-funcion-bound))
+ (start-line (car bound))
+ (end-line (cdr bound)))
+ (with-temp-buffer
+ (unless (process-file "global" nil t nil "-f" "-r" file)
+ (error "Failed: global -f -r %s" file))
+ (goto-char (point-min))
+ (let (tagnames finish)
+ (while (and (not finish) (not (eobp)))
+ (let* ((cols (split-string (helm-current-line-contents) nil t))
+ (lineno (string-to-number (cl-second cols))))
+ (if (and (> lineno start-line) (< lineno end-line))
+ (let* ((tag (cl-first cols))
+ (elm (cl-find tag tagnames :test 'equal)))
+ (unless elm
+ (push tag tagnames)))
+ (when (>= lineno end-line)
+ (setq finish t)))
+ (forward-line 1)))
+ (reverse tagnames)))))
+
+(defun helm-gtags--tag-in-function-persistent-action (cand)
+ (let* ((bound (helm-gtags--current-funcion-bound))
+ (limit (save-excursion
+ (goto-char (point-min))
+ (forward-line (cdr bound))
+ (goto-char (line-end-position))
+ (point))))
+ (when (search-forward cand nil limit)
+ (helm-highlight-current-line))))
+
+;;;###autoload
+(defun helm-gtags-tags-in-this-function ()
+ "Show tagnames which are referenced in this function and jump to it."
+ (interactive)
+ (let ((tags (helm-gtags--tags-refered-from-this-function)))
+ (unless tags
+ (error "There are no tags which are refered from this function."))
+ (let* ((name (format "Tags in [%s]" (which-function)))
+ (tag (helm-comp-read
+ "Tagnames: " tags
+ :must-match t :name name
+ :persistent-action 'helm-gtags--tag-in-function-persistent-action)))
+ (helm-gtags-find-tag tag))))
+
+(defun helm-gtags--source-select-tag (candidate)
+ (helm-build-in-buffer-source "Select Tag"
+ :init (lambda () (helm-gtags--tags-init candidate))
+ :candidate-number-limit helm-gtags-maximum-candidates
+ :persistent-action 'helm-gtags--persistent-action
+ :fuzzy-match helm-gtags-fuzzy-match
+ :action helm-gtags--find-file-action))
+
+(defun helm-gtags--source-select-rtag (candidate)
+ (helm-build-in-buffer-source "Select Rtag"
+ :init (lambda () (helm-gtags--rtags-init candidate))
+ :candidate-number-limit helm-gtags-maximum-candidates
+ :persistent-action 'helm-gtags--persistent-action
+ :fuzzy-match helm-gtags-fuzzy-match
+ :action helm-gtags--find-file-action))
+
+(defsubst helm-gtags--action-by-timer (src)
+ (run-with-timer 0.1 nil (lambda () (helm-gtags--common (list src) nil))))
+
+(defun helm-gtags--select-tag-action (c)
+ (helm-gtags--action-by-timer (helm-gtags--source-select-tag c)))
+
+(defun helm-gtags--select-rtag-action (c)
+ (helm-gtags--action-by-timer (helm-gtags--source-select-rtag c)))
+
+(defun helm-gtags--select-cache-init-common (args tagfile)
+ (let ((cache (helm-gtags--get-result-cache tagfile)))
+ (if cache
+ (insert cache)
+ (apply #'process-file "global" nil t nil args)
+ (let* ((cache (buffer-string))
+ (cache-size (length cache)))
+ (when (<= cache-size helm-gtags-cache-max-result-size)
+ (helm-gtags--put-result-cache tagfile cache))))))
+
+(defun helm-gtags--source-select-init ()
+ (with-current-buffer (helm-candidate-buffer 'global)
+ (if (not helm-gtags-cache-select-result)
+ (progn
+ (process-file "global" nil t nil "-c")
+ (helm-gtags--remove-carrige-returns))
+ (helm-gtags--select-cache-init-common '("-c") "GTAGS"))))
+
+(defvar helm-source-gtags-select
+ (helm-build-in-buffer-source "Find tag from here"
+ :init 'helm-gtags--source-select-init
+ :candidate-number-limit helm-gtags-maximum-candidates
+ :persistent-action #'ignore
+ :fuzzy-match helm-gtags-fuzzy-match
+ :action (helm-make-actions
+ "Goto the location" #'helm-gtags--select-tag-action
+ "Goto the location(other buffer)"
+ (lambda (c)
+ (setq helm-gtags--use-otherwin t)
+ (helm-gtags--select-tag-action c))
+ "Move to the referenced point" #'helm-gtags--select-rtag-action)))
+
+(defun helm-gtags--select-path-init ()
+ (helm-gtags--find-tag-directory)
+ (with-current-buffer (helm-candidate-buffer 'global)
+ (let ((options (if (eq helm-gtags-path-style 'relative) "-Po" "-Poa")))
+ (if (not helm-gtags-cache-select-result)
+ (progn
+ (process-file "global" nil t nil options)
+ (helm-gtags--remove-carrige-returns))
+ (helm-gtags--select-cache-init-common (list options) "GPATH")))))
+
+(defun helm-gtags--file-name (name)
+ (let ((remote (file-remote-p default-directory)))
+ (if (not remote)
+ name
+ (cl-case helm-gtags-path-style
+ (relative name)
+ (otherwise (concat remote name))))))
+
+(defun helm-gtags--find-file-common (open-fn cand)
+ (let ((default-directory (helm-gtags--base-directory)))
+ (funcall open-fn (helm-gtags--file-name cand))))
+
+(defun helm-gtags--find-file (cand)
+ (helm-gtags--find-file-common #'find-file cand))
+
+(defun helm-gtags--find-file-other-window (cand)
+ (helm-gtags--find-file-common #'find-file-other-window cand))
+
+(defvar helm-gtags--file-util-action
+ (helm-make-actions
+ "Open file" #'helm-gtags--find-file
+ "Open file other window" #'helm-gtags--find-file-other-window))
+
+(defun helm-gtags--file-persistent-action (cand)
+ (let ((default-directory (with-helm-current-buffer
+ default-directory)))
+ (helm-ff-kill-or-find-buffer-fname (helm-gtags--file-name cand))))
+
+(defvar helm-source-gtags-select-path
+ (helm-build-in-buffer-source "Select path"
+ :init 'helm-gtags--select-path-init
+ :candidate-number-limit helm-gtags-maximum-candidates
+ :real-to-display 'helm-gtags--files-candidate-transformer
+ :persistent-action #'helm-gtags--file-persistent-action
+ :fuzzy-match helm-gtags-fuzzy-match
+ :action helm-gtags--file-util-action))
+
+(defun helm-gtags--searched-directory ()
+ (cl-case (prefix-numeric-value current-prefix-arg)
+ (4 (let ((dir (read-directory-name "Input Directory: ")))
+ (setq helm-gtags--local-directory (file-name-as-directory dir))))
+ (16 (file-name-directory (buffer-file-name)))))
+
+(defsubst helm-gtags--using-other-window-p ()
+ (< (prefix-numeric-value current-prefix-arg) 0))
+
+(defun helm-gtags--make-gtags-sentinel (action)
+ (lambda (process _event)
+ (when (eq (process-status process) 'exit)
+ (if (zerop (process-exit-status process))
+ (message "Success: %s TAGS" action)
+ (message "Failed: %s TAGS(%d)" action (process-exit-status process))))))
+
+(defsubst helm-gtags--read-gtagslabel ()
+ (let ((labels '("default" "native" "ctags" "new-ctags" "pygments")))
+ (completing-read "GTAGSLABEL(Default: default): " labels nil t nil nil "default")))
+
+(defsubst helm-gtags--label-option (label)
+ (concat "--gtagslabel=" label))
+
+;;;###autoload
+(defun helm-gtags-create-tags (dir label)
+ (interactive
+ (list (read-directory-name "Root Directory: ")
+ (helm-gtags--read-gtagslabel)))
+ (let ((default-directory dir)
+ (proc-buf (get-buffer-create " *helm-gtags-create*")))
+ (let ((proc (start-file-process "helm-gtags-create" proc-buf
+ "gtags" "-q" (helm-gtags--label-option label))))
+ (set-process-sentinel proc (helm-gtags--make-gtags-sentinel 'create)))))
+
+(defun helm-gtags--find-tag-simple ()
+ (or (getenv "GTAGSROOT")
+ (locate-dominating-file default-directory "GTAGS")
+ (if (not (yes-or-no-p "File GTAGS not found. Run 'gtags'? "))
+ (user-error "Abort")
+ (let* ((tagroot (read-directory-name "Root Directory: "))
+ (label (helm-gtags--read-gtagslabel))
+ (default-directory tagroot))
+ (message "gtags is generating tags....")
+ (let ((label-opt (helm-gtags--label-option label)))
+ (unless (zerop (process-file "gtags" nil nil nil "-q" label-opt))
+ (error "Failed: 'gtags -q %s'" label-opt)))
+ tagroot))))
+
+(defun helm-gtags--current-file-and-line ()
+ (let* ((buffile (buffer-file-name))
+ (path (cl-case helm-gtags-path-style
+ (absolute buffile)
+ (root
+ (file-relative-name buffile (helm-gtags--find-tag-directory)))
+ (relative
+ (file-relative-name buffile (helm-gtags--base-directory))))))
+ (format "%s:%d" path (line-number-at-pos))))
+
+(defsubst helm-gtags--clear-variables ()
+ (setq helm-gtags--last-default-directory nil))
+
+(defun helm-gtags--common (srcs tagname)
+ (helm-gtags--clear-variables)
+ (let ((helm-quit-if-no-candidate t)
+ (helm-execute-action-at-once-if-one t)
+ (dir (helm-gtags--searched-directory))
+ (src (car srcs))
+ (preselect-regexp (when helm-gtags-preselect
+ (regexp-quote (helm-gtags--current-file-and-line)))))
+ (when (symbolp src)
+ (setq src (symbol-value src)))
+ (unless helm-gtags--use-otherwin
+ (setq helm-gtags--use-otherwin (helm-gtags--using-other-window-p)))
+ (when tagname
+ (setq helm-gtags--query tagname))
+ (let ((tagroot (helm-gtags--find-tag-simple)))
+ (helm-attrset 'helm-gtags-base-directory dir src)
+ (when tagname
+ (helm-attrset 'name (format "%s in %s" tagname (or dir tagroot)) src))
+ (helm :sources srcs :buffer helm-gtags--buffer
+ :preselect preselect-regexp))))
+
+;;;###autoload
+(defun helm-gtags-delete-tags ()
+ "Delete file GTAGS, GRTAGS, GPATH, ID etc. generated by gtags."
+ (interactive)
+ (let* ((root-dir (helm-gtags--tag-directory))
+ (re (concat "\\`" (regexp-opt '("GPATH" "GRTAGS" "GTAGS" "ID")) "\\'"))
+ (files (cl-remove-if-not
+ (lambda (file)
+ ;; Don't trust `directory-files'.
+ (let ((case-fold-search nil))
+ (string-match-p re (file-name-nondirectory file))))
+ (directory-files root-dir t re)))
+ (buffer "*GTags File List*"))
+ (unless files
+ (user-error "No tag files found"))
+ (with-output-to-temp-buffer buffer
+ (princ (mapconcat #'identity files "\n")))
+ (let ((win (get-buffer-window buffer)))
+ (unwind-protect
+ (progn
+ (fit-window-to-buffer win)
+ (when (yes-or-no-p "Remove GNU Global tag files? ")
+ (with-demoted-errors (mapc #'delete-file files))
+ ))
+ (when (window-live-p win)
+ (quit-window t win))))))
+
+;;;###autoload
+(defun helm-gtags-find-tag (tag)
+ "Jump to definition"
+ (interactive
+ (list (helm-gtags--read-tagname 'tag)))
+ (helm-gtags--common '(helm-source-gtags-tags) tag))
+
+;;;###autoload
+(defun helm-gtags-find-tag-other-window (tag)
+ "Jump to definition in other window."
+ (interactive
+ (list (helm-gtags--read-tagname 'tag)))
+ (setq helm-gtags--use-otherwin t)
+ (helm-gtags-find-tag tag))
+
+;;;###autoload
+(defun helm-gtags-find-rtag (tag)
+ "Jump to referenced point"
+ (interactive
+ (list (helm-gtags--read-tagname 'rtag (which-function))))
+ (helm-gtags--common '(helm-source-gtags-rtags) tag))
+
+;;;###autoload
+(defun helm-gtags-find-symbol (tag)
+ "Jump to the symbol location"
+ (interactive
+ (list (helm-gtags--read-tagname 'symbol)))
+ (helm-gtags--common '(helm-source-gtags-gsyms) tag))
+
+;;;###autoload
+(defun helm-gtags-find-pattern (pattern)
+ "Grep and jump by gtags tag files."
+ (interactive
+ (list (helm-gtags--read-tagname 'pattern)))
+ (helm-gtags--common '(helm-source-gtags-pattern) pattern))
+
+(defun helm-gtags--find-file-after-hook ()
+ (helm-gtags--push-context helm-gtags--saved-context))
+
+(defvar helm-source-gtags-files
+ (helm-build-in-buffer-source "Find files"
+ :init #'helm-gtags--files-init
+ :candidate-number-limit helm-gtags-maximum-candidates
+ :real-to-display #'helm-gtags--files-candidate-transformer
+ :persistent-action #'helm-gtags--file-persistent-action
+ :fuzzy-match helm-gtags-fuzzy-match
+ :action helm-gtags--file-util-action))
+
+;;;###autoload
+(defun helm-gtags-find-files (file)
+ "Find file from tagged with gnu global."
+ (interactive
+ (list (helm-gtags--read-tagname 'find-file)))
+ (add-hook 'helm-after-action-hook 'helm-gtags--find-file-after-hook)
+ (unwind-protect
+ (helm-gtags--common '(helm-source-gtags-files) file)
+ (remove-hook 'helm-after-action-hook 'helm-gtags--find-file-after-hook)))
+
+;;;###autoload
+(defun helm-gtags-find-tag-from-here ()
+ "Jump point by current point information.
+Jump to definition point if cursor is on its reference.
+Jump to reference point if curosr is on its definition"
+ (interactive)
+ (helm-gtags--common '(helm-source-gtags-find-tag-from-here) nil))
+
+;;;###autoload
+(defun helm-gtags-dwim ()
+ "Find by context. Here is
+- on include statement then jump to included file
+- on symbol definition then jump to its references
+- on reference point then jump to its definition."
+ (interactive)
+ (let ((line (helm-current-line-contents)))
+ (if (string-match helm-gtags--include-regexp line)
+ (let ((helm-gtags-use-input-at-cursor t))
+ (helm-gtags-find-files (match-string-no-properties 1 line)))
+ (if (and (buffer-file-name) (thing-at-point 'symbol))
+ (helm-gtags-find-tag-from-here)
+ (call-interactively 'helm-gtags-find-tag)))))
+
+(defun helm-gtags--set-parsed-file ()
+ (let* ((this-file (file-name-nondirectory (buffer-file-name)))
+ (file (if current-prefix-arg
+ (read-file-name "Parsed File: " nil this-file)
+ this-file)))
+ (setq helm-gtags--parsed-file (expand-file-name file))))
+
+(defun helm-gtags--find-preselect-line ()
+ (let ((defun-bound (bounds-of-thing-at-point 'defun)))
+ (if (not defun-bound)
+ (line-number-at-pos)
+ (let ((defun-begin-line (line-number-at-pos (car defun-bound)))
+ (filename (helm-gtags--real-file-name)))
+ (with-temp-buffer
+ (unless (zerop (process-file "global" nil t nil "-f" filename))
+ (error "Failed: global -f"))
+ (goto-char (point-min))
+ (let (start-line)
+ (while (and (not start-line)
+ (re-search-forward "^\\S-+\\s-+\\([1-9][0-9]*\\)" nil t))
+ (let ((line (string-to-number (match-string-no-properties 1))))
+ (when (>= line defun-begin-line)
+ (setq start-line line))))
+ (or start-line (line-number-at-pos))))))))
+
+;;;###autoload
+(defun helm-gtags-parse-file ()
+ "Parse current file with gnu global. This is similar to `imenu'.
+You can jump definitions of functions, symbols in this file."
+ (interactive)
+ (helm-gtags--find-tag-directory)
+ (helm-gtags--save-current-context)
+ (setq helm-gtags--use-otherwin (helm-gtags--using-other-window-p))
+ (helm-gtags--set-parsed-file)
+ (helm-attrset 'name
+ (format "Parsed File: %s"
+ (file-relative-name helm-gtags--parsed-file
+ helm-gtags--tag-location))
+ helm-source-gtags-parse-file)
+ (let ((presel (when helm-gtags-preselect
+ (format "^\\S-+\\s-+%d\\s-+" (helm-gtags--find-preselect-line)))))
+ (helm :sources '(helm-source-gtags-parse-file)
+ :buffer helm-gtags--buffer :preselect presel)))
+
+;;;###autoload
+(defun helm-gtags-pop-stack ()
+ "Jump to previous point on the context stack and pop it from stack."
+ (interactive)
+ (let* ((context-info (helm-gtags--get-context-info))
+ (context-stack (plist-get context-info :stack))
+ (context (pop context-stack)))
+ (helm-gtags--put-context-stack helm-gtags--tag-location -1 context-stack)
+ (helm-gtags--move-to-context context)))
+
+;;;###autoload
+(defun helm-gtags-show-stack ()
+ "Show current context stack."
+ (interactive)
+ (helm-other-buffer 'helm-source-gtags-show-stack
+ (get-buffer-create helm-gtags--buffer)))
+
+;;;###autoload
+(defun helm-gtags-clear-stack ()
+ "Clear current context stack."
+ (interactive)
+ (let ((tag-location (helm-gtags--find-tag-directory)))
+ (message "Clear '%s' context stack." tag-location)
+ (remhash tag-location helm-gtags--context-stack)))
+
+;;;###autoload
+(defun helm-gtags-clear-all-stacks ()
+ "Clear all context stacks."
+ (interactive)
+ (message "Clear all context statks.")
+ (setq helm-gtags--context-stack (make-hash-table :test 'equal)))
+
+(defun helm-gtags--read-tag-directory ()
+ (let ((dir (read-directory-name "Directory tag generated: " nil nil t)))
+ ;; On Windows, "gtags d:/tmp" work, but "gtags d:/tmp/" doesn't
+ (directory-file-name (expand-file-name dir))))
+
+(defsubst helm-gtags--how-to-update-tags ()
+ (cl-case (prefix-numeric-value current-prefix-arg)
+ (4 'entire-update)
+ (16 'generate-other-directory)
+ (otherwise 'single-update)))
+
+(defun helm-gtags--update-tags-command (how-to)
+ (cl-case how-to
+ (entire-update '("global" "-u"))
+ (generate-other-directory (list "gtags" (helm-gtags--read-tag-directory)))
+ (single-update (list "global" "--single-update" (helm-gtags--real-file-name)))))
+
+(defun helm-gtags--update-tags-p (how-to interactive-p current-time)
+ (or interactive-p
+ (and (eq how-to 'single-update)
+ (buffer-file-name)
+ (or (not helm-gtags-update-interval-second)
+ (>= (- current-time helm-gtags--last-update-time)
+ helm-gtags-update-interval-second)))))
+
+;;;###autoload
+(defun helm-gtags-update-tags ()
+ "Update TAG file. Update All files with `C-u' prefix.
+Generate new TAG file in selected directory with `C-u C-u'"
+ (interactive)
+ (let ((how-to (helm-gtags--how-to-update-tags))
+ (interactive-p (called-interactively-p 'interactive))
+ (current-time (float-time (current-time))))
+ (when (helm-gtags--update-tags-p how-to interactive-p current-time)
+ (let* ((cmds (helm-gtags--update-tags-command how-to))
+ (proc (apply #'start-file-process "helm-gtags-update-tag" nil cmds)))
+ (if (not proc)
+ (message "Failed: %s" (string-join cmds " "))
+ (set-process-sentinel proc (helm-gtags--make-gtags-sentinel 'update))
+ (setq helm-gtags--last-update-time current-time))))))
+
+;;;###autoload
+(defun helm-gtags-resume ()
+ "Resurrect previously invoked `helm-gtags` command."
+ (interactive)
+ (unless (get-buffer helm-gtags--buffer)
+ (error "Error: helm-gtags buffer is not existed."))
+ (helm-resume helm-gtags--buffer))
+
+(defsubst helm-gtags--check-browser-installed (browser)
+ (let ((used-browser (or browser "mozilla")))
+ (unless (executable-find used-browser)
+ (error "Not found browser '%s'" used-browser))))
+
+(defun helm-gtags-display-browser ()
+ "Display current screen on hypertext browser.
+`browse-url-generic-program' is used as browser if its value is non-nil.
+`mozilla' is used in other case."
+ (interactive)
+ (let ((file (buffer-file-name)))
+ (if (not file)
+ (error "This buffer is not related to file.")
+ (let* ((lineopt (concat "+" (number-to-string (line-number-at-pos))))
+ (browser (symbol-value 'browse-url-generic-program))
+ (args (list lineopt file)))
+ (helm-gtags--check-browser-installed browser)
+ (when browser
+ (setq args (append (list "-b" browser) args)))
+ ;; `gozilla' commend never returns error status if command is failed.
+ (apply #'process-file "gozilla" nil nil nil args)))))
+
+(defvar helm-gtags-mode-name " HelmGtags")
+(defvar helm-gtags-mode-map (make-sparse-keymap))
+
+;;;###autoload
+(define-minor-mode helm-gtags-mode ()
+ "Enable helm-gtags"
+ :init-value nil
+ :global nil
+ :keymap helm-gtags-mode-map
+ :lighter helm-gtags-mode-name
+ (if helm-gtags-mode
+ (when helm-gtags-auto-update
+ (add-hook 'after-save-hook 'helm-gtags-update-tags nil t))
+ (when helm-gtags-auto-update
+ (remove-hook 'after-save-hook 'helm-gtags-update-tags t))))
+
+;; Key mapping of gtags-mode.
+(when helm-gtags-suggested-key-mapping
+ ;; Current key mapping.
+ (let ((command-table '(("h" . helm-gtags-display-browser)
+ ("P" . helm-gtags-find-files)
+ ("f" . helm-gtags-parse-file)
+ ("g" . helm-gtags-find-pattern)
+ ("s" . helm-gtags-find-symbol)
+ ("r" . helm-gtags-find-rtag)
+ ("t" . helm-gtags-find-tag)
+ ("d" . helm-gtags-find-tag)))
+ (key-func (if (string-prefix-p "\\" helm-gtags-prefix-key)
+ #'concat
+ (lambda (prefix key) (kbd (concat prefix " " key))))))
+ (cl-loop for (key . command) in command-table
+ do
+ (define-key helm-gtags-mode-map (funcall key-func helm-gtags-prefix-key key) command))
+
+ ;; common
+ (define-key helm-gtags-mode-map "\C-]" 'helm-gtags-find-tag-from-here)
+ (define-key helm-gtags-mode-map "\C-t" 'helm-gtags-pop-stack)
+ (define-key helm-gtags-mode-map "\e*" 'helm-gtags-pop-stack)
+ (define-key helm-gtags-mode-map "\e." 'helm-gtags-find-tag)
+ (define-key helm-gtags-mode-map "\C-x4." 'helm-gtags-find-tag-other-window)))
+
+(provide 'helm-gtags)
+
+;; Local Variables:
+;; coding: utf-8
+;; indent-tabs-mode: nil
+;; End:
+
+;;; helm-gtags.el ends here
+++ /dev/null
-;;; helm-projectile-autoloads.el --- automatically extracted autoloads
-;;
-;;; Code:
-(add-to-list 'load-path (or (file-name-directory #$) (car load-path)))
-\f
-;;;### (autoloads nil "helm-projectile" "helm-projectile.el" (22215
-;;;;;; 7828 0 0))
-;;; Generated autoloads from helm-projectile.el
-
-(defvar helm-projectile-fuzzy-match t "\
-Enable fuzzy matching for Helm Projectile commands.
-This needs to be set before loading helm-projectile.")
-
-(custom-autoload 'helm-projectile-fuzzy-match "helm-projectile" t)
-
-(autoload 'helm-projectile-find-file-dwim "helm-projectile" "\
-Find file at point based on context.
-
-\(fn)" t nil)
-
-(autoload 'helm-projectile-find-other-file "helm-projectile" "\
-Switch between files with the same name but different extensions using Helm.
-With FLEX-MATCHING, match any file that contains the base name of current file.
-Other file extensions can be customized with the variable `projectile-other-file-alist'.
-
-\(fn &optional FLEX-MATCHING)" t nil)
-
-(autoload 'helm-projectile-on "helm-projectile" "\
-Turn on helm-projectile key bindings.
-
-\(fn)" t nil)
-
-(autoload 'helm-projectile-off "helm-projectile" "\
-Turn off helm-projectile key bindings.
-
-\(fn)" t nil)
-
-(autoload 'helm-projectile-grep "helm-projectile" "\
-Helm version of `projectile-grep'.
-DIR is the project root, if not set then current directory is used
-
-\(fn &optional DIR)" t nil)
-
-(autoload 'helm-projectile-ack "helm-projectile" "\
-Helm version of projectile-ack.
-
-\(fn &optional DIR)" t nil)
-
-(autoload 'helm-projectile-ag "helm-projectile" "\
-Helm version of projectile-ag.
-
-\(fn &optional OPTIONS)" t nil)
-
-(autoload 'helm-projectile "helm-projectile" "\
-Use projectile with Helm instead of ido.
-
-With a prefix ARG invalidates the cache first.
-If invoked outside of a project, displays a list of known projects to jump.
-
-\(fn &optional ARG)" t nil)
-
-(eval-after-load 'projectile '(progn (define-key projectile-command-map (kbd "h") #'helm-projectile)))
-
-;;;***
-\f
-;; Local Variables:
-;; version-control: never
-;; no-byte-compile: t
-;; no-update-autoloads: t
-;; End:
-;;; helm-projectile-autoloads.el ends here
+++ /dev/null
-(define-package "helm-projectile" "20151220.221" "Helm integration for Projectile" '((helm "1.7.7") (projectile "0.13.0") (dash "1.5.0") (cl-lib "0.3")) :url "https://github.com/bbatsov/projectile" :keywords '("project" "convenience"))
+++ /dev/null
-;;; helm-projectile.el --- Helm integration for Projectile
-
-;; Copyright (C) 2011-2015 Bozhidar Batsov
-
-;; Author: Bozhidar Batsov
-;; URL: https://github.com/bbatsov/projectile
-;; Package-Version: 20151220.221
-;; Created: 2011-31-07
-;; Keywords: project, convenience
-;; Version: 0.13.0
-;; Package-Requires: ((helm "1.7.7") (projectile "0.13.0") (dash "1.5.0") (cl-lib "0.3"))
-
-;; This file is NOT part of GNU Emacs.
-
-;;; License:
-
-;; 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, 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 GNU Emacs; see the file COPYING. If not, write to the
-;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
-;; Boston, MA 02110-1301, USA.
-
-;;; Commentary:
-;;
-;; This library provides easy project management and navigation. The
-;; concept of a project is pretty basic - just a folder containing
-;; special file. Currently git, mercurial and bazaar repos are
-;; considered projects by default. If you want to mark a folder
-;; manually as a project just create an empty .projectile file in
-;; it. See the README for more details.
-;;
-;;; Code:
-
-(require 'projectile)
-(require 'cl-lib)
-(require 'grep)
-(require 'helm)
-(require 'helm-types)
-(require 'helm-locate)
-(require 'helm-buffers)
-(require 'helm-files)
-
-(declare-function eshell "eshell")
-(declare-function helm-do-ag "helm-ag")
-(defvar helm-ag-base-command)
-
-(defvar grep-find-ignored-directories)
-(defvar grep-find-ignored-files)
-
-(defgroup helm-projectile nil
- "Helm support for projectile."
- :prefix "helm-projectile-"
- :group 'projectile
- :link `(url-link :tag "helm-projectile homepage" "https://github.com/bbatsov/projectile"))
-
-(defvar helm-projectile-current-project-root)
-
-;;;###autoload
-(defcustom helm-projectile-fuzzy-match t
- "Enable fuzzy matching for Helm Projectile commands.
-This needs to be set before loading helm-projectile."
- :group 'helm-projectile
- :type 'boolean)
-
-(defun helm-projectile-coerce-file (candidate)
- (with-current-buffer (helm-candidate-buffer)
- (expand-file-name candidate (projectile-project-root))))
-
-(defmacro helm-projectile-define-key (keymap key def &rest bindings)
- "In KEYMAP, define key sequence KEY1 as DEF1, KEY2 as DEF2 ..."
- (declare (indent defun))
- (let ((ret '(progn)))
- (while key
- (push
- `(define-key ,keymap ,key
- (lambda ()
- (interactive)
- (helm-exit-and-execute-action ,def)))
- ret)
- (setq key (pop bindings)
- def (pop bindings)))
- (reverse ret)))
-
-(defun helm-projectile-hack-actions (actions &rest prescription)
- "Given a Helm action list and a prescription, return a hacked
-Helm action list, after applying the PRESCRIPTION.
-
-The Helm action list ACTIONS is of the form:
-
-\(\(DESCRIPTION1 . FUNCTION1\)
- \(DESCRIPTION2 . FUNCTION2\)
- ...
- \(DESCRIPTIONn . FUNCTIONn\)\)
-
-PRESCRIPTION is in the form:
-
-\(INSTRUCTION1 INSTRUCTION2 ... INSTRUCTIONn\)
-
-If an INSTRUCTION is a symbol, the action with function name
-INSTRUCTION is deleted.
-
-If an INSTRUCTION is of the form \(FUNCTION1 . FUNCTION2\), the
-action with function name FUNCTION1 will change it's function to
-FUNCTION2.
-
-If an INSTRUCTION is of the form \(FUNCTION . DESCRIPTION\), and
-if an action with function name FUNCTION exists in the original
-Helm action list, the action in the Helm action list, with
-function name FUNCTION will change it's description to
-DESCRIPTION. Otherwise, (FUNCTION . DESCRIPTION) will be added to
-the action list.
-
-Please check out how `helm-projectile-file-actions' is defined
-for an example of how this function is being used."
- (let* ((to-delete (cl-remove-if (lambda (entry) (listp entry)) prescription))
- (actions (cl-delete-if (lambda (action) (memq (cdr action) to-delete))
- (copy-alist actions)))
- new)
- (cl-dolist (action actions)
- (when (setq new (cdr (assq (cdr action) prescription)))
- (if (stringp new)
- (setcar action new)
- (setcdr action new))))
- ;; Add new actions from PRESCRIPTION
- (setq new nil)
- (cl-dolist (instruction prescription)
- (when (and (listp instruction)
- (null (rassq (car instruction) actions))
- (symbolp (car instruction)) (stringp (cdr instruction)))
- (push (cons (cdr instruction) (car instruction)) new)))
- (append actions (nreverse new))))
-
-(defun helm-projectile-vc (dir)
- "A Helm action for jumping to project root using `vc-dir' or Magit.
-DIR is a directory to be switched"
- (let ((projectile-require-project-root nil))
- (projectile-vc dir)))
-
-(defun helm-projectile-compile-project (dir)
- "A Helm action for compile a project.
-DIR is the project root."
- (let ((helm--reading-passwd-or-string t)
- (default-directory dir))
- (projectile-compile-project helm-current-prefix-arg dir)))
-
-(defun helm-projectile-test-project (dir)
- "A Helm action for test a project.
-DIR is the project root."
- (let ((helm--reading-passwd-or-string t)
- (default-directory dir))
- (projectile-test-project helm-current-prefix-arg)))
-
-(defun helm-projectile-run-project (dir)
- "A Helm action for run a project.
-DIR is the project root."
- (let ((helm--reading-passwd-or-string t)
- (default-directory dir))
- (projectile-run-project helm-current-prefix-arg)))
-
-(defun helm-projectile-remove-known-project (_ignore)
- "Delete selected projects.
-_IGNORE means the argument does not matter.
-It is there because Helm requires it."
- (let* ((projects (helm-marked-candidates :with-wildcard t))
- (len (length projects)))
- (with-helm-display-marked-candidates
- helm-marked-buffer-name
- projects
- (if (not (y-or-n-p (format "Delete *%s projects(s)? " len)))
- (message "(No deletion performed)")
- (progn
- (mapc (lambda (p)
- (delete p projectile-known-projects))
- projects)
- (projectile-save-known-projects))
- (message "%s projects(s) deleted" len)))))
-
-(defvar helm-projectile-projects-map
- (let ((map (make-sparse-keymap)))
- (set-keymap-parent map helm-map)
- (helm-projectile-define-key map
- (kbd "C-d") #'dired
- (kbd "M-g") #'helm-projectile-vc
- (kbd "M-e") #'helm-projectile-switch-to-eshell
- (kbd "C-s") #'helm-projectile-grep
- (kbd "M-c") #'helm-projectile-compile-project
- (kbd "M-t") #'helm-projectile-test-project
- (kbd "M-r") #'helm-projectile-run-project
- (kbd "M-D") #'helm-projectile-remove-known-project)
- map)
- "Mapping for known projectile projects.")
-
-(defvar helm-source-projectile-projects
- (helm-build-in-buffer-source "Projectile projects"
- :data (lambda ()
- (if (projectile-project-p)
- (cons (abbreviate-file-name (projectile-project-root))
- (projectile-relevant-known-projects))
- projectile-known-projects))
- :fuzzy-match helm-projectile-fuzzy-match
- :keymap helm-projectile-projects-map
- :mode-line helm-read-file-name-mode-line-string
- :action '(("Switch to project" .
- (lambda (project)
- (let ((projectile-completion-system 'helm))
- (projectile-switch-project-by-name project))))
- ("Open Dired in project's directory `C-d'" . dired)
- ("Open project root in vc-dir or magit `M-g'" . helm-projectile-vc)
- ("Switch to Eshell `M-e'" . helm-projectile-switch-to-eshell)
- ("Grep in projects `C-s'" . helm-projectile-grep)
- ("Compile project `M-c'. With C-u, new compile command"
- . helm-projectile-compile-project)
- ("Remove project(s) `M-D'" . helm-projectile-remove-known-project)))
- "Helm source for known projectile projects.")
-
-(define-key helm-etags-map (kbd "C-c p f")
- (lambda ()
- (interactive)
- (helm-run-after-exit 'helm-projectile-find-file nil)))
-
-(defun helm-projectile-find-files-eshell-command-on-file-action (_candidate)
- (interactive)
- (let* ((helm-ff-default-directory (file-name-directory _candidate)))
- (helm-find-files-eshell-command-on-file _candidate)))
-
-(defun helm-projectile-ff-etags-select-action (_candidate)
- (interactive)
- (let* ((helm-ff-default-directory (file-name-directory _candidate)))
- (helm-ff-etags-select _candidate)))
-
-(defun helm-projectile-switch-to-eshell (dir)
- (interactive)
- (let* ((projectile-require-project-root nil)
- (helm-ff-default-directory (file-name-directory (projectile-expand-root dir))))
- (helm-ff-switch-to-eshell dir)))
-
-(defun helm-projectile-files-in-current-dired-buffer ()
- "Return a list of files (only) in the current dired buffer."
- (let (flist)
- (cl-flet ((fpush (fname) (push fname flist)))
- (save-excursion
- (let (file buffer-read-only)
- (goto-char (point-min))
- (while (not (eobp))
- (save-excursion
- (and (not (eolp))
- (setq file (dired-get-filename t t)) ; nil on non-file
- (progn (end-of-line)
- (funcall #'fpush file))))
- (forward-line 1)))))
- (mapcar 'file-truename (nreverse flist))))
-
-(defun helm-projectile-all-dired-buffers ()
- "Get all current Dired buffers."
- (mapcar (lambda (b)
- (with-current-buffer b (buffer-name)))
- (-filter (lambda (b)
- (with-current-buffer b
- (and (eq major-mode 'dired-mode)
- (buffer-name))))
- (buffer-list))))
-
-(defvar helm-projectile-virtual-dired-remote-enable nil
- "Enable virtual Dired manager on remote host.
-Disabled by default.")
-
-(defun helm-projectile-dired-files-new-action (candidate)
- "Create a Dired buffer from chosen files.
-CANDIDATE is the selected file, but choose the marked files if available."
- (if (and (file-remote-p (projectile-project-root))
- (not helm-projectile-virtual-dired-remote-enable))
- (message "Virtual Dired manager is disabled in remote host. Enable with %s."
- (propertize "helm-projectile-virtual-dired-remote-enable" 'face 'font-lock-keyword-face))
- (let ((files (-filter (lambda (f)
- (not (string= f "")))
- (mapcar (lambda (file)
- (replace-regexp-in-string (projectile-project-root) "" file))
- (helm-marked-candidates :with-wildcard t))))
- (new-name (completing-read "Select or enter a new buffer name: "
- (helm-projectile-all-dired-buffers)))
- (helm--reading-passwd-or-string t)
- (default-directory (projectile-project-root)))
- ;; create a unique buffer that is unique to any directory in default-directory
- ;; or opened buffer; when Dired is passed with a non-existence directory name,
- ;; it only creates a buffer and insert everything. If a new name user supplied
- ;; exists as default-directory, Dired throws error when insert anything that
- ;; does not exist in current directory.
- (with-current-buffer (dired (cons (make-temp-name new-name)
- (if files
- files
- (list candidate))))
- (when (get-buffer new-name)
- (kill-buffer new-name))
- (rename-buffer new-name)))))
-
-(defun helm-projectile-dired-files-add-action (candidate)
- "Add files to a Dired buffer.
-CANDIDATE is the selected file. Used when no file is explicitly marked."
- (if (and (file-remote-p (projectile-project-root))
- (not helm-projectile-virtual-dired-remote-enable))
- (message "Virtual Dired manager is disabled in remote host. Enable with %s."
- (propertize "helm-projectile-virtual-dired-remote-enable" 'face 'font-lock-keyword-face))
- (if (eq (with-helm-current-buffer major-mode) 'dired-mode)
- (let* ((marked-files (helm-marked-candidates :with-wildcard t))
- (helm--reading-passwd-or-string t)
- (root (projectile-project-root)) ; store root for later use
- (dired-buffer-name (or (and (eq major-mode 'dired-mode) (buffer-name))
- (completing-read "Select a Dired buffer:"
- (helm-projectile-all-dired-buffers))))
- (dired-files (with-current-buffer dired-buffer-name
- (helm-projectile-files-in-current-dired-buffer)))
- (files (sort (mapcar (lambda (file)
- (replace-regexp-in-string (projectile-project-root) "" file))
- (cl-nunion (if marked-files
- marked-files
- (list candidate))
- dired-files
- :test #'string-equal))
- 'string-lessp)))
- (kill-buffer dired-buffer-name)
- ;; Rebind default-directory because after killing a buffer, we
- ;; could be in any buffer and default-directory is set to that
- ;; random buffer
- ;;
- ;; Also use saved root directory, because after killing a buffer,
- ;; we could be outside of current project
- (let ((default-directory root))
- (with-current-buffer (dired (cons (make-temp-name dired-buffer-name)
- (if files
- (mapcar (lambda (file)
- (replace-regexp-in-string root "" file))
- files)
- (list candidate))))
- (rename-buffer dired-buffer-name))))
- (error "You're not in a Dired buffer to add"))))
-
-(defun helm-projectile-dired-files-delete-action (candidate)
- "Delete selected entries from a Dired buffer.
-CANDIDATE is the selected file. Used when no file is explicitly marked."
- (if (and (file-remote-p (projectile-project-root))
- (not helm-projectile-virtual-dired-remote-enable))
- (message "Virtual Dired manager is disabled in remote host. Enable with %s."
- (propertize "helm-projectile-virtual-dired-remote-enable" 'face 'font-lock-keyword-face))
- (let* ((helm--reading-passwd-or-string t)
- (root (projectile-project-root))
- (dired-buffer-name (with-helm-current-buffer (buffer-name)))
- (dired-files (with-current-buffer dired-buffer-name
- (helm-projectile-files-in-current-dired-buffer)))
- (files (sort (cl-set-exclusive-or (helm-marked-candidates :with-wildcard t)
- dired-files
- :test #'string-equal) #'string-lessp)))
- (kill-buffer dired-buffer-name)
- ;; similar reason to `helm-projectile-dired-files-add-action'
- (let ((default-directory root))
- (with-current-buffer (dired (cons (make-temp-name dired-buffer-name)
- (if files
- (mapcar (lambda (file)
- (replace-regexp-in-string root "" file))
- files)
- (list candidate))))
- (rename-buffer dired-buffer-name))))))
-
-(defvar helm-projectile-find-file-map
- (let ((map (copy-keymap helm-find-files-map)))
- (helm-projectile-define-key map
- (kbd "C-c f") #'helm-projectile-dired-files-new-action
- (kbd "C-c a") #'helm-projectile-dired-files-add-action
- (kbd "M-e") #'helm-projectile-switch-to-eshell
- (kbd "M-.") #'helm-projectile-ff-etags-select-action
- (kbd "M-!") #'helm-projectile-find-files-eshell-command-on-file-action)
- (define-key map (kbd "<left>") #'helm-previous-source)
- (define-key map (kbd "<right>") #'helm-next-source)
- map)
- "Mapping for file commands in Helm Projectile.")
-
-(defvar helm-projectile-file-actions
- (helm-projectile-hack-actions
- helm-find-files-actions
- ;; Delete these actions
- 'helm-ff-browse-project
- 'helm-insert-file-name-completion-at-point
- 'helm-ff-find-sh-command
- 'helm-ff-cache-add-file
- ;; Substitute these actions
- '(helm-ff-switch-to-eshell . helm-projectile-switch-to-eshell)
- '(helm-ff-etags-select . helm-projectile-ff-etags-select-action)
- '(helm-find-files-eshell-command-on-file
- . helm-projectile-find-files-eshell-command-on-file-action)
- ;; Change action descriptions
- '(helm-find-file-as-root . "Find file as root `C-c r'")
- ;; New actions
- '(helm-projectile-dired-files-new-action
- . "Create Dired buffer from files `C-c f'")
- '(helm-projectile-dired-files-add-action
- . "Add files to Dired buffer `C-c a'"))
- "Action for files.")
-
-(defun helm-projectile-build-dwim-source (candidates)
- "Dynamically build a Helm source definition for Projectile files based on context with CANDIDATES."
- ""
- (helm-build-in-buffer-source "Projectile files"
- :data candidates
- :fuzzy-match helm-projectile-fuzzy-match
- :coerce 'helm-projectile-coerce-file
- :action-transformer 'helm-find-files-action-transformer
- :keymap helm-projectile-find-file-map
- :help-message helm-ff-help-message
- :mode-line helm-read-file-name-mode-line-string
- :action helm-projectile-file-actions))
-
-(defvar helm-source-projectile-files-list
- (helm-build-in-buffer-source "Projectile files"
- :data (lambda ()
- (condition-case nil
- (projectile-current-project-files)
- (error nil)))
- :fuzzy-match helm-projectile-fuzzy-match
- :coerce 'helm-projectile-coerce-file
- :keymap helm-projectile-find-file-map
- :help-message 'helm-ff-help-message
- :mode-line helm-read-file-name-mode-line-string
- :action helm-projectile-file-actions
- )
- "Helm source definition for Projectile files.")
-
-(defvar helm-source-projectile-files-in-all-projects-list
- (helm-build-in-buffer-source "Projectile files in all Projects"
- :data (lambda ()
- (condition-case nil
- (let ((projectile-require-project-root nil))
- (projectile-all-project-files))
- (error nil)))
- :keymap helm-find-files-map
- :help-message 'helm-ff-help-message
- :mode-line helm-read-file-name-mode-line-string
- :action helm-projectile-file-actions
- )
- "Helm source definition for all Projectile files in all projects.")
-
-(defvar helm-projectile-dired-file-actions
- (helm-projectile-hack-actions
- helm-projectile-file-actions
- ;; New actions
- '(helm-projectile-dired-files-delete-action . "Remove entry(s) from Dired buffer `C-c d'")))
-
-(defvar helm-source-projectile-dired-files-list
- (helm-build-in-buffer-source "Projectile files in current Dired buffer"
- :data (lambda ()
- (condition-case nil
- (if (and (file-remote-p (projectile-project-root))
- (not helm-projectile-virtual-dired-remote-enable))
- nil
- (let ((default-directory (projectile-project-root)))
- (when (eq major-mode 'dired-mode)
- (mapcar (lambda (file)
- (replace-regexp-in-string default-directory "" file))
- (helm-projectile-files-in-current-dired-buffer)))))
- (error nil)))
- :coerce 'helm-projectile-coerce-file
- :filter-one-by-one (lambda (file)
- (let ((default-directory (projectile-project-root)))
- (helm-ff-filter-candidate-one-by-one file)))
- :action-transformer 'helm-find-files-action-transformer
- :keymap (let ((map (copy-keymap helm-projectile-find-file-map)))
- (helm-projectile-define-key map
- (kbd "C-c d") 'helm-projectile-dired-files-delete-action)
- map)
- :help-message 'helm-ff-help-message
- :mode-line helm-read-file-name-mode-line-string
- :action helm-projectile-dired-file-actions)
- "Helm source definition for Projectile delete files.")
-
-(defun helm-projectile-dired-find-dir (dir)
- "Jump to a selected directory DIR from helm-projectile."
- (dired (expand-file-name dir (projectile-project-root)))
- (run-hooks 'projectile-find-dir-hook))
-
-(defun helm-projectile-dired-find-dir-other-window (dir)
- "Jump to a selected directory DIR from helm-projectile."
- (dired-other-window (expand-file-name dir (projectile-project-root)))
- (run-hooks 'projectile-find-dir-hook))
-
-(defvar helm-source-projectile-directories-list
- (helm-build-in-buffer-source "Projectile directories"
- :data (lambda ()
- (condition-case nil
- (if projectile-find-dir-includes-top-level
- (append '("./") (projectile-current-project-dirs))
- (projectile-current-project-dirs))
- (error nil)))
- :fuzzy-match helm-projectile-fuzzy-match
- :coerce 'helm-projectile-coerce-file
- :action-transformer 'helm-find-files-action-transformer
- :keymap (let ((map (make-sparse-keymap)))
- (set-keymap-parent map helm-map)
- (helm-projectile-define-key map
- (kbd "<left>") #'helm-previous-source
- (kbd "<right>") #'helm-next-source
- (kbd "C-c o") #'helm-projectile-dired-find-dir-other-window
- (kbd "M-e") #'helm-projectile-switch-to-eshell
- (kbd "C-c f") #'helm-projectile-dired-files-new-action
- (kbd "C-c a") #'helm-projectile-dired-files-add-action
- (kbd "C-s") #'helm-projectile-grep)
- map)
- :help-message 'helm-ff-help-message
- :mode-line helm-read-file-name-mode-line-string
- :action '(("Open Dired" . helm-projectile-dired-find-dir)
- ("Open Dired in other window `C-c o'" . helm-projectile-dired-find-dir)
- ("Switch to Eshell `M-e'" . helm-projectile-switch-to-eshell)
- ("Grep in projects `C-s'" . helm-projectile-grep)
- ("Create Dired buffer from files `C-c f'" . helm-projectile-dired-files-new-action)
- ("Add files to Dired buffer `C-c a'" . helm-projectile-dired-files-add-action)))
- "Helm source for listing project directories.")
-
-(defvar helm-projectile-buffers-list-cache nil)
-
-(defclass helm-source-projectile-buffer (helm-source-sync helm-type-buffer)
- ((init :initform (lambda ()
- ;; Issue #51 Create the list before `helm-buffer' creation.
- (setq helm-projectile-buffers-list-cache (condition-case nil
- (cdr (projectile-project-buffer-names))
- (error nil)))
- (let ((result (cl-loop for b in helm-projectile-buffers-list-cache
- maximize (length b) into len-buf
- maximize (length (with-current-buffer b
- (symbol-name major-mode)))
- into len-mode
- finally return (cons len-buf len-mode))))
- (unless helm-buffer-max-length
- (setq helm-buffer-max-length (car result)))
- (unless helm-buffer-max-len-mode
- ;; If a new buffer is longer that this value
- ;; this value will be updated
- (setq helm-buffer-max-len-mode (cdr result))))))
- (candidates :initform helm-projectile-buffers-list-cache)
- (matchplugin :initform nil)
- (match :initform 'helm-buffers-match-function)
- (persistent-action :initform 'helm-buffers-list-persistent-action)
- (keymap :initform helm-buffer-map)
- (volatile :initform t)
- (persistent-help
- :initform
- "Show this buffer / C-u \\[helm-execute-persistent-action]: Kill this buffer")))
-
-(defvar helm-source-projectile-buffers-list (helm-make-source "Project buffers" 'helm-source-projectile-buffer))
-
-(defvar helm-source-projectile-recentf-list
- (helm-build-in-buffer-source "Projectile recent files"
- :data (lambda ()
- (condition-case nil
- (projectile-recentf-files)
- (error nil)))
- :fuzzy-match helm-projectile-fuzzy-match
- :coerce 'helm-projectile-coerce-file
- :keymap helm-projectile-find-file-map
- :help-message 'helm-ff-help-message
- :mode-line helm-read-file-name-mode-line-string
- :action helm-projectile-file-actions
- )
- "Helm source definition for recent files in current project.")
-
-(defvar helm-source-projectile-files-and-dired-list
- '(helm-source-projectile-dired-files-list
- helm-source-projectile-files-list))
-
-(defvar helm-source-projectile-directories-and-dired-list
- '(helm-source-projectile-dired-files-list
- helm-source-projectile-directories-list))
-
-(defcustom helm-projectile-sources-list
- '(helm-source-projectile-buffers-list
- helm-source-projectile-files-list
- helm-source-projectile-projects
- )
- "Default sources for `helm-projectile'."
- :group 'helm-projectile)
-
-(defmacro helm-projectile-command (command source prompt &optional not-require-root)
- "Template for generic helm-projectile commands.
-COMMAND is a command name to be appended with \"helm-projectile\" prefix.
-SOURCE is a Helm source that should be Projectile specific.
-PROMPT is a string for displaying as a prompt.
-NOT-REQUIRE-ROOT specifies the command doesn't need to be used in a
-project root."
- `(defun ,(intern (concat "helm-projectile-" command)) (&optional arg)
- "Use projectile with Helm for finding files in project
-
-With a prefix ARG invalidates the cache first."
- (interactive "P")
- (if (projectile-project-p)
- (projectile-maybe-invalidate-cache arg)
- (unless ,not-require-root
- (error "You're not in a project")))
- (let ((helm-ff-transformer-show-only-basename nil)
- ;; for consistency, we should just let Projectile take care of ignored files
- (helm-boring-file-regexp-list nil))
- (helm :sources ,source
- :buffer "*helm projectile*"
- :prompt (projectile-prepend-project-name ,prompt)))))
-
-(helm-projectile-command "switch-project" 'helm-source-projectile-projects "Switch to project: " t)
-(helm-projectile-command "find-file" helm-source-projectile-files-and-dired-list "Find file: ")
-(helm-projectile-command "find-file-in-known-projects" 'helm-source-projectile-files-in-all-projects-list "Find file in projects: " t)
-(helm-projectile-command "find-dir" helm-source-projectile-directories-and-dired-list "Find dir: ")
-(helm-projectile-command "recentf" 'helm-source-projectile-recentf-list "Recently visited file: ")
-(helm-projectile-command "switch-to-buffer" 'helm-source-projectile-buffers-list "Switch to buffer: ")
-
-;;;###autoload
-(defun helm-projectile-find-file-dwim ()
- "Find file at point based on context."
- (interactive)
- (let* ((project-files (projectile-current-project-files))
- (files (projectile-select-files project-files)))
- (if (= (length files) 1)
- (find-file (expand-file-name (car files) (projectile-project-root)))
- (helm :sources (helm-projectile-build-dwim-source (if (> (length files) 1)
- files
- project-files))
- :buffer "*helm projectile*"
- :prompt (projectile-prepend-project-name "Find file: ")))))
-
-;;;###autoload
-(defun helm-projectile-find-other-file (&optional flex-matching)
- "Switch between files with the same name but different extensions using Helm.
-With FLEX-MATCHING, match any file that contains the base name of current file.
-Other file extensions can be customized with the variable `projectile-other-file-alist'."
- (interactive "P")
- (-if-let (other-files (projectile-get-other-files (buffer-file-name)
- (projectile-current-project-files)
- flex-matching))
- (if (= (length other-files) 1)
- (find-file (expand-file-name (car other-files) (projectile-project-root)))
- (progn
- (let* ((helm-ff-transformer-show-only-basename nil))
- (helm :sources (helm-build-in-buffer-source "Projectile other files"
- :data other-files
- :coerce 'helm-projectile-coerce-file
- :keymap (let ((map (copy-keymap helm-find-files-map)))
- (define-key map (kbd "<left>") 'helm-previous-source)
- (define-key map (kbd "<right>") 'helm-next-source)
- map)
- :help-message helm-ff-help-message
- :mode-line helm-read-file-name-mode-line-string
- :action helm-projectile-file-actions)
- :buffer "*helm projectile*"
- :prompt (projectile-prepend-project-name "Find other file: ")))))
- (error "No other file found")))
-
-(defun helm-projectile-grep-or-ack (&optional dir use-ack-p ack-ignored-pattern ack-executable)
- "Perform helm-grep at project root.
-DIR directory where to search
-USE-ACK-P indicates whether to use ack or not.
-ACK-IGNORED-PATTERN is a file regex to exclude from searching.
-ACK-EXECUTABLE is the actual ack binary name.
-It is usually \"ack\" or \"ack-grep\".
-If it is nil, or ack/ack-grep not found then use default grep command."
- (let* ((default-directory (or dir (projectile-project-root)))
- (helm-ff-default-directory default-directory)
- (follow (and helm-follow-mode-persistent
- (assoc-default 'follow helm-source-grep)))
- (helm-grep-in-recurse t)
- (helm-grep-ignored-files (-union (projectile-ignored-files-rel) grep-find-ignored-files))
- (helm-grep-ignored-directories (-union (projectile-ignored-directories-rel) grep-find-ignored-directories))
- (helm-grep-default-command (if use-ack-p
- (concat ack-executable " -H --no-group --no-color " ack-ignored-pattern " %p %f")
- (if (and projectile-use-git-grep (eq (projectile-project-vcs) 'git))
- "git --no-pager grep --no-color -n -e %p -- %f"
- "grep -a -r %e -n%cH -e %p %f .")))
- (helm-grep-default-recurse-command helm-grep-default-command)
- (helm-source-grep
- (helm-build-async-source
- (capitalize (helm-grep-command t))
- :header-name (lambda (name)
- (let ((name (if use-ack-p
- "Helm Projectile Ack"
- "Helm Projectile Grep")))
- (concat name " " "(C-c ? Help)")))
- :candidates-process 'helm-grep-collect-candidates
- :filter-one-by-one 'helm-grep-filter-one-by-one
- :candidate-number-limit 9999
- :nohighlight t
- ;; We need to specify keymap here and as :keymap arg [1]
- ;; to make it available in further resuming.
- :keymap helm-grep-map
- :history 'helm-grep-history
- :action (helm-make-actions
- "Find file" 'helm-grep-action
- "Find file other frame" 'helm-grep-other-frame
- (lambda () (and (locate-library "elscreen")
- "Find file in Elscreen"))
- 'helm-grep-jump-elscreen
- "Save results in grep buffer" 'helm-grep-save-results
- "Find file other window" 'helm-grep-other-window)
- :persistent-action 'helm-grep-persistent-action
- :persistent-help "Jump to line (`C-u' Record in mark ring)"
- :requires-pattern 2)))
- (helm
- :sources 'helm-source-grep
- :input (if (region-active-p)
- (buffer-substring-no-properties (region-beginning) (region-end))
- (thing-at-point 'symbol))
- :buffer (format "*helm %s*" (if use-ack-p
- "ack"
- "grep"))
- :default-directory default-directory
- :keymap helm-grep-map
- :history 'helm-grep-history
- :truncate-lines t)))
-
-;;;###autoload
-(defun helm-projectile-on ()
- "Turn on helm-projectile key bindings."
- (interactive)
- (message "Turn on helm-projectile key bindings")
- (helm-projectile-toggle 1))
-
-;;;###autoload
-(defun helm-projectile-off ()
- "Turn off helm-projectile key bindings."
- (interactive)
- (message "Turn off helm-projectile key bindings")
- (helm-projectile-toggle -1))
-
-;;;###autoload
-(defun helm-projectile-grep (&optional dir)
- "Helm version of `projectile-grep'.
-DIR is the project root, if not set then current directory is used"
- (interactive)
- (let ((project-root (or dir (projectile-project-root) (error "You're not in a project"))))
- (funcall'run-with-timer 0.01 nil
- #'helm-projectile-grep-or-ack project-root nil)))
-
-;;;###autoload
-(defun helm-projectile-ack (&optional dir)
- "Helm version of projectile-ack."
- (interactive)
- (let ((project-root (or dir (projectile-project-root) (error "You're not in a project"))))
- (let ((ack-ignored (mapconcat
- 'identity
- (-union (-map (lambda (path)
- (concat "--ignore-dir=" (file-name-nondirectory (directory-file-name path))))
- (projectile-ignored-directories))
- (-map (lambda (path)
- (concat "--ignore-file=match:" (shell-quote-argument path)))
- (projectile-ignored-files))) " "))
- (helm-ack-grep-executable (cond
- ((executable-find "ack") "ack")
- ((executable-find "ack-grep") "ack-grep")
- (t (error "ack or ack-grep is not available.")))))
- (funcall 'run-with-timer 0.01 nil
- #'helm-projectile-grep-or-ack project-root t ack-ignored helm-ack-grep-executable))))
-
-;;;###autoload
-(defun helm-projectile-ag (&optional options)
- "Helm version of projectile-ag."
- (interactive (if current-prefix-arg (list (read-string "option: " "" 'helm-ag--extra-options-history))))
- (if (require 'helm-ag nil 'noerror)
- (if (projectile-project-p)
- (let* ((grep-find-ignored-files (-union (projectile-ignored-files-rel) grep-find-ignored-files))
- (grep-find-ignored-directories (-union (projectile-ignored-directories-rel) grep-find-ignored-directories))
- (ignored (mapconcat (lambda (i)
- (concat "--ignore " i))
- (append grep-find-ignored-files grep-find-ignored-directories)
- " "))
- (helm-ag-command-option options)
- (helm-ag-base-command (concat helm-ag-base-command " " ignored))
- (current-prefix-arg nil))
- (helm-do-ag (projectile-project-root)))
- (error "You're not in a project"))
- (error "helm-ag not available")))
-
-(defun helm-projectile-commander-bindings ()
- (def-projectile-commander-method ?a
- "Run ack on project."
- (call-interactively 'helm-projectile-ack))
-
- (def-projectile-commander-method ?A
- "Find ag on project."
- (call-interactively 'helm-projectile-ag))
-
- (def-projectile-commander-method ?f
- "Find file in project."
- (helm-projectile-find-file))
-
- (def-projectile-commander-method ?b
- "Switch to project buffer."
- (helm-projectile-switch-to-buffer))
-
- (def-projectile-commander-method ?d
- "Find directory in project."
- (helm-projectile-find-dir))
-
- (def-projectile-commander-method ?g
- "Run grep on project."
- (helm-projectile-grep))
-
- (def-projectile-commander-method ?s
- "Switch project."
- (helm-projectile-switch-project))
-
- (def-projectile-commander-method ?e
- "Find recently visited file in project."
- (helm-projectile-recentf)))
-
-(defun helm-projectile-toggle (toggle)
- "Toggle Helm version of Projectile commands."
- (if (> toggle 0)
- (progn
- (setq projectile-switch-project-action #'helm-projectile-find-file)
- (define-key projectile-command-map (kbd "a") #'helm-projectile-find-other-file)
- (define-key projectile-command-map (kbd "f") #'helm-projectile-find-file)
- (define-key projectile-command-map (kbd "F") #'helm-projectile-find-file-in-known-projects)
- (define-key projectile-command-map (kbd "g") #'helm-projectile-find-file-dwim)
- (define-key projectile-command-map (kbd "d") #'helm-projectile-find-dir)
- (define-key projectile-command-map (kbd "p") #'helm-projectile-switch-project)
- (define-key projectile-command-map (kbd "e") #'helm-projectile-recentf)
- (define-key projectile-command-map (kbd "b") #'helm-projectile-switch-to-buffer)
- (define-key projectile-command-map (kbd "s g") #'helm-projectile-grep)
- (define-key projectile-command-map (kbd "s a") #'helm-projectile-ack)
- (define-key projectile-command-map (kbd "s s") #'helm-projectile-ag)
- (helm-projectile-commander-bindings))
- (progn
- (setq projectile-switch-project-action #'projectile-find-file)
- (define-key projectile-command-map (kbd "a") #'projectile-find-other-file)
- (define-key projectile-command-map (kbd "f") #'projectile-find-file)
- (define-key projectile-command-map (kbd "F") #'projectile-find-file-in-known-projects)
- (define-key projectile-command-map (kbd "g") #'helm-projectile-find-file-dwim)
- (define-key projectile-command-map (kbd "d") #'projectile-find-dir)
- (define-key projectile-command-map (kbd "p") #'projectile-switch-project)
- (define-key projectile-command-map (kbd "e") #'projectile-recentf)
- (define-key projectile-command-map (kbd "b") #'projectile-switch-to-buffer)
- (define-key projectile-command-map (kbd "s g") #'projectile-grep)
- (define-key projectile-command-map (kbd "s s") #'projectile-ag)
- (projectile-commander-bindings))))
-
-;;;###autoload
-(defun helm-projectile (&optional arg)
- "Use projectile with Helm instead of ido.
-
-With a prefix ARG invalidates the cache first.
-If invoked outside of a project, displays a list of known projects to jump."
- (interactive "P")
- (if (projectile-project-p)
- (projectile-maybe-invalidate-cache arg))
- (let ((helm-ff-transformer-show-only-basename nil))
- (helm :sources helm-projectile-sources-list
- :buffer "*helm projectile*"
- :prompt (projectile-prepend-project-name (if (projectile-project-p)
- "pattern: "
- "Switch to project: ")))))
-
-;;;###autoload
-(eval-after-load 'projectile
- '(progn
- (define-key projectile-command-map (kbd "h") #'helm-projectile)))
-
-(provide 'helm-projectile)
-
-;;; helm-projectile.el ends here
--- /dev/null
+;;; helm-projectile-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+
+(add-to-list 'load-path (directory-file-name
+ (or (file-name-directory #$) (car load-path))))
+
+\f
+;;;### (autoloads nil "helm-projectile" "helm-projectile.el" (0 0
+;;;;;; 0 0))
+;;; Generated autoloads from helm-projectile.el
+
+(defvar helm-projectile-fuzzy-match t "\
+Enable fuzzy matching for Helm Projectile commands.
+This needs to be set before loading helm-projectile.el.")
+
+(custom-autoload 'helm-projectile-fuzzy-match "helm-projectile" t)
+
+(autoload 'helm-projectile-find-file-dwim "helm-projectile" "\
+Find file at point based on context.
+
+\(fn)" t nil)
+
+(autoload 'helm-projectile-find-other-file "helm-projectile" "\
+Switch between files with the same name but different extensions using Helm.
+With FLEX-MATCHING, match any file that contains the base name of current file.
+Other file extensions can be customized with the variable `projectile-other-file-alist'.
+
+\(fn &optional FLEX-MATCHING)" t nil)
+
+(autoload 'helm-projectile-on "helm-projectile" "\
+Turn on `helm-projectile' key bindings.
+
+\(fn)" t nil)
+
+(autoload 'helm-projectile-off "helm-projectile" "\
+Turn off `helm-projectile' key bindings.
+
+\(fn)" t nil)
+
+(autoload 'helm-projectile-grep "helm-projectile" "\
+Helm version of `projectile-grep'.
+DIR is the project root, if not set then current directory is used
+
+\(fn &optional DIR)" t nil)
+
+(autoload 'helm-projectile-ack "helm-projectile" "\
+Helm version of projectile-ack.
+
+\(fn &optional DIR)" t nil)
+
+(autoload 'helm-projectile-ag "helm-projectile" "\
+Helm version of `projectile-ag'.
+
+\(fn &optional OPTIONS)" t nil)
+
+(autoload 'helm-projectile-rg "helm-projectile" "\
+Projectile version of `helm-rg'.
+
+\(fn)" t nil)
+
+(autoload 'helm-projectile-toggle "helm-projectile" "\
+Toggle Helm version of Projectile commands.
+
+\(fn TOGGLE)" nil nil)
+
+(autoload 'helm-projectile "helm-projectile" "\
+Use projectile with Helm instead of ido.
+
+With a prefix ARG invalidates the cache first.
+If invoked outside of a project, displays a list of known projects to jump.
+
+\(fn &optional ARG)" t nil)
+
+(eval-after-load 'projectile '(progn (define-key projectile-command-map (kbd "h") #'helm-projectile)))
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-projectile" '("helm-")))
+
+;;;***
+\f
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; coding: utf-8
+;; End:
+;;; helm-projectile-autoloads.el ends here
--- /dev/null
+;;; -*- no-byte-compile: t -*-
+(define-package "helm-projectile" "20180815.1514" "Helm integration for Projectile" '((helm "1.9.9") (projectile "0.14.0") (cl-lib "0.3")) :commit "8a2dbc973548fac89356c11d70f7f474ea1367a5" :keywords '("project" "convenience") :authors '(("Bozhidar Batsov")) :maintainer '("Bozhidar Batsov") :url "https://github.com/bbatsov/helm-projectile")
--- /dev/null
+;;; helm-projectile.el --- Helm integration for Projectile -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2011-2016 Bozhidar Batsov
+
+;; Author: Bozhidar Batsov
+;; URL: https://github.com/bbatsov/helm-projectile
+;; Package-Version: 20180815.1514
+;; Created: 2011-31-07
+;; Keywords: project, convenience
+;; Version: 0.14.0
+;; Package-Requires: ((helm "1.9.9") (projectile "0.14.0") (cl-lib "0.3"))
+
+;; This file is NOT part of GNU Emacs.
+
+;;; License:
+
+;; 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, 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 GNU Emacs; see the file COPYING. If not, write to the
+;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+;; Boston, MA 02110-1301, USA.
+
+;;; Commentary:
+;;
+;; This library provides easy project management and navigation. The
+;; concept of a project is pretty basic - just a folder containing
+;; special file. Currently git, mercurial and bazaar repos are
+;; considered projects by default. If you want to mark a folder
+;; manually as a project just create an empty .projectile file in
+;; it. See the README for more details.
+;;
+;;; Code:
+
+(require 'subr-x)
+(require 'projectile)
+(require 'cl-lib)
+(require 'grep)
+(require 'helm)
+(require 'helm-types)
+(require 'helm-locate)
+(require 'helm-buffers)
+(require 'helm-files)
+
+(declare-function eshell "eshell")
+(declare-function helm-do-ag "helm-ag")
+(declare-function dired-get-filename "dired")
+(defvar helm-ag-base-command)
+
+(defvar grep-find-ignored-directories)
+(defvar grep-find-ignored-files)
+
+(defgroup helm-projectile nil
+ "Helm support for projectile."
+ :prefix "helm-projectile-"
+ :group 'projectile
+ :group 'helm
+ :link `(url-link :tag "GitHub" "https://github.com/bbatsov/helm-projectile"))
+
+(defvar helm-projectile-current-project-root)
+
+(defcustom helm-projectile-truncate-lines nil
+ "Truncate lines in helm projectile commands when non--nil.
+
+Some `helm-projectile' commands have similar behavior with existing
+Helms. In these cases their respective custom var for truncation
+of lines will be honored. E.g. `helm-buffers-truncate-lines'
+dictates the truncation in `helm-projectile-switch-to-buffer'."
+ :group 'helm-projectile
+ :type 'boolean)
+
+;;;###autoload
+(defcustom helm-projectile-fuzzy-match t
+ "Enable fuzzy matching for Helm Projectile commands.
+This needs to be set before loading helm-projectile.el."
+ :group 'helm-projectile
+ :type 'boolean)
+
+(defmacro helm-projectile-define-key (keymap key def &rest bindings)
+ "In KEYMAP, define KEY - DEF sequence KEY1 as DEF1, KEY2 as DEF2 ..."
+ (declare (indent defun))
+ (let ((ret '(progn)))
+ (while key
+ (push
+ `(define-key ,keymap ,key
+ (lambda ()
+ (interactive)
+ (helm-exit-and-execute-action ,def)))
+ ret)
+ (setq key (pop bindings)
+ def (pop bindings)))
+ (reverse ret)))
+
+(defun helm-projectile-hack-actions (actions &rest prescription)
+ "Given a Helm action list and a prescription, return a hacked Helm action list, after applying the PRESCRIPTION.
+
+The Helm action list ACTIONS is of the form:
+
+\(\(DESCRIPTION1 . FUNCTION1\)
+ \(DESCRIPTION2 . FUNCTION2\)
+ ...
+ \(DESCRIPTIONn . FUNCTIONn\)\)
+
+PRESCRIPTION is in the form:
+
+\(INSTRUCTION1 INSTRUCTION2 ... INSTRUCTIONn\)
+
+If an INSTRUCTION is a symbol, the action with function name
+INSTRUCTION is deleted.
+
+If an INSTRUCTION is of the form \(FUNCTION1 . FUNCTION2\), the
+action with function name FUNCTION1 will change it's function to
+FUNCTION2.
+
+If an INSTRUCTION is of the form \(FUNCTION . DESCRIPTION\), and
+if an action with function name FUNCTION exists in the original
+Helm action list, the action in the Helm action list, with
+function name FUNCTION will change it's description to
+DESCRIPTION. Otherwise, (FUNCTION . DESCRIPTION) will be added to
+the action list.
+
+Please check out how `helm-projectile-file-actions' is defined
+for an example of how this function is being used."
+ (let* ((to-delete (cl-remove-if (lambda (entry) (listp entry)) prescription))
+ (actions (cl-delete-if (lambda (action) (memq (cdr action) to-delete))
+ (copy-alist actions)))
+ new)
+ (cl-dolist (action actions)
+ (when (setq new (cdr (assq (cdr action) prescription)))
+ (if (stringp new)
+ (setcar action new)
+ (setcdr action new))))
+ ;; Add new actions from PRESCRIPTION
+ (setq new nil)
+ (cl-dolist (instruction prescription)
+ (when (and (listp instruction)
+ (null (rassq (car instruction) actions))
+ (symbolp (car instruction)) (stringp (cdr instruction)))
+ (push (cons (cdr instruction) (car instruction)) new)))
+ (append actions (nreverse new))))
+
+(defun helm-projectile-vc (dir)
+ "A Helm action for jumping to project root using `vc-dir' or Magit.
+DIR is a directory to be switched"
+ (let ((projectile-require-project-root nil))
+ (projectile-vc dir)))
+
+(defun helm-projectile-compile-project (dir)
+ "A Helm action for compile a project.
+DIR is the project root."
+ (let ((helm--reading-passwd-or-string t)
+ (default-directory dir))
+ (projectile-compile-project helm-current-prefix-arg)))
+
+(defun helm-projectile-test-project (dir)
+ "A Helm action for test a project.
+DIR is the project root."
+ (let ((helm--reading-passwd-or-string t)
+ (default-directory dir))
+ (projectile-test-project helm-current-prefix-arg)))
+
+(defun helm-projectile-run-project (dir)
+ "A Helm action for run a project.
+DIR is the project root."
+ (let ((helm--reading-passwd-or-string t)
+ (default-directory dir))
+ (projectile-run-project helm-current-prefix-arg)))
+
+(defun helm-projectile-remove-known-project (_ignore)
+ "Remove selected projects from projectile project list.
+_IGNORE means the argument does not matter.
+It is there because Helm requires it."
+ (let* ((projects (helm-marked-candidates :with-wildcard t))
+ (len (length projects)))
+ (with-helm-display-marked-candidates
+ helm-marked-buffer-name
+ projects
+ (if (not (y-or-n-p (format "Remove *%s projects(s)? " len)))
+ (message "(No removal performed)")
+ (progn
+ (mapc (lambda (p)
+ (delete p projectile-known-projects))
+ projects)
+ (projectile-save-known-projects))
+ (message "%s projects(s) removed" len)))))
+
+(defvar helm-projectile-projects-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map helm-map)
+ (helm-projectile-define-key map
+ (kbd "C-d") #'dired
+ (kbd "M-g") #'helm-projectile-vc
+ (kbd "M-e") #'helm-projectile-switch-to-eshell
+ (kbd "C-s") #'helm-projectile-grep
+ (kbd "M-c") #'helm-projectile-compile-project
+ (kbd "M-t") #'helm-projectile-test-project
+ (kbd "M-r") #'helm-projectile-run-project
+ (kbd "M-D") #'helm-projectile-remove-known-project)
+ map)
+ "Mapping for known projectile projects.")
+
+(defcustom helm-source-projectile-projects-actions
+ (helm-make-actions
+ "Switch to project" (lambda (project)
+ (let ((projectile-completion-system 'helm))
+ (projectile-switch-project-by-name project)))
+ "Open Dired in project's directory `C-d'" #'dired
+ "Open project root in vc-dir or magit `M-g'" #'helm-projectile-vc
+ "Switch to Eshell `M-e'" #'helm-projectile-switch-to-eshell
+ "Grep in projects `C-s'" #'helm-projectile-grep
+ "Compile project `M-c'. With C-u, new compile command" #'helm-projectile-compile-project
+ "Remove project(s) from project list `M-D'" #'helm-projectile-remove-known-project)
+ "Actions for `helm-source-projectile-projects'."
+ :group 'helm-projectile
+ :type '(alist :key-type string :value-type function))
+
+(defvar helm-source-projectile-projects
+ (helm-build-sync-source "Projectile projects"
+ :candidates (lambda () (with-helm-current-buffer projectile-known-projects))
+ :fuzzy-match helm-projectile-fuzzy-match
+ :keymap helm-projectile-projects-map
+ :mode-line helm-read-file-name-mode-line-string
+ :action 'helm-source-projectile-projects-actions)
+ "Helm source for known projectile projects.")
+
+(defvar helm-projectile-dirty-projects-map
+ (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map helm-map)
+ (helm-projectile-define-key map
+ (kbd "C-d") #'dired
+ (kbd "M-o") #'(lambda (project)
+ (let ((projectile-completion-system 'helm))
+ (projectile-switch-project-by-name project)))
+ (kbd "M-e") #'helm-projectile-switch-to-eshell
+ (kbd "C-s") #'helm-projectile-grep
+ (kbd "M-c") #'helm-projectile-compile-project
+ (kbd "M-t") #'helm-projectile-test-project
+ (kbd "M-r") #'helm-projectile-run-project
+ (kbd "M-D") #'helm-projectile-remove-known-project)
+ map)
+ "Mapping for dirty projectile projects.")
+
+(defvar helm-source-projectile-dirty-projects
+ (helm-build-sync-source "Projectile dirty projects"
+ :candidates (lambda () (with-helm-current-buffer (helm-projectile-get-dirty-projects)))
+ :fuzzy-match helm-projectile-fuzzy-match
+ :keymap helm-projectile-dirty-projects-map
+ :mode-line helm-read-file-name-mode-line-string
+ :action '(("Open project root in vc-dir or magit" . helm-projectile-vc)
+ ("Switch to project `M-o'" .
+ (lambda (project)
+ (let ((projectile-completion-system 'helm))
+ (projectile-switch-project-by-name project))))
+ ("Open Dired in project's directory `C-d'" . dired)
+ ("Switch to Eshell `M-e'" . helm-projectile-switch-to-eshell)
+ ("Grep in projects `C-s'" . helm-projectile-grep)
+ ("Compile project `M-c'. With C-u, new compile command"
+ . helm-projectile-compile-project)))
+ "Helm source for dirty version controlled projectile projects.")
+
+(defun helm-projectile-get-dirty-projects ()
+ "Return dirty version controlled known projects as an alist to
+have a nice display in Helm."
+ (message "Checking for dirty known projects...")
+ (let* ((status (projectile-check-vcs-status-of-known-projects))
+ (proj-dir (cl-loop for stat in status
+ collect (car stat)))
+ (status-display (cl-loop for stat in status collect
+ (propertize (format "[%s]" (mapconcat 'identity (car (cdr stat)) ", ")) 'face 'helm-match)))
+ (max-status-display-length (cl-loop for sd in status-display
+ maximize (length sd)))
+ (status-display (cl-loop for sd in status-display collect
+ (format "%s%s " sd (make-string (- max-status-display-length (length sd)) ? ))))
+ (full-display (cl-mapcar 'concat status-display proj-dir))
+ (helm-list (cl-pairlis full-display proj-dir)))
+ helm-list))
+
+(define-key helm-etags-map (kbd "C-c p f")
+ (lambda ()
+ (interactive)
+ (helm-run-after-exit 'helm-projectile-find-file nil)))
+
+(defun helm-projectile-file-persistent-action (candidate)
+ "Persistent action for file-related functionality.
+
+Previews the contents of a file in a temporary buffer."
+ (let ((buf (get-buffer-create " *helm-projectile persistent*")))
+ (cl-flet ((preview (candidate)
+ (switch-to-buffer buf)
+ (setq inhibit-read-only t)
+ (erase-buffer)
+ (insert-file-contents candidate)
+ (let ((buffer-file-name candidate))
+ (set-auto-mode))
+ (font-lock-ensure)
+ (setq inhibit-read-only nil)))
+ (if (and (helm-attr 'previewp)
+ (string= candidate (helm-attr 'current-candidate)))
+ (progn
+ (kill-buffer buf)
+ (helm-attrset 'previewp nil))
+ (preview candidate)
+ (helm-attrset 'previewp t)))
+ (helm-attrset 'current-candidate candidate)))
+
+(defun helm-projectile-find-files-eshell-command-on-file-action (candidate)
+ (interactive)
+ (let* ((helm-ff-default-directory (file-name-directory candidate)))
+ (helm-find-files-eshell-command-on-file candidate)))
+
+(defun helm-projectile-ff-etags-select-action (candidate)
+ (interactive)
+ (let* ((helm-ff-default-directory (file-name-directory candidate)))
+ (helm-ff-etags-select candidate)))
+
+(defun helm-projectile-switch-to-eshell (dir)
+ (interactive)
+ (let* ((projectile-require-project-root nil)
+ (helm-ff-default-directory (file-name-directory (projectile-expand-root dir))))
+ (helm-ff-switch-to-eshell dir)))
+
+(defun helm-projectile-files-in-current-dired-buffer ()
+ "Return a list of files (only) in the current dired buffer."
+ (let (flist)
+ (cl-flet ((fpush (fname) (push fname flist)))
+ (save-excursion
+ (let (file buffer-read-only)
+ (goto-char (point-min))
+ (while (not (eobp))
+ (save-excursion
+ (and (not (eolp))
+ (setq file (dired-get-filename t t)) ; nil on non-file
+ (progn (end-of-line)
+ (funcall #'fpush file))))
+ (forward-line 1)))))
+ (mapcar 'file-truename (nreverse flist))))
+
+(defun helm-projectile-all-dired-buffers ()
+ "Get all current Dired buffers."
+ (mapcar (lambda (b)
+ (with-current-buffer b (buffer-name)))
+ (cl-remove-if-not
+ (lambda (b)
+ (with-current-buffer b
+ (and (eq major-mode 'dired-mode)
+ (buffer-name))))
+ (buffer-list))))
+
+(defvar helm-projectile-virtual-dired-remote-enable nil
+ "Enable virtual Dired manager on remote host.
+Disabled by default.")
+
+(defun helm-projectile-dired-files-new-action (candidate)
+ "Create a Dired buffer from chosen files.
+CANDIDATE is the selected file, but choose the marked files if available."
+ (if (and (file-remote-p (projectile-project-root))
+ (not helm-projectile-virtual-dired-remote-enable))
+ (message "Virtual Dired manager is disabled in remote host. Enable with %s."
+ (propertize "helm-projectile-virtual-dired-remote-enable" 'face 'font-lock-keyword-face))
+ (let ((files (cl-remove-if-not
+ (lambda (f)
+ (not (string= f "")))
+ (mapcar (lambda (file)
+ (replace-regexp-in-string (projectile-project-root) "" file))
+ (helm-marked-candidates :with-wildcard t))))
+ (new-name (completing-read "Select or enter a new buffer name: "
+ (helm-projectile-all-dired-buffers)))
+ (helm--reading-passwd-or-string t)
+ (default-directory (projectile-project-root)))
+ ;; create a unique buffer that is unique to any directory in default-directory
+ ;; or opened buffer; when Dired is passed with a non-existence directory name,
+ ;; it only creates a buffer and insert everything. If a new name user supplied
+ ;; exists as default-directory, Dired throws error when insert anything that
+ ;; does not exist in current directory.
+ (with-current-buffer (dired (cons (make-temp-name new-name)
+ (if files
+ files
+ (list candidate))))
+ (when (get-buffer new-name)
+ (kill-buffer new-name))
+ (rename-buffer new-name)))))
+
+(defun helm-projectile-dired-files-add-action (candidate)
+ "Add files to a Dired buffer.
+CANDIDATE is the selected file. Used when no file is explicitly marked."
+ (if (and (file-remote-p (projectile-project-root))
+ (not helm-projectile-virtual-dired-remote-enable))
+ (message "Virtual Dired manager is disabled in remote host. Enable with %s."
+ (propertize "helm-projectile-virtual-dired-remote-enable" 'face 'font-lock-keyword-face))
+ (if (eq (with-helm-current-buffer major-mode) 'dired-mode)
+ (let* ((marked-files (helm-marked-candidates :with-wildcard t))
+ (helm--reading-passwd-or-string t)
+ (root (projectile-project-root)) ; store root for later use
+ (dired-buffer-name (or (and (eq major-mode 'dired-mode) (buffer-name))
+ (completing-read "Select a Dired buffer:"
+ (helm-projectile-all-dired-buffers))))
+ (dired-files (with-current-buffer dired-buffer-name
+ (helm-projectile-files-in-current-dired-buffer)))
+ (files (sort (mapcar (lambda (file)
+ (replace-regexp-in-string (projectile-project-root) "" file))
+ (cl-nunion (if marked-files
+ marked-files
+ (list candidate))
+ dired-files
+ :test #'string-equal))
+ 'string-lessp)))
+ (kill-buffer dired-buffer-name)
+ ;; Rebind default-directory because after killing a buffer, we
+ ;; could be in any buffer and default-directory is set to that
+ ;; random buffer
+ ;;
+ ;; Also use saved root directory, because after killing a buffer,
+ ;; we could be outside of current project
+ (let ((default-directory root))
+ (with-current-buffer (dired (cons (make-temp-name dired-buffer-name)
+ (if files
+ (mapcar (lambda (file)
+ (replace-regexp-in-string root "" file))
+ files)
+ (list candidate))))
+ (rename-buffer dired-buffer-name))))
+ (error "You're not in a Dired buffer to add"))))
+
+(defun helm-projectile-dired-files-delete-action (candidate)
+ "Delete selected entries from a Dired buffer.
+CANDIDATE is the selected file. Used when no file is explicitly marked."
+ (if (and (file-remote-p (projectile-project-root))
+ (not helm-projectile-virtual-dired-remote-enable))
+ (message "Virtual Dired manager is disabled in remote host. Enable with %s."
+ (propertize "helm-projectile-virtual-dired-remote-enable" 'face 'font-lock-keyword-face))
+ (let* ((helm--reading-passwd-or-string t)
+ (root (projectile-project-root))
+ (dired-buffer-name (with-helm-current-buffer (buffer-name)))
+ (dired-files (with-current-buffer dired-buffer-name
+ (helm-projectile-files-in-current-dired-buffer)))
+ (files (sort (cl-set-exclusive-or (helm-marked-candidates :with-wildcard t)
+ dired-files
+ :test #'string-equal) #'string-lessp)))
+ (kill-buffer dired-buffer-name)
+ ;; similar reason to `helm-projectile-dired-files-add-action'
+ (let ((default-directory root))
+ (with-current-buffer (dired (cons (make-temp-name dired-buffer-name)
+ (if files
+ (mapcar (lambda (file)
+ (replace-regexp-in-string root "" file))
+ files)
+ (list candidate))))
+ (rename-buffer dired-buffer-name))))))
+
+(defun helm-projectile-run-projectile-hooks-after-find-file (_orig-fun &rest _args)
+ "Run `projectile-find-file-hook' if using projectile."
+ (when (and projectile-mode (projectile-project-p))
+ (run-hooks 'projectile-find-file-hook)))
+
+(advice-add 'helm-find-file-or-marked
+ :after #'helm-projectile-run-projectile-hooks-after-find-file)
+
+(defvar helm-projectile-find-file-map
+ (let ((map (copy-keymap helm-find-files-map)))
+ (helm-projectile-define-key map
+ (kbd "C-c f") #'helm-projectile-dired-files-new-action
+ (kbd "C-c a") #'helm-projectile-dired-files-add-action
+ (kbd "M-e") #'helm-projectile-switch-to-eshell
+ (kbd "M-.") #'helm-projectile-ff-etags-select-action
+ (kbd "M-!") #'helm-projectile-find-files-eshell-command-on-file-action)
+ (define-key map (kbd "<left>") #'helm-previous-source)
+ (define-key map (kbd "<right>") #'helm-next-source)
+ (dolist (cmd '(helm-find-files-up-one-level
+ helm-find-files-down-last-level))
+ (substitute-key-definition cmd nil map))
+ map)
+ "Mapping for file commands in Helm Projectile.")
+
+(defvar helm-projectile-file-actions
+ (helm-projectile-hack-actions
+ helm-find-files-actions
+ ;; Delete these actions
+ 'helm-ff-browse-project
+ 'helm-insert-file-name-completion-at-point
+ 'helm-ff-find-sh-command
+ 'helm-ff-cache-add-file
+ ;; Substitute these actions
+ '(helm-ff-switch-to-eshell . helm-projectile-switch-to-eshell)
+ '(helm-ff-etags-select . helm-projectile-ff-etags-select-action)
+ '(helm-find-files-eshell-command-on-file
+ . helm-projectile-find-files-eshell-command-on-file-action)
+ ;; Change action descriptions
+ '(helm-find-file-as-root . "Find file as root `C-c r'")
+ ;; New actions
+ '(helm-projectile-dired-files-new-action
+ . "Create Dired buffer from files `C-c f'")
+ '(helm-projectile-dired-files-add-action
+ . "Add files to Dired buffer `C-c a'"))
+ "Action for files.")
+
+(defun helm-projectile--move-selection-p (selection)
+ "Return non-nil if should move Helm selector after SELECTION.
+
+SELECTION should be moved unless it's one of:
+
+- Non-string
+- Existing file
+- Non-remote file that matches `helm-tramp-file-name-regexp'"
+ (not (or (not (stringp selection))
+ (file-exists-p selection)
+ (and (string-match helm-tramp-file-name-regexp selection)
+ (not (file-remote-p selection nil t))))))
+
+(defun helm-projectile--move-to-real ()
+ "Move to first real candidate.
+
+Similar to `helm-ff--move-to-first-real-candidate', but without
+unnecessary complexity."
+ (while (let* ((src (helm-get-current-source))
+ (selection (and (not (helm-empty-source-p))
+ (helm-get-selection nil nil src))))
+ (and (not (helm-end-of-source-p))
+ (helm-projectile--move-selection-p selection)))
+ (helm-next-line)))
+
+(defun helm-projectile--remove-move-to-real ()
+ "Hook function to remove `helm-projectile--move-to-real'.
+
+Meant to be added to `helm-cleanup-hook', from which it removes
+ itself at the end."
+ (remove-hook 'helm-after-update-hook #'helm-projectile--move-to-real)
+ (remove-hook 'helm-cleanup-hook #'helm-projectile--remove-move-to-real))
+
+(defvar helm-source-projectile-files-list
+ (helm-build-sync-source "Projectile files"
+ :before-init-hook (lambda ()
+ (add-hook 'helm-after-update-hook #'helm-projectile--move-to-real)
+ (add-hook 'helm-cleanup-hook #'helm-projectile--remove-move-to-real))
+ :candidates (lambda ()
+ (when (projectile-project-p)
+ (with-helm-current-buffer
+ (cl-loop with root = (projectile-project-root)
+ for display in (projectile-current-project-files)
+ collect (cons display (expand-file-name display root))))))
+ :filtered-candidate-transformer
+ (lambda (files _source)
+ (with-helm-current-buffer
+ (let* ((root (projectile-project-root))
+ (file-at-root (file-relative-name (expand-file-name helm-pattern root))))
+ (if (or (string-empty-p helm-pattern)
+ (assoc helm-pattern files))
+ files
+ (if (equal helm-pattern file-at-root)
+ (cl-acons (helm-ff-prefix-filename helm-pattern nil t)
+ (expand-file-name helm-pattern)
+ files)
+ (cl-pairlis (list (helm-ff-prefix-filename helm-pattern nil t)
+ (helm-ff-prefix-filename file-at-root nil t))
+ (list (expand-file-name helm-pattern)
+ (expand-file-name helm-pattern root))
+ files))))))
+ :fuzzy-match helm-projectile-fuzzy-match
+ :keymap helm-projectile-find-file-map
+ :help-message 'helm-ff-help-message
+ :mode-line helm-read-file-name-mode-line-string
+ :action helm-projectile-file-actions
+ :persistent-action #'helm-projectile-file-persistent-action
+ :persistent-help "Preview file")
+ "Helm source definition for Projectile files.")
+
+(defvar helm-source-projectile-files-in-all-projects-list
+ (helm-build-sync-source "Projectile files in all Projects"
+ :candidates (lambda ()
+ (with-helm-current-buffer
+ (let ((projectile-require-project-root nil))
+ (projectile-all-project-files))))
+ :keymap helm-projectile-find-file-map
+ :help-message 'helm-ff-help-message
+ :mode-line helm-read-file-name-mode-line-string
+ :action helm-projectile-file-actions
+ :persistent-action #'helm-projectile-file-persistent-action
+ :persistent-help "Preview file")
+ "Helm source definition for all Projectile files in all projects.")
+
+(defvar helm-projectile-dired-file-actions
+ (helm-projectile-hack-actions
+ helm-projectile-file-actions
+ ;; New actions
+ '(helm-projectile-dired-files-delete-action . "Remove entry(s) from Dired buffer `C-c d'")))
+
+(defvar helm-source-projectile-dired-files-list
+ (helm-build-in-buffer-source "Projectile files in current Dired buffer"
+ :data (lambda ()
+ (if (and (file-remote-p (projectile-project-root))
+ (not helm-projectile-virtual-dired-remote-enable))
+ nil
+ (when (eq major-mode 'dired-mode)
+ (helm-projectile-files-in-current-dired-buffer))))
+ :filter-one-by-one (lambda (file)
+ (let ((helm-ff-transformer-show-only-basename t))
+ (helm-ff-filter-candidate-one-by-one file)))
+ :action-transformer 'helm-find-files-action-transformer
+ :keymap (let ((map (copy-keymap helm-projectile-find-file-map)))
+ (helm-projectile-define-key map
+ (kbd "C-c d") 'helm-projectile-dired-files-delete-action)
+ map)
+ :help-message 'helm-ff-help-message
+ :mode-line helm-read-file-name-mode-line-string
+ :action helm-projectile-dired-file-actions)
+ "Helm source definition for Projectile delete files.")
+
+(defun helm-projectile-dired-find-dir (dir)
+ "Jump to a selected directory DIR from `helm-projectile'."
+ (dired (expand-file-name dir (projectile-project-root)))
+ (run-hooks 'projectile-find-dir-hook))
+
+(defun helm-projectile-dired-find-dir-other-window (dir)
+ "Jump to a selected directory DIR from `helm-projectile'."
+ (dired-other-window (expand-file-name dir (projectile-project-root)))
+ (run-hooks 'projectile-find-dir-hook))
+
+(defvar helm-source-projectile-directories-list
+ (helm-build-sync-source "Projectile directories"
+ :candidates (lambda ()
+ (when (projectile-project-p)
+ (with-helm-current-buffer
+ (let ((dirs (if projectile-find-dir-includes-top-level
+ (append '("./") (projectile-current-project-dirs))
+ (projectile-current-project-dirs))))
+ (helm-projectile--files-display-real dirs (projectile-project-root))))))
+ :fuzzy-match helm-projectile-fuzzy-match
+ :action-transformer 'helm-find-files-action-transformer
+ :keymap (let ((map (make-sparse-keymap)))
+ (set-keymap-parent map helm-map)
+ (helm-projectile-define-key map
+ (kbd "<left>") #'helm-previous-source
+ (kbd "<right>") #'helm-next-source
+ (kbd "C-c o") #'helm-projectile-dired-find-dir-other-window
+ (kbd "M-e") #'helm-projectile-switch-to-eshell
+ (kbd "C-c f") #'helm-projectile-dired-files-new-action
+ (kbd "C-c a") #'helm-projectile-dired-files-add-action
+ (kbd "C-s") #'helm-projectile-grep)
+ map)
+ :help-message 'helm-ff-help-message
+ :mode-line helm-read-file-name-mode-line-string
+ :action '(("Open Dired" . helm-projectile-dired-find-dir)
+ ("Open Dired in other window `C-c o'" . helm-projectile-dired-find-dir)
+ ("Switch to Eshell `M-e'" . helm-projectile-switch-to-eshell)
+ ("Grep in projects `C-s'" . helm-projectile-grep)
+ ("Create Dired buffer from files `C-c f'" . helm-projectile-dired-files-new-action)
+ ("Add files to Dired buffer `C-c a'" . helm-projectile-dired-files-add-action)))
+ "Helm source for listing project directories.")
+
+(defvar helm-projectile-buffers-list-cache nil)
+
+(defclass helm-source-projectile-buffer (helm-source-sync helm-type-buffer)
+ ((init :initform (lambda ()
+ ;; Issue #51 Create the list before `helm-buffer' creation.
+ (setq helm-projectile-buffers-list-cache
+ (ignore-errors (cdr (projectile-project-buffer-names))))
+ (let ((result (cl-loop for b in helm-projectile-buffers-list-cache
+ maximize (length b) into len-buf
+ maximize (length (with-current-buffer b
+ (symbol-name major-mode)))
+ into len-mode
+ finally return (cons len-buf len-mode))))
+ (unless helm-buffer-max-length
+ (setq helm-buffer-max-length (car result)))
+ (unless helm-buffer-max-len-mode
+ ;; If a new buffer is longer that this value
+ ;; this value will be updated
+ (setq helm-buffer-max-len-mode (cdr result))))))
+ (candidates :initform helm-projectile-buffers-list-cache)
+ (matchplugin :initform nil)
+ (match :initform 'helm-buffers-match-function)
+ (persistent-action :initform 'helm-buffers-list-persistent-action)
+ (keymap :initform helm-buffer-map)
+ (volatile :initform t)
+ (persistent-help
+ :initform
+ "Show this buffer / C-u \\[helm-execute-persistent-action]: Kill this buffer")))
+
+(defvar helm-source-projectile-buffers-list (helm-make-source "Project buffers" 'helm-source-projectile-buffer))
+
+(defvar helm-source-projectile-recentf-list
+ (helm-build-sync-source "Projectile recent files"
+ :candidates (lambda ()
+ (when (projectile-project-p)
+ (with-helm-current-buffer
+ (helm-projectile--files-display-real (projectile-recentf-files)
+ (projectile-project-root)))))
+ :fuzzy-match helm-projectile-fuzzy-match
+ :keymap helm-projectile-find-file-map
+ :help-message 'helm-ff-help-message
+ :mode-line helm-read-file-name-mode-line-string
+ :action helm-projectile-file-actions
+ :persistent-action #'helm-projectile-file-persistent-action
+ :persistent-help "Preview file")
+ "Helm source definition for recent files in current project.")
+
+(defvar helm-source-projectile-files-and-dired-list
+ '(helm-source-projectile-dired-files-list
+ helm-source-projectile-files-list))
+
+(defvar helm-source-projectile-directories-and-dired-list
+ '(helm-source-projectile-dired-files-list
+ helm-source-projectile-directories-list))
+
+(defcustom helm-projectile-sources-list
+ '(helm-source-projectile-buffers-list
+ helm-source-projectile-files-list
+ helm-source-projectile-projects)
+ "Default sources for `helm-projectile'."
+ :type 'list
+ :group 'helm-projectile)
+
+(defmacro helm-projectile-command (command source prompt &optional not-require-root truncate-lines-var)
+ "Template for generic `helm-projectile' commands.
+COMMAND is a command name to be appended with \"helm-projectile\" prefix.
+SOURCE is a Helm source that should be Projectile specific.
+PROMPT is a string for displaying as a prompt.
+NOT-REQUIRE-ROOT specifies the command doesn't need to be used in a
+project root.
+TRUNCATE-LINES-VAR is the symbol used dictate truncation of lines.
+Defaults is `helm-projectile-truncate-lines'."
+ (unless truncate-lines-var (setq truncate-lines-var 'helm-projectile-truncate-lines))
+ `(defun ,(intern (concat "helm-projectile-" command)) (&optional arg)
+ "Use projectile with Helm for finding files in project
+
+With a prefix ARG invalidates the cache first."
+ (interactive "P")
+ (if (projectile-project-p)
+ (projectile-maybe-invalidate-cache arg)
+ (unless ,not-require-root
+ (error "You're not in a project")))
+ (let ((helm-ff-transformer-show-only-basename nil)
+ ;; for consistency, we should just let Projectile take care of ignored files
+ (helm-boring-file-regexp-list nil))
+ (helm :sources ,source
+ :buffer (concat "*helm projectile: " (projectile-project-name) "*")
+ :truncate-lines ,truncate-lines-var
+ :prompt (projectile-prepend-project-name ,prompt)))))
+
+(helm-projectile-command "switch-project" 'helm-source-projectile-projects "Switch to project: " t)
+(helm-projectile-command "find-file" helm-source-projectile-files-and-dired-list "Find file: ")
+(helm-projectile-command "find-file-in-known-projects" 'helm-source-projectile-files-in-all-projects-list "Find file in projects: " t)
+(helm-projectile-command "find-dir" helm-source-projectile-directories-and-dired-list "Find dir: ")
+(helm-projectile-command "recentf" 'helm-source-projectile-recentf-list "Recently visited file: ")
+(helm-projectile-command "switch-to-buffer" 'helm-source-projectile-buffers-list "Switch to buffer: " nil helm-buffers-truncate-lines)
+(helm-projectile-command "browse-dirty-projects" 'helm-source-projectile-dirty-projects "Select a project: " t)
+
+(defun helm-projectile--files-display-real (files root)
+ "Create (DISPLAY . REAL) pairs with FILES and ROOT.
+
+ DISPLAY is the short file name. REAL is the full path."
+ (cl-loop for display in files
+ collect (cons display (expand-file-name display root))))
+
+;;;###autoload
+(defun helm-projectile-find-file-dwim ()
+ "Find file at point based on context."
+ (interactive)
+ (let* ((project-root (projectile-project-root))
+ (project-files (projectile-current-project-files))
+ (files (projectile-select-files project-files)))
+ (if (= (length files) 1)
+ (find-file (expand-file-name (car files) (projectile-project-root)))
+ (helm :sources (helm-build-sync-source "Projectile files"
+ :candidates (if (> (length files) 1)
+ (helm-projectile--files-display-real files project-root)
+ (helm-projectile--files-display-real project-files project-root))
+ :fuzzy-match helm-projectile-fuzzy-match
+ :action-transformer 'helm-find-files-action-transformer
+ :keymap helm-projectile-find-file-map
+ :help-message helm-ff-help-message
+ :mode-line helm-read-file-name-mode-line-string
+ :action helm-projectile-file-actions
+ :persistent-action #'helm-projectile-file-persistent-action
+ :persistent-help "Preview file")
+ :buffer "*helm projectile*"
+ :truncate-lines helm-projectile-truncate-lines
+ :prompt (projectile-prepend-project-name "Find file: ")))))
+
+;;;###autoload
+(defun helm-projectile-find-other-file (&optional flex-matching)
+ "Switch between files with the same name but different extensions using Helm.
+With FLEX-MATCHING, match any file that contains the base name of current file.
+Other file extensions can be customized with the variable `projectile-other-file-alist'."
+ (interactive "P")
+ (let* ((project-root (projectile-project-root))
+ (other-files (projectile-get-other-files (buffer-file-name)
+ (projectile-current-project-files)
+ flex-matching)))
+ (if other-files
+ (if (= (length other-files) 1)
+ (find-file (expand-file-name (car other-files) project-root))
+ (progn
+ (let* ((helm-ff-transformer-show-only-basename nil))
+ (helm :sources (helm-build-sync-source "Projectile other files"
+ :candidates (helm-projectile--files-display-real other-files project-root)
+ :keymap helm-projectile-find-file-map
+ :help-message helm-ff-help-message
+ :mode-line helm-read-file-name-mode-line-string
+ :action helm-projectile-file-actions
+ :persistent-action #'helm-projectile-file-persistent-action
+ :persistent-help "Preview file")
+ :buffer "*helm projectile*"
+ :truncate-lines helm-projectile-truncate-lines
+ :prompt (projectile-prepend-project-name "Find other file: ")))))
+ (error "No other file found"))))
+
+(defcustom helm-projectile-grep-or-ack-actions
+ '("Find file" helm-grep-action
+ "Find file other frame" helm-grep-other-frame
+ (lambda () (and (locate-library "elscreen")
+ "Find file in Elscreen"))
+ helm-grep-jump-elscreen
+ "Save results in grep buffer" helm-grep-save-results
+ "Find file other window" helm-grep-other-window)
+ "Available actions for `helm-projectile-grep-or-ack'.
+The contents of this list are passed as the arguments to `helm-make-actions'."
+ :type 'symbol
+ :group 'helm-projectile)
+
+(defcustom helm-projectile-set-input-automatically t
+ "If non-nil, attempt to set search input automatically.
+Automatic input selection uses the region (if there is an active
+region), otherwise it uses the current symbol at point (if there
+is one). Applies to `helm-projectile-grep' and
+`helm-projectile-ack' only. If the `helm-ag' package is
+installed, then automatic input behavior for `helm-projectile-ag'
+can be customized using `helm-ag-insert-at-point'."
+ :group 'helm-projectile
+ :type 'boolean)
+
+(defun helm-projectile-grep-or-ack (&optional dir use-ack-p ack-ignored-pattern ack-executable)
+ "Perform helm-grep at project root.
+DIR directory where to search
+USE-ACK-P indicates whether to use ack or not.
+ACK-IGNORED-PATTERN is a file regex to exclude from searching.
+ACK-EXECUTABLE is the actual ack binary name.
+It is usually \"ack\" or \"ack-grep\".
+If it is nil, or ack/ack-grep not found then use default grep command."
+ (let* ((default-directory (or dir (projectile-project-root)))
+ (helm-ff-default-directory default-directory)
+ (helm-grep-in-recurse t)
+ (helm-grep-ignored-files (cl-union (projectile-ignored-files-rel) grep-find-ignored-files))
+ (helm-grep-ignored-directories
+ (cl-union (mapcar 'directory-file-name (projectile-ignored-directories-rel))
+ grep-find-ignored-directories))
+ (helm-grep-default-command (if use-ack-p
+ (concat ack-executable " -H --no-group --no-color " ack-ignored-pattern " %p %f")
+ (if (and projectile-use-git-grep (eq (projectile-project-vcs) 'git))
+ "git --no-pager grep --no-color -n%c -e %p -- %f"
+ "grep -a -r %e -n%cH -e %p %f .")))
+ (helm-grep-default-recurse-command helm-grep-default-command))
+
+ (setq helm-source-grep
+ (helm-build-async-source
+ (capitalize (helm-grep-command t))
+ :header-name (lambda (_name)
+ (let ((name (if use-ack-p
+ "Helm Projectile Ack"
+ "Helm Projectile Grep")))
+ (concat name " " "(C-c ? Help)")))
+ :candidates-process 'helm-grep-collect-candidates
+ :filter-one-by-one 'helm-grep-filter-one-by-one
+ :candidate-number-limit 9999
+ :nohighlight t
+ ;; We need to specify keymap here and as :keymap arg [1]
+ ;; to make it available in further resuming.
+ :keymap helm-grep-map
+ :history 'helm-grep-history
+ :action (apply #'helm-make-actions helm-projectile-grep-or-ack-actions)
+ :persistent-action 'helm-grep-persistent-action
+ :persistent-help "Jump to line (`C-u' Record in mark ring)"
+ :requires-pattern 2))
+ (helm
+ :sources 'helm-source-grep
+ :input (when helm-projectile-set-input-automatically
+ (if (region-active-p)
+ (buffer-substring-no-properties (region-beginning) (region-end))
+ (thing-at-point 'symbol)))
+ :buffer (format "*helm %s*" (if use-ack-p
+ "ack"
+ "grep"))
+ :default-directory default-directory
+ :keymap helm-grep-map
+ :history 'helm-grep-history
+ :truncate-lines helm-grep-truncate-lines)))
+
+;;;###autoload
+(defun helm-projectile-on ()
+ "Turn on `helm-projectile' key bindings."
+ (interactive)
+ (message "Turn on helm-projectile key bindings")
+ (helm-projectile-toggle 1))
+
+;;;###autoload
+(defun helm-projectile-off ()
+ "Turn off `helm-projectile' key bindings."
+ (interactive)
+ (message "Turn off helm-projectile key bindings")
+ (helm-projectile-toggle -1))
+
+;;;###autoload
+(defun helm-projectile-grep (&optional dir)
+ "Helm version of `projectile-grep'.
+DIR is the project root, if not set then current directory is used"
+ (interactive)
+ (let ((project-root (or dir (projectile-project-root) (error "You're not in a project"))))
+ (funcall 'run-with-timer 0.01 nil
+ #'helm-projectile-grep-or-ack project-root nil)))
+
+;;;###autoload
+(defun helm-projectile-ack (&optional dir)
+ "Helm version of projectile-ack."
+ (interactive)
+ (let ((project-root (or dir (projectile-project-root) (error "You're not in a project"))))
+ (let ((ack-ignored (mapconcat
+ 'identity
+ (cl-union (mapcar (lambda (path)
+ (concat "--ignore-dir=" (file-name-nondirectory (directory-file-name path))))
+ (projectile-ignored-directories))
+ (mapcar (lambda (path)
+ (concat "--ignore-file=match:" (shell-quote-argument path)))
+ (append (projectile-ignored-files) (projectile-patterns-to-ignore)))) " "))
+ (helm-ack-grep-executable (cond
+ ((executable-find "ack") "ack")
+ ((executable-find "ack-grep") "ack-grep")
+ (t (error "ack or ack-grep is not available")))))
+ (funcall 'run-with-timer 0.01 nil
+ #'helm-projectile-grep-or-ack project-root t ack-ignored helm-ack-grep-executable))))
+
+;;;###autoload
+(defun helm-projectile-ag (&optional options)
+ "Helm version of `projectile-ag'."
+ (interactive (if current-prefix-arg (list (helm-read-string "option: " "" 'helm-ag--extra-options-history))))
+ (if (require 'helm-ag nil t)
+ (if (projectile-project-p)
+ (let* ((grep-find-ignored-files (cl-union (projectile-ignored-files-rel) grep-find-ignored-files))
+ (grep-find-ignored-directories (cl-union (projectile-ignored-directories-rel) grep-find-ignored-directories))
+ (ignored (mapconcat (lambda (i)
+ (concat "--ignore " i))
+ (append grep-find-ignored-files grep-find-ignored-directories (cadr (projectile-parse-dirconfig-file)))
+ " "))
+ (helm-ag-base-command (concat helm-ag-base-command " " ignored " " options))
+ (current-prefix-arg nil))
+ (helm-do-ag (projectile-project-root) (car (projectile-parse-dirconfig-file))))
+ (error "You're not in a project"))
+ (when (yes-or-no-p "`helm-ag' is not installed. Install? ")
+ (condition-case nil
+ (progn
+ (package-install 'helm-ag)
+ (helm-projectile-ag options))
+ (error (error "`helm-ag' is not available. Is MELPA in your `package-archives'?"))))))
+
+;; Declare/define these to satisfy the byte compiler
+(defvar helm-rg-prepend-file-name-line-at-top-of-matches)
+(defvar helm-rg-include-file-on-every-match-line)
+(declare-function helm-rg "helm-rg")
+
+(defun helm-projectile-rg--region-selection ()
+ (when (use-region-p)
+ (buffer-substring-no-properties (region-beginning) (region-end))))
+
+;;;###autoload
+(defun helm-projectile-rg ()
+ "Projectile version of `helm-rg'."
+ (interactive)
+ (if (require 'helm-rg nil t)
+ (if (projectile-project-p)
+ (let ((helm-rg-prepend-file-name-line-at-top-of-matches nil)
+ (helm-rg-include-file-on-every-match-line t))
+ (helm-rg (or (helm-projectile-rg--region-selection) "") nil (list (projectile-project-root))))
+ (error "You're not in a project"))
+ (when (yes-or-no-p "`helm-rg' is not installed. Install? ")
+ (condition-case nil
+ (progn
+ (package-install 'helm-rg)
+ (helm-projectile-rg))
+ (error "`helm-rg' is not available. Is MELPA in your `package-archives'?")))))
+
+(defun helm-projectile-commander-bindings ()
+ (def-projectile-commander-method ?a
+ "Run ack on project."
+ (call-interactively 'helm-projectile-ack))
+
+ (def-projectile-commander-method ?A
+ "Find ag on project."
+ (call-interactively 'helm-projectile-ag))
+
+ (def-projectile-commander-method ?f
+ "Find file in project."
+ (helm-projectile-find-file))
+
+ (def-projectile-commander-method ?b
+ "Switch to project buffer."
+ (helm-projectile-switch-to-buffer))
+
+ (def-projectile-commander-method ?d
+ "Find directory in project."
+ (helm-projectile-find-dir))
+
+ (def-projectile-commander-method ?g
+ "Run grep on project."
+ (helm-projectile-grep))
+
+ (def-projectile-commander-method ?s
+ "Switch project."
+ (helm-projectile-switch-project))
+
+ (def-projectile-commander-method ?e
+ "Find recently visited file in project."
+ (helm-projectile-recentf))
+
+ (def-projectile-commander-method ?V
+ "Find dirty projects."
+ (helm-projectile-browse-dirty-projects)))
+
+;;;###autoload
+(defun helm-projectile-toggle (toggle)
+ "Toggle Helm version of Projectile commands."
+ (if (> toggle 0)
+ (progn
+ (when (eq projectile-switch-project-action #'projectile-find-file)
+ (setq projectile-switch-project-action #'helm-projectile-find-file))
+ (define-key projectile-mode-map [remap projectile-find-other-file] #'helm-projectile-find-other-file)
+ (define-key projectile-mode-map [remap projectile-find-file] #'helm-projectile-find-file)
+ (define-key projectile-mode-map [remap projectile-find-file-in-known-projects] #'helm-projectile-find-file-in-known-projects)
+ (define-key projectile-mode-map [remap projectile-find-file-dwim] #'helm-projectile-find-file-dwim)
+ (define-key projectile-mode-map [remap projectile-find-dir] #'helm-projectile-find-dir)
+ (define-key projectile-mode-map [remap projectile-switch-project] #'helm-projectile-switch-project)
+ (define-key projectile-mode-map [remap projectile-recentf] #'helm-projectile-recentf)
+ (define-key projectile-mode-map [remap projectile-switch-to-buffer] #'helm-projectile-switch-to-buffer)
+ (define-key projectile-mode-map [remap projectile-grep] #'helm-projectile-grep)
+ (define-key projectile-mode-map [remap projectile-ack] #'helm-projectile-ack)
+ (define-key projectile-mode-map [remap projectile-ag] #'helm-projectile-ag)
+ (define-key projectile-mode-map [remap projectile-ripgrep] #'helm-projectile-rg)
+ (define-key projectile-mode-map [remap projectile-browse-dirty-projects] #'helm-projectile-browse-dirty-projects)
+ (helm-projectile-commander-bindings))
+ (progn
+ (when (eq projectile-switch-project-action #'helm-projectile-find-file)
+ (setq projectile-switch-project-action #'projectile-find-file))
+ (define-key projectile-mode-map [remap projectile-find-other-file] nil)
+ (define-key projectile-mode-map [remap projectile-find-file] nil)
+ (define-key projectile-mode-map [remap projectile-find-file-in-known-projects] nil)
+ (define-key projectile-mode-map [remap projectile-find-file-dwim] nil)
+ (define-key projectile-mode-map [remap projectile-find-dir] nil)
+ (define-key projectile-mode-map [remap projectile-switch-project] nil)
+ (define-key projectile-mode-map [remap projectile-recentf] nil)
+ (define-key projectile-mode-map [remap projectile-switch-to-buffer] nil)
+ (define-key projectile-mode-map [remap projectile-grep] nil)
+ (define-key projectile-mode-map [remap projectile-ag] nil)
+ (define-key projectile-mode-map [remap projectile-ripgrep] nil)
+ (define-key projectile-mode-map [remap projectile-browse-dirty-projects] nil)
+ (projectile-commander-bindings))))
+
+;;;###autoload
+(defun helm-projectile (&optional arg)
+ "Use projectile with Helm instead of ido.
+
+With a prefix ARG invalidates the cache first.
+If invoked outside of a project, displays a list of known projects to jump."
+ (interactive "P")
+ (if (not (projectile-project-p))
+ (helm-projectile-switch-project arg)
+ (projectile-maybe-invalidate-cache arg)
+ (let ((helm-ff-transformer-show-only-basename nil))
+ (helm :sources helm-projectile-sources-list
+ :buffer "*helm projectile*"
+ :truncate-lines helm-projectile-truncate-lines
+ :prompt (projectile-prepend-project-name (if (projectile-project-p)
+ "pattern: "
+ "Switch to project: "))))))
+
+;;;###autoload
+(eval-after-load 'projectile
+ '(progn
+ (define-key projectile-command-map (kbd "h") #'helm-projectile)))
+
+(provide 'helm-projectile)
+
+;;; helm-projectile.el ends here
+++ /dev/null
-This library provides easy project management and navigation. The
-concept of a project is pretty basic - just a folder containing
-special file. Currently git, mercurial and bazaar repos are
-considered projects by default. If you want to mark a folder
-manually as a project just create an empty .projectile file in
-it. See the README for more details.
+++ /dev/null
-;;; helm-safari-autoloads.el --- automatically extracted autoloads
-;;
-;;; Code:
-(add-to-list 'load-path (or (file-name-directory #$) (car load-path)))
-\f
-;;;### (autoloads nil "helm-safari" "helm-safari.el" (22184 48066
-;;;;;; 0 0))
-;;; Generated autoloads from helm-safari.el
-
-(autoload 'helm-safari-bookmarks "helm-safari" "\
-Search Safari Bookmark using `helm'.
-
-\(fn)" t nil)
-
-(autoload 'helm-safari-history "helm-safari" "\
-Search Safari Bookmark using `helm'.
-
-\(fn)" t nil)
-
-;;;***
-\f
-;; Local Variables:
-;; version-control: never
-;; no-byte-compile: t
-;; no-update-autoloads: t
-;; End:
-;;; helm-safari-autoloads.el ends here
+++ /dev/null
-(define-package "helm-safari" "20160115.2334" "Helm interface for Safari Bookmarks and History" '((helm "1.9.1") (emacs "24")) :keywords '("tools"))
+++ /dev/null
-;;; helm-safari.el --- Helm interface for Safari Bookmarks and History -*- lexical-binding: t; -*-
-
-;; Copyright (C) 2016 Chunyang Xu
-
-;; Author: Chunyang Xu <xuchunyang56NOSPAMgmail.com>
-;; Package-Requires: ((helm "1.9.1") (emacs "24"))
-;; Version: 0.1
-;; Package-Version: 20160115.2334
-;; Keywords: tools
-
-;; 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/>.
-
-;;; Commentary:
-
-;;
-
-;;; Code:
-
-(require 'helm)
-
-(defgroup helm-safari nil
- "Helm interface for Safari Bookmarks and History."
- :group 'helm)
-
-(defun helm-safari-list-to-alist (list)
- ;; '(1 2 3 4) ⇒ ((2 . 1) (4 . 3))
- (let* ((idx 0)
- res)
- (while (< idx (length list))
- (push (cons (nth (1+ idx) list)
- (nth idx list))
- res)
- (setq idx (+ idx 2)))
- (nreverse res)))
-
-(defvar helm-safari-bookmarks-alist nil)
-(defvar helm-source-safari-bookmarks
- (helm-build-sync-source "Safari Bookmarks"
- :init
- (lambda ()
- (setq helm-safari-bookmarks-alist
- (let ((bookmarks-list
- (split-string
- (shell-command-to-string
- "plutil -p ~/Library/Safari/Bookmarks.plist | grep 'URLString\\|title' | sed 's/.* => \"\\(.*\\)\"/\\1/'")
- "\n" t)))
- (helm-safari-list-to-alist bookmarks-list))))
- :candidates 'helm-safari-bookmarks-alist
- :action '(("Browse Url" . browse-url))))
-
-;;;###autoload
-(defun helm-safari-bookmarks ()
- "Search Safari Bookmark using `helm'."
- (interactive)
- (helm :sources 'helm-source-safari-bookmarks
- :prompt "Find Bookmark: "
- :buffer "*Helm Safari Bookmarks*"))
-
-(defvar helm-safari-history-alist nil)
-(defvar helm-source-safari-history
- (helm-build-sync-source "Safari History"
- :init
- (lambda ()
- (setq helm-safari-history-alist
- (let ((history-list
- (split-string
- (shell-command-to-string
- "plutil -p ~/Library/Safari/History.plist | grep '\"title\"\\|\"\" ' | sed 's/.* => \"\\(.*\\)\"$/\\1/'")
- "\n" t)))
- (helm-safari-list-to-alist history-list))))
- :candidates 'helm-safari-history-alist
- :action '(("Browse Url" . browse-url))))
-
-;;;###autoload
-(defun helm-safari-history ()
- "Search Safari Bookmark using `helm'."
- (interactive)
- (helm :sources 'helm-source-safari-history
- :prompt "Find Bookmark: "
- :buffer "*Helm Safari History*"))
-
-(provide 'helm-safari)
-;;; helm-safari.el ends here
--- /dev/null
+;;; helm-safari-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+
+(add-to-list 'load-path (directory-file-name
+ (or (file-name-directory #$) (car load-path))))
+
+\f
+;;;### (autoloads nil "helm-safari" "helm-safari.el" (0 0 0 0))
+;;; Generated autoloads from helm-safari.el
+
+(autoload 'helm-safari-bookmarks "helm-safari" "\
+Search Safari Bookmarks.
+
+\(fn)" t nil)
+
+(autoload 'helm-safari-history "helm-safari" "\
+Search Safari History.
+
+\(fn)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-safari" '("helm-s")))
+
+;;;***
+\f
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; coding: utf-8
+;; End:
+;;; helm-safari-autoloads.el ends here
--- /dev/null
+;;; -*- no-byte-compile: t -*-
+(define-package "helm-safari" "20160404.324" "Browse your Safari bookmarks and history" '((helm "1.9.1") (emacs "24")) :commit "664c7f4488829228eed7e90cd53002e14bec555b" :keywords '("tools") :authors '(("Chunyang Xu" . "xuchunyang56NOSPAMgmail.com")) :maintainer '("Chunyang Xu" . "xuchunyang56NOSPAMgmail.com") :url "https://github.com/xuchunyang/helm-safari")
--- /dev/null
+;;; helm-safari.el --- Browse your Safari bookmarks and history -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2016 Chunyang Xu
+
+;; Author: Chunyang Xu <xuchunyang56NOSPAMgmail.com>
+;; URL: https://github.com/xuchunyang/helm-safari
+;; Package-Version: 20160404.324
+;; Package-Requires: ((helm "1.9.1") (emacs "24"))
+;; Version: 0.1
+;; Keywords: tools
+
+;; 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/>.
+
+;;; Commentary:
+
+;; Browse your Safari bookmarks and history with Helm.
+
+;; To use, type M-x helm-safari-bookmarks or M-x helm-safari-history
+
+;; FIXME: `helm-safari-history' is slow and ugly, it takes me more than 15
+;; seconds to be ready with 1166 history entries
+;; TODO: Improve UI to show link along side name
+;; TODO: Search (match) against link (not just name)
+;; TODO: Improve performance, especially for `helm-safari-history'
+
+;;; Code:
+
+(require 'helm)
+(require 'json)
+
+(defgroup helm-safari nil
+ "Helm interface for Safari Bookmarks and History."
+ :group 'helm)
+
+(defun helm-safari-list-to-alist (list)
+ ;; '(1 2 3 4) ⇒ ((2 . 1) (4 . 3))
+ (let* ((idx 0)
+ res)
+ (while (< idx (length list))
+ (push (cons (nth (1+ idx) list)
+ (nth idx list))
+ res)
+ (setq idx (+ idx 2)))
+ (nreverse res)))
+
+(defun helm-safari-init (dir)
+ (let* ((dir (expand-file-name dir))
+ (files
+ (delete (concat dir "..")
+ (delete (concat dir ".")
+ (directory-files dir 'full nil 'nosort))))
+ name-url-alist)
+ (with-temp-buffer
+ (dolist (f files)
+ (erase-buffer)
+ (let ((cmd (format "plutil -convert json -o - -- %s" (shell-quote-argument f)))
+ json)
+ (when (zerop (call-process-shell-command cmd nil t))
+ (setq json (json-read-from-string (buffer-string)))
+ (push (cons (cdr (assoc 'Name json))
+ (cdr (assoc 'URL json)))
+ name-url-alist)))))
+ name-url-alist))
+
+(defvar helm-safari-bookmarks-alist nil)
+
+(defvar helm-source-safari-bookmarks
+ (helm-build-sync-source "Safari Bookmarks"
+ :candidates 'helm-safari-bookmarks-alist
+ :action '(("Browse Url" . browse-url))))
+
+;;;###autoload
+(defun helm-safari-bookmarks ()
+ "Search Safari Bookmarks."
+ (interactive)
+ (unless helm-safari-bookmarks-alist
+ (setq helm-safari-bookmarks-alist
+ (helm-safari-init "~/Library/Caches/Metadata/Safari/Bookmarks/")))
+ (helm :sources 'helm-source-safari-bookmarks
+ :prompt "Find Bookmarks: "
+ :buffer "*Helm Safari Bookmarks*"))
+
+(defvar helm-source-safari-history
+ (helm-build-in-buffer-source "Safari History"
+ :init #'helm-safari-history-init
+ :action (lambda (candidate)
+ (browse-url (cdr (assoc 'URL (json-read-from-string candidate)))))))
+
+(defun helm-safari-history-init ()
+ (with-current-buffer (helm-candidate-buffer 'global)
+ (let* ((dir
+ (expand-file-name "~/Library/Caches/Metadata/Safari/History/"))
+ (files
+ (delete (concat dir "..")
+ (delete (concat dir ".")
+ (directory-files dir 'full nil 'nosort)))))
+ (dolist (f files)
+ (call-process "plutil" nil t nil "-convert" "json" "-o" "-" "--" f)
+ (insert "\n")))))
+
+;;;###autoload
+(defun helm-safari-history ()
+ "Search Safari History."
+ (interactive)
+ (helm :sources 'helm-source-safari-history
+ :prompt "Find History: "
+ :buffer "*Helm Safari History*"))
+
+(provide 'helm-safari)
+;;; helm-safari.el ends here
+++ /dev/null
-;;; helm-swoop-autoloads.el --- automatically extracted autoloads
-;;
-;;; Code:
-(add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path))))
-\f
-;;;### (autoloads nil "helm-swoop" "helm-swoop.el" (23005 64951 0
-;;;;;; 0))
-;;; Generated autoloads from helm-swoop.el
-
-(autoload 'helm-swoop-back-to-last-point "helm-swoop" "\
-Go back to last position where `helm-swoop' was called
-
-\(fn &optional $CANCEL)" t nil)
-
-(autoload 'helm-swoop "helm-swoop" "\
-List the all lines to another buffer, which is able to squeeze by
- any words you input. At the same time, the original buffer's cursor
- is jumping line to line according to moving up and down the list.
-
-\(fn &key $QUERY $SOURCE ($MULTILINE current-prefix-arg))" t nil)
-
-(autoload 'helm-swoop-from-isearch "helm-swoop" "\
-Invoke `helm-swoop' from isearch.
-
-\(fn)" t nil)
-
-(autoload 'helm-multi-swoop "helm-swoop" "\
-Usage:
-M-x helm-multi-swoop
-1. Select any buffers by [C-SPC] or [M-SPC]
-2. Press [RET] to start helm-multi-swoop
-
-C-u M-x helm-multi-swoop
-If you have done helm-multi-swoop before, you can skip select buffers step.
-Last selected buffers will be applied to helm-multi-swoop.
-
-\(fn &optional $QUERY $BUFLIST)" t nil)
-
-(autoload 'helm-multi-swoop-all "helm-swoop" "\
-Apply all buffers to helm-multi-swoop
-
-\(fn &optional $QUERY)" t nil)
-
-(autoload 'helm-multi-swoop-org "helm-swoop" "\
-Applies all org-mode buffers to helm-multi-swoop
-
-\(fn &optional $QUERY)" t nil)
-
-(autoload 'helm-multi-swoop-current-mode "helm-swoop" "\
-Applies all buffers of the same mode as the current buffer to helm-multi-swoop
-
-\(fn &optional $QUERY)" t nil)
-
-(autoload 'helm-multi-swoop-projectile "helm-swoop" "\
-Apply all opened buffers of the current project to helm-multi-swoop
-
-\(fn &optional $QUERY)" t nil)
-
-(autoload 'helm-swoop-without-pre-input "helm-swoop" "\
-Start helm-swoop without pre input query.
-
-\(fn)" t nil)
-
-(autoload 'helm-swoop-symble-pre-input "helm-swoop" "\
-Start helm-swoop without pre input query.
-
-\(fn)" t nil)
-
-(autoload 'helm-multi-swoop-edit "helm-swoop" "\
-
-
-\(fn)" t nil)
-
-;;;***
-\f
-;; Local Variables:
-;; version-control: never
-;; no-byte-compile: t
-;; no-update-autoloads: t
-;; End:
-;;; helm-swoop-autoloads.el ends here
+++ /dev/null
-;;; -*- no-byte-compile: t -*-
-(define-package "helm-swoop" "20170923.2127" "Efficiently hopping squeezed lines powered by helm interface" '((helm "1.0") (emacs "24.3")) :commit "66a951700e0ef0621cc705791bdd6699488ab121" :url "https://github.com/ShingoFukuyama/helm-swoop" :keywords '("helm" "swoop" "inner" "buffer" "search"))
+++ /dev/null
-;;; helm-swoop.el --- Efficiently hopping squeezed lines powered by helm interface -*- coding: utf-8; lexical-binding: t -*-
-
-;; Copyright (C) 2013 - 2017 by Shingo Fukuyama
-
-;; Version: 1.7.3
-;; Package-Version: 20170923.2127
-;; Author: Shingo Fukuyama - http://fukuyama.co
-;; URL: https://github.com/ShingoFukuyama/helm-swoop
-;; Created: Oct 24 2013
-;; Keywords: helm swoop inner buffer search
-;; Package-Requires: ((helm "1.0") (emacs "24.3"))
-
-;; 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 2 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.
-
-;;; Commentary:
-
-;; List the all lines to another buffer, which is able to squeeze
-;; by any words you input. At the same time, the original buffer's
-;; cursor is jumping line to line according to moving up and down
-;; the list.
-
-;; Example config
-;; ----------------------------------------------------------------
-;; ;; helm from https://github.com/emacs-helm/helm
-;; (require 'helm)
-
-;; ;; Locate the helm-swoop folder to your path
-;; ;; This line is unnecessary if you get this program from MELPA
-;; (add-to-list 'load-path "~/.emacs.d/elisp/helm-swoop")
-
-;; (require 'helm-swoop)
-
-;; ;; Change keybinds to whatever you like :)
-;; (global-set-key (kbd "M-i") 'helm-swoop)
-;; (global-set-key (kbd "M-I") 'helm-swoop-back-to-last-point)
-;; (global-set-key (kbd "C-c M-i") 'helm-multi-swoop)
-;; (global-set-key (kbd "C-x M-i") 'helm-multi-swoop-all)
-
-;; ;; When doing isearch, hand the word over to helm-swoop
-;; (define-key isearch-mode-map (kbd "M-i") 'helm-swoop-from-isearch)
-;; (define-key helm-swoop-map (kbd "M-i") 'helm-multi-swoop-all-from-helm-swoop)
-
-;; ;; Save buffer when helm-multi-swoop-edit complete
-;; (setq helm-multi-swoop-edit-save t)
-
-;; ;; If this value is t, split window inside the current window
-;; (setq helm-swoop-split-with-multiple-windows nil)
-
-;; ;; Split direction. 'split-window-vertically or 'split-window-horizontally
-;; (setq helm-swoop-split-direction 'split-window-vertically)
-
-;; ;; If nil, you can slightly boost invoke speed in exchange for text color
-;; (setq helm-swoop-speed-or-color nil)
-
-;; ;; Go to the opposite side of line from the end or beginning of line
-;; (setq helm-swoop-move-to-line-cycle t)
-
-;; ;; Optional face for line numbers
-;; ;; Face name is `helm-swoop-line-number-face`
-;; (setq helm-swoop-use-line-number-face t)
-
-;; ----------------------------------------------------------------
-
-;; * `M-x helm-swoop` when region active
-;; * `M-x helm-swoop` when the cursor is at any symbol
-;; * `M-x helm-swoop` when the cursor is not at any symbol
-;; * `M-3 M-x helm-swoop` or `C-u 5 M-x helm-swoop` multi separated line culling
-;; * `M-x helm-multi-swoop` multi-occur like feature
-;; * `M-x helm-multi-swoop-all` apply all buffers
-;; * `C-u M-x helm-multi-swoop` apply last selected buffers from the second time
-;; * `M-x helm-swoop-same-face-at-point` list lines have the same face at the cursor is on
-;; * During isearch `M-i` to hand the word over to helm-swoop
-;; * During helm-swoop `M-i` to hand the word over to helm-multi-swoop-all
-;; * While doing `helm-swoop` press `C-c C-e` to edit mode, apply changes to original buffer by `C-x C-s`
-
-;; Helm Swoop Edit
-;; While doing helm-swoop, press keybind [C-c C-e] to move to edit buffer.
-;; Edit the list and apply by [C-x C-s]. If you'd like to cancel, [C-c C-g]
-
-;;; Code:
-
-(require 'cl-lib)
-(require 'helm)
-(require 'helm-utils)
-(require 'helm-grep)
-
-(declare-function migemo-search-pattern-get "migemo")
-(declare-function projectile-buffers-with-file-or-process "projectile")
-(declare-function projectile-project-buffers "projectile")
-(defvar projectile-buffers-filter-function)
-
-;;; @ helm-swoop ----------------------------------------------
-
-(defgroup helm-swoop nil
- "Open helm-swoop."
- :prefix "helm-swoop-" :group 'helm)
-
-(defface helm-swoop-target-line-face
- '((t (:background "#e3e300" :foreground "#222222")))
- "Face for helm-swoop target line"
- :group 'helm-swoop)
-(defface helm-swoop-target-line-block-face
- '((t (:background "#cccc00" :foreground "#222222")))
- "Face for target line"
- :group 'helm-swoop)
-(defface helm-swoop-target-word-face
- '((t (:background "#7700ff" :foreground "#ffffff")))
- "Face for target word"
- :group 'helm-swoop)
-(defface helm-swoop-line-number-face
- '((t (:foreground "#999999")))
- "Face for line numbers"
- :group 'helm-swoop)
-
-(defcustom helm-swoop-speed-or-color nil
- "If nil, you can slightly boost invoke speed in exchange for text color"
- :group 'helm-swoop :type 'boolean)
-(defcustom helm-swoop-use-line-number-face nil
- "Use face to line numbers on helm-swoop buffer"
- :group 'helm-swoop :type 'boolean)
-(defcustom helm-swoop-split-with-multiple-windows nil
- "Split window when having multiple windows open"
- :group 'helm-swoop :type 'boolean)
-(defcustom helm-swoop-move-to-line-cycle t
- "Return to the opposite side of line"
- :group 'helm-swoop :type 'boolean)
-(defcustom helm-swoop-split-direction 'split-window-vertically
- "Split direction"
- :type '(choice (const :tag "vertically" split-window-vertically)
- (const :tag "horizontally" split-window-horizontally))
- :group 'helm-swoop)
-(defcustom helm-swoop-use-fuzzy-match nil
- "If t, use fuzzy matching functions as well as exact matches."
- :group 'helm-swoop :type 'boolean)
-
-(defvar helm-swoop-split-window-function
- (lambda ($buf)
- (if helm-swoop-split-with-multiple-windows
- (funcall helm-swoop-split-direction)
- (when (one-window-p)
- (funcall helm-swoop-split-direction)))
- (other-window 1)
- (switch-to-buffer $buf))
- "Change the way to split window only when `helm-swoop' is calling")
-
-(defcustom helm-swoop-after-goto-line-action-hook nil
- "hooks run after `helm-swoop--goto-line"
- :group 'helm-swoop
- :type 'hook)
-(defcustom helm-swoop-before-goto-line-action-hook nil
- "hooks run before `helm-swoop--goto-line"
- :group 'helm-swoop
- :type 'hook)
-
-(defvar helm-swoop-candidate-number-limit 19999)
-(defvar helm-swoop-buffer "*Helm Swoop*")
-(defvar helm-swoop-prompt "Swoop: ")
-(defvar helm-swoop-last-point nil)
-(defvar helm-swoop-invisible-targets nil)
-(defvar helm-swoop-last-line-info nil)
-
-;; Buffer local variables
-(defvar helm-swoop-list-cache)
-(defvar helm-swoop-pattern) ; Keep helm-pattern value
-(defvar helm-swoop-last-query) ; Last search query for resume
-(defvar-local helm-swoop-last-prefix-number 1) ; For multiline highlight
-
-;; Global variables
-(defvar helm-swoop-synchronizing-window nil
- "Window object where `helm-swoop' called from")
-(defvar helm-swoop-target-buffer nil
- "Buffer object where `helm-swoop' called from")
-(defvar helm-swoop-line-overlay nil
- "Overlay object to indicate other window's line")
-
-(defvar helm-swoop-map
- (let (($map (make-sparse-keymap)))
- (set-keymap-parent $map helm-map)
- (define-key $map (kbd "C-c C-e") 'helm-swoop-edit)
- (define-key $map (kbd "M-i") 'helm-multi-swoop-all-from-helm-swoop)
- (define-key $map (kbd "C-w") 'helm-swoop-yank-thing-at-point)
- (define-key $map (kbd "^") 'helm-swoop-caret-match)
- (delq nil $map))
- "Keymap for helm-swoop")
-
-(defvar helm-multi-swoop-map
- (let (($map (make-sparse-keymap)))
- (set-keymap-parent $map helm-map)
- (define-key $map (kbd "C-c C-e") 'helm-multi-swoop-edit)
- (delq nil $map)))
-
-(defvar helm-c-source-swoop-match-functions
- '(helm-mm-exact-match
- helm-mm-match
- helm-mm-3-migemo-match))
-
-(defvar helm-c-source-swoop-search-functions
- '(helm-mm-exact-search
- helm-mm-search
- helm-candidates-in-buffer-search-default-fn
- helm-mm-3-migemo-search))
-
-(defun helm-swoop-match-functions ()
- (if helm-swoop-use-fuzzy-match
- (append helm-c-source-swoop-match-functions '(helm-fuzzy-match))
- helm-c-source-swoop-match-functions))
-
-(defun helm-swoop-search-functions ()
- (if helm-swoop-use-fuzzy-match
- (append helm-c-source-swoop-search-functions '(helm-fuzzy-search))
- helm-c-source-swoop-search-functions))
-
-(defcustom helm-swoop-pre-input-function
- (lambda () (thing-at-point 'symbol))
- "This function can pre-input keywords when helm-swoop invoked"
- :group 'helm-swoop :type 'function)
-
-(defun helm-swoop-pre-input-optimize ($query)
- (when $query
- (let (($regexp (list '("\+" . "\\\\+")
- '("\*" . "\\\\*")
- '("\#" . "\\\\#"))))
- (mapc (lambda ($r)
- (setq $query (replace-regexp-in-string (car $r) (cdr $r) $query)))
- $regexp)
- $query)))
-
-(defsubst helm-swoop--goto-line ($line)
- (goto-char (point-min))
- (forward-line (1- $line)))
-
-(defsubst helm-swoop--recenter ()
- (recenter (/ (window-height) 2)))
-
-(defsubst helm-swoop--delete-overlay ($identity &optional $beg $end)
- (or $beg (setq $beg (point-min)))
- (or $end (setq $end (point-max)))
- (overlay-recenter $end)
- (mapc (lambda ($o)
- (if (overlay-get $o $identity)
- (delete-overlay $o)))
- (overlays-in $beg $end)))
-
-(defsubst helm-swoop--get-string-at-line ()
- (buffer-substring-no-properties (point-at-bol) (point-at-eol)))
-
-(defsubst helm-swoop--buffer-substring ($point-min $point-max)
- (if helm-swoop-speed-or-color
- (let (($content (buffer-substring $point-min $point-max)))
- (with-temp-buffer
- (let ((inhibit-read-only t))
- (insert $content)
- (remove-text-properties (point-min) (point-max) '(read-only t))
- (setq $content (buffer-substring (point-min) (point-max)))))
- $content)
- (buffer-substring-no-properties $point-min $point-max)))
-
-;;;###autoload
-(defun helm-swoop-back-to-last-point (&optional $cancel)
- "Go back to last position where `helm-swoop' was called"
- (interactive)
- (if helm-swoop-last-point
- (let (($po (point)))
- (switch-to-buffer (cdr helm-swoop-last-point))
- (goto-char (car helm-swoop-last-point))
- (unless $cancel
- (setq helm-swoop-last-point
- (cons $po (buffer-name (current-buffer))))))))
-
-(defun helm-swoop--split-lines-by ($string $regexp $step)
- "split-string by $step for multiline"
- (or $step (setq $step 1))
- (let (($from1 0) ;; last match point
- ($from2 0) ;; last substring point
- $list
- ($i 1)) ;; from line 1
- (while (string-match $regexp $string $from1)
- (setq $i (1+ $i))
- (if (eq 0 (% $i $step))
- (progn
- (setq $list (cons (substring $string $from2 (match-beginning 0))
- $list))
- (setq $from2 (match-end 0))
- (setq $from1 (match-end 0)))
- (setq $from1 (match-end 0))))
- (setq $list (cons (substring $string $from2) $list))
- (nreverse $list)))
-
-(defun helm-swoop--target-line-overlay-move (&optional $buf)
- "Add color to the target line"
- (move-overlay
- helm-swoop-line-overlay
- (progn
- (search-backward
- "\n" nil t (% (line-number-at-pos) helm-swoop-last-prefix-number))
- (goto-char (point-at-bol)))
- ;; For multiline highlight
- (save-excursion
- (goto-char (point-at-bol))
- (or (re-search-forward "\n" nil t helm-swoop-last-prefix-number)
- ;; For the end of buffer error
- (point-max)))
- $buf)
- (helm-swoop--unveil-invisible-overlay))
-
-(defun helm-swoop--validate-regexp (regexp)
- (condition-case nil
- (progn
- (string-match-p regexp "")
- t)
- (invalid-regexp nil)))
-
-(defun helm-swoop--target-word-overlay ($identity &optional $threshold)
- (interactive)
- (or $threshold (setq $threshold 2))
- (save-excursion
- (let (($pat (split-string helm-pattern " "))
- $o)
- (mapc (lambda ($wd)
- (when (and (helm-swoop--validate-regexp $wd) (< $threshold (length $wd)))
- (goto-char (point-min))
- ;; Optional require migemo.el
- (if (and (featurep 'migemo) helm-migemo-mode)
- (setq $wd (migemo-search-pattern-get $wd)))
- ;; For caret begging match
- (if (string-match "^\\^\\[0\\-9\\]\\+\\.\\(.+\\)" $wd)
- (setq $wd (concat "^" (match-string 1 $wd))))
- (overlay-recenter (point-max))
- (let (finish)
- (while (and (not finish) (re-search-forward $wd nil t))
- (if (= (match-beginning 0) (match-end 0))
- (forward-char 1)
- (setq $o (make-overlay (match-beginning 0) (match-end 0)))
- (overlay-put $o 'face 'helm-swoop-target-word-face)
- (overlay-put $o $identity t))
- (when (eobp)
- (setq finish t))))))
- $pat))))
-
-(defun helm-swoop--restore-unveiled-overlay ()
- (when helm-swoop-invisible-targets
- (mapc (lambda ($ov) (overlay-put (car $ov) 'invisible (cdr $ov)))
- helm-swoop-invisible-targets)
- (setq helm-swoop-invisible-targets nil)))
-
-(defun helm-swoop--unveil-invisible-overlay ()
- "Show hidden text temporarily to view it during helm-swoop.
-This function needs to call after latest helm-swoop-line-overlay set."
- (helm-swoop--restore-unveiled-overlay)
- (mapc (lambda ($ov)
- (let (($type (overlay-get $ov 'invisible)))
- (when $type
- (overlay-put $ov 'invisible nil)
- (setq helm-swoop-invisible-targets
- (cons (cons $ov $type) helm-swoop-invisible-targets)))))
- (overlays-in (overlay-start helm-swoop-line-overlay)
- (overlay-end helm-swoop-line-overlay))))
-
-;; helm action ------------------------------------------------
-
-(defadvice helm-next-line (around helm-swoop-next-line disable)
- (let ((helm-move-to-line-cycle-in-source t))
- ad-do-it
- (when (called-interactively-p 'any)
- (helm-swoop--move-line-action))))
-
-(defadvice helm-previous-line (around helm-swoop-previous-line disable)
- (let ((helm-move-to-line-cycle-in-source t))
- ad-do-it
- (when (called-interactively-p 'any)
- (helm-swoop--move-line-action))))
-
-(defadvice helm-toggle-visible-mark (around helm-swoop-toggle-visible-mark disable)
- (let ((helm-move-to-line-cycle-in-source t))
- ad-do-it
- (when (called-interactively-p 'any)
- (helm-swoop--move-line-action))))
-
-(defun helm-swoop--move-line-action ()
- (with-helm-window
- (let* (($key (helm-swoop--get-string-at-line))
- ($num (when (string-match "^[0-9]+" $key)
- (string-to-number (match-string 0 $key)))))
- ;; Synchronizing line position
- (when (and $key $num)
- (with-selected-window helm-swoop-synchronizing-window
- (progn
- (helm-swoop--goto-line $num)
- (with-current-buffer helm-swoop-target-buffer
- (delete-overlay helm-swoop-line-overlay)
- (helm-swoop--target-line-overlay-move))
- (helm-swoop--recenter)))
- (setq helm-swoop-last-line-info
- (cons helm-swoop-target-buffer $num))))))
-
-(defun helm-swoop--nearest-line ($target $list)
- "Return the nearest number of $target out of $list."
- (when (and $target $list)
- (let ($result)
- (cl-labels ((filter ($fn $elem $list)
- (let ($r)
- (mapc (lambda ($e)
- (if (funcall $fn $elem $e)
- (setq $r (cons $e $r))))
- $list) $r)))
- (if (eq 1 (length $list))
- (setq $result (car $list))
- (let* (($lts (filter '> $target $list))
- ($gts (filter '< $target $list))
- ($lt (if $lts (apply 'max $lts)))
- ($gt (if $gts (apply 'min $gts)))
- ($ltg (if $lt (- $target $lt)))
- ($gtg (if $gt (- $gt $target))))
- (setq $result
- (cond ((memq $target $list) $target)
- ((and (not $lt) (not $gt)) nil)
- ((not $gtg) $lt)
- ((not $ltg) $gt)
- ((eq $ltg $gtg) $gt)
- ((< $ltg $gtg) $lt)
- ((> $ltg $gtg) $gt)
- (t 1))))))
- $result)))
-
-(defun helm-swoop--keep-nearest-position ()
- (with-helm-window
- (let (($p (point-min)) $list $bound
- $nearest-line $target-point
- ($buf (rx-to-string (buffer-name (car helm-swoop-last-line-info)) t)))
- (save-excursion
- (goto-char $p)
- (while (if $p (setq $p (re-search-forward (concat "^" $buf "$") nil t)))
- (when (get-text-property (point-at-bol) 'helm-header)
- (forward-char 1)
- (setq $bound (next-single-property-change (point) 'helm-header))
- (while (re-search-forward "^[0-9]+" $bound t)
- (setq $list (cons
- (string-to-number (match-string 0))
- $list)))
- (setq $nearest-line (helm-swoop--nearest-line
- (cdr helm-swoop-last-line-info)
- $list))
- (goto-char $p)
- (re-search-forward (concat "^"
- (number-to-string $nearest-line)
- "\\s-") $bound t)
- (setq $target-point (point))
- (setq $p nil))))
- (when $target-point
- (goto-char $target-point)
- (helm-mark-current-line)
- (if (equal helm-swoop-buffer (buffer-name (current-buffer)))
- (helm-swoop--move-line-action)
- (helm-multi-swoop--move-line-action))))))
-
-(defun helm-swoop--pattern-match ()
- "Overlay target words"
- (with-helm-window
- (setq helm-swoop-pattern helm-pattern)
- (when (< 2 (length helm-pattern))
- (helm-swoop--delete-overlay 'target-buffer)
- (helm-swoop--target-word-overlay 'target-buffer)
- (with-selected-window helm-swoop-synchronizing-window
- (helm-swoop--delete-overlay 'target-buffer)
- (helm-swoop--target-word-overlay 'target-buffer)))))
-
-(defun helm-swoop-flash-word ($match-beg $match-end)
- (interactive)
- (unwind-protect
- (let (($o (make-overlay $match-beg $match-end)))
- (when $o
- (overlay-put $o 'face 'helm-swoop-target-word-face)
- (overlay-put $o 'helm-swoop-overlay-word-frash t)))
- (run-with-idle-timer
- 0.6 nil (lambda () (helm-swoop--delete-overlay 'helm-swoop-overlay-word-frash)))))
-
-;; core ------------------------------------------------
-
-(defun helm-swoop--get-content ($buffer &optional $linum)
- "Get the whole content in buffer and add line number at the head.
-If $linum is number, lines are separated by $linum"
- (let (($buf (get-buffer $buffer)))
- (when $buf
- (with-current-buffer $buf
- (let (($bufstr (helm-swoop--buffer-substring (point-min) (point-max)))
- $return)
- (with-temp-buffer
- (insert $bufstr)
- (goto-char (point-min))
- (let (($i 1))
- (insert (format "%s " $i))
- (while (re-search-forward "\n" nil t)
- (cl-incf $i)
- (if helm-swoop-use-line-number-face
- (insert (propertize (format "%s" $i) 'font-lock-face 'helm-swoop-line-number-face) " ")
- (insert (format "%s " $i))))
- ;; Delete empty lines
- (unless $linum
- (goto-char (point-min))
- (while (re-search-forward "^[0-9]+\\s-*$" nil t)
- (replace-match ""))))
- (setq $return (helm-swoop--buffer-substring (point-min) (point-max))))
- $return)))))
-
-(defun helm-swoop--goto-line-action ($line)
- (run-hooks 'helm-swoop-before-goto-line-action-hook)
- (helm-swoop--goto-line
- (when (string-match "^[0-9]+" $line)
- (string-to-number (match-string 0 $line))))
- (let (($regex
- (mapconcat 'identity
- (split-string helm-pattern " ")
- "\\|")))
- (when (or (and (and (featurep 'migemo) helm-migemo-mode)
- (migemo-forward $regex nil t))
- (re-search-forward $regex nil t))
- (helm-swoop-flash-word (match-beginning 0) (match-end 0))
- (goto-char (match-beginning 0))
- (run-hooks 'helm-swoop-after-goto-line-action-hook)))
- (helm-swoop--recenter))
-
-(defun helm-c-source-swoop ()
- `((name . ,(buffer-name helm-swoop-target-buffer))
- (candidates . ,(if helm-swoop-list-cache
- (progn
- (helm-swoop--split-lines-by
- helm-swoop-list-cache "\n" helm-swoop-last-prefix-number))
- (helm-swoop--split-lines-by
- (setq helm-swoop-list-cache
- (helm-swoop--get-content helm-swoop-target-buffer t))
- "\n" helm-swoop-last-prefix-number)))
- (get-line . ,(if helm-swoop-speed-or-color
- 'helm-swoop--buffer-substring
- 'buffer-substring-no-properties))
- (keymap . ,helm-swoop-map)
- (header-line . ,(substitute-command-keys
- "[\\<helm-swoop-map>\\[helm-swoop-edit]] Edit mode, \
-[\\<helm-swoop-map>\\[helm-multi-swoop-all-from-helm-swoop]] apply all buffers"))
- (action . (("Go to Line" . helm-swoop--goto-line-action)))
- ,(if (and helm-swoop-last-prefix-number
- (> helm-swoop-last-prefix-number 1))
- '(multiline))
- (match . ,(helm-swoop-match-functions))
- (search . ,(helm-swoop-search-functions))))
-
-(defun helm-c-source-multi-swoop ($buf $func $action $multiline)
- `((name . ,$buf)
- (candidates . ,(funcall $func))
- (action . ,$action)
- (header-line . ,(concat $buf
- (substitute-command-keys
- " [\\<helm-multi-swoop-map>\\[helm-multi-swoop-edit]] Edit mode")))
- (keymap . ,helm-multi-swoop-map)
- (requires-pattern . 2)
- ,(if (and $multiline
- (> $multiline 1))
- '(multiline))
- (match . ,(helm-swoop-match-functions))
- (search . ,(helm-swoop-search-functions))))
-
-(defun helm-swoop--set-prefix ($multiline)
- ;; Enable scrolling margin
- (setq helm-swoop-last-prefix-number
- (or $multiline 1))) ;; $multiline is for resume
-
-;; Delete cache when modified file is saved
-(defun helm-swoop--clear-cache ()
- (if (boundp 'helm-swoop-list-cache) (setq helm-swoop-list-cache nil)))
-(add-hook 'after-save-hook 'helm-swoop--clear-cache)
-
-(defadvice narrow-to-region (around helm-swoop-advice-narrow-to-region activate)
- (helm-swoop--clear-cache)
- ad-do-it)
-(defadvice narrow-to-defun (around helm-swoop-advice-narrow-to-defun activate)
- (helm-swoop--clear-cache)
- ad-do-it)
-(defadvice narrow-to-page (around helm-swoop-advice-narrow-to-page activate)
- (helm-swoop--clear-cache)
- ad-do-it)
-(defadvice widen (around helm-swoop-advice-widen activate)
- (helm-swoop--clear-cache)
- ad-do-it)
-
-(defun helm-swoop--restore ()
- (when (= 1 helm-exit-status)
- (helm-swoop-back-to-last-point t)
- (helm-swoop--restore-unveiled-overlay))
- (setq helm-swoop-invisible-targets nil)
- (ad-disable-advice 'helm-next-line 'around 'helm-swoop-next-line)
- (ad-activate 'helm-next-line)
- (ad-disable-advice 'helm-previous-line 'around 'helm-swoop-previous-line)
- (ad-activate 'helm-previous-line)
- (ad-disable-advice 'helm-toggle-visible-mark 'around 'helm-swoop-toggle-visible-mark)
- (ad-activate 'helm-toggle-visible-mark)
- (ad-disable-advice 'helm-move--next-line-fn 'around
- 'helm-multi-swoop-next-line-cycle)
- (ad-activate 'helm-move--next-line-fn)
- (ad-disable-advice 'helm-move--previous-line-fn 'around
- 'helm-multi-swoop-previous-line-cycle)
- (ad-activate 'helm-move--previous-line-fn)
- (remove-hook 'helm-update-hook 'helm-swoop--pattern-match)
- (remove-hook 'helm-after-update-hook 'helm-swoop--keep-nearest-position)
- (setq helm-swoop-last-query helm-swoop-pattern)
- (mapc (lambda ($ov)
- (when (or (eq 'helm-swoop-target-line-face (overlay-get $ov 'face))
- (eq 'helm-swoop-target-line-block-face
- (overlay-get $ov 'face)))
- (delete-overlay $ov)))
- (overlays-in (point-min) (point-max)))
- (helm-swoop--delete-overlay 'target-buffer)
- (deactivate-mark t))
-
-;;;###autoload
-(cl-defun helm-swoop (&key $query $source ($multiline current-prefix-arg))
- "List the all lines to another buffer, which is able to squeeze by
- any words you input. At the same time, the original buffer's cursor
- is jumping line to line according to moving up and down the list."
- (interactive)
- (setq helm-swoop-synchronizing-window (selected-window))
- (setq helm-swoop-last-point (cons (point) (buffer-name (current-buffer))))
- (setq helm-swoop-last-line-info
- (cons (current-buffer) (line-number-at-pos)))
- (unless (boundp 'helm-swoop-last-query)
- (set (make-local-variable 'helm-swoop-last-query) ""))
- (setq helm-swoop-target-buffer (current-buffer))
- (helm-swoop--set-prefix (prefix-numeric-value $multiline))
- ;; Overlay
- (setq helm-swoop-line-overlay (make-overlay (point) (point)))
- (overlay-put helm-swoop-line-overlay
- 'face (if (< 1 helm-swoop-last-prefix-number)
- 'helm-swoop-target-line-block-face
- 'helm-swoop-target-line-face))
- ;; Cache
- (cond ((not (boundp 'helm-swoop-list-cache))
- (set (make-local-variable 'helm-swoop-list-cache) nil))
- ((buffer-modified-p)
- (setq helm-swoop-list-cache nil)))
- (unwind-protect
- (progn
- ;; For synchronizing line position
- (ad-enable-advice 'helm-next-line 'around 'helm-swoop-next-line)
- (ad-activate 'helm-next-line)
- (ad-enable-advice 'helm-previous-line 'around 'helm-swoop-previous-line)
- (ad-activate 'helm-previous-line)
- (ad-enable-advice 'helm-toggle-visible-mark 'around 'helm-swoop-toggle-visible-mark)
- (ad-activate 'helm-toggle-visible-mark)
- (ad-enable-advice 'helm-move--next-line-fn 'around
- 'helm-multi-swoop-next-line-cycle)
- (ad-activate 'helm-move--next-line-fn)
- (ad-enable-advice 'helm-move--previous-line-fn 'around
- 'helm-multi-swoop-previous-line-cycle)
- (ad-activate 'helm-move--previous-line-fn)
- (add-hook 'helm-update-hook 'helm-swoop--pattern-match)
- (add-hook 'helm-after-update-hook 'helm-swoop--keep-nearest-position t)
- (cond ($query
- (if (string-match
- "\\(\\^\\[0\\-9\\]\\+\\.\\)\\(.*\\)" $query)
- $query ;; NEED FIX #1 to appear as a "^"
- $query))
- (mark-active
- (let (($st (buffer-substring-no-properties
- (region-beginning) (region-end))))
- (if (string-match "\n" $st)
- (message "Multi line region is not allowed")
- (setq $query (helm-swoop-pre-input-optimize $st)))))
- ((setq $query (helm-swoop-pre-input-optimize
- (funcall helm-swoop-pre-input-function))))
- (t (setq $query "")))
- ;; First behavior
- (helm-swoop--recenter)
- (move-beginning-of-line 1)
- (helm-swoop--target-line-overlay-move)
- ;; Execute helm
- (let ((helm-display-function helm-swoop-split-window-function)
- (helm-display-source-at-screen-top nil)
- (helm-completion-window-scroll-margin 5))
- (helm :sources
- (or $source
- (helm-c-source-swoop))
- :buffer helm-swoop-buffer
- :input $query
- :prompt helm-swoop-prompt
- :preselect
- ;; Get current line has content or else near one
- (if (string-match "^[\t\n\s]*$" (helm-swoop--get-string-at-line))
- (save-excursion
- (if (re-search-forward "[^\t\n\s]" nil t)
- (format "^%s\s" (line-number-at-pos))
- (re-search-backward "[^\t\n\s]" nil t)
- (format "^%s\s" (line-number-at-pos))))
- (format "^%s\s" (line-number-at-pos)))
- :candidate-number-limit helm-swoop-candidate-number-limit)))
- ;; Restore helm's hook and window function etc
- (helm-swoop--restore)))
-
-;; Receive word from isearch ---------------
-;;;###autoload
-(defun helm-swoop-from-isearch ()
- "Invoke `helm-swoop' from isearch."
- (interactive)
- (let (($query (if isearch-regexp
- isearch-string
- (regexp-quote isearch-string))))
- (let (search-nonincremental-instead)
- (isearch-exit))
- (helm-swoop :$query $query)))
-;; When doing isearch, hand the word over to helm-swoop
-(define-key isearch-mode-map (kbd "M-i") 'helm-swoop-from-isearch)
-
-;; Receive word from evil search ---------------
-(defun helm-swoop-from-evil-search ()
- "Invoke `helm-swoop' from evil isearch"
- (interactive)
- (if (string-match "\\(isearch-\\|evil.*search\\)" (symbol-name real-last-command))
- (helm-swoop :$query (if isearch-regexp
- isearch-string
- (regexp-quote isearch-string)))
- (helm-swoop)))
-;; When doing evil-search, hand the word over to helm-swoop
-;; (define-key evil-motion-state-map (kbd "M-i") 'helm-swoop-from-evil-search)
-
-;; Receive word from evil search ---------------
-(defun helm-swoop-yank-thing-at-point ()
- "Insert string at which the point helm-swoop started."
- (interactive)
- (let ($amend $buf)
- (with-selected-window helm-swoop-synchronizing-window
- (setq $buf (get-buffer (cdr helm-swoop-last-point)))
- (when $buf
- (with-current-buffer $buf
- (save-excursion
- (goto-char (car helm-swoop-last-point))
- (setq $amend (thing-at-point 'symbol))))))
- (when $amend
- (with-selected-window (minibuffer-window)
- (insert $amend)))))
-
-;; For helm-resume ------------------------
-(defadvice helm-resume-select-buffer
- (around helm-swoop-if-selected-as-resume activate)
- "Resume if *Helm Swoop* buffer selected as a resume
- when helm-resume with prefix"
- (if (boundp 'helm-swoop-last-query)
- ad-do-it
- ;; If the buffer hasn't called helm-swoop, just hide from options
- (let ((helm-buffers (delete helm-swoop-buffer helm-buffers)))
- ad-do-it))
- (when (and (equal ad-return-value helm-swoop-buffer)
- (boundp 'helm-swoop-last-query))
- (helm-swoop :$query helm-swoop-last-query
- :$multiline helm-swoop-last-prefix-number)
- (setq ad-return-value nil)))
-
-(defadvice helm-resume (around helm-swoop-resume activate)
- "Resume if the last used helm buffer is helm-swoop-buffer"
- (if (equal helm-last-buffer helm-swoop-buffer)
- (if (boundp 'helm-swoop-last-query)
- (if (not (ad-get-arg 0))
- (helm-swoop :$query helm-swoop-last-query
- :$multiline helm-swoop-last-prefix-number))
- ;; Temporary apply second last buffer
- (let ((helm-last-buffer (cadr helm-buffers))) ad-do-it))
- ad-do-it))
-
-;; For caret beginning-match -----------------------------
-(defun helm-swoop--caret-match-delete ($o $aft $beg $end &optional $len)
- (if $aft
- (- $end $beg $len) ;; Unused argument? To avoid byte compile error
- (delete-region (overlay-start $o) (1- (overlay-end $o)))))
-
-(defun helm-swoop-caret-match (&optional _$resume)
- (interactive)
- (let* (($prompt helm-swoop-prompt) ;; Accept change of the variable
- ($line-number-regexp "^[0-9]+.")
- ($prompt-regexp
- (funcall `(lambda ()
- (rx bol ,$prompt))))
- ($prompt-regexp-with-line-number
- (funcall `(lambda ()
- (rx bol ,$prompt (group ,$line-number-regexp)))))
- ($disguise-caret
- (lambda ()
- (save-excursion
- (re-search-backward $prompt-regexp-with-line-number nil t)
- (let (($o (make-overlay (match-beginning 1) (match-end 1))))
- (overlay-put $o 'face 'helm-swoop-target-word-face)
- (overlay-put $o 'modification-hooks '(helm-swoop--caret-match-delete))
- (overlay-put $o 'display "^")
- (overlay-put $o 'evaporate t))))))
- (if (and (minibufferp)
- (string-match $prompt-regexp
- (buffer-substring-no-properties
- (point-min) (point-max)))
- (eq (point) (+ 1 (length helm-swoop-prompt))))
- (progn
- (insert $line-number-regexp)
- (funcall $disguise-caret))
- (insert "^"))))
-
-;;; @ helm-swoop-edit -----------------------------------------
-
-(defvar helm-swoop-edit-target-buffer)
-(defvar helm-swoop-edit-buffer "*Helm Swoop Edit*")
-(defvar helm-swoop-edit-map
- (let (($map (make-sparse-keymap)))
- (define-key $map (kbd "C-x C-s") 'helm-swoop--edit-complete)
- (define-key $map (kbd "C-c C-g") 'helm-swoop--edit-cancel)
- (define-key $map (kbd "C-c C-q C-k") 'helm-swoop--edit-delete-all-lines)
- $map))
-
-(defun helm-swoop--clear-edit-buffer ($prop)
- (let ((inhibit-read-only t))
- (mapc (lambda ($ov)
- (when (overlay-get $ov $prop)
- (delete-overlay $ov)))
- (overlays-in (point-min) (point-max)))
- (set-text-properties (point-min) (point-max) nil)
- (goto-char (point-min))
- (erase-buffer)))
-
-(defun helm-swoop--collect-edited-lines ()
- "Create a list of edited lines with each its own line number"
- (interactive)
- (let ($list)
- (goto-char (point-min))
- (while (re-search-forward "^\\([0-9]+\\)\s" nil t)
- (setq $list
- (cons (cons (string-to-number (match-string 1))
- (buffer-substring-no-properties
- (point)
- (save-excursion
- (if (re-search-forward
- "^\\([0-9]+\\)\s\\|^\\(\\-+\\)" nil t)
- (1- (match-beginning 0))
- (goto-char (point-max))
- (re-search-backward "\n" nil t)))))
- $list)))
- $list))
-
-(defun helm-swoop--edit ($candidate)
- "This function will only be called from `helm-swoop-edit'"
- (interactive)
- (setq helm-swoop-edit-target-buffer helm-swoop-target-buffer)
- (delete-overlay helm-swoop-line-overlay)
- (helm-swoop--delete-overlay 'target-buffer)
- (with-current-buffer (get-buffer-create helm-swoop-edit-buffer)
-
- (helm-swoop--clear-edit-buffer 'helm-swoop-edit)
- (let (($bufstr ""))
- ;; Get target line number to edit
- (with-current-buffer helm-swoop-buffer
- ;; Use selected line by [C-SPC] or [M-SPC]
- (mapc (lambda ($ov)
- (when (eq 'helm-visible-mark (overlay-get $ov 'face))
- (setq $bufstr (concat (buffer-substring-no-properties
- (overlay-start $ov) (overlay-end $ov))
- $bufstr))))
- (overlays-in (point-min) (point-max)))
- (if (equal "" $bufstr)
- ;; Not found selected line
- (setq $bufstr (buffer-substring-no-properties
- (point-min) (point-max)))
- ;; Attach title
- (setq $bufstr (concat "Helm Swoop\n" $bufstr))))
-
- ;; Set for edit buffer
- (insert $bufstr)
- (add-text-properties (point-min) (point-max)
- '(read-only t rear-nonsticky t front-sticky t))
-
- ;; Set for editable context
- (let ((inhibit-read-only t))
- ;; Title and explanation
- (goto-char (point-min))
- (let (($o (make-overlay (point) (point-at-eol))))
- (overlay-put $o 'helm-swoop-edit t)
- (overlay-put $o 'face 'font-lock-function-name-face)
- (overlay-put $o 'after-string
- (propertize
- (substitute-command-keys
- (concat
- " [\\<helm-swoop-edit-map>\\[helm-swoop--edit-complete]] Complete"
- ", [\\<helm-swoop-edit-map>\\[helm-swoop--edit-cancel]] Cancel"
- ", [\\<helm-swoop-edit-map>\\[helm-swoop--edit-delete-all-lines]] Delete All"
- ))
- 'face 'helm-bookmark-addressbook)))
- ;; Line number and editable area
- (while (re-search-forward "^\\([0-9]+\s\\)\\(.*\\)$" nil t)
- (let* (($bol1 (match-beginning 1))
- ($eol1 (match-end 1))
- ($bol2 (match-beginning 2))
- ($eol2 (match-end 2)))
- ;; Line number
- (add-text-properties $bol1 $eol1
- '(face font-lock-function-name-face
- intangible t))
- ;; Editable area
- (remove-text-properties $bol2 $eol2 '(read-only t))
- ;; For line tail
- (set-text-properties $eol2 (or (1+ $eol2) (point-max))
- '(read-only t rear-nonsticky t))))
- (helm-swoop--target-word-overlay 'edit-buffer 0))))
-
- (other-window 1)
- (switch-to-buffer helm-swoop-edit-buffer)
- (goto-char (point-min))
- (if (string-match "^[0-9]+" $candidate)
- (re-search-forward
- (concat "^" (match-string 0 $candidate)) nil t))
- (use-local-map helm-swoop-edit-map))
-
-(defun helm-swoop--edit-complete ()
- "Apply changes and kill temporary edit buffer"
- (interactive)
- (let (($list (helm-swoop--collect-edited-lines)))
- (with-current-buffer helm-swoop-edit-target-buffer
- ;; Replace from the end of buffer
- (save-excursion
- (mapc (lambda ($cell)
- (let (($k (car $cell))
- ($v (cdr $cell)))
- (goto-char (point-min))
- (delete-region (point-at-bol $k) (point-at-eol $k))
- (goto-char (point-at-bol $k))
- (insert $v)))
- $list)))
- (select-window helm-swoop-synchronizing-window)
- (kill-buffer (get-buffer helm-swoop-edit-buffer)))
- (message "Successfully helm-swoop-edit applied to original buffer"))
-
-(defun helm-swoop--edit-delete-all-lines ()
- "Apply changes and kill temporary edit buffer"
- (interactive)
- (let (($list (helm-swoop--collect-edited-lines)))
- (with-current-buffer helm-swoop-edit-target-buffer
- ;; Replace from the end of buffer
- (save-excursion
- (mapc (lambda ($cell)
- (let (($k (car $cell)))
- (goto-char (point-min))
- (delete-region (point-at-bol $k)
- (if (eq (point-at-eol $k) (point-max))
- (point-at-eol $k)
- (1+ (point-at-eol $k))))))
- $list)))
- (select-window helm-swoop-synchronizing-window)
- (kill-buffer (get-buffer helm-swoop-edit-buffer)))
- (message "Successfully helm-swoop-edit applied to original buffer"))
-
-(defun helm-swoop--edit-cancel ()
- "Cancel edit and kill temporary buffer"
- (interactive)
- (select-window helm-swoop-synchronizing-window)
- (kill-buffer (get-buffer helm-swoop-edit-buffer))
- (message "helm-swoop-edit canceled"))
-
-(defun helm-swoop-edit ()
- (interactive)
- (helm-exit-and-execute-action 'helm-swoop--edit))
-
-;;; @ helm-multi-swoop ----------------------------------------
-(defvar helm-multi-swoop-buffer-list "*helm-multi-swoop buffers list*"
- "Buffer name")
-(defvar helm-multi-swoop-ignore-buffers-match "^\\*"
- "Regexp to eliminate buffers you don't want to see")
-(defvar helm-multi-swoop-candidate-number-limit 250)
-(defvar helm-multi-swoop-last-selected-buffers nil)
-(defvar helm-multi-swoop-last-query nil)
-(defvar helm-multi-swoop-query nil)
-(defvar helm-multi-swoop-buffer "*Helm Multi Swoop*")
-(defvar helm-multi-swoop-all-from-helm-swoop-last-point nil
- "For the last position, when helm-multi-swoop-all-from-helm-swoop canceled")
-(defvar helm-multi-swoop-move-line-action-last-buffer nil)
-
-(defvar helm-multi-swoop-buffers-map
- (let (($map (make-sparse-keymap)))
- (set-keymap-parent $map helm-map)
- (define-key $map (kbd "RET")
- (lambda () (interactive)
- (helm-exit-and-execute-action 'helm-multi-swoop--exec)))
- (delq nil $map)))
-
-(defvar helm-multi-swoop-projectile-buffers-filter
- #'projectile-buffers-with-file-or-process)
-;; action -----------------------------------------------------
-
-(defadvice helm-next-line (around helm-multi-swoop-next-line disable)
- (let ((helm-move-to-line-cycle-in-source nil))
- ad-do-it
- (when (called-interactively-p 'any)
- (helm-multi-swoop--move-line-action))))
-
-(defadvice helm-previous-line (around helm-multi-swoop-previous-line disable)
- (let ((helm-move-to-line-cycle-in-source nil))
- ad-do-it
- (when (called-interactively-p 'any)
- (helm-multi-swoop--move-line-action))))
-
-(defadvice helm-toggle-visible-mark (around helm-multi-swoop-toggle-visible-mark disable)
- (let ((helm-move-to-line-cycle-in-source nil))
- ad-do-it
- (when (called-interactively-p 'any)
- (helm-multi-swoop--move-line-action))))
-
-(defadvice helm-move--next-line-fn (around helm-multi-swoop-next-line-cycle disable)
- (if (not (helm-pos-multiline-p))
- (if (eq (point-max) (save-excursion (forward-line 1) (point)))
- (when helm-swoop-move-to-line-cycle
- (helm-beginning-of-buffer)
- (helm-swoop--recenter))
- (forward-line 1))
- (let ((line-num (line-number-at-pos)))
- (helm-move--next-multi-line-fn)
- (when (and helm-swoop-move-to-line-cycle
- (eq line-num (line-number-at-pos)))
- (helm-beginning-of-buffer)))))
-
-(defadvice helm-move--previous-line-fn (around helm-multi-swoop-previous-line-cycle disable)
- (if (not (helm-pos-multiline-p))
- (forward-line -1)
- (helm-move--previous-multi-line-fn))
- (when (and (helm-pos-header-line-p)
- (eq (point) (save-excursion (forward-line -1) (point))))
- (when helm-swoop-move-to-line-cycle
- (helm-end-of-buffer))
- (when (helm-pos-multiline-p)
- (helm-move--previous-multi-line-fn))))
-
-(defun helm-multi-swoop--move-line-action ()
- (with-helm-window
- (let* (($key (buffer-substring (point-at-bol) (point-at-eol)))
- ($num (when (string-match "^[0-9]+" $key)
- (string-to-number (match-string 0 $key))))
- ($source (helm-get-current-source))
- ($buf (let (($name (assoc-default 'name $source)))
- (when $name (get-buffer $name)))))
- (when $buf
- ;; Synchronizing line position
- (with-selected-window helm-swoop-synchronizing-window
- (with-current-buffer $buf
- (when (not (eq $buf helm-multi-swoop-move-line-action-last-buffer))
- (set-window-buffer nil $buf)
- (helm-swoop--pattern-match))
- (helm-swoop--goto-line $num)
- (helm-swoop--target-line-overlay-move $buf)
- (helm-swoop--recenter))
- (setq helm-multi-swoop-move-line-action-last-buffer $buf))
- (setq helm-swoop-last-line-info (cons $buf $num))))))
-
-(defun helm-multi-swoop--get-marked-buffers ()
- (let ($list
- ($buf (get-buffer helm-multi-swoop-buffer-list)))
- (when $buf
- (with-current-buffer (get-buffer helm-multi-swoop-buffer-list)
- (mapc (lambda ($ov)
- (when (eq 'helm-visible-mark (overlay-get $ov 'face))
- (setq $list (cons
- (let (($word (buffer-substring-no-properties
- (overlay-start $ov) (overlay-end $ov))))
- (mapc (lambda ($r)
- (setq $word (replace-regexp-in-string
- (car $r) (cdr $r) $word)))
- (list '("\\`[ \t\n\r]+" . "")
- '("[ \t\n\r]+\\'" . "")))
- $word)
- $list))))
- (overlays-in (point-min) (point-max))))
- (delete "" $list))))
-
-;; core --------------------------------------------------------
-
-(cl-defun helm-multi-swoop--exec (ignored &key $query $buflist $func $action)
- (interactive)
- (setq helm-swoop-synchronizing-window (selected-window))
- (setq helm-swoop-last-point
- (or helm-multi-swoop-all-from-helm-swoop-last-point
- (cons (point) (buffer-name (current-buffer)))))
- (setq helm-swoop-last-line-info
- (cons (current-buffer) (line-number-at-pos)))
- (unless (get-buffer helm-multi-swoop-buffer-list)
- (get-buffer-create helm-multi-swoop-buffer-list))
- (helm-swoop--set-prefix (prefix-numeric-value current-prefix-arg))
- (let (($buffs (or $buflist
- (helm-multi-swoop--get-marked-buffers)
- `(,(buffer-name helm-swoop-target-buffer))
- (error "No buffer selected")))
- $contents
- $preserve-position
- ($prefix-arg (prefix-numeric-value
- (or current-prefix-arg helm-swoop-last-prefix-number 1))))
- (helm-swoop--set-prefix $prefix-arg)
- (setq helm-multi-swoop-last-selected-buffers $buffs)
- ;; Create buffer sources
- (mapc (lambda ($buf)
- (when (get-buffer $buf)
- (with-current-buffer (get-buffer $buf)
- (let* (($func
- (or $func
- (lambda ()
- (helm-swoop--split-lines-by
- (helm-swoop--get-content $buf t)
- "\n" $prefix-arg))))
- ($action
- (or $action
- `(("Go to Line"
- . (lambda ($line)
- (switch-to-buffer ,$buf)
- (helm-swoop--goto-line
- (when (string-match "^[0-9]+" $line)
- (string-to-number
- (match-string 0 $line))))
- (when (re-search-forward
- (mapconcat 'identity
- (split-string
- helm-pattern " ") "\\|")
- nil t)
- (helm-swoop-flash-word (match-beginning 0) (match-end 0))
- (goto-char (match-beginning 0)))
- (helm-swoop--recenter)))))))
- (setq $preserve-position
- (cons (cons $buf (point)) $preserve-position))
- (setq
- $contents
- (cons
- (helm-c-source-multi-swoop $buf $func $action $prefix-arg)
- $contents))))))
- $buffs)
- (unwind-protect
- (progn
- (ad-enable-advice 'helm-next-line 'around
- 'helm-multi-swoop-next-line)
- (ad-activate 'helm-next-line)
- (ad-enable-advice 'helm-previous-line 'around
- 'helm-multi-swoop-previous-line)
- (ad-activate 'helm-previous-line)
- (ad-enable-advice 'helm-toggle-visible-mark 'around
- 'helm-multi-swoop-toggle-visible-mark)
- (ad-activate 'helm-toggle-visible-mark)
- (ad-enable-advice 'helm-move--next-line-fn 'around
- 'helm-multi-swoop-next-line-cycle)
- (ad-activate 'helm-move--next-line-fn)
- (ad-enable-advice 'helm-move--previous-line-fn 'around
- 'helm-multi-swoop-previous-line-cycle)
- (ad-activate 'helm-move--previous-line-fn)
- (add-hook 'helm-update-hook 'helm-swoop--pattern-match)
- (add-hook 'helm-after-update-hook 'helm-swoop--keep-nearest-position t)
- (setq helm-swoop-line-overlay
- (make-overlay (point) (point)))
- (overlay-put helm-swoop-line-overlay
- 'face 'helm-swoop-target-line-face)
- (helm-swoop--target-line-overlay-move)
- ;; Execute helm
- (let ((helm-display-function helm-swoop-split-window-function)
- (helm-display-source-at-screen-top nil)
- (helm-completion-window-scroll-margin 5))
- (helm :sources $contents
- :buffer helm-multi-swoop-buffer
- :input (or $query helm-multi-swoop-query "")
- :prompt helm-swoop-prompt
- :candidate-number-limit
- helm-multi-swoop-candidate-number-limit
- :preselect
- (regexp-quote
- (format "%s %s" (line-number-at-pos)
- (helm-swoop--get-string-at-line))))))
- ;; Restore
- (progn
- (when (= 1 helm-exit-status)
- (helm-swoop-back-to-last-point t)
- (helm-swoop--restore-unveiled-overlay))
- (setq helm-swoop-invisible-targets nil)
- (ad-disable-advice 'helm-next-line 'around
- 'helm-multi-swoop-next-line)
- (ad-activate 'helm-next-line)
- (ad-disable-advice 'helm-previous-line 'around
- 'helm-multi-swoop-previous-line)
- (ad-activate 'helm-previous-line)
- (ad-disable-advice 'helm-toggle-visible-mark 'around
- 'helm-multi-swoop-toggle-visible-mark)
- (ad-activate 'helm-toggle-visible-mark)
- (ad-disable-advice 'helm-move--next-line-fn 'around
- 'helm-multi-swoop-next-line-cycle)
- (ad-activate 'helm-move--next-line-fn)
- (ad-disable-advice 'helm-move--previous-line-fn 'around
- 'helm-multi-swoop-previous-line-cycle)
- (ad-activate 'helm-move--previous-line-fn)
- (remove-hook 'helm-update-hook 'helm-swoop--pattern-match)
- (remove-hook 'helm-after-update-hook 'helm-swoop--keep-nearest-position)
- (setq helm-multi-swoop-last-query helm-swoop-pattern)
- (helm-swoop--restore-unveiled-overlay)
- (setq helm-multi-swoop-query nil)
- (setq helm-multi-swoop-all-from-helm-swoop-last-point nil)
- (mapc (lambda ($buf)
- (let (($current-buffer (buffer-name (current-buffer))))
- (with-current-buffer (car $buf)
- ;; Delete overlay
- (delete-overlay helm-swoop-line-overlay)
- (helm-swoop--delete-overlay 'target-buffer)
- ;; Restore each buffer's position
- (unless (equal (car $buf) $current-buffer)
- (goto-char (cdr $buf))))))
- $preserve-position)))))
-
-(defun helm-multi-swoop--get-buffer-list ()
- (let ($buflist1 $buflist2)
- ;; eliminate buffers start with whitespace and dired buffers
- (mapc (lambda ($buf)
- (setq $buf (buffer-name $buf))
- (unless (string-match "^\\s-" $buf)
- (unless (eq 'dired-mode (with-current-buffer $buf major-mode))
- (setq $buflist1 (cons $buf $buflist1)))))
- (buffer-list))
- ;; eliminate buffers match pattern
- (mapc (lambda ($buf)
- (unless (string-match
- helm-multi-swoop-ignore-buffers-match
- $buf)
- (setq $buflist2 (cons $buf $buflist2))))
- $buflist1)
- $buflist2))
-
-(defun helm-c-source-helm-multi-swoop-buffers ()
- "Show buffer list to select"
- `((name . "helm-multi-swoop select buffers")
- (candidates . helm-multi-swoop--get-buffer-list)
- (header-line . "[C-SPC]/[M-SPC] select, [RET] next step")
- (keymap . ,helm-multi-swoop-buffers-map)
- (match . ,(helm-swoop-match-functions))
- (search . ,(helm-swoop-search-functions))))
-
-(defun helm-multi-swoop--get-query ($query)
- (cond ($query
- (setq helm-multi-swoop-query $query))
- (mark-active
- (let (($st (buffer-substring-no-properties
- (region-beginning) (region-end))))
- (if (string-match "\n" $st)
- (message "Multi line region is not allowed")
- (setq helm-multi-swoop-query
- (helm-swoop-pre-input-optimize $st)))))
- ((setq helm-multi-swoop-query
- (helm-swoop-pre-input-optimize
- (funcall helm-swoop-pre-input-function))))
- (t (setq helm-multi-swoop-query ""))))
-
-;;;###autoload
-(defun helm-multi-swoop (&optional $query $buflist)
- "\
-Usage:
-M-x helm-multi-swoop
-1. Select any buffers by [C-SPC] or [M-SPC]
-2. Press [RET] to start helm-multi-swoop
-
-C-u M-x helm-multi-swoop
-If you have done helm-multi-swoop before, you can skip select buffers step.
-Last selected buffers will be applied to helm-multi-swoop.
-"
- (interactive)
- (setq helm-multi-swoop-query (helm-multi-swoop--get-query $query))
- (if (equal current-prefix-arg '(4))
- (helm-multi-swoop--exec nil
- :$query helm-multi-swoop-query
- :$buflist $buflist)
- (if $buflist
- (helm-multi-swoop--exec nil
- :$query $query
- :$buflist $buflist)
- (helm :sources (helm-c-source-helm-multi-swoop-buffers)
- :buffer helm-multi-swoop-buffer-list
- :prompt "Mark any buffers by [C-SPC] or [M-SPC]: "))))
-
-;;;###autoload
-(defun helm-multi-swoop-all (&optional $query)
- "Apply all buffers to helm-multi-swoop"
- (interactive)
- (setq helm-multi-swoop-query (helm-multi-swoop--get-query $query))
- (helm-multi-swoop--exec nil
- :$query helm-multi-swoop-query
- :$buflist (helm-multi-swoop--get-buffer-list)))
-
-(defun get-buffers-matching-mode ($mode)
- "Returns a list of buffers where their major-mode is equal to MODE"
- (let ($buffer-mode-matches)
- (mapc (lambda ($buf)
- (when (get-buffer $buf)
- (with-current-buffer (get-buffer $buf)
- (if (eq $mode major-mode)
- (add-to-list '$buffer-mode-matches (buffer-name $buf))))))
- (buffer-list))
- $buffer-mode-matches))
-
-(defun helm-multi-swoop-by-mode ($mode &optional $query)
- "Apply all buffers whose mode is MODE to helm-multi-swoop"
- (setq helm-multi-swoop-query (helm-multi-swoop--get-query $query))
- (if (get-buffers-matching-mode $mode)
- (helm-multi-swoop--exec nil
- :$query helm-multi-swoop-query
- :$buflist (get-buffers-matching-mode $mode))
- (message "there are no buffers in that mode right now")))
-
-;;;###autoload
-(defun helm-multi-swoop-org (&optional $query)
- "Applies all org-mode buffers to helm-multi-swoop"
- (interactive)
- (helm-multi-swoop-by-mode 'org-mode $query))
-
-;;;###autoload
-(defun helm-multi-swoop-current-mode (&optional $query)
- "Applies all buffers of the same mode as the current buffer to helm-multi-swoop"
- (interactive)
- (helm-multi-swoop-by-mode major-mode $query))
-
-;;;###autoload
-(defun helm-multi-swoop-projectile (&optional $query)
- "Apply all opened buffers of the current project to helm-multi-swoop"
- (interactive)
- (setq helm-multi-swoop-query (helm-multi-swoop--get-query $query))
- (if (require 'projectile nil 'noerror)
- ;; set filter function that is used in projectile-project-buffers
- (let ((projectile-buffers-filter-function
- helm-multi-swoop-projectile-buffers-filter))
- (helm-multi-swoop--exec nil
- :$query helm-multi-swoop-query
- :$buflist (mapcar #'buffer-name
- (projectile-project-buffers))))
- (error "Package 'projectile' is not available")))
-
-
-(defun helm-swoop--wrap-function-with-pre-input-function ($target-func $pre-input-func)
- (let (($restore helm-swoop-pre-input-function))
- (unwind-protect
- (progn
- (setq helm-swoop-pre-input-function $pre-input-func)
- (funcall $target-func))
- (setq helm-swoop-pre-input-function $restore))))
-
-;;;###autoload
-(defun helm-swoop-without-pre-input ()
- "Start helm-swoop without pre input query."
- (interactive)
- (helm-swoop--wrap-function-with-pre-input-function
- 'helm-swoop (lambda () nil)))
-
-;;;###autoload
-(defun helm-swoop-symble-pre-input ()
- "Start helm-swoop without pre input query."
- (interactive)
- (helm-swoop--wrap-function-with-pre-input-function
- 'helm-swoop (lambda () (format "\\_<%s\\_> " (thing-at-point 'symbol)))))
-
-;; option -------------------------------------------------------
-
-(defun helm-multi-swoop-all-from-isearch ()
- "Invoke `helm-multi-swoop-all' from isearch."
- (interactive)
- (let (($query (if isearch-regexp
- isearch-string
- (regexp-quote isearch-string))))
- (let (search-nonincremental-instead)
- (isearch-exit))
- (helm-multi-swoop-all $query)))
-;; When doing isearch, hand the word over to helm-swoop
-;; (define-key isearch-mode-map (kbd "C-x M-i") 'helm-multi-swoop-all-from-isearch)
-
-(defun helm-multi-swoop-all-from-helm-swoop ()
- "Invoke `helm-multi-swoop-all' from helm-swoop."
- (interactive)
- (helm-swoop--restore)
- (delete-overlay helm-swoop-line-overlay)
- (setq helm-multi-swoop-all-from-helm-swoop-last-point helm-swoop-last-point)
- (let (($query helm-pattern))
- (run-with-timer 0 nil (lambda () (helm-multi-swoop-all $query))))
- (helm-exit-minibuffer))
-
-(defun helm-multi-swoop-current-mode-from-helm-swoop ()
- "Invoke `helm-multi-swoop-all' from helm-swoop."
- (interactive)
- (helm-swoop--restore)
- (delete-overlay helm-swoop-line-overlay)
- (setq helm-multi-swoop-all-from-helm-swoop-last-point helm-swoop-last-point)
- (let (($query helm-pattern))
- (run-with-timer 0 nil (lambda () (helm-multi-swoop-current-mode $query))))
- (helm-exit-minibuffer))
-;; (define-key helm-swoop-map (kbd "M-m") 'helm-multi-swoop-current-mode-from-helm-swoop)
-
-(defadvice helm-resume (around helm-multi-swoop-resume activate)
- "Resume if the last used helm buffer is *Helm Swoop*"
- (if (equal helm-last-buffer helm-multi-swoop-buffer)
-
- (if (boundp 'helm-multi-swoop-last-query)
- (if (not (ad-get-arg 0))
- (helm-multi-swoop helm-multi-swoop-last-query
- helm-multi-swoop-last-selected-buffers))
- ;; Temporary apply second last buffer
- (let ((helm-last-buffer (cadr helm-buffers))) ad-do-it))
- ad-do-it))
-
-;;; @ helm-multi-swoop-edit -----------------------------------
-(defvar helm-multi-swoop-edit-save t
- "Save each buffer you edit when editing is complete")
-(defvar helm-multi-swoop-edit-buffer "*Helm Multi Swoop Edit*")
-
-(defvar helm-multi-swoop-edit-map
- (let (($map (make-sparse-keymap)))
- (define-key $map (kbd "C-x C-s") 'helm-multi-swoop--edit-complete)
- (define-key $map (kbd "C-c C-g") 'helm-multi-swoop--edit-cancel)
- (define-key $map (kbd "C-c C-q C-k") 'helm-multi-swoop--edit-delete-all-lines)
- $map))
-
-(defun helm-multi-swoop--edit ($candidate)
- "This function will only be called from `helm-swoop-edit'"
- (interactive)
- (delete-overlay helm-swoop-line-overlay)
- (helm-swoop--delete-overlay 'target-buffer)
- (with-current-buffer (get-buffer-create helm-multi-swoop-edit-buffer)
- (helm-swoop--clear-edit-buffer 'helm-multi-swoop-edit)
- (let (($bufstr "")
- ($mark nil)
- ($buf (get-buffer helm-multi-swoop-buffer)))
- ;; Get target line number to edit
- (when $buf
- (with-current-buffer $buf
- ;; Set overlay to helm-source-header for editing marked lines
- (save-excursion
- (goto-char (point-min))
- (let (($beg (point)) $end)
- (overlay-recenter (point-max))
- (while (setq $beg (text-property-any $beg (point-max)
- 'face 'helm-source-header))
- (setq $end (next-single-property-change $beg 'face))
- (overlay-put (make-overlay $beg $end) 'source-header t)
- (setq $beg $end)
- (goto-char $end))))
- ;; Use selected line by [C-SPC] or [M-SPC]
- (mapc (lambda ($ov)
- (when (overlay-get $ov 'source-header)
- (setq $bufstr (concat (buffer-substring
- (overlay-start $ov) (overlay-end $ov))
- $bufstr)))
- (when (eq 'helm-visible-mark (overlay-get $ov 'face))
- (let (($str (buffer-substring (overlay-start $ov) (overlay-end $ov))))
- (unless (equal "" $str) (setq $mark t))
- (setq $bufstr (concat (buffer-substring
- (overlay-start $ov) (overlay-end $ov))
- $bufstr)))))
- (overlays-in (point-min) (point-max)))
- (if $mark
- (progn (setq $bufstr (concat "Helm Multi Swoop\n" $bufstr))
- (setq $mark nil))
- (setq $bufstr (concat "Helm Multi Swoop\n"
- (buffer-substring
- (point-min) (point-max)))))))
-
- ;; Set for edit buffer
- (insert $bufstr)
- (add-text-properties (point-min) (point-max)
- '(read-only t rear-nonsticky t front-sticky t))
-
- ;; Set for editable context
- (let ((inhibit-read-only t))
- ;; Title and explanation
- (goto-char (point-min))
- (let (($o (make-overlay (point) (point-at-eol))))
- (overlay-put $o 'helm-multi-swoop-edit t)
- (overlay-put $o 'face 'font-lock-function-name-face)
- (overlay-put $o 'after-string
- (propertize
- (substitute-command-keys
- (concat
- " [\\<helm-swoop-edit-map>\\[helm-swoop--edit-complete]] Complete"
- ", [\\<helm-swoop-edit-map>\\[helm-swoop--edit-cancel]] Cancel"
- ", [\\<helm-swoop-edit-map>\\[helm-swoop--edit-delete-all-lines]] Delete All"
- ))
- 'face 'helm-bookmark-addressbook)))
- ;; Line number and editable area
- (while (re-search-forward "^\\([0-9]+\s\\)\\(.*\\)$" nil t)
- (let* (($bol1 (match-beginning 1))
- ($eol1 (match-end 1))
- ($bol2 (match-beginning 2))
- ($eol2 (match-end 2)))
-
- ;; Line number
- (add-text-properties $bol1 $eol1
- '(face font-lock-function-name-face
- intangible t))
- ;; Editable area
- (remove-text-properties $bol2 $eol2 '(read-only t))
- ;; (add-text-properties $bol2 $eol2 '(font-lock-face helm-match))
-
- ;; For line tail
- (set-text-properties $eol2 (or (1+ $eol2) (point-max))
- '(read-only t rear-nonsticky t))))
- (helm-swoop--target-word-overlay 'edit-buffer 0))))
-
- (other-window 1)
- (switch-to-buffer helm-multi-swoop-edit-buffer)
- (goto-char (point-min))
- (if (string-match "^[0-9]+" $candidate)
- (re-search-forward
- (concat "^" (match-string 0 $candidate)) nil t))
- (use-local-map helm-multi-swoop-edit-map))
-
-(defun helm-multi-swoop--separate-text-property-into-list ($property)
- (interactive)
- (let ($list $end)
- (save-excursion
- (goto-char (point-min))
- (while (setq $end (next-single-property-change (point) $property))
- ;; Must eliminate last return because of unexpected edit result
- (setq $list (cons
- (let (($str (buffer-substring-no-properties (point) $end)))
- (if (string-match "\n\n\\'" $str)
- (replace-regexp-in-string "\n\\'" "" $str)
- $str))
- $list))
- (goto-char $end))
- (setq $list (cons (buffer-substring-no-properties (point) (point-max))
- $list)))
- (nreverse $list)))
-
-(defun helm-multi-swoop--collect-edited-lines ()
- "Create a list of edited lines with each its own line number"
- (interactive)
- (let* (($list
- (helm-multi-swoop--separate-text-property-into-list 'helm-header))
- ($length (length $list))
- ($i 1) ;; 0th $list is header
- $pairs)
- (while (<= $i $length)
- (let ($contents)
- ;; Make ((number . line) (number . line) (number . line) ...)
- (with-temp-buffer
- (insert (format "%s" (nth (1+ $i) $list)))
- (goto-char (point-min))
- (while (re-search-forward "^\\([0-9]+\\)\s" nil t)
- (setq $contents
- (cons (cons (string-to-number (match-string 1))
- (buffer-substring-no-properties
- (point)
- (save-excursion
- (if (re-search-forward
- "^\\([0-9]+\\)\s\\|^\\(\\-+\\)" nil t)
- (1- (match-beginning 0))
- (goto-char (point-max))
- (re-search-backward "\n" nil t)))))
- $contents))))
- ;; Make ((buffer-name (number . line) (number . line) ...)
- ;; (buffer-name (number . line) (number . line) ...) ...)
- (setq $pairs (cons (cons (nth $i $list) $contents) $pairs)))
- (setq $i (+ $i 2)))
- (delete '(nil) $pairs)))
-
-(defun helm-multi-swoop--edit-complete ()
- "Delete all extracted lines, and apply changes to buffers and kill temporary edit buffer"
- (interactive)
- (let (($list (helm-multi-swoop--collect-edited-lines))
- $read-only)
- (mapc (lambda ($x)
- (with-current-buffer (car $x)
- (unless buffer-read-only
- (save-excursion
- (mapc (lambda ($cell)
- (let (($k (car $cell))
- ($v (cdr $cell)))
- (goto-char (point-min))
- (delete-region (point-at-bol $k) (point-at-eol $k))
- (goto-char (point-at-bol $k))
- (insert $v)))
- (cdr $x))))
- (if helm-multi-swoop-edit-save
- (if buffer-read-only
- (setq $read-only t)
- (save-buffer)))))
- $list)
- (select-window helm-swoop-synchronizing-window)
- (kill-buffer (get-buffer helm-multi-swoop-edit-buffer))
- (if $read-only
- (message "Couldn't save some buffers because of read-only")
- (message "Successfully helm-multi-swoop-edit applied to original buffer"))))
-
-(defun helm-multi-swoop--edit-delete-all-lines ()
- "Delete all extracted lines, and apply changes to buffers and kill temporary edit buffer"
- (interactive)
- (let (($list (helm-multi-swoop--collect-edited-lines))
- $read-only)
- (mapc (lambda ($x)
- (with-current-buffer (car $x)
- (unless buffer-read-only
- (save-excursion
- (mapc (lambda ($cell)
- (let (($k (car $cell)))
- (goto-char (point-min))
- (delete-region (point-at-bol $k)
- (if (eq (point-at-eol $k) (point-max))
- (point-at-eol $k)
- (1+ (point-at-eol $k))))))
- (cdr $x))))
- (if helm-multi-swoop-edit-save
- (if buffer-read-only
- (setq $read-only t)
- (save-buffer)))))
- $list)
- (select-window helm-swoop-synchronizing-window)
- (kill-buffer (get-buffer helm-multi-swoop-edit-buffer))
- (if $read-only
- (message "Couldn't save some buffers because of read-only")
- (message "Successfully helm-multi-swoop-edit applied to original buffer"))))
-
-(defun helm-multi-swoop--edit-cancel ()
- "Cancel edit and kill temporary buffer"
- (interactive)
- (select-window helm-swoop-synchronizing-window)
- (kill-buffer (get-buffer helm-multi-swoop-edit-buffer))
- (message "helm-multi-swoop-edit canceled"))
-
-;;;###autoload
-(defun helm-multi-swoop-edit ()
- (interactive)
- (helm-exit-and-execute-action 'helm-multi-swoop--edit))
-
-;;; @ helm-swoop-same-face-at-point -----------------------------------
-
-(defsubst helm-swoop--get-at-face (&optional $point)
- (or $point (setq $point (point)))
- (let (($face (or (get-char-property $point 'read-face-name)
- (get-char-property $point 'face))))
- $face))
-
-(defun helm-swoop--cull-face-include-line ($face)
- (let (($list) ($po (point-min)))
- (save-excursion
- (while (setq $po (next-single-property-change $po 'face))
- (when (equal $face (helm-swoop--get-at-face $po))
- (goto-char $po)
- (setq $list (cons (format "%s %s"
- (line-number-at-pos $po)
- (buffer-substring (point-at-bol) (point-at-eol)))
- $list))
- (let (($ov (make-overlay $po (or (next-single-property-change $po 'face)
- (point-max)))))
- (overlay-put $ov 'face 'helm-swoop-target-word-face)
- (overlay-put $ov 'target-buffer 'helm-swoop-target-word-face)))))
- (nreverse (delete-dups $list))))
-
-(defun helm-swoop-same-face-at-point (&optional $face)
- (interactive)
- (or $face (setq $face (helm-swoop--get-at-face)))
- (helm-swoop :$query ""
- :$source
- `((name . "helm-swoop-same-face-at-point")
- (candidates . ,(helm-swoop--cull-face-include-line $face))
- (header-line . ,(format "%s" $face))
- (action
- . (("Go to Line"
- . (lambda ($line)
- (helm-swoop--goto-line
- (when (string-match "^[0-9]+" $line)
- (string-to-number (match-string 0 $line))))
- (let (($po (point))
- ($poe (point-at-eol)))
- (while (<= (setq $po (next-single-property-change $po 'face)) $poe)
- (when (eq 'helm-swoop-target-word-face (helm-swoop--get-at-face $po))
- (goto-char $po))))
- (helm-swoop--recenter))))))))
-
-(defun helm-multi-swoop-same-face-at-point (&optional $face)
- (interactive)
- (or $face (setq $face (helm-swoop--get-at-face)))
- (helm-multi-swoop--exec
- nil
- :$query ""
- :$func (lambda () (helm-swoop--cull-face-include-line $face))
- :$action (lambda ($line)
- (switch-to-buffer (assoc-default 'name (helm-get-current-source)))
- (helm-swoop--goto-line
- (when (string-match "^[0-9]+" $line)
- (string-to-number (match-string 0 $line))))
- (let (($po (point))
- ($poe (point-at-eol)))
- (while (<= (setq $po (next-single-property-change $po 'face)) $poe)
- (when (eq 'helm-swoop-target-word-face (helm-swoop--get-at-face $po))
- (goto-char $po))))
- (helm-swoop--recenter))
- :$buflist (helm-multi-swoop--get-buffer-list)))
-
-(provide 'helm-swoop)
-;;; helm-swoop.el ends here
--- /dev/null
+;;; helm-swoop-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+
+(add-to-list 'load-path (directory-file-name
+ (or (file-name-directory #$) (car load-path))))
+
+\f
+;;;### (autoloads nil "helm-swoop" "helm-swoop.el" (0 0 0 0))
+;;; Generated autoloads from helm-swoop.el
+
+(autoload 'helm-swoop-back-to-last-point "helm-swoop" "\
+Go back to last position where `helm-swoop' was called
+
+\(fn &optional $CANCEL)" t nil)
+
+(autoload 'helm-swoop "helm-swoop" "\
+List the all lines to another buffer, which is able to squeeze by
+ any words you input. At the same time, the original buffer's cursor
+ is jumping line to line according to moving up and down the list.
+
+\(fn &key $QUERY $SOURCE ($MULTILINE current-prefix-arg))" t nil)
+
+(autoload 'helm-swoop-from-isearch "helm-swoop" "\
+Invoke `helm-swoop' from isearch.
+
+\(fn)" t nil)
+
+(autoload 'helm-multi-swoop "helm-swoop" "\
+Usage:
+M-x helm-multi-swoop
+1. Select any buffers by [C-SPC] or [M-SPC]
+2. Press [RET] to start helm-multi-swoop
+
+C-u M-x helm-multi-swoop
+If you have done helm-multi-swoop before, you can skip select buffers step.
+Last selected buffers will be applied to helm-multi-swoop.
+
+\(fn &optional $QUERY $BUFLIST)" t nil)
+
+(autoload 'helm-multi-swoop-all "helm-swoop" "\
+Apply all buffers to helm-multi-swoop
+
+\(fn &optional $QUERY)" t nil)
+
+(autoload 'helm-multi-swoop-org "helm-swoop" "\
+Applies all org-mode buffers to helm-multi-swoop
+
+\(fn &optional $QUERY)" t nil)
+
+(autoload 'helm-multi-swoop-current-mode "helm-swoop" "\
+Applies all buffers of the same mode as the current buffer to helm-multi-swoop
+
+\(fn &optional $QUERY)" t nil)
+
+(autoload 'helm-multi-swoop-projectile "helm-swoop" "\
+Apply all opened buffers of the current project to helm-multi-swoop
+
+\(fn &optional $QUERY)" t nil)
+
+(autoload 'helm-swoop-without-pre-input "helm-swoop" "\
+Start helm-swoop without pre input query.
+
+\(fn)" t nil)
+
+(autoload 'helm-swoop-symble-pre-input "helm-swoop" "\
+Start helm-swoop without pre input query.
+
+\(fn)" t nil)
+
+(autoload 'helm-multi-swoop-edit "helm-swoop" "\
+
+
+\(fn)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-swoop" '("helm-" "get-buffers-matching-mode")))
+
+;;;***
+\f
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; coding: utf-8
+;; End:
+;;; helm-swoop-autoloads.el ends here
--- /dev/null
+;;; -*- no-byte-compile: t -*-
+(define-package "helm-swoop" "20180215.1154" "Efficiently hopping squeezed lines powered by helm interface" '((helm "1.0") (emacs "24.3")) :commit "c66336b8245ddc51c4206f19c119f1081920985c" :keywords '("helm" "swoop" "inner" "buffer" "search") :authors '(("Shingo Fukuyama - http://fukuyama.co")) :maintainer '("Shingo Fukuyama - http://fukuyama.co") :url "https://github.com/ShingoFukuyama/helm-swoop")
--- /dev/null
+;;; helm-swoop.el --- Efficiently hopping squeezed lines powered by helm interface -*- coding: utf-8; lexical-binding: t -*-
+
+;; Copyright (C) 2013 - 2018 by Shingo Fukuyama
+
+;; Version: 1.7.4
+;; Package-Version: 20180215.1154
+;; Author: Shingo Fukuyama - http://fukuyama.co
+;; URL: https://github.com/ShingoFukuyama/helm-swoop
+;; Created: Oct 24 2013
+;; Keywords: helm swoop inner buffer search
+;; Package-Requires: ((helm "1.0") (emacs "24.3"))
+
+;; 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 2 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.
+
+;;; Commentary:
+
+;; List the all lines to another buffer, which is able to squeeze
+;; by any words you input. At the same time, the original buffer's
+;; cursor is jumping line to line according to moving up and down
+;; the list.
+
+;; Example config
+;; ----------------------------------------------------------------
+;; ;; helm from https://github.com/emacs-helm/helm
+;; (require 'helm)
+
+;; ;; Locate the helm-swoop folder to your path
+;; ;; This line is unnecessary if you get this program from MELPA
+;; (add-to-list 'load-path "~/.emacs.d/elisp/helm-swoop")
+
+;; (require 'helm-swoop)
+
+;; ;; Change keybinds to whatever you like :)
+;; (global-set-key (kbd "M-i") 'helm-swoop)
+;; (global-set-key (kbd "M-I") 'helm-swoop-back-to-last-point)
+;; (global-set-key (kbd "C-c M-i") 'helm-multi-swoop)
+;; (global-set-key (kbd "C-x M-i") 'helm-multi-swoop-all)
+
+;; ;; When doing isearch, hand the word over to helm-swoop
+;; (define-key isearch-mode-map (kbd "M-i") 'helm-swoop-from-isearch)
+;; (define-key helm-swoop-map (kbd "M-i") 'helm-multi-swoop-all-from-helm-swoop)
+
+;; ;; Save buffer when helm-multi-swoop-edit complete
+;; (setq helm-multi-swoop-edit-save t)
+
+;; ;; If this value is t, split window inside the current window
+;; (setq helm-swoop-split-with-multiple-windows nil)
+
+;; ;; Split direction. 'split-window-vertically or 'split-window-horizontally
+;; (setq helm-swoop-split-direction 'split-window-vertically)
+
+;; ;; If nil, you can slightly boost invoke speed in exchange for text color
+;; (setq helm-swoop-speed-or-color nil)
+
+;; ;; Go to the opposite side of line from the end or beginning of line
+;; (setq helm-swoop-move-to-line-cycle t)
+
+;; ;; Optional face for line numbers
+;; ;; Face name is `helm-swoop-line-number-face`
+;; (setq helm-swoop-use-line-number-face t)
+
+;; ----------------------------------------------------------------
+
+;; * `M-x helm-swoop` when region active
+;; * `M-x helm-swoop` when the cursor is at any symbol
+;; * `M-x helm-swoop` when the cursor is not at any symbol
+;; * `M-3 M-x helm-swoop` or `C-u 5 M-x helm-swoop` multi separated line culling
+;; * `M-x helm-multi-swoop` multi-occur like feature
+;; * `M-x helm-multi-swoop-all` apply all buffers
+;; * `C-u M-x helm-multi-swoop` apply last selected buffers from the second time
+;; * `M-x helm-swoop-same-face-at-point` list lines have the same face at the cursor is on
+;; * During isearch `M-i` to hand the word over to helm-swoop
+;; * During helm-swoop `M-i` to hand the word over to helm-multi-swoop-all
+;; * While doing `helm-swoop` press `C-c C-e` to edit mode, apply changes to original buffer by `C-x C-s`
+
+;; Helm Swoop Edit
+;; While doing helm-swoop, press keybind [C-c C-e] to move to edit buffer.
+;; Edit the list and apply by [C-x C-s]. If you'd like to cancel, [C-c C-g]
+
+;;; Code:
+
+(require 'cl-lib)
+(require 'helm)
+(require 'helm-utils)
+(require 'helm-grep)
+
+(declare-function migemo-search-pattern-get "migemo")
+(declare-function projectile-buffers-with-file-or-process "projectile")
+(declare-function projectile-project-buffers "projectile")
+(defvar projectile-buffers-filter-function)
+
+;;; @ helm-swoop ----------------------------------------------
+
+(defgroup helm-swoop nil
+ "Open helm-swoop."
+ :prefix "helm-swoop-" :group 'helm)
+
+(defface helm-swoop-target-line-face
+ '((t (:background "#e3e300" :foreground "#222222")))
+ "Face for helm-swoop target line"
+ :group 'helm-swoop)
+(defface helm-swoop-target-line-block-face
+ '((t (:background "#cccc00" :foreground "#222222")))
+ "Face for target line"
+ :group 'helm-swoop)
+(defface helm-swoop-target-word-face
+ '((t (:background "#7700ff" :foreground "#ffffff")))
+ "Face for target word"
+ :group 'helm-swoop)
+(defface helm-swoop-line-number-face
+ '((t (:foreground "#999999")))
+ "Face for line numbers"
+ :group 'helm-swoop)
+
+(defcustom helm-swoop-speed-or-color nil
+ "If nil, you can slightly boost invoke speed in exchange for text color"
+ :group 'helm-swoop :type 'boolean)
+(defcustom helm-swoop-use-line-number-face nil
+ "Use face to line numbers on helm-swoop buffer"
+ :group 'helm-swoop :type 'boolean)
+(defcustom helm-swoop-split-with-multiple-windows nil
+ "Split window when having multiple windows open"
+ :group 'helm-swoop :type 'boolean)
+(defcustom helm-swoop-move-to-line-cycle t
+ "Return to the opposite side of line"
+ :group 'helm-swoop :type 'boolean)
+(defcustom helm-swoop-split-direction 'split-window-vertically
+ "Split direction"
+ :type '(choice (const :tag "vertically" split-window-vertically)
+ (const :tag "horizontally" split-window-horizontally))
+ :group 'helm-swoop)
+(defcustom helm-swoop-use-fuzzy-match nil
+ "If t, use fuzzy matching functions as well as exact matches."
+ :group 'helm-swoop :type 'boolean)
+
+(defvar helm-swoop-split-window-function
+ (lambda ($buf &rest _$args)
+ (if helm-swoop-split-with-multiple-windows
+ (funcall helm-swoop-split-direction)
+ (when (one-window-p)
+ (funcall helm-swoop-split-direction)))
+ (other-window 1)
+ (switch-to-buffer $buf))
+ "Change the way to split window only when `helm-swoop' is calling")
+
+(defcustom helm-swoop-after-goto-line-action-hook nil
+ "hooks run after `helm-swoop--goto-line"
+ :group 'helm-swoop
+ :type 'hook)
+(defcustom helm-swoop-before-goto-line-action-hook nil
+ "hooks run before `helm-swoop--goto-line"
+ :group 'helm-swoop
+ :type 'hook)
+
+(defvar helm-swoop-candidate-number-limit 19999)
+(defvar helm-swoop-buffer "*Helm Swoop*")
+(defvar helm-swoop-prompt "Swoop: ")
+(defvar helm-swoop-last-point nil)
+(defvar helm-swoop-invisible-targets nil)
+(defvar helm-swoop-last-line-info nil)
+
+;; Buffer local variables
+(defvar helm-swoop-list-cache)
+(defvar helm-swoop-pattern) ; Keep helm-pattern value
+(defvar helm-swoop-last-query) ; Last search query for resume
+(defvar-local helm-swoop-last-prefix-number 1) ; For multiline highlight
+
+;; Global variables
+(defvar helm-swoop-synchronizing-window nil
+ "Window object where `helm-swoop' called from")
+(defvar helm-swoop-target-buffer nil
+ "Buffer object where `helm-swoop' called from")
+(defvar helm-swoop-line-overlay nil
+ "Overlay object to indicate other window's line")
+
+(defvar helm-swoop-map
+ (let (($map (make-sparse-keymap)))
+ (set-keymap-parent $map helm-map)
+ (define-key $map (kbd "C-c C-e") 'helm-swoop-edit)
+ (define-key $map (kbd "M-i") 'helm-multi-swoop-all-from-helm-swoop)
+ (define-key $map (kbd "C-w") 'helm-swoop-yank-thing-at-point)
+ (define-key $map (kbd "^") 'helm-swoop-caret-match)
+ (delq nil $map))
+ "Keymap for helm-swoop")
+
+(defvar helm-multi-swoop-map
+ (let (($map (make-sparse-keymap)))
+ (set-keymap-parent $map helm-map)
+ (define-key $map (kbd "C-c C-e") 'helm-multi-swoop-edit)
+ (delq nil $map)))
+
+(defvar helm-c-source-swoop-match-functions
+ '(helm-mm-exact-match
+ helm-mm-match
+ helm-mm-3-migemo-match))
+
+(defvar helm-c-source-swoop-search-functions
+ '(helm-mm-exact-search
+ helm-mm-search
+ helm-candidates-in-buffer-search-default-fn
+ helm-mm-3-migemo-search))
+
+(defun helm-swoop-match-functions ()
+ (if helm-swoop-use-fuzzy-match
+ (append helm-c-source-swoop-match-functions '(helm-fuzzy-match))
+ helm-c-source-swoop-match-functions))
+
+(defun helm-swoop-search-functions ()
+ (if helm-swoop-use-fuzzy-match
+ (append helm-c-source-swoop-search-functions '(helm-fuzzy-search))
+ helm-c-source-swoop-search-functions))
+
+(defcustom helm-swoop-pre-input-function
+ (lambda () (thing-at-point 'symbol))
+ "This function can pre-input keywords when helm-swoop invoked"
+ :group 'helm-swoop :type 'function)
+
+(defun helm-swoop-pre-input-optimize ($query)
+ (when $query
+ (let (($regexp (list '("\+" . "\\\\+")
+ '("\*" . "\\\\*")
+ '("\#" . "\\\\#"))))
+ (mapc (lambda ($r)
+ (setq $query (replace-regexp-in-string (car $r) (cdr $r) $query)))
+ $regexp)
+ $query)))
+
+(defsubst helm-swoop--goto-line ($line)
+ (goto-char (point-min))
+ (forward-line (1- $line)))
+
+(defsubst helm-swoop--recenter ()
+ (recenter (/ (window-height) 2)))
+
+(defsubst helm-swoop--delete-overlay ($identity &optional $beg $end)
+ (or $beg (setq $beg (point-min)))
+ (or $end (setq $end (point-max)))
+ (overlay-recenter $end)
+ (mapc (lambda ($o)
+ (if (overlay-get $o $identity)
+ (delete-overlay $o)))
+ (overlays-in $beg $end)))
+
+(defsubst helm-swoop--get-string-at-line ()
+ (buffer-substring-no-properties (point-at-bol) (point-at-eol)))
+
+(defsubst helm-swoop--buffer-substring ($point-min $point-max)
+ (if helm-swoop-speed-or-color
+ (let (($content (buffer-substring $point-min $point-max)))
+ (with-temp-buffer
+ (let ((inhibit-read-only t))
+ (insert $content)
+ (remove-text-properties (point-min) (point-max) '(read-only t))
+ (setq $content (buffer-substring (point-min) (point-max)))))
+ $content)
+ (buffer-substring-no-properties $point-min $point-max)))
+
+;;;###autoload
+(defun helm-swoop-back-to-last-point (&optional $cancel)
+ "Go back to last position where `helm-swoop' was called"
+ (interactive)
+ (if helm-swoop-last-point
+ (let (($po (point)))
+ (switch-to-buffer (cdr helm-swoop-last-point))
+ (goto-char (car helm-swoop-last-point))
+ (unless $cancel
+ (setq helm-swoop-last-point
+ (cons $po (buffer-name (current-buffer))))))))
+
+(defun helm-swoop--split-lines-by ($string $regexp $step)
+ "split-string by $step for multiline"
+ (or $step (setq $step 1))
+ (let (($from1 0) ;; last match point
+ ($from2 0) ;; last substring point
+ $list
+ ($i 1)) ;; from line 1
+ (while (string-match $regexp $string $from1)
+ (setq $i (1+ $i))
+ (if (eq 0 (% $i $step))
+ (progn
+ (setq $list (cons (substring $string $from2 (match-beginning 0))
+ $list))
+ (setq $from2 (match-end 0))
+ (setq $from1 (match-end 0)))
+ (setq $from1 (match-end 0))))
+ (setq $list (cons (substring $string $from2) $list))
+ (nreverse $list)))
+
+(defun helm-swoop--target-line-overlay-move (&optional $buf)
+ "Add color to the target line"
+ (move-overlay
+ helm-swoop-line-overlay
+ (progn
+ (search-backward
+ "\n" nil t (% (line-number-at-pos) helm-swoop-last-prefix-number))
+ (goto-char (point-at-bol)))
+ ;; For multiline highlight
+ (save-excursion
+ (goto-char (point-at-bol))
+ (or (re-search-forward "\n" nil t helm-swoop-last-prefix-number)
+ ;; For the end of buffer error
+ (point-max)))
+ $buf)
+ (helm-swoop--unveil-invisible-overlay))
+
+(defun helm-swoop--validate-regexp (regexp)
+ (condition-case nil
+ (progn
+ (string-match-p regexp "")
+ t)
+ (invalid-regexp nil)))
+
+(defun helm-swoop--target-word-overlay ($identity &optional $threshold)
+ (interactive)
+ (or $threshold (setq $threshold 2))
+ (save-excursion
+ (let (($pat (split-string helm-pattern " "))
+ $o)
+ (mapc (lambda ($wd)
+ (when (and (helm-swoop--validate-regexp $wd) (< $threshold (length $wd)))
+ (goto-char (point-min))
+ ;; Optional require migemo.el
+ (if (and (featurep 'migemo) helm-migemo-mode)
+ (setq $wd (migemo-search-pattern-get $wd)))
+ ;; For caret begging match
+ (if (string-match "^\\^\\[0\\-9\\]\\+\\.\\(.+\\)" $wd)
+ (setq $wd (concat "^" (match-string 1 $wd))))
+ (overlay-recenter (point-max))
+ (let (finish)
+ (while (and (not finish) (re-search-forward $wd nil t))
+ (if (= (match-beginning 0) (match-end 0))
+ (forward-char 1)
+ (setq $o (make-overlay (match-beginning 0) (match-end 0)))
+ (overlay-put $o 'face 'helm-swoop-target-word-face)
+ (overlay-put $o $identity t))
+ (when (eobp)
+ (setq finish t))))))
+ $pat))))
+
+(defun helm-swoop--restore-unveiled-overlay ()
+ (when helm-swoop-invisible-targets
+ (mapc (lambda ($ov) (overlay-put (car $ov) 'invisible (cdr $ov)))
+ helm-swoop-invisible-targets)
+ (setq helm-swoop-invisible-targets nil)))
+
+(defun helm-swoop--unveil-invisible-overlay ()
+ "Show hidden text temporarily to view it during helm-swoop.
+This function needs to call after latest helm-swoop-line-overlay set."
+ (helm-swoop--restore-unveiled-overlay)
+ (mapc (lambda ($ov)
+ (let (($type (overlay-get $ov 'invisible)))
+ (when $type
+ (overlay-put $ov 'invisible nil)
+ (setq helm-swoop-invisible-targets
+ (cons (cons $ov $type) helm-swoop-invisible-targets)))))
+ (overlays-in (overlay-start helm-swoop-line-overlay)
+ (overlay-end helm-swoop-line-overlay))))
+
+;; helm action ------------------------------------------------
+
+(defadvice helm-next-line (around helm-swoop-next-line disable)
+ (let ((helm-move-to-line-cycle-in-source t))
+ ad-do-it
+ (when (called-interactively-p 'any)
+ (helm-swoop--move-line-action))))
+
+(defadvice helm-previous-line (around helm-swoop-previous-line disable)
+ (let ((helm-move-to-line-cycle-in-source t))
+ ad-do-it
+ (when (called-interactively-p 'any)
+ (helm-swoop--move-line-action))))
+
+(defadvice helm-toggle-visible-mark (around helm-swoop-toggle-visible-mark disable)
+ (let ((helm-move-to-line-cycle-in-source t))
+ ad-do-it
+ (when (called-interactively-p 'any)
+ (helm-swoop--move-line-action))))
+
+(defun helm-swoop--move-line-action ()
+ (with-helm-window
+ (let* (($key (helm-swoop--get-string-at-line))
+ ($num (when (string-match "^[0-9]+" $key)
+ (string-to-number (match-string 0 $key)))))
+ ;; Synchronizing line position
+ (when (and $key $num)
+ (with-selected-window helm-swoop-synchronizing-window
+ (progn
+ (helm-swoop--goto-line $num)
+ (with-current-buffer helm-swoop-target-buffer
+ (delete-overlay helm-swoop-line-overlay)
+ (helm-swoop--target-line-overlay-move))
+ (helm-swoop--recenter)))
+ (setq helm-swoop-last-line-info
+ (cons helm-swoop-target-buffer $num))))))
+
+(defun helm-swoop--nearest-line ($target $list)
+ "Return the nearest number of $target out of $list."
+ (when (and $target $list)
+ (let ($result)
+ (cl-labels ((filter ($fn $elem $list)
+ (let ($r)
+ (mapc (lambda ($e)
+ (if (funcall $fn $elem $e)
+ (setq $r (cons $e $r))))
+ $list) $r)))
+ (if (eq 1 (length $list))
+ (setq $result (car $list))
+ (let* (($lts (filter '> $target $list))
+ ($gts (filter '< $target $list))
+ ($lt (if $lts (apply 'max $lts)))
+ ($gt (if $gts (apply 'min $gts)))
+ ($ltg (if $lt (- $target $lt)))
+ ($gtg (if $gt (- $gt $target))))
+ (setq $result
+ (cond ((memq $target $list) $target)
+ ((and (not $lt) (not $gt)) nil)
+ ((not $gtg) $lt)
+ ((not $ltg) $gt)
+ ((eq $ltg $gtg) $gt)
+ ((< $ltg $gtg) $lt)
+ ((> $ltg $gtg) $gt)
+ (t 1))))))
+ $result)))
+
+(defun helm-swoop--keep-nearest-position ()
+ (with-helm-window
+ (let (($p (point-min)) $list $bound
+ $nearest-line $target-point
+ ($buf (rx-to-string (buffer-name (car helm-swoop-last-line-info)) t)))
+ (save-excursion
+ (goto-char $p)
+ (while (if $p (setq $p (re-search-forward (concat "^" $buf "$") nil t)))
+ (when (get-text-property (point-at-bol) 'helm-header)
+ (forward-char 1)
+ (setq $bound (next-single-property-change (point) 'helm-header))
+ (while (re-search-forward "^[0-9]+" $bound t)
+ (setq $list (cons
+ (string-to-number (match-string 0))
+ $list)))
+ (setq $nearest-line (helm-swoop--nearest-line
+ (cdr helm-swoop-last-line-info)
+ $list))
+ (goto-char $p)
+ (re-search-forward (concat "^"
+ (number-to-string $nearest-line)
+ "\\s-") $bound t)
+ (setq $target-point (point))
+ (setq $p nil))))
+ (when $target-point
+ (goto-char $target-point)
+ (helm-mark-current-line)
+ (if (equal helm-swoop-buffer (buffer-name (current-buffer)))
+ (helm-swoop--move-line-action)
+ (helm-multi-swoop--move-line-action))))))
+
+(defun helm-swoop--pattern-match ()
+ "Overlay target words"
+ (with-helm-window
+ (setq helm-swoop-pattern helm-pattern)
+ (when (< 2 (length helm-pattern))
+ (helm-swoop--delete-overlay 'target-buffer)
+ (helm-swoop--target-word-overlay 'target-buffer)
+ (with-selected-window helm-swoop-synchronizing-window
+ (helm-swoop--delete-overlay 'target-buffer)
+ (helm-swoop--target-word-overlay 'target-buffer)))))
+
+(defun helm-swoop-flash-word ($match-beg $match-end)
+ (interactive)
+ (unwind-protect
+ (let (($o (make-overlay $match-beg $match-end)))
+ (when $o
+ (overlay-put $o 'face 'helm-swoop-target-word-face)
+ (overlay-put $o 'helm-swoop-overlay-word-frash t)))
+ (run-with-idle-timer
+ 0.6 nil (lambda () (helm-swoop--delete-overlay 'helm-swoop-overlay-word-frash)))))
+
+;; core ------------------------------------------------
+
+(defun helm-swoop--get-content ($buffer &optional $linum)
+ "Get the whole content in buffer and add line number at the head.
+If $linum is number, lines are separated by $linum"
+ (let (($buf (get-buffer $buffer)))
+ (when $buf
+ (with-current-buffer $buf
+ (let (($bufstr (helm-swoop--buffer-substring (point-min) (point-max)))
+ $return)
+ (with-temp-buffer
+ (insert $bufstr)
+ (goto-char (point-min))
+ (let (($i 1))
+ (insert (format "%s " $i))
+ (while (re-search-forward "\n" nil t)
+ (cl-incf $i)
+ (if helm-swoop-use-line-number-face
+ (insert (propertize (format "%s" $i) 'font-lock-face 'helm-swoop-line-number-face) " ")
+ (insert (format "%s " $i))))
+ ;; Delete empty lines
+ (unless $linum
+ (goto-char (point-min))
+ (while (re-search-forward "^[0-9]+\\s-*$" nil t)
+ (replace-match ""))))
+ (setq $return (helm-swoop--buffer-substring (point-min) (point-max))))
+ $return)))))
+
+(defun helm-swoop--goto-line-action ($line)
+ (run-hooks 'helm-swoop-before-goto-line-action-hook)
+ (helm-swoop--goto-line
+ (when (string-match "^[0-9]+" $line)
+ (string-to-number (match-string 0 $line))))
+ (let (($regex
+ (mapconcat 'identity
+ (split-string helm-pattern " ")
+ "\\|")))
+ (when (or (and (and (featurep 'migemo) helm-migemo-mode)
+ (migemo-forward $regex nil t))
+ (re-search-forward $regex nil t))
+ (helm-swoop-flash-word (match-beginning 0) (match-end 0))
+ (goto-char (match-beginning 0))
+ (run-hooks 'helm-swoop-after-goto-line-action-hook)))
+ (helm-swoop--recenter))
+
+(defun helm-c-source-swoop ()
+ `((name . ,(buffer-name helm-swoop-target-buffer))
+ (candidates . ,(if helm-swoop-list-cache
+ (progn
+ (helm-swoop--split-lines-by
+ helm-swoop-list-cache "\n" helm-swoop-last-prefix-number))
+ (helm-swoop--split-lines-by
+ (setq helm-swoop-list-cache
+ (helm-swoop--get-content helm-swoop-target-buffer t))
+ "\n" helm-swoop-last-prefix-number)))
+ (get-line . ,(if helm-swoop-speed-or-color
+ 'helm-swoop--buffer-substring
+ 'buffer-substring-no-properties))
+ (keymap . ,helm-swoop-map)
+ (header-line . ,(substitute-command-keys
+ "[\\<helm-swoop-map>\\[helm-swoop-edit]] Edit mode, \
+[\\<helm-swoop-map>\\[helm-multi-swoop-all-from-helm-swoop]] apply all buffers"))
+ (action . (("Go to Line" . helm-swoop--goto-line-action)))
+ ,(if (and helm-swoop-last-prefix-number
+ (> helm-swoop-last-prefix-number 1))
+ '(multiline))
+ (match . ,(helm-swoop-match-functions))
+ (search . ,(helm-swoop-search-functions))))
+
+(defun helm-c-source-multi-swoop ($buf $func $action $multiline)
+ `((name . ,$buf)
+ (candidates . ,(funcall $func))
+ (action . ,$action)
+ (header-line . ,(concat $buf
+ (substitute-command-keys
+ " [\\<helm-multi-swoop-map>\\[helm-multi-swoop-edit]] Edit mode")))
+ (keymap . ,helm-multi-swoop-map)
+ (requires-pattern . 2)
+ ,(if (and $multiline
+ (> $multiline 1))
+ '(multiline))
+ (match . ,(helm-swoop-match-functions))
+ (search . ,(helm-swoop-search-functions))))
+
+(defun helm-swoop--set-prefix ($multiline)
+ ;; Enable scrolling margin
+ (setq helm-swoop-last-prefix-number
+ (or $multiline 1))) ;; $multiline is for resume
+
+;; Delete cache when modified file is saved
+(defun helm-swoop--clear-cache ()
+ (if (boundp 'helm-swoop-list-cache) (setq helm-swoop-list-cache nil)))
+(add-hook 'after-save-hook 'helm-swoop--clear-cache)
+
+(defadvice narrow-to-region (around helm-swoop-advice-narrow-to-region activate)
+ (helm-swoop--clear-cache)
+ ad-do-it)
+(defadvice narrow-to-defun (around helm-swoop-advice-narrow-to-defun activate)
+ (helm-swoop--clear-cache)
+ ad-do-it)
+(defadvice narrow-to-page (around helm-swoop-advice-narrow-to-page activate)
+ (helm-swoop--clear-cache)
+ ad-do-it)
+(defadvice widen (around helm-swoop-advice-widen activate)
+ (helm-swoop--clear-cache)
+ ad-do-it)
+
+(defun helm-swoop--restore ()
+ (when (= 1 helm-exit-status)
+ (helm-swoop-back-to-last-point t)
+ (helm-swoop--restore-unveiled-overlay))
+ (setq helm-swoop-invisible-targets nil)
+ (ad-disable-advice 'helm-next-line 'around 'helm-swoop-next-line)
+ (ad-activate 'helm-next-line)
+ (ad-disable-advice 'helm-previous-line 'around 'helm-swoop-previous-line)
+ (ad-activate 'helm-previous-line)
+ (ad-disable-advice 'helm-toggle-visible-mark 'around 'helm-swoop-toggle-visible-mark)
+ (ad-activate 'helm-toggle-visible-mark)
+ (ad-disable-advice 'helm-move--next-line-fn 'around
+ 'helm-multi-swoop-next-line-cycle)
+ (ad-activate 'helm-move--next-line-fn)
+ (ad-disable-advice 'helm-move--previous-line-fn 'around
+ 'helm-multi-swoop-previous-line-cycle)
+ (ad-activate 'helm-move--previous-line-fn)
+ (remove-hook 'helm-update-hook 'helm-swoop--pattern-match)
+ (remove-hook 'helm-after-update-hook 'helm-swoop--keep-nearest-position)
+ (setq helm-swoop-last-query helm-swoop-pattern)
+ (mapc (lambda ($ov)
+ (when (or (eq 'helm-swoop-target-line-face (overlay-get $ov 'face))
+ (eq 'helm-swoop-target-line-block-face
+ (overlay-get $ov 'face)))
+ (delete-overlay $ov)))
+ (overlays-in (point-min) (point-max)))
+ (helm-swoop--delete-overlay 'target-buffer)
+ (deactivate-mark t))
+
+;;;###autoload
+(cl-defun helm-swoop (&key $query $source ($multiline current-prefix-arg))
+ "List the all lines to another buffer, which is able to squeeze by
+ any words you input. At the same time, the original buffer's cursor
+ is jumping line to line according to moving up and down the list."
+ (interactive)
+ (setq helm-swoop-synchronizing-window (selected-window))
+ (setq helm-swoop-last-point (cons (point) (buffer-name (current-buffer))))
+ (setq helm-swoop-last-line-info
+ (cons (current-buffer) (line-number-at-pos)))
+ (unless (boundp 'helm-swoop-last-query)
+ (set (make-local-variable 'helm-swoop-last-query) ""))
+ (setq helm-swoop-target-buffer (current-buffer))
+ (helm-swoop--set-prefix (prefix-numeric-value $multiline))
+ ;; Overlay
+ (setq helm-swoop-line-overlay (make-overlay (point) (point)))
+ (overlay-put helm-swoop-line-overlay
+ 'face (if (< 1 helm-swoop-last-prefix-number)
+ 'helm-swoop-target-line-block-face
+ 'helm-swoop-target-line-face))
+ ;; Cache
+ (cond ((not (boundp 'helm-swoop-list-cache))
+ (set (make-local-variable 'helm-swoop-list-cache) nil))
+ ((buffer-modified-p)
+ (setq helm-swoop-list-cache nil)))
+ (unwind-protect
+ (progn
+ ;; For synchronizing line position
+ (ad-enable-advice 'helm-next-line 'around 'helm-swoop-next-line)
+ (ad-activate 'helm-next-line)
+ (ad-enable-advice 'helm-previous-line 'around 'helm-swoop-previous-line)
+ (ad-activate 'helm-previous-line)
+ (ad-enable-advice 'helm-toggle-visible-mark 'around 'helm-swoop-toggle-visible-mark)
+ (ad-activate 'helm-toggle-visible-mark)
+ (ad-enable-advice 'helm-move--next-line-fn 'around
+ 'helm-multi-swoop-next-line-cycle)
+ (ad-activate 'helm-move--next-line-fn)
+ (ad-enable-advice 'helm-move--previous-line-fn 'around
+ 'helm-multi-swoop-previous-line-cycle)
+ (ad-activate 'helm-move--previous-line-fn)
+ (add-hook 'helm-update-hook 'helm-swoop--pattern-match)
+ (add-hook 'helm-after-update-hook 'helm-swoop--keep-nearest-position t)
+ (cond ($query
+ (if (string-match
+ "\\(\\^\\[0\\-9\\]\\+\\.\\)\\(.*\\)" $query)
+ $query ;; NEED FIX #1 to appear as a "^"
+ $query))
+ (mark-active
+ (let (($st (buffer-substring-no-properties
+ (region-beginning) (region-end))))
+ (if (string-match "\n" $st)
+ (message "Multi line region is not allowed")
+ (setq $query (helm-swoop-pre-input-optimize $st)))))
+ ((setq $query (helm-swoop-pre-input-optimize
+ (funcall helm-swoop-pre-input-function))))
+ (t (setq $query "")))
+ ;; First behavior
+ (helm-swoop--recenter)
+ (move-beginning-of-line 1)
+ (helm-swoop--target-line-overlay-move)
+ ;; Execute helm
+ (let ((helm-display-function helm-swoop-split-window-function)
+ (helm-display-source-at-screen-top nil)
+ (helm-completion-window-scroll-margin 5))
+ (helm :sources
+ (or $source
+ (helm-c-source-swoop))
+ :buffer helm-swoop-buffer
+ :input $query
+ :prompt helm-swoop-prompt
+ :preselect
+ ;; Get current line has content or else near one
+ (if (string-match "^[\t\n\s]*$" (helm-swoop--get-string-at-line))
+ (save-excursion
+ (if (re-search-forward "[^\t\n\s]" nil t)
+ (format "^%s\s" (line-number-at-pos))
+ (re-search-backward "[^\t\n\s]" nil t)
+ (format "^%s\s" (line-number-at-pos))))
+ (format "^%s\s" (line-number-at-pos)))
+ :candidate-number-limit helm-swoop-candidate-number-limit)))
+ ;; Restore helm's hook and window function etc
+ (helm-swoop--restore)))
+
+;; Receive word from isearch ---------------
+;;;###autoload
+(defun helm-swoop-from-isearch ()
+ "Invoke `helm-swoop' from isearch."
+ (interactive)
+ (let (($query (if isearch-regexp
+ isearch-string
+ (regexp-quote isearch-string))))
+ (let (search-nonincremental-instead)
+ (isearch-exit))
+ (helm-swoop :$query $query)))
+;; When doing isearch, hand the word over to helm-swoop
+(define-key isearch-mode-map (kbd "M-i") 'helm-swoop-from-isearch)
+
+;; Receive word from evil search ---------------
+(defun helm-swoop-from-evil-search ()
+ "Invoke `helm-swoop' from evil isearch"
+ (interactive)
+ (if (string-match "\\(isearch-\\|evil.*search\\)" (symbol-name real-last-command))
+ (helm-swoop :$query (if isearch-regexp
+ isearch-string
+ (regexp-quote isearch-string)))
+ (helm-swoop)))
+;; When doing evil-search, hand the word over to helm-swoop
+;; (define-key evil-motion-state-map (kbd "M-i") 'helm-swoop-from-evil-search)
+
+;; Receive word from evil search ---------------
+(defun helm-swoop-yank-thing-at-point ()
+ "Insert string at which the point helm-swoop started."
+ (interactive)
+ (let ($amend $buf)
+ (with-selected-window helm-swoop-synchronizing-window
+ (setq $buf (get-buffer (cdr helm-swoop-last-point)))
+ (when $buf
+ (with-current-buffer $buf
+ (save-excursion
+ (goto-char (car helm-swoop-last-point))
+ (setq $amend (thing-at-point 'symbol))))))
+ (when $amend
+ (with-selected-window (minibuffer-window)
+ (insert $amend)))))
+
+;; For helm-resume ------------------------
+(defadvice helm-resume-select-buffer
+ (around helm-swoop-if-selected-as-resume activate)
+ "Resume if *Helm Swoop* buffer selected as a resume
+ when helm-resume with prefix"
+ (if (boundp 'helm-swoop-last-query)
+ ad-do-it
+ ;; If the buffer hasn't called helm-swoop, just hide from options
+ (let ((helm-buffers (delete helm-swoop-buffer helm-buffers)))
+ ad-do-it))
+ (when (and (equal ad-return-value helm-swoop-buffer)
+ (boundp 'helm-swoop-last-query))
+ (helm-swoop :$query helm-swoop-last-query
+ :$multiline helm-swoop-last-prefix-number)
+ (setq ad-return-value nil)))
+
+(defadvice helm-resume (around helm-swoop-resume activate)
+ "Resume if the last used helm buffer is helm-swoop-buffer"
+ (if (equal helm-last-buffer helm-swoop-buffer)
+ (if (boundp 'helm-swoop-last-query)
+ (if (not (ad-get-arg 0))
+ (helm-swoop :$query helm-swoop-last-query
+ :$multiline helm-swoop-last-prefix-number))
+ ;; Temporary apply second last buffer
+ (let ((helm-last-buffer (cadr helm-buffers))) ad-do-it))
+ ad-do-it))
+
+;; For caret beginning-match -----------------------------
+(defun helm-swoop--caret-match-delete ($o $aft $beg $end &optional $len)
+ (if $aft
+ (- $end $beg $len) ;; Unused argument? To avoid byte compile error
+ (delete-region (overlay-start $o) (1- (overlay-end $o)))))
+
+(defun helm-swoop-caret-match (&optional _$resume)
+ (interactive)
+ (let* (($prompt helm-swoop-prompt) ;; Accept change of the variable
+ ($line-number-regexp "^[0-9]+.")
+ ($prompt-regexp
+ (funcall `(lambda ()
+ (rx bol ,$prompt))))
+ ($prompt-regexp-with-line-number
+ (funcall `(lambda ()
+ (rx bol ,$prompt (group ,$line-number-regexp)))))
+ ($disguise-caret
+ (lambda ()
+ (save-excursion
+ (re-search-backward $prompt-regexp-with-line-number nil t)
+ (let (($o (make-overlay (match-beginning 1) (match-end 1))))
+ (overlay-put $o 'face 'helm-swoop-target-word-face)
+ (overlay-put $o 'modification-hooks '(helm-swoop--caret-match-delete))
+ (overlay-put $o 'display "^")
+ (overlay-put $o 'evaporate t))))))
+ (if (and (minibufferp)
+ (string-match $prompt-regexp
+ (buffer-substring-no-properties
+ (point-min) (point-max)))
+ (eq (point) (+ 1 (length helm-swoop-prompt))))
+ (progn
+ (insert $line-number-regexp)
+ (funcall $disguise-caret))
+ (insert "^"))))
+
+;;; @ helm-swoop-edit -----------------------------------------
+
+(defvar helm-swoop-edit-target-buffer)
+(defvar helm-swoop-edit-buffer "*Helm Swoop Edit*")
+(defvar helm-swoop-edit-map
+ (let (($map (make-sparse-keymap)))
+ (define-key $map (kbd "C-x C-s") 'helm-swoop--edit-complete)
+ (define-key $map (kbd "C-c C-g") 'helm-swoop--edit-cancel)
+ (define-key $map (kbd "C-c C-q C-k") 'helm-swoop--edit-delete-all-lines)
+ $map))
+
+(defun helm-swoop--clear-edit-buffer ($prop)
+ (let ((inhibit-read-only t))
+ (mapc (lambda ($ov)
+ (when (overlay-get $ov $prop)
+ (delete-overlay $ov)))
+ (overlays-in (point-min) (point-max)))
+ (set-text-properties (point-min) (point-max) nil)
+ (goto-char (point-min))
+ (erase-buffer)))
+
+(defun helm-swoop--collect-edited-lines ()
+ "Create a list of edited lines with each its own line number"
+ (interactive)
+ (let ($list)
+ (goto-char (point-min))
+ (while (re-search-forward "^\\([0-9]+\\)\s" nil t)
+ (setq $list
+ (cons (cons (string-to-number (match-string 1))
+ (buffer-substring-no-properties
+ (point)
+ (save-excursion
+ (if (re-search-forward
+ "^\\([0-9]+\\)\s\\|^\\(\\-+\\)" nil t)
+ (1- (match-beginning 0))
+ (goto-char (point-max))
+ (re-search-backward "\n" nil t)))))
+ $list)))
+ $list))
+
+(defun helm-swoop--edit ($candidate)
+ "This function will only be called from `helm-swoop-edit'"
+ (interactive)
+ (setq helm-swoop-edit-target-buffer helm-swoop-target-buffer)
+ (delete-overlay helm-swoop-line-overlay)
+ (helm-swoop--delete-overlay 'target-buffer)
+ (with-current-buffer (get-buffer-create helm-swoop-edit-buffer)
+
+ (helm-swoop--clear-edit-buffer 'helm-swoop-edit)
+ (let (($bufstr ""))
+ ;; Get target line number to edit
+ (with-current-buffer helm-swoop-buffer
+ ;; Use selected line by [C-SPC] or [M-SPC]
+ (mapc (lambda ($ov)
+ (when (eq 'helm-visible-mark (overlay-get $ov 'face))
+ (setq $bufstr (concat (buffer-substring-no-properties
+ (overlay-start $ov) (overlay-end $ov))
+ $bufstr))))
+ (overlays-in (point-min) (point-max)))
+ (if (equal "" $bufstr)
+ ;; Not found selected line
+ (setq $bufstr (buffer-substring-no-properties
+ (point-min) (point-max)))
+ ;; Attach title
+ (setq $bufstr (concat "Helm Swoop\n" $bufstr))))
+
+ ;; Set for edit buffer
+ (insert $bufstr)
+ (add-text-properties (point-min) (point-max)
+ '(read-only t rear-nonsticky t front-sticky t))
+
+ ;; Set for editable context
+ (let ((inhibit-read-only t))
+ ;; Title and explanation
+ (goto-char (point-min))
+ (let (($o (make-overlay (point) (point-at-eol))))
+ (overlay-put $o 'helm-swoop-edit t)
+ (overlay-put $o 'face 'font-lock-function-name-face)
+ (overlay-put $o 'after-string
+ (propertize
+ (substitute-command-keys
+ (concat
+ " [\\<helm-swoop-edit-map>\\[helm-swoop--edit-complete]] Complete"
+ ", [\\<helm-swoop-edit-map>\\[helm-swoop--edit-cancel]] Cancel"
+ ", [\\<helm-swoop-edit-map>\\[helm-swoop--edit-delete-all-lines]] Delete All"
+ ))
+ 'face 'helm-bookmark-addressbook)))
+ ;; Line number and editable area
+ (while (re-search-forward "^\\([0-9]+\s\\)\\(.*\\)$" nil t)
+ (let* (($bol1 (match-beginning 1))
+ ($eol1 (match-end 1))
+ ($bol2 (match-beginning 2))
+ ($eol2 (match-end 2)))
+ ;; Line number
+ (add-text-properties $bol1 $eol1
+ '(face font-lock-function-name-face
+ intangible t))
+ ;; Editable area
+ (remove-text-properties $bol2 $eol2 '(read-only t))
+ ;; For line tail
+ (set-text-properties $eol2 (or (1+ $eol2) (point-max))
+ '(read-only t rear-nonsticky t))))
+ (helm-swoop--target-word-overlay 'edit-buffer 0))))
+
+ (other-window 1)
+ (switch-to-buffer helm-swoop-edit-buffer)
+ (goto-char (point-min))
+ (if (string-match "^[0-9]+" $candidate)
+ (re-search-forward
+ (concat "^" (match-string 0 $candidate)) nil t))
+ (use-local-map helm-swoop-edit-map))
+
+(defun helm-swoop--edit-complete ()
+ "Apply changes and kill temporary edit buffer"
+ (interactive)
+ (let (($list (helm-swoop--collect-edited-lines)))
+ (with-current-buffer helm-swoop-edit-target-buffer
+ ;; Replace from the end of buffer
+ (save-excursion
+ (mapc (lambda ($cell)
+ (let (($k (car $cell))
+ ($v (cdr $cell)))
+ (goto-char (point-min))
+ (delete-region (point-at-bol $k) (point-at-eol $k))
+ (goto-char (point-at-bol $k))
+ (insert $v)))
+ $list)))
+ (select-window helm-swoop-synchronizing-window)
+ (kill-buffer (get-buffer helm-swoop-edit-buffer)))
+ (message "Successfully helm-swoop-edit applied to original buffer"))
+
+(defun helm-swoop--edit-delete-all-lines ()
+ "Apply changes and kill temporary edit buffer"
+ (interactive)
+ (let (($list (helm-swoop--collect-edited-lines)))
+ (with-current-buffer helm-swoop-edit-target-buffer
+ ;; Replace from the end of buffer
+ (save-excursion
+ (mapc (lambda ($cell)
+ (let (($k (car $cell)))
+ (goto-char (point-min))
+ (delete-region (point-at-bol $k)
+ (if (eq (point-at-eol $k) (point-max))
+ (point-at-eol $k)
+ (1+ (point-at-eol $k))))))
+ $list)))
+ (select-window helm-swoop-synchronizing-window)
+ (kill-buffer (get-buffer helm-swoop-edit-buffer)))
+ (message "Successfully helm-swoop-edit applied to original buffer"))
+
+(defun helm-swoop--edit-cancel ()
+ "Cancel edit and kill temporary buffer"
+ (interactive)
+ (select-window helm-swoop-synchronizing-window)
+ (kill-buffer (get-buffer helm-swoop-edit-buffer))
+ (message "helm-swoop-edit canceled"))
+
+(defun helm-swoop-edit ()
+ (interactive)
+ (helm-exit-and-execute-action 'helm-swoop--edit))
+
+;;; @ helm-multi-swoop ----------------------------------------
+(defvar helm-multi-swoop-buffer-list "*helm-multi-swoop buffers list*"
+ "Buffer name")
+(defvar helm-multi-swoop-ignore-buffers-match "^\\*"
+ "Regexp to eliminate buffers you don't want to see")
+(defvar helm-multi-swoop-candidate-number-limit 250)
+(defvar helm-multi-swoop-last-selected-buffers nil)
+(defvar helm-multi-swoop-last-query nil)
+(defvar helm-multi-swoop-query nil)
+(defvar helm-multi-swoop-buffer "*Helm Multi Swoop*")
+(defvar helm-multi-swoop-all-from-helm-swoop-last-point nil
+ "For the last position, when helm-multi-swoop-all-from-helm-swoop canceled")
+(defvar helm-multi-swoop-move-line-action-last-buffer nil)
+
+(defvar helm-multi-swoop-buffers-map
+ (let (($map (make-sparse-keymap)))
+ (set-keymap-parent $map helm-map)
+ (define-key $map (kbd "RET")
+ (lambda () (interactive)
+ (helm-exit-and-execute-action 'helm-multi-swoop--exec)))
+ (delq nil $map)))
+
+(defvar helm-multi-swoop-projectile-buffers-filter
+ #'projectile-buffers-with-file-or-process)
+;; action -----------------------------------------------------
+
+(defadvice helm-next-line (around helm-multi-swoop-next-line disable)
+ (let ((helm-move-to-line-cycle-in-source nil))
+ ad-do-it
+ (when (called-interactively-p 'any)
+ (helm-multi-swoop--move-line-action))))
+
+(defadvice helm-previous-line (around helm-multi-swoop-previous-line disable)
+ (let ((helm-move-to-line-cycle-in-source nil))
+ ad-do-it
+ (when (called-interactively-p 'any)
+ (helm-multi-swoop--move-line-action))))
+
+(defadvice helm-toggle-visible-mark (around helm-multi-swoop-toggle-visible-mark disable)
+ (let ((helm-move-to-line-cycle-in-source nil))
+ ad-do-it
+ (when (called-interactively-p 'any)
+ (helm-multi-swoop--move-line-action))))
+
+(defadvice helm-move--next-line-fn (around helm-multi-swoop-next-line-cycle disable)
+ (if (not (helm-pos-multiline-p))
+ (if (eq (point-max) (save-excursion (forward-line 1) (point)))
+ (when helm-swoop-move-to-line-cycle
+ (helm-beginning-of-buffer)
+ (helm-swoop--recenter))
+ (forward-line 1))
+ (let ((line-num (line-number-at-pos)))
+ (helm-move--next-multi-line-fn)
+ (when (and helm-swoop-move-to-line-cycle
+ (eq line-num (line-number-at-pos)))
+ (helm-beginning-of-buffer)))))
+
+(defadvice helm-move--previous-line-fn (around helm-multi-swoop-previous-line-cycle disable)
+ (if (not (helm-pos-multiline-p))
+ (forward-line -1)
+ (helm-move--previous-multi-line-fn))
+ (when (and (helm-pos-header-line-p)
+ (eq (point) (save-excursion (forward-line -1) (point))))
+ (when helm-swoop-move-to-line-cycle
+ (helm-end-of-buffer))
+ (when (helm-pos-multiline-p)
+ (helm-move--previous-multi-line-fn))))
+
+(defun helm-multi-swoop--move-line-action ()
+ (with-helm-window
+ (let* (($key (buffer-substring (point-at-bol) (point-at-eol)))
+ ($num (when (string-match "^[0-9]+" $key)
+ (string-to-number (match-string 0 $key))))
+ ($source (helm-get-current-source))
+ ($buf (let (($name (assoc-default 'name $source)))
+ (when $name (get-buffer $name)))))
+ (when $buf
+ ;; Synchronizing line position
+ (with-selected-window helm-swoop-synchronizing-window
+ (with-current-buffer $buf
+ (when (not (eq $buf helm-multi-swoop-move-line-action-last-buffer))
+ (set-window-buffer nil $buf)
+ (helm-swoop--pattern-match))
+ (helm-swoop--goto-line $num)
+ (helm-swoop--target-line-overlay-move $buf)
+ (helm-swoop--recenter))
+ (setq helm-multi-swoop-move-line-action-last-buffer $buf))
+ (setq helm-swoop-last-line-info (cons $buf $num))))))
+
+(defun helm-multi-swoop--get-marked-buffers ()
+ (let ($list
+ ($buf (get-buffer helm-multi-swoop-buffer-list)))
+ (when $buf
+ (with-current-buffer (get-buffer helm-multi-swoop-buffer-list)
+ (mapc (lambda ($ov)
+ (when (eq 'helm-visible-mark (overlay-get $ov 'face))
+ (setq $list (cons
+ (let (($word (buffer-substring-no-properties
+ (overlay-start $ov) (overlay-end $ov))))
+ (mapc (lambda ($r)
+ (setq $word (replace-regexp-in-string
+ (car $r) (cdr $r) $word)))
+ (list '("\\`[ \t\n\r]+" . "")
+ '("[ \t\n\r]+\\'" . "")))
+ $word)
+ $list))))
+ (overlays-in (point-min) (point-max))))
+ (delete "" $list))))
+
+;; core --------------------------------------------------------
+
+(cl-defun helm-multi-swoop--exec (ignored &key $query $buflist $func $action)
+ (interactive)
+ (setq helm-swoop-synchronizing-window (selected-window))
+ (setq helm-swoop-last-point
+ (or helm-multi-swoop-all-from-helm-swoop-last-point
+ (cons (point) (buffer-name (current-buffer)))))
+ (setq helm-swoop-last-line-info
+ (cons (current-buffer) (line-number-at-pos)))
+ (unless (get-buffer helm-multi-swoop-buffer-list)
+ (get-buffer-create helm-multi-swoop-buffer-list))
+ (helm-swoop--set-prefix (prefix-numeric-value current-prefix-arg))
+ (let (($buffs (or $buflist
+ (helm-multi-swoop--get-marked-buffers)
+ `(,(buffer-name helm-swoop-target-buffer))
+ (error "No buffer selected")))
+ $contents
+ $preserve-position
+ ($prefix-arg (prefix-numeric-value
+ (or current-prefix-arg helm-swoop-last-prefix-number 1))))
+ (helm-swoop--set-prefix $prefix-arg)
+ (setq helm-multi-swoop-last-selected-buffers $buffs)
+ ;; Create buffer sources
+ (mapc (lambda ($buf)
+ (when (get-buffer $buf)
+ (with-current-buffer (get-buffer $buf)
+ (let* (($func
+ (or $func
+ (lambda ()
+ (helm-swoop--split-lines-by
+ (helm-swoop--get-content $buf t)
+ "\n" $prefix-arg))))
+ ($action
+ (or $action
+ `(("Go to Line"
+ . (lambda ($line)
+ (switch-to-buffer ,$buf)
+ (helm-swoop--goto-line
+ (when (string-match "^[0-9]+" $line)
+ (string-to-number
+ (match-string 0 $line))))
+ (when (re-search-forward
+ (mapconcat 'identity
+ (split-string
+ helm-pattern " ") "\\|")
+ nil t)
+ (helm-swoop-flash-word (match-beginning 0) (match-end 0))
+ (goto-char (match-beginning 0)))
+ (helm-swoop--recenter)))))))
+ (setq $preserve-position
+ (cons (cons $buf (point)) $preserve-position))
+ (setq
+ $contents
+ (cons
+ (helm-c-source-multi-swoop $buf $func $action $prefix-arg)
+ $contents))))))
+ $buffs)
+ (unwind-protect
+ (progn
+ (ad-enable-advice 'helm-next-line 'around
+ 'helm-multi-swoop-next-line)
+ (ad-activate 'helm-next-line)
+ (ad-enable-advice 'helm-previous-line 'around
+ 'helm-multi-swoop-previous-line)
+ (ad-activate 'helm-previous-line)
+ (ad-enable-advice 'helm-toggle-visible-mark 'around
+ 'helm-multi-swoop-toggle-visible-mark)
+ (ad-activate 'helm-toggle-visible-mark)
+ (ad-enable-advice 'helm-move--next-line-fn 'around
+ 'helm-multi-swoop-next-line-cycle)
+ (ad-activate 'helm-move--next-line-fn)
+ (ad-enable-advice 'helm-move--previous-line-fn 'around
+ 'helm-multi-swoop-previous-line-cycle)
+ (ad-activate 'helm-move--previous-line-fn)
+ (add-hook 'helm-update-hook 'helm-swoop--pattern-match)
+ (add-hook 'helm-after-update-hook 'helm-swoop--keep-nearest-position t)
+ (setq helm-swoop-line-overlay
+ (make-overlay (point) (point)))
+ (overlay-put helm-swoop-line-overlay
+ 'face 'helm-swoop-target-line-face)
+ (helm-swoop--target-line-overlay-move)
+ ;; Execute helm
+ (let ((helm-display-function helm-swoop-split-window-function)
+ (helm-display-source-at-screen-top nil)
+ (helm-completion-window-scroll-margin 5))
+ (helm :sources $contents
+ :buffer helm-multi-swoop-buffer
+ :input (or $query helm-multi-swoop-query "")
+ :prompt helm-swoop-prompt
+ :candidate-number-limit
+ helm-multi-swoop-candidate-number-limit
+ :preselect
+ (regexp-quote
+ (format "%s %s" (line-number-at-pos)
+ (helm-swoop--get-string-at-line))))))
+ ;; Restore
+ (progn
+ (when (= 1 helm-exit-status)
+ (helm-swoop-back-to-last-point t)
+ (helm-swoop--restore-unveiled-overlay))
+ (setq helm-swoop-invisible-targets nil)
+ (ad-disable-advice 'helm-next-line 'around
+ 'helm-multi-swoop-next-line)
+ (ad-activate 'helm-next-line)
+ (ad-disable-advice 'helm-previous-line 'around
+ 'helm-multi-swoop-previous-line)
+ (ad-activate 'helm-previous-line)
+ (ad-disable-advice 'helm-toggle-visible-mark 'around
+ 'helm-multi-swoop-toggle-visible-mark)
+ (ad-activate 'helm-toggle-visible-mark)
+ (ad-disable-advice 'helm-move--next-line-fn 'around
+ 'helm-multi-swoop-next-line-cycle)
+ (ad-activate 'helm-move--next-line-fn)
+ (ad-disable-advice 'helm-move--previous-line-fn 'around
+ 'helm-multi-swoop-previous-line-cycle)
+ (ad-activate 'helm-move--previous-line-fn)
+ (remove-hook 'helm-update-hook 'helm-swoop--pattern-match)
+ (remove-hook 'helm-after-update-hook 'helm-swoop--keep-nearest-position)
+ (setq helm-multi-swoop-last-query helm-swoop-pattern)
+ (helm-swoop--restore-unveiled-overlay)
+ (setq helm-multi-swoop-query nil)
+ (setq helm-multi-swoop-all-from-helm-swoop-last-point nil)
+ (mapc (lambda ($buf)
+ (let (($current-buffer (buffer-name (current-buffer))))
+ (with-current-buffer (car $buf)
+ ;; Delete overlay
+ (delete-overlay helm-swoop-line-overlay)
+ (helm-swoop--delete-overlay 'target-buffer)
+ ;; Restore each buffer's position
+ (unless (equal (car $buf) $current-buffer)
+ (goto-char (cdr $buf))))))
+ $preserve-position)))))
+
+(defun helm-multi-swoop--get-buffer-list ()
+ (let ($buflist1 $buflist2)
+ ;; eliminate buffers start with whitespace and dired buffers
+ (mapc (lambda ($buf)
+ (setq $buf (buffer-name $buf))
+ (unless (string-match "^\\s-" $buf)
+ (unless (eq 'dired-mode (with-current-buffer $buf major-mode))
+ (setq $buflist1 (cons $buf $buflist1)))))
+ (buffer-list))
+ ;; eliminate buffers match pattern
+ (mapc (lambda ($buf)
+ (unless (string-match
+ helm-multi-swoop-ignore-buffers-match
+ $buf)
+ (setq $buflist2 (cons $buf $buflist2))))
+ $buflist1)
+ $buflist2))
+
+(defun helm-c-source-helm-multi-swoop-buffers ()
+ "Show buffer list to select"
+ `((name . "helm-multi-swoop select buffers")
+ (candidates . helm-multi-swoop--get-buffer-list)
+ (header-line . "[C-SPC]/[M-SPC] select, [RET] next step")
+ (keymap . ,helm-multi-swoop-buffers-map)
+ (match . ,(helm-swoop-match-functions))
+ (search . ,(helm-swoop-search-functions))))
+
+(defun helm-multi-swoop--get-query ($query)
+ (cond ($query
+ (setq helm-multi-swoop-query $query))
+ (mark-active
+ (let (($st (buffer-substring-no-properties
+ (region-beginning) (region-end))))
+ (if (string-match "\n" $st)
+ (message "Multi line region is not allowed")
+ (setq helm-multi-swoop-query
+ (helm-swoop-pre-input-optimize $st)))))
+ ((setq helm-multi-swoop-query
+ (helm-swoop-pre-input-optimize
+ (funcall helm-swoop-pre-input-function))))
+ (t (setq helm-multi-swoop-query ""))))
+
+;;;###autoload
+(defun helm-multi-swoop (&optional $query $buflist)
+ "\
+Usage:
+M-x helm-multi-swoop
+1. Select any buffers by [C-SPC] or [M-SPC]
+2. Press [RET] to start helm-multi-swoop
+
+C-u M-x helm-multi-swoop
+If you have done helm-multi-swoop before, you can skip select buffers step.
+Last selected buffers will be applied to helm-multi-swoop.
+"
+ (interactive)
+ (setq helm-multi-swoop-query (helm-multi-swoop--get-query $query))
+ (if (equal current-prefix-arg '(4))
+ (helm-multi-swoop--exec nil
+ :$query helm-multi-swoop-query
+ :$buflist $buflist)
+ (if $buflist
+ (helm-multi-swoop--exec nil
+ :$query $query
+ :$buflist $buflist)
+ (helm :sources (helm-c-source-helm-multi-swoop-buffers)
+ :buffer helm-multi-swoop-buffer-list
+ :prompt "Mark any buffers by [C-SPC] or [M-SPC]: "))))
+
+;;;###autoload
+(defun helm-multi-swoop-all (&optional $query)
+ "Apply all buffers to helm-multi-swoop"
+ (interactive)
+ (setq helm-multi-swoop-query (helm-multi-swoop--get-query $query))
+ (helm-multi-swoop--exec nil
+ :$query helm-multi-swoop-query
+ :$buflist (helm-multi-swoop--get-buffer-list)))
+
+(defun get-buffers-matching-mode ($mode)
+ "Returns a list of buffers where their major-mode is equal to MODE"
+ (let ($buffer-mode-matches)
+ (mapc (lambda ($buf)
+ (when (get-buffer $buf)
+ (with-current-buffer (get-buffer $buf)
+ (if (eq $mode major-mode)
+ (add-to-list '$buffer-mode-matches (buffer-name $buf))))))
+ (buffer-list))
+ $buffer-mode-matches))
+
+(defun helm-multi-swoop-by-mode ($mode &optional $query)
+ "Apply all buffers whose mode is MODE to helm-multi-swoop"
+ (setq helm-multi-swoop-query (helm-multi-swoop--get-query $query))
+ (if (get-buffers-matching-mode $mode)
+ (helm-multi-swoop--exec nil
+ :$query helm-multi-swoop-query
+ :$buflist (get-buffers-matching-mode $mode))
+ (message "there are no buffers in that mode right now")))
+
+;;;###autoload
+(defun helm-multi-swoop-org (&optional $query)
+ "Applies all org-mode buffers to helm-multi-swoop"
+ (interactive)
+ (helm-multi-swoop-by-mode 'org-mode $query))
+
+;;;###autoload
+(defun helm-multi-swoop-current-mode (&optional $query)
+ "Applies all buffers of the same mode as the current buffer to helm-multi-swoop"
+ (interactive)
+ (helm-multi-swoop-by-mode major-mode $query))
+
+;;;###autoload
+(defun helm-multi-swoop-projectile (&optional $query)
+ "Apply all opened buffers of the current project to helm-multi-swoop"
+ (interactive)
+ (setq helm-multi-swoop-query (helm-multi-swoop--get-query $query))
+ (if (require 'projectile nil 'noerror)
+ ;; set filter function that is used in projectile-project-buffers
+ (let ((projectile-buffers-filter-function
+ helm-multi-swoop-projectile-buffers-filter))
+ (helm-multi-swoop--exec nil
+ :$query helm-multi-swoop-query
+ :$buflist (mapcar #'buffer-name
+ (projectile-project-buffers))))
+ (error "Package 'projectile' is not available")))
+
+
+(defun helm-swoop--wrap-function-with-pre-input-function ($target-func $pre-input-func)
+ (let (($restore helm-swoop-pre-input-function))
+ (unwind-protect
+ (progn
+ (setq helm-swoop-pre-input-function $pre-input-func)
+ (funcall $target-func))
+ (setq helm-swoop-pre-input-function $restore))))
+
+;;;###autoload
+(defun helm-swoop-without-pre-input ()
+ "Start helm-swoop without pre input query."
+ (interactive)
+ (helm-swoop--wrap-function-with-pre-input-function
+ 'helm-swoop (lambda () nil)))
+
+;;;###autoload
+(defun helm-swoop-symble-pre-input ()
+ "Start helm-swoop without pre input query."
+ (interactive)
+ (helm-swoop--wrap-function-with-pre-input-function
+ 'helm-swoop (lambda () (format "\\_<%s\\_> " (thing-at-point 'symbol)))))
+
+;; option -------------------------------------------------------
+
+(defun helm-multi-swoop-all-from-isearch ()
+ "Invoke `helm-multi-swoop-all' from isearch."
+ (interactive)
+ (let (($query (if isearch-regexp
+ isearch-string
+ (regexp-quote isearch-string))))
+ (let (search-nonincremental-instead)
+ (isearch-exit))
+ (helm-multi-swoop-all $query)))
+;; When doing isearch, hand the word over to helm-swoop
+;; (define-key isearch-mode-map (kbd "C-x M-i") 'helm-multi-swoop-all-from-isearch)
+
+(defun helm-multi-swoop-all-from-helm-swoop ()
+ "Invoke `helm-multi-swoop-all' from helm-swoop."
+ (interactive)
+ (helm-swoop--restore)
+ (delete-overlay helm-swoop-line-overlay)
+ (setq helm-multi-swoop-all-from-helm-swoop-last-point helm-swoop-last-point)
+ (let (($query helm-pattern))
+ (run-with-timer 0 nil (lambda () (helm-multi-swoop-all $query))))
+ (helm-exit-minibuffer))
+
+(defun helm-multi-swoop-current-mode-from-helm-swoop ()
+ "Invoke `helm-multi-swoop-all' from helm-swoop."
+ (interactive)
+ (helm-swoop--restore)
+ (delete-overlay helm-swoop-line-overlay)
+ (setq helm-multi-swoop-all-from-helm-swoop-last-point helm-swoop-last-point)
+ (let (($query helm-pattern))
+ (run-with-timer 0 nil (lambda () (helm-multi-swoop-current-mode $query))))
+ (helm-exit-minibuffer))
+;; (define-key helm-swoop-map (kbd "M-m") 'helm-multi-swoop-current-mode-from-helm-swoop)
+
+(defadvice helm-resume (around helm-multi-swoop-resume activate)
+ "Resume if the last used helm buffer is *Helm Swoop*"
+ (if (equal helm-last-buffer helm-multi-swoop-buffer)
+
+ (if (boundp 'helm-multi-swoop-last-query)
+ (if (not (ad-get-arg 0))
+ (helm-multi-swoop helm-multi-swoop-last-query
+ helm-multi-swoop-last-selected-buffers))
+ ;; Temporary apply second last buffer
+ (let ((helm-last-buffer (cadr helm-buffers))) ad-do-it))
+ ad-do-it))
+
+;;; @ helm-multi-swoop-edit -----------------------------------
+(defvar helm-multi-swoop-edit-save t
+ "Save each buffer you edit when editing is complete")
+(defvar helm-multi-swoop-edit-buffer "*Helm Multi Swoop Edit*")
+
+(defvar helm-multi-swoop-edit-map
+ (let (($map (make-sparse-keymap)))
+ (define-key $map (kbd "C-x C-s") 'helm-multi-swoop--edit-complete)
+ (define-key $map (kbd "C-c C-g") 'helm-multi-swoop--edit-cancel)
+ (define-key $map (kbd "C-c C-q C-k") 'helm-multi-swoop--edit-delete-all-lines)
+ $map))
+
+(defun helm-multi-swoop--edit ($candidate)
+ "This function will only be called from `helm-swoop-edit'"
+ (interactive)
+ (delete-overlay helm-swoop-line-overlay)
+ (helm-swoop--delete-overlay 'target-buffer)
+ (with-current-buffer (get-buffer-create helm-multi-swoop-edit-buffer)
+ (helm-swoop--clear-edit-buffer 'helm-multi-swoop-edit)
+ (let (($bufstr "")
+ ($mark nil)
+ ($buf (get-buffer helm-multi-swoop-buffer)))
+ ;; Get target line number to edit
+ (when $buf
+ (with-current-buffer $buf
+ ;; Set overlay to helm-source-header for editing marked lines
+ (save-excursion
+ (goto-char (point-min))
+ (let (($beg (point)) $end)
+ (overlay-recenter (point-max))
+ (while (setq $beg (text-property-any $beg (point-max)
+ 'face 'helm-source-header))
+ (setq $end (next-single-property-change $beg 'face))
+ (overlay-put (make-overlay $beg $end) 'source-header t)
+ (setq $beg $end)
+ (goto-char $end))))
+ ;; Use selected line by [C-SPC] or [M-SPC]
+ (mapc (lambda ($ov)
+ (when (overlay-get $ov 'source-header)
+ (setq $bufstr (concat (buffer-substring
+ (overlay-start $ov) (overlay-end $ov))
+ $bufstr)))
+ (when (eq 'helm-visible-mark (overlay-get $ov 'face))
+ (let (($str (buffer-substring (overlay-start $ov) (overlay-end $ov))))
+ (unless (equal "" $str) (setq $mark t))
+ (setq $bufstr (concat (buffer-substring
+ (overlay-start $ov) (overlay-end $ov))
+ $bufstr)))))
+ (overlays-in (point-min) (point-max)))
+ (if $mark
+ (progn (setq $bufstr (concat "Helm Multi Swoop\n" $bufstr))
+ (setq $mark nil))
+ (setq $bufstr (concat "Helm Multi Swoop\n"
+ (buffer-substring
+ (point-min) (point-max)))))))
+
+ ;; Set for edit buffer
+ (insert $bufstr)
+ (add-text-properties (point-min) (point-max)
+ '(read-only t rear-nonsticky t front-sticky t))
+
+ ;; Set for editable context
+ (let ((inhibit-read-only t))
+ ;; Title and explanation
+ (goto-char (point-min))
+ (let (($o (make-overlay (point) (point-at-eol))))
+ (overlay-put $o 'helm-multi-swoop-edit t)
+ (overlay-put $o 'face 'font-lock-function-name-face)
+ (overlay-put $o 'after-string
+ (propertize
+ (substitute-command-keys
+ (concat
+ " [\\<helm-swoop-edit-map>\\[helm-swoop--edit-complete]] Complete"
+ ", [\\<helm-swoop-edit-map>\\[helm-swoop--edit-cancel]] Cancel"
+ ", [\\<helm-swoop-edit-map>\\[helm-swoop--edit-delete-all-lines]] Delete All"
+ ))
+ 'face 'helm-bookmark-addressbook)))
+ ;; Line number and editable area
+ (while (re-search-forward "^\\([0-9]+\s\\)\\(.*\\)$" nil t)
+ (let* (($bol1 (match-beginning 1))
+ ($eol1 (match-end 1))
+ ($bol2 (match-beginning 2))
+ ($eol2 (match-end 2)))
+
+ ;; Line number
+ (add-text-properties $bol1 $eol1
+ '(face font-lock-function-name-face
+ intangible t))
+ ;; Editable area
+ (remove-text-properties $bol2 $eol2 '(read-only t))
+ ;; (add-text-properties $bol2 $eol2 '(font-lock-face helm-match))
+
+ ;; For line tail
+ (set-text-properties $eol2 (or (1+ $eol2) (point-max))
+ '(read-only t rear-nonsticky t))))
+ (helm-swoop--target-word-overlay 'edit-buffer 0))))
+
+ (other-window 1)
+ (switch-to-buffer helm-multi-swoop-edit-buffer)
+ (goto-char (point-min))
+ (if (string-match "^[0-9]+" $candidate)
+ (re-search-forward
+ (concat "^" (match-string 0 $candidate)) nil t))
+ (use-local-map helm-multi-swoop-edit-map))
+
+(defun helm-multi-swoop--separate-text-property-into-list ($property)
+ (interactive)
+ (let ($list $end)
+ (save-excursion
+ (goto-char (point-min))
+ (while (setq $end (next-single-property-change (point) $property))
+ ;; Must eliminate last return because of unexpected edit result
+ (setq $list (cons
+ (let (($str (buffer-substring-no-properties (point) $end)))
+ (if (string-match "\n\n\\'" $str)
+ (replace-regexp-in-string "\n\\'" "" $str)
+ $str))
+ $list))
+ (goto-char $end))
+ (setq $list (cons (buffer-substring-no-properties (point) (point-max))
+ $list)))
+ (nreverse $list)))
+
+(defun helm-multi-swoop--collect-edited-lines ()
+ "Create a list of edited lines with each its own line number"
+ (interactive)
+ (let* (($list
+ (helm-multi-swoop--separate-text-property-into-list 'helm-header))
+ ($length (length $list))
+ ($i 1) ;; 0th $list is header
+ $pairs)
+ (while (<= $i $length)
+ (let ($contents)
+ ;; Make ((number . line) (number . line) (number . line) ...)
+ (with-temp-buffer
+ (insert (format "%s" (nth (1+ $i) $list)))
+ (goto-char (point-min))
+ (while (re-search-forward "^\\([0-9]+\\)\s" nil t)
+ (setq $contents
+ (cons (cons (string-to-number (match-string 1))
+ (buffer-substring-no-properties
+ (point)
+ (save-excursion
+ (if (re-search-forward
+ "^\\([0-9]+\\)\s\\|^\\(\\-+\\)" nil t)
+ (1- (match-beginning 0))
+ (goto-char (point-max))
+ (re-search-backward "\n" nil t)))))
+ $contents))))
+ ;; Make ((buffer-name (number . line) (number . line) ...)
+ ;; (buffer-name (number . line) (number . line) ...) ...)
+ (setq $pairs (cons (cons (nth $i $list) $contents) $pairs)))
+ (setq $i (+ $i 2)))
+ (delete '(nil) $pairs)))
+
+(defun helm-multi-swoop--edit-complete ()
+ "Delete all extracted lines, and apply changes to buffers and kill temporary edit buffer"
+ (interactive)
+ (let (($list (helm-multi-swoop--collect-edited-lines))
+ $read-only)
+ (mapc (lambda ($x)
+ (with-current-buffer (car $x)
+ (unless buffer-read-only
+ (save-excursion
+ (mapc (lambda ($cell)
+ (let (($k (car $cell))
+ ($v (cdr $cell)))
+ (goto-char (point-min))
+ (delete-region (point-at-bol $k) (point-at-eol $k))
+ (goto-char (point-at-bol $k))
+ (insert $v)))
+ (cdr $x))))
+ (if helm-multi-swoop-edit-save
+ (if buffer-read-only
+ (setq $read-only t)
+ (save-buffer)))))
+ $list)
+ (select-window helm-swoop-synchronizing-window)
+ (kill-buffer (get-buffer helm-multi-swoop-edit-buffer))
+ (if $read-only
+ (message "Couldn't save some buffers because of read-only")
+ (message "Successfully helm-multi-swoop-edit applied to original buffer"))))
+
+(defun helm-multi-swoop--edit-delete-all-lines ()
+ "Delete all extracted lines, and apply changes to buffers and kill temporary edit buffer"
+ (interactive)
+ (let (($list (helm-multi-swoop--collect-edited-lines))
+ $read-only)
+ (mapc (lambda ($x)
+ (with-current-buffer (car $x)
+ (unless buffer-read-only
+ (save-excursion
+ (mapc (lambda ($cell)
+ (let (($k (car $cell)))
+ (goto-char (point-min))
+ (delete-region (point-at-bol $k)
+ (if (eq (point-at-eol $k) (point-max))
+ (point-at-eol $k)
+ (1+ (point-at-eol $k))))))
+ (cdr $x))))
+ (if helm-multi-swoop-edit-save
+ (if buffer-read-only
+ (setq $read-only t)
+ (save-buffer)))))
+ $list)
+ (select-window helm-swoop-synchronizing-window)
+ (kill-buffer (get-buffer helm-multi-swoop-edit-buffer))
+ (if $read-only
+ (message "Couldn't save some buffers because of read-only")
+ (message "Successfully helm-multi-swoop-edit applied to original buffer"))))
+
+(defun helm-multi-swoop--edit-cancel ()
+ "Cancel edit and kill temporary buffer"
+ (interactive)
+ (select-window helm-swoop-synchronizing-window)
+ (kill-buffer (get-buffer helm-multi-swoop-edit-buffer))
+ (message "helm-multi-swoop-edit canceled"))
+
+;;;###autoload
+(defun helm-multi-swoop-edit ()
+ (interactive)
+ (helm-exit-and-execute-action 'helm-multi-swoop--edit))
+
+;;; @ helm-swoop-same-face-at-point -----------------------------------
+
+(defsubst helm-swoop--get-at-face (&optional $point)
+ (or $point (setq $point (point)))
+ (let (($face (or (get-char-property $point 'read-face-name)
+ (get-char-property $point 'face))))
+ $face))
+
+(defun helm-swoop--cull-face-include-line ($face)
+ (let (($list) ($po (point-min)))
+ (save-excursion
+ (while (setq $po (next-single-property-change $po 'face))
+ (when (equal $face (helm-swoop--get-at-face $po))
+ (goto-char $po)
+ (setq $list (cons (format "%s %s"
+ (line-number-at-pos $po)
+ (buffer-substring (point-at-bol) (point-at-eol)))
+ $list))
+ (let (($ov (make-overlay $po (or (next-single-property-change $po 'face)
+ (point-max)))))
+ (overlay-put $ov 'face 'helm-swoop-target-word-face)
+ (overlay-put $ov 'target-buffer 'helm-swoop-target-word-face)))))
+ (nreverse (delete-dups $list))))
+
+(defun helm-swoop-same-face-at-point (&optional $face)
+ (interactive)
+ (or $face (setq $face (helm-swoop--get-at-face)))
+ (helm-swoop :$query ""
+ :$source
+ `((name . "helm-swoop-same-face-at-point")
+ (candidates . ,(helm-swoop--cull-face-include-line $face))
+ (header-line . ,(format "%s" $face))
+ (action
+ . (("Go to Line"
+ . (lambda ($line)
+ (helm-swoop--goto-line
+ (when (string-match "^[0-9]+" $line)
+ (string-to-number (match-string 0 $line))))
+ (let (($po (point))
+ ($poe (point-at-eol)))
+ (while (<= (setq $po (next-single-property-change $po 'face)) $poe)
+ (when (eq 'helm-swoop-target-word-face (helm-swoop--get-at-face $po))
+ (goto-char $po))))
+ (helm-swoop--recenter))))))))
+
+(defun helm-multi-swoop-same-face-at-point (&optional $face)
+ (interactive)
+ (or $face (setq $face (helm-swoop--get-at-face)))
+ (helm-multi-swoop--exec
+ nil
+ :$query ""
+ :$func (lambda () (helm-swoop--cull-face-include-line $face))
+ :$action (lambda ($line)
+ (switch-to-buffer (assoc-default 'name (helm-get-current-source)))
+ (helm-swoop--goto-line
+ (when (string-match "^[0-9]+" $line)
+ (string-to-number (match-string 0 $line))))
+ (let (($po (point))
+ ($poe (point-at-eol)))
+ (while (<= (setq $po (next-single-property-change $po 'face)) $poe)
+ (when (eq 'helm-swoop-target-word-face (helm-swoop--get-at-face $po))
+ (goto-char $po))))
+ (helm-swoop--recenter))
+ :$buflist (helm-multi-swoop--get-buffer-list)))
+
+(provide 'helm-swoop)
+;;; helm-swoop.el ends here
+++ /dev/null
-List the all lines to another buffer, which is able to squeeze
-by any words you input. At the same time, the original buffer's
-cursor is jumping line to line according to moving up and down
-the list.
-
-Example config
-----------------------------------------------------------------
-helm from https://github.com/emacs-helm/helm
-(require 'helm)
-
-Locate the helm-swoop folder to your path
-This line is unnecessary if you get this program from MELPA
-(add-to-list 'load-path "~/.emacs.d/elisp/helm-swoop")
-
-(require 'helm-swoop)
-
-Change keybinds to whatever you like :)
-(global-set-key (kbd "M-i") 'helm-swoop)
-(global-set-key (kbd "M-I") 'helm-swoop-back-to-last-point)
-(global-set-key (kbd "C-c M-i") 'helm-multi-swoop)
-(global-set-key (kbd "C-x M-i") 'helm-multi-swoop-all)
-
-When doing isearch, hand the word over to helm-swoop
-(define-key isearch-mode-map (kbd "M-i") 'helm-swoop-from-isearch)
-(define-key helm-swoop-map (kbd "M-i") 'helm-multi-swoop-all-from-helm-swoop)
-
-Save buffer when helm-multi-swoop-edit complete
-(setq helm-multi-swoop-edit-save t)
-
-If this value is t, split window inside the current window
-(setq helm-swoop-split-with-multiple-windows nil)
-
-Split direction. 'split-window-vertically or 'split-window-horizontally
-(setq helm-swoop-split-direction 'split-window-vertically)
-
-If nil, you can slightly boost invoke speed in exchange for text color
-(setq helm-swoop-speed-or-color nil)
-
-Go to the opposite side of line from the end or beginning of line
-(setq helm-swoop-move-to-line-cycle t)
-
-Optional face for line numbers
-Face name is `helm-swoop-line-number-face`
-(setq helm-swoop-use-line-number-face t)
-
-----------------------------------------------------------------
-
-* `M-x helm-swoop` when region active
-* `M-x helm-swoop` when the cursor is at any symbol
-* `M-x helm-swoop` when the cursor is not at any symbol
-* `M-3 M-x helm-swoop` or `C-u 5 M-x helm-swoop` multi separated line culling
-* `M-x helm-multi-swoop` multi-occur like feature
-* `M-x helm-multi-swoop-all` apply all buffers
-* `C-u M-x helm-multi-swoop` apply last selected buffers from the second time
-* `M-x helm-swoop-same-face-at-point` list lines have the same face at the cursor is on
-* During isearch `M-i` to hand the word over to helm-swoop
-* During helm-swoop `M-i` to hand the word over to helm-multi-swoop-all
-* While doing `helm-swoop` press `C-c C-e` to edit mode, apply changes to original buffer by `C-x C-s`
-
-Helm Swoop Edit
-While doing helm-swoop, press keybind [C-c C-e] to move to edit buffer.
-Edit the list and apply by [C-x C-s]. If you'd like to cancel, [C-c C-g]
+++ /dev/null
-;;; restclient-helm-autoloads.el --- automatically extracted autoloads
-;;
-;;; Code:
-(add-to-list 'load-path (or (file-name-directory #$) (car load-path)))
-\f
-;;;### (autoloads nil "restclient-helm" "restclient-helm.el" (22294
-;;;;;; 20081 0 0))
-;;; Generated autoloads from restclient-helm.el
-
-(autoload 'helm-restclient "restclient-helm" "\
-Helm for Restclient.
-
-\(fn)" t nil)
-
-;;;***
-\f
-;; Local Variables:
-;; version-control: never
-;; no-byte-compile: t
-;; no-update-autoloads: t
-;; End:
-;;; restclient-helm-autoloads.el ends here
+++ /dev/null
-(define-package "restclient-helm" "20160407.249" "helm interface for restclient.el" '((restclient "0") (helm "1.9.4")) :keywords '("http" "helm"))
+++ /dev/null
-;;; restclient-helm.el --- helm interface for restclient.el
-;;
-;; Public domain.
-
-;; Author: Pavel Kurnosov <pashkyNOSPAMgmail.com>
-;; Maintainer: Pavel Kurnosov <pashkyNOSPAMgmail.com>
-;; Created: 01 Apr 2016
-;; Keywords: http helm
-;; Package-Version: 20160407.249
-;; Package-Requires: ((restclient "0") (helm "1.9.4"))
-
-;; This file is not part of GNU Emacs.
-;; This file is public domain software. Do what you want.
-
-;;; Commentary:
-;;
-;; This is a companion to restclient.el to add helm sources for requests and variables in current restclient-mode buffer.
-
-;;; Code:
-;;
-(require 'helm)
-(require 'helm-utils)
-(require 'restclient)
-
-(defun restclient-helm-find-candidates-matching (regexp process)
- (let ((result '()))
- (with-helm-current-buffer
- (if (fboundp 'font-lock-ensure)
- (font-lock-ensure)
- (with-no-warnings
- (font-lock-fontify-buffer)))
- (save-excursion
- (goto-char (point-min))
- (while (re-search-forward regexp nil t)
- (setq result (cons (cons (funcall process) (line-number-at-pos)) result))))
- result)))
-
-(defun restclient-helm-find-requests ()
- (restclient-helm-find-candidates-matching
- restclient-method-url-regexp
- '(lambda () (match-string 0))))
-
-(defun restclient-helm-find-variables ()
- (restclient-helm-find-candidates-matching
- restclient-var-regexp
- '(lambda () (match-string 1))))
-
-(defun restclient-helm-goto (candidate)
- (switch-to-buffer helm-current-buffer)
- (helm-goto-line candidate))
-
-(defconst restclient-helm-requests-source
- (helm-build-sync-source "Variables"
- :action '(("Go to declaration" . restclient-helm-goto))
- :candidates 'restclient-helm-find-variables))
-
-(defconst restclient-helm-variables-source
- (helm-build-sync-source "Requests"
- :action '(("Go to" . restclient-helm-goto))
- :candidates 'restclient-helm-find-requests))
-
-;;;###autoload
-(defun helm-restclient ()
- "Helm for Restclient."
- (interactive)
- (helm :sources '(restclient-helm-requests-source restclient-helm-variables-source)))
-
-(provide 'restclient-helm)
-
-(eval-after-load 'restclient
- '(progn
- (define-key restclient-mode-map (kbd "C-c C-g") #'helm-restclient)))
-
-;;; helm-restclient.el ends here
-
-;;; restclient-helm.el ends here
--- /dev/null
+;;; restclient-helm-autoloads.el --- automatically extracted autoloads
+;;
+;;; Code:
+
+(add-to-list 'load-path (directory-file-name
+ (or (file-name-directory #$) (car load-path))))
+
+\f
+;;;### (autoloads nil "restclient-helm" "restclient-helm.el" (0 0
+;;;;;; 0 0))
+;;; Generated autoloads from restclient-helm.el
+
+(autoload 'helm-restclient "restclient-helm" "\
+Helm for Restclient.
+
+\(fn)" t nil)
+
+(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "restclient-helm" '("restclient-helm-")))
+
+;;;***
+\f
+;; Local Variables:
+;; version-control: never
+;; no-byte-compile: t
+;; no-update-autoloads: t
+;; coding: utf-8
+;; End:
+;;; restclient-helm-autoloads.el ends here
--- /dev/null
+;;; -*- no-byte-compile: t -*-
+(define-package "restclient-helm" "20170314.1554" "helm interface for restclient.el" '((restclient "0") (helm "1.9.4")) :commit "859d944796ce298b5779d9d256bd8d271d57e221" :keywords '("http" "helm") :authors '(("Pavel Kurnosov" . "pashkyNOSPAMgmail.com")) :maintainer '("Pavel Kurnosov" . "pashkyNOSPAMgmail.com"))
--- /dev/null
+;;; restclient-helm.el --- helm interface for restclient.el
+;;
+;; Public domain.
+
+;; Author: Pavel Kurnosov <pashkyNOSPAMgmail.com>
+;; Maintainer: Pavel Kurnosov <pashkyNOSPAMgmail.com>
+;; Created: 01 Apr 2016
+;; Keywords: http helm
+;; Package-Version: 20170314.1554
+;; Package-Requires: ((restclient "0") (helm "1.9.4"))
+
+;; This file is not part of GNU Emacs.
+;; This file is public domain software. Do what you want.
+
+;;; Commentary:
+;;
+;; This is a companion to restclient.el to add helm sources for requests and variables in current restclient-mode buffer.
+
+;;; Code:
+;;
+(require 'helm)
+(require 'helm-utils)
+(require 'restclient)
+
+(defun restclient-helm-find-candidates-matching (regexp process)
+ (let ((result '()))
+ (with-helm-current-buffer
+ (if (fboundp 'font-lock-ensure)
+ (font-lock-ensure)
+ (with-no-warnings
+ (font-lock-fontify-buffer)))
+ (save-excursion
+ (goto-char (point-min))
+ (while (re-search-forward regexp nil t)
+ (setq result (cons (cons (funcall process) (line-number-at-pos)) result))))
+ result)))
+
+(defun restclient-helm-find-requests ()
+ (restclient-helm-find-candidates-matching
+ restclient-method-url-regexp
+ '(lambda () (match-string 0))))
+
+(defun restclient-helm-find-variables ()
+ (restclient-helm-find-candidates-matching
+ restclient-var-regexp
+ '(lambda () (match-string 1))))
+
+(defun restclient-helm-goto (candidate)
+ (switch-to-buffer helm-current-buffer)
+ (helm-goto-line candidate))
+
+(defconst restclient-helm-requests-source
+ (helm-build-sync-source "Variables"
+ :action '(("Go to declaration" . restclient-helm-goto))
+ :candidates 'restclient-helm-find-variables))
+
+(defconst restclient-helm-variables-source
+ (helm-build-sync-source "Requests"
+ :action '(("Go to" . restclient-helm-goto))
+ :candidates 'restclient-helm-find-requests))
+
+;;;###autoload
+(defun helm-restclient ()
+ "Helm for Restclient."
+ (interactive)
+ (helm :sources '(restclient-helm-requests-source restclient-helm-variables-source)))
+
+(provide 'restclient-helm)
+
+(eval-after-load 'restclient
+ '(progn
+ (define-key restclient-mode-map (kbd "C-c C-g") #'helm-restclient)))
+
+;;; restclient-helm.el ends here
+++ /dev/null
-This is a companion to restclient.el to add helm sources for requests and variables in current restclient-mode buffer.