12

I frequently find myself typing on a line, when I realize I need(ed) a variable definition (or something similar) on the line above. What I would like is to

  1. press C-return from anywhere on a line and have the cursor move to a newly inserted blank line above, with correct indentation (or at least the same as the original line).
  2. be able to yank any text...
  3. and C-u C-space to get back to the original position

I've managed to do #1, but my emacs-fu isn't strong enough to do the rest.

Luke Girvin
  • 13,221
  • 9
  • 64
  • 84
thebjorn
  • 26,297
  • 11
  • 96
  • 138

3 Answers3

10

Here's my humble solution:

(defun my-insert-before-line ()
  (interactive)
  (save-excursion
    (beginning-of-line)
    ; I've changed the order of (yank) and (indent-according-to-mode)
    ; in order to handle the case when yanked line comes with its own indent
    (yank)(indent-according-to-mode)
    ; could be as well changed to simple (newline) it's metter of taste
    ; and of usage
    (newline-and-indent)))

Hope it helps.

ashawley
  • 4,195
  • 1
  • 27
  • 40
Serge
  • 7,706
  • 5
  • 40
  • 46
  • 1
    Interesting. IIUC, your solution keeps the cursor stationary and "auto-yanks" into a correctly indented line above. I think that might fit my usage pattern better than what I asked for. Thank you :-) – thebjorn Mar 10 '09 at 18:08
  • 1
    The code should use `save-excursion`, should avoid using `yank`, and should be general to handle when the text isn't at the end of the buffer (`point-max`). – ashawley Mar 12 '09 at 06:56
  • @aaronhawley - why 'save-excursion'? I don't change mark I handle properly point, and the above code will hardly provoke a crush of the buffer. Can you be more specific about "when the text isn't at the end of the buffer" case, it does the same thing whenever point is at the moment of invokation – Serge Mar 12 '09 at 13:47
4

Probably bad form to answer my own question, but Cheeso's answer motivated me to do some lisp programming for the second time in ten years (my original version was a named keyboard macro, but it stepped all over the kill/mark-rings). Here's what I came up with

(defun insert-and-indent-line-above ()
  (interactive)
  (push-mark)
  (let* 
    ((ipt (progn (back-to-indentation) (point)))
     (bol (progn (move-beginning-of-line 1) (point)))
     (indent (buffer-substring bol ipt)))
    (newline)
    (previous-line)
    (insert indent)))

(global-set-key [ (control return) ] 'insert-and-indent-line-above)

there are probably many better ways of doing this, but two hours of lisp-hacking can hardly be called wasted time :-)

thebjorn
  • 26,297
  • 11
  • 96
  • 138
  • I love this solution, however I haven't been able to modify it to work on the terminal. Any ideas on how to achieve that? – Sambatyon Dec 30 '18 at 15:02
  • @Sambatyon no idea (terminal + emacs + windows is usually painful so I tend to avoid it). If you ask a new question I'm sure someone will know... – thebjorn Dec 30 '18 at 15:32
  • 1
    I just figure it out a few minutes ago. The problem is that the terminal emulator was not sending the correct message, I needed to go to iTerm preferences and add a keybinding for cmd+enter to do [13;5u – Sambatyon Dec 30 '18 at 19:02
3

Here's what you can do if you are not a Zen master emacs dude.

Emacs has a record-macro thing, kmacro-start-macro and kmacro-end-macro.

After recording your macro, do name-last-kbd-macro. then visit .emacs, and do insert-kbd-macro.

You then have an fset statement that defines your macro. It may look funny, and it is not as maintainable as elisp, but if you stuff it into your .emacs, that macro (by that name) will be available to any of your editing sessions. And you can bind it to a key sequence as well.

Cheeso
  • 189,189
  • 101
  • 473
  • 713