1 | # stream.ysh
|
2 | #
|
3 | # Usage:
|
4 | # source --builtin stream.ysh
|
5 | #
|
6 | # For reading lines, decoding, extracting, splitting
|
7 |
|
8 | # make this file a test server
|
9 | source $LIB_OSH/byo-server.sh
|
10 |
|
11 | source $LIB_YSH/args.ysh
|
12 |
|
13 | proc slurp-by (; num_lines) {
|
14 | var buf = []
|
15 | for line in (io.stdin) {
|
16 | call buf->append(line)
|
17 | if (len(buf) === num_lines) {
|
18 | json write (buf, space=0)
|
19 |
|
20 | # TODO:
|
21 | #call buf->clear()
|
22 | setvar buf = []
|
23 | }
|
24 | }
|
25 | if (buf) {
|
26 | json write (buf, space=0)
|
27 | }
|
28 | }
|
29 |
|
30 | proc test-slurp-by {
|
31 | seq 8 | slurp-by (3)
|
32 | }
|
33 |
|
34 | ### Awk
|
35 |
|
36 | # Naming
|
37 | #
|
38 | # TEXT INPUT
|
39 | # each-word # this doesn't go by lines, it does a global regex split or something?
|
40 | #
|
41 | # LINE INPUT
|
42 | # each-line --j8 { echo "-- $_line" } # similar to @()
|
43 | # each-line --j8 (^"-- $_line") # is this superfluous?
|
44 | #
|
45 | # each-split name1 name2
|
46 | # (delim=' ')
|
47 | # (ifs=' ')
|
48 | # (pat=/d+/)
|
49 | # # also assign names for each part?
|
50 | #
|
51 | # each-match # regex match
|
52 | # must-match # assert that every line matches
|
53 | #
|
54 | # TABLE INPUT
|
55 | # each-row # TSV and TSV8 input?
|
56 | #
|
57 | # They all take templates or blocks?
|
58 |
|
59 | proc each-line (...words; template=null; ; block=null) {
|
60 | # TODO:
|
61 | # parse --j8 --max-jobs flag
|
62 |
|
63 | # parse template_str as string
|
64 | # TODO: this is dangerous though ... because you can execute code
|
65 | # I think you need a SAFE version
|
66 |
|
67 | # evaluate template string expression - I guess that allows $(echo hi) and so
|
68 | # forth
|
69 |
|
70 | # evaluate block with _line binding
|
71 | # block: execute in parallel with --max-jobs
|
72 |
|
73 | for line in (stdin) {
|
74 | echo TODO
|
75 | }
|
76 | }
|
77 |
|
78 | proc test-each-line {
|
79 | echo 'TODO: need basic test runner'
|
80 |
|
81 | # ysh-tool test stream.ysh
|
82 | #
|
83 | # Col
|
84 | }
|
85 |
|
86 | proc each-row (; ; block) {
|
87 | echo TODO
|
88 | }
|
89 |
|
90 | proc split-by (; delim; ifs=null; block) {
|
91 |
|
92 | # TODO: provide the option to bind names? Or is that a separate thing?
|
93 | # The output of this is "ragged"
|
94 |
|
95 | for line in (io.stdin) {
|
96 | #pp (line)
|
97 | var parts = line.split(delim)
|
98 | pp (parts)
|
99 |
|
100 | # variable number
|
101 | call io->eval(block, dollar0=line, pos_args=parts)
|
102 | }
|
103 | }
|
104 |
|
105 | proc chop () {
|
106 | ### alias for split-by
|
107 | echo TODO
|
108 | }
|
109 |
|
110 | proc test-split-by {
|
111 | var z = 'z' # test out scoping
|
112 | var count = 0 # test out mutation
|
113 |
|
114 | # TODO: need split by space
|
115 | # Where the leading and trailing are split
|
116 | # if-split-by(' ') doesn't work well
|
117 |
|
118 | line-data | split-by (/s+/) {
|
119 |
|
120 | # how do we deal with nonexistent?
|
121 | # should we also bind _parts or _words?
|
122 |
|
123 | echo "$z | $0 | $1 | $z"
|
124 |
|
125 | setvar count += 1
|
126 | }
|
127 | echo "count = $count"
|
128 | }
|
129 |
|
130 | proc must-split-by (; ; ifs=null; block) {
|
131 | ### like if-split-by
|
132 |
|
133 | echo TODO
|
134 | }
|
135 |
|
136 | # Naming: each-match, each-split?
|
137 |
|
138 | proc if-match (; pattern, template=null; ; block=null) {
|
139 | ### like 'grep' but with submatches
|
140 |
|
141 | for line in (io.stdin) {
|
142 | var m = line.search(pattern)
|
143 | if (m) {
|
144 | #pp asdl_ (m)
|
145 | #var groups = m.groups()
|
146 |
|
147 | # Should we also pass _line?
|
148 |
|
149 | if (block) {
|
150 | call io->eval(block, dollar0=m.group(0))
|
151 | } elif (template) {
|
152 | echo TEMPLATE
|
153 | } else {
|
154 | echo TSV
|
155 | }
|
156 | }
|
157 | }
|
158 |
|
159 | # always succeeds - I think must-match is the one that can fail
|
160 | }
|
161 |
|
162 | proc must-match (; pattern; block) {
|
163 | ### like if-match
|
164 |
|
165 | echo TODO
|
166 | }
|
167 |
|
168 | proc line-data {
|
169 | # note: trailing ''' issue, I should probably get rid of the last line
|
170 |
|
171 | write --end '' -- '''
|
172 | prefix 30 foo
|
173 | oils
|
174 | /// 42 bar
|
175 | '''
|
176 | }
|
177 |
|
178 | const pat = /<capture d+> s+ <capture w+>/
|
179 |
|
180 | proc test-if-match {
|
181 | var z = 'z' # test out scoping
|
182 | var count = 0 # test out mutation
|
183 |
|
184 | # Test cases should be like:
|
185 | # grep: print the matches, or just count them
|
186 | # sed: print a new line based on submatches
|
187 | # awk: re-arrange the cols, and also accumulate counters
|
188 |
|
189 | line-data | if-match (pat) {
|
190 | echo "$z $0 $z"
|
191 | # TODO: need pos_args
|
192 |
|
193 | #echo "-- $2 $1 --"
|
194 |
|
195 | setvar count += 1
|
196 | }
|
197 | echo "count = $count"
|
198 | }
|
199 |
|
200 | proc test-if-match-2 {
|
201 | # If there's no block or template, it should print out a TSV with:
|
202 | #
|
203 | # $0 ...
|
204 | # $1 $2
|
205 | # $_line maybe?
|
206 |
|
207 | #line-data | if-match (pat)
|
208 |
|
209 | var z = 'z' # scoping
|
210 | line-data | if-match (pat, ^"$z $0 $z")
|
211 | line-data | if-match (pat, ^"-- $0 --")
|
212 | }
|
213 |
|
214 | # might be a nice way to write it, not sure if byo.sh can discover it
|
215 | if false {
|
216 | tests 'if-match' {
|
217 | proc case-block {
|
218 | echo TODO
|
219 | }
|
220 | proc case-template {
|
221 | echo TODO
|
222 | }
|
223 | }
|
224 | }
|
225 |
|
226 | # Protocol:
|
227 | #
|
228 | # - The file lists its tests the "actions"
|
229 | # - Then the test harness runs them
|
230 | # - But should it be ENV vars
|
231 | #
|
232 | # - BYO_LIST_TESTS=1
|
233 | # - BYO_RUN_TEST=foo
|
234 | # - $PWD is a CLEAN temp dir, the process doesn't have to do anything
|
235 |
|
236 | # - silent on success, but prints file on output
|
237 | # - OK this makes sense
|
238 | #
|
239 | # The trivial test in Python:
|
240 | #
|
241 | # from test import byo
|
242 | # byo.maybe_main()
|
243 | #
|
244 | # bash library:
|
245 | # source --builtin byo-server.sh
|
246 | #
|
247 | # byo-maybe-main # reads env variables, and then exits
|
248 | #
|
249 | # source --builtin assertions.ysh
|
250 | #
|
251 | # assert-ok 'echo hi'
|
252 | # assert-stdout 'hi' 'echo -n hi'
|
253 | #
|
254 | # "$@"
|
255 | #
|
256 | # Run all tests
|
257 | # util/byo-client.sh run-tests $YSH stdlib/table.ysh
|
258 | # util/byo-client.sh run-tests -f x $YSH stdlib/table.ysh
|
259 |
|
260 | # Clean process
|
261 | # Clean working dir
|
262 |
|
263 | #
|
264 | # Stream Protocol:
|
265 | # #.byo - is this she-dot, that's for a file
|
266 | # Do we need metadata?
|
267 | #
|
268 |
|
269 | # The harness
|
270 | #
|
271 | # It's process based testing.
|
272 | #
|
273 | # Test runner process: bash or OSH (unlike sharness!)
|
274 | # Tested process: any language - bash,
|
275 | #
|
276 | # Key point: you don't have to quote shell code?
|
277 |
|
278 | list-byo-tests() {
|
279 | echo TODO
|
280 | }
|
281 |
|
282 | run-byo-tests() {
|
283 | # source it
|
284 | echo TODO
|
285 | }
|
286 |
|
287 | byo-maybe-run
|