Update all packages

This commit is contained in:
Mateus Pinto Rodrigues
2018-07-17 19:34:58 -03:00
parent 3c61003537
commit 25baa00351
259 changed files with 1404 additions and 4340 deletions

View File

@@ -0,0 +1,111 @@
#!/bin/sh
## Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiatto@gmail.com>
##
## This program is free software; you can redistribute it and/or modify
## it under the terms of the GNU General Public License as published by
## the Free Software Foundation, either version 3 of the License, or
## (at your option) any later version.
##
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
## GNU General Public License for more details.
##
## You should have received a copy of the GNU General Public License
## along with this program. If not, see <http://www.gnu.org/licenses/>.
## Commentary:
# Preconfigured `emacs -Q' with a basic Helm configuration.
# Run it from this directory or symlink it somewhere in your PATH.
# If TEMP env var exists, use it, otherwise declare it.
test -z "$TEMP" && TEMP="/tmp"
CONF_FILE="$TEMP/helm-cfg.el"
EMACS=emacs
case $1 in
-P)
shift 1
EMACS=$1
shift 1
;;
-h)
echo "Usage: ${0##*/} [-P} Emacs path [-h} help [--] EMACS ARGS"
exit 1
;;
esac
LOAD_PATH=$($EMACS -q -batch --eval "(prin1 load-path)")
cd "${0%/*}" || exit 1
# Check if autoload file exists.
# It may be in a different directory if emacs-helm.sh is a symlink.
TRUENAME=$(find . -samefile "$0" -printf "%l")
if [ ! -z "$TRUENAME" ]; then
AUTO_FILE="${TRUENAME%/*}/helm-autoloads.el"
else
AUTO_FILE="helm-autoloads.el"
fi
if [ ! -e "$AUTO_FILE" ]; then
echo No autoloads found, please run make first to generate autoload file
exit 1
fi
cat > $CONF_FILE <<EOF
(setq initial-scratch-message (concat initial-scratch-message
";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\\n\
;; This Emacs is Powered by \`HELM' using\\n\
;; emacs program \"$EMACS\".\\n\
;; This is a minimal \`helm' configuration to discover \`helm' or debug it.\\n\
;; You can retrieve this minimal configuration in \"$CONF_FILE\".\\n\
;; Some original Emacs commands are replaced by their \`helm' counterparts:\\n\\n\
;; - \`find-file'(C-x C-f) =>\`helm-find-files'\\n\
;; - \`occur'(M-s o) =>\`helm-occur'\\n\
;; - \`list-buffers'(C-x C-b) =>\`helm-buffers-list'\\n\
;; - \`completion-at-point'(M-tab) =>\`helm-lisp-completion-at-point'[1]\\n\
;; - \`dabbrev-expand'(M-/) =>\`helm-dabbrev'\\n\
;; - \`execute-extended-command'(M-x) =>\`helm-M-x'\\n\\n
;; Some other Emacs commands are \"helmized\" by \`helm-mode'.\\n\
;; [1] Coming with emacs-24.4, \`completion-at-point' is \"helmized\" by \`helm-mode'\\n\
;; which provides Helm completion in many places like \`shell-mode'.\\n\
;; Find context help for most Helm commands with \`C-h m'.\\n\
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;\\n\\n"))
(setq load-path (quote $LOAD_PATH))
(require 'package)
;; User may be using a non standard \`package-user-dir'.
;; Modify \`package-directory-list' instead of \`package-user-dir'
;; in case the user starts Helm from a non-ELPA installation.
(unless (file-equal-p package-user-dir "~/.emacs.d/elpa")
(add-to-list 'package-directory-list (directory-file-name
(file-name-directory
(directory-file-name default-directory)))))
(setq package-load-list '((helm-core t) (helm t) (async t) (popup t)))
(package-initialize)
(add-to-list 'load-path (file-name-directory (file-truename "$0")))
(setq default-frame-alist '((vertical-scroll-bars . nil)
(tool-bar-lines . 0)
(menu-bar-lines . 0)
(fullscreen . nil)))
(blink-cursor-mode -1)
(require 'helm-config)
(helm-mode 1)
(define-key global-map [remap find-file] 'helm-find-files)
(define-key global-map [remap occur] 'helm-occur)
(define-key global-map [remap list-buffers] 'helm-buffers-list)
(define-key global-map [remap dabbrev-expand] 'helm-dabbrev)
(define-key global-map [remap execute-extended-command] 'helm-M-x)
(unless (boundp 'completion-in-region-function)
(define-key lisp-interaction-mode-map [remap completion-at-point] 'helm-lisp-completion-at-point)
(define-key emacs-lisp-mode-map [remap completion-at-point] 'helm-lisp-completion-at-point))
(add-hook 'kill-emacs-hook #'(lambda () (and (file-exists-p "$CONF_FILE") (delete-file "$CONF_FILE"))))
EOF
$EMACS -Q -l "$CONF_FILE" "$@"

View File

@@ -0,0 +1,277 @@
;;; helm-adaptive.el --- Adaptive Sorting of Candidates. -*- lexical-binding: t -*-
;; Original Author: Tamas Patrovics
;; Copyright (C) 2007 Tamas Patrovics
;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Code:
(require 'cl-lib)
(require 'helm)
(defgroup helm-adapt nil
"Adaptative sorting of candidates for Helm."
:group 'helm)
(defcustom helm-adaptive-history-file
"~/.emacs.d/helm-adaptive-history"
"Path of file where history information is stored.
When nil history is not saved nor restored after emacs restart unless
you save/restore `helm-adaptive-history' with something else like
psession or desktop."
:type 'string
:group 'helm-adapt)
(defcustom helm-adaptive-history-length 50
"Maximum number of candidates stored for a source."
:type 'number
:group 'helm-adapt)
(defcustom helm-adaptive-sort-by-frequent-recent-usage t
"Try to sort on an average of frequent and recent usage when non-nil.
When nil sort on frequency usage only.
Only frequency:
When candidate have low frequency, you have to hit on it many times to
make it going up on top.
Frequency+recent:
Even with a low frequency, candidate go up on top. If a candidate
have a high frequency but it is not used since some time, it goes
down slowly, but as soon you reuse it it go up on top quickly."
:group 'helm-adapt
:type 'boolean)
;; Internal
(defvar helm-adaptive-done nil
"nil if history information is not yet stored for the current
selection.")
(defvar helm-adaptive-history nil
"Contains the stored history information.
Format: ((SOURCE-NAME (SELECTED-CANDIDATE (PATTERN . NUMBER-OF-USE) ...) ...) ...)")
(defconst helm-adaptive-freq-coefficient 5)
(defconst helm-adaptive-recent-coefficient 2)
(defun helm-adaptive-done-reset ()
(setq helm-adaptive-done nil))
;;;###autoload
(define-minor-mode helm-adaptive-mode
"Toggle adaptive sorting in all sources."
:group 'helm-adapt
:require 'helm-adaptive
:global t
(if helm-adaptive-mode
(progn
(unless helm-adaptive-history
(helm-adaptive-maybe-load-history))
(add-hook 'kill-emacs-hook 'helm-adaptive-save-history)
;; Should run at beginning of `helm-initial-setup'.
(add-hook 'helm-before-initialize-hook 'helm-adaptive-done-reset)
;; Should run at beginning of `helm-exit-minibuffer'.
(add-hook 'helm-before-action-hook 'helm-adaptive-store-selection)
;; Should run at beginning of `helm-select-action'.
(add-hook 'helm-select-action-hook 'helm-adaptive-store-selection))
(helm-adaptive-save-history)
(setq helm-adaptive-history nil)
(remove-hook 'kill-emacs-hook 'helm-adaptive-save-history)
(remove-hook 'helm-before-initialize-hook 'helm-adaptive-done-reset)
(remove-hook 'helm-before-action-hook 'helm-adaptive-store-selection)
(remove-hook 'helm-select-action-hook 'helm-adaptive-store-selection)))
(defun helm-adapt-use-adaptive-p (&optional source-name)
"Return current source only if it use adaptive history, nil otherwise."
(when helm-adaptive-mode
(let* ((source (or source-name (helm-get-current-source)))
(adapt-source (or (assoc-default 'filtered-candidate-transformer source)
(assoc-default 'candidate-transformer source))))
(if (listp adapt-source)
(and (memq 'helm-adaptive-sort adapt-source) source)
(and (eq adapt-source 'helm-adaptive-sort) source)))))
(defun helm-adaptive-store-selection ()
"Store history information for the selected candidate."
(unless helm-adaptive-done
(setq helm-adaptive-done t)
(let ((source (helm-adapt-use-adaptive-p)))
(when source
(let* ((source-name (assoc-default 'name source))
(source-info (or (assoc source-name helm-adaptive-history)
(progn
(push (list source-name) helm-adaptive-history)
(car helm-adaptive-history))))
(selection (helm-get-selection nil t))
(selection-info (progn
(setcdr source-info
(cons
(let ((found (assoc selection (cdr source-info))))
(if (not found)
;; new entry
(list selection)
;; move entry to the beginning of the
;; list, so that it doesn't get
;; trimmed when the history is
;; truncated
(setcdr source-info
(delete found (cdr source-info)))
found))
(cdr source-info)))
(cadr source-info)))
(pattern-info (progn
(setcdr selection-info
(cons
(let ((found (assoc helm-pattern (cdr selection-info))))
(if (not found)
;; new entry
(cons helm-pattern 0)
;; move entry to the beginning of the
;; list, so if two patterns used the
;; same number of times then the one
;; used last appears first in the list
(setcdr selection-info
(delete found (cdr selection-info)))
found))
(cdr selection-info)))
(cadr selection-info)))
(timestamp-info (helm-aif (assq 'timestamp (cdr selection-info))
it
(setcdr selection-info (cons (cons 'timestamp 0) (cdr selection-info)))
(cadr selection-info))))
;; Increase usage count.
(setcdr pattern-info (1+ (cdr pattern-info)))
;; Update timestamp.
(setcdr timestamp-info (float-time))
;; Truncate history if needed.
(if (> (length (cdr selection-info)) helm-adaptive-history-length)
(setcdr selection-info
(cl-subseq (cdr selection-info) 0 helm-adaptive-history-length))))))))
(defun helm-adaptive-maybe-load-history ()
"Load `helm-adaptive-history-file' which contain `helm-adaptive-history'.
Returns nil if `helm-adaptive-history-file' doesn't exist."
(when (and helm-adaptive-history-file
(file-readable-p helm-adaptive-history-file))
(load-file helm-adaptive-history-file)))
(defun helm-adaptive-save-history (&optional arg)
"Save history information to file given by `helm-adaptive-history-file'."
(interactive "p")
(when helm-adaptive-history-file
(with-temp-buffer
(insert
";; -*- mode: emacs-lisp -*-\n"
";; History entries used for helm adaptive display.\n")
(prin1 `(setq helm-adaptive-history ',helm-adaptive-history)
(current-buffer))
(insert ?\n)
(write-region (point-min) (point-max) helm-adaptive-history-file nil
(unless arg 'quiet)))))
(defun helm-adaptive-sort (candidates source)
"Sort the CANDIDATES for SOURCE by usage frequency.
This is a filtered candidate transformer you can use with the
`filtered-candidate-transformer' attribute."
(let* ((source-name (assoc-default 'name source))
(source-info (assoc source-name helm-adaptive-history)))
(if source-info
(let ((usage
;; Loop in the SOURCE entry of `helm-adaptive-history'
;; and assemble a list containing the (CANDIDATE
;; . USAGE-COUNT) pairs.
(cl-loop with cf = (if helm-adaptive-sort-by-frequent-recent-usage
helm-adaptive-freq-coefficient 1)
with cr = helm-adaptive-recent-coefficient
for (src-cand . infos) in (cdr source-info)
for count-freq = 0
for count-rec =
(helm-aif (and helm-adaptive-sort-by-frequent-recent-usage
(assq 'timestamp infos))
(* cr (+ (float-time) (cdr it)))
0)
do (cl-loop for (pattern . score) in
(remove (assq 'timestamp infos) infos)
;; If current pattern is equal to
;; the previously used one then
;; this candidate has priority
;; (that's why its count-freq is
;; boosted by 10000) and it only
;; has to compete with other
;; candidates which were also
;; selected with the same pattern.
if (equal pattern helm-pattern)
return (setq count-freq (+ 10000 score))
else do (cl-incf count-freq score))
and collect (cons src-cand (+ (* count-freq cf) count-rec))
into results
;; Sort the list in descending order, so
;; candidates with highest priority come
;; first.
finally return
(sort results (lambda (first second)
(> (cdr first) (cdr second)))))))
(if (consp usage)
;; Put those candidates first which have the highest usage count.
(cl-loop for (cand . _freq) in usage
for info = (or (and (assq 'multiline source)
(replace-regexp-in-string
"\n\\'" "" cand))
cand)
when (cl-member info candidates
:test 'helm-adaptive-compare)
collect (car it) into sorted
and do (setq candidates
(cl-remove info candidates
:test 'helm-adaptive-compare))
finally return (append sorted candidates))
(message "Your `%s' is maybe corrupted or too old, \
you should reinitialize it with `helm-reset-adaptive-history'"
helm-adaptive-history-file)
(sit-for 1)
candidates))
;; if there is no information stored for this source then do nothing
candidates)))
;;;###autoload
(defun helm-reset-adaptive-history ()
"Delete all `helm-adaptive-history' and his file.
Useful when you have a old or corrupted `helm-adaptive-history-file'."
(interactive)
(when (y-or-n-p "Really delete all your `helm-adaptive-history'? ")
(setq helm-adaptive-history nil)
(delete-file helm-adaptive-history-file)))
(defun helm-adaptive-compare (x y)
"Compare display parts if some of candidates X and Y.
Arguments X and Y are cons cell in (DISPLAY . REAL) format or atoms."
(equal (if (listp x) (car x) x)
(if (listp y) (car y) y)))
(provide 'helm-adaptive)
;; Local Variables:
;; byte-compile-warnings: (not obsolete)
;; coding: utf-8
;; indent-tabs-mode: nil
;; End:
;;; helm-adaptive.el ends here

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,721 @@
;;; helm-bookmark.el --- Helm for Emacs regular Bookmarks. -*- lexical-binding: t -*-
;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Code:
(require 'cl-lib)
(require 'bookmark)
(require 'helm)
(require 'helm-lib)
(require 'helm-help)
(require 'helm-types)
(require 'helm-utils)
(require 'helm-info)
(require 'helm-adaptive)
(require 'helm-net)
(declare-function helm-browse-project "helm-files" (arg))
(declare-function addressbook-bookmark-edit "ext:addressbook-bookmark.el" (bookmark))
(defgroup helm-bookmark nil
"Predefined configurations for `helm.el'."
:group 'helm)
(defcustom helm-bookmark-show-location nil
"Show location of bookmark on display."
:group 'helm-bookmark
:type 'boolean)
(defcustom helm-bookmark-default-filtered-sources
(append '(helm-source-bookmark-org
helm-source-bookmark-files&dirs
helm-source-bookmark-helm-find-files
helm-source-bookmark-info
helm-source-bookmark-gnus
helm-source-bookmark-man
helm-source-bookmark-images
helm-source-bookmark-w3m)
(list 'helm-source-bookmark-uncategorized
'helm-source-bookmark-set))
"List of sources to use in `helm-filtered-bookmarks'."
:group 'helm-bookmark
:type '(repeat (choice symbol)))
(defface helm-bookmark-info
'((t (:foreground "green")))
"Face used for W3m Emacs bookmarks (not w3m bookmarks)."
:group 'helm-bookmark)
(defface helm-bookmark-w3m
'((t (:foreground "yellow")))
"Face used for W3m Emacs bookmarks (not w3m bookmarks)."
:group 'helm-bookmark)
(defface helm-bookmark-gnus
'((t (:foreground "magenta")))
"Face used for Gnus bookmarks."
:group 'helm-bookmark)
(defface helm-bookmark-man
'((t (:foreground "Orange4")))
"Face used for Woman/man bookmarks."
:group 'helm-bookmark)
(defface helm-bookmark-file
'((t (:foreground "Deepskyblue2")))
"Face used for file bookmarks."
:group 'helm-bookmark)
(defface helm-bookmark-file-not-found
'((t (:foreground "Slategray4")))
"Face used for file bookmarks."
:group 'helm-bookmark)
(defface helm-bookmark-directory
'((t (:inherit helm-ff-directory)))
"Face used for file bookmarks."
:group 'helm-bookmark)
(defface helm-bookmark-addressbook
'((t (:foreground "tomato")))
"Face used for addressbook bookmarks."
:group 'helm-bookmark)
(defvar helm-bookmark-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map helm-map)
(define-key map (kbd "C-c o") 'helm-bookmark-run-jump-other-window)
(define-key map (kbd "C-d") 'helm-bookmark-run-delete)
(define-key map (kbd "C-]") 'helm-bookmark-toggle-filename)
(define-key map (kbd "M-e") 'helm-bookmark-run-edit)
map)
"Generic Keymap for emacs bookmark sources.")
(defclass helm-source-basic-bookmarks (helm-source-in-buffer helm-type-bookmark)
((init :initform (lambda ()
(bookmark-maybe-load-default-file)
(helm-init-candidates-in-buffer
'global
(bookmark-all-names))))
(filtered-candidate-transformer :initform 'helm-bookmark-transformer)))
(defvar helm-source-bookmarks
(helm-make-source "Bookmarks" 'helm-source-basic-bookmarks)
"See (info \"(emacs)Bookmarks\").")
(defun helm-bookmark-transformer (candidates _source)
(cl-loop for i in candidates
for loc = (bookmark-location i)
for len = (string-width i)
for trunc = (if (> len bookmark-bmenu-file-column)
(helm-substring i bookmark-bmenu-file-column)
i)
for sep = (make-string (- (+ bookmark-bmenu-file-column 2)
(length trunc))
? )
if helm-bookmark-show-location
collect (cons (concat trunc sep (if (listp loc) (car loc) loc)) i)
else collect i))
(defun helm-bookmark-toggle-filename-1 (_candidate)
(let* ((real (helm-get-selection helm-buffer))
(trunc (if (> (string-width real) bookmark-bmenu-file-column)
(helm-substring real bookmark-bmenu-file-column)
real))
(loc (bookmark-location real)))
(setq helm-bookmark-show-location (not helm-bookmark-show-location))
(helm-update (if helm-bookmark-show-location
(concat (regexp-quote trunc)
" +"
(regexp-quote
(if (listp loc) (car loc) loc)))
(regexp-quote real)))))
(defun helm-bookmark-toggle-filename ()
"Toggle bookmark location visibility."
(interactive)
(with-helm-alive-p
(helm-attrset 'toggle-filename
'(helm-bookmark-toggle-filename-1 . never-split))
(helm-execute-persistent-action 'toggle-filename)))
(put 'helm-bookmark-toggle-filename 'helm-only t)
(defun helm-bookmark-jump (candidate)
"Jump to bookmark from keyboard."
(let ((current-prefix-arg helm-current-prefix-arg)
non-essential)
(bookmark-jump candidate)))
(defun helm-bookmark-jump-other-window (candidate)
(let (non-essential)
(bookmark-jump-other-window candidate)))
;;; bookmark-set
;;
(defvar helm-source-bookmark-set
(helm-build-dummy-source "Set Bookmark"
:filtered-candidate-transformer
(lambda (_candidates _source)
(list (or (and (not (string= helm-pattern ""))
helm-pattern)
"Enter a bookmark name to record")))
:action '(("Set bookmark" . (lambda (candidate)
(if (string= helm-pattern "")
(message "No bookmark name given for record")
(bookmark-set candidate))))))
"See (info \"(emacs)Bookmarks\").")
;;; Predicates
;;
(defconst helm-bookmark--non-file-filename " - no file -"
"Name to use for `filename' entry, for non-file bookmarks.")
(defun helm-bookmark-gnus-bookmark-p (bookmark)
"Return non-nil if BOOKMARK is a Gnus bookmark.
BOOKMARK is a bookmark name or a bookmark record."
(or (eq (bookmark-get-handler bookmark) 'bmkext-jump-gnus)
(eq (bookmark-get-handler bookmark) 'gnus-summary-bookmark-jump)
(eq (bookmark-get-handler bookmark) 'bookmarkp-jump-gnus)))
(defun helm-bookmark-w3m-bookmark-p (bookmark)
"Return non-nil if BOOKMARK is a W3m bookmark.
BOOKMARK is a bookmark name or a bookmark record."
(or (eq (bookmark-get-handler bookmark) 'bmkext-jump-w3m)
(eq (bookmark-get-handler bookmark) 'bookmark-w3m-bookmark-jump)
(eq (bookmark-get-handler bookmark) 'bookmarkp-jump-w3m)))
(defun helm-bookmark-woman-bookmark-p (bookmark)
"Return non-nil if BOOKMARK is a Woman bookmark.
BOOKMARK is a bookmark name or a bookmark record."
(or (eq (bookmark-get-handler bookmark) 'bmkext-jump-woman)
(eq (bookmark-get-handler bookmark) 'woman-bookmark-jump)
(eq (bookmark-get-handler bookmark) 'bookmarkp-jump-woman)))
(defun helm-bookmark-man-bookmark-p (bookmark)
"Return non-nil if BOOKMARK is a Man bookmark.
BOOKMARK is a bookmark name or a bookmark record."
(or (eq (bookmark-get-handler bookmark) 'bmkext-jump-man)
(eq (bookmark-get-handler bookmark) 'Man-bookmark-jump)
(eq (bookmark-get-handler bookmark) 'bookmarkp-jump-man)))
(defun helm-bookmark-woman-man-bookmark-p (bookmark)
"Return non-nil if BOOKMARK is a Man or Woman bookmark.
BOOKMARK is a bookmark name or a bookmark record."
(or (helm-bookmark-man-bookmark-p bookmark)
(helm-bookmark-woman-bookmark-p bookmark)))
(defun helm-bookmark-info-bookmark-p (bookmark)
"Return non-nil if BOOKMARK is an Info bookmark.
BOOKMARK is a bookmark name or a bookmark record."
(eq (bookmark-get-handler bookmark) 'Info-bookmark-jump))
(defun helm-bookmark-image-bookmark-p (bookmark)
"Return non-nil if BOOKMARK bookmarks an image file."
(if (stringp bookmark)
(assq 'image-type (assq bookmark bookmark-alist))
(assq 'image-type bookmark)))
(defun helm-bookmark-file-p (bookmark)
"Return non-nil if BOOKMARK bookmarks a file or directory.
BOOKMARK is a bookmark name or a bookmark record.
This excludes bookmarks of a more specific kind (Info, Gnus, and W3m)."
(let* ((filename (bookmark-get-filename bookmark))
(isnonfile (equal filename helm-bookmark--non-file-filename)))
(and filename (not isnonfile) (not (bookmark-get-handler bookmark)))))
(defun helm-bookmark-org-file-p (bookmark)
(let* ((filename (bookmark-get-filename bookmark)))
(or (string-suffix-p ".org" filename t)
(string-suffix-p ".org_archive" filename t))))
(defun helm-bookmark-helm-find-files-p (bookmark)
"Return non-nil if BOOKMARK bookmarks a `helm-find-files' session.
BOOKMARK is a bookmark name or a bookmark record."
(eq (bookmark-get-handler bookmark) 'helm-ff-bookmark-jump))
(defun helm-bookmark-addressbook-p (bookmark)
"Return non--nil if BOOKMARK is a contact recorded with addressbook-bookmark.
BOOKMARK is a bookmark name or a bookmark record."
(if (listp bookmark)
(string= (assoc-default 'type bookmark) "addressbook")
(string= (assoc-default
'type (assoc bookmark bookmark-alist)) "addressbook")))
(defun helm-bookmark-uncategorized-bookmark-p (bookmark)
"Return non--nil if BOOKMARK match no known category."
(cl-loop for pred in '(helm-bookmark-org-file-p
helm-bookmark-addressbook-p
helm-bookmark-gnus-bookmark-p
helm-bookmark-w3m-bookmark-p
helm-bookmark-woman-man-bookmark-p
helm-bookmark-info-bookmark-p
helm-bookmark-image-bookmark-p
helm-bookmark-file-p
helm-bookmark-helm-find-files-p
helm-bookmark-addressbook-p)
never (funcall pred bookmark)))
(defun helm-bookmark-filter-setup-alist (fn)
"Return a filtered `bookmark-alist' sorted alphabetically."
(cl-loop for b in bookmark-alist
for name = (car b)
when (funcall fn b) collect
(propertize name 'location (bookmark-location name))))
;;; Bookmark handlers
;;
(defvar w3m-async-exec)
(defun helm-bookmark-jump-w3m (bookmark)
"Jump to W3m bookmark BOOKMARK, setting a new tab.
If `browse-url-browser-function' is set to something else
than `w3m-browse-url' use it."
(require 'helm-net)
(let* ((file (or (bookmark-prop-get bookmark 'filename)
(bookmark-prop-get bookmark 'url)))
(buf (generate-new-buffer-name "*w3m*"))
(w3m-async-exec nil)
;; If user don't have anymore w3m installed let it browse its
;; bookmarks with default browser otherwise assume bookmark
;; have been bookmarked from w3m and use w3m.
(browse-url-browser-function (or (and (fboundp 'w3m-browse-url)
(executable-find "w3m")
'w3m-browse-url)
browse-url-browser-function))
(really-use-w3m (equal browse-url-browser-function 'w3m-browse-url)))
(helm-browse-url file really-use-w3m)
(when really-use-w3m
(bookmark-default-handler
`("" (buffer . ,buf) . ,(bookmark-get-bookmark-record bookmark))))))
;; All bookmarks recorded with the handler provided with w3m
;; (`bookmark-w3m-bookmark-jump') will use our handler which open
;; the bookmark in a new tab or in an external browser depending
;; on `browse-url-browser-function'.
(defalias 'bookmark-w3m-bookmark-jump 'helm-bookmark-jump-w3m)
;; Provide compatibility with old handlers provided in external
;; packages bookmark-extensions.el and bookmark+.
(defalias 'bmkext-jump-woman 'woman-bookmark-jump)
(defalias 'bmkext-jump-man 'Man-bookmark-jump)
(defalias 'bmkext-jump-w3m 'helm-bookmark-jump-w3m)
(defalias 'bmkext-jump-gnus 'gnus-summary-bookmark-jump)
(defalias 'bookmarkp-jump-gnus 'gnus-summary-bookmark-jump)
(defalias 'bookmarkp-jump-w3m 'helm-bookmark-jump-w3m)
(defalias 'bookmarkp-jump-woman 'woman-bookmark-jump)
(defalias 'bookmarkp-jump-man 'Man-bookmark-jump)
;;;; Filtered bookmark sources
;;
;;
(defclass helm-source-filtered-bookmarks (helm-source-in-buffer helm-type-bookmark)
((filtered-candidate-transformer
:initform '(helm-adaptive-sort
helm-highlight-bookmark))))
;;; W3m bookmarks.
;;
(defun helm-bookmark-w3m-setup-alist ()
"Specialized filter function for bookmarks w3m."
(helm-bookmark-filter-setup-alist 'helm-bookmark-w3m-bookmark-p))
(defvar helm-source-bookmark-w3m
(helm-make-source "Bookmark W3m" 'helm-source-filtered-bookmarks
:init (lambda ()
(bookmark-maybe-load-default-file)
(helm-init-candidates-in-buffer
'global (helm-bookmark-w3m-setup-alist)))))
;;; Images
;;
(defun helm-bookmark-images-setup-alist ()
"Specialized filter function for images bookmarks."
(helm-bookmark-filter-setup-alist 'helm-bookmark-image-bookmark-p))
(defvar helm-source-bookmark-images
(helm-make-source "Bookmark Images" 'helm-source-filtered-bookmarks
:init (lambda ()
(bookmark-maybe-load-default-file)
(helm-init-candidates-in-buffer
'global (helm-bookmark-images-setup-alist)))))
;;; Woman Man
;;
(defun helm-bookmark-man-setup-alist ()
"Specialized filter function for bookmarks w3m."
(helm-bookmark-filter-setup-alist 'helm-bookmark-woman-man-bookmark-p))
(defvar helm-source-bookmark-man
(helm-make-source "Bookmark Woman&Man" 'helm-source-filtered-bookmarks
:init (lambda ()
(bookmark-maybe-load-default-file)
(helm-init-candidates-in-buffer
'global (helm-bookmark-man-setup-alist)))))
;;; Org files
;;
(defun helm-bookmark-org-setup-alist ()
"Specialized filter function for Org file bookmarks."
(helm-bookmark-filter-setup-alist 'helm-bookmark-org-file-p))
(defvar helm-source-bookmark-org
(helm-make-source " Bookmarked Org files" 'helm-source-filtered-bookmarks
:init (lambda ()
(bookmark-maybe-load-default-file)
(helm-init-candidates-in-buffer
'global (helm-bookmark-org-setup-alist)))))
;;; Gnus
;;
(defun helm-bookmark-gnus-setup-alist ()
"Specialized filter function for bookmarks gnus."
(helm-bookmark-filter-setup-alist 'helm-bookmark-gnus-bookmark-p))
(defvar helm-source-bookmark-gnus
(helm-make-source "Bookmark Gnus" 'helm-source-filtered-bookmarks
:init (lambda ()
(bookmark-maybe-load-default-file)
(helm-init-candidates-in-buffer
'global (helm-bookmark-gnus-setup-alist)))))
;;; Info
;;
(defun helm-bookmark-info-setup-alist ()
"Specialized filter function for bookmarks info."
(helm-bookmark-filter-setup-alist 'helm-bookmark-info-bookmark-p))
(defvar helm-source-bookmark-info
(helm-make-source "Bookmark Info" 'helm-source-filtered-bookmarks
:init (lambda ()
(bookmark-maybe-load-default-file)
(helm-init-candidates-in-buffer
'global (helm-bookmark-info-setup-alist)))))
;;; Files and directories
;;
(defun helm-bookmark-local-files-setup-alist ()
"Specialized filter function for bookmarks locals files."
(helm-bookmark-filter-setup-alist 'helm-bookmark-file-p))
(defvar helm-source-bookmark-files&dirs
(helm-make-source "Bookmark Files&Directories" 'helm-source-filtered-bookmarks
:init (lambda ()
(bookmark-maybe-load-default-file)
(helm-init-candidates-in-buffer
'global (helm-bookmark-local-files-setup-alist)))))
;;; Helm find files sessions.
;;
(defun helm-bookmark-helm-find-files-setup-alist ()
"Specialized filter function for `helm-find-files' bookmarks."
(helm-bookmark-filter-setup-alist 'helm-bookmark-helm-find-files-p))
(defun helm-bookmark-browse-project (candidate)
"Run `helm-browse-project' from action."
(with-helm-default-directory
(bookmark-get-filename candidate)
(helm-browse-project nil)))
(defun helm-bookmark-run-browse-project ()
"Run `helm-bookmark-browse-project' from keyboard."
(interactive)
(with-helm-alive-p
(helm-exit-and-execute-action 'helm-bookmark-browse-project)))
(put 'helm-bookmark-run-browse-project 'helm-only t)
(defvar helm-bookmark-find-files-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map helm-bookmark-map)
(define-key map (kbd "C-c o") 'ignore)
(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
(remove '("Jump to BM other window" . helm-bookmark-jump-other-window)
helm-type-bookmark-actions)
'(("Browse project" . helm-bookmark-browse-project)) 1))
(setf (slot-value source 'keymap) helm-bookmark-find-files-map))
(defclass helm-bookmark-find-files-class (helm-source-filtered-bookmarks
helm-bookmark-override-inheritor)
())
(defvar helm-source-bookmark-helm-find-files
(helm-make-source "Bookmark helm-find-files sessions" 'helm-bookmark-find-files-class
:init (lambda ()
(bookmark-maybe-load-default-file)
(helm-init-candidates-in-buffer
'global (helm-bookmark-helm-find-files-setup-alist)))
:persistent-action (lambda (_candidate) (ignore))
:persistent-help "Do nothing"))
;;; Uncategorized bookmarks
;;
(defun helm-bookmark-uncategorized-setup-alist ()
"Specialized filter function for uncategorized bookmarks."
(helm-bookmark-filter-setup-alist 'helm-bookmark-uncategorized-bookmark-p))
(defvar helm-source-bookmark-uncategorized
(helm-make-source "Bookmark uncategorized" 'helm-source-filtered-bookmarks
:init (lambda ()
(bookmark-maybe-load-default-file)
(helm-init-candidates-in-buffer
'global (helm-bookmark-uncategorized-setup-alist)))))
;;; Transformer
;;
(defun helm-highlight-bookmark (bookmarks _source)
"Used as `filtered-candidate-transformer' to colorize bookmarks."
(let ((non-essential t))
(cl-loop for i in bookmarks
for isfile = (bookmark-get-filename i)
for hff = (helm-bookmark-helm-find-files-p i)
for handlerp = (and (fboundp 'bookmark-get-handler)
(bookmark-get-handler i))
for isw3m = (and (fboundp 'helm-bookmark-w3m-bookmark-p)
(helm-bookmark-w3m-bookmark-p i))
for isgnus = (and (fboundp 'helm-bookmark-gnus-bookmark-p)
(helm-bookmark-gnus-bookmark-p i))
for isman = (and (fboundp 'helm-bookmark-man-bookmark-p) ; Man
(helm-bookmark-man-bookmark-p i))
for iswoman = (and (fboundp 'helm-bookmark-woman-bookmark-p) ; Woman
(helm-bookmark-woman-bookmark-p i))
for isannotation = (bookmark-get-annotation i)
for isabook = (string= (bookmark-prop-get i 'type)
"addressbook")
for isinfo = (eq handlerp 'Info-bookmark-jump)
for loc = (bookmark-location i)
for len = (string-width i)
for trunc = (if (and helm-bookmark-show-location
(> len bookmark-bmenu-file-column))
(helm-substring
i bookmark-bmenu-file-column)
i)
;; Add a * if bookmark have annotation
if (and isannotation (not (string-equal isannotation "")))
do (setq trunc (concat "*" (if helm-bookmark-show-location trunc i)))
for sep = (and helm-bookmark-show-location
(make-string (- (+ bookmark-bmenu-file-column 2)
(string-width trunc))
? ))
for bmk = (cond ( ;; info buffers
isinfo
(propertize trunc 'face 'helm-bookmark-info
'help-echo isfile))
( ;; w3m buffers
isw3m
(propertize trunc 'face 'helm-bookmark-w3m
'help-echo isfile))
( ;; gnus buffers
isgnus
(propertize trunc 'face 'helm-bookmark-gnus
'help-echo isfile))
( ;; Man Woman
(or iswoman isman)
(propertize trunc 'face 'helm-bookmark-man
'help-echo isfile))
( ;; Addressbook
isabook
(propertize trunc 'face 'helm-bookmark-addressbook))
(;; Directories (helm-find-files)
hff
(if (and (file-remote-p isfile)
(not (file-remote-p isfile nil t)))
(propertize trunc 'face 'helm-bookmark-file-not-found
'help-echo isfile)
(propertize trunc 'face 'helm-bookmark-directory
'help-echo isfile)))
( ;; Directories (dired)
(and isfile
;; This is needed because `non-essential'
;; is not working on Emacs-24.2 and the behavior
;; of tramp seems to have changed since previous
;; versions (Need to reenter password even if a
;; first connection have been established,
;; probably when host is named differently
;; i.e machine/localhost)
(and (not (file-remote-p isfile))
(file-directory-p isfile)))
(propertize trunc 'face 'helm-bookmark-directory
'help-echo isfile))
( ;; Non existing files.
(and isfile
;; Be safe and call `file-exists-p'
;; only if file is not remote or
;; remote but connected.
(or (and (file-remote-p isfile)
(not (file-remote-p isfile nil t)))
(not (file-exists-p isfile))))
(propertize trunc 'face 'helm-bookmark-file-not-found
'help-echo isfile))
( ;; regular files
t
(propertize trunc 'face 'helm-bookmark-file
'help-echo isfile)))
collect (if helm-bookmark-show-location
(cons (concat bmk sep (if (listp loc) (car loc) loc))
i)
(cons bmk i)))))
;;; Edit/rename/save bookmarks.
;;
;;
(defun helm-bookmark-edit-bookmark (bookmark-name)
"Edit bookmark's name and file name, and maybe save them.
BOOKMARK-NAME is the current (old) name of the bookmark to be renamed."
(let ((bmk (helm-bookmark-get-bookmark-from-name bookmark-name))
(handler (bookmark-prop-get bookmark-name 'handler)))
(if (eq handler 'addressbook-bookmark-jump)
(addressbook-bookmark-edit
(assoc bmk bookmark-alist))
(helm-bookmark-edit-bookmark-1 bookmark-name handler))))
(defun helm-bookmark-edit-bookmark-1 (bookmark-name handler)
(let* ((helm--reading-passwd-or-string t)
(bookmark-fname (bookmark-get-filename bookmark-name))
(bookmark-loc (bookmark-prop-get bookmark-name 'location))
(new-name (read-from-minibuffer "Name: " bookmark-name))
(new-loc (read-from-minibuffer "FileName or Location: "
(or bookmark-fname
(if (consp bookmark-loc)
(car bookmark-loc)
bookmark-loc))))
(docid (and (eq handler 'mu4e-bookmark-jump)
(read-number "Docid: " (cdr bookmark-loc)))))
(when docid
(setq new-loc (cons new-loc docid)))
(when (and (not (equal new-name "")) (not (equal new-loc ""))
(y-or-n-p "Save changes? "))
(if bookmark-fname
(progn
(helm-bookmark-rename bookmark-name new-name 'batch)
(bookmark-set-filename new-name new-loc))
(bookmark-prop-set
(bookmark-get-bookmark bookmark-name) 'location new-loc)
(helm-bookmark-rename bookmark-name new-name 'batch))
(helm-bookmark-maybe-save-bookmark)
(list new-name new-loc))))
(defun helm-bookmark-maybe-save-bookmark ()
"Increment save counter and maybe save `bookmark-alist'."
(setq bookmark-alist-modification-count (1+ bookmark-alist-modification-count))
(when (bookmark-time-to-save-p) (bookmark-save)))
(defun helm-bookmark-rename (old &optional new batch)
"Change bookmark's name from OLD to NEW.
Interactively:
If called from the keyboard, then prompt for OLD.
If called from the menubar, select OLD from a menu.
If NEW is nil, then prompt for its string value.
If BATCH is non-nil, then do not rebuild the menu list.
While the user enters the new name, repeated `C-w' inserts consecutive
words from the buffer into the new bookmark name."
(interactive (list (bookmark-completing-read "Old bookmark name")))
(bookmark-maybe-historicize-string old)
(bookmark-maybe-load-default-file)
(save-excursion (skip-chars-forward " ") (setq bookmark-yank-point (point)))
(setq bookmark-current-buffer (current-buffer))
(let ((newname (or new (read-from-minibuffer
"New name: " nil
(let ((now-map (copy-keymap minibuffer-local-map)))
(define-key now-map "\C-w" 'bookmark-yank-word)
now-map)
nil 'bookmark-history))))
(bookmark-set-name old newname)
(setq bookmark-current-bookmark newname)
(unless batch (bookmark-bmenu-surreptitiously-rebuild-list))
(helm-bookmark-maybe-save-bookmark) newname))
(defun helm-bookmark-run-edit ()
"Run `helm-bookmark-edit-bookmark' from keyboard."
(interactive)
(with-helm-alive-p
(helm-exit-and-execute-action 'helm-bookmark-edit-bookmark)))
(put 'helm-bookmark-run-edit 'helm-only t)
(defun helm-bookmark-run-jump-other-window ()
"Jump to bookmark from keyboard."
(interactive)
(with-helm-alive-p
(helm-exit-and-execute-action 'helm-bookmark-jump-other-window)))
(put 'helm-bookmark-run-jump-other-window 'helm-only t)
(defun helm-bookmark-run-delete ()
"Delete bookmark from keyboard."
(interactive)
(with-helm-alive-p
(when (y-or-n-p "Delete bookmark(s)?")
(helm-exit-and-execute-action 'helm-delete-marked-bookmarks))))
(put 'helm-bookmark-run-delete 'helm-only t)
(defun helm-bookmark-get-bookmark-from-name (bmk)
"Return bookmark name even if it is a bookmark with annotation.
e.g prepended with *."
(let ((bookmark (replace-regexp-in-string "\\`\\*" "" bmk)))
(if (assoc bookmark bookmark-alist) bookmark bmk)))
(defun helm-delete-marked-bookmarks (_ignore)
"Delete this bookmark or all marked bookmarks."
(cl-dolist (i (helm-marked-candidates))
(bookmark-delete (helm-bookmark-get-bookmark-from-name i)
'batch)))
;;;###autoload
(defun helm-bookmarks ()
"Preconfigured `helm' for bookmarks."
(interactive)
(helm :sources '(helm-source-bookmarks
helm-source-bookmark-set)
:buffer "*helm bookmarks*"
:default (buffer-name helm-current-buffer)))
;;;###autoload
(defun helm-filtered-bookmarks ()
"Preconfigured helm for bookmarks (filtered by category).
Optional source `helm-source-bookmark-addressbook' is loaded
only if external addressbook-bookmark package is installed."
(interactive)
(helm :sources helm-bookmark-default-filtered-sources
:prompt "Search Bookmark: "
:buffer "*helm filtered bookmarks*"
:default (list (thing-at-point 'symbol)
(buffer-name helm-current-buffer))))
(provide 'helm-bookmark)
;; Local Variables:
;; byte-compile-warnings: (not obsolete)
;; coding: utf-8
;; indent-tabs-mode: nil
;; End:
;;; helm-bookmark.el ends here

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,170 @@
;;; helm-color.el --- colors and faces -*- lexical-binding: t -*-
;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Code:
(require 'cl-lib)
(require 'helm)
(require 'helm-help)
(require 'helm-elisp)
;;; Customize Face
;;
;;
(defun helm-custom-faces-init ()
"Initialize buffer for `helm-source-customize-face'."
(unless (helm-candidate-buffer)
(save-selected-window
(list-faces-display)
(message nil))
(helm-init-candidates-in-buffer
'global
(with-current-buffer (get-buffer "*Faces*")
(buffer-substring
(next-single-char-property-change (point-min) 'face)
(point-max))))
(kill-buffer "*Faces*")))
(defvar helm-source-customize-face
(helm-build-in-buffer-source "Customize Face"
:init 'helm-custom-faces-init
:get-line 'buffer-substring
:persistent-action (lambda (candidate)
(helm-elisp--persistent-help
(intern (car (split-string candidate)))
'helm-describe-face))
:persistent-help "Describe face"
:action '(("Customize"
. (lambda (line)
(customize-face (intern (car (split-string line))))))
("Copy name"
. (lambda (line)
(kill-new (car (split-string line " " t)))))))
"See (info \"(emacs)Faces\")")
;;; Colors browser
;;
;;
(defun helm-colors-init ()
(unless (helm-candidate-buffer)
(save-selected-window
(list-colors-display)
(message nil))
(helm-init-candidates-in-buffer
'global
(with-current-buffer (get-buffer "*Colors*")
(buffer-string)))
(kill-buffer "*Colors*")))
(defun helm-color-insert-name (candidate)
(with-helm-current-buffer
(insert (helm-colors-get-name candidate))))
(defun helm-color-kill-name (candidate)
(kill-new (helm-colors-get-name candidate)))
(defun helm-color-insert-rgb (candidate)
(with-helm-current-buffer
(insert (helm-colors-get-rgb candidate))))
(defun helm-color-kill-rgb (candidate)
(kill-new (helm-colors-get-rgb candidate)))
(defun helm-color-run-insert-name ()
"Insert name of color from `helm-source-colors'"
(interactive)
(with-helm-alive-p (helm-exit-and-execute-action 'helm-color-insert-name)))
(put 'helm-color-run-insert-name 'helm-only t)
(defun helm-color-run-kill-name ()
"Kill name of color from `helm-source-colors'"
(interactive)
(with-helm-alive-p (helm-exit-and-execute-action 'helm-color-kill-name)))
(put 'helm-color-run-kill-name 'helm-only t)
(defun helm-color-run-insert-rgb ()
"Insert RGB of color from `helm-source-colors'"
(interactive)
(with-helm-alive-p (helm-exit-and-execute-action 'helm-color-insert-rgb)))
(put 'helm-color-run-insert-rgb 'helm-only t)
(defun helm-color-run-kill-rgb ()
"Kill RGB of color from `helm-source-colors'"
(interactive)
(with-helm-alive-p (helm-exit-and-execute-action 'helm-color-kill-rgb)))
(put 'helm-color-run-kill-rgb 'helm-only t)
(defvar helm-color-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map helm-map)
(define-key map (kbd "C-c n") 'helm-color-run-insert-name)
(define-key map (kbd "C-c N") 'helm-color-run-kill-name)
(define-key map (kbd "C-c r") 'helm-color-run-insert-rgb)
(define-key map (kbd "C-c R") 'helm-color-run-kill-rgb)
map))
(defvar helm-source-colors
(helm-build-in-buffer-source "Colors"
:init 'helm-colors-init
:get-line 'buffer-substring
:keymap helm-color-map
:persistent-help "Kill entry in RGB format."
:persistent-action 'helm-color-kill-rgb
:help-message 'helm-colors-help-message
:action
'(("Copy Name (C-c N)" . helm-color-kill-name)
("Copy RGB (C-c R)" . helm-color-kill-rgb)
("Insert Name (C-c n)" . helm-color-insert-name)
("Insert RGB (C-c r)" . helm-color-insert-rgb))))
(defun helm-colors-get-name (candidate)
"Get color name."
(replace-regexp-in-string
" " ""
(with-temp-buffer
(insert (capitalize candidate))
(goto-char (point-min))
(search-forward-regexp "\\s-\\{2,\\}")
(delete-region (point) (point-max))
(buffer-string))))
(defun helm-colors-get-rgb (candidate)
"Get color RGB."
(replace-regexp-in-string
" " ""
(with-temp-buffer
(insert (capitalize candidate))
(goto-char (point-max))
(search-backward-regexp "\\s-\\{2,\\}")
(delete-region (point) (point-min))
(buffer-string))))
;;;###autoload
(defun helm-colors ()
"Preconfigured `helm' for color."
(interactive)
(helm :sources '(helm-source-colors helm-source-customize-face)
:buffer "*helm colors*"))
(provide 'helm-color)
;; Local Variables:
;; byte-compile-warnings: (not obsolete)
;; coding: utf-8
;; indent-tabs-mode: nil
;; End:
;;; helm-color.el ends here

View File

@@ -0,0 +1,306 @@
;;; helm-command.el --- Helm execute-exended-command. -*- lexical-binding: t -*-
;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Code:
(require 'cl-lib)
(require 'helm)
(require 'helm-help)
(require 'helm-mode)
(require 'helm-elisp)
(defgroup helm-command nil
"Emacs command related Applications and libraries for Helm."
:group 'helm)
(defcustom helm-M-x-requires-pattern 0
"Value of requires-pattern for `helm-M-x'.
Show all candidates on startup when 0 (default)."
:group 'helm-command
:type 'boolean)
(defcustom helm-M-x-always-save-history nil
"`helm-M-x' Save command in `extended-command-history' even when it fail."
:group 'helm-command
:type 'boolean)
(defcustom helm-M-x-reverse-history nil
"The history source of `helm-M-x' appear in second position when non--nil."
:group 'helm-command
:type 'boolean)
(defcustom helm-M-x-fuzzy-match nil
"Enable fuzzy matching in `helm-M-x' when non--nil."
:group 'helm-command
:type 'boolean)
(defcustom helm-M-x-default-sort-fn #'helm-M-x-fuzzy-sort-candidates
"Default sort function for `helm-M-x'.
It should sort against REAL value of candidates.
It is used only when `helm-M-x-fuzzy-match' is enabled."
:group 'helm-command
:type 'function)
;;; Faces
;;
;;
(defgroup helm-command-faces nil
"Customize the appearance of helm-command."
:prefix "helm-"
:group 'helm-command
:group 'helm-faces)
(defface helm-M-x-key '((t (:foreground "orange" :underline t)))
"Face used in helm-M-x to show keybinding."
:group 'helm-command-faces)
(defvar helm-M-x-input-history nil)
(defvar helm-M-x-prefix-argument nil
"Prefix argument before calling `helm-M-x'.")
(defun helm-M-x-get-major-mode-command-alist (mode-map)
"Return alist of MODE-MAP."
(when mode-map
(cl-loop for key being the key-seqs of mode-map using (key-bindings com)
for str-key = (key-description key)
for ismenu = (string-match "<menu-bar>" str-key)
unless ismenu collect (cons str-key com))))
(defun helm-get-mode-map-from-mode (mode)
"Guess the mode-map name according to MODE.
Some modes don't use conventional mode-map name
so we need to guess mode-map name. e.g python-mode ==> py-mode-map.
Return nil if no mode-map found."
(cl-loop ;; Start with a conventional mode-map name.
with mode-map = (intern-soft (format "%s-map" mode))
with mode-string = (symbol-name mode)
with mode-name = (replace-regexp-in-string "-mode" "" mode-string)
while (not mode-map)
for count downfrom (length mode-name)
;; Return when no result after parsing entire string.
when (eq count 0) return nil
for sub-name = (substring mode-name 0 count)
do (setq mode-map (intern-soft (format "%s-map" (concat sub-name "-mode"))))
finally return mode-map))
(defun helm-M-x-current-mode-map-alist ()
"Return mode-map alist of current `major-mode'."
(let ((map-sym (helm-get-mode-map-from-mode major-mode)))
(when (and map-sym (boundp map-sym))
(helm-M-x-get-major-mode-command-alist (symbol-value map-sym)))))
(defun helm-M-x-transformer-1 (candidates &optional sort)
"Transformer function to show bindings in emacs commands.
Show global bindings and local bindings according to current `major-mode'.
If SORT is non nil sort list with `helm-generic-sort-fn'.
Note that SORT should not be used when fuzzy matching because
fuzzy matching is running its own sort function with a different algorithm."
(with-helm-current-buffer
(cl-loop with local-map = (helm-M-x-current-mode-map-alist)
for cand in candidates
for local-key = (car (rassq cand local-map))
for key = (substitute-command-keys (format "\\[%s]" cand))
unless (get (intern (if (consp cand) (car cand) cand)) 'helm-only)
collect
(cons (cond ((and (string-match "^M-x" key) local-key)
(format "%s (%s)"
cand (propertize
local-key
'face 'helm-M-x-key)))
((string-match "^M-x" key) cand)
(t (format "%s (%s)"
cand (propertize
key
'face 'helm-M-x-key))))
cand)
into ls
finally return
(if sort (sort ls #'helm-generic-sort-fn) ls))))
(defun helm-M-x-transformer (candidates _source)
"Transformer function for `helm-M-x' candidates."
(helm-M-x-transformer-1 candidates (null helm--in-fuzzy)))
(defun helm-M-x-transformer-hist (candidates _source)
"Transformer function for `helm-M-x' candidates."
(helm-M-x-transformer-1 candidates))
(defun helm-M-x--notify-prefix-arg ()
;; Notify a prefix-arg set AFTER calling M-x.
(when prefix-arg
(with-helm-window
(helm-display-mode-line (helm-get-current-source) 'force))))
(defun helm-cmd--get-current-function-name ()
(save-excursion
(beginning-of-defun)
(cadr (split-string (buffer-substring-no-properties
(point-at-bol) (point-at-eol))))))
(defun helm-cmd--get-preconfigured-commands (&optional dir)
(let* ((helm-dir (or dir (helm-basedir (locate-library "helm"))))
(helm-autoload-file (expand-file-name "helm-autoloads.el" helm-dir))
results)
(when (file-exists-p helm-autoload-file)
(with-temp-buffer
(insert-file-contents helm-autoload-file)
(while (re-search-forward "Preconfigured" nil t)
(push (substring (helm-cmd--get-current-function-name) 1) results))))
results))
(defvar helm-M-x-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map helm-comp-read-map)
(define-key map (kbd "C-u") nil)
(define-key map (kbd "C-u") 'helm-M-x-universal-argument)
map))
(defun helm-M-x-universal-argument ()
"Same as `universal-argument' but for `helm-M-x'."
(interactive)
(if helm-M-x-prefix-argument
(progn (setq helm-M-x-prefix-argument nil)
(let ((inhibit-read-only t))
(with-selected-window (minibuffer-window)
(save-excursion
(goto-char (point-min))
(delete-char (- (minibuffer-prompt-width) (length "M-x "))))))
(message "Initial prefix arg disabled"))
(setq prefix-arg (list 4))
(universal-argument--mode)))
(put 'helm-M-x-universal-argument 'helm-only t)
(defun helm-M-x-fuzzy-sort-candidates (candidates _source)
(helm-fuzzy-matching-default-sort-fn-1 candidates t))
(defun helm-M-x-read-extended-command (&optional collection history)
"Read command name to invoke in `helm-M-x'.
Helm completion is not provided when executing or defining
kbd macros.
Optional arg COLLECTION is to allow using another COLLECTION
than the default which is OBARRAY."
(if (or defining-kbd-macro executing-kbd-macro)
(if helm-mode
(unwind-protect
(progn
(helm-mode -1)
(read-extended-command))
(helm-mode 1))
(read-extended-command))
(let* ((helm-fuzzy-sort-fn helm-M-x-default-sort-fn)
(helm--mode-line-display-prefarg t)
(tm (run-at-time 1 0.1 'helm-M-x--notify-prefix-arg))
(helm-move-selection-after-hook
(cons (lambda () (setq current-prefix-arg nil))
helm-move-selection-after-hook)))
(setq extended-command-history
(cl-loop for c in extended-command-history
when (and c (commandp (intern c)))
do (set-text-properties 0 (length c) nil c)
and collect c))
(unwind-protect
(progn
(setq current-prefix-arg nil)
(helm-comp-read
(concat (cond
((eq helm-M-x-prefix-argument '-) "- ")
((and (consp helm-M-x-prefix-argument)
(eq (car helm-M-x-prefix-argument) 4)) "C-u ")
((and (consp helm-M-x-prefix-argument)
(integerp (car helm-M-x-prefix-argument)))
(format "%d " (car helm-M-x-prefix-argument)))
((integerp helm-M-x-prefix-argument)
(format "%d " helm-M-x-prefix-argument)))
"M-x ")
(or collection obarray)
:test 'commandp
:requires-pattern helm-M-x-requires-pattern
:name "Emacs Commands"
:buffer "*helm M-x*"
:persistent-action (lambda (candidate)
(helm-elisp--persistent-help
candidate 'helm-describe-function))
:persistent-help "Describe this command"
:history (or history extended-command-history)
:reverse-history helm-M-x-reverse-history
:input-history 'helm-M-x-input-history
:del-input nil
:help-message 'helm-M-x-help-message
:keymap helm-M-x-map
:must-match t
:match-part (lambda (c) (car (split-string c)))
:fuzzy helm-M-x-fuzzy-match
:nomark t
:candidates-in-buffer t
:fc-transformer 'helm-M-x-transformer
:hist-fc-transformer 'helm-M-x-transformer-hist))
(cancel-timer tm)
(setq helm--mode-line-display-prefarg nil)))))
;;;###autoload
(defun helm-M-x (_arg &optional command-name)
"Preconfigured `helm' for Emacs commands.
It is `helm' replacement of regular `M-x' `execute-extended-command'.
Unlike regular `M-x' emacs vanilla `execute-extended-command' command,
the prefix args if needed, can be passed AFTER starting `helm-M-x'.
When a prefix arg is passed BEFORE starting `helm-M-x', the first `C-u'
while in `helm-M-x' session will disable it.
You can get help on each command by persistent action."
(interactive
(progn
(setq helm-M-x-prefix-argument current-prefix-arg)
(list current-prefix-arg (helm-M-x-read-extended-command))))
(unless (string= command-name "")
(let ((sym-com (and (stringp command-name) (intern-soft command-name))))
(when sym-com
;; Avoid having `this-command' set to *exit-minibuffer.
(setq this-command sym-com
;; Handle C-x z (repeat) Issue #322
real-this-command sym-com)
;; If helm-M-x is called with regular emacs completion (kmacro)
;; use the value of arg otherwise use helm-current-prefix-arg.
(let ((prefix-arg (or helm-current-prefix-arg helm-M-x-prefix-argument)))
(cl-flet ((save-hist (command)
(setq extended-command-history
(cons command (delete command extended-command-history)))))
(condition-case-unless-debug err
(progn
(command-execute sym-com 'record)
(save-hist command-name))
(error
(when helm-M-x-always-save-history
(save-hist command-name))
(signal (car err) (cdr err))))))))))
(put 'helm-M-x 'interactive-only 'command-execute)
(provide 'helm-command)
;; Local Variables:
;; byte-compile-warnings: (not obsolete)
;; coding: utf-8
;; indent-tabs-mode: nil
;; End:
;;; helm-command.el ends here

View File

@@ -0,0 +1,172 @@
;;; helm-config.el --- Applications library for `helm.el' -*- lexical-binding: t -*-
;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Code:
;;; Require
;;
;;
(declare-function async-bytecomp-package-mode "ext:async-bytecomp.el")
(when (require 'async-bytecomp nil t)
(and (fboundp 'async-bytecomp-package-mode)
(async-bytecomp-package-mode 1)))
(defgroup helm-config nil
"Various configurations for Helm."
:group 'helm)
(defcustom helm-command-prefix-key "C-x c"
"The key `helm-command-prefix' is bound to in the global map."
:type '(choice (string :tag "Key") (const :tag "no binding"))
:group 'helm-config
:set
(lambda (var key)
(when (and (boundp var) (symbol-value var))
(define-key (current-global-map)
(read-kbd-macro (symbol-value var)) nil))
(when key
(define-key (current-global-map)
(read-kbd-macro key) 'helm-command-prefix))
(set var key)))
(defcustom helm-minibuffer-history-key "C-r"
"The key `helm-minibuffer-history' is bound to in minibuffer local maps."
:type '(choice (string :tag "Key") (const :tag "no binding"))
:group 'helm-config
:set
(lambda (var key)
(cl-dolist (map '(minibuffer-local-completion-map
minibuffer-local-filename-completion-map
minibuffer-local-filename-must-match-map ; Emacs 23.1.+
minibuffer-local-isearch-map
minibuffer-local-map
minibuffer-local-must-match-filename-map ; Older Emacsen
minibuffer-local-must-match-map
minibuffer-local-ns-map))
(when (and (boundp map) (keymapp (symbol-value map)))
(when (and (boundp var) (symbol-value var))
(define-key (symbol-value map)
(read-kbd-macro (symbol-value var)) nil))
(when key
(define-key (symbol-value map)
(read-kbd-macro key) 'helm-minibuffer-history))))
(set var key)))
;;; Command Keymap
;;
;;
(defvar helm-command-map
(let ((map (make-sparse-keymap)))
(define-key map (kbd "a") 'helm-apropos)
(define-key map (kbd "e") 'helm-etags-select)
(define-key map (kbd "l") 'helm-locate)
(define-key map (kbd "s") 'helm-surfraw)
(define-key map (kbd "r") 'helm-regexp)
(define-key map (kbd "m") 'helm-man-woman)
(define-key map (kbd "t") 'helm-top)
(define-key map (kbd "/") 'helm-find)
(define-key map (kbd "i") 'helm-semantic-or-imenu)
(define-key map (kbd "I") 'helm-imenu-in-all-buffers)
(define-key map (kbd "<tab>") 'helm-lisp-completion-at-point)
(define-key map (kbd "p") 'helm-list-emacs-process)
(define-key map (kbd "C-x r b") 'helm-filtered-bookmarks)
(define-key map (kbd "M-y") 'helm-show-kill-ring)
(define-key map (kbd "C-c <SPC>") 'helm-all-mark-rings)
(define-key map (kbd "C-x C-f") 'helm-find-files)
(define-key map (kbd "f") 'helm-multi-files)
(define-key map (kbd "C-:") 'helm-eval-expression-with-eldoc)
(define-key map (kbd "C-,") 'helm-calcul-expression)
(define-key map (kbd "M-x") 'helm-M-x)
(define-key map (kbd "M-s o") 'helm-occur)
(define-key map (kbd "M-g a") 'helm-do-grep-ag)
(define-key map (kbd "c") 'helm-colors)
(define-key map (kbd "F") 'helm-select-xfont)
(define-key map (kbd "8") 'helm-ucs)
(define-key map (kbd "C-c f") 'helm-recentf)
(define-key map (kbd "C-c g") 'helm-google-suggest)
(define-key map (kbd "h i") 'helm-info-at-point)
(define-key map (kbd "h r") 'helm-info-emacs)
(define-key map (kbd "h g") 'helm-info-gnus)
(define-key map (kbd "h h") 'helm-documentation)
(define-key map (kbd "C-x C-b") 'helm-buffers-list)
(define-key map (kbd "C-x r i") 'helm-register)
(define-key map (kbd "C-c C-x") 'helm-run-external-command)
(define-key map (kbd "b") 'helm-resume)
(define-key map (kbd "M-g i") 'helm-gid)
(define-key map (kbd "@") 'helm-list-elisp-packages)
map))
;; Don't override the keymap we just defined with an empty
;; keymap. This also protect bindings changed by the user.
(defvar helm-command-prefix)
(define-prefix-command 'helm-command-prefix)
(fset 'helm-command-prefix helm-command-map)
(setq helm-command-prefix helm-command-map)
;;; Menu
(require 'helm-easymenu)
;;;###autoload
(defun helm-configuration ()
"Customize `helm'."
(interactive)
(customize-group "helm"))
;;; Fontlock
(cl-dolist (mode '(emacs-lisp-mode lisp-interaction-mode))
(font-lock-add-keywords
mode
'(("(\\<\\(with-helm-after-update-hook\\)\\>" 1 font-lock-keyword-face)
("(\\<\\(with-helm-temp-hook\\)\\>" 1 font-lock-keyword-face)
("(\\<\\(with-helm-window\\)\\>" 1 font-lock-keyword-face)
("(\\<\\(with-helm-quittable\\)\\>" 1 font-lock-keyword-face)
("(\\<\\(with-helm-current-buffer\\)\\>" 1 font-lock-keyword-face)
("(\\<\\(with-helm-buffer\\)\\>" 1 font-lock-keyword-face)
("(\\<\\(with-helm-show-completion\\)\\>" 1 font-lock-keyword-face)
("(\\<\\(with-helm-default-directory\\)\\>" 1 font-lock-keyword-face)
("(\\<\\(with-helm-restore-variables\\)\\>" 1 font-lock-keyword-face)
("(\\<\\(helm-multi-key-defun\\)\\>" 1 font-lock-keyword-face)
("(\\<\\(helm-while-no-input\\)\\>" 1 font-lock-keyword-face)
("(\\<\\(helm-aif\\)\\>" 1 font-lock-keyword-face)
("(\\<\\(helm-awhile\\)\\>" 1 font-lock-keyword-face)
("(\\<\\(helm-acond\\)\\>" 1 font-lock-keyword-face)
("(\\<\\(helm-aand\\)\\>" 1 font-lock-keyword-face)
("(\\<\\(helm-with-gensyms\\)\\>" 1 font-lock-keyword-face)
("(\\<\\(helm-read-answer\\)\\>" 1 font-lock-keyword-face))))
;;; Load the autoload file
;; It should have been generated either by
;; package.el or the make file.
(load "helm-autoloads" nil t)
(provide 'helm-config)
;; Local Variables:
;; byte-compile-warnings: (not obsolete)
;; coding: utf-8
;; indent-tabs-mode: nil
;; End:
;;; helm-config.el ends here

View File

@@ -0,0 +1,351 @@
;;; helm-dabbrev.el --- Helm implementation of dabbrev. -*- lexical-binding: t -*-
;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Code:
(require 'helm)
(require 'helm-lib)
(require 'helm-help)
(require 'helm-elisp) ; For show-completion.
(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-candidates-number-limit 600
"Maximum number of candidates to collect before stopping.
Higher this number is slower the computation of candidates will be."
: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)))
(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--exclude-current-buffer-flag nil)
(defvar helm-dabbrev--cache nil)
(defvar helm-dabbrev--data nil)
(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 (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)))))))
(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.
;; 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) return (nreverse result)
finally return (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 (abbrev)
(cl-assert abbrev nil "[No Match]")
(with-current-buffer (current-buffer)
(let* ((dabbrev-get (lambda (str all-bufs)
(helm-dabbrev--collect
str helm-dabbrev-candidates-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-separator-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-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 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
:group 'helm-dabbrev)
:buffer "*helm dabbrev*"
:input (concat "^" dabbrev " ")
:resume 'noresume
:allow-nest t)))))))
(provide 'helm-dabbrev)
;; Local Variables:
;; byte-compile-warnings: (not obsolete)
;; coding: utf-8
;; indent-tabs-mode: nil
;; End:
;;; helm-dabbrev.el ends here

View File

@@ -0,0 +1,90 @@
;;; helm-easymenu.el --- Helm easymenu definitions. -*- lexical-binding: t -*-
;; Copyright (C) 2015 ~ 2018 Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Code:
(require 'easymenu)
(easy-menu-add-item
nil '("Tools")
'("Helm"
["Find any Files/Buffers" helm-multi-files t]
["Helm Everywhere (Toggle)" helm-mode t]
["Helm resume" helm-resume t]
"----"
("Files"
["Find files" helm-find-files t]
["Recent Files" helm-recentf t]
["Locate" helm-locate t]
["Search Files with find" helm-find t]
["Bookmarks" helm-filtered-bookmarks t])
("Buffers"
["Find buffers" helm-buffers-list t])
("Commands"
["Emacs Commands" helm-M-x t]
["Externals Commands" helm-run-external-command t])
("Help"
["Helm Apropos" helm-apropos t])
("Info"
["Info at point" helm-info-at-point t]
["Emacs Manual index" helm-info-emacs t]
["Gnus Manual index" helm-info-gnus t]
["Helm documentation" helm-documentation t])
("Org"
["Org headlines in org agenda files" helm-org-agenda-files-headings t]
["Org headlines in buffer" helm-org-in-buffer-headings t])
("Elpa"
["Elisp packages" helm-list-elisp-packages t]
["Elisp packages no fetch" helm-list-elisp-packages-no-fetch t])
("Tools"
["Occur" helm-occur t]
["Grep current directory with AG" helm-do-grep-ag t]
["Gid" helm-gid t]
["Etags" helm-etags-select t]
["Lisp complete at point" helm-lisp-completion-at-point t]
["Browse Kill ring" helm-show-kill-ring t]
["Browse register" helm-register t]
["Mark Ring" helm-all-mark-rings t]
["Regexp handler" helm-regexp t]
["Colors & Faces" helm-colors t]
["Show xfonts" helm-select-xfont t]
["Ucs Symbols" helm-ucs t]
["Imenu" helm-imenu t]
["Imenu all" helm-imenu-in-all-buffers t]
["Semantic or Imenu" helm-semantic-or-imenu t]
["Google Suggest" helm-google-suggest t]
["Eval expression" helm-eval-expression-with-eldoc t]
["Calcul expression" helm-calcul-expression t]
["Man pages" helm-man-woman t]
["Top externals process" helm-top t]
["Emacs internals process" helm-list-emacs-process t])
"----"
["Preferred Options" helm-configuration t])
"Spell Checking")
(easy-menu-add-item nil '("Tools") '("----") "Spell Checking")
(provide 'helm-easymenu)
;; Local Variables:
;; byte-compile-warnings: (not obsolete)
;; coding: utf-8
;; indent-tabs-mode: nil
;; End:
;;; helm-easymenu.el ends here

View File

@@ -0,0 +1,467 @@
;;; helm-elisp-package.el --- helm interface for package.el -*- lexical-binding: t -*-
;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Code:
(require 'cl-lib)
(require 'helm)
(require 'helm-help)
(require 'package)
(defgroup helm-el-package nil
"helm elisp packages."
:group 'helm)
(defcustom helm-el-package-initial-filter 'all
"Show only installed, upgraded or all packages at startup."
:group 'helm-el-package
:type '(radio :tag "Initial filter for elisp packages"
(const :tag "Show all packages" all)
(const :tag "Show installed packages" installed)
(const :tag "Show not installed packages" uninstalled)
(const :tag "Show upgradable packages" upgrade)))
(defcustom helm-el-truncate-lines t
"Truncate lines in helm-buffer when non--nil."
:group 'helm-el-package
:type 'boolean)
;; internals vars
(defvar helm-el-package--show-only 'all)
(defvar helm-el-package--initialized-p nil)
(defvar helm-el-package--tabulated-list nil)
(defvar helm-el-package--upgrades nil)
(defvar helm-el-package--removable-packages nil)
;; Shutup bytecompiler for emacs-24*
(defvar package-menu-async) ; Only available on emacs-25.
(declare-function async-byte-recompile-directory "ext:async-bytecomp.el")
(defun helm-el-package--init ()
(let (package-menu-async
(inhibit-read-only t))
(when (null package-alist)
(setq helm-el-package--show-only 'all))
(when (and (fboundp 'package--removable-packages)
(setq helm-el-package--removable-packages
(package--removable-packages))
(fboundp 'package-autoremove))
(package-autoremove))
(unwind-protect
(progn
(save-selected-window
(if (and helm-el-package--initialized-p
(fboundp 'package-show-package-list))
;; Use this as `list-packages' doesn't work
;; properly (empty buffer) when called from lisp
;; with 'no-fetch (emacs-25 WA).
(package-show-package-list)
(when helm--force-updating-p (message "Refreshing packages list..."))
(list-packages helm-el-package--initialized-p))
(setq helm-el-package--initialized-p t)
(message nil))
(helm-init-candidates-in-buffer
'global
(with-current-buffer (get-buffer "*Packages*")
(setq helm-el-package--tabulated-list tabulated-list-entries)
(remove-text-properties (point-min) (point-max)
'(read-only button follow-link category))
(buffer-string)))
(setq helm-el-package--upgrades (helm-el-package-menu--find-upgrades))
(if helm--force-updating-p
(if helm-el-package--upgrades
(message "Refreshing packages list done, [%d] package(s) to upgrade"
(length helm-el-package--upgrades))
(message "Refreshing packages list done, no upgrades available"))
(setq helm-el-package--show-only (if helm-el-package--upgrades
'upgrade
helm-el-package-initial-filter))))
(kill-buffer "*Packages*"))))
(defun helm-el-package-describe (candidate)
(let ((id (get-text-property 0 'tabulated-list-id candidate)))
(describe-package (if (fboundp 'package-desc-name)
(package-desc-name id)
(car id)))))
(defun helm-el-package-visit-homepage (candidate)
(let* ((id (get-text-property 0 'tabulated-list-id candidate))
(pkg (if (fboundp 'package-desc-name) (package-desc-name id)
(car id)))
(desc (cadr (assoc pkg package-archive-contents)))
(extras (package-desc-extras desc))
(url (and (listp extras) (cdr-safe (assoc :url extras)))))
(if (stringp url)
(browse-url url)
(message "Package %s has no homepage"
(propertize (symbol-name pkg)
'face 'font-lock-keyword-face)))))
(defun helm-el-run-visit-homepage ()
(interactive)
(with-helm-alive-p
(helm-exit-and-execute-action 'helm-el-package-visit-homepage)))
(put 'helm-el-run-visit-homepage 'helm-only t)
(defun helm-el-package-install-1 (pkg-list)
(cl-loop with mkd = pkg-list
for p in mkd
for id = (get-text-property 0 'tabulated-list-id p)
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 (if (fboundp 'package-desc-full-name)
(message (format "%d packages installed:\n(%s)"
(length installed-list)
(mapconcat #'package-desc-full-name
installed-list ", ")))
(message (format "%d packages installed:\n(%s)"
(length installed-list)
(mapconcat 'symbol-name installed-list ", "))))))
(defun helm-el-package-install (_candidate)
(helm-el-package-install-1 (helm-marked-candidates)))
(defun helm-el-run-package-install ()
(interactive)
(with-helm-alive-p
(helm-exit-and-execute-action 'helm-el-package-install)))
(put 'helm-el-run-package-install 'helm-only t)
(defun helm-el-package-uninstall-1 (pkg-list &optional force)
(cl-loop with mkd = pkg-list
for p in mkd
for id = (get-text-property 0 'tabulated-list-id p)
do
(condition-case-unless-debug err
(with-no-warnings
(if (fboundp 'package-desc-full-name)
;; emacs 24.4
(condition-case nil
(package-delete id force)
(wrong-number-of-arguments
(package-delete id)))
;; emacs 24.3
(package-delete (symbol-name (car id))
(package-version-join (cdr id)))))
(error (message (cadr err))))
;; Seems like package-descs are symbols with props instead of
;; vectors in emacs-27, use package-desc-name to ensure
;; compatibility in all emacs versions.
unless (assoc (package-desc-name id) package-alist)
collect (if (fboundp 'package-desc-full-name)
id
(cons (symbol-name (car id))
(package-version-join (cdr id))))
into delete-list
finally do (if delete-list
(if (fboundp 'package-desc-full-name)
;; emacs 24.4
(message (format "%d packages deleted:\n(%s)"
(length delete-list)
(mapconcat #'package-desc-full-name
delete-list ", ")))
;; emacs 24.3
(message (format "%d packages deleted:\n(%s)"
(length delete-list)
(mapconcat (lambda (x)
(concat (car x) "-" (cdr x)))
delete-list ", ")))
;; emacs 24.3 doesn't update
;; its `package-alist' after deleting.
(cl-loop for p in package-alist
when (assq (symbol-name (car p)) delete-list)
do (setq package-alist (delete p package-alist))))
"No package deleted")))
(defun helm-el-package-uninstall (_candidate)
(helm-el-package-uninstall-1 (helm-marked-candidates) helm-current-prefix-arg))
(defun helm-el-run-package-uninstall ()
(interactive)
(with-helm-alive-p
(helm-exit-and-execute-action 'helm-el-package-uninstall)))
(put 'helm-el-run-package-uninstall 'helm-only t)
(defun helm-el-package-menu--find-upgrades ()
(cl-loop for entry in helm-el-package--tabulated-list
for pkg-desc = (car entry)
for status = (package-desc-status pkg-desc)
when (member status '("installed" "unsigned" "dependency"))
collect pkg-desc
into installed
when (member status '("available" "new"))
collect (cons (package-desc-name pkg-desc) pkg-desc)
into available
finally return
(cl-loop for pkg in installed
for avail-pkg = (assq (package-desc-name pkg) available)
when (and avail-pkg
(version-list-< (package-desc-version pkg)
(package-desc-version
(cdr avail-pkg))))
collect avail-pkg)))
(defun helm-el-package-upgrade-1 (pkg-list)
(cl-loop for p in pkg-list
for pkg-desc = (car p)
for upgrade = (cdr (assq (package-desc-name pkg-desc)
helm-el-package--upgrades))
do
(cond ((null upgrade)
(ignore))
((equal pkg-desc upgrade)
;;Install.
(with-no-warnings
(if (boundp 'package-selected-packages)
(package-install pkg-desc t)
(package-install pkg-desc))))
(t
;; Delete.
(if (boundp 'package-selected-packages)
(with-no-warnings
(package-delete pkg-desc t t))
(package-delete pkg-desc))))))
(defun helm-el-package-upgrade (_candidate)
(helm-el-package-upgrade-1
(cl-loop with pkgs = (helm-marked-candidates)
for p in helm-el-package--tabulated-list
for pkg = (car p)
if (member (symbol-name (package-desc-name pkg)) pkgs)
collect p)))
(defun helm-el-run-package-upgrade ()
(interactive)
(with-helm-alive-p
(helm-exit-and-execute-action 'helm-el-package-upgrade)))
(put 'helm-el-run-package-upgrade 'helm-only t)
(defun helm-el-package-upgrade-all ()
(if helm-el-package--upgrades
(with-helm-display-marked-candidates
helm-marked-buffer-name (mapcar (lambda (x) (symbol-name (car x)))
helm-el-package--upgrades)
(when (y-or-n-p "Upgrade all packages? ")
(helm-el-package-upgrade-1 helm-el-package--tabulated-list)))
(message "No packages to upgrade actually!")))
(defun helm-el-package-upgrade-all-action (_candidate)
(helm-el-package-upgrade-all))
(defun helm-el-run-package-upgrade-all ()
(interactive)
(with-helm-alive-p
(helm-exit-and-execute-action 'helm-el-package-upgrade-all-action)))
(put 'helm-el-run-package-upgrade-all 'helm-only t)
(defun helm-el-package--transformer (candidates _source)
(cl-loop for c in candidates
for id = (get-text-property 0 'tabulated-list-id c)
for name = (if (fboundp 'package-desc-name)
(and id (package-desc-name id))
(car id))
for desc = (package-desc-status id)
for built-in-p = (and (package-built-in-p name)
(not (member desc '("available" "new"
"installed" "dependency"))))
for installed-p = (member desc '("installed" "dependency"))
for upgrade-p = (assq name helm-el-package--upgrades)
for user-installed-p = (and (boundp 'package-selected-packages)
(memq name package-selected-packages))
do (when user-installed-p (put-text-property 0 2 'display "S " c))
do (when (memq name helm-el-package--removable-packages)
(put-text-property 0 2 'display "U " c)
(put-text-property
2 (+ (length (symbol-name name)) 2)
'face 'font-lock-variable-name-face c))
for cand = (cons c (car (split-string c)))
when (or (and built-in-p
(eq helm-el-package--show-only 'built-in))
(and upgrade-p
(eq helm-el-package--show-only 'upgrade))
(and installed-p
(eq helm-el-package--show-only 'installed))
(and (not installed-p)
(not built-in-p)
(eq helm-el-package--show-only 'uninstalled))
(eq helm-el-package--show-only 'all))
collect cand))
(defun helm-el-package-show-built-in ()
(interactive)
(with-helm-alive-p
(setq helm-el-package--show-only 'built-in)
(helm-update)))
(put 'helm-el-package-show-built-in 'helm-only t)
(defun helm-el-package-show-upgrade ()
(interactive)
(with-helm-alive-p
(setq helm-el-package--show-only 'upgrade)
(helm-update)))
(put 'helm-el-package-show-upgrade 'helm-only t)
(defun helm-el-package-show-installed ()
(interactive)
(with-helm-alive-p
(setq helm-el-package--show-only 'installed)
(helm-update)))
(put 'helm-el-package-show-installed 'helm-only t)
(defun helm-el-package-show-all ()
(interactive)
(with-helm-alive-p
(setq helm-el-package--show-only 'all)
(helm-update)))
(put 'helm-el-package-show-all 'helm-only t)
(defun helm-el-package-show-uninstalled ()
(interactive)
(with-helm-alive-p
(setq helm-el-package--show-only 'uninstalled)
(helm-update)))
(put 'helm-el-package-show-uninstalled 'helm-only t)
(defvar helm-el-package-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map helm-map)
(define-key map (kbd "M-I") 'helm-el-package-show-installed)
(define-key map (kbd "M-O") 'helm-el-package-show-uninstalled)
(define-key map (kbd "M-U") 'helm-el-package-show-upgrade)
(define-key map (kbd "M-B") 'helm-el-package-show-built-in)
(define-key map (kbd "M-A") 'helm-el-package-show-all)
(define-key map (kbd "C-c i") 'helm-el-run-package-install)
(define-key map (kbd "C-c r") 'helm-el-run-package-reinstall)
(define-key map (kbd "C-c d") 'helm-el-run-package-uninstall)
(define-key map (kbd "C-c u") 'helm-el-run-package-upgrade)
(define-key map (kbd "C-c U") 'helm-el-run-package-upgrade-all)
(define-key map (kbd "C-c @") 'helm-el-run-visit-homepage)
map))
(defvar helm-source-list-el-package nil)
(defclass helm-list-el-package-source (helm-source-in-buffer)
((init :initform 'helm-el-package--init)
(get-line :initform 'buffer-substring)
(filtered-candidate-transformer :initform 'helm-el-package--transformer)
(action-transformer :initform 'helm-el-package--action-transformer)
(help-message :initform 'helm-el-package-help-message)
(keymap :initform helm-el-package-map)
(update :initform 'helm-el-package--update)
(candidate-number-limit :initform 9999)
(action :initform '(("Describe package" . helm-el-package-describe)
("Visit homepage" . helm-el-package-visit-homepage)))
(group :initform 'helm-el-package)))
(defun helm-el-package--action-transformer (actions candidate)
(let* ((pkg-desc (get-text-property 0 'tabulated-list-id candidate))
(status (package-desc-status pkg-desc))
(pkg-name (package-desc-name pkg-desc))
(built-in (and (package-built-in-p pkg-name)
(not (member status '("available" "new"
"installed" "dependency")))))
(acts (if helm-el-package--upgrades
(append actions '(("Upgrade all packages"
. helm-el-package-upgrade-all-action)))
actions)))
(cond (built-in '(("Describe package" . helm-el-package-describe)))
((and (package-installed-p pkg-name)
(cdr (assq pkg-name helm-el-package--upgrades))
(member status '("installed" "dependency")))
(append '(("Upgrade package(s)" . helm-el-package-upgrade)
("Uninstall package(s)" . helm-el-package-uninstall))
acts))
((and (package-installed-p pkg-name)
(cdr (assq pkg-name helm-el-package--upgrades))
(string= status "available"))
(append '(("Upgrade package(s)" . helm-el-package-upgrade))
acts))
((and (package-installed-p pkg-name)
(or (null (package-built-in-p pkg-name))
(and (package-built-in-p pkg-name)
(assq pkg-name package-alist))))
(append acts '(("Reinstall package(s)" . helm-el-package-reinstall)
("Recompile package(s)" . helm-el-package-recompile)
("Uninstall package(s)" . helm-el-package-uninstall))))
(t (append acts '(("Install packages(s)" . helm-el-package-install)))))))
(defun helm-el-package--update ()
(setq helm-el-package--initialized-p nil))
(defun helm-el-package-recompile (_pkg)
(cl-loop for p in (helm-marked-candidates)
for pkg-desc = (get-text-property 0 'tabulated-list-id p)
for name = (package-desc-name pkg-desc)
for dir = (package-desc-dir pkg-desc)
do (if (fboundp 'async-byte-recompile-directory)
(async-byte-recompile-directory dir)
(when (y-or-n-p (format "Really recompile `%s' while already loaded ?" name))
(byte-recompile-directory dir 0 t)))))
(defun helm-el-package-reinstall (_pkg)
(cl-loop for p in (helm-marked-candidates)
for pkg-desc = (get-text-property 0 'tabulated-list-id p)
for name = (package-desc-name pkg-desc)
do (if (boundp 'package-selected-packages)
(with-no-warnings
(package-delete pkg-desc 'force 'nosave)
;; pkg-desc contain the description
;; of the installed package just removed
;; and is BTW no more valid.
;; Use the entry in package-archive-content
;; which is the non--installed package entry.
;; For some reason `package-install'
;; need a pkg-desc (package-desc-p) for the build-in
;; packages already installed, the name (as symbol)
;; fails with such packages.
(package-install
(cadr (assq name package-archive-contents)) t))
(package-delete pkg-desc)
(package-install name))))
(defun helm-el-run-package-reinstall ()
(interactive)
(with-helm-alive-p
(helm-exit-and-execute-action 'helm-el-package-reinstall)))
(put 'helm-el-run-package-reinstall 'helm-only t)
;;;###autoload
(defun helm-list-elisp-packages (arg)
"Preconfigured helm for listing and handling emacs packages."
(interactive "P")
(when arg (setq helm-el-package--initialized-p nil))
(unless helm-source-list-el-package
(setq helm-source-list-el-package
(helm-make-source "list packages" 'helm-list-el-package-source)))
(helm :sources 'helm-source-list-el-package
:truncate-lines helm-el-truncate-lines
:full-frame t
:buffer "*helm list packages*"))
;;;###autoload
(defun helm-list-elisp-packages-no-fetch (arg)
"Preconfigured helm for emacs packages.
Same as `helm-list-elisp-packages' but don't fetch packages on remote.
Called with a prefix ARG always fetch packages on remote."
(interactive "P")
(let ((helm-el-package--initialized-p (null arg)))
(helm-list-elisp-packages nil)))
(provide 'helm-elisp-package)
;;; helm-elisp-package.el ends here

View File

@@ -0,0 +1,979 @@
;;; helm-elisp.el --- Elisp symbols completion for helm. -*- lexical-binding: t -*-
;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Code:
(require 'cl-lib)
(require 'helm)
(require 'helm-lib)
(require 'helm-help)
(require 'helm-types)
(require 'helm-utils)
(require 'helm-info)
(require 'helm-eval)
(require 'helm-files)
(declare-function 'helm-describe-function "helm-lib")
(declare-function 'helm-describe-variable "helm-lib")
(declare-function 'helm-describe-face "helm-lib")
;;; Customizable values
(defgroup helm-elisp nil
"Elisp related Applications and libraries for Helm."
:group 'helm)
(defcustom helm-turn-on-show-completion t
"Display candidate in `current-buffer' while moving selection when non--nil."
:group 'helm-elisp
:type 'boolean)
(defcustom helm-show-completion-min-window-height 7
"Minimum completion window height used in show completion.
This is used in macro `with-helm-show-completion'."
:group 'helm-elisp
:type 'integer)
(defcustom helm-lisp-quoted-function-list
'(funcall apply mapc cl-mapc mapcar cl-mapcar
callf callf2 cl-callf cl-callf2 fset
fboundp fmakunbound symbol-function)
"List of function where quoted function completion happen.
e.g give only function names after \(funcall '."
:group 'helm-elisp
:type '(repeat (choice symbol)))
(defcustom helm-lisp-unquoted-function-list
'(function defadvice)
"List of function where unquoted function completion happen.
e.g give only function names after \(function ."
:group 'helm-elisp
:type '(repeat (choice symbol)))
(defcustom helm-apropos-fuzzy-match nil
"Enable fuzzy matching for `helm-apropos' when non-nil."
:group 'helm-elisp
:type 'boolean)
(defcustom helm-lisp-fuzzy-completion nil
"Enable fuzzy matching in emacs-lisp completion when non-nil.
NOTE: This enable fuzzy matching in helm native implementation of
elisp completion, but not on helmized elisp completion, i.e
fuzzy completion is not available in `completion-at-point'."
:group 'helm-elisp
:type 'boolean)
(defcustom helm-apropos-function-list '(helm-def-source--emacs-commands
helm-def-source--emacs-functions
helm-def-source--eieio-classes
helm-def-source--eieio-generic
helm-def-source--emacs-variables
helm-def-source--emacs-faces)
"A list of functions that build helm sources to use in `helm-apropos'."
:group 'helm-elisp
:type '(repeat (choice symbol)))
(defcustom helm-apropos-defaut-info-lookup-sources '(helm-source-info-elisp
helm-source-info-cl
helm-source-info-eieio)
"A list of sources to look into when searching info page of a symbol."
:group 'helm-elisp
:type '(repeat (choice symbol)))
(defcustom helm-show-completion-display-function
(if (display-graphic-p)
#'helm-display-buffer-in-own-frame
#'helm-show-completion-default-display-function)
"The function used to display helm completion buffer.
This function is used by `with-helm-show-completion', when nil
fallback to `helm-default-display-buffer'.
Default is to use a separate frame on graphic display and
`helm-show-completion-default-display-function' on non graphic
display."
:group 'helm-elisp
:type 'function)
;;; Faces
;;
;;
(defgroup helm-elisp-faces nil
"Customize the appearance of helm-elisp."
:prefix "helm-"
:group 'helm-elisp
:group 'helm-faces)
(defface helm-lisp-show-completion
'((t (:background "DarkSlateGray")))
"Face used for showing candidates in `helm-lisp-completion'."
:group 'helm-elisp-faces)
(defface helm-lisp-completion-info
'((t (:foreground "red")))
"Face used for showing info in `helm-lisp-completion'."
:group 'helm-elisp-faces)
(defcustom helm-elisp-help-function
'helm-elisp-show-help
"Function for displaying help for Lisp symbols."
:group 'helm-elisp
:type '(choice (function :tag "Open help for the symbol."
helm-elisp-show-help)
(function :tag "Show one liner in modeline."
helm-elisp-show-doc-modeline)))
(defcustom helm-locate-library-fuzzy-match t
"Enable fuzzy-matching in `helm-locate-library' when non--nil."
:type 'boolean
:group 'helm-elisp)
;;; Show completion.
;;
;; Provide show completion with macro `with-helm-show-completion'.
(defvar helm-show-completion-overlay nil)
;; Called each time cursor move in helm-buffer.
(defun helm-show-completion ()
(with-helm-current-buffer
(overlay-put helm-show-completion-overlay
'display (substring-no-properties
(helm-get-selection)))))
(defun helm-show-completion-init-overlay (beg end)
(setq helm-show-completion-overlay (make-overlay beg end))
(overlay-put helm-show-completion-overlay
'face 'helm-lisp-show-completion))
(defun helm-show-completion-default-display-function (buffer &rest _args)
"A special resized helm window is used depending on position in BUFFER."
(with-selected-window (selected-window)
(if (window-dedicated-p)
(helm-default-display-buffer buffer)
(let* ((screen-size (+ (count-screen-lines (window-start) (point) t)
1 ; mode-line
(if header-line-format 1 0))) ; header-line
(def-size (- (window-height)
helm-show-completion-min-window-height))
(upper-height (max window-min-height (min screen-size def-size)))
split-window-keep-point)
(recenter -1)
(set-window-buffer (if (active-minibuffer-window)
(minibuffer-selected-window)
(split-window nil upper-height
helm-split-window-default-side))
buffer)))))
(defmacro with-helm-show-completion (beg end &rest body)
"Show helm candidate in an overlay at point.
BEG and END are the beginning and end position of the current completion
in `helm-current-buffer'.
BODY is an helm call where we want to enable show completion.
If `helm-turn-on-show-completion' is nil do nothing."
(declare (indent 2) (debug t))
`(unwind-protect
(if helm-turn-on-show-completion
(let ((helm-move-selection-after-hook
(append (list 'helm-show-completion)
helm-move-selection-after-hook))
(helm-split-window-default-side
(if (eq helm-split-window-default-side 'same)
'below helm-split-window-default-side))
helm-split-window-inside-p
helm-reuse-last-window-split-state)
(helm-set-local-variable
'helm-display-function
(or helm-show-completion-display-function
'helm-default-display-buffer))
(helm-show-completion-init-overlay ,beg ,end)
,@body)
,@body)
(when (and helm-show-completion-overlay
(overlayp helm-show-completion-overlay))
(delete-overlay helm-show-completion-overlay))))
;;; Lisp symbol completion.
;;
;;
(defun helm-lisp-completion--predicate-at-point (beg)
;; Return a predicate for `all-completions'.
(let ((fn-sym-p (lambda ()
(or
(and (eq (char-before) ?\ )
(save-excursion
(skip-syntax-backward " " (point-at-bol))
(memq (symbol-at-point)
helm-lisp-unquoted-function-list)))
(and (eq (char-before) ?\')
(save-excursion
(forward-char -1)
(eq (char-before) ?\#)))))))
(save-excursion
(goto-char beg)
(if (or
;; Complete on all symbols in non--lisp modes (logs mail etc..)
(not (memq major-mode '(emacs-lisp-mode
lisp-interaction-mode
inferior-emacs-lisp-mode)))
(not (or (funcall fn-sym-p)
(and (eq (char-before) ?\')
(save-excursion
(forward-char (if (funcall fn-sym-p) -2 -1))
(skip-syntax-backward " " (point-at-bol))
(memq (symbol-at-point)
helm-lisp-quoted-function-list)))
(eq (char-before) ?\())) ; no paren before str.
;; Looks like we are in a let statement.
(condition-case nil
(progn (up-list -2) (forward-char 1)
(eq (char-after) ?\())
(error nil)))
(lambda (sym)
(or (boundp sym) (fboundp sym) (symbol-plist sym)))
#'fboundp))))
(defun helm-thing-before-point (&optional limits regexp)
"Return symbol name before point.
If REGEXP is specified return what REGEXP find before point.
By default match the beginning of symbol before point.
With LIMITS arg specified return the beginning and end position
of symbol before point."
(save-excursion
(let (beg
(end (point))
(boundary (field-beginning nil nil (point-at-bol))))
(if (re-search-backward (or regexp "\\_<") boundary t)
(setq beg (match-end 0))
(setq beg boundary))
(unless (= beg end)
(if limits
(cons beg end)
(buffer-substring-no-properties beg end))))))
(defun helm-bounds-of-thing-before-point (&optional regexp)
"Get the beginning and end position of `helm-thing-before-point'.
Return a cons \(beg . end\)."
(helm-thing-before-point 'limits regexp))
(defun helm-insert-completion-at-point (beg end str)
;; When there is no space after point
;; we are completing inside a symbol or
;; after a partial symbol with the next arg aside
;; without space, in this case mark the region.
;; deleting it would remove the
;; next arg which is unwanted.
(delete-region beg end)
(insert str)
(let ((pos (cdr (or (bounds-of-thing-at-point 'symbol)
;; needed for helm-dabbrev.
(bounds-of-thing-at-point 'filename)))))
(when (and pos (< (point) pos))
(push-mark pos t t))))
(defvar helm-lisp-completion--cache nil)
(defvar helm-lgst-len nil)
;;;###autoload
(defun helm-lisp-completion-at-point ()
"Preconfigured helm for lisp symbol completion at point."
(interactive)
(setq helm-lgst-len 0)
(let* ((target (helm-thing-before-point))
(beg (car (helm-bounds-of-thing-before-point)))
(end (point))
(pred (and beg (helm-lisp-completion--predicate-at-point beg)))
(loc-vars (and (fboundp 'elisp--local-variables)
(ignore-errors
(mapcar #'symbol-name (elisp--local-variables)))))
(glob-syms (and target pred (all-completions target obarray pred)))
(candidates (append loc-vars glob-syms))
(helm-quit-if-no-candidate t)
(helm-execute-action-at-once-if-one t)
(enable-recursive-minibuffers t))
(setq helm-lisp-completion--cache (cl-loop for sym in candidates
for len = (length sym)
when (> len helm-lgst-len)
do (setq helm-lgst-len len)
collect sym))
(if candidates
(with-helm-show-completion beg end
;; Overlay is initialized now in helm-current-buffer.
(helm
:sources (helm-build-in-buffer-source "Lisp completion"
:data helm-lisp-completion--cache
:persistent-action `(helm-lisp-completion-persistent-action .
,(and (eq helm-elisp-help-function
'helm-elisp-show-doc-modeline)
'never-split))
:nomark t
:match-part (lambda (c) (car (split-string c)))
:fuzzy-match helm-lisp-fuzzy-completion
:persistent-help (helm-lisp-completion-persistent-help)
:filtered-candidate-transformer
'helm-lisp-completion-transformer
:action (lambda (candidate)
(with-helm-current-buffer
(run-with-timer
0.01 nil
'helm-insert-completion-at-point
beg end candidate))))
:input (if helm-lisp-fuzzy-completion
target (concat target " "))
:resume 'noresume
:truncate-lines t
:buffer "*helm lisp completion*"
:allow-nest t))
(message "[No Match]"))))
(defun helm-lisp-completion-persistent-action (candidate &optional name)
"Show documentation for the function.
Documentation is shown briefly in mode-line or completely
in other window according to the value of `helm-elisp-help-function'."
(funcall helm-elisp-help-function candidate name))
(defun helm-lisp-completion-persistent-help ()
"Return persistent-help according to the value of `helm-elisp-help-function'"
(cl-ecase helm-elisp-help-function
(helm-elisp-show-doc-modeline "Show brief doc in mode-line")
(helm-elisp-show-help "Toggle show help for the symbol")))
(defun helm-elisp--show-help-1 (candidate &optional name)
(let ((sym (intern-soft candidate)))
(cl-typecase sym
((and fboundp boundp)
(if (member name '("describe-function" "describe-variable"))
(funcall (intern (format "helm-%s" name)) sym)
;; When there is no way to know what to describe
;; prefer describe-function.
(helm-describe-function sym)))
(fbound (helm-describe-function sym))
(bound (helm-describe-variable sym))
(face (helm-describe-face sym)))))
(defun helm-elisp-show-help (candidate &optional name)
"Show full help for the function CANDIDATE.
Arg NAME specify the name of the top level function
calling helm generic completion (e.g \"describe-function\")
which allow calling the right function when CANDIDATE symbol
refers at the same time to variable and a function."
(helm-elisp--persistent-help
candidate 'helm-elisp--show-help-1 name))
(defun helm-elisp-show-doc-modeline (candidate &optional name)
"Show brief documentation for the function in modeline."
(let ((cursor-in-echo-area t)
mode-line-in-non-selected-windows)
(helm-show-info-in-mode-line
(propertize
(helm-get-first-line-documentation
(intern candidate) name)
'face 'helm-lisp-completion-info))))
(defun helm-lisp-completion-transformer (candidates _source)
"Helm candidates transformer for lisp completion."
(cl-loop for c in candidates
for sym = (intern c)
for annot = (cl-typecase sym
(command " (Com)")
(class " (Class)")
(generic " (Gen)")
(fbound " (Fun)")
(bound " (Var)")
(face " (Face)"))
for spaces = (make-string (- helm-lgst-len (length c)) ? )
collect (cons (concat c spaces annot) c) into lst
finally return (sort lst #'helm-generic-sort-fn)))
(defun helm-get-first-line-documentation (sym &optional name)
"Return first line documentation of symbol SYM.
If SYM is not documented, return \"Not documented\"."
(let ((doc (cl-typecase sym
((and fboundp boundp)
(cond ((string= name "describe-function")
(documentation sym t))
((string= name "describe-variable")
(documentation-property sym 'variable-documentation t))
(t (documentation sym t))))
(fbound (documentation sym t))
(bound (documentation-property sym 'variable-documentation t))
(face (face-documentation sym)))))
(if (and doc (not (string= doc ""))
;; `documentation' return "\n\n(args...)"
;; for CL-style functions.
(not (string-match-p "^\n\n" doc)))
(car (split-string doc "\n"))
"Not documented")))
;;; File completion.
;;
;; Complete file name at point.
;;;###autoload
(defun helm-complete-file-name-at-point (&optional force)
"Preconfigured helm to complete file name at point."
(interactive)
(require 'helm-mode)
(let* ((tap (thing-at-point 'filename))
beg
(init (and tap
(or force
(save-excursion
(end-of-line)
(search-backward tap (point-at-bol) t)
(setq beg (point))
(looking-back "[^'`( ]" (1- (point)))))
(expand-file-name
(substring-no-properties tap))))
(end (point))
(helm-quit-if-no-candidate t)
(helm-execute-action-at-once-if-one t)
completion)
(with-helm-show-completion beg end
(setq completion (helm-read-file-name "FileName: "
:initial-input init)))
(when (and completion (not (string= completion "")))
(delete-region beg end) (insert (if (string-match "^~" tap)
(abbreviate-file-name completion)
completion)))))
;;;###autoload
(defun helm-lisp-indent ()
;; It is meant to use with `helm-define-multi-key' which
;; does not support args for functions yet, so use `current-prefix-arg'
;; for now instead of (interactive "P").
(interactive)
(let ((tab-always-indent (or (eq tab-always-indent 'complete)
tab-always-indent)))
(indent-for-tab-command current-prefix-arg)))
;;;###autoload
(defun helm-lisp-completion-or-file-name-at-point ()
"Preconfigured helm to complete lisp symbol or filename at point.
Filename completion happen if string start after or between a double quote."
(interactive)
(let* ((tap (thing-at-point 'filename)))
(if (and tap (save-excursion
(end-of-line)
(search-backward tap (point-at-bol) t)
(looking-back "[^'`( ]" (1- (point)))))
(helm-complete-file-name-at-point)
(helm-lisp-completion-at-point))))
;;; Apropos
;;
;;
(defvar helm-apropos-history nil)
(defun helm-apropos-init (test default)
"Init candidates buffer for `helm-apropos' sources."
(require 'helm-help)
(helm-init-candidates-in-buffer 'global
(let ((default-symbol (and (stringp default)
(intern-soft default)))
(symbols (all-completions "" obarray test)))
(if (and default-symbol (funcall test default-symbol))
(cons default-symbol symbols)
symbols))))
(defun helm-apropos-init-faces (default)
"Init candidates buffer for faces for `helm-apropos'."
(require 'helm-help)
(with-current-buffer (helm-candidate-buffer 'global)
(goto-char (point-min))
(let ((default-symbol (and (stringp default)
(intern-soft default)))
(faces (face-list)))
(when (and default-symbol (facep default-symbol))
(insert (concat default "\n")))
(insert
(mapconcat #'prin1-to-string
(if default
(cl-remove-if (lambda (sym) (string= sym default)) faces)
faces)
"\n")))))
(defun helm-apropos-default-sort-fn (candidates _source)
(if (string= helm-pattern "")
candidates
(sort candidates #'helm-generic-sort-fn)))
(defun helm-apropos-clean-history-variable (candidate)
(with-helm-current-buffer ; var is maybe local
(let* ((sym (intern-soft candidate))
(cands (symbol-value sym))
(mkds (and (listp cands)
(helm-comp-read "Delete entry: "
cands :marked-candidates t))))
(cl-assert (listp mkds) nil "Variable value is not a list")
(cl-loop for elm in mkds do
(if (local-variable-p sym)
(set (make-local-variable sym)
(setq cands (delete elm cands)))
(set sym (setq cands (delete elm cands))))))))
(defun helm-apropos-clean-ring (candidate)
(with-helm-current-buffer ; var is maybe local
(let* ((sym (intern-soft candidate))
(val (symbol-value sym))
(cands (and (ring-p val) (ring-elements val)))
(mkds (and cands (helm-comp-read
"Delete entry: "
cands :marked-candidates t))))
(when mkds
(cl-loop for elm in mkds do
(ring-remove
val (helm-position
elm
(ring-elements val)
:test 'equal))
and do (if (local-variable-p sym)
(set (make-local-variable sym) val)
(set sym val)))))))
(defun helm-apropos-action-transformer (actions candidate)
(let* ((sym (helm-symbolify candidate))
(val (with-helm-current-buffer (symbol-value sym))))
(cond ((custom-variable-p sym)
(append
actions
(let ((standard-value (eval (car (get sym 'standard-value)))))
(unless (equal standard-value (symbol-value sym))
`(("Reset Variable to default value"
. ,(lambda (candidate)
(let ((sym (helm-symbolify candidate)))
(set sym standard-value)))))))
'(("Customize variable" .
(lambda (candidate)
(customize-option (helm-symbolify candidate)))))))
((and val (with-helm-current-buffer (ring-p (symbol-value sym))))
(append actions
'(("Clean ring" . helm-apropos-clean-ring))))
((and (string-match-p "history" candidate) (listp val))
(append actions
'(("Clean variable" .
helm-apropos-clean-history-variable))))
(t actions))))
(defun helm-def-source--emacs-variables (&optional default)
(helm-build-in-buffer-source "Variables"
:init (lambda ()
(helm-apropos-init
(lambda (x) (and (boundp x) (not (keywordp x)))) default))
:fuzzy-match helm-apropos-fuzzy-match
:filtered-candidate-transformer (and (null helm-apropos-fuzzy-match)
'helm-apropos-default-sort-fn)
:nomark t
:persistent-action (lambda (candidate)
(helm-elisp--persistent-help
candidate 'helm-describe-variable))
:persistent-help "Toggle describe variable"
:action '(("Describe variable" . helm-describe-variable)
("Find variable" . helm-find-variable)
("Info lookup" . helm-info-lookup-symbol)
("Set variable" . helm-set-variable))
:action-transformer 'helm-apropos-action-transformer))
(defun helm-def-source--emacs-faces (&optional default)
"Create `helm' source for faces to be displayed with
`helm-apropos'."
(helm-build-in-buffer-source "Faces"
:init (lambda () (helm-apropos-init-faces default))
:fuzzy-match helm-apropos-fuzzy-match
:filtered-candidate-transformer
(append (and (null helm-apropos-fuzzy-match)
'(helm-apropos-default-sort-fn))
(list
(lambda (candidates _source)
(cl-loop for c in candidates
collect (propertize c 'face (intern c))))))
:persistent-action (lambda (candidate)
(helm-elisp--persistent-help
candidate 'helm-describe-face))
:persistent-help "Toggle describe face"
:action '(("Describe face" . helm-describe-face)
("Find face" . helm-find-face-definition)
("Customize face" . (lambda (candidate)
(customize-face (helm-symbolify candidate)))))))
(defun helm-def-source--emacs-commands (&optional default)
(helm-build-in-buffer-source "Commands"
:init (lambda ()
(helm-apropos-init 'commandp default))
:fuzzy-match helm-apropos-fuzzy-match
:filtered-candidate-transformer (and (null helm-apropos-fuzzy-match)
'helm-apropos-default-sort-fn)
:nomark t
:persistent-action (lambda (candidate)
(helm-elisp--persistent-help
candidate 'helm-describe-function))
:persistent-help "Toggle describe command"
:action '(("Describe function" . helm-describe-function)
("Find function" . helm-find-function)
("Info lookup" . helm-info-lookup-symbol))))
(defun helm-def-source--emacs-functions (&optional default)
(helm-build-in-buffer-source "Functions"
:init (lambda ()
(helm-apropos-init (lambda (x)
(and (fboundp x)
(not (commandp x))
(not (generic-p x))
(not (class-p x))))
default))
:fuzzy-match helm-apropos-fuzzy-match
:filtered-candidate-transformer (and (null helm-apropos-fuzzy-match)
'helm-apropos-default-sort-fn)
:persistent-action (lambda (candidate)
(helm-elisp--persistent-help
candidate 'helm-describe-function))
:persistent-help "Toggle describe function"
:nomark t
:action '(("Describe function" . helm-describe-function)
("Find function" . helm-find-function)
("Info lookup" . helm-info-lookup-symbol))))
(defun helm-def-source--eieio-classes (&optional default)
(helm-build-in-buffer-source "Classes"
:init (lambda ()
(helm-apropos-init (lambda (x)
(class-p x))
default))
:fuzzy-match helm-apropos-fuzzy-match
:filtered-candidate-transformer (and (null helm-apropos-fuzzy-match)
'helm-apropos-default-sort-fn)
:nomark t
:persistent-action (lambda (candidate)
(helm-elisp--persistent-help
candidate 'helm-describe-function))
:persistent-help "Toggle describe class"
:action '(("Describe function" . helm-describe-function)
("Find function" . helm-find-function)
("Info lookup" . helm-info-lookup-symbol))))
(defun helm-def-source--eieio-generic (&optional default)
(helm-build-in-buffer-source "Generic functions"
:init (lambda ()
(helm-apropos-init (lambda (x)
(generic-p x))
default))
:fuzzy-match helm-apropos-fuzzy-match
:filtered-candidate-transformer (and (null helm-apropos-fuzzy-match)
'helm-apropos-default-sort-fn)
:nomark t
:persistent-action (lambda (candidate)
(helm-elisp--persistent-help
candidate 'helm-describe-function))
:persistent-help "Toggle describe generic function"
:action '(("Describe function" . helm-describe-function)
("Find function" . helm-find-function)
("Info lookup" . helm-info-lookup-symbol))))
(defun helm-info-lookup-fallback-source (candidate)
(let ((sym (helm-symbolify candidate))
src-name fn)
(cond ((class-p sym)
(setq fn #'helm-describe-function
src-name "Describe class"))
((generic-p sym)
(setq fn #'helm-describe-function
src-name "Describe generic function"))
((fboundp sym)
(setq fn #'helm-describe-function
src-name "Describe function"))
((facep sym)
(setq fn #'helm-describe-face
src-name "Describe face"))
(t
(setq fn #'helm-describe-variable
src-name "Describe variable")))
(helm-build-sync-source src-name
:candidates (list candidate)
:persistent-action (lambda (candidate)
(helm-elisp--persistent-help
candidate fn))
:persistent-help src-name
:nomark t
:action fn)))
(defun helm-info-lookup-symbol-1 (c)
(let ((helm-execute-action-at-once-if-one 'current-source))
(helm :sources (append helm-apropos-defaut-info-lookup-sources
(list (helm-info-lookup-fallback-source c)))
:resume 'noresume
:buffer "*helm lookup*"
:input c)))
(defun helm-info-lookup-symbol (candidate)
;; ???:Running an idle-timer allows not catching RET when exiting
;; with the fallback source.
;; (run-with-idle-timer 0.01 nil #'helm-info-lookup-symbol-1 candidate)
(helm-info-lookup-symbol-1 candidate))
;;;###autoload
(defun helm-apropos (default)
"Preconfigured helm to describe commands, functions, variables and faces.
In non interactives calls DEFAULT argument should be provided as a string,
i.e the `symbol-name' of any existing symbol."
(interactive (list (thing-at-point 'symbol)))
(helm :sources
(mapcar (lambda (func)
(funcall func default))
helm-apropos-function-list)
:history 'helm-apropos-history
:buffer "*helm apropos*"
:preselect (and default (concat "\\_<" (regexp-quote default) "\\_>"))))
;;; Advices
;;
;;
(defvar helm-source-advice
(helm-build-sync-source "Function Advice"
:init (lambda () (require 'advice))
:candidates 'helm-advice-candidates
:action (helm-make-actions "Toggle Enable/Disable" 'helm-advice-toggle)
:persistent-action 'helm-advice-persistent-action
:nomark t
:multiline t
:persistent-help "Toggle describe function / C-u C-j: Toggle advice"))
(defun helm-advice-candidates ()
(cl-loop for (fname) in ad-advised-functions
for function = (intern fname)
append
(cl-loop for class in ad-advice-classes append
(cl-loop for advice in (ad-get-advice-info-field function class)
for enabled = (ad-advice-enabled advice)
collect
(cons (format
"%s %s %s"
(if enabled "Enabled " "Disabled")
(propertize fname 'face 'font-lock-function-name-face)
(ad-make-single-advice-docstring advice class nil))
(list function class advice))))))
(defun helm-advice-persistent-action (func-class-advice)
(if current-prefix-arg
(helm-advice-toggle func-class-advice)
(describe-function (car func-class-advice))))
(defun helm-advice-toggle (func-class-advice)
(cl-destructuring-bind (function _class advice) func-class-advice
(cond ((ad-advice-enabled advice)
(ad-advice-set-enabled advice nil)
(message "Disabled"))
(t
(ad-advice-set-enabled advice t)
(message "Enabled")))
(ad-activate function)
(and helm-in-persistent-action
(helm-advice-update-current-display-string))))
(defun helm-advice-update-current-display-string ()
(helm-edit-current-selection
(let ((newword (cond ((looking-at "Disabled") "Enabled")
((looking-at "Enabled") "Disabled"))))
(when newword
(delete-region (point) (progn (forward-word 1) (point)))
(insert newword)))))
;;;###autoload
(defun helm-manage-advice ()
"Preconfigured `helm' to disable/enable function advices."
(interactive)
(helm-other-buffer 'helm-source-advice "*helm advice*"))
;;; Locate elisp library
;;
;;
(defun helm-locate-library-scan-list ()
(cl-loop for dir in load-path
with load-suffixes = '(".el")
when (file-directory-p dir)
append (directory-files
dir t (concat (regexp-opt (get-load-suffixes))
"\\'"))))
;;;###autoload
(defun helm-locate-library ()
"Preconfigured helm to locate elisp libraries."
(interactive)
(helm :sources (helm-build-in-buffer-source "Elisp libraries (Scan)"
:data #'helm-locate-library-scan-list
:fuzzy-match helm-locate-library-fuzzy-match
:keymap helm-generic-files-map
:search (unless helm-locate-library-fuzzy-match
(lambda (regexp)
(re-search-forward
(if helm-ff-transformer-show-only-basename
(replace-regexp-in-string
"\\`\\^" "" regexp)
regexp)
nil t)))
:match-part (lambda (candidate)
(if helm-ff-transformer-show-only-basename
(helm-basename candidate) candidate))
:filter-one-by-one (lambda (c)
(if helm-ff-transformer-show-only-basename
(cons (helm-basename c) c) c))
:action (helm-actions-from-type-file))
:ff-transformer-show-only-basename nil
:buffer "*helm locate library*"))
(defun helm-set-variable (var)
"Set value to VAR interactively."
(let* ((sym (helm-symbolify var))
(val (default-value sym)))
(set-default sym (eval-minibuffer (format "Set `%s': " var)
(if (or (stringp val) (memq val '(nil t)))
(prin1-to-string val)
(format "'%s" (prin1-to-string val)))))))
;;; Elisp Timers.
;;
;;
(defclass helm-absolute-time-timers-class (helm-source-sync helm-type-timers)
((candidates :initform timer-list)
(allow-dups :initform t)
(candidate-transformer
:initform
(lambda (candidates)
(cl-loop for timer in candidates
collect (cons (helm-elisp--format-timer timer) timer))))))
(defvar helm-source-absolute-time-timers
(helm-make-source "Absolute Time Timers" 'helm-absolute-time-timers-class))
(defclass helm-idle-time-timers-class (helm-source-sync helm-type-timers)
((candidates :initform timer-idle-list)
(allow-dups :initform t)
(candidate-transformer
:initform
(lambda (candidates)
(cl-loop for timer in candidates
collect (cons (helm-elisp--format-timer timer) timer))))))
(defvar helm-source-idle-time-timers
(helm-make-source "Idle Time Timers" 'helm-idle-time-timers-class))
(defun helm-elisp--format-timer (timer)
(format "%s repeat=%s %s(%s)"
(let ((time (timer--time timer)))
(if (timer--idle-delay timer)
(format-time-string "idle-for=%5s" time)
(format-time-string "%m/%d %T" time)))
(or (timer--repeat-delay timer) "nil")
(mapconcat 'identity (split-string
(prin1-to-string (timer--function timer))
"\n") " ")
(mapconcat 'prin1-to-string (timer--args timer) " ")))
;;;###autoload
(defun helm-timers ()
"Preconfigured `helm' for timers."
(interactive)
(helm :sources '(helm-source-absolute-time-timers
helm-source-idle-time-timers)
:buffer "*helm timers*"))
;;; Complex command history
;;
;;
(defun helm-btf--usable-p ()
"Return t if current version of `backtrace-frame' accept 2 arguments."
(condition-case nil
(progn (backtrace-frame 1 'condition-case) t)
(wrong-number-of-arguments nil)))
(if (helm-btf--usable-p) ; Check if BTF accept more than one arg.
;; Emacs 24.4.
(dont-compile
(defvar helm-sexp--last-sexp nil)
;; This wont work compiled.
(defun helm-sexp-eval-1 ()
(interactive)
(unwind-protect
(progn
;; Trick called-interactively-p into thinking that `cand' is
;; an interactive call, See `repeat-complex-command'.
(add-hook 'called-interactively-p-functions
#'helm-complex-command-history--called-interactively-skip)
(eval (read helm-sexp--last-sexp)))
(remove-hook 'called-interactively-p-functions
#'helm-complex-command-history--called-interactively-skip)))
(defun helm-complex-command-history--called-interactively-skip (i _frame1 frame2)
(and (eq 'eval (cadr frame2))
(eq 'helm-sexp-eval-1
(cadr (backtrace-frame (+ i 2) #'called-interactively-p)))
1))
(defun helm-sexp-eval (_candidate)
(call-interactively #'helm-sexp-eval-1)))
;; Emacs 24.3
(defun helm-sexp-eval (cand)
(let ((sexp (read cand)))
(condition-case err
(if (> (length (remove nil sexp)) 1)
(eval sexp)
(apply 'call-interactively sexp))
(error (message "Evaluating gave an error: %S" err)
nil)))))
(defvar helm-source-complex-command-history
(helm-build-sync-source "Complex Command History"
:candidates (lambda ()
;; Use cdr to avoid adding
;; `helm-complex-command-history' here.
(cl-loop for i in command-history
unless (equal i '(helm-complex-command-history))
collect (prin1-to-string i)))
:action (helm-make-actions
"Eval" (lambda (candidate)
(and (boundp 'helm-sexp--last-sexp)
(setq helm-sexp--last-sexp candidate))
(let ((command (read candidate)))
(unless (equal command (car command-history))
(setq command-history (cons command command-history))))
(run-with-timer 0.1 nil #'helm-sexp-eval candidate))
"Edit and eval" (lambda (candidate)
(edit-and-eval-command "Eval: " (read candidate))))
:persistent-action #'helm-sexp-eval
:multiline t))
;;;###autoload
(defun helm-complex-command-history ()
"Preconfigured helm for complex command history."
(interactive)
(helm :sources 'helm-source-complex-command-history
:buffer "*helm complex commands*"))
(provide 'helm-elisp)
;; Local Variables:
;; byte-compile-warnings: (not obsolete)
;; coding: utf-8
;; indent-tabs-mode: nil
;; End:
;;; helm-elisp.el ends here

View File

@@ -0,0 +1,487 @@
;;; helm-eshell.el --- pcomplete and eshell completion for helm. -*- lexical-binding: t -*-
;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;;
;; Enable like this in .emacs:
;; (add-hook 'eshell-mode-hook
;; (lambda ()
;; (eshell-cmpl-initialize)
;; (define-key eshell-mode-map [remap eshell-pcomplete] 'helm-esh-pcomplete)
;; (define-key eshell-mode-map (kbd "M-s f") 'helm-eshell-prompts-all)))
;; (define-key eshell-mode-map (kbd "M-r") 'helm-eshell-history)))
;;; Code:
(require 'cl-lib)
(require 'helm)
(require 'helm-lib)
(require 'helm-help)
(require 'helm-elisp)
(declare-function eshell-read-aliases-list "em-alias")
(declare-function eshell-send-input "esh-mode" (&optional use-region queue-p no-newline))
(declare-function eshell-bol "esh-mode")
(declare-function eshell-parse-arguments "esh-arg" (beg end))
(declare-function eshell-backward-argument "esh-mode" (&optional arg))
(declare-function helm-quote-whitespace "helm-lib")
(declare-function eshell-skip-prompt "em-prompt")
(defvar eshell-special-chars-outside-quoting)
(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

View File

@@ -0,0 +1,204 @@
;;; helm-eval.el --- eval expressions from helm. -*- lexical-binding: t -*-
;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Code:
(require 'cl-lib)
(require 'helm)
(require 'helm-help)
(require 'eldoc)
(require 'edebug)
(defgroup helm-eval nil
"Eval related Applications and libraries for Helm."
:group 'helm)
(defcustom helm-eldoc-in-minibuffer-show-fn
'helm-show-info-in-mode-line
"A function to display eldoc info.
Should take one arg: the string to display."
:group 'helm-eval
:type 'symbol)
(defcustom helm-show-info-in-mode-line-delay 12
"Eldoc will show info in mode-line during this delay if user is idle."
:type 'integer
:group 'helm-eval)
;;; Eldoc compatibility between emacs-24 and emacs-25
;;
(if (require 'elisp-mode nil t) ; emacs-25
;; Maybe the eldoc functions have been
;; already aliased by eldoc-eval.
(cl-loop for (f . a) in '((eldoc-current-symbol .
elisp--current-symbol)
(eldoc-fnsym-in-current-sexp .
elisp--fnsym-in-current-sexp)
(eldoc-get-fnsym-args-string .
elisp-get-fnsym-args-string)
(eldoc-get-var-docstring .
elisp-get-var-docstring))
unless (fboundp f)
do (defalias f a))
;; Emacs-24.
(declare-function eldoc-current-symbol "eldoc")
(declare-function eldoc-get-fnsym-args-string "eldoc" (sym &optional index))
(declare-function eldoc-get-var-docstring "eldoc" (sym))
(declare-function eldoc-fnsym-in-current-sexp "eldoc"))
;;; Evaluation Result
;;
;;
;; Internal
(defvar helm-eldoc-active-minibuffers-list nil)
(defvar helm-eval-expression-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map helm-map)
(define-key map (kbd "<C-return>") 'helm-eval-new-line-and-indent)
(define-key map (kbd "<M-tab>") 'lisp-indent-line)
(define-key map (kbd "<C-tab>") 'helm-lisp-completion-at-point)
(define-key map (kbd "C-p") 'previous-line)
(define-key map (kbd "C-n") 'next-line)
(define-key map (kbd "<up>") 'previous-line)
(define-key map (kbd "<down>") 'next-line)
(define-key map (kbd "<right>") 'forward-char)
(define-key map (kbd "<left>") 'backward-char)
map))
(defun helm-build-evaluation-result-source ()
(helm-build-dummy-source "Evaluation Result"
:multiline t
:mode-line "C-RET: nl-and-indent, M-tab: reindent, C-tab:complete, C-p/n: next/prec-line."
:filtered-candidate-transformer (lambda (_candidates _source)
(list
(condition-case nil
(with-helm-current-buffer
(pp-to-string
(if edebug-active
(edebug-eval-expression
(read helm-pattern))
(eval (read helm-pattern)))))
(error "Error"))))
:nohighlight t
:keymap helm-eval-expression-map
:action '(("Copy result to kill-ring" . (lambda (candidate)
(kill-new
(replace-regexp-in-string
"\n" "" candidate))
(message "Result copied to kill-ring")))
("copy sexp to kill-ring" . (lambda (_candidate)
(kill-new helm-input)
(message "Sexp copied to kill-ring"))))))
(defun helm-eval-new-line-and-indent ()
(interactive)
(newline) (lisp-indent-line))
(defun helm-eldoc-store-minibuffer ()
"Store minibuffer buffer name in `helm-eldoc-active-minibuffers-list'."
(with-selected-window (minibuffer-window)
(push (current-buffer) helm-eldoc-active-minibuffers-list)))
(defun helm-eldoc-show-in-eval ()
"Return eldoc in mode-line for current minibuffer input."
(let ((buf (window-buffer (active-minibuffer-window))))
(condition-case err
(when (member buf helm-eldoc-active-minibuffers-list)
(with-current-buffer buf
(let* ((sym (save-excursion
(unless (looking-back ")\\|\"" (1- (point)))
(forward-char -1))
(eldoc-current-symbol)))
(info-fn (eldoc-fnsym-in-current-sexp))
(doc (or (eldoc-get-var-docstring sym)
(eldoc-get-fnsym-args-string
(car info-fn) (cadr info-fn)))))
(when doc (funcall helm-eldoc-in-minibuffer-show-fn doc)))))
(error (message "Eldoc in minibuffer error: %S" err) nil))))
(defun helm-show-info-in-mode-line (str)
"Display string STR in mode-line."
(save-selected-window
(with-current-buffer helm-buffer
(let ((mode-line-format (concat " " str)))
(force-mode-line-update)
(sit-for helm-show-info-in-mode-line-delay))
(force-mode-line-update))))
;;; Calculation Result
;;
;;
(defvar helm-source-calculation-result
(helm-build-dummy-source "Calculation Result"
:filtered-candidate-transformer (lambda (_candidates _source)
(list
(condition-case nil
(calc-eval helm-pattern)
(error "error"))))
:nohighlight t
:action '(("Copy result to kill-ring" . (lambda (candidate)
(kill-new candidate)
(message "Result \"%s\" copied to kill-ring"
candidate)))
("Copy operation to kill-ring" . (lambda (_candidate)
(kill-new helm-input)
(message "Calculation copied to kill-ring"))))))
;;;###autoload
(defun helm-eval-expression (arg)
"Preconfigured helm for `helm-source-evaluation-result'."
(interactive "P")
(helm :sources (helm-build-evaluation-result-source)
:input (when arg (thing-at-point 'sexp))
:buffer "*helm eval*"
:echo-input-in-header-line nil
:history 'read-expression-history))
(defvar eldoc-idle-delay)
;;;###autoload
(defun helm-eval-expression-with-eldoc ()
"Preconfigured helm for `helm-source-evaluation-result' with `eldoc' support. "
(interactive)
(let ((timer (run-with-idle-timer
eldoc-idle-delay 'repeat
'helm-eldoc-show-in-eval)))
(unwind-protect
(minibuffer-with-setup-hook
'helm-eldoc-store-minibuffer
(call-interactively 'helm-eval-expression))
(and timer (cancel-timer timer))
(setq helm-eldoc-active-minibuffers-list
(cdr helm-eldoc-active-minibuffers-list)))))
;;;###autoload
(defun helm-calcul-expression ()
"Preconfigured helm for `helm-source-calculation-result'."
(interactive)
(helm :sources 'helm-source-calculation-result
:buffer "*helm calcul*"))
(provide 'helm-eval)
;; Local Variables:
;; byte-compile-warnings: (not obsolete)
;; coding: utf-8
;; indent-tabs-mode: nil
;; End:
;;; helm-eval.el ends here

View File

@@ -0,0 +1,213 @@
;;; helm-external.el --- Run Externals commands within Emacs with helm completion. -*- lexical-binding: t -*-
;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Code:
(require 'cl-lib)
(require 'helm)
(require 'helm-help)
(require 'helm-net)
(defgroup helm-external nil
"External related Applications and libraries for Helm."
:group 'helm)
(defcustom helm-raise-command nil
"A shell command to jump to a window running specific program.
Need external program wmctrl.
This will be use with `format', so use something like \"wmctrl -xa %s\"."
:type 'string
:group 'helm-external)
(defcustom helm-external-programs-associations nil
"Alist to store externals programs associated with file extension.
This variable overhide setting in .mailcap file.
e.g : '\(\(\"jpg\" . \"gqview\"\) (\"pdf\" . \"xpdf\"\)\) "
:type '(alist :key-type string :value-type string)
:group 'helm-external)
(defcustom helm-default-external-file-browser "nautilus"
"Default external file browser for your system.
Directories will be opened externally with it when
opening file externally in `helm-find-files'.
Set to nil if you do not have external file browser
or do not want to use it.
Windows users should set that to \"explorer.exe\"."
:group 'helm-external
:type 'string)
;;; Internals
(defvar helm-external-command-history nil)
(defvar helm-external-commands-list nil
"A list of all external commands the user can execute.
If this variable is not set by the user, it will be calculated
automatically.")
(defun helm-external-commands-list-1 (&optional sort)
"Returns a list of all external commands the user can execute.
If `helm-external-commands-list' is non-nil it will
return its contents. Else it calculates all external commands
and sets `helm-external-commands-list'."
(helm-aif helm-external-commands-list
it
(setq helm-external-commands-list
(cl-loop
for dir in (split-string (getenv "PATH") path-separator)
when (and (file-exists-p dir) (file-accessible-directory-p dir))
for lsdir = (cl-loop for i in (directory-files dir t)
for bn = (file-name-nondirectory i)
when (and (not (member bn completions))
(not (file-directory-p i))
(file-executable-p i))
collect bn)
append lsdir into completions
finally return
(if sort (sort completions 'string-lessp) completions)))))
(defun helm-run-or-raise (exe &optional file)
"Run asynchronously EXE or jump to the application window.
If EXE is already running just jump to his window if `helm-raise-command'
is non--nil.
When FILE argument is provided run EXE with FILE."
(let* ((real-com (car (split-string exe)))
(proc (if file (concat real-com " " file) real-com))
process-connection-type)
(if (get-process proc)
(if helm-raise-command
(shell-command (format helm-raise-command real-com))
(error "Error: %s is already running" real-com))
(when (member real-com helm-external-commands-list)
(message "Starting %s..." real-com)
(if file
(start-process-shell-command
proc nil (format "%s %s"
real-com
(shell-quote-argument
(if (eq system-type 'windows-nt)
(helm-w32-prepare-filename file)
(expand-file-name file)))))
(start-process-shell-command proc nil real-com))
(set-process-sentinel
(get-process proc)
(lambda (process event)
(when (and (string= event "finished\n")
helm-raise-command
(not (helm-get-pid-from-process-name real-com)))
(shell-command (format helm-raise-command "emacs")))
(message "%s process...Finished." process))))
(setq helm-external-commands-list
(cons real-com
(delete real-com helm-external-commands-list))))))
(defun helm-get-mailcap-for-file (filename)
"Get the command to use for FILENAME from mailcap files."
(mailcap-parse-mailcaps)
(let* ((ext (file-name-extension filename))
(mime (when ext (mailcap-extension-to-mime ext)))
(result (when mime (mailcap-mime-info mime))))
;; If elisp file have no associations in .mailcap
;; `mailcap-maybe-eval' is returned, in this case just return nil.
(when (stringp result) (helm-basename result))))
(defun helm-get-default-program-for-file (filename)
"Try to find a default program to open FILENAME.
Try first in `helm-external-programs-associations' and then in mailcap file
if nothing found return nil."
(let* ((ext (file-name-extension filename))
(def-prog (assoc-default ext helm-external-programs-associations)))
(cond ((and def-prog (not (string= def-prog ""))) def-prog)
((and helm-default-external-file-browser (file-directory-p filename))
helm-default-external-file-browser)
(t (helm-get-mailcap-for-file filename)))))
(defun helm-open-file-externally (file)
"Open FILE with an external program.
Try to guess which program to use with `helm-get-default-program-for-file'.
If not found or a prefix arg is given query the user which tool to use."
(let* ((fname (expand-file-name file))
(collection (helm-external-commands-list-1 'sort))
(def-prog (helm-get-default-program-for-file fname))
(program (if (or helm-current-prefix-arg (not def-prog))
;; Prefix arg or no default program.
(prog1
(helm-comp-read
"Program: " collection
:must-match t
:name "Open file Externally"
:del-input nil
:history helm-external-command-history)
;; Always prompt to set this program as default.
(setq def-prog nil))
;; No prefix arg or default program exists.
def-prog)))
(unless (or def-prog ; Association exists, no need to record it.
;; Don't try to record non--filenames associations (e.g urls).
(not (file-exists-p fname)))
(when
(y-or-n-p
(format
"Do you want to make `%s' the default program for this kind of files? "
program))
(helm-aif (assoc (file-name-extension fname)
helm-external-programs-associations)
(setq helm-external-programs-associations
(delete it helm-external-programs-associations)))
(push (cons (file-name-extension fname)
(helm-read-string
"Program (Add args maybe and confirm): " program))
helm-external-programs-associations)
(customize-save-variable 'helm-external-programs-associations
helm-external-programs-associations)))
(helm-run-or-raise program file)
(setq helm-external-command-history
(cons program
(delete program
(cl-loop for i in helm-external-command-history
when (executable-find i) collect i))))))
;;;###autoload
(defun helm-run-external-command (program)
"Preconfigured `helm' to run External PROGRAM asyncronously from Emacs.
If program is already running exit with error.
You can set your own list of commands with
`helm-external-commands-list'."
(interactive (list
(helm-comp-read
"RunProgram: "
(helm-external-commands-list-1 'sort)
:must-match t
:del-input nil
:name "External Commands"
:history helm-external-command-history)))
(helm-run-or-raise program)
(setq helm-external-command-history
(cons program (delete program
(cl-loop for i in helm-external-command-history
when (executable-find i) collect i)))))
(provide 'helm-external)
;; Local Variables:
;; byte-compile-warnings: (not obsolete)
;; coding: utf-8
;; indent-tabs-mode: nil
;; End:
;;; helm-external ends here

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,172 @@
;;; helm-find.el --- helm interface for find command. -*- lexical-binding: t -*-
;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Code:
(require 'helm-files)
(require 'helm-external)
(defcustom helm-findutils-skip-boring-files t
"Ignore boring files in find command results."
:group 'helm-files
:type 'boolean)
(defcustom helm-findutils-search-full-path nil
"Search in full path with shell command find when non--nil.
I.e use the -path/ipath arguments of find instead of -name/iname."
:group 'helm-files
:type 'boolean)
(defvar helm-source-findutils
(helm-build-async-source "Find"
:header-name (lambda (name)
(concat name " in [" (helm-default-directory) "]"))
:candidates-process 'helm-find-shell-command-fn
:filtered-candidate-transformer 'helm-findutils-transformer
:action-transformer 'helm-transform-file-load-el
:persistent-action 'helm-ff-kill-or-find-buffer-fname
:action 'helm-type-file-actions
:keymap helm-generic-files-map
:candidate-number-limit 9999
:requires-pattern 3))
(defun helm-findutils-transformer (candidates _source)
(let (non-essential
(default-directory (helm-default-directory)))
(cl-loop for i in candidates
for abs = (expand-file-name
(helm-aif (file-remote-p default-directory)
(concat it i) i))
for type = (car (file-attributes abs))
for disp = (if (and helm-ff-transformer-show-only-basename
(not (string-match "[.]\\{1,2\\}$" i)))
(helm-basename abs) abs)
collect (cond ((eq t type)
(cons (propertize disp 'face 'helm-ff-directory)
abs))
((stringp type)
(cons (propertize disp 'face 'helm-ff-symlink)
abs))
(t (cons (propertize disp 'face 'helm-ff-file)
abs))))))
(defun helm-find--build-cmd-line ()
(require 'find-cmd)
(let* ((default-directory (or (file-remote-p default-directory 'localname)
default-directory))
(patterns+options (split-string helm-pattern "\\(\\`\\| +\\)\\* +"))
(fold-case (helm-set-case-fold-search (car patterns+options)))
(patterns (split-string (car patterns+options)))
(additional-options (and (cdr patterns+options)
(list (concat (cadr patterns+options) " "))))
(ignored-dirs ())
(ignored-files (when helm-findutils-skip-boring-files
(cl-loop for f in completion-ignored-extensions
if (string-match "/$" f)
do (push (replace-match "" nil t f)
ignored-dirs)
else collect (concat "*" f))))
(path-or-name (if helm-findutils-search-full-path
'(ipath path) '(iname name)))
(name-or-iname (if fold-case
(car path-or-name) (cadr path-or-name))))
(find-cmd (and ignored-dirs
`(prune (name ,@ignored-dirs)))
(and ignored-files
`(not (name ,@ignored-files)))
`(and ,@(mapcar
(lambda (pattern)
`(,name-or-iname ,(concat "*" pattern "*")))
patterns)
,@additional-options))))
(defun helm-find-shell-command-fn ()
"Asynchronously fetch candidates for `helm-find'.
Additional find options can be specified after a \"*\"
separator."
(let* (process-connection-type
non-essential
(cmd (helm-find--build-cmd-line))
(proc (start-file-process-shell-command "hfind" helm-buffer cmd)))
(helm-log "Find command:\n%s" cmd)
(prog1 proc
(set-process-sentinel
proc
(lambda (process event)
(helm-process-deferred-sentinel-hook
process event (helm-default-directory))
(if (string= event "finished\n")
(with-helm-window
(setq mode-line-format
'(" " mode-line-buffer-identification " "
(:eval (format "L%s" (helm-candidate-number-at-point))) " "
(:eval (propertize
(format "[Find process finished - (%s results)]"
(max (1- (count-lines
(point-min) (point-max)))
0))
'face 'helm-locate-finish))))
(force-mode-line-update))
(helm-log "Error: Find %s"
(replace-regexp-in-string "\n" "" event))))))))
(defun helm-find-1 (dir)
(let ((default-directory (file-name-as-directory dir)))
(helm :sources 'helm-source-findutils
:buffer "*helm find*"
:ff-transformer-show-only-basename nil
:case-fold-search helm-file-name-case-fold-search)))
;;; 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

View File

@@ -0,0 +1,337 @@
;;; helm-font --- Font and ucs selection for Helm -*- lexical-binding: t -*-
;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Code:
(require 'cl-lib)
(require 'helm)
(require 'helm-help)
(defgroup helm-font nil
"Related applications to display fonts in helm."
:group 'helm)
(defcustom helm-ucs-recent-size 10
"Number of recent chars to keep."
:type 'integer
:group 'helm-font)
(defcustom helm-ucs-actions
'(("Insert character" . helm-ucs-insert-char)
("Insert character name" . helm-ucs-insert-name)
("Insert character code in hex" . helm-ucs-insert-code)
("Kill marked characters" . helm-ucs-kill-char)
("Kill name" . helm-ucs-kill-name)
("Kill code" . helm-ucs-kill-code))
"Actions for `helm-source-ucs'."
:group 'helm-font
:type '(alist :key-type string :value-type function))
(defvar helm-ucs-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map helm-map)
(define-key map (kbd "<C-backspace>") 'helm-ucs-persistent-delete)
(define-key map (kbd "<C-left>") 'helm-ucs-persistent-backward)
(define-key map (kbd "<C-right>") 'helm-ucs-persistent-forward)
(define-key map (kbd "C-c SPC") 'helm-ucs-persistent-insert-space)
map)
"Keymap for `helm-ucs'.")
(defface helm-ucs-char
'((((class color) (background dark)) (:foreground "Gold")))
"Face used to display ucs characters."
:group 'helm-font)
;;; 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
:match-part (lambda (candidate) (cadr (split-string candidate ":")))
: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
:match-part (lambda (candidate) (cadr (split-string candidate ":")))
: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

View File

@@ -0,0 +1,308 @@
;;; helm-for-files.el --- helm-for-files and related. -*- lexical-binding: t -*-
;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Code:
(require 'helm-files)
(require 'helm-external)
(require 'helm-bookmark)
(defcustom helm-multi-files-toggle-locate-binding "C-c p"
"Default binding to switch back and forth locate in `helm-multi-files'."
:group 'helm-files
:type 'string)
(defcustom helm-for-files-preferred-list
'(helm-source-buffers-list
helm-source-recentf
helm-source-bookmarks
helm-source-file-cache
helm-source-files-in-current-dir
helm-source-locate)
"Your preferred sources for `helm-for-files' and `helm-multi-files'.
When adding a source here it is up to you to ensure the library of
this source is accessible and properly loaded."
:type '(repeat (choice symbol))
:group 'helm-files)
(defcustom helm-for-files-tramp-not-fancy t
"Colorize remote files when non nil.
Be aware that a nil value will make tramp display very slow."
:group 'helm-files
:type 'boolean)
;;; File Cache
;;
;;
(defvar file-cache-alist)
(defclass helm-file-cache (helm-source-in-buffer helm-type-file)
((init :initform (lambda () (require 'filecache)))))
(defun helm-file-cache-get-candidates ()
(cl-loop for item in file-cache-alist append
(cl-destructuring-bind (base &rest dirs) item
(cl-loop for dir in dirs collect
(concat dir base)))))
(defvar helm-source-file-cache nil)
(defcustom helm-file-cache-fuzzy-match nil
"Enable fuzzy matching in `helm-source-file-cache' when non--nil."
:group 'helm-files
:type 'boolean
:set (lambda (var val)
(set var val)
(setq helm-source-file-cache
(helm-make-source "File Cache" 'helm-file-cache
:fuzzy-match helm-file-cache-fuzzy-match
:data 'helm-file-cache-get-candidates))))
(cl-defun helm-file-cache-add-directory-recursively
(dir &optional match (ignore-dirs t))
(require 'filecache)
(cl-loop for f in (helm-walk-directory
dir
:path 'full
:directories nil
:match match
:skip-subdirs ignore-dirs)
do (file-cache-add-file f)))
(defun helm-transform-file-cache (actions _candidate)
(let ((source (helm-get-current-source)))
(if (string= (assoc-default 'name source) "File Cache")
(append actions
'(("Remove marked files from file-cache"
. helm-ff-file-cache-remove-file)))
actions)))
;;; Recentf files
;;
;;
(defvar helm-recentf--basename-flag nil)
(defun helm-recentf-pattern-transformer (pattern)
(let ((pattern-no-flag (replace-regexp-in-string " -b" "" pattern)))
(cond ((and (string-match " " pattern-no-flag)
(string-match " -b\\'" pattern))
(setq helm-recentf--basename-flag t)
pattern-no-flag)
((string-match "\\([^ ]*\\) -b\\'" pattern)
(prog1 (match-string 1 pattern)
(setq helm-recentf--basename-flag t)))
(t (setq helm-recentf--basename-flag nil)
pattern))))
(defcustom helm-turn-on-recentf t
"Automatically turn on `recentf-mode' when non-nil."
:group 'helm-files
:type 'boolean)
(defclass helm-recentf-source (helm-source-sync helm-type-file)
((init :initform (lambda ()
(require 'recentf)
(when helm-turn-on-recentf (recentf-mode 1))))
(candidates :initform (lambda () recentf-list))
(pattern-transformer :initform 'helm-recentf-pattern-transformer)
(match-part :initform (lambda (candidate)
(if (or helm-ff-transformer-show-only-basename
helm-recentf--basename-flag)
(helm-basename candidate) candidate)))
(migemo :initform t)
(persistent-action :initform 'helm-ff-kill-or-find-buffer-fname)))
(defmethod helm--setup-source :after ((source helm-recentf-source))
(setf (slot-value source 'action)
(append (symbol-value (helm-actions-from-type-file))
'(("Delete file(s) from recentf" .
(lambda (_candidate)
(cl-loop for file in (helm-marked-candidates)
do (setq recentf-list (delete file recentf-list)))))))))
(defvar helm-source-recentf nil
"See (info \"(emacs)File Conveniences\").
Set `recentf-max-saved-items' to a bigger value if default is too small.")
(defcustom helm-recentf-fuzzy-match nil
"Enable fuzzy matching in `helm-source-recentf' when non--nil."
:group 'helm-files
:type 'boolean
:set (lambda (var val)
(set var val)
(let ((helm-fuzzy-sort-fn 'helm-fuzzy-matching-sort-fn-preserve-ties-order))
(setq helm-source-recentf
(helm-make-source "Recentf" 'helm-recentf-source
:fuzzy-match helm-recentf-fuzzy-match)))))
;;; 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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,131 @@
;;; helm-id-utils.el --- Helm interface for id-utils. -*- lexical-binding: t -*-
;; Copyright (C) 2015 ~ 2018 Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Code:
(require 'helm-grep)
(require 'helm-help)
(defgroup helm-id-utils nil
"ID-Utils related Applications and libraries for Helm."
:group 'helm)
(defcustom helm-gid-program "gid"
"Name of gid command (usually `gid').
For Mac OS X users, if you install GNU coreutils, the name `gid'
might be occupied by `id' from GNU coreutils, and you should set
it to correct name (or absolute path), for example, if using
MacPorts to install id-utils, it should be `gid32'."
:group 'helm-id-utils
:type 'file)
(defcustom helm-gid-db-file-name "ID"
"Name of a database file created by `mkid' command from `ID-utils'."
:group 'helm-id-utils
:type 'string)
(defun helm-gid-candidates-process ()
(let* ((patterns (helm-mm-split-pattern helm-pattern))
(default-com (format "%s -r %s" helm-gid-program
(shell-quote-argument (car patterns))))
(cmd (helm-aif (cdr patterns)
(concat default-com
(cl-loop for p in it
concat (format " | grep --color=always %s"
(shell-quote-argument p))))
default-com))
(proc (start-process-shell-command
"gid" helm-buffer cmd)))
(set (make-local-variable 'helm-grep-last-cmd-line) cmd)
(prog1 proc
(set-process-sentinel
proc (lambda (_process event)
(when (string= event "finished\n")
(helm-maybe-show-help-echo)
(with-helm-window
(setq mode-line-format
'(" " mode-line-buffer-identification " "
(:eval (format "L%s" (helm-candidate-number-at-point))) " "
(:eval (propertize
(format "[Helm Gid process finished - (%s results)]"
(max (1- (count-lines
(point-min) (point-max)))
0))
'face 'helm-locate-finish))))
(force-mode-line-update))
(helm-log "Error: Gid %s"
(replace-regexp-in-string "\n" "" event))))))))
(defun helm-gid-filtered-candidate-transformer (candidates _source)
;; "gid -r" may add dups in some rare cases.
(cl-loop for c in (helm-fast-remove-dups candidates :test 'equal)
collect (helm-grep--filter-candidate-1 c)))
(defclass helm-gid-source (helm-source-async)
((header-name
:initform
(lambda (name)
(concat name " [" (helm-attr 'db-dir) "]")))
(db-dir :initarg :db-dir
:initform nil
:custom string
:documentation " Location of ID file.")
(candidates-process :initform #'helm-gid-candidates-process)
(filtered-candidate-transformer
:initform #'helm-gid-filtered-candidate-transformer)
(candidate-number-limit :initform 99999)
(action :initform (helm-make-actions
"Find File" 'helm-grep-action
"Find file other frame" 'helm-grep-other-frame
"Save results in grep buffer" 'helm-grep-save-results
"Find file other window" 'helm-grep-other-window))
(persistent-action :initform 'helm-grep-persistent-action)
(history :initform 'helm-grep-history)
(nohighlight :initform t)
(help-message :initform 'helm-grep-help-message)
(requires-pattern :initform 2)))
;;;###autoload
(defun helm-gid ()
"Preconfigured helm for `gid' command line of `ID-Utils'.
Need A database created with the command `mkid'
above `default-directory'.
Need id-utils as dependency which provide `mkid', `gid' etc...
See <https://www.gnu.org/software/idutils/>."
(interactive)
(let* ((db (locate-dominating-file
default-directory
helm-gid-db-file-name))
(helm-grep-default-directory-fn
(lambda () default-directory))
(helm--maybe-use-default-as-input t))
(cl-assert db nil "No DataBase found, create one with `mkid'")
(helm :sources (helm-make-source "Gid" 'helm-gid-source
:db-dir db)
:buffer "*helm gid*"
:keymap helm-grep-map
:truncate-lines helm-grep-truncate-lines)))
(provide 'helm-id-utils)
;; Local Variables:
;; byte-compile-warnings: (not obsolete)
;; coding: utf-8
;; indent-tabs-mode: nil
;; End:
;;; helm-id-utils ends here

View File

@@ -0,0 +1,363 @@
;;; helm-imenu.el --- Helm interface for Imenu -*- lexical-binding: t -*-
;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Code:
(require 'cl-lib)
(require 'helm)
(require 'helm-lib)
(require 'imenu)
(require 'helm-utils)
(require 'helm-help)
(defgroup helm-imenu nil
"Imenu related libraries and applications for helm."
:group 'helm)
(defcustom helm-imenu-delimiter " / "
"Delimit types of candidates and his value in `helm-buffer'."
:group 'helm-imenu
:type 'string)
(defcustom helm-imenu-execute-action-at-once-if-one
#'helm-imenu--execute-action-at-once-p
"Goto the candidate when only one is remaining."
:group 'helm-imenu
:type 'function)
(defcustom helm-imenu-lynx-style-map t
"Use Arrow keys to jump to occurences."
:group 'helm-imenu
:type 'boolean)
(defcustom helm-imenu-all-buffer-assoc nil
"Major mode association alist for `helm-imenu-in-all-buffers'.
Allow `helm-imenu-in-all-buffers' searching in these associated buffers
even if they are not derived from each other.
The alist is bidirectional, i.e no need to add '((foo . bar) (bar . foo))
only '((foo . bar)) is needed."
:type '(alist :key-type symbol :value-type symbol)
:group 'helm-imenu)
(defcustom helm-imenu-in-all-buffers-separate-sources t
"Display imenu index of each buffer in its own source when non-nil.
When nil all candidates are displayed in a single source.
NOTE: Each source will have as name \"Imenu <buffer-name>\".
`helm-source-imenu-all' will not be set, however it will continue
to be used as a flag for using default as input, if you do not want
this behavior, remove it from `helm-sources-using-default-as-input'
even if not using a single source to display imenu in all buffers."
:type 'boolean
:group 'helm-imenu)
(defcustom helm-imenu-type-faces
'(("^Variables$" . font-lock-variable-name-face)
("^\\(Function\\|Functions\\|Defuns\\)$" . font-lock-function-name-face)
("^\\(Types\\|Provides\\|Requires\\|Classes\\|Class\\|Includes\\|Imports\\|Misc\\|Code\\)$" . font-lock-type-face))
"Faces for showing type in helm-imenu.
This is a list of cons cells. The cdr of each cell is a face to be used,
and it can also just be like \\='(:foreground \"yellow\").
Each car is a regexp match pattern of the imenu type string."
:group 'helm-faces
:type '(repeat
(cons
(regexp :tag "Imenu type regexp pattern")
(sexp :tag "Face"))))
(defcustom helm-imenu-extra-modes nil
"Extra modes where helm-imenu-in-all-buffers should look into."
:group 'helm-imenu
:type '(repeat symbol))
;;; keymap
(defvar helm-imenu-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map helm-map)
(define-key map (kbd "M-<down>") 'helm-imenu-next-section)
(define-key map (kbd "M-<up>") 'helm-imenu-previous-section)
(when helm-imenu-lynx-style-map
(define-key map (kbd "<left>") 'helm-maybe-exit-minibuffer)
(define-key map (kbd "<right>") 'helm-execute-persistent-action)
(define-key map (kbd "M-<left>") 'helm-previous-source)
(define-key map (kbd "M-<right>") 'helm-next-source))
(delq nil map)))
(defun helm-imenu-next-or-previous-section (n)
(with-helm-buffer
(let* ((fn (lambda ()
(car (split-string (helm-get-selection nil t)
helm-imenu-delimiter))))
(curtype (funcall fn))
(move-fn (if (> n 0) #'helm-next-line #'helm-previous-line))
(stop-fn (if (> n 0)
#'helm-end-of-source-p
#'helm-beginning-of-source-p)))
(catch 'break
(while (not (funcall stop-fn))
(funcall move-fn)
(unless (string= curtype (funcall fn))
(throw 'break nil)))))))
(defun helm-imenu-next-section ()
(interactive)
(helm-imenu-next-or-previous-section 1))
(defun helm-imenu-previous-section ()
(interactive)
(helm-imenu-next-or-previous-section -1))
;;; Internals
(defvar helm-cached-imenu-alist nil)
(make-variable-buffer-local 'helm-cached-imenu-alist)
(defvar helm-cached-imenu-candidates nil)
(make-variable-buffer-local 'helm-cached-imenu-candidates)
(defvar helm-cached-imenu-tick nil)
(make-variable-buffer-local 'helm-cached-imenu-tick)
(defvar helm-imenu--in-all-buffers-cache nil)
(defvar helm-source-imenu nil "See (info \"(emacs)Imenu\")")
(defvar helm-source-imenu-all nil)
(defclass helm-imenu-source (helm-source-sync)
((candidates :initform 'helm-imenu-candidates)
(candidate-transformer :initform 'helm-imenu-transformer)
(persistent-action :initform 'helm-imenu-persistent-action)
(persistent-help :initform "Show this entry")
(nomark :initform t)
(keymap :initform helm-imenu-map)
(help-message :initform 'helm-imenu-help-message)
(action :initform 'helm-imenu-action)
(group :initform 'helm-imenu)))
(defcustom helm-imenu-fuzzy-match nil
"Enable fuzzy matching in `helm-source-imenu'."
:group 'helm-imenu
:type 'boolean
:set (lambda (var val)
(set var val)
(setq helm-source-imenu
(helm-make-source "Imenu" 'helm-imenu-source
:fuzzy-match helm-imenu-fuzzy-match))))
(defun helm-imenu--maybe-switch-to-buffer (candidate)
(let ((cand (cdr candidate)))
(helm-aif (and (markerp cand) (marker-buffer cand))
(switch-to-buffer it))))
(defun helm-imenu--execute-action-at-once-p ()
(let ((cur (helm-get-selection))
(mb (with-helm-current-buffer
(save-excursion
(goto-char (point-at-bol))
(point-marker)))))
(if (equal (cdr cur) mb)
(prog1 nil
(helm-set-pattern "")
(helm-force-update))
t)))
(defun helm-imenu-action (candidate)
"Default action for `helm-source-imenu'."
(helm-log-run-hook 'helm-goto-line-before-hook)
(helm-imenu--maybe-switch-to-buffer candidate)
(imenu candidate)
;; If semantic is supported in this buffer
;; imenu used `semantic-imenu-goto-function'
;; and position have been highlighted,
;; no need to highlight again.
(unless (eq imenu-default-goto-function
'semantic-imenu-goto-function)
(helm-highlight-current-line)))
(defun helm-imenu-persistent-action (candidate)
"Default persistent action for `helm-source-imenu'."
(helm-imenu--maybe-switch-to-buffer candidate)
(imenu candidate)
(helm-highlight-current-line))
(defun helm-imenu-candidates (&optional buffer)
(with-current-buffer (or buffer helm-current-buffer)
(let ((tick (buffer-modified-tick)))
(if (eq helm-cached-imenu-tick tick)
helm-cached-imenu-candidates
(setq imenu--index-alist nil)
(prog1 (setq helm-cached-imenu-candidates
(let ((index (imenu--make-index-alist t)))
(helm-imenu--candidates-1
(delete (assoc "*Rescan*" index) index))))
(setq helm-cached-imenu-tick tick))))))
(defun helm-imenu-candidates-in-all-buffers (&optional build-sources)
(let* ((lst (buffer-list))
(progress-reporter (make-progress-reporter
"Imenu indexing buffers..." 1 (length lst))))
(prog1
(cl-loop with cur-buf = (if build-sources
(current-buffer) helm-current-buffer)
for b in lst
for count from 1
when (with-current-buffer b
(and (or (member major-mode helm-imenu-extra-modes)
(derived-mode-p 'prog-mode))
(helm-same-major-mode-p
cur-buf helm-imenu-all-buffer-assoc)))
if build-sources
collect (helm-make-source
(format "Imenu in %s" (buffer-name b))
'helm-imenu-source
:candidates (with-current-buffer b
(helm-imenu-candidates b))
:fuzzy-match helm-imenu-fuzzy-match)
else
append (with-current-buffer b
(helm-imenu-candidates b))
do (progress-reporter-update progress-reporter count))
(progress-reporter-done progress-reporter))))
(defun helm-imenu--candidates-1 (alist)
(cl-loop for elm in alist
nconc (cond
((imenu--subalist-p elm)
(helm-imenu--candidates-1
(cl-loop for (e . v) in (cdr elm) collect
(cons (propertize
e 'helm-imenu-type (car elm))
;; If value is an integer, convert it
;; to a marker, otherwise it is a cons cell
;; and it will be converted on next recursions.
;; (Issue #1060) [1].
(if (integerp v) (copy-marker v) v)))))
((listp (cdr elm))
(and elm (list elm)))
(t
;; bug in imenu, should not be needed.
(and (cdr elm)
;; Semantic uses overlays whereas imenu uses
;; markers (issue #1706).
(setcdr elm (pcase (cdr elm) ; Same as [1].
((and ov (pred overlayp))
(copy-overlay ov))
((and mk (or (pred markerp)
(pred integerp)))
(copy-marker mk))))
(list elm))))))
(defun helm-imenu--get-prop (item)
;; property value of ITEM can have itself
;; a property value which have itself a property value
;; ...and so on; Return a list of all these
;; properties values starting at ITEM.
(let* ((prop (get-text-property 0 'helm-imenu-type item))
(lst (list prop item)))
(when prop
(while prop
(setq prop (get-text-property 0 'helm-imenu-type prop))
(and prop (push prop lst)))
lst)))
(defun helm-imenu-transformer (candidates)
(cl-loop for (k . v) in candidates
;; (k . v) == (symbol-name . marker)
for bufname = (buffer-name
(pcase v
((pred overlayp) (overlay-buffer v))
((or (pred markerp) (pred integerp))
(marker-buffer v))))
for types = (or (helm-imenu--get-prop k)
(list (if (with-current-buffer bufname
(derived-mode-p 'prog-mode))
"Function"
"Top level")
k))
for disp1 = (mapconcat
(lambda (x)
(propertize
x 'face
(cl-loop for (p . f) in helm-imenu-type-faces
when (string-match p x) return f
finally return 'default)))
types helm-imenu-delimiter)
for disp = (propertize disp1 'help-echo bufname)
collect
(cons disp (cons k v))))
;;;###autoload
(defun helm-imenu ()
"Preconfigured `helm' for `imenu'."
(interactive)
(unless helm-source-imenu
(setq helm-source-imenu
(helm-make-source "Imenu" 'helm-imenu-source
:fuzzy-match helm-imenu-fuzzy-match)))
(let ((imenu-auto-rescan t)
(str (thing-at-point 'symbol))
(helm-execute-action-at-once-if-one
helm-imenu-execute-action-at-once-if-one))
(helm :sources 'helm-source-imenu
:default (list (concat "\\_<" (and str (regexp-quote str)) "\\_>") str)
:preselect str
:buffer "*helm imenu*")))
;;;###autoload
(defun helm-imenu-in-all-buffers ()
"Preconfigured helm for fetching imenu entries in all buffers with similar mode as current.
A mode is similar as current if it is the same, it is derived i.e `derived-mode-p'
or it have an association in `helm-imenu-all-buffer-assoc'."
(interactive)
(unless helm-imenu-in-all-buffers-separate-sources
(unless helm-source-imenu-all
(setq helm-source-imenu-all
(helm-make-source "Imenu in all buffers" 'helm-imenu-source
:init (lambda ()
;; Use a cache to avoid repeatedly sending
;; progress-reporter message when updating
;; (Issue #1704).
(setq helm-imenu--in-all-buffers-cache
(helm-imenu-candidates-in-all-buffers)))
:candidates 'helm-imenu--in-all-buffers-cache
:fuzzy-match helm-imenu-fuzzy-match))))
(let ((imenu-auto-rescan t)
(str (thing-at-point 'symbol))
(helm-execute-action-at-once-if-one
helm-imenu-execute-action-at-once-if-one)
(helm--maybe-use-default-as-input
(not (null (memq 'helm-source-imenu-all
helm-sources-using-default-as-input))))
(sources (if helm-imenu-in-all-buffers-separate-sources
(helm-imenu-candidates-in-all-buffers 'build-sources)
'(helm-source-imenu-all))))
(helm :sources sources
:default (list (concat "\\_<" (and str (regexp-quote str)) "\\_>") str)
:preselect (unless helm--maybe-use-default-as-input str)
:buffer "*helm imenu all*")))
(provide 'helm-imenu)
;; Local Variables:
;; byte-compile-warnings: (not obsolete)
;; coding: utf-8
;; indent-tabs-mode: nil
;; End:
;;; helm-imenu.el ends here

View File

@@ -0,0 +1,261 @@
;;; helm-info.el --- Browse info index with helm -*- lexical-binding: t -*-
;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Code:
(require 'cl-lib)
(require 'helm)
(require 'helm-lib)
(require 'helm-utils)
(require 'info)
(declare-function Info-index-nodes "info" (&optional file))
(declare-function Info-goto-node "info" (&optional fork))
(declare-function Info-find-node "info.el" (filename nodename &optional no-going-back))
(defvar Info-history)
(defvar Info-directory-list)
;;; Customize
(defgroup helm-info nil
"Info-related applications and libraries for Helm."
:group 'helm)
(defcustom helm-info-default-sources
'(helm-source-info-elisp
helm-source-info-cl
helm-source-info-eieio
helm-source-info-pages)
"Default sources to use for looking up symbols at point in Info
files with `helm-info-at-point'."
:group 'helm-info
:type '(repeat (choice symbol)))
;;; Build info-index sources with `helm-info-source' class.
(cl-defun helm-info-init (&optional (file (helm-attr 'info-file)))
;; Allow reinit candidate buffer when using edebug.
(helm-aif (and debug-on-error
(helm-candidate-buffer))
(kill-buffer it))
(unless (helm-candidate-buffer)
(save-selected-window
(info file " *helm info temp buffer*")
(let ((tobuf (helm-candidate-buffer 'global))
Info-history
start end line)
(cl-dolist (node (Info-index-nodes))
(Info-goto-node node)
(goto-char (point-min))
(while (search-forward "\n* " nil t)
(unless (search-forward "Menu:\n" (1+ (point-at-eol)) t)
(setq start (point-at-bol)
;; Fix issue #1503 by getting the invisible
;; info displayed on next line in long strings.
;; e.g "* Foo.\n (line 12)" instead of
;; "* Foo.(line 12)"
end (or (save-excursion
(goto-char (point-at-bol))
(re-search-forward "(line +[0-9]+)" nil t))
(point-at-eol))
;; Long string have a new line inserted before the
;; invisible spec, remove it.
line (replace-regexp-in-string
"\n" "" (buffer-substring start end)))
(with-current-buffer tobuf
(insert line)
(insert "\n")))))
(bury-buffer)))))
(defun helm-info-goto (node-line)
(Info-goto-node (car node-line))
(helm-goto-line (cdr node-line)))
(defun helm-info-display-to-real (line)
(and (string-match
;; This regexp is stolen from Info-apropos-matches
"\\* +\\([^\n]*.+[^\n]*\\):[ \t]+\\([^\n]*\\)\\.\\(?:[ \t\n]*(line +\\([0-9]+\\))\\)?" line)
(cons (format "(%s)%s" (helm-attr 'info-file) (match-string 2 line))
(string-to-number (or (match-string 3 line) "1")))))
(defclass helm-info-source (helm-source-in-buffer)
((info-file :initarg :info-file
:initform nil
:custom 'string)
(init :initform #'helm-info-init)
(display-to-real :initform #'helm-info-display-to-real)
(get-line :initform #'buffer-substring)
(action :initform '(("Goto node" . helm-info-goto)))))
(defmacro helm-build-info-source (fname &rest args)
`(helm-make-source (concat "Info Index: " ,fname) 'helm-info-source
:info-file ,fname ,@args))
(defun helm-build-info-index-command (name doc source buffer)
"Define a helm command NAME with documentation DOC.
Arg SOURCE will be an existing helm source named
`helm-source-info-<NAME>' and BUFFER a string buffer name."
(defalias (intern (concat "helm-info-" name))
(lambda ()
(interactive)
(helm :sources source
:buffer buffer
:candidate-number-limit 1000))
doc))
(defun helm-define-info-index-sources (var-value &optional commands)
"Define helm sources named helm-source-info-<NAME>.
Sources are generated for all entries of `helm-default-info-index-list'.
If COMMANDS arg is non-nil, also build commands named `helm-info-<NAME>'.
Where NAME is an element of `helm-default-info-index-list'."
(cl-loop for str in var-value
for sym = (intern (concat "helm-source-info-" str))
do (set sym (helm-build-info-source str))
when commands
do (helm-build-info-index-command
str (format "Predefined helm for %s info." str)
sym (format "*helm info %s*" str))))
(defun helm-info-index-set (var value)
(set var value)
(helm-define-info-index-sources value t))
;;; Search Info files
;; `helm-info' is the main entry point here. It prompts the user for an Info
;; file, then a term in the file's index to jump to.
(defvar helm-info-searched (make-ring 32)
"Ring of previously searched Info files.")
(defun helm-get-info-files ()
"Return list of Info files to use for `helm-info'.
Elements of the list are strings of Info file names without
extensions (e.g. \"emacs\" for file \"emacs.info.gz\"). Info
files are found by searching directories in
`Info-directory-list'."
(let ((files (cl-loop for d in (or Info-directory-list
Info-default-directory-list)
when (file-directory-p d)
append (directory-files d nil "\\.info"))))
(helm-fast-remove-dups
(cl-loop for f in files collect
(helm-file-name-sans-extension f))
:test 'equal)))
(defcustom helm-default-info-index-list
(helm-get-info-files)
"Info files to search in with `helm-info'."
:group 'helm-info
:type '(repeat (choice string))
:set 'helm-info-index-set)
(defun helm-info-search-index (candidate)
"Search the index of CANDIDATE's Info file using the function
helm-info-<CANDIDATE>."
(let ((helm-info-function
(intern-soft (concat "helm-info-" candidate))))
(when (fboundp helm-info-function)
(funcall helm-info-function)
(ring-insert helm-info-searched candidate))))
(defun helm-def-source--info-files ()
"Return a `helm' source for Info files."
(helm-build-sync-source "Helm Info"
:candidates
(lambda () (copy-sequence helm-default-info-index-list))
:candidate-number-limit 999
:candidate-transformer
(lambda (candidates)
(sort candidates #'string-lessp))
:nomark t
:action '(("Search index" . helm-info-search-index))))
;;;###autoload
(defun helm-info (&optional refresh)
"Preconfigured `helm' for searching Info files' indices.
With a prefix argument \\[universal-argument], set REFRESH to non-nil.
Optional parameter REFRESH, when non-nil, reevaluates
`helm-default-info-index-list'. If the variable has been
customized, set it to its saved value. If not, set it to its
standard value. See `custom-reevaluate-setting' for more.
REFRESH is useful when new Info files are installed. If
`helm-default-info-index-list' has not been customized, the new
Info files are made available."
(interactive "P")
(let ((default (unless (ring-empty-p helm-info-searched)
(ring-ref helm-info-searched 0))))
(when refresh
(custom-reevaluate-setting 'helm-default-info-index-list))
(helm :sources (helm-def-source--info-files)
:buffer "*helm Info*"
:preselect (and default
(concat "\\_<" (regexp-quote default) "\\_>")))))
;;;; Info at point
;; `helm-info-at-point' is the main entry point here. It searches for the
;; symbol at point through the Info sources defined in
;; `helm-info-default-sources' and jumps to it.
(defvar helm-info--pages-cache nil
"Cache for all Info pages on the system.")
(defvar helm-source-info-pages
(helm-build-sync-source "Info Pages"
:init #'helm-info-pages-init
:candidates (lambda () helm-info--pages-cache)
:action '(("Show with Info" .(lambda (node-str)
(info (replace-regexp-in-string
"^[^:]+: " "" node-str)))))
:requires-pattern 2)
"Helm source for Info pages.")
(defun helm-info-pages-init ()
"Collect candidates for initial Info node Top."
(if helm-info--pages-cache
helm-info--pages-cache
(let ((info-topic-regexp "\\* +\\([^:]+: ([^)]+)[^.]*\\)\\.")
topics)
(with-temp-buffer
(Info-find-node "dir" "top")
(goto-char (point-min))
(while (re-search-forward info-topic-regexp nil t)
(push (match-string-no-properties 1) topics))
(kill-buffer))
(setq helm-info--pages-cache topics))))
;;;###autoload
(defun helm-info-at-point ()
"Preconfigured `helm' for searching info at point."
(interactive)
(helm :sources helm-info-default-sources
:buffer "*helm info*"))
(provide 'helm-info)
;; Local Variables:
;; byte-compile-warnings: (not obsolete)
;; coding: utf-8
;; indent-tabs-mode: nil
;; End:
;;; helm-info.el ends here

View File

@@ -0,0 +1,484 @@
;;; helm-locate.el --- helm interface for locate. -*- lexical-binding: t -*-
;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;; NOTE for WINDOZE users:
;; You have to install Everything with his command line interface here:
;; http://www.voidtools.com/download.php
;;; Code:
(require 'cl-lib)
(require 'helm)
(require 'helm-types)
(require 'helm-help)
(defgroup helm-locate nil
"Locate related Applications and libraries for Helm."
:group 'helm)
(defcustom helm-locate-db-file-regexp "m?locate\.db$"
"Default regexp to match locate database.
If nil Search in all files."
:type 'string
:group 'helm-locate)
(defcustom helm-ff-locate-db-filename "locate.db"
"The basename of the locatedb file you use locally in your directories.
When this is set and `helm' find such a file in the directory from
where you launch locate, it will use this file and will not prompt you
for a db file.
Note that this happen only when locate is launched with a prefix arg."
:group 'helm-locate
:type 'string)
(defcustom helm-locate-command nil
"A list of arguments for locate program.
Helm will calculate a default value for your system on startup unless
`helm-locate-command' is non-nil, here the default values it will use
according to your system:
Gnu/linux: \"locate %s -e -A --regex %s\"
berkeley-unix: \"locate %s %s\"
windows-nt: \"es %s %s\"
Others: \"locate %s %s\"
This string will be passed to format so it should end with `%s'.
The first format spec is used for the \"-i\" value of locate/es,
So don't set it directly but use `helm-locate-case-fold-search'
for this.
The last option must be the one preceding pattern i.e \"-r\" or \"--regex\".
You will be able to pass other options such as \"-b\" or \"l\"
during helm invocation after entering pattern only when multi matching,
not when fuzzy matching.
Note that the \"-b\" option is added automatically by helm when
var `helm-locate-fuzzy-match' is non-nil and switching back from
multimatch to fuzzy matching (this is done automatically when a space
is detected in pattern)."
:type 'string
:group 'helm-locate)
(defcustom helm-locate-create-db-command
"updatedb -l 0 -o '%s' -U '%s'"
"Command used to create a locale locate db file."
:type 'string
:group 'helm-locate)
(defcustom helm-locate-case-fold-search helm-case-fold-search
"It have the same meaning as `helm-case-fold-search'.
The -i option of locate will be used depending of value of
`helm-pattern' when this is set to 'smart.
When nil \"-i\" will not be used at all.
and when non--nil it will always be used.
NOTE: the -i option of the \"es\" command used on windows does
the opposite of \"locate\" command."
:group 'helm-locate
:type 'symbol)
(defcustom helm-locate-fuzzy-match nil
"Enable fuzzy matching in `helm-locate'.
Note that when this is enabled searching is done on basename."
:group 'helm-locate
:type 'boolean)
(defcustom helm-locate-fuzzy-sort-fn
#'helm-locate-default-fuzzy-sort-fn
"Default fuzzy matching sort function for locate."
:group 'helm-locate
:type 'boolean)
(defcustom helm-locate-project-list nil
"A list of directories, your projects.
When set, allow browsing recursively files in all
directories of this list with `helm-projects-find-files'."
:group 'helm-locate
:type '(repeat string))
(defcustom helm-locate-recursive-dirs-command "locate -i -e -A --regex '^%s' '%s.*$'"
"Command used for recursive directories completion in `helm-find-files'.
For Windows and `es' use something like \"es -r ^%s.*%s.*$\"
The two format specs are mandatory.
If for some reasons you can't use locate because your filesystem
doesn't have a data base, you can use find command from findutils but
be aware that it will be much slower, see `helm-find-files' embebded
help for more infos."
:type 'string
:group 'helm-files)
(defvar helm-generic-files-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map helm-map)
(define-key map (kbd "C-]") 'helm-ff-run-toggle-basename)
(define-key map (kbd "C-s") 'helm-ff-run-grep)
(define-key map (kbd "M-g s") 'helm-ff-run-grep)
(define-key map (kbd "M-g z") 'helm-ff-run-zgrep)
(define-key map (kbd "M-g p") 'helm-ff-run-pdfgrep)
(define-key map (kbd "C-c g") 'helm-ff-run-gid)
(define-key map (kbd "M-R") 'helm-ff-run-rename-file)
(define-key map (kbd "M-C") 'helm-ff-run-copy-file)
(define-key map (kbd "M-B") 'helm-ff-run-byte-compile-file)
(define-key map (kbd "M-L") 'helm-ff-run-load-file)
(define-key map (kbd "M-S") 'helm-ff-run-symlink-file)
(define-key map (kbd "M-H") 'helm-ff-run-hardlink-file)
(define-key map (kbd "M-D") 'helm-ff-run-delete-file)
(define-key map (kbd "C-=") 'helm-ff-run-ediff-file)
(define-key map (kbd "C-c =") 'helm-ff-run-ediff-merge-file)
(define-key map (kbd "C-c o") 'helm-ff-run-switch-other-window)
(define-key map (kbd "C-c r") 'helm-ff-run-find-file-as-root)
(define-key map (kbd "C-c C-o") 'helm-ff-run-switch-other-frame)
(define-key map (kbd "M-i") 'helm-ff-properties-persistent)
(define-key map (kbd "C-c C-x") 'helm-ff-run-open-file-externally)
(define-key map (kbd "C-c X") 'helm-ff-run-open-file-with-default-tool)
(define-key map (kbd "M-.") 'helm-ff-run-etags)
(define-key map (kbd "C-c @") 'helm-ff-run-insert-org-link)
(define-key map (kbd "C-x C-q") 'helm-ff-run-marked-files-in-dired)
(define-key map (kbd "C-c C-a") 'helm-ff-run-mail-attach-files)
map)
"Generic Keymap for files.")
(defface helm-locate-finish
'((t (:foreground "Green")))
"Face used in mode line when locate process is finish."
:group 'helm-locate)
(defun helm-ff-find-locatedb (&optional from-ff)
"Try to find if a local locatedb file is available.
The search is done in `helm-ff-default-directory' or
fall back to `default-directory' if FROM-FF is nil."
(helm-aif (and helm-ff-locate-db-filename
(locate-dominating-file
(or (and from-ff
helm-ff-default-directory)
default-directory)
helm-ff-locate-db-filename))
(expand-file-name helm-ff-locate-db-filename it)))
(defun helm-locate-create-db-default-function (db-name directory)
"Default function used to create a locale locate db file.
Argument DB-NAME name of the db file.
Argument DIRECTORY root of file system subtree to scan."
(format helm-locate-create-db-command
db-name (expand-file-name directory)))
(defvar helm-locate-create-db-function
#'helm-locate-create-db-default-function
"Function used to create a locale locate db file.
It should receive the same arguments as
`helm-locate-create-db-default-function'.")
(defun helm-locate-1 (&optional localdb init from-ff default)
"Generic function to run Locate.
Prefix arg LOCALDB when (4) search and use a local locate db file when it
exists or create it, when (16) force update of existing db file
even if exists.
It have no effect when locate command is 'es'.
INIT is a string to use as initial input in prompt.
See `helm-locate-with-db' and `helm-locate'."
(require 'helm-mode)
(helm-locate-set-command)
(let ((pfn (lambda (candidate)
(if (file-directory-p candidate)
(message "Error: The locate Db should be a file")
(if (= (shell-command
(funcall helm-locate-create-db-function
candidate
helm-ff-default-directory))
0)
(message "New locatedb file `%s' created" candidate)
(error "Failed to create locatedb file `%s'" candidate)))))
(locdb (and localdb
(not (string-match "^es" helm-locate-command))
(or (and (equal '(4) localdb)
(helm-ff-find-locatedb from-ff))
(helm-read-file-name
"Create Locate Db file: "
:initial-input (expand-file-name "locate.db"
(or helm-ff-default-directory
default-directory))
:preselect helm-locate-db-file-regexp
:test (lambda (x)
(if helm-locate-db-file-regexp
;; Select only locate db files and directories
;; to allow navigation.
(or (string-match
helm-locate-db-file-regexp x)
(file-directory-p x))
x)))))))
(when (and locdb (or (equal localdb '(16))
(not (file-exists-p locdb))))
(funcall pfn locdb))
(helm-locate-with-db (and localdb locdb) init default)))
(defun helm-locate-set-command ()
"Setup `helm-locate-command' if not already defined."
(unless helm-locate-command
(setq helm-locate-command
(cl-case system-type
(gnu/linux "locate %s -e -A --regex %s")
(berkeley-unix "locate %s %s")
(windows-nt "es %s %s")
(t "locate %s %s")))))
(defun helm-locate-initial-setup ()
(require 'helm-for-files)
(helm-locate-set-command))
(defvar helm-file-name-history nil)
(defun helm-locate-with-db (&optional db initial-input default)
"Run locate -d DB.
If DB is not given or nil use locate without -d option.
Argument DB can be given as a string or list of db files.
Argument INITIAL-INPUT is a string to use as initial-input.
See also `helm-locate'."
(require 'helm-files)
(when (and db (stringp db)) (setq db (list db)))
(helm-locate-set-command)
(let ((helm-locate-command
(if db
(replace-regexp-in-string
"locate"
(format (if helm-locate-fuzzy-match
"locate -b -d '%s'" "locate -d '%s'")
(mapconcat 'identity
;; Remove eventually
;; marked directories by error.
(cl-loop for i in db
unless (file-directory-p i)
;; expand-file-name to resolve
;; abbreviated fnames not
;; expanding inside single
;; quotes i.e. '%s'.
collect (expand-file-name i))
":"))
helm-locate-command)
(if (and helm-locate-fuzzy-match
(not (string-match-p "\\`locate -b" helm-locate-command)))
(replace-regexp-in-string
"\\`locate" "locate -b" helm-locate-command)
helm-locate-command))))
(setq helm-file-name-history (mapcar 'helm-basename file-name-history))
(helm :sources 'helm-source-locate
:buffer "*helm locate*"
:ff-transformer-show-only-basename nil
:input initial-input
:default default
:history 'helm-file-name-history)))
(defun helm-locate-init ()
"Initialize async locate process for `helm-source-locate'."
(let* ((locate-is-es (string-match "\\`es" helm-locate-command))
(real-locate (string-match "\\`locate" helm-locate-command))
(case-sensitive-flag (if locate-is-es "-i" ""))
(ignore-case-flag (if (or locate-is-es
(not real-locate)) "" "-i"))
(args (helm-mm-split-pattern helm-pattern))
(cmd (format helm-locate-command
(cl-case helm-locate-case-fold-search
(smart (let ((case-fold-search nil))
(if (string-match "[[:upper:]]" helm-pattern)
case-sensitive-flag
ignore-case-flag)))
(t (if helm-locate-case-fold-search
ignore-case-flag
case-sensitive-flag)))
(concat
;; The pattern itself.
(shell-quote-argument (car args)) " "
;; Possible locate args added
;; after pattern, don't quote them.
(mapconcat 'identity (cdr args) " "))))
(default-directory (if (file-directory-p default-directory)
default-directory "/")))
(helm-log "Starting helm-locate process")
(helm-log "Command line used was:\n\n%s"
(concat ">>> " (propertize cmd 'face 'font-lock-comment-face) "\n\n"))
(prog1
(start-process-shell-command
"locate-process" helm-buffer
cmd)
(set-process-sentinel
(get-buffer-process helm-buffer)
(lambda (process event)
(let* ((err (process-exit-status process))
(noresult (= err 1)))
(cond (noresult
(with-helm-buffer
(unless (cdr helm-sources)
(insert (concat "* Exit with code 1, no result found,"
" command line was:\n\n "
cmd)))))
((string= event "finished\n")
(when (and helm-locate-fuzzy-match
(not (string-match-p "\\s-" helm-pattern)))
(helm-redisplay-buffer))
(with-helm-window
(setq mode-line-format
'(" " mode-line-buffer-identification " "
(:eval (format "L%s" (helm-candidate-number-at-point))) " "
(:eval (propertize
(format "[Locate process finished - (%s results)]"
(max (1- (count-lines
(point-min) (point-max)))
0))
'face 'helm-locate-finish))))
(force-mode-line-update)))
(t
(helm-log "Error: Locate %s"
(replace-regexp-in-string "\n" "" event))))))))))
(defun helm-locate-default-fuzzy-sort-fn (candidates)
"Default sort function for files in fuzzy matching.
Sort is done on basename of CANDIDATES."
(helm-fuzzy-matching-default-sort-fn-1 candidates nil t))
(defclass helm-locate-source (helm-source-async helm-type-file)
((init :initform 'helm-locate-initial-setup)
(candidates-process :initform 'helm-locate-init)
(requires-pattern :initform 3)
(history :initform 'helm-file-name-history)
(persistent-action :initform 'helm-ff-kill-or-find-buffer-fname)
(candidate-number-limit :initform 9999)
(redisplay :initform (progn helm-locate-fuzzy-sort-fn))
(group :initform 'helm-locate)))
(defvar helm-source-locate
(helm-make-source "Locate" 'helm-locate-source
:pattern-transformer 'helm-locate-pattern-transformer
;; :match-part is only used here to tell helm which part
;; of candidate to highlight.
:match-part (lambda (candidate)
(if (or (string-match-p " -b\\'" helm-pattern)
(and helm-locate-fuzzy-match
(not (string-match "\\s-" helm-pattern))))
(helm-basename candidate)
candidate))))
(defun helm-locate-pattern-transformer (pattern)
(if helm-locate-fuzzy-match
;; When fuzzy is enabled helm add "-b" option on startup.
(cond ((string-match-p " " pattern)
(when (string-match "\\`locate -b" helm-locate-command)
(setq helm-locate-command
(replace-match "locate" t t helm-locate-command)))
pattern)
(t
(unless (string-match-p "\\`locate -b" helm-locate-command)
(setq helm-locate-command
(replace-regexp-in-string
"\\`locate" "locate -b" helm-locate-command)))
(helm--mapconcat-pattern pattern)))
pattern))
(defun helm-locate-find-dbs-in-projects (&optional update)
(let* ((pfn (lambda (candidate directory)
(unless (= (shell-command
(funcall helm-locate-create-db-function
candidate
directory))
0)
(error "Failed to create locatedb file `%s'" candidate)))))
(cl-loop for p in helm-locate-project-list
for db = (expand-file-name
helm-ff-locate-db-filename
(file-name-as-directory p))
if (and (null update) (file-exists-p db))
collect db
else do (funcall pfn db p)
and collect db)))
;;; Directory completion for hff.
;;
(defclass helm-locate-subdirs-source (helm-source-in-buffer)
((basedir :initarg :basedir
:initform nil
:custom string)
(subdir :initarg :subdir
:initform nil
:custom 'string)
(data :initform #'helm-locate-init-subdirs)
(group :initform 'helm-locate)))
(defun helm-locate-init-subdirs ()
(with-temp-buffer
(call-process-shell-command
(format helm-locate-recursive-dirs-command
(if (string-match-p "\\`es" helm-locate-recursive-dirs-command)
;; Fix W32 paths.
(replace-regexp-in-string
"/" "\\\\\\\\" (helm-attr 'basedir))
(helm-attr 'basedir))
(helm-attr 'subdir))
nil t nil)
(buffer-string)))
;;;###autoload
(defun helm-projects-find-files (update)
"Find files with locate in `helm-locate-project-list'.
With a prefix arg refresh the database in each project."
(interactive "P")
(helm-locate-set-command)
(cl-assert (and (string-match-p "\\`locate" helm-locate-command)
(executable-find "updatedb"))
nil "Unsupported locate version")
(let ((dbs (helm-locate-find-dbs-in-projects update)))
(if dbs
(helm-locate-with-db dbs)
(user-error "No projects found, please setup `helm-locate-project-list'"))))
;;;###autoload
(defun helm-locate (arg)
"Preconfigured `helm' for Locate.
Note: you can add locate options after entering pattern.
See 'man locate' for valid options and also `helm-locate-command'.
You can specify a local database with prefix argument ARG.
With two prefix arg, refresh the current local db or create it
if it doesn't exists.
To create a user specific db, use
\"updatedb -l 0 -o db_path -U directory\".
Where db_path is a filename matched by
`helm-locate-db-file-regexp'."
(interactive "P")
(helm-set-local-variable 'helm-async-outer-limit-hook
(list (lambda ()
(when (and helm-locate-fuzzy-match
(not (string-match-p
"\\s-" helm-pattern)))
(helm-redisplay-buffer)))))
(setq helm-ff-default-directory default-directory)
(helm-locate-1 arg nil nil (thing-at-point 'filename)))
(provide 'helm-locate)
;; Local Variables:
;; byte-compile-warnings: (not obsolete)
;; coding: utf-8
;; indent-tabs-mode: nil
;; End:
;;; helm-locate.el ends here

View File

@@ -0,0 +1,119 @@
;;; helm-man.el --- Man and woman UI -*- lexical-binding: t -*-
;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Code:
(require 'cl-lib)
(require 'helm)
(require 'helm-help)
(defvar woman-topic-all-completions)
(defvar woman-manpath)
(defvar woman-path)
(defvar woman-expanded-directory-path)
(declare-function woman-file-name "woman.el" (topic &optional re-cache))
(declare-function woman-file-name-all-completions "woman.el" (topic))
(declare-function Man-getpage-in-background "man.el" (topic))
(declare-function woman-expand-directory-path "woman.el" (path-dirs path-regexps))
(declare-function woman-topic-all-completions "woman.el" (path))
(declare-function helm-generic-sort-fn "helm-utils.el" (S1 S2))
(defgroup helm-man nil
"Man and Woman applications for helm."
:group 'helm)
(defcustom helm-man-or-woman-function 'Man-getpage-in-background
"Default command to display a man page."
:group 'helm-man
:type '(radio :tag "Preferred command to display a man page"
(const :tag "Man" Man-getpage-in-background)
(const :tag "Woman" woman)))
(defcustom helm-man-format-switches (cl-case system-type
((darwin macos) "%s")
(t "-l %s"))
"Arguments to pass to the `manual-entry' function.
Arguments are passed to `manual-entry' with `format.'"
:group 'helm-man
:type 'string)
;; Internal
(defvar helm-man--pages nil
"All man pages on system.
Will be calculated the first time you invoke helm with this
source.")
(defun helm-man-default-action (candidate)
"Default action for jumping to a woman or man page from helm."
(let ((wfiles (mapcar #'car (woman-file-name-all-completions candidate))))
(condition-case nil
(let ((file (if (cdr wfiles)
(helm-comp-read "ManFile: " wfiles :must-match t)
(car wfiles))))
(if (eq helm-man-or-woman-function 'Man-getpage-in-background)
(manual-entry (format helm-man-format-switches file))
(condition-case nil
(woman-find-file file)
;; If woman is unable to format correctly
;; try Man instead.
(error (kill-buffer)
(manual-entry (format helm-man-format-switches file))))))
;; If even Man failed with file as argument, try again with Man
;; but using Topic candidate instead of the file calculated by
;; woman.
(error (kill-buffer)
(Man-getpage-in-background candidate)))))
(defun helm-man--init ()
(require 'woman)
(require 'helm-utils)
(unless helm-man--pages
(setq woman-expanded-directory-path
(woman-expand-directory-path woman-manpath woman-path))
(setq woman-topic-all-completions
(woman-topic-all-completions woman-expanded-directory-path))
(setq helm-man--pages (mapcar 'car woman-topic-all-completions)))
(helm-init-candidates-in-buffer 'global helm-man--pages))
(defvar helm-source-man-pages
(helm-build-in-buffer-source "Manual Pages"
:init #'helm-man--init
:persistent-action #'ignore
:filtered-candidate-transformer
(lambda (candidates _source)
(sort candidates #'helm-generic-sort-fn))
:action '(("Display Man page" . helm-man-default-action))
:group 'helm-man))
;;;###autoload
(defun helm-man-woman (arg)
"Preconfigured `helm' for Man and Woman pages.
With a prefix arg reinitialize the cache."
(interactive "P")
(when arg (setq helm-man--pages nil))
(helm :sources 'helm-source-man-pages
:buffer "*helm man woman*"))
(provide 'helm-man)
;; Local Variables:
;; byte-compile-warnings: (not obsolete)
;; coding: utf-8
;; indent-tabs-mode: nil
;; End:
;;; helm-man.el ends here

View File

@@ -0,0 +1,361 @@
;;; helm-misc.el --- Various functions for helm -*- lexical-binding: t -*-
;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Code:
(require 'cl-lib)
(require 'helm)
(require 'helm-help)
(require 'helm-types)
(declare-function display-time-world-display "time.el")
(defvar display-time-world-list)
(declare-function LaTeX-math-mode "ext:latex.el")
(declare-function jabber-chat-with "ext:jabber.el")
(declare-function jabber-read-account "ext:jabber.el")
(defgroup helm-misc nil
"Various Applications and libraries for Helm."
:group 'helm)
(defcustom helm-time-zone-home-location "Paris"
"The time zone of your home"
:group 'helm-misc
:type 'string)
(defcustom helm-timezone-actions
'(("Set timezone env (TZ)" . (lambda (candidate)
(setenv "TZ" candidate))))
"Actions for helm-timezone."
:group 'helm-misc
:type '(alist :key-type string :value-type function))
(defface helm-time-zone-current
'((t (:foreground "green")))
"Face used to colorize current time in `helm-world-time'."
:group 'helm-misc)
(defface helm-time-zone-home
'((t (:foreground "red")))
"Face used to colorize home time in `helm-world-time'."
:group 'helm-misc)
;;; Latex completion
;;
;; Test
;; (setq LaTeX-math-menu '("Math"
;; ["foo" val0 t]
;; ("bar"
;; ["baz" val1 t])
;; ("aze"
;; ["zer" val2 t])
;; ("AMS"
;; ("rec"
;; ["fer" val3 t])
;; ("rty"
;; ["der" val4 t]))
;; ("ABC"
;; ("xcv"
;; ["sdf" val5 t])
;; ("dfg"
;; ["fgh" val6 t]))))
;; (helm-latex-math-candidates)
;; =>
;; (("foo" . val0)
;; ("baz" . val1)
;; ("zer" . val2)
;; ("fer" . val3)
;; ("der" . val4)
;; ("sdf" . val5)
;; ("fgh" . val6))
(defvar LaTeX-math-menu)
(defun helm-latex-math-candidates ()
(cl-labels ((helm-latex--math-collect (L)
(cond ((vectorp L)
(list (cons (aref L 0) (aref L 1))))
((listp L)
(cl-loop for a in L nconc
(helm-latex--math-collect a))))))
(helm-latex--math-collect LaTeX-math-menu)))
(defvar helm-source-latex-math
(helm-build-sync-source "Latex Math Menu"
:init (lambda ()
(with-helm-current-buffer
(LaTeX-math-mode 1)))
:candidate-number-limit 9999
:candidates 'helm-latex-math-candidates
:action (lambda (candidate)
(call-interactively candidate))))
;;; Jabber Contacts (jabber.el)
(defun helm-jabber-online-contacts ()
"List online Jabber contacts."
(with-no-warnings
(cl-loop for item in (jabber-concat-rosters)
when (get item 'connected)
collect
(if (get item 'name)
(cons (get item 'name) item)
(cons (symbol-name item) item)))))
(defvar helm-source-jabber-contacts
(helm-build-sync-source "Jabber Contacts"
:init (lambda () (require 'jabber))
:candidates (lambda () (mapcar 'car (helm-jabber-online-contacts)))
:action (lambda (x)
(jabber-chat-with
(jabber-read-account)
(symbol-name
(cdr (assoc x (helm-jabber-online-contacts))))))))
;;; World time
;;
(defvar zoneinfo-style-world-list)
(defvar legacy-style-world-list)
(defun helm-time-zone-transformer (candidates _source)
(cl-loop for i in candidates
for (z . p) in display-time-world-list
collect
(cons
(cond ((string-match (format-time-string "%H:%M" (current-time)) i)
(propertize i 'face 'helm-time-zone-current))
((string-match helm-time-zone-home-location i)
(propertize i 'face 'helm-time-zone-home))
(t i))
z)))
(defvar helm-source-time-world
(helm-build-in-buffer-source "Time World List"
:init (lambda ()
(require 'time)
(unless (and display-time-world-list
(listp display-time-world-list))
;; adapted from `time--display-world-list' from
;; emacs-27 for compatibility as
;; `display-time-world-list' is set by default to t.
(setq display-time-world-list
;; Determine if zoneinfo style timezones are
;; supported by testing that America/New York and
;; Europe/London return different timezones.
(let ((nyt (format-time-string "%z" nil "America/New_York"))
(gmt (format-time-string "%z" nil "Europe/London")))
(if (string-equal nyt gmt)
legacy-style-world-list
zoneinfo-style-world-list)))))
:data (lambda ()
(with-temp-buffer
(display-time-world-display display-time-world-list)
(buffer-string)))
:action 'helm-timezone-actions
:filtered-candidate-transformer 'helm-time-zone-transformer))
;;; Commands
;;
(defun helm-call-interactively (cmd-or-name)
"Execute CMD-OR-NAME as Emacs command.
It is added to `extended-command-history'.
`helm-current-prefix-arg' is used as the command's prefix argument."
(setq extended-command-history
(cons (helm-stringify cmd-or-name)
(delete (helm-stringify cmd-or-name) extended-command-history)))
(let ((current-prefix-arg helm-current-prefix-arg)
(cmd (helm-symbolify cmd-or-name)))
(if (stringp (symbol-function cmd))
(execute-kbd-macro (symbol-function cmd))
(setq this-command cmd)
(call-interactively cmd))))
;;; Minibuffer History
;;
;;
(defvar helm-minibuffer-history-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map helm-map)
(define-key map [remap helm-minibuffer-history] 'undefined)
map))
(defcustom helm-minibuffer-history-must-match t
"Allow inserting non matching elements when nil or 'confirm."
:group 'helm-misc
:type '(choice
(const :tag "Must match" t)
(const :tag "Confirm" 'confirm)
(const :tag "Always allow" nil)))
;;; Shell history
;;
;;
(defun helm-comint-input-ring-action (candidate)
"Default action for comint history."
(with-helm-current-buffer
(delete-region (comint-line-beginning-position) (point-max))
(insert candidate)))
(defvar helm-source-comint-input-ring
(helm-build-sync-source "Comint history"
:candidates (lambda ()
(with-helm-current-buffer
(ring-elements comint-input-ring)))
:action 'helm-comint-input-ring-action)
"Source that provide helm completion against `comint-input-ring'.")
;;; Helm ratpoison UI
;;
;;
(defvar helm-source-ratpoison-commands
(helm-build-in-buffer-source "Ratpoison Commands"
:init 'helm-ratpoison-commands-init
:action (helm-make-actions
"Execute the command" 'helm-ratpoison-commands-execute)
:display-to-real 'helm-ratpoison-commands-display-to-real
:candidate-number-limit 999999))
(defun helm-ratpoison-commands-init ()
(unless (helm-candidate-buffer)
(with-current-buffer (helm-candidate-buffer 'global)
;; with ratpoison prefix key
(save-excursion
(call-process "ratpoison" nil (current-buffer) nil "-c" "help"))
(while (re-search-forward "^\\([^ ]+\\) \\(.+\\)$" nil t)
(replace-match "<ratpoison> \\1: \\2"))
(goto-char (point-max))
;; direct binding
(save-excursion
(call-process "ratpoison" nil (current-buffer) nil "-c" "help top"))
(while (re-search-forward "^\\([^ ]+\\) \\(.+\\)$" nil t)
(replace-match "\\1: \\2")))))
(defun helm-ratpoison-commands-display-to-real (display)
(and (string-match ": " display)
(substring display (match-end 0))))
(defun helm-ratpoison-commands-execute (candidate)
(call-process "ratpoison" nil nil nil "-ic" candidate))
;;; Helm stumpwm UI
;;
;;
(defvar helm-source-stumpwm-commands
(helm-build-in-buffer-source "Stumpwm Commands"
:init 'helm-stumpwm-commands-init
:action (helm-make-actions
"Execute the command" 'helm-stumpwm-commands-execute)
:candidate-number-limit 999999))
(defun helm-stumpwm-commands-init ()
(with-current-buffer (helm-candidate-buffer 'global)
(save-excursion
(call-process "stumpish" nil (current-buffer) nil "commands"))
(while (re-search-forward "[ ]*\\([^ ]+\\)[ ]*\n?" nil t)
(replace-match "\n\\1\n"))
(delete-blank-lines)
(sort-lines nil (point-min) (point-max))
(goto-char (point-max))))
(defun helm-stumpwm-commands-execute (candidate)
(call-process "stumpish" nil nil nil candidate))
;;;###autoload
(defun helm-world-time ()
"Preconfigured `helm' to show world time.
Default action change TZ environment variable locally to emacs."
(interactive)
(helm-other-buffer 'helm-source-time-world "*helm world time*"))
;;;###autoload
(defun helm-insert-latex-math ()
"Preconfigured helm for latex math symbols completion."
(interactive)
(helm-other-buffer 'helm-source-latex-math "*helm latex*"))
;;;###autoload
(defun helm-ratpoison-commands ()
"Preconfigured `helm' to execute ratpoison commands."
(interactive)
(helm-other-buffer 'helm-source-ratpoison-commands
"*helm ratpoison commands*"))
;;;###autoload
(defun helm-stumpwm-commands()
"Preconfigured helm for stumpwm commands."
(interactive)
(helm-other-buffer 'helm-source-stumpwm-commands
"*helm stumpwm commands*"))
;;;###autoload
(defun helm-minibuffer-history ()
"Preconfigured `helm' for `minibuffer-history'."
(interactive)
(cl-assert (minibuffer-window-active-p (selected-window)) nil
"Error: Attempt to use minibuffer history outside a minibuffer")
(let* ((enable-recursive-minibuffers t)
(query-replace-p (or (eq last-command 'query-replace)
(eq last-command 'query-replace-regexp)))
(elm (helm-comp-read "pattern: "
(cl-loop for i in
(symbol-value minibuffer-history-variable)
unless (string= "" i) collect i into history
finally return
(if (consp (car history))
(mapcar 'prin1-to-string history)
history))
:header-name
(lambda (name)
(format "%s (%s)" name minibuffer-history-variable))
:buffer "*helm minibuffer-history*"
:must-match helm-minibuffer-history-must-match
:multiline t
:keymap helm-minibuffer-history-map
:allow-nest t)))
;; Fix issue #1667 with emacs-25+ `query-replace-from-to-separator'.
(when (and (boundp 'query-replace-from-to-separator) query-replace-p)
(let ((pos (string-match "\0" elm)))
(and pos
(add-text-properties
pos (1+ pos)
`(display ,query-replace-from-to-separator separator t)
elm))))
(delete-minibuffer-contents)
(insert elm)))
;;;###autoload
(defun helm-comint-input-ring ()
"Preconfigured `helm' that provide completion of `comint' history."
(interactive)
(when (derived-mode-p 'comint-mode)
(helm :sources 'helm-source-comint-input-ring
:input (buffer-substring-no-properties (comint-line-beginning-position)
(point-at-eol))
:buffer "*helm comint history*")))
(provide 'helm-misc)
;; Local Variables:
;; byte-compile-warnings: (not obsolete)
;; coding: utf-8
;; indent-tabs-mode: nil
;; End:
;;; helm-misc.el ends here

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,584 @@
;;; helm-net.el --- helm browse url and search web. -*- lexical-binding: t -*-
;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Code:
(require 'cl-lib)
(require 'helm)
(require 'helm-help)
(require 'url)
(require 'xml)
(require 'browse-url)
(defgroup helm-net nil
"Net related applications and libraries for Helm."
:group 'helm)
(defcustom helm-google-suggest-default-browser-function nil
"The browse url function you prefer to use with google suggest.
When nil, use the first browser function available
See `helm-browse-url-default-browser-alist'."
:group 'helm-net
:type 'symbol)
(defcustom helm-home-url "https://www.google.com"
"Default url to use as home url."
:group 'helm-net
:type 'string)
(defcustom helm-surfraw-default-browser-function nil
"The browse url function you prefer to use with surfraw.
When nil, fallback to `browse-url-browser-function'."
:group 'helm-net
:type 'symbol)
(defcustom helm-google-suggest-url
"https://encrypted.google.com/complete/search?output=toolbar&q=%s"
"URL used for looking up Google suggestions.
This is a format string, don't forget the `%s'."
:type 'string
:group 'helm-net)
(defcustom helm-google-suggest-search-url
"https://encrypted.google.com/search?ie=utf-8&oe=utf-8&q=%s"
"URL used for Google searching.
This is a format string, don't forget the `%s'."
:type 'string
:group 'helm-net)
(defvaralias 'helm-google-suggest-use-curl-p 'helm-net-prefer-curl)
(make-obsolete-variable 'helm-google-suggest-use-curl-p 'helm-net-prefer-curl "1.7.7")
(defcustom helm-net-prefer-curl nil
"When non--nil use CURL external program to fetch data.
Otherwise `url-retrieve-synchronously' is used."
:type 'boolean
:group 'helm-net)
(defcustom helm-surfraw-duckduckgo-url
"https://duckduckgo.com/lite/?q=%s&kp=1"
"The duckduckgo url.
This is a format string, don't forget the `%s'.
If you have personal settings saved on duckduckgo you should have
a personal url, see your settings on duckduckgo."
:type 'string
:group 'helm-net)
(defcustom helm-wikipedia-suggest-url
"https://en.wikipedia.org/w/api.php?action=opensearch&search=%s"
"Url used for looking up Wikipedia suggestions.
This is a format string, don't forget the `%s'."
:type 'string
:group 'helm-net)
(defcustom helm-search-suggest-action-wikipedia-url
"https://en.wikipedia.org/wiki/Special:Search?search=%s"
"The Wikipedia search url.
This is a format string, don't forget the `%s'."
:type 'string
:group 'helm-net)
(defcustom helm-wikipedia-summary-url
"https://en.wikipedia.org/w/api.php?action=parse&format=json&prop=text&section=0&page=%s"
"URL for getting the summary of a Wikipedia topic.
This is a format string, don't forget the `%s'."
:type 'string
:group 'helm-net)
(defcustom helm-search-suggest-action-youtube-url
"https://www.youtube.com/results?aq=f&search_query=%s"
"The Youtube search url.
This is a format string, don't forget the `%s'."
:type 'string
:group 'helm-net)
(defcustom helm-search-suggest-action-imdb-url
"http://www.imdb.com/find?s=all&q=%s"
"The IMDb search url.
This is a format string, don't forget the `%s'."
:type 'string
:group 'helm-net)
(defcustom helm-search-suggest-action-google-maps-url
"https://maps.google.com/maps?f=q&source=s_q&q=%s"
"The Google Maps search url.
This is a format string, don't forget the `%s'."
:type 'string
:group 'helm-net)
(defcustom helm-search-suggest-action-google-news-url
"https://www.google.com/search?safe=off&prmd=nvlifd&source=lnms&tbs=nws:1&q=%s"
"The Google News search url.
This is a format string, don't forget the `%s'."
:type 'string
:group 'helm-net)
(defcustom helm-google-suggest-actions
'(("Google Search" . helm-google-suggest-action)
("Wikipedia" . (lambda (candidate)
(helm-search-suggest-perform-additional-action
helm-search-suggest-action-wikipedia-url
candidate)))
("Youtube" . (lambda (candidate)
(helm-search-suggest-perform-additional-action
helm-search-suggest-action-youtube-url
candidate)))
("IMDb" . (lambda (candidate)
(helm-search-suggest-perform-additional-action
helm-search-suggest-action-imdb-url
candidate)))
("Google Maps" . (lambda (candidate)
(helm-search-suggest-perform-additional-action
helm-search-suggest-action-google-maps-url
candidate)))
("Google News" . (lambda (candidate)
(helm-search-suggest-perform-additional-action
helm-search-suggest-action-google-news-url
candidate))))
"List of actions for google suggest sources."
:group 'helm-net
:type '(alist :key-type string :value-type function))
(defcustom helm-browse-url-firefox-new-window "-new-tab"
"Allow choosing to browse url in new window or new tab.
Can be \"-new-tab\" (default) or \"-new-window\"."
:group 'helm-net
:type '(radio
(const :tag "New tab" "-new-tab")
(const :tag "New window" "-new-window")))
;;; Additional actions for search suggestions
;;
;;
;; Internal
(defun helm-search-suggest-perform-additional-action (url query)
"Perform the search via URL using QUERY as input."
(browse-url (format url (url-hexify-string query))))
(defun helm-net--url-retrieve-sync (request parser)
(if helm-net-prefer-curl
(with-temp-buffer
(call-process "curl" nil t nil request)
(funcall parser))
(with-current-buffer (url-retrieve-synchronously request)
(funcall parser))))
;;; Google Suggestions
;;
;;
(defun helm-google-suggest-parser ()
(cl-loop
with result-alist = (xml-get-children
(car (xml-parse-region
(point-min) (point-max)))
'CompleteSuggestion)
for i in result-alist collect
(cdr (cl-caadr (assq 'suggestion i)))))
(defun helm-google-suggest-fetch (input)
"Fetch suggestions for INPUT from XML buffer."
(let ((request (format helm-google-suggest-url
(url-hexify-string input))))
(helm-net--url-retrieve-sync
request #'helm-google-suggest-parser)))
(defun helm-google-suggest-set-candidates (&optional request-prefix)
"Set candidates with result and number of google results found."
(let ((suggestions (helm-google-suggest-fetch
(or (and request-prefix
(concat request-prefix
" " helm-pattern))
helm-pattern))))
(if (member helm-pattern suggestions)
suggestions
;; if there is no suggestion exactly matching the input then
;; prepend a Search on Google item to the list
(append
suggestions
(list (cons (format "Search for '%s' on Google" helm-input)
helm-input))))))
(defun helm-ggs-set-number-result (num)
(if num
(progn
(and (numberp num) (setq num (number-to-string num)))
(cl-loop for i in (reverse (split-string num "" t))
for count from 1
append (list i) into C
when (= count 3)
append (list ",") into C
and do (setq count 0)
finally return
(replace-regexp-in-string
"^," "" (mapconcat 'identity (reverse C) ""))))
"?"))
(defun helm-google-suggest-action (candidate)
"Default action to jump to a google suggested candidate."
(let ((arg (format helm-google-suggest-search-url
(url-hexify-string candidate))))
(helm-aif helm-google-suggest-default-browser-function
(funcall it arg)
(helm-browse-url arg))))
(defvar helm-google-suggest-default-function
'helm-google-suggest-set-candidates
"Default function to use in helm google suggest.")
(defvar helm-source-google-suggest
(helm-build-sync-source "Google Suggest"
:candidates (lambda ()
(funcall helm-google-suggest-default-function))
:action 'helm-google-suggest-actions
:volatile t
:keymap helm-map
:requires-pattern 3))
(defun helm-google-suggest-emacs-lisp ()
"Try to emacs lisp complete with google suggestions."
(helm-google-suggest-set-candidates "emacs lisp"))
;;; Wikipedia suggestions
;;
;;
(declare-function json-read-from-string "json" (string))
(defun helm-wikipedia-suggest-fetch ()
"Fetch Wikipedia suggestions and return them as a list."
(require 'json)
(let ((request (format helm-wikipedia-suggest-url
(url-hexify-string helm-pattern))))
(helm-net--url-retrieve-sync
request #'helm-wikipedia--parse-buffer)))
(defun helm-wikipedia--parse-buffer ()
(goto-char (point-min))
(when (re-search-forward "^\\[.+\\[\\(.*\\)\\]\\]" nil t)
(cl-loop for i across (aref (json-read-from-string (match-string 0)) 1)
collect i into result
finally return (or result
(append
result
(list (cons (format "Search for '%s' on wikipedia"
helm-pattern)
helm-pattern)))))))
(defvar helm-wikipedia--summary-cache (make-hash-table :test 'equal))
(defun helm-wikipedia-show-summary (input)
"Show Wikipedia summary for INPUT in new buffer."
(interactive)
(let ((buffer (get-buffer-create "*helm wikipedia summary*"))
(summary (helm-wikipedia--get-summary input)))
(with-current-buffer buffer
(visual-line-mode)
(erase-buffer)
(insert summary)
(pop-to-buffer (current-buffer))
(goto-char (point-min)))))
(defun helm-wikipedia-persistent-action (candidate)
(unless (string= (format "Search for '%s' on wikipedia"
helm-pattern)
(helm-get-selection nil t))
(message "Fetching summary from Wikipedia...")
(let ((buf (get-buffer-create "*helm wikipedia summary*"))
(result (helm-wikipedia--get-summary candidate)))
(with-current-buffer buf
(erase-buffer)
(setq cursor-type nil)
(insert result)
(fill-region (point-min) (point-max))
(goto-char (point-min)))
(display-buffer buf))))
(defun helm-wikipedia--get-summary (input)
"Return Wikipedia summary for INPUT as string.
Follows any redirections from Wikipedia, and stores results in
`helm-wikipedia--summary-cache'."
(let (result)
(while (progn
(setq result (or (gethash input helm-wikipedia--summary-cache)
(puthash input
(helm-wikipedia--fetch-summary input)
helm-wikipedia--summary-cache)))
(when (and result
(listp result))
(setq input (cdr result))
(message "Redirected to %s" input)
t)))
(unless result
(error "Error when getting summary."))
result))
(defun helm-wikipedia--fetch-summary (input)
(let* ((request (format helm-wikipedia-summary-url
(url-hexify-string input))))
(helm-net--url-retrieve-sync
request #'helm-wikipedia--parse-summary)))
(defun helm-wikipedia--parse-summary ()
(goto-char (point-min))
(when (search-forward "{" nil t)
(let ((result (cdr (assq '*
(assq 'text
(assq 'parse
(json-read-from-string
(buffer-substring-no-properties
(1- (point)) (point-max)))))))))
(when result
(if (string-match "<span class=\"redirectText\"><a href=[^>]+>\\([^<]+\\)" result)
(cons 'redirect (match-string 1 result))
;; find the beginning of the summary text in the result
;; check if there is a table before the summary and skip that
(when (or (string-match "</table>\\(\n<div.*?</div>\\)?\n<p>" result)
;; otherwise just find the first paragraph
(string-match "<p>" result))
;; remove cruft and do a simple formatting
(replace-regexp-in-string
"Cite error: .*" ""
(replace-regexp-in-string
"&#160;" ""
(replace-regexp-in-string
"\\[[^\]]+\\]" ""
(replace-regexp-in-string
"<[^>]*>" ""
(replace-regexp-in-string
"</p>\n<p>" "\n\n"
(substring result (match-end 0)))))))))))))
(defvar helm-wikipedia-map
(let ((map (copy-keymap helm-map)))
(define-key map (kbd "<C-return>") 'helm-wikipedia-show-summary-action)
map)
"Keymap for `helm-wikipedia-suggest'.")
(defvar helm-source-wikipedia-suggest
(helm-build-sync-source "Wikipedia Suggest"
:candidates #'helm-wikipedia-suggest-fetch
:action '(("Wikipedia" . (lambda (candidate)
(helm-search-suggest-perform-additional-action
helm-search-suggest-action-wikipedia-url
candidate)))
("Show summary in new buffer (C-RET)" . helm-wikipedia-show-summary))
:persistent-action #'helm-wikipedia-persistent-action
:persistent-help "show summary"
:volatile t
:keymap helm-wikipedia-map
:requires-pattern 3))
(defun helm-wikipedia-show-summary-action ()
"Exit Helm buffer and call `helm-wikipedia-show-summary' with selected candidate."
(interactive)
(with-helm-alive-p
(helm-exit-and-execute-action 'helm-wikipedia-show-summary)))
;;; Web browser functions.
;;
;;
;; If default setting of `w3m-command' is not
;; what you want and you modify it, you will have to reeval
;; also `helm-browse-url-default-browser-alist'.
(defvar helm-browse-url-chromium-program "chromium-browser")
(defvar helm-browse-url-uzbl-program "uzbl-browser")
(defvar helm-browse-url-conkeror-program "conkeror")
(defvar helm-browse-url-opera-program "opera")
(defvar helm-browse-url-default-browser-alist
`((,(or (and (boundp 'w3m-command) w3m-command)
"/usr/bin/w3m") . w3m-browse-url)
(,browse-url-firefox-program . browse-url-firefox)
(,helm-browse-url-chromium-program . helm-browse-url-chromium)
(,helm-browse-url-conkeror-program . helm-browse-url-conkeror)
(,helm-browse-url-opera-program . helm-browse-url-opera)
(,helm-browse-url-uzbl-program . helm-browse-url-uzbl)
(,browse-url-kde-program . browse-url-kde)
(,browse-url-gnome-moz-program . browse-url-gnome-moz)
(,browse-url-mozilla-program . browse-url-mozilla)
(,browse-url-galeon-program . browse-url-galeon)
(,browse-url-netscape-program . browse-url-netscape)
(,browse-url-mosaic-program . browse-url-mosaic)
(,browse-url-xterm-program . browse-url-text-xterm)
("emacs" . eww-browse-url))
"*Alist of \(executable . function\) to try to find a suitable url browser.")
(cl-defun helm-generic-browser (url cmd-name &rest args)
"Browse URL with NAME browser."
(let ((proc (concat cmd-name " " url)))
(message "Starting %s..." cmd-name)
(apply 'start-process proc nil cmd-name
(append args (list url)))
(set-process-sentinel
(get-process proc)
(lambda (process event)
(when (string= event "finished\n")
(message "%s process %s" process event))))))
;;;###autoload
(defun helm-browse-url-firefox (url &optional _ignore)
"Same as `browse-url-firefox' but detach from emacs.
So when you quit emacs you can keep your firefox session open
and not be prompted to kill firefox process.
NOTE: Probably not supported on some systems (e.g Windows)."
(interactive (list (read-string "URL: " (browse-url-url-at-point))
nil))
(setq url (browse-url-encode-url url))
(let ((process-environment (browse-url-process-environment)))
(call-process-shell-command
(format "(%s %s %s &)"
browse-url-firefox-program
helm-browse-url-firefox-new-window
(shell-quote-argument url)))))
;;;###autoload
(defun helm-browse-url-opera (url &optional _ignore)
"Browse URL with opera browser and detach from emacs.
So when you quit emacs you can keep your opera session open
and not be prompted to kill opera process.
NOTE: Probably not supported on some systems (e.g Windows)."
(interactive (list (read-string "URL: " (browse-url-url-at-point))
nil))
(setq url (browse-url-encode-url url))
(let ((process-environment (browse-url-process-environment)))
(call-process-shell-command
(format "(%s %s &)"
helm-browse-url-opera-program (shell-quote-argument url)))))
;;;###autoload
(defun helm-browse-url-chromium (url &optional _ignore)
"Browse URL with google chrome browser."
(interactive "sURL: ")
(helm-generic-browser
url helm-browse-url-chromium-program))
;;;###autoload
(defun helm-browse-url-uzbl (url &optional _ignore)
"Browse URL with uzbl browser."
(interactive "sURL: ")
(helm-generic-browser url helm-browse-url-uzbl-program "-u"))
;;;###autoload
(defun helm-browse-url-conkeror (url &optional _ignore)
"Browse URL with conkeror browser."
(interactive "sURL: ")
(helm-generic-browser url helm-browse-url-conkeror-program))
(defun helm-browse-url-default-browser (url &rest args)
"Find the first available browser and ask it to load URL."
(let ((default-browser-fn
(cl-loop for (exe . fn) in helm-browse-url-default-browser-alist
thereis (and exe (executable-find exe) (fboundp fn) fn))))
(if default-browser-fn
(apply default-browser-fn url args)
(error "No usable browser found"))))
(defun helm-browse-url (url &rest args)
"Default command to browse URL."
(if browse-url-browser-function
(browse-url url args)
(helm-browse-url-default-browser url args)))
;;; Surfraw
;;
;; Need external program surfraw.
;; <http://surfraw.alioth.debian.org/>
;; Internal
(defvar helm-surfraw-engines-history nil)
(defvar helm-surfraw-input-history nil)
(defvar helm-surfraw--elvi-cache nil)
(defun helm-build-elvi-list ()
"Return list of all engines and descriptions handled by surfraw."
(or helm-surfraw--elvi-cache
(setq helm-surfraw--elvi-cache
(cdr (with-temp-buffer
(call-process "surfraw" nil t nil "-elvi")
(split-string (buffer-string) "\n"))))))
;;;###autoload
(defun helm-surfraw (pattern engine)
"Preconfigured `helm' to search PATTERN with search ENGINE."
(interactive
(list
(let* ((default (if (use-region-p)
(buffer-substring-no-properties
(region-beginning) (region-end))
(thing-at-point 'symbol)))
(prompt (if default
(format "SearchFor (default %s): " default)
"SearchFor: ")))
(read-string prompt nil 'helm-surfraw-input-history default))
(helm-comp-read
"Engine: "
(helm-build-elvi-list)
:must-match t
:name "Surfraw Search Engines"
:del-input nil
:history helm-surfraw-engines-history)))
(let* ((engine-nodesc (car (split-string engine)))
(url (if (string= engine-nodesc "duckduckgo")
;; "sr duckduckgo -p foo" is broken, workaround.
(format helm-surfraw-duckduckgo-url
(url-hexify-string pattern))
(with-temp-buffer
(apply 'call-process "surfraw" nil t nil
(append (list engine-nodesc "-p") (split-string pattern)))
(replace-regexp-in-string
"\n" "" (buffer-string)))))
(browse-url-browser-function (or helm-surfraw-default-browser-function
browse-url-browser-function)))
(if (string= engine-nodesc "W")
(helm-browse-url helm-home-url)
(helm-browse-url url)
(setq helm-surfraw-engines-history
(cons engine (delete engine helm-surfraw-engines-history))))))
;;;###autoload
(defun helm-google-suggest ()
"Preconfigured `helm' for google search with google suggest."
(interactive)
(helm-other-buffer 'helm-source-google-suggest "*helm google*"))
;;;###autoload
(defun helm-wikipedia-suggest ()
"Preconfigured `helm' for Wikipedia lookup with Wikipedia suggest."
(interactive)
(helm :sources 'helm-source-wikipedia-suggest
:buffer "*helm wikipedia*"))
(provide 'helm-net)
;; Local Variables:
;; byte-compile-warnings: (not obsolete)
;; coding: utf-8
;; indent-tabs-mode: nil
;; End:
;;; helm-net.el ends here

View File

@@ -0,0 +1,426 @@
;;; helm-org.el --- Helm for org headlines and keywords completion -*- lexical-binding: t -*-
;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Code:
(require 'cl-lib)
(require 'helm)
(require 'helm-utils)
(require 'org)
;; Load org-with-point-at macro when compiling
(eval-when-compile
(require 'org-macs))
(declare-function org-agenda-switch-to "org-agenda.el")
(defgroup helm-org nil
"Org related functions for helm."
:group 'helm)
(defcustom helm-org-headings-fontify nil
"Fontify org buffers before parsing them.
This reflect fontification in helm-buffer when non--nil.
NOTE: This will be slow on large org buffers."
:group 'helm-org
:type 'boolean)
(defcustom helm-org-format-outline-path nil
"Show all org level as path."
:group 'helm-org
:type 'boolean)
(defcustom helm-org-show-filename nil
"Show org filenames in `helm-org-agenda-files-headings' when non--nil.
Note this have no effect in `helm-org-in-buffer-headings'."
:group 'helm-org
:type 'boolean)
(defcustom helm-org-headings-min-depth 1
"Minimum depth of org headings to start with."
:group 'helm-org
:type 'integer)
(defcustom helm-org-headings-max-depth 8
"Go down to this maximum depth of org headings."
:group 'helm-org
:type 'integer)
(defcustom helm-org-headings-actions
'(("Go to heading" . helm-org-goto-marker)
("Open in indirect buffer `C-c i'" . helm-org--open-heading-in-indirect-buffer)
("Refile heading(s) (marked-to-selected|current-to-selected) `C-c w`" . helm-org--refile-heading-to)
("Insert link to this heading `C-c l`" . helm-org-insert-link-to-heading-at-marker))
"Default actions alist for
`helm-source-org-headings-for-files'."
:group 'helm-org
:type '(alist :key-type string :value-type function))
(defcustom helm-org-truncate-lines t
"Truncate org-header-lines when non-nil"
:type 'boolean
:group 'helm-org)
(defcustom helm-org-ignore-autosaves nil
"Ignore autosave files when starting `helm-org-agenda-files-headings'."
:type 'boolean
:group 'helm-org)
;;; Org capture templates
;;
;;
(defvar org-capture-templates)
(defun helm-source-org-capture-templates ()
(helm-build-sync-source "Org Capture Templates:"
:candidates (cl-loop for template in org-capture-templates
collect (cons (nth 1 template) (nth 0 template)))
:action '(("Do capture" . (lambda (template-shortcut)
(org-capture nil template-shortcut))))))
;;; Org headings
;;
;;
(defun helm-org-goto-marker (marker)
(switch-to-buffer (marker-buffer marker))
(goto-char (marker-position marker))
(org-show-context)
(re-search-backward "^\\*+ " nil t)
(org-show-entry))
(defun helm-org--open-heading-in-indirect-buffer (marker)
(helm-org-goto-marker marker)
(org-tree-to-indirect-buffer)
;; Put the non-indirect buffer at the bottom of the prev-buffers
;; list so it won't be selected when the indirect buffer is killed
(set-window-prev-buffers nil (append (cdr (window-prev-buffers))
(car (window-prev-buffers)))))
(defun helm-org-run-open-heading-in-indirect-buffer ()
"Open selected Org heading in an indirect buffer."
(interactive)
(with-helm-alive-p
(helm-exit-and-execute-action #'helm-org--open-heading-in-indirect-buffer)))
(put 'helm-org-run-open-heading-in-indirect-buffer 'helm-only t)
(defvar helm-org-headings-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map helm-map)
(define-key map (kbd "C-c i") 'helm-org-run-open-heading-in-indirect-buffer)
(define-key map (kbd "C-c w") 'helm-org-run-refile-heading-to)
(define-key map (kbd "C-c l") 'helm-org-run-insert-link-to-heading-at-marker)
map)
"Keymap for `helm-source-org-headings-for-files'.")
(defclass helm-org-headings-class (helm-source-sync)
((parents
:initarg :parents
:initform nil
:custom boolean)
(match :initform
(lambda (candidate)
(string-match
helm-pattern
(helm-aif (get-text-property 0 'helm-real-display candidate)
it
candidate))))
(help-message :initform 'helm-org-headings-help-message)
(action :initform 'helm-org-headings-actions)
(keymap :initform 'helm-org-headings-map)
(group :initform 'helm-org)))
(defmethod helm--setup-source :after ((source helm-org-headings-class))
(let ((parents (slot-value source 'parents)))
(setf (slot-value source 'candidate-transformer)
(lambda (candidates)
(let ((cands (helm-org-get-candidates candidates parents)))
(if parents (nreverse cands) cands))))))
(defun helm-source-org-headings-for-files (filenames &optional parents)
(helm-make-source "Org Headings" 'helm-org-headings-class
:filtered-candidate-transformer 'helm-org-startup-visibility
:parents parents
:candidates filenames))
(defun helm-org-startup-visibility (candidates _source)
"Indent headings and hide leading stars displayed in the helm buffer.
If `org-startup-indented' and `org-hide-leading-stars' are nil, do
nothing to CANDIDATES."
(cl-loop for i in candidates
collect
;; Transformation is not needed if these variables are t.
(if (or helm-org-show-filename helm-org-format-outline-path)
(cons
(car i) (cdr i))
(cons
(if helm-org-headings-fontify
(when (string-match "^\\(\\**\\)\\(\\* \\)\\(.*\n?\\)" (car i))
(replace-match "\\1\\2\\3" t nil (car i)))
(when (string-match "^\\(\\**\\)\\(\\* \\)\\(.*\n?\\)" (car i))
(let ((foreground (org-find-invisible-foreground)))
(with-helm-current-buffer
(cond
;; org-startup-indented is t, and org-hide-leading-stars is t
;; Or: #+STARTUP: indent hidestars
((and org-startup-indented org-hide-leading-stars)
(with-helm-buffer
(require 'org-indent)
(org-indent-mode 1)
(replace-match
(format "%s\\2\\3"
(propertize (replace-match "\\1" t nil (car i))
'face `(:foreground ,foreground)))
t nil (car i))))
;; org-startup-indented is nil, org-hide-leading-stars is t
;; Or: #+STARTUP: noindent hidestars
((and (not org-startup-indented) org-hide-leading-stars)
(with-helm-buffer
(replace-match
(format "%s\\2\\3"
(propertize (replace-match "\\1" t nil (car i))
'face `(:foreground ,foreground)))
t nil (car i))))
;; org-startup-indented is nil, and org-hide-leading-stars is nil
;; Or: #+STARTUP: noindent showstars
(t
(with-helm-buffer
(replace-match "\\1\\2\\3" t nil (car i)))))))))
(cdr i)))))
(defun helm-org-get-candidates (filenames &optional parents)
(apply #'append
(mapcar (lambda (filename)
(helm-org--get-candidates-in-file
filename
helm-org-headings-fontify
(or parents (null helm-org-show-filename))
parents))
filenames)))
(defun helm-org--get-candidates-in-file (filename &optional fontify nofname parents)
(with-current-buffer (pcase filename
((pred bufferp) filename)
((pred stringp) (find-file-noselect filename t)))
(let ((match-fn (if fontify
#'match-string
#'match-string-no-properties))
(search-fn (lambda ()
(re-search-forward
org-complex-heading-regexp nil t)))
(file (unless nofname
(concat (helm-basename filename) ":"))))
(when parents
(add-function :around (var search-fn)
(lambda (old-fn &rest args)
(when (org-up-heading-safe)
(apply old-fn args)))))
(save-excursion
(save-restriction
(unless (and (bufferp filename)
(buffer-base-buffer filename))
;; Only widen direct buffers, not indirect ones.
(widen))
(unless parents (goto-char (point-min)))
;; clear cache for new version of org-get-outline-path
(and (boundp 'org-outline-path-cache)
(setq org-outline-path-cache nil))
(cl-loop with width = (window-width (helm-window))
while (funcall search-fn)
for beg = (point-at-bol)
for end = (point-at-eol)
when (and fontify
(null (text-property-any
beg end 'fontified t)))
do (jit-lock-fontify-now beg end)
for level = (length (match-string-no-properties 1))
for heading = (funcall match-fn 4)
if (and (>= level helm-org-headings-min-depth)
(<= level helm-org-headings-max-depth))
collect `(,(propertize
(if helm-org-format-outline-path
(org-format-outline-path
;; org-get-outline-path changed in signature and behaviour since org's
;; commit 105a4466971. Let's fall-back to the new version in case
;; of wrong-number-of-arguments error.
(condition-case nil
(append (apply #'org-get-outline-path
(unless parents
(list t level heading)))
(list heading))
(wrong-number-of-arguments
(org-get-outline-path t t)))
width file)
(if file
(concat file (funcall match-fn 0))
(funcall match-fn 0)))
'helm-real-display heading)
. ,(point-marker))))))))
(defun helm-org-insert-link-to-heading-at-marker (marker)
(with-current-buffer (marker-buffer marker)
(let ((heading-name (save-excursion (goto-char (marker-position marker))
(nth 4 (org-heading-components))))
(file-name (buffer-file-name)))
(with-helm-current-buffer
(org-insert-link
file-name (concat "file:" file-name "::*" heading-name))))))
(defun helm-org-run-insert-link-to-heading-at-marker ()
(interactive)
(with-helm-alive-p
(helm-exit-and-execute-action
'helm-org-insert-link-to-heading-at-marker)))
(defun helm-org--refile-heading-to (marker)
"Refile headings to heading at MARKER.
If multiple candidates are marked in the Helm session, they will
all be refiled. If no headings are marked, the selected heading
will be refiled."
(let* ((victims (with-helm-buffer (helm-marked-candidates)))
(buffer (marker-buffer marker))
(filename (buffer-file-name buffer))
(rfloc (list nil filename nil marker)))
(when (and (= 1 (length victims))
(equal (helm-get-selection) (car victims)))
;; No candidates are marked; we are refiling the entry at point
;; to the selected heading
(setq victims (list (point))))
;; Probably best to check that everything returned a value
(when (and victims buffer filename rfloc)
(cl-loop for victim in victims
do (org-with-point-at victim
(org-refile nil nil rfloc))))))
(defun helm-org-in-buffer-preselect ()
(if (org-on-heading-p)
(buffer-substring-no-properties (point-at-bol) (point-at-eol))
(save-excursion
(outline-previous-visible-heading 1)
(buffer-substring-no-properties (point-at-bol) (point-at-eol)))))
(defun helm-org-run-refile-heading-to ()
(interactive)
(with-helm-alive-p
(helm-exit-and-execute-action 'helm-org--refile-heading-to)))
(put 'helm-org-run-refile-heading-to 'helm-only t)
;;;###autoload
(defun helm-org-agenda-files-headings ()
"Preconfigured helm for org files headings."
(interactive)
(let ((autosaves (cl-loop for f in (org-agenda-files)
when (file-exists-p
(expand-file-name
(concat "#" (helm-basename f) "#")
(helm-basedir f)))
collect (helm-basename f))))
(when (or (null autosaves)
helm-org-ignore-autosaves
(y-or-n-p (format "%s have auto save data, continue?"
(mapconcat 'identity autosaves ", "))))
(helm :sources (helm-source-org-headings-for-files (org-agenda-files))
:candidate-number-limit 99999
:truncate-lines helm-org-truncate-lines
:buffer "*helm org headings*"))))
;;;###autoload
(defun helm-org-in-buffer-headings ()
"Preconfigured helm for org buffer headings."
(interactive)
(let (helm-org-show-filename)
(helm :sources (helm-source-org-headings-for-files
(list (current-buffer)))
:candidate-number-limit 99999
:preselect (helm-org-in-buffer-preselect)
:truncate-lines helm-org-truncate-lines
:buffer "*helm org inbuffer*")))
;;;###autoload
(defun helm-org-parent-headings ()
"Preconfigured helm for org headings that are parents of the
current heading."
(interactive)
;; Use a large max-depth to ensure all parents are displayed.
(let ((helm-org-headings-min-depth 1)
(helm-org-headings-max-depth 50))
(helm :sources (helm-source-org-headings-for-files
(list (current-buffer)) t)
:candidate-number-limit 99999
:truncate-lines helm-org-truncate-lines
:buffer "*helm org parent headings*")))
;;;###autoload
(defun helm-org-capture-templates ()
"Preconfigured helm for org templates."
(interactive)
(helm :sources (helm-source-org-capture-templates)
:candidate-number-limit 99999
:truncate-lines helm-org-truncate-lines
:buffer "*helm org capture templates*"))
;;; Org tag completion
;; Based on code from Anders Johansson posted on 3 Mar 2016 at
;; <https://groups.google.com/d/msg/emacs-helm/tA6cn6TUdRY/G1S3TIdzBwAJ>
(defvar crm-separator)
;;;###autoload
(defun helm-org-completing-read-tags (prompt collection pred req initial
hist def inherit-input-method _name _buffer)
"Completing read function for Org tags.
This function is used as a `completing-read' function in
`helm-completing-read-handlers-alist' by `org-set-tags' and
`org-capture'.
NOTE: Org tag completion will work only if you disable org fast tag
selection, see (info \"(org) setting tags\")."
(if (not (string= "Tags: " prompt))
;; Not a tags prompt. Use normal completion by calling
;; `org-icompleting-read' again without this function in
;; `helm-completing-read-handlers-alist'
(let ((helm-completing-read-handlers-alist
(rassq-delete-all
'helm-org-completing-read-tags
(copy-alist helm-completing-read-handlers-alist))))
(org-icompleting-read
prompt collection pred req initial hist def inherit-input-method))
;; Tags prompt
(let* ((curr (and (stringp initial)
(not (string= initial ""))
(org-split-string initial ":")))
(table (delete curr
(org-uniquify
(mapcar 'car org-last-tags-completion-table))))
(crm-separator ":\\|,\\|\\s-"))
(cl-letf (((symbol-function 'crm-complete-word)
'self-insert-command))
(mapconcat 'identity
(completing-read-multiple
prompt table pred nil initial hist def)
":")))))
(provide 'helm-org)
;; Local Variables:
;; byte-compile-warnings: (not obsolete)
;; coding: utf-8
;; indent-tabs-mode: nil
;; End:
;;; helm-org.el ends here

View File

@@ -0,0 +1,9 @@
(define-package "helm" "20180716.322" "Helm is an Emacs incremental and narrowing framework"
'((emacs "24.4")
(async "1.9.3")
(popup "0.5.3")
(helm-core "2.9.8"))
:url "https://emacs-helm.github.io/helm/")
;; Local Variables:
;; no-byte-compile: t
;; End:

View File

@@ -0,0 +1,763 @@
;;; helm-regexp.el --- In buffer regexp searching and replacement for helm. -*- lexical-binding: t -*-
;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Code:
(require 'cl-lib)
(require 'helm)
(require 'helm-help)
(require 'helm-utils)
(declare-function helm-mm-split-pattern "helm-multi-match")
(defgroup helm-regexp nil
"Regexp related Applications and libraries for Helm."
:group 'helm)
(defcustom helm-moccur-always-search-in-current nil
"Helm multi occur always search in current buffer when non--nil."
:group 'helm-regexp
:type 'boolean)
(defcustom helm-moccur-use-ioccur-style-keys t
"Similar to `helm-grep-use-ioccur-style-keys' but for multi occur."
:group 'helm-regexp
:type 'boolean)
(defcustom helm-moccur-auto-update-on-resume nil
"Allow auto updating helm-(m)occur buffer when outdated.
noask => Always update without asking
nil => Don't update but signal buffer needs update
never => Never update and do not signal buffer needs update
Any other non--nil value update after confirmation."
:group 'helm-regexp
:type '(radio :tag "Allow auto updating helm-(m)occur buffer when outdated."
(const :tag "Always update without asking" noask)
(const :tag "Never update and do not signal buffer needs update" never)
(const :tag "Don't update but signal buffer needs update" nil)
(const :tag "Update after confirmation" t)))
(defcustom helm-source-multi-occur-actions
'(("Go to Line" . helm-moccur-goto-line)
("Goto line other window (C-u vertically)" . helm-moccur-goto-line-ow)
("Goto line new frame" . helm-moccur-goto-line-of))
"Actions for helm-occur and helm-moccur."
:group 'helm-regexp
:type '(alist :key-type string :value-type function))
(defcustom helm-moccur-truncate-lines t
"When nil the (m)occur line that appears will not be truncated."
:group 'helm-regexp
:type 'boolean)
(defcustom helm-moccur-show-buffer-fontification nil
"Show fontification of searched buffer in results when non nil.
This enable or disable fontification globally in results, but you can
override this default setting with `helm-moccur-buffer-substring-fn-for-modes'."
:group 'helm-regexp
:type '(radio :tag "Allow preserving fontification of searched buffer in results"
(const :tag "Don't preserve buffer fontification" nil)
(const :tag "Preserve buffer fontification" t)))
(defcustom helm-moccur-buffer-substring-fn-for-modes
'((mu4e-headers-mode . buffer-substring)
(package-menu-mode . buffer-substring-no-properties))
"Alist that allow configuring the function to use for storing a buffer.
Can be one of `buffer-substring' or `buffer-substring-no-properties'.
Allow overriding the global effect of `helm-moccur-show-buffer-fontification'
for a specific mode."
:group 'helm-regexp
:type '(alist :key-type (symbol :tag "Mode")
:value-type (radio (const :tag "With text properties" buffer-substring)
(const :tag "Without text properties" buffer-substring-no-properties))))
(defcustom helm-occur-show-buffer-name nil
"Show buffer name in `helm-occur' results when non-nil.
Not that this doesn't affect `helm-moccur' results and
`helm-moccur-mode' buffers where buffer names are always shown."
:group 'helm-regexp
:type 'boolean)
(defface helm-moccur-buffer
'((t (:foreground "DarkTurquoise" :underline t)))
"Face used to highlight moccur buffer names."
:group 'helm-regexp)
(defface helm-resume-need-update
'((t (:background "red")))
"Face used to flash moccur buffer when it needs update."
:group 'helm-regexp)
(defvar helm-moccur-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map helm-map)
(define-key map (kbd "M-<down>") 'helm-goto-next-file)
(define-key map (kbd "M-<up>") 'helm-goto-precedent-file)
(define-key map (kbd "C-c o") 'helm-moccur-run-goto-line-ow)
(define-key map (kbd "C-c C-o") 'helm-moccur-run-goto-line-of)
(define-key map (kbd "C-x C-s") 'helm-moccur-run-save-buffer)
(when helm-moccur-use-ioccur-style-keys
(define-key map (kbd "<right>") 'helm-execute-persistent-action)
(define-key map (kbd "<left>") 'helm-moccur-run-default-action))
(delq nil map))
"Keymap used in Moccur source.")
;; History vars
(defvar helm-build-regexp-history nil)
(defvar helm-occur-history nil)
(defun helm-query-replace-regexp (_candidate)
"Query replace regexp from `helm-regexp'.
With a prefix arg replace only matches surrounded by word boundaries,
i.e Don't replace inside a word, regexp is surrounded with \\bregexp\\b."
(let ((regexp helm-input))
(apply 'query-replace-regexp
(helm-query-replace-args regexp))))
(defun helm-kill-regexp-as-sexp (_candidate)
"Kill regexp in a format usable in lisp code."
(helm-regexp-kill-new
(prin1-to-string helm-input)))
(defun helm-kill-regexp (_candidate)
"Kill regexp as it is in `helm-pattern'."
(helm-regexp-kill-new helm-input))
(defun helm-query-replace-args (regexp)
"create arguments of `query-replace-regexp' action in `helm-regexp'."
(let ((region-only (helm-region-active-p)))
(list
regexp
(query-replace-read-to regexp
(format "Query replace %sregexp %s"
(if helm-current-prefix-arg "word " "")
(if region-only "in region " ""))
t)
helm-current-prefix-arg
(when region-only (region-beginning))
(when region-only (region-end)))))
(defvar helm-source-regexp
(helm-build-in-buffer-source "Regexp Builder"
:init (lambda ()
(helm-init-candidates-in-buffer
'global (with-temp-buffer
(insert-buffer-substring helm-current-buffer)
(buffer-string))))
:get-line #'helm-regexp-get-line
:persistent-action #'helm-regexp-persistent-action
:persistent-help "Show this line"
:multiline t
:multimatch nil
:requires-pattern 2
:group 'helm-regexp
:mode-line "Press TAB to select action."
:action '(("Kill Regexp as sexp" . helm-kill-regexp-as-sexp)
("Query Replace Regexp (C-u Not inside word.)"
. helm-query-replace-regexp)
("Kill Regexp" . helm-kill-regexp))))
(defun helm-regexp-get-line (s e)
(let ((matches (match-data))
(line (buffer-substring s e)))
(propertize
(cl-loop with ln = (format "%5d: %s" (1- (line-number-at-pos s)) line)
for i from 0 to (1- (/ (length matches) 2))
if (match-string i)
concat (format "\n%s%s'%s'"
(make-string 10 ? ) (format "Group %d: " i) it)
into ln1
finally return (concat ln ln1))
'helm-realvalue s)))
(defun helm-regexp-persistent-action (pt)
(helm-goto-char pt)
(helm-highlight-current-line))
(defun helm-regexp-kill-new (input)
(kill-new (substring-no-properties input))
(message "Killed: %s" input))
;;; Occur
;;
;;
(defvar helm-source-occur nil)
(defun helm-occur-init-source ()
(unless helm-source-occur
(setq helm-source-occur
(helm-make-source "Occur" 'helm-source-multi-occur))))
;;; Multi occur
;;
;;
;; Internal
(defvar helm-multi-occur-buffer-list nil)
(defvar helm-multi-occur-buffer-tick nil)
(defvar helm-occur--invisible nil
"[INTERNAL] Hide buffer name in results when non-nil.
Should be a local var to helm-buffer to allow resuming.")
(defun helm-moccur-init ()
"Create the initial helm multi occur buffer."
(helm-init-candidates-in-buffer
'global
(cl-loop with buffers = (helm-attr 'moccur-buffers)
with bsubstring = (if helm-moccur-show-buffer-fontification
#'buffer-substring #'buffer-substring-no-properties)
for buf in buffers
for bufstr = (with-current-buffer buf
(helm-aif (assq major-mode
helm-moccur-buffer-substring-fn-for-modes)
(setq bsubstring (cdr it)))
;; A leading space is needed to allow helm
;; searching the first line of buffer
;; (#1725).
(concat (if (memql (char-after (point-min))
'(? ?\t ?\n))
"" " ")
(funcall bsubstring (point-min) (point-max))))
do (add-text-properties
0 (length bufstr)
`(buffer-name ,(buffer-name (get-buffer buf)))
bufstr)
concat bufstr)))
(defun helm-moccur--next-or-previous-char ()
(save-excursion
(or (re-search-forward "^." nil t)
(re-search-backward "^." nil t))))
(defun helm-moccur-get-line (beg end)
"Format line for `helm-source-moccur'."
(prog1
(format "%s:%d:%s"
(get-text-property (if (= beg end)
(helm-moccur--next-or-previous-char)
beg)
'buffer-name)
(save-restriction
(narrow-to-region (or (previous-single-property-change
(point) 'buffer-name)
(point-at-bol 2))
(or (next-single-property-change
(if (= beg end)
(helm-moccur--next-or-previous-char)
(point))
'buffer-name)
(point-max)))
(line-number-at-pos beg))
;; When matching empty line, use empty string
;; to allow saving and modifying with wgrep.
(if (= beg end) "" (buffer-substring beg end)))
;; When matching empty line, forward char ("\n")
;; to not be blocked forever here.
(when (= beg end) (forward-char 1))))
(cl-defun helm-moccur-action (candidate
&optional (method (quote buffer)))
"Jump to CANDIDATE with METHOD.
arg METHOD can be one of buffer, buffer-other-window, buffer-other-frame."
(require 'helm-grep)
(let* ((split (helm-grep-split-line candidate))
(buf (car split))
(lineno (string-to-number (nth 1 split)))
(split-pat (helm-mm-split-pattern helm-input)))
(cl-case method
(buffer (switch-to-buffer buf))
(buffer-other-window (helm-window-show-buffers (list buf) t))
(buffer-other-frame (switch-to-buffer-other-frame buf)))
(with-current-buffer buf
(helm-goto-line lineno)
;; Move point to the nearest matching regexp from bol.
(cl-loop for reg in split-pat
when (save-excursion
(condition-case _err
(if helm-migemo-mode
(helm-mm-migemo-forward reg (point-at-eol) t)
(re-search-forward reg (point-at-eol) t))
(invalid-regexp nil)))
collect (match-beginning 0) into pos-ls
finally (when pos-ls (goto-char (apply #'min pos-ls)))))))
(defun helm-moccur-persistent-action (candidate)
(helm-moccur-goto-line candidate)
(helm-highlight-current-line))
(defun helm-moccur-goto-line (candidate)
"From multi occur, switch to buffer and go to nth 1 CANDIDATE line."
(helm-moccur-action
candidate 'buffer))
(defun helm-moccur-goto-line-ow (candidate)
"Go to CANDIDATE line in other window.
Same as `helm-moccur-goto-line' but go in other window."
(helm-moccur-action
candidate 'buffer-other-window))
(defun helm-moccur-goto-line-of (candidate)
"Go to CANDIDATE line in new frame.
Same as `helm-moccur-goto-line' but go in new frame."
(helm-moccur-action
candidate 'buffer-other-frame))
(defun helm-moccur-run-goto-line-ow ()
"Run goto line other window action from `helm-source-moccur'."
(interactive)
(with-helm-alive-p
(helm-exit-and-execute-action 'helm-moccur-goto-line-ow)))
(put 'helm-moccur-run-goto-line-ow 'helm-only t)
(defun helm-moccur-run-goto-line-of ()
"Run goto line new frame action from `helm-source-moccur'."
(interactive)
(with-helm-alive-p
(helm-exit-and-execute-action 'helm-moccur-goto-line-of)))
(put 'helm-moccur-run-goto-line-of 'helm-only t)
(defun helm-moccur-run-default-action ()
(interactive)
(with-helm-alive-p
(helm-exit-and-execute-action 'helm-moccur-goto-line)))
(put 'helm-moccur-run-default-action 'helm-only t)
(defvar helm-moccur-before-init-hook nil
"Hook that runs before initialization of the helm buffer.")
(defvar helm-moccur-after-init-hook nil
"Hook that runs after initialization of the helm buffer.")
(defvar helm-source-moccur nil)
(defclass helm-source-multi-occur (helm-source-in-buffer)
((init :initform (lambda ()
(require 'helm-grep)
(helm-moccur-init)))
(filter-one-by-one :initform 'helm-moccur-filter-one-by-one)
(get-line :initform helm-moccur-get-line)
(nohighlight :initform t)
(nomark :initform t)
(migemo :initform t)
(action :initform 'helm-source-multi-occur-actions)
(persistent-action :initform 'helm-moccur-persistent-action)
(persistent-help :initform "Go to line")
(resume :initform 'helm-moccur-resume-fn)
(candidate-number-limit :initform 9999)
(help-message :initform 'helm-moccur-help-message)
(keymap :initform helm-moccur-map)
(history :initform 'helm-occur-history)
(requires-pattern :initform 2)
(before-init-hook :initform 'helm-moccur-before-init-hook)
(after-init-hook :initform 'helm-moccur-after-init-hook)
(group :initform 'helm-regexp)))
(defun helm-moccur-resume-fn ()
(with-helm-buffer
(let (new-tick-ls buffer-is-modified)
(set (make-local-variable 'helm-multi-occur-buffer-list)
(cl-loop for b in helm-multi-occur-buffer-list
when (buffer-live-p (get-buffer b))
collect b))
(setq buffer-is-modified (/= (length helm-multi-occur-buffer-list)
(length (helm-attr 'moccur-buffers))))
(helm-attrset 'moccur-buffers helm-multi-occur-buffer-list)
(setq new-tick-ls (cl-loop for b in helm-multi-occur-buffer-list
collect (buffer-chars-modified-tick (get-buffer b))))
(when buffer-is-modified
(setq helm-multi-occur-buffer-tick new-tick-ls))
(cl-assert (> (length helm-multi-occur-buffer-list) 0) nil
"helm-resume error: helm-(m)occur buffer list is empty")
(unless (eq helm-moccur-auto-update-on-resume 'never)
(when (or buffer-is-modified
(cl-loop for b in helm-multi-occur-buffer-list
for new-tick = (buffer-chars-modified-tick (get-buffer b))
for tick in helm-multi-occur-buffer-tick
thereis (/= tick new-tick)))
(helm-aif helm-moccur-auto-update-on-resume
(when (or (eq it 'noask)
(y-or-n-p "Helm (m)occur Buffer outdated, update? "))
(run-with-idle-timer 0.1 nil (lambda ()
(with-helm-buffer
(helm-force-update)
(message "Helm (m)occur Buffer have been udated")
(sit-for 1) (message nil))))
(unless buffer-is-modified (setq helm-multi-occur-buffer-tick new-tick-ls)))
(run-with-idle-timer 0.1 nil (lambda ()
(with-helm-buffer
(let ((ov (make-overlay (save-excursion
(goto-char (point-min))
(forward-line 1)
(point))
(point-max))))
(overlay-put ov 'face 'helm-resume-need-update)
(sit-for 0.3) (delete-overlay ov)
(message "[Helm occur Buffer outdated (C-c C-u to update)]")))))
(unless buffer-is-modified
(with-helm-after-update-hook
(setq helm-multi-occur-buffer-tick new-tick-ls)
(message "Helm (m)occur Buffer have been udated")))))))))
(defun helm-moccur-filter-one-by-one (candidate &optional outside-helm)
"`filter-one-by-one' function for `helm-source-moccur'."
(require 'helm-grep)
(let* ((split (helm-grep-split-line candidate))
(buf (car split))
(lineno (nth 1 split))
(str (nth 2 split)))
(cons (concat (propertize
buf
'invisible (and (null outside-helm)
(with-helm-buffer
helm-occur--invisible))
'face 'helm-moccur-buffer
'help-echo (buffer-file-name
(get-buffer buf))
'buffer-name buf)
(propertize ":" 'invisible (and (null outside-helm)
(with-helm-buffer
helm-occur--invisible)))
(propertize lineno 'face 'helm-grep-lineno)
":"
(helm-grep-highlight-match str t))
candidate)))
(defun helm-multi-occur-1 (buffers &optional input)
"Main function to call `helm-source-moccur' with BUFFERS list."
(let ((bufs (if helm-moccur-always-search-in-current
(cons
;; will become helm-current-buffer later.
(buffer-name (current-buffer))
(remove helm-current-buffer buffers))
buffers)))
(unless helm-source-moccur
(setq helm-source-moccur
(helm-make-source "Moccur" 'helm-source-multi-occur)))
(helm-attrset 'moccur-buffers bufs helm-source-moccur)
(helm-set-local-variable 'helm-multi-occur-buffer-list bufs)
(helm-set-local-variable
'helm-multi-occur-buffer-tick
(cl-loop for b in bufs
collect (buffer-chars-modified-tick (get-buffer b)))))
(helm :sources 'helm-source-moccur
:buffer "*helm multi occur*"
:default (helm-aif (thing-at-point 'symbol) (regexp-quote it))
:history 'helm-occur-history
:keymap helm-moccur-map
:input input
:truncate-lines helm-moccur-truncate-lines))
(defun helm-moccur-run-save-buffer ()
"Run moccur save results action from `helm-moccur'."
(interactive)
(with-helm-alive-p
(helm-exit-and-execute-action 'helm-moccur-save-results)))
(put 'helm-moccur-run-save-buffer 'helm-only t)
;;; helm-moccur-mode
;;
;;
(defvar helm-moccur-mode-map
(let ((map (make-sparse-keymap)))
(define-key map (kbd "RET") 'helm-moccur-mode-goto-line)
(define-key map (kbd "C-o") 'helm-moccur-mode-goto-line-ow)
(define-key map (kbd "<C-down>") 'helm-moccur-mode-goto-line-ow-forward)
(define-key map (kbd "<C-up>") 'helm-moccur-mode-goto-line-ow-backward)
(define-key map (kbd "<M-down>") 'helm-gm-next-file)
(define-key map (kbd "<M-up>") 'helm-gm-precedent-file)
(define-key map (kbd "M-n") 'helm-moccur-mode-goto-line-ow-forward)
(define-key map (kbd "M-p") 'helm-moccur-mode-goto-line-ow-backward)
(define-key map (kbd "M-N") 'helm-gm-next-file)
(define-key map (kbd "M-P") 'helm-gm-precedent-file)
map))
(defun helm-moccur-mode-goto-line ()
(interactive)
(helm-aif (get-text-property (point) 'helm-realvalue)
(progn (helm-moccur-goto-line it) (helm-match-line-cleanup-pulse))))
(defun helm-moccur-mode-goto-line-ow ()
(interactive)
(helm-aif (get-text-property (point) 'helm-realvalue)
(progn (helm-moccur-goto-line-ow it) (helm-match-line-cleanup-pulse))))
(defun helm-moccur-mode-goto-line-ow-forward-1 (arg)
(condition-case nil
(progn
(save-selected-window
(helm-moccur-mode-goto-line-ow)
(recenter))
(forward-line arg))
(error nil)))
(defun helm-moccur-mode-goto-line-ow-forward ()
(interactive)
(helm-moccur-mode-goto-line-ow-forward-1 1))
(defun helm-moccur-mode-goto-line-ow-backward ()
(interactive)
(helm-moccur-mode-goto-line-ow-forward-1 -1))
(defun helm-moccur-save-results (_candidate)
"Save helm moccur results in a `helm-moccur-mode' buffer."
(let ((buf "*hmoccur*")
new-buf)
(when (get-buffer buf)
(setq new-buf (helm-read-string "OccurBufferName: " buf))
(cl-loop for b in (helm-buffer-list)
when (and (string= new-buf b)
(not (y-or-n-p
(format "Buffer `%s' already exists overwrite? "
new-buf))))
do (setq new-buf (helm-read-string "OccurBufferName: " "*hmoccur ")))
(setq buf new-buf))
(with-current-buffer (get-buffer-create buf)
(setq buffer-read-only t)
(let ((inhibit-read-only t)
(map (make-sparse-keymap)))
(erase-buffer)
(insert "-*- mode: helm-moccur -*-\n\n"
(format "Moccur Results for `%s':\n\n" helm-input))
(save-excursion
(insert (with-current-buffer helm-buffer
(goto-char (point-min)) (forward-line 1)
(buffer-substring (point) (point-max)))))
(save-excursion
(while (not (eobp))
(add-text-properties
(point-at-bol) (point-at-eol)
`(keymap ,map
help-echo ,(concat
(buffer-file-name
(get-buffer (get-text-property
(point) 'buffer-name)))
"\nmouse-1: set point\nmouse-2: jump to selection")
mouse-face highlight
invisible nil))
(define-key map [mouse-1] 'mouse-set-point)
(define-key map [mouse-2] 'helm-moccur-mode-mouse-goto-line)
(define-key map [mouse-3] 'ignore)
(forward-line 1))))
(helm-moccur-mode))
(pop-to-buffer buf)
(message "Helm Moccur Results saved in `%s' buffer" buf)))
(defun helm-moccur-mode-mouse-goto-line (event)
(interactive "e")
(let* ((window (posn-window (event-end event)))
(pos (posn-point (event-end event))))
(with-selected-window window
(when (eq major-mode 'helm-moccur-mode)
(goto-char pos)
(helm-moccur-mode-goto-line)))))
(put 'helm-moccur-mode-mouse-goto-line 'helm-only t)
;;;###autoload
(define-derived-mode helm-moccur-mode
special-mode "helm-moccur"
"Major mode to provide actions in helm moccur saved buffer.
Special commands:
\\{helm-moccur-mode-map}"
(set (make-local-variable 'helm-multi-occur-buffer-list)
(with-helm-buffer helm-multi-occur-buffer-list))
(set (make-local-variable 'revert-buffer-function)
#'helm-moccur-mode--revert-buffer-function))
(put 'helm-moccur-mode 'helm-only t)
(defun helm-moccur-mode--revert-buffer-function (&optional _ignore-auto _noconfirm)
(goto-char (point-min))
(let (pattern)
(when (re-search-forward "^Moccur Results for `\\(.*\\)'" nil t)
(setq pattern (match-string 1))
(forward-line 0)
(when (re-search-forward "^$" nil t)
(forward-line 1))
(let ((inhibit-read-only t)
(buffer (current-buffer))
(buflst helm-multi-occur-buffer-list)
(bsubstring (if helm-moccur-show-buffer-fontification
#'buffer-substring #'buffer-substring-no-properties)))
(delete-region (point) (point-max))
(message "Reverting buffer...")
(save-excursion
(with-temp-buffer
(insert
"\n"
(cl-loop for buf in buflst
for bufstr = (or (and (buffer-live-p (get-buffer buf))
(with-current-buffer buf
(funcall bsubstring
(point-min) (point-max))))
"")
unless (string= bufstr "")
do (add-text-properties
0 (length bufstr)
`(buffer-name ,(buffer-name (get-buffer buf)))
bufstr)
concat bufstr)
"\n")
(goto-char (point-min))
(cl-loop with helm-pattern = pattern
while (helm-mm-search pattern)
for line = (helm-moccur-get-line (point-at-bol) (point-at-eol))
when line
do (with-current-buffer buffer
(insert
(propertize
(car (helm-moccur-filter-one-by-one line t))
'helm-realvalue line)
"\n")))))
(message "Reverting buffer done")))))
;;; Predefined commands
;;
;;
;;;###autoload
(defun helm-regexp ()
"Preconfigured helm to build regexps.
`query-replace-regexp' can be run from there against found regexp."
(interactive)
(save-restriction
(when (and (helm-region-active-p)
;; Don't narrow to region if buffer is already narrowed.
(not (helm-current-buffer-narrowed-p (current-buffer))))
(narrow-to-region (region-beginning) (region-end)))
(helm :sources helm-source-regexp
:buffer "*helm regexp*"
:prompt "Regexp: "
:history 'helm-build-regexp-history)))
;;;###autoload
(defun helm-occur ()
"Preconfigured helm for searching lines matching pattern in `current-buffer'.
When `helm-source-occur' is member of
`helm-sources-using-default-as-input' which is the default,
symbol at point is searched at startup.
When a region is marked search only in this region by narrowing.
To search in multiples buffers start from one of the commands listing
buffers (i.e. a helm command using `helm-source-buffers-list' like
`helm-mini') and use the multi occur buffers action.
This is the helm implementation that collect lines matching pattern
like vanilla emacs `occur' but have nothing to do with it, the search
engine beeing completely different."
(interactive)
(helm-occur-init-source)
(let ((bufs (list (buffer-name (current-buffer)))))
(helm-attrset 'moccur-buffers bufs helm-source-occur)
(helm-set-local-variable 'helm-multi-occur-buffer-list bufs)
(helm-set-local-variable
'helm-multi-occur-buffer-tick
(cl-loop for b in bufs
collect (buffer-chars-modified-tick (get-buffer b)))))
(helm-set-local-variable 'helm-occur--invisible
(null helm-occur-show-buffer-name))
(save-restriction
(let (def pos)
(when (use-region-p)
;; When user mark defun with `mark-defun' with intention of
;; using helm-occur on this region, it is relevant to use the
;; thing-at-point located at previous position which have been
;; pushed to `mark-ring'.
(setq def (save-excursion
(goto-char (setq pos (car mark-ring)))
(helm-aif (thing-at-point 'symbol) (regexp-quote it))))
(narrow-to-region (region-beginning) (region-end)))
(unwind-protect
(helm :sources 'helm-source-occur
:buffer "*helm occur*"
:default (or def (helm-aif (thing-at-point 'symbol) (regexp-quote it)))
:history 'helm-occur-history
:preselect (and (memq 'helm-source-occur helm-sources-using-default-as-input)
(format "%s:%d:" (regexp-quote (buffer-name))
(line-number-at-pos (or pos (point)))))
:truncate-lines helm-moccur-truncate-lines)
(deactivate-mark t)))))
;;;###autoload
(defun helm-occur-from-isearch ()
"Invoke `helm-occur' from isearch."
(interactive)
(let ((input (if isearch-regexp
isearch-string
(regexp-quote isearch-string)))
(bufs (list (buffer-name (current-buffer)))))
(isearch-exit)
(helm-occur-init-source)
(helm-attrset 'moccur-buffers bufs helm-source-occur)
(helm-set-local-variable 'helm-multi-occur-buffer-list bufs)
(helm-set-local-variable
'helm-multi-occur-buffer-tick
(cl-loop for b in bufs
collect (buffer-chars-modified-tick (get-buffer b))))
(helm-set-local-variable 'helm-occur--invisible
(null helm-occur-show-buffer-name))
(helm :sources 'helm-source-occur
:buffer "*helm occur*"
:history 'helm-occur-history
:input input
:truncate-lines helm-moccur-truncate-lines)))
;;;###autoload
(defun helm-multi-occur-from-isearch (&optional _arg)
"Invoke `helm-multi-occur' from isearch.
With a prefix arg, reverse the behavior of
`helm-moccur-always-search-in-current'.
The prefix arg can be set before calling
`helm-multi-occur-from-isearch' or during the buffer selection."
(interactive "p")
(let (buf-list
helm-moccur-always-search-in-current
(input (if isearch-regexp
isearch-string
(regexp-quote isearch-string))))
(isearch-exit)
(setq buf-list (helm-comp-read "Buffers: "
(helm-buffer-list)
:name "Occur in buffer(s)"
:marked-candidates t))
(setq helm-moccur-always-search-in-current
(if (or current-prefix-arg
helm-current-prefix-arg)
(not helm-moccur-always-search-in-current)
helm-moccur-always-search-in-current))
(helm-multi-occur-1 buf-list input)))
(provide 'helm-regexp)
;; Local Variables:
;; byte-compile-warnings: (not obsolete)
;; coding: utf-8
;; indent-tabs-mode: nil
;; End:
;;; helm-regexp.el ends here

View File

@@ -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 <thierry.volpiatto@gmail.com>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Code:
(require 'cl-lib)
(require 'helm)
(require 'helm-utils)
(require 'helm-help)
(require 'helm-elisp)
(declare-function undo-tree-restore-state-from-register "ext:undo-tree.el" (register))
(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)))
;;;; <Mark ring>
;; DO NOT use these sources with other sources use
;; the commands `helm-mark-ring', `helm-global-mark-ring' or
;; `helm-all-mark-rings' instead.
(defun helm-mark-ring-line-string-at-pos (pos)
"Return line string at position POS."
(save-excursion
(goto-char pos)
(forward-line 0)
(let ((line (car (split-string (thing-at-point 'line) "[\n\r]"))))
(remove-text-properties 0 (length line) '(read-only) line)
(if (string= "" line)
"<EMPTY LINE>"
line))))
(defun helm-mark-ring-get-candidates ()
(with-helm-current-buffer
(cl-loop with marks = (if (mark t)
(cons (mark-marker) mark-ring)
mark-ring)
for marker in marks
with max-line-number = (line-number-at-pos (point-max))
with width = (length (number-to-string max-line-number))
for m = (format (concat "%" (number-to-string width) "d: %s")
(line-number-at-pos marker)
(helm-mark-ring-line-string-at-pos marker))
unless (and recip (assoc m recip))
collect (cons m marker) into recip
finally return recip)))
(defun helm-mark-ring-default-action (candidate)
(let ((target (copy-marker candidate)))
(helm-aif (marker-buffer candidate)
(progn
(switch-to-buffer it)
(helm-log-run-hook 'helm-goto-line-before-hook)
(helm-match-line-cleanup)
(with-helm-current-buffer
(unless helm-yank-point (setq helm-yank-point (point))))
(helm-goto-char target)
(helm-highlight-current-line))
;; marker points to no buffer, no need to dereference it, just
;; delete it.
(setq mark-ring (delete target mark-ring))
(error "Marker points to no buffer"))))
(defvar helm-source-mark-ring
(helm-build-sync-source "mark-ring"
:candidates #'helm-mark-ring-get-candidates
:action '(("Goto line" . helm-mark-ring-default-action))
:persistent-help "Show this line"
:group 'helm-ring))
;;; Global-mark-ring
(defvar helm-source-global-mark-ring
(helm-build-sync-source "global-mark-ring"
:candidates #'helm-global-mark-ring-get-candidates
:action '(("Goto line" . helm-mark-ring-default-action))
:persistent-help "Show this line"
:group 'helm-ring))
(defun helm-global-mark-ring-format-buffer (marker)
(with-current-buffer (marker-buffer marker)
(goto-char marker)
(forward-line 0)
(let ((line (pcase (thing-at-point 'line)
((and line (pred stringp)
(guard (not (string-match-p "\\`\n?\\'" line))))
(car (split-string line "[\n\r]")))
(_ "<EMPTY LINE>"))))
(remove-text-properties 0 (length line) '(read-only) line)
(format "%7d:%s: %s"
(line-number-at-pos) (marker-buffer marker) line))))
(defun helm-global-mark-ring-get-candidates ()
(let ((marks global-mark-ring))
(when marks
(cl-loop for marker in marks
for mb = (marker-buffer marker)
for gm = (unless (or (string-match "^ " (format "%s" mb))
(null mb))
(helm-global-mark-ring-format-buffer marker))
when (and gm (not (assoc gm recip)))
collect (cons gm marker) into recip
finally return recip))))
;;;; <Register>
;;; Insert from register
(defvar helm-source-register
(helm-build-sync-source "Registers"
:candidates #'helm-register-candidates
:action-transformer #'helm-register-action-transformer
:persistent-help ""
:multiline t
:action '(("Delete Register(s)" .
(lambda (_candidate)
(cl-loop for candidate in (helm-marked-candidates)
for register = (car candidate)
do (setq register-alist
(delq (assoc register register-alist)
register-alist))))))
:group 'helm-ring)
"See (info \"(emacs)Registers\")")
(defun helm-register-candidates ()
"Collecting register contents and appropriate commands."
(cl-loop for (char . val) in register-alist
for key = (single-key-description char)
for string-actions =
(cond
((numberp val)
(list (int-to-string val)
'insert-register
'increment-register))
((markerp val)
(let ((buf (marker-buffer val)))
(if (null buf)
(list "a marker in no buffer")
(list (concat
"a buffer position:"
(buffer-name buf)
", position "
(int-to-string (marker-position val)))
'jump-to-register
'insert-register))))
((and (consp val) (window-configuration-p (car val)))
(list "window configuration."
'jump-to-register))
((and (vectorp val)
(fboundp 'undo-tree-register-data-p)
(undo-tree-register-data-p (elt val 1)))
(list
"Undo-tree entry."
'undo-tree-restore-state-from-register))
((or (and (vectorp val) (eq 'registerv (aref val 0)))
(and (consp val) (frame-configuration-p (car val))))
(list "frame configuration."
'jump-to-register))
((and (consp val) (eq (car val) 'file))
(list (concat "file:"
(prin1-to-string (cdr val))
".")
'jump-to-register))
((and (consp val) (eq (car val) 'file-query))
(list (concat "file:a file-query reference: file "
(car (cdr val))
", position "
(int-to-string (car (cdr (cdr val))))
".")
'jump-to-register))
((consp val)
(let ((lines (format "%4d" (length val))))
(list (format "%s: %s\n" lines
(truncate-string-to-width
(mapconcat 'identity (list (car val))
"^J") (- (window-width) 15)))
'insert-register)))
((stringp val)
(list
;; without properties
(concat (substring-no-properties
val 0 (min (length val) helm-register-max-offset))
(if (> (length val) helm-register-max-offset)
"[...]" ""))
'insert-register
'append-to-register
'prepend-to-register)))
unless (null string-actions) ; Fix Issue #1107.
collect (cons (format "Register %3s:\n %s" key (car string-actions))
(cons char (cdr string-actions)))))
(defun helm-register-action-transformer (actions register-and-functions)
"Decide actions by the contents of register."
(cl-loop with func-actions =
'((insert-register
"Insert Register" .
(lambda (c) (insert-register (car c))))
(jump-to-register
"Jump to Register" .
(lambda (c) (jump-to-register (car c))))
(append-to-register
"Append Region to Register" .
(lambda (c) (append-to-register
(car c) (region-beginning) (region-end))))
(prepend-to-register
"Prepend Region to Register" .
(lambda (c) (prepend-to-register
(car c) (region-beginning) (region-end))))
(increment-register
"Increment Prefix Arg to Register" .
(lambda (c) (increment-register
helm-current-prefix-arg (car c))))
(undo-tree-restore-state-from-register
"Restore Undo-tree register" .
(lambda (c) (and (fboundp 'undo-tree-restore-state-from-register)
(undo-tree-restore-state-from-register (car c))))))
for func in (cdr register-and-functions)
when (assq func func-actions)
collect (cdr it) into transformer-actions
finally return (append transformer-actions actions)))
;;;###autoload
(defun helm-mark-ring ()
"Preconfigured `helm' for `helm-source-mark-ring'."
(interactive)
(helm :sources 'helm-source-mark-ring
:resume 'noresume
:buffer "*helm mark*"))
;;;###autoload
(defun helm-global-mark-ring ()
"Preconfigured `helm' for `helm-source-global-mark-ring'."
(interactive)
(helm :sources 'helm-source-global-mark-ring
:resume 'noresume
:buffer "*helm global mark*"))
;;;###autoload
(defun helm-all-mark-rings ()
"Preconfigured `helm' for `helm-source-global-mark-ring' and \
`helm-source-mark-ring'."
(interactive)
(helm :sources '(helm-source-mark-ring
helm-source-global-mark-ring)
:resume 'noresume
:buffer "*helm mark ring*"))
;;;###autoload
(defun helm-register ()
"Preconfigured `helm' for Emacs registers."
(interactive)
(helm :sources 'helm-source-register
:resume 'noresume
:buffer "*helm register*"))
;;;###autoload
(defun helm-show-kill-ring ()
"Preconfigured `helm' for `kill-ring'.
It is drop-in replacement of `yank-pop'.
First call open the kill-ring browser, next calls move to next line."
(interactive)
(setq helm-kill-ring--truncated-flag nil)
(let ((enable-recursive-minibuffers t))
(helm :sources helm-source-kill-ring
:buffer "*helm kill ring*"
:resume 'noresume
:allow-nest t)))
;;;###autoload
(defun helm-execute-kmacro ()
"Preconfigured helm for keyboard macros.
Define your macros with `f3' and `f4'.
See (info \"(emacs) Keyboard Macros\") for detailed infos.
This command is useful when used with persistent action."
(interactive)
(let ((helm-quit-if-no-candidate
(lambda () (message "No kbd macro has been defined"))))
(helm :sources
(helm-build-sync-source "Kmacro"
:candidates (lambda ()
(helm-fast-remove-dups
(cons (kmacro-ring-head)
kmacro-ring)
:test 'equal))
:multiline t
:candidate-transformer
(lambda (candidates)
(cl-loop for c in candidates collect
(propertize (help-key-description (car c) nil)
'helm-realvalue c)))
:persistent-help "Execute kmacro"
:help-message 'helm-kmacro-help-message
:action
(helm-make-actions
"Execute kmacro (`C-u <n>' to execute <n> times)"
'helm-kbd-macro-execute
"Concat marked macros"
'helm-kbd-macro-concat-macros
"Delete marked macros"
'helm-kbd-macro-delete-macro
"Edit marked macro"
'helm-kbd-macro-edit-macro)
:group 'helm-ring)
:buffer "*helm kmacro*")))
(defun helm-kbd-macro-execute (candidate)
;; Move candidate on top of list for next use.
(setq kmacro-ring (delete candidate kmacro-ring))
(kmacro-push-ring)
(kmacro-split-ring-element candidate)
(kmacro-exec-ring-item
candidate helm-current-prefix-arg))
(defun helm-kbd-macro-concat-macros (_candidate)
(let ((mkd (helm-marked-candidates)))
(when (cdr mkd)
(kmacro-push-ring)
(setq last-kbd-macro
(mapconcat 'identity
(cl-loop for km in mkd
if (vectorp km)
append (cl-loop for k across km collect
(key-description (vector k)))
into result
else collect (car km) into result
finally return result)
"")))))
(defun helm-kbd-macro-delete-macro (_candidate)
(let ((mkd (helm-marked-candidates)))
(kmacro-push-ring)
(cl-loop for km in mkd
do (setq kmacro-ring (delete km kmacro-ring)))
(kmacro-pop-ring1)))
(defun helm-kbd-macro-edit-macro (candidate)
(kmacro-push-ring)
(setq kmacro-ring (delete candidate kmacro-ring))
(kmacro-split-ring-element candidate)
(kmacro-edit-macro))
(provide 'helm-ring)
;; Local Variables:
;; byte-compile-warnings: (not obsolete)
;; coding: utf-8
;; indent-tabs-mode: nil
;; End:
;;; helm-ring.el ends here

View File

@@ -0,0 +1,231 @@
;;; helm-semantic.el --- Helm interface for Semantic -*- lexical-binding: t -*-
;; Copyright (C) 2012 ~ 2017 Daniel Hackney <dan@haxney.org>
;; 2012 ~ 2018 Thierry Volpiatto<thierry.volpiatto@gmail.com>
;; Author: Daniel Hackney <dan@haxney.org>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Commentary:
;; Uses `candidates-in-buffer' for speed.
;;; Code:
(require 'cl-lib)
(require 'semantic)
(require 'helm-help)
(require 'helm-imenu)
(declare-function pulse-momentary-highlight-one-line "pulse.el" (point &optional face))
(defgroup helm-semantic nil
"Semantic tags related libraries and applications for helm."
:group 'helm)
(defcustom helm-semantic-lynx-style-map t
"Use Arrow keys to jump to occurences."
:group 'helm-semantic
:type 'boolean)
(defcustom helm-semantic-display-style
'((python-mode . semantic-format-tag-summarize)
(c-mode . semantic-format-tag-concise-prototype-c-mode)
(emacs-lisp-mode . semantic-format-tag-abbreviate-emacs-lisp-mode))
"Function to present a semantic tag according to `major-mode'.
It is an alist where the `car' of each element is a `major-mode' and
the `cdr' a `semantic-format-tag-*' function.
If no function is found for current `major-mode', fall back to
`semantic-format-tag-summarize' default function.
You can have more or less informations depending of the `semantic-format-tag-*'
function you choose.
All the supported functions are prefixed with \"semantic-format-tag-\",
you have completion on these functions with `C-M i' in the customize interface."
:group 'helm-semantic
:type '(alist :key-type symbol :value-type symbol))
;;; keymap
(defvar helm-semantic-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map helm-map)
(when helm-semantic-lynx-style-map
(define-key map (kbd "<left>") 'helm-maybe-exit-minibuffer)
(define-key map (kbd "<right>") 'helm-execute-persistent-action))
(delq nil map)))
;; Internals vars
(defvar helm-semantic--tags-cache nil)
(defun helm-semantic--fetch-candidates (tags depth &optional class)
"Write the contents of TAGS to the current buffer."
(let ((class class) cur-type
(stylefn (or (with-helm-current-buffer
(assoc-default major-mode helm-semantic-display-style))
#'semantic-format-tag-summarize)))
(cl-dolist (tag tags)
(when (listp tag)
(cl-case (setq cur-type (semantic-tag-class tag))
((function variable type)
(let ((spaces (make-string (* depth 2) ?\s))
(type-p (eq cur-type 'type)))
(unless (and (> depth 0) (not type-p))
(setq class nil))
(insert
(if (and class (not type-p))
(format "%s%s(%s) "
spaces (if (< depth 2) "" "├►") class)
spaces)
;; Save the tag for later
(propertize (funcall stylefn tag nil t)
'semantic-tag tag)
"\n")
(and type-p (setq class (car tag)))
;; Recurse to children
(unless (eq cur-type 'function)
(helm-semantic--fetch-candidates
(semantic-tag-components tag) (1+ depth) class))))
;; Don't do anything with packages or includes for now
((package include)
(insert
(propertize (funcall stylefn tag nil t)
'semantic-tag tag)
"\n")
)
;; Catch-all
(t))))))
(defun helm-semantic-default-action (_candidate &optional persistent)
;; By default, helm doesn't pass on the text properties of the selection.
;; Fix this.
(helm-log-run-hook 'helm-goto-line-before-hook)
(with-current-buffer helm-buffer
(when (looking-at " ")
(goto-char (next-single-property-change
(point-at-bol) 'semantic-tag nil (point-at-eol))))
(let ((tag (get-text-property (point) 'semantic-tag)))
(semantic-go-to-tag tag)
(unless persistent
(pulse-momentary-highlight-one-line (point))))))
(defun helm-semantic--maybe-set-needs-update ()
(with-helm-current-buffer
(when (semantic-parse-tree-needs-update-p)
(semantic-parse-tree-set-needs-update))))
(defvar helm-source-semantic nil)
(defclass helm-semantic-source (helm-source-in-buffer)
((init :initform (lambda ()
(helm-semantic--maybe-set-needs-update)
(setq helm-semantic--tags-cache (semantic-fetch-tags))
(with-current-buffer (helm-candidate-buffer 'global)
(let ((major-mode (with-helm-current-buffer major-mode)))
(helm-semantic--fetch-candidates helm-semantic--tags-cache 0)))))
(get-line :initform 'buffer-substring)
(persistent-help :initform "Show this entry")
(keymap :initform 'helm-semantic-map)
(help-message :initform 'helm-semantic-help-message)
(persistent-action :initform (lambda (elm)
(helm-semantic-default-action elm t)
(helm-highlight-current-line)))
(action :initform 'helm-semantic-default-action)))
(defcustom helm-semantic-fuzzy-match nil
"Enable fuzzy matching in `helm-source-semantic'."
:group 'helm-semantic
:type 'boolean
:set (lambda (var val)
(set var val)
(setq helm-source-semantic
(helm-make-source "Semantic Tags" 'helm-semantic-source
:fuzzy-match helm-semantic-fuzzy-match))))
;;;###autoload
(defun helm-semantic (arg)
"Preconfigured `helm' for `semantic'.
If ARG is supplied, pre-select symbol at point instead of current"
(interactive "P")
(let ((tag (helm-aif (car (semantic-current-tag-parent))
(let ((curtag (car (semantic-current-tag))))
(if (string= it curtag)
(format "\\_<%s\\_>" curtag)
(cons (format "\\_<%s\\_>" it)
(format "\\_<%s\\_>" curtag))))
(format "\\_<%s\\_>" (car (semantic-current-tag))))))
(unless helm-source-semantic
(setq helm-source-semantic
(helm-make-source "Semantic Tags" 'helm-semantic-source
:fuzzy-match helm-semantic-fuzzy-match)))
(helm :sources 'helm-source-semantic
:candidate-number-limit 9999
:preselect (if arg
(thing-at-point 'symbol)
tag)
:buffer "*helm semantic*")))
;;;###autoload
(defun helm-semantic-or-imenu (arg)
"Preconfigured helm for `semantic' or `imenu'.
If ARG is supplied, pre-select symbol at point instead of current
semantic tag in scope.
If `semantic-mode' is active in the current buffer, then use
semantic for generating tags, otherwise fall back to `imenu'.
Fill in the symbol at point by default."
(interactive "P")
(unless helm-source-semantic
(setq helm-source-semantic
(helm-make-source "Semantic Tags" 'helm-semantic-source
:fuzzy-match helm-semantic-fuzzy-match)))
(unless helm-source-imenu
(setq helm-source-imenu
(helm-make-source "Imenu" 'helm-imenu-source
:fuzzy-match helm-imenu-fuzzy-match)))
(let* ((source (if (semantic-active-p)
'helm-source-semantic
'helm-source-imenu))
(imenu-p (eq source 'helm-source-imenu))
(imenu-auto-rescan imenu-p)
(str (thing-at-point 'symbol))
(helm-execute-action-at-once-if-one
(and imenu-p
helm-imenu-execute-action-at-once-if-one))
(tag (helm-aif (car (semantic-current-tag-parent))
(let ((curtag (car (semantic-current-tag))))
(if (string= it curtag)
(format "\\_<%s\\_>" curtag)
(cons (format "\\_<%s\\_>" it)
(format "\\_<%s\\_>" curtag))))
(format "\\_<%s\\_>" (car (semantic-current-tag))))))
(helm :sources source
:candidate-number-limit 9999
:default (and imenu-p (list (concat "\\_<" (and str (regexp-quote str)) "\\_>") str))
:preselect (if (or arg imenu-p) str tag)
:buffer "*helm semantic/imenu*")))
(provide 'helm-semantic)
;; Local Variables:
;; byte-compile-warnings: (not obsolete)
;; coding: utf-8
;; indent-tabs-mode: nil
;; End:
;;; helm-semantic.el ends here

View File

@@ -0,0 +1,459 @@
;;; helm-sys.el --- System related functions for helm. -*- lexical-binding: t -*-
;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Code:
(require 'cl-lib)
(require 'helm)
(require 'helm-help)
(require 'helm-utils)
(defgroup helm-sys nil
"System related helm library."
:group 'helm)
(defface helm-top-columns
'((t :inherit helm-header))
"Face for helm help string in minibuffer."
:group 'helm-sys)
(defcustom helm-top-command
(cl-case system-type
(darwin "env COLUMNS=%s ps -axo pid,user,pri,nice,ucomm,tty,start_time,vsz,%%cpu,%%mem,etime,command")
(t "env COLUMNS=%s top -b -n 1"))
"Top command used to display output of top.
A format string where %s will be replaced with `frame-width'.
To use 'top' command, a version supporting batch mode (-b option) is needed.
On Mac OSX 'top' command doesn't support this, so ps command
is used instead by default.
Normally 'top' command output have 12 columns, but in some versions you may
have less than this, so you can either customize top to use 12 columns with the
interactives 'f' and 'W' commands of top, or modify
`helm-top-sort-columns-alist' to fit with the number of columns
your 'top' command is using.
If you modify 'ps' command be sure that 'pid' comes in first
and \"env COLUMNS=%s\" is specified at beginning of command.
Ensure also that no elements contain spaces (e.g use start_time and not start).
Same as for 'top' you can customize `helm-top-sort-columns-alist' to make sort commands
working properly according to your settings."
:group 'helm-sys
:type 'string)
(defcustom helm-top-sort-columns-alist '((com . 11)
(mem . 9)
(cpu . 8)
(user . 1))
"Allow defining which column to use when sorting output of top/ps command.
Only com, mem, cpu and user are sorted, so no need to put something else there,
it will have no effect.
Note that column numbers are counted from zero, i.e column 1 is the nth 0 column."
:group 'helm-sys
:type '(alist :key-type symbol :value-type (integer :tag "Column number")))
(defcustom helm-top-poll-delay 1.5
"Helm top poll after this delay when `helm-top-poll-mode' is enabled.
The minimal delay allowed is 1.5, if less than this helm-top will use 1.5."
:group 'helm-sys
:type 'float)
(defcustom helm-top-poll-delay-post-command 1.0
"Helm top stop polling during this delay.
This delay is additioned to `helm-top-poll-delay' after emacs stop
being idle."
:group 'helm-sys
:type 'float)
(defcustom helm-top-poll-preselection 'linum
"Stay on same line or follow candidate when `helm-top-poll' update display.
Possible values are 'candidate or 'linum.
This affect also sorting functions in the same way."
:group'helm-sys
:type '(radio :tag "Preferred preselection action for helm-top"
(const :tag "Follow candidate" candidate)
(const :tag "Stay on same line" linum)))
;;; Top (process)
;;
;;
(defvar helm-top-sort-fn nil)
(defvar helm-top-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map helm-map)
(define-key map (kbd "M-P") 'helm-top-run-sort-by-cpu)
(define-key map (kbd "M-C") 'helm-top-run-sort-by-com)
(define-key map (kbd "M-M") 'helm-top-run-sort-by-mem)
(define-key map (kbd "M-U") 'helm-top-run-sort-by-user)
map))
(defvar helm-top-after-init-hook nil
"Local hook for helm-top.")
(defvar helm-top--poll-timer nil)
(defun helm-top-poll (&optional no-update delay)
(when helm-top--poll-timer
(cancel-timer helm-top--poll-timer))
(condition-case nil
(progn
(when (and (helm--alive-p) (null no-update))
;; Fix quitting while process is running
;; by binding `with-local-quit' in init function
;; Issue #1521.
(helm-force-update
(cl-ecase helm-top-poll-preselection
(candidate (replace-regexp-in-string
"[0-9]+" "[0-9]+"
(regexp-quote (helm-get-selection nil t))))
(linum `(lambda ()
(goto-char (point-min))
(forward-line ,(helm-candidate-number-at-point)))))))
(setq helm-top--poll-timer
(run-with-idle-timer
(helm-aif (current-idle-time)
(time-add it (seconds-to-time
(or delay (helm-top--poll-delay))))
(or delay (helm-top--poll-delay)))
nil
'helm-top-poll)))
(quit (cancel-timer helm-top--poll-timer))))
(defun helm-top--poll-delay ()
(max 1.5 helm-top-poll-delay))
(defun helm-top-poll-no-update ()
(helm-top-poll t (+ (helm-top--poll-delay)
helm-top-poll-delay-post-command)))
(defun helm-top-initialize-poll-hooks ()
;; When emacs is idle during say 20s
;; the idle timer will run in 20+1.5 s.
;; This is fine when emacs stays idle, because the next timer
;; will run at 21.5+1.5 etc... so the display will be updated
;; at every 1.5 seconds.
;; But as soon as emacs looses its idleness, the next update
;; will occur at say 21+1.5 s, so we have to reinitialize
;; the timer at 0+1.5.
(add-hook 'post-command-hook 'helm-top-poll-no-update)
(add-hook 'focus-in-hook 'helm-top-poll-no-update))
;;;###autoload
(define-minor-mode helm-top-poll-mode
"Refresh automatically helm top buffer once enabled."
:group 'helm-top
:global t
(if helm-top-poll-mode
(progn
(add-hook 'helm-top-after-init-hook 'helm-top-poll-no-update)
(add-hook 'helm-top-after-init-hook 'helm-top-initialize-poll-hooks))
(remove-hook 'helm-top-after-init-hook 'helm-top-poll-no-update)
(remove-hook 'helm-top-after-init-hook 'helm-top-initialize-poll-hooks)))
(defvar helm-source-top
(helm-build-in-buffer-source "Top"
:header-name (lambda (name)
(concat name (if helm-top-poll-mode
" (auto updating)"
" (Press C-c C-u to refresh)")))
:init #'helm-top-init
:after-init-hook 'helm-top-after-init-hook
:cleanup (lambda ()
(when helm-top--poll-timer
(cancel-timer helm-top--poll-timer))
(remove-hook 'post-command-hook 'helm-top-poll-no-update)
(remove-hook 'focus-in-hook 'helm-top-poll-no-update))
:display-to-real #'helm-top-display-to-real
:persistent-action '(helm-top-sh-persistent-action . never-split)
:persistent-help "SIGTERM"
:help-message 'helm-top-help-message
:mode-line 'helm-top-mode-line
:follow 'never
:keymap helm-top-map
:filtered-candidate-transformer #'helm-top-sort-transformer
:action-transformer #'helm-top-action-transformer
:group 'helm-sys))
(defvar helm-top--line nil)
(defun helm-top-transformer (candidates _source)
"Transformer for `helm-top'.
Return empty string for non--valid candidates."
(cl-loop for disp in candidates collect
(cond ((string-match "^ *[0-9]+" disp) disp)
((string-match "^ *PID" disp)
(setq helm-top--line (cons (propertize disp 'face 'helm-top-columns) "")))
(t (cons disp "")))
into lst
finally return (or (member helm-top--line lst)
(cons helm-top--line lst))))
(defun helm-top--skip-top-line ()
(let* ((src (helm-get-current-source))
(src-name (assoc-default 'name src)))
(helm-aif (and (stringp src-name)
(string= src-name "Top")
(helm-get-selection nil t src))
(when (string-match-p "^ *PID" it)
(helm-next-line)))))
(defun helm-top-action-transformer (actions _candidate)
"Action transformer for `top'.
Show actions only on line starting by a PID."
(let ((disp (helm-get-selection nil t)))
(cond ((string-match "\\` *[0-9]+" disp)
(list '("kill (SIGTERM)" . (lambda (_pid)
(helm-top-sh "TERM" (helm-top--marked-pids))))
'("kill (SIGKILL)" . (lambda (_pid)
(helm-top-sh "KILL" (helm-top--marked-pids))))
'("kill (SIGINT)" . (lambda (_pid)
(helm-top-sh "INT" (helm-top--marked-pids))))
'("kill (Choose signal)"
. (lambda (_pid)
(let ((pids (helm-top--marked-pids)))
(helm-top-sh
(helm-comp-read (format "Kill %d pids with signal: "
(length pids))
'("ALRM" "HUP" "INT" "KILL" "PIPE" "POLL"
"PROF" "TERM" "USR1" "USR2" "VTALRM"
"STKFLT" "PWR" "WINCH" "CHLD" "URG"
"TSTP" "TTIN" "TTOU" "STOP" "CONT"
"ABRT" "FPE" "ILL" "QUIT" "SEGV"
"TRAP" "SYS" "EMT" "BUS" "XCPU" "XFSZ")
:must-match t)
pids))))))
(t actions))))
(defun helm-top--marked-pids ()
(helm-remove-if-not-match "\\`[0-9]+\\'" (helm-marked-candidates)))
(defun helm-top-sh (sig pids)
"Run kill shell command with signal SIG on PIDS for `helm-top'."
(message "kill -%s %s exited with status %s"
sig (mapconcat 'identity pids " ")
(apply #'call-process
"kill" nil nil nil (format "-%s" sig) pids)))
(defun helm-top-sh-persistent-action (pid)
(helm-top-sh "TERM" (list pid))
(helm-delete-current-selection))
(defun helm-top-init ()
"Insert output of top command in candidate buffer."
(with-local-quit
(unless helm-top-sort-fn (helm-top-set-mode-line "CPU"))
(with-current-buffer (helm-candidate-buffer 'global)
(call-process-shell-command
(format helm-top-command (frame-width))
nil (current-buffer)))))
(defun helm-top-display-to-real (line)
"Return pid only from LINE."
(car (split-string line)))
;; Sort top command
(defun helm-top-set-mode-line (str)
(if (string-match "Sort:\\[\\(.*\\)\\] " helm-top-mode-line)
(setq helm-top-mode-line (replace-match str nil nil helm-top-mode-line 1))
(setq helm-top-mode-line (concat (format "Sort:[%s] " str) helm-top-mode-line))))
(defun helm-top-sort-transformer (candidates source)
(helm-top-transformer
(if helm-top-sort-fn
(cl-loop for c in candidates
if (string-match "^ *[0-9]+" c)
collect c into pid-cands
else collect c into header-cands
finally return (append
header-cands
(sort pid-cands helm-top-sort-fn)))
candidates)
source))
(defun helm-top-sort-by-com (s1 s2)
(let* ((split-1 (split-string s1))
(split-2 (split-string s2))
(col (cdr (assq 'com helm-top-sort-columns-alist)))
(com-1 (nth col split-1))
(com-2 (nth col split-2)))
(string< com-1 com-2)))
(defun helm-top-sort-by-mem (s1 s2)
(let* ((split-1 (split-string s1))
(split-2 (split-string s2))
(col (cdr (assq 'mem helm-top-sort-columns-alist)))
(mem-1 (string-to-number (nth col split-1)))
(mem-2 (string-to-number (nth col split-2))))
(> mem-1 mem-2)))
(defun helm-top-sort-by-cpu (s1 s2)
(let* ((split-1 (split-string s1))
(split-2 (split-string s2))
(col (cdr (assq 'cpu helm-top-sort-columns-alist)))
(cpu-1 (string-to-number (nth col split-1)))
(cpu-2 (string-to-number (nth col split-2))))
(> cpu-1 cpu-2)))
(defun helm-top-sort-by-user (s1 s2)
(let* ((split-1 (split-string s1))
(split-2 (split-string s2))
(col (cdr (assq 'user helm-top-sort-columns-alist)))
(user-1 (nth col split-1))
(user-2 (nth col split-2)))
(string< user-1 user-2)))
(defun helm-top--preselect-fn ()
(if (eq helm-top-poll-preselection 'linum)
`(lambda ()
(goto-char (point-min))
(forward-line ,(helm-candidate-number-at-point)))
(replace-regexp-in-string
"[0-9]+" "[0-9]+"
(regexp-quote (helm-get-selection nil t)))))
(defun helm-top-run-sort-by-com ()
(interactive)
(helm-top-set-mode-line "COM")
(setq helm-top-sort-fn 'helm-top-sort-by-com)
(helm-update (helm-top--preselect-fn)))
(defun helm-top-run-sort-by-cpu ()
(interactive)
(helm-top-set-mode-line "CPU")
;; Force sorting by CPU even if some versions of top are using by
;; default CPU sorting (Issue #1908).
(setq helm-top-sort-fn 'helm-top-sort-by-cpu)
(helm-update (helm-top--preselect-fn)))
(defun helm-top-run-sort-by-mem ()
(interactive)
(helm-top-set-mode-line "MEM")
(setq helm-top-sort-fn 'helm-top-sort-by-mem)
(helm-update (helm-top--preselect-fn)))
(defun helm-top-run-sort-by-user ()
(interactive)
(helm-top-set-mode-line "USER")
(setq helm-top-sort-fn 'helm-top-sort-by-user)
(helm-update (helm-top--preselect-fn)))
;;; X RandR resolution change
;;
;;
;;; FIXME I do not care multi-display.
(defun helm-xrandr-info ()
"Return a pair with current X screen number and current X display name."
(with-temp-buffer
(call-process "xrandr" nil (current-buffer) nil
"--current")
(let (screen output)
(goto-char (point-min))
(save-excursion
(when (re-search-forward "\\(^Screen \\)\\([0-9]\\):" nil t)
(setq screen (match-string 2))))
(when (re-search-forward "^\\(.*\\) connected" nil t)
(setq output (match-string 1)))
(list screen output))))
(defun helm-xrandr-screen ()
"Return current X screen number."
(car (helm-xrandr-info)))
(defun helm-xrandr-output ()
"Return current X display name."
(cadr (helm-xrandr-info)))
(defvar helm-source-xrandr-change-resolution
(helm-build-sync-source "Change Resolution"
:candidates
(lambda ()
(with-temp-buffer
(call-process "xrandr" nil (current-buffer) nil
"--screen" (helm-xrandr-screen) "-q")
(goto-char 1)
(cl-loop while (re-search-forward " \\([0-9]+x[0-9]+\\)" nil t)
for mode = (match-string 1)
unless (member mode modes)
collect mode into modes
finally return modes)))
:action
(helm-make-actions "Change Resolution"
(lambda (mode)
(call-process "xrandr" nil nil nil
"--screen" (helm-xrandr-screen)
"--output" (helm-xrandr-output)
"--mode" mode)))))
;;; Emacs process
;;
;;
(defvar helm-source-emacs-process
(helm-build-sync-source "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 (helm-make-actions "Kill Process"
(lambda (_elm)
(cl-loop for p in (helm-marked-candidates)
do (delete-process (get-process p)))))))
;;;###autoload
(defun helm-top ()
"Preconfigured `helm' for top command."
(interactive)
(add-hook 'helm-after-update-hook 'helm-top--skip-top-line)
(save-window-excursion
(unless helm-alive-p (delete-other-windows))
(unwind-protect
(helm :sources 'helm-source-top
:buffer "*helm top*" :full-frame t
:candidate-number-limit 9999
:preselect "^\\s-*[0-9]+"
:truncate-lines helm-show-action-window-other-window)
(remove-hook 'helm-after-update-hook 'helm-top--skip-top-line))))
;;;###autoload
(defun helm-list-emacs-process ()
"Preconfigured `helm' for emacs process."
(interactive)
(helm-other-buffer 'helm-source-emacs-process "*helm process*"))
;;;###autoload
(defun helm-xrandr-set ()
"Preconfigured helm for xrandr."
(interactive)
(helm :sources 'helm-source-xrandr-change-resolution
:buffer "*helm xrandr*"))
(provide 'helm-sys)
;; Local Variables:
;; byte-compile-warnings: (not obsolete)
;; coding: utf-8
;; indent-tabs-mode: nil
;; End:
;;; helm-sys.el ends here

View File

@@ -0,0 +1,345 @@
;;; helm-tags.el --- Helm for Etags. -*- lexical-binding: t -*-
;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Code:
(require 'cl-lib)
(require 'helm)
(require 'helm-help)
(require 'helm-utils)
(require 'helm-grep)
(defgroup helm-tags nil
"Tags related Applications and libraries for Helm."
:group 'helm)
(defcustom helm-etags-tag-file-name "TAGS"
"Etags tag file name."
:type 'string
:group 'helm-tags)
(defcustom helm-etags-tag-file-search-limit 10
"The limit level of directory to search tag file.
Don't search tag file deeply if outside this value."
:type 'number
:group 'helm-tags)
(defcustom helm-etags-match-part-only 'tag
"Allow choosing the tag part of CANDIDATE in `helm-source-etags-select'.
A tag looks like this:
filename: \(defun foo
You can choose matching against the tag part (i.e \"(defun foo\"),
or against the whole candidate (i.e \"(filename:5:(defun foo\")."
:type '(choice
(const :tag "Match only tag" tag)
(const :tag "Match all file+tag" all))
:group 'helm-tags)
(defcustom helm-etags-execute-action-at-once-if-one t
"Whether to jump straight to the selected tag if there's only
one match."
:type 'boolean
:group 'helm-tags)
(defgroup helm-tags-faces nil
"Customize the appearance of helm-tags faces."
:prefix "helm-"
:group 'helm-tags
:group 'helm-faces)
(defface helm-etags-file
'((t (:foreground "Lightgoldenrod4"
:underline t)))
"Face used to highlight etags filenames."
:group 'helm-tags-faces)
;;; Etags
;;
;;
(defun helm-etags-run-switch-other-window ()
"Run switch to other window action from `helm-source-etags-select'."
(interactive)
(with-helm-alive-p
(helm-exit-and-execute-action
(lambda (c)
(helm-etags-action-goto 'find-file-other-window c)))))
(put 'helm-etags-run-switch-other-window 'helm-only t)
(defun helm-etags-run-switch-other-frame ()
"Run switch to other frame action from `helm-source-etags-select'."
(interactive)
(with-helm-alive-p
(helm-exit-and-execute-action
(lambda (c)
(helm-etags-action-goto 'find-file-other-frame c)))))
(put 'helm-etags-run-switch-other-frame 'helm-only t)
(defvar helm-etags-map
(let ((map (make-sparse-keymap)))
(set-keymap-parent map helm-map)
(define-key map (kbd "M-<down>") 'helm-goto-next-file)
(define-key map (kbd "M-<up>") 'helm-goto-precedent-file)
(define-key map (kbd "C-c o") 'helm-etags-run-switch-other-window)
(define-key map (kbd "C-c C-o") 'helm-etags-run-switch-other-frame)
map)
"Keymap used in Etags.")
(defvar helm-etags-mtime-alist nil
"Store the last modification time of etags files here.")
(defvar helm-etags-cache (make-hash-table :test 'equal)
"Cache content of etags files used here for faster access.")
(defun helm-etags-get-tag-file (&optional directory)
"Return the path of etags file if found.
Lookes recursively in parents directorys for a
`helm-etags-tag-file-name' file."
;; Get tag file from `default-directory' or upper directory.
(let ((current-dir (helm-etags-find-tag-file-directory
(or directory default-directory))))
;; Return nil if not find tag file.
(when current-dir
(expand-file-name helm-etags-tag-file-name current-dir))))
(defun helm-etags-all-tag-files ()
"Return files from the following sources;
1) An automatically located file in the parent directories, by `helm-etags-get-tag-file'.
2) `tags-file-name', which is commonly set by `find-tag' command.
3) `tags-table-list' which is commonly set by `visit-tags-table' command."
(helm-fast-remove-dups
(delq nil
(append (list (helm-etags-get-tag-file)
tags-file-name)
tags-table-list))
:test 'equal))
(defun helm-etags-find-tag-file-directory (current-dir)
"Try to find the directory containing tag file.
If not found in CURRENT-DIR search in upper directory."
(let ((file-exists? (lambda (dir)
(let ((tag-path (expand-file-name
helm-etags-tag-file-name dir)))
(and (stringp tag-path)
(file-regular-p tag-path)
(file-readable-p tag-path))))))
(cl-loop with count = 0
until (funcall file-exists? current-dir)
;; Return nil if outside the value of
;; `helm-etags-tag-file-search-limit'.
if (= count helm-etags-tag-file-search-limit)
do (cl-return nil)
;; Or search upper directories.
else
do (cl-incf count)
(setq current-dir (expand-file-name (concat current-dir "../")))
finally return current-dir)))
(defun helm-etags-get-header-name (_x)
"Create header name for this helm etags session."
(concat "Etags in "
(with-helm-current-buffer
(helm-etags-get-tag-file))))
(defun helm-etags-create-buffer (file)
"Create the `helm-buffer' based on contents of etags tag FILE."
(let* (max
(split (with-temp-buffer
(insert-file-contents file)
(prog1
(split-string (buffer-string) "\n" 'omit-nulls)
(setq max (line-number-at-pos (point-max))))))
(progress-reporter (make-progress-reporter "Loading tag file..." 0 max)))
(cl-loop
with fname
with cand
for i in split for count from 0
for elm = (unless (string-match "^\x0c" i) ;; "^L"
(helm-aif (string-match "\177" i) ;; "^?"
(substring i 0 it)
i))
for linum = (when (string-match "[0-9]+,?[0-9]*$" i)
(car (split-string (match-string 0 i) ",")))
do (cond ((and elm (string-match "^\\([^,]+\\),[0-9]+$" elm))
(setq fname (propertize (match-string 1 elm)
'face 'helm-etags-file)))
(elm (setq cand (format "%s:%s:%s" fname linum elm)))
(t (setq cand nil)))
when cand do (progn
(insert (propertize (concat cand "\n") 'linum linum))
(progress-reporter-update progress-reporter count)))))
(defun helm-etags-init ()
"Feed `helm-buffer' using `helm-etags-cache' or tag file.
If no entry in cache, create one."
(let ((tagfiles (helm-etags-all-tag-files)))
(when tagfiles
(with-current-buffer (helm-candidate-buffer 'global)
(dolist (f tagfiles)
(helm-aif (gethash f helm-etags-cache)
;; An entry is present in cache, insert it.
(insert it)
;; No entry, create a new buffer using content of tag file (slower).
(helm-etags-create-buffer f)
;; Store content of buffer in cache.
(puthash f (buffer-string) helm-etags-cache)
;; Store or set the last modification of tag file.
(helm-aif (assoc f helm-etags-mtime-alist)
;; If an entry exists modify it.
(setcdr it (helm-etags-mtime f))
;; No entry create a new one.
(cl-pushnew (cons f (helm-etags-mtime f))
helm-etags-mtime-alist
:test 'equal))))))))
(defvar helm-source-etags-select nil
"Helm source for Etags.")
(defun helm-etags-build-source ()
(helm-build-in-buffer-source "Etags"
:header-name 'helm-etags-get-header-name
:init 'helm-etags-init
:get-line 'buffer-substring
:match-part (lambda (candidate)
;; Match only the tag part of CANDIDATE
;; and not the filename.
(cl-case helm-etags-match-part-only
(tag (cl-caddr (helm-grep-split-line candidate)))
(t candidate)))
:fuzzy-match helm-etags-fuzzy-match
:help-message 'helm-etags-help-message
:keymap helm-etags-map
:action '(("Go to tag" . (lambda (c)
(helm-etags-action-goto 'find-file c)))
("Go to tag in other window" . (lambda (c)
(helm-etags-action-goto
'find-file-other-window
c)))
("Go to tag in other frame" . (lambda (c)
(helm-etags-action-goto
'find-file-other-frame
c))))
:group 'helm-tags
:persistent-help "Go to line"
:persistent-action (lambda (candidate)
(helm-etags-action-goto 'find-file candidate)
(helm-highlight-current-line))))
(defcustom helm-etags-fuzzy-match nil
"Use fuzzy matching in `helm-etags-select'."
:group 'helm-tags
:type 'boolean
:set (lambda (var val)
(set var val)
(setq helm-source-etags-select
(helm-etags-build-source))))
(defvar find-tag-marker-ring)
(defsubst helm-etags--file-from-tag (fname)
(cl-loop for ext in
(cons "" (remove "" tags-compression-info-list))
for file = (concat fname ext)
when (file-exists-p file)
return file))
(defun helm-etags-action-goto (switcher candidate)
"Helm default action to jump to an etags entry in other window."
(require 'etags)
(deactivate-mark t)
(helm-log-run-hook 'helm-goto-line-before-hook)
(let* ((split (helm-grep-split-line candidate))
(fname (cl-loop for tagf being the hash-keys of helm-etags-cache
for f = (expand-file-name
(car split) (file-name-directory tagf))
;; Try to find an existing file, possibly compressed.
when (helm-etags--file-from-tag f)
return it))
(elm (cl-caddr split))
(linum (string-to-number (cadr split))))
(if (null fname)
(error "file %s not found" fname)
(ring-insert find-tag-marker-ring (point-marker))
(funcall switcher fname)
(helm-goto-line linum t)
(when (search-forward elm nil t)
(goto-char (match-beginning 0))))))
(defun helm-etags-mtime (file)
"Last modification time of etags tag FILE."
(cadr (nth 5 (file-attributes file))))
(defun helm-etags-file-modified-p (file)
"Check if tag FILE have been modified in this session.
If FILE is nil return nil."
(let ((last-modif (and file
(assoc-default file helm-etags-mtime-alist))))
(and last-modif
(/= last-modif (helm-etags-mtime file)))))
;;;###autoload
(defun helm-etags-select (reinit)
"Preconfigured helm for etags.
If called with a prefix argument REINIT
or if any of the tag files have been modified, reinitialize cache.
This function aggregates three sources of tag files:
1) An automatically located file in the parent directories,
by `helm-etags-get-tag-file'.
2) `tags-file-name', which is commonly set by `find-tag' command.
3) `tags-table-list' which is commonly set by `visit-tags-table' command."
(interactive "P")
(let ((tag-files (helm-etags-all-tag-files))
(helm-execute-action-at-once-if-one
helm-etags-execute-action-at-once-if-one)
(str (if (region-active-p)
(buffer-substring-no-properties
(region-beginning) (region-end))
(thing-at-point 'symbol))))
(if (cl-notany 'file-exists-p tag-files)
(message "Error: No tag file found.\
Create with etags shell command, or visit with `find-tag' or `visit-tags-table'.")
(cl-loop for k being the hash-keys of helm-etags-cache
unless (member k tag-files)
do (remhash k helm-etags-cache))
(mapc (lambda (f)
(when (or (equal reinit '(4))
(and helm-etags-mtime-alist
(helm-etags-file-modified-p f)))
(remhash f helm-etags-cache)))
tag-files)
(unless helm-source-etags-select
(setq helm-source-etags-select
(helm-etags-build-source)))
(helm :sources 'helm-source-etags-select
:keymap helm-etags-map
:default (if helm-etags-fuzzy-match
str
(list (concat "\\_<" str "\\_>") str))
:buffer "*helm etags*"))))
(provide 'helm-tags)
;; Local Variables:
;; byte-compile-warnings: (not obsolete)
;; coding: utf-8
;; indent-tabs-mode: nil
;; End:
;;; helm-tags.el ends here

View File

@@ -0,0 +1,286 @@
;;; helm-types.el --- Helm types classes and methods. -*- lexical-binding: t -*-
;; Copyright (C) 2015 ~ 2018 Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; Author: Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; URL: http://github.com/emacs-helm/helm
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Code:
(require 'cl-lib)
(require 'eieio)
;; Files
(defclass helm-type-file (helm-source) ()
"A class to define helm type file.")
(defmethod helm-source-get-action-from-type ((object helm-type-file))
(slot-value object 'action))
(defun helm-actions-from-type-file ()
(let ((source (make-instance 'helm-type-file)))
(helm--setup-source source)
(helm-source-get-action-from-type source)))
(defcustom helm-type-file-actions
(helm-make-actions
"Find file" 'helm-find-many-files
"Find file as root" 'helm-find-file-as-root
"Find file other window" 'helm-find-files-other-window
"Find file other frame" 'find-file-other-frame
"Open dired in file's directory" 'helm-open-dired
"Attach file(s) to mail buffer `C-c C-a'" 'helm-ff-mail-attach-files
"Marked files in dired" 'helm-marked-files-in-dired
"Grep File(s) `C-u recurse'" 'helm-find-files-grep
"Zgrep File(s) `C-u Recurse'" 'helm-ff-zgrep
"Pdfgrep File(s)" 'helm-ff-pdfgrep
"Insert as org link" 'helm-files-insert-as-org-link
"Checksum File" 'helm-ff-checksum
"Ediff File" 'helm-find-files-ediff-files
"Ediff Merge File" 'helm-find-files-ediff-merge-files
"Etags `M-., C-u reload tag file'" 'helm-ff-etags-select
"View file" 'view-file
"Insert file" 'insert-file
"Add marked files to file-cache" 'helm-ff-cache-add-file
"Delete file(s)" 'helm-ff-delete-files
"Copy file(s) `M-C, C-u to follow'" 'helm-find-files-copy
"Rename file(s) `M-R, C-u to follow'" 'helm-find-files-rename
"Symlink files(s) `M-S, C-u to follow'" 'helm-find-files-symlink
"Relsymlink file(s) `C-u to follow'" 'helm-find-files-relsymlink
"Hardlink file(s) `M-H, C-u to follow'" 'helm-find-files-hardlink
"Open file externally (C-u to choose)" 'helm-open-file-externally
"Open file with default tool" 'helm-open-file-with-default-tool
"Find file in hex dump" 'hexl-find-file)
"Default actions for type files."
:group 'helm-files
:type '(alist :key-type string :value-type function))
(defmethod helm--setup-source :primary ((_source helm-type-file)))
(defmethod helm--setup-source :before ((source helm-type-file))
(setf (slot-value source 'action) 'helm-type-file-actions)
(setf (slot-value source 'persistent-help) "Show this file")
(setf (slot-value source 'action-transformer)
'(helm-transform-file-load-el
helm-transform-file-browse-url
helm-transform-file-cache))
(setf (slot-value source 'candidate-transformer)
'(helm-skip-boring-files
helm-w32-pathname-transformer))
(setf (slot-value source 'filtered-candidate-transformer)
'helm-highlight-files)
(setf (slot-value source 'help-message) 'helm-generic-file-help-message)
(setf (slot-value source 'mode-line) (list "File(s)" helm-mode-line-string))
(setf (slot-value source 'keymap) helm-generic-files-map)
(setf (slot-value source 'group) 'helm-files))
;; Bookmarks
(defclass helm-type-bookmark (helm-source) ()
"A class to define type bookmarks.")
(defcustom helm-type-bookmark-actions
(helm-make-actions
"Jump to bookmark" 'helm-bookmark-jump
"Jump to BM other window" 'helm-bookmark-jump-other-window
"Bookmark edit annotation" 'bookmark-edit-annotation
"Bookmark show annotation" 'bookmark-show-annotation
"Delete bookmark(s)" 'helm-delete-marked-bookmarks
"Edit Bookmark" 'helm-bookmark-edit-bookmark
"Rename bookmark" 'helm-bookmark-rename
"Relocate bookmark" 'bookmark-relocate)
"Default actions for type bookmarks."
:group 'helm-bookmark
:type '(alist :key-type string
:value-type function))
(defmethod helm-source-get-action-from-type ((object helm-type-bookmark))
(slot-value object 'action))
(defmethod helm--setup-source :primary ((_source helm-type-bookmark)))
(defmethod helm--setup-source :before ((source helm-type-bookmark))
(setf (slot-value source 'action) 'helm-type-bookmark-actions)
(setf (slot-value source 'keymap) helm-bookmark-map)
(setf (slot-value source 'mode-line) (list "Bookmark(s)" helm-mode-line-string))
(setf (slot-value source 'help-message) 'helm-bookmark-help-message)
(setf (slot-value source 'migemo) t)
(setf (slot-value source 'follow) 'never)
(setf (slot-value source 'group) 'helm-bookmark))
;; Buffers
(defclass helm-type-buffer (helm-source) ()
"A class to define type buffer.")
(defcustom helm-type-buffer-actions
(helm-make-actions
"Switch to buffer(s)" 'helm-buffer-switch-buffers
"Switch to buffer(s) other window `C-c o'"
'helm-buffer-switch-buffers-other-window
"Switch to buffer other frame `C-c C-o'"
'switch-to-buffer-other-frame
"Browse project from buffer"
'helm-buffers-browse-project
"Query replace regexp `C-M-%'"
'helm-buffer-query-replace-regexp
"Query replace `M-%'" 'helm-buffer-query-replace
"View buffer" 'view-buffer
"Display buffer" 'display-buffer
"Rename buffer" 'helm-buffers-rename-buffer
"Grep buffers `M-g s' (C-u grep all buffers)"
'helm-zgrep-buffers
"Multi occur buffer(s) `C-s'" 'helm-multi-occur-as-action
"Revert buffer(s) `M-U'" 'helm-revert-marked-buffers
"Insert buffer" 'insert-buffer
"Kill buffer(s) `M-D'" 'helm-kill-marked-buffers
"Diff with file `C-='" 'diff-buffer-with-file
"Ediff Marked buffers `C-c ='" 'helm-ediff-marked-buffers
"Ediff Merge marked buffers `M-='"
(lambda (candidate)
(helm-ediff-marked-buffers candidate t)))
"Default actions for type buffers."
:group 'helm-buffers
:type '(alist :key-type string :value-type function))
(defmethod helm-source-get-action-from-type ((object helm-type-buffer))
(slot-value object 'action))
(defmethod helm--setup-source :primary ((_source helm-type-buffer)))
(defmethod helm--setup-source :before ((source helm-type-buffer))
(setf (slot-value source 'action) 'helm-type-buffer-actions)
(setf (slot-value source 'persistent-help) "Show this buffer")
(setf (slot-value source 'mode-line) (list "Buffer(s)" helm-mode-line-string))
(setf (slot-value source 'filtered-candidate-transformer)
'(helm-skip-boring-buffers
helm-buffers-sort-transformer
helm-highlight-buffers))
(setf (slot-value source 'group) 'helm-buffers))
;; Functions
(defclass helm-type-function (helm-source) ()
"A class to define helm type function.")
(defcustom helm-type-function-actions
(helm-make-actions
"Describe command" 'describe-function
"Add command to kill ring" 'helm-kill-new
"Go to command's definition" 'find-function
"Debug on entry" 'debug-on-entry
"Cancel debug on entry" 'cancel-debug-on-entry
"Trace function" 'trace-function
"Trace function (background)" 'trace-function-background
"Untrace function" 'untrace-function)
"Default actions for type functions."
:group 'helm-elisp
:type '(alist :key-type string :value-type function))
(defmethod helm-source-get-action-from-type ((object helm-type-function))
(slot-value object 'action))
(defun helm-actions-from-type-function ()
(let ((source (make-instance 'helm-type-function)))
(helm--setup-source source)
(helm-source-get-action-from-type source)))
(defmethod helm--setup-source :primary ((_source helm-type-function)))
(defmethod helm--setup-source :before ((source helm-type-function))
(setf (slot-value source 'action) 'helm-type-function-actions)
(setf (slot-value source 'action-transformer)
'helm-transform-function-call-interactively)
(setf (slot-value source 'candidate-transformer)
'helm-mark-interactive-functions)
(setf (slot-value source 'coerce) 'helm-symbolify))
;; Commands
(defclass helm-type-command (helm-source) ()
"A class to define helm type command.")
(defun helm-actions-from-type-command ()
(let ((source (make-instance 'helm-type-command)))
(helm--setup-source source)
(helm-source-get-action-from-type source)))
(defcustom helm-type-command-actions
(append (helm-make-actions
"Call interactively" 'helm-call-interactively)
(helm-actions-from-type-function))
"Default actions for type command."
:group 'helm-command
:type '(alist :key-type string :value-type function))
(defmethod helm--setup-source :primary ((_source helm-type-command)))
(defmethod helm--setup-source :before ((source helm-type-command))
(setf (slot-value source 'action) 'helm-type-command-actions)
(setf (slot-value source 'coerce) 'helm-symbolify)
(setf (slot-value source 'persistent-action) 'describe-function)
(setf (slot-value source 'group) 'helm-command))
;; Timers
(defclass helm-type-timers (helm-source) ()
"A class to define helm type timers.")
(defcustom helm-type-timers-actions
'(("Cancel Timer" . (lambda (_timer)
(let ((mkd (helm-marked-candidates)))
(cl-loop for timer in mkd
do (cancel-timer timer)))))
("Describe Function" . (lambda (tm)
(describe-function (timer--function tm))))
("Find Function" . (lambda (tm)
(helm-aif (timer--function tm)
(if (byte-code-function-p it)
(message "Can't find anonymous function `%s'" it)
(find-function it))))))
"Default actions for type timers."
:group 'helm-elisp
:type '(alist :key-type string :value-type function))
(defmethod helm--setup-source :primary ((_source helm-type-timers)))
(defmethod helm--setup-source :before ((source helm-type-timers))
(setf (slot-value source 'action) 'helm-type-timers-actions)
(setf (slot-value source 'persistent-action)
(lambda (tm)
(describe-function (timer--function tm))))
(setf (slot-value source 'persistent-help) "Describe Function")
(setf (slot-value source 'group) 'helm-elisp))
;; Builders.
(defun helm-build-type-file ()
(helm-make-type 'helm-type-file))
(defun helm-build-type-function ()
(helm-make-type 'helm-type-function))
(defun helm-build-type-command ()
(helm-make-type 'helm-type-command))
(provide 'helm-types)
;; Local Variables:
;; byte-compile-warnings: (not obsolete)
;; coding: utf-8
;; indent-tabs-mode: nil
;; End:
;;; helm-types.el ends here

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,128 @@
;;; helm-x-files.el --- helm auxiliary functions and sources. -*- lexical-binding: t -*-
;; Copyright (C) 2012 ~ 2018 Thierry Volpiatto <thierry.volpiatto@gmail.com>
;; This program is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; This program is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with this program. If not, see <http://www.gnu.org/licenses/>.
;;; Code:
(require 'helm-for-files)
;;; 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