Here's what I generally use. Somehow it's more useful for me
to kill the balanced expression instead of copying. If I want a
copy instead, I first kill, then undo.
This function kills a string, if the point is inside string,
otherwise the balanced expression, i.e. ()
,[]
,{}
,<>
or whatever is defined by the syntax.
(defun kill-at-point ()
"Kill the quoted string or the list that includes the point"
(interactive)
(let ((p (nth 8 (syntax-ppss))))
(cond
;; string
((eq (char-after p) ?\")
(goto-char p)
(kill-sexp))
;; list
((ignore-errors (when (eq (char-after) ?\()
(forward-char))
(up-list)
t)
(let ((beg (point)))
(backward-list)
(kill-region beg (point)))))))
I've also tried to add a special case for when the point is
inside the comment, but I couldn't find a generic
way to determine bounds of comment at point. If anyone knows,
please tell me.
This other function can be relevant as well. It marks instead
of killing, like the previous one. The nice thing that it
extends the region each time it's called.
I bind the first one to C-, and the second to
C-M-,.
(defun mark-at-point ()
"Mark the quoted string or the list that includes the point"
(interactive)
(let ((p (nth 8 (syntax-ppss))))
(if (eq (char-after p) ?\")
(progn
(goto-char p)
(set-mark (point))
(forward-sexp))
(progn
(when (eq (char-after) 40)
(forward-char))
(condition-case nil
(progn
(up-list)
(set-mark (point))
(let ((beg (point)))
(backward-list)
(exchange-point-and-mark)))
(error
(when (looking-back "}")
(exchange-point-and-mark)
;; assumes functions are separated by one empty line
(re-search-backward "^[^A-Z-a-z]" nil t)
(forward-char))))))))