1

Unfortunately the dollar-sign in variable-names in the syntax-highlight is in the theme I use defined as 'default' face instead of being part of the variable name.

Is there a way to customize this?

OsunSeyi
  • 31
  • 4

1 Answers1

4

Emacs calls syntax highlighting “font lock”. Specifically, font lock is the part of syntax highlighting that parses the text to determine what parts are comments, keywords, variable names, etc., and assigns them font characteristics such as bold, italics, colors, etc. A theme can determine how colors are rendered. Since you want to change how $ is recognized, not what color is used for variable names, the theme is not relevant: you need to configure font locking.

Font locking for a major mode is specified through a list of font lock keywords. Each entry in the list is itself a list, consisting of a regular expression and specifications of the face to use for each group. (I'm just describing the most common case here, see the manual for details.)

There's a generic way to add your own keywords: call font-lock-add-keywords. So the simplest way to do what you asked is to call this function and tell it to use the variable name face for a regular expression that includes the $ as well as the variable name.

(font-lock-add-keywords 'sh-mode '(
    ("\\$\\([A-Z_a-z][A-Z_a-z0-9]+\\|[-!$#*0-9?@]\\)"
      (0 font-lock-variable-name-face))
    ))

In ${variable}, the braces are left in the default color. It's trivially easy to highlight the opening brace as well, but it takes more work to also highlight the matching closing brace. Here's code that matches the closing brace as well. It uses the “function” form of font lock keyword locator in an “anchored” matcher.

(defun match-closing-brace (limit)
  "Match the closing brace following the previous opening brace.
Move the point just after the closing brace and return non-nil.
If no matching closing brace is found, return nil."
  (and (search-backward-regexp "{[^{}]*\\=" nil t)
       (condition-case nil (progn (forward-sexp) t) (error nil))
       (save-excursion (backward-char) (looking-at "}"))))

(font-lock-add-keywords 'sh-mode '( ("\$\([A-Z_a-z][A-Z_a-z0-9]+\|[-!$#*0-9?@]\)" (0 font-lock-variable-name-face)) ("\${\([A-Z_a-z][A-Z_a-z0-9]+\|[-!$#*0-9?@]?\)" (0 font-lock-variable-name-face) (match-closing-brace nil nil (0 font-lock-variable-name-face))) ))


Using the generic mechanism font-lock-add-keywords affects all buffers in sh mode, regardless of the sh variant. In this particular case, I don't think this is a problem. If you wanted to customize only a specific variant, you'd have to dig deeper. The font lock specification for a mode foo-mode is typically in a variable called foo-mode-font-lock-keywords or variations around this theme. This can be more complex for modes that support multiple language variants or multiple levels of syntactic sophistication. Shell mode has both. To find its font lock specification, run C-h v sh-*font-lock-keywords* and see what completions are offered. This leads you to sh-font-lock-keywords-var.