* eshell/esh-util.el (eshell-path-env): New defvar.
(eshell-parse-colon-path): New defun.
(eshell-file-attributes): Use `eshell-parse-colon-path'.
* eshell/esh-ext.el (eshell-search-path): Use
`eshell-parse-colon-path'.
(eshell-remote-command): Remove argument HANDLER.
(eshell-external-command): Check for FTP remote connection.
* eshell/esh-proc.el (eshell-gather-process-output): Use
`file-truename', in order to start also symlinked files. Apply
`start-file-process' instead of `start-process'. Shorten `command'
to the local file name part.
* eshell/em-cmpl.el (eshell-complete-commands-list): Use
`eshell-parse-colon-path'.
* eshell/em-unix.el (eshell/du): Check for FTP remote connection.
* net/tramp.el (tramp-eshell-directory-change): New defun. Add it
to `eshell-directory-change-hook'.
+2009-11-24 Michael Albinus <michael.albinus@gmx.de>
+
+ Improve handling of processes on remote hosts.
+
+ * eshell/esh-util.el (eshell-path-env): New defvar.
+ (eshell-parse-colon-path): New defun.
+ (eshell-file-attributes): Use `eshell-parse-colon-path'.
+
+ * eshell/esh-ext.el (eshell-search-path): Use
+ `eshell-parse-colon-path'.
+ (eshell-remote-command): Remove argument HANDLER.
+ (eshell-external-command): Check for FTP remote connection.
+
+ * eshell/esh-proc.el (eshell-gather-process-output): Use
+ `file-truename', in order to start also symlinked files. Apply
+ `start-file-process' instead of `start-process'. Shorten `command'
+ to the local file name part.
+
+ * eshell/em-cmpl.el (eshell-complete-commands-list): Use
+ `eshell-parse-colon-path'.
+
+ * eshell/em-unix.el (eshell/du): Check for FTP remote connection.
+
+ * net/tramp.el (tramp-eshell-directory-change): New defun. Add it
+ to `eshell-directory-change-hook'.
+
2009-11-24 Tassilo Horn <tassilo@member.fsf.org>
* doc-view.el (doc-view-mode): Switch off view-mode explicitly,
(setq filename (substring filename 1)
pcomplete-stub filename
glob-name t))
- (let* ((paths (split-string (getenv "PATH") path-separator))
+ (let* ((paths (eshell-parse-colon-path eshell-path-env))
(cwd (file-name-as-directory
(expand-file-name default-directory)))
(path "") (comps-in-path ())
(if (and ext-du
(not (catch 'have-ange-path
(eshell-for arg args
- (if (eq (find-file-name-handler (expand-file-name arg)
- 'directory-files)
- 'ange-ftp-hook-function)
+ (if (string-equal
+ (file-remote-p (expand-file-name arg) 'method) "ftp")
(throw 'have-ange-path t))))))
(throw 'eshell-replace-command
(eshell-parse-command ext-du args))
"Search the environment path for NAME."
(if (file-name-absolute-p name)
name
- (let ((list (parse-colon-path (getenv "PATH")))
+ (let ((list (eshell-parse-colon-path eshell-path-env))
suffixes n1 n2 file)
(while list
(setq n1 (concat (car list) name))
(error "%s: external command not found"
(substring command 1))))))
-(defun eshell-remote-command (handler command args)
+(defun eshell-remote-command (command args)
"Insert output from a remote COMMAND, using ARGS.
A remote command is something that executes on a different machine.
An external command simply means external to Emacs.
(unwind-protect
(progn
(setq exitcode
- (funcall handler 'shell-command
- (mapconcat 'shell-quote-argument
- (append (list command) args) " ")
- outbuf errbuf))
+ (shell-command
+ (mapconcat 'shell-quote-argument
+ (append (list command) args) " ")
+ outbuf errbuf))
(eshell-print (with-current-buffer outbuf (buffer-string)))
(eshell-error (with-current-buffer errbuf (buffer-string))))
(eshell-close-handles exitcode 'nil)
(defun eshell-external-command (command args)
"Insert output from an external COMMAND, using ARGS."
(setq args (eshell-stringify-list (eshell-flatten-list args)))
- (let ((handler
- (unless (or (equal default-directory "/")
- (and (eshell-under-windows-p)
- (string-match "\\`[A-Za-z]:[/\\\\]\\'"
- default-directory)))
- (find-file-name-handler default-directory
- 'shell-command))))
- (if (and handler
- (not (and (featurep 'xemacs)
- (eq handler 'dired-handler-fn))))
- (eshell-remote-command handler command args))
- (let ((interp (eshell-find-interpreter command)))
- (assert interp)
- (if (functionp (car interp))
- (apply (car interp) (append (cdr interp) args))
- (eshell-gather-process-output
- (car interp) (append (cdr interp) args))))))
+ (if (string-equal (file-remote-p default-directory 'method) "ftp")
+ (eshell-remote-command command args))
+ (let ((interp (eshell-find-interpreter command)))
+ (assert interp)
+ (if (functionp (car interp))
+ (apply (car interp) (append (cdr interp) args))
+ (eshell-gather-process-output
+ (car interp) (append (cdr interp) args)))))
(defun eshell/addpath (&rest args)
"Add a set of paths to PATH."
(defun eshell-gather-process-output (command args)
"Gather the output from COMMAND + ARGS."
(unless (and (file-executable-p command)
- (file-regular-p command))
+ (file-regular-p (file-truename command)))
(error "%s: not an executable file" command))
(let* ((delete-exited-processes
(if eshell-current-subjob-p
(process-environment (eshell-environment-variables))
proc decoding encoding changed)
(cond
- ((fboundp 'start-process)
+ ((fboundp 'start-file-process)
(setq proc
(let ((process-connection-type
(unless (eshell-needs-pipe-p command)
- process-connection-type)))
- (apply 'start-process
+ process-connection-type))
+ (command (or (file-remote-p command 'localname) command)))
+ (apply 'start-file-process
(file-name-nondirectory command) nil
;; `start-process' can't deal with relative filenames.
(append (list (expand-file-name command)) args))))
a (last a)))
a))
+(defvar eshell-path-env (getenv "PATH")
+ "Content of $PATH.
+It might be different from \(getenv \"PATH\"\), when
+`default-directory' points to a remote host.")
+
+(defun eshell-parse-colon-path (path-env)
+ "Split string with `parse-colon-path'.
+Prepend remote identification of `default-directory', if any."
+ (let ((remote (file-remote-p default-directory)))
+ (if remote
+ (mapcar
+ (lambda (x) (concat remote x))
+ (parse-colon-path path-env))
+ (parse-colon-path path-env))))
+
(defun eshell-split-path (path)
"Split a path into multiple subparts."
(let ((len (length path))
(defun eshell-file-attributes (file)
"Return the attributes of FILE, playing tricks if it's over ange-ftp."
(let* ((file (expand-file-name file))
- (handler (find-file-name-handler file 'file-attributes))
entry)
- (if (not handler)
- (file-attributes file)
- (if (eq (find-file-name-handler (file-name-directory file)
- 'directory-files)
- 'ange-ftp-hook-function)
- (let ((base (file-name-nondirectory file))
- (dir (file-name-directory file)))
+ (if (string-equal (file-remote-p file 'method) "ftp")
+ (let ((base (file-name-nondirectory file))
+ (dir (file-name-directory file)))
+ (if (boundp 'ange-cache)
+ (setq entry (cdr (assoc base (cdr (assoc dir ange-cache))))))
+ (unless entry
+ (setq entry (eshell-parse-ange-ls dir))
(if (boundp 'ange-cache)
- (setq entry (cdr (assoc base (cdr (assoc dir ange-cache))))))
- (unless entry
- (setq entry (eshell-parse-ange-ls dir))
- (if (boundp 'ange-cache)
- (setq ange-cache
- (cons (cons dir entry)
- ange-cache)))
- (if entry
- (let ((fentry (assoc base (cdr entry))))
- (if fentry
- (setq entry (cdr fentry))
- (setq entry nil)))))))
- (or entry (funcall handler 'file-attributes file)))))
+ (setq ange-cache
+ (cons (cons dir entry)
+ ange-cache)))
+ (if entry
+ (let ((fentry (assoc base (cdr entry))))
+ (if fentry
+ (setq entry (cdr fentry))
+ (setq entry nil))))))
+ (file-attributes file))))
(defalias 'eshell-copy-tree 'copy-tree)
'tramp-rfn-eshadow-update-overlay))))
+;;; Integration of eshell.el:
+
+(eval-when-compile
+ (defvar eshell-path-env))
+
+;; eshell.el keeps the path in `eshell-path-env'. We must change it
+;; when `default-directory' points to another host.
+(defun tramp-eshell-directory-change ()
+ "Set `eshell-path-env' to $PATH of the host related to `default-directory'."
+ (setq eshell-path-env
+ (if (file-remote-p default-directory)
+ (with-parsed-tramp-file-name default-directory nil
+ (mapconcat
+ 'identity
+ (tramp-get-remote-path v)
+ ":"))
+ (getenv "PATH"))))
+
+(eval-after-load "esh-util"
+ '(progn
+ (tramp-eshell-directory-change)
+ (add-hook 'eshell-directory-change-hook
+ 'tramp-eshell-directory-change)
+ (add-hook 'tramp-unload-hook
+ (lambda ()
+ (remove-hook 'eshell-directory-change-hook
+ 'tramp-eshell-directory-change)))))
+
+
;;; File Name Handler Functions:
(defun tramp-handle-make-symbolic-link