Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to kill a quoted string at point in emacs?

Tags:

emacs

elisp

I would like to kill a quoted string in a source file without having to mark the beginning of the string and kill-region, but just by placing the point anywhere inside the quoted string and pressing a shortcut.

I tried to write a function in elisp for this, but I figured out that the file would need to be parsed from the beginning up to point to determine whether the point is inside quoted string, and to find the bounds of the quoted string(also handle the \")...

But the file is already parsed by font-lock. So now I can find out if I'm inside quoted string:

(defun inside-quoted-string? ()
  (interactive)
  (print (find 'font-lock-doc-face (text-properties-at (point)))))

But how do I get the bounds of the string? font-lock knows it, since it nicely highlights it in blue, but how do I get it?

Edit: Thanks for the answers. I came up with this code that does exactly what I wanted - move code around without selecting region or even moving to beginning of code.

(defun kill-at-point ()
  "Kill 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)
      (kill-sexp))
      (progn
    (up-list)
    (let ((beg (point)))
      (backward-list)
      (kill-region beg (point)))))))
(global-set-key (kbd "C-,") 'kill-at-point)

Any suggestions to improve it are welcome.

like image 500
abo-abo Avatar asked Jul 04 '12 15:07

abo-abo


3 Answers

Rather than rely on font-lock, you can use the underlying parser's data. The start of the string around point (if any) is available as (nth 8 (syntax-ppss)). You can then use (forward-sexp 1) to jump over the string to find its end.

like image 96
Stefan Avatar answered Nov 17 '22 22:11

Stefan


You can find the bounds of a property with previous-property-change and next-property-change. For example:

(defun kill-by-property (arg)
  (interactive "d")
  (kill-region
    (previous-property-change arg nil (point-min))
    (next-property-change arg nil (point-max))))
like image 26
ataylor Avatar answered Nov 17 '22 21:11

ataylor


Building off of Stefan's suggestion of using syntax-ppss, the following should do the trick

(defun kill-string ()
  (interactive)
  (let ((string-start (nth 8 (syntax-ppss))))
    (goto-char string-start)
    (kill-sexp)))

It uses (nth 8 (syntax-ppss)) to find the beginning of the string, jumps there, then uses the built-in kill-sexp to kill the s-expression at point (in this case, the string we want gone). No need at all for any kind of region calculation on your part.

like image 37
Inaimathi Avatar answered Nov 17 '22 21:11

Inaimathi