Brackets can be detected using forward-sexp
and backward-sexp
, this examples uses these functions to implement context sensitive bracket removal.
(defun find-surrounding-brackets (pt &optional strict)
"Find surrounding braces.
Argument PT is the point which is checked for brackets.
When argument STRICT is non-nil, only use braces at PT,
otherwise surrounding brackets are searched for."
(catch 'match
(let
(
(re-begin "\\((\\|{\\|\\[\\)")
(re-end "\\()\\|}\\|\\]\\)")
(pt-begin nil)
(pt-end nil))
;; First check if we're already on an ending bracket with a match,
;; handle this as a special case because there is no ambiguity in this instance.
;; Otherwise search for the previous bracket.
(save-excursion
(goto-char pt)
(save-match-data
(cond
((looking-at re-begin)
(when (setq pt-end (ignore-errors (forward-sexp) (1- (point))))
(setq pt-begin pt)
(throw 'match (list pt-begin pt-end))))
((looking-at re-end)
(forward-char 1)
(when (setq pt-begin (ignore-errors (backward-sexp) (point)))
(setq pt-end pt)
(throw 'match (list pt-begin pt-end)))))))
;; Now loop over preview brackets
;; until we find a match which includes `pt'.
(unless strict
(let ((pt-iter (1+ pt)))
(while
(setq pt-begin
(save-excursion
(goto-char pt-iter)
(save-match-data
(when (search-backward-regexp re-begin (point-min) t 1)
(match-beginning 0)))))
(setq pt-end
(save-excursion
(goto-char pt-begin)
(ignore-errors (forward-sexp) (1- (point)))))
(when (and pt-end (< pt pt-end))
(throw 'match (list pt-begin pt-end)))
(setq pt-iter pt-begin)))))
(throw 'match nil)))
(defun delete-surround-at-point (arg)
(interactive "p")
(let ((range (find-surrounding-brackets (point))))
(unless range
(user-error "No surrounding brackets"))
(pcase-let ((`(,start ,end) range))
(save-excursion
(goto-char end)
(delete-char 1)
(goto-char start)
(delete-char 1)))))