Wrapping FTP in emacs – part 2

Now that we have a nice wrapper around copying a file that handles connecting to the remote server if we are not already connected, implementing the single key press upload function is trivial.

My website related directories are all under c:/home/juang/website. However, sometimes I like to upload some of my elisp files which live elsewhere. I should probably have an external environment variable which points to my home directory (e.g. %HOME%) but for the moment I have constants within my elisp source.

(defconst *ftp-HOME* "c:/home/juang/")
(defconst *ftp-WEB* (concat *ftp-HOME* "website/"))

In elisp we normally use a list of lists where we might use a hash in Perl. This is not because elisp doesn’t have hashes (it does), but because the syntax for lists is cleaner. A simple mapping might look like this:

(defconst *map*
  '(("c:/www" "/www")
    ("c:/emacs-files" "/www/emacs-files")))

However, quote suppresses variable evaluation so we need to be a little bit more verbose.

(defconst *ftp-location-map*
   (list (concat *ftp-WEB* "wordpress") "/www/blog")
   (list *ftp-WEB* "/www/")
   (list (concat *ftp-HOME* "emacs-files") "/www/files")))

I like emacs to ask for confirmation before it uploads a file but as others might want to skip that step we add a variable to allow the alternative behaviour.

(defcustom *ftp-upload-skip-prompt* nil
  "Skip the ftp prompt")

A couple of comments about (ftp-upload-file …):

  • (do-list (var list) body) iterates through a list, setting var to each item in turn.
  • (y-or-n-p &prompt) displays the prompt in the mini-buffer and waits for a y or n input.

The rest of the function should be fairly self-explanatory.

(defun ftp-upload-file (from)
  (let ((to from))
    (dolist (tuple *ftp-location-map*)
      (let ((regex (car tuple))
            (replace (cadr tuple)))
        (when (string-match (concat "^" regex) to)
          (setq to (replace-match replace t t to)))))
    (if (or *ftp-upload-skip-prompt*
            (y-or-n-p (format "Query: Upload %s to %s ? " from to)))
        (ftp-copy-file from to)
      (message "Info: upload %s to %s aborted" from to))))

(defun ftp-upload-current-file ()
  (ftp-upload-file (expand-file-name (buffer-file-name))))

(global-set-key [f9] 'ftp-upload-current-file)

We also provide a convenience function to upload the current file and bind it to a single key. The final result is linked from the original version of this page.



Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: