/parinfer-mode

Parinfer for Emacs :)

Primary LanguageEmacs LispGNU General Public License v3.0GPL-3.0

Parinfer Mode

https://melpa.org/packages/parinfer-badge.svg https://stable.melpa.org/packages/parinfer-badge.svg

images/logo.png

About Smart Mode

Currently this project is rewriting for providing smart mode on branch `smart`. It’s under development and highly experimental, should be used for testing only.

Smart Mode combines Indent Mode and Paren Mode since parinfer v3.0. `parinfer-smart.el` provide `Smart Mode` implementation. This is NOT compatible with the old `parinfer-mode`.

If you want to have a try:

(require 'parinfer-smart)

;; M-x parinfer-mode<RET>

Performance

`parinfer-smart` is much faster than the old version, with `byte-compile`, it can process 1.7k lines in 40ms on my MBP2015.

Demo

images/demo.gif

Table of contents

What Is Parinfer

Parinfer is a proof-of-concept editor mode for Lisp programming languages. It will infer some changes to keep Parens and Indentation inline with one another. Parinfer consists of two modes:

Indent Mode
Indent Mode gives you full control of indentation, while Parinfer corrects parens.
Paren Mode
Paren Mode gives you full control of parens, while Parinfer corrects indentation.

To learn more about Parinfer, please take a look at its home page.

And the parinfer-mode is the implementation on Emacs with parinfer-elisp.

Installation

Parinfer is available on MELPA(and MELPA Stable) now, I recommend to install with use-package.

Add following code to your .emacs or init.el.

(use-package parinfer
  :ensure t
  :bind
  (("C-," . parinfer-toggle-mode))
  :init
  (progn
    (setq parinfer-extensions
          '(defaults       ; should be included.
            pretty-parens  ; different paren styles for different modes.
            evil           ; If you use Evil.
            lispy          ; If you use Lispy. With this extension, you should install Lispy and do not enable lispy-mode directly.
            paredit        ; Introduce some paredit commands.
            smart-tab      ; C-b & C-f jump positions and smart shift with tab & S-tab.
            smart-yank))   ; Yank behavior depend on mode.
    (add-hook 'clojure-mode-hook #'parinfer-mode)
    (add-hook 'emacs-lisp-mode-hook #'parinfer-mode)
    (add-hook 'common-lisp-mode-hook #'parinfer-mode)
    (add-hook 'scheme-mode-hook #'parinfer-mode)
    (add-hook 'lisp-mode-hook #'parinfer-mode)))

Indent And Paren Modes

Toggle Indent Mode and Paren Mode with command parinfer-toggle-mode.

Avoid unexpect buffer changes.

Whenever you switch to Indent Mode, parinfer-mode will correct all parens of current buffer.

After opening a file, the parinfer-mode enable Indent Mode if it won’t make any changes. Otherwise, Paren Mode will be enabled, you can switch to Indent Mode manually later.

Alternatively, you can use parinfer-diff command to see how will Indent Mode modify the buffer with Ediff.

images/diff_demo.gif

And there are some keybindings in Ediff:

KeyDescription
qQuit diff.
bB->A in Ediff, this can apply change to your origin code.
raRestore A in Ediff, this can revert change.
nMove to next difference.
pMove to previous difference.

Also, There’s a command parinfer-auto-fix to fix wrong indentation for whole buffer. (Only works with balanced parens)

Configurations

parinfer-auto-switch-indent-mode

(setq parinfer-auto-switch-indent-mode nil)  ;; default

t for enable, Parinfer will auto switch to Indent Mode whenever parens are balance in Paren Mode.

parinfer-auto-switch-indent-mode-when-closing

(setq parinfer-auto-switch-indent-mode-when-closing nil)  ;; default

t for enable, Parinfer will auto switch to Indent Mode when the inserted close parens (), ], }) balance the parens of current sexp.

parinfer-delay-invoke-threshold

(setq parinfer-delay-invoke-threshold 6000)  ;; default

When the length of text for processing is longer than this, Parinfer will process text after a idle delay instead of process immediately.

parinfer-delay-invoke-idle

(setq parinfer-delay-invoke-idle 0.3)  ;; default

The idle seconds before Parinfer processing text on large sexp.

parinfer-extensions

(setq parinfer-extensions '(defaults pretty-parens smart-yank))

The extensions that will be enabled. The list could contain followings:

ExtensionFunction
defaultsShould be enabled, basic compatibility
pretty-parensUse dim style for Indent Mode, rainbow delimiters for Paren Mode
smart-yankYank will preserve indentation in Indent Mode, will preserve parens in Paren Mode
smart-tabC-f & C-b on empty line will goto next/previous import indentation.
pareditIntroduce some paredit commands from paredit-mode.
lispyIntegration with Lispy.
evilIntegration with Evil.
oneExperimental on fuzz Indent Mode and Paren Mode. Not recommanded.

parinfer-lighters

(setq parinfer-lighters '(" Parinfer:Indent" . "Parinfer:Paren"))

Troubleshooting

If Parinfer seems to be indenting incorrectly, ensure indent-tabs-mode is set to nil via (setq-default indent-tabs-mode nil). While Parinfer’s theoretical model is able to correctly handle indentation with tabs, parinfer-mode can currently only handle indentation using spaces.

Credits

shaunlebron
Create Parinfer.
oakmac
Bring Parinfer to Emacs with parinfer-elisp.
tumashu
Help me a lot in writing this plugin.
purcell & syohex
Advice and Tips for writing emacs plugin

Contribution

Please open an issue if there’s any bug or suggestion, and PR is welcomed!

License

parinferlib.el from parinfer-elisp, is licensed under the ISC.

Rest part licensed under the GPLv3.