equal to @code{nil}, calling @code{shell} interactively will prompt
for a shell name.
+Starting with Emacs 26, you could use connection-local variables for
+setting different values of @option{explicit-shell-file-name} for
+different remote hosts.
+@ifinfo
+@pxref{Connection Local Variables, , , elisp}
+@end ifinfo
+
+@lisp
+@group
+(connection-local-set-profile-variables
+ 'remote-bash
+ '((explicit-shell-file-name . "/bin/bash")
+ (explicit-bash-args . ("-i"))))
+@end group
+
+@group
+(connection-local-set-profile-variables
+ 'remote-ksh
+ '((explicit-shell-file-name . "/bin/ksh")
+ (explicit-ksh-args . ("-i"))))
+@end group
+
+@group
+(connection-local-set-profiles
+ '(:application 'tramp :protocol "ssh" :machine "localhost")
+ 'remote-bash)
+@end group
+
+@group
+(connection-local-set-profiles
+ `(:application 'tramp :protocol "sudo"
+ :user "root" :machine ,(system-name))
+ 'remote-ksh)
+@end group
+@end lisp
+
@subsection Running @code{shell-command} on a remote host
@cindex shell-command
@end group
@end example
-@code{eshell} in Emacs 23.2 added custom @code{su} and @code{sudo}
-commands that set the default directory correctly for the
-@file{*eshell*} buffer. @value{tramp} silently updates
-@option{tramp-default-proxies-alist} with an entry for this directory
-(@pxref{Multi-hops}):
+@code{eshell} added custom @code{su} and @code{sudo} commands that set
+the default directory correctly for the @file{*eshell*} buffer.
+@value{tramp} silently updates @option{tramp-default-proxies-alist}
+with an entry for this directory (@pxref{Multi-hops}):
@example
@group
@item
Which systems does it work on?
-The package works successfully on Emacs 23, Emacs 24, and Emacs 25.
+The package works successfully on Emacs 23, Emacs 24, Emacs 25, and
+Emacs 26.
While Unix and Unix-like systems are the primary remote targets,
@value{tramp} has equal success connecting to other platforms, such as
-MS Windows XP/Vista/7.
+MS Windows 7/8/10.
@item
nil
(mapcar
(lambda (property)
- (when (plist-member criteria property)
+ (when (and (plist-member criteria property) (plist-get criteria property))
(list property (plist-get criteria property))))
properties)))
;;;###autoload
(defun connection-local-set-profiles (criteria &rest profiles)
- "Add PROFILES for remote servers.
-CRITERIA is either a regular expression identifying a remote
-server, or a function with one argument IDENTIFICATION, which
-returns non-nil when a remote server shall apply PROFILE's
-variables. If CRITERIA is nil, it always applies.
-PROFILES are the names of a connection profile (a symbol).
+ "Add PROFILES for CRITERIA.
+CRITERIA is a plist identifying a connection and the application
+using this connection, see `connection-local-criteria-alist'.
+PROFILES are the names of connection profiles (a symbol).
When a connection to a remote server is opened and CRITERIA
matches to that server, the connection-local variables from
;;;###autoload
(defmacro with-connection-local-profiles (profiles &rest body)
"Apply connection-local variables according to PROFILES in current buffer.
-Execute BODY, and unwind connection local variables."
+Execute BODY, and unwind connection-local variables."
(declare (indent 1) (debug t))
`(let ((enable-connection-local-variables t)
(old-buffer-local-variables (buffer-local-variables))
;; If the current buffer is a dead shell buffer, use it.
(current-buffer)))
- ;; On remote hosts, the local `shell-file-name' might be useless.
- (if (and (called-interactively-p 'any)
- (file-remote-p default-directory)
- (null explicit-shell-file-name)
- (null (getenv "ESHELL")))
- (with-current-buffer buffer
- (set (make-local-variable 'explicit-shell-file-name)
- (expand-file-name
- (file-local-name
- (read-file-name
- "Remote shell path: " default-directory shell-file-name
- t shell-file-name))))))
-
- ;; The buffer's window must be correctly set when we call comint (so
- ;; that comint sets the COLUMNS env var properly).
- (pop-to-buffer buffer)
- (unless (comint-check-proc buffer)
- (let* ((prog (or explicit-shell-file-name
- (getenv "ESHELL") shell-file-name))
- (name (file-name-nondirectory prog))
- (startfile (concat "~/.emacs_" name))
- (xargs-name (intern-soft (concat "explicit-" name "-args"))))
- (unless (file-exists-p startfile)
- (setq startfile (concat user-emacs-directory "init_" name ".sh")))
- (apply 'make-comint-in-buffer "shell" buffer prog
- (if (file-exists-p startfile) startfile)
- (if (and xargs-name (boundp xargs-name))
- (symbol-value xargs-name)
- '("-i")))
- (shell-mode)))
+ (with-current-buffer buffer
+ (when (file-remote-p default-directory)
+ ;; Apply connection-local variables.
+ (hack-connection-local-variables-apply
+ `(:application 'tramp
+ :protocol ,(file-remote-p default-directory 'method)
+ :user ,(file-remote-p default-directory 'user)
+ :machine ,(file-remote-p default-directory 'host)))
+
+ ;; On remote hosts, the local `shell-file-name' might be useless.
+ (if (and (called-interactively-p 'any)
+ (null explicit-shell-file-name)
+ (null (getenv "ESHELL")))
+ (set (make-local-variable 'explicit-shell-file-name)
+ (expand-file-name
+ (file-local-name
+ (read-file-name
+ "Remote shell path: " default-directory shell-file-name
+ t shell-file-name))))))
+
+ ;; The buffer's window must be correctly set when we call comint
+ ;; (so that comint sets the COLUMNS env var properly).
+ (pop-to-buffer buffer)
+ (unless (comint-check-proc buffer)
+ (let* ((prog (or explicit-shell-file-name
+ (getenv "ESHELL") shell-file-name))
+ (name (file-name-nondirectory prog))
+ (startfile (concat "~/.emacs_" name))
+ (xargs-name (intern-soft (concat "explicit-" name "-args"))))
+ (unless (file-exists-p startfile)
+ (setq startfile (concat user-emacs-directory "init_" name ".sh")))
+ (apply 'make-comint-in-buffer "shell" buffer prog
+ (if (file-exists-p startfile) startfile)
+ (if (and xargs-name (boundp xargs-name))
+ (symbol-value xargs-name)
+ '("-i")))
+ (shell-mode))))
buffer)
;;; Directory tracking