3

I'm asking for several tips to make editing lisp like languages in evil mode better. In particular there is one feature that I would really like but couldn't manage to get it to work. For example given the following code (cursor is indicated by |):

(line| of code
    (other line of code))

I would like to delete the whole expression with dd (which normally would delete only the line I'm in). Basically I would like to operate on expressions rather then on lines for all the evil commands that are working on lines normally.

Edit: For anyone interested evil-cleverparens looks interesting, too and it has a list of other similar packages at the end of the README.

  • What about lispy ? github.com/abo-abo/lispy#list-commands-overview a vi-like paredit, i.e. a specific mode to edit lisp with evil-mode. – Ehvince Sep 15 '15 at 10:42
  • A wiki page summing up some info: wikemacs.org/wiki/Lisp_editing – Ehvince Sep 15 '15 at 11:45
  • @Ehvince I havn't tried lispy yet but I don't like that I have to be at certain spots in the expressions to have the keybindings available. I would prefer something like a second normal state in evil for lisp like langagues where all commands are optimized for editing lisp code. My question above would be just the starting point for some state like this. – clemera Sep 15 '15 at 13:58
  • Ok, makes sense. Do you know expand-region ? It could help. It can select regions by sexp, starting small and getting more inclusive call by call. For example, in the string (hello "foo | oo"), calling it will select "foo", then "\"foo\"", then "hello \"foooo\"", then with the parenthesis. melpa.org/#/expand-region – Ehvince Sep 15 '15 at 19:14
  • @Ehvince Yes I use it and like it too. I use this because I like to press v just multiple times to expand. – clemera Sep 16 '15 at 9:39
1

Another potential solution is evil-smartparens, which works with smartparens-strict-mode to ensure that the current file is always balanced.

It doesn't behave exactly like you specify. For example:

dd (| stands for the point) on this:

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

Yields this:

(let ((foo 1.01))
  )

However, you may find that the defaults are well chosen in general, and perhaps they will work for you.

  • I accepted this answer to have the question closed. I don't use evil-mode anymore, anyway. – clemera Oct 19 '16 at 10:59
2

Not exactly what you want, but this is what I use:

;; textobject for the sexp immediately before/after point
(defun my/evil-next-thing (count &optional beg end type inclusive)
  (ignore-errors
    (save-excursion
      (call-interactively 'sp-select-next-thing count)
      (if (> (point) (mark))
          (exchange-point-and-mark))
      ;; check, it doesn't make sense to take the "inside" of a symbol
      (if (or inclusive
              (not (and
                    (string-match
                     (string (char-after (point)))
                     "[^[:punct:]([{]")
                    (string-match
                     (string (char-before (mark)))
                     "[^[:punct:])\]}]"))))
          (evil-range (point) (mark))
        (evil-range (1+ (point)) (1- (mark)))))))

(evil-define-text-object evil-a-next-thing (count &optional beg end type)
  "Select the range defined by sp-select-next-thing."
  (my/evil-next-thing count beg end type t))
(evil-define-text-object evil-i-next-thing (count &optional beg end type)
  "Select the range defined by sp-select-next-thing."
  (my/evil-next-thing count beg end type))

(define-key evil-outer-text-objects-map "n" #'evil-a-next-thing)
(define-key evil-inner-text-objects-map "n" #'evil-i-next-thing)

Note: This requires the smartparens package.

To delete your expression, you would use 0dan, which is admittedly a bit longer, but it's a far less intrusive modification to evil.

  • Hey, the guy from flx-search :) small (emacs)world it is :) You just remembered me to look into the flx-search issue I had, I will reply to it later today. Thanks for your answer, but in that case I would prefer to use the built in da( as recommended by the other answer because it is shorter. – clemera Sep 15 '15 at 10:06
1

di( or da( that's not lisp specific stuff, just vim/evil text objects.

  • Thanks, I know that but in my opinion dd would be much more convenient and would make sense in lisp languages anyway because I almost never want to delete lines. – clemera Sep 15 '15 at 9:51
  • you can redefine the key of text object, check evil/evil-maps.el, the original code is: (define-key evil-motion-state-map "(" 'evil-backward-sentence-begin) (define-key evil-motion-state-map ")" 'evil-forward-sentence-begin) – chen bin Sep 15 '15 at 23:25
  • I tried but just rebinding it so that dd deletes the expression does not work. I tried (define-key evil-operator-state-map ")" 'evil-a-paren) which does what I want but with d), maybe I can live with that ;) – clemera Sep 15 '15 at 23:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.