Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/justinbarclay/parinfer-rust-mode
Simplifying how you write Lisp
https://github.com/justinbarclay/parinfer-rust-mode
Last synced: about 1 month ago
JSON representation
Simplifying how you write Lisp
- Host: GitHub
- URL: https://github.com/justinbarclay/parinfer-rust-mode
- Owner: justinbarclay
- License: gpl-3.0
- Created: 2019-06-01T18:30:57.000Z (over 5 years ago)
- Default Branch: main
- Last Pushed: 2024-11-09T04:53:45.000Z (3 months ago)
- Last Synced: 2025-01-19T18:06:49.332Z (about 1 month ago)
- Language: Emacs Lisp
- Homepage: https://shaunlebron.github.io/parinfer/
- Size: 5.55 MB
- Stars: 241
- Watchers: 6
- Forks: 17
- Open Issues: 7
-
Metadata Files:
- Readme: readme.org
- License: LICENSE
Awesome Lists containing this project
README
#+ATTR_HTML: :alt "Github Actions"
[[https://github.com/justinbarclay/parinfer-rust-mode/actions/workflows/test.yml/badge.svg][https://github.com/justinbarclay/parinfer-rust-mode/actions/workflows/test.yml/badge.svg]]
[[https://melpa.org/#/parinfer-rust-mode][file:https://melpa.org/packages/parinfer-rust-mode-badge.svg]]
[[https://stable.melpa.org/#/parinfer-rust-mode][file:https://stable.melpa.org/packages/parinfer-rust-mode-badge.svg]][[file:https://raw.githubusercontent.com/ocodo/parinfer-logo/master/pngs/parinfer-org-logo-128x128.png]]
* Parinfer
[[https://shaunlebron.github.io/parinfer/][Parinfer]] is a plugin that aims to make writing lisp simple. This library is a minimalistic wrapper around [[https://github.com/justinbarclay/parinfer-rust][justinbarclay/parinfer-rust-emacs]], an Emacs-centric fork of [[https://github.com/eraserhd/parinfer-rust][eraserhd/parinfer-rust]], to provide an Emacs minor mode. parinfer-rust-mode aims to be a simple implementation of Parinfer that leverages the parinfer-rust plugin to do most of the heavy lifting.#+begin_quote
[!WARNING]
Version 0.9 and greater of ~parinfer-rust-mode~ only supports my fork of ~parinfer-rust~, ~parinfer-rust-emacs~. My primary reason for forking was to add better support for ~parinfer-rust~ options, which will allow ~parinfer-rust-mode~ to work better with non-clojure-like lisps. You can read more [[https://github.com/justinbarclay/parinfer-rust/discussions/9][here]].For those wanting to continue using ~parinfer-rust~, you should pin your install to version 0.8.5.
#+end_quote** Capabilities:
- Making code auto-adhere to formatting conventions
- Influencing expression-nesting with indentation
- Maintaining indentation when expressions shift
- Allowing Paredit-like features without hot keys
** Requirements
1. Emacs (26+) compiled with Dynamic Module support.
2. Running on MacOS/Linux, with Windows support coming soon.
3. (Optional) Curl - to download the library for you
** Installation
*** parinfer-rust-mode
**** From source
You can install ~parinfer-rust-mode~ from source (this github repo)
#+BEGIN_SRC shell
cd /path/for/elisp-packages
git clone [email protected]:justinbarclay/parinfer-rust-mode.git
#+END_SRCAfter that add it to your load path and go wild.
#+BEGIN_SRC emacs-lisp
(add-to-list 'load-path "/path/to/parinfer-rust-mode")
(require 'parinfer-rust-mode)
(add-hook 'emacs-lisp-mode 'parinfer-rust-mode)
#+END_SRC**** Use Package
Alternatively, you can tell something like [[https://github.com/quelpa/quelpa-use-package][use-package]] to manage it for you.
#+BEGIN_SRC emacs-lisp
(use-package parinfer-rust-mode
:hook emacs-lisp-mode)
#+END_SRC*** parinfer-rust library
You'll also need to have the library installed on your system for you somewhere.
**** Option 1: Let Parinfer Rust install it for you
That's it. There are no instructions here. When parinfer-rust-mode prompts you to download the library, say yes. ~parinfer-rust-mode~ will then use curl to download ~parinfer-rust~ and save it in ~${EMACS_DIRECTORY}/parinfer-rust/~./Supported OS & Arch[fn:1]/
#+NAME: Supported OS
| Operating System | Architecture |
| Windows | x86_64 |
| Darwin | aarch64 |
| Linux | x86_64 |
| Freebsd | x86_64 |
#+BEGIN_QUOTE
List of supported operating systems and the architecture for which libraries are prebuilt
#+END_QUOTEIf you're curious, you can find the library files that parinfer-rust-mode downloads as release artifacts for [[https://github.com/eraserhd/parinfer-rust/releases][parinfer-rust-emacs]].
If you would always like parinfer-rust-mode to keep the library version in sync for you, automatically download it, then add the following line into your config:
#+BEGIN_SRC emacs-lisp
(setq parinfer-rust-auto-download t)
#+END_SRCIf you are using the ==use-package== snippet from above, that would look like:
#+BEGIN_SRC emacs-lisp
(use-package parinfer-rust-mode
:hook emacs-lisp-mode
:init
(setq parinfer-rust-auto-download t))
#+END_SRC[fn:1] Don't see your OS/Arch on here? Feel free to open up a PR at [[https://github.com/justinbarclay/parinfer-rust][parinfer-rust-emacs]] and add your OS to the GitHub actions.
**** Option 2: Building library from sources
For the more adventurous, you can also download and compile the ~parinfer-rust~ library from source.
***** Step 1: Build the Parinfer Rust Emacs library
When manually compiling the library, the file name differs from platform to platform. Additionally, Emacs expects that these libraries have specific file extensions when first loading them up. This is a problem for MacOS because Rust compiles it as ~.dylib~, and we'll need to give the file an ~.so~ extension when we copy it to its final location.| Platform | File name | Required extension |
|----------+------------------------+--------------------|
| Linux | libparinfer_rust.so | .so |
| MacOS | libparinfer_rust.dylib | .so |
| Windows | parinfer_rust.dll | .dll |#+BEGIN_SRC shell
git clone https://github.com/justinbarclay/parinfer-rust-emacs.git
cd parinfer-rust
cargo build --release
cp ./target/release/${library-name} ~/.emacs.d/parinfer-rust/${lib-name}
#+END_SRC
***** Step 2: Configure parinfer-rust-mode
Once you have compiled the libraries from source code you'll need to tell ~parinfer-rust-mode~ how to find these libraries
#+BEGIN_SRC elisp
(setq parinfer-rust-library "/path/to/parinfer-rust-library.so")
#+END_SRC** Modes
Parinfer can operate under three different modes when writing lisp.
*** Paren
Paren Mode gives you full control of parens, while Parinfer corrects indentation. You can still adjust indentation, but you won't be able to indent/dedent past certain boundaries set by parens on previous lines.[[./videos/paren-mode.gif]]
*** Indent
Indent Mode gives you full control of indentation, while Parinfer corrects or inserts close-parens where appropriate. Specifically, it only touches the groups of close-parens at the end of each line.[[./videos/indent-mode.gif]]
*** Smart
Smart Mode is like Indent Mode, but it tries to preserve the structure too.[[./videos/smart-mode.gif]]
** Commands
| Command | Description |
|---------------------------------+-------------------------------------------------------|
| parinfer-rust-switch-mode | Quickly switch between paren, indent, and smart modes |
| parinfer-rust-toggle-disable | Toggle parinfer-rust-mode mode on or off |
| parinfer-rust-toggle-paren-mode | Toggle between paren mode and current mode |These commands are no longer bound to the ~C-c C-p~ prefix keys by default.
If you prefer to use the old bindings, add this to your configuration (keep in mind it may clash with some major mode bindings):#+begin_src elisp
(define-key parinfer-rust-mode-map (kbd "C-c C-p t") #'parinfer-rust-toggle-paren-mode)
(define-key parinfer-rust-mode-map (kbd "C-c C-p s") #'parinfer-rust-switch-mode)
(define-key parinfer-rust-mode-map (kbd "C-c C-p d") #'parinfer-rust-toggle-disable)
#+end_src** Customizations
parinfer-rust-mode is purposefully light on option, but it does give a few options to tweak behavior.- ~parinfer-rust-library~
The location to find or install the parinfer-rust library.
#+BEGIN_QUOTE
default: ~/.emacs.d/parinfer-rust/parinfer-rust-*.so
#+END_QUOTE- ~parinfer-rust-library-dir~
The directory to store or to find the parinfer-rust library in. This allows a more fine grained approach to installing the parinfer library, if you don't want to rename the library itself.
#+BEGIN_QUOTE
default: ~/.emacs.d/parinfer-rust/parinfer-rust-*.so
#+END_QUOTE- ~parinfer-rust-preferred-mode~
The mode you want parinfer-rust-mode to start in.
Options:
+ smart
+ indent
+ paren#+BEGIN_QUOTE
default: smart
#+END_QUOTE
- ~parinfer-rust-check-before-enable~Perform check on indentation before enabling `parinfer-rust-mode'
If Parinfer detects that it needs to change the indentation in the before first running, it will prompt the user whether it is OK to adjust the indentation. If the user disagrees Parinfer will disable itself. The user may choose to get the prompt immediately whenever parinfer-rust-mode is enabled, defer it until the first change in the buffer, or disable it and never receive a prompt. When disabled, parinfer-rust-mode will run automatically balance the indentation for the user.
Options:
+ immediate
+ defer
+ nil
#+BEGIN_QUOTE
default: defer
#+END_QUOTE
- ~parinfer-rust-auto-download~Have parinfer-rust-mode download the latest version of the parinfer-rust library without prompting you. Generally used for automating your set-up.
#+BEGIN_QUOTE
default: nil
#+END_QUOTE
- ~parinfer-rust-dim-parens~Dim parentheses that are inferred by Parinfer in ~indent~ and ~smart~ modes. Color can be configured via the ~parinfer-rust-dim-parens~ face.
#+BEGIN_QUOTE
default: t
#+END_QUOTE- ~parinfer-rust-troublesome-modes~
A list of modes that may conflict when run alongside parinfer-rust-mode. ~parinfer-rust-mode~ will check for these modes when first enabled in a buffer and it will prompt to disable these modes for you. To disable parinfer-rust for checking for these modes, parinfer-rust-troublesome-modes to nil.
#+BEGIN_QUOTE
default: (electric-pair-mode hungry-delete-mode global-hungry-delete-mode)
#+END_QUOTE- ~parinfer-rust-disable-troublesome-modes~
Disables troublesome modes without prompting the user.
Troublesome modes are listed in `parinfer-rust-disable-troublesome-modes'.
Set this to non-nil to disable troublesome modes without prompting.
#+BEGIN_QUOTE
default: nil
#+END_QUOTE
- ~parinfer-rust-buffer-replace-strategy~
The strategy to use when replacing the buffer's text.When set to `safe' the buffer is replaced using the slower but more
fastiduous `replace-buffer-contents'.
When set to `fast' the buffer is replaced using `delete-region'.
For more info on why the default is `replace-buffer-contents', see Info
node `(elisp)Replacing'Options:
+ safe
+ fast
#+begin_quote
default: safe
#+end_quote
** Error reporting
parinfer-rust-mode uses flycheck and flymake to report parsing errors.
*** Flymake
There should be no config needed to work in ==flymake-mode== is enabled.
*** Flycheck
parinfer-rust-mode is set-up to be chained with the ==emacs-lisp== checker.However, if you want it to work alongside other checkers you'll need to [[https://www.flycheck.org/en/latest/user/syntax-checkers.html#configuring-checker-chains][chain]] it yourself.
#+begin_src emacs-lisp
(use-package parinfer-rust-mode
:config
(flycheck-add-next-checker 'emacs-lisp 'parinfer-rust t))
#+end_src
*** Message buffer
If neither Flycheck or Flymake are enabled then ==parinfer-rust-mode== will output the error to ==*Messages*== buffer.
** parinfer-mode
There is an alternate implementation of Parinfer for Emacs called [[https://github.com/DogLooksGood/parinfer-mode][parinfer-mode]]. It currently has support for Parinfer's "paren" and "indent". Additionally, it has had experimental support for "smart" mode, however, this has remained hidden on a branch and not accessible from MELPA for over a year.
parinfer-smart-mode aims to be a simpler adaptation of Parinfer that just offers "smart mode", leveraging the parinfer-rust plugin to do most of the heavy lifting.
** Known Issues
- Multiple cursors do not work as intended
- Does not play well with other modes that insert parens or manage whitespace. If you have modes like electric-pair-mode or hungry-delete-mode enabled, you may want to disable them for any mode that has parinfer-rust-mode enabled. To help users work around this we offer to disable known troublesome modes if we detect them.
*** Troubleshooting
Sometimes ~parinfer-rust-mode~ can get confused when interacting with some minor modes or certain commands. Check out the wiki for known [[https://github.com/justinbarclay/parinfer-rust-mode/wiki][issues]].
** Reporting bugs
In some cases, parinfer-rust-mode can misbehave by making the wrong choices. When that happens I recommend you file a bug report. If you want to make my life easier, I recommend following [[https://github.com/justinbarclay/parinfer-rust-mode/issues/7][these]] [[https://github.com/justinbarclay/parinfer-rust-mode/issues/9][two]] as some pretty great examples on how to file a bug report.
** Contributing
If you'd like to help contribute to the development of ~parinfer-rust-mode~ the only caveat interesting section of note is the testing framework.~parinfer-rust-mode~ relies on [[https://github.com/cask/cask][Cask]] to manage development libraries and to set-up the tests themselves.
Then after you have made some changes just run:
#+BEGIN_SRC shell
PARINFER_RUST_TEST=true make test
#+END_SRCAnd you should get something like:
#+BEGIN_SRC shell
✦ ❯ PARINFER_RUST_TEST=true make test
emacs --version
GNU Emacs 28.0.50
Copyright (C) 2020 Free Software Foundation, Inc.
GNU Emacs comes with ABSOLUTELY NO WARRANTY.
You may redistribute copies of GNU Emacs
under the terms of the GNU General Public License.
For more information about these matters, see the file named COPYING.
cask build
Compiling /home/justin/dev/parinfer-rust-mode/parinfer-helper.el...
Compiling /home/justin/dev/parinfer-rust-mode/parinfer-rust-mode-autoloads.el...
Compiling /home/justin/dev/parinfer-rust-mode/parinfer-rust-mode.el...In toplevel form:
parinfer-rust-mode.el:72:1: Error: Symbol’s value as variable is void: parinfer-rust-library
Compiling /home/justin/dev/parinfer-rust-mode/test-helper.el...
cask exec ert-runner test/**.el --quiet
...............................................................................................................................................Ran 143 tests in 0.061 seconds
#+END_SRC
** Thanks
- Shaun Lebron for creating Parinfer
- Jason Felice for creating and maintaining the parinfer-rust project
- tianshu for helping me fall in love with parinfer-mode in Emacs.
- Andrey Orst for his contributions to this project
- Gerry Agbobada for adding support to customize options in parinfer-rust-emacs