Lisp editing

From WikEmacs
Revision as of 17:40, 21 September 2015 by Elvince (talk | contribs) (→‎Paxedit)
Jump to navigation Jump to search

Tips on how to edit lisp code efficiently.

Built-in modes

Extensions

Smartparens

Smartparens is a minor mode for Emacs that deals with parens pairs and tries to be smart about it.

It is available in melpa.

Paxedit

Paxedit is an Emacs extension which eliminates the work, tedium, and mistakes involved with manual editing and refactoring LISP code. Paxedit allows the quick refactoring of symbols, symbolic expressions (explicit and implicit), and comments. Normally a unique command or set of commands would allow a user to delete, copy, or transpose symbols, symbolic expressions, or comments. Additionally, after executing some delete or general refactoring commands the user must clean up any extraneous whitespace, correct indentation, and make sure all their expressions are balanced.

Paxedit takes a departure from the above manual state of code editing through automation. Paxedit does away with multiple different commands. Paxedit knows when it’s in a symbol or a comment. Paxedit does the right thing in the right context. For example, Paxedit has one delete command which can be used to delete comments and symbolic expressions explicit and implicit. That is just one of many Paxedit’s context aware commands. Additionally, all Paxedit commands by default cleanup whitespace, fix indentation issues caused by refactoring, and expressions stay balanced.


  • Conceptually consistent
  • Parenthesis, brackets, quotes, etc. stay balanced
  • Removes the need to select different commands for different contexts
  • No need for manual whitespace cleanup
  • Code stays correctly indented
  • Understands implicit expressions
  • Customizable: Can be extended to work for other languages, Can even be used for general text editing

Example

The sign "-!-" stands for the cursor:

(if x
    (message-!- "It's true!")
  (message "It's false!"))

;;; To delete the "(message "It's true!")" symbolic
;;; expression from the containing if expression
;;; consider the number of steps required.

;;; 1. Move the cursor to the outside of the expression

(if x
    -!-(message "It's true!")
  (message "It's false!"))

;;; 2. Delete the expression with a command that deletes the expression

(if x
    -!-
  (message "It's false!"))

;;; 3. Clean up the remaining whitespace

(if x-!-
  (message "It's false!"))

;;; Paxedit can accomplish the above in one command.
;;; Place the cursor inside the expression you want
;;; to delete and run the command:
;;; paxedit-delete

There are many more examples in the project's page.

Installation

It is available in melpa.

With evil-mode

Lispy, a vi-like paredit

Lispy makes it easier to edit lisp code when we use evil-mode.

It offers very short keybindings. For example, going to the next parenthesis is bound to j, s moves down the current expression, e to eval and xe to edebug, xd turns current lambda into a defun, etc

The price to pay is that the bindings are only active when:

  • the point is before an open paren: (, [ or {
  • the point is after a close paren: ), ] or }
  • the region is active

Installation

Via MELPA:

   M-x package-install RET lispy RET

(you might want to M-x package-refresh-content beforehand).

Evil-smartparens

evil-smartparens is a minor mode which makes evil play nicely with smartparens. It helps keeping expressions balanced when you type evil commands like dd.

It is available on Melpa.

Let's take the example of dd, which in evil-mode means "delete the current line". Let's consider the following expression, where the cursor is represented by "|":

(let| ((foo 1.01))
  (frobnicate foo))

If we hit dd then nothing will happen. But If we move down a line and hit dd then we will see:

(let ((foo 1.01))
  )

The last parenthesis is preserved to keep our s-expression correct. You can see many more examples on the project's page.

Evil-cleverparens

Evil-cleverparens has a lot in common with evil-smartparens but has some more features, like helpers for navigation, moving expressions around, slurping and barfing and wrapping text.

Tips and tricks

Integrate expand-region

expand-region is handy because it permits to expand the region by semantic units. For example, in the string (hello "foo | oo"), calling it the first will select "foo", then "\"foo\"", then "hello \"foooo\"", then the whole expression with the parenthesis.

The following snippet binds "v" to expand-region when the region is active.

;; https://emacs.stackexchange.com/questions/16614/make-evil-mode-more-lisp-friendly
(defun evil-visual-char-or-expand-region ()
  (interactive)
  (if (region-active-p)
        (call-interactively 'er/expand-region)
    (evil-visual-char)))

(define-key evil-normal-state-map "v" 'evil-visual-char-or-expand-region)
(define-key evil-visual-state-map "v" 'evil-visual-char-or-expand-region)
(define-key evil-visual-state-map [escape] 'evil-visual-char)

Make "dd" delete an expression

di( or da( isn't specific to lisp, they are just evil text objects.

See also

The emacs lisp page.