OILS / test / shell-vs-shell.sh View on Github | oils.pub

314 lines, 142 significant
1#!/usr/bin/env bash
2#
3# Compare alternative shell designs!
4#
5# Usage:
6# test/shell-vs-shell.sh <function name>
7
8set -o nounset
9set -o pipefail
10set -o errexit
11
12readonly BASE_DIR=_tmp/shell-vs-shell
13readonly REPO_ROOT=$(cd $(dirname $0)/.. ; pwd)
14
15readonly TAB=$'\t'
16
17html-head() {
18 PYTHONPATH=. doctools/html_head.py "$@"
19}
20
21cmark() {
22 # copied from build/doc.sh
23 PYTHONPATH=. doctools/cmark.py --toc-tag h2 --toc-tag h3 --toc-pretty-href "$@"
24}
25
26highlight-code() {
27 PYTHONPATH=. doctools/oils_doc.py highlight "$@"
28}
29
30desc() {
31 echo "$@" > description.txt
32}
33
34src() {
35 local lang=$1
36
37 local prog=src/$lang
38
39 # read from stdin
40 cat > $prog
41
42 case $lang in
43 ysh)
44 $REPO_ROOT/bin/ysh $prog | tee output/$lang.txt
45 ;;
46 shpp)
47 ~/git/languages/shell-plus-plus/build/shell/shpp $prog | tee output/$lang.txt
48 ;;
49 (*)
50 die "Invalid language $lang"
51 ;;
52 esac
53}
54
55CASE-hello() {
56
57 desc "Print a string"
58
59 # TODO:
60 # - need to group these into a row somehow ...
61 # code-begin or something
62 # - setup script
63 # - show output in the HTML too
64 # - save that in a dir and then escape it
65
66 src ysh <<'EOF'
67# ysh requires quotes
68echo 'hello world'
69
70const name = 'world'
71echo "hello $name"
72EOF
73
74 src shpp <<'EOF'
75# no single quotes
76echo hello world
77
78name = "world"
79echo "hello ${name}" # braces required
80EOF
81}
82
83CASE-pipeline() {
84 desc 'Pipeline and Glob'
85
86 touch src{1,2,3,4,5}
87
88 src ysh <<EOF
89ls src* | sort -r | head -n 3
90EOF
91
92 src shpp <<EOF
93ls src* | sort -r | head -n 3
94EOF
95
96}
97
98CASE-try() {
99 desc 'Error Handling'
100
101 src ysh <<'EOF'
102# TODO: Oils could expose strerror() like shpp
103
104#test
105try { zzz }
106if (_error.code === 127) {
107 echo "zzz not installed"
108}
109EOF
110
111 src shpp <<'EOF'
112try {
113 zzz
114} catch InvalidCmdException as ex {
115 print("zzz not installed [msg: ", ex, "]")
116}
117EOF
118}
119
120CASE-read() {
121 desc 'Read User Input'
122
123 src ysh <<'EOF'
124echo hello | read --line
125
126# _line starts with _, so it's a
127# "register" mutated by the interpreter
128echo "line: $_line"
129EOF
130
131 src shpp <<'EOF'
132# not sure how to feed stdin
133
134line = read()
135print("line: ", line)
136EOF
137}
138
139# TODO: Sort by section
140CASE-ZZ-array() {
141 desc 'Use Arrays'
142
143 touch {foo,bar}.py
144
145 src ysh <<'EOF'
146const array1 = ['physics', 'chemistry', 1997, 2000]
147const array2 = [1, 2, 3, 4, 5, 6, 7]
148
149write -- "array1[0]: $[array1[0]]"
150
151# TODO: Oils needs @[]
152const slice = array2[1:5]
153write -- "array2[1:5]" @slice
154
155# use the word language: bare words, glob, brace expansion
156const shell_style = %( README.md *.py {alice,bob}@example.com )
157write -- @shell_style
158EOF
159
160 src shpp <<'EOF'
161array1 = ["physics", "chemistry", 1997, 2000];
162array2 = [1, 2, 3, 4, 5, 6, 7 ];
163
164print("array1[0]: ", array1[0])
165print("array2[1:5]: ", array2[1:5])
166EOF
167
168}
169
170CASE-path() {
171 desc 'Test if path exists'
172
173 src ysh <<'EOF'
174if test --exists /bin/grep {
175 echo 'file exists'
176}
177EOF
178
179 src shpp <<'EOF'
180if path("/bin/grep").exists() {
181 echo "file exists"
182}
183EOF
184}
185
186test-one() {
187 local func_name=$1
188
189 echo "$TAB---"
190 echo "$TAB$func_name"
191 echo "$TAB---"
192
193 local dir=$BASE_DIR/$func_name
194
195 mkdir -p $dir/{src,output}
196 pushd $dir >/dev/null
197
198 $func_name
199
200 popd >/dev/null
201
202}
203
204test-all() {
205 rm -r -f -v $BASE_DIR/
206 mkdir -p $BASE_DIR/
207 compgen -A function | grep '^CASE-' | xargs -n 1 -- $0 test-one
208
209 tree $BASE_DIR
210}
211
212html-escape() {
213 sed 's/&/\&amp;/g; s/</\&lt;/g; s/>/\&gt;/g' "$@"
214}
215
216html-footer() {
217 echo '
218 </body>
219</html>
220'
221}
222
223# TODO: Run through doctools plugin for syntax highlighting
224
225make-table() {
226 echo '<h2>'
227 html-escape description.txt
228 echo '</h2>'
229
230 echo '<table>'
231 echo ' <thead>'
232 echo ' <tr>'
233 echo ' <td></td>'
234 for src_file in src/*; do
235 echo "<td>$(basename $src_file)</td>"
236 done
237 echo ' </tr>'
238 echo ' </thead>'
239
240 echo ' <tr>'
241 echo ' <td>source</td>'
242 for src_file in src/*; do
243 echo '<td><pre>'
244 cat $src_file | html-escape
245 echo '</pre></td>'
246 done
247 echo ' </tr>'
248
249 echo ' <tr>'
250 echo ' <td>output</td>'
251 for out_file in output/*; do
252 echo '<td><pre>'
253 cat $out_file | html-escape
254 echo '</pre></td>'
255 done
256 echo ' </tr>'
257
258 echo '</table>'
259}
260
261
262_html-all() {
263 html-head --title 'Shell vs. Shell' \
264 ../web/base.css ../web/shell-vs-shell.css ../web/language.css
265
266 echo '<body class="width50">'
267
268 cmark <<EOF
269# Shell Design Comparison
270
271This is a friendly comparison of the syntax of different shells!
272
273- Oils: <https://github.com/oils-for-unix/oils>
274 - [A Tour of YSH](https://oils.pub/release/latest/doc/ysh-tour.html)
275- Shell++: <https://github.com/alexst07/shell-plus-plus>
276 - [Shell++ Language Basics](https://alexst07.github.io/shell-plus-plus/lang-basics/)
277
278&nbsp;
279
280- More shells: <https://github.com/oils-for-unix/oils/wiki/Alternative-Shells>
281- Script that generates this file:
282 <https://github.com/oils-for-unix/oils/blob/master/test/shell-vs-shell.sh>
283
284&nbsp;
285
286EOF
287
288 for dir in $BASE_DIR/CASE-*; do
289 pushd $dir >/dev/null
290
291 make-table
292
293 popd >/dev/null
294 done
295
296 html-footer
297}
298
299html-all() {
300 mkdir -p $BASE_DIR
301
302 local out=$BASE_DIR/index.html
303
304 _html-all | highlight-code > $out
305
306 echo "Wrote $out"
307}
308
309all() {
310 test-all
311 html-all
312}
313
314"$@"