Subject: Re: bug#753: [Fwd: sh-script.el: indentation of ( )]

From: Glenn Morris <[email-masked]>
Date: Thu, 08 Jan 2009 21:39:01 -0500

Stefan Monnier wrote:

> Basically, what I saw is that it recognized "done|" as a keyword,
> which I fixed by adding ?| to the "not in keywords" chars. By the
> same reasonging "done)" is not a keyword, so I added ?\) (and ?\( as
> well for good measure).

Adding them causes the problem you are trying to avoid.

Applying (skip-chars-forward "^ \t\n;&|")

to "done) "

results in "done)", which is not a recognized keyword.

>  I guess that sh-get-kw should be fixed more robustly by recognizing
> ")" and "(" but not "(done", nor "(done|toto)" for that matter. Can
> you take care of that and make sure it fixes the problem at hand
> without breaking the problem that prompted my misguided fix?

It's tricky. Consider the following two examples:

for f in 1; do
    case $f in
        done) echo t ;;
    esac
done

(for f in 1; do
   echo $f
done)

In the second one, "done)" ends a for loop, in the first one it does not.

Both Emacs 22.3 and the current CVS get both examples wrong, in
different ways.

ii), though valid syntax, seems ugly (and hopefully uncommon) to me,
especially considering that in Bash at least, the same problem cannot
arise with {}, since these must be isolated by whitespace.

A simple fix for i) is as follows. I don't know how to fix both i) and ii).

Did you have any other examples of shell syntax to be considered?

*** sh-script.el	5 Jan 2009 03:23:50 -0000	1.220
--- sh-script.el	9 Jan 2009 02:22:31 -0000
***************
*** 1421,1427 ****
    "Make a regexp which matches WORD as a word.
  This specifically excludes an occurrence of WORD followed by
  punctuation characters like '-'."
!   (concat word "\\([^-[:alnum:]_]\\|$\\)"))
  
  (defconst sh-re-done (sh-mkword-regexpr "done"))
  
--- 1421,1428 ----
    "Make a regexp which matches WORD as a word.
  This specifically excludes an occurrence of WORD followed by
  punctuation characters like '-'."
!   ;; ")}" excludes things like "done)" in case statements.
!   (concat word "\\([^-[:alnum:]_)}]\\|$\\)"))
  
  (defconst sh-re-done (sh-mkword-regexpr "done"))