Current section

8 Versions

Jump to

Compare versions

6 files changed
+167 additions
-118 deletions
  @@ -1,9 +1,9 @@
1 1 {<<"links">>,
2 2 [{<<"Gitlab">>,<<"https://gitlab.com/lab42-hex-projects/cliex_map">>}]}.
3 3 {<<"name">>,<<"cliex_map">>}.
4 - {<<"version">>,<<"0.2.5">>}.
4 + {<<"version">>,<<"0.2.6">>}.
5 5 {<<"description">>,<<"Map lines with a powerful mini language">>}.
6 - {<<"elixir">>,<<"~> 1.15">>}.
6 + {<<"elixir">>,<<"~> 1.16">>}.
7 7 {<<"app">>,<<"cliex_map">>}.
8 8 {<<"files">>,
9 9 [<<"lib">>,<<"lib/cliex_map.ex">>,<<"lib/cliex_map">>,
  @@ -99,15 +99,39 @@ defmodule CliexMap do
99 99 iex(13)> run(["", "", ""], "%xmics", C.for_now(1691231907123456))
100 100 ["6022a9d0e9100", "6022a9d0e9100", "6022a9d0e9100"]
101 101
102 + ### Regex Pattern Matches
103 +
104 + This builtin will also filter out lines that are not matched unless a replacement string is provided.
105 + In its simplest form the whole match of the field is returned
106 +
107 + iex(14)> run(["a", "12"], ~s{%(rgx "[[:digit:]]+")})
108 + ["12"]
109 +
110 + Or we can just get a capture group
111 +
112 + iex(15)> run(["a", "12"], ~s{%(rgx "(.)([[:digit:]])" 2)})
113 + ["2"]
114 +
115 + And we can provide a default value
116 +
117 + iex(16)> run(["a", "12"], ~s{%(rgx "(.)([[:digit:]])" 2 "no digit found")})
118 + ["no digit found", "2"]
119 +
120 + Which we can also do if we want to match the whole regex
121 +
122 + iex(17)> run(["a", "12"], ~s{%(rgx "[[:digit:]]+" oh_no)})
123 + ["oh_no", "12"]
124 +
125 +
102 126 ### Variables
103 127
104 128 While, up to here, patterns have been simple we will see later that they can become quite complicated.
105 129 Without explaining the details of the following examples we will see that we need to rewrite a long
106 130 pattern to create the desired command for each input line
107 131
108 - iex(14)> run(["src/DIR/subdir/file.jsno"],
109 - ...(14)> ~s{mkdir -p bup/%xs/%(segments 1 -2)(downcase); cp % bup/%xs/%(segments 1 -2)(downcase)/%(segments -1)(sub ".jsno" ".json")},
110 - ...(14)> C.for_now(1691231907123456))
132 + iex(18)> run(["src/DIR/subdir/file.jsno"],
133 + ...(18)> ~s{mkdir -p bup/%xs/%(segments 1 -2)(downcase); cp % bup/%xs/%(segments 1 -2)(downcase)/%(segments -1)(sub ".jsno" ".json")},
134 + ...(18)> C.for_now(1691231907123456))
111 135 ["mkdir -p bup/64ce26a3/dir/subdir; cp src/DIR/subdir/file.jsno bup/64ce26a3/dir/subdir/file.json"]
112 136
113 137 Actually the patterns above are a little bit more complicated as needed but this is to demonstrate the usage of Variables
  @@ -117,22 +141,22 @@ defmodule CliexMap do
117 141 The `%S<varname><pattern>` will compile `<pattern>` but instead of rendering its result it will store it in the context, thusly the
118 142 following is useless
119 143
120 - iex(15)> run(["useless input"], "%Saa<%(split)(revlist)(join)>")
144 + iex(19)> run(["useless input"], "%Saa<%(split)(revlist)(join)>")
121 145 [""]
122 146
123 147 We can, however use the variable **after** its declaration, and that, many times
124 148
125 - iex(16)> run(["A B"], "%Sx<%(downcase)(split)(revlist)(join)>-%Lx-%Lx-%Lx-")
149 + iex(20)> run(["A B"], "%Sx<%(downcase)(split)(revlist)(join)>-%Lx-%Lx-%Lx-")
126 150 ["-ba-ba-ba-"]
127 151
128 152 Of course a loaded variable can be modified as every other field
129 153
130 - iex(17)> run(["A B"], "%Sx<%(downcase)(split)(revlist)(join)>-%Lx-%Lx(upcase)")
154 + iex(21)> run(["A B"], "%Sx<%(downcase)(split)(revlist)(join)>-%Lx-%Lx(upcase)")
131 155 ["-ba-BA"]
132 156
133 157 Variables can also be used to store constant strings
134 158
135 - iex(18)> run([""], "%Sworld<Brave new world>%Lworld %Lworld(split)(at 1)")
159 + iex(22)> run([""], "%Sworld<Brave new world>%Lworld %Lworld(split)(at 1)")
136 160 ["Brave new world new"]
137 161
138 162 ## Pattern Modifiers
  @@ -144,8 +168,8 @@ defmodule CliexMap do
144 168 injected into the second s-expression and so forth, here are some examples to demonstrate the
145 169 principle
146 170
147 - iex(19)> run(["alpha"], "%(reverse)")
148 - ["ahpla"]
171 + iex(23)> run(["alpha"], "%(reverse)")
172 + ["ahpla"]
149 173
150 174 Below we will list all available built in functions, but here we will also show the more common use
151 175 cases like splitting, extracting and combining segments of strings, formatting output and the shortcut
  @@ -156,24 +180,24 @@ defmodule CliexMap do
156 180 Let us imagien that we want to preceede line numbers by their tenfolds and want to start with 10, what
157 181 we can do of course is to use LLLML as follows
158 182
159 - iex(20)> run(["a", "a", "a", "a"], "%n(+ 1)(* 10) %")
183 + iex(24)> run(["a", "a", "a", "a"], "%n(+ 1)(* 10) %")
160 184 ["10 a", "20 a", "30 a", "40 a"]
161 185
162 186 There are cases where we need the injected line number to be the second argument of a function, e.g.
163 187 if we want to count down. We can indicate the position where a value shall be injected by the placeholder `_`
164 188
165 - iex(21)> run(["b", "b", "b"], "%n(* -10)(+ 110) %")
189 + iex(25)> run(["b", "b", "b"], "%n(* -10)(+ 110) %")
166 190 ["110 b", "100 b", "90 b"]
167 191
168 192
169 193 This is obviously a handful, and therefore we provide a shortcut with a simple value notation
170 194
171 - iex(22)> run(["b", "b", "b"], "%n:110,-10: %")
195 + iex(26)> run(["b", "b", "b"], "%n:110,-10: %")
172 196 ["110 b", "100 b", "90 b"]
173 197
174 198 And the one value version can be used to change the start count, 1 being a popular choice ;)
175 199
176 - iex(23)> run(["b", "b", "e"], "%n:1: %")
200 + iex(27)> run(["b", "b", "e"], "%n:1: %")
177 201 ["1 b", "2 b", "3 e"]
178 202
179 203 ### Formatting Modifiers and their shortcuts
  @@ -183,36 +207,36 @@ defmodule CliexMap do
183 207 as we will show here, shorter patterns are desired and therefore implemented.
184 208
185 209 #### Aligning strings and numbers
186 - iex(24)> run(~w[alpha beta], "%(rpad 6)")
210 + iex(28)> run(~w[alpha beta], "%(rpad 6)")
187 211 ["alpha ", "beta "]
188 212
189 213 And the shorter
190 214
191 - iex(25)> run(~w[alpha beta], "%<-6>")
215 + iex(29)> run(~w[alpha beta], "%<-6>")
192 216 ["alpha ", "beta "]
193 217
194 218 Or
195 219
196 - iex(26)> run(~w[alpha beta], "%(lpad 6 -)")
220 + iex(30)> run(~w[alpha beta], "%(lpad 6 -)")
197 221 ["-alpha", "--beta"]
198 222
199 223 And the shorter
200 224
201 - iex(27)> run(~w[alpha beta], "%<6->")
225 + iex(31)> run(~w[alpha beta], "%<6->")
202 226 ["-alpha", "--beta"]
203 227
204 228
205 - iex(28)> run(["", ""], "%n<2 0>") # Note the space in order to avoid a length of 20
229 + iex(32)> run(["", ""], "%n<2 0>") # Note the space in order to avoid a length of 20
206 230 ["00", "01"]
207 231
208 232 #### Formatting Numbers
209 233
210 - iex(29)> run(["", ""], "%n:15:(to_s 16)(lpad 2 0)")
234 + iex(33)> run(["", ""], "%n:15:(to_s 16)(lpad 2 0)")
211 235 ["0f", "10"]
212 236
213 237 And the shorter
214 238
215 - iex(30)> run(["", ""], "%n:15:<2x0>")
239 + iex(34)> run(["", ""], "%n:15:<2x0>")
216 240 ["0f", "10"]
217 241
218 242
  @@ -227,7 +251,7 @@ defmodule CliexMap do
227 251 We can demonstrate with an explicit implementation of counting down line numbers (which of course is done with the
228 252 shortcuts shown above
229 253
230 - iex(31)> run(["", "", ""], "%n(- 10 _)")
254 + iex(35)> run(["", "", ""], "%n(- 10 _)")
231 255 ["10", "9", "8"]
232 256
233 257 ## Cookbooks
  @@ -272,21 +296,21 @@ defmodule CliexMap do
272 296
273 297 By using the output from, e.g. `git ls-files src` or `find src -name '*.json'` we can map the input with the following pattern
274 298
275 - iex(32)> input = ~W[ src/namespace_1/file1.json src/namespace_2/file1.json src/namespace_2/file2.json ]
276 - ...(32)> run(input, "mkdir -p tests/json_tests/%(segment 1); touch tests/json_tests/%(segments 1 2)(sub '.json' '_test.exs')")
277 - [
278 - "mkdir -p tests/json_tests/namespace_1; touch tests/json_tests/namespace_1/file1_test.exs",
279 - "mkdir -p tests/json_tests/namespace_2; touch tests/json_tests/namespace_2/file1_test.exs",
280 - "mkdir -p tests/json_tests/namespace_2; touch tests/json_tests/namespace_2/file2_test.exs"
281 - ]
299 + iex(36)> input = ~W[ src/namespace_1/file1.json src/namespace_2/file1.json src/namespace_2/file2.json ]
300 + ...(36)> run(input, "mkdir -p tests/json_tests/%(segment 1); touch tests/json_tests/%(segments 1 2)(sub '.json' '_test.exs')")
301 + [
302 + "mkdir -p tests/json_tests/namespace_1; touch tests/json_tests/namespace_1/file1_test.exs",
303 + "mkdir -p tests/json_tests/namespace_2; touch tests/json_tests/namespace_2/file1_test.exs",
304 + "mkdir -p tests/json_tests/namespace_2; touch tests/json_tests/namespace_2/file2_test.exs"
305 + ]
282 306
283 307 Changing and using extensions of filenames is frequent enough to justify the `ext` builtin
284 308
285 - iex(33)> input = ~W[ src/namespace_1/file1.json ]
286 - ...(33)> run(input, "mkdir -p tests/json_tests/%(segment 1); touch tests/json_tests/%(segments 1 2)(ext _test.exs)")
287 - [
288 - "mkdir -p tests/json_tests/namespace_1; touch tests/json_tests/namespace_1/file1_test.exs",
289 - ]
309 + iex(37)> input = ~W[ src/namespace_1/file1.json ]
310 + ...(37)> run(input, "mkdir -p tests/json_tests/%(segment 1); touch tests/json_tests/%(segments 1 2)(ext _test.exs)")
311 + [
312 + "mkdir -p tests/json_tests/namespace_1; touch tests/json_tests/namespace_1/file1_test.exs",
313 + ]
290 314
291 315 ## Comprehensive List of Builtin Functions
292 316
  @@ -294,191 +318,191 @@ defmodule CliexMap do
294 318 only if needed
295 319
296 320 ### abs
297 - iex(34)> B.abs(nil, [-10])
321 + iex(38)> B.abs(nil, [-10])
298 322 10
299 323
300 324 ### add (used for `+`)
301 - iex(35)> B._add(nil, [1, 2, 3, 4])
325 + iex(39)> B._add(nil, [1, 2, 3, 4])
302 326 10
303 327
304 328 ### at (alias to Enum.at)
305 - iex(36)> B.at(nil, [~w[a b c], 2])
329 + iex(40)> B.at(nil, [~w[a b c], 2])
306 330 "c"
307 331
308 - iex(37)> B.at(nil, [~w[a b c], -3])
332 + iex(41)> B.at(nil, [~w[a b c], -3])
309 333 "a"
310 334
311 - iex(38)> B.at(nil, [~w[a b c], 1, :default])
335 + iex(42)> B.at(nil, [~w[a b c], 1, :default])
312 336 "b"
313 337
314 - iex(39)> B.at(nil, [~w[a b c], 3, :default])
338 + iex(43)> B.at(nil, [~w[a b c], 3, :default])
315 339 :default
316 340
317 341 ### bn (Path.basename)
318 - iex(40)> B.bn(nil, ~W[a/b])
342 + iex(44)> B.bn(nil, ~W[a/b])
319 343 "b"
320 344
321 - iex(41)> B.bn(nil, ~W[b.ext])
345 + iex(45)> B.bn(nil, ~W[b.ext])
322 346 "b.ext"
323 347
324 - iex(42)> B.bn(nil, ~W[a/c/b.ext])
348 + iex(46)> B.bn(nil, ~W[a/c/b.ext])
325 349 "b.ext"
326 350
327 351 ### div (used for `/`)
328 - iex(43)> B._div(nil, [9, 4])
352 + iex(47)> B._div(nil, [9, 4])
329 353 2.25
330 354
331 355 ### dn (Path.dirname)
332 - iex(44)> B.dn(nil, ~W[a/b])
356 + iex(48)> B.dn(nil, ~W[a/b])
333 357 "a"
334 358
335 - iex(45)> B.dn(nil, ~W[b.ext])
359 + iex(49)> B.dn(nil, ~W[b.ext])
336 360 "."
337 361
338 - iex(46)> B.dn(nil, ~W[a/c/b.ext])
362 + iex(50)> B.dn(nil, ~W[a/c/b.ext])
339 363 "a/c"
340 364
341 365 ### downcase
342 - iex(47)> B.downcase(nil, ["HELLO"])
366 + iex(51)> B.downcase(nil, ["HELLO"])
343 367 "hello"
344 368
345 369 ### ext/1
346 370 Returns last extension of a filename
347 371
348 - iex(48)> B.ext(nil, ["a.html.eex"])
372 + iex(52)> B.ext(nil, ["a.html.eex"])
349 373 "eex"
350 374
351 375 If no extension is found it returns an empty string
352 376
353 - iex(49)> B.ext(nil, ["a"])
377 + iex(53)> B.ext(nil, ["a"])
354 378 ""
355 379
356 380 ### ext/2
357 381 Changes last extension of a filename, **N.B.** that the `.` is not added automatically
358 - iex(50)> B.ext(nil, ["a.html.erb", ".eex"])
382 + iex(54)> B.ext(nil, ["a.html.erb", ".eex"])
359 383 "a.html.eex"
360 384
361 385 ### idiv (used for `:`)
362 - iex(51)> B._idiv(nil, [9, 4])
386 + iex(55)> B._idiv(nil, [9, 4])
363 387 2
364 388
365 389 ### join
366 - iex(52)> B.join(nil, [[1, 2]])
390 + iex(56)> B.join(nil, [[1, 2]])
367 391 "12"
368 392
369 - iex(53)> B.join(nil, [[1, 2, 3], " "])
393 + iex(57)> B.join(nil, [[1, 2, 3], " "])
370 394 "1 2 3"
371 395
372 396 ### lpad
373 - iex(54)> B.lpad(nil, ["a", 2])
374 - " a"
397 + iex(58)> B.lpad(nil, ["a", 2])
398 + " a"
375 399
376 - iex(55)> B.lpad(nil, ["a", 3, :"-*"])
377 - "-*a"
400 + iex(59)> B.lpad(nil, ["a", 3, :"-*"])
401 + "-*a"
378 402
379 403 ### mul
380 - iex(56)> B._mul(nil, [1, 2, 3, 4])
404 + iex(60)> B._mul(nil, [1, 2, 3, 4])
381 405 24
382 406
383 407 ### reverse
384 - iex(57)> B.reverse(nil, ["alpha"])
408 + iex(61)> B.reverse(nil, ["alpha"])
385 409 "ahpla"
386 410
387 411 ### revlist
388 - iex(58)> B.revlist(nil, [~W[a b]])
412 + iex(62)> B.revlist(nil, [~W[a b]])
389 413 ~W[b a]
390 414
391 415 ### rpad
392 - iex(59)> B.rpad(nil, ["a", 2])
393 - "a "
416 + iex(63)> B.rpad(nil, ["a", 2])
417 + "a "
394 418
395 - iex(60)> B.rpad(nil, ["a", 3, :"--"])
396 - "a--"
419 + iex(64)> B.rpad(nil, ["a", 3, :"--"])
420 + "a--"
397 421
398 422 ### segment Extract a path
399 423
400 424 - with -1 like `basename`
401 - iex(61)> B.segment(nil, ["a/b/c", -1])
425 + iex(65)> B.segment(nil, ["a/b/c", -1])
402 426 "c"
403 427
404 428 - without an arg like `dirname`
405 - iex(62)> B.segment(nil, ["a/b/c"])
429 + iex(66)> B.segment(nil, ["a/b/c"])
406 430 "a/b"
407 431
408 432 - or any part
409 433
410 - iex(63)> B.segment(nil, ["a/b/c", 0])
434 + iex(67)> B.segment(nil, ["a/b/c", 0])
411 435 "a"
412 436
413 - iex(64)> B.segment(nil, ["a/b/c", -2])
437 + iex(68)> B.segment(nil, ["a/b/c", -2])
414 438 "b"
415 439
416 440
417 441 ### segments (short for `(splicej "/" _1 _2)`)
418 - iex(65)> B.segments(nil, ["x/y/z", 2])
442 + iex(69)> B.segments(nil, ["x/y/z", 2])
419 443 "z"
420 444
421 - iex(66)> B.segments(nil, ["x/y/z", -2, -1])
445 + iex(70)> B.segments(nil, ["x/y/z", -2, -1])
422 446 "y/z"
423 447
424 448 ### slice
425 449
426 450 #### lists
427 451
428 - iex(67)> B.slice(nil, [~w[a b c d], 1])
452 + iex(71)> B.slice(nil, [~w[a b c d], 1])
429 453 ~w[b c d]
430 454
431 - iex(68)> B.slice(nil, [~w[a b c d], 2, 3])
455 + iex(72)> B.slice(nil, [~w[a b c d], 2, 3])
432 456 ~w[c d]
433 457
434 - iex(69)> B.slice(nil, [~w[a b c d], -2])
458 + iex(73)> B.slice(nil, [~w[a b c d], -2])
435 459 ~w[c d]
436 460
437 - iex(70)> B.slice(nil, [~w[a b c d], -4, -2])
461 + iex(74)> B.slice(nil, [~w[a b c d], -4, -2])
438 462 ~w[a b c]
439 463
440 - iex(71)> B.slice(nil, [~w[a b c d], -4, 1])
464 + iex(75)> B.slice(nil, [~w[a b c d], -4, 1])
441 465 ~w[a b]
442 466
443 - iex(72)> B.slice(nil, [~w[a b c d], 1, 0])
467 + iex(76)> B.slice(nil, [~w[a b c d], 1, 0])
444 468 []
445 469
446 470 #### strings
447 471
448 - iex(73)> B.slice(nil, ["abc", 1])
472 + iex(77)> B.slice(nil, ["abc", 1])
449 473 "bc"
450 474
451 - iex(74)> B.slice(nil, ["abc", -1])
475 + iex(78)> B.slice(nil, ["abc", -1])
452 476 "c"
453 477
454 - iex(75)> B.slice(nil, ["abc", 1, 2])
478 + iex(79)> B.slice(nil, ["abc", 1, 2])
455 479 "bc"
456 480
457 - iex(76)> B.slice(nil, ["abcd", -2, -1])
481 + iex(80)> B.slice(nil, ["abcd", -2, -1])
458 482 "cd"
459 483
460 - iex(77)> B.slice(nil, ["abcd", -2, 3])
484 + iex(81)> B.slice(nil, ["abcd", -2, 3])
461 485 "cd"
462 486
463 - iex(78)> B.slice(nil, ["abc", 0, -2])
487 + iex(82)> B.slice(nil, ["abc", 0, -2])
464 488 "ab"
465 489
466 490 #### safe
467 491
468 492 - First index out of bounds
469 493
470 - iex(79)> B.slice(nil, ["abc", 4])
494 + iex(83)> B.slice(nil, ["abc", 4])
471 495 ""
472 496
473 - iex(80)> B.slice(nil, [~w[a b], 2])
497 + iex(84)> B.slice(nil, [~w[a b], 2])
474 498 []
475 499
476 500 - Last index out of bounds
477 501
478 - iex(81)> B.slice(nil, ["abc", 2, 5])
502 + iex(85)> B.slice(nil, ["abc", 2, 5])
479 503 "c"
480 504
481 - iex(82)> B.slice(nil, [~w[a b], 1, 4])
505 + iex(86)> B.slice(nil, [~w[a b], 1, 4])
482 506 ~w[b]
483 507
484 508
  @@ -486,47 +510,47 @@ defmodule CliexMap do
486 510
487 511 - join on original seperator
488 512
489 - iex(83)> B.splicej(nil, ["a/b/c/d/e", "/", 2, 3])
490 - "c/d"
513 + iex(87)> B.splicej(nil, ["a/b/c/d/e", "/", 2, 3])
514 + "c/d"
491 515
492 516 - join on original seperator, slice to the end
493 517
494 - iex(84)> B.splicej(nil, ["a/b/c/d/e", "/", 2])
495 - "c/d/e"
518 + iex(88)> B.splicej(nil, ["a/b/c/d/e", "/", 2])
519 + "c/d/e"
496 520
497 521 - join with different string
498 522
499 - iex(85)> B.splice_join(nil, ["a/b/c/d/e", "/", 2, 3, ","])
500 - "c,d"
523 + iex(89)> B.splice_join(nil, ["a/b/c/d/e", "/", 2, 3, ","])
524 + "c,d"
501 525
502 526 ### split
503 527
504 - iex(86)> B.split(nil, ["a b"])
528 + iex(90)> B.split(nil, ["a b"])
505 529 ["a", "b"]
506 530
507 - iex(87)> B.split(nil, ["a,b", ","])
531 + iex(91)> B.split(nil, ["a,b", ","])
508 532 ["a", "b"]
509 533
510 534 ### sub (from `-`) (use with care)
511 - iex(88)> B._sub(nil, [1, 2, 3, 4])
535 + iex(92)> B._sub(nil, [1, 2, 3, 4])
512 536 -8
513 537
514 538 ### sub (from `sub`)
515 - iex(89)> B.sub(nil, ["Hello World", "l"])
539 + iex(93)> B.sub(nil, ["Hello World", "l"])
516 540 "Heo Word"
517 541
518 - iex(90)> B.sub(nil, ["Hello World", "l", "L"])
542 + iex(94)> B.sub(nil, ["Hello World", "l", "L"])
519 543 "HeLLo WorLd"
520 544
521 545 ### to_s (for numbers only)
522 - iex(91)> B.to_s(nil, [12])
546 + iex(95)> B.to_s(nil, [12])
523 547 "12"
524 548
525 - iex(92)> B.to_s(nil, [12, 16])
549 + iex(96)> B.to_s(nil, [12, 16])
526 550 "c"
527 551
528 552 ### upcase
529 - iex(93)> B.upcase(nil, ["hello"])
553 + iex(97)> B.upcase(nil, ["hello"])
530 554 "HELLO"
531 555
532 556 """
  @@ -81,6 +81,24 @@ defmodule CliexMap.Builtins do
81 81 @spec revlist(Context.t, list()) :: list()
82 82 def revlist(_context, [list]), do: Enum.reverse(list)
83 83
84 + @spec rgx(Context.t, list()) :: binary()
85 + def rgx(context, [src, pattern]) do
86 + rgx(context, [src, pattern, 0])
87 + end
88 + def rgx(context, [src, pattern, count]) when is_number(count) do
89 + rgx(context, [src, pattern, count, nil])
90 + end
91 + def rgx(context, [src, pattern, count]) do
92 + rgx(context, [src, pattern, 0, to_string(count)])
93 + end
94 + def rgx(_context, [src, pattern, count, replacement]) do
95 + p = Regex.compile!(to_string(pattern))
96 + case Regex.run(p, src) do
97 + nil -> if replacement, do: replacement, else: {:halt, :ignore}
98 + m -> Enum.at(m, count)
99 + end
100 + end
101 +
84 102 @spec rnd(Context.t, list()) :: binary()
85 103 def rnd(_context, args) do
86 104 case args do
  @@ -52,7 +52,7 @@ defmodule CliexMap.Cli do
52 52 |> Enum.each(&IO.puts/1)
53 53 end
54 54
55 - @spec help_pattern() :: :ok
55 + @spec help_pattern() :: nil
56 56 defp help_pattern do
57 57 # Color.putc([
58 58 # "A pattern always starts with a ",
  @@ -3,7 +3,7 @@ defmodule CliexMap.Mapper do
3 3
4 4 alias CliexMap.{Context, Fn, FunctionList}
5 5
6 - @moduledoc ~S"""
6 + @moduledoc ~S"""
7 7 Maps each line according to pattern to a new, `\n` terminated string
8 8 """
9 9
  @@ -15,20 +15,25 @@ defmodule CliexMap.Mapper do
15 15 Stream.zip(line_numbers, input_stream |> Stream.map(&String.trim_trailing(&1, "\n")))
16 16
17 17 numbered_lines
18 - |> Enum.map(&transform_line(&1, function_pipeline, context))
18 + |> Stream.map(&transform_line(&1, function_pipeline, context))
19 + |> Enum.filter(&is_binary/1)
19 20 end
20 21
21 22 @spec transform_line(numbered_line_t(), list(FunctionList.t()), Context.t()) :: binary()
22 23 def transform_line(line, function_pipelines, context) do
23 24 with {_context, outputresult} <-
24 25 function_pipelines
25 - |> Enum.reduce({context, []}, fn pipeline, {ctxt, output} ->
26 - {ctxt1, output1} = transform_chunk(line, pipeline, ctxt)
27 - {ctxt1, [output1 | output]}
26 + |> Enum.reduce_while({context, []}, fn pipeline, {ctxt, output} ->
27 + case transform_chunk(line, pipeline, ctxt) do
28 + {ctxt1, output1} -> {:cont, {ctxt1, [output1 | output]}}
29 + :ignore -> {:halt, :ignore}
30 + _value -> raise "Not yet implemented"
31 + end
28 32 end) do
29 - outputresult
30 - |> Enum.reverse
31 - |> Enum.join
33 + case outputresult do
34 + :ignore -> :ignore
35 + o -> o |> Enum.reverse |> Enum.join
36 + end
32 37 end
33 38 end
34 39
  @@ -38,10 +43,12 @@ defmodule CliexMap.Mapper do
38 43 #
39 44 function_pipeline.functions
40 45 |> Enum.reverse()
41 - |> Enum.reduce({context, line}, fn function, {ctxt, input} ->
46 + |> Enum.reduce_while({context, line}, fn function, {ctxt, input} ->
42 47 case Fn.call(function, input, ctxt) do
43 - {ctxt1, text} -> {ctxt1, text}
44 - text -> {ctxt, text}
48 + :halt -> {:halt, :ignore}
49 + {:halt, _} = hv -> hv
50 + {_, _} = cc -> {:cont, cc}
51 + text -> {:cont, {ctxt, text}}
45 52 end
46 53 end)
47 54 end
Loading more files…