tran@umn-cs.UUCP (Michael Tran) (10/05/87)
I wrote this small module this summer while exploring ways to get Emacs to do remote editing on a Cray 2. The main functions are find-remote-file (which I mapped to C-c C-f in my .emacs) save-remote-file (C-c C-s) write-remote-file (C-c C-w) ;; rcp.el ;; Module to do remote editing via rcp. Assume .rhosts files are ;; set up properly on both machines. ;; Modeled after ftp.el by MLY.PREP.AI.MIT.EDU ;; ;; Nick Tran ;; University of Minnesota ;; Summer 87 ;; (make-variable-buffer-local 'default-remote-directory) (make-variable-buffer-local 'buffer-remote-file-name) (setq-default default-remote-directory "sb:") (defun find-remote-file () (interactive) (let (proc temp s host file time default (olddir default-directory)) (setq s "") (while (not (string-match "\\`[ \t]*\\([^ \t:]+\\)[ \t]*:\\(.+\\)\\'" s)) (setq s (read-string "Find remote file: " default-remote-directory))) (setq host (substring s (match-beginning 1) (match-end 1))) (setq file (substring s (match-beginning 2) (match-end 2))) (if (string-match "[^\t /]+$" file) (and (setq temp (substring file (match-beginning 0) nil)) (setq default (substring file 0 (match-beginning 0)))) (and (setq temp file) (setq default ""))) (setq temp (concat "/tmp/" temp)) (setq proc (start-process temp nil "/bin/rcp" (concat host ":" file) temp)) (setq default-remote-directory (concat host ":" default)) (message "Finding %s:%s ..." host file) (setq time 0) (while (eq (process-status proc) 'run) (setq time (1+ time)) (sleep-for 1) ) (if (and (eq (process-status proc) 'exit) (eq (process-exit-status proc) 0)) (progn (find-file-read-only temp) (message "%d bytes in %d seconds (~ %d Kb/s)" (buffer-size) time (/ (buffer-size) (* time 1024))) (delete-file temp) (setq buffer-file-name "") (setq buffer-remote-file-name (concat host ":" file)) (setq default-remote-directory (concat host ":" default)) (setq default-directory olddir) ) (message "Find-remote-file failed (exit status %d)" (process-exit-status proc))) )) (defun save-remote-file() (interactive) (cond ((eq 0 (length buffer-remote-file-name)) (write-remote-file)) ( t (do-write-remote-file buffer-remote-file-name)))) (defun write-remote-file () (interactive) (let ((s "")) (while (not (string-match "\\`[ \t]*\\([^ \t:]+\\)[ \t]*:\\(.+\\)\\'" s)) (or (not (and (string= s "") (eq 0 (length (setq s buffer-remote-file-name))))) (setq s default-remote-directory)) (setq s (read-string "Write remote file: " s))) (do-write-remote-file s))) (defun do-write-remote-file (s) (if (buffer-modified-p) (let (host file temp proc time (size (buffer-size)) (olddir default-directory)) (string-match "\\`[ \t]*\\([^ \t:]+\\)[ \t]*:\\(.+\\)\\'" s) (setq host (substring s (match-beginning 1) (match-end 1))) (setq file (substring s (match-beginning 2) (match-end 2))) (setq temp (concat "/tmp/" (buffer-name))) (if (string-match "[^\t /]+$" file) (setq default-remote-directory (concat host ":" (substring file 0 (match-beginning 0)))) (setq default (concat host ":"))) (setq buffer-remote-file-name (concat host ":" file)) (write-file temp) (message "Writing %s:%s ..." host file) (setq proc (start-process temp nil "/bin/rcp" temp (concat host ":" file))) (setq time 0) (while (eq (process-status proc) 'run) (setq time (1+ time)) (sleep-for 1) ) (if (and (eq (process-status proc) 'exit) (eq (process-exit-status proc) 0)) (message "%d bytes in %d seconds (~ %d Kb/s)" size time (/ size (* time 1024))) (and (set-buffer-modified-p t) (message "Write-remote-file failed (exit status %d)" (process-exit-status proc)))) (delete-file temp) (set-visited-file-name "") (setq default-directory olddir) ) (message "(No changes need to be saved)") ))
mayer@hplabsz.HPL.HP.COM (Niels Mayer) (10/08/87)
An intersting extension you might want to consider once you have remote editing up and running: When you want to do a 'make' after you've just edited a remote file, use a modified version of compile.el that looks at a buffer-local variable containing the remote host's name and run the compilation through rsh(1) on the remote host. Under HPUX+GNU, we can access remote files by opening a network connection via M-X netunam, and then access the file normally with ^X^F /net/host/path/file. I made a simple and crufty extension to compile.el that looks to see whether the buffer-file-name is remote and if so, I execute the compile command in a remsh (HPUX equivalent to rsh, renamed to prevent conflict with SYSV rsh which is a restricted sh).... Those of you using ftp.el or rcp.el to do remote editing may want to do something similar by storing the appropriate information in a buffer-local variable and munging compile.el appropriately. here's the relevant diffs between the 18.47 version of compile.el and my version: 82,91c82,119 < (setq compilation-process < (start-process "compilation" "*compilation*" < shell-file-name < "-c" (concat "exec " command))) < (with-output-to-temp-buffer "*compilation*" < (princ "cd ") < (princ default-directory) < (terpri) < (princ command) < (terpri)) --- > (cond > ((string-match "/net" default-directory) > (let (host > host-dir) > (setq host (substring default-directory > (+ 1 (match-end 0)) > (string-match "/" default-directory (+ 1 (match-end 0))))) > (setq host-dir (substring default-directory > (- (match-end 0) 1) > (length default-directory))) > (let ((default-directory (getenv "HOME"))) ;to prevent shell bug caused by pwd being a /net directory > (setq compilation-process > (start-process "compilation" "*compilation*" > "/usr/bin/remsh" host > "cd " host-dir ";" command))) > (with-output-to-temp-buffer "*compilation*" > (princ "remsh ") > (princ host) > (terpri) > (princ "cd ") > (princ host-dir) > (terpri) > (princ command) > (terpri)) > ) > ) > (t > (setq compilation-process > (start-process "compilation" "*compilation*" > shell-file-name > "-c" (concat "exec " command))) > (with-output-to-temp-buffer "*compilation*" > (princ "cd ") > (princ default-directory) > (terpri) > (princ command) > (terpri)) > ))