Code Monkey home page Code Monkey logo

parinfer-mode's Introduction

Parinfer Mode

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

images/logo.png

Deprecated

This project is no longer maintained.I have no success for a fast enough implementation in Emacs Lisp.

Fortunately, there’s a parinfer-rust-mode!

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.

parinfer-mode's People

Contributors

ahrjarrett avatar doglooksgood avatar gilch avatar gwbrown avatar jvshahid avatar kisaragi-hiu avatar kwrooijen avatar richardsonpaul avatar syohex avatar tumashu avatar yqrashawn avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

parinfer-mode's Issues

Strategy 'instantly when reindenting region

Hi!

First of all: thanks for developing this amazing mode: editing Lisp is so much fun now!

I am however having trouble trying to always get the strategy 'instantly to work... I would like everything to be instant, I don't care about CPU usage but I find it very confusing when the indentation does not get updated inmmediatelly. In particular, I would like to get parens immediatelly rebalanced when I reindent whole regions. Here is my config:

(use-package parinfer
  :ensure t
  :config
  (parinfer-strategy-add 'instantly
    '(parinfer-smart-tab:dwim-right
      parinfer-smart-tab:dwim-left))
  :bind
  (:map parinfer-mode-map
        ("<tab>" . parinfer-smart-tab:dwim-right)
        ("S-<tab>" . parinfer-smart-tab:dwim-left)
        ("<backtab>" . parinfer-smart-tab:dwim-left)
        ("C-," . parinfer-toggle-mode)
        :map parinfer-region-mode-map
        ("<tab>" . parinfer-smart-tab:dwim-right)
        ("S-<tab>" . parinfer-smart-tab:dwim-left)
        ("<backtab>" . parinfer-smart-tab:dwim-left))
  :init
  (progn
    (setq parinfer-extensions
          '(defaults
             pretty-parens
             smart-tab
             smart-yank))))

However, when I do <tab>, <backtab> with a region selected, the parenthesis do not update inmediatelly. I also have tried things like:

  (parinfer-strategy-add 'instantly "" "*" ".*"))

But I did not get the desired effect. Do you have any suggestions on what can I do? Is this a bug?

Compatibility for cua-mode.

Mentioned at #14 , cua-mode overwrite = the default keybindings, maybe an extension for compatibility is needed.
Need some use cases, e.g. with cua-mode, what we can do? how?

evil mode

Hi it seems when I am in insert mode I can't type "<" or ">" signs. Is there a quick fix for this? Otherwise it works very well with evil mode. Thanks

error when edit the - in the line ";; Homepage: https://github.com/DogLooksGood/parinfer-mode "

Debugger entered--Lisp error: (args-out-of-range "-mode" 5)
  aref("-mode" 5)
  (string (aref line i))
  (parinferlib--close-paren\? (string (aref line i)))
  (if (parinferlib--close-paren\? (string (aref line i))) (progn (setq remove-count (1+ remove-count))))
  (while (< i new-start-x) (if (parinferlib--close-paren\? (string (aref line i))) (progn (setq remove-count (1+ remove-count)))) (setq i (1+ i)))
  (let* ((cursor-x (gethash :cursorX result)) (new-start-x (max start-x cursor-x)) (new-end-x (max end-x cursor-x)) (line-no (gethash :lineNo result)) (lines (gethash :lines result)) (line (aref lines line-no)) (remove-count 0) (i start-x)) (while (< i new-start-x) (if (parinferlib--close-paren\? (string (aref line i))) (progn (setq remove-count (1+ remove-count)))) (setq i (1+ i))) (if (> remove-count 0) (progn (let* ((openers (gethash :parenTrailOpeners result)) (new-openers (nbutlast openers remove-count))) (puthash :parenTrailOpeners new-openers result)))) (puthash :parenTrailStartX new-start-x result) (puthash :parenTrailEndX new-end-x result))
  (progn (let* ((cursor-x (gethash :cursorX result)) (new-start-x (max start-x cursor-x)) (new-end-x (max end-x cursor-x)) (line-no (gethash :lineNo result)) (lines (gethash :lines result)) (line (aref lines line-no)) (remove-count 0) (i start-x)) (while (< i new-start-x) (if (parinferlib--close-paren\? (string (aref line i))) (progn (setq remove-count (1+ remove-count)))) (setq i (1+ i))) (if (> remove-count 0) (progn (let* ((openers (gethash :parenTrailOpeners result)) (new-openers (nbutlast openers remove-count))) (puthash :parenTrailOpeners new-openers result)))) (puthash :parenTrailStartX new-start-x result) (puthash :parenTrailEndX new-end-x result)))
  (if cursor-clamping\? (progn (let* ((cursor-x (gethash :cursorX result)) (new-start-x (max start-x cursor-x)) (new-end-x (max end-x cursor-x)) (line-no (gethash :lineNo result)) (lines (gethash :lines result)) (line (aref lines line-no)) (remove-count 0) (i start-x)) (while (< i new-start-x) (if (parinferlib--close-paren\? (string (aref line i))) (progn (setq remove-count (1+ remove-count)))) (setq i (1+ i))) (if (> remove-count 0) (progn (let* ((openers ...) (new-openers ...)) (puthash :parenTrailOpeners new-openers result)))) (puthash :parenTrailStartX new-start-x result) (puthash :parenTrailEndX new-end-x result))))
  (let* ((start-x (gethash :parenTrailStartX result)) (end-x (gethash :parenTrailEndX result)) (cursor-clamping\? (and (parinferlib--cursor-on-right\? result start-x) (not (parinferlib--cursor-in-comment\? result))))) (if cursor-clamping\? (progn (let* ((cursor-x (gethash :cursorX result)) (new-start-x (max start-x cursor-x)) (new-end-x (max end-x cursor-x)) (line-no (gethash :lineNo result)) (lines (gethash :lines result)) (line (aref lines line-no)) (remove-count 0) (i start-x)) (while (< i new-start-x) (if (parinferlib--close-paren\? (string ...)) (progn (setq remove-count ...))) (setq i (1+ i))) (if (> remove-count 0) (progn (let* (... ...) (puthash :parenTrailOpeners new-openers result)))) (puthash :parenTrailStartX new-start-x result) (puthash :parenTrailEndX new-end-x result)))))
  parinferlib--clamp-paren-trail-to-cursor(#s(hash-table size 65 test eql rehash-size 1.5 rehash-threshold 0.8 data (:mode :indent :origText "-mode\n;; Keywords: Parinfer\n\n;; This file is not part of GNU Emacs.\n\n;; This program is free software; you can redistribute it and/or\n;; modify it under the terms of the GNU General Public License\n;; as published by the Free Software Foundation; either version 3\n;; of the License, or (at your option) any later version.\n\n;; This program is distributed in the hope that it will be useful,\n;; but WITHOUT ANY WARRANTY; without even the implied warranty of\n;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;; GNU General Public License for more details.\n\n;; You should have received a copy of the GNU General Public License\n;; along with GNU Emacs; see the file COPYING.  If not, write to the\n;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,\n;; Boston, MA 02110-1301, USA.\n\n;;; Commentary:\n\n;; Extensions of parinfer\n\n;;; Code:\n\n" :origLines ["-mode" ";; Keywords: Parinfer" "" ";; This file is not part of GNU Emacs." "" ";; 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 GNU Emacs; see the file COPYING.  If not, write to the" ";; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor," ";; Boston, MA 02110-1301, USA." "" ";;; Commentary:" "" ";; Extensions of parinfer" "" ";;; Code:" "" ""] :origCursorX 53 :lines ["-mode" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil] :lineNo 0 :ch "" :x 5 :parenStack nil :tabStops nil :parenTrailLineNo 0 :parenTrailStartX 5 :parenTrailEndX 5 :parenTrailOpeners nil :cursorX 52 :cursorLine 0 :cursorDx nil :previewCursorScope nil :canPreviewCursorScope nil :isInCode t :isEscaping nil :isInStr nil :isInComment nil :commentX nil :quoteDanger nil :trackingIndent nil :skipChar nil :success nil :maxIndent nil :indentDelta 0 :error nil :errorPosCache nil ...)))
  (progn (parinferlib--clamp-paren-trail-to-cursor result) (parinferlib--pop-paren-trail result))
  (cond (in-str\? (parinferlib--invalidate-paren-trail result)) ((equal mode :indent) (progn (parinferlib--clamp-paren-trail-to-cursor result) (parinferlib--pop-paren-trail result))) ((and (equal mode :paren) (not (equal line-no cursor-line))) (parinferlib--clean-paren-trail result)))
  (let* ((in-str\? (gethash :isInStr result)) (mode (gethash :mode result)) (line-no (gethash :lineNo result)) (cursor-line (gethash :cursorLine result))) (cond (in-str\? (parinferlib--invalidate-paren-trail result)) ((equal mode :indent) (progn (parinferlib--clamp-paren-trail-to-cursor result) (parinferlib--pop-paren-trail result))) ((and (equal mode :paren) (not (equal line-no cursor-line))) (parinferlib--clean-paren-trail result))))
  parinferlib--finish-new-paren-trail(#s(hash-table size 65 test eql rehash-size 1.5 rehash-threshold 0.8 data (:mode :indent :origText "-mode\n;; Keywords: Parinfer\n\n;; This file is not part of GNU Emacs.\n\n;; This program is free software; you can redistribute it and/or\n;; modify it under the terms of the GNU General Public License\n;; as published by the Free Software Foundation; either version 3\n;; of the License, or (at your option) any later version.\n\n;; This program is distributed in the hope that it will be useful,\n;; but WITHOUT ANY WARRANTY; without even the implied warranty of\n;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;; GNU General Public License for more details.\n\n;; You should have received a copy of the GNU General Public License\n;; along with GNU Emacs; see the file COPYING.  If not, write to the\n;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,\n;; Boston, MA 02110-1301, USA.\n\n;;; Commentary:\n\n;; Extensions of parinfer\n\n;;; Code:\n\n" :origLines ["-mode" ";; Keywords: Parinfer" "" ";; This file is not part of GNU Emacs." "" ";; 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 GNU Emacs; see the file COPYING.  If not, write to the" ";; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor," ";; Boston, MA 02110-1301, USA." "" ";;; Commentary:" "" ";; Extensions of parinfer" "" ";;; Code:" "" ""] :origCursorX 53 :lines ["-mode" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil] :lineNo 0 :ch "" :x 5 :parenStack nil :tabStops nil :parenTrailLineNo 0 :parenTrailStartX 5 :parenTrailEndX 5 :parenTrailOpeners nil :cursorX 52 :cursorLine 0 :cursorDx nil :previewCursorScope nil :canPreviewCursorScope nil :isInCode t :isEscaping nil :isInStr nil :isInComment nil :commentX nil :quoteDanger nil :trackingIndent nil :skipChar nil :success nil :maxIndent nil :indentDelta 0 :error nil :errorPosCache nil ...)))
  (progn (parinferlib--finish-new-paren-trail result))
  (if (equal (gethash :lineNo result) (gethash :parenTrailLineNo result)) (progn (parinferlib--finish-new-paren-trail result)))
  parinferlib--process-line(#s(hash-table size 65 test eql rehash-size 1.5 rehash-threshold 0.8 data (:mode :indent :origText "-mode\n;; Keywords: Parinfer\n\n;; This file is not part of GNU Emacs.\n\n;; This program is free software; you can redistribute it and/or\n;; modify it under the terms of the GNU General Public License\n;; as published by the Free Software Foundation; either version 3\n;; of the License, or (at your option) any later version.\n\n;; This program is distributed in the hope that it will be useful,\n;; but WITHOUT ANY WARRANTY; without even the implied warranty of\n;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;; GNU General Public License for more details.\n\n;; You should have received a copy of the GNU General Public License\n;; along with GNU Emacs; see the file COPYING.  If not, write to the\n;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,\n;; Boston, MA 02110-1301, USA.\n\n;;; Commentary:\n\n;; Extensions of parinfer\n\n;;; Code:\n\n" :origLines ["-mode" ";; Keywords: Parinfer" "" ";; This file is not part of GNU Emacs." "" ";; 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 GNU Emacs; see the file COPYING.  If not, write to the" ";; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor," ";; Boston, MA 02110-1301, USA." "" ";;; Commentary:" "" ";; Extensions of parinfer" "" ";;; Code:" "" ""] :origCursorX 53 :lines ["-mode" nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil nil] :lineNo 0 :ch "" :x 5 :parenStack nil :tabStops nil :parenTrailLineNo 0 :parenTrailStartX 5 :parenTrailEndX 5 :parenTrailOpeners nil :cursorX 52 :cursorLine 0 :cursorDx nil :previewCursorScope nil :canPreviewCursorScope nil :isInCode t :isEscaping nil :isInStr nil :isInComment nil :commentX nil :quoteDanger nil :trackingIndent nil :skipChar nil :success nil :maxIndent nil :indentDelta 0 :error nil :errorPosCache nil ...)) "-mode")
  (while (< i lines-length) (parinferlib--process-line result (aref orig-lines i)) (setq i (1+ i)))
  (catch (quote parinferlib-error) (while (< i lines-length) (parinferlib--process-line result (aref orig-lines i)) (setq i (1+ i))) (parinferlib--finalize-result result) nil)
  (let* ((result (parinferlib--create-initial-result text mode options)) (orig-lines (gethash :origLines result)) (lines-length (length orig-lines)) (i 0) (err (catch (quote parinferlib-error) (while (< i lines-length) (parinferlib--process-line result (aref orig-lines i)) (setq i (1+ i))) (parinferlib--finalize-result result) nil))) (if err (progn (parinferlib--process-error result err))) result)
  parinferlib--process-text("-mode\n;; Keywords: Parinfer\n\n;; This file is not part of GNU Emacs.\n\n;; This program is free software; you can redistribute it and/or\n;; modify it under the terms of the GNU General Public License\n;; as published by the Free Software Foundation; either version 3\n;; of the License, or (at your option) any later version.\n\n;; This program is distributed in the hope that it will be useful,\n;; but WITHOUT ANY WARRANTY; without even the implied warranty of\n;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;; GNU General Public License for more details.\n\n;; You should have received a copy of the GNU General Public License\n;; along with GNU Emacs; see the file COPYING.  If not, write to the\n;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,\n;; Boston, MA 02110-1301, USA.\n\n;;; Commentary:\n\n;; Extensions of parinfer\n\n;;; Code:\n\n" :indent (:cursor-x 53 :cursor-line 0 :preview-cursor-scope nil))
  (let ((result (parinferlib--process-text text :indent options))) (parinferlib--public-result result))
  parinferlib-indent-mode("-mode\n;; Keywords: Parinfer\n\n;; This file is not part of GNU Emacs.\n\n;; This program is free software; you can redistribute it and/or\n;; modify it under the terms of the GNU General Public License\n;; as published by the Free Software Foundation; either version 3\n;; of the License, or (at your option) any later version.\n\n;; This program is distributed in the hope that it will be useful,\n;; but WITHOUT ANY WARRANTY; without even the implied warranty of\n;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;; GNU General Public License for more details.\n\n;; You should have received a copy of the GNU General Public License\n;; along with GNU Emacs; see the file COPYING.  If not, write to the\n;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,\n;; Boston, MA 02110-1301, USA.\n\n;;; Commentary:\n\n;; Extensions of parinfer\n\n;;; Code:\n\n" (:cursor-x 53 :cursor-line 0 :preview-cursor-scope nil))
  (let* ((opts (plist-get context :opts)) (text (plist-get context :text)) (result (parinferlib-indent-mode text opts))) (parinfer--apply-result result context))
  parinfer--execute-instantly((:text "-mode\n;; Keywords: Parinfer\n\n;; This file is not part of GNU Emacs.\n\n;; This program is free software; you can redistribute it and/or\n;; modify it under the terms of the GNU General Public License\n;; as published by the Free Software Foundation; either version 3\n;; of the License, or (at your option) any later version.\n\n;; This program is distributed in the hope that it will be useful,\n;; but WITHOUT ANY WARRANTY; without even the implied warranty of\n;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;; GNU General Public License for more details.\n\n;; You should have received a copy of the GNU General Public License\n;; along with GNU Emacs; see the file COPYING.  If not, write to the\n;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,\n;; Boston, MA 02110-1301, USA.\n\n;;; Commentary:\n\n;; Extensions of parinfer\n\n;;; Code:\n\n" :opts (:cursor-x 53 :cursor-line 0 :preview-cursor-scope nil) :orig (:start 166 :end 1028 :window-start-pos 1 :line-number 6)))
  (if (> (length text) parinfer-delay-invoke-threshold) (setq parinfer--delay-timer (run-with-idle-timer parinfer-delay-invoke-idle nil (function parinfer-indent-instantly))) (parinfer--execute-instantly context))
  (let ((text (plist-get context :text))) (if (> (length text) parinfer-delay-invoke-threshold) (setq parinfer--delay-timer (run-with-idle-timer parinfer-delay-invoke-idle nil (function parinfer-indent-instantly))) (parinfer--execute-instantly context)))
  parinfer--execute((:text "-mode\n;; Keywords: Parinfer\n\n;; This file is not part of GNU Emacs.\n\n;; This program is free software; you can redistribute it and/or\n;; modify it under the terms of the GNU General Public License\n;; as published by the Free Software Foundation; either version 3\n;; of the License, or (at your option) any later version.\n\n;; This program is distributed in the hope that it will be useful,\n;; but WITHOUT ANY WARRANTY; without even the implied warranty of\n;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n;; GNU General Public License for more details.\n\n;; You should have received a copy of the GNU General Public License\n;; along with GNU Emacs; see the file COPYING.  If not, write to the\n;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,\n;; Boston, MA 02110-1301, USA.\n\n;;; Commentary:\n\n;; Extensions of parinfer\n\n;;; Code:\n\n" :opts (:cursor-x 53 :cursor-line 0 :preview-cursor-scope nil) :orig (:start 166 :end 1028 :window-start-pos 1 :line-number 6)))
  (let ((context (parinfer--prepare))) (parinfer--execute context))
  parinfer-indent()
  (cond ((eq (quote paren) parinfer--mode) (parinfer-paren)) ((eq (quote indent) parinfer--mode) (parinfer-indent)) (t "nothing"))
  (progn (fset (quote message) (function format)) (cond ((eq (quote paren) parinfer--mode) (parinfer-paren)) ((eq (quote indent) parinfer--mode) (parinfer-indent)) (t "nothing")))
  (unwind-protect (progn (fset (quote message) (function format)) (cond ((eq (quote paren) parinfer--mode) (parinfer-paren)) ((eq (quote indent) parinfer--mode) (parinfer-indent)) (t "nothing"))) (fset (quote message) old))
  (let* ((old (symbol-function (quote message)))) (unwind-protect (progn (fset (quote message) (function format)) (cond ((eq (quote paren) parinfer--mode) (parinfer-paren)) ((eq (quote indent) parinfer--mode) (parinfer-indent)) (t "nothing"))) (fset (quote message) old)))
  (if (and pos (not (eq pos (point)))) (let ((current-pos (point))) (goto-char pos) (parinfer--invoke-parinfer) (goto-char current-pos)) (let* ((old (symbol-function (quote message)))) (unwind-protect (progn (fset (quote message) (function format)) (cond ((eq (quote paren) parinfer--mode) (parinfer-paren)) ((eq (quote indent) parinfer--mode) (parinfer-indent)) (t "nothing"))) (fset (quote message) old))))
  parinfer--invoke-parinfer()
  (progn (if (eq (quote paren) parinfer--mode) (if (string-match-p "^[[:space:]]+$" (buffer-substring-no-properties (line-beginning-position) (point))) (delete-indentation) (backward-delete-char 1)) (backward-delete-char 1)) (progn (setq parinfer--text-modified t) (if parinfer-debug (progn (message "parinfer: set parinfer--text-modified to %S." parinfer--text-modified)))) (parinfer--invoke-parinfer))
  parinfer-backward-delete-char()
  funcall-interactively(parinfer-backward-delete-char)
  #<subr call-interactively>(parinfer-backward-delete-char nil nil)
  ad-Advice-call-interactively(#<subr call-interactively> parinfer-backward-delete-char nil nil)
  apply(ad-Advice-call-interactively #<subr call-interactively> (parinfer-backward-delete-char nil nil))
  call-interactively(parinfer-backward-delete-char nil nil)
  command-execute(parinfer-backward-delete-char)

Smart mode status?

What's the status of smart mode? Is it ready for prime time? If so, what is the method for installing the smart mode branch?

Thanks.

Use with Evil.

The parinfer-indent or parinfer-paren should be called after very command in evil normal state and evil visual state.

Yank not work properly.

(defun hello ()
  (print 1) ;; <- yank before this line
  (print 2)
  (print 3)) ;; <- kill this line

the result will be

(defun hello ()
  (print 3))  ;; <- wrong close paren
  (print 1)
  (print 2)

We need to invoke parinfer after cursor position change to fix this.

Poor performance with long lists

Huh, finally I got it. Well, my Emacs package contains ~500 LOC list with face specs here, but when I try to put something at the end of file parinfer causes 1-2 seconds delay before I can see anything in the current buffer. Works fine if I have list with 100 or maybe 200 LOC.

Tested with completely clear Emacs configuration(only parinfer installed) and also with the two other packages(doom-themes and gruvbox) similar to mine.

GNU Emacs 25.3.1 (x86_64-pc-linux-gnu, GTK+ Version 3.22.19) of 2018-02-12
Parinfer installed from MELPA, parinfer-20180214.1040. Default config for use-package taken from README.md.

parinfer no longer starts in indent mode

It wasn't apparent to me since I don't have lighters, but parinfer has been opening in all buffers in paren mode, not indent mode. These files open in paredit/atom in indent mode just fine and without complaints.

save-mark-and-excursion is undefined in the prior version of Emacs

Hi, I found a problem about parinfer-mode but it maybe is not problem of parinfer-mode.
The cursor will auto backward many lines when I use backspace delete char in evil insert state, and the problem went away when I disable parinfer-mode.
The problem only found in Emacs 24.5 on windows 7, not be found in Emacs 24 on debian.

Problems with smart tab on blank line

My .emacs settings relating to parinfer:

(use-package parinfer
  :ensure t
  :config
  (parinfer-strategy-add 'default 'newline-and-indent)
  :bind
  (:map parinfer-mode-map
	("<tab>" . parinfer-smart-tab:dwim-right)
	("S-<tab>" . parinfer-smart-tab:dwim-left)
	("C-i" . parinfer--reindent-sexp)
	("C-M-i" . parinfer-auto-fix)
	("C-," . parinfer-toggle-mode)
	:map parinfer-region-mode-map
	("C-i" . indent-for-tab-command)
	("<tab>" . parinfer-smart-tab:dwim-right)
	("S-<tab>" . parinfer-smart-tab:dwim-left) )
  :init
  (progn
    (setq parinfer-extensions
          '(defaults       ; should be included.
	     pretty-parens  ; different paren styles for different modes
	     smart-yank))   ; Yank behavior depend on mode.
    (add-hook 'clojure-mode-hook #'parinfer-mode)
    (add-hook 'emacs-lisp-mode-hook #'parinfer-mode)))

Example of problem:

(defonce game
  (let [PhaserGame (oget js/Phaser "Game")]
    (PhaserGame. 1152 648 (oget js/Phaser "AUTO") "app" #js{"create" create, "preload" preload})))

In indent mode, position cursor at the end of the let line, and then hit enter, and then hit tab. Instead of moving the cursor to the next reasonable indent position on the blank line, it moves the cursor to the beginning of the next line.

Another issue I'm having is that in indent mode, when the cursor is in the middle of the line and I hit tab to move the line over, the cursor jumps to the end of the line. Is there a way it could stay in its position within the line?

Option to not fiddle with rainbow-delimiter-mode

I think it would be for the best if we could, instead of having an extension that does one thing that might not be what everyone wants (I for instance don't want to use rainbow-delimiter-mode at all, but I do want to use parinfer in both modes), use hooks for this and let the user configure the behavior.

Can't enable paredit extension

File mode specification error: (invalid-function bind-key)
parinfer-paredit:init: Invalid function: bind-key

Installing the bind-key package does not fix the situation, so I'm not quite sure what exactly is broken.

parinfer--prepare: Invalid function: parinfer-save-excursion

After installing parinfer 0.4.10 from MELPA Stable in emacs 24.5 I cannot work on clojure files anymore. Cursor jumps to random place on backspace and in Messages I see lines:
parinfer--prepare: Invalid function: parinfer-save-excursion.

It looks like version 0.4.9 works correctly. Previously I used version 0.4.5 which also worked for me.

Region gets deleted when region is deselected

This is a weird one. Steps to reproduce:

  1. Select a region (while in parinfer mode)
  2. Insert a character: the character gets inserted and the region gets de-selected, as expected.
  3. Press delete: the whole region that was last selected gets unexpectedly deleted. Since no region is visible, I expect it to only delete one character (the one inserted in step 2).

My configuration is:

(use-package parinfer
  :ensure t
  :config
  (parinfer-strategy-add 'instantly
    '(parinfer-smart-tab:dwim-right
      parinfer-smart-tab:dwim-left))
  :bind
  (:map parinfer-mode-map
        ("<tab>" . parinfer-smart-tab:dwim-right)
        ("S-<tab>" . parinfer-smart-tab:dwim-left)
        ("<backtab>" . parinfer-smart-tab:dwim-left)
        ("C-," . parinfer-toggle-mode)
        :map parinfer-region-mode-map
        ("<tab>" . parinfer-smart-tab:dwim-right)
        ("S-<tab>" . parinfer-smart-tab:dwim-left)
        ("<backtab>" . parinfer-smart-tab:dwim-left))
  :init
  (progn
    (setq parinfer-extensions
          '(defaults
             pretty-parens
             smart-tab
             smart-yank))))

Extra quote causing problems

Hi,

This is working really well for me! With one exception:
Say that I type (println "foo"). It actually comes out as (println "foo")") -- when I type the closing quote, an extra quote is created (so at that point it's (println "foo"" with the cursor before the final quote), and then typing the closing paren ends up between those two final quotes. This causes hard-to-track-down bugs in the code, because an indeterminate amount of extra stuff is considered quoted.

I'm on Ubuntu/Gnome, on develop branch, GNU Emacs 25.1.1. Happy to provide any other stats if it'd be helpful.

Thanks for all your work on this!

messed up setq forms in Emacs Lisp

Hello. I have tried parinfer configuration from readme and got my Emacs configuration broken 💢 . Here is an example:

-    :ensure t
-    :config
-    (add-hook 'lsp-mode-hook 'lsp-ui-mode)
-    (setq lsp-ui-doc-enable nil
-         lsp-ui-peek-enable nil
-         lsp-ui-sideline-enable nil
-         lsp-ui-imenu-enable nil
-         lsp-ui-flycheck-enable t))
+              :ensure t
+              :config
+              (add-hook 'lsp-mode-hook 'lsp-ui-mode)
+              (setq lsp-ui-doc-enable nil)
+              lsp-ui-peek-enable nil
+              lsp-ui-sideline-enable nil
+              lsp-ui-imenu-enable nil
+              lsp-ui-flycheck-enable t)
-    (setq org-caldav-calendars
-         '((:calendar-id "xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx"
-                         :files ("~/org/calendar/personal.org")
-                         :inbox "~/org/calendar/personal-inbox.org")))
+              (setq org-caldav-calendars)
+              '((:calendar-id "xxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxx"
+                              :files ("~/org/calendar/personal.org")
+                              :inbox "~/org/calendar/personal-inbox.org"))

To summarize: (setq foo bar baz qux ...) become (setq foo bar) baz qux ...

Not work well with yas + cljr

Use cljr-prefix hh n ar cause issues, have to quit hydra menu with q before press tab for jumping. Need to address if it is relative with parinfer-mode.

Use cljr-prefix a r works correctly.

Parenthesis and Indent re-arangement

Hello Shaun,

There is an issue happens in both Indent and Paren mode: When adding a ; comment inside a function at the right side of a form, parinfer adds parenthesis and re-arranges everything.
For example:

It's written normally (and works ok):
(defun convert-to-letter (num)
  (cond ((equal num 1) "O")
        ((equal num 10) "X") 
        (t " ")))

and when adding a ; comment to any of the cond's clauses, it's becoming:
(defun convert-to-letter (num)
  (cond ((equal num 1) "O"))  ; some comment
  ((equal num 10) "X")
  (t " ")) 

Emacs 25.2

Thank you very much.
nicon

Availability through package-install

Hello,

I think it would be useful to have this great project available to emacs through MELPA or Marmalade.

I was very surprised (and dissapointed) when I saw I can't yet install parinfer in emacs through package.el, while most other modern editors have had parinfer available in their plugin repositories since months ago.

If you could add your project to any of the community emacs packages repositories, I think you would do the emacs project a big favor!

Thanks for sharing your work!

Ediff usability.

I was having major problems with with a merge with Ediff. I think parinfer kept re-indenting or complicating the merge. Is there a way to disable this in ediff mode? Is that possibly my problem?

Incorrect "correction" of emacs lisp code

I'm toying with setting up an emacs from scratch, and I'm trying to work with parfiner before putting in paredit or the like. Anyway, if I have a buffer with this code, auto-indented:

(setq org-src-fontify-natively t
      org-src-tab-acts-natively t)

and then enable parinfer-mode, it starts in paren mode. Switching to indent mode and agreeing to let it modify the buffer gets me this:

  (setq org-src-fontify-natively t)
  org-src-tab-acts-natively t

Which is clearly not correct. Is there some sort of magic I have to do to get elisp code indenting correctly with parinfer?

Emacs (mac): Inspection of the parenthesis pairs with cursor movement is not working.

I just install Parinfer for Emacs and i can’t find out how set on the inspection of parens. You know, the little underscore and the background color to the closing (or opening) paren that indicates a pair of parens around an expression. Although in ATOM it works fine and without any special instructions, in Emacs is not working at all.

The lines added in .emacs file are as follows:

;; Parinfer setup.
(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. (disabled. not installed yet.)
	     ;paredit         ; Introduce some paredit commands. (disabled. not installed yet.)
	     smart-tab       ; C-b & C-f jump positions and smart shift with tab & S-tab.
	     smart-yank))      ; Yank behavior depend on mode.
    
    (setq parinfer-auto-switch-indent-mode nil)  ;; default
    (setq parinfer-auto-switch-indent-mode-when-closing nil)  ;; default
    (setq parinfer-delay-invoke-threshold 6000)  ;; default
    (setq parinfer-delay-invoke-idle 0.3)  ;; default
    (setq parinfer-lighters '(" Parinfer:Indent" . "Parinfer:Paren"))
    (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)))

Wrapping parens doesn't work

I don't have any fancy config. I just configured parinfer-mode as suggested, i.e. it is a very default setup →

  (use-package parinfer
    :bind (("C-," . parinfer-toggle-mode))
    :defer t
    :hook ((lisp-mode       . parinfer-mode)
           (clojure-mode    . parinfer-mode)
           (emacs-lisp-mode . parinfer-mode)
           (scheme-mode     . parinfer-mode))
    :init (setq parinfer-extensions '(defaults pretty-parens evil)
                  parinfer-auto-switch-indent-mode t))

But inserting a '(' before another doesn't work as suggested over here

Expected:

(foo [1 2 3 4 5 6])

Actual:

(foo []1 2 3 4 5 6)

Trying to insert before 1 causes this behavior.

Use with Lispy.

I think lispy-mode can be used with parinfer-mode(Indent Mode), the compatibility problem should be easy to fix.
And there should be a document for 'why we like to integrate parinfer with lispy'.

Parinfer-mode insists on breaking this code in indent mode

I have this code in my emacs config:

(setq-default mode-line-format
	      '("    "
		(:eval (case evil-state
			 ('normal "N")
			 ('insert "I")
			 ('visual "V")
			 ('emacs  "E")))
		" %04l %n "
		"    "
		(:propertize (:eval (if buffer-read-only " RO: "))
			     face font-lock-warning-face)
		(:propertize "%b"
			     face font-lock-keyword-face)
		" "
		(:eval (if (buffer-modified-p) "(!!)"))
		" "
		(:propertize
		 (:eval (when (magit-get-current-branch)
			  (concat " [" (magit-get-current-branch) "]")))
		 face font-lock-string-face)
		" :: "
		(:propertize "%m"
			     face font-lock-constant-face)
		" %e "
		(:eval (format-time-string "%H:%M" (current-time)))
		" %-"))

Whenever I switch to parinfer-indent-mode it breaks the parens, and makes it impossible to get the correct parens back for the first case sexp, it forces 3 closing parens at the end of the line and no matter how I indent the 4 cases underneath the parens dont seem to be affected.

The entire block turns into this:

(setq-default mode-line-format
        '("    ")
    (:eval (case evil-state)
       ('normal "N")
       ('insert "I")
       ('visual "V")
       ('emacs  "E"))
    " %04l %n "
    "    "
    (:propertize (:eval (if buffer-read-only " RO: "))
           face font-lock-warning-face)
    (:propertize "%b"
           face font-lock-keyword-face)
    " "
    (:eval (if (buffer-modified-p) "(!!)"))
    " "
    (:propertize
     (:eval (when (magit-get-current-branch))
        (concat " [" (magit-get-current-branch) "]"))
     face font-lock-string-face)
    " :: "
    (:propertize "%m"
           face font-lock-constant-face)
    " %e "
    (:eval (format-time-string "%H:%M" (current-time)))
    " %-")

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.