emacs-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH] New with-file-buffer macro


From: Adam Porter
Subject: [PATCH] New with-file-buffer macro
Date: Thu, 31 Dec 2020 13:13:57 -0600
User-agent: Gnus/5.13 (Gnus v5.13) Emacs/26.3 (gnu/linux)

Hi,

Attached is a patch which adds a new macro, with-file-buffer.  It's
similar to the macro with-temp-file, and it simplifies some common
cases, like reading a file's contents into a buffer and returning a
value from forms evaluated in its buffer, writing to a file that
shouldn't already exist, overwriting an existing file, etc.

For example, here's a recently updated function in package-build.el
which uses with-temp-buffer and write-region:

#+BEGIN_SRC elisp
  (defun package-build--write-pkg-readme (name files directory)
    (when-let ((commentary
                (let* ((file (concat name ".el"))
                       (file (or (car (rassoc file files)) file))
                       (file (and file (expand-file-name file directory))))
                  (and (file-exists-p file)
                       (lm-commentary file)))))
      (with-temp-buffer
        (if (>= emacs-major-version 27)
            (insert commentary)
          ;; Taken from 27.1's `lm-commentary'.
          (insert
           (replace-regexp-in-string ; Get rid of...
            "[[:blank:]]*$" "" ; trailing white-space
            (replace-regexp-in-string
             (format "%s\\|%s\\|%s"
                     ;; commentary header
                     (concat "^;;;[[:blank:]]*\\("
                             lm-commentary-header
                             "\\):[[:blank:]\n]*")
                     "^;;[[:blank:]]*" ; double semicolon prefix
                     "[[:blank:]\n]*\\'") ; trailing new-lines
             "" commentary))))
        (unless (= (char-before) ?\n)
          (insert ?\n))
        (let ((coding-system-for-write buffer-file-coding-system))
          (write-region nil nil
                        (expand-file-name (concat name "-readme.txt")
                                          package-build-archive-dir))))))
#+END_SRC

Here's how it could work using this new with-file-buffer macro:

#+BEGIN_SRC elisp
  (defun package-build--write-pkg-readme (name files directory)
    (when-let ((commentary
                (let* ((file (concat name ".el"))
                       (file (or (car (rassoc file files)) file))
                       (file (and file (expand-file-name file directory))))
                  (and (file-exists-p file)
                       (lm-commentary file)))))
      (let ((coding-system-for-write buffer-file-coding-system))
        (with-file-buffer (expand-file-name (concat name "-readme.txt")
                                            package-build-archive-dir)
            (:insert nil :write t :overwrite t)
          (if (>= emacs-major-version 27)
              (insert commentary)
            ;; Taken from 27.1's `lm-commentary'.
            (insert
             (replace-regexp-in-string ; Get rid of...
              "[[:blank:]]*$" "" ; trailing white-space
              (replace-regexp-in-string
               (format "%s\\|%s\\|%s"
                       ;; commentary header
                       (concat "^;;;[[:blank:]]*\\("
                               lm-commentary-header
                               "\\):[[:blank:]\n]*")
                       "^;;[[:blank:]]*" ; double semicolon prefix
                       "[[:blank:]\n]*\\'") ; trailing new-lines
               "" commentary))))
          (unless (= (char-before) ?\n)
            (insert ?\n))))))
#+END_SRC

This example isn't the most dramatically different, but it shows a few
improvements: the options list after the filename shows clearly what the
form does (write a file, overwriting if it already exists), whereas
calling write-region directly requires reading to the end of the body
forms (which might not fit within the window); and the options list also
makes arguments to write-region easier to use, as well as making it easy
to control write-region-inhibit-fsync and file-precious-flag.  Without
this macro, these operations and options are, IMO, harder to use and
easy to overlook, so I think this would be a worthwhile addition.

If this idea seems useful, I'm sure various improvements may be made, so
I would appreciate any feedback.  For example, it might be better for
":insert nil" to be the default, so ":insert t" would be specified to
read the file's contents into the buffer.

Thanks,
Adam

Attachment: 0001-lisp-subr.el-with-file-buffer-New-macro.patch
Description: Patch adding with-file-buffer macro


reply via email to

[Prev in Thread] Current Thread [Next in Thread]