emacs-elpa-diffs
[Top][All Lists]
Advanced

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

[nongnu] elpa/reformatter d0d58c4eef 01/81: Initial commit


From: ELPA Syncer
Subject: [nongnu] elpa/reformatter d0d58c4eef 01/81: Initial commit
Date: Tue, 5 Sep 2023 04:03:32 -0400 (EDT)

branch: elpa/reformatter
commit d0d58c4eef2b6abea5ba6e51306e38d47dcd20c1
Author: Steve Purcell <steve@sanityinc.com>
Commit: Steve Purcell <steve@sanityinc.com>

    Initial commit
---
 README.md      |  96 +++++++++++++++++++++++++++++++++++
 reformatter.el | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 254 insertions(+)

diff --git a/README.md b/README.md
new file mode 100644
index 0000000000..c1121825ed
--- /dev/null
+++ b/README.md
@@ -0,0 +1,96 @@
+[![Melpa 
Status](http://melpa.org/packages/reformatter-badge.svg)](http://melpa.org/#/reformatter)
+[![Melpa Stable 
Status](http://stable.melpa.org/packages/reformatter-badge.svg)](http://stable.melpa.org/#/reformatter)
+<a href="https://www.patreon.com/sanityinc";><img alt="Support me" 
src="https://img.shields.io/badge/Support%20Me-%F0%9F%92%97-ff69b4.svg";></a>
+
+# Define commands which run reformatters on the current Emacs buffer
+
+This library allows elisp authors to easily provide an idiomatic
+command to reformat the current buffer using a command-line program,
+together with an optional minor mode which can apply this command
+automatically on save.
+
+In its initial release it supports only reformatters which can read
+from stdin and write to stdout, but a more versatile interface will
+be provided as development continues.
+
+As an example, let's define a reformat command that applies the
+"dhall format" command.  We'll assume that we've already defined a
+variable `dhall-command` which holds the string name or path of the
+dhall executable:
+
+    ;;;###autoload (autoload 'dhall-format "current-file" nil t)
+    ;;;###autoload (autoload 'dhall-format-on-save-mode "current-file" nil t)
+    (define-reformatter dhall-format
+      :program dhall-command
+      :args '("format")
+      :lighter 'DF)
+
+The `define-reformatter` macro expands to code which generates both
+the `dhall-format` interactive command and a local minor mode called
+`dhall-format-on-save-mode`.  The example above includes autoloads
+which will be useful to library authors.
+
+The generated minor mode allows idiomatic per-directory or per-file
+customisation, via the "modes" support baked into Emacs' file-local
+and directory-local variables mechanisms.  For example, users of the
+above example might add the following to a project-specific
+`.dir-locals.el` file:
+
+    ((dhall-mode
+       (mode . dhall-format-on-save-mode)))
+
+See the documentation for `define-reformatter`, which provides a
+number of options for customising the generated code.
+
+## Rationale
+
+I contribute to a number of Emacs programming language modes and
+tools, and increasingly use code reformatters in my daily work.  It's
+surprisingly difficult to write robust, correct code to apply these
+reformatters, given that it must consider such issues as:
+
+* Missing programs
+* Buffers not yet saved to a file
+* Displaying error output
+* Colorising ANSI escape sequences in any error output
+* Handling file encodings correctly
+
+With this library, I hope to help the community standardise on best
+practices, and make things easier for tool authors and end users
+alike.
+
+## Installation
+
+### Manual
+
+Ensure `reformatter.el` is in a directory on your load-path, and add
+the following to your `~/.emacs` or `~/.emacs.d/init.el`:
+
+``` lisp
+(require 'reformatter)
+```
+
+### MELPA
+
+If you're an Emacs 24 user or you have a recent version of
+`package.el` you can install `reformatter` from the
+[MELPA](http://melpa.org) repository. The version of
+`reformatter` there will always be up-to-date.
+
+See the command `reformatter`.
+
+## About
+
+Author: Steve Purcell <steve at sanityinc dot com>
+
+Homepage: https://github.com/purcell/reformatter
+
+<hr>
+
+[💝 Support this project and my other Open Source 
work](https://www.patreon.com/sanityinc)
+
+[💼 LinkedIn profile](https://uk.linkedin.com/in/stevepurcell)
+
+[✍ sanityinc.com](http://www.sanityinc.com/)
+
+[🐦 @sanityinc](https://twitter.com/sanityinc)
diff --git a/reformatter.el b/reformatter.el
new file mode 100644
index 0000000000..77c31938ee
--- /dev/null
+++ b/reformatter.el
@@ -0,0 +1,158 @@
+;;; reformatter.el --- Define commands which run reformatters on the current 
buffer  -*- lexical-binding: t; -*-
+
+;; Copyright (C) 2019  Steve Purcell
+
+;; Author: Steve Purcell <steve@sanityinc.com>
+;; Keywords: convenience, tools
+;; Package-Requires: ((emacs "24.3"))
+;; Package-Version: 0
+
+;; This program is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; This program is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <https://www.gnu.org/licenses/>.
+
+;;; Commentary:
+
+;; This library allows elisp authors to easily provide an idiomatic
+;; command to reformat the current buffer using a command-line
+;; program, together with an optional minor mode which can apply this
+;; command automatically on save.
+
+;; In its initial release it supports only reformatters which read
+;; from stdin and write to stdout, but a more versatile interface will
+;; be provided as development continues.
+
+;; As an example, let's define a reformat command that applies the
+;; "dhall format" command.  We'll assume that we've already defined a
+;; variable `dhall-command' which holds the string name or path of the
+;; dhall executable:
+
+;;     ;;;###autoload (autoload 'dhall-format "current-file" nil t)
+;;     ;;;###autoload (autoload 'dhall-format-on-save-mode "current-file" nil 
t)
+;;     (define-reformatter dhall-format
+;;       :program dhall-command
+;;       :args '("format"))
+
+;; The `define-reformatter' macro expands to code which generates both
+;; the `dhall-format' interactive command and a local minor mode
+;; called `dhall-format-on-save-mode'.  The example above includes
+;; autoloads which will be useful to library authors.
+
+;; The generated minor mode allows idiomatic per-directory or per-file
+;; customisation, via the "modes" support baked into Emacs' file-local
+;; and directory-local variables mechanisms.  For example, users of
+;; the above example might add the following to a project-specific
+;; .dir-locals.el file:
+
+;;     ((dhall-mode
+;;       (mode . dhall-format-on-save-mode)))
+
+;; See the documentation for `define-reformatter', which provides a
+;; number of options for customising the generated code.
+
+;;; Code:
+(eval-when-compile
+  (require 'cl-lib))
+(require 'ansi-color)
+
+;;;###autoload
+(cl-defmacro define-reformatter (name &key program args (mode t) lighter 
keymap)
+  "Define a reformatter command with NAME.
+
+When called, the reformatter will use PROGRAM and any ARGS to
+reformat the current buffer.  The contents of the buffer will be
+passed as standard input to the reformatter, which should output
+them to standard output.  A nonzero exit code will be reported as
+failure, and the output of the command to standard error will be
+displayed to the user.
+
+The macro accepts the following keyword arguments:
+
+:program (required)
+
+  Provides a form which should evaluate to a string at runtime,
+  e.g. a literal string, or the name of a variable which holds
+  the program path.
+
+:args
+
+  If provided, this is a form which evaluates to a list of
+  strings at runtime.  Default is the empty list.
+
+:mode
+
+  Unless nil, also generate a minor mode that will call the
+  reformatter command from `before-save-hook' when enabled.
+  Default is t.
+
+:lighter
+
+  If provided, this is a mode lighter symbol or string which will be used
+  for the \"-on-save\" minor mode.  Default is to use no lighter.
+
+:keymap
+
+  If provided, this is the symbol name of the \"-on-save\" mode's
+  keymap, which you must declare yourself.  Default is no keymap.
+"
+  (declare (indent defun))
+  (cl-assert (symbolp name))
+  (cl-assert program)
+  (let ((minor-mode-form
+         (when mode
+           (let ((on-save-mode-name (intern-soft (format "%s-on-save-mode" 
name))))
+             `(define-minor-mode ,on-save-mode-name
+                ,(format "When enabled, call `%s' when this buffer is saved." 
name)
+                nil
+                :global nil
+                ,@(when keymap (list :keymap keymap))
+                ,@(when lighter (list :lighter lighter))
+                (if ,on-save-mode-name
+                    (add-hook 'before-save-hook ',name nil t)
+                  (remove-hook 'before-save-hook ',name t)))))))
+    `(progn
+       (defun ,name (&optional display-errors)
+         "Reformats the current buffer.
+When called interactively, or with prefix argument
+DISPLAY-ERRORS, shows a buffer if the formatting fails."
+         (interactive "p")
+         (message "Formatting buffer")
+         (let* ((err-file (make-temp-file ,(symbol-name name)))
+                (out-file (make-temp-file ,(symbol-name name)))
+                (coding-system-for-read 'utf-8)
+                (coding-system-for-write 'utf-8))
+           (unwind-protect
+               (let* ((error-buffer (get-buffer-create ,(format "*%s errors*" 
name)))
+                      (retcode
+                       (apply 'call-process-region (point-min) (point-max) 
,program
+                              nil (list (list :file out-file) err-file)
+                              nil
+                              ,args)))
+                 (with-current-buffer error-buffer
+                   (let ((inhibit-read-only t))
+                     (insert-file-contents err-file nil nil nil t)
+                     (ansi-color-apply-on-region (point-min) (point-max)))
+                   (special-mode))
+                 (if (eq retcode 0)
+                     (progn
+                       (insert-file-contents out-file nil nil nil t)
+                       (whitespace-cleanup))
+                   (if display-errors
+                       (display-buffer error-buffer)
+                     (message ,(concat (symbol-name name) " failed: see %s") 
(buffer-name error-buffer)))))
+             (delete-file err-file)
+             (delete-file out-file))))
+       ,minor-mode-form)))
+
+
+(provide 'reformatter)
+;;; reformatter.el ends here



reply via email to

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