Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Elisp, how to get path string with slash properly inserted?

Tags:

emacs

lisp

elisp

I am manually constructing path strings in Elisp by concatenating partial paths and directory names. Unfortunately sometimes the paths end with slash, sometimes not. Therefore, I need to insert slash before concatenating a directory name when necessary but not otherwise. What's a good way to do this?

like image 761
qazwsx Avatar asked Mar 14 '12 01:03

qazwsx


4 Answers

(file-name-as-directory dir) will return directory path dir with a trailing slash, adding one if necessary, and not otherwise.

If you had your sequence of partial paths in a list, you could do something like:

(let ((directory-list '("/foo" "bar/" "p/q/" "x/y"))
      (file-name "some_file.el"))
  (concat
   (mapconcat 'file-name-as-directory directory-list "")
   file-name))

"/foo/bar/p/q/x/y/some_file.el"

or as an alternative, if you wanted to include the file name in the list, you could utilise directory-file-name which does the opposite of file-name-as-directory:

(let ((path-list '("/foo" "bar/" "p/q/" "x/y/some_file.el")))
  (mapconcat 'directory-file-name path-list "/"))

"/foo/bar/p/q/x/y/some_file.el"

(Someone please correct me if using directory-file-name on a non-directory is not portable?)

like image 125
phils Avatar answered Nov 16 '22 03:11

phils


The easiest way to assemble file names from parts of questionable content is with expand-file-name. For example:

(expand-file-name "foo.txt")

this common form will give you a full file name based on default-directory:

/home/me/foo.txt

but if you have a variable 'dir' whose content is "/home/them/subdir" and want to use that, do this:

(expand-file-name "foo.txt" dir)

it doesn't matter if dir ends in / or not. If you are on some other platform, and contains the other slash, it will do the right thing then too. Do you have a mix? Just stack them:

(expand-file-name "foo.txt" (expand-file-name "somesubdir" dir))
like image 22
Eric Avatar answered Nov 16 '22 02:11

Eric


Something like this should work as a starting point, although you'd want to flesh it out a bit to make it platform independent, etc.

(defun append-path-component (path new-part)
  (if (string-match ".*/$" path)
    (concat path new-part)
    (concat path "/" new-part)))

As per usual, there's probably some bit of elisp that already does this that I'm just not aware of.

like image 43
deong Avatar answered Nov 16 '22 04:11

deong


Unless you really care about keeping relative file names as relative, then it's always much better to avoid concat and use expand-file-name instead.

like image 41
Stefan Avatar answered Nov 16 '22 03:11

Stefan