I have two copies of the same project, one local, one on a remote server, and I am editing a project's file locally, while running an inferior ESS process on the remote server. The remote files get synchronized outside Emacs, and I would like to avoid editing files remotely if I can help it.

When I try to load the file (ess-load-file), it obviously sends the command "source()" as expected. The problem is that I would like it to use the file name with the local directories stripped from it because they don't exist on the remote server, just the bare filename.

I know thatess-load-file uses (buffer-file-name) to find out the file name, but I think I just can't replace a buffer's file name with whatever I want. I've been using

(ess-load-file (file-name-nondirectory (buffer-file-name)))

and rebinding the keybinding for ess-load-file to run this instead, but is there some nicer way of doing this?

2 Answers 2


I don't know. That looks pretty nice to me. You might unify this under one binding if you please. I'm not too sure what your setup is like, so this might not work. Please correct me if I'm wrong.

(defun ess-load-remote-or-local ()
    (if (file-readable-p (buffer-file-name))
      (file-name-nondirectory (buffer-file-name)))))

I don't think the solution is going to get any simpler. It may get smarter and more automated, but that choice is up to you.


I was just answering something similar in Superuser.

With the following function you can copy the file. You may adapt it to do the copy remotely.

(defun my-copy-file ()
  (cond ((equal "home.org" (file-name-nondirectory (buffer-file-name)))
         (write-region (point-min) (point-max)
                       (concat "~/org/" (file-name-nondirectory (buffer-file-name)))))))

(add-hook 'before-save-hook #'my-copy-file)

Here there is another function you may adapt to copy files checking for path components, so you don't have to copy in every case.

;; /plink:[email protected]:/the/remote/path/finename.cc
(defun my-mirror-remote-file ()
  ;; first search the at sign `@' in the buffer file name
  (let* ((file_name (buffer-file-name))
         (atpos (string-match "@" file_name)))
    ;; if there is an at sign in the file name, we assume it is a remote file
    (cond (atpos
       ;; we look for the second colon, which is after the host part
       ;; and we get the diretory and file name
       (let* ((hoston (substring file_name atpos))
              (colonpos (string-match ":" hoston)))
         ;; and we write the file locally (it will NOT create the dir though)
         (write-region (point-min) (point-max)
                       (concat "~" (substring hoston (+ colonpos 1)))))))))
  • I don't think the OP is preoccupied with the copying itself, only with using the local files "as if" accessing the remote files.
    – Stefan
    Commented Jul 22, 2019 at 13:16

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.