When I press dd in haskell-interactive-mode at the prompt, it doesn't delete anything, because part of the line is read-only. I would like to map dd to 'haskell-interactive-mode-kill-whole-line.


(evil-define-key 'normal haskell-interactive-mode-map
  (kbd "dd") 'haskell-interactive-mode-kill-whole-line)

doesn't solve the problem. Although it binds dd, it clobbers evil-mode's d binding, making commands like dw no longer work. Just adding things to the evil-operator-shortcut-map (like what evil-surround does) doesn't quite cut it either, because that would bind nonsensical sequences like yd which should remain unbound.

These two links are relevant, but not quite answers.

  • yd? What does that do? – PythonNut May 22 '15 at 4:29
  • Nothing, as it should. – Alex R May 22 '15 at 14:49
  • If you are still interested, I can immediately post a high-quality solution. Would you open bounty for that? – Alexander Shukaev Aug 21 '15 at 20:10
  • Sure. It's not like I'm using that reputation for anything anyway. – Alex R Aug 22 '15 at 2:02

Your initial idea to merely remap dd has another subtle issue. As you surely know Vd is basically the same as dd (in a sense that it operates on a whole line), so it should also exhibit the same desired behavior somehow (i.e. use haskell-interactive-mode-kill-whole-line as a back end). I hope it's clear that this also applies to an infinite set of other possibilities: 10dd, Vjjjd, and etc. Hence, we are going to define our own haskell-delete operator (thanks to the Evil framework facilities):

(evil-define-operator haskell-delete
    (beg end type register yank-handler)
  "Delete text from BEG to END with TYPE.
Save in REGISTER or in the kill-ring with YANK-HANDLER."
  (interactive "<R><x><y>")
  (if (eq type 'line)
        (unless register
          (let ((text (filter-buffer-substring beg end)))
            (unless (string-match-p "\n" text)
              (evil-set-register ?- text))))
        (let ((evil-was-yanked-without-register nil))
          (evil-yank beg end type register yank-handler))
        (dotimes (var (count-lines beg end))
    (evil-delete beg end type register yank-handler))
  (when (and (evil-called-interactively-p)
             (eq type 'line))

And now simply remap d in haskell-interactive-mode-map specific to the Normal state:

(evil-define-key 'normal haskell-interactive-mode-map
  (kbd "d") #'haskell-delete)

Please, let me know if you encounter any issues, so that we could jointly fix them.

| improve this answer | |
  • That looks like it will work. I'll try it and get back to you. – Alex R Aug 22 '15 at 20:38
  • This seems to work; the only problem is that it puts the point at the beginning of the line rather than at the end. Replacing (evil-first-non-blank) with (evil-end-of-line) solves that. Would you consider explaining your operator definition so that I could write my own for yy and cc? – Alex R Aug 25 '15 at 17:54
  • Simply take a look at what evil-delete does. The part with register dancing is there to handle yanking of what you delete (same way the default evil-delete does, thus this code is copy/paste from it). The loop simply solves the problem when several lines are involved. The very last part with evil-first-non-black is again copy/paste from evil-delete (i.e. that's how default delete operator is expected to function, hence your choice of evil-end-of-line looks weird to me). The condition on whether type is 'line distinguishes the case where we want to apply operator to line(s). – Alexander Shukaev Aug 25 '15 at 19:03
  • evil-first-non-blank puts the point before the prompt. – Alex R Aug 26 '15 at 3:51

I found that the right way to map operators is using evil-operator-state-map. So this

(defun my-haskell-maps() 
  (define-key evil-operator-state-local-map
  "D" 'haskell-interactive-mode-kill-whole-line))

(add-hook 'haskell-interactive-mode-hook 'my-haskell-maps)

will map dD to the correct function without interfere with the other d operators. However, for some reason, mapping dd does not work. Maybe because it doesn't override evil defaults. I'll let you know if I manage to fix the dd binding

| improve this answer | |
  • It's probably because evil hardcodes repetition of the operator as a line-wise operation, hacking around that will be more involved than your snippet I'm afraid. – wasamasa May 22 '15 at 18:59
  • The relevant portion of the code that defines "dd" (albeit indirectly) is: gitorious.org/evil/evil/source/… – Alex R May 22 '15 at 20:03

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.