From: Ken Manheimer Date: Thu, 11 Feb 2016 06:19:39 +0000 (-0500) Subject: multishell - method to conclude minibuffer interaction from multishell-list X-Git-Url: https://code.delx.au/gnu-emacs-elpa/commitdiff_plain/fd514d34466844216e754ad3c16a9ce33db7f8df multishell - method to conclude minibuffer interaction from multishell-list Use throw-catch facility for non-local minibuffer exit. Originally implemented for invoking and passing control to the minibuffer-list from the minibuffer, it proves to be much more tidy than the non-local minibuffer exit provisions in, eg, buff-menu. For now, the most crucial binding in this context is the mouse-click. The keyboard cases are also handled, but generally switching the *Completions* buffer to the target one. --- diff --git a/multishell-list.el b/multishell-list.el index 496682080..773b799fe 100644 --- a/multishell-list.el +++ b/multishell-list.el @@ -33,7 +33,7 @@ pop to the buffer but don't change its run state." (if arg (pop-to-buffer (multishell-bracket (multishell-name-from-entry entry))) - (multishell-pop-to-shell nil entry)) + (multishell-list-selected entry t)) (with-current-buffer list-buffer (revert-buffer) (multishell-list-goto-item-by-entry entry)))) @@ -44,7 +44,7 @@ pop to the buffer but don't change its run state." (let ((list-buffer (current-buffer)) (entry (tabulated-list-get-id))) (message "%s <==" (multishell-name-from-entry entry)) - (multishell-pop-to-shell '(16) entry) + (multishell-list-selected entry t t) (with-current-buffer list-buffer (revert-buffer) (multishell-list-goto-item-by-entry entry)))) @@ -61,7 +61,7 @@ switch to the buffer but don't activate (or deactivate) it it." (if arg (switch-to-buffer (multishell-bracket (multishell-name-from-entry entry))) - (multishell-pop-to-shell nil entry 'here)) + (multishell-list-selected entry nil)) (with-current-buffer list-buffer (revert-buffer)))) @@ -105,7 +105,7 @@ starting it if it's not already going." (with-current-buffer buffer (rename-buffer (multishell-bracket revised-name))))) (when arg - (multishell-pop-to-shell nil revised-name)) + (multishell-list-selected revised-name t)) (with-current-buffer list-buffer (revert-buffer) (multishell-list-goto-item-by-entry revised)))) @@ -131,7 +131,24 @@ The already existing original entry is left untouched." (revert-buffer) (multishell-list-goto-item-by-entry new) (when arg - (multishell-pop-to-shell nil new-name))))) + (multishell-list-selected new-name t))))) + +(defun multishell-list-mouse-select (event) + "Select the shell whose line is clicked." + (interactive "e") + (select-window (posn-window (event-end event))) + (let ((entry (tabulated-list-get-id (posn-point (event-end event))))) + (multishell-list-selected entry nil))) + +(defun multishell-list-selected (entry pop &optional set-primary) + "Select multishell ENTRY, popping to window if POP is non-nil. + +Optional arg SET-PRIMARY non-nil sets `multishell-primary-name' to entry. + +Provide for concluding minibuffer interaction if we're in completing mode." + (if multishell-completing + (throw 'multishell-minibuffer-exit entry) + (multishell-pop-to-shell (and set-primary '(16)) entry (not pop)))) (defun multishell-list-placeholder (value default) "Return VALUE if non-empty string, else DEFAULT." @@ -191,13 +208,6 @@ The already existing original entry is left untouched." 'font-lock-face 'multishell-list-name 'mouse-face 'highlight)) -(defun multishell-list-mouse-select (event) - "Select the shell whose line is clicked." - (interactive "e") - (select-window (posn-window (event-end event))) - (let ((entry (tabulated-list-get-id (posn-point (event-end event))))) - (multishell-pop-to-shell nil entry 'here))) - (defvar multishell-list-mode-map (let ((map (make-sparse-keymap))) (set-keymap-parent map tabulated-list-mode-map) @@ -236,28 +246,44 @@ Initial sort is from most to least recently used: (tabulated-list-init-header)) ;;;###autoload -(defun multishell-list (&optional buffer-name) +(defun multishell-list (&optional completing) "Edit your current and historic list of shell buffers. -Optional BUFFER-NAME specifies buffer to use for list. When a -buffer is specified, we do not select the buffer, just fill -it. Otherwise, we pop to the *Shells* buffer. +If optional COMPLETING is nil, we present the full +`multishell-history' list in a popped buffer named '*Shells*'. In the buffer, hit ? or h for a list of commands. -You can get to the shell listing manager by recursively invoking +When optional COMPLETING is non-nil, it must be a list of +multishell-history completion candidate entries, as provided by +`completing-read'. Then we present the list as a part of +minibuffer completion. + +You can get to the shells listing by recursively invoking \\[multishell-pop-to-shell] at the `multishell-pop-to-shell' `universal-argument' prompts." (interactive) (let ((from-entry (car (multishell-history-entries (multishell-unbracket (buffer-name (current-buffer)))))) - (buffer (get-buffer-create (or buffer-name "*Shells*")))) - (if buffer-name + (buffer (get-buffer-create (if completing + "*Completions*" + "*Shells*")))) + (if completing (set-buffer buffer) (pop-to-buffer buffer)) (multishell-list-mode) - (tabulated-list-print) + (progv + ;; Temporarily assign multishell-history only when completing: + (when completing '(multishell-history)) + (when completing (list (mapcar 'substring-no-properties completing))) + (tabulated-list-print)) + (when completing + ;; XXX Do proper completion prep. + ;; - looks like stuff in minibuffer.el.gz is too hairy w/too little gain. + ;; - Add a buffer-change hook that throws a 'multishell-completion-done, + ;; and revise the catch in multishell-pop-to-shell + ) (when from-entry (multishell-list-goto-item-by-entry from-entry)))) diff --git a/multishell.el b/multishell.el index a0783ee5b..429d914b4 100644 --- a/multishell.el +++ b/multishell.el @@ -269,6 +269,10 @@ one emacs session to be resumed at the next, customize `savehist-additional-variables' to include the `multishell-primary-name'.") +(defvar multishell-completing nil + "Internal use, conveying whether or not we're in the midst of a multishell +completing-read.") + ;; Multiple entries happen because completion also adds name to history. (defun multishell-register-name-to-path (name path) "Add or replace entry associating NAME with PATH in `multishell-history'. @@ -430,11 +434,12 @@ customize the savehist group to activate savehist." (let ((token '(token))) (if (window-minibuffer-p) - (throw 'multishell-do-list token) - (if (equal token - (catch 'multishell-do-list - (multishell-pop-to-shell-worker arg name here))) - (multishell-list))))) + (throw 'multishell-minibuffer-exit token) + (let ((got (catch 'multishell-minibuffer-exit + (multishell-pop-to-shell-worker arg name here)))) + (if (equal token got) + (multishell-list) + (multishell-pop-to-shell-worker nil got here)))))) (defun multishell-pop-to-shell-worker (&optional arg name here) "Do real work of `multishell-pop-to-shell', which see." @@ -605,11 +610,6 @@ completions." (append multishell-history active-names) multishell-history))) -(defun multishell-display-completion-list (completions) - "Present COMPLETIONS using multishell-list for `display-completion-list'." - (let ((multishell-history (mapcar 'substring-no-properties completions))) - (multishell-list "*Completions*"))) - (defun multishell-read-unbracketed-entry (prompt &optional initial no-record) "PROMPT for shell buffer name, sans asterisks. @@ -628,18 +628,19 @@ Return what's provided, if anything, else nil." ;; minibuffer-completion-help. `cl-letf' for dynamic ;; binding; cl-flet's lexical doesn't do what's needed. (((symbol-function 'display-completion-list) - #'multishell-display-completion-list)) - (completing-read prompt - ;; COLLECTION: - (reverse candidates) - ;; PREDICATE: - nil - ;; REQUIRE-MATCH: - 'confirm - ;; INITIAL-INPUT - initial - ;; HIST: - 'multishell-history)))) + #'multishell-list)) + (let ((multishell-completing t)) + (completing-read prompt + ;; COLLECTION: + (reverse candidates) + ;; PREDICATE: + nil + ;; REQUIRE-MATCH: + 'confirm + ;; INITIAL-INPUT + initial + ;; HIST: + 'multishell-history))))) (when no-record (setq multishell-history was-multishell-history)) (if (not (string= got "")) @@ -698,7 +699,7 @@ and path nil if none is resolved." (when (and (derived-mode-p 'shell-mode) (file-remote-p path)) ;; Returning to disconnected remote shell - do some tidying. - ;; (Prevents the "Args out of range" failure when reconnecting.) + ;; Prevents an "Args out of range" failure when reconnecting. (tramp-cleanup-connection (tramp-dissect-file-name default-directory 'noexpand) 'keep-debug 'keep-password))