OILS / _gen / bin / text_files.cc View on Github | oilshell.org

1059 lines, 111 significant
1
2#include "cpp/embedded_file.h"
3
4namespace embedded_file {
5GLOBAL_STR(gStr0, R"zZXx(Errors
6
7 [JSON] json-encode-err json-decode-err
8 [JSON8] json8-encode-err json8-decode-err
9 [Packle] packle-encode-err packle-decode-err
10 [UTF8] utf8-encode-err utf8-decode-err
11)zZXx");
12
13GLOBAL_STR(gStr1, R"zZXx(J8 Notation
14
15 [J8 Strings] json-string "hi" json-escape \" \\ \u1234
16 surrogate-pair \ud83e\udd26
17 u-prefix u'hi' b-prefix b'hi'
18 j8-escape \u{1f926} \yff
19 no-prefix 'hi'
20 [JSON8] json8-num json8-str
21 json8-list json-dict
22 json8-comment
23 [TSV8] column-attrs column-types
24)zZXx");
25
26GLOBAL_STR(gStr2, R"zZXx(Packle
27
28 [Atoms] Null Bool Int Float Bytes Unicode
29 [Compound] List Dict
30)zZXx");
31
32GLOBAL_STR(gStr3, R"zZXx(Usage: help TOPIC?
33
34Examples:
35
36 help # this help
37 help echo # help on the 'echo' builtin
38 help com-sub # help on command sub $(date)
39
40 help oils-usage # identical to oils-for-unix --help
41 help osh-usage # osh --help
42 help ysh-usage # ysh --help
43)zZXx");
44
45GLOBAL_STR(gStr4, R"zZXx(bin/oils-for-unix is an executable that contains OSH, YSH, and more.
46
47Usage: oils-for-unix MAIN_NAME ARG*
48 MAIN_NAME ARG*
49
50It behaves like busybox. The command name can be passed as the first argument:
51
52 oils-for-unix ysh -c 'echo hi'
53
54More commonly, it's invoked through a symlink like 'ysh', which causes it to
55behave like that command:
56
57 ysh -c 'echo hi'
58)zZXx");
59
60GLOBAL_STR(gStr5, R"zZXx(Builtin Commands
61
62 [I/O] read echo printf
63 readarray mapfile
64 [Run Code] source . eval trap
65 [Set Options] set shopt
66 [Working Dir] cd pwd pushd popd dirs
67 [Completion] complete compgen compopt compadjust compexport
68 [Shell Process] exec X logout
69 umask X ulimit times
70 [Child Process] jobs wait ampersand &
71 fg X bg X kill X disown
72 [External] test [ getopts
73 [Introspection] help hash type X caller
74 [Word Lookup] command builtin
75 [Interactive] alias unalias history X fc X bind
76X [Unsupported] enable
77)zZXx");
78
79GLOBAL_STR(gStr6, R"zZXx(The reference is divided in to "chapters", each of which has its own table of
80contents. Type:
81
82 help osh-$CHAPTER
83
84Where $CHAPTER is one of:
85
86 front-end
87 command-lang
88 osh-assign
89 word-lang
90 mini-lang
91 builtin-cmd
92 option
93 special-var
94 plugin
95
96Example:
97
98 help osh-word-lang
99)zZXx");
100
101GLOBAL_STR(gStr7, R"zZXx(Command Language
102
103 [Commands] simple-command semicolon ;
104 [Conditional] case if true false colon :
105 bang ! and && or || dbracket [[
106 [Iteration] while until for for-expr-sh ((
107 [Control Flow] break continue return exit
108 [Grouping] sh-func sh-block { subshell (
109 [Concurrency] pipe | X |&
110 ampersand &
111 [Redirects] redir-file > >> >| < <> X &>
112 redir-desc >& <&
113 here-doc << <<- <<<
114 [Other Command] dparen (( time X coproc X select
115)zZXx");
116
117GLOBAL_STR(gStr8, R"zZXx(Front End
118
119 [Usage] osh-usage config startup line-editing prompt
120 exit-codes
121 [Lexing] comment # line-continuation \
122)zZXx");
123
124GLOBAL_STR(gStr9, R"zZXx(Other Mini Languages
125
126 [Arithmetic] arith-context Where legacy arithmetic is allowed
127 sh-numbers 0xFF 0755 etc.
128 sh-arith 1 + 2*3 a *= 2
129 sh-logical !a && b
130 sh-bitwise ~a ^ b
131 [Boolean] dbracket [[ vs. the test builtin
132 bool-expr [[ ! $x && $y || $z ]]
133 test ! $x -a $y -o $z
134 bool-infix [[ $a -nt $b ]] [[ $x == $y ]]
135 bool-path [[ -d /etc ]]
136 bool-str [[ -z '' ]]
137 bool-other [[ -o errexit ]]
138 [Patterns] glob-pat *.py
139 extglob ,(*.py|*.sh)
140 regex [[ foo =~ [a-z]+ ]]
141 [Other Sublang] braces {alice,bob}@example.com
142 histsub !$ !! !n
143 char-escapes \t \c \x00 \u03bc
144)zZXx");
145
146GLOBAL_STR(gStr10, R"zZXx(Global Shell Options
147
148 [Errors] nounset pipefail errexit inherit_errexit
149 [Globbing] noglob nullglob failglob dashglob
150 [Debugging] xtrace X verbose X extdebug
151 [Interactive] emacs vi
152 [Other Option] X noclobber
153)zZXx");
154
155GLOBAL_STR(gStr11, R"zZXx(Assignments and Expressions
156
157 [Literals] sh-array array=(a b c) array[1]=B "${a[@]}"
158 sh-assoc assoc=(['a']=1 ['b']=2) assoc['x']=b
159 [Operators] sh-assign str='xyz'
160 sh-append str+='abc'
161 [Builtins] local readonly export unset shift
162 declare typeset X let
163)zZXx");
164
165GLOBAL_STR(gStr12, R"zZXx(Plugins and Hooks
166
167 [Signals] SIGTERM X SIGINT X SIGABRT SIG...
168 [Traps] DEBUG ERR EXIT X RETURN
169 [Words] PS1 X PS2 X PS3 PS4
170 [Completion] complete
171 [Other Plugin] X command_not_found PROMPT_COMMAND
172)zZXx");
173
174GLOBAL_STR(gStr13, R"zZXx(Special Variables
175
176 [Shell Vars] IFS X LANG X GLOBIGNORE
177 [Shell Options] SHELLOPTS X BASHOPTS
178 [Other Env] HOME PATH
179 [POSIX Special] $@ $* $# $? $- $$ $! $0 $9
180 [Other Special] BASH_REMATCH @PIPESTATUS
181 [Platform] HOSTNAME OSTYPE
182 [Call Stack] @BASH_SOURCE @FUNCNAME @BASH_LINENO
183 X @BASH_ARGV X @BASH_ARGC
184 [Tracing] LINENO
185 [Process State] X BASHPID X PPID UID EUID
186X [Process Stack] BASH_SUBSHELL SHLVL
187X [Shell State] BASH_CMDS @DIRSTACK
188 [Completion] @COMP_WORDS COMP_CWORD COMP_LINE COMP_POINT
189 COMP_WORDBREAKS @COMPREPLY X COMP_KEY
190 X COMP_TYPE COMP_ARGV
191 [History] HISTFILE
192 [cd] PWD OLDPWD X CDPATH
193 [getopts] OPTIND OPTARG X OPTERR
194 [read] REPLY
195 [Functions] X RANDOM X SECONDS
196)zZXx");
197
198GLOBAL_STR(gStr14, R"zZXx(bin/osh is compatible with POSIX shell, bash, and other shells.
199
200Usage: osh FLAG* SCRIPT ARG*
201 osh FLAG* -c COMMAND ARG*
202 osh FLAG*
203
204The command line accepted by `bin/osh` is compatible with /bin/sh and bash.
205
206 osh -c 'echo hi'
207 osh myscript.sh
208 echo 'echo hi' | osh
209
210It also has a few enhancements:
211
212 osh -n -c 'hello' # pretty-print the AST
213 osh --ast-format text -n -c 'hello' # print it full
214
215osh accepts POSIX sh flags, with these additions:
216
217 -n parse the program but don't execute it. Print the AST.
218 --ast-format what format the AST should be in
219)zZXx");
220
221GLOBAL_STR(gStr15, R"zZXx(Word Language
222
223 [Quotes] osh-string 'abc' $'line\n' "$var"
224 [Substitutions] com-sub $(command) `command` @(split command)
225 var-sub ${var} $0 $9
226 arith-sub $((1 + 2))
227 tilde-sub ~/src
228 proc-sub diff <(sort L.txt) <(sort R.txt)
229 [Var Ops] op-test ${x:-default}
230 op-strip ${x%%suffix} etc.
231 op-replace ${x//y/z}
232 op-index ${a[i+1}
233 op-slice ${a[@]:0:1}
234 op-format ${x@P}
235)zZXx");
236
237GLOBAL_STR(gStr16, R"zZXx(Builtin Commands
238
239 [Memory] append Add elements to end of array
240 pp asdl cell X gc-stats line proc
241 [Handle Errors] try Run with errexit, set _status _error
242 boolstatus Enforce 0 or 1 exit status
243 error error 'failed' (status=2)
244 [Shell State] ysh-cd ysh-shopt compatible, and takes a block
245 shvar Temporary modify global settings
246 ctx Share and update a temporary "context"
247 push-registers Save registers like $?, PIPESTATUS
248 [Modules] runproc Run a proc; use as main entry point
249 module guard against duplicate 'source'
250 is-main false when sourcing a file
251 use change first word lookup
252 [I/O] ysh-read flags --all, -0
253 ysh-echo no -e -n with simple_echo
254 write Like echo, with --, --sep, --end
255 fork forkwait Replace & and (), and takes a block
256 fopen Open multiple streams, takes a block
257 X dbg Only thing that can be used in funcs
258 X log X die common functions (polyfill)
259 [Hay Config] hay haynode For DSLs and config files
260 [Completion] compadjust compexport
261 [Data Formats] json read write
262 json8 read write
263 X packle read write, Graph-shaped
264X [TSV8] rows pick rows; dplyr filter()
265 cols pick columns ('select' already taken)
266 group-by add a column with a group ID [ext]
267 sort-by sort by columns; dplyr arrange() [ext]
268 summary count, sum, histogram, etc. [ext]
269 [Args Parser] parser Parse command line arguments
270 flag
271 arg
272 rest
273 parseArgs()
274X [Testing] describe Test harness
275 assert takes an expression
276X [External Lang] BEGIN END when (awk)
277 rule (make) each (xargs) fs (find)
278)zZXx");
279
280GLOBAL_STR(gStr17, R"zZXx(Builtin Functions
281
282 [Values] len() type() X repeat()
283 [Conversions] bool() int() float() str() list() dict()
284 X chr() X ord() X runes()
285X [Str] strcmp() X split() shSplit()
286 [List] join() any() all()
287 [Collections] X copy() X deepCopy()
288 [Word] glob() maybe()
289 [Math] abs() max() min() X round() sum()
290 [Serialize] toJson() fromJson()
291 toJson8() fromJson8()
292X [J8 Decode] J8.Bool() J8.Int() ...
293X [Codecs] quoteUrl() quoteHtml() quoteSh() quoteC()
294 quoteMake() quoteNinja()
295 [Pattern] _group() _start() _end()
296 [Introspection] shvarGet() evalExpr()
297 [Hay Config] parseHay() evalHay()
298X [Wok] _field()
299X [Hashing] sha1dc() sha256()
300)zZXx");
301
302GLOBAL_STR(gStr18, R"zZXx(The reference is divided in to "chapters", each of which has its own table of
303contents. Type:
304
305 help ysh-$CHAPTER
306
307Where $CHAPTER is one of:
308
309 front-end
310 command-lang
311 expr-lang
312 word-lang
313 builtin-cmd
314 option
315 special-var
316 type-method
317 builtin-func
318
319Example:
320
321 help ysh-expr-lang
322)zZXx");
323
324GLOBAL_STR(gStr19, R"zZXx(Command Language
325
326 [YSH Simple] typed-arg json write (x)
327 lazy-expr-arg assert [42 === x]
328 block-arg cd /tmp { echo $PWD }
329 [YSH Assign] const var setvar setglobal
330 [YSH Expr] equal = = 1 + 2*3
331 call call mylist->append(42)
332 [YSH Code] proc-def proc p (out Ref; pos, ...rest; n=0; b Block) {
333 func-def func f(x; opt1, opt2) { return (x + 1) }
334 ysh-return return (myexpr)
335 [YSH Cond] ysh-case case (x) { *.py { echo 'python' } }
336 ysh-if if (x > 0) { echo }
337 [YSH Iter] ysh-while while (x > 0) { echo }
338 ysh-for for i, item in (mylist) { echo }
339)zZXx");
340
341GLOBAL_STR(gStr20, R"zZXx(Expression Language and Assignments
342
343 [Assign Ops] = += -= *= /= **= //= %=
344 &= |= ^= <<= >>=
345 [Literals] bool-literal true false null
346 int-literal 42 65_536 0xFF 0o755 0b10
347 float-lit 3.14 1.5e-10
348 X num-suffix 42 K Ki M Mi G Gi T Ti / ms us
349 rune-literal #'a' #'_' \n \\ \u{3bc}
350 ysh-string "$x" r'[a-z]\n' u'line\n' b'byte \yff'
351 triple-quoted """ r''' u''' b'''
352 str-template ^"$a and $b" for Str::replace()
353 list-literal ['one', 'two', 3] :| unquoted words |
354 dict-literal {name: 'bob'}
355 range 1 .. n+1
356 block-literal ^(echo $PWD)
357 expr-lit ^[1 + 2*3]
358 X to-string $[myobj]
359 X to-array @[myobj]
360 [Operators] concat s1 ++ s2, L1 ++ L2
361 ysh-equals === !== ~== is, is not, in, not in
362 ysh-compare < <= > >= (numbers only)
363 ysh-logical not and or
364 ysh-arith + - * / // % **
365 ysh-bitwise ~ & | ^ << >>
366 ysh-ternary '+' if x >= 0 else '-'
367 ysh-index a[3] s[3]
368 ysh-attr mydict.key
369 ysh-slice a[1:-1] s[1:-1]
370 func-call f(x, y)
371 thin-arrow mylist->pop()
372 fat-arrow mystr => startsWith('prefix')
373 match-ops ~ !~ ~~ !~~
374 [Eggex] re-literal / d+ ; re-flags ; ERE /
375 re-primitive %zero 'sq'
376 class-literal [c a-z 'abc' @str_var \\ \xFF \u0100]
377 named-class dot digit space word d s w
378 re-repeat d? d* d+ d{3} d{2,4}
379 re-compound seq1 seq2 alt1|alt2 (expr1 expr2)
380 re-capture <capture d+ as name: int>
381 re-splice Subpattern @subpattern
382 re-flags reg_icase reg_newline
383 X re-multiline ///
384)zZXx");
385
386GLOBAL_STR(gStr21, R"zZXx(Front End
387
388 [Usage] bundle-usage ysh-usage
389 [YSH Lexing] doc-comment ### multiline-command ...
390 [Tools] cat-em
391)zZXx");
392
393GLOBAL_STR(gStr22, R"zZXx(Shell Options
394
395 [Option Groups] strict:all ysh:upgrade ysh:all
396 [Strictness] ... More Runtime Errors
397 strict_argv No empty argv
398 strict_arith Fatal parse errors (on by default)
399 strict_array Arrays don't decay to strings
400 strict_control_flow Disallow misplaced keyword, empty arg
401 strict_errexit Disallow code that ignores failure
402 strict_nameref trap invalid variable names
403 strict_word_eval Expose unicode and slicing errors
404 strict_tilde Tilde subst can result in error
405 X strict_glob Parse the sublanguage more strictly
406 [YSH Upgrade] ... Migrate Existing Code to YSH
407 parse_at echo @array @[arrayfunc(x, y)]
408 parse_brace if true { ... }; cd ~/src { ... }
409 parse_equals x = 'val' in Caps { } config blocks
410 parse_paren if (x > 0) ...
411 parse_proc proc p { ... }
412 parse_triple_quote """$x""" '''x''' (command mode)
413 parse_ysh_string echo r'\' u'\\' b'\\' (command mode)
414 command_sub_errexit Synchronous errexit check
415 process_sub_fail Analogous to pipefail for process subs
416 sigpipe_status_ok status 141 -> 0 in pipelines
417 simple_word_eval No splitting, static globbing
418 xtrace_rich Hierarchical and process tracing
419 xtrace_details (-u) Disable most tracing with +
420 dashglob (-u) Disabled to avoid files like -rf
421 expand_aliases (-u) Whether aliases are expanded
422 redefine_proc (-u) Can procs be redefined?
423 [Interactive] redefine_module 'module' builtin always returns 0
424 X redefine_const Can consts be redefined?
425 [Simplicity] ... More Consistent Style
426 simple_echo echo doesn't accept flags -e -n
427 simple_eval_builtin eval takes exactly 1 argument
428 simple_test_builtin 3 args or fewer; use test not [
429 X simple_trap Function name only
430 [YSH Breaking] ... The Full YSH Language
431 parse_at_all @ starting any word is an operator
432 parse_backslash (-u) Allow bad backslashes in "" and $''
433 parse_backticks (-u) Allow legacy syntax `echo hi`
434 parse_bare_word (-u) 'case unquoted' and 'for x in unquoted'
435 parse_dollar (-u) Allow bare $ to mean \$ (maybe $/d+/)
436 parse_dparen (-u) Is (( legacy arithmetic allowed?
437 parse_ignored (-u) Parse, but ignore, certain redirects
438 parse_sh_arith (-u) Allow legacy shell arithmetic
439 X copy_env (-u) Use $[ENV.PYTHONPATH] when false
440 X old_builtins (-u) local/declare/etc. pushd/popd/dirs
441 ... source unset printf [un]alias
442 ... getopts
443 X old_syntax (-u) [[ $(( )) ( ) ${x%prefix}
444 ${a[@]} $$
445 [Compatibility] eval_unsafe_arith Allow dynamically parsed a[$(echo 42)]
446 verbose_errexit Whether to print detailed errors
447 [More Options] _allow_command_sub To implement strict_errexit, eval_unsafe_arith
448 _allow_process_sub To implement strict_errexit
449 dynamic_scope To implement 'proc'
450 _no_debug_trap Used in pipelines in job control shell
451)zZXx");
452
453GLOBAL_STR(gStr23, R"zZXx(Plugins and Hooks
454
455 [YSH] renderPrompt()
456)zZXx");
457
458GLOBAL_STR(gStr24, R"zZXx(Special Variables
459
460 [YSH Vars] ARGV X ENV X _ESCAPE
461 _this_dir
462 [YSH Status] _status _error
463 _pipeline_status _process_sub_status
464 [YSH Tracing] SHX_indent SHX_punct SHX_pid_str
465 [YSH read] _reply
466 [History] YSH_HISTFILE
467 [Oils VM] OILS_VERSION
468 OILS_GC_THRESHOLD OILS_GC_ON_EXIT
469 OILS_GC_STATS OILS_GC_STATS_FD
470X [Wok] _filename _line
471X [Builtin Sub] _buffer
472)zZXx");
473
474GLOBAL_STR(gStr25, R"zZXx(Builtin Types and Methods
475
476 [Primitive] Bool Int Float Str Slice Range
477 [Str] X find(eggex) replace()
478 trim() trimStart() trimEnd()
479 startsWith() endsWith()
480 upper() lower() # ascii or unicode
481 search() leftMatch()
482 [Match] group() start() end()
483 X groups() X groupDict()
484 [List] append() pop() extend() indexOf()
485 X insert() X remove() reverse()
486 [Dict] keys() values() X get() X erase()
487 X inc() X accum()
488X [Func] name() location() toJson()
489X [Proc] name() location() toJson()
490X [Module] name() filename()
491 [Place] setValue()
492 [IO] X eval() X captureStdout()
493 promptVal()
494 X time() X strftime()
495 X glob()
496 [Quotation] Expr X Template Command
497 [Code] BuiltinFunc BuiltinMethod
498X [Guts] heapId()
499)zZXx");
500
501GLOBAL_STR(gStr26, R"zZXx(bin/ysh is the shell with data tYpes, influenced by pYthon, JavaScript, ...
502
503Usage: ysh FLAG* SCRIPT ARG*
504 ysh FLAG* -c COMMAND ARG*
505 ysh FLAG*
506
507`bin/ysh` is the same as `bin/osh` with a the `ysh:all` option group set. So
508`bin/ysh` also accepts shell flags.
509
510 ysh -c 'echo hi'
511 ysh myscript.ysh
512 echo 'echo hi' | ysh
513)zZXx");
514
515GLOBAL_STR(gStr27, R"zZXx(Word Language
516
517 [Quotes] ysh-string "$x" r'[a-z]\n' u'line\n' b'byte \yff'
518 triple-quoted """ r''' u''' b'''
519 X tagged-str "<span id=$x>"html
520 [Expression] expr-sub echo $[42 + a[i]]
521 expr-splice echo @[split(x)]
522 var-splice @myarray @ARGV
523 [Formatting] X ysh-printf ${x %.3f}
524 X ysh-format ${x|html}
525)zZXx");
526
527GLOBAL_STR(gStr28, R"zZXx(# args.ysh
528#
529# Usage:
530# source --builtin args.sh
531#
532# parser (&spec) {
533# flag -v --verbose (help="Verbosely") # default is Bool, false
534#
535# flag -P --max-procs ('int', default=-1, doc='''
536# Run at most P processes at a time
537# ''')
538#
539# flag -i --invert ('bool', default=true, doc='''
540# Long multiline
541# Description
542# ''')
543#
544# arg src (help='Source')
545# arg dest (help='Dest')
546# arg times (help='Foo')
547#
548# rest files
549# }
550#
551# var args = parseArgs(spec, ARGV)
552#
553# echo "Verbose $[args.verbose]"
554
555# TODO: See list
556# - It would be nice to keep `flag` and `arg` private, injecting them into the
557# proc namespace only within `Args`
558# - We need "type object" to replace the strings 'int', 'bool', etc.
559# - flag builtin:
560# - handle only long flag or only short flag
561# - flag aliases
562
563proc parser (; place ; ; block_def) {
564 ## Create an args spec which can be passed to parseArgs.
565 ##
566 ## Example:
567 ##
568 ## # NOTE: &spec will create a variable named spec
569 ## parser (&spec) {
570 ## flag -v --verbose ('bool')
571 ## }
572 ##
573 ## var args = parseArgs(spec, ARGV)
574
575 var p = {flags: [], args: []}
576 ctx push (p, block_def)
577
578 # Validate that p.rest = [name] or null and reduce p.rest into name or null.
579 if ('rest' in p) {
580 if (len(p.rest) > 1) {
581 error '`rest` was called more than once' (status=3)
582 } else {
583 setvar p.rest = p.rest[0]
584 }
585 } else {
586 setvar p.rest = null
587 }
588
589 var names = {}
590 for items in ([p.flags, p.args]) {
591 for x in (items) {
592 if (x.name in names) {
593 error "Duplicate flag/arg name $[x.name] in spec" (status=3)
594 }
595
596 setvar names[x.name] = null
597 }
598 }
599
600 # TODO: what about `flag --name` and then `arg name`?
601
602 call place->setValue(p)
603}
604
605proc flag (short, long ; type='bool' ; default=null, help=null) {
606 ## Declare a flag within an `arg-parse`.
607 ##
608 ## Examples:
609 ##
610 ## arg-parse (&spec) {
611 ## flag -v --verbose
612 ## flag -n --count ('int', default=1)
613 ## flag -f --file ('str', help="File to process")
614 ## }
615
616 # bool has a default of false, not null
617 if (type === 'bool' and default === null) {
618 setvar default = false
619 }
620
621 # TODO: validate `type`
622
623 # TODO: Should use "trimPrefix"
624 var name = long[2:]
625
626 ctx emit flags ({short, long, name, type, default, help})
627}
628
629proc arg (name ; ; help=null) {
630 ## Declare a positional argument within an `arg-parse`.
631 ##
632 ## Examples:
633 ##
634 ## arg-parse (&spec) {
635 ## arg name
636 ## arg config (help="config file path")
637 ## }
638
639 ctx emit args ({name, help})
640}
641
642proc rest (name) {
643 ## Take the remaining positional arguments within an `arg-parse`.
644 ##
645 ## Examples:
646 ##
647 ## arg-parse (&grepSpec) {
648 ## arg query
649 ## rest files
650 ## }
651
652 # We emit instead of set to detect multiple invocations of "rest"
653 ctx emit rest (name)
654}
655
656func parseArgs(spec, argv) {
657 ## Given a spec created by `parser`. Parse an array of strings `argv` per
658 ## that spec.
659 ##
660 ## See `parser` for examples of use.
661
662 var i = 0
663 var positionalPos = 0
664 var argc = len(argv)
665 var args = {}
666 var rest = []
667
668 var value
669 var found
670 while (i < argc) {
671 var arg = argv[i]
672 if (arg->startsWith('-')) {
673 setvar found = false
674
675 for flag in (spec.flags) {
676 if ( (flag.short and flag.short === arg) or
677 (flag.long and flag.long === arg) ) {
678 case (flag.type) {
679 ('bool') | (null) { setvar value = true }
680 int {
681 setvar i += 1
682 if (i >= len(argv)) {
683 error "Expected integer after '$arg'" (status=2)
684 }
685
686 try { setvar value = int(argv[i]) }
687 if (_status !== 0) {
688 error "Expected integer after '$arg', got '$[argv[i]]'" (status=2)
689 }
690 }
691 }
692
693 setvar args[flag.name] = value
694 setvar found = true
695 break
696 }
697 }
698
699 if (not found) {
700 error "Unknown flag '$arg'" (status=2)
701 }
702 } elif (positionalPos >= len(spec.args)) {
703 if (not spec.rest) {
704 error "Too many arguments, unexpected '$arg'" (status=2)
705 }
706
707 call rest->append(arg)
708 } else {
709 var pos = spec.args[positionalPos]
710 setvar positionalPos += 1
711 setvar value = arg
712 setvar args[pos.name] = value
713 }
714
715 setvar i += 1
716 }
717
718 if (spec.rest) {
719 setvar args[spec.rest] = rest
720 }
721
722 # Set defaults for flags
723 for flag in (spec.flags) {
724 if (flag.name not in args) {
725 setvar args[flag.name] = flag.default
726 }
727 }
728
729 # Raise error on missing args
730 for arg in (spec.args) {
731 if (arg.name not in args) {
732 error "Usage Error: Missing required argument $[arg.name]" (status=2)
733 }
734 }
735
736 return (args)
737}
738)zZXx");
739
740GLOBAL_STR(gStr29, R"zZXx(func identity(x) {
741 ## The identity function. Returns its argument.
742
743 return (x)
744}
745)zZXx");
746
747GLOBAL_STR(gStr30, R"zZXx(func any(list) {
748 ## Returns true if any value in the list is truthy.
749 ##
750 ## If the list is empty, return false.
751
752 for item in (list) {
753 if (item) {
754 return (true)
755 }
756 }
757 return (false)
758}
759
760func all(list) {
761 ## Returns true if all values in the list are truthy.
762 ##
763 ## If the list is empty, return true.
764
765 for item in (list) {
766 if (not item) {
767 return (false)
768 }
769 }
770 return (true)
771}
772
773func sum(list; start=0) {
774 ## Computes the sum of all elements in the list.
775 ##
776 ## Returns 0 for an empty list.
777
778 var sum = start
779 for item in (list) {
780 setvar sum += item
781 }
782 return (sum)
783}
784)zZXx");
785
786GLOBAL_STR(gStr31, R"zZXx(func __math_select(list, cmp) {
787 ## Internal helper for `max` and `min`.
788 ##
789 ## NOTE: If `list` is empty, then an error is thrown.
790
791 if (len(list) === 0) {
792 error "Unexpected empty list" (status=3)
793 }
794
795 if (len(list) === 1) {
796 return (list[0])
797 }
798
799 var match = list[0]
800 for i in (1 .. len(list)) {
801 setvar match = cmp(list[i], match)
802 }
803 return (match)
804}
805
806func max(...args) {
807 ## Compute the maximum of 2 or more values.
808 ##
809 ## `max` takes two different signatures:
810 ## - `max(a, b)` to return the maximum of `a`, `b`
811 ## - `max(list)` to return the greatest item in the `list`
812 ##
813 ## So, for example:
814 ##
815 ## max(1, 2) # => 2
816 ## max([1, 2, 3]) # => 3
817
818 case (len(args)) {
819 (1) { return (__math_select(args[0], max)) }
820 (2) {
821 if (args[0] > args[1]) {
822 return (args[0])
823 } else {
824 return (args[1])
825 }
826 }
827 (else) { error "max expects 1 or 2 args" (status=3) }
828 }
829}
830
831func min(...args) {
832 ## Compute the minimum of 2 or more values.
833 ##
834 ## `min` takes two different signatures:
835 ## - `min(a, b)` to return the minimum of `a`, `b`
836 ## - `min(list)` to return the least item in the `list`
837 ##
838 ## So, for example:
839 ##
840 ## min(2, 3) # => 2
841 ## max([1, 2, 3]) # => 1
842
843 case (len(args)) {
844 (1) { return (__math_select(args[0], min)) }
845 (2) {
846 if (args[0] < args[1]) {
847 return (args[0])
848 } else {
849 return (args[1])
850 }
851 }
852 (else) { error "min expects 1 or 2 args" (status=3) }
853 }
854}
855
856func abs(x) {
857 ## Compute the absolute (positive) value of a number (float or int).
858
859 if (x < 0) {
860 return (-x)
861 } else {
862 return (x)
863 }
864}
865)zZXx");
866
867GLOBAL_STR(gStr32, R"zZXx(# Can we define methods in pure YSH?
868#
869# (mylist->find(42) !== -1)
870#
871# instead of
872#
873# ('42' in mylist)
874#
875# Because 'in' is for Dict
876
877func find (haystack List, needle) {
878 for i, x in (haystack) {
879 if (x === needle) {
880 return (i)
881 }
882 }
883 return (-1)
884}
885)zZXx");
886
887GLOBAL_STR(gStr33, R"zZXx(# These were helpful while implementing args.ysh
888# Maybe we will want to export them in a prelude so that others can use them too?
889#
890# Prior art: Rust has `todo!()` which is quite nice. Other languages allow
891# users to `raise NotImplmentedError()`.
892
893# Andy comments:
894# - 'pass' can be : or true in shell. It's a little obscure / confusing, but
895# there is an argument for minimalism. Although I prefer words like 'true',
896# and that already means something.
897# - UPDATE: we once took 'pass' as a keyword, but users complained because
898# there is a command 'pass'. So we probably can't have this by default.
899# Need to discuss source --builtin.
900
901# - todo could be more static? Rust presumably does it at compile time
902
903proc todo () {
904 ## Raises a not implemented error when run.
905 error ("TODO: not implemented") # TODO: is error code 1 ok?
906}
907
908proc pass () {
909 ## Use when you want to temporarily leave a block empty.
910 _ null
911}
912)zZXx");
913
914GLOBAL_STR(gStr34, R"zZXx(# testing.ysh
915#
916# Usage:
917# source --builtin testing.sh
918#
919# func f(x) { return (x + 1) }
920#
921# describe foo {
922# assert (43 === f(42))
923# }
924#
925# if is-main {
926# run-tests @ARGV # --filter
927# }
928
929module stdlib/testing || return 0
930
931source --builtin args.ysh
932
933# Opt in to lazy evaluation
934
935proc assert ( ; cond LAZY ) {
936 echo hi
937
938 # TODO: evalExpr() builtin
939 var val = evalExpr(cond)
940 if (not val) {
941 # TODO: if it's an expr.Binary
942 # Then
943 #
944 # Then print $left != $right
945 #
946 # I think you need to introspect on the source code
947 #
948 # Or print '5 != 3'
949 #
950 # Or you can evaluate left and right separately, and then compare them
951
952 echo
953 }
954}
955
956# What happens when there are duplicate test IDs?
957#
958# Also I think filter by "$test_id/$case_id"
959
960proc __it (case_id ; ; ; block) {
961 # This uses a clean directory
962 echo TODO
963}
964
965# is this accessible to users?
966# It can contain a global list of things to run
967
968# Naming convention: a proc named 'describe' mutates a global named _describe?
969# Or maybe _describe_list ?
970
971var _describe_list = []
972
973proc describe (test_id ; ; ; block) {
974 echo describe
975 = desc
976
977 # TODO:
978 # - need append
979 # - need ::
980 # _ _describe->append(cmd)
981 #
982 # Need to clean this up
983 # append (_describe, cmd) # does NOT work!
984
985 _ _describe_list->append(block)
986}
987
988# Problem: this creates a global variable?
989Args :spec {
990 flag --filter 'Regex of test descriptions'
991}
992
993proc run-tests {
994
995 # TODO: fix this crap
996 var opt = null
997 var i = null
998 setvar opt, i = parseArgs(spec, ARGV)
999
1000 # TODO:
1001 # - parse --filter foo, which you can use eggex for!
1002
1003 for cmd in (_describe) {
1004 # TODO: print filename and 'describe' name?
1005 try {
1006 eval (cmd)
1007 }
1008 if (_status !== 0) {
1009 echo 'failed'
1010 }
1011 }
1012}
1013)zZXx");
1014
1015
1016
1017TextFile array[] = {
1018 {.rel_path = "_devbuild/help/data-errors", .contents = gStr0},
1019 {.rel_path = "_devbuild/help/data-j8-notation", .contents = gStr1},
1020 {.rel_path = "_devbuild/help/data-packle", .contents = gStr2},
1021 {.rel_path = "_devbuild/help/help", .contents = gStr3},
1022 {.rel_path = "_devbuild/help/oils-usage", .contents = gStr4},
1023 {.rel_path = "_devbuild/help/osh-builtin-cmd", .contents = gStr5},
1024 {.rel_path = "_devbuild/help/osh-chapters", .contents = gStr6},
1025 {.rel_path = "_devbuild/help/osh-cmd-lang", .contents = gStr7},
1026 {.rel_path = "_devbuild/help/osh-front-end", .contents = gStr8},
1027 {.rel_path = "_devbuild/help/osh-mini-lang", .contents = gStr9},
1028 {.rel_path = "_devbuild/help/osh-option", .contents = gStr10},
1029 {.rel_path = "_devbuild/help/osh-osh-assign", .contents = gStr11},
1030 {.rel_path = "_devbuild/help/osh-plugin", .contents = gStr12},
1031 {.rel_path = "_devbuild/help/osh-special-var", .contents = gStr13},
1032 {.rel_path = "_devbuild/help/osh-usage", .contents = gStr14},
1033 {.rel_path = "_devbuild/help/osh-word-lang", .contents = gStr15},
1034 {.rel_path = "_devbuild/help/ysh-builtin-cmd", .contents = gStr16},
1035 {.rel_path = "_devbuild/help/ysh-builtin-func", .contents = gStr17},
1036 {.rel_path = "_devbuild/help/ysh-chapters", .contents = gStr18},
1037 {.rel_path = "_devbuild/help/ysh-cmd-lang", .contents = gStr19},
1038 {.rel_path = "_devbuild/help/ysh-expr-lang", .contents = gStr20},
1039 {.rel_path = "_devbuild/help/ysh-front-end", .contents = gStr21},
1040 {.rel_path = "_devbuild/help/ysh-option", .contents = gStr22},
1041 {.rel_path = "_devbuild/help/ysh-plugin", .contents = gStr23},
1042 {.rel_path = "_devbuild/help/ysh-special-var", .contents = gStr24},
1043 {.rel_path = "_devbuild/help/ysh-type-method", .contents = gStr25},
1044 {.rel_path = "_devbuild/help/ysh-usage", .contents = gStr26},
1045 {.rel_path = "_devbuild/help/ysh-word-lang", .contents = gStr27},
1046 {.rel_path = "stdlib/args.ysh", .contents = gStr28},
1047 {.rel_path = "stdlib/funcs.ysh", .contents = gStr29},
1048 {.rel_path = "stdlib/list.ysh", .contents = gStr30},
1049 {.rel_path = "stdlib/math.ysh", .contents = gStr31},
1050 {.rel_path = "stdlib/methods.ysh", .contents = gStr32},
1051 {.rel_path = "stdlib/prelude.ysh", .contents = gStr33},
1052 {.rel_path = "stdlib/testing.ysh", .contents = gStr34},
1053
1054 {.rel_path = nullptr, .contents = nullptr},
1055};
1056
1057} // namespace embedded_file
1058
1059TextFile* gEmbeddedFiles = embedded_file::array; // turn array into pointer