From 0b67e10ebffa73b512fad9ea36d76281970b1583 Mon Sep 17 00:00:00 2001 From: Andreas Gerler Date: Mon, 12 Nov 2018 14:53:16 +0100 Subject: [PATCH] Updating helm. Signed-off-by: Andreas Gerler --- bba.org | 6 +- elpa/ac-helm-20140919.917/ac-helm-pkg.el | 1 - .../ac-helm-autoloads.el | 11 +- elpa/ac-helm-20160319.233/ac-helm-pkg.el | 2 + .../ac-helm.el | 4 +- elpa/ac-helm-readme.txt | 25 - elpa/helm-20160530.424/helm-apt.el | 300 - elpa/helm-20160530.424/helm-dabbrev.el | 327 - elpa/helm-20160530.424/helm-elscreen.el | 102 - elpa/helm-20160530.424/helm-eshell.el | 265 - elpa/helm-20160530.424/helm-files.el | 3589 ----------- elpa/helm-20160530.424/helm-font.el | 201 - elpa/helm-20160530.424/helm-help.el | 1507 ----- elpa/helm-20160530.424/helm-multi-match.el | 373 -- elpa/helm-20160530.424/helm-pkg.el | 9 - elpa/helm-20160530.424/helm-plugin.el | 137 - elpa/helm-20160530.424/helm-ring.el | 476 -- .../emacs-helm.sh | 93 +- .../helm-adaptive.el | 186 +- .../helm-autoloads.el | 438 +- .../helm-bookmark.el | 268 +- .../helm-buffers.el | 505 +- .../helm-color.el | 10 +- .../helm-command.el | 119 +- .../helm-config.el | 10 +- elpa/helm-20181110.1615/helm-dabbrev.el | 388 ++ .../helm-easymenu.el | 4 +- .../helm-elisp-package.el | 196 +- .../helm-elisp.el | 366 +- elpa/helm-20181110.1615/helm-eshell.el | 487 ++ .../helm-eval.el | 8 +- .../helm-external.el | 8 +- elpa/helm-20181110.1615/helm-files.el | 4476 +++++++++++++ elpa/helm-20181110.1615/helm-find.el | 172 + elpa/helm-20181110.1615/helm-font.el | 335 + elpa/helm-20181110.1615/helm-for-files.el | 308 + .../helm-grep.el | 593 +- elpa/helm-20181110.1615/helm-help.el | 1728 +++++ .../helm-id-utils.el | 10 +- .../helm-imenu.el | 196 +- .../helm-info.el | 69 +- .../helm-locate.el | 187 +- .../helm-man.el | 44 +- .../helm-misc.el | 245 +- .../helm-mode.el | 646 +- .../helm-net.el | 198 +- .../helm-org.el | 173 +- elpa/helm-20181110.1615/helm-pkg.el | 9 + .../helm-regexp.el | 223 +- elpa/helm-20181110.1615/helm-ring.el | 559 ++ .../helm-semantic.el | 28 +- .../helm-sys.el | 235 +- .../helm-tags.el | 36 +- .../helm-types.el | 87 +- .../helm-utils.el | 595 +- elpa/helm-20181110.1615/helm-x-files.el | 128 + elpa/helm-aws-20151124.133/helm-aws-pkg.el | 1 - .../helm-aws-autoloads.el | 10 +- elpa/helm-aws-20180514.1032/helm-aws-pkg.el | 2 + .../helm-aws.el | 50 +- elpa/helm-aws-readme.txt | 6 - .../helm-c-yasnippet-pkg.el | 1 - .../helm-c-yasnippet-autoloads.el | 12 +- .../helm-c-yasnippet-pkg.el | 2 + .../helm-c-yasnippet.el | 20 +- elpa/helm-c-yasnippet-readme.txt | 2 - .../helm-core-autoloads.el | 202 - elpa/helm-core-20160105.2046/helm-core-pkg.el | 8 - elpa/helm-core-20160105.2046/helm-lib.el | 674 -- .../helm-multi-match.el | 373 -- elpa/helm-core-20160105.2046/helm-source.el | 1008 --- elpa/helm-core-20160105.2046/helm.el | 5532 ---------------- .../helm-core-autoloads.el | 202 - elpa/helm-core-20160217.958/helm-core-pkg.el | 7 - elpa/helm-core-20160217.958/helm-lib.el | 714 --- .../helm-multi-match.el | 373 -- elpa/helm-core-20160217.958/helm-source.el | 1016 --- elpa/helm-core-20160217.958/helm.el | 5641 ----------------- .../helm-core-autoloads.el | 200 - elpa/helm-core-20160530.52/helm-core-pkg.el | 7 - elpa/helm-core-20160530.52/helm-lib.el | 803 --- .../helm-core-autoloads.el | 261 + elpa/helm-core-20181110.1635/helm-core-pkg.el | 7 + elpa/helm-core-20181110.1635/helm-lib.el | 1379 ++++ .../helm-multi-match.el | 30 +- .../helm-source.el | 307 +- .../helm.el | 4346 ++++++++----- .../helm-descbinds-autoloads.el | 46 - .../helm-descbinds-pkg.el | 1 - .../helm-descbinds.el | 297 - .../helm-descbinds-pkg.el | 1 - .../helm-descbinds-autoloads.el | 15 +- .../helm-descbinds-pkg.el | 2 + .../helm-descbinds.el | 66 +- .../helm-git-autoloads.el | 18 - elpa/helm-git-20120630.1403/helm-git-pkg.el | 1 - .../helm-git-autoloads.el | 22 + elpa/helm-git-20120630.2103/helm-git-pkg.el | 2 + .../helm-git.el | 2 +- elpa/helm-git-readme.txt | 6 - .../helm-gtags-20160202.503/helm-gtags-pkg.el | 1 - .../helm-gtags-autoloads.el | 16 +- .../helm-gtags-20170116.529/helm-gtags-pkg.el | 2 + .../helm-gtags.el | 142 +- .../helm-projectile-pkg.el | 1 - .../helm-projectile-autoloads.el | 30 +- .../helm-projectile-pkg.el | 2 + .../helm-projectile.el | 643 +- elpa/helm-projectile-readme.txt | 6 - .../helm-safari-pkg.el | 1 - elpa/helm-safari-20160115.2334/helm-safari.el | 94 - .../helm-safari-autoloads.el | 15 +- .../helm-safari-pkg.el | 2 + elpa/helm-safari-20160404.324/helm-safari.el | 121 + elpa/helm-safari-readme.txt | 0 .../helm-swoop-pkg.el | 2 - .../helm-swoop-autoloads.el | 11 +- .../helm-swoop-pkg.el | 2 + .../helm-swoop.el | 8 +- elpa/helm-swoop-readme.txt | 62 - .../restclient-helm-pkg.el | 1 - .../restclient-helm-autoloads.el | 12 +- .../restclient-helm-pkg.el | 2 + .../restclient-helm.el | 4 +- elpa/restclient-helm-readme.txt | 1 - 125 files changed, 17856 insertions(+), 28701 deletions(-) delete mode 100644 elpa/ac-helm-20140919.917/ac-helm-pkg.el rename elpa/{ac-helm-20140919.917 => ac-helm-20160319.233}/ac-helm-autoloads.el (61%) create mode 100644 elpa/ac-helm-20160319.233/ac-helm-pkg.el rename elpa/{ac-helm-20140919.917 => ac-helm-20160319.233}/ac-helm.el (98%) delete mode 100644 elpa/ac-helm-readme.txt delete mode 100644 elpa/helm-20160530.424/helm-apt.el delete mode 100644 elpa/helm-20160530.424/helm-dabbrev.el delete mode 100644 elpa/helm-20160530.424/helm-elscreen.el delete mode 100644 elpa/helm-20160530.424/helm-eshell.el delete mode 100644 elpa/helm-20160530.424/helm-files.el delete mode 100644 elpa/helm-20160530.424/helm-font.el delete mode 100644 elpa/helm-20160530.424/helm-help.el delete mode 100644 elpa/helm-20160530.424/helm-multi-match.el delete mode 100644 elpa/helm-20160530.424/helm-pkg.el delete mode 100644 elpa/helm-20160530.424/helm-plugin.el delete mode 100644 elpa/helm-20160530.424/helm-ring.el rename elpa/{helm-20160530.424 => helm-20181110.1615}/emacs-helm.sh (54%) rename elpa/{helm-20160530.424 => helm-20181110.1615}/helm-adaptive.el (56%) rename elpa/{helm-20160530.424 => helm-20181110.1615}/helm-autoloads.el (64%) rename elpa/{helm-20160530.424 => helm-20181110.1615}/helm-bookmark.el (79%) rename elpa/{helm-20160530.424 => helm-20181110.1615}/helm-buffers.el (63%) rename elpa/{helm-20160530.424 => helm-20181110.1615}/helm-color.el (93%) rename elpa/{helm-20160530.424 => helm-20181110.1615}/helm-command.el (69%) rename elpa/{helm-20160530.424 => helm-20181110.1615}/helm-config.el (96%) create mode 100644 elpa/helm-20181110.1615/helm-dabbrev.el rename elpa/{helm-20160530.424 => helm-20181110.1615}/helm-easymenu.el (96%) rename elpa/{helm-20160530.424 => helm-20181110.1615}/helm-elisp-package.el (69%) rename elpa/{helm-20160530.424 => helm-20181110.1615}/helm-elisp.el (76%) create mode 100644 elpa/helm-20181110.1615/helm-eshell.el rename elpa/{helm-20160530.424 => helm-20181110.1615}/helm-eval.el (97%) rename elpa/{helm-20160530.424 => helm-20181110.1615}/helm-external.el (97%) create mode 100644 elpa/helm-20181110.1615/helm-files.el create mode 100644 elpa/helm-20181110.1615/helm-find.el create mode 100644 elpa/helm-20181110.1615/helm-font.el create mode 100644 elpa/helm-20181110.1615/helm-for-files.el rename elpa/{helm-20160530.424 => helm-20181110.1615}/helm-grep.el (72%) create mode 100644 elpa/helm-20181110.1615/helm-help.el rename elpa/{helm-20160530.424 => helm-20181110.1615}/helm-id-utils.el (93%) rename elpa/{helm-20160530.424 => helm-20181110.1615}/helm-imenu.el (52%) rename elpa/{helm-20160530.424 => helm-20181110.1615}/helm-info.el (81%) rename elpa/{helm-20160530.424 => helm-20181110.1615}/helm-locate.el (69%) rename elpa/{helm-20160530.424 => helm-20181110.1615}/helm-man.el (72%) rename elpa/{helm-20160530.424 => helm-20181110.1615}/helm-misc.el (56%) rename elpa/{helm-20160530.424 => helm-20181110.1615}/helm-mode.el (68%) rename elpa/{helm-20160530.424 => helm-20181110.1615}/helm-net.el (76%) rename elpa/{helm-20160530.424 => helm-20181110.1615}/helm-org.el (62%) create mode 100644 elpa/helm-20181110.1615/helm-pkg.el rename elpa/{helm-20160530.424 => helm-20181110.1615}/helm-regexp.el (73%) create mode 100644 elpa/helm-20181110.1615/helm-ring.el rename elpa/{helm-20160530.424 => helm-20181110.1615}/helm-semantic.el (88%) rename elpa/{helm-20160530.424 => helm-20181110.1615}/helm-sys.el (60%) rename elpa/{helm-20160530.424 => helm-20181110.1615}/helm-tags.el (93%) rename elpa/{helm-20160530.424 => helm-20181110.1615}/helm-types.el (76%) rename elpa/{helm-20160530.424 => helm-20181110.1615}/helm-utils.el (53%) create mode 100644 elpa/helm-20181110.1615/helm-x-files.el delete mode 100644 elpa/helm-aws-20151124.133/helm-aws-pkg.el rename elpa/{helm-aws-20151124.133 => helm-aws-20180514.1032}/helm-aws-autoloads.el (55%) create mode 100644 elpa/helm-aws-20180514.1032/helm-aws-pkg.el rename elpa/{helm-aws-20151124.133 => helm-aws-20180514.1032}/helm-aws.el (81%) delete mode 100644 elpa/helm-aws-readme.txt delete mode 100644 elpa/helm-c-yasnippet-20151231.10/helm-c-yasnippet-pkg.el rename elpa/{helm-c-yasnippet-20151231.10 => helm-c-yasnippet-20170128.1542}/helm-c-yasnippet-autoloads.el (73%) create mode 100644 elpa/helm-c-yasnippet-20170128.1542/helm-c-yasnippet-pkg.el rename elpa/{helm-c-yasnippet-20151231.10 => helm-c-yasnippet-20170128.1542}/helm-c-yasnippet.el (96%) delete mode 100644 elpa/helm-c-yasnippet-readme.txt delete mode 100644 elpa/helm-core-20160105.2046/helm-core-autoloads.el delete mode 100644 elpa/helm-core-20160105.2046/helm-core-pkg.el delete mode 100644 elpa/helm-core-20160105.2046/helm-lib.el delete mode 100644 elpa/helm-core-20160105.2046/helm-multi-match.el delete mode 100644 elpa/helm-core-20160105.2046/helm-source.el delete mode 100644 elpa/helm-core-20160105.2046/helm.el delete mode 100644 elpa/helm-core-20160217.958/helm-core-autoloads.el delete mode 100644 elpa/helm-core-20160217.958/helm-core-pkg.el delete mode 100644 elpa/helm-core-20160217.958/helm-lib.el delete mode 100644 elpa/helm-core-20160217.958/helm-multi-match.el delete mode 100644 elpa/helm-core-20160217.958/helm-source.el delete mode 100644 elpa/helm-core-20160217.958/helm.el delete mode 100644 elpa/helm-core-20160530.52/helm-core-autoloads.el delete mode 100644 elpa/helm-core-20160530.52/helm-core-pkg.el delete mode 100644 elpa/helm-core-20160530.52/helm-lib.el create mode 100644 elpa/helm-core-20181110.1635/helm-core-autoloads.el create mode 100644 elpa/helm-core-20181110.1635/helm-core-pkg.el create mode 100644 elpa/helm-core-20181110.1635/helm-lib.el rename elpa/{helm-core-20160530.52 => helm-core-20181110.1635}/helm-multi-match.el (94%) rename elpa/{helm-core-20160530.52 => helm-core-20181110.1635}/helm-source.el (77%) rename elpa/{helm-core-20160530.52 => helm-core-20181110.1635}/helm.el (56%) delete mode 100644 elpa/helm-descbinds-20151019.230/helm-descbinds-autoloads.el delete mode 100644 elpa/helm-descbinds-20151019.230/helm-descbinds-pkg.el delete mode 100644 elpa/helm-descbinds-20151019.230/helm-descbinds.el delete mode 100644 elpa/helm-descbinds-20160108.1947/helm-descbinds-pkg.el rename elpa/{helm-descbinds-20160108.1947 => helm-descbinds-20180429.1456}/helm-descbinds-autoloads.el (81%) create mode 100644 elpa/helm-descbinds-20180429.1456/helm-descbinds-pkg.el rename elpa/{helm-descbinds-20160108.1947 => helm-descbinds-20180429.1456}/helm-descbinds.el (86%) delete mode 100644 elpa/helm-git-20120630.1403/helm-git-autoloads.el delete mode 100644 elpa/helm-git-20120630.1403/helm-git-pkg.el create mode 100644 elpa/helm-git-20120630.2103/helm-git-autoloads.el create mode 100644 elpa/helm-git-20120630.2103/helm-git-pkg.el rename elpa/{helm-git-20120630.1403 => helm-git-20120630.2103}/helm-git.el (99%) delete mode 100644 elpa/helm-git-readme.txt delete mode 100644 elpa/helm-gtags-20160202.503/helm-gtags-pkg.el rename elpa/{helm-gtags-20160202.503 => helm-gtags-20170116.529}/helm-gtags-autoloads.el (88%) create mode 100644 elpa/helm-gtags-20170116.529/helm-gtags-pkg.el rename elpa/{helm-gtags-20160202.503 => helm-gtags-20170116.529}/helm-gtags.el (92%) delete mode 100644 elpa/helm-projectile-20151220.221/helm-projectile-pkg.el rename elpa/{helm-projectile-20151220.221 => helm-projectile-20180815.1514}/helm-projectile-autoloads.el (71%) create mode 100644 elpa/helm-projectile-20180815.1514/helm-projectile-pkg.el rename elpa/{helm-projectile-20151220.221 => helm-projectile-20180815.1514}/helm-projectile.el (55%) delete mode 100644 elpa/helm-projectile-readme.txt delete mode 100644 elpa/helm-safari-20160115.2334/helm-safari-pkg.el delete mode 100644 elpa/helm-safari-20160115.2334/helm-safari.el rename elpa/{helm-safari-20160115.2334 => helm-safari-20160404.324}/helm-safari-autoloads.el (53%) create mode 100644 elpa/helm-safari-20160404.324/helm-safari-pkg.el create mode 100644 elpa/helm-safari-20160404.324/helm-safari.el delete mode 100644 elpa/helm-safari-readme.txt delete mode 100644 elpa/helm-swoop-20170923.2127/helm-swoop-pkg.el rename elpa/{helm-swoop-20170923.2127 => helm-swoop-20180215.1154}/helm-swoop-autoloads.el (86%) create mode 100644 elpa/helm-swoop-20180215.1154/helm-swoop-pkg.el rename elpa/{helm-swoop-20170923.2127 => helm-swoop-20180215.1154}/helm-swoop.el (99%) delete mode 100644 elpa/helm-swoop-readme.txt delete mode 100644 elpa/restclient-helm-20160407.249/restclient-helm-pkg.el rename elpa/{restclient-helm-20160407.249 => restclient-helm-20170314.1554}/restclient-helm-autoloads.el (52%) create mode 100644 elpa/restclient-helm-20170314.1554/restclient-helm-pkg.el rename elpa/{restclient-helm-20160407.249 => restclient-helm-20170314.1554}/restclient-helm.el (97%) delete mode 100644 elpa/restclient-helm-readme.txt diff --git a/bba.org b/bba.org index 62d9b389..013c06bb 100644 --- a/bba.org +++ b/bba.org @@ -3299,7 +3299,7 @@ If you are new to tags check [[http://tuhdo.github.io/c-ide.html][this]]. (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() @@ -3333,7 +3333,7 @@ Some links you might check out: (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) @@ -3380,7 +3380,7 @@ Some links you might check out: #+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) ) diff --git a/elpa/ac-helm-20140919.917/ac-helm-pkg.el b/elpa/ac-helm-20140919.917/ac-helm-pkg.el deleted file mode 100644 index be2c58fa..00000000 --- a/elpa/ac-helm-20140919.917/ac-helm-pkg.el +++ /dev/null @@ -1 +0,0 @@ -(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")))) diff --git a/elpa/ac-helm-20140919.917/ac-helm-autoloads.el b/elpa/ac-helm-20160319.233/ac-helm-autoloads.el similarity index 61% rename from elpa/ac-helm-20140919.917/ac-helm-autoloads.el rename to elpa/ac-helm-20160319.233/ac-helm-autoloads.el index 5b2bd63c..a8cde72b 100644 --- a/elpa/ac-helm-20140919.917/ac-helm-autoloads.el +++ b/elpa/ac-helm-20160319.233/ac-helm-autoloads.el @@ -2,9 +2,11 @@ ;; ;;; Code: +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + -;;;### (autoloads (ac-complete-with-helm) "ac-helm" "ac-helm.el" -;;;;;; (21793 7937 0 0)) +;;;### (autoloads nil "ac-helm" "ac-helm.el" (0 0 0 0)) ;;; Generated autoloads from ac-helm.el (autoload 'ac-complete-with-helm "ac-helm" "\ @@ -13,13 +15,10 @@ It is useful to narrow candidates. \(fn)" t nil) -;;;*** - -;;;### (autoloads nil nil ("ac-helm-pkg.el") (21793 7937 70647 0)) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "ac-helm" '("helm-"))) ;;;*** -(provide 'ac-helm-autoloads) ;; Local Variables: ;; version-control: never ;; no-byte-compile: t diff --git a/elpa/ac-helm-20160319.233/ac-helm-pkg.el b/elpa/ac-helm-20160319.233/ac-helm-pkg.el new file mode 100644 index 00000000..3089bfb3 --- /dev/null +++ b/elpa/ac-helm-20160319.233/ac-helm-pkg.el @@ -0,0 +1,2 @@ +;;; -*- 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" . "rubikitch@ruby-lang.org") ("Yasuyuki Oka" . "yasuyk@gmail.com")) :maintainer '("Yasuyuki Oka" . "yasuyk@gmail.com")) diff --git a/elpa/ac-helm-20140919.917/ac-helm.el b/elpa/ac-helm-20160319.233/ac-helm.el similarity index 98% rename from elpa/ac-helm-20140919.917/ac-helm.el rename to elpa/ac-helm-20160319.233/ac-helm.el index 08e2c51c..ad4176b4 100644 --- a/elpa/ac-helm-20140919.917/ac-helm.el +++ b/elpa/ac-helm-20160319.233/ac-helm.el @@ -7,7 +7,7 @@ ;; Yasuyuki Oka ;; Maintainer: Yasuyuki Oka ;; Version: 2.2 -;; Package-Version: 20140919.917 +;; 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 @@ -57,7 +57,7 @@ ;;; Code: (require 'helm) -(require 'helm-match-plugin nil t) +(require 'helm-multi-match nil t) (require 'helm-elisp) (require 'auto-complete) (require 'cl-lib) diff --git a/elpa/ac-helm-readme.txt b/elpa/ac-helm-readme.txt deleted file mode 100644 index 7d4aa332..00000000 --- a/elpa/ac-helm-readme.txt +++ /dev/null @@ -1,25 +0,0 @@ -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. diff --git a/elpa/helm-20160530.424/helm-apt.el b/elpa/helm-20160530.424/helm-apt.el deleted file mode 100644 index d8ea2fa8..00000000 --- a/elpa/helm-20160530.424/helm-apt.el +++ /dev/null @@ -1,300 +0,0 @@ -;;; helm-apt.el --- Helm interface for Debian/Ubuntu packages (apt-*) -*- lexical-binding: t -*- - -;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto - -;; 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 . - -;;; 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") - - -(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) - - -(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)) - - -(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 diff --git a/elpa/helm-20160530.424/helm-dabbrev.el b/elpa/helm-20160530.424/helm-dabbrev.el deleted file mode 100644 index 21d54f7d..00000000 --- a/elpa/helm-20160530.424/helm-dabbrev.el +++ /dev/null @@ -1,327 +0,0 @@ -;;; helm-dabbrev.el --- Helm implementation of dabbrev. -*- lexical-binding: t -*- - -;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto - -;; 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 . - -;;; Code: - -(require 'helm) -(require 'helm-lib) -(require 'helm-help) -(require 'helm-elisp) ; For show-completion. - -(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))) - - -(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) - - -(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)))) - -(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 diff --git a/elpa/helm-20160530.424/helm-elscreen.el b/elpa/helm-20160530.424/helm-elscreen.el deleted file mode 100644 index 44ac52cd..00000000 --- a/elpa/helm-20160530.424/helm-elscreen.el +++ /dev/null @@ -1,102 +0,0 @@ -;;; helm-elscreen.el -- Elscreen support -*- lexical-binding: t -*- - -;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto - -;; 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 . - -;;; 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 diff --git a/elpa/helm-20160530.424/helm-eshell.el b/elpa/helm-20160530.424/helm-eshell.el deleted file mode 100644 index b8473d6b..00000000 --- a/elpa/helm-20160530.424/helm-eshell.el +++ /dev/null @@ -1,265 +0,0 @@ -;;; helm-eshell.el --- pcomplete and eshell completion for helm. -*- lexical-binding: t -*- - -;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto - -;; 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 . - -;;; 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") - - -(defgroup helm-eshell nil - "Helm eshell completion and history." - :group 'helm) - - -(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'.") - - -(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)))))) - -;;; 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.") - - -;;;###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 diff --git a/elpa/helm-20160530.424/helm-files.el b/elpa/helm-20160530.424/helm-files.el deleted file mode 100644 index dba88eaf..00000000 --- a/elpa/helm-20160530.424/helm-files.el +++ /dev/null @@ -1,3589 +0,0 @@ -;;; helm-files.el --- helm file browser and related. -*- lexical-binding: t -*- - -;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto - -;; 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 . - -;;; Code: - -(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) - - -(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 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- 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 ." - :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-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) - - -;;; 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) - - -;;; 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-") 'helm-ff-run-toggle-auto-update) - (define-key map (kbd "C-c ") '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 "") 'helm-find-files-up-one-level) - (define-key map (kbd "") '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 "") 'helm-cr-empty-string) - (define-key map (kbd "") '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-") 'helm-ff-run-toggle-auto-update) - (define-key map (kbd "C-c ") '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 "") 'helm-find-files-up-one-level) - (define-key map (kbd "") 'helm-execute-persistent-action) - (define-key map (kbd "") 'helm-previous-source) - (define-key map (kbd "") 'helm-next-source)) - (delq nil map)) - "Keymap for `helm-read-file-name'.") - - -;; Internal. -(defvar helm-find-files-doc-header " (\\\\[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) - - -;;; 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 -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 - (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-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))))) - - -;;; 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))))) - - -;;; 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) - - -;;; 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)) - - -;;; 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))) - - -;;; 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: -;; -;; -;; 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: - -and - -and -." - (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.") - - -;;; 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)) - - -;;; 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.") - - -;;; 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) - - -;;; 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 diff --git a/elpa/helm-20160530.424/helm-font.el b/elpa/helm-20160530.424/helm-font.el deleted file mode 100644 index c88e3ba9..00000000 --- a/elpa/helm-20160530.424/helm-font.el +++ /dev/null @@ -1,201 +0,0 @@ -;;; helm-font --- Font and ucs selection for Helm -*- lexical-binding: t -*- - -;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto - -;; 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 . - -;;; 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 "") 'helm-ucs-persistent-delete) - (define-key map (kbd "") 'helm-ucs-persistent-backward) - (define-key map (kbd "") 'helm-ucs-persistent-forward) - (define-key map (kbd "") '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 diff --git a/elpa/helm-20160530.424/helm-help.el b/elpa/helm-20160530.424/helm-help.el deleted file mode 100644 index 2232da65..00000000 --- a/elpa/helm-20160530.424/helm-help.el +++ /dev/null @@ -1,1507 +0,0 @@ -;;; helm-help.el --- Help messages for Helm. -*- lexical-binding: t -*- - -;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto - -;; 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 . - -;;; Code: -(require 'helm) - -(defvar helm-org-headings--nofilename) -(declare-function helm-source-org-headings-for-files "helm-org.el") - - -(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) - -(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)) - - -;;;###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*"))) - -;;; 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-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-' - -*** `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-'). - -*** 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- may not work, use in this case C-c . - -*** You can create a new directory and a new file at the same time - -Just write the path in prompt and press `'. -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 - -*** 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-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- and then . -This should not be needed when copying/renaming files because autoupdate is disabled -by default in that case. -NOTE: On a terminal C- may not work, use in this case C-c . - -*** 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 . -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 - -**** 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-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 ...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-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-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-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-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-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-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., - - 'candidate_file' - -But you can also pass an argument or more after 'candidate_file' like this: - - %s [extra_args] - -'candidate_file' will be added at '%s' and your command will look at this: - - 'candidate_file' [extra_args] - -*** Specify many files as args (marked files) - -E.g. 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: - - file1 file2 etc... - -** Commands -\\") - -;;; Ido virtual buffer help -;; -;; -(defvar helm-buffers-ido-virtual-help-message - "* Helm ido virtual buffers - -** Commands -\\ -\\[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-' and `C-' 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-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-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-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 . - -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-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-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-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 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 -\\") - - -;;; Mode line strings -;; -;; -;;;###autoload -(defvar helm-comp-read-mode-line "\ -\\\ -C/\\[helm-cr-empty-string]:Empty \ -\\\ -\\[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-help]:Help \ -C/\\[helm-cr-empty-string]:Empty \ -\\\ -\\[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-help]:Help \ -\\\ -\\[helm-select-action]:Act \ -\\[helm-maybe-exit-minibuffer]/\ -f1/f2/f-n:NthAct \ -\\[helm-toggle-suspend-update]:Tog.suspend") - - -;;; 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-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 diff --git a/elpa/helm-20160530.424/helm-multi-match.el b/elpa/helm-20160530.424/helm-multi-match.el deleted file mode 100644 index a926adbc..00000000 --- a/elpa/helm-20160530.424/helm-multi-match.el +++ /dev/null @@ -1,373 +0,0 @@ -;;; 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 - -;; Author: Thierry Volpiatto -;; 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 . - -;;; Code: - -(require 'cl-lib) -(require 'helm-lib) - - -(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) - - -;; 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)) - - -;;; 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) ".*")) - - -;;; 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))) - - -;;; 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)) - - -;;; 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)) - - -;;; 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)) - - -;;; 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)) - -;;; 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))) - - -;;; 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)) - - -;;; 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 diff --git a/elpa/helm-20160530.424/helm-pkg.el b/elpa/helm-20160530.424/helm-pkg.el deleted file mode 100644 index f3c8f596..00000000 --- a/elpa/helm-20160530.424/helm-pkg.el +++ /dev/null @@ -1,9 +0,0 @@ -(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: diff --git a/elpa/helm-20160530.424/helm-plugin.el b/elpa/helm-20160530.424/helm-plugin.el deleted file mode 100644 index 82f60d42..00000000 --- a/elpa/helm-20160530.424/helm-plugin.el +++ /dev/null @@ -1,137 +0,0 @@ -;;; helm-plugin.el --- Helm plugins -*- lexical-binding: t -*- - -;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto - -;; 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 . - -;;; Code: - -(require 'cl-lib) -(require 'helm) -(require 'helm-utils) - - -;;; 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\"))") - - -;;; 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.") - - -;;; 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-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)"))) - - -;;; 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 diff --git a/elpa/helm-20160530.424/helm-ring.el b/elpa/helm-20160530.424/helm-ring.el deleted file mode 100644 index 3221af6f..00000000 --- a/elpa/helm-20160530.424/helm-ring.el +++ /dev/null @@ -1,476 +0,0 @@ -;;; helm-ring.el --- kill-ring, mark-ring, and register browsers for helm. -*- lexical-binding: t -*- - -;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto - -;; 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 . - -;;; 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)) - - -(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)) - - -;;; 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))) - - -;;;; -;; 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) - "" - 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]"))) - (_ "")))) - (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)))) - -;;;; -;;; 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 ' to execute 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 diff --git a/elpa/helm-20160530.424/emacs-helm.sh b/elpa/helm-20181110.1615/emacs-helm.sh similarity index 54% rename from elpa/helm-20160530.424/emacs-helm.sh rename to elpa/helm-20181110.1615/emacs-helm.sh index 1213a867..2f688eef 100755 --- a/elpa/helm-20160530.424/emacs-helm.sh +++ b/elpa/helm-20181110.1615/emacs-helm.sh @@ -1,29 +1,28 @@ -#!/usr/bin/env bash +#!/bin/sh -## Copyright (C) 2012 ~ 2016 Thierry Volpiatto -## +## Copyright (C) 2012 ~ 2018 Thierry Volpiatto +## ## 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 . ## Commentary: -# Preconfigured Emacs with a basic helm configuration. -# Useful to start quickly an emacs -Q with helm. +# 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. -[ -z $TEMP ] && declare TEMP="/tmp" +# If TEMP env var exists, use it, otherwise declare it. +test -z "$TEMP" && TEMP="/tmp" CONF_FILE="$TEMP/helm-cfg.el" EMACS=emacs @@ -31,58 +30,65 @@ EMACS=emacs case $1 in -P) shift 1 - declare EMACS=$1 + EMACS=$1 shift 1 ;; -h) echo "Usage: ${0##*/} [-P} Emacs path [-h} help [--] EMACS ARGS" - exit 2 + exit 1 ;; esac -cd $(dirname "$0") +LOAD_PATH=$($EMACS -q -batch --eval "(prin1 load-path)") + +cd "${0%/*}" || exit 1 # 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" +# 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 2 + exit 1 fi cat > $CONF_FILE <\`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")) +";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\\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-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)) +(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) @@ -95,12 +101,11 @@ cat > $CONF_FILE < +;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto ;; 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 @@ -30,7 +30,10 @@ (defcustom helm-adaptive-history-file "~/.emacs.d/helm-adaptive-history" - "Path of file where history information is stored." + "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) @@ -39,6 +42,21 @@ :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) ;; Internal (defvar helm-adaptive-done nil @@ -49,6 +67,9 @@ selection.") "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)) @@ -80,16 +101,10 @@ Format: ((SOURCE-NAME (SELECTED-CANDIDATE (PATTERN . NUMBER-OF-USE) ...) ...) .. "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) + (adapt-source (or (assoc-default 'filtered-candidate-transformer source) (assoc-default 'candidate-transformer source)))) (if (listp adapt-source) - (and (member 'helm-adaptive-sort adapt-source) source) + (and (memq 'helm-adaptive-sort adapt-source) source) (and (eq adapt-source 'helm-adaptive-sort) source))))) (defun helm-adaptive-store-selection () @@ -98,13 +113,12 @@ Format: ((SOURCE-NAME (SELECTED-CANDIDATE (PATTERN . NUMBER-OF-USE) ...) ...) .. (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))) + (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)) + (selection (helm-get-selection nil t)) (selection-info (progn (setcdr source-info (cons @@ -128,7 +142,6 @@ Format: ((SOURCE-NAME (SELECTED-CANDIDATE (PATTERN . NUMBER-OF-USE) ...) ...) .. (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 @@ -137,12 +150,16 @@ Format: ((SOURCE-NAME (SELECTED-CANDIDATE (PATTERN . NUMBER-OF-USE) ...) ...) .. (delete found (cdr selection-info))) found)) (cdr selection-info))) - (cadr selection-info)))) - - ;; increase usage count + (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))) - - ;; truncate history if needed + ;; 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)))))))) @@ -150,72 +167,88 @@ Format: ((SOURCE-NAME (SELECTED-CANDIDATE (PATTERN . NUMBER-OF-USE) ...) ...) .. (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) + (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") - (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)))) + (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 (or (assoc-default 'type source) - (assoc-default 'name source))) + (let* ((source-name (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, \ + ;; 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))) + 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 () @@ -227,16 +260,17 @@ Useful when you have a old or corrupted `helm-adaptive-history-file'." (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))) + "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 cl-functions obsolete) +;; byte-compile-warnings: (not obsolete) ;; coding: utf-8 ;; indent-tabs-mode: nil ;; End: diff --git a/elpa/helm-20160530.424/helm-autoloads.el b/elpa/helm-20181110.1615/helm-autoloads.el similarity index 64% rename from elpa/helm-20160530.424/helm-autoloads.el rename to elpa/helm-20181110.1615/helm-autoloads.el index 61ff81c4..6e4a3959 100644 --- a/elpa/helm-20160530.424/helm-autoloads.el +++ b/elpa/helm-20181110.1615/helm-autoloads.el @@ -1,15 +1,18 @@ ;;; helm-autoloads.el --- automatically extracted autoloads ;; ;;; Code: -(add-to-list 'load-path (or (file-name-directory #$) (car load-path))) + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + -;;;### (autoloads nil "helm-adaptive" "helm-adaptive.el" (22348 36311 -;;;;;; 0 0)) +;;;### (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 command `helm-adaptive-mode' for a description of this minor mode. +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'.") @@ -27,21 +30,11 @@ Useful when you have a old or corrupted `helm-adaptive-history-file'. \(fn)" t nil) -;;;*** - -;;;### (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) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-adaptive" '("helm-adapt"))) ;;;*** -;;;### (autoloads nil "helm-bookmark" "helm-bookmark.el" (22348 36311 -;;;;;; 0 0)) +;;;### (autoloads nil "helm-bookmark" "helm-bookmark.el" (0 0 0 0)) ;;; Generated autoloads from helm-bookmark.el (autoload 'helm-bookmarks "helm-bookmark" "\ @@ -52,14 +45,15 @@ Preconfigured `helm' for bookmarks. (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. +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"))) + ;;;*** -;;;### (autoloads nil "helm-buffers" "helm-buffers.el" (22348 36311 -;;;;;; 0 0)) +;;;### (autoloads nil "helm-buffers" "helm-buffers.el" (0 0 0 0)) ;;; Generated autoloads from helm-buffers.el (autoload 'helm-buffers-list "helm-buffers" "\ @@ -72,10 +66,11 @@ Preconfigured `helm' lightweight version (buffer -> recentf). \(fn)" t nil) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-buffers" '("helm-"))) + ;;;*** -;;;### (autoloads nil "helm-color" "helm-color.el" (22348 36311 0 -;;;;;; 0)) +;;;### (autoloads nil "helm-color" "helm-color.el" (0 0 0 0)) ;;; Generated autoloads from helm-color.el (autoload 'helm-colors "helm-color" "\ @@ -83,10 +78,11 @@ Preconfigured `helm' for color. \(fn)" t nil) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-color" '("helm-"))) + ;;;*** -;;;### (autoloads nil "helm-command" "helm-command.el" (22348 36311 -;;;;;; 0 0)) +;;;### (autoloads nil "helm-command" "helm-command.el" (0 0 0 0)) ;;; Generated autoloads from helm-command.el (autoload 'helm-M-x "helm-command" "\ @@ -94,16 +90,19 @@ 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'. +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-"))) + ;;;*** -;;;### (autoloads nil "helm-config" "helm-config.el" (22348 36311 -;;;;;; 0 0)) +;;;### (autoloads nil "helm-config" "helm-config.el" (0 0 0 0)) ;;; Generated autoloads from helm-config.el (autoload 'helm-configuration "helm-config" "\ @@ -111,10 +110,11 @@ Customize `helm'. \(fn)" t nil) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-config" '("helm-"))) + ;;;*** -;;;### (autoloads nil "helm-dabbrev" "helm-dabbrev.el" (22348 36311 -;;;;;; 0 0)) +;;;### (autoloads nil "helm-dabbrev" "helm-dabbrev.el" (0 0 0 0)) ;;; Generated autoloads from helm-dabbrev.el (autoload 'helm-dabbrev "helm-dabbrev" "\ @@ -122,10 +122,11 @@ Preconfigured helm for dynamic abbreviations. \(fn)" t nil) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-dabbrev" '("helm-dabbrev-"))) + ;;;*** -;;;### (autoloads nil "helm-elisp" "helm-elisp.el" (22348 36311 0 -;;;;;; 0)) +;;;### (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" "\ @@ -176,10 +177,12 @@ Preconfigured helm for complex command history. \(fn)" t nil) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-elisp" '("helm-" "with-helm-show-completion"))) + ;;;*** ;;;### (autoloads nil "helm-elisp-package" "helm-elisp-package.el" -;;;;;; (22348 36311 0 0)) +;;;;;; (0 0 0 0)) ;;; Generated autoloads from helm-elisp-package.el (autoload 'helm-list-elisp-packages "helm-elisp-package" "\ @@ -189,30 +192,17 @@ Preconfigured helm for listing and handling emacs packages. (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) -;;;*** - -;;;### (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) +Same as `helm-list-elisp-packages' but don't fetch packages on remote. +Called with a prefix ARG always fetch packages on remote. -(autoload 'helm-elscreen-history "helm-elscreen" "\ -Preconfigured helm to list elscreen in history order. +\(fn ARG)" t nil) -\(fn)" t nil) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-elisp-package" '("helm-"))) ;;;*** -;;;### (autoloads nil "helm-eshell" "helm-eshell.el" (22348 36311 -;;;;;; 0 0)) +;;;### (autoloads nil "helm-eshell" "helm-eshell.el" (0 0 0 0)) ;;; Generated autoloads from helm-eshell.el (autoload 'helm-esh-pcomplete "helm-eshell" "\ @@ -225,9 +215,21 @@ 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"))) + ;;;*** -;;;### (autoloads nil "helm-eval" "helm-eval.el" (22348 36311 0 0)) +;;;### (autoloads nil "helm-eval" "helm-eval.el" (0 0 0 0)) ;;; Generated autoloads from helm-eval.el (autoload 'helm-eval-expression "helm-eval" "\ @@ -245,10 +247,11 @@ Preconfigured helm for `helm-source-calculation-result'. \(fn)" t nil) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-eval" '("helm-"))) + ;;;*** -;;;### (autoloads nil "helm-external" "helm-external.el" (22348 36311 -;;;;;; 0 0)) +;;;### (autoloads nil "helm-external" "helm-external.el" (0 0 0 0)) ;;; Generated autoloads from helm-external.el (autoload 'helm-run-external-command "helm-external" "\ @@ -259,12 +262,18 @@ You can set your own list of commands with \(fn PROGRAM)" t nil) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-external" '("helm-"))) + ;;;*** -;;;### (autoloads nil "helm-files" "helm-files.el" (22348 36311 0 -;;;;;; 0)) +;;;### (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. @@ -280,13 +289,36 @@ NOTE: The prefix ARG have no effect on the VCS controlled directories. Needed dependencies for VCS: and - -and -. +. + +\(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-find "helm-files" "\ +(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"))) + +;;;*** + +;;;### (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 @@ -306,51 +338,59 @@ 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. +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-find" '("helm-"))) -\(fn ARG)" t nil) +;;;*** + +;;;### (autoloads nil "helm-font" "helm-font.el" (0 0 0 0)) +;;; Generated autoloads from helm-font.el -(autoload 'helm-for-files "helm-files" "\ -Preconfigured `helm' for opening files. -Run all sources defined in `helm-for-files-preferred-list'. +(autoload 'helm-select-xfont "helm-font" "\ +Preconfigured `helm' to select Xfont. \(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. +(autoload 'helm-ucs "helm-font" "\ +Preconfigured helm for `ucs-names'. -\(fn)" t nil) +Called with a prefix arg force reloading cache. -(autoload 'helm-recentf "helm-files" "\ -Preconfigured `helm' for `recentf'. +\(fn ARG)" t nil) -\(fn)" t nil) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-font" '("helm-"))) ;;;*** -;;;### (autoloads nil "helm-font" "helm-font.el" (22348 36311 0 0)) -;;; Generated autoloads from helm-font.el +;;;### (autoloads nil "helm-for-files" "helm-for-files.el" (0 0 0 +;;;;;; 0)) +;;; Generated autoloads from helm-for-files.el -(autoload 'helm-select-xfont "helm-font" "\ -Preconfigured `helm' to select Xfont. +(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-ucs "helm-font" "\ -Preconfigured helm for `ucs-names' math symbols. +(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-"))) + ;;;*** -;;;### (autoloads nil "helm-grep" "helm-grep.el" (22348 36311 0 0)) +;;;### (autoloads nil "helm-grep" "helm-grep.el" (0 0 0 0)) ;;; Generated autoloads from helm-grep.el (autoload 'helm-goto-precedent-file "helm-grep" "\ @@ -375,18 +415,20 @@ 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-"))) + ;;;*** -;;;### (autoloads nil "helm-help" "helm-help.el" (22348 36311 0 0)) +;;;### (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. +Preconfigured Helm for Helm documentation. With a prefix arg refresh the documentation. -Find here the documentation of all sources actually documented. +Find here the documentation of all documented sources. -\(fn ARG)" t nil) +\(fn)" t nil) (defvar helm-comp-read-mode-line "\\C/\\[helm-cr-empty-string]:Empty \\\\[helm-help]:Help \\[helm-select-action]:Act \\[helm-maybe-exit-minibuffer]/f1/f2/f-n:NthAct \\[helm-toggle-suspend-update]:Tog.suspend") @@ -395,16 +437,11 @@ String displayed in mode-line in `helm-source-find-files'.") (defvar helm-top-mode-line "\\\\[helm-help]:Help \\\\[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) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-help" '("helm-"))) ;;;*** -;;;### (autoloads nil "helm-id-utils" "helm-id-utils.el" (22348 36311 -;;;;;; 0 0)) +;;;### (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" "\ @@ -416,10 +453,11 @@ See . \(fn)" t nil) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-id-utils" '("helm-gid-"))) + ;;;*** -;;;### (autoloads nil "helm-imenu" "helm-imenu.el" (22348 36311 0 -;;;;;; 0)) +;;;### (autoloads nil "helm-imenu" "helm-imenu.el" (0 0 0 0)) ;;; Generated autoloads from helm-imenu.el (autoload 'helm-imenu "helm-imenu" "\ @@ -434,26 +472,39 @@ 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-"))) + ;;;*** -;;;### (autoloads nil "helm-info" "helm-info.el" (22348 36311 0 0)) +;;;### (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. -\(fn)" t nil) +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. -With a prefix-arg insert symbol at point. \(fn)" t nil) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-info" '("helm-"))) + ;;;*** -;;;### (autoloads nil "helm-locate" "helm-locate.el" (22348 36311 -;;;;;; 0 0)) +;;;### (autoloads nil "helm-locate" "helm-locate.el" (0 0 0 0)) ;;; Generated autoloads from helm-locate.el (autoload 'helm-projects-find-files "helm-locate" "\ @@ -478,9 +529,11 @@ Where db_path is a filename matched by \(fn ARG)" t nil) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-locate" '("helm-"))) + ;;;*** -;;;### (autoloads nil "helm-man" "helm-man.el" (22348 36311 0 0)) +;;;### (autoloads nil "helm-man" "helm-man.el" (0 0 0 0)) ;;; Generated autoloads from helm-man.el (autoload 'helm-man-woman "helm-man" "\ @@ -489,16 +542,13 @@ With a prefix arg reinitialize the cache. \(fn ARG)" t nil) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-man" '("helm-"))) + ;;;*** -;;;### (autoloads nil "helm-misc" "helm-misc.el" (22348 36311 0 0)) +;;;### (autoloads nil "helm-misc" "helm-misc.el" (0 0 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. @@ -530,9 +580,11 @@ Preconfigured `helm' that provide completion of `comint' history. \(fn)" t nil) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-misc" '("helm-"))) + ;;;*** -;;;### (autoloads nil "helm-mode" "helm-mode.el" (22348 36311 0 0)) +;;;### (autoloads nil "helm-mode" "helm-mode.el" (0 0 0 0)) ;;; Generated autoloads from helm-mode.el (autoload 'helm-comp-read "helm-mode" "\ @@ -593,6 +645,8 @@ Keys description: - 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). @@ -620,13 +674,21 @@ Keys description: `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\") 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) +\(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. @@ -652,23 +714,26 @@ Keys description: - 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: a persistent action function. +- 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 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) +\(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 command `helm-mode' for a description of this minor mode. +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'.") @@ -681,9 +746,14 @@ 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'. @@ -693,15 +763,57 @@ 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-"))) + ;;;*** -;;;### (autoloads nil "helm-net" "helm-net.el" (22348 36311 0 0)) +;;;### (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. @@ -717,9 +829,11 @@ Preconfigured `helm' for Wikipedia lookup with Wikipedia suggest. \(fn)" t nil) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-net" '("helm-"))) + ;;;*** -;;;### (autoloads nil "helm-org" "helm-org.el" (22348 36311 0 0)) +;;;### (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" "\ @@ -744,14 +858,22 @@ 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-"))) + ;;;*** -;;;### (autoloads nil "helm-regexp" "helm-regexp.el" (22348 36311 -;;;;;; 0 0)) +;;;### (autoloads nil "helm-regexp" "helm-regexp.el" (0 0 0 0)) ;;; Generated autoloads from helm-regexp.el (autoload 'helm-moccur-mode "helm-regexp" "\ @@ -769,7 +891,21 @@ Preconfigured helm to build regexps. \(fn)" t nil) (autoload 'helm-occur "helm-regexp" "\ -Preconfigured helm for 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. \(fn)" t nil) @@ -788,27 +924,13 @@ The prefix arg can be set before calling \(fn &optional ARG)" t nil) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-regexp" '("helm-"))) + ;;;*** -;;;### (autoloads nil "helm-ring" "helm-ring.el" (22348 36311 0 0)) +;;;### (autoloads nil "helm-ring" "helm-ring.el" (0 0 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'. @@ -845,10 +967,11 @@ This command is useful when used with persistent action. \(fn)" t nil) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-ring" '("helm-"))) + ;;;*** -;;;### (autoloads nil "helm-semantic" "helm-semantic.el" (22348 36311 -;;;;;; 0 0)) +;;;### (autoloads nil "helm-semantic" "helm-semantic.el" (0 0 0 0)) ;;; Generated autoloads from helm-semantic.el (autoload 'helm-semantic "helm-semantic" "\ @@ -868,14 +991,17 @@ Fill in the symbol at point by default. \(fn ARG)" t nil) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-semantic" '("helm-s"))) + ;;;*** -;;;### (autoloads nil "helm-sys" "helm-sys.el" (22348 36311 0 0)) +;;;### (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 command `helm-top-poll-mode' for a description of this minor mode. +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'.") @@ -902,9 +1028,11 @@ Preconfigured helm for xrandr. \(fn)" t nil) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-sys" '("helm-"))) + ;;;*** -;;;### (autoloads nil "helm-tags" "helm-tags.el" (22348 36311 0 0)) +;;;### (autoloads nil "helm-tags" "helm-tags.el" (0 0 0 0)) ;;; Generated autoloads from helm-tags.el (autoload 'helm-etags-select "helm-tags" "\ @@ -921,15 +1049,24 @@ This function aggregates three sources of tag files: \(fn REINIT)" t nil) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-tags" '("helm-"))) + ;;;*** -;;;### (autoloads nil "helm-utils" "helm-utils.el" (22348 36311 0 -;;;;;; 0)) +;;;### (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-"))) + +;;;*** + +;;;### (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 command `helm-popup-tip-mode' for a description of this minor mode. +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'.") @@ -941,11 +1078,19 @@ 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"))) + ;;;*** -;;;### (autoloads nil nil ("helm-easymenu.el" "helm-multi-match.el" -;;;;;; "helm-pkg.el" "helm-plugin.el" "helm-types.el") (22348 36311 -;;;;;; 363287 0)) +;;;### (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-"))) + +;;;*** + +;;;### (autoloads nil nil ("helm-easymenu.el" "helm-pkg.el") (0 0 +;;;;;; 0 0)) ;;;*** @@ -953,5 +1098,6 @@ Show help-echo informations in a popup tip at end of line. ;; version-control: never ;; no-byte-compile: t ;; no-update-autoloads: t +;; coding: utf-8 ;; End: ;;; helm-autoloads.el ends here diff --git a/elpa/helm-20160530.424/helm-bookmark.el b/elpa/helm-20181110.1615/helm-bookmark.el similarity index 79% rename from elpa/helm-20160530.424/helm-bookmark.el rename to elpa/helm-20181110.1615/helm-bookmark.el index 9ce49ce5..0c7af085 100644 --- a/elpa/helm-20160530.424/helm-bookmark.el +++ b/elpa/helm-20181110.1615/helm-bookmark.el @@ -1,6 +1,6 @@ ;;; helm-bookmark.el --- Helm for Emacs regular Bookmarks. -*- lexical-binding: t -*- -;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto +;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto ;; 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 @@ -19,6 +19,7 @@ (require 'cl-lib) (require 'bookmark) (require 'helm) +(require 'helm-lib) (require 'helm-help) (require 'helm-types) (require 'helm-utils) @@ -26,11 +27,8 @@ (require 'helm-adaptive) (require 'helm-net) +(declare-function helm-browse-project "helm-files" (arg)) (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)) - (defgroup helm-bookmark nil "Predefined configurations for `helm.el'." @@ -42,78 +40,20 @@ :type 'boolean) (defcustom helm-bookmark-default-filtered-sources - (append '(helm-source-bookmark-files&dirs + (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) - (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)) - (defface helm-bookmark-info '((t (:foreground "green"))) @@ -140,6 +80,11 @@ "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." @@ -154,10 +99,11 @@ (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) + (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.") @@ -211,12 +157,19 @@ (put 'helm-bookmark-toggle-filename 'helm-only t) (defun helm-bookmark-jump (candidate) - "Jump to bookmark from keyboard." + "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))) @@ -284,8 +237,8 @@ BOOKMARK is a bookmark name or a bookmark record." (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))) + (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. @@ -295,6 +248,11 @@ This excludes bookmarks of a more specific kind (Info, Gnus, and W3m)." (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." @@ -310,7 +268,8 @@ BOOKMARK is a bookmark name or a bookmark record." (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 + (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 @@ -336,11 +295,18 @@ BOOKMARK is a bookmark name or a bookmark record." 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))) + (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 @@ -411,6 +377,19 @@ than `w3m-browse-url' use it." (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 () @@ -456,8 +435,45 @@ than `w3m-browse-url' use it." "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-source-filtered-bookmarks + (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 @@ -478,48 +494,6 @@ than `w3m-browse-url' use it." (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 ;; @@ -576,20 +550,37 @@ than `w3m-browse-url' use it." ( ;; Addressbook isabook (propertize trunc 'face 'helm-bookmark-addressbook)) - ( ;; directories + (;; 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 - (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)))) + ;; 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 @@ -679,11 +670,18 @@ words from the buffer into the new bookmark name." (put 'helm-bookmark-run-edit 'helm-only t) +(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 'bookmark-jump-other-window))) + (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 () @@ -720,7 +718,7 @@ e.g prepended with *." (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." +only if external addressbook-bookmark package is installed." (interactive) (helm :sources helm-bookmark-default-filtered-sources :prompt "Search Bookmark: " @@ -731,7 +729,7 @@ only if external library addressbook-bookmark.el is available." (provide 'helm-bookmark) ;; Local Variables: -;; byte-compile-warnings: (not cl-functions obsolete) +;; byte-compile-warnings: (not obsolete) ;; coding: utf-8 ;; indent-tabs-mode: nil ;; End: diff --git a/elpa/helm-20160530.424/helm-buffers.el b/elpa/helm-20181110.1615/helm-buffers.el similarity index 63% rename from elpa/helm-20160530.424/helm-buffers.el rename to elpa/helm-20181110.1615/helm-buffers.el index b06819e9..65f37359 100644 --- a/elpa/helm-20160530.424/helm-buffers.el +++ b/elpa/helm-20181110.1615/helm-buffers.el @@ -1,6 +1,6 @@ ;;; helm-buffers.el --- helm support for buffers. -*- lexical-binding: t -*- -;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto +;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto ;; 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 @@ -21,9 +21,7 @@ (require 'helm) (require 'helm-types) (require 'helm-utils) -(require 'helm-elscreen) (require 'helm-grep) -(require 'helm-plugin) (require 'helm-regexp) (require 'helm-help) @@ -38,7 +36,7 @@ :group 'helm) (defcustom helm-boring-buffer-regexp-list - '("\\` " "\\*helm" "\\*helm-mode" "\\*Echo Area" "\\*Minibuf") + '("\\` " "\\`\\*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 @@ -93,7 +91,10 @@ Only buffer names are fuzzy matched when this is enabled, (defcustom helm-mini-default-sources '(helm-source-buffers-list helm-source-recentf helm-source-buffer-not-found) - "Default sources list used in `helm-mini'." + "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))) @@ -102,6 +103,22 @@ Only buffer names are fuzzy matched when this is enabled, :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) ;;; Faces ;; @@ -122,6 +139,11 @@ Only buffer names are fuzzy matched when this is enabled, "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")) @@ -143,6 +165,28 @@ Only buffer names are fuzzy matched when this is enabled, "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) + ;;; Buffers keymap ;; @@ -160,17 +204,18 @@ Only buffer names are fuzzy matched when this is enabled, (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 "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 "") 'helm-buffers-mark-similar-buffers) + (define-key map (kbd "C-M-SPC") 'helm-buffers-mark-similar-buffers) map) "Keymap for buffer sources in helm.") @@ -186,17 +231,30 @@ Only buffer names are fuzzy matched when this is enabled, map)) -(defvar helm-buffers-list-cache nil) (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. - (setq helm-buffers-list-cache (funcall (helm-attr 'buffer-list))) - (let ((result (cl-loop for b in helm-buffers-list-cache + ;; 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 (with-current-buffer b - (format-mode-line mode-name))) + 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) @@ -212,24 +270,15 @@ Only buffer names are fuzzy matched when this is enabled, :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) + (multimatch :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) + (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 @@ -321,89 +370,132 @@ See `ido-make-buffer-list' for more infos." (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) - (let* ((mode (with-current-buffer buffer (format-mode-line mode-name))) + (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)))) + (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) + (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-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)))))) + '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 (cons (if helm-buffer-details-flag - (concat truncbuf "\t" formatted-size - " " fmode " " meta) - name) - (get-buffer i)))) + 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) @@ -413,30 +505,44 @@ Should be called after others transformers i.e (boring buffers)." (helm-substring-by-width bufname helm-buffer-max-length helm-buffers-end-truncated-string)) - (concat (regexp-quote bufname) - (if helm-buffer-details-flag - "$" "[[:blank:]]+")))))) + (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)))) + (let* ((buf (helm-get-selection)) + (preselect (helm-buffer--get-preselection buf))) (setq helm-buffer-details-flag (not helm-buffer-details-flag)) - (helm-force-update preselect)))) + (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-sort-transformer (candidates _source) +(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 - (sort candidates - (lambda (s1 s2) - (< (string-width s1) (string-width s2)))))) + (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 ((type (get-text-property - 0 'type (helm-get-selection nil 'withprop)))) + (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) @@ -449,13 +555,13 @@ Should be called after others transformers i.e (boring buffers)." (maxpoint (or end (point-max)))) (while (< (point) maxpoint) (helm-mark-current-line) - (let ((cand (helm-get-selection nil 'withprop))) + (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 (helm-get-current-source) t) + (helm-display-mode-line src t) (message "%s candidates marked" (length helm-marked-candidates))))) (defun helm-buffers-mark-similar-buffers () @@ -488,11 +594,18 @@ i.e same color." (and pos pos-test) (and neg neg-test (not neg-test))))))) -(defun helm-buffer--match-pattern (pattern candidate) +(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--mapconcat-pattern + #'helm-buffer--memo-pattern #'identity)) (mfn (if helm-migemo-mode #'helm-mm-migemo-string-match #'string-match))) @@ -505,32 +618,33 @@ i.e same color." (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) + for p in (helm-mm-split-pattern pattern) when (string-match "\\`\\*" p) return p))) (if regexp (when buf (with-current-buffer buf - (let ((mjm (format-mode-line mode-name))) + (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 (split-string pattern) - unless (string-match - "\\`\\(\\*\\|/\\|@\\)" p) - collect p))) + (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)) + 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 (split-string pattern) + for p in (helm-mm-split-pattern pattern) when (string-match "\\`@\\(.*\\)" p) return (match-string 1 p)))) (if (and buf regexp) @@ -545,14 +659,15 @@ i.e same color." (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)) + (buf-fname (or (buffer-file-name buf) + (car-safe (rassoc buf dired-buffers)))) (regexps (cl-loop with pattern = helm-pattern - for p in (split-string pattern) + for p in (helm-mm-split-pattern pattern) when (string-match "\\`/" p) collect p))) (if regexps (cl-loop for re in regexps - thereis + thereis (and buf-fname (string-match (substring re 1) (helm-basedir buf-fname)))) @@ -593,11 +708,10 @@ If REGEXP-FLAG is given use `query-replace-regexp'." (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))))) + (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." @@ -616,12 +730,13 @@ If REGEXP-FLAG is given use `query-replace-regexp'." (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))) + (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." @@ -632,14 +747,15 @@ If REGEXP-FLAG is given use `query-replace-regexp'." (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)))) + (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." @@ -649,6 +765,17 @@ If REGEXP-FLAG is given use `query-replace-regexp'." (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) @@ -660,9 +787,10 @@ If REGEXP-FLAG is given use `query-replace-regexp'." (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)) + (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 () @@ -704,7 +832,7 @@ If REGEXP-FLAG is given use `query-replace-regexp'." "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))) + (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 () @@ -714,12 +842,18 @@ If REGEXP-FLAG is given use `query-replace-regexp'." (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-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'." @@ -735,51 +869,66 @@ If REGEXP-FLAG is given use `query-replace-regexp'." (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) +(defun helm-buffers-persistent-kill-1 (buffer-or-name) "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)))))) + (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 helm-buffer-max-length + (if (and helm-buffer-max-length + helm-buffer-details-flag) (helm-substring-by-width bufname helm-buffer-max-length "") - bufname))))) + bufname))))) (defun helm-buffers-persistent-kill (_buffer) - (let ((marked (helm-marked-candidates))) + (let ((marked (helm-marked-candidates)) + (sel (helm-get-selection))) (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))) + 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 - (helm-get-selection)))))) + (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 (eql current (get-buffer helm-current-buffer)) + (if (or (helm-follow-mode-p) + (eql current (get-buffer helm-current-buffer)) (not (eql current (get-buffer candidate)))) (switch-to-buffer candidate) - (switch-to-buffer helm-current-buffer)))) + (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'. @@ -796,7 +945,7 @@ With optional arg MERGE call `ediff-merge-buffers'." (setq buf1 (cl-first (helm-marked-candidates)) buf2 (cl-second (helm-marked-candidates)))) (t - (error "Error:To much buffers marked!"))) + (error "Error:Too many buffers marked!"))) (if merge (ediff-merge-buffers buf1 buf2) (ediff-buffers buf1 buf2)))) @@ -836,12 +985,12 @@ Can be used by any source that list buffers." (cons 'helm-skip-boring-buffers (remove 'helm-shadow-boring-buffers filter-attrs)) - helm-source-buffers-list t) + 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 t)) + helm-source-buffers-list)) (helm-force-update)))) (put 'helm-buffers-toggle-show-hidden-buffers 'helm-only t) @@ -890,7 +1039,7 @@ displayed with the `file-name-shadow' face if available." (defun helm-mini () "Preconfigured `helm' lightweight version \(buffer -> recentf\)." (interactive) - (require 'helm-files) + (require 'helm-x-files) (unless helm-source-buffers-list (setq helm-source-buffers-list (helm-make-source "Buffers" 'helm-source-buffers))) @@ -899,10 +1048,16 @@ displayed with the `file-name-shadow' face if available." :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 cl-functions obsolete) +;; byte-compile-warnings: (not obsolete) ;; coding: utf-8 ;; indent-tabs-mode: nil ;; End: diff --git a/elpa/helm-20160530.424/helm-color.el b/elpa/helm-20181110.1615/helm-color.el similarity index 93% rename from elpa/helm-20160530.424/helm-color.el rename to elpa/helm-20181110.1615/helm-color.el index 4122cf3f..106e9bec 100644 --- a/elpa/helm-20160530.424/helm-color.el +++ b/elpa/helm-20181110.1615/helm-color.el @@ -1,6 +1,6 @@ ;;; helm-color.el --- colors and faces -*- lexical-binding: t -*- -;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto +;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto ;; 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 @@ -19,6 +19,7 @@ (require 'cl-lib) (require 'helm) (require 'helm-help) +(require 'helm-elisp) ;;; Customize Face ;; @@ -41,6 +42,11 @@ (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)))))) @@ -156,7 +162,7 @@ (provide 'helm-color) ;; Local Variables: -;; byte-compile-warnings: (not cl-functions obsolete) +;; byte-compile-warnings: (not obsolete) ;; coding: utf-8 ;; indent-tabs-mode: nil ;; End: diff --git a/elpa/helm-20160530.424/helm-command.el b/elpa/helm-20181110.1615/helm-command.el similarity index 69% rename from elpa/helm-20160530.424/helm-command.el rename to elpa/helm-20181110.1615/helm-command.el index 69beab24..7639a781 100644 --- a/elpa/helm-20160530.424/helm-command.el +++ b/elpa/helm-20181110.1615/helm-command.el @@ -1,6 +1,6 @@ ;;; helm-command.el --- Helm execute-exended-command. -*- lexical-binding: t -*- -;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto +;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto ;; 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 @@ -49,6 +49,14 @@ Show all candidates on startup when 0 (default)." :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) ;;; Faces ;; @@ -65,9 +73,11 @@ Show all candidates on startup when 0 (default)." (defvar helm-M-x-input-history nil) +(defvar helm-M-x-prefix-argument nil + "Prefix argument before calling `helm-M-x'.") -(cl-defun helm-M-x-get-major-mode-command-alist (mode-map) +(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) @@ -158,6 +168,31 @@ fuzzy matching is running its own sort function with a different algorithm." (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 @@ -172,10 +207,7 @@ than the default which is OBARRAY." (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))) + (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 @@ -187,16 +219,20 @@ than the default which is OBARRAY." 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)) + (progn (setq current-prefix-arg nil) (helm-comp-read - "M-x " (or collection obarray) + (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" @@ -210,7 +246,9 @@ than the default which is OBARRAY." :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 @@ -220,38 +258,47 @@ than the default which is OBARRAY." (setq helm--mode-line-display-prefarg nil))))) ;;;###autoload -(defun helm-M-x (arg &optional command-name) +(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'. +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 (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)))))) - + (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 cl-functions obsolete) +;; byte-compile-warnings: (not obsolete) ;; coding: utf-8 ;; indent-tabs-mode: nil ;; End: diff --git a/elpa/helm-20160530.424/helm-config.el b/elpa/helm-20181110.1615/helm-config.el similarity index 96% rename from elpa/helm-20160530.424/helm-config.el rename to elpa/helm-20181110.1615/helm-config.el index 1a1bf586..b99ab639 100644 --- a/elpa/helm-20160530.424/helm-config.el +++ b/elpa/helm-20181110.1615/helm-config.el @@ -1,6 +1,6 @@ ;;; helm-config.el --- Applications library for `helm.el' -*- lexical-binding: t -*- -;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto +;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto ;; 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 @@ -144,15 +144,15 @@ ("(\\<\\(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)))) + ("(\\<\\(helm-aand\\)\\>" 1 font-lock-keyword-face) + ("(\\<\\(helm-with-gensyms\\)\\>" 1 font-lock-keyword-face) + ("(\\<\\(helm-read-answer\\)\\>" 1 font-lock-keyword-face)))) ;;; Load the autoload file @@ -164,7 +164,7 @@ (provide 'helm-config) ;; Local Variables: -;; byte-compile-warnings: (not cl-functions obsolete) +;; byte-compile-warnings: (not obsolete) ;; coding: utf-8 ;; indent-tabs-mode: nil ;; End: diff --git a/elpa/helm-20181110.1615/helm-dabbrev.el b/elpa/helm-20181110.1615/helm-dabbrev.el new file mode 100644 index 00000000..33617a36 --- /dev/null +++ b/elpa/helm-20181110.1615/helm-dabbrev.el @@ -0,0 +1,388 @@ +;;; helm-dabbrev.el --- Helm implementation of dabbrev. -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto + +;; 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 . + +;;; Code: + +(require 'helm) +(require 'helm-lib) +(require 'helm-help) +(require 'helm-elisp) ; For show-completion. + +(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.") + + +(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) + + +(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)) + +(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 diff --git a/elpa/helm-20160530.424/helm-easymenu.el b/elpa/helm-20181110.1615/helm-easymenu.el similarity index 96% rename from elpa/helm-20160530.424/helm-easymenu.el rename to elpa/helm-20181110.1615/helm-easymenu.el index 9ab3580c..5619aacb 100644 --- a/elpa/helm-20160530.424/helm-easymenu.el +++ b/elpa/helm-20181110.1615/helm-easymenu.el @@ -1,6 +1,6 @@ ;;; helm-easymenu.el --- Helm easymenu definitions. -*- lexical-binding: t -*- -;; Copyright (C) 2015 ~ 2016 Thierry Volpiatto +;; Copyright (C) 2015 ~ 2018 Thierry Volpiatto ;; 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 @@ -82,7 +82,7 @@ (provide 'helm-easymenu) ;; Local Variables: -;; byte-compile-warnings: (not cl-functions obsolete) +;; byte-compile-warnings: (not obsolete) ;; coding: utf-8 ;; indent-tabs-mode: nil ;; End: diff --git a/elpa/helm-20160530.424/helm-elisp-package.el b/elpa/helm-20181110.1615/helm-elisp-package.el similarity index 69% rename from elpa/helm-20160530.424/helm-elisp-package.el rename to elpa/helm-20181110.1615/helm-elisp-package.el index 29914d47..be0de6b4 100644 --- a/elpa/helm-20160530.424/helm-elisp-package.el +++ b/elpa/helm-20181110.1615/helm-elisp-package.el @@ -1,6 +1,6 @@ ;;; helm-elisp-package.el --- helm interface for package.el -*- lexical-binding: t -*- -;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto +;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto ;; 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 @@ -34,6 +34,11 @@ (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) @@ -43,39 +48,48 @@ ;; 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) + (let (package-menu-async + (inhibit-read-only t)) (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*"))) + (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))) @@ -104,26 +118,19 @@ (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 ", "))))))) + 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))) @@ -134,7 +141,7 @@ (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) +(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) @@ -143,12 +150,18 @@ (with-no-warnings (if (fboundp 'package-desc-full-name) ;; emacs 24.4 - (package-delete id) + (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)))) - unless (assoc (elt id 1) package-alist) + ;; 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)) @@ -175,7 +188,7 @@ "No package deleted"))) (defun helm-el-package-uninstall (_candidate) - (helm-el-package-uninstall-1 (helm-marked-candidates))) + (helm-el-package-uninstall-1 (helm-marked-candidates) helm-current-prefix-arg)) (defun helm-el-run-package-uninstall () (interactive) @@ -212,7 +225,10 @@ (ignore)) ((equal pkg-desc upgrade) ;;Install. - (package-install pkg-desc)) + (with-no-warnings + (if (boundp 'package-selected-packages) + (package-install pkg-desc t) + (package-install pkg-desc)))) (t ;; Delete. (if (boundp 'package-selected-packages) @@ -258,7 +274,11 @@ for name = (if (fboundp 'package-desc-name) (and id (package-desc-name id)) (car id)) - for installed-p = (assq name package-alist) + 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)) @@ -269,15 +289,25 @@ 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 + 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) - (eq helm-el-package--show-only 'uninstalled)) + (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 @@ -312,6 +342,7 @@ (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) @@ -332,31 +363,54 @@ (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))))) + ("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)) + (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 ((and (package-installed-p pkg-name) - (cdr (assq pkg-name helm-el-package--upgrades))) + (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)) + ("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) @@ -374,7 +428,7 @@ ;; packages already installed, the name (as symbol) ;; fails with such packages. (package-install - (cadr (assq name package-archive-contents)))) + (cadr (assq name package-archive-contents)) t)) (package-delete pkg-desc) (package-install name)))) @@ -393,14 +447,18 @@ (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 () +(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." - (interactive) - (let ((helm-el-package--initialized-p t)) + +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) diff --git a/elpa/helm-20160530.424/helm-elisp.el b/elpa/helm-20181110.1615/helm-elisp.el similarity index 76% rename from elpa/helm-20160530.424/helm-elisp.el rename to elpa/helm-20181110.1615/helm-elisp.el index abb29956..40b5d549 100644 --- a/elpa/helm-20160530.424/helm-elisp.el +++ b/elpa/helm-20181110.1615/helm-elisp.el @@ -1,6 +1,6 @@ ;;; helm-elisp.el --- Elisp symbols completion for helm. -*- lexical-binding: t -*- -;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto +;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto ;; 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 @@ -18,13 +18,13 @@ ;;; 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) -(require 'advice) (declare-function 'helm-describe-function "helm-lib") (declare-function 'helm-describe-variable "helm-lib") @@ -38,14 +38,7 @@ :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." + "Display candidate in `current-buffer' while moving selection when non--nil." :group 'helm-elisp :type 'boolean) @@ -89,12 +82,32 @@ fuzzy completion is not available in `completion-at-point'." 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) + 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) ;;; Faces ;; @@ -124,6 +137,11 @@ fuzzy completion is not available in `completion-at-point'." (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) + ;;; Show completion. ;; @@ -139,12 +157,11 @@ fuzzy completion is not available in `completion-at-point'." (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))) + (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) +(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) @@ -168,31 +185,28 @@ fuzzy completion is not available in `completion-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." +If `helm-turn-on-show-completion' is nil 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))))) + `(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)))) ;;; Lisp symbol completion. @@ -303,21 +317,26 @@ Return a cons \(beg . end\)." (helm :sources (helm-build-in-buffer-source "Lisp completion" :data helm-lisp-completion--cache - :persistent-action 'helm-lisp-completion-persistent-action + :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)))) + :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]")))) @@ -350,7 +369,9 @@ in other window according to the value of `helm-elisp-help-function'." (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\")." +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)) @@ -458,6 +479,8 @@ Filename completion happen if string start after or between a double quote." ;;; Apropos ;; ;; +(defvar helm-apropos-history nil) + (defun helm-apropos-init (test default) "Init candidates buffer for `helm-apropos' sources." (require 'helm-help) @@ -491,11 +514,68 @@ Filename completion happen if string start after or between a double quote." 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)) + :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) @@ -503,27 +583,12 @@ Filename completion happen if string start after or between a double quote." :persistent-action (lambda (candidate) (helm-elisp--persistent-help candidate 'helm-describe-variable)) - :persistent-help "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 - (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))))) + :action-transformer 'helm-apropos-action-transformer)) (defun helm-def-source--emacs-faces (&optional default) "Create `helm' source for faces to be displayed with @@ -541,35 +606,16 @@ Filename completion happen if string start after or between a double quote." :persistent-action (lambda (candidate) (helm-elisp--persistent-help candidate 'helm-describe-face)) - :persistent-help "Describe face" - :nomark t + :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--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)) + :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) @@ -577,27 +623,27 @@ Filename completion happen if string start after or between a double quote." :persistent-action (lambda (candidate) (helm-elisp--persistent-help candidate 'helm-describe-function)) - :persistent-help "Describe command" + :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)) + :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" + :persistent-help "Toggle describe function" :nomark t :action '(("Describe function" . helm-describe-function) ("Find function" . helm-find-function) @@ -605,10 +651,10 @@ Filename completion happen if string start after or between a double quote." (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)) + :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) @@ -616,17 +662,17 @@ Filename completion happen if string start after or between a double quote." :persistent-action (lambda (candidate) (helm-elisp--persistent-help candidate 'helm-describe-function)) - :persistent-help "Describe class" + :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)) + :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) @@ -634,42 +680,51 @@ Filename completion happen if string start after or between a double quote." :persistent-action (lambda (candidate) (helm-elisp--persistent-help candidate 'helm-describe-function)) - :persistent-help "Describe generic 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 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) + (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) - (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))) + ;; ???: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) @@ -681,6 +736,7 @@ i.e the `symbol-name' of any existing symbol." (mapcar (lambda (func) (funcall func default)) helm-apropos-function-list) + :history 'helm-apropos-history :buffer "*helm apropos*" :preselect (and default (concat "\\_<" (regexp-quote default) "\\_>")))) @@ -689,13 +745,14 @@ i.e the `symbol-name' of any existing symbol." ;; ;; (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"))) + (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 @@ -749,20 +806,28 @@ i.e the `symbol-name' of any existing symbol." ;; (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))) + 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 (lambda () (helm-locate-library-scan-list)) - :fuzzy-match t + :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)) @@ -770,6 +835,7 @@ i.e the `symbol-name' of any existing symbol." (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) @@ -905,7 +971,7 @@ i.e the `symbol-name' of any existing symbol." (provide 'helm-elisp) ;; Local Variables: -;; byte-compile-warnings: (not cl-functions obsolete) +;; byte-compile-warnings: (not obsolete) ;; coding: utf-8 ;; indent-tabs-mode: nil ;; End: diff --git a/elpa/helm-20181110.1615/helm-eshell.el b/elpa/helm-20181110.1615/helm-eshell.el new file mode 100644 index 00000000..66e81d75 --- /dev/null +++ b/elpa/helm-20181110.1615/helm-eshell.el @@ -0,0 +1,487 @@ +;;; helm-eshell.el --- pcomplete and eshell completion for helm. -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto + +;; 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 . + +;;; 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) + + +(defgroup helm-eshell nil + "Helm eshell completion and history." + :group 'helm) + + +(defcustom helm-eshell-fuzzy-match nil + "Enable fuzzy matching in `helm-esh-pcomplete' when non--nil." + :group 'helm-eshell + :type 'boolean) + + +(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) + + +(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)))))) + +;;; 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.") + + +;;;###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))))) + + +;;; 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 diff --git a/elpa/helm-20160530.424/helm-eval.el b/elpa/helm-20181110.1615/helm-eval.el similarity index 97% rename from elpa/helm-20160530.424/helm-eval.el rename to elpa/helm-20181110.1615/helm-eval.el index 21594390..06ffd081 100644 --- a/elpa/helm-20160530.424/helm-eval.el +++ b/elpa/helm-20181110.1615/helm-eval.el @@ -1,6 +1,6 @@ ;;; helm-eval.el --- eval expressions from helm. -*- lexical-binding: t -*- -;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto +;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto ;; 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 @@ -96,6 +96,7 @@ Should take one arg: the string to display." (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 @@ -167,8 +168,7 @@ Should take one arg: the string to display." :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)) + :history 'read-expression-history)) (defvar eldoc-idle-delay) ;;;###autoload @@ -196,7 +196,7 @@ Should take one arg: the string to display." (provide 'helm-eval) ;; Local Variables: -;; byte-compile-warnings: (not cl-functions obsolete) +;; byte-compile-warnings: (not obsolete) ;; coding: utf-8 ;; indent-tabs-mode: nil ;; End: diff --git a/elpa/helm-20160530.424/helm-external.el b/elpa/helm-20181110.1615/helm-external.el similarity index 97% rename from elpa/helm-20160530.424/helm-external.el rename to elpa/helm-20181110.1615/helm-external.el index 899b2d4b..5c9015ca 100644 --- a/elpa/helm-20160530.424/helm-external.el +++ b/elpa/helm-20181110.1615/helm-external.el @@ -1,6 +1,6 @@ ;;; helm-external.el --- Run Externals commands within Emacs with helm completion. -*- lexical-binding: t -*- -;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto +;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto ;; 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 @@ -81,7 +81,7 @@ and sets `helm-external-commands-list'." (if sort (sort completions 'string-lessp) completions))))) (defun helm-run-or-raise (exe &optional file) - "Generic command that run asynchronously EXE. + "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." @@ -101,7 +101,7 @@ When FILE argument is provided run EXE with FILE." (shell-quote-argument (if (eq system-type 'windows-nt) (helm-w32-prepare-filename file) - file)))) + (expand-file-name file))))) (start-process-shell-command proc nil real-com)) (set-process-sentinel (get-process proc) @@ -205,7 +205,7 @@ You can set your own list of commands with (provide 'helm-external) ;; Local Variables: -;; byte-compile-warnings: (not cl-functions obsolete) +;; byte-compile-warnings: (not obsolete) ;; coding: utf-8 ;; indent-tabs-mode: nil ;; End: diff --git a/elpa/helm-20181110.1615/helm-files.el b/elpa/helm-20181110.1615/helm-files.el new file mode 100644 index 00000000..18e16d0b --- /dev/null +++ b/elpa/helm-20181110.1615/helm-files.el @@ -0,0 +1,4476 @@ +;;; helm-files.el --- helm file browser and related. -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto + +;; 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 . + +;;; Code: + +(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) + +(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 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- 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 ." + :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-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-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-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-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) + +;;; 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) + +;;; 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-") 'helm-ff-run-toggle-auto-update) + (define-key map (kbd "C-c ") '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 "") 'helm-find-files-up-one-level) + (define-key map (kbd "") '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 "") '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-") 'helm-ff-run-toggle-auto-update) + (define-key map (kbd "C-c ") '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 "") 'helm-find-files-up-one-level) + (define-key map (kbd "") 'helm-execute-persistent-action) + (define-key map (kbd "") 'helm-previous-source) + (define-key map (kbd "") 'helm-next-source)) + (delq nil map)) + "Keymap for `helm-read-file-name'.") + + +;; Internal. +(defvar helm-find-files-doc-header " (\\\\[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*") + +;;; 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 +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 + (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-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 ") + (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 + 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 + 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)))))) + + +;;; 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))))) + + +;;; 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))))) + + +;;; 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 " + (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))) + + +;;; 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) + +;;; Browse project +;; Need dependencies: +;; +;; +;; 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: + +and +." + (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) + + +;;;###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 diff --git a/elpa/helm-20181110.1615/helm-find.el b/elpa/helm-20181110.1615/helm-find.el new file mode 100644 index 00000000..196366c6 --- /dev/null +++ b/elpa/helm-20181110.1615/helm-find.el @@ -0,0 +1,172 @@ +;;; helm-find.el --- helm interface for find command. -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto + +;; 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 . + +;;; 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))) + + +;;; 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 diff --git a/elpa/helm-20181110.1615/helm-font.el b/elpa/helm-20181110.1615/helm-font.el new file mode 100644 index 00000000..c4e25d9d --- /dev/null +++ b/elpa/helm-20181110.1615/helm-font.el @@ -0,0 +1,335 @@ +;;; helm-font --- Font and ucs selection for Helm -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto + +;; 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 . + +;;; Code: + +(require 'cl-lib) +(require 'helm) +(require 'helm-help) + + +(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 "") 'helm-ucs-persistent-delete) + (define-key map (kbd "") 'helm-ucs-persistent-backward) + (define-key map (kbd "") '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) + +;;; 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")) + + +;;; 𝕌𝕔𝕤 𝕊𝕪𝕞𝕓𝕠𝕝 𝕔𝕠𝕞𝕡𝕝𝕖𝕥𝕚𝕠𝕟 +;; +;; +(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.") + +;;;###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 diff --git a/elpa/helm-20181110.1615/helm-for-files.el b/elpa/helm-20181110.1615/helm-for-files.el new file mode 100644 index 00000000..c259704d --- /dev/null +++ b/elpa/helm-20181110.1615/helm-for-files.el @@ -0,0 +1,308 @@ +;;; helm-for-files.el --- helm-for-files and related. -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto + +;; 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 . + +;;; 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))))) + + +;;; 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 diff --git a/elpa/helm-20160530.424/helm-grep.el b/elpa/helm-20181110.1615/helm-grep.el similarity index 72% rename from elpa/helm-20160530.424/helm-grep.el rename to elpa/helm-20181110.1615/helm-grep.el index 790e2115..24451bd1 100644 --- a/elpa/helm-20160530.424/helm-grep.el +++ b/elpa/helm-20181110.1615/helm-grep.el @@ -1,6 +1,6 @@ ;;; helm-grep.el --- Helm Incremental Grep. -*- lexical-binding: t -*- -;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto +;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto ;; 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 @@ -17,6 +17,7 @@ ;;; Code: (require 'cl-lib) +(require 'format-spec) (require 'helm) (require 'helm-help) (require 'helm-regexp) @@ -25,9 +26,9 @@ (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 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) @@ -125,6 +126,14 @@ 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 @@ -137,7 +146,8 @@ 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." +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) @@ -197,15 +207,36 @@ Possible value are: (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) + "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) + ;;; Faces ;; @@ -219,7 +250,8 @@ Possible value are: (defface helm-grep-match '((((background light)) :foreground "#b00000") (((background dark)) :foreground "gold1")) - "Face used to highlight grep matches." + "Face used to highlight grep matches. +Have no effect when grep backend use \"--color=\"." :group 'helm-grep-faces) (defface helm-grep-file @@ -239,7 +271,7 @@ Possible value are: :group 'helm-grep-faces) (defface helm-grep-cmd-line - '((t (:inherit diff-added))) + '((t (:inherit font-lock-type-face))) "Face used to highlight grep command line when no results." :group 'helm-grep-faces) @@ -254,7 +286,6 @@ Possible value are: (define-key map (kbd "M-") '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 "") 'helm-execute-persistent-action) @@ -267,7 +298,6 @@ Possible value are: (set-keymap-parent map helm-map) (define-key map (kbd "M-") 'helm-goto-next-file) (define-key map (kbd "M-") 'helm-goto-precedent-file) - (define-key map (kbd "C-w") 'helm-yank-text-at-point) map) "Keymap used in pdfgrep.") @@ -293,6 +323,7 @@ Possible value are: (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) @@ -317,58 +348,67 @@ It is intended to use as a let-bound variable, DON'T set this globaly.") ;; 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) + ;; 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 (and com (car (split-string com " "))))) + (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) @@ -384,6 +424,18 @@ It is intended to use as a let-bound variable, DON'T set this globaly.") (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) @@ -415,21 +467,20 @@ It is intended to use as a let-bound variable, DON'T set this globaly.") ;; we need to pass an empty string ;; to types to avoid error. (or include ""))) - (smartcase (if (helm-grep-use-ack-p) "" - (unless (let ((case-fold-search nil)) - (string-match-p - "[[:upper:]]" helm-pattern)) "i"))) + (smartcase (if (helm-grep-use-ack-p) + "" + (unless (let ((case-fold-search nil)) + (string-match-p + "[[:upper:]]" helm-pattern)) + "i"))) (helm-grep-default-command (concat helm-grep-default-command " %m")) ; `%m' like multi. - (patterns (split-string helm-pattern)) + (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 = (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))) + (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))) ""))) @@ -454,6 +505,13 @@ It is intended to use as a let-bound variable, DON'T set this globaly.") ;; 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) @@ -461,7 +519,7 @@ It is intended to use as a let-bound variable, DON'T set this globaly.") (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) + proc-name helm-buffer cmd-line) ;; Init sentinel. (set-process-sentinel (get-buffer-process helm-buffer) @@ -472,49 +530,52 @@ It is intended to use as a let-bound variable, DON'T set this globaly.") (helm-process-deferred-sentinel-hook process event (helm-default-directory))) (cond ((and noresult - ;; [FIXME] This is a workaround for zgrep + ;; 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 (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 " " + `(" " 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))))) + ,proc-name) 'face 'helm-grep-finish)))))) - ((string= event "finished\n") + ((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 " " + `(" " 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)))) + "[%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))) + (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" - (if helm-grep-use-zgrep "Zgrep" "Grep") + proc-name (replace-regexp-in-string "\n" "" event)))))))))) (defun helm-grep-collect-candidates () @@ -529,16 +590,17 @@ It is intended to use as a let-bound variable, DON'T set this globaly.") ;;; Actions ;; ;; -(defun helm-grep-action (candidate &optional where mark) +(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, elscreen, other-frame." +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) 'help-echo)) + (get-text-property (point-at-bol) 'helm-grep-fname)) (car split))) (tramp-method (file-remote-p (or helm-ff-default-directory default-directory) 'method)) @@ -548,19 +610,28 @@ WHERE can be one of other-window, elscreen, other-frame." (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-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)) (doc-view-goto-page lineno))) + (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)) - (when mark - (set-marker (mark-marker) (point)) - (push-mark (point) 'nomsg)) + ;; 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) @@ -577,9 +648,7 @@ WHERE can be one of other-window, elscreen, other-frame." (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-grep-action candidate) (helm-highlight-current-line)) (defun helm-grep-other-window (candidate) @@ -590,10 +659,6 @@ With a prefix arg record CANDIDATE in `mark-ring'." "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." @@ -615,10 +680,12 @@ If N is positive go forward otherwise go backward." ;; 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) 'help-echo)))) + (not (get-text-property (point-at-bol) 'helm-grep-fname)))) (funcall mark-maybe) (throw 'break nil)))) (cond ((and (> n 0) (eobp)) @@ -626,11 +693,13 @@ If N is positive go forward otherwise go backward." (forward-line 0) (funcall mark-maybe)) ((and (< n 0) (bobp)) - (helm-aif (next-single-property-change (point-at-bol) 'help-echo) + (helm-aif (next-single-property-change (point-at-bol) 'helm-grep-fname) (goto-char it) (forward-line 1)) (funcall mark-maybe))) - (helm-log-run-hook 'helm-move-selection-after-hook))) + (unless allow-mode + (helm-follow-execute-persistent-action-maybe) + (helm-log-run-hook 'helm-move-selection-after-hook)))) ;;;###autoload (defun helm-goto-precedent-file () @@ -706,18 +775,42 @@ If N is positive go forward otherwise go backward." (helm-default-directory) default-directory)) (setq buffer-read-only t) - (let ((inhibit-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)))))) + (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. @@ -773,7 +866,8 @@ Special commands: (defun helm-grep-mode-jump () (interactive) (helm-grep-action - (buffer-substring (point-at-bol) (point-at-eol)))) + (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)))) @@ -781,6 +875,7 @@ Special commands: (progn (save-selected-window (helm-grep-action candidate 'other-window) + (helm-match-line-cleanup-pulse) (recenter)) (forward-line arg)) (error nil)))) @@ -797,7 +892,8 @@ Special commands: (interactive) (let ((candidate (buffer-substring (point-at-bol) (point-at-eol)))) (condition-case nil - (helm-grep-action candidate 'other-window) + (progn (helm-grep-action candidate 'other-window) + (helm-match-line-cleanup-pulse)) (error nil)))) @@ -873,6 +969,7 @@ These extensions will be added to command line with --include arg of grep." (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 @@ -892,46 +989,79 @@ These extensions will be added to command line with --include arg of grep." ;;; 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))) + (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) -(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. +(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. -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.")) + +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 zgrep) ; zgrep doesn't handle -r opt. - (not (helm-grep-use-ack-p :where 'recursive)) + (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 @@ -942,20 +1072,21 @@ in recurse, and ignoring EXTS, search being made on (remove "*" exts) exts) " "))) (types (and (not include-files) - (not zgrep) + (not (eq backend 'zgrep)) recurse - (helm-grep-use-ack-p :where 'recursive) + 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))) - (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)))))) + (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) @@ -968,26 +1099,20 @@ in recurse, and ignoring EXTS, search being made on ;; 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-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 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)) + 'helm-grep-use-zgrep (eq backend 'zgrep) + 'helm-grep-default-command com 'default-directory helm-ff-default-directory) ;; [1] ;; Setup the source. - (setq helm-source-grep (helm-make-source src-name 'helm-grep-class - :follow follow)) + (set source (helm-make-source src-name 'helm-grep-class + :backend backend + :pcre (string-match-p "\\`ack" com))) (helm - :sources 'helm-source-grep - :buffer (format "*helm %s*" - (if zgrep "zgrep" (helm-grep-command recurse))) + :sources source + :buffer (format "*helm %s*" (helm-grep-command recurse backend)) :default default-input :input input :keymap helm-grep-map @@ -1038,7 +1163,13 @@ in recurse, and ignoring EXTS, search being made on (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) + ;; 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)) @@ -1050,7 +1181,8 @@ in recurse, and ignoring EXTS, search being made on (if (and display-fname lineno str) (cons (concat (propertize display-fname 'face 'helm-grep-file - 'help-echo fname) + 'help-echo (abbreviate-file-name fname) + 'helm-grep-fname fname) ":" (propertize lineno 'face 'helm-grep-lineno) ":" @@ -1095,7 +1227,7 @@ in recurse, and ignoring EXTS, search being made on (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))) + (helm-add-face-text-properties beg end 'helm-grep-match)) do (goto-char (point-min))) (buffer-string)) (error nil)))) @@ -1153,7 +1285,7 @@ If a prefix arg is given run grep on all buffers ignoring non--file-buffers." ;; and a pdf-reader (e.g xpdf) are needed. ;; (defvar helm-pdfgrep-default-function 'helm-pdfgrep-init) -(defun helm-pdfgrep-init (only-files) +(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)) @@ -1164,7 +1296,9 @@ If a prefix arg is given run grep on all buffers ignoring non--file-buffers." only-files) only-files) default-directory)) - (cmd-line (format helm-pdfgrep-default-command + (cmd-line (format (if recurse + helm-pdfgrep-default-recurse-command + helm-pdfgrep-default-command) helm-pattern fnargs)) process-connection-type) @@ -1189,15 +1323,17 @@ If a prefix arg is given run grep on all buffers ignoring non--file-buffers." (max (1- (count-lines (point-min) (point-max))) 0)) 'face 'helm-grep-finish)))) - (force-mode-line-update)) + (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) +(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 never used in 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) @@ -1211,7 +1347,8 @@ If a prefix arg is given run grep on all buffers ignoring non--file-buffers." (setq helm-ff-default-directory (or helm-ff-default-directory default-directory))) :candidates-process (lambda () - (funcall helm-pdfgrep-default-function helm-pdfgrep-targets)) + (funcall helm-pdfgrep-default-function + helm-pdfgrep-targets recurse)) :nohighlight t :nomark t :filter-one-by-one #'helm-grep-filter-one-by-one @@ -1235,49 +1372,77 @@ If a prefix arg is given run grep on all buffers ignoring non--file-buffers." (format-spec helm-pdfgrep-default-read-command (list (cons ?f fname) (cons ?p pageno)))))) -;;; AG - PT +;;; AG - PT - RG ;; ;; https://github.com/ggreer/the_silver_searcher ;; https://github.com/monochromegane/the_platinum_searcher +;; https://github.com/BurntSushi/ripgrep (defcustom helm-grep-ag-command "ag --line-numbers -S --hidden --color --nogroup %s %s %s" - "The default command for AG or PT. + "The default command for AG, PT or RG. + Takes three format specs, the first for type(s), the second for pattern and the third for directory. +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 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. -You can use safely \"--color\" (default)." +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 (split-string helm-grep-ag-command))) + (car (helm-remove-if-match + "\\`[A-Z]*=" (split-string helm-grep-ag-command)))) (defun helm-grep-ag-get-types () "Returns a list of AG types if available with AG version. -See AG option \"--list-file-types\"." +See AG option \"--list-file-types\" +Ripgrep (rg) types are also supported if this backend is used." (with-temp-buffer - (when (equal (call-process (helm-grep--ag-command) - nil t nil "--list-file-types") 0) - (goto-char (point-min)) - (cl-loop while (re-search-forward "^ *\\(--[a-z]*\\)" nil t) - collect (match-string 1))))) + (let* ((com (helm-grep--ag-command)) + (ripgrep (string= com "rg")) + (regex (if ripgrep "^\\(.*\\):" "^ *\\(--[a-z]*\\)")) + (prefix (if ripgrep "-t" ""))) + (when (equal (call-process com + nil t nil + (if ripgrep + "--type-list" "--list-file-types")) 0) + (goto-char (point-min)) + (cl-loop while (re-search-forward regex nil t) + for type = (match-string 1) + collect (cons type (concat prefix type))))))) (defun helm-grep-ag-prepare-cmd-line (pattern directory &optional type) "Prepare AG command line to search PATTERN in DIRECTORY. When TYPE is specified it is one of what returns `helm-grep-ag-get-types' if available with current AG version." - (let* ((patterns (split-string pattern)) - (pipe-cmd (cond ((executable-find "ack") "ack --color") - ((executable-find "ack-grep") "ack-grep --color") - (t "grep --perl-regexp --color=always"))) + (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)) @@ -1290,16 +1455,23 @@ if available with current AG version." (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))) + (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'" - (helm-grep--ag-command) directory) + proc-name 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) + (start-file-process-shell-command + proc-name helm-buffer cmd-line) (set-process-sentinel (get-buffer-process helm-buffer) (lambda (process event) @@ -1312,43 +1484,64 @@ if available with current AG version." (propertize helm-grep-last-cmd-line 'face 'helm-grep-cmd-line))) (setq mode-line-format - '(" " mode-line-buffer-identification " " + `(" " 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))) + ,(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 " " + `(" " 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)) + "[%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))) + (force-mode-line-update) + (when helm-allow-mouse + (helm--bind-mouse-for-selection helm-selection-point)))) (t (helm-log "Error: %s %s" - (helm-grep--ag-command) + 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))) + (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 @@ -1360,12 +1553,14 @@ if available with current AG version." (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)) @@ -1379,8 +1574,10 @@ When WITH-TYPES is non-nil provide completion on AG types." ;;; Git grep ;; ;; +(defvar helm-source-grep-git nil) + (defcustom helm-grep-git-grep-command - "git --no-pager grep -n%cH --color=always --exclude-standard --no-index --full-name -e %p -- %f" + "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 @@ -1388,7 +1585,8 @@ 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. +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 @@ -1402,16 +1600,15 @@ 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 + (let* (helm-grep-default-recurse-command ;; Expand filename of each candidate with the git root dir. - ;; The filename will be in the help-echo prop. + ;; 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 nil nil default input))) + nil 'git nil default input 'helm-source-grep-git))) ;;;###autoload @@ -1420,7 +1617,7 @@ arg INPUT is what you will have by default at prompt on startup." With prefix-arg prompt for type if available with your AG version." (interactive "P") (require 'helm-files) - (helm-grep-ag default-directory arg)) + (helm-grep-ag (expand-file-name default-directory) arg)) ;;;###autoload (defun helm-grep-do-git-grep (arg) @@ -1434,7 +1631,7 @@ With a prefix arg ARG git-grep the whole repository." (provide 'helm-grep) ;; Local Variables: -;; byte-compile-warnings: (not cl-functions obsolete) +;; byte-compile-warnings: (not obsolete) ;; coding: utf-8 ;; indent-tabs-mode: nil ;; End: diff --git a/elpa/helm-20181110.1615/helm-help.el b/elpa/helm-20181110.1615/helm-help.el new file mode 100644 index 00000000..935ddba8 --- /dev/null +++ b/elpa/helm-20181110.1615/helm-help.el @@ -0,0 +1,1728 @@ +;;; helm-help.el --- Help messages for Helm. -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto + +;; 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 . + +;;; Code: +(require 'helm) + +(defvar helm-org-headings--nofilename) +(declare-function helm-source-org-headings-for-files "helm-org.el") + + +(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) + +(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*") + +;;;###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*"))) + +;;; 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-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-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-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-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-up-one-level]' on a directory to go up one level + +**** Use `\\\\[helm-find-files-down-last-level]' to walk back the resulting tree of all the `\\\\[helm-execute-persistent-action]' you did + +The tree is reinitialized each time you browse a new tree with +`\\\\[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-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-' may not work. +In this case use `C-c '. + +*** 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 => \"%::\" +- 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: + + \"\\@/// + +You can select a substring from the string represented by the placeholder: + + \"\\@::\" + +- 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-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 \"%::\". + +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: \"\\@::\". +The length of placeholder is used for 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: \"\\@///\". + +Incremental replacement is also handled in . + +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\" 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-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-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-ff-run-zgrep]'. + +Otherwise you can use recursive commands like \`\\\\[helm-ff-run-grep-ag]' or `\\\\[helm-ff-run-git-grep]' +that are much faster than using `\\\\[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-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-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-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-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-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-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-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-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 \\\\[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-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-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-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-execute-persistent-action]' to display an image + +**** `\\\\[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-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-' and then `'. +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-' may not work. +In this case use `C-c '. + +*** 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-cr-empty-string]. +It is useful when some commands are prompting continuously until you enter an empty prompt. + +** Commands +\\ +\\[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 , 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-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-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-toggle-suspend-update]' (suspend process) before +typing, and hit again `\\\\[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-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-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-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-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-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 + + candidate_file + +But you can also pass an argument or more after \"candidate_file\" like this: + + %s [extra_args] + +\"candidate_file\" will be added at \"%s\" and the command will look at this: + + candidate_file [extra_args] + +*** Specify marked files as arguments + +Example: + + 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: + + file1 + file2 + ... + +** Commands +\\") + +;;; Ido virtual buffer help +;; +;; +(defvar helm-buffers-ido-virtual-help-message + "* Helm Ido virtual buffers + +** Commands +\\ +\\[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-execute-persistent-action]' (persistent-action), to do it repeatedly +you can use `\\\\[helm-follow-action-forward]' and `\\\\[helm-follow-action-backward]' or enable `helm-follow-mode' with `\\\\[helm-follow-mode]'. + +*** Switch to buffer in other window + +The command \\\\[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-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-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-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-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-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-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-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 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 +\\") + +;;; 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-kill-selection-and-quit]'. + +To save space, Helm-kill-ring truncates the candidates longer than +`helm-kill-ring-max-offset'. +`\\\\[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-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-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-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-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-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-cr-empty-string]. +It is useful when some commands are prompting continuously until you enter an empty prompt. + +** Commands +\\ +\\[helm-cr-empty-string]\t\tExit minibuffer with empty string." + com com))) + + +;;; Mode line strings +;; +;; +;;;###autoload +(defvar helm-comp-read-mode-line "\ +\\\ +C/\\[helm-cr-empty-string]:Empty \ +\\\ +\\[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-help]:Help \ +C/\\[helm-cr-empty-string]:Empty \ +\\\ +\\[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-help]:Help \ +\\\ +\\[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 diff --git a/elpa/helm-20160530.424/helm-id-utils.el b/elpa/helm-20181110.1615/helm-id-utils.el similarity index 93% rename from elpa/helm-20160530.424/helm-id-utils.el rename to elpa/helm-20181110.1615/helm-id-utils.el index ee51cb3a..b01aea54 100644 --- a/elpa/helm-20160530.424/helm-id-utils.el +++ b/elpa/helm-20181110.1615/helm-id-utils.el @@ -1,6 +1,6 @@ ;;; helm-id-utils.el --- Helm interface for id-utils. -*- lexical-binding: t -*- -;; Copyright (C) 2015 ~ 2016 Thierry Volpiatto +;; Copyright (C) 2015 ~ 2018 Thierry Volpiatto ;; 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 @@ -39,7 +39,7 @@ MacPorts to install id-utils, it should be `gid32'." :type 'string) (defun helm-gid-candidates-process () - (let* ((patterns (split-string helm-pattern)) + (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) @@ -55,6 +55,7 @@ MacPorts to install id-utils, it should be `gid32'." (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 " " @@ -90,9 +91,6 @@ MacPorts to install id-utils, it should be `gid32'." (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) @@ -125,7 +123,7 @@ See ." (provide 'helm-id-utils) ;; Local Variables: -;; byte-compile-warnings: (not cl-functions obsolete) +;; byte-compile-warnings: (not obsolete) ;; coding: utf-8 ;; indent-tabs-mode: nil ;; End: diff --git a/elpa/helm-20160530.424/helm-imenu.el b/elpa/helm-20181110.1615/helm-imenu.el similarity index 52% rename from elpa/helm-20160530.424/helm-imenu.el rename to elpa/helm-20181110.1615/helm-imenu.el index 8cb8b8f1..6ebac9e3 100644 --- a/elpa/helm-20160530.424/helm-imenu.el +++ b/elpa/helm-20181110.1615/helm-imenu.el @@ -1,6 +1,6 @@ ;;; helm-imenu.el --- Helm interface for Imenu -*- lexical-binding: t -*- -;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto +;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto ;; 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 @@ -53,6 +53,38 @@ 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 \". +`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)) ;;; keymap (defvar helm-imenu-map @@ -61,8 +93,10 @@ only '((foo . bar)) is needed." (define-key map (kbd "M-") 'helm-imenu-next-section) (define-key map (kbd "M-") 'helm-imenu-previous-section) (when helm-imenu-lynx-style-map - (define-key map (kbd "") 'helm-maybe-exit-minibuffer) - (define-key map (kbd "") 'helm-execute-persistent-action)) + (define-key map (kbd "") 'helm-maybe-exit-minibuffer) + (define-key map (kbd "") 'helm-execute-persistent-action) + (define-key map (kbd "M-") 'helm-previous-source) + (define-key map (kbd "M-") 'helm-next-source)) (delq nil map))) (defun helm-imenu-next-or-previous-section (n) @@ -100,6 +134,7 @@ only '((foo . bar)) is needed." (defvar helm-cached-imenu-tick nil) (make-variable-buffer-local 'helm-cached-imenu-tick) +(defvar helm-imenu--in-all-buffers-cache nil) (defvar helm-source-imenu nil "See (info \"(emacs)Imenu\")") (defvar helm-source-imenu-all nil) @@ -109,9 +144,11 @@ only '((foo . bar)) is needed." (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))) + (action :initform 'helm-imenu-action) + (group :initform 'helm-imenu))) (defcustom helm-imenu-fuzzy-match nil "Enable fuzzy matching in `helm-source-imenu'." @@ -124,8 +161,9 @@ only '((foo . bar)) is needed." :fuzzy-match helm-imenu-fuzzy-match)))) (defun helm-imenu--maybe-switch-to-buffer (candidate) - (helm-aif (marker-buffer (cdr candidate)) - (switch-to-buffer it))) + (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)) @@ -150,7 +188,7 @@ only '((foo . bar)) is needed." ;; no need to highlight again. (unless (eq imenu-default-goto-function 'semantic-imenu-goto-function) - (helm-highlight-current-line nil nil nil nil 'pulse))) + (helm-highlight-current-line))) (defun helm-imenu-persistent-action (candidate) "Default persistent action for `helm-source-imenu'." @@ -170,40 +208,60 @@ only '((foo . bar)) is needed." (delete (assoc "*Rescan*" index) index)))) (setq helm-cached-imenu-tick tick)))))) -(defun helm-imenu-candidates-in-all-buffers () +(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 for b in lst + (cl-loop with cur-buf = (if build-sources + (current-buffer) helm-current-buffer) + 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 + 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))) + (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 (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))))) + 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 @@ -220,22 +278,29 @@ only '((foo . bar)) is needed." (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)))) + ;; (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)))) ;;;###autoload (defun helm-imenu () @@ -250,7 +315,7 @@ only '((foo . bar)) is needed." (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) + :default (list (concat "\\_<" (and str (regexp-quote str)) "\\_>") str) :preselect str :buffer "*helm imenu*"))) @@ -260,26 +325,37 @@ only '((foo . bar)) is needed." 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))) + (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 :sources 'helm-source-imenu-all - :default (list (concat "\\_<" str "\\_>") str) - :preselect (unless (memq 'helm-source-imenu-all - helm-sources-using-default-as-input) - str) + 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 cl-functions obsolete) +;; byte-compile-warnings: (not obsolete) ;; coding: utf-8 ;; indent-tabs-mode: nil ;; End: diff --git a/elpa/helm-20160530.424/helm-info.el b/elpa/helm-20181110.1615/helm-info.el similarity index 81% rename from elpa/helm-20160530.424/helm-info.el rename to elpa/helm-20181110.1615/helm-info.el index ecc8b3ca..b5216c41 100644 --- a/elpa/helm-20160530.424/helm-info.el +++ b/elpa/helm-20181110.1615/helm-info.el @@ -1,6 +1,6 @@ ;;; helm-info.el --- Browse info index with helm -*- lexical-binding: t -*- -;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto +;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto ;; 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 @@ -20,7 +20,7 @@ (require 'cl-lib) (require 'helm) (require 'helm-lib) -(require 'helm-plugin) +(require 'helm-utils) (require 'info) (declare-function Info-index-nodes "info" (&optional file)) @@ -53,8 +53,8 @@ files with `helm-info-at-point'." (helm-candidate-buffer)) (kill-buffer it)) (unless (helm-candidate-buffer) - (save-window-excursion - (info file) + (save-selected-window + (info file " *helm info temp buffer*") (let ((tobuf (helm-candidate-buffer 'global)) Info-history start end line) @@ -78,7 +78,8 @@ files with `helm-info-at-point'." "\n" "" (buffer-substring start end))) (with-current-buffer tobuf (insert line) - (insert "\n"))))))))) + (insert "\n"))))) + (bury-buffer))))) (defun helm-info-goto (node-line) (Info-goto-node (car node-line)) @@ -186,11 +187,24 @@ helm-info-." :action '(("Search index" . helm-info-search-index)))) ;;;###autoload -(defun helm-info () - "Preconfigured `helm' for searching Info files' indices." - (interactive) +(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 @@ -209,38 +223,43 @@ helm-info-." (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))))) + :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)))) + (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. -With a prefix-arg insert symbol 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*")) (provide 'helm-info) ;; Local Variables: -;; byte-compile-warnings: (not cl-functions obsolete) +;; byte-compile-warnings: (not obsolete) ;; coding: utf-8 ;; indent-tabs-mode: nil ;; End: diff --git a/elpa/helm-20160530.424/helm-locate.el b/elpa/helm-20181110.1615/helm-locate.el similarity index 69% rename from elpa/helm-20160530.424/helm-locate.el rename to elpa/helm-20181110.1615/helm-locate.el index 03289d60..a6793b47 100644 --- a/elpa/helm-20160530.424/helm-locate.el +++ b/elpa/helm-20181110.1615/helm-locate.el @@ -1,6 +1,6 @@ ;;; helm-locate.el --- helm interface for locate. -*- lexical-binding: t -*- -;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto +;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto ;; 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 @@ -48,28 +48,36 @@ Note that this happen only when locate is launched with a prefix arg." (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: +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 --regex %s\" +Gnu/linux: \"locate %s -e -A --regex %s\" berkeley-unix: \"locate %s %s\" -windows-nt: \"es %s %s\" -Others: \"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\"." + +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" + "updatedb -l 0 -o '%s' -U '%s'" "Command used to create a locale locate db file." :type 'string :group 'helm-locate) @@ -86,7 +94,14 @@ the opposite of \"locate\" command." :type 'symbol) (defcustom helm-locate-fuzzy-match nil - "Enable fuzzy matching in `helm-locate'." + "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) @@ -97,6 +112,20 @@ 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) + (defvar helm-generic-files-map (let ((map (make-sparse-keymap))) @@ -117,13 +146,15 @@ directories of this list with `helm-projects-find-files'." (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-w") 'helm-yank-text-at-point) (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.") @@ -138,29 +169,20 @@ directories of this list with `helm-projects-find-files'." "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)))))) - + (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 directory)) + (format helm-locate-create-db-command + db-name (expand-file-name directory))) (defvar helm-locate-create-db-function #'helm-locate-create-db-default-function @@ -216,11 +238,15 @@ See `helm-locate-with-db' and `helm-locate'." (unless helm-locate-command (setq helm-locate-command (cl-case system-type - (gnu/linux "locate %s -e --regex %s") + (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. @@ -235,15 +261,25 @@ See also `helm-locate'." (if db (replace-regexp-in-string "locate" - (format "locate -d %s" + (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) - collect i) ":")) + ;; expand-file-name to resolve + ;; abbreviated fnames not + ;; expanding inside single + ;; quotes i.e. '%s'. + collect (expand-file-name i)) + ":")) helm-locate-command) - 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*" @@ -259,7 +295,7 @@ See also `helm-locate'." (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 " ")) + (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)) @@ -274,7 +310,9 @@ See also `helm-locate'." (shell-quote-argument (car args)) " " ;; Possible locate args added ;; after pattern, don't quote them. - (mapconcat 'identity (cdr args) " "))))) + (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")) @@ -294,6 +332,9 @@ See also `helm-locate'." " 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 " " @@ -309,26 +350,47 @@ See also `helm-locate'." (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-set-command) + ((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))) + (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)) + :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 - (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))) + ;; 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) @@ -348,6 +410,31 @@ See also `helm-locate'." 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'. @@ -377,13 +464,19 @@ To create a user specific db, use 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 cl-functions obsolete) +;; byte-compile-warnings: (not obsolete) ;; coding: utf-8 ;; indent-tabs-mode: nil ;; End: diff --git a/elpa/helm-20160530.424/helm-man.el b/elpa/helm-20181110.1615/helm-man.el similarity index 72% rename from elpa/helm-20160530.424/helm-man.el rename to elpa/helm-20181110.1615/helm-man.el index 987624f6..ab2d3002 100644 --- a/elpa/helm-20160530.424/helm-man.el +++ b/elpa/helm-20181110.1615/helm-man.el @@ -1,6 +1,6 @@ ;;; helm-man.el --- Man and woman UI -*- lexical-binding: t -*- -;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto +;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto ;; 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 @@ -43,12 +43,11 @@ (const :tag "Man" Man-getpage-in-background) (const :tag "Woman" woman))) -(defcustom helm-man-format-switches "-l %s" +(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.' -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" +Arguments are passed to `manual-entry' with `format.'" :group 'helm-man :type 'string) @@ -60,19 +59,23 @@ 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)))) + (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. + (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 () @@ -93,7 +96,8 @@ source.") :filtered-candidate-transformer (lambda (candidates _source) (sort candidates #'helm-generic-sort-fn)) - :action '(("Display Man page" . helm-man-default-action)))) + :action '(("Display Man page" . helm-man-default-action)) + :group 'helm-man)) ;;;###autoload (defun helm-man-woman (arg) @@ -107,7 +111,7 @@ With a prefix arg reinitialize the cache." (provide 'helm-man) ;; Local Variables: -;; byte-compile-warnings: (not cl-functions obsolete) +;; byte-compile-warnings: (not obsolete) ;; coding: utf-8 ;; indent-tabs-mode: nil ;; End: diff --git a/elpa/helm-20160530.424/helm-misc.el b/elpa/helm-20181110.1615/helm-misc.el similarity index 56% rename from elpa/helm-20160530.424/helm-misc.el rename to elpa/helm-20181110.1615/helm-misc.el index 202e5a94..971650bf 100644 --- a/elpa/helm-20160530.424/helm-misc.el +++ b/elpa/helm-20181110.1615/helm-misc.el @@ -1,6 +1,6 @@ ;;; helm-misc.el --- Various functions for helm -*- lexical-binding: t -*- -;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto +;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto ;; 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 @@ -23,6 +23,9 @@ (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") (defgroup helm-misc nil @@ -41,13 +44,6 @@ :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'." @@ -61,23 +57,53 @@ ;;; 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 () - "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)) + (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 - '((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))))) + (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)))) ;;; Jabber Contacts (jabber.el) @@ -92,17 +118,20 @@ (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))))))))) + (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 @@ -117,6 +146,22 @@ (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) @@ -124,50 +169,8 @@ :action 'helm-timezone-actions :filtered-candidate-transformer 'helm-time-zone-transformer)) -;;; LaCarte -;; +;;; Commands ;; -(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'. @@ -185,23 +188,19 @@ It is added to `extended-command-history'. ;;; 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)))) +(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 ;; @@ -213,11 +212,11 @@ It is added to `extended-command-history'. (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)) + (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'.") @@ -225,12 +224,12 @@ It is added to `extended-command-history'. ;; ;; (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))) + (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) @@ -258,11 +257,11 @@ It is added to `extended-command-history'. ;; ;; (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))) + (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) @@ -308,9 +307,37 @@ Default action change TZ environment variable locally to emacs." (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*"))) + (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 () @@ -326,7 +353,7 @@ Default action change TZ environment variable locally to emacs." (provide 'helm-misc) ;; Local Variables: -;; byte-compile-warnings: (not cl-functions obsolete) +;; byte-compile-warnings: (not obsolete) ;; coding: utf-8 ;; indent-tabs-mode: nil ;; End: diff --git a/elpa/helm-20160530.424/helm-mode.el b/elpa/helm-20181110.1615/helm-mode.el similarity index 68% rename from elpa/helm-20160530.424/helm-mode.el rename to elpa/helm-20181110.1615/helm-mode.el index 47af0578..15ee93c0 100644 --- a/elpa/helm-20160530.424/helm-mode.el +++ b/elpa/helm-20181110.1615/helm-mode.el @@ -1,6 +1,6 @@ ;;; helm-mode.el --- Enable helm completion everywhere. -*- lexical-binding: t -*- -;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto +;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto ;; 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 @@ -19,8 +19,11 @@ (require 'cl-lib) (require 'helm) +(require 'helm-lib) (require 'helm-files) +(defvar crm-separator) + (defgroup helm-mode nil "Enable helm completion." @@ -36,26 +39,73 @@ (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) + (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) - (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\) + (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 an helm function that take same arguments as +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. -This function prefix name must start by \"helm\". +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)) -See `helm-completing-read-symbols' for example. +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 @@ -64,16 +114,25 @@ 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\). +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. -e.g ido completion for `find-file': -\(find-file . 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." + + (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)) @@ -106,6 +165,18 @@ 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 @@ -124,32 +195,32 @@ 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) + (defvar helm-comp-read-map (let ((map (make-sparse-keymap))) (set-keymap-parent map helm-map) (define-key map (kbd "") 'helm-cr-empty-string) - (define-key map (kbd "") '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'.") - - -;;; Internal -;; -;; -;; Flag to know if `helm-pattern' have been added -;; to candidate list in `helm-comp-read'. -(defvar helm-cr-unknown-pattern-flag nil) - -;;; Helm `completing-read' replacement +;;; helm-comp-read ;; ;; (defun helm-cr-empty-string () @@ -167,7 +238,9 @@ and all functions belonging in this list from `minibuffer-setup-hook'." (let ((debug-on-quit nil)) (signal 'quit nil))) -(cl-defun helm-comp-read-get-candidates (collection &optional test sort-fn alistp (input "")) +(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. @@ -177,7 +250,8 @@ 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. +so we return the alist as it is with no transformation by +`all-completions'. e.g @@ -195,6 +269,16 @@ e.g 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 @@ -219,60 +303,100 @@ If COLLECTION is an `obarray', a TEST should be needed. See `obarray'." ;; 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))))))) + (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) minibuffer-completing-file-name) - (cl-loop for f in (funcall collection helm-pattern test t) + ((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 ffap-url-regexp helm-pattern) + if (string-match helm--url-regexp input) collect f else collect (concat (file-name-as-directory - (helm-basedir helm-pattern)) f))) + (helm-basedir input)) + 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) + ((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-default-transformer (candidates _source) +(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'." - (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))) + (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 @@ -295,17 +419,21 @@ If COLLECTION is an `obarray', a TEST should be needed. See `obarray'." 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 'helm-cr-default-transformer) + fc-transformer hist-fc-transformer marked-candidates nomark (alistp t) - (candidate-number-limit helm-candidate-number-limit)) + (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. @@ -363,6 +491,8 @@ Keys description: - 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). @@ -390,6 +520,14 @@ Keys description: `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. @@ -408,7 +546,11 @@ that use `helm-comp-read' See `helm-M-x' for example." (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)) + (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)) @@ -419,83 +561,80 @@ that use `helm-comp-read' See `helm-M-x' for example." (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)))))) + (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 - :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)) + :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 - :filtered-candidate-transformer fc-transformer + :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 - :filtered-candidate-transformer fc-transformer + :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 - (if candidates-in-buffer - src-1 src))) + (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) @@ -512,9 +651,10 @@ that use `helm-comp-read' See `helm-M-x' for example." :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 - :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)) @@ -528,20 +668,9 @@ that use `helm-comp-read' See `helm-M-x' for example." (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))))) + (or result (helm-mode--keyboard-quit))))) + ;; Generic completing-read ;; ;; Support also function as collection. @@ -579,6 +708,7 @@ that use `helm-comp-read' See `helm-M-x' for example." (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) @@ -606,25 +736,12 @@ 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 @@ -632,9 +749,11 @@ It should be used when candidate list don't need to rebuild dynamically." :reverse-history helm-mode-reverse-history :input-history history :must-match require-match - :alistp alistp ; Ensure `all-completions' is used when non-nil [1]. + :alistp nil + :help-message #'helm-comp-read-help-message :name name - :requires-pattern (if (and (string= default "") + :requires-pattern (if (and (stringp default) + (string= default "") (or (eq require-match 'confirm) (eq require-match 'confirm-after-completion))) @@ -652,20 +771,47 @@ It should be used when candidate list don't need to rebuild dynamically." ;; helm-comp-read. :initial-input initial-input))) -(defun helm-completing-read-with-cands-in-buffer +(defun helm-completing-read-default-find-tag (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." + "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 (all-completions (or init "") collection))) + (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 @@ -711,7 +857,16 @@ See documentation of `completing-read' and `all-completions' for details." collect h)) ;; Disable hack that could be used before `completing-read'. ;; i.e (push ?\t unread-command-events). - 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 @@ -746,11 +901,13 @@ See documentation of `completing-read' and `all-completions' for details." ;; 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))) + (;; 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 @@ -773,12 +930,13 @@ See documentation of `completing-read' and `all-completions' for details." preselect history must-match + (fuzzy t) default marked-candidates (candidate-number-limit helm-ff-candidate-number-limit) nomark (alistp t) - (persistent-action 'helm-find-files-persistent-action) + (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. @@ -804,18 +962,20 @@ Keys description: - 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: a persistent action function. +- 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, @@ -836,17 +996,28 @@ Keys description: (helm-ff-auto-update-initial-value (and helm-ff-auto-update-initial-value (not (minibuffer-window-active-p (minibuffer-window))))) - helm-full-frame + 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 helm-comp-read-must-match-map)) + (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" @@ -861,8 +1032,10 @@ Keys description: :mode-line mode-line :candidates hist :nohighlight t - :persistent-action persistent-action + :fuzzy-match fuzzy + :persistent-action-if persistent-action-if :persistent-help persistent-help + :keymap cmap :nomark nomark :action action-fn) ;; Other source. @@ -881,9 +1054,10 @@ Keys description: :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) + (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 @@ -892,23 +1066,25 @@ Keys description: (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-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 src-list + :sources (if helm-mode-reverse-history + (reverse src-list) 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 + :full-frame nil :preselect preselect))) (or (cond ((and result (stringp result) @@ -918,15 +1094,11 @@ Keys description: (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)) + ((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) @@ -958,6 +1130,7 @@ Don't use it directly, use instead `helm-read-file-name' in your programs." 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. @@ -966,6 +1139,9 @@ Don't use it directly, use instead `helm-read-file-name' in your programs." 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 @@ -995,7 +1171,11 @@ Don't use it directly, use instead `helm-read-file-name' in your programs." (unwind-protect (setq fname (cond (;; A specialized function exists, run it - ;; with the two extra args specific to helm.. + ;; 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))) @@ -1015,6 +1195,7 @@ Don't use it directly, use instead `helm-read-file-name' in your programs." :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 @@ -1023,13 +1204,52 @@ Don't use it directly, use instead `helm-read-file-name' in your programs." (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'. + (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))) + + +;;; 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'." @@ -1044,6 +1264,7 @@ Can be used as value for `completion-in-region-function'." (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) @@ -1076,7 +1297,8 @@ Can be used as value for `completion-in-region-function'." (setcdr last-data nil)) 0)) (init-space-suffix (unless (or helm-completion-in-region-fuzzy-match - (string-suffix-p " " input)) + (string-suffix-p " " input) + (string= input "")) " ")) (file-comp-p (or (eq (completion-metadata-get metadata 'category) 'file) (helm-mode--in-file-completion-p) @@ -1110,23 +1332,23 @@ Can be used as value for `completion-in-region-function'." data)) :name str-command :fuzzy helm-completion-in-region-fuzzy-match - :nomark t + :nomark (null crm) + :marked-candidates crm :initial-input (cond ((and file-comp-p (not (string-match "/\\'" input))) (concat (helm-basename input) - (unless (string= input "") - init-space-suffix))) + 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))))) + :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 () @@ -1137,11 +1359,22 @@ Can be used as value for `completion-in-region-function'." (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))) + (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)))) @@ -1159,9 +1392,14 @@ Can be used as value for `completion-in-region-function'." 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'. @@ -1171,6 +1409,11 @@ 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 @@ -1184,11 +1427,14 @@ Note: This mode is incompatible with Emacs23." #'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-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)) @@ -1197,11 +1443,13 @@ Note: This mode is incompatible with Emacs23." (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-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)) @@ -1210,7 +1458,7 @@ Note: This mode is incompatible with Emacs23." (provide 'helm-mode) ;; Local Variables: -;; byte-compile-warnings: (not cl-functions obsolete) +;; byte-compile-warnings: (not obsolete) ;; coding: utf-8 ;; indent-tabs-mode: nil ;; End: diff --git a/elpa/helm-20160530.424/helm-net.el b/elpa/helm-20181110.1615/helm-net.el similarity index 76% rename from elpa/helm-20160530.424/helm-net.el rename to elpa/helm-20181110.1615/helm-net.el index cc885391..9678f71c 100644 --- a/elpa/helm-20160530.424/helm-net.el +++ b/elpa/helm-20181110.1615/helm-net.el @@ -1,6 +1,6 @@ ;;; helm-net.el --- helm browse url and search web. -*- lexical-binding: t -*- -;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto +;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto ;; 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 @@ -36,7 +36,7 @@ See `helm-browse-url-default-browser-alist'." :group 'helm-net :type 'symbol) -(defcustom helm-home-url "http://www.google.fr" +(defcustom helm-home-url "https://www.google.com" "Default url to use as home url." :group 'helm-net :type 'string) @@ -48,26 +48,28 @@ When nil, fallback to `browse-url-browser-function'." :type 'symbol) (defcustom helm-google-suggest-url - "http://google.com/complete/search?output=toolbar&q=" - "URL used for looking up Google suggestions." + "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 - "http://www.google.com/search?ie=utf-8&oe=utf-8&q=%s" - "URL used for Google searching." + "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) -(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. @@ -78,8 +80,9 @@ a personal url, see your settings on duckduckgo." :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." + "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) @@ -91,18 +94,14 @@ This is a format string, don't forget the `%s'." :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." + "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-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" + "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 @@ -116,14 +115,14 @@ This is a format string, don't forget the `%s'." :group 'helm-net) (defcustom helm-search-suggest-action-google-maps-url - "http://maps.google.com/maps?f=q&source=s_q&q=%s" + "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 - "http://www.google.com/search?safe=off&prmd=nvlifd&source=lnms&tbs=nws:1&q=%s" + "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 @@ -192,11 +191,11 @@ Can be \"-new-tab\" (default) or \"-new-window\"." (point-min) (point-max))) 'CompleteSuggestion) for i in result-alist collect - (cdr (cl-caadr (assoc 'suggestion i))))) + (cdr (cl-caadr (assq 'suggestion i))))) (defun helm-google-suggest-fetch (input) "Fetch suggestions for INPUT from XML buffer." - (let ((request (concat helm-google-suggest-url + (let ((request (format helm-google-suggest-url (url-hexify-string input)))) (helm-net--url-retrieve-sync request #'helm-google-suggest-parser))) @@ -264,7 +263,7 @@ Can be \"-new-tab\" (default) or \"-new-window\"." (defun helm-wikipedia-suggest-fetch () "Fetch Wikipedia suggestions and return them as a list." (require 'json) - (let ((request (concat helm-wikipedia-suggest-url + (let ((request (format helm-wikipedia-suggest-url (url-hexify-string helm-pattern)))) (helm-net--url-retrieve-sync request #'helm-wikipedia--parse-buffer))) @@ -282,38 +281,54 @@ Can be \"-new-tab\" (default) or \"-new-window\"." 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 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 + (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))) @@ -321,9 +336,9 @@ Can be \"-new-tab\" (default) or \"-new-window\"." (defun helm-wikipedia--parse-summary () (goto-char (point-min)) (when (search-forward "{" nil t) - (let ((result (cdr (assoc '* - (assoc 'text - (assoc 'parse + (let ((result (cdr (assq '* + (assq 'text + (assq 'parse (json-read-from-string (buffer-substring-no-properties (1- (point)) (point-max))))))))) @@ -351,20 +366,32 @@ Can be \"-new-tab\" (default) or \"-new-window\"." (substring result (match-end 0))))))))))))) +(defvar helm-wikipedia-map + (let ((map (copy-keymap helm-map))) + (define-key map (kbd "") '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)))) + 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-map - :follow 1 - :follow-delay helm-wikipedia-follow-delay + :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))) + ;;; Web browser functions. ;; @@ -376,12 +403,14 @@ Can be \"-new-tab\" (default) or \"-new-window\"." (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) @@ -405,32 +434,54 @@ Can be \"-new-tab\" (default) or \"-new-window\"." (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 open + +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 - url)))) + (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: ") @@ -473,16 +524,23 @@ NOTE: Probably not supported on some systems (e.g Windows)." ;;;###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))) + (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. @@ -518,7 +576,7 @@ NOTE: Probably not supported on some systems (e.g Windows)." (provide 'helm-net) ;; Local Variables: -;; byte-compile-warnings: (not cl-functions obsolete) +;; byte-compile-warnings: (not obsolete) ;; coding: utf-8 ;; indent-tabs-mode: nil ;; End: diff --git a/elpa/helm-20160530.424/helm-org.el b/elpa/helm-20181110.1615/helm-org.el similarity index 62% rename from elpa/helm-20160530.424/helm-org.el rename to elpa/helm-20181110.1615/helm-org.el index 33b06956..b045ddaa 100644 --- a/elpa/helm-20160530.424/helm-org.el +++ b/elpa/helm-20181110.1615/helm-org.el @@ -1,6 +1,6 @@ ;;; helm-org.el --- Helm for org headlines and keywords completion -*- lexical-binding: t -*- -;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto +;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto ;; 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 @@ -20,6 +20,10 @@ (require 'helm) (require 'helm-utils) (require 'org) + +;; Load org-with-point-at macro when compiling +(eval-when-compile + (require 'org-macs)) (declare-function org-agenda-switch-to "org-agenda.el") @@ -57,9 +61,9 @@ Note this have no effect in `helm-org-in-buffer-headings'." (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)) + ("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 @@ -70,6 +74,12 @@ Note this have no effect in `helm-org-in-buffer-headings'." :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) + + ;;; Org capture templates ;; ;; @@ -80,7 +90,7 @@ Note this have no effect in `helm-org-in-buffer-headings'." collect (cons (nth 1 template) (nth 0 template))) :action '(("Do capture" . (lambda (template-shortcut) (org-capture nil template-shortcut)))))) - + ;;; Org headings ;; ;; @@ -100,19 +110,19 @@ Note this have no effect in `helm-org-in-buffer-headings'." (set-window-prev-buffers nil (append (cdr (window-prev-buffers)) (car (window-prev-buffers))))) -(defun helm-org--run-open-heading-in-indirect-buffer () +(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) +(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 "") '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) + (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'.") @@ -128,8 +138,10 @@ Note this have no effect in `helm-org-in-buffer-headings'." (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))) + (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))) @@ -140,9 +152,55 @@ Note this have no effect in `helm-org-in-buffer-headings'." (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) @@ -156,14 +214,14 @@ Note this have no effect in `helm-org-in-buffer-headings'." (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))) + ((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 nofname + (file (unless (or (bufferp filename) nofname) (concat (helm-basename filename) ":")))) (when parents (add-function :around (var search-fn) @@ -172,7 +230,10 @@ Note this have no effect in `helm-org-in-buffer-headings'." (apply old-fn args))))) (save-excursion (save-restriction - (widen) + (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) @@ -218,35 +279,73 @@ Note this have no effect in `helm-org-in-buffer-headings'." (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))))) +(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) + ;;;###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*")) + (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 nil)) + (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*"))) @@ -272,7 +371,7 @@ current heading." :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 @@ -283,6 +382,14 @@ current heading." ;;;###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 @@ -290,7 +397,7 @@ current heading." (let ((helm-completing-read-handlers-alist (rassq-delete-all 'helm-org-completing-read-tags - helm-completing-read-handlers-alist))) + (copy-alist helm-completing-read-handlers-alist)))) (org-icompleting-read prompt collection pred req initial hist def inherit-input-method)) ;; Tags prompt @@ -311,7 +418,7 @@ current heading." (provide 'helm-org) ;; Local Variables: -;; byte-compile-warnings: (not cl-functions obsolete) +;; byte-compile-warnings: (not obsolete) ;; coding: utf-8 ;; indent-tabs-mode: nil ;; End: diff --git a/elpa/helm-20181110.1615/helm-pkg.el b/elpa/helm-20181110.1615/helm-pkg.el new file mode 100644 index 00000000..70023e7f --- /dev/null +++ b/elpa/helm-20181110.1615/helm-pkg.el @@ -0,0 +1,9 @@ +(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: diff --git a/elpa/helm-20160530.424/helm-regexp.el b/elpa/helm-20181110.1615/helm-regexp.el similarity index 73% rename from elpa/helm-20160530.424/helm-regexp.el rename to elpa/helm-20181110.1615/helm-regexp.el index 13a5623d..f0edbbcd 100644 --- a/elpa/helm-20160530.424/helm-regexp.el +++ b/elpa/helm-20181110.1615/helm-regexp.el @@ -1,6 +1,6 @@ ;;; helm-regexp.el --- In buffer regexp searching and replacement for helm. -*- lexical-binding: t -*- -;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto +;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto ;; 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 @@ -21,7 +21,6 @@ (require 'helm) (require 'helm-help) (require 'helm-utils) -(require 'helm-plugin) (declare-function helm-mm-split-pattern "helm-multi-match") @@ -55,7 +54,7 @@ Any other non--nil value update after confirmation." (defcustom helm-source-multi-occur-actions '(("Go to Line" . helm-moccur-goto-line) - ("Goto line other window" . helm-moccur-goto-line-ow) + ("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 @@ -66,6 +65,36 @@ Any other non--nil value update after confirmation." :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) (defface helm-moccur-buffer '((t (:foreground "DarkTurquoise" :underline t))) @@ -83,7 +112,6 @@ Any other non--nil value update after confirmation." (set-keymap-parent map helm-map) (define-key map (kbd "M-") 'helm-goto-next-file) (define-key map (kbd "M-") '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) @@ -140,8 +168,9 @@ i.e Don't replace inside a word, regexp is surrounded with \\bregexp\\b." :persistent-action #'helm-regexp-persistent-action :persistent-help "Show this line" :multiline t - :matchplugin nil + :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.)" @@ -154,8 +183,9 @@ i.e Don't replace inside a word, regexp is surrounded with \\bregexp\\b." (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)) + 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))) @@ -165,7 +195,7 @@ i.e Don't replace inside a word, regexp is surrounded with \\bregexp\\b." (helm-highlight-current-line)) (defun helm-regexp-kill-new (input) - (kill-new input) + (kill-new (substring-no-properties input)) (message "Killed: %s" input)) @@ -186,13 +216,29 @@ i.e Don't replace inside a word, regexp is surrounded with \\bregexp\\b." ;; 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 (buffer-string)) + 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))) @@ -214,7 +260,8 @@ i.e Don't replace inside a word, regexp is surrounded with \\bregexp\\b." 'buffer-name) (save-restriction (narrow-to-region (or (previous-single-property-change - (point) 'buffer-name) 1) + (point) 'buffer-name) + (point-at-bol 2)) (or (next-single-property-change (if (= beg end) (helm-moccur--next-or-previous-char) @@ -230,7 +277,7 @@ i.e Don't replace inside a word, regexp is surrounded with \\bregexp\\b." (when (= beg end) (forward-char 1)))) (cl-defun helm-moccur-action (candidate - &optional (method (quote buffer)) mark) + &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) @@ -240,22 +287,20 @@ arg METHOD can be one of buffer, buffer-other-window, buffer-other-frame." (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-window (helm-window-show-buffers (list buf) t)) (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)))) + (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) @@ -264,24 +309,19 @@ arg METHOD can be one of buffer, buffer-other-window, buffer-other-frame." (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. + 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 - (or current-prefix-arg ; persistent. - helm-current-prefix-arg))) ; exit. + 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 - (or current-prefix-arg ; persistent. - helm-current-prefix-arg))) ; exit. + candidate 'buffer-other-frame)) (defun helm-moccur-run-goto-line-ow () "Run goto line other window action from `helm-source-moccur'." @@ -303,6 +343,12 @@ Same as `helm-moccur-goto-line' but go in new frame." (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 () @@ -321,7 +367,10 @@ Same as `helm-moccur-goto-line' but go in new frame." (help-message :initform 'helm-moccur-help-message) (keymap :initform helm-moccur-map) (history :initform 'helm-occur-history) - (requires-pattern :initform 2))) + (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 @@ -369,7 +418,7 @@ Same as `helm-moccur-goto-line' but go in new frame." (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) +(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)) @@ -378,11 +427,16 @@ Same as `helm-moccur-goto-line' but go in new frame." (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)) @@ -407,6 +461,7 @@ Same as `helm-moccur-goto-line' but go in new frame." 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 @@ -440,12 +495,12 @@ Same as `helm-moccur-goto-line' but go in new frame." (defun helm-moccur-mode-goto-line () (interactive) (helm-aif (get-text-property (point) 'helm-realvalue) - (helm-moccur-goto-line it))) + (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) - (helm-moccur-goto-line-ow it))) + (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 @@ -479,18 +534,45 @@ Same as `helm-moccur-goto-line' but go in new frame." (setq buf new-buf)) (with-current-buffer (get-buffer-create buf) (setq buffer-read-only t) - (let ((inhibit-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)))))) + (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" @@ -514,7 +596,9 @@ Special commands: (forward-line 1)) (let ((inhibit-read-only t) (buffer (current-buffer)) - (buflst helm-multi-occur-buffer-list)) + (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 @@ -524,7 +608,8 @@ Special commands: (cl-loop for buf in buflst for bufstr = (or (and (buffer-live-p (get-buffer buf)) (with-current-buffer buf - (buffer-string))) + (funcall bsubstring + (point-min) (point-max)))) "") unless (string= bufstr "") do (add-text-properties @@ -541,7 +626,7 @@ Special commands: do (with-current-buffer buffer (insert (propertize - (car (helm-moccur-filter-one-by-one line)) + (car (helm-moccur-filter-one-by-one line t)) 'helm-realvalue line) "\n"))))) (message "Reverting buffer done"))))) @@ -568,7 +653,21 @@ Special commands: ;;;###autoload (defun helm-occur () - "Preconfigured helm for 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))))) @@ -578,13 +677,29 @@ Special commands: '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)) + (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 () @@ -602,6 +717,8 @@ Special commands: '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 @@ -638,7 +755,7 @@ The prefix arg can be set before calling (provide 'helm-regexp) ;; Local Variables: -;; byte-compile-warnings: (not cl-functions obsolete) +;; byte-compile-warnings: (not obsolete) ;; coding: utf-8 ;; indent-tabs-mode: nil ;; End: diff --git a/elpa/helm-20181110.1615/helm-ring.el b/elpa/helm-20181110.1615/helm-ring.el new file mode 100644 index 00000000..f744536b --- /dev/null +++ b/elpa/helm-20181110.1615/helm-ring.el @@ -0,0 +1,559 @@ +;;; helm-ring.el --- kill-ring, mark-ring, and register browsers for helm. -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto + +;; 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 . + +;;; 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)) + + +(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) + +;;; 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))) + + +;;;; +;; 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) + "" + 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]"))) + (_ "")))) + (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)))) + +;;;; +;;; 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 ' to execute 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 diff --git a/elpa/helm-20160530.424/helm-semantic.el b/elpa/helm-20181110.1615/helm-semantic.el similarity index 88% rename from elpa/helm-20160530.424/helm-semantic.el rename to elpa/helm-20181110.1615/helm-semantic.el index 5baa00ae..dcb55e09 100644 --- a/elpa/helm-20160530.424/helm-semantic.el +++ b/elpa/helm-20181110.1615/helm-semantic.el @@ -1,6 +1,8 @@ ;;; helm-semantic.el --- Helm interface for Semantic -*- lexical-binding: t -*- -;; Copyright (C) 2012 ~ 2016 Daniel Hackney +;; Copyright (C) 2012 ~ 2017 Daniel Hackney +;; 2012 ~ 2018 Thierry Volpiatto + ;; Author: Daniel Hackney ;; This program is free software; you can redistribute it and/or modify @@ -160,10 +162,13 @@ you have completion on these functions with `C-M i' in the customize interface." "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)))))) + (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 @@ -202,20 +207,23 @@ Fill in the symbol at point by default." (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)))) + (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 "\\_<" str "\\_>") str)) + :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 cl-functions obsolete) +;; byte-compile-warnings: (not obsolete) ;; coding: utf-8 ;; indent-tabs-mode: nil ;; End: diff --git a/elpa/helm-20160530.424/helm-sys.el b/elpa/helm-20181110.1615/helm-sys.el similarity index 60% rename from elpa/helm-20160530.424/helm-sys.el rename to elpa/helm-20181110.1615/helm-sys.el index 6f94dfa3..9ec918d2 100644 --- a/elpa/helm-20160530.424/helm-sys.el +++ b/elpa/helm-20181110.1615/helm-sys.el @@ -1,6 +1,6 @@ ;;; helm-sys.el --- System related functions for helm. -*- lexical-binding: t -*- -;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto +;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto ;; 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 @@ -33,28 +33,43 @@ :group 'helm-sys) -(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" +(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. -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'." +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 'string - :set 'helm-top-command-set-fn) + :type '(alist :key-type symbol :value-type (integer :tag "Column number"))) (defcustom helm-top-poll-delay 1.5 - "Helm top poll after this dealy when `helm-top-poll-mode' is enabled. + "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) @@ -68,7 +83,8 @@ being idle." (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." +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) @@ -97,7 +113,7 @@ Possible values are 'candidate or 'linum." (cancel-timer helm-top--poll-timer)) (condition-case nil (progn - (when (and (helm-alive-p) (null no-update)) + (when (and (helm--alive-p) (null no-update)) ;; Fix quitting while process is running ;; by binding `with-local-quit' in init function ;; Issue #1521. @@ -163,15 +179,16 @@ Possible values are 'candidate or 'linum." (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-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)) + :action-transformer #'helm-top-action-transformer + :group 'helm-sys)) (defvar helm-top--line nil) (defun helm-top-transformer (candidates _source) @@ -187,10 +204,11 @@ Return empty string for non--valid candidates." (cons helm-top--line lst)))) (defun helm-top--skip-top-line () - (let ((src-name (assoc-default 'name (helm-get-current-source)))) + (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)) + (helm-get-selection nil t src)) (when (string-match-p "^ *PID" it) (helm-next-line))))) @@ -198,33 +216,42 @@ Return empty string for non--valid candidates." "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))) + (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) - (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))))) + . (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-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--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) - (delete-other-windows) - (helm-top-sh "TERM" pid) - (helm-force-update)) + (helm-top-sh "TERM" (list pid)) + (helm-delete-current-selection)) (defun helm-top-init () "Insert output of top command in candidate buffer." @@ -262,55 +289,69 @@ Show actions only on line starting by a PID." (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))) + (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)) - (mem-1 (string-to-number (nth 9 split-1))) - (mem-2 (string-to-number (nth 9 split-2)))) + (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)) - (user-1 (nth 1 split-1)) - (user-2 (nth 1 split-2))) + (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 (replace-regexp-in-string - "[0-9]+" "[0-9]+" - (regexp-quote (helm-get-selection nil t))))) + (helm-update (helm-top--preselect-fn))) (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))))) + ;; 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 (replace-regexp-in-string - "[0-9]+" "[0-9]+" - (regexp-quote (helm-get-selection nil t))))) + (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 (replace-regexp-in-string - "[0-9]+" "[0-9]+" - (regexp-quote (helm-get-selection nil t))))) + (helm-update (helm-top--preselect-fn))) ;;; X RandR resolution change @@ -341,41 +382,44 @@ Show actions only on line starting by a PID." (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) + (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 - ("Change Resolution" - . (lambda (mode) - (call-process "xrandr" nil nil nil - "--screen" (helm-xrandr-screen) - "--output" (helm-xrandr-output) - "--mode" mode)))))) + 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))))) ;;; 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))))))) + (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))))))) ;;;###autoload @@ -389,7 +433,8 @@ Show actions only on line starting by a PID." (helm :sources 'helm-source-top :buffer "*helm top*" :full-frame t :candidate-number-limit 9999 - :preselect "^\\s-*[0-9]+") + :preselect "^\\s-*[0-9]+" + :truncate-lines helm-show-action-window-other-window) (remove-hook 'helm-after-update-hook 'helm-top--skip-top-line)))) ;;;###autoload @@ -408,7 +453,7 @@ Show actions only on line starting by a PID." (provide 'helm-sys) ;; Local Variables: -;; byte-compile-warnings: (not cl-functions obsolete) +;; byte-compile-warnings: (not obsolete) ;; coding: utf-8 ;; indent-tabs-mode: nil ;; End: diff --git a/elpa/helm-20160530.424/helm-tags.el b/elpa/helm-20181110.1615/helm-tags.el similarity index 93% rename from elpa/helm-20160530.424/helm-tags.el rename to elpa/helm-20181110.1615/helm-tags.el index 4cc4e6b5..88fc9043 100644 --- a/elpa/helm-20160530.424/helm-tags.el +++ b/elpa/helm-20181110.1615/helm-tags.el @@ -1,6 +1,6 @@ ;;; helm-tags.el --- Helm for Etags. -*- lexical-binding: t -*- -;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto +;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto ;; 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 @@ -96,7 +96,6 @@ one match." (set-keymap-parent map helm-map) (define-key map (kbd "M-") 'helm-goto-next-file) (define-key map (kbd "M-") '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) @@ -204,8 +203,9 @@ If no entry in cache, create one." ;; 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)))))))))) + (cl-pushnew (cons f (helm-etags-mtime f)) + helm-etags-mtime-alist + :test 'equal)))))))) (defvar helm-source-etags-select nil "Helm source for Etags.") @@ -234,6 +234,7 @@ If no entry in cache, create one." (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) @@ -250,16 +251,25 @@ If no entry in cache, create one." (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)) - when (file-exists-p f) - return f)) + 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) @@ -301,13 +311,7 @@ This function aggregates three sources of tag files: (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))))) + (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'.") @@ -333,7 +337,7 @@ Create with etags shell command, or visit with `find-tag' or `visit-tags-table'. (provide 'helm-tags) ;; Local Variables: -;; byte-compile-warnings: (not cl-functions obsolete) +;; byte-compile-warnings: (not obsolete) ;; coding: utf-8 ;; indent-tabs-mode: nil ;; End: diff --git a/elpa/helm-20160530.424/helm-types.el b/elpa/helm-20181110.1615/helm-types.el similarity index 76% rename from elpa/helm-20160530.424/helm-types.el rename to elpa/helm-20181110.1615/helm-types.el index fcf8f489..5eaacc78 100644 --- a/elpa/helm-20160530.424/helm-types.el +++ b/elpa/helm-20181110.1615/helm-types.el @@ -1,6 +1,6 @@ ;;; helm-types.el --- Helm types classes and methods. -*- lexical-binding: t -*- -;; Copyright (C) 2015 ~ 2016 Thierry Volpiatto +;; Copyright (C) 2015 ~ 2018 Thierry Volpiatto ;; Author: Thierry Volpiatto ;; URL: http://github.com/emacs-helm/helm @@ -39,31 +39,33 @@ (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) + "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)) @@ -79,11 +81,13 @@ 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 '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 'keymap) helm-generic-files-map) + (setf (slot-value source 'group) 'helm-files)) ;; Bookmarks @@ -94,6 +98,7 @@ (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 @@ -115,7 +120,9 @@ (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 'migemo) t) + (setf (slot-value source 'follow) 'never) + (setf (slot-value source 'group) 'helm-bookmark)) ;; Buffers @@ -124,17 +131,11 @@ (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)" 'helm-buffer-switch-buffers "Switch to buffer(s) other window `C-c o'" - 'helm-switch-to-buffers-other-window + 'helm-buffer-switch-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-%'" @@ -142,6 +143,7 @@ "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 @@ -169,7 +171,8 @@ (setf (slot-value source 'filtered-candidate-transformer) '(helm-skip-boring-buffers helm-buffers-sort-transformer - helm-highlight-buffers))) + helm-highlight-buffers)) + (setf (slot-value source 'group) 'helm-buffers)) ;; Functions (defclass helm-type-function (helm-source) () @@ -230,7 +233,8 @@ (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 'persistent-action) 'describe-function) + (setf (slot-value source 'group) 'helm-command)) ;; Timers (defclass helm-type-timers (helm-source) () @@ -259,7 +263,8 @@ (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 'persistent-help) "Describe Function") + (setf (slot-value source 'group) 'helm-elisp)) ;; Builders. (defun helm-build-type-file () @@ -274,7 +279,7 @@ (provide 'helm-types) ;; Local Variables: -;; byte-compile-warnings: (not cl-functions obsolete) +;; byte-compile-warnings: (not obsolete) ;; coding: utf-8 ;; indent-tabs-mode: nil ;; End: diff --git a/elpa/helm-20160530.424/helm-utils.el b/elpa/helm-20181110.1615/helm-utils.el similarity index 53% rename from elpa/helm-20160530.424/helm-utils.el rename to elpa/helm-20181110.1615/helm-utils.el index e9300c74..bfa5e07a 100644 --- a/elpa/helm-20160530.424/helm-utils.el +++ b/elpa/helm-20181110.1615/helm-utils.el @@ -1,6 +1,6 @@ ;;; helm-utils.el --- Utilities Functions for helm. -*- lexical-binding: t -*- -;; Copyright (C) 2012 ~ 2016 Thierry Volpiatto +;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto ;; 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 @@ -20,12 +20,12 @@ (require 'cl-lib) (require 'helm) (require 'helm-help) -(require 'compile) ; Fixme: Is this needed? -(require 'dired) +(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) (defgroup helm-utils nil @@ -64,7 +64,7 @@ It is a float, usually 1024.0 but could be 1000.0 on some systems." :type 'integer) (defcustom helm-sources-using-help-echo-popup '("Moccur" "Imenu in all buffers" - "Ack-Grep" "AG" "Gid" "Git-Grep") + "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))) @@ -108,7 +108,7 @@ In this case last position is added to the register ("¥" . 165) ;; Â¥ ("¦" . 166) ;; ¦ ("§" . 167) ;; § - ("¨" . 32) ;; SPC + ("¨" . 32) ;; SPC ("©" . 169) ;; © ("ª" . 97) ;; a ("«" . 171) ;; « @@ -122,7 +122,7 @@ In this case last position is added to the register ("µ" . 956) ;; μ ("¶" . 182) ;; ¶ ("·" . 183) ;; · - ("¸" . 32) ;; SPC + ("¸" . 32) ;; SPC ("¹" . 49) ;; 1 ("º" . 111) ;; o ("»" . 187) ;; » @@ -198,6 +198,9 @@ In this case last position is added to the register ("­" . 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'.") ;;; Faces. ;; @@ -211,50 +214,187 @@ In this case last position is added to the register "Face used to highlight item matched in a selected line." :group 'helm-faces) - -;; 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)) - ;;; Utils functions ;; ;; -(defun helm-switch-to-buffers (buffer-or-name &optional other-window) - "Switch to buffer BUFFER-OR-NAME. +(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 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 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 - (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)) + (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)) + (buffer helm-current-buffer)) "Check if BUFFER is narrowed. Default is `helm-current-buffer'." (with-current-buffer buffer @@ -265,21 +405,30 @@ Default is `helm-current-buffer'." (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) - (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))) + (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 nil nil nil nil 'pulse))) + (helm-highlight-current-line))) (defun helm-save-pos-to-register-before-jump () "Save current buffer position to `helm-save-pos-before-jump-register'. @@ -340,11 +489,13 @@ 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) + (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 @@ -373,19 +524,20 @@ from its directory." (eq major-mode 'org-agenda-mode)) org-directory (expand-file-name org-directory)) - (with-current-buffer buf default-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 ffap-url-regexp - (string-match ffap-url-regexp it)) + (if (and helm--url-regexp + (string-match helm--url-regexp it)) it (expand-file-name it)) - default-directory)) - ((or (file-remote-p sel) - (file-exists-p sel)) + (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))) @@ -393,54 +545,53 @@ from its directory." ;; Occur. (grep-line (with-current-buffer (get-buffer (car grep-line)) - (or (buffer-file-name) default-directory))) + (expand-file-name (or (buffer-file-name) default-directory)))) ;; Url. - ((and ffap-url-regexp (string-match ffap-url-regexp sel)) sel) + ((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 default-preselection)))))) + (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* ((pattern (regexp-quote helm-pattern)) - (reg1 (concat "\\_<" pattern "\\_>")) - (reg2 (concat "\\_<" pattern)) + (let* ((qpattern (regexp-quote helm-pattern)) + (reg1 (concat "\\_<" qpattern "\\_>")) + (reg2 (concat "\\_<" qpattern)) (reg3 helm-pattern) - (split (split-string 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 "\\`" pattern) str) 1 0) + (+ (if (string-match (concat "\\`" qpattern) str) 1 0) (cond ((string-match r1 str) 5) - ((and (string-match " " pattern) - (string-match (concat "\\_<" (car lst)) str) + ((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 " " pattern) - (cl-loop for r in lst always (string-match r str))) 3) + ((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 pattern)) + (cond ((or (zerop (string-width qpattern)) (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. @@ -451,9 +602,9 @@ KBSIZE is a floating point number, defaulting to `helm-default-kbsize'." 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))))) + (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 @@ -485,64 +636,65 @@ 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))))) + (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. @@ -562,6 +714,13 @@ If STRING is non--nil return instead a space separated 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) @@ -570,11 +729,11 @@ If STRING is non--nil return instead a space separated string." (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-split-window-inside-p helm-reuse-last-window-split-state ,window) (with-current-buffer ,buffer - (dired-format-columns-of-files ,candidates)) + (helm-format-columns-of-files ,candidates)) (unwind-protect (with-selected-window (setq ,window (temp-buffer-window-show @@ -591,53 +750,83 @@ If STRING is non--nil return instead a space separated string." (defvar helm-match-line-overlay nil) (defvar helm--match-item-overlays nil) -(defun helm-highlight-current-line (&optional start end buf face pulse) +(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 (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))) + 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)) - (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)))) + ;; 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 @@ -646,6 +835,10 @@ If STRING is non--nil return instead a space separated string." (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) @@ -657,8 +850,13 @@ If STRING is non--nil return instead a space separated string." (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. @@ -670,23 +868,26 @@ If STRING is non--nil return instead a space separated string." (cancel-timer helm--show-help-echo-timer) (setq helm--show-help-echo-timer nil))) -(defun helm-show-help-echo () +(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-idle-timer + (run-with-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)))))))))) + (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 @@ -695,12 +896,10 @@ If STRING is non--nil return instead a space separated string." (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-move-selection-after-hook 'helm-maybe-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))) + (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." @@ -746,8 +945,11 @@ directory, open this directory." (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)))) + (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. @@ -771,8 +973,9 @@ If COUNT is non--nil add a number after each prompt." (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)))) + (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))) @@ -800,7 +1003,7 @@ When unable to decode ENTITY returns nil." (provide 'helm-utils) ;; Local Variables: -;; byte-compile-warnings: (not cl-functions obsolete) +;; byte-compile-warnings: (not obsolete) ;; coding: utf-8 ;; indent-tabs-mode: nil ;; End: diff --git a/elpa/helm-20181110.1615/helm-x-files.el b/elpa/helm-20181110.1615/helm-x-files.el new file mode 100644 index 00000000..7aad88a4 --- /dev/null +++ b/elpa/helm-20181110.1615/helm-x-files.el @@ -0,0 +1,128 @@ +;;; helm-x-files.el --- helm auxiliary functions and sources. -*- lexical-binding: t -*- + +;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto + +;; 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 . + +;;; Code: + +(require 'helm-for-files) + + +;;; 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)))) + + +;;; 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 diff --git a/elpa/helm-aws-20151124.133/helm-aws-pkg.el b/elpa/helm-aws-20151124.133/helm-aws-pkg.el deleted file mode 100644 index 027bbadd..00000000 --- a/elpa/helm-aws-20151124.133/helm-aws-pkg.el +++ /dev/null @@ -1 +0,0 @@ -(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") diff --git a/elpa/helm-aws-20151124.133/helm-aws-autoloads.el b/elpa/helm-aws-20180514.1032/helm-aws-autoloads.el similarity index 55% rename from elpa/helm-aws-20151124.133/helm-aws-autoloads.el rename to elpa/helm-aws-20180514.1032/helm-aws-autoloads.el index fe93cf19..245c05f4 100644 --- a/elpa/helm-aws-20151124.133/helm-aws-autoloads.el +++ b/elpa/helm-aws-20180514.1032/helm-aws-autoloads.el @@ -1,9 +1,12 @@ ;;; helm-aws-autoloads.el --- automatically extracted autoloads ;; ;;; Code: -(add-to-list 'load-path (or (file-name-directory #$) (car load-path))) + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + -;;;### (autoloads nil "helm-aws" "helm-aws.el" (22215 7747 0 0)) +;;;### (autoloads nil "helm-aws" "helm-aws.el" (0 0 0 0)) ;;; Generated autoloads from helm-aws.el (autoload 'helm-aws "helm-aws" "\ @@ -11,11 +14,14 @@ Show helm with a table of aws information. \(fn)" t nil) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-aws" '("aws-"))) + ;;;*** ;; Local Variables: ;; version-control: never ;; no-byte-compile: t ;; no-update-autoloads: t +;; coding: utf-8 ;; End: ;;; helm-aws-autoloads.el ends here diff --git a/elpa/helm-aws-20180514.1032/helm-aws-pkg.el b/elpa/helm-aws-20180514.1032/helm-aws-pkg.el new file mode 100644 index 00000000..ba8f1232 --- /dev/null +++ b/elpa/helm-aws-20180514.1032/helm-aws-pkg.el @@ -0,0 +1,2 @@ +;;; -*- 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") diff --git a/elpa/helm-aws-20151124.133/helm-aws.el b/elpa/helm-aws-20180514.1032/helm-aws.el similarity index 81% rename from elpa/helm-aws-20151124.133/helm-aws.el rename to elpa/helm-aws-20180514.1032/helm-aws.el index 1f81ee05..04b7b023 100644 --- a/elpa/helm-aws-20151124.133/helm-aws.el +++ b/elpa/helm-aws-20180514.1032/helm-aws.el @@ -4,7 +4,7 @@ ;; Author: istib ;; URL: https://github.com/istib/helm-aws -;; Package-Version: 20151124.133 +;; 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")) @@ -40,6 +40,30 @@ (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.") @@ -85,10 +109,15 @@ Argument INSTANCE is the aws json in plist form" (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))) + (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) @@ -139,6 +168,11 @@ Argument INSTANCE-JSON is the json behind the row of helm data." (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." @@ -146,7 +180,7 @@ If it is stopped, start it. If it is running, stop it." (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))) + (aws-compile command))) ;;;###autoload (defun helm-aws () @@ -155,8 +189,8 @@ If it is stopped, start it. If it is running, stop it." (let ((choices (aws-get-active-instances))) (helm :buffer "*helm-aws*" - :sources '((name . "EC2 Instances") - (candidates . choices) + :sources `((name . "EC2 Instances") + (candidates . ,choices) (action . (("SSH" . (lambda (instance-json) (aws-ssh-into-instance (aws-get-ip-from-instance instance-json)))) diff --git a/elpa/helm-aws-readme.txt b/elpa/helm-aws-readme.txt deleted file mode 100644 index 241fd389..00000000 --- a/elpa/helm-aws-readme.txt +++ /dev/null @@ -1,6 +0,0 @@ -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/) diff --git a/elpa/helm-c-yasnippet-20151231.10/helm-c-yasnippet-pkg.el b/elpa/helm-c-yasnippet-20151231.10/helm-c-yasnippet-pkg.el deleted file mode 100644 index 2e82c7c3..00000000 --- a/elpa/helm-c-yasnippet-20151231.10/helm-c-yasnippet-pkg.el +++ /dev/null @@ -1 +0,0 @@ -(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")) diff --git a/elpa/helm-c-yasnippet-20151231.10/helm-c-yasnippet-autoloads.el b/elpa/helm-c-yasnippet-20170128.1542/helm-c-yasnippet-autoloads.el similarity index 73% rename from elpa/helm-c-yasnippet-20151231.10/helm-c-yasnippet-autoloads.el rename to elpa/helm-c-yasnippet-20170128.1542/helm-c-yasnippet-autoloads.el index f4fc61d2..41d5930b 100644 --- a/elpa/helm-c-yasnippet-20151231.10/helm-c-yasnippet-autoloads.el +++ b/elpa/helm-c-yasnippet-20170128.1542/helm-c-yasnippet-autoloads.el @@ -1,10 +1,13 @@ ;;; helm-c-yasnippet-autoloads.el --- automatically extracted autoloads ;; ;;; Code: -(add-to-list 'load-path (or (file-name-directory #$) (car load-path))) + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + -;;;### (autoloads nil "helm-c-yasnippet" "helm-c-yasnippet.el" (22156 -;;;;;; 56481 0 0)) +;;;### (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" "\ @@ -22,11 +25,14 @@ 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-"))) + ;;;*** ;; Local Variables: ;; version-control: never ;; no-byte-compile: t ;; no-update-autoloads: t +;; coding: utf-8 ;; End: ;;; helm-c-yasnippet-autoloads.el ends here diff --git a/elpa/helm-c-yasnippet-20170128.1542/helm-c-yasnippet-pkg.el b/elpa/helm-c-yasnippet-20170128.1542/helm-c-yasnippet-pkg.el new file mode 100644 index 00000000..5ffe639f --- /dev/null +++ b/elpa/helm-c-yasnippet-20170128.1542/helm-c-yasnippet-pkg.el @@ -0,0 +1,2 @@ +;;; -*- 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.imakaado@gmail.com")) :maintainer '("Kenji.I (Kenji Imakado)" . "ken.imakaado@gmail.com")) diff --git a/elpa/helm-c-yasnippet-20151231.10/helm-c-yasnippet.el b/elpa/helm-c-yasnippet-20170128.1542/helm-c-yasnippet.el similarity index 96% rename from elpa/helm-c-yasnippet-20151231.10/helm-c-yasnippet.el rename to elpa/helm-c-yasnippet-20170128.1542/helm-c-yasnippet.el index f763928b..1582abda 100644 --- a/elpa/helm-c-yasnippet-20151231.10/helm-c-yasnippet.el +++ b/elpa/helm-c-yasnippet-20170128.1542/helm-c-yasnippet.el @@ -6,7 +6,7 @@ ;; Author: Kenji.I (Kenji Imakado) ;; Version: 0.6.7 -;; Package-Version: 20151231.10 +;; Package-Version: 20170128.1542 ;; Package-Requires: ((helm "1.7.7") (yasnippet "0.8.0") (cl-lib "0.3")) ;; Keywords: convenience, emulation @@ -137,11 +137,11 @@ ex. for (...) { ... }" "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))) + (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 major-mode-dir yas-dir 'snippet-file) - (let ((target-dir (format "%s/%s/" yas-dir major-mode-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) @@ -170,10 +170,10 @@ If SNIPPET-FILE does not contain directory, it is placed in default snippet dire do (if (and (funcall predfunc file) (string-match regexp file)) (progn (setq found t) - (return (file-name-as-directory file))) + (cl-return (file-name-as-directory file))) (when (file-directory-p file) (setq result (helm-yas-find-recursively regexp file predicate)))) - finally (return result)))) + finally (cl-return result)))) (defun helm-yas-build-cur-snippets-alist (&optional table) @@ -230,8 +230,8 @@ like `yas--current-key'" (error "")) (skip-syntax-backward syntax) (setq start (point)) - (values (buffer-substring-no-properties start end) start end)) - (error (values "" (point) (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" @@ -297,7 +297,7 @@ space match anyword greedy" `((name . "Yasnippet") (init . (lambda () (setq helm-yas-selected-text (if mark-active (buffer-substring-no-properties (region-beginning) (region-end)) "")) - (multiple-value-setq + (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)) diff --git a/elpa/helm-c-yasnippet-readme.txt b/elpa/helm-c-yasnippet-readme.txt deleted file mode 100644 index 934b2f02..00000000 --- a/elpa/helm-c-yasnippet-readme.txt +++ /dev/null @@ -1,2 +0,0 @@ -Actions: Insert snippet, Open snippet file, Open snippet file other window -C-z: execute-persistent-action diff --git a/elpa/helm-core-20160105.2046/helm-core-autoloads.el b/elpa/helm-core-20160105.2046/helm-core-autoloads.el deleted file mode 100644 index 71356981..00000000 --- a/elpa/helm-core-20160105.2046/helm-core-autoloads.el +++ /dev/null @@ -1,202 +0,0 @@ -;;; helm-core-autoloads.el --- automatically extracted autoloads -;; -;;; Code: -(add-to-list 'load-path (or (file-name-directory #$) (car load-path))) - -;;;### (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 \" q\" '(foo bar baz) 2) - -Each time \" 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 \\\\[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 \\\\[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) - -;;;*** - -;;;### (autoloads nil nil ("helm-core-pkg.el" "helm-lib.el" "helm-multi-match.el" -;;;;;; "helm-source.el") (22156 56341 612132 0)) - -;;;*** - -;; Local Variables: -;; version-control: never -;; no-byte-compile: t -;; no-update-autoloads: t -;; End: -;;; helm-core-autoloads.el ends here diff --git a/elpa/helm-core-20160105.2046/helm-core-pkg.el b/elpa/helm-core-20160105.2046/helm-core-pkg.el deleted file mode 100644 index 7e688058..00000000 --- a/elpa/helm-core-20160105.2046/helm-core-pkg.el +++ /dev/null @@ -1,8 +0,0 @@ -(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: diff --git a/elpa/helm-core-20160105.2046/helm-lib.el b/elpa/helm-core-20160105.2046/helm-lib.el deleted file mode 100644 index 999f36f5..00000000 --- a/elpa/helm-core-20160105.2046/helm-lib.el +++ /dev/null @@ -1,674 +0,0 @@ -;;; helm-lib.el --- Helm routines. -*- lexical-binding: t -*- - -;; Copyright (C) 2015 Thierry Volpiatto - -;; Author: Thierry Volpiatto -;; 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 . - -;;; Commentary: -;; All helm functions that don't require specific helm code should go here. - -;;; Code: - -(require 'cl-lib) -(require 'dired) - - -;;; 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 \\\\[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) - - -;;; 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.") - -;;; 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)) - -;;; 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))) - -;;; 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)))) - -;;; 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)))))) - - -;;; 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))) - -;;; 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)) - - -;;; 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)) - -;;; 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)))) - -;;; 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)) - - -;; 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 diff --git a/elpa/helm-core-20160105.2046/helm-multi-match.el b/elpa/helm-core-20160105.2046/helm-multi-match.el deleted file mode 100644 index 3e740da2..00000000 --- a/elpa/helm-core-20160105.2046/helm-multi-match.el +++ /dev/null @@ -1,373 +0,0 @@ -;;; 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 - -;; Author: Thierry Volpiatto -;; 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 . - -;;; Code: - -(require 'cl-lib) -(require 'helm-lib) - - -(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) - - -;; 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)) - - -;;; 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) ".*")) - - -;;; 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))) - - -;;; 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)) - - -;;; 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)) - - -;;; 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)) - - -;;; 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)) - -;;; 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))) - - -;;; 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)) - - -;;; 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 diff --git a/elpa/helm-core-20160105.2046/helm-source.el b/elpa/helm-core-20160105.2046/helm-source.el deleted file mode 100644 index beb737ff..00000000 --- a/elpa/helm-core-20160105.2046/helm-source.el +++ /dev/null @@ -1,1008 +0,0 @@ -;;; helm-source.el --- Helm source creation. -*- lexical-binding: t -*- - -;; Copyright (C) 2015 Thierry Volpiatto - -;; Author: Thierry Volpiatto -;; 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 . - -;;; 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") - - -(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.") - - -;;; 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.") - - -;;; 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."))) - - -;;; 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)))))) - - -;;; 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))))) - - -;;; Methods to build sources. -;; -;; -(defun helm-source--persistent-help-string (string source) - (substitute-command-keys - (concat "\\\\[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-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'"))) - - -;;; 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 diff --git a/elpa/helm-core-20160105.2046/helm.el b/elpa/helm-core-20160105.2046/helm.el deleted file mode 100644 index 6f2c0d21..00000000 --- a/elpa/helm-core-20160105.2046/helm.el +++ /dev/null @@ -1,5532 +0,0 @@ -;;; helm.el --- Emacs incremental and narrowing framework -*- lexical-binding: t -*- - -;; Copyright (C) 2007 Tamas Patrovics -;; 2008 ~ 2011 rubikitch -;; 2011 ~ 2015 Thierry Volpiatto - -;; This is a fork of anything.el wrote by Tamas Patrovics. - -;; Authors of anything.el: Tamas Patrovics -;; rubikitch -;; Thierry Volpiatto - -;; Author: Thierry Volpiatto -;; 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 . - -;;; Code: - -(require 'cl-lib) -(require 'advice) ; Shutup byte compiler about ad-deactivate. -(require 'helm-lib) -(require 'helm-multi-match) -(require 'helm-source) - - -;;; 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 \" q\" '(foo bar baz) 2) - -Each time \" 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)))))) - - -;;; Keymap -;; -;; -(defvar helm-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map minibuffer-local-map) - (define-key map (kbd "") 'helm-next-line) - (define-key map (kbd "") '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 "") 'helm-follow-action-forward) - (define-key map (kbd "") 'helm-follow-action-backward) - (define-key map (kbd "") 'helm-previous-page) - (define-key map (kbd "") '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 "") 'helm-next-source) - (define-key map (kbd "") 'helm-previous-source) - (define-key map (kbd "") '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-") '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-") 'helm-scroll-other-window-down) - (define-key map (kbd "") 'helm-scroll-other-window) - (define-key map (kbd "") '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 "") '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 "" (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.") - - -(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) - - -;;; 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) - - -;;; 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-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' 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 => execute default action on number candidate before selection. -C-c => execute default action on number 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 - -\\\\[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'. - - -;;; 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\\)://\\)") - -;; 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-' -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")))) - - -;; 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)))) - - -;; 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))) - - -;; 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)))) - - -;; 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)))))) - - -;; 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))) - - -;; 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 \\\\[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 \\\\[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)))) - - -;;; 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)))) - - -;;;###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))))))) - - -;;; 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))) - - -;;; 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))) - - -;;; 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))) - -;; 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))))) - - -;;; 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) - - -;;; 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)) - - -;; 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)))) - - -;;; 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)) - - -;; 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)) - - -;;; 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))))) - - -;;; 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")) - - -;;; 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)) - - -;;; 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))) - - -;; 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)) - - -;;; 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")))) - - -;; 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))) - - -;;; 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)) - - -;;; 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)) - - - -;; 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)))))) - - -;;; 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))))) - - -;;; 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 diff --git a/elpa/helm-core-20160217.958/helm-core-autoloads.el b/elpa/helm-core-20160217.958/helm-core-autoloads.el deleted file mode 100644 index 92f393d1..00000000 --- a/elpa/helm-core-20160217.958/helm-core-autoloads.el +++ /dev/null @@ -1,202 +0,0 @@ -;;; helm-core-autoloads.el --- automatically extracted autoloads -;; -;;; Code: -(add-to-list 'load-path (or (file-name-directory #$) (car load-path))) - -;;;### (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 \" q\" '(foo bar baz) 2) - -Each time \" 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 \\\\[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 \\\\[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) - -;;;*** - -;;;### (autoloads nil nil ("helm-core-pkg.el" "helm-lib.el" "helm-multi-match.el" -;;;;;; "helm-source.el") (22215 7773 270790 0)) - -;;;*** - -;; Local Variables: -;; version-control: never -;; no-byte-compile: t -;; no-update-autoloads: t -;; End: -;;; helm-core-autoloads.el ends here diff --git a/elpa/helm-core-20160217.958/helm-core-pkg.el b/elpa/helm-core-20160217.958/helm-core-pkg.el deleted file mode 100644 index e3073b51..00000000 --- a/elpa/helm-core-20160217.958/helm-core-pkg.el +++ /dev/null @@ -1,7 +0,0 @@ -(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: diff --git a/elpa/helm-core-20160217.958/helm-lib.el b/elpa/helm-core-20160217.958/helm-lib.el deleted file mode 100644 index cd7cd2ad..00000000 --- a/elpa/helm-core-20160217.958/helm-lib.el +++ /dev/null @@ -1,714 +0,0 @@ -;;; helm-lib.el --- Helm routines. -*- lexical-binding: t -*- - -;; Copyright (C) 2015 Thierry Volpiatto - -;; Author: Thierry Volpiatto -;; 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 . - -;;; Commentary: -;; All helm functions that don't require specific helm code should go here. - -;;; Code: - -(require 'cl-lib) -(require 'dired) - - -;;; 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 \\\\[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) - - -;;; 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.") - -;;; 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)) - -;;; 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))) - -;;; 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)))) - -;;; 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)))))) - - -;;; 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))) - -;;; 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)) - - -;;; 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)) - -;;; 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)))) - -;;; 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)) - - -;; 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 diff --git a/elpa/helm-core-20160217.958/helm-multi-match.el b/elpa/helm-core-20160217.958/helm-multi-match.el deleted file mode 100644 index 3e740da2..00000000 --- a/elpa/helm-core-20160217.958/helm-multi-match.el +++ /dev/null @@ -1,373 +0,0 @@ -;;; 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 - -;; Author: Thierry Volpiatto -;; 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 . - -;;; Code: - -(require 'cl-lib) -(require 'helm-lib) - - -(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) - - -;; 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)) - - -;;; 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) ".*")) - - -;;; 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))) - - -;;; 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)) - - -;;; 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)) - - -;;; 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)) - - -;;; 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)) - -;;; 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))) - - -;;; 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)) - - -;;; 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 diff --git a/elpa/helm-core-20160217.958/helm-source.el b/elpa/helm-core-20160217.958/helm-source.el deleted file mode 100644 index 71d22b5f..00000000 --- a/elpa/helm-core-20160217.958/helm-source.el +++ /dev/null @@ -1,1016 +0,0 @@ -;;; helm-source.el --- Helm source creation. -*- lexical-binding: t -*- - -;; Copyright (C) 2015 Thierry Volpiatto - -;; Author: Thierry Volpiatto -;; 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 . - -;;; 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") - - -(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.") - - -;;; 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.") - - -;;; 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."))) - - -;;; 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)))))) - - -;;; 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))))) - - -;;; Methods to build sources. -;; -;; -(defun helm-source--persistent-help-string (string source) - (substitute-command-keys - (concat "\\\\[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-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'"))) - - -;;; 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 diff --git a/elpa/helm-core-20160217.958/helm.el b/elpa/helm-core-20160217.958/helm.el deleted file mode 100644 index 18379138..00000000 --- a/elpa/helm-core-20160217.958/helm.el +++ /dev/null @@ -1,5641 +0,0 @@ -;;; helm.el --- Emacs incremental and narrowing framework -*- lexical-binding: t -*- - -;; Copyright (C) 2007 Tamas Patrovics -;; 2008 ~ 2011 rubikitch -;; 2011 ~ 2015 Thierry Volpiatto - -;; This is a fork of anything.el wrote by Tamas Patrovics. - -;; Authors of anything.el: Tamas Patrovics -;; rubikitch -;; Thierry Volpiatto - -;; Author: Thierry Volpiatto -;; 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 . - -;;; Code: - -(require 'cl-lib) -(require 'advice) ; Shutup byte compiler about ad-deactivate. -(require 'helm-lib) -(require 'helm-multi-match) -(require 'helm-source) - - -;;; 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 \" q\" '(foo bar baz) 2) - -Each time \" 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)))))) - - -;;; Keymap -;; -;; -(defvar helm-map - (let ((map (make-sparse-keymap))) - (set-keymap-parent map minibuffer-local-map) - (define-key map (kbd "") 'helm-next-line) - (define-key map (kbd "") '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 "") 'helm-follow-action-forward) - (define-key map (kbd "") 'helm-follow-action-backward) - (define-key map (kbd "") 'helm-previous-page) - (define-key map (kbd "") '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 "") 'helm-next-source) - (define-key map (kbd "") 'helm-previous-source) - (define-key map (kbd "") '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-") '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-") 'helm-scroll-other-window-down) - (define-key map (kbd "") 'helm-scroll-other-window) - (define-key map (kbd "") '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 "") '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 "" (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.") - - -(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) - - -;;; 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) - - -;;; 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-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' 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 => execute default action on number candidate before selection. -C-c => execute default action on number 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 - -\\\\[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'. - - -;;; 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\\)://\\)") - -;; 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-' -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")))) - - -;; 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)))) - - -;; 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))) - - -;; 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)))) - - -;; 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)))))) - - -;; 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))) - - -;; 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 \\\\[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 \\\\[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)))) - - -;;; 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)))) - - -;;;###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))))))) - - -;;; 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))) - - -;;; 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)))))) - - -;;; 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))) - -;; 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))))) - - -;;; 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) - - -;;; 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)) - - -;; 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)))) - - -;;; 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)) - - -;; 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)) - - -;;; 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))))) - - -;;; 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")) - - -;;; 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)) - - -;;; 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))) - - -;; 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)) - - -;;; 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) - - -;; 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))) - - -;;; 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)) - - -;;; 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) - - - -;; 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) - - -;;; 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))))) - - -;;; 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 diff --git a/elpa/helm-core-20160530.52/helm-core-autoloads.el b/elpa/helm-core-20160530.52/helm-core-autoloads.el deleted file mode 100644 index 43839806..00000000 --- a/elpa/helm-core-20160530.52/helm-core-autoloads.el +++ /dev/null @@ -1,200 +0,0 @@ -;;; helm-core-autoloads.el --- automatically extracted autoloads -;; -;;; Code: -(add-to-list 'load-path (or (file-name-directory #$) (car load-path))) - -;;;### (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 \" q\" '(foo bar baz) 2) - -Each time \" 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 -\\\\[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. \\\\[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) - -;;;*** - -;;;### (autoloads nil nil ("helm-core-pkg.el" "helm-lib.el" "helm-multi-match.el" -;;;;;; "helm-source.el") (22348 36024 558133 0)) - -;;;*** - -;; Local Variables: -;; version-control: never -;; no-byte-compile: t -;; no-update-autoloads: t -;; End: -;;; helm-core-autoloads.el ends here diff --git a/elpa/helm-core-20160530.52/helm-core-pkg.el b/elpa/helm-core-20160530.52/helm-core-pkg.el deleted file mode 100644 index 74629d30..00000000 --- a/elpa/helm-core-20160530.52/helm-core-pkg.el +++ /dev/null @@ -1,7 +0,0 @@ -(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: diff --git a/elpa/helm-core-20160530.52/helm-lib.el b/elpa/helm-core-20160530.52/helm-lib.el deleted file mode 100644 index 59f59739..00000000 --- a/elpa/helm-core-20160530.52/helm-lib.el +++ /dev/null @@ -1,803 +0,0 @@ -;;; helm-lib.el --- Helm routines. -*- lexical-binding: t -*- - -;; Copyright (C) 2015 ~ 2016 Thierry Volpiatto - -;; Author: Thierry Volpiatto -;; 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 . - -;;; Commentary: -;; All helm functions that don't require specific helm code should go here. - -;;; Code: - -(require 'cl-lib) -(require 'dired) - - -;;; 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 \\\\[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) - - -;;; 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.") - -;;; 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)) - -;;; 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)))) - -;;; 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))) - -;;; 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)))) - -;;; 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)))))) - - -;;; 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))) - -;;; 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)) - - -;;; 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)) - - -;;; 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))))) - -;;; 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)))) - -;;; 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)) - - -;; 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 diff --git a/elpa/helm-core-20181110.1635/helm-core-autoloads.el b/elpa/helm-core-20181110.1635/helm-core-autoloads.el new file mode 100644 index 00000000..adc09a32 --- /dev/null +++ b/elpa/helm-core-20181110.1635/helm-core-autoloads.el @@ -0,0 +1,261 @@ +;;; helm-core-autoloads.el --- automatically extracted autoloads +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (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 \" q\") '(foo bar baz) 2) + +Each time \" 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 +\\\\[next-history-element]. + +It can be a string or a list of strings, in this case +\\\\[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-"))) + +;;;*** + +;;;### (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-"))) + +;;;*** + +;;;### (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"))) + +;;;*** + +;;;### (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-"))) + +;;;*** + +;;;### (autoloads nil nil ("helm-core-pkg.el") (0 0 0 0)) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; helm-core-autoloads.el ends here diff --git a/elpa/helm-core-20181110.1635/helm-core-pkg.el b/elpa/helm-core-20181110.1635/helm-core-pkg.el new file mode 100644 index 00000000..c8d0e81d --- /dev/null +++ b/elpa/helm-core-20181110.1635/helm-core-pkg.el @@ -0,0 +1,7 @@ +(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: diff --git a/elpa/helm-core-20181110.1635/helm-lib.el b/elpa/helm-core-20181110.1635/helm-lib.el new file mode 100644 index 00000000..4c74a809 --- /dev/null +++ b/elpa/helm-core-20181110.1635/helm-lib.el @@ -0,0 +1,1379 @@ +;;; helm-lib.el --- Helm routines. -*- lexical-binding: t -*- + +;; Copyright (C) 2015 ~ 2018 Thierry Volpiatto + +;; Author: Thierry Volpiatto +;; 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 . + +;;; 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) + +;;; 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 \\\\[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) + + +;;; 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.") + + +;;; 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)))) + +;;; 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)) + +;;; 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)))) + + +;;; 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))) + + +;;; 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))))))) + +;;; 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)))) + +;;; 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)))))) + + +;;; 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)))) + +;;; 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))) + +;;; 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)))) + +;;; 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)) + + +;;; 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))))) + +;;; 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)))) + +;;; 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)) + + +;; 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 diff --git a/elpa/helm-core-20160530.52/helm-multi-match.el b/elpa/helm-core-20181110.1635/helm-multi-match.el similarity index 94% rename from elpa/helm-core-20160530.52/helm-multi-match.el rename to elpa/helm-core-20181110.1635/helm-multi-match.el index a926adbc..3d36bfea 100644 --- a/elpa/helm-core-20160530.52/helm-multi-match.el +++ b/elpa/helm-core-20181110.1635/helm-multi-match.el @@ -3,7 +3,7 @@ ;; Original Author: rubikitch ;; Copyright (C) 2008 ~ 2011 rubikitch -;; Copyright (C) 2011 ~ 2016 Thierry Volpiatto +;; Copyright (C) 2011 ~ 2018 Thierry Volpiatto ;; Author: Thierry Volpiatto ;; URL: http://github.com/emacs-helm/helm @@ -54,30 +54,30 @@ when these options are used." ;; Internal -(defconst helm-mm-default-match-functions +(defvar helm-mm-default-match-functions '(helm-mm-exact-match helm-mm-match)) -(defconst helm-mm-default-search-functions +(defvar helm-mm-default-search-functions '(helm-mm-exact-search helm-mm-search)) ;;; Build regexps ;; ;; -(defvar helm-mm-space-regexp "[\\ ] " +(defconst helm-mm-space-regexp "\\s\\\\s-" "Regexp to represent space itself in multiple regexp match.") -(defun helm-mm-split-pattern (pattern) +(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\"=> (\"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)))) +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 \"\.*\"." @@ -365,7 +365,7 @@ e.g \"bar foo\" will match \"barfoo\" but not \"foobar\" contrarily to ;; Local Variables: -;; byte-compile-warnings: (not cl-functions obsolete) +;; byte-compile-warnings: (not obsolete) ;; coding: utf-8 ;; indent-tabs-mode: nil ;; End: diff --git a/elpa/helm-core-20160530.52/helm-source.el b/elpa/helm-core-20181110.1635/helm-source.el similarity index 77% rename from elpa/helm-core-20160530.52/helm-source.el rename to elpa/helm-core-20181110.1635/helm-source.el index 6510620a..f656cc27 100644 --- a/elpa/helm-core-20160530.52/helm-source.el +++ b/elpa/helm-core-20181110.1635/helm-source.el @@ -1,6 +1,6 @@ ;;; helm-source.el --- Helm source creation. -*- lexical-binding: t -*- -;; Copyright (C) 2015 ~ 2016 Thierry Volpiatto +;; Copyright (C) 2015 ~ 2018 Thierry Volpiatto ;; Author: Thierry Volpiatto ;; URL: http://github.com/emacs-helm/helm @@ -126,15 +126,11 @@ (keymap :initarg :keymap - :initform nil + :initform helm-map :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.") + default value is `helm-map'.") (action :initarg :action @@ -161,8 +157,63 @@ " 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.") + 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 @@ -171,8 +222,8 @@ :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.") + 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 @@ -185,9 +236,14 @@ (multiline :initarg :multiline :initform nil - :custom boolean + :custom (choice boolean integer) :documentation - " Enable to selection multiline candidates.") + " 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 @@ -255,11 +311,11 @@ " 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 + `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 `candidates-transformer' + 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.") @@ -268,29 +324,40 @@ :initform nil :custom function :documentation - " Function called with one parameter; the selected candidate. + " Transform the selected candidate when passing it to action. - 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. + Function called with one parameter, the selected candidate. - 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. + 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: This is deprecated and you have better time using `filter-one-by-one'.") + 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 - " Function called with one parameter; the selected candidate. + " 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. - See `display-to-real'.") + 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 @@ -379,7 +446,23 @@ 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).") + 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 @@ -417,7 +500,11 @@ :custom symbol :documentation " Allow passing history variable to helm from source. - It should be a quoted symbol.") + 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 @@ -447,7 +534,8 @@ :custom (choice string function) :documentation " Source local `header-line-format'. - Have no effect when `helm-echo-input-in-header-line' is non--nil. + 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 @@ -467,9 +555,7 @@ :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) - +With a value of 1 enable, a value of -1 or nil disable the mode. See `helm-follow-mode' for more infos.") (follow-delay @@ -481,17 +567,18 @@ 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 + (multimatch + :initarg :multimatch :initform t - :custom boolean) + :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 @@ -502,7 +589,9 @@ 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.") + 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 @@ -534,7 +623,14 @@ :custom (choice null integer) :documentation " This slot have no more effect and is just kept for backward compatibility. - Please don't use it.")) + 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) @@ -543,13 +639,6 @@ ((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 @@ -575,7 +664,7 @@ 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.")) + 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 @@ -597,9 +686,7 @@ Matching is done basically with `string-match' against each candidate.") 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))) + (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 @@ -614,17 +701,12 @@ inherit from `helm-source'.") :initform nil :custom (choice list string) :documentation - " A string or a list that will be used to feed the `helm-candidates-buffer'. + " 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'. + 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.") - (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 @@ -653,10 +735,12 @@ inherit from `helm-source'.") :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'. + 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'.") + `buffer-substring-no-properties' which does no conversion and doesn't carry + text properties.") (search :initarg :search @@ -667,7 +751,7 @@ inherit from `helm-source'.") 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, + 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 @@ -688,20 +772,28 @@ inherit from `helm-source'.") list of functions or a single symbol function. NOTE: This have the same effect as using a nil value for - :MATCHPLUGIN slot.")) + :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.") +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 'helm-dummy-candidate) + :initform (lambda (_candidates _source) (list helm-pattern))) - (matchplugin + (multimatch :initform nil) (accept-empty @@ -720,16 +812,28 @@ like `re-search-forward', see below documentation of :search slot.") (defclass helm-source-in-file (helm-source-in-buffer) ((init :initform (lambda () - (let ((file (helm-attr 'candidates-file))) + (let ((file (helm-attr 'candidates-file)) + (count 1)) (with-current-buffer (helm-candidate-buffer 'global) - (insert-file-contents file))))) + (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.")) + :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.") + "The contents of the FILE will be used as candidates in buffer.") ;;; Error functions @@ -813,14 +917,15 @@ 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))) + (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) @@ -878,9 +983,6 @@ an eieio class." (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) @@ -892,7 +994,13 @@ an eieio class." (helm-aif (slot-value source 'filtered-candidate-transformer) (append (helm-mklist it) (list #'helm-fuzzy-highlight-matches)) - (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))) @@ -903,10 +1011,10 @@ an eieio class." (append (helm-mklist it) (list helm-fuzzy-match-fn))) (setf (slot-value source 'match) helm-fuzzy-match-fn))) - (when (slot-value source 'matchplugin) + (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 'matchplugin)) + (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) @@ -926,17 +1034,20 @@ an eieio class." (lambda () (helm-init-candidates-in-buffer 'global - (if (functionp it) (funcall it) it)))))))) + (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 'matchplugin) + (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 'matchplugin)) + (helm-aif (and (null (slot-value source 'multimatch)) (slot-value source 'migemo)) (unless (eq it 'nomultimatch) (setf (slot-value source 'search) @@ -952,8 +1063,10 @@ an eieio class." (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.")) + (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))) @@ -1008,7 +1121,7 @@ Args ARGS are keywords provided by `helm-source-in-file'." (provide 'helm-source) ;; Local Variables: -;; byte-compile-warnings: (not cl-functions obsolete) +;; byte-compile-warnings: (not obsolete) ;; coding: utf-8 ;; indent-tabs-mode: nil ;; End: diff --git a/elpa/helm-core-20160530.52/helm.el b/elpa/helm-core-20181110.1635/helm.el similarity index 56% rename from elpa/helm-core-20160530.52/helm.el rename to elpa/helm-core-20181110.1635/helm.el index 22601e3f..50ecc130 100644 --- a/elpa/helm-core-20160530.52/helm.el +++ b/elpa/helm-core-20181110.1635/helm.el @@ -2,7 +2,7 @@ ;; Copyright (C) 2007 Tamas Patrovics ;; 2008 ~ 2011 rubikitch -;; 2011 ~ 2016 Thierry Volpiatto +;; 2011 ~ 2018 Thierry Volpiatto ;; This is a fork of anything.el wrote by Tamas Patrovics. @@ -29,6 +29,7 @@ ;;; Code: (require 'cl-lib) +(require 'async) (require 'advice) ; Shutup byte compiler about ad-deactivate. (require 'helm-lib) (require 'helm-multi-match) @@ -41,22 +42,25 @@ ;;;###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. +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\")) + (defun foo () + (interactive) + (message \"Run foo\")) + (defun bar () + (interactive) + (message \"Run bar\")) + (defun baz () + (interactive) + (message \"Run baz\")) -\(helm-define-multi-key global-map \" q\" '(foo bar baz) 2) +\(helm-define-multi-key global-map (kbd \" q\") '(foo bar baz) 2) -Each time \" q\" is pressed, the next function is executed. Waiting -more than 2 seconds between key presses switches back to executing the first +Each time \" 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))) @@ -78,7 +82,9 @@ Run each function in the FUNCTIONS list in turn when called within DELAY seconds (iter (cl-gensym "helm-iter-key")) (timeout delay)) (eval (list 'defvar iter nil)) - (lambda () (interactive) (helm-run-multi-key-command funs iter timeout)))) + (lambda () + (interactive) + (helm-run-multi-key-command funs iter timeout)))) (defun helm-run-multi-key-command (functions iterator delay) (let ((fn (lambda () @@ -93,9 +99,11 @@ Run each function in the FUNCTIONS list in turn when called within DELAY seconds (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)))))) + (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. @@ -106,7 +114,7 @@ and second call within 0.5s runs `helm-swap-windows'." ;;;###autoload (defun helm-define-key-with-subkeys (map key subkey command - &optional other-subkeys menu exit-fn) + &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 @@ -126,15 +134,15 @@ 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. +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 char syntax only -\(e.g ?n), so don't use strings or vectors to define them." +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 () @@ -142,7 +150,7 @@ NOTE: SUBKEY and OTHER-SUBKEYS bindings support char syntax only (unwind-protect (progn (call-interactively command) - (while (let ((input (read-key menu)) other kb com) + (while (let ((input (read-key prompt)) other kb com) (setq last-command-event input) (cond ((eq input subkey) @@ -188,6 +196,7 @@ NOTE: SUBKEY and OTHER-SUBKEYS bindings support char syntax only (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) @@ -208,15 +217,15 @@ NOTE: SUBKEY and OTHER-SUBKEYS bindings support char syntax only (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 _") '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) @@ -228,6 +237,7 @@ NOTE: SUBKEY and OTHER-SUBKEYS bindings support char syntax only (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 "") 'undefined) ;; Multi keys @@ -235,10 +245,14 @@ NOTE: SUBKEY and OTHER-SUBKEYS bindings support char syntax only ;; 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)) @@ -249,23 +263,60 @@ NOTE: SUBKEY and OTHER-SUBKEYS bindings support char syntax only `(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.") +(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+) + (defgroup helm nil "Open helm." @@ -310,15 +361,14 @@ 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) -(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." @@ -340,22 +390,28 @@ 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'." + "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. +upper case characters in the pattern. Use nil or t to turn off smart behavior and use `case-fold-search' behavior. @@ -407,7 +463,7 @@ Other acceptable values are `same' which always display 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 +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 @@ -415,15 +471,29 @@ NOTE: this have no effect if `helm-split-window-preferred-function' is not :group 'helm :type 'symbol) -(defcustom helm-display-buffer-default-size nil +(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. See -`display-buffer' for more info." +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)) -(defcustom helm-split-window-in-side-p nil +(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'. @@ -439,7 +509,7 @@ handle this." 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', +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 @@ -450,13 +520,46 @@ 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-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." @@ -471,19 +574,45 @@ See documentation for `helm-delete-minibuffer-contents'." :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." + "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 escape from minibuffer during the helm session." + "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. + "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) @@ -500,7 +629,7 @@ This applies when using `helm-next/previous-line'." (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." +When nil, sorting is not done." :group 'helm :type 'function) @@ -528,7 +657,7 @@ See `fit-window-to-buffer' for details." (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. +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" @@ -551,10 +680,26 @@ The default is to enable this by default and then toggle :type 'boolean) (defcustom helm-echo-input-in-header-line nil - "Send current input in header-line." + "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. @@ -578,6 +723,63 @@ 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) ;;; Faces ;; @@ -620,7 +822,13 @@ See `helm-log-save-maybe' for more info." (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) + "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" @@ -658,26 +866,15 @@ See `helm-log-save-maybe' for more info." "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) + ;;; 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.") @@ -696,17 +893,11 @@ before creation of `helm-buffer'. Set local variables for 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'.") +(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. -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.") + "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 @@ -748,17 +939,12 @@ minibuffer abnormally (e.g. via `helm-keyboard-quit').") (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.") + "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. @@ -776,12 +962,6 @@ If `nil', `helm-debug-output' includes only variables with 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-help]:Help \ @@ -809,95 +989,311 @@ 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 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' is an Emacs framework for incremental -completions and narrowing selections. +\\[helm-documentation]: Show all helm documentations concatenated in one org file. -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. +From a Helm session, just hit \\\\[helm-help] to have the +documentation for the current source followed by the global Helm documentation. -** Helm Help +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. -C-h m\t\tShows this generic Helm help. +The hard-coded documentation bindings are: -** Helm's Basic Operations and Default Key Bindings +| 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- | | Toggle mark | +| RET | | Follow org link | +| C-% | | Push org mark | +| C-& | | Goto org mark-ring | +| TAB | | Org cycle | +| M- | | Toggle visibility | +| M-w | | Copy region | +| q | | Quit | -| 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) | +** Customize Helm -** Shortcuts For nth Action +Helm provides a lot of user variables for extensive customization. +From any Helm session, type \\\\[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'. -f1-12: Execute nth Action where n is 1 to 12. +Note: Some sources may not have their group set and default to the `helm' group. -** Shortcuts for executing Default Action on the nth candidate +** Helm's basic operations and default key bindings -C-x => executes default action on number candidate before currently selected candidate. +| 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) | -C-c => executes default action on number candidate after current selected candidate. +\[1] Delete from point to end or all depending on the value of +`helm-delete-minibuffer-contents-from-point'. + +** Shortcuts for n-th action -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. +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 : Execute default action on the n-th candidate before currently selected candidate. + +C-c : 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). -** Visible Marks +** 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. -Visible marks are displayed next to selected candidates, if any. -Some Helm actions operate on marked candidates. +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-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-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-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 and then select next line. -\\[helm-follow-action-backward]\t\tRun persistent action and then select previous line. +\\[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\tSuspend/reenable updates to candidates list. +\\[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-next-line], \\\\[helm-previous-line], etc. See above basic commands. +When `helm-buffer' contains more than one source, change source with \\\\[helm-next-source]. + +Note: When reaching the end of a source, \\\\[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-next-source]. + +** Resume previous session from current Helm session -** Global Commands +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'. -\\\\[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. +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-') this time + with a simple `define-key'. (Note that `S-' is not available in terminals.) -** Debugging helm +Note: `helm-define-key-with-subkeys' is available only once Helm is loaded. -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. +You can also use \\\\[helm-resume-previous-session-after-quit] to resume +the previous session, or \\\\[helm-resume-list-buffers-after-quit] +to have completion on all resumable buffers. -A convenient command is bound to \\\\[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-toggle-suspend-update] to turn off updating, then when you -are ready turn it on again to start updating. +** Global commands -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. +*** Resume Helm session from outside Helm -NOTE: Be aware that helm log buffers grow really fast, so use `helm-debug' only when needed. +\\\\[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 \\\\[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-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-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}" @@ -906,18 +1302,32 @@ 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.") ;;; 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-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 @@ -930,18 +1340,17 @@ It also accepts function or variable symbol.") "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--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) @@ -949,18 +1358,19 @@ It also accepts function or variable symbol.") (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--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 +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 @@ -974,7 +1384,7 @@ See `helm-exit-minibuffer' and `helm-keyboard-quit'.") (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.") + "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.") @@ -993,14 +1403,49 @@ precedence on :default.") "[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") + '("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. +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--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) ;; Utility: logging (defun helm-log (format-string &rest args) @@ -1013,16 +1458,16 @@ Use optional arguments ARGS like in `format'." (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)))))))) + (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." @@ -1049,14 +1494,16 @@ 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)))) + (cl-pushnew msg helm-issued-errors :test 'equal)))) (defun helm-log-save-maybe () - "Save log buffer if `helm-debug-root-directory' is set to a valid directory. + "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) - (file-directory-p helm-debug-root-directory) - helm-debug) + (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))) @@ -1088,33 +1535,6 @@ Messages are logged to a file named with todays date and time in this directory. (message "Helm issued errors: %s" (mapconcat 'identity (reverse helm-issued-errors) "\n")))) - -;; 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)))) - ;; Test tools (defmacro with-helm-time-after-update (&rest body) @@ -1133,19 +1553,6 @@ and not `exit-minibuffer' or other unwanted functions." ;; 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 @@ -1183,82 +1590,59 @@ and not `exit-minibuffer' or other unwanted functions." (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)) + +;;; 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 -(i.e a variable)." + +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 (or (assq attribute-name src) - (helm-get-attribute-from-source-type attribute-name src)) + (helm-aif (assq 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)) + (cdr it))))) (cl-defun helm-attrset (attribute-name value &optional - (src (helm-get-current-source)) - alter-type) + (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 ALTER-TYPE is non-`nil' alter the value of ATTRIBUTE-NAME in `helm-attributes' -if it exists. + +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." - (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)))) +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. @@ -1315,11 +1699,11 @@ only when predicate helm-ff-candidates-lisp-p return non-`nil': (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))))) + (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)) @@ -1332,6 +1716,9 @@ only when predicate helm-ff-candidates-lisp-p return non-`nil': :test 'equal) source)))) + +;;; Source filter +;; (defun helm-set-source-filter (sources) "Set the value of `helm-source-filter' to SOURCES and update. @@ -1361,13 +1748,14 @@ Shift+A shows all results: 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))))) + (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 @@ -1381,44 +1769,21 @@ existing Helm function names." 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) + (setq helm-sources (helm-get-sources sources)) (helm-log "helm-sources = %S" helm-sources)) - (unless no-init (helm-funcall-foreach 'init)) + (unless no-init (helm-compute-attr-in-sources '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) +(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 +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) + (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 @@ -1431,71 +1796,76 @@ with its properties." ;; 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) + (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 () +(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\)." +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)))) + (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. -Allow also checking if helm-buffer contain candidates." +Return nil when `helm-buffer' is empty." (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))))))) + (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* ((b (get-buffer buffer)) - (key (concat (buffer-name b) "/" (helm-attr 'name))) + (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 b)) - (modifiedp (/= source-tick buffer-tick))) + (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) @@ -1529,10 +1899,51 @@ 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 (helm-get-selection)) + (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) @@ -1547,7 +1958,7 @@ 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)) + (helm-apply-functions-from-source source value)) ((and (functionp value) (not (eq compute 'ignorefn))) (funcall value)) ((and (symbolp value) (boundp value)) @@ -1572,7 +1983,7 @@ 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 + (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)))) @@ -1581,8 +1992,24 @@ IOW Don't use VALUE of previous VAR to set the VALUE of next VAR. 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))) + -;; Core: API helper +;; API helper (cl-defun helm-empty-buffer-p (&optional (buffer helm-buffer)) "Check if BUFFER have candidates. Default value for BUFFER is `helm-buffer'." @@ -1592,27 +2019,40 @@ Default value for BUFFER is `helm-buffer'." "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)))))) + (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))))))) -;; Core: tools +;; 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. +(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)) + (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 "helm--source-name = %S" helm--source-name) (helm-log "functions = %S" functions) (helm-log "args = %S" args) (cl-loop with result @@ -1628,20 +2068,31 @@ Return the result of last function call." 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))))) +(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." - (cond ((or (and sources (symbolp sources)) - (and (listp sources) (assq 'name sources))) - (list sources)) - (sources) - (t helm-sources))) + (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'. @@ -1652,9 +2103,9 @@ only." (helm-empty-source-p)) 0 (save-excursion - (if in-current-source - (goto-char (helm-get-previous-header-pos)) - (goto-char (point-min))) + (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 @@ -1689,7 +2140,7 @@ only." ;; See comment about this in `with-local-quit'. (eval '(ignore nil))))) -;; Core: entry point +;; Entry point ;; `:allow-nest' is not in this list because it is treated before. (defconst helm-argument-keys '(:sources :input :prompt :resume @@ -1699,108 +2150,139 @@ only." (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 below. +- :sources +- :input +- :prompt +- :resume +- :preselect +- :buffer +- :keymap +- :default +- :history +- :allow-nest -PLIST is a list like \(:key1 val1 :key2 val2 ...\) or -\(&optional sources input prompt resume - preselect buffer keymap default history\). +Extra LOCAL-VARS keywords are supported, see the \"** Other +keywords\" section below. Basic keywords are the following: -\:sources +*** :sources + +One of the following: -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. +- 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 +*** :input -Temporary value of `helm-pattern', ie. initial input of minibuffer. +Initial input of minibuffer (temporary value of `helm-pattern') -\:prompt +*** :prompt -Prompt other than \"pattern: \". +Minibuffer prompt. Default value is `helm--prompt'. -\:resume +*** :resume + +If t, allow resumption of the previous session of this Helm +command, skipping initialization. -If t, Resurrect previously instance of `helm'. Skip the initialization. If 'noresume, this instance of `helm' cannot be resumed. -\:preselect +*** :preselect -Initially selected candidate. Specified by exact candidate or a regexp. +Initially selected candidate (string or regexp). -\:buffer +*** :buffer -`helm-buffer' instead of *helm*. +Buffer name for this Helm session. `helm-buffer' will take this value. -\:keymap +*** :keymap -`helm-map' for current `helm' session. +\[Obsolete] -\:default +Keymap used at the start of this Helm session. -A default argument that will be inserted in minibuffer \ with -\\\\[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. \\\\[next-history-element] -cycles through the list items. +It is overridden by keymaps specified in sources, and is kept +only for backward compatibility. -\:history +Keymaps should be specified in sources using the :keymap slot +instead. See `helm-source'. -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. +This keymap is not restored by `helm-resume'. + +*** :default + +Default value inserted into the minibuffer \ with +\\\\[next-history-element]. -\:allow-nest +It can be a string or a list of strings, in this case +\\\\[next-history-element] cycles through +the list items, starting with the first. -Allow running this helm command in a running helm session. +If nil, `thing-at-point' is used. -Standard arguments are supported. These two are the same: +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. -\(helm :sources sources :input input :prompt prompt :resume resume - :preselect preselect :buffer buffer :keymap keymap :default default - :history history\) +*** :history -and +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 -\(helm sources input prompt resume preselect buffer keymap default history\) +Allow running this Helm command in a running Helm session. -are the same for now. However, the use of non-keyword args is -deprecated and should not be used. +** Other keywords -Other keywords are interpreted as local variables of this helm +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\) + :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: -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. +\(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) + #'helm--nest) ((keywordp (car plist)) #'helm) (t #'helm-internal)))) (if (and helm-alive-p (eq fn #'helm)) - (if (helm-alive-p) + (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 @@ -1826,13 +2308,13 @@ to 10 as a session local variable. 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 +(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 'visible) + (get-buffer-window (helm-buffer-get) 'visible) (minibuffer-window-active-p (minibuffer-window)) (minibufferp (current-buffer)))) @@ -1859,7 +2341,7 @@ example, :candidate-number-limit is bound to unless (memq key helm-argument-keys) collect (cons sym value))) -;;; Core: entry point helper +;;; Entry point helper (defun helm-internal (&optional any-sources any-input any-prompt any-resume @@ -1868,13 +2350,18 @@ example, :candidate-number-limit is bound to "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)) + (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) @@ -1884,65 +2371,82 @@ ANY-KEYMAP ANY-DEFAULT ANY-HISTORY See `helm'." (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) - (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' + (let ( ;; `helm--source-name' is non-`nil' ;; when `helm' is invoked by action, reset it. - helm-source-name + 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))) + (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)) - (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)) + (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 "") - (and old--cua (cua-mode 1)) + (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))) ;;; Helm resume ;; @@ -1953,7 +2457,11 @@ 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) + (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) @@ -1961,12 +2469,13 @@ as a string with ARG." (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 helm-compiled-sources nil) (setq cur-dir (buffer-local-value 'default-directory (get-buffer any-buffer))) (setq helm-saved-selection nil @@ -1974,23 +2483,31 @@ as a string with ARG." (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)))) + (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)))) + (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) @@ -2017,6 +2534,53 @@ Return nil if no `helm-buffer' found." :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) + ;;;###autoload (defun helm-other-buffer (any-sources any-buffer) @@ -2024,17 +2588,32 @@ Return nil if no `helm-buffer' found." 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'" +;;; 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)) + (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 @@ -2042,14 +2621,16 @@ Arguments SAME-AS-HELM are the same as `helm'" (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)) + (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) @@ -2063,12 +2644,14 @@ Arguments SAME-AS-HELM are the same as `helm'" (if (fboundp 'advice-add) (progn (advice-add 'tramp-read-passwd - :around #'helm--advice-tramp-read-passwd) + :around #'helm--suspend-read-passwd) (advice-add 'ange-ftp-get-passwd - :around #'helm--advice-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)) - (when helm-prevent-escaping-from-minibuffer + (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 @@ -2078,7 +2661,7 @@ Arguments SAME-AS-HELM are the same as `helm'" (helm-display-mode-line (helm-get-current-source))))))) -;;; Core: Accessors +;;; Accessors ;; (defun helm-current-position (save-or-restore) "Save or restore current position in `helm-current-buffer'. @@ -2119,19 +2702,47 @@ frame configuration as per `helm-save-configuration-functions'." ;; 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)))) + (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-in-side-p) + helm-split-window-inside-p) (split-window (selected-window) nil (if (eq helm-split-window-default-side 'other) 'below helm-split-window-default-side)) @@ -2163,11 +2774,32 @@ frame configuration as per `helm-save-configuration-functions'." ;;; Display helm buffer ;; ;; -(defun helm-display-buffer (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 to display `helm-buffer'." - (let (pop-up-frames - (split-window-preferred-function + +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) @@ -2176,9 +2808,16 @@ The function to display `helm-buffer'." ((eq helm-split-window-default-side 'other) 'other) (helm--window-side-state) (t helm-split-window-default-side)) - 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 (with-current-buffer buffer helm-display-function) buffer) + (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 @@ -2193,66 +2832,186 @@ Arg ENABLE is the value of `no-other-window' window property." (set-window-parameter w 'no-other-window enabled))) 0)) -(defun helm-default-display-buffer (buffer) +(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'." - (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)) + (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 `(nil . ((window-height . ,helm-display-buffer-default-size)))))) - + 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) -;;; Core: initialize +;;; 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) - (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")) + (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." @@ -2272,12 +3031,9 @@ For ANY-RESUME ANY-INPUT ANY-DEFAULT and ANY-SOURCES See `helm'." "Restore position in `helm-current-buffer' when quitting." (helm-current-position 'restore)) -(defun helm--recent-push (elm sym) +(defun helm--push-and-remove-dups (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))) + (set sym (cons elm (delete elm (symbol-value sym))))) (defun helm--current-buffer () "[internal] Return `current-buffer' BEFORE `helm-buffer' is initialized. @@ -2298,26 +3054,26 @@ helm was started, use `helm-current-buffer' instead." (window-buffer (with-selected-window (minibuffer-window) (minibuffer-selected-window))))) -(defun helm--run-init-hooks (hook) +(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 (helm-get-sources) + 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) +(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) + (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) @@ -2325,11 +3081,18 @@ See :after-init-hook and :before-init-hook in `helm-source'." 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-compiled-sources 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) @@ -2341,12 +3104,7 @@ See :after-init-hook and :before-init-hook in `helm-source'." (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)))) + (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) @@ -2360,7 +3118,7 @@ See :after-init-hook and :before-init-hook in `helm-source'." ;; Run global hook. (helm-log-run-hook 'helm-after-initialize-hook) ;; Run local source hook. - (helm--run-init-hooks 'after-init-hook)) + (helm--run-init-hooks 'after-init-hook sources)) (define-derived-mode helm-major-mode fundamental-mode "Hmm" @@ -2371,19 +3129,20 @@ Unuseful when used outside helm, don't use it.") (defun helm-create-helm-buffer () "Create and setup `helm-buffer'." - (let ((root-dir default-directory)) + (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 'inhibit-read-only) t) + (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-follow-mode) nil) - (set (make-local-variable 'helm-display-function) helm-display-function) + (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 @@ -2394,9 +3153,7 @@ Unuseful when used outside helm, don't use it.") (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)) + (helm--set-local-variables-internal) (setq truncate-lines helm-truncate-lines) ; already local. (setq cursor-type nil)) (helm-initialize-overlays helm-buffer) @@ -2418,17 +3175,17 @@ please don't use it outside helm. (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) + 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) + (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)) - (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) @@ -2439,16 +3196,15 @@ For ANY-PRESELECT ANY-RESUME ANY-KEYMAP ANY-DEFAULT ANY-HISTORY, See `helm'." (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)))) + (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 @@ -2476,7 +3232,9 @@ For ANY-PRESELECT ANY-RESUME ANY-KEYMAP ANY-DEFAULT ANY-HISTORY, See `helm'." (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-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)) @@ -2487,6 +3245,9 @@ For ANY-PRESELECT ANY-RESUME ANY-KEYMAP ANY-DEFAULT ANY-HISTORY, See `helm'." (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 () @@ -2496,7 +3257,6 @@ For ANY-PRESELECT ANY-RESUME ANY-KEYMAP ANY-DEFAULT ANY-HISTORY, See `helm'." ;; 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)) @@ -2515,8 +3275,10 @@ For ANY-PRESELECT ANY-RESUME ANY-KEYMAP ANY-DEFAULT ANY-HISTORY, See `helm'." (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: ") + ;; 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)) @@ -2524,7 +3286,8 @@ For ANY-PRESELECT ANY-RESUME ANY-KEYMAP ANY-DEFAULT ANY-HISTORY, See `helm'." (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." +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)) @@ -2532,24 +3295,15 @@ This can be useful for example for quietly writing a complex regexp." (setq helm-pattern "")) (message (if helm-suspend-update-flag "Helm update suspended!" - "Helm update re-enabled!")))) + "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) -(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) +(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) @@ -2561,26 +3315,6 @@ This can be useful for example for quietly writing a complex regexp." (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. @@ -2610,7 +3344,7 @@ map)." [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)) + do (define-key map k 'ignore)) map)) (define-minor-mode helm--remap-mouse-mode @@ -2625,19 +3359,29 @@ WARNING: Do not use this mode yourself, it is internal to helm." (setq helm--remap-mouse-mode-map nil))) (put 'helm--remap-mouse-mode 'helm-only t) -;; Core: clean up +;; 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)) + (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 @@ -2657,6 +3401,10 @@ WARNING: Do not use this mode yourself, it is internal to helm." ;; 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)) @@ -2671,7 +3419,7 @@ WARNING: Do not use this mode yourself, it is internal to helm." (delete-minibuffer-contents))))) -;;; Core: input handling +;;; Input handling ;; ;; (defun helm-check-minibuffer-input () @@ -2697,28 +3445,10 @@ WARNING: Do not use this mode yourself, it is internal to helm." helm-exit-idle-delay nil (lambda () (setq helm--in-update nil)))) -(add-hook 'helm-after-update-hook #'helm--reset-update-flag) - - -;;; 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)) +;; (add-hook 'helm-after-update-hook #'helm--reset-update-flag) -;; Core: all candidates +;; All candidates (defun helm-get-candidates (source) "Retrieve and return the list of candidates from SOURCE." @@ -2740,18 +3470,21 @@ Helm plug-ins are realized by this function." (if candidate-proc ;; Calling `helm-interpret-value' with no ;; SOURCE arg force the use of `funcall' - ;; and not `helm-funcall-with-source'. + ;; 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)))) - (when (and (processp candidates) (not candidate-proc)) - (warn "Candidates function `%s' should be called in a `candidates-process' attribute" - candidate-fn)) + (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 (funcall notify-error cfn-error)) + (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 @@ -2762,16 +3495,17 @@ Helm plug-ins are realized by this function." (equal candidates '(""))) nil) ((listp candidates) - ;; Transform candidates with `candidate-transformer' functions if - ;; some, otherwise return 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")) - inhibit-quit) + (let ((catch-sym (make-symbol "input"))) `(with-local-quit (catch ',catch-sym (let ((throw-on-input ',catch-sym)) @@ -2794,39 +3528,42 @@ Cache the candidates if there is no cached value yet." helm-async-processes) (set-process-filter candidates 'helm-output-filter) (setq candidates nil)) - ((not (assoc 'volatile source)) + ((not (assq 'volatile source)) (puthash name candidates helm-candidate-cache))) candidates)))) -;;; Core: candidate transformers +;;; 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) + (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-funcall-with-source source it candidates 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 CANDIDATE in SOURCE." + "Execute `filter-one-by-one' function(s) on real value of 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))) + (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 when pattern is empty." +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 @@ -2846,32 +3583,36 @@ functions if some, otherwise return 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 + (setq candidates (helm-apply-functions-from-source source 'mapcar - (lambda (cand_) - (if (consp cand_) + (lambda (cand) + (if (consp cand) ;; override DISPLAY from candidate-transformer - (cons (funcall it (cdr cand_)) (cdr cand_)) - (cons (funcall it cand_) cand_))) + (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." +`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 - (helm--initialize-one-by-one-candidates candidates source) source) + candidates source) source process-p) source)) -;; Core: narrowing candidates +;; Narrowing candidates (defun helm-candidate-number-limit (source) "Apply candidate-number-limit attribute value. This overrides `helm-candidate-number-limit' variable. @@ -2880,7 +3621,9 @@ 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) + ;; 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) @@ -2897,7 +3640,7 @@ cons cell." (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) + (helm-apply-functions-from-source source it pattern) pattern)) (defun helm-default-match-function (candidate) @@ -2965,7 +3708,7 @@ This function is used with sources built with `helm-source-sync'." ;; 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, + ;; 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) @@ -2991,7 +3734,12 @@ CANDIDATE. Contiguous matches get a coefficient of 2." 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)) + (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))) @@ -3004,14 +3752,16 @@ CANDIDATE. Contiguous matches get a coefficient of 2." pat-lookup str-lookup :test 'equal)) 2))))) -(defun helm-fuzzy-matching-default-sort-fn (candidates _source &optional use-real) +(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'. Ties in scores are sorted by -length of the candidates. Set USE-REAL to non-`nil' to sort on the -real part." +`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))) @@ -3020,12 +3770,16 @@ real part." ;; 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)) + (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 @@ -3043,9 +3797,22 @@ real part." (scr1 (car data1)) (scr2 (car data2))) (cond ((= scr1 scr2) - (< len1 len2)) + (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)) @@ -3083,30 +3850,30 @@ to the matching method in use." ;; 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))) + (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 - (split-string helm-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) - (add-text-properties + (helm-add-face-text-properties (match-beginning 0) (match-end 0) - '(face helm-match))) + 'helm-match)) (goto-char (point-min))) ;; Fuzzy matches (literal patterns). else do (when (search-forward p nil t) - (add-text-properties + (helm-add-face-text-properties (match-beginning 0) (match-end 0) - '(face helm-match)))))) + 'helm-match))))) (invalid-regexp nil)) ;; Now replace the original match-part with the part ;; with face properties added. @@ -3119,6 +3886,10 @@ See `helm-fuzzy-default-highlight-match'." (cl-loop for c in candidates collect (funcall helm-fuzzy-matching-highlight-fn c))) + +;;; Matching candidates +;; +;; (defun helm-match-functions (source) (let ((matchfns (or (assoc-default 'match source) (assoc-default 'match-strict source) @@ -3137,29 +3908,6 @@ 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) @@ -3211,7 +3959,7 @@ and `helm-pattern'." (save-current-buffer (let ((matchfns (helm-match-functions source)) (matchpartfn (assoc-default 'match-part source)) - (helm-source-name (assoc-default 'name source)) + (helm--source-name (assoc-default 'name source)) (helm-current-source source) (limit (helm-candidate-number-limit source)) (helm-pattern (helm-process-pattern-transformer @@ -3220,17 +3968,28 @@ and `helm-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 + ;; 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)) + ;; 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) @@ -3241,20 +4000,22 @@ and `helm-pattern'." (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))))) + (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." @@ -3267,33 +4028,77 @@ and `helm-pattern'." (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))) -;;; Core: helm-update +;;; Case fold search +;; ;; -(defun helm-update (&optional preselect source) +(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))) + + +;;; 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." +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'. - (with-helm-window - (when helm-onewindow-p (delete-other-windows))) + (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-get-sources) + (cl-loop for src in helm-sources when (helm-update-source-p src) collect src)) ;; When no sources to update erase buffer @@ -3303,30 +4108,42 @@ to a particular place after finishing update." ;; 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 (helm--collect-matches sources))) + (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 + (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)))) - (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)) + 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) - (helm-preselect preselect source)) - (setq helm-force-updating-p nil)) + (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 need updating or not." + "Whether SOURCE needs updating or not." (let ((len (string-width - (if (or (assoc 'matchplugin source) - (null (assoc 'no-matchplugin source))) + (if (assq 'multimatch source) ;; Don't count spaces entered when using ;; multi-match. (replace-regexp-in-string " " "" helm-pattern) @@ -3334,21 +4151,29 @@ to a particular place after finishing update." (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)) + (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 (&optional without-hook) +(defun helm--update-move-first-line () "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)) + (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))) -(defun helm-force-update (&optional preselect) +(cl-defun helm-force-update (&optional preselect (recenter t)) "Force recalculation and update of candidates. Unlike `helm-update', this function re-evaluates `init' and @@ -3356,18 +4181,21 @@ Unlike `helm-update', this function re-evaluates `init' and 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)))) +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." @@ -3378,38 +4206,169 @@ PRESELECT, if specified." (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) + ;; 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-funcall-with-source source it))) + (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) - "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." +(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))) + (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 (point-at-eol) + (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 (point-at-eol) 'helm-cand-num 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 @@ -3418,7 +4377,7 @@ if SOURCE has header-name attribute." (helm-insert-header name (helm-aif (assoc-default 'header-name source) - (helm-funcall-with-source source it name))))) + (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. @@ -3446,7 +4405,7 @@ this additional info after the source name by overlay." (insert "\n")) -;;; Core: async process +;;; Async process ;; (defun helm-output-filter (process output-string) "The `process-filter' function for helm async sources." @@ -3473,7 +4432,7 @@ this additional info after the source name by overlay." (cl-dolist (candidate (helm-transform-candidates (helm-output-filter--collect-candidates (split-string output-string "\n") - (assoc 'incomplete-line source)) + (assq 'incomplete-line source)) source t)) (setq candidate (helm--maybe-process-filter-one-by-one-candidate candidate source)) @@ -3481,13 +4440,16 @@ this additional info after the source name by overlay." (let ((start (point))) (helm-insert-candidate-separator) (helm-insert-match candidate 'insert-before-markers - (1+ (cdr (assoc 'item-count source)))) + (1+ (cdr (assq 'item-count source))) + 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))) + (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) @@ -3517,14 +4479,15 @@ this additional info after the source name by overlay." 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))))) + (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. @@ -3567,7 +4530,7 @@ function." (delete-process process)) -;;; Core: action +;;; Actions ;; (defun helm-execute-selection-action () "Execute current action." @@ -3575,8 +4538,10 @@ function." ;; 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))) + (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 @@ -3590,7 +4555,8 @@ If PRESERVE-SAVED-ACTION is non-`nil', then save the 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) + (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))) @@ -3598,8 +4564,8 @@ If PRESERVE-SAVED-ACTION is non-`nil', then save the action." (setq selection (helm-coerce-selection (or selection helm-saved-selection - (helm-get-selection) - (and (assoc 'accept-empty source) "")) + (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)))) @@ -3608,7 +4574,7 @@ If PRESERVE-SAVED-ACTION is non-`nil', then save the action." "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) + (helm-apply-functions-from-source source it selection) selection)) (defun helm-get-default-action (action) @@ -3617,50 +4583,81 @@ Coerce source with coerce function." (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 - (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))))) + (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) - (set-window-buffer (get-buffer-window helm-buffer) helm-action-buffer) + (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)" "TAB:BackToCands RET/f1/f2/fn:NthAct") + :mode-line '("Action(s)" "\\\\[helm-select-action]:BackToCands RET/f1/f2/fn:NthAct") :candidate-transformer (lambda (candidates) (cl-loop for (i . j) in candidates @@ -3679,7 +4676,7 @@ If action buffer is selected, back to the helm buffer." (helm-initialize-overlays helm-action-buffer))) -;; Core: selection +;; Selection of candidates (defun helm-display-source-at-screen-top-maybe (unit) "Display source at the top of screen when UNIT value is 'source. @@ -3692,7 +4689,7 @@ Returns nil for any other value of UNIT." "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." +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. @@ -3711,13 +4708,22 @@ DIRECTION is either 'next or 'previous." -1 1))))) (defun helm-display-mode-line (source &optional force) - "Setup mode-line and header-line for `helm-buffer'." + "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 (eq (cdr (assq 'follow source)) 1) " (HF)")) + (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 @@ -3727,25 +4733,37 @@ DIRECTION is either 'next or 'previous." ;; 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 + (" " 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 (helm-show-candidate-number - (car-safe helm-mode-line-string))) - " " helm--mode-line-string-real " " mode-line-end-spaces) + '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) @@ -3757,9 +4775,9 @@ DIRECTION is either 'next or 'previous." (helm--set-header-line)) (helm-display-header-line (let ((hlstr (helm-interpret-value - (and (listp source) - (assoc-default 'header-line source)) - source)) + (and (listp source) + (assoc-default 'header-line source)) + source)) (endstr (make-string (window-width) ? ))) (setq header-line-format (propertize (concat " " hlstr endstr) @@ -3768,30 +4786,64 @@ DIRECTION is either 'next or 'previous." (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-quote helm--prompt) cont) - '(space :width left-fringe) + '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 " ")) - (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) + (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. @@ -3805,8 +4857,19 @@ 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))) + (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-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) @@ -3823,9 +4886,11 @@ it is \"Candidate\(s\)\" by default." (format "[%s %s]" (helm-get-candidate-number 'in-current-source) cand-name)) - 'face 'helm-candidate-number))))) + 'face (if helm-suspend-update-flag + 'helm-candidate-number-suspended + 'helm-candidate-number)))))) -(cl-defun helm-move-selection-common (&key where direction) +(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: @@ -3855,6 +4920,8 @@ Key arg DIRECTION can be one of: (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)) @@ -3862,8 +4929,9 @@ Key arg DIRECTION can be one of: (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-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))))) @@ -3936,12 +5004,15 @@ Key arg DIRECTION can be one of: (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))) + (helm-aif (helm-get-next-header-pos) + (progn (goto-char it) (forward-line -2)) + (goto-char (point-max)))) (defun helm-move--beginning-of-source () - (goto-char (helm-get-previous-header-pos)) - (forward-line 1)) + (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) @@ -3962,12 +5033,15 @@ Key arg DIRECTION can be one of: (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))))) + (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 @@ -4051,19 +5125,31 @@ next source)." (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." +(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)) + (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)) + (eq last-command 'helm-execute-persistent-action) + in-follow-mode) (if (> arg 0) - (helm-next-line 1) - (helm-previous-line 1))) - (helm-execute-persistent-action))) + (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." @@ -4077,11 +5163,14 @@ next source)." (with-helm-alive-p (helm--follow-action -1))) (put 'helm-follow-action-backward 'helm-only t) -(defun helm-mark-current-line (&optional resumep) +(defun helm-mark-current-line (&optional resumep nomouse) "Move `helm-selection-overlay' to current line. -Note that this is unrelated to visible marks used for marking +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-window + (with-helm-buffer (when resumep (goto-char helm-selection-point)) (move-overlay @@ -4096,8 +5185,9 @@ candidates." header-pos (point-max))) (1+ (point-at-eol)))) - (setq helm-selection-point (overlay-start helm-selection-overlay))) - (helm-follow-execute-persistent-action-maybe)) + (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. @@ -4112,13 +5202,14 @@ don't exit and send message 'no match'." (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 + (let* ((src (helm-get-current-source)) + (empty-buffer-p (with-current-buffer helm-buffer (eq (point-min) (point-max)))) - (sel (helm-get-selection)) + (sel (helm-get-selection nil nil src)) (unknown (and (not empty-buffer-p) (string= (get-text-property 0 'display - (helm-get-selection nil 'withprop)) + (helm-get-selection nil 'withprop src)) "[?]")))) (cond ((and (or empty-buffer-p unknown) (eq minibuffer-completion-confirm 'confirm)) @@ -4173,8 +5264,10 @@ don't exit and send message 'no match'." (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)) + (progn + (message "[Display not ready]") + (sit-for 0.5) (message nil) + (helm-update)) (helm-exit-minibuffer)))) (put 'helm-maybe-exit-minibuffer 'helm-only t) @@ -4259,14 +5352,6 @@ to a list of forms.\n\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) @@ -4280,7 +5365,7 @@ to a list of forms.\n\n") (put 'helm-enable-or-switch-to-debug 'helm-only t) -;; Core: misc +;; Misc (defun helm-kill-buffer-hook () "Remove tick entry from `helm-tick-hash' and remove buffer from `helm-buffers' when killing a buffer." @@ -4291,15 +5376,22 @@ to a list of forms.\n\n") (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 + "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 (and helm-force-updating-p source) + (if source (helm-goto-source source) (goto-char (point-min)) (forward-line 1)) @@ -4318,8 +5410,10 @@ want to preselect." (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 (helm-get-current-source)) + (helm-display-mode-line (or source (helm-get-current-source))) (helm-log-run-hook 'helm-after-preselection-hook))) (defun helm-delete-current-selection () @@ -4346,27 +5440,24 @@ want to preselect." (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." +(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 1)) - (or (eq (point-at-bol) (point-at-eol)) - (helm-pos-header-line-p) - (eobp))))) + (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." - (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))))) + (helm-end-of-source-1 -1 at-point)) -(defun helm-edit-current-selection-internal (func) +(defun helm--edit-current-selection-internal (func) (with-helm-window (forward-line 0) (let ((realvalue (get-text-property (point) 'helm-realvalue)) @@ -4377,7 +5468,9 @@ want to preselect." (put-text-property (point) (point-at-eol) 'helm-realvalue realvalue)) (and multiline - (put-text-property (point) (point-at-eol) + (put-text-property (point) + (or (helm-get-next-candidate-separator-pos) + (point-max)) 'helm-multiline multiline)) (helm-mark-current-line)))) @@ -4385,7 +5478,7 @@ want to preselect." "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 + `(helm--edit-current-selection-internal (lambda () ,@forms))) (defun helm--delete-minibuffer-contents-from (from-str) @@ -4414,111 +5507,14 @@ When at the end of minibuffer, deletes all." (helm--delete-minibuffer-contents-from str))) -;;; Plugins (Deprecated in favor of helm-types) +;;; helm-source-in-buffer. ;; -;; 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'. + "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. 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. +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. @@ -4534,18 +5530,13 @@ 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 +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. @@ -4554,25 +5545,17 @@ 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. +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. +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. @@ -4582,8 +5565,8 @@ 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." +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) @@ -4622,7 +5605,7 @@ To customize `helm-candidates-in-buffer' behavior, use `search', (defun helm-search-from-candidate-buffer (pattern get-line-fn search-fns limit start-point match-part-fn source) - (let (buffer-read-only) + (let ((inhibit-read-only t)) (helm--search-from-candidate-buffer-1 (lambda () (cl-loop with hash = (make-hash-table :test 'equal) @@ -4677,18 +5660,19 @@ To customize `helm-candidates-in-buffer' behavior, use `search', and collect cand)))))) (defun helm-search-match-part (candidate pattern) - "Match PATTERN only on part of CANDIDATE returned by MATCH-PART-FN. + "Match PATTERN only on match-part property value of CANDIDATE. + 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)) +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 (split-string pattern) always + (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))) @@ -4726,96 +5710,140 @@ this function is always called." (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. +(defun helm-candidate-buffer (&optional buffer-spec) + "Register and return a buffer storing candidates of current source. -Acceptable values of CREATE-OR-BUFFER: +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. -- nil (omit) - Only return the candidates buffer. -- a buffer - Register a buffer as a candidates buffer. -- 'global +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*\". -- other non-`nil' value + 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\"." - (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'. + 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." +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 ((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)) + (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))) ;;; Resplit helm window @@ -4825,37 +5853,43 @@ Returns the resulting buffer." "Toggle resplit helm window, vertically or horizontally." (interactive) (with-helm-alive-p - (when helm-prevent-escaping-from-minibuffer - (helm-prevent-switching-other-window :enabled nil)) - (unwind-protect - (with-helm-window - (if (or helm-full-frame (one-window-p t)) - (message "Error: Attempt to resplit a single window") - (let ((before-height (window-height))) - (delete-window) - (set-window-buffer - (select-window - (if (= (window-height) before-height) ; initial split was horizontal. - ;; Split window vertically with `helm-buffer' placed - ;; on the good side according to actual value of - ;; `helm-split-window-default-side'. - (prog1 - (cond ((or (eq helm-split-window-default-side 'above) - (eq helm-split-window-default-side 'left)) - (split-window - (selected-window) nil 'above)) - (t (split-window-vertically))) - (setq helm-split-window-state 'vertical)) - ;; Split window vertically, same comment as above. - (setq helm-split-window-state 'horizontal) - (cond ((or (eq helm-split-window-default-side 'left) - (eq helm-split-window-default-side 'above)) - (split-window (selected-window) nil 'left)) - (t (split-window-horizontally))))) - helm-buffer))) - (setq helm--window-side-state (helm--get-window-side-state))) - (when helm-prevent-escaping-from-minibuffer - (helm-prevent-switching-other-window :enabled t))))) + (if (= (length (window-list nil 1)) 2) + (progn + (when helm-prevent-escaping-from-minibuffer + (helm-prevent-switching-other-window :enabled nil)) + (unwind-protect + (with-helm-window + (cond ((or helm-full-frame (one-window-p t)) + (user-error "Attempt to resplit a single window")) + ((helm-action-window) + (user-error "Can't resplit while selecting actions")) + (t + (let ((before-height (window-height))) + (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. @@ -4881,47 +5915,76 @@ If N is positive enlarge, if negative narrow." (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 (and helm-full-frame (one-window-p t)) - (error "Error: Can't swap windows in a single window") - (let* ((w1 (helm-window)) - (split-state (eq helm-split-window-state 'horizontal)) - (w1size (window-total-size w1 split-state)) - (b1 (window-buffer w1)) ; helm-buffer - (s1 (window-start w1)) - (cur-frame (window-frame w1)) - (w2 (with-selected-window (helm-window) - ;; Don't try to display helm-buffer - ;; in a dedicated window. - (get-window-with-predicate - (lambda (w) (not (window-dedicated-p w))) - 1 cur-frame))) - (w2size (window-total-size w2 split-state)) - (b2 (window-buffer w2)) ; probably helm-current-buffer - (s2 (window-start w2)) - resize) - (with-selected-frame (window-frame w1) - (helm-replace-buffer-in-window w1 b1 b2) - (helm-replace-buffer-in-window w2 b2 b1) - (setq resize - (cond ( ;; helm-window is smaller than other window. - (< w1size w2size) - (- (- (max w2size w1size) - (min w2size w1size)))) - ( ;; helm-window is larger than other window. - (> w1size w2size) - (- (max w2size w1size) - (min w2size w1size))) - ( ;; windows have probably same size. - t nil))) - ;; Maybe resize the window holding helm-buffer. - (and resize (window-resize w2 resize split-state)) - (set-window-start w1 s2 t) - (set-window-start w2 s1 t)) - (setq helm--window-side-state (helm--get-window-side-state)))))) + (if (= (length (window-list nil 1)) 2) + (cond ((and helm-full-frame (one-window-p t)) + (user-error "Can't swap windows in a single window")) + ((helm-action-window) + (user-error "Can't resplit while selecting actions")) + (t + (let* ((w1 (helm-window)) + (split-state (eq helm-split-window-state 'horizontal)) + (w1size (window-total-size w1 split-state)) + (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 () @@ -4944,16 +6007,17 @@ Possible values are 'left 'right 'below or 'above." ;; 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)) + (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)) @@ -4967,30 +6031,27 @@ Possible values are 'left 'right 'below or 'above." (error "Error in `helm-select-nth-action'")))) (defun helm-execute-selection-action-at-nth (linum) - "Allow to execute default action on candidate at 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))) - -;; 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)) - + +;;; 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 'persistent-action) split-onewindow) +(cl-defun helm-execute-persistent-action (&optional attr split-onewindow) "Perform the associated action ATTR without quitting helm. -ATTR default is 'persistent-action', but it can be anything else. +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 @@ -4998,134 +6059,142 @@ 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)))))))) + (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 - (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)))))) + (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))) - (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))) + (prog1 + (select-window + (setq minibuffer-scroll-window + (helm-persistent-action-display-window split-onewindow))) + (helm-log "Selected window is %S" minibuffer-scroll-window))) + +;;; 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 () - "Scroll other window (not *Helm* window) downward." - (interactive) - (with-helm-alive-p (helm-other-window-base 'scroll-down))) +(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 () - "`recenter-top-bottom' in other window (not *Helm* window)." - (interactive) - (with-helm-alive-p (helm-other-window-base 'recenter-top-bottom 'noscroll))) +(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 () - "`helm-reposition-window' in other window (not *Helm* window)." - (interactive) - (with-helm-alive-p (helm-other-window-base 'reposition-window 'noscroll))) +(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) - ;; Utility: Visible Mark @@ -5135,114 +6204,159 @@ Argument ACTION, when present, is used as second argument of `display-buffer'." (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)) + (cl-loop for o in (overlays-at (point)) + when (overlay-get o 'visible-mark) + 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)))))) + (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 (helm-get-current-source))) + (overlay-put o 'source (assoc-default 'name 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) + (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)))) + (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") - (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))))))) + (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 () +(defun helm-file-completion-source-p (&optional source) "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))))) + (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 () - "Mark all visible unmarked candidates in current source." - (interactive) +(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 - (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)))))) + (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) @@ -5255,20 +6369,23 @@ Argument ACTION, when present, is used as second argument of `display-buffer'." (helm-display-mode-line (helm-get-current-source))))) (put 'helm-unmark-all 'helm-only t) -(defun helm-toggle-all-marks () +(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" - (interactive) +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))))) + (helm-mark-all all))))) (put 'helm-toggle-all-marks 'helm-only t) -(defun helm--compute-marked (real source wildcard) +(defun helm--compute-marked (real source &optional wildcard) (let* ((coerced (helm-coerce-selection real source)) (wilds (and wildcard (condition-case nil @@ -5286,26 +6403,44 @@ visible or invisible in all sources of current helm session" (setq coerced nil)) (or wilds (and coerced (list coerced))))) -(cl-defun helm-marked-candidates (&key with-wildcard) +(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." +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 ((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))))) + (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)) @@ -5323,7 +6458,8 @@ selection. When key WITH-WILDCARD is specified, expand it." (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))) + (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)) @@ -5340,7 +6476,7 @@ selection. When key WITH-WILDCARD is specified, expand it." (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) +(add-hook 'helm-after-update-hook 'helm-revive-visible-mark) (defun helm-next-point-in-list (curpos points &optional prev) (cond @@ -5431,6 +6567,11 @@ display values." ;;; 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. @@ -5439,92 +6580,108 @@ This mode is source local, i.e It apply on current source only. 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. +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 "p") + (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)) - (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))) + (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-attrset 'follow (if enabled -1 1) src) - (setq helm-follow-mode (not enabled)) + (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 + (if (helm-follow-mode-p src) "enabled" "disabled")) - (helm-display-mode-line src t)) - (unless helm-follow-mode-persistent - (and sym (set sym (remove (assq 'follow src) src))))) + (helm-display-mode-line src t))) (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 () +(defun helm-follow-execute-persistent-action-maybe (&optional delay) "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))))) +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))))) ;;; 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)))) + (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. @@ -5543,7 +6700,11 @@ See `fit-window-to-buffer' for more infos." (remove-hook 'helm-window-configuration-hook 'helm--autoresize-hook))) (defun helm-help () - "Help of `helm'." + "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 @@ -5566,13 +6727,14 @@ It may appear after first results popup in helm buffer.")) (with-helm-alive-p (with-helm-buffer (setq truncate-lines (not truncate-lines)) - (helm-update (regexp-quote (helm-get-selection nil t)))))) + (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 cl-functions obsolete) +;; byte-compile-warnings: (not obsolete) ;; coding: utf-8 ;; indent-tabs-mode: nil ;; End: diff --git a/elpa/helm-descbinds-20151019.230/helm-descbinds-autoloads.el b/elpa/helm-descbinds-20151019.230/helm-descbinds-autoloads.el deleted file mode 100644 index 5f906d0a..00000000 --- a/elpa/helm-descbinds-20151019.230/helm-descbinds-autoloads.el +++ /dev/null @@ -1,46 +0,0 @@ -;;; helm-descbinds-autoloads.el --- automatically extracted autoloads -;; -;;; Code: -(add-to-list 'load-path (or (file-name-directory #$) (car load-path))) - -;;;### (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) - -;;;*** - -;; Local Variables: -;; version-control: never -;; no-byte-compile: t -;; no-update-autoloads: t -;; End: -;;; helm-descbinds-autoloads.el ends here diff --git a/elpa/helm-descbinds-20151019.230/helm-descbinds-pkg.el b/elpa/helm-descbinds-20151019.230/helm-descbinds-pkg.el deleted file mode 100644 index b8225d97..00000000 --- a/elpa/helm-descbinds-20151019.230/helm-descbinds-pkg.el +++ /dev/null @@ -1 +0,0 @@ -(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")) diff --git a/elpa/helm-descbinds-20151019.230/helm-descbinds.el b/elpa/helm-descbinds-20151019.230/helm-descbinds.el deleted file mode 100644 index 20960318..00000000 --- a/elpa/helm-descbinds-20151019.230/helm-descbinds.el +++ /dev/null @@ -1,297 +0,0 @@ -;;; helm-descbinds.el --- Yet Another `describe-bindings' with `helm'. - -;; Copyright (C) 2008, 2009, 2010 Taiki SUGAWARA -;; Copyright (C) 2012, 2013 Michael Markert -;; Copyright (C) 2013 Daniel Hackney - -;; Author: Taiki SUGAWARA -;; 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 -;; * helm-descbinds.el: Version 1.08 -;; Merge Daniel Hackney's helm-descbinds minor mode. -;; Several bugfixes. -;; -;; 2012-03-18 Michael Markert -;; * helm-descbinds.el: Version 1.07 -;; make strings bound to keys insertable -;; -;; 2012-03-18 Michael Markert -;; * helm-descbinds.el: Version 1.06 -;; port to helm -;; -;; 2010-02-05 Taiki SUGAWARA -;; -;; * descbinds-anything.el: Version 1.05 -;; bug fix. -;; -;; 2010-02-02 UTC Taiki SUGAWARA -;; -;; * descbinds-anything.el: Version 1.04 -;; add sorting feature. -;; separete sorce creation function. -;; add persistent action. -;; -;; 2009-03-29 UTC Taiki SUGAWARA -;; -;; * descbinds-anything.el: Version 1.03 -;; fix typo. -;; -;; 2008-11-16 UTC Taiki SUGAWARA -;; -;; * descbinds-anything.el: Version 1.02 -;; bound `indent-tabs-mode` to t for nil environment. -;; -;; 2008-11-16 UTC Taiki SUGAWARA -;; -;; * 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 diff --git a/elpa/helm-descbinds-20160108.1947/helm-descbinds-pkg.el b/elpa/helm-descbinds-20160108.1947/helm-descbinds-pkg.el deleted file mode 100644 index a58f1c39..00000000 --- a/elpa/helm-descbinds-20160108.1947/helm-descbinds-pkg.el +++ /dev/null @@ -1 +0,0 @@ -(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")) diff --git a/elpa/helm-descbinds-20160108.1947/helm-descbinds-autoloads.el b/elpa/helm-descbinds-20180429.1456/helm-descbinds-autoloads.el similarity index 81% rename from elpa/helm-descbinds-20160108.1947/helm-descbinds-autoloads.el rename to elpa/helm-descbinds-20180429.1456/helm-descbinds-autoloads.el index 36088bbe..30cbe3c2 100644 --- a/elpa/helm-descbinds-20160108.1947/helm-descbinds-autoloads.el +++ b/elpa/helm-descbinds-20180429.1456/helm-descbinds-autoloads.el @@ -1,15 +1,19 @@ ;;; helm-descbinds-autoloads.el --- automatically extracted autoloads ;; ;;; Code: -(add-to-list 'load-path (or (file-name-directory #$) (car load-path))) + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + -;;;### (autoloads nil "helm-descbinds" "helm-descbinds.el" (22215 -;;;;;; 7793 0 0)) +;;;### (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 command `helm-descbinds-mode' for a description of this minor mode. +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'.") @@ -54,11 +58,14 @@ 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"))) + ;;;*** ;; Local Variables: ;; version-control: never ;; no-byte-compile: t ;; no-update-autoloads: t +;; coding: utf-8 ;; End: ;;; helm-descbinds-autoloads.el ends here diff --git a/elpa/helm-descbinds-20180429.1456/helm-descbinds-pkg.el b/elpa/helm-descbinds-20180429.1456/helm-descbinds-pkg.el new file mode 100644 index 00000000..ffe94d1e --- /dev/null +++ b/elpa/helm-descbinds-20180429.1456/helm-descbinds-pkg.el @@ -0,0 +1,2 @@ +;;; -*- 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.taiki@gmail.com")) :maintainer '("Taiki SUGAWARA" . "buzz.taiki@gmail.com") :url "https://github.com/emacs-helm/helm-descbinds") diff --git a/elpa/helm-descbinds-20160108.1947/helm-descbinds.el b/elpa/helm-descbinds-20180429.1456/helm-descbinds.el similarity index 86% rename from elpa/helm-descbinds-20160108.1947/helm-descbinds.el rename to elpa/helm-descbinds-20180429.1456/helm-descbinds.el index e0456489..bbc524bc 100644 --- a/elpa/helm-descbinds-20160108.1947/helm-descbinds.el +++ b/elpa/helm-descbinds-20180429.1456/helm-descbinds.el @@ -3,13 +3,13 @@ ;; Copyright (C) 2008, 2009, 2010 Taiki SUGAWARA ;; Copyright (C) 2012, 2013 Michael Markert ;; Copyright (C) 2013 Daniel Hackney -;; Copyright (C) 2015 Michael Heerdegen +;; Copyright (C) 2015, 2016 Michael Heerdegen ;; Author: Taiki SUGAWARA ;; URL: https://github.com/emacs-helm/helm-descbinds -;; Package-Version: 20160108.1947 +;; Package-Version: 20180429.1456 ;; Keywords: helm, help -;; Version: 1.10 +;; Version: 1.12 ;; Package-Requires: ((helm "1.5")) ;; This file is free software; you can redistribute it and/or modify @@ -32,7 +32,7 @@ ;; 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. @@ -107,15 +107,6 @@ This function will be called with two arguments KEY and BINDING." "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) @@ -125,8 +116,11 @@ This function will be called with two arguments KEY and BINDING." :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))) + (progn + (advice-add 'describe-bindings :override #'helm-descbinds) + (global-unset-key (kbd " C-h"))) + (advice-remove 'describe-bindings #'helm-descbinds) + (global-set-key (kbd " C-h") 'help-for-help))) ;;;###autoload (defun helm-descbinds-install () @@ -193,7 +187,10 @@ This function will be called with two arguments KEY and BINDING." ((stringp x) (insert x)) ((commandp x) - (run-at-time 0.01 nil (lambda (command) (call-interactively command)) 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." @@ -219,23 +216,21 @@ This function will be called with two arguments KEY and BINDING." 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)) + (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 (equal (cdr-safe cand) "Prefix Command") - `(("helm-descbinds this prefix" . ,(lambda (cand) (interactive) - (run-with-timer - 0 nil - #'describe-bindings (kbd (car cand)))))) - actions)) + (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 @@ -247,10 +242,17 @@ Provide a useful behavior for prefix commands." (< (helm-descbinds-order-section a) (helm-descbinds-order-section b)))))) +(defclass helm-descbinds-source-class (helm-source-sync) ()) + (defun helm-descbinds-source (name candidates) - `((name . ,name) - (candidates . ,candidates) - ,@helm-descbinds-source-template)) + (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) diff --git a/elpa/helm-git-20120630.1403/helm-git-autoloads.el b/elpa/helm-git-20120630.1403/helm-git-autoloads.el deleted file mode 100644 index a5dd6de9..00000000 --- a/elpa/helm-git-20120630.1403/helm-git-autoloads.el +++ /dev/null @@ -1,18 +0,0 @@ -;;; helm-git-autoloads.el --- automatically extracted autoloads -;; -;;; Code: - - -;;;### (autoloads nil nil ("helm-git-pkg.el" "helm-git.el") (21792 -;;;;;; 6079 675972 0)) - -;;;*** - -(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 diff --git a/elpa/helm-git-20120630.1403/helm-git-pkg.el b/elpa/helm-git-20120630.1403/helm-git-pkg.el deleted file mode 100644 index cbbddda0..00000000 --- a/elpa/helm-git-20120630.1403/helm-git-pkg.el +++ /dev/null @@ -1 +0,0 @@ -(define-package "helm-git" "20120630.1403" "Helm extension for Git." (quote nil)) diff --git a/elpa/helm-git-20120630.2103/helm-git-autoloads.el b/elpa/helm-git-20120630.2103/helm-git-autoloads.el new file mode 100644 index 00000000..8f7f49f6 --- /dev/null +++ b/elpa/helm-git-20120630.2103/helm-git-autoloads.el @@ -0,0 +1,22 @@ +;;; helm-git-autoloads.el --- automatically extracted autoloads +;; +;;; Code: + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + + +;;;### (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-"))) + +;;;*** + +;; Local Variables: +;; version-control: never +;; no-byte-compile: t +;; no-update-autoloads: t +;; coding: utf-8 +;; End: +;;; helm-git-autoloads.el ends here diff --git a/elpa/helm-git-20120630.2103/helm-git-pkg.el b/elpa/helm-git-20120630.2103/helm-git-pkg.el new file mode 100644 index 00000000..2439bf3b --- /dev/null +++ b/elpa/helm-git-20120630.2103/helm-git-pkg.el @@ -0,0 +1,2 @@ +;;; -*- no-byte-compile: t -*- +(define-package "helm-git" "20120630.2103" "Helm extension for Git." 'nil :commit "cb96a52b5aecadd3c27aba7749d14e43ab128d55" :keywords '("helm" "git") :authors '(("Marian Schubert" . "marian.schubert@gmail.com")) :maintainer '("Marian Schubert" . "marian.schubert@gmail.com") :url "https://github.com/maio/helm-git") diff --git a/elpa/helm-git-20120630.1403/helm-git.el b/elpa/helm-git-20120630.2103/helm-git.el similarity index 99% rename from elpa/helm-git-20120630.1403/helm-git.el rename to elpa/helm-git-20120630.2103/helm-git.el index d2a23960..aeaf389f 100644 --- a/elpa/helm-git-20120630.1403/helm-git.el +++ b/elpa/helm-git-20120630.2103/helm-git.el @@ -4,7 +4,7 @@ ;; Author : Marian Schubert ;; URL : https://github.com/maio/helm-git -;; Package-Version: 20120630.1403 +;; Package-Version: 20120630.2103 ;; Version : 1.1 ;; Keywords : helm, git diff --git a/elpa/helm-git-readme.txt b/elpa/helm-git-readme.txt deleted file mode 100644 index fd9c7077..00000000 --- a/elpa/helm-git-readme.txt +++ /dev/null @@ -1,6 +0,0 @@ -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. diff --git a/elpa/helm-gtags-20160202.503/helm-gtags-pkg.el b/elpa/helm-gtags-20160202.503/helm-gtags-pkg.el deleted file mode 100644 index ecfc74d8..00000000 --- a/elpa/helm-gtags-20160202.503/helm-gtags-pkg.el +++ /dev/null @@ -1 +0,0 @@ -(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") diff --git a/elpa/helm-gtags-20160202.503/helm-gtags-autoloads.el b/elpa/helm-gtags-20170116.529/helm-gtags-autoloads.el similarity index 88% rename from elpa/helm-gtags-20160202.503/helm-gtags-autoloads.el rename to elpa/helm-gtags-20170116.529/helm-gtags-autoloads.el index 7d07abfa..68e6e539 100644 --- a/elpa/helm-gtags-20160202.503/helm-gtags-autoloads.el +++ b/elpa/helm-gtags-20170116.529/helm-gtags-autoloads.el @@ -1,10 +1,12 @@ ;;; helm-gtags-autoloads.el --- automatically extracted autoloads ;; ;;; Code: -(add-to-list 'load-path (or (file-name-directory #$) (car load-path))) + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + -;;;### (autoloads nil "helm-gtags" "helm-gtags.el" (22215 7814 0 -;;;;;; 0)) +;;;### (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" "\ @@ -47,6 +49,11 @@ Show tagnames which are referenced in this function and jump to it. \(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 @@ -138,11 +145,14 @@ the mode if ARG is omitted or nil, and toggle it if ARG is `toggle'. \(fn &optional ARG)" t nil) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-gtags" '("helm-"))) + ;;;*** ;; Local Variables: ;; version-control: never ;; no-byte-compile: t ;; no-update-autoloads: t +;; coding: utf-8 ;; End: ;;; helm-gtags-autoloads.el ends here diff --git a/elpa/helm-gtags-20170116.529/helm-gtags-pkg.el b/elpa/helm-gtags-20170116.529/helm-gtags-pkg.el new file mode 100644 index 00000000..6cd6fd0e --- /dev/null +++ b/elpa/helm-gtags-20170116.529/helm-gtags-pkg.el @@ -0,0 +1,2 @@ +;;; -*- 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" . "syohex@gmail.com")) :maintainer '("Syohei YOSHIDA" . "syohex@gmail.com") :url "https://github.com/syohex/emacs-helm-gtags") diff --git a/elpa/helm-gtags-20160202.503/helm-gtags.el b/elpa/helm-gtags-20170116.529/helm-gtags.el similarity index 92% rename from elpa/helm-gtags-20160202.503/helm-gtags.el rename to elpa/helm-gtags-20170116.529/helm-gtags.el index 637cef15..8832c31b 100644 --- a/elpa/helm-gtags-20160202.503/helm-gtags.el +++ b/elpa/helm-gtags-20170116.529/helm-gtags.el @@ -4,9 +4,9 @@ ;; Author: Syohei YOSHIDA ;; 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")) +;; 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 @@ -54,6 +54,7 @@ (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") @@ -73,6 +74,10 @@ "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) @@ -293,6 +298,9 @@ Always update if value of this variable is nil." 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") @@ -303,7 +311,7 @@ Always update if value of this variable is nil." (when (looking-at "^\\([^\r\n]+\\)") (let ((tag-path (match-string-no-properties 1))) (file-name-as-directory - (if (eq system-type 'cygwin) + (if (helm-gtags--convert-cygwin-windows-file-name-p) (cygwin-convert-file-name-from-windows tag-path) tag-path))))))) @@ -510,7 +518,7 @@ Always update if value of this variable is nil." (setq helm-gtags--local-directory dir))) (let ((input (or in helm-gtags--query)) (options (helm-gtags--construct-options type nil))) - (when (string= input "") + (when (string-empty-p input) (error "Input is empty!!")) (setq helm-gtags--last-input input) (reverse (cons input options)))) @@ -547,7 +555,7 @@ Always update if value of this variable is nil." (let* ((filename (helm-gtags--real-file-name)) (from-here-opt (format "--from-here=%d:%s" (line-number-at-pos) - (if (eq system-type 'cygwin) + (if (helm-gtags--convert-cygwin-windows-file-name-p) (cygwin-convert-file-name-to-windows filename) filename)))) (setq helm-gtags--last-input token) @@ -666,11 +674,6 @@ Always update if value of this variable is nil." (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 @@ -748,15 +751,6 @@ Always update if value of this variable is nil." (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 @@ -933,7 +927,35 @@ Always update if value of this variable is nil." (progn (process-file "global" nil t nil options) (helm-gtags--remove-carrige-returns)) - (helm-gtags--select-cache-init-common options "GPATH"))))) + (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" @@ -942,7 +964,7 @@ Always update if value of this variable is nil." :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))) + :action helm-gtags--file-util-action)) (defun helm-gtags--searched-directory () (cl-case (prefix-numeric-value current-prefix-arg) @@ -961,7 +983,7 @@ Always update if value of this variable is nil." (message "Failed: %s TAGS(%d)" action (process-exit-status process)))))) (defsubst helm-gtags--read-gtagslabel () - (let ((labels '("default" "native" "ctags" "pygments"))) + (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) @@ -987,9 +1009,9 @@ Always update if value of this variable is nil." (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'")) + (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 () @@ -1021,10 +1043,38 @@ Always update if value of this variable is nil." (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) + (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" @@ -1064,6 +1114,15 @@ Always update if value of this variable is nil." (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." @@ -1210,7 +1269,7 @@ Generate new TAG file in selected directory with `C-u C-u'" (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 " ")) + (message "Failed: %s" (string-join cmds " ")) (set-process-sentinel proc (helm-gtags--make-gtags-sentinel 'update)) (setq helm-gtags--last-update-time current-time)))))) @@ -1263,19 +1322,24 @@ Generate new TAG file in selected directory with `C-u C-u'" ;; 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) + (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))) diff --git a/elpa/helm-projectile-20151220.221/helm-projectile-pkg.el b/elpa/helm-projectile-20151220.221/helm-projectile-pkg.el deleted file mode 100644 index 633bf7ce..00000000 --- a/elpa/helm-projectile-20151220.221/helm-projectile-pkg.el +++ /dev/null @@ -1 +0,0 @@ -(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")) diff --git a/elpa/helm-projectile-20151220.221/helm-projectile-autoloads.el b/elpa/helm-projectile-20180815.1514/helm-projectile-autoloads.el similarity index 71% rename from elpa/helm-projectile-20151220.221/helm-projectile-autoloads.el rename to elpa/helm-projectile-20180815.1514/helm-projectile-autoloads.el index 4532059d..815b4e92 100644 --- a/elpa/helm-projectile-20151220.221/helm-projectile-autoloads.el +++ b/elpa/helm-projectile-20180815.1514/helm-projectile-autoloads.el @@ -1,15 +1,18 @@ ;;; helm-projectile-autoloads.el --- automatically extracted autoloads ;; ;;; Code: -(add-to-list 'load-path (or (file-name-directory #$) (car load-path))) + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + -;;;### (autoloads nil "helm-projectile" "helm-projectile.el" (22215 -;;;;;; 7828 0 0)) +;;;### (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.") +This needs to be set before loading helm-projectile.el.") (custom-autoload 'helm-projectile-fuzzy-match "helm-projectile" t) @@ -26,12 +29,12 @@ Other file extensions can be customized with the variable `projectile-other-file \(fn &optional FLEX-MATCHING)" t nil) (autoload 'helm-projectile-on "helm-projectile" "\ -Turn on helm-projectile key bindings. +Turn on `helm-projectile' key bindings. \(fn)" t nil) (autoload 'helm-projectile-off "helm-projectile" "\ -Turn off helm-projectile key bindings. +Turn off `helm-projectile' key bindings. \(fn)" t nil) @@ -47,10 +50,20 @@ Helm version of projectile-ack. \(fn &optional DIR)" t nil) (autoload 'helm-projectile-ag "helm-projectile" "\ -Helm version of projectile-ag. +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. @@ -61,11 +74,14 @@ If invoked outside of a project, displays a list of known projects to jump. (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-"))) + ;;;*** ;; Local Variables: ;; version-control: never ;; no-byte-compile: t ;; no-update-autoloads: t +;; coding: utf-8 ;; End: ;;; helm-projectile-autoloads.el ends here diff --git a/elpa/helm-projectile-20180815.1514/helm-projectile-pkg.el b/elpa/helm-projectile-20180815.1514/helm-projectile-pkg.el new file mode 100644 index 00000000..3cdbdc3f --- /dev/null +++ b/elpa/helm-projectile-20180815.1514/helm-projectile-pkg.el @@ -0,0 +1,2 @@ +;;; -*- 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") diff --git a/elpa/helm-projectile-20151220.221/helm-projectile.el b/elpa/helm-projectile-20180815.1514/helm-projectile.el similarity index 55% rename from elpa/helm-projectile-20151220.221/helm-projectile.el rename to elpa/helm-projectile-20180815.1514/helm-projectile.el index e44b871c..723d0a71 100644 --- a/elpa/helm-projectile-20151220.221/helm-projectile.el +++ b/elpa/helm-projectile-20180815.1514/helm-projectile.el @@ -1,14 +1,14 @@ -;;; helm-projectile.el --- Helm integration for Projectile +;;; helm-projectile.el --- Helm integration for Projectile -*- lexical-binding: t; -*- -;; Copyright (C) 2011-2015 Bozhidar Batsov +;; Copyright (C) 2011-2016 Bozhidar Batsov ;; Author: Bozhidar Batsov -;; URL: https://github.com/bbatsov/projectile -;; Package-Version: 20151220.221 +;; URL: https://github.com/bbatsov/helm-projectile +;; Package-Version: 20180815.1514 ;; 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")) +;; 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. @@ -40,6 +40,7 @@ ;; ;;; Code: +(require 'subr-x) (require 'projectile) (require 'cl-lib) (require 'grep) @@ -51,6 +52,7 @@ (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) @@ -60,23 +62,30 @@ "Helm support for projectile." :prefix "helm-projectile-" :group 'projectile - :link `(url-link :tag "helm-projectile homepage" "https://github.com/bbatsov/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." +This needs to be set before loading helm-projectile.el." :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 ..." + "In KEYMAP, define KEY - DEF sequence KEY1 as DEF1, KEY2 as DEF2 ..." (declare (indent defun)) (let ((ret '(progn))) (while key @@ -91,8 +100,7 @@ This needs to be set before loading helm-projectile." (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. + "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: @@ -116,7 +124,7 @@ 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 +DESCRIPTION. Otherwise, (FUNCTION . DESCRIPTION) will be added to the action list. Please check out how `helm-projectile-file-actions' is defined @@ -150,7 +158,7 @@ DIR is a directory to be switched" DIR is the project root." (let ((helm--reading-passwd-or-string t) (default-directory dir)) - (projectile-compile-project helm-current-prefix-arg dir))) + (projectile-compile-project helm-current-prefix-arg))) (defun helm-projectile-test-project (dir) "A Helm action for test a project. @@ -167,7 +175,7 @@ DIR is the project root." (projectile-run-project helm-current-prefix-arg))) (defun helm-projectile-remove-known-project (_ignore) - "Delete selected projects. + "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)) @@ -175,14 +183,14 @@ It is there because Helm requires it." (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)") + (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) deleted" len))))) + (message "%s projects(s) removed" len))))) (defvar helm-projectile-projects-map (let ((map (make-sparse-keymap))) @@ -199,43 +207,119 @@ It is there because Helm requires it." 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-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)) + (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 '(("Switch to project" . + :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) - ("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.") + . 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-find-files-eshell-command-on-file-action (_candidate) +(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))) + (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) +(defun helm-projectile-ff-etags-select-action (candidate) (interactive) - (let* ((helm-ff-default-directory (file-name-directory _candidate))) - (helm-ff-etags-select _candidate))) + (let* ((helm-ff-default-directory (file-name-directory candidate))) + (helm-ff-etags-select candidate))) (defun helm-projectile-switch-to-eshell (dir) (interactive) @@ -263,11 +347,12 @@ It is there because Helm requires it." "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)))) + (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. @@ -280,11 +365,12 @@ CANDIDATE is the selected file, but choose the marked files if available." (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)))) + (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) @@ -369,6 +455,14 @@ CANDIDATE is the selected file. Used when no file is explicitly marked." (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 @@ -379,6 +473,9 @@ CANDIDATE is the selected file. Used when no file is explicitly marked." (kbd "M-!") #'helm-projectile-find-files-eshell-command-on-file-action) (define-key map (kbd "") #'helm-previous-source) (define-key map (kbd "") #'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.") @@ -404,46 +501,88 @@ CANDIDATE is the selected file. Used when no file is explicitly marked." . "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)) +(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-in-buffer-source "Projectile files" - :data (lambda () - (condition-case nil - (projectile-current-project-files) - (error nil))) + (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 - :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 - ) + :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-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 + (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 @@ -455,19 +594,13 @@ CANDIDATE is the selected file. Used when no file is explicitly marked." (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 + (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 ((default-directory (projectile-project-root))) + (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))) @@ -480,25 +613,25 @@ CANDIDATE is the selected file. Used when no file is explicitly marked." "Helm source definition for Projectile delete files.") (defun helm-projectile-dired-find-dir (dir) - "Jump to a selected directory DIR from helm-projectile." + "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." + "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))) + (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 - :coerce 'helm-projectile-coerce-file :action-transformer 'helm-find-files-action-transformer :keymap (let ((map (make-sparse-keymap))) (set-keymap-parent map helm-map) @@ -526,9 +659,8 @@ CANDIDATE is the selected file. Used when no file is explicitly marked." (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))) + (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 @@ -554,18 +686,19 @@ CANDIDATE is the selected file. Used when no file is explicitly marked." (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))) + (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 - :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 - ) + :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 @@ -579,18 +712,21 @@ CANDIDATE is the selected file. Used when no file is explicitly marked." (defcustom helm-projectile-sources-list '(helm-source-projectile-buffers-list helm-source-projectile-files-list - helm-source-projectile-projects - ) + 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) - "Template for generic helm-projectile commands. +(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." +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 @@ -604,7 +740,8 @@ With a prefix ARG invalidates the cache first." ;; for consistency, we should just let Projectile take care of ignored files (helm-boring-file-regexp-list nil)) (helm :sources ,source - :buffer "*helm projectile*" + :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) @@ -612,20 +749,39 @@ With a prefix ARG invalidates the cache first." (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: ") +(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-files (projectile-current-project-files)) + (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-projectile-build-dwim-source (if (> (length files) 1) - files - project-files)) + (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 @@ -634,26 +790,51 @@ With a prefix ARG invalidates the cache first." 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 "") 'helm-previous-source) - (define-key map (kbd "") '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"))) + (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. @@ -665,21 +846,22 @@ 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-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 -e %p -- %f" + "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) - (helm-source-grep + (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) + :header-name (lambda (_name) (let ((name (if use-ack-p "Helm Projectile Ack" "Helm Projectile Grep"))) @@ -692,40 +874,34 @@ If it is nil, or ack/ack-grep not found then use default grep command." ;; 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) + :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))) + :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)) + :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 t))) + :truncate-lines helm-grep-truncate-lines))) ;;;###autoload (defun helm-projectile-on () - "Turn on helm-projectile key bindings." + "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." + "Turn off `helm-projectile' key bindings." (interactive) (message "Turn off helm-projectile key bindings") (helm-projectile-toggle -1)) @@ -736,8 +912,8 @@ If it is nil, or ack/ack-grep not found then use default grep command." 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))) + (funcall 'run-with-timer 0.01 nil + #'helm-projectile-grep-or-ack project-root nil))) ;;;###autoload (defun helm-projectile-ack (&optional dir) @@ -746,37 +922,67 @@ DIR is the project root, if not set then current directory is used" (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))) " ")) + (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."))))) + (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) + "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 (-union (projectile-ignored-files-rel) grep-find-ignored-files)) - (grep-find-ignored-directories (-union (projectile-ignored-directories-rel) grep-find-ignored-directories)) + (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) + (append grep-find-ignored-files grep-find-ignored-directories (cadr (projectile-parse-dirconfig-file))) " ")) - (helm-ag-command-option options) - (helm-ag-base-command (concat helm-ag-base-command " " ignored)) + (helm-ag-base-command (concat helm-ag-base-command " " ignored " " options)) (current-prefix-arg nil)) - (helm-do-ag (projectile-project-root))) + (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")) - (error "helm-ag not available"))) + (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 @@ -809,37 +1015,48 @@ DIR is the project root, if not set then current directory is used" (def-projectile-commander-method ?e "Find recently visited file in project." - (helm-projectile-recentf))) + (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 - (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) + (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 - (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) + (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 @@ -849,14 +1066,16 @@ DIR is the project root, if not set then current directory is used" 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: "))))) + (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 diff --git a/elpa/helm-projectile-readme.txt b/elpa/helm-projectile-readme.txt deleted file mode 100644 index f3969faf..00000000 --- a/elpa/helm-projectile-readme.txt +++ /dev/null @@ -1,6 +0,0 @@ -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. diff --git a/elpa/helm-safari-20160115.2334/helm-safari-pkg.el b/elpa/helm-safari-20160115.2334/helm-safari-pkg.el deleted file mode 100644 index eb3fce19..00000000 --- a/elpa/helm-safari-20160115.2334/helm-safari-pkg.el +++ /dev/null @@ -1 +0,0 @@ -(define-package "helm-safari" "20160115.2334" "Helm interface for Safari Bookmarks and History" '((helm "1.9.1") (emacs "24")) :keywords '("tools")) diff --git a/elpa/helm-safari-20160115.2334/helm-safari.el b/elpa/helm-safari-20160115.2334/helm-safari.el deleted file mode 100644 index b12ea492..00000000 --- a/elpa/helm-safari-20160115.2334/helm-safari.el +++ /dev/null @@ -1,94 +0,0 @@ -;;; helm-safari.el --- Helm interface for Safari Bookmarks and History -*- lexical-binding: t; -*- - -;; Copyright (C) 2016 Chunyang Xu - -;; Author: Chunyang Xu -;; 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 . - -;;; 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 diff --git a/elpa/helm-safari-20160115.2334/helm-safari-autoloads.el b/elpa/helm-safari-20160404.324/helm-safari-autoloads.el similarity index 53% rename from elpa/helm-safari-20160115.2334/helm-safari-autoloads.el rename to elpa/helm-safari-20160404.324/helm-safari-autoloads.el index a0c38195..1bc57c1a 100644 --- a/elpa/helm-safari-20160115.2334/helm-safari-autoloads.el +++ b/elpa/helm-safari-20160404.324/helm-safari-autoloads.el @@ -1,27 +1,32 @@ ;;; helm-safari-autoloads.el --- automatically extracted autoloads ;; ;;; Code: -(add-to-list 'load-path (or (file-name-directory #$) (car load-path))) + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + -;;;### (autoloads nil "helm-safari" "helm-safari.el" (22184 48066 -;;;;;; 0 0)) +;;;### (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 Bookmark using `helm'. +Search Safari Bookmarks. \(fn)" t nil) (autoload 'helm-safari-history "helm-safari" "\ -Search Safari Bookmark using `helm'. +Search Safari History. \(fn)" t nil) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-safari" '("helm-s"))) + ;;;*** ;; Local Variables: ;; version-control: never ;; no-byte-compile: t ;; no-update-autoloads: t +;; coding: utf-8 ;; End: ;;; helm-safari-autoloads.el ends here diff --git a/elpa/helm-safari-20160404.324/helm-safari-pkg.el b/elpa/helm-safari-20160404.324/helm-safari-pkg.el new file mode 100644 index 00000000..d14428da --- /dev/null +++ b/elpa/helm-safari-20160404.324/helm-safari-pkg.el @@ -0,0 +1,2 @@ +;;; -*- 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" . "xuchunyang56@gmail.com")) :maintainer '("Chunyang Xu" . "xuchunyang56@gmail.com") :url "https://github.com/xuchunyang/helm-safari") diff --git a/elpa/helm-safari-20160404.324/helm-safari.el b/elpa/helm-safari-20160404.324/helm-safari.el new file mode 100644 index 00000000..a5f0514f --- /dev/null +++ b/elpa/helm-safari-20160404.324/helm-safari.el @@ -0,0 +1,121 @@ +;;; helm-safari.el --- Browse your Safari bookmarks and history -*- lexical-binding: t; -*- + +;; Copyright (C) 2016 Chunyang Xu + +;; Author: Chunyang Xu +;; 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 . + +;;; 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 diff --git a/elpa/helm-safari-readme.txt b/elpa/helm-safari-readme.txt deleted file mode 100644 index e69de29b..00000000 diff --git a/elpa/helm-swoop-20170923.2127/helm-swoop-pkg.el b/elpa/helm-swoop-20170923.2127/helm-swoop-pkg.el deleted file mode 100644 index 353ee92a..00000000 --- a/elpa/helm-swoop-20170923.2127/helm-swoop-pkg.el +++ /dev/null @@ -1,2 +0,0 @@ -;;; -*- 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")) diff --git a/elpa/helm-swoop-20170923.2127/helm-swoop-autoloads.el b/elpa/helm-swoop-20180215.1154/helm-swoop-autoloads.el similarity index 86% rename from elpa/helm-swoop-20170923.2127/helm-swoop-autoloads.el rename to elpa/helm-swoop-20180215.1154/helm-swoop-autoloads.el index 7fa74c74..e1063e72 100644 --- a/elpa/helm-swoop-20170923.2127/helm-swoop-autoloads.el +++ b/elpa/helm-swoop-20180215.1154/helm-swoop-autoloads.el @@ -1,10 +1,12 @@ ;;; helm-swoop-autoloads.el --- automatically extracted autoloads ;; ;;; Code: -(add-to-list 'load-path (directory-file-name (or (file-name-directory #$) (car load-path)))) + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + -;;;### (autoloads nil "helm-swoop" "helm-swoop.el" (23005 64951 0 -;;;;;; 0)) +;;;### (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" "\ @@ -71,11 +73,14 @@ Start helm-swoop without pre input query. \(fn)" t nil) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "helm-swoop" '("helm-" "get-buffers-matching-mode"))) + ;;;*** ;; Local Variables: ;; version-control: never ;; no-byte-compile: t ;; no-update-autoloads: t +;; coding: utf-8 ;; End: ;;; helm-swoop-autoloads.el ends here diff --git a/elpa/helm-swoop-20180215.1154/helm-swoop-pkg.el b/elpa/helm-swoop-20180215.1154/helm-swoop-pkg.el new file mode 100644 index 00000000..a1901a19 --- /dev/null +++ b/elpa/helm-swoop-20180215.1154/helm-swoop-pkg.el @@ -0,0 +1,2 @@ +;;; -*- 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") diff --git a/elpa/helm-swoop-20170923.2127/helm-swoop.el b/elpa/helm-swoop-20180215.1154/helm-swoop.el similarity index 99% rename from elpa/helm-swoop-20170923.2127/helm-swoop.el rename to elpa/helm-swoop-20180215.1154/helm-swoop.el index ba070617..d0ce214b 100644 --- a/elpa/helm-swoop-20170923.2127/helm-swoop.el +++ b/elpa/helm-swoop-20180215.1154/helm-swoop.el @@ -1,9 +1,9 @@ ;;; helm-swoop.el --- Efficiently hopping squeezed lines powered by helm interface -*- coding: utf-8; lexical-binding: t -*- -;; Copyright (C) 2013 - 2017 by Shingo Fukuyama +;; Copyright (C) 2013 - 2018 by Shingo Fukuyama -;; Version: 1.7.3 -;; Package-Version: 20170923.2127 +;; 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 @@ -142,7 +142,7 @@ :group 'helm-swoop :type 'boolean) (defvar helm-swoop-split-window-function - (lambda ($buf) + (lambda ($buf &rest _$args) (if helm-swoop-split-with-multiple-windows (funcall helm-swoop-split-direction) (when (one-window-p) diff --git a/elpa/helm-swoop-readme.txt b/elpa/helm-swoop-readme.txt deleted file mode 100644 index 3bf8efc4..00000000 --- a/elpa/helm-swoop-readme.txt +++ /dev/null @@ -1,62 +0,0 @@ -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] diff --git a/elpa/restclient-helm-20160407.249/restclient-helm-pkg.el b/elpa/restclient-helm-20160407.249/restclient-helm-pkg.el deleted file mode 100644 index 1bf1de75..00000000 --- a/elpa/restclient-helm-20160407.249/restclient-helm-pkg.el +++ /dev/null @@ -1 +0,0 @@ -(define-package "restclient-helm" "20160407.249" "helm interface for restclient.el" '((restclient "0") (helm "1.9.4")) :keywords '("http" "helm")) diff --git a/elpa/restclient-helm-20160407.249/restclient-helm-autoloads.el b/elpa/restclient-helm-20170314.1554/restclient-helm-autoloads.el similarity index 52% rename from elpa/restclient-helm-20160407.249/restclient-helm-autoloads.el rename to elpa/restclient-helm-20170314.1554/restclient-helm-autoloads.el index 952feb61..faf64c14 100644 --- a/elpa/restclient-helm-20160407.249/restclient-helm-autoloads.el +++ b/elpa/restclient-helm-20170314.1554/restclient-helm-autoloads.el @@ -1,10 +1,13 @@ ;;; restclient-helm-autoloads.el --- automatically extracted autoloads ;; ;;; Code: -(add-to-list 'load-path (or (file-name-directory #$) (car load-path))) + +(add-to-list 'load-path (directory-file-name + (or (file-name-directory #$) (car load-path)))) + -;;;### (autoloads nil "restclient-helm" "restclient-helm.el" (22294 -;;;;;; 20081 0 0)) +;;;### (autoloads nil "restclient-helm" "restclient-helm.el" (0 0 +;;;;;; 0 0)) ;;; Generated autoloads from restclient-helm.el (autoload 'helm-restclient "restclient-helm" "\ @@ -12,11 +15,14 @@ Helm for Restclient. \(fn)" t nil) +(if (fboundp 'register-definition-prefixes) (register-definition-prefixes "restclient-helm" '("restclient-helm-"))) + ;;;*** ;; Local Variables: ;; version-control: never ;; no-byte-compile: t ;; no-update-autoloads: t +;; coding: utf-8 ;; End: ;;; restclient-helm-autoloads.el ends here diff --git a/elpa/restclient-helm-20170314.1554/restclient-helm-pkg.el b/elpa/restclient-helm-20170314.1554/restclient-helm-pkg.el new file mode 100644 index 00000000..6769acbf --- /dev/null +++ b/elpa/restclient-helm-20170314.1554/restclient-helm-pkg.el @@ -0,0 +1,2 @@ +;;; -*- 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" . "pashky@gmail.com")) :maintainer '("Pavel Kurnosov" . "pashky@gmail.com")) diff --git a/elpa/restclient-helm-20160407.249/restclient-helm.el b/elpa/restclient-helm-20170314.1554/restclient-helm.el similarity index 97% rename from elpa/restclient-helm-20160407.249/restclient-helm.el rename to elpa/restclient-helm-20170314.1554/restclient-helm.el index 39b66363..e47d596a 100644 --- a/elpa/restclient-helm-20160407.249/restclient-helm.el +++ b/elpa/restclient-helm-20170314.1554/restclient-helm.el @@ -6,7 +6,7 @@ ;; Maintainer: Pavel Kurnosov ;; Created: 01 Apr 2016 ;; Keywords: http helm -;; Package-Version: 20160407.249 +;; Package-Version: 20170314.1554 ;; Package-Requires: ((restclient "0") (helm "1.9.4")) ;; This file is not part of GNU Emacs. @@ -71,6 +71,4 @@ '(progn (define-key restclient-mode-map (kbd "C-c C-g") #'helm-restclient))) -;;; helm-restclient.el ends here - ;;; restclient-helm.el ends here diff --git a/elpa/restclient-helm-readme.txt b/elpa/restclient-helm-readme.txt deleted file mode 100644 index d6809709..00000000 --- a/elpa/restclient-helm-readme.txt +++ /dev/null @@ -1 +0,0 @@ -This is a companion to restclient.el to add helm sources for requests and variables in current restclient-mode buffer. -- 2.47.3