views:

136

answers:

6

I've just started using emacs, and there's one feature I'd really like, and searching around a bit was fruitless. I hope someone else has done this because I don't want to learn elisp just yet.

void foo()<cursor>

I would like typing an "{" to cause this to happen

void foo(){
    <cursor>
}

I would like this to only happen in cc-mode, and only at the end of a line when not in a string/comment/etc

The first thing that came to mind was rebinding "{" to do this always(I could figure out how to do this myself), but it would be hard to make it only happen at the right time.

any hints would be appreciated.

+2  A: 

Try yasnippet (or on the Emacs Wiki page yasnippet). There are many packages for Emacs which support doing this kind of thing, but yasnippet seems to have momentum currently and is very extensible. Check out the videos.

Trey Jackson
That looks really cool, I'll look into it
Bwmat
This doesn't seem to be ideal, I need to press tab to expand it and it doesn't work if there isn't a space between the "{" and whatever is before it.
Bwmat
You could probably modify to template to remove the space. Modifying/creating templates is pretty easy.
matt harrison
+1  A: 

Are you looking for something like yasnippet?

matt harrison
+1  A: 

You will need to delve into emacs-lisp to do this exactly as you wish, since YASnippet will do something nice for you but not exactly what you're asking for.

I think the simplest way to do this would be to bind a function to the RET key, in the cc-mode key-map.

The function should check to that the previous character is an { and if so, perform the required RET, RET, TAB, }, Up, TAB to get the cursor where you want and the closing } inserted.

You can make the feature more robust by having it check for a balanced closing } but this would be more complicated, and I'd recommend seeing how it feels without this additional polishing feature.

If you like I can write the function and the key-map binding for you, but since you asked for an idea of how it's done, I'll leave it up to you to ask for more assistance if you need it.

Alternatively, I find that autopair.el does this nicely enough for me, and I do the newlines myself ;)

slomojo
that's what I thought. is there an easy way to, inside the lisp function, check whether I'm in a comment/string and whether I'm at the end of the line? I know cc-mode does this internally and it would make it really easy if I could just use that.
Bwmat
You can use thing-at-point to determine what context you're in.
slomojo
+2  A: 

I heartily recommend you to try out the excellent autopair minor mode - it does a lot more than simply inserting braces and makes Emacs a lot more IDE like in that area. I guess combining it with the electric braces setting in cc-mode will give you more or less the behavior you seek.

Bozhidar Batsov
+3  A: 

This will do it:

(defun my-c-mode-insert-lcurly ()
  (interactive)
  (insert "{")
  (let ((pps (syntax-ppss)))
    (when (and (eolp) (not (or (nth 3 pps) (nth 4 pps)))) ;; EOL and not in string or comment
      (c-indent-line)
      (insert "\n\n}")
      (c-indent-line)
      (forward-line -1)
      (c-indent-line))))

(define-key c-mode-base-map "{" 'my-c-mode-insert-lcurly)
scottfrazer
thanks, this worked great.
Bwmat
+1  A: 

on latest emacs you can use :

electric-pair-mode is an interactive compiled Lisp function.

(electric-pair-mode &optional ARG)

Automatically pair-up parens when inserting an open paren.

this is integrated in Emacs 24.1 (actually CVS)

Chmouel Boudjnah