Helm/Eshell: Refactor helm-eshell-prompts

master
Pierre Neidhardt 2017-10-30 10:58:12 +01:00
parent 1123dee34b
commit c139b87df4
1 changed files with 63 additions and 76 deletions

View File

@ -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)