| 1 | ---
 | 
| 2 | in_progress: true
 | 
| 3 | default_highlighter: oils-sh
 | 
| 4 | ---
 | 
| 5 | 
 | 
| 6 | YSH I/O Builtins
 | 
| 7 | ================
 | 
| 8 | 
 | 
| 9 | POSIX shell has overlapping and quirky constructs for doing I/O:
 | 
| 10 | 
 | 
| 11 | - the builtins `echo`, `printf`, and `read`
 | 
| 12 | - the `$(command sub)` construct
 | 
| 13 | - Bash has `mapfile` and `readarray`
 | 
| 14 | 
 | 
| 15 | YSH rationalizes I/O with:
 | 
| 16 | 
 | 
| 17 | - A new `write` builtin
 | 
| 18 | - Long flags to `read`, like `--all`
 | 
| 19 | - The distinction between `$(string sub)` and `@(array sub)`
 | 
| 20 | - A set of data languages called [J8 Notation](j8-notation.html).
 | 
| 21 | 
 | 
| 22 | YSH also has orthogonal mechanisms for string processing:
 | 
| 23 | 
 | 
| 24 | - `${.myproc arg}` and `@{.myproc arg}` are an optimization (TODO)
 | 
| 25 | - `${x %.2f}` as a static version of the `printf` builtin (TODO)
 | 
| 26 | - `${x|html}` for safe escaping (TODO)
 | 
| 27 | 
 | 
| 28 | These are discussed in more detail the [strings](strings.html) doc.
 | 
| 29 | 
 | 
| 30 | <!-- TODO: should run all this code as in tour.md -->
 | 
| 31 | 
 | 
| 32 | <div id="toc">
 | 
| 33 | </div>
 | 
| 34 | 
 | 
| 35 | ## Problems With Shell
 | 
| 36 | 
 | 
| 37 | - `echo` is flaky because `echo $x` is a bug.  `$x` could be `-n`.
 | 
| 38 |   - YSH `write` accepts `--`.
 | 
| 39 | - `read` is non-obvious because the `-r` flag to ignore `\` line continuations
 | 
| 40 |   isn't the default.  The `\` creates a mini-language that isn't understood by
 | 
| 41 |   other line-based tools like `grep` and `awk`.
 | 
| 42 |   - TODO: YSH should have a mechanism to read buffered lines.
 | 
| 43 | - There's no way to tell if `$()` strips the trailing newline,.
 | 
| 44 |   - YSH has `read --all`, as well as lastpipe being on.
 | 
| 45 | 
 | 
| 46 | Example:
 | 
| 47 | 
 | 
| 48 |     hostname | read --all (&x)
 | 
| 49 |     write -- $x
 | 
| 50 | 
 | 
| 51 | ## Summary of YSH features
 | 
| 52 | 
 | 
| 53 | - `write`: `--qsn`, `--sep`, `--end`
 | 
| 54 | - `read`: `--all` (future: `--line`, `--all-lines`?)
 | 
| 55 | - `$(string sub)` removes the trailing newline, if any
 | 
| 56 | - `@(array sub)` splits by IFS
 | 
| 57 |   - TODO: should it split by `IFS=$'\n'`?
 | 
| 58 | 
 | 
| 59 | ### write
 | 
| 60 | 
 | 
| 61 | - `-sep`: Characters to separate each argument.  (Default: newline)
 | 
| 62 | - `-end`: Characters to terminate the whole invocation.  (Default: newline)
 | 
| 63 | - `-n`: A synonym for `-end ''`.
 | 
| 64 | 
 | 
| 65 | ## Buffered vs. Unbuffered
 | 
| 66 | 
 | 
| 67 | - The POSIX flags to `read` issue many `read(0, 1)` calls.  They do it
 | 
| 68 |   byte-by-byte.
 | 
| 69 | - The `--long` flags to `read` use buffered I/O.
 | 
| 70 | 
 | 
| 71 | ## Invariants
 | 
| 72 | 
 | 
| 73 | Here are some design notes on making the I/O builtins orthogonal and
 | 
| 74 | composable.  There should be clean ways to "round trip" data between the OS and
 | 
| 75 | YSH data structures.
 | 
| 76 | 
 | 
| 77 | ### File -> String -> File
 | 
| 78 | 
 | 
| 79 |     cat input.txt | read --all
 | 
| 80 | 
 | 
| 81 |     # suppress the newline
 | 
| 82 |     write --end '' $_reply > output.txt
 | 
| 83 | 
 | 
| 84 |     diff input.txt output.txt  # should be equal
 | 
| 85 | 
 | 
| 86 | 
 | 
| 87 | ### File -> Array -> File
 | 
| 88 | 
 | 
| 89 | TODO
 | 
| 90 | 
 | 
| 91 |     cat input.txt | read --all-lines :myarray
 | 
| 92 | 
 | 
| 93 |     # suppress the newline
 | 
| 94 |     write --sep '' --end '' -- @myarray > output.txt
 | 
| 95 | 
 | 
| 96 |     diff input.txt output.txt  # should be equal
 | 
| 97 | 
 | 
| 98 | ### Array -> J8 Lines -> Array
 | 
| 99 | 
 | 
| 100 | TODO
 | 
| 101 | 
 | 
| 102 | ## Related
 | 
| 103 | 
 | 
| 104 | - [JSON](json.html) support.
 |