]> code.delx.au - gnu-emacs-elpa/blobdiff - packages/multishell/multishell.el
Fix some quoting problems in doc strings
[gnu-emacs-elpa] / packages / multishell / multishell.el
index 8d19a051096c6b723e87f64fb16e912f21e7d8db..54d04367b62373390e10c9bfcf0422f15eb88726 100644 (file)
@@ -1,9 +1,9 @@
-;;; multishell.el --- facilitate multiple local and remote shell buffers
+;;; multishell.el --- Easily use multiple shell buffers, local and remote.
 
 ;; Copyright (C) 1999-2016 Free Software Foundation, Inc.
 
 ;; Author: Ken Manheimer <ken.manheimer@gmail.com>
-;; Version: 1.1.3
+;; Version: 1.1.5
 ;; Created: 1999 -- first public availability
 ;; Keywords: processes
 ;; URL: https://github.com/kenmanheimer/EmacsMultishell
 ;;
 ;; Change Log:
 ;;
+;; * 2016-02-11 1.1.5 Ken Manheimer:
+;;   - Rectify multishell list sorting to preserve recentness
+;;   - Increment the actual multishell-version setting, neglected for 1.1.4.
+;; * 2016-02-11 1.1.4 Ken Manheimer:
+;;   - hookup multishell-list as completion help buffer.
+;;     Mouse and keyboard selections from help listing properly exits
+;;     minibuffer.
 ;; * 2016-02-09 1.1.3 Ken Manheimer:
 ;;   multishell-list:
 ;;   - add some handy operations, like cloning new entry from existing
 ;;
 ;; TODO and Known Issues:
 ;;
-;; * Add mouse actions - buttons - to multishell-list entries
-;;   - see buf-menu.el, eg Buffer-menu-mouse-select
-;; * Resolve multishell-list sort glitches:
-;;   - Fix config so multishell-list-revert-buffer-kludge is not needed
-;;   - Make multishell-list-edit-entry in-place, so changed entries recency
-;;     doesn't change.
-;;   - Fill in kill-buffer prompting gaps, eg if default live-process
-;;     prompts are inhibited.
 ;; * Add custom shell launch prep actions
 ;;   - for, eg, port knocking, interface activations
 ;;   - shell commands to execute when shell name or path matches a regexp
 ;;   - list of (regexp, which - name, path, or both, command)
-;; * Adapt multishell-list facilities for all-completions
-;;   - See info on minibuffer-completion-help, display-completion-list
 ;; * Investigate whether we can recognize and provide for failed hops.
 ;;   - Tramp doesn't provide useful reactions for any hop but the first
 ;;   - Might be stuff we can do to detect and convey failures?
 (require 'savehist)
 (require 'multishell-list)
 
-(defvar multishell-version "1.1.3")
+(defvar multishell-version "1.1.5")
 (defun multishell-version (&optional here)
   "Return string describing the loaded multishell version."
   (interactive "P")
@@ -182,8 +179,8 @@ with allout-mode."
 (defcustom multishell-command-key "\M- "
   "The key to use if `multishell-activate-command-key' is true.
 
-You can instead manually bind `multishell-pop-to-shell` using emacs
-lisp, eg: (global-set-key \"\\M- \" 'multishell-pop-to-shell)."
+You can instead manually bind `multishell-pop-to-shell' using emacs
+lisp, eg: (global-set-key \"\\M- \" \\='multishell-pop-to-shell)."
   :type 'key-sequence)
 
 (defvar multishell--responsible-for-command-key nil
@@ -213,8 +210,8 @@ If optional UNBIND is true, globally unbind the key.
 (defcustom multishell-activate-command-key nil
   "Set this to impose the `multishell-command-key' binding.
 
-You can instead manually bind `multishell-pop-to-shell` using emacs
-lisp, eg: (global-set-key \"\\M- \" 'multishell-pop-to-shell)."
+You can instead manually bind `multishell-pop-to-shell' using emacs
+lisp, eg: (global-set-key \"\\M- \" \\='multishell-pop-to-shell)."
   :type 'boolean
   :set 'multishell-activate-command-key-setter)
 
@@ -267,6 +264,10 @@ one emacs session to be resumed at the next, customize
 `savehist-additional-variables' to include the
 `multishell-primary-name'.")
 
+(defvar multishell-completing-read 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'.
@@ -363,7 +364,7 @@ prefixing your \\[multishell-pop-to-shell] invocation with single or double
 
  - With a single universal argument, prompt for the buffer name
    to use (without the asterisks that shell mode will put around
-   the name), defaulting to 'shell'.
+   the name), defaulting to `shell'.
 
    Completion is available.
 
@@ -388,21 +389,21 @@ prefixing your \\[multishell-pop-to-shell] invocation with single or double
 The shell buffer name you give to the prompt for a universal arg
 can include an appended path. That will be used for the startup
 directory. You can use tramp remote syntax to specify a remote
-shell. If there is an element after a final '/', that's used for
+shell. If there is an element after a final `/', that's used for
 the buffer name. Otherwise, the host, domain, or path is used.
 
 For example:
 
-* '#root/sudo:root@localhost:/etc' for a buffer named \"*#root*\" with a
+* `#root/sudo:root@localhost:/etc' for a buffer named \"*#root*\" with a
   root shell starting in /etc.
 
-* '/ssh:example.net:' for a shell buffer in your homedir on example.net. 
+* `/ssh:example.net:' for a shell buffer in your homedir on example.net.
   The buffer will be named \"*example.net*\".
 
-* '#ex/ssh:example.net|sudo:root@example.net:/var/log' for a root shell
+* `#ex/ssh:example.net|sudo:root@example.net:/var/log' for a root shell
   starting in /var/log on example.net named \"*#ex*\".
 
-* 'interior/ssh:gateway.corp.com|ssh:interior.corp.com:' to go
+* `interior/ssh:gateway.corp.com|ssh:interior.corp.com:' to go
   via gateway.corp.com to your homedir on interior.corp.com.  The
   buffer will be named \"*interior*\". You could append a sudo
   hop to the path, combining the previous example, and so on.
@@ -428,11 +429,19 @@ 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))))
+        ;; Handle catch or plain fall-through - see cond comments for protocol.
+        (cond
+         ;; Caught token from recursive invocation in minibuffer:
+         ((equal token got) (multishell-list))
+         ;; Caught specifaction of multishell args, eg from multishell-list:
+         ((listp got) (multishell-pop-to-shell-worker (nth 2 got)
+                                                      (nth 0 got)
+                                                      (nth 1 got)))
+         ;; Regular fallthrough - just relay the result:
+         (t got))))))
 
 (defun multishell-pop-to-shell-worker (&optional arg name here)
   "Do real work of `multishell-pop-to-shell', which see."
@@ -471,7 +480,7 @@ customize the savehist group to activate savehist."
 
     ;; Situate:
 
-    (cond 
+    (cond
 
      ((and (or curr-buff-proc from-buffer-is-shell)
            (not arg)
@@ -616,7 +625,14 @@ Input and completion can include associated path, if any.
 Return what's provided, if anything, else nil."
   (let* ((was-multishell-history multishell-history)
          (candidates (multishell-all-entries 'active-duplicated))
-         (got (completing-read prompt
+         (multishell-completing-read t)
+         (got
+          ;; Use `cl-letf' to dynamically bind multishell-list to
+          ;; display-completion-list, so multishell-list is used when doing
+          ;; minibuffer-completion-help.
+          (cl-letf (((symbol-function 'display-completion-list)
+                     #'multishell-list))
+              (completing-read prompt
                                ;; COLLECTION:
                                (reverse candidates)
                                ;; PREDICATE:
@@ -626,7 +642,7 @@ Return what's provided, if anything, else nil."
                                ;; INITIAL-INPUT
                                initial
                                ;; HIST:
-                               'multishell-history)))
+                               'multishell-history))))
     (when no-record
       (setq multishell-history was-multishell-history))
     (if (not (string= got ""))
@@ -636,7 +652,7 @@ Return what's provided, if anything, else nil."
 (defun multishell-resolve-target-name-and-path (shell-spec)
   "Given name/tramp-style address shell spec, resolve buffer name and directory.
 
-The name is the part of the string up to the first '/' slash, if
+The name is the part of the string up to the first `/' slash, if
 any. Missing pieces are filled in from remote path elements, if
 any, and multishell history. Given a tramp-style remote address
 and no name part, either the user@host is used for the buffer
@@ -685,7 +701,11 @@ 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.)
+        ;; Without this cleanup, occasionally restarting a disconnected
+        ;; remote session, particularly one that includes sudo, results in
+        ;; an untraceable "Args out of range" error. That never happens if
+        ;; we precedeed connection attempts with this cleanup -
+        ;; prophylactic.
         (tramp-cleanup-connection
          (tramp-dissect-file-name default-directory 'noexpand)
          'keep-debug 'keep-password))