vimemacseditorediting

Emacs equivalents of Vim's dd,o,O


I am currently playing around with emacs and happy with most of the concepts. But I really adored the convenience of the three vim commands: dd,o,O Hopefully you can tell me how to mirror them in emacs :)

dd - deletes whole line, including newline, no matter where the cursor is.

I found something similar to do the trick:

C-a C-k C-k

While C-a moves the cursor to the beginning of the line, the first C-k kills the text, the second one kills the newline. The only problem is that this is not working on empty lines where I only need to type C-k which is quite inconvenient as I have to use different commands for the same task: killing a line.

o / O - creates a new empty line below / above cursor and moves cursor to the new line, indented correctly

Well, C-a C-o is nearly like O, just the idention is missing. C-e C-o creates an empty line below the current but does not move the cursor.

Are there any better solutions to my problems or do I have to learn Lisp and define new commands to fulfill my needs?


Solution

  • For o and O, here are a few functions I wrote many years ago:

    (defun vi-open-line-above ()
      "Insert a newline above the current line and put point at beginning."
      (interactive)
      (unless (bolp)
        (beginning-of-line))
      (newline)
      (forward-line -1)
      (indent-according-to-mode))
    
    (defun vi-open-line-below ()
      "Insert a newline below the current line and put point at beginning."
      (interactive)
      (unless (eolp)
        (end-of-line))
      (newline-and-indent))
    
    (defun vi-open-line (&optional abovep)
      "Insert a newline below the current line and put point at beginning.
    With a prefix argument, insert a newline above the current line."
      (interactive "P")
      (if abovep
          (vi-open-line-above)
        (vi-open-line-below)))
    

    You can bind vi-open-line to, say, M-insert as follows:

    (define-key global-map [(meta insert)] 'vi-open-line)
    

    For dd, if you want the killed line to make it onto the kill ring, you can use this function that wraps kill-line:

    (defun kill-current-line (&optional n)
      (interactive "p")
      (save-excursion
        (beginning-of-line)
        (let ((kill-whole-line t))
          (kill-line n))))
    

    For completeness, it accepts a prefix argument and applies it to kill-line, so that it can kill much more than the "current" line.

    You might also look at the source for viper-mode to see how it implements the equivalent dd, o, and O commands.