10
votes

I have the following file data.txt

A
B
C
D

I would like to read the contents of this file into a Lisp list, like

(defun read-list-from-file (fn)
  (interactive)
  (list "A" "B" "C" "D"))

(defun my-read ()
  (interactive)
  (let (( mylist (read-list-from-file "data.txt")))
    (print mylist t)))

How can I modify read-list-from-file such that it returns the same list, but instead reads from the file given as input argument fn.. Each line in the file should be a separate item in the list..

2

2 Answers

10
votes

This code:

(with-current-buffer
    (find-file-noselect "~/data.txt")
  (split-string
   (save-restriction
     (widen)
     (buffer-substring-no-properties
      (point-min)
      (point-max)))
   "\n" t))

UPD:

Here's a version with insert-file-contents:

(defun slurp (f)
  (with-temp-buffer
    (insert-file-contents f)
    (buffer-substring-no-properties
       (point-min)
       (point-max))))

(split-string
 (slurp "~/data.txt") "\n" t)
7
votes

Much easier, than creating a temporary buffer, is to use f file manipulation library's f-read function that returns textual content of a file (default coding UTF-8). f is a third-party that you need to install from MELPA, read Xah Lee's tutorial on how to use Emacs package management system. Then you could use either split-string or s string manipulation library's s-split (which is a simple wrapper around the former function):

(s-split "\n" (f-read "~/data.txt") t) ; ("A" "B" "C" "D")

Note: third parameter to s-split set to t omits empty strings. You could use s-lines, but as textual files on *nix systems usually contain a trailing newline, the returned list would be ("A" "B" "C" "D" ""). You can remove the last element with dash list manipulation library's butlast function, but this works in O(n), so probably stick to s-split, unless you want empty lines to be preserved in the list.