Emacs has several packages for dealing with parentheses. Emacs comes with ways to highlight the matching parenthesis when you're on one; try show-paren-mode
. One of the newer add-on packages is Nikolaj Schumacher's highlight-parentheses mode, which
shows the parentheses that enclose the current cursor position. I tried modifying it to highlight the containing expressions instead of only their parentheses:
(defun hl-paren-highlight () "Highlight the parentheses around point." (unless (= (point) hl-paren-last-point) (save-excursion (let ((pos (point)) (match-pos (point)) (level -1) (max (1- (length hl-paren-overlays)))) (while (and match-pos (< level max)) (setq match-pos (when (setq pos (cadr (syntax-ppss pos))) (ignore-errors (scan-sexps pos 1)))) (when match-pos (if (eq 'expression hl-paren-type) (hl-paren-put-overlay pos match-pos (incf level)) (hl-paren-put-overlay pos (1+ pos) (incf level)) (hl-paren-put-overlay (1- match-pos) match-pos (incf level))) )) (while (< level max) (hl-paren-put-overlay nil nil (incf level))))) (setq hl-paren-last-point (point))))
Unfortunately, as you can see, it's a mess. I tried better colors (white, gray, etc.) but I just couldn't make it usable. So I gave up on highlighting the regions and went back to highlighting just the parentheses. It's a bit better:
(defun hl-paren-highlight () "Highlight the parentheses around point." (unless (= (point) hl-paren-last-point) (save-excursion (let ((pos (point)) (match-pos (point)) (level -1) (max (1- (length hl-paren-overlays)))) (while (and match-pos (< level max)) (setq match-pos (when (setq pos (cadr (syntax-ppss pos))) (ignore-errors (scan-sexps pos 1)))) (when match-pos (if (eq 'expression hl-paren-type) (hl-paren-put-overlay pos match-pos (incf level)) (hl-paren-put-overlay pos (1+ pos) (incf level)) (hl-paren-put-overlay (1- match-pos) match-pos (incf level))) )) (while (< level max) (hl-paren-put-overlay nil nil (incf level))))) (setq hl-paren-last-point (point))))
However it's still a bit too … colorful. So I changed it to simply make the enclosing parentheses bold:
(defun hl-paren-highlight () "Highlight the parentheses around point." (unless (= (point) hl-paren-last-point) (save-excursion (let ((pos (point)) (match-pos (point)) (level -1) (max (1- (length hl-paren-overlays)))) (while (and match-pos (< level max)) (setq match-pos (when (setq pos (cadr (syntax-ppss pos))) (ignore-errors (scan-sexps pos 1)))) (when match-pos (if (eq 'expression hl-paren-type) (hl-paren-put-overlay pos match-pos (incf level)) (hl-paren-put-overlay pos (1+ pos) (incf level)) (hl-paren-put-overlay (1- match-pos) match-pos (incf level))) )) (while (< level max) (hl-paren-put-overlay nil nil (incf level))))) (setq hl-paren-last-point (point))))
That's nicer, although perhaps too subtle. I added more bolding:
(defun hl-paren-highlight () "Highlight the parentheses around point." (unless (= (point) hl-paren-last-point) (save-excursion (let ((pos (point)) (match-pos (point)) (level -1) (max (1- (length hl-paren-overlays)))) (while (and match-pos (< level max)) (setq match-pos (when (setq pos (cadr (syntax-ppss pos))) (ignore-errors (scan-sexps pos 1)))) (when match-pos (if (eq 'expression hl-paren-type) (hl-paren-put-overlay pos match-pos (incf level)) (hl-paren-put-overlay pos (1+ pos) (incf level)) (hl-paren-put-overlay (1- match-pos) match-pos (incf level))) )) (while (< level max) (hl-paren-put-overlay nil nil (incf level))))) (setq hl-paren-last-point (point))))
It bolds the parentheses and also the first s-expression inside the opening parenthesis. It doesn't understand when the parentheses begin a form (instead of all the other uses of parentheses), so it sometimes highlights the first s-expression even when it's not special in any way. Despite this wart, I like this form of highlighting so far.
Update: [2007-05-29] However, there is one more thing I wanted. I de-emphasize parentheses by using a lighter color for them; I want the enclosing parentheses to be bold and black. However I want the enclosing first s-expressions to be bold, but not necessarily black. Note in the above example the keywords are normally blue, but when enclosing the current point they are black. I fixed this by adding separate highlighting for the enclosing parentheses and the first s-expression:
(defun hl-paren-highlight () "Highlight the parentheses around point." (unless (= (point) hl-paren-last-point) (save-excursion (let ((pos (point)) (match-pos (point)) (level -1) (max (1- (length hl-paren-overlays)))) (while (and match-pos (< level max)) (setq match-pos (when (setq pos (cadr (syntax-ppss pos))) (ignore-errors (scan-sexps pos 1)))) (when match-pos (if (eq 'expression hl-paren-type) (hl-paren-put-overlay pos match-pos (incf level)) (hl-paren-put-overlay pos (1+ pos) (incf level)) (hl-paren-put-overlay (1- match-pos) match-pos (incf level))) )) (while (< level max) (hl-paren-put-overlay nil nil (incf level))))) (setq hl-paren-last-point (point))))
I'm pretty happy with this variant of highlight-parentheses.el
.
Update: [2014-05-10] Also check out the rainbow-blocks and rainbow-delimiters modes. For Python or Ruby code, highlight-indentation-mode may be useful. Update: [2019-08-05] Also see prism.
Labels: emacs
lemonodor has some other packages listed on his blog.
Any chance you could post a link to your version?
My version is pretty messy and doesn't work reliably, so I didn't put it up. A few days after Anonymous asked, Nikolaj put up a new version with optional background highlighting and bolding. It doesn't highlight the first sexp; I might try patching it to support that.
Also see rainbow-delimiters.
See also HighlightSexp
Also see HighlightSexps (highlights multiple levels, unlike HighlightSexp)
Post a Comment