From c139b87df46fe6960b81707b736622c755f14c0c Mon Sep 17 00:00:00 2001 From: Pierre Neidhardt Date: Mon, 30 Oct 2017 10:58:12 +0100 Subject: [PATCH] Helm/Eshell: Refactor helm-eshell-prompts --- .emacs.d/lisp/package-helm-eshell.el | 139 ++++++++++++--------------- 1 file changed, 63 insertions(+), 76 deletions(-) diff --git a/.emacs.d/lisp/package-helm-eshell.el b/.emacs.d/lisp/package-helm-eshell.el index 82fdc6e4..defae923 100644 --- a/.emacs.d/lisp/package-helm-eshell.el +++ b/.emacs.d/lisp/package-helm-eshell.el @@ -1,11 +1,8 @@ ;;; TODO: Commit upstream. -;;; TODO: defvar for sources -;;; TODO: Support multiline prompts? -;;; TODO: Use candidate transformer and factor list function. -;;; TODO: Add action to yank prompt, output (prompt+output?) -;;; TODO: Reverse output. +;;; TODO: defvar for sources? +;;; TODO: Support multiline prompts? Probably hard since there are few means to know where output starts. -(defface helm-eshell-prompts-promptno +(defface helm-eshell-prompts-promptidx '((t (:foreground "cyan"))) "Face used to highlight Eshell prompt index." :group 'helm-eshell-faces) @@ -15,84 +12,73 @@ "Face used to highlight Eshell buffer name." :group 'helm-eshell-faces) -(defcustom helm-eshell-prompts-max-length 400 - "Max number of chars displayed per candidate in the Eshell prompt browser. -When t, don't truncate candidate, show all. -By default it is approximatively the number of bytes contained in five lines -of 80 single-byte characters each i.e 80*5. -Note that if you set this to nil, multiline will be disabled, i.e. there -will not be separators between candidates anymore." - :type '(choice (const :tag "Disabled" t) - (integer :tag "Max candidate offset")) - :group 'helm-eshell) - -(defcustom helm-eshell-prompts-promptno-p t +(defcustom helm-eshell-prompts-promptidx-p t "Show prompt number." :group 'helm-eshell :type 'boolean) -(defun helm-eshell-prompts-list () - "Return an alist of (prompt . pos)." - (let (list) - (save-excursion - (goto-char (point-min)) - (let ((promptno 1)) - (while (not (eobp)) - (eshell-next-prompt 1) - (let ((prompt (buffer-substring-no-properties (point) (line-end-position)))) - (setq list (cons `(,(if helm-eshell-prompts-promptno-p - (format "%s:%s" - (propertize (number-to-string promptno) 'face 'helm-eshell-prompts-promptno) - prompt) - prompt) - . ,(point)) - list) - promptno (1+ promptno)))))) - list)) +(defun helm-eshell-prompts-list (&optional buffer) + "List the prompts in Eshell BUFFER. + +Return a list of (\"prompt\" (point) (buffer-name) prompt-index)). +If BUFFER is nil, use current buffer." + (let ((buffer (or buffer (current-buffer))) + list) + (with-current-buffer buffer + (when (eq major-mode 'eshell-mode) + (save-excursion + (goto-char (point-min)) + (let ((promptno 1)) + (while (not (eobp)) + (eshell-next-prompt 1) + (setq list (cons (list (buffer-substring-no-properties (point) (line-end-position)) + (point) + (buffer-name) + (if helm-eshell-prompts-promptidx-p promptno)) + list) + promptno (1+ promptno))))))) + (nreverse list))) (defun helm-eshell-prompts-list-all () - "Return an alist of (\"buffer-name:prompt\" . (buffer . pos))." + "List the prompts of all Eshell buffers. +See `helm-eshell-prompts-list'." (let (list) (dolist (b (buffer-list)) - (with-current-buffer b - (when (eq major-mode 'eshell-mode) - (save-excursion - (goto-char (point-min)) - (let ((buffer-name (propertize (buffer-name) 'face 'helm-eshell-prompts-buffer-name)) - (promptno 1)) - (while (not (eobp)) - (eshell-next-prompt 1) - (setq list (cons `(,(format "%s:%s:%s" - buffer-name - (propertize (number-to-string promptno) 'face 'helm-eshell-prompts-promptno) - (buffer-substring-no-properties (point) (line-end-position))) - . (,b . ,(point))) - list)) - (setq promptno (1+ promptno)))))))) + (setq list (append (helm-eshell-prompts-list b) list))) list)) +(defun helm-eshell-prompts-transformer (candidates &optional all) + (dolist (c candidates) + (setcar c + (concat + (when all + (concat (propertize (nth 2 c) 'face 'helm-eshell-prompts-buffer-name) ":")) + (when helm-eshell-prompts-promptidx-p + (concat (propertize (number-to-string (nth 3 c)) 'face 'helm-eshell-prompts-promptidx) ":")) + (car c)))) + candidates) + +(defun helm-eshell-prompts-all-transformer (candidates &optional all) + (helm-eshell-prompts-transformer candidates t)) + (defun helm-eshell-prompts-goto (candidate) - (goto-char candidate)) + (when (nth 1 candidate) + (switch-to-buffer (nth 1 candidate))) + (goto-char (car candidate))) -;; TODO: Merge goto and goto-buffer, check for buffer existence in candidate. -(defun helm-eshell-prompts-goto-buffer (candidate) - ;; (if (alist-get ...)... - (switch-to-buffer (car candidate)) - (goto-char (cdr candidate))) +(defun helm-eshell-prompts-goto-other-window (candidate) + (switch-to-buffer-other-window (cdr candidate)) + (goto-char (car candidate))) -(defun helm-eshell-prompts-goto-buffer-other-window (candidate) - (switch-to-buffer-other-window (car candidate)) - (goto-char (cdr candidate))) - -(defun helm-eshell-prompts-goto-buffer-other-window (candidate) - (switch-to-buffer-other-frame (car candidate)) - (goto-char (cdr candidate))) +(defun helm-eshell-prompts-goto-other-frame (candidate) + (switch-to-buffer-other-frame (cdr candidate)) + (goto-char (car candidate))) (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-goto-all-prompt-other-window) - (define-key map (kbd "C-c C-o") 'helm-eshell-goto-all-prompt-other-frame) + (define-key map (kbd "C-c o") 'helm-eshell-prompts-goto-other-window) + (define-key map (kbd "C-c C-o") 'helm-eshell-prompts-goto-other-frame) map) "Keymap for `helm-eshell-prompt-all'.") @@ -103,13 +89,11 @@ will not be separators between candidates anymore." (if (eq major-mode 'eshell-mode) (helm :sources (helm-build-sync-source "Eshell prompts" - ;; :init (lambda () - ;; (helm-attrset 'multiline helm-eshell-prompts-max-length)) :candidates (helm-eshell-prompts-list) + :candidate-transformer 'helm-eshell-prompts-transformer :action '(("Go to prompt" . helm-eshell-prompts-goto)) - ;; :multiline 'helm-eshell-prompts-max-length) ) - :buffer "*helm-eshell-prompts*") + :buffer "*helm Eshell prompts*") (message "Current buffer is not an Eshell buffer"))) ;;;###autoload @@ -119,11 +103,14 @@ will not be separators between candidates anymore." (helm :sources (helm-build-sync-source "All Eshell prompts" :candidates (helm-eshell-prompts-list-all) - :action '(("Go to prompt" . helm-eshell-prompts-goto-buffer) - ("Go to prompt in other window `C-c o`" . helm-eshell-prompts-goto-buffer-other-window) - ("Go to prompt in other frame `C-c C-o`" . helm-eshell-prompts-goto-buffer-other-frame))) - :buffer "*helm-eshell-all-prompts*")) + :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))) + :buffer "*helm Eshell all prompts*")) -(add-to-list 'helm-source-names-using-follow "helm-eshell-prompts") +;;; Custom +(add-to-list 'helm-source-names-using-follow "Eshell prompts") +(add-to-list 'helm-source-names-using-follow "All Eshell prompts") (provide 'package-helm-eshell)