I recently transitioned from vim to emacs and miss one key feature of shell scripting: variables being highlighted inside double quotes. How do I put this feature back in?
I read in another thread that you can use syntax-ppss
to detect interior of quotes, but how do I actually change the color?
Note that the colors should be turned on for: name="$first $last"
but NOT for name='$first $last'
Interestingly, this exact question was asked and answered in emacs.stackexchange.com just a couple of days ago:
The code below use a font-lock rule with a function instead of a regexp, the function search for occurrences of $VAR
but only when they are inside a double-quoted string. The function (syntax-ppss)
is used to determine this.
The font-lock rule use the prepend
flag to add itself on top of the existing string highlighting. (Note that many packages use t
for this. Unfortunately, this overwrites all aspects of the existing highlighting. For example, using prepend
will retain a string background color (if there is one) while replacing the foreground color.)
(defun sh-script-extra-font-lock-is-in-double-quoted-string ()
"Non-nil if point in inside a double-quoted string."
(let ((state (syntax-ppss)))
(eq (nth 3 state) ?\")))
(defun sh-script-extra-font-lock-match-var-in-double-quoted-string (limit)
"Search for variables in double-quoted strings."
(let (res)
(while
(and (setq res
(re-search-forward
"\\$\\({#?\\)?\\([[:alpha:]_][[:alnum:]_]*\\|[-#?@!]\\)"
limit t))
(not (sh-script-extra-font-lock-is-in-double-quoted-string))))
res))
(defvar sh-script-extra-font-lock-keywords
'((sh-script-extra-font-lock-match-var-in-double-quoted-string
(2 font-lock-variable-name-face prepend))))
(defun sh-script-extra-font-lock-activate ()
(interactive)
(font-lock-add-keywords nil sh-script-extra-font-lock-keywords)
(if (fboundp 'font-lock-flush)
(font-lock-flush)
(when font-lock-mode
(with-no-warnings
(font-lock-fontify-buffer)))))
You can call use this by adding the last function to a suitable hook, for example:
(add-hook 'sh-mode-hook 'sh-script-extra-font-lock-activate)