2

To help catch predictable errors, I've written my own linting tasks that read the code and report any inconsistencies it finds. One of the hackier pieces to this right now is the following function:

(defun lint-get-forms (filename)
  "Read FILENAME and return a list of its Lisp forms."
  (let ((pos 0) forms)
    (with-temp-buffer
      (insert-file-contents filename)
      (condition-case _
          (while t
            (when-let ((cell (read-from-string (buffer-string) pos)))
              (push (car cell) forms)
              (goto-char (setq pos (cdr cell)))))
        (error forms)))
    forms))

Is there a better way to do this (preferably without condition-case)?

Ideally these checks would be done at compile-time, but they're not stable enough yet to move to the other repository.

  • Why convert buffer text to a string and read from that string? Why not read directly from the buffer? The latter is typically how to read from a Lisp file. – Drew May 15 '17 at 14:22
  • @Drew Hence why I'm posting this question :-) I think I neglected to consider read's optional argument. – Sean Allred May 16 '17 at 2:46
  • Got it. It's a good question. – Drew May 16 '17 at 14:13
4

See Drew's answer to a related question.

If you do not mind ignoring all errors (I do not know which errors read might signal), you should use ignore-errors. Otherwise, your error handler should probably be specific to end-of-file errors.

Personally, I take (sometimes guilty) pleasure in K&R-style and functional brevity, so I would write your function like this:

(defun lint-get-forms (filename)
  "Read FILENAME and return a list of its Lisp forms."
  (with-temp-buffer
    (let ((buf (current-buffer))
          forms)
      (insert-file-contents filename)
      (while (ignore-errors (push (read buf) forms)))
      (nreverse forms))))

Regardless of whether you find this while form too terse, I recommend using read over read-from-string, as the former is much more powerful in the type of its argument. If, for some reason I am missing, you are intent on using read-from-string, I suggest caching the result of buffer-string.

P.S. Is there a reason you are calling goto-char?

| improve this answer | |
  • re goto-char: read-string does not advance point. And terse is fine by me :-) – Sean Allred May 16 '17 at 2:47
  • @SeanAllred Yes, but you were already passing an updated pos to read-from-string. – Basil May 16 '17 at 9:40

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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