Did thomeone thay "th1 in pikthr"?
(1.1) By Stephan Beal (stephan) on 2020-09-13 18:45:54 edited from 1.0 [link] [source]
This is still very much a work in progress, but...
$ cat th1.pikchr
<th1>
set date [date]
</th1>
box "Hi, date=$<date>"
text "Hi, world"
<th1>
puts {line}
</th1>
$ ./fossil pikchr -th th1.pikchr
<svg class="pikchr" viewBox="0 0 343.44 76.32">
<path d="M109,74L217,74L217,2L109,2Z" style="fill:none;stroke-width:2.16;stroke:rgb(0,0,0);" />
<text x="163" y="38" text-anchor="middle" fill="rgb(0,0,0)" dominant-baseline="central">Hi, date=2020-09-13 16:39:41</text>
<text x="217" y="38" text-anchor="middle" fill="rgb(0,0,0)" dominant-baseline="central">Hi, world</text>
<path d="M269,38L341,38" style="fill:none;stroke-width:2.16;stroke:rgb(0,0,0);" />
</svg>
The code: https://fossil-scm.org/fossil/timeline?r=pikchr-th
There are several th1 integration issues left to solve:
- Output redirection. TH1 has historically only handled stdout and CGI as output channels, but we need output captured to a blob.
- HTML escaping: TH1 does this even where pikchr does not want it, like outputing:
puts "hi"
as:
&quot;hi&quot;
Still trying to figure out if we can bypass such assumptions without too much rewiring of th1.
(2) By Warren Young (wyoung) on 2020-09-13 16:54:42 in reply to 1.0 [link] [source]
Did someone way "th1 in pikchr"?
Yeah, me. :)
I skimmed the code, and it diverges from my concept wildly. You're creating a single command that accepts Pikchr strings, but I was thinking you'd hoist all Pikchr verbs up as TH1 commands so you could interlace TH1 and PIC code, as in my initial motivating example, to add looping to Pikchr, filling a hole in it relative to PIC.
I believe it was Sean who posted the example of a network switch. It would be nice to have a 2-level nested loop, 12 iterations for the ports on each row of a 24-port switch, 2 for the rows. This should yield a Tcl list of references to PIC objects that you could then manipulate, such as to add per-port glossy pictures with circles and arrows and a paragraph inside each one.
we need output captured to a blob.
Why not return a blob object? Tcl isn't limited to C-style POD objects. It isn't even limited to the return of a single object: you can return a complex nested data structure, if you want.
(3) By Stephan Beal (stephan) on 2020-09-13 17:12:55 in reply to 2 [link] [source]
I skimmed the code, and it diverges from my concept wildly. You're creating a single command that accepts Pikchr strings, but I was thinking you'd hoist all Pikchr verbs up as TH1 commands so you could interlace TH1 and PIC code,...
Yeah, that's a different thing: pikchr's API would first need to support plugging in new bindings, but it doesn't. The current API is a single function which takes a string and returns a string. For custom bindings it would instead require a context object which could be configured before running the processor.
If/when pikchr can define macros (presumably as functions), that capability would likely come "for free", but would still require exposing a context object to the client so they could plug in their bits.
as in my initial motivating example, to add looping to Pikchr, filling a hole in it relative to PIC.
That's actually what prompted me to try this: a semi-long pikchr which would have been greatly simplified by looping, and figured that could be done by generating the pikchr code via a th1 loop.
Whether or not this will amount to anything is still up in the air. i'm currently fighting with the crossover for escaping things it shouldn't be escaping, making this binding of very little use.
(4) By Stephan Beal (stephan) on 2020-09-13 18:34:41 in reply to 1.0 [link] [source]
Baby steps in pikchr-with-embedded th1:
[pi@pi4b8:~/fossil/fossil]$ cat th1.pikchr
# Draw nodes of a hexagon...
D: dot rad 150% color red
<th1>
set w 0.5
set h 0
for {} {$h <= 360} {set h [expr {$h + 60}]} {
puts "dot at $w heading $h from D.c\n"
}
</th1>
[pi@pi4b8:~/fossil/fossil]$ ./fossil pikchr -th th1.pikchr -th-nopic
# Draw nodes of a hexagon...
D: dot rad 150% color red
dot at 0.5 heading 0 from D.c
dot at 0.5 heading 60 from D.c
dot at 0.5 heading 120 from D.c
dot at 0.5 heading 180 from D.c
dot at 0.5 heading 240 from D.c
dot at 0.5 heading 300 from D.c
dot at 0.5 heading 360 from D.c
[pi@pi4b8:~/fossil/fossil]$ ./fossil pikchr -th th1.pikchr
<svg class="pikchr" viewBox="0 0 141.988 161.28">
<circle cx="70" cy="80" r="3.24"style="fill:rgb(255,0,0);stroke-width:2.16;stroke:rgb(255,0,0);" />
<circle cx="70" cy="8" r="2.16"style="fill:rgb(0,0,0);stroke-width:2.16;stroke:rgb(0,0,0);" />
<circle cx="133" cy="44" r="2.16"style="fill:rgb(0,0,0);stroke-width:2.16;stroke:rgb(0,0,0);" />
<circle cx="133" cy="116" r="2.16"style="fill:rgb(0,0,0);stroke-width:2.16;stroke:rgb(0,0,0);" />
<circle cx="70" cy="152" r="2.16"style="fill:rgb(0,0,0);stroke-width:2.16;stroke:rgb(0,0,0);" />
<circle cx="8" cy="116" r="2.16"style="fill:rgb(0,0,0);stroke-width:2.16;stroke:rgb(0,0,0);" />
<circle cx="8" cy="44" r="2.16"style="fill:rgb(0,0,0);stroke-width:2.16;stroke:rgb(0,0,0);" />
<circle cx="70" cy="8" r="2.16"style="fill:rgb(0,0,0);stroke-width:2.16;stroke:rgb(0,0,0);" />
</svg>
And to demonstrate that the above-generated pikchr is valid:
# Draw nodes of a hexagon... D: dot rad 150% color red dot at 0.5 heading 0 from D.c dot at 0.5 heading 60 from D.c dot at 0.5 heading 120 from D.c dot at 0.5 heading 180 from D.c dot at 0.5 heading 240 from D.c dot at 0.5 heading 300 from D.c dot at 0.5 heading 360 from D.c→ /pikchrshow
(5) By Stephan Beal (stephan) on 2020-09-13 21:50:26 in reply to 1.0 [link] [source]
Baby steps...
The new captureTh1
TH1 command runs its argument as TH1 code and redirects all output it generates to a string, which becomes the result of the captureTh1
call:
$ cat bogo.pikchr
# Draw nodes of a hexagon...
D: dot rad 150% color red
<th1>set bogoCap [captureTh1 {
set w 0.5
set h 0
for {} {$h <= 360} {set h [expr {$h + 60}]} {
puts "dot at $w heading $h from D.c\n"
}
}]
</th1>
text "bogoCap" at D +0,+0.2
$bogoCap
Compare the ordering of those last 2 lines to the evaluated output of that script:
$ ./fossil pikchr -th bogo.pikchr -th-nosvg
# Draw nodes of a hexagon...
D: dot rad 150% color red
text "bogoCap" at D +0,+0.2
dot at 0.5 heading 0 from D.c
dot at 0.5 heading 60 from D.c
dot at 0.5 heading 120 from D.c
dot at 0.5 heading 180 from D.c
dot at 0.5 heading 240 from D.c
dot at 0.5 heading 300 from D.c
dot at 0.5 heading 360 from D.c
(That extra blank line is a side-effect of the newline after the </th1>
tag being part of the containing script, not part of the TH1 script.)
That enables reusing static parts of a pikchr. e.g. if we restructure the script slightly:
<th1>set bogoCap [captureTh1 {
puts "D: dot rad 150% color red\n"
set w 0.5
set h 0
for {} {$h <= 360} {set h [expr {$h + 60}]} {
puts "dot at $w heading $h from D.c\n"
}
puts "move 1 from D\n"
}]
</th1>
$bogoCap
$bogoCap
$bogoCap
Note the re-use of the captured output in the bottom 3 lines. Now process it, leaving us with:
D: dot rad 150% color red dot at 0.5 heading 0 from D.c dot at 0.5 heading 60 from D.c dot at 0.5 heading 120 from D.c dot at 0.5 heading 180 from D.c dot at 0.5 heading 240 from D.c dot at 0.5 heading 300 from D.c dot at 0.5 heading 360 from D.c move 1 from D D: dot rad 150% color red dot at 0.5 heading 0 from D.c dot at 0.5 heading 60 from D.c dot at 0.5 heading 120 from D.c dot at 0.5 heading 180 from D.c dot at 0.5 heading 240 from D.c dot at 0.5 heading 300 from D.c dot at 0.5 heading 360 from D.c move 1 from D D: dot rad 150% color red dot at 0.5 heading 0 from D.c dot at 0.5 heading 60 from D.c dot at 0.5 heading 120 from D.c dot at 0.5 heading 180 from D.c dot at 0.5 heading 240 from D.c dot at 0.5 heading 300 from D.c dot at 0.5 heading 360 from D.c move 1 from D→ /pikchrshow
(6) By Stephan Beal (stephan) on 2020-09-13 23:10:58 in reply to 1.1 [source]
th1's access to the db is extremely limited, but it's enough to allow us to do silly stuff like...
$ cat sql.pikchr
<th1>
query {
select substr(b.uuid,1,6) bu from event e join blob b on e.objid=b.rid order by e.mtime desc limit 5
} {
puts "box \"$bu\"; arrow 0.25;\n"
}
</th1>
box "..."
$ ./fossil pikchr -th sql.pikchr -th-nosvg
box "e7dcfc"; arrow 0.25; box "c39914"; arrow 0.25; box "b95861"; arrow 0.25; box "a5eaa0"; arrow 0.25; box "..."→ /pikchrshow
Certainly some enterprising users can figure out interesting uses for that, especially if we can get this integrated sanely with th1Docs. Inherent conflicts in such an effort include th1's default HTML-encoding of things like quotes. The pikchr CLI command explicitly disables that via a new Th1Interp flag, but th1Docs won't be able to. We'll need a new th1 command which enables/disables that feature on demand.