changeset 106219:16b061d2742d

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'.
author Michael Albinus <michael.albinus@gmx.de>
date Tue, 24 Nov 2009 10:25:54 +0000
parents 8ccde493b34d
children a88a54e96796
files lisp/ChangeLog lisp/eshell/em-cmpl.el lisp/eshell/em-unix.el lisp/eshell/esh-ext.el lisp/eshell/esh-proc.el lisp/eshell/esh-util.el lisp/net/tramp.el
diffstat 7 files changed, 108 insertions(+), 52 deletions(-) [+]
line wrap: on
line diff
--- a/lisp/ChangeLog	Tue Nov 24 09:19:09 2009 +0000
+++ b/lisp/ChangeLog	Tue Nov 24 10:25:54 2009 +0000
@@ -1,3 +1,29 @@
+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,
--- a/lisp/eshell/em-cmpl.el	Tue Nov 24 09:19:09 2009 +0000
+++ b/lisp/eshell/em-cmpl.el	Tue Nov 24 10:25:54 2009 +0000
@@ -402,7 +402,7 @@
 	  (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 ())
--- a/lisp/eshell/em-unix.el	Tue Nov 24 09:19:09 2009 +0000
+++ b/lisp/eshell/em-unix.el	Tue Nov 24 10:25:54 2009 +0000
@@ -859,9 +859,8 @@
     (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))
--- a/lisp/eshell/esh-ext.el	Tue Nov 24 09:19:09 2009 +0000
+++ b/lisp/eshell/esh-ext.el	Tue Nov 24 10:25:54 2009 +0000
@@ -73,7 +73,7 @@
   "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))
@@ -176,7 +176,7 @@
 	(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.
@@ -190,10 +190,10 @@
     (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)
@@ -203,23 +203,14 @@
 (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."
--- a/lisp/eshell/esh-proc.el	Tue Nov 24 09:19:09 2009 +0000
+++ b/lisp/eshell/esh-proc.el	Tue Nov 24 10:25:54 2009 +0000
@@ -261,7 +261,7 @@
 (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
@@ -270,12 +270,13 @@
 	 (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/lisp/eshell/esh-util.el	Tue Nov 24 09:19:09 2009 +0000
+++ b/lisp/eshell/esh-util.el	Tue Nov 24 10:25:54 2009 +0000
@@ -237,6 +237,21 @@
 	    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))
@@ -682,29 +697,24 @@
 (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)
 
--- a/lisp/net/tramp.el	Tue Nov 24 09:19:09 2009 +0000
+++ b/lisp/net/tramp.el	Tue Nov 24 10:25:54 2009 +0000
@@ -2383,6 +2383,35 @@
 			   '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