zsh has a ton of syntax. In particular, the # character serves a bunch of different roles. Here are two that are problematic:

Prefix globbing flags


This finds all files that end in .c and captures their basenames using backreferences (#b).

Postfix alternative glob qualifiers


This lists the uppercase names of all files that end in .c.

In sh[zsh]-mode, the the #s are incorrectly detected as starting comments:


Normally, this wouldn't be a big deal, but unfortunately, this throws the braces out of balance (as indicated by rainbow-parentheses), which messes with the indentation of the rest of the file, making certain files essentially uneditable.

I took a stab at the sh-mode source, but it's pretty dizzying. How can I teach Emacs about this syntax, and how can I answer this sort of question myself should anything similar arise in the future?

p.s. see the Emacs bug I filed a while back.

  • YAML mode also use # for two different things, in some contexts it's a comment character, in others it's parts of an identifier. See emacs.stackexchange.com/questions/20377/… for one method to handle this. Commented Feb 18, 2016 at 8:42
  • @Lindydancer in zsh's case, the # is used for at least 12 syntactically distinct roles, and that's just globbing, parameter expansion, and comments. So this is going to be an extra level of fun. :)
    – PythonNut
    Commented Feb 18, 2016 at 15:08
  • Maybe I'm banging on my own drum here, but I have found it invaluable to set up an automated test system for things like this, so that you don't accidentally break one thing when you fix another. You can try my faceup package for this: github.com/Lindydancer/faceup Commented Feb 18, 2016 at 15:22
  • @Lindydancer thanks, I remember reading about it when it first appeared on MELPA, and I was just thinking that I'd need to hunt it down.
    – PythonNut
    Commented Feb 18, 2016 at 17:43

1 Answer 1


You want to look at sh-syntax-propertize-function where it currently uses the regexp "\\(?:[^|&;<>()``\\\"' \t\n]\\|\\${\\)\\(#+\\)" to match those # chars which should not be considered as starting a comment. If you remove the ( char in the char range (i.e. replace () with just )), then it should solve your particular problem. It will also cause the code below to be improperly handled:

(#hey this is just a "comment
 echo and this is the actual command)

I don't know enough about zsh's syntax to tell you how to ditinguish the (# that start a comment from those that don't.

BTW, please post this problem (ideally with a patch) via M-x report-emacs-bug.

  • I already reported the bug, but I don't have a patch. Let me tinker with it the regex. It'll probably take quite a while to verify that all of the different syntax variations are not broken.
    – PythonNut
    Commented Feb 18, 2016 at 14:59
  • Just to clarify, the shell type doesn't have any affect on the syntax definitions, right?
    – PythonNut
    Commented Feb 18, 2016 at 15:15
  • Yes and no. In this specific respect, I think we do not distinguish currently, but in general sh-script.el does distinguish various kinds of shells.
    – Stefan
    Commented Feb 19, 2016 at 4:15
  • Alright, I've sent in a preliminary patch.
    – PythonNut
    Commented Feb 21, 2016 at 2:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.