3
The following documents the modifications to the haserl parser
4
when --enable-bash-extensions is enabled. The following was
5
written by Scott, and should not be considered as a core part
6
of haserl. (Ask on the mailing list if you need help)
8
--------------------------------------------------------------
10
Haserl supports four tags by default. These are generic and
11
suitable for use with a great variety of shells. If, like
12
me, you write your scripts with vi (vim) with the syntax
13
highlighting enabled, then you will have noted how badly
14
this looks in the editor.
16
I also prefer the tags to be a bit more intelligent, as I
17
find it makes the source that much more readable.
19
To this end I have added the following tags (again, these
20
are designed with bash in mind, may not work with other
21
sh-type shells, and are not at all supported if you are
25
Tag version: Expands to:
26
------------------------ ------------------------
27
<%if list %> if [[ list ]] ; then
28
<%elif list %> elif [[ list ]] ; then
29
<%else [comment] %> else [# comment]
30
<%endif [comment] %> fi [# comment]
32
<%case word %> case word in
33
<%when pattern %> pattern)
34
<%otherwise [comment] %> *) : [comment] ;;
35
<%endcase [comment] %> esac [# comment]
37
<%while list %> while list ; do
38
<%endwhile %> done [# comment]
40
<%until list %> until list ; do
41
<%enduntil [comment] %> done [# comment]
43
<%for name in word %> for name in word ; do
44
<%endfor [comment] %> done [# comment]
46
<%unless list %> if [[ ! list ]] ; then
47
<%elun list %> elif [[ ! list ]] ; then
48
<%unelse [comment] %> else [#comment]
49
<%endunless [comment %> fi [# comment]
52
To simplify parsing, and to reduce confusion when reading
53
your source, unique words are used. For example, the use of
54
endwhile, enduntil and endfor instead of done. Also, for
55
clarity I have used endif/endcase instead of fi/esac.
61
Note the last command, the unless...endunless. I find it is
62
often more clear to express an unless condition than an if
63
not condition. For example, and to show the streamlining of
64
code these tags provide:
66
<% if [[ ! IsLogged ]] ; then %>
70
This is the improved (IMHO) version:
76
Personally, I find no use for "else unless", but I decided
77
to include it for consistency.
83
There is one syntactic problem, concerning the use of the
84
<%if %>, <%while %>, <%until %> and <%unless %> tags. The
85
default action is to create a test-style condition; however,
86
sometime you need to do this:
88
<% if grep "text" file &>/dev/null ; then %>
90
If you simply write this:
92
<%if grep "text" file &>/dev/null %>
94
Then it is expanded to:
96
if [[ grep "text" file &>/dev/null ]] %>
98
That is obviously incorrect. To allow for this the parser
99
provides a bit of syntactic sugar. It checks the first
100
character of the expression list and if it is, then it
101
rewrites the list as a command. For example:
103
<%if |grep "text" file &>/dev/null %>
107
if grep "text" file &>/dev/null ; then
113
The case statement provided another challenge, namely how to
114
handle the pesky ;; required at the end of each case. I am
115
not a C person, so personally I find the next instance of a
116
case to be sufficient to terminate the first. Given that the
117
shell version of case can accept multiple conditions, there
118
is really no reason to worry with cases falling through as
119
they do in C. In other words, I'm all for ditching the ;;
120
construct altogether.
124
The enhanced <%case %> tag operates without an explicit ;;
125
being required. It is perhaps easier to show than explain,
126
so here's an example:
130
echo "It's an apple!"
132
echo "It's an orange!"
133
<%otherwise something else %>
134
echo "Not what I expected."
137
The parser renders this as follows:
143
echo "It's an apple!"
146
echo "It's an orange!"
149
echo "Not what I expected."
153
Note the odd first case. The parser inserts this so ensure
154
that each subsequent when/otherwise/endcase can be preceded
155
by ;;. This eliminates the need to remember the ;;, and I
156
believe makes for cleaner code. There is, of course, a small
157
performance penalty for always having to evaluate this extra
158
case. In real life I find this not to be a problem, however,
159
if you are processing inside a loop and expect a large chunk
160
of items, then it is something to be aware of.