| 1 | 
 | 
| 2 | #include "cpp/embedded_file.h"
 | 
| 3 | 
 | 
| 4 | namespace embedded_file {
 | 
| 5 | GLOBAL_STR(gStr0, R"zZXx(
 | 
| 6 |   Errors
 | 
| 7 |   <a class="group-link" href="chap-errors.html">errors</a>
 | 
| 8 | 
 | 
| 9 | 
 | 
| 10 |   [UTF8]      err-utf8-encode       err-utf8-decode
 | 
| 11 |   [J8 String] err-j8-str-encode     err-j8-str-decode
 | 
| 12 |   [J8 Lines]  err-j8-lines-encode   err-j8-lines-decode
 | 
| 13 |   [JSON]      err-json-encode       err-json-decode
 | 
| 14 |   [JSON8]     err-json8-encode      err-json8-decode
 | 
| 15 | )zZXx");
 | 
| 16 | 
 | 
| 17 | GLOBAL_STR(gStr1, R"zZXx(
 | 
| 18 |   
 | 
| 19 |   Front End <a class="group-link" href="chap-front-end.html">front-end</a>
 | 
| 20 | 
 | 
| 21 | 
 | 
| 22 |   [Lexing]        ascii-whitespace [ \t\r\n]
 | 
| 23 |                   ascii-control-chars
 | 
| 24 | )zZXx");
 | 
| 25 | 
 | 
| 26 | GLOBAL_STR(gStr2, R"zZXx(
 | 
| 27 |   J8 Notation
 | 
| 28 |   <a class="group-link" href="chap-j8.html">j8</a>
 | 
| 29 | 
 | 
| 30 | 
 | 
| 31 |   [J8 Strings]   json-string        "hi"
 | 
| 32 |                  json-escape        \"  \\  \u1234
 | 
| 33 |                  surrogate-pair     \ud83e\udd26
 | 
| 34 |                  j8-escape          \'  \u{1f926}  \yff
 | 
| 35 |                  u-prefix           u'hi'
 | 
| 36 |                  b-prefix           b'hi'
 | 
| 37 |                  no-prefix          'hi'
 | 
| 38 |   [J8 Lines]     unquoted-line
 | 
| 39 |   [JSON8]        json8-num          json8-str
 | 
| 40 |                X json8-list       X json8-dict
 | 
| 41 |                  json8-comment
 | 
| 42 |   [TSV8]         column-attrs       column-types
 | 
| 43 | )zZXx");
 | 
| 44 | 
 | 
| 45 | GLOBAL_STR(gStr3, R"zZXx(Usage: help TOPIC?
 | 
| 46 | 
 | 
| 47 | Examples:
 | 
| 48 | 
 | 
| 49 |     help               # this help
 | 
| 50 |     help echo          # help on the 'echo' builtin
 | 
| 51 |     help command-sub   # help on command sub $(date)
 | 
| 52 | 
 | 
| 53 |     help oils-usage    # identical to oils-for-unix --help
 | 
| 54 |     help osh-usage     #              osh --help
 | 
| 55 |     help ysh-usage     #              ysh --help
 | 
| 56 | )zZXx");
 | 
| 57 | 
 | 
| 58 | GLOBAL_STR(gStr4, R"zZXx(bin/oils-for-unix is an executable that contains OSH, YSH, and more.
 | 
| 59 | 
 | 
| 60 | Usage: oils-for-unix MAIN_NAME ARG*
 | 
| 61 |        MAIN_NAME ARG*
 | 
| 62 | 
 | 
| 63 | It behaves like busybox.  The command name can be passed as the first argument:
 | 
| 64 | 
 | 
| 65 |     oils-for-unix ysh -c 'echo hi'
 | 
| 66 | 
 | 
| 67 | More commonly, it's invoked through a symlink like 'ysh', which causes it to
 | 
| 68 | behave like that command:
 | 
| 69 | 
 | 
| 70 |     ysh -c 'echo hi'
 | 
| 71 | )zZXx");
 | 
| 72 | 
 | 
| 73 | GLOBAL_STR(gStr5, R"zZXx(
 | 
| 74 |   Builtin Commands <a class="group-link" href="chap-builtin-cmd.html">builtin-cmd</a>
 | 
| 75 | 
 | 
| 76 | 
 | 
| 77 |   [I/O]           read        echo      printf
 | 
| 78 |                   readarray   mapfile
 | 
| 79 |   [Run Code]      source .    eval      trap
 | 
| 80 |   [Set Options]   set         shopt
 | 
| 81 |   [Working Dir]   cd          pwd       pushd     popd         dirs
 | 
| 82 |   [Completion]    complete    compgen   compopt   compadjust   compexport
 | 
| 83 |   [Shell Process] exec      X logout 
 | 
| 84 |                   umask       ulimit    times
 | 
| 85 |   [Child Process] jobs        wait
 | 
| 86 |                   fg        X bg      X kill        X disown 
 | 
| 87 |   [External]      test [      getopts
 | 
| 88 |   [Introspection] help        hash      cmd/type    X caller
 | 
| 89 |   [Word Lookup]   command     builtin
 | 
| 90 |   [Interactive]   alias       unalias   history     X fc     X bind
 | 
| 91 | X [Unsupported]   enable
 | 
| 92 | )zZXx");
 | 
| 93 | 
 | 
| 94 | GLOBAL_STR(gStr6, R"zZXx(The reference is divided in to "chapters", each of which has its own table of
 | 
| 95 | contents.  Type:
 | 
| 96 | 
 | 
| 97 |     help osh-$CHAPTER
 | 
| 98 | 
 | 
| 99 | Where $CHAPTER is one of:
 | 
| 100 | 
 | 
| 101 |     front-end
 | 
| 102 |     command-lang
 | 
| 103 |     osh-assign
 | 
| 104 |     word-lang
 | 
| 105 |     mini-lang
 | 
| 106 |     builtin-cmd
 | 
| 107 |     option
 | 
| 108 |     special-var
 | 
| 109 |     plugin
 | 
| 110 | 
 | 
| 111 | Example:
 | 
| 112 | 
 | 
| 113 |     help osh-word-lang
 | 
| 114 | )zZXx");
 | 
| 115 | 
 | 
| 116 | GLOBAL_STR(gStr7, R"zZXx(
 | 
| 117 |   Command Language <a class="group-link" href="chap-cmd-lang.html">cmd-lang</a>
 | 
| 118 | 
 | 
| 119 | 
 | 
| 120 |   [Commands]      simple-command            semicolon ;
 | 
| 121 |   [Conditional]   case        if            dbracket [[
 | 
| 122 |                   true        false         colon :
 | 
| 123 |                   bang !      and &&        or ||
 | 
| 124 |   [Iteration]     while       until         for            for-expr-sh ((
 | 
| 125 |   [Control Flow]  break       continue      return         exit
 | 
| 126 |   [Grouping]      sh-func     sh-block {    subshell (
 | 
| 127 |   [Concurrency]   pipe |    X pipe-amp |&   ampersand &
 | 
| 128 |   [Redirects]     redir-file  >  >>  >|  <  <>   not impl: &>
 | 
| 129 |                   redir-desc  >&  <&
 | 
| 130 |                   here-doc    <<  <<-  <<<
 | 
| 131 |   [Other Command] dparen ((   time        X coproc       X select
 | 
| 132 | )zZXx");
 | 
| 133 | 
 | 
| 134 | GLOBAL_STR(gStr8, R"zZXx(
 | 
| 135 |   Front End <a class="group-link" href="chap-front-end.html">front-end</a>
 | 
| 136 | 
 | 
| 137 | 
 | 
| 138 |   [Usage]         oils-usage   osh-usage             config
 | 
| 139 |                   startup      line-editing          exit-codes
 | 
| 140 |   [Lexing]        comment #    line-continuation \   ascii-whitespace [ \t\r\n]
 | 
| 141 | )zZXx");
 | 
| 142 | 
 | 
| 143 | GLOBAL_STR(gStr9, R"zZXx(
 | 
| 144 |   Other Mini Languages <a class="group-link" href="chap-mini-lang.html">mini-lang</a>
 | 
| 145 | 
 | 
| 146 | 
 | 
| 147 |   [Arithmetic]    arith-context Where legacy arithmetic is allowed
 | 
| 148 |                   sh-numbers    0xFF  0755  etc.
 | 
| 149 |                   sh-arith      1 + 2*3   a *= 2
 | 
| 150 |                   sh-logical    !a && b
 | 
| 151 |                   sh-bitwise    ~a ^ b
 | 
| 152 |   [Boolean]       bool-expr     [[ ! $x && $y || $z ]]
 | 
| 153 |                                 test ! $x -a $y -o $z
 | 
| 154 |                   bool-infix    $a -nt $b    $x == $y
 | 
| 155 |                   bool-path     -d /etc
 | 
| 156 |                   bool-str      -n foo   -z '' 
 | 
| 157 |                   bool-other    -o errexit   -v name[index]
 | 
| 158 |   [Patterns]      glob-pat      *.py
 | 
| 159 |                   extglob       ,(*.py|*.sh)
 | 
| 160 |                   regex         [[ foo =~ [a-z]+ ]]
 | 
| 161 |   [Other Sublang] braces        {alice,bob}@example.com
 | 
| 162 |                   histsub       !$  !!  !n
 | 
| 163 |                   char-escapes  \t  \c  \x00  \u03bc
 | 
| 164 | )zZXx");
 | 
| 165 | 
 | 
| 166 | GLOBAL_STR(gStr10, R"zZXx(
 | 
| 167 |   Global Shell Options <a class="group-link" href="chap-option.html">option</a>
 | 
| 168 | 
 | 
| 169 | 
 | 
| 170 |   [Errors]         nounset -u      errexit -e   inherit_errexit   pipefail
 | 
| 171 |   [Globbing]       noglob -f       nullglob     failglob        X dotglob
 | 
| 172 |                    dashglob (true)
 | 
| 173 |   [Debugging]      xtrace        X verbose    X extdebug
 | 
| 174 |   [Interactive]    emacs           vi
 | 
| 175 |   [Other POSIX]  X noclobber
 | 
| 176 |   [Compat]         eval_unsafe_arith            ignore_flags_not_impl
 | 
| 177 | )zZXx");
 | 
| 178 | 
 | 
| 179 | GLOBAL_STR(gStr11, R"zZXx(
 | 
| 180 |   Assignments and Expressions <a class="group-link" href="chap-osh-assign.html">osh-assign</a>
 | 
| 181 | 
 | 
| 182 | 
 | 
| 183 |   [Literals]      sh-array      array=(a b c)   array[1]=B   "${a[@]}"
 | 
| 184 |                   sh-assoc      assoc=(['a']=1 ['b']=2)   assoc['x']=b
 | 
| 185 |   [Operators]     sh-assign     str='xyz'
 | 
| 186 |                   sh-append     str+='abc'
 | 
| 187 |   [Builtins]      local     readonly    export   unset   shift
 | 
| 188 |                   declare   typeset   X let
 | 
| 189 | )zZXx");
 | 
| 190 | 
 | 
| 191 | GLOBAL_STR(gStr12, R"zZXx(
 | 
| 192 |   Plugins and Hooks <a class="group-link" href="chap-plugin.html">plugin</a>
 | 
| 193 | 
 | 
| 194 | 
 | 
| 195 |   [Signals]       SIGTERM     SIGINT     SIGQUIT
 | 
| 196 |                   SIGTTIN     SIGTTOU    SIGWINCH
 | 
| 197 |   [Traps]         DEBUG       ERR        EXIT    X RETURN
 | 
| 198 |   [Words]         PS1       X PS2      X PS3       PS4
 | 
| 199 |   [Completion]    complete
 | 
| 200 |   [Other Plugin]  PROMPT_COMMAND       X command_not_found    
 | 
| 201 | )zZXx");
 | 
| 202 | 
 | 
| 203 | GLOBAL_STR(gStr13, R"zZXx(
 | 
| 204 |   Special Variables <a class="group-link" href="chap-special-var.html">special-var</a>
 | 
| 205 | 
 | 
| 206 | 
 | 
| 207 |   [POSIX Special] $@  $*  $#     $?  $-     $$  $!   $0  $9
 | 
| 208 |   [Shell Vars]    IFS             X LANG       X GLOBIGNORE
 | 
| 209 |   [Shell Options] SHELLOPTS       X BASHOPTS
 | 
| 210 |   [Other Env]     HOME              PATH
 | 
| 211 |   [Other Special] BASH_REMATCH     @PIPESTATUS
 | 
| 212 |   [Platform]      HOSTNAME          OSTYPE
 | 
| 213 |   [Call Stack]    @BASH_SOURCE     @FUNCNAME    @BASH_LINENO   
 | 
| 214 |                 X @BASH_ARGV     X @BASH_ARGC
 | 
| 215 |   [Tracing]       LINENO
 | 
| 216 |   [Process State] UID               EUID         PPID       X BASHPID
 | 
| 217 | X [Process Stack] BASH_SUBSHELL     SHLVL
 | 
| 218 | X [Shell State]   BASH_CMDS        @DIRSTACK
 | 
| 219 |   [Completion]   @COMP_WORDS        COMP_CWORD    COMP_LINE   COMP_POINT
 | 
| 220 |                   COMP_WORDBREAKS  @COMPREPLY   X COMP_KEY
 | 
| 221 |                 X COMP_TYPE         COMP_ARGV
 | 
| 222 |   [History]       HISTFILE
 | 
| 223 |   [cd]            PWD               OLDPWD      X CDPATH
 | 
| 224 |   [getopts]       OPTIND            OPTARG      X OPTERR
 | 
| 225 |   [read]          REPLY
 | 
| 226 |   [Functions]   X RANDOM            SECONDS
 | 
| 227 |   [Oils VM]       OILS_VERSION      LIB_OSH
 | 
| 228 | )zZXx");
 | 
| 229 | 
 | 
| 230 | GLOBAL_STR(gStr14, R"zZXx(
 | 
| 231 |   Standard Library <a class="group-link" href="chap-stdlib.html">stdlib</a>
 | 
| 232 | 
 | 
| 233 | 
 | 
| 234 |   [two]           log             die
 | 
| 235 |   [no-quotes]     nq-assert       nq-run          
 | 
| 236 |                   nq-capture      nq-capture-2
 | 
| 237 |                   nq-redir        nq-redir-2
 | 
| 238 |   [bash-strict]   
 | 
| 239 |   [task-five]     
 | 
| 240 | )zZXx");
 | 
| 241 | 
 | 
| 242 | GLOBAL_STR(gStr15, R"zZXx(
 | 
| 243 |   OSH Types <a class="group-link" href="chap-type-method.html">type-method</a>
 | 
| 244 | 
 | 
| 245 | 
 | 
| 246 |   [OSH]           BashArray   BashAssoc
 | 
| 247 | )zZXx");
 | 
| 248 | 
 | 
| 249 | GLOBAL_STR(gStr16, R"zZXx(bin/osh is compatible with POSIX shell, bash, and other shells.
 | 
| 250 | 
 | 
| 251 | Usage: osh FLAG* SCRIPT ARG*
 | 
| 252 |        osh FLAG* -c COMMAND ARG*
 | 
| 253 |        osh FLAG*
 | 
| 254 | 
 | 
| 255 | The command line accepted by `bin/osh` is compatible with /bin/sh and bash.
 | 
| 256 | 
 | 
| 257 |     osh -c 'echo hi'
 | 
| 258 |     osh myscript.sh
 | 
| 259 |     echo 'echo hi' | osh
 | 
| 260 | 
 | 
| 261 | It also has a few enhancements:
 | 
| 262 | 
 | 
| 263 |     osh -n -c 'hello'                    # pretty-print the AST
 | 
| 264 |     osh --ast-format text -n -c 'hello'  # print it full
 | 
| 265 | 
 | 
| 266 | osh accepts POSIX sh flags, with these additions:
 | 
| 267 | 
 | 
| 268 |     -n             parse the program but don't execute it.  Print the AST.
 | 
| 269 |     --ast-format   what format the AST should be in
 | 
| 270 | )zZXx");
 | 
| 271 | 
 | 
| 272 | GLOBAL_STR(gStr17, R"zZXx(
 | 
| 273 |   Word Language <a class="group-link" href="chap-word-lang.html">word-lang</a>
 | 
| 274 | 
 | 
| 275 | 
 | 
| 276 |   [Quotes]        osh-string    'abc'  $'line\n'  "$var"
 | 
| 277 |   [Substitutions] command-sub   $(command)   `command`
 | 
| 278 |                   var-sub       ${var}   $0   $9   
 | 
| 279 |                   arith-sub     $((1 + 2))
 | 
| 280 |                   tilde-sub     ~/src
 | 
| 281 |                   proc-sub      diff <(sort L.txt) <(sort R.txt)
 | 
| 282 |   [Var Ops]       op-test       ${x:-default}  
 | 
| 283 |                   op-strip      ${x%%suffix}  etc.
 | 
| 284 |                   op-replace    ${x//y/z}
 | 
| 285 |                   op-index      ${a[i+1}
 | 
| 286 |                   op-slice      ${a[@]:0:1}
 | 
| 287 |                   op-format     ${x@P}
 | 
| 288 | )zZXx");
 | 
| 289 | 
 | 
| 290 | GLOBAL_STR(gStr18, R"zZXx(
 | 
| 291 |   Builtin Commands <a class="group-link" href="chap-builtin-cmd.html">builtin-cmd</a>
 | 
| 292 | 
 | 
| 293 | 
 | 
| 294 |   [Memory]        cmd/append             Add elements to end of array
 | 
| 295 |                   pp                     asdl   cell   X gc-stats   line   proc
 | 
| 296 |   [Handle Errors] error                  error 'failed' (status=2)
 | 
| 297 |                   try                    Run with errexit, set _error
 | 
| 298 |                   failed                 Test if _error.code !== 0
 | 
| 299 |                   boolstatus             Enforce 0 or 1 exit status
 | 
| 300 |   [Shell State]   ysh-cd       ysh-shopt compatible, and takes a block
 | 
| 301 |                   shvar                  Temporary modify global settings
 | 
| 302 |                   ctx                    Share and update a temporary "context"
 | 
| 303 |                   push-registers         Save registers like $?, PIPESTATUS
 | 
| 304 |   [Modules]       runproc                Run a proc; use as main entry point
 | 
| 305 |                   module                 guard against duplicate 'source'
 | 
| 306 |                   is-main                false when sourcing a file
 | 
| 307 |                   use                    change first word lookup
 | 
| 308 |   [I/O]           ysh-read               flags --all, -0
 | 
| 309 |                   ysh-echo               no -e -n with simple_echo
 | 
| 310 |                   write                  Like echo, with --, --sep, --end
 | 
| 311 |                   fork         forkwait  Replace & and (), and takes a block
 | 
| 312 |                   fopen                  Open multiple streams, takes a block
 | 
| 313 |                 X dbg                    Only thing that can be used in funcs
 | 
| 314 |   [Hay Config]    hay          haynode   For DSLs and config files
 | 
| 315 |   [Completion]    compadjust   compexport
 | 
| 316 |   [Data Formats]  json                   read write
 | 
| 317 |                   json8                  read write
 | 
| 318 | X [Testing]       assert                 takes an expression
 | 
| 319 | )zZXx");
 | 
| 320 | 
 | 
| 321 | GLOBAL_STR(gStr19, R"zZXx(
 | 
| 322 |   Builtin Functions <a class="group-link" href="chap-builtin-func.html">builtin-func</a>
 | 
| 323 | 
 | 
| 324 | 
 | 
| 325 |   [Values]        len()             func/type()
 | 
| 326 |   [Conversions]   bool()            int()           float()
 | 
| 327 |                   str()             list()          dict()
 | 
| 328 |                 X runes()         X encodeRunes()
 | 
| 329 |                 X bytes()         X encodeBytes()
 | 
| 330 |   [Str]         X strcmp()        X split()         shSplit()
 | 
| 331 |   [List]          join()       
 | 
| 332 |   [Float]         floatsEqual()   X isinf()       X isnan()
 | 
| 333 |   [Collections] X copy()          X deepCopy()
 | 
| 334 |   [Word]          glob()            maybe()
 | 
| 335 |   [Serialize]     toJson()          fromJson()
 | 
| 336 |                   toJson8()         fromJson8()
 | 
| 337 | X [J8 Decode]     J8.Bool()         J8.Int()        ...
 | 
| 338 |   [Pattern]       _group()          _start()        _end()
 | 
| 339 |   [Introspection] shvarGet()        getVar()        evalExpr()
 | 
| 340 |   [Hay Config]    parseHay()        evalHay()
 | 
| 341 | X [Hashing]       sha1dc()          sha256()
 | 
| 342 | )zZXx");
 | 
| 343 | 
 | 
| 344 | GLOBAL_STR(gStr20, R"zZXx(The reference is divided in to "chapters", each of which has its own table of
 | 
| 345 | contents.  Type:
 | 
| 346 | 
 | 
| 347 |     help ysh-$CHAPTER
 | 
| 348 | 
 | 
| 349 | Where $CHAPTER is one of:
 | 
| 350 | 
 | 
| 351 |     front-end
 | 
| 352 |     command-lang
 | 
| 353 |     expr-lang
 | 
| 354 |     word-lang
 | 
| 355 |     builtin-cmd
 | 
| 356 |     option
 | 
| 357 |     special-var
 | 
| 358 |     type-method
 | 
| 359 |     builtin-func
 | 
| 360 | 
 | 
| 361 | Example:
 | 
| 362 | 
 | 
| 363 |     help ysh-expr-lang
 | 
| 364 | )zZXx");
 | 
| 365 | 
 | 
| 366 | GLOBAL_STR(gStr21, R"zZXx(
 | 
| 367 |   Command Language <a class="group-link" href="chap-cmd-lang.html">cmd-lang</a>
 | 
| 368 | 
 | 
| 369 | 
 | 
| 370 |   [YSH Simple]    typed-arg     json write (x)
 | 
| 371 |                   lazy-expr-arg assert [42 === x]
 | 
| 372 |                   block-arg     cd /tmp { echo $PWD }; cd /tmp (; ; blockexpr)
 | 
| 373 |   [YSH Cond]      ysh-case      case (x) { *.py { echo 'python' } }
 | 
| 374 |                   ysh-if        if (x > 0) { echo }
 | 
| 375 |   [YSH Iter]      ysh-while     while (x > 0) { echo }
 | 
| 376 |                   ysh-for       for i, item in (mylist) { echo }
 | 
| 377 | )zZXx");
 | 
| 378 | 
 | 
| 379 | GLOBAL_STR(gStr22, R"zZXx(
 | 
| 380 |   Expression Language and Assignments <a class="group-link" href="chap-expr-lang.html">expr-lang</a>
 | 
| 381 | 
 | 
| 382 | 
 | 
| 383 |   [Assignment]    assign        =
 | 
| 384 |                   aug-assign    +=   -=   *=   /=   **=   //=   %=
 | 
| 385 |                                 &=   |=   ^=   <<=   >>=
 | 
| 386 |   [Literals]      atom-literal  true   false   null
 | 
| 387 |                   int-literal   42  65_536  0xFF  0o755  0b10
 | 
| 388 |                   float-lit     3.14  1.5e-10
 | 
| 389 |                   char-literal  \\ \t \"   \y00   \u{3bc}
 | 
| 390 |                 X num-suffix    42 K Ki M Mi G Gi T Ti / ms us
 | 
| 391 |                   ysh-string    "x is $x"  $"x is $x"   r'[a-z]\n'
 | 
| 392 |                                 u'line\n'  b'byte \yff'
 | 
| 393 |                   triple-quoted """  $"""  r'''  u'''  b'''
 | 
| 394 |                   str-template  ^"$a and $b" for Str::replace()
 | 
| 395 |                   list-literal  ['one', 'two', 3]  :| unquoted words |
 | 
| 396 |                   dict-literal  {name: 'bob'}  {a, b}
 | 
| 397 |                   range         1 .. n+1
 | 
| 398 |                   block-expr    ^(echo $PWD)
 | 
| 399 |                   expr-literal  ^[1 + 2*3]
 | 
| 400 |                 X expr-sub      $[myobj]
 | 
| 401 |                 X expr-splice   @[myobj]
 | 
| 402 |   [Operators]     op-precedence Like Python
 | 
| 403 |                   concat        s1 ++ s2,  L1 ++ L2
 | 
| 404 |                   ysh-equals    ===   !==   ~==   is, is not
 | 
| 405 |                   ysh-in        in, not in
 | 
| 406 |                   ysh-compare   <  <=  >  >=  (numbers only)
 | 
| 407 |                   ysh-logical   not  and  or
 | 
| 408 |                   ysh-arith     +  -  *  /  //  %   ** 
 | 
| 409 |                   ysh-bitwise   ~  &  |  ^  <<  >>
 | 
| 410 |                   ysh-ternary   '+' if x >= 0 else '-'
 | 
| 411 |                   ysh-index     s[0]  mylist[3]  mydict['key']
 | 
| 412 |                   ysh-attr      mydict.key
 | 
| 413 |                   ysh-slice     a[1:-1]  s[1:-1]
 | 
| 414 |                   func-call     f(x, y; ...named)
 | 
| 415 |                   thin-arrow    mylist->pop()
 | 
| 416 |                   fat-arrow     mystr => startsWith('prefix')
 | 
| 417 |                   match-ops     ~   !~   ~~   !~~
 | 
| 418 |   [Eggex]         re-literal    / d+ ; re-flags ; ERE /
 | 
| 419 |                   re-primitive  %zero    'sq'
 | 
| 420 |                   class-literal [c a-z 'abc' @str_var \\ \xFF \u0100]
 | 
| 421 |                   named-class    dot   digit   space   word   d  s  w
 | 
| 422 |                   re-repeat     d?   d*   d+   d{3}   d{2,4}
 | 
| 423 |                   re-compound    seq1 seq2   alt1|alt2   (expr1 expr2)
 | 
| 424 |                   re-capture    <capture d+ as name: int>
 | 
| 425 |                   re-splice     Subpattern   @subpattern
 | 
| 426 |                   re-flags      reg_icase   reg_newline
 | 
| 427 |                 X re-multiline  ///
 | 
| 428 | )zZXx");
 | 
| 429 | 
 | 
| 430 | GLOBAL_STR(gStr23, R"zZXx(
 | 
| 431 |   Front End <a class="group-link" href="chap-front-end.html">front-end</a>
 | 
| 432 | 
 | 
| 433 | 
 | 
| 434 |   [Usage]         oils-usage                   ysh-usage
 | 
| 435 |   [Lexing]        ascii-whitespace [ \t\r\n]
 | 
| 436 |                   doc-comment ###              multiline-command ...
 | 
| 437 |   [Tools]         cat-em
 | 
| 438 | )zZXx");
 | 
| 439 | 
 | 
| 440 | GLOBAL_STR(gStr24, R"zZXx(
 | 
| 441 |   Other Mini Languages <a class="group-link" href="chap-mini-lang.html">mini-lang</a>
 | 
| 442 | 
 | 
| 443 | 
 | 
| 444 |   [Patterns]      glob-pat      *.py
 | 
| 445 |   [Other Sublang] braces        {alice,bob}@example.com
 | 
| 446 | )zZXx");
 | 
| 447 | 
 | 
| 448 | GLOBAL_STR(gStr25, R"zZXx(
 | 
| 449 |   Global Shell Options <a class="group-link" href="chap-option.html">option</a>
 | 
| 450 | 
 | 
| 451 | 
 | 
| 452 |   [Groups]       strict:all      ysh:upgrade     ysh:all
 | 
| 453 |   [YSH Details]  opts-redefine   opts-internal
 | 
| 454 | )zZXx");
 | 
| 455 | 
 | 
| 456 | GLOBAL_STR(gStr26, R"zZXx(
 | 
| 457 |   Plugins and Hooks <a class="group-link" href="chap-plugin.html">plugin</a>
 | 
| 458 | 
 | 
| 459 | 
 | 
| 460 |   [YSH]   renderPrompt()
 | 
| 461 | )zZXx");
 | 
| 462 | 
 | 
| 463 | GLOBAL_STR(gStr27, R"zZXx(
 | 
| 464 |   Special Variables <a class="group-link" href="chap-special-var.html">special-var</a>
 | 
| 465 | 
 | 
| 466 | 
 | 
| 467 |   [YSH Vars]      ARGV              X ENV                 X _ESCAPE
 | 
| 468 |                   _this_dir
 | 
| 469 |   [YSH Status]    _error
 | 
| 470 |                   _pipeline_status    _process_sub_status
 | 
| 471 |   [YSH Tracing]   SHX_indent          SHX_punct             SHX_pid_str
 | 
| 472 |   [YSH read]      _reply
 | 
| 473 |   [History]       YSH_HISTFILE
 | 
| 474 |   [Oils VM]       OILS_VERSION
 | 
| 475 |                   OILS_GC_THRESHOLD   OILS_GC_ON_EXIT
 | 
| 476 |                   OILS_GC_STATS       OILS_GC_STATS_FD
 | 
| 477 |                   LIB_YSH
 | 
| 478 |   [Float]         NAN                 INFINITY
 | 
| 479 | )zZXx");
 | 
| 480 | 
 | 
| 481 | GLOBAL_STR(gStr28, R"zZXx(
 | 
| 482 |   Standard Library<a class="group-link" href="chap-stdlib.html">stdlib</a>
 | 
| 483 | 
 | 
| 484 | 
 | 
| 485 |   [math]          abs()     
 | 
| 486 |                   max()     min()
 | 
| 487 |                 X round()
 | 
| 488 |                   sum()     
 | 
| 489 |   [list]          all()     any()     
 | 
| 490 |                   repeat()
 | 
| 491 |   [args]          parser                 Parse command line arguments
 | 
| 492 |                   flag
 | 
| 493 |                   arg
 | 
| 494 |                   rest
 | 
| 495 |                   parseArgs()
 | 
| 496 |   [yblocks]       yb-capture
 | 
| 497 |                   yb-capture-2
 | 
| 498 | X [Lines]         slurp-by               combine adjacent lines into cells
 | 
| 499 | X [Awk]           each-line              --j8 --max-jobs (Str, Template, Block) - xargs
 | 
| 500 |                   each-row               --max-jobs (Str, Template, Block) - xargs
 | 
| 501 |                   each-word              xargs-like splitting, similar to IFS too
 | 
| 502 |                   split-by               (str=\n, ifs=':', pattern=/s+/)
 | 
| 503 |                   if-split-by  
 | 
| 504 |                   chop                   alias for split-by (pattern=/s+/)
 | 
| 505 |                   must-match             (/ <capture d+> </capture w+> /)
 | 
| 506 |                   if-match               
 | 
| 507 | X [Table Create]  table                  --by-row --by-col (&place); construct/parse a table
 | 
| 508 |                   table/cols             cols name age - cols name:Str age:Int
 | 
| 509 |                   types                  type       Str Int
 | 
| 510 |                   attr                   attr units -   secs
 | 
| 511 |                   row                    emit row
 | 
| 512 |                   table cat              concatenate TSV8
 | 
| 513 |                   table align            to ssv8
 | 
| 514 |                   table tabify           to tsv8
 | 
| 515 |                   table header           (cols = :|name age|, types = :|Str Int|, units = :|- secs|)
 | 
| 516 |                   table slice            e.g. slice (1, -1)   slice (5, 7)
 | 
| 517 |                   table to-tsv           lose type info, and error on \t in cells
 | 
| 518 | X [Table Ops]     where                  subset of rows; dplyr filter()
 | 
| 519 |                   pick                   subset of columns ('select' taken by shell)
 | 
| 520 |                   mutate    transmute    [average = count / sum] - drop the ones that are used?
 | 
| 521 |                   rename                 (bytes='bytes', path='filename')
 | 
| 522 |                   group-by               add a column with a group ID [ext]
 | 
| 523 |                   sort-by                sort by columns; dplyr arrange() [ext]
 | 
| 524 |                   summary                count, sum, histogram, any, all, reduce(), etc. [ext]
 | 
| 525 | )zZXx");
 | 
| 526 | 
 | 
| 527 | GLOBAL_STR(gStr29, R"zZXx(
 | 
| 528 |   Types and Methods <a class="group-link" href="chap-type-method.html">type-method</a>
 | 
| 529 | 
 | 
| 530 | 
 | 
| 531 |   [Atom Types]     Null           Bool
 | 
| 532 |   [Number Types]   Int            Float
 | 
| 533 |   [Str]          X find()         replace()
 | 
| 534 |                    trim()         trimStart()   trimEnd()
 | 
| 535 |                    startsWith()   endsWith()
 | 
| 536 |                    upper()        lower()
 | 
| 537 |                    search()       leftMatch()
 | 
| 538 |   [List]           List/append()  pop()         extend()    indexOf()
 | 
| 539 |                  X insert()     X remove()      reverse()
 | 
| 540 |   [Dict]           keys()         values()    X get()     X erase()
 | 
| 541 |                  X inc()        X accum()
 | 
| 542 |   [Range] 
 | 
| 543 |   [Eggex] 
 | 
| 544 |   [Match]          group()        start()       end()
 | 
| 545 |                  X groups()     X groupDict()
 | 
| 546 |   [Place]          setValue()
 | 
| 547 |   [Code Types]     Expr           Command
 | 
| 548 |                    BuiltinFunc    BoundFunc
 | 
| 549 | X [Func]           name()         location()    toJson()
 | 
| 550 | X [Proc]           name()         location()    toJson()
 | 
| 551 | X [Module]         name()         filename()
 | 
| 552 |   [IO]           X eval()       X captureStdout()
 | 
| 553 |                    promptVal()
 | 
| 554 |                  X time()       X strftime()
 | 
| 555 |                  X glob()
 | 
| 556 | X [Guts]           heapId()
 | 
| 557 | )zZXx");
 | 
| 558 | 
 | 
| 559 | GLOBAL_STR(gStr30, R"zZXx(bin/ysh is the shell with data tYpes, influenced by pYthon, JavaScript, ...
 | 
| 560 | 
 | 
| 561 | Usage: ysh FLAG* SCRIPT ARG*
 | 
| 562 |        ysh FLAG* -c COMMAND ARG*
 | 
| 563 |        ysh FLAG*
 | 
| 564 | 
 | 
| 565 | `bin/ysh` is the same as `bin/osh` with a the `ysh:all` option group set.  So
 | 
| 566 | `bin/ysh` also accepts shell flags.
 | 
| 567 | 
 | 
| 568 |     ysh -c 'echo hi'
 | 
| 569 |     ysh myscript.ysh
 | 
| 570 |     echo 'echo hi' | ysh
 | 
| 571 | )zZXx");
 | 
| 572 | 
 | 
| 573 | GLOBAL_STR(gStr31, R"zZXx(
 | 
| 574 |   Word Language <a class="group-link" href="chap-word-lang.html">word-lang</a>
 | 
| 575 | 
 | 
| 576 | 
 | 
| 577 |   [Quotes]        ysh-string    "x is $x"  $"x is $x"  r'[a-z]\n'
 | 
| 578 |                                 u'line\n'  b'byte \yff'
 | 
| 579 |                   triple-quoted """  $"""  r'''  u'''  b'''
 | 
| 580 |                 X tagged-str    "<span id=$x>"html
 | 
| 581 |   [Substitutions] expr-sub      echo $[42 + a[i]]
 | 
| 582 |                   expr-splice   echo @[split(x)]
 | 
| 583 |                   var-splice    @myarray @ARGV
 | 
| 584 |                   command-sub   @(split command)
 | 
| 585 |   [Formatting]  X ysh-printf    ${x %.3f}
 | 
| 586 |                 X ysh-format    ${x|html}
 | 
| 587 | )zZXx");
 | 
| 588 | 
 | 
| 589 | GLOBAL_STR(gStr32, R"zZXx(
 | 
| 590 |   YSH Command Language Keywords <a class="group-link" href="chap-ysh-cmd.html">ysh-cmd</a>
 | 
| 591 | 
 | 
| 592 | 
 | 
| 593 |   [Assignment]    const   var   Declare variables
 | 
| 594 |                   setvar        setvar a[i] = 42
 | 
| 595 |                   setglobal     setglobal d.key = 'foo'
 | 
| 596 |   [Expression]    equal =       = 1 + 2*3
 | 
| 597 |                   call          call mylist->append(42)
 | 
| 598 |   [Definitions]   proc          proc p (s, ...rest) {
 | 
| 599 |                                 typed proc p (; typed, ...rest; n=0; b) {
 | 
| 600 |                   func          func f(x; opt1, opt2) { return (x + 1) }
 | 
| 601 |                   ysh-return    return (myexpr)
 | 
| 602 | )zZXx");
 | 
| 603 | 
 | 
| 604 | GLOBAL_STR(gStr33, R"zZXx(func identity(x) {
 | 
| 605 |   ## The identity function. Returns its argument.
 | 
| 606 | 
 | 
| 607 |   return (x)
 | 
| 608 | }
 | 
| 609 | )zZXx");
 | 
| 610 | 
 | 
| 611 | GLOBAL_STR(gStr34, R"zZXx(# Can we define methods in pure YSH?
 | 
| 612 | #
 | 
| 613 | # (mylist->find(42) !== -1)
 | 
| 614 | #
 | 
| 615 | #   instead of 
 | 
| 616 | #
 | 
| 617 | # ('42' in mylist)
 | 
| 618 | #
 | 
| 619 | # Because 'in' is for Dict
 | 
| 620 | 
 | 
| 621 | func find (haystack List, needle) {
 | 
| 622 |   for i, x in (haystack) {
 | 
| 623 |     if (x === needle) {
 | 
| 624 |       return (i)
 | 
| 625 |     }
 | 
| 626 |   }
 | 
| 627 |   return (-1)
 | 
| 628 | }
 | 
| 629 | )zZXx");
 | 
| 630 | 
 | 
| 631 | GLOBAL_STR(gStr35, R"zZXx(# Bash strict mode, updated for 2024
 | 
| 632 | 
 | 
| 633 | set -o nounset
 | 
| 634 | set -o pipefail
 | 
| 635 | set -o errexit
 | 
| 636 | shopt -s inherit_errexit
 | 
| 637 | shopt -s strict:all 2>/dev/null || true  # dogfood for OSH
 | 
| 638 | 
 | 
| 639 | )zZXx");
 | 
| 640 | 
 | 
| 641 | GLOBAL_STR(gStr36, R"zZXx(# Library to turn a shell file into a "BYO test server"
 | 
| 642 | #
 | 
| 643 | # Usage:
 | 
| 644 | #
 | 
| 645 | #   # from both bash and OSH
 | 
| 646 | #   if test -z "$LIB_OSH"; then LIB_OSH=stdlib/osh; fi
 | 
| 647 | #   source $LIB_OSH/byo-server-lib.sh
 | 
| 648 | #
 | 
| 649 | # The client creates a clean process state and directory state for each tests.
 | 
| 650 | #
 | 
| 651 | # (This file requires compgen -A, and maybe declare -f, so it's not POSIX
 | 
| 652 | # shell.)
 | 
| 653 | 
 | 
| 654 | : ${LIB_OSH:-stdlib/osh}
 | 
| 655 | source $LIB_OSH/two.sh
 | 
| 656 | 
 | 
| 657 | byo-maybe-run() {
 | 
| 658 |   local command=${BYO_COMMAND:-}
 | 
| 659 | 
 | 
| 660 |   case $command in
 | 
| 661 |     '')
 | 
| 662 |       # Do nothing if it's not specified
 | 
| 663 |       return 
 | 
| 664 |       ;;
 | 
| 665 | 
 | 
| 666 |     detect)
 | 
| 667 |       # all the commands supported, except 'detect'
 | 
| 668 |       echo list-tests
 | 
| 669 |       echo run-test
 | 
| 670 | 
 | 
| 671 |       exit 66  # ASCII code for 'B' - what the protocol specifies
 | 
| 672 |       ;;
 | 
| 673 | 
 | 
| 674 |     list-tests)
 | 
| 675 |       # bash extension that OSH also implements
 | 
| 676 |       compgen -A function | grep '^test-'
 | 
| 677 |       exit 0
 | 
| 678 |       ;;
 | 
| 679 | 
 | 
| 680 |     run-test)
 | 
| 681 |       local test_name=${BYO_ARG:-}
 | 
| 682 |       if test -z "$test_name"; then
 | 
| 683 |         die "BYO run-test: Expected BYO_ARG"
 | 
| 684 |       fi
 | 
| 685 | 
 | 
| 686 |       # Shell convention: we name functions test-*
 | 
| 687 |       $test_name
 | 
| 688 | 
 | 
| 689 |       # Only run if not set -e.  Either way it's equivalent
 | 
| 690 |       exit $?
 | 
| 691 |       ;;
 | 
| 692 | 
 | 
| 693 |     *)
 | 
| 694 |       die "Invalid BYO command '$command'"
 | 
| 695 |       ;;
 | 
| 696 |   esac
 | 
| 697 | 
 | 
| 698 |   # Do nothing if BYO_COMMAND is not set.
 | 
| 699 |   # The program continues to its "main".
 | 
| 700 | }
 | 
| 701 | 
 | 
| 702 | byo-must-run() {
 | 
| 703 |   local command=${BYO_COMMAND:-}
 | 
| 704 |   if test -z "$command"; then
 | 
| 705 |     die "Expected BYO_COMMAND= in environment"
 | 
| 706 |   fi
 | 
| 707 | 
 | 
| 708 |   byo-maybe-run
 | 
| 709 | }
 | 
| 710 | )zZXx");
 | 
| 711 | 
 | 
| 712 | GLOBAL_STR(gStr37, R"zZXx(#!/usr/bin/env bash
 | 
| 713 | #
 | 
| 714 | # Testing library for bash and OSH.
 | 
| 715 | #
 | 
| 716 | # Capture status/stdout/stderr, and nq-assert those values.
 | 
| 717 | 
 | 
| 718 | : ${LIB_OSH=stdlib/osh}
 | 
| 719 | source $LIB_OSH/two.sh
 | 
| 720 | 
 | 
| 721 | nq-assert() {
 | 
| 722 |   ### Assertion with same syntax as shell 'test'
 | 
| 723 | 
 | 
| 724 |   if ! test "$@"; then
 | 
| 725 |     die "line ${BASH_LINENO[0]}: nq-assert $(printf '%q ' "$@") failed"
 | 
| 726 |   fi
 | 
| 727 | }
 | 
| 728 | 
 | 
| 729 | # Problem: we want to capture status and stdout at the same time
 | 
| 730 | #
 | 
| 731 | # We use:
 | 
| 732 | #
 | 
| 733 | #  __stdout=$(set -o errexit; "$@")
 | 
| 734 | #  __status=$?
 | 
| 735 | #
 | 
| 736 | # However, we lose the trailing \n, since that's how command subs work.
 | 
| 737 | 
 | 
| 738 | # Here is another possibility:
 | 
| 739 | #
 | 
| 740 | # shopt -s lastpipe  # need this too
 | 
| 741 | # ( set -o errexit; "$@" ) | read -r -d __stdout
 | 
| 742 | # __status=${PIPESTATUS[0]}
 | 
| 743 | # shopt -u lastpipe
 | 
| 744 | #
 | 
| 745 | # But this feels complex for just the \n issue, which can be easily worked
 | 
| 746 | # around.
 | 
| 747 | 
 | 
| 748 | nq-run() {
 | 
| 749 |   ### capture status only
 | 
| 750 | 
 | 
| 751 |   local -n out_status=$1
 | 
| 752 |   shift
 | 
| 753 | 
 | 
| 754 |   local __status
 | 
| 755 | 
 | 
| 756 |   # Tricky: turn errexit off so we can capture it, but turn it on against
 | 
| 757 |   set +o errexit
 | 
| 758 |   ( set -o errexit; "$@" )
 | 
| 759 |   __status=$?
 | 
| 760 |   set -o errexit
 | 
| 761 | 
 | 
| 762 |   out_status=$__status
 | 
| 763 | }
 | 
| 764 | 
 | 
| 765 | nq-capture() {
 | 
| 766 |   ### capture status and stdout
 | 
| 767 | 
 | 
| 768 |   local -n out_status=$1
 | 
| 769 |   local -n out_stdout=$2
 | 
| 770 |   shift 2
 | 
| 771 | 
 | 
| 772 |   local __status
 | 
| 773 |   local __stdout
 | 
| 774 | 
 | 
| 775 |   # Tricky: turn errexit off so we can capture it, but turn it on against
 | 
| 776 |   set +o errexit
 | 
| 777 |   __stdout=$(set -o errexit; "$@")
 | 
| 778 |   __status=$?
 | 
| 779 |   set -o errexit
 | 
| 780 | 
 | 
| 781 |   out_status=$__status
 | 
| 782 |   out_stdout=$__stdout
 | 
| 783 | }
 | 
| 784 | 
 | 
| 785 | nq-capture-2() {
 | 
| 786 |   ### capture status and stderr 
 | 
| 787 |   
 | 
| 788 |   # This is almost identical to the above
 | 
| 789 | 
 | 
| 790 |   local -n out_status=$1
 | 
| 791 |   local -n out_stderr=$2
 | 
| 792 |   shift 2
 | 
| 793 | 
 | 
| 794 |   local __status
 | 
| 795 |   local __stderr
 | 
| 796 | 
 | 
| 797 |   # Tricky: turn errexit off so we can capture it, but turn it on against
 | 
| 798 |   set +o errexit
 | 
| 799 |   __stderr=$(set -o errexit; "$@" 2>&1)
 | 
| 800 |   __status=$?
 | 
| 801 |   set -o errexit
 | 
| 802 | 
 | 
| 803 |   out_status=$__status
 | 
| 804 |   out_stderr=$__stderr
 | 
| 805 | }
 | 
| 806 | 
 | 
| 807 | # 'byo test' can set this?
 | 
| 808 | : ${NQ_TEST_TEMP=/tmp}
 | 
| 809 | 
 | 
| 810 | nq-redir() {
 | 
| 811 |   ### capture status and stdout
 | 
| 812 | 
 | 
| 813 |   local -n out_status=$1
 | 
| 814 |   local -n out_stdout_file=$2
 | 
| 815 |   shift 2
 | 
| 816 | 
 | 
| 817 |   local __status
 | 
| 818 |   local __stdout_file=$NQ_TEST_TEMP/nq-redir-$$.txt
 | 
| 819 | 
 | 
| 820 |   # Tricky: turn errexit off so we can capture it, but turn it on against
 | 
| 821 |   set +o errexit
 | 
| 822 |   ( set -o errexit; "$@" ) > $__stdout_file
 | 
| 823 |   __status=$?
 | 
| 824 |   set -o errexit
 | 
| 825 | 
 | 
| 826 |   out_status=$__status
 | 
| 827 |   out_stdout_file=$__stdout_file
 | 
| 828 | }
 | 
| 829 | 
 | 
| 830 | nq-redir-2() {
 | 
| 831 |   ### capture status and stdout
 | 
| 832 | 
 | 
| 833 |   local -n out_status=$1
 | 
| 834 |   local -n out_stderr_file=$2
 | 
| 835 |   shift 2
 | 
| 836 | 
 | 
| 837 |   local __status
 | 
| 838 |   local __stderr_file=$NQ_TEST_TEMP/nq-redir-$$.txt
 | 
| 839 | 
 | 
| 840 |   # Tricky: turn errexit off so we can capture it, but turn it on against
 | 
| 841 |   set +o errexit
 | 
| 842 |   ( set -o errexit; "$@" ) 2> $__stderr_file
 | 
| 843 |   __status=$?
 | 
| 844 |   set -o errexit
 | 
| 845 | 
 | 
| 846 |   out_status=$__status
 | 
| 847 |   out_stderr_file=$__stderr_file
 | 
| 848 | }
 | 
| 849 | )zZXx");
 | 
| 850 | 
 | 
| 851 | GLOBAL_STR(gStr38, R"zZXx(#!/usr/bin/env bash
 | 
| 852 | #
 | 
| 853 | # Common shell functions for task scripts.
 | 
| 854 | #
 | 
| 855 | # Usage:
 | 
| 856 | #   source $LIB_OSH/task-five.sh
 | 
| 857 | #
 | 
| 858 | #   test-foo() {  # define task functions
 | 
| 859 | #     echo foo
 | 
| 860 | #   }
 | 
| 861 | #   task-five "$@"
 | 
| 862 | 
 | 
| 863 | # Definition of a "task"
 | 
| 864 | #
 | 
| 865 | # - File invokes task-five "$@"
 | 
| 866 | #   - or maybe you can look at its source
 | 
| 867 | # - It's a shell function
 | 
| 868 | #   - Has ### docstring
 | 
| 869 | #   - Doesn't start with _
 | 
| 870 | 
 | 
| 871 | : ${LIB_OSH=stdlib/osh}
 | 
| 872 | source $LIB_OSH/byo-server.sh
 | 
| 873 | 
 | 
| 874 | 
 | 
| 875 | # List all functions defined in this file (and not in sourced files).
 | 
| 876 | _bash-print-funcs() {
 | 
| 877 |   ### Print shell functions in this file that don't start with _ (bash reflection)
 | 
| 878 | 
 | 
| 879 |   local funcs
 | 
| 880 |   funcs=($(compgen -A function))
 | 
| 881 |   # extdebug makes `declare -F` print the file path, but, annoyingly, only
 | 
| 882 |   # if you pass the function names as arguments.
 | 
| 883 |   shopt -s extdebug
 | 
| 884 |   declare -F "${funcs[@]}" | grep --fixed-strings " $0" | awk '{print $1}'
 | 
| 885 |   shopt -u extdebug
 | 
| 886 | }
 | 
| 887 | 
 | 
| 888 | _gawk-print-funcs() {
 | 
| 889 |   ### Print shell functions in this file that don't start with _ (awk parsing)
 | 
| 890 | 
 | 
| 891 |   # Using gawk because it has match()
 | 
| 892 |   # - doesn't start with _
 | 
| 893 | 
 | 
| 894 |   # space     = / ' '* /
 | 
| 895 |   # shfunc    = / %begin
 | 
| 896 |   #               <capture !['_' ' '] ![' ']*>
 | 
| 897 |   #               '()' space '{' space
 | 
| 898 |   #               %end /
 | 
| 899 |   # docstring = / %begin
 | 
| 900 |   #               space '###' ' '+
 | 
| 901 |   #               <capture dot*>
 | 
| 902 |   #               %end /
 | 
| 903 |   gawk '
 | 
| 904 |   match($0, /^([^_ ][^ ]*)\(\)[ ]*{[ ]*$/, m) {
 | 
| 905 |     #print NR " shfunc " m[1]
 | 
| 906 |     print m[1]
 | 
| 907 |     #print m[0]
 | 
| 908 |   }
 | 
| 909 | 
 | 
| 910 |   match($0, /^[ ]*###[ ]+(.*)$/, m) {
 | 
| 911 |     print NR " docstring " m[1]
 | 
| 912 |   }
 | 
| 913 | ' $0
 | 
| 914 | }
 | 
| 915 | 
 | 
| 916 | _print-funcs() {
 | 
| 917 |   if command -v gawk > /dev/null; then
 | 
| 918 |     _gawk-print-funcs
 | 
| 919 |   else
 | 
| 920 |     _bash-print-funcs
 | 
| 921 |   fi
 | 
| 922 | }
 | 
| 923 | 
 | 
| 924 | _show-help() {
 | 
| 925 |   # TODO:
 | 
| 926 |   # - Use awk to find comments at the top of the file?
 | 
| 927 |   # - Use OSH to extract docstrings
 | 
| 928 |   # - BYO_COMMAND=list-tasks will reuse that logic?  It only applies to the
 | 
| 929 |   #   current file, not anything in a different file?
 | 
| 930 | 
 | 
| 931 |   echo "Usage: $0 TASK_NAME ARGS..."
 | 
| 932 |   echo
 | 
| 933 |   echo "To complete tasks, run:"
 | 
| 934 |   echo "   source devtools/completion.bash"
 | 
| 935 |   echo
 | 
| 936 |   echo "Tasks:"
 | 
| 937 | 
 | 
| 938 |   if command -v column >/dev/null; then
 | 
| 939 |     _print-funcs | column
 | 
| 940 |   else
 | 
| 941 |     _print-funcs
 | 
| 942 |   fi
 | 
| 943 | }
 | 
| 944 | 
 | 
| 945 | task-five() {
 | 
| 946 |   # Respond to BYO_COMMAND=list-tasks, etc.  All task files need this.
 | 
| 947 |   byo-maybe-run
 | 
| 948 | 
 | 
| 949 |   case ${1:-} in
 | 
| 950 |     ''|--help|-h)
 | 
| 951 |       _show-help
 | 
| 952 |       exit 0
 | 
| 953 |       ;;
 | 
| 954 |   esac
 | 
| 955 | 
 | 
| 956 |   if ! declare -f "$1" >/dev/null; then
 | 
| 957 |     echo "$0: '$1' isn't an action in this task file.  Try '$0 --help'"
 | 
| 958 |     exit 1
 | 
| 959 |   fi
 | 
| 960 | 
 | 
| 961 |   "$@"
 | 
| 962 | }
 | 
| 963 | )zZXx");
 | 
| 964 | 
 | 
| 965 | GLOBAL_STR(gStr39, R"zZXx(# Two functions I actually use, all the time.
 | 
| 966 | #
 | 
| 967 | # To keep depenedencies small, this library will NEVER grow other functions
 | 
| 968 | # (and is named to imply that.)
 | 
| 969 | #
 | 
| 970 | # Usage:
 | 
| 971 | #   source --builtin two.sh
 | 
| 972 | #
 | 
| 973 | # Examples:
 | 
| 974 | #    log 'hi'
 | 
| 975 | #    die 'expected a number'
 | 
| 976 | 
 | 
| 977 | if command -v source-guard >/dev/null; then  # include guard for YSH
 | 
| 978 |   source-guard two || return 0
 | 
| 979 | fi
 | 
| 980 | 
 | 
| 981 | log() {
 | 
| 982 |   ### Write a message to stderr.
 | 
| 983 |   echo "$@" >&2
 | 
| 984 | }
 | 
| 985 | 
 | 
| 986 | die() {
 | 
| 987 |   ### Write an error message with the script name, and exit with status 1.
 | 
| 988 |   log "$0: fatal: $@"
 | 
| 989 |   exit 1
 | 
| 990 | }
 | 
| 991 | 
 | 
| 992 | )zZXx");
 | 
| 993 | 
 | 
| 994 | GLOBAL_STR(gStr40, R"zZXx(# These were helpful while implementing args.ysh
 | 
| 995 | # Maybe we will want to export them in a prelude so that others can use them too?
 | 
| 996 | #
 | 
| 997 | # Prior art: Rust has `todo!()` which is quite nice. Other languages allow
 | 
| 998 | # users to `raise NotImplmentedError()`.
 | 
| 999 | 
 | 
| 1000 | # Andy comments:
 | 
| 1001 | # - 'pass' can be : or true in shell.  It's a little obscure / confusing, but
 | 
| 1002 | #   there is an argument for minimalism.  Although I prefer words like 'true',
 | 
| 1003 | #   and that already means something.
 | 
| 1004 | #   - UPDATE: we once took 'pass' as a keyword, but users complained because
 | 
| 1005 | #     there is a command 'pass'.  So we probably can't have this by default.
 | 
| 1006 | #     Need to discuss source --builtin.
 | 
| 1007 | 
 | 
| 1008 | # - todo could be more static?  Rust presumably does it at compile time
 | 
| 1009 | 
 | 
| 1010 | proc todo () {
 | 
| 1011 |   ## Raises a not implemented error when run.
 | 
| 1012 |   error ("TODO: not implemented")  # TODO: is error code 1 ok?
 | 
| 1013 | }
 | 
| 1014 | 
 | 
| 1015 | proc pass () {
 | 
| 1016 |   ## Use when you want to temporarily leave a block empty.
 | 
| 1017 |   _ null
 | 
| 1018 | }
 | 
| 1019 | )zZXx");
 | 
| 1020 | 
 | 
| 1021 | GLOBAL_STR(gStr41, R"zZXx(# testing.ysh
 | 
| 1022 | #
 | 
| 1023 | # Usage:
 | 
| 1024 | #   source --builtin testing.sh
 | 
| 1025 | #
 | 
| 1026 | # func f(x) { return (x + 1) }
 | 
| 1027 | #
 | 
| 1028 | # describe foo {
 | 
| 1029 | #   assert (43 === f(42))
 | 
| 1030 | # }
 | 
| 1031 | #
 | 
| 1032 | # if is-main {
 | 
| 1033 | #   run-tests @ARGV   # --filter
 | 
| 1034 | # }
 | 
| 1035 | 
 | 
| 1036 | module stdlib/testing || return 0
 | 
| 1037 | 
 | 
| 1038 | source --builtin args.ysh
 | 
| 1039 | 
 | 
| 1040 | proc assert ( ; cond ; fail_message='default fail message') {
 | 
| 1041 |   echo 'hi from assert'
 | 
| 1042 | 
 | 
| 1043 |   = cond
 | 
| 1044 | 
 | 
| 1045 |   # I think this might be ready now?
 | 
| 1046 | 
 | 
| 1047 |   var val = evalExpr(cond) 
 | 
| 1048 | 
 | 
| 1049 |   echo
 | 
| 1050 |   echo 'value'
 | 
| 1051 |   = val
 | 
| 1052 |   pp line (val)
 | 
| 1053 | 
 | 
| 1054 |   = fail_message
 | 
| 1055 | 
 | 
| 1056 |   if (val) {
 | 
| 1057 |     echo 'OK'
 | 
| 1058 |   } else {
 | 
| 1059 |     var m = evalExpr(fail_message) 
 | 
| 1060 |     echo "FAIL - this is where we extract the string - $m"
 | 
| 1061 |   }
 | 
| 1062 | }
 | 
| 1063 | 
 | 
| 1064 | proc test-assert {
 | 
| 1065 |   var x = 42
 | 
| 1066 |   assert [42 === x]
 | 
| 1067 | }
 | 
| 1068 | 
 | 
| 1069 | proc test-expr ( ; expr ) {
 | 
| 1070 |   echo 'expr'
 | 
| 1071 |   pp line (expr)
 | 
| 1072 | }
 | 
| 1073 | 
 | 
| 1074 | proc test-named ( ; ; n=^[99] ) {
 | 
| 1075 |   echo 'n'
 | 
| 1076 |   pp line (n)
 | 
| 1077 | }
 | 
| 1078 | 
 | 
| 1079 | # What happens when there are duplicate test IDs?
 | 
| 1080 | #
 | 
| 1081 | # Also I think filter by "$test_id/$case_id"
 | 
| 1082 | 
 | 
| 1083 | proc __it (case_id ; ; ; block) {
 | 
| 1084 |   # This uses a clean directory
 | 
| 1085 |   echo TODO
 | 
| 1086 | }
 | 
| 1087 | 
 | 
| 1088 | # is this accessible to users?
 | 
| 1089 | # It can contain a global list of things to run
 | 
| 1090 | 
 | 
| 1091 | # Naming convention: a proc named 'describe' mutates a global named _describe?
 | 
| 1092 | # Or maybe _describe_list ?
 | 
| 1093 | 
 | 
| 1094 | var _describe_list = []
 | 
| 1095 | 
 | 
| 1096 | proc describe (test_id ; ; ; block) {
 | 
| 1097 |   echo describe
 | 
| 1098 |   #= desc
 | 
| 1099 | 
 | 
| 1100 |   # TODO:
 | 
| 1101 |   # - need append
 | 
| 1102 |   # - need ::
 | 
| 1103 |   # _ _describe->append(cmd)
 | 
| 1104 |   #
 | 
| 1105 |   # Need to clean this up
 | 
| 1106 |   # append (_describe, cmd)  # does NOT work!
 | 
| 1107 | 
 | 
| 1108 |   call _describe_list->append(block)
 | 
| 1109 | }
 | 
| 1110 | 
 | 
| 1111 | proc Args {
 | 
| 1112 |   echo TODO
 | 
| 1113 | }
 | 
| 1114 | 
 | 
| 1115 | # Problem: this creates a global variable?
 | 
| 1116 | Args (&spec) {
 | 
| 1117 |   flag --filter 'Regex of test descriptions'
 | 
| 1118 | }
 | 
| 1119 | 
 | 
| 1120 | proc run-tests {
 | 
| 1121 |   var opt, i = parseArgs(spec, ARGV)
 | 
| 1122 | 
 | 
| 1123 |   # TODO:
 | 
| 1124 |   # - parse --filter foo, which you can use eggex for!
 | 
| 1125 | 
 | 
| 1126 |   for cmd in (_describe) {
 | 
| 1127 |     # TODO: print filename and 'describe' name?
 | 
| 1128 |     try {
 | 
| 1129 |       eval (cmd)
 | 
| 1130 |     }
 | 
| 1131 |     if (_status !== 0) {
 | 
| 1132 |       echo 'failed'
 | 
| 1133 |     }
 | 
| 1134 |   }
 | 
| 1135 | }
 | 
| 1136 | )zZXx");
 | 
| 1137 | 
 | 
| 1138 | 
 | 
| 1139 | 
 | 
| 1140 | TextFile array[] = {
 | 
| 1141 |     {.rel_path = "_devbuild/help/data-errors", .contents = gStr0},
 | 
| 1142 |     {.rel_path = "_devbuild/help/data-front-end", .contents = gStr1},
 | 
| 1143 |     {.rel_path = "_devbuild/help/data-j8-notation", .contents = gStr2},
 | 
| 1144 |     {.rel_path = "_devbuild/help/help", .contents = gStr3},
 | 
| 1145 |     {.rel_path = "_devbuild/help/oils-usage", .contents = gStr4},
 | 
| 1146 |     {.rel_path = "_devbuild/help/osh-builtin-cmd", .contents = gStr5},
 | 
| 1147 |     {.rel_path = "_devbuild/help/osh-chapters", .contents = gStr6},
 | 
| 1148 |     {.rel_path = "_devbuild/help/osh-cmd-lang", .contents = gStr7},
 | 
| 1149 |     {.rel_path = "_devbuild/help/osh-front-end", .contents = gStr8},
 | 
| 1150 |     {.rel_path = "_devbuild/help/osh-mini-lang", .contents = gStr9},
 | 
| 1151 |     {.rel_path = "_devbuild/help/osh-option", .contents = gStr10},
 | 
| 1152 |     {.rel_path = "_devbuild/help/osh-osh-assign", .contents = gStr11},
 | 
| 1153 |     {.rel_path = "_devbuild/help/osh-plugin", .contents = gStr12},
 | 
| 1154 |     {.rel_path = "_devbuild/help/osh-special-var", .contents = gStr13},
 | 
| 1155 |     {.rel_path = "_devbuild/help/osh-stdlib", .contents = gStr14},
 | 
| 1156 |     {.rel_path = "_devbuild/help/osh-type-method", .contents = gStr15},
 | 
| 1157 |     {.rel_path = "_devbuild/help/osh-usage", .contents = gStr16},
 | 
| 1158 |     {.rel_path = "_devbuild/help/osh-word-lang", .contents = gStr17},
 | 
| 1159 |     {.rel_path = "_devbuild/help/ysh-builtin-cmd", .contents = gStr18},
 | 
| 1160 |     {.rel_path = "_devbuild/help/ysh-builtin-func", .contents = gStr19},
 | 
| 1161 |     {.rel_path = "_devbuild/help/ysh-chapters", .contents = gStr20},
 | 
| 1162 |     {.rel_path = "_devbuild/help/ysh-cmd-lang", .contents = gStr21},
 | 
| 1163 |     {.rel_path = "_devbuild/help/ysh-expr-lang", .contents = gStr22},
 | 
| 1164 |     {.rel_path = "_devbuild/help/ysh-front-end", .contents = gStr23},
 | 
| 1165 |     {.rel_path = "_devbuild/help/ysh-mini-lang", .contents = gStr24},
 | 
| 1166 |     {.rel_path = "_devbuild/help/ysh-option", .contents = gStr25},
 | 
| 1167 |     {.rel_path = "_devbuild/help/ysh-plugin", .contents = gStr26},
 | 
| 1168 |     {.rel_path = "_devbuild/help/ysh-special-var", .contents = gStr27},
 | 
| 1169 |     {.rel_path = "_devbuild/help/ysh-stdlib", .contents = gStr28},
 | 
| 1170 |     {.rel_path = "_devbuild/help/ysh-type-method", .contents = gStr29},
 | 
| 1171 |     {.rel_path = "_devbuild/help/ysh-usage", .contents = gStr30},
 | 
| 1172 |     {.rel_path = "_devbuild/help/ysh-word-lang", .contents = gStr31},
 | 
| 1173 |     {.rel_path = "_devbuild/help/ysh-ysh-cmd", .contents = gStr32},
 | 
| 1174 |     {.rel_path = "stdlib/funcs.ysh", .contents = gStr33},
 | 
| 1175 |     {.rel_path = "stdlib/methods.ysh", .contents = gStr34},
 | 
| 1176 |     {.rel_path = "stdlib/osh/bash-strict.sh", .contents = gStr35},
 | 
| 1177 |     {.rel_path = "stdlib/osh/byo-server.sh", .contents = gStr36},
 | 
| 1178 |     {.rel_path = "stdlib/osh/no-quotes.sh", .contents = gStr37},
 | 
| 1179 |     {.rel_path = "stdlib/osh/task-five.sh", .contents = gStr38},
 | 
| 1180 |     {.rel_path = "stdlib/osh/two.sh", .contents = gStr39},
 | 
| 1181 |     {.rel_path = "stdlib/prelude.ysh", .contents = gStr40},
 | 
| 1182 |     {.rel_path = "stdlib/testing.ysh", .contents = gStr41},
 | 
| 1183 | 
 | 
| 1184 |     {.rel_path = nullptr, .contents = nullptr},
 | 
| 1185 | };
 | 
| 1186 | 
 | 
| 1187 | }  // namespace embedded_file
 | 
| 1188 | 
 | 
| 1189 | TextFile* gEmbeddedFiles = embedded_file::array;  // turn array into pointer
 |