summaryrefslogtreecommitdiff
path: root/helm-eshell.el
diff options
context:
space:
mode:
authorThierry Volpiatto <thierry.volpiatto@gmail.com>2012-03-22 12:58:42 +0100
committerThierry Volpiatto <thierry.volpiatto@gmail.com>2012-03-22 12:58:42 +0100
commit00184513fe985b05965ce51ebf4156c6815e783e (patch)
tree9d9a2682d26270df10c3834893e6976b3a545ec2 /helm-eshell.el
parent7946b64e3319eb666db7e6b5304d38365c67bf45 (diff)
* helm-config.el: Move pcomplete and eshell hist to helm-eshell.el
* helm-eshell.el: new file.
Diffstat (limited to 'helm-eshell.el')
-rw-r--r--helm-eshell.el128
1 files changed, 128 insertions, 0 deletions
diff --git a/helm-eshell.el b/helm-eshell.el
new file mode 100644
index 00000000..bd38781f
--- /dev/null
+++ b/helm-eshell.el
@@ -0,0 +1,128 @@
+;;; helm-eshell.el --- pcomplete and eshell completion for helm.
+
+;; Copyright (C) 2012 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:
+(eval-when-compile (require 'cl))
+(require 'helm)
+(require 'helm-elisp)
+(require 'helm-regexp)
+
+;; Enable like this in .emacs:
+;;
+;; (add-hook 'eshell-mode-hook
+;; #'(lambda ()
+;; (define-key eshell-mode-map [remap pcomplete] 'helm-esh-pcomplete)))
+;;
+
+(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-c-source-esh
+ '((name . "Eshell completions")
+ (init . (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 . helm-esh-get-candidates)
+ (action . helm-ec-insert))
+ "Helm source for Eshell completion.")
+
+;; Internal.
+(defvar helm-ec-target "")
+(defun helm-ec-insert (candidate)
+ "Replace text at point with CANDIDATE.
+The function that call this should set `helm-ec-target' to thing at point."
+ (let ((pt (point)))
+ (when (and helm-ec-target
+ (search-backward helm-ec-target nil t)
+ (string= (buffer-substring (point) pt) helm-ec-target))
+ (delete-region (point) pt)))
+ (insert (helm-quote-whitespace candidate)))
+
+(defun helm-esh-get-candidates ()
+ "Get candidates for eshell completion using `pcomplete'."
+ (catch 'pcompleted
+ (let* ((pcomplete-stub)
+ pcomplete-seen pcomplete-norm-func
+ pcomplete-args pcomplete-last pcomplete-index
+ (pcomplete-autolist pcomplete-autolist)
+ (pcomplete-suffix-list pcomplete-suffix-list))
+ (with-helm-current-buffer
+ (loop with table = (pcomplete-completions)
+ with entry = (condition-case nil
+ ;; On Emacs24 `try-completion' return
+ ;; pattern when more than one result.
+ ;; Otherwise Emacs23 return nil, which
+ ;; is wrong, in this case use pattern
+ ;; to behave like Emacs24.
+ (or (try-completion helm-pattern
+ (pcomplete-entries))
+ helm-pattern)
+ ;; In Emacs23 `pcomplete-entries' may fail
+ ;; with error, so try this instead.
+ (error
+ nil
+ (let ((fc (car (last
+ (pcomplete-parse-arguments)))))
+ ;; Check if last arg require fname completion.
+ (and (file-name-directory fc) fc))))
+ for i in (all-completions pcomplete-stub table)
+ for file-cand = (and entry
+ (if (file-remote-p i) i
+ (expand-file-name
+ i (file-name-directory entry))))
+ if (and file-cand (or (file-remote-p file-cand)
+ (file-exists-p file-cand)))
+ collect file-cand into ls
+ else collect i into ls
+ finally return
+ (if (and entry (not (string= entry "")) (file-exists-p entry))
+ (append (list (expand-file-name entry default-directory)) ls)
+ ls))))))
+
+;;; Eshell history.
+;;
+;;
+(defvar helm-c-source-eshell-history
+ `((name . "Eshell history")
+ (init . (lambda ()
+ (let (eshell-hist-ignoredups)
+ ;; Write the content's of ring to file.
+ (eshell-write-history eshell-history-file-name t)
+ (with-current-buffer (helm-candidate-buffer 'global)
+ (insert-file-contents eshell-history-file-name)))
+ ;; Same comment as in `helm-c-source-esh'
+ (remove-hook 'minibuffer-setup-hook 'eshell-mode)))
+ (candidates-in-buffer)
+ (keymap . ,helm-eshell-history-map)
+ (filtered-candidate-transformer . (lambda (candidates sources)
+ (reverse candidates)))
+ (candidate-number-limit . 9999)
+ (action . (lambda (candidate)
+ (eshell-kill-input)
+ (insert candidate))))
+ "Helm source for Eshell history.")
+
+(provide 'helm-eshell)
+
+;;; helm-eshell ends here