tessella 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (188) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +900 -0
  4. data/doc/README.md +74 -0
  5. data/doc/bitfield.md +123 -0
  6. data/doc/charts.md +1370 -0
  7. data/doc/check.rb +75 -0
  8. data/doc/cli.md +483 -0
  9. data/doc/composition.md +599 -0
  10. data/doc/getting-started.md +121 -0
  11. data/doc/glyphs.md +134 -0
  12. data/doc/images.md +325 -0
  13. data/doc/library.md +239 -0
  14. data/doc/lint.md +270 -0
  15. data/doc/meter.md +210 -0
  16. data/doc/rule.md +51 -0
  17. data/doc/seq.md +169 -0
  18. data/doc/sparkline.md +63 -0
  19. data/doc/table.md +347 -0
  20. data/doc/targets.md +222 -0
  21. data/doc/text.md +84 -0
  22. data/doc/tree.md +108 -0
  23. data/doc/wave.md +122 -0
  24. data/examples/README.md +103 -0
  25. data/examples/ages.txt +9 -0
  26. data/examples/bad.csv +3 -0
  27. data/examples/boxes.txt +3 -0
  28. data/examples/broken.txt +4 -0
  29. data/examples/calibration.rb +12 -0
  30. data/examples/cities.csv +4 -0
  31. data/examples/cjk.rb +13 -0
  32. data/examples/comment.rb +9 -0
  33. data/examples/comment.sh +13 -0
  34. data/examples/cpu.txt +60 -0
  35. data/examples/dashboard.sh +25 -0
  36. data/examples/datasheet.rb +16 -0
  37. data/examples/disc.pgm +0 -0
  38. data/examples/disks.sh +18 -0
  39. data/examples/disks.txt +5 -0
  40. data/examples/dose.txt +7 -0
  41. data/examples/drift.txt +4 -0
  42. data/examples/ethernet.txt +3 -0
  43. data/examples/figure.c +5 -0
  44. data/examples/fit.rb +16 -0
  45. data/examples/floors.rb +21 -0
  46. data/examples/gallery.sh +20 -0
  47. data/examples/gauges.sh +31 -0
  48. data/examples/gradient.rb +16 -0
  49. data/examples/growth.txt +6 -0
  50. data/examples/hosts.csv +4 -0
  51. data/examples/icmp.txt +3 -0
  52. data/examples/ipv4.txt +12 -0
  53. data/examples/kinds.csv +4 -0
  54. data/examples/langs.csv +4 -0
  55. data/examples/lint.rb +16 -0
  56. data/examples/load.rb +14 -0
  57. data/examples/login.txt +10 -0
  58. data/examples/neg.csv +4 -0
  59. data/examples/normal.txt +200 -0
  60. data/examples/note.txt +2 -0
  61. data/examples/notes-fixed.md +17 -0
  62. data/examples/notes.md +17 -0
  63. data/examples/ohlc.txt +7 -0
  64. data/examples/os.csv +10 -0
  65. data/examples/outline.txt +8 -0
  66. data/examples/plot.txt +5 -0
  67. data/examples/refusals.rb +17 -0
  68. data/examples/report.sh +21 -0
  69. data/examples/rfc.sh +22 -0
  70. data/examples/samples.txt +7 -0
  71. data/examples/shapes.pgm +0 -0
  72. data/examples/sizes.tsv +3 -0
  73. data/examples/spi.txt +6 -0
  74. data/examples/status.sh +23 -0
  75. data/examples/stem.txt +12 -0
  76. data/examples/table-drift.txt +4 -0
  77. data/examples/temps.txt +31 -0
  78. data/examples/trig.sh +13 -0
  79. data/examples/trig.txt +102 -0
  80. data/examples/week.txt +8 -0
  81. data/examples/wide.txt +2 -0
  82. data/exe/tessella +6 -0
  83. data/lib/tessella/axis.rb +71 -0
  84. data/lib/tessella/bitfield.rb +194 -0
  85. data/lib/tessella/block.rb +56 -0
  86. data/lib/tessella/borders.rb +85 -0
  87. data/lib/tessella/canvas/area.rb +155 -0
  88. data/lib/tessella/canvas/ascii.rb +120 -0
  89. data/lib/tessella/canvas/block.rb +40 -0
  90. data/lib/tessella/canvas/braille.rb +30 -0
  91. data/lib/tessella/canvas/clip.rb +49 -0
  92. data/lib/tessella/canvas/density.rb +51 -0
  93. data/lib/tessella/canvas/dot.rb +27 -0
  94. data/lib/tessella/canvas/eighths.rb +43 -0
  95. data/lib/tessella/canvas/half.rb +51 -0
  96. data/lib/tessella/canvas/sextant.rb +36 -0
  97. data/lib/tessella/canvas.rb +168 -0
  98. data/lib/tessella/cell.rb +10 -0
  99. data/lib/tessella/chart.rb +211 -0
  100. data/lib/tessella/check.rb +52 -0
  101. data/lib/tessella/cli/bitfield.rb +121 -0
  102. data/lib/tessella/cli/chart.rb +615 -0
  103. data/lib/tessella/cli/chart_candle.rb +36 -0
  104. data/lib/tessella/cli/chart_heatmap.rb +21 -0
  105. data/lib/tessella/cli/chart_help.rb +85 -0
  106. data/lib/tessella/cli/chart_pie.rb +38 -0
  107. data/lib/tessella/cli/compose.rb +156 -0
  108. data/lib/tessella/cli/compose_options.rb +259 -0
  109. data/lib/tessella/cli/glyphs.rb +97 -0
  110. data/lib/tessella/cli/image.rb +250 -0
  111. data/lib/tessella/cli/input.rb +44 -0
  112. data/lib/tessella/cli/iso_time.rb +28 -0
  113. data/lib/tessella/cli/lint.rb +102 -0
  114. data/lib/tessella/cli/lint_options.rb +99 -0
  115. data/lib/tessella/cli/main.rb +121 -0
  116. data/lib/tessella/cli/meter.rb +80 -0
  117. data/lib/tessella/cli/rule.rb +57 -0
  118. data/lib/tessella/cli/seq.rb +117 -0
  119. data/lib/tessella/cli/sparkline.rb +72 -0
  120. data/lib/tessella/cli/table.rb +167 -0
  121. data/lib/tessella/cli/text.rb +78 -0
  122. data/lib/tessella/cli/tree.rb +100 -0
  123. data/lib/tessella/cli/wave.rb +148 -0
  124. data/lib/tessella/cli.rb +36 -0
  125. data/lib/tessella/color.rb +106 -0
  126. data/lib/tessella/compose.rb +243 -0
  127. data/lib/tessella/compose_fill.rb +176 -0
  128. data/lib/tessella/compose_grid.rb +36 -0
  129. data/lib/tessella/compose_shadow.rb +41 -0
  130. data/lib/tessella/error.rb +13 -0
  131. data/lib/tessella/frame.rb +170 -0
  132. data/lib/tessella/glyphs.rb +106 -0
  133. data/lib/tessella/image.rb +454 -0
  134. data/lib/tessella/image_octant.rb +46 -0
  135. data/lib/tessella/image_petscii.rb +116 -0
  136. data/lib/tessella/kinds/bar.rb +344 -0
  137. data/lib/tessella/kinds/box.rb +213 -0
  138. data/lib/tessella/kinds/box_upright.rb +110 -0
  139. data/lib/tessella/kinds/candlestick.rb +164 -0
  140. data/lib/tessella/kinds/columns.rb +259 -0
  141. data/lib/tessella/kinds/date_axis.rb +102 -0
  142. data/lib/tessella/kinds/error_bars.rb +71 -0
  143. data/lib/tessella/kinds/heatmap.rb +130 -0
  144. data/lib/tessella/kinds/line.rb +173 -0
  145. data/lib/tessella/kinds/multibar.rb +98 -0
  146. data/lib/tessella/kinds/multibar_columns.rb +130 -0
  147. data/lib/tessella/kinds/multibar_fine.rb +45 -0
  148. data/lib/tessella/kinds/multibar_rows.rb +93 -0
  149. data/lib/tessella/kinds/pie.rb +123 -0
  150. data/lib/tessella/kinds/pie_rim.rb +78 -0
  151. data/lib/tessella/kinds/sideways.rb +62 -0
  152. data/lib/tessella/kinds/stem.rb +134 -0
  153. data/lib/tessella/kinds/threshold.rb +73 -0
  154. data/lib/tessella/legend.rb +31 -0
  155. data/lib/tessella/lint/alphabet.rb +56 -0
  156. data/lib/tessella/lint/drift.rb +82 -0
  157. data/lib/tessella/lint/fences.rb +51 -0
  158. data/lib/tessella/lint/geometry.rb +120 -0
  159. data/lib/tessella/lint/geometry_checks.rb +224 -0
  160. data/lib/tessella/lint/lines.rb +115 -0
  161. data/lib/tessella/lint/mixing.rb +61 -0
  162. data/lib/tessella/lint/runner.rb +73 -0
  163. data/lib/tessella/lint/shadows.rb +120 -0
  164. data/lib/tessella/lint/target_rows.rb +66 -0
  165. data/lib/tessella/lint.rb +158 -0
  166. data/lib/tessella/meter.rb +133 -0
  167. data/lib/tessella/meter_upright.rb +43 -0
  168. data/lib/tessella/png.rb +456 -0
  169. data/lib/tessella/raster.rb +92 -0
  170. data/lib/tessella/rmagick_reader.rb +52 -0
  171. data/lib/tessella/rule.rb +59 -0
  172. data/lib/tessella/seq.rb +522 -0
  173. data/lib/tessella/sparkline.rb +57 -0
  174. data/lib/tessella/stats.rb +199 -0
  175. data/lib/tessella/table.rb +547 -0
  176. data/lib/tessella/table_cells.rb +225 -0
  177. data/lib/tessella/target.rb +105 -0
  178. data/lib/tessella/text.rb +76 -0
  179. data/lib/tessella/text_forms.rb +150 -0
  180. data/lib/tessella/tree.rb +221 -0
  181. data/lib/tessella/version.rb +5 -0
  182. data/lib/tessella/wave.rb +353 -0
  183. data/lib/tessella/width.rb +122 -0
  184. data/lib/tessella/width_class.rb +77 -0
  185. data/lib/tessella/width_invisible.rb +66 -0
  186. data/lib/tessella/width_invisible_high.rb +60 -0
  187. data/lib/tessella.rb +94 -0
  188. metadata +226 -0
data/doc/tree.md ADDED
@@ -0,0 +1,108 @@
1
+ # Trees
2
+
3
+ `tree` draws an indented outline as a box-drawing tree: a directory
4
+ layout, a class hierarchy, a table of contents.
5
+
6
+ ```ruby
7
+ Tessella.tree(outline, style: nil, ascii: false, root: nil) # => Block
8
+ ```
9
+
10
+ ```text
11
+ tessella tree [--style S] [--ascii] [--root NAME] [--max-width N] [file]
12
+ ```
13
+
14
+ ## The outline
15
+
16
+ One node per line; depth is the leading spaces. The indent unit is
17
+ whatever the first indented line uses, and every indent must be a
18
+ whole multiple of it.
19
+
20
+ ```text
21
+ $ cat outline.txt
22
+ tessella
23
+ lib # the library
24
+ tessella.rb # the entry
25
+ tessella
26
+ cli
27
+ exe
28
+ tessella # the command
29
+ test
30
+ ```
31
+
32
+ - A leading `- ` or `* ` bullet is dropped, so a Markdown list reads
33
+ as is.
34
+ - Two or more spaces then `#` start a note. Notes are lined up in one
35
+ column across the whole tree.
36
+ - A line may go at most one level deeper than the line above it.
37
+
38
+ ```text
39
+ $ tessella tree outline.txt
40
+ tessella
41
+ ├── lib # the library
42
+ │ ├── tessella.rb # the entry
43
+ │ └── tessella
44
+ │ └── cli
45
+ ├── exe
46
+ │ └── tessella # the command
47
+ └── test
48
+ ```
49
+
50
+ ## Styles
51
+
52
+ `--style light` (the default), `heavy` or `rounded`; `--ascii` draws
53
+ `|--` and `` `-- `` instead, and allows no other style.
54
+
55
+ ```text
56
+ $ tessella tree --style rounded outline.txt
57
+ tessella
58
+ ├── lib # the library
59
+ │ ├── tessella.rb # the entry
60
+ │ ╰── tessella
61
+ │ ╰── cli
62
+ ├── exe
63
+ │ ╰── tessella # the command
64
+ ╰── test
65
+ ```
66
+
67
+ ```text
68
+ $ tessella tree --ascii outline.txt
69
+ tessella
70
+ |-- lib # the library
71
+ | |-- tessella.rb # the entry
72
+ | `-- tessella
73
+ | `-- cli
74
+ |-- exe
75
+ | `-- tessella # the command
76
+ `-- test
77
+ ```
78
+
79
+ ## Forests and roots
80
+
81
+ Several lines at the top level are a forest: each is drawn as a root
82
+ of its own. `--root NAME` (`root: "NAME"`) gathers them under one
83
+ root instead:
84
+
85
+ <!-- tessella: allow-mixed -->
86
+ ```text
87
+ $ printf -- '- lib\n- exe\n- test\n' | tessella tree --root tessella
88
+ tessella
89
+ ├── lib
90
+ ├── exe
91
+ └── test
92
+ ```
93
+
94
+ ## Errors
95
+
96
+ Bad input raises `ArgumentError` naming the line (exit 1 on the
97
+ command line): a tab, an indent that is not a whole multiple of the
98
+ unit, a line two levels deeper than the one before it, an empty
99
+ label, no node at all, and a non-ASCII label under `--ascii`.
100
+
101
+ ```text
102
+ $ printf 'a\n b\n c\n' | tessella tree
103
+ tessella tree: line 3: indentation is not a multiple of 3
104
+ ```
105
+
106
+ An unknown style, or a style other than the default with `--ascii`,
107
+ is a usage error (exit 2). `--max-width N` refuses (exit 1) a tree
108
+ wider than N columns, naming the node that overflows.
data/doc/wave.md ADDED
@@ -0,0 +1,122 @@
1
+ # Timing diagrams
2
+
3
+ `wave` draws digital signals over time from a WaveDrom-like text: one
4
+ signal per line, one character per time step.
5
+
6
+ ```ruby
7
+ Tessella.wave(text, period: 4, ascii: false, ruler: false) # => Block
8
+ ```
9
+
10
+ ```text
11
+ tessella wave [--period N] [--ascii] [--ruler] [--max-width N] [file]
12
+ ```
13
+
14
+ ## Input
15
+
16
+ Each line is `name: wave`, optionally followed by `| label label ...`
17
+ naming the bus values in order. A lone `---` line draws an empty row
18
+ between groups of signals.
19
+
20
+ | Char | Step |
21
+ |------|-----------------------------------------|
22
+ | `0` | low |
23
+ | `1` | high |
24
+ | `p` | a clock period, starting high |
25
+ | `n` | a clock period, starting low |
26
+ | `x` | unknown (shaded) |
27
+ | `z` | high impedance (dotted) |
28
+ | `=` | a bus value, labelled by the next label |
29
+ | `.` | the previous state continues |
30
+
31
+ ```text
32
+ $ cat spi.txt
33
+ clk: p.......
34
+ cs: 10.....1
35
+ mosi: x=.=.=.x | A0 D0 D1
36
+ miso: z..=.=.z | R0 R1
37
+ ---
38
+ irq: 0....1.0
39
+ ```
40
+
41
+ ```text
42
+ $ tessella wave spi.txt
43
+ ──┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐
44
+ clk └─┘ └─┘ └─┘ └─┘ └─┘ └─┘ └─┘ └─
45
+
46
+ ────┐ ┌───
47
+ cs └───────────────────────┘
48
+
49
+ ▒▒▒▒╳ ╳ ╳ ▒▒▒▒
50
+ mosi ▒▒▒▒╳──A0───╳──D0───╳──D1───▒▒▒▒
51
+
52
+ ┄┄┄┄┄┄┄┄┄┄┄┄╳ ╳ ┄┄┄┄
53
+ miso ┄┄┄┄┄┄┄┄┄┄┄┄╳──R0───╳──R1───┄┄┄┄
54
+
55
+
56
+ ┌───────┐
57
+ irq ────────────────────┘ └───
58
+ ```
59
+
60
+ ## Options
61
+
62
+ `--period N` (`period:`) is the number of columns per step, 4 by
63
+ default; it must be 2 or more, since a clock needs a column to rise
64
+ and one to fall. `--ruler` numbers the steps under the diagram.
65
+
66
+ ```text
67
+ $ tessella wave --period 3 --ruler spi.txt
68
+ ─┐ ┌┐ ┌┐ ┌┐ ┌┐ ┌┐ ┌┐ ┌┐
69
+ clk └─┘└─┘└─┘└─┘└─┘└─┘└─┘└─
70
+
71
+ ───┐ ┌──
72
+ cs └─────────────────┘
73
+
74
+ ▒▒▒╳ ╳ ╳ ▒▒▒
75
+ mosi ▒▒▒╳─A0──╳─D0──╳─D1──▒▒▒
76
+
77
+ ┄┄┄┄┄┄┄┄┄╳ ╳ ┄┄┄
78
+ miso ┄┄┄┄┄┄┄┄┄╳─R0──╳─R1──┄┄┄
79
+
80
+
81
+ ┌─────┐
82
+ irq ───────────────┘ └──
83
+
84
+ 0 1 2 3 4 5 6 7
85
+ ```
86
+
87
+ `--ascii` draws `_ | X` and `x`, `-` for unknown and high impedance:
88
+
89
+ ```text
90
+ $ tessella wave --ascii spi.txt
91
+ __ _ _ _ _ _ _ _
92
+ clk |_| |_| |_| |_| |_| |_| |_| |_
93
+
94
+ ____ ___
95
+ cs |_______________________|
96
+
97
+ xxxx xxxx
98
+ mosi xxxxX__A0___X__D0___X__D1___xxxx
99
+
100
+ ------------ ----
101
+ miso ------------X__R0___X__R1___----
102
+
103
+
104
+ _______
105
+ irq ____________________| |___
106
+ ```
107
+
108
+ A diagram that ends on `---` does not keep that last blank row: no
109
+ block ends with a blank line.
110
+
111
+ ## Errors
112
+
113
+ An unknown wave character, a line without `name:`, labels that do
114
+ not match the `=` steps one for one, or a non-ASCII name or label
115
+ under `--ascii` exits 1, naming the line:
116
+
117
+ ```text
118
+ $ printf 'clk: pq\n' | tessella wave
119
+ tessella wave: line 1: unknown wave character q
120
+ ```
121
+
122
+ A `--period` below 2 is a usage error (exit 2).
@@ -0,0 +1,103 @@
1
+ # tessella examples
2
+
3
+ Input files and Ruby scripts the documentation in [doc/](../doc/)
4
+ draws its figures from. Run them from this directory, with tessella
5
+ installed (`make install`), or from a checkout:
6
+
7
+ ```sh
8
+ cd examples
9
+ RUBYLIB=../lib ruby load.rb
10
+ ../exe/tessella chart --kind bar langs.csv
11
+ ```
12
+
13
+ ## Ruby scripts
14
+
15
+ | Script | Shows | In |
16
+ |------------------|----------------------------------------------------|-------------------------------------|
17
+ | `calibration.rb` | a line chart with measured points marked on it | [charts](../doc/charts.md) |
18
+ | `load.rb` | a bar chart beside a table, framed and captioned | [composition](../doc/composition.md) |
19
+ | `datasheet.rb` | a register layout stacked over its timing diagram | [composition](../doc/composition.md) |
20
+ | `comment.rb` | an ASCII tree indented as a source comment | [composition](../doc/composition.md) |
21
+ | `fit.rb` | a table fitted to a width, with a multi-line cell | [table](../doc/table.md) |
22
+ | `floors.rb` | a table's per-column width floors, against one | [table](../doc/table.md) |
23
+ | `gradient.rb` | a `Raster` built in Ruby, drawn in three styles | [images](../doc/images.md) |
24
+ | `refusals.rb` | what the library refuses, and its messages | [library](../doc/library.md) |
25
+ | `cjk.rb` | a Unicode table and frame drawn for a CJK terminal | [targets](../doc/targets.md) |
26
+ | `lint.rb` | the lint's findings and rulers, from Ruby | [lint](../doc/lint.md) |
27
+
28
+ ## Shell scripts
29
+
30
+ POSIX sh, for FreeBSD and GNU/Linux alike; each finds its inputs
31
+ from any directory. `tessella` must be on `PATH`:
32
+ `PATH=../exe:$PATH sh report.sh` from a checkout.
33
+
34
+ | Script | Shows |
35
+ |--------------|----------------------------------------------------------|
36
+ | `trig.sh` | awk's output piped into a chart |
37
+ | `report.sh` | a chart and a table from one CSV, composed via temp files |
38
+ | `gallery.sh` | one picture in four styles, captioned, side by side |
39
+ | `comment.sh` | an ASCII tree as a C block comment, held to 72 columns |
40
+ | `rfc.sh` | an RFC-style figure: seq and bitfield, ASCII, indented |
41
+ | `status.sh` | exit 1 (bad data) told apart from exit 2 (bad call) |
42
+ | `disks.sh` | one meter per input line, titles aligned, framed |
43
+ | `gauges.sh` | upright meters side by side, one per input line |
44
+ | `dashboard.sh` | a chart, a table, meters, a sparkline in a framed grid |
45
+
46
+ All are shown with their output in
47
+ [doc/cli.md](../doc/cli.md#scripts).
48
+
49
+ ## Inputs
50
+
51
+ | File | For | Holds |
52
+ |----------------|-------------------------|-----------------------------------------------|
53
+ | `langs.csv` | `chart`, `table` | three labels and values, with a header |
54
+ | `trig.txt` | `chart` | `x sin cos`, 101 rows for x in 0..10 |
55
+ | `cpu.txt` | `chart --area` | 60 load samples between 10 and 90 |
56
+ | `temps.txt` | `chart --xdate` | a month of daily temperatures, ISO dates |
57
+ | `dose.txt` | `chart --yerr` | x, y and an error per point |
58
+ | `os.csv` | `chart --kind pie` | nine shares, for the legend under the disc |
59
+ | `cities.csv` | `--target cjk` | a CJK label and an accented one |
60
+ | `ohlc.txt` | `chart --kind candlestick` | a week of open/high/low/close prices |
61
+ | `growth.txt` | `chart --xscale` | x over four decades |
62
+ | `hosts.csv` | `chart --kind bar` | three series per label, for grouped/stacked |
63
+ | `week.txt` | `chart --kind heatmap` | a load per day and per three hours |
64
+ | `neg.csv` | `chart --kind bar` | negative, positive and zero values |
65
+ | `normal.txt` | `chart --kind histogram`| 200 roughly normal samples |
66
+ | `samples.txt` | `chart --kind box` | three columns of samples |
67
+ | `stem.txt` | `chart --kind stem` | one column of values |
68
+ | `ages.txt` | `chart --kind stem` | two columns, for the back-to-back form |
69
+ | `bad.csv` | `status.sh` | a CSV with a value that is not a number |
70
+ | `plot.txt` | `compose` | a bar chart, as `tessella chart` printed it |
71
+ | `disks.txt` | `disks.sh` | mount points and how full each is |
72
+ | `boxes.txt` | `compose fill` | two hand-drawn boxes joined by a line |
73
+ | `note.txt` | `compose` | two lines of text |
74
+ | `outline.txt` | `tree` | an indented outline with notes |
75
+ | `kinds.csv` | `table` | CSV with quoted fields holding commas |
76
+ | `sizes.tsv` | `table --tsv` | tab-separated rows |
77
+ | `ipv4.txt` | `bitfield` | the IPv4 header, up to the source address |
78
+ | `ethernet.txt` | `bitfield` | fields longer than a row |
79
+ | `icmp.txt` | `bitfield` | a 32-bit ICMP header |
80
+ | `spi.txt` | `wave` | an SPI transfer: clock, select, buses, an IRQ |
81
+ | `login.txt` | `seq` | a login exchange with a self call and a note |
82
+ | `broken.txt` | `lint` | a tab, a trailing blank, a wandering box side |
83
+ | `drift.txt` | `lint --border` | a frame in a custom set, one side moved |
84
+ | `table-drift.txt` | `lint --ruler` | a table whose verticals drift on one row |
85
+ | `notes.md` | `lint --fences` | Markdown: a table, prose, a flawed diagram |
86
+ | `notes-fixed.md` | `lint --target web` | `notes.md`'s diagram redrawn for the web |
87
+ | `figure.c` | `lint --forbid` | a diagram in a C comment, holding `*/` |
88
+ | `wide.txt` | `lint --no-wide` | a CJK label |
89
+ | `shapes.pgm` | `image --style petscii` | a ring and a wedge, black and white, 96 × 64 |
90
+ | `disc.pgm` | `image` | a 64 × 64 grey disc, bright at its centre |
91
+
92
+ `trig.txt`, `normal.txt`, `cpu.txt` and `temps.txt` were generated:
93
+
94
+ ```sh
95
+ ruby -e 'puts "x sin cos"; 0.step(10, 0.1) { puts [it.round(1),
96
+ Math.sin(it), Math.cos(it)].join(" ") }' > trig.txt
97
+ ruby -e 'srand 7; 200.times {
98
+ puts (Array.new(12) { rand }.sum - 6).round(3) }' > normal.txt
99
+ ruby -e '60.times { puts (50 + (40 * Math.sin(it / 6.0))).round }' > cpu.txt
100
+ ruby -e 't = Time.utc(2026, 10, 1); puts "date temp"; 30.times { |i|
101
+ puts "#{(t + (i * 86400)).strftime("%Y-%m-%d")} " \
102
+ "#{(12 + (6 * Math.sin(i / 4.0))).round(1)}" }' > temps.txt
103
+ ```
data/examples/ages.txt ADDED
@@ -0,0 +1,9 @@
1
+ men women
2
+ 12 18
3
+ 15 22
4
+ 21 25
5
+ 23 31
6
+ 27 33
7
+ 34 36
8
+ 38 41
9
+ 45 44
data/examples/bad.csv ADDED
@@ -0,0 +1,3 @@
1
+ lang,loc
2
+ ruby,12
3
+ c,many
@@ -0,0 +1,3 @@
1
+ ┌────┐ ┌────┐
2
+ │ │──│ ok │
3
+ └────┘ └────┘
@@ -0,0 +1,4 @@
1
+ a b
2
+ ┌──┐
3
+ │ab │
4
+ └──┘
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ # examples/calibration.rb: measured points marked on a fitted line.
4
+ require "tessella"
5
+
6
+ xs = (0..20).map { it * 0.5 }
7
+ fit = Tessella.line(xs, xs.map { (0.5 * it) + 1 },
8
+ name: "fit", width: 30, height: 6, title: "calibration",
9
+ canvas: :block)
10
+ fit.add([1, 3, 4.5, 7, 9], [1.4, 2.7, 3.0, 4.9, 5.4],
11
+ name: "measured", mark: "●")
12
+ puts fit
@@ -0,0 +1,4 @@
1
+ city,pop
2
+ 東京,14
3
+ Paris,2
4
+ Zürich,0.4
data/examples/cjk.rb ADDED
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ # examples/cjk.rb: a table and a frame asked for in Unicode under the
4
+ # cjk target. Their inner widths are rounded up to whole border
5
+ # glyphs, so they close in a CJK terminal; read in a Western one, as
6
+ # here, the boxes look a column wide here and there.
7
+ require "tessella"
8
+
9
+ Tessella::Target.with(:cjk) do
10
+ rows = Tessella::Table.parse(File.read("cities.csv"))
11
+ puts Tessella.table(rows, ascii: false)
12
+ puts Tessella.frame(File.read("note.txt"), ascii: false)
13
+ end
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ # examples/comment.rb: a tree, in ASCII, as a comment block for a
4
+ # source file kept to ASCII.
5
+ require "tessella"
6
+
7
+ outline = File.read("outline.txt")
8
+ puts Tessella.indent(Tessella.tree(outline, ascii: true),
9
+ prefix: "# ", ascii: true)
@@ -0,0 +1,13 @@
1
+ #!/bin/sh
2
+ # examples/comment.sh -- a tree as a C block comment, for a header
3
+ # kept to ASCII and 72 columns: --max-width fails the build (exit 1)
4
+ # rather than let the figure wrap.
5
+ # usage: sh comment.sh
6
+ set -eu
7
+
8
+ cd -- "$(dirname -- "$0")" || exit 1
9
+
10
+ printf '/*\n'
11
+ tessella tree --ascii --max-width 69 outline.txt |
12
+ tessella compose indent --ascii --prefix ' * ' -
13
+ printf ' */\n'
data/examples/cpu.txt ADDED
@@ -0,0 +1,60 @@
1
+ 50
2
+ 57
3
+ 63
4
+ 69
5
+ 75
6
+ 80
7
+ 84
8
+ 87
9
+ 89
10
+ 90
11
+ 90
12
+ 89
13
+ 86
14
+ 83
15
+ 79
16
+ 74
17
+ 68
18
+ 62
19
+ 56
20
+ 49
21
+ 42
22
+ 36
23
+ 30
24
+ 24
25
+ 20
26
+ 16
27
+ 13
28
+ 11
29
+ 10
30
+ 10
31
+ 12
32
+ 14
33
+ 17
34
+ 22
35
+ 27
36
+ 33
37
+ 39
38
+ 45
39
+ 52
40
+ 59
41
+ 65
42
+ 71
43
+ 76
44
+ 81
45
+ 85
46
+ 88
47
+ 89
48
+ 90
49
+ 90
50
+ 88
51
+ 85
52
+ 82
53
+ 78
54
+ 72
55
+ 66
56
+ 60
57
+ 54
58
+ 47
59
+ 40
60
+ 34
@@ -0,0 +1,25 @@
1
+ #!/bin/sh
2
+ # examples/dashboard.sh -- a dashboard: a chart, a table, meters and a
3
+ # sparkline, each drawn to a file and laid out two to a row by
4
+ # `compose grid`, then framed.
5
+ # usage: sh dashboard.sh
6
+ set -eu
7
+
8
+ cd -- "$(dirname -- "$0")" || exit 1
9
+
10
+ tmpdir=
11
+ cleanup() { [ -z "$tmpdir" ] || rm -rf -- "$tmpdir"; }
12
+ trap cleanup EXIT INT HUP TERM
13
+ tmpdir=$(mktemp -d "${TMPDIR:-/tmp}/dashboard.XXXXXX") || exit 1
14
+
15
+ tessella chart --kind bar --width 16 langs.csv > "$tmpdir/1"
16
+ tessella table --style rounded langs.csv > "$tmpdir/2"
17
+ {
18
+ tessella meter --width 12 --title cpu --title-width 4 0.62
19
+ tessella meter --width 12 --title disk --title-width 4 0.87
20
+ } > "$tmpdir/3"
21
+ tessella sparkline --width 20 < cpu.txt |
22
+ tessella compose caption --text 'cpu, last hour' - > "$tmpdir/4"
23
+ tessella compose grid --columns 2 --gap 3 --align middle \
24
+ "$tmpdir/1" "$tmpdir/2" "$tmpdir/3" "$tmpdir/4" |
25
+ tessella compose frame --title status -
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ # examples/datasheet.rb: a register layout over its timing, as a
4
+ # datasheet draws them, stacked under one rule.
5
+ require "tessella"
6
+
7
+ register = Tessella.bitfield([["MODE", 4], ["DIV", 8], ["EN", 4]],
8
+ word: 16)
9
+ timing = Tessella.wave(<<~WAVE, period: 4)
10
+ sclk: p.......
11
+ cs: 10.....1
12
+ mosi: x=.=.=.x | CMD ADDR DATA
13
+ WAVE
14
+ puts Tessella.stack(Tessella.caption(register, text: "CTRL (0x04)",
15
+ above: true),
16
+ timing, gap: 1, rule: "─")
data/examples/disc.pgm ADDED
Binary file
data/examples/disks.sh ADDED
@@ -0,0 +1,18 @@
1
+ #!/bin/sh
2
+ # examples/disks.sh -- one meter per line of "name fraction", their
3
+ # titles padded to one width so the bars line up, framed: a small
4
+ # status board.
5
+ # usage: sh disks.sh [file] (default disks.txt)
6
+ set -eu
7
+
8
+ cd -- "$(dirname -- "$0")" || exit 1
9
+ input=${1:-disks.txt}
10
+
11
+ while read -r name fraction; do
12
+ case $name in
13
+ '' | '#'*) continue ;;
14
+ esac
15
+ tessella meter --width 16 --title "$name" --title-width 6 \
16
+ -- "$fraction"
17
+ done < "$input" |
18
+ tessella compose frame --title disks -
@@ -0,0 +1,5 @@
1
+ # name fraction
2
+ / 0.62
3
+ /home 0.87
4
+ /var 0.31
5
+ /tmp 0.04
data/examples/dose.txt ADDED
@@ -0,0 +1,7 @@
1
+ dose effect err
2
+ 1 2.1 0.4
3
+ 2 3.0 0.5
4
+ 3 4.6 0.3
5
+ 4 5.2 0.8
6
+ 5 6.9 0.6
7
+ 6 7.4 1.0
@@ -0,0 +1,4 @@
1
+ *=================*
2
+ ! ruby is 12 kLOC !
3
+ ! c is the bulk !
4
+ *=================*
@@ -0,0 +1,3 @@
1
+ Destination MAC:48
2
+ Source MAC:48
3
+ EtherType:16
data/examples/figure.c ADDED
@@ -0,0 +1,5 @@
1
+ /*
2
+ * +--------+ */ +-------+
3
+ * | client |------->| server|
4
+ * +--------+ +-------+
5
+ */
data/examples/fit.rb ADDED
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ # examples/fit.rb: a table fitted to a width. At 40 columns only the
4
+ # widest column narrows and wraps; at 26 it has come down to the next
5
+ # widest, and both narrow together. A cell holding a newline keeps its
6
+ # own lines. Fitted to 20, the table is refused, naming the width it
7
+ # needs.
8
+ require "tessella"
9
+
10
+ rows = Tessella::Table.parse(File.read("kinds.csv"))
11
+ rows << ["box", "none", "quartiles\nand whiskers"]
12
+ [40, 26, 20].each do |width|
13
+ puts Tessella.table(rows, width: width)
14
+ rescue ArgumentError => e
15
+ puts e.message
16
+ end
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ # examples/floors.rb: one table fitted to 70 columns twice. With one
4
+ # floor for every column, the variable name is cut with the path; with
5
+ # a floor per column, the names keep their width and the path alone
6
+ # wraps. A list of the wrong length is refused.
7
+ require "tessella"
8
+
9
+ rows = [
10
+ %w[name variable path mode size age],
11
+ ["tado-pairing", "CLIMAT_PAIRING",
12
+ "/home/user/.config/climat-control/tado-pairing.json", "0600",
13
+ "1.2 kB", "3 d"]
14
+ ]
15
+ puts Tessella.table(rows, width: 70, min_width: 4)
16
+ puts Tessella.table(rows, width: 70, min_width: [12, 14, 12, 4, 6, 7])
17
+ begin
18
+ Tessella.table(rows, width: 70, min_width: [12, 14])
19
+ rescue ArgumentError => e
20
+ puts e.message
21
+ end
@@ -0,0 +1,20 @@
1
+ #!/bin/sh
2
+ # examples/gallery.sh -- one picture in several styles, each captioned
3
+ # with its name, then set side by side.
4
+ # usage: sh gallery.sh [image] (default disc.pgm)
5
+ set -eu
6
+
7
+ cd -- "$(dirname -- "$0")" || exit 1
8
+ image=${1:-disc.pgm}
9
+
10
+ tmpdir=
11
+ cleanup() { [ -z "$tmpdir" ] || rm -rf -- "$tmpdir"; }
12
+ trap cleanup EXIT INT HUP TERM
13
+ tmpdir=$(mktemp -d "${TMPDIR:-/tmp}/gallery.XXXXXX") || exit 1
14
+
15
+ for style in ramp half quadrant edges; do
16
+ tessella image --style "$style" --width 14 -- "$image" |
17
+ tessella compose caption --text "$style" - > "$tmpdir/$style"
18
+ done
19
+ tessella compose beside --gap 3 --align bottom \
20
+ "$tmpdir/ramp" "$tmpdir/half" "$tmpdir/quadrant" "$tmpdir/edges"
@@ -0,0 +1,31 @@
1
+ #!/bin/sh
2
+ # examples/gauges.sh -- upright meters side by side, one per line of
3
+ # "name fraction", bottoms aligned: a row of gauges.
4
+ # usage: sh gauges.sh [file] (default disks.txt)
5
+ set -eu
6
+
7
+ cd -- "$(dirname -- "$0")" || exit 1
8
+ input=${1:-disks.txt}
9
+
10
+ tmpdir=
11
+ cleanup() { [ -z "$tmpdir" ] || rm -rf -- "$tmpdir"; }
12
+ trap cleanup EXIT INT HUP TERM
13
+ tmpdir=$(mktemp -d "${TMPDIR:-/tmp}/gauges.XXXXXX") || exit 1
14
+
15
+ n=0
16
+ while read -r name fraction; do
17
+ case $name in
18
+ '' | '#'*) continue ;;
19
+ esac
20
+ n=$((n + 1))
21
+ tessella meter --orientation vertical --height 6 --title "$name" \
22
+ -- "$fraction" > "$tmpdir/$n"
23
+ done < "$input"
24
+
25
+ set --
26
+ i=1
27
+ while [ "$i" -le "$n" ]; do
28
+ set -- "$@" "$tmpdir/$i"
29
+ i=$((i + 1))
30
+ done
31
+ tessella compose beside --gap 3 --align bottom "$@"