2

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

(#b)(*).c

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

Postfix alternative glob qualifiers

*.c(#q:u)

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:

screenshot

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.

PythonNut
  • 10,243
  • 2
  • 29
  • 75
  • 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 http://emacs.stackexchange.com/questions/20377/highlighting-yaml-comments-correctly for one method to handle this. – Lindydancer Feb 18 '16 at 08: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 Feb 18 '16 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: https://github.com/Lindydancer/faceup – Lindydancer Feb 18 '16 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 Feb 18 '16 at 17:43

1 Answers1

2

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.

Stefan
  • 26,154
  • 3
  • 46
  • 84
  • 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 Feb 18 '16 at 14:59
  • Just to clarify, the shell type doesn't have any affect on the syntax definitions, right? – PythonNut Feb 18 '16 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 Feb 19 '16 at 04:15
  • Alright, I've sent in a preliminary patch. – PythonNut Feb 21 '16 at 02:14