7

Is there a way to find out the type of the surrounding parenthesis (i.e. '(', '[' or '{') around point? For example (using | to represent point)

{ abc, | df }

should return '{', and

{ abc[ | ], 123 }

should return '['. Ideally I would like it to handle quotation marks as well.


In case anyone is curious or needs more details: my aim is to set up smart automatic spacing around : in python using electric-spacing (also known as smart-operator). The problem is that normally (in python) : is either the slice operator or the start of a for/if/... statement, which shouldn't be surrounded by spaces. However, within a dictionary it is something like an assignment operator, and so it should be surrounded by spaces. So I a way need to check if point is inside a dict (i.e. inside {}), but not inside a slice operation or string within that dict (i.e. not inside [] or "").


Edit:

Here's the helper function I wrote, based on abo-abo's answer:

(defun enclosing-paren ()
  "Return the closing parenthesis of the enclosing parens, or nil if not inside any parens."
  (ignore-errors
    (save-excursion
      (up-list)
      (char-before))))

Then then the final predicate is:

(and (not (in-string-p))
     (eq (enclosing-paren) ?\}))

Edit 2:

The above function turned out to be too slow (it often caused a noticeable lag when a : was typed). I'm using Stefan's answer instead now, which seems to be much faster.

  • 1
    Not a full answer, but for the specific case of "", you can use the built-in in-string-p. – T. Verron Mar 30 '15 at 13:09
10

Rather than up-list I'd recommend you use (syntax-ppss) which will return to you some parsing state. This will include info about whether you're inside a string or a comment, the position of the last open "paren" etc...

E.g. you can find the kind of paren with

(let ((ppss (syntax-ppss)))
  (when (nth 1 ppss) (char-after (nth 1 ppss))))

and it should hopefully let you handle quotation marks as well (by checking (nth 3 ppss) and (char-after (nth 8 ppss))).

5

Try this:

(save-excursion
  (up-list)
  (char-before))

Note that up-list can throw, so you need to handle errors as well.

  • I like the simplicity of this answer but it turned out to be too slow in python when point is not inside any parens (very common with python's whitespace syntax). Presumably it's because it ends up parsing the entire buffer in this case. – dshepherd Jun 1 '15 at 9:42
1

While the preferable answer IMO was given by Stefan, here an example which includes a solution not relying on syntax-table WRT delimiters: It uses something like

 (skip-chars-backward "^{\(\[\]\)}")

and a stack. See source here

https://github.com/emacs-berlin/general-close

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.