the ugly ocaml monstrosity powering my site oppi.li
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

new post: tablespoon

+576 -19
+17 -17
docs/index.html
··· 39 39 <tr> 40 40 <td class=table-post> 41 41 <div class="date"> 42 + 01/08 — 2024 43 + </div> 44 + <a href="/posts/introducing_tablespoon" class="post-link"> 45 + <span class="post-link">Introducing Tablespoon</span> 46 + </a> 47 + </td> 48 + <td class=table-stats> 49 + <span class="stats-number"> 50 + 4.5 51 + </span> 52 + <span class=stats-unit>min</span> 53 + </td> 54 + </tr> 55 + 56 + <tr> 57 + <td class=table-post> 58 + <div class="date"> 42 59 29/05 — 2024 43 60 </div> 44 61 <a href="/posts/snip_snap" class="post-link"> ··· 65 82 <td class=table-stats> 66 83 <span class="stats-number"> 67 84 8.9 68 - </span> 69 - <span class=stats-unit>min</span> 70 - </td> 71 - </tr> 72 - 73 - <tr> 74 - <td class=table-post> 75 - <div class="date"> 76 - 03/09 — 2022 77 - </div> 78 - <a href="/posts/curing_a_case_of_git-UX" class="post-link"> 79 - <span class="post-link">Curing A Case Of Git-UX</span> 80 - </a> 81 - </td> 82 - <td class=table-stats> 83 - <span class="stats-number"> 84 - 9.6 85 85 </span> 86 86 <span class=stats-unit>min</span> 87 87 </td>
+145
docs/index.xml
··· 12 12 <language>en-us</language> 13 13 <copyright>Creative Commons BY-NC-SA 4.0</copyright> 14 14 <item> 15 + <title>Introducing Tablespoon</title> 16 + <description>&lt;p&gt;&lt;a href="https://git.peppe.rs/languages/tbsp"&gt;tbsp&lt;/a&gt; (tree-based 17 + source-processing language) is an awk-like language that operates on 18 + tree-sitter syntax trees. To motivate the need for such a program, we 19 + could begin by writing a markdown-to-html converter using 20 + &lt;code&gt;tbsp&lt;/code&gt; and &lt;a 21 + href="https://github.com/tree-sitter-grammars/tree-sitter-markdown"&gt;tree-sitter-md&lt;/a&gt;. 22 + We need some markdown to begin with:&lt;/p&gt; 23 + &lt;pre&gt;&lt;code&gt;# 1 heading 24 + 25 + content of first paragraph 26 + 27 + ## 1.1 heading 28 + 29 + content of nested paragraph&lt;/code&gt;&lt;/pre&gt; 30 + &lt;p&gt;For future reference, this markdown is parsed like so by 31 + tree-sitter-md (visualization generated by &lt;a 32 + href="https://git.peppe.rs/cli/tree-viz"&gt;tree-viz&lt;/a&gt;):&lt;/p&gt; 33 + &lt;pre&gt;&lt;code&gt;document 34 + | section 35 + | | atx_heading 36 + | | | atx_h1_marker &amp;quot;#&amp;quot; 37 + | | | heading_content inline &amp;quot;1 heading&amp;quot; 38 + | | paragraph 39 + | | | inline &amp;quot;content of first paragraph&amp;quot; 40 + | | section 41 + | | | atx_heading 42 + | | | | atx_h2_marker &amp;quot;##&amp;quot; 43 + | | | | heading_content inline &amp;quot;1.1 heading&amp;quot; 44 + | | | paragraph 45 + | | | | inline &amp;quot;content of nested paragraph&amp;quot;&lt;/code&gt;&lt;/pre&gt; 46 + &lt;p&gt;Onto the converter itself. Every &lt;code&gt;tbsp&lt;/code&gt; program is written 47 + as a collection of stanzas. Typically, we start with a stanza like 48 + so:&lt;/p&gt; 49 + &lt;pre&gt;&lt;code&gt;BEGIN { 50 + int depth = 0; 51 + 52 + print(&amp;quot;&amp;lt;html&amp;gt;\n&amp;quot;); 53 + print(&amp;quot;&amp;lt;body&amp;gt;\n&amp;quot;); 54 + }&lt;/code&gt;&lt;/pre&gt; 55 + &lt;p&gt;The stanza begins with a “pattern”, in this case, &lt;code&gt;BEGIN&lt;/code&gt;, 56 + and is followed a block of code. This block specifically, is executed 57 + right at the beginning, before traversing the parse tree. In this 58 + stanza, we set a “depth” variable to keep track of nesting of markdown 59 + headers, and begin our html document by printing the 60 + &lt;code&gt;&amp;lt;html&amp;gt;&lt;/code&gt; and &lt;code&gt;&amp;lt;body&amp;gt;&lt;/code&gt; tags.&lt;/p&gt; 61 + &lt;p&gt;We can follow this stanza with an &lt;code&gt;END&lt;/code&gt; stanza, that is 62 + executed after the traversal:&lt;/p&gt; 63 + &lt;pre&gt;&lt;code&gt;END { 64 + print(&amp;quot;&amp;lt;/body&amp;gt;\n&amp;quot;); 65 + print(&amp;quot;&amp;lt;/html&amp;gt;\n&amp;quot;); 66 + }&lt;/code&gt;&lt;/pre&gt; 67 + &lt;p&gt;In this stanza, we close off the tags we opened at the start of the 68 + document. We can move onto the interesting bits of the conversion 69 + now:&lt;/p&gt; 70 + &lt;pre&gt;&lt;code&gt;enter section { 71 + depth += 1; 72 + } 73 + leave section { 74 + depth -= 1; 75 + }&lt;/code&gt;&lt;/pre&gt; 76 + &lt;p&gt;The above stanzas begin with &lt;code&gt;enter&lt;/code&gt; and 77 + &lt;code&gt;leave&lt;/code&gt; clauses, followed by the name of a tree-sitter node 78 + kind: &lt;code&gt;section&lt;/code&gt;. The &lt;code&gt;section&lt;/code&gt; identifier is 79 + visible in the tree-visualization above, it encompasses a 80 + markdown-section, and is created for every markdown header. To 81 + understand how &lt;code&gt;tbsp&lt;/code&gt; executes above stanzas:&lt;/p&gt; 82 + &lt;pre&gt;&lt;code&gt;document ... depth = 0 83 + | section &amp;lt;-------- enter section (1) ... depth = 1 84 + | | atx_heading 85 + | | | inline 86 + | | paragraph 87 + | | | inline 88 + | | section &amp;lt;----- enter section (2) ... depth = 2 89 + | | | atx_heading 90 + | | | | inline 91 + | | | paragraph 92 + | | | | inline 93 + | | | &amp;lt;----------- leave section (2) ... depth = 1 94 + | | &amp;lt;-------------- leave section (1) ... depth = 0 &lt;/code&gt;&lt;/pre&gt; 95 + &lt;p&gt;The following stanzas should be self-explanatory now:&lt;/p&gt; 96 + &lt;pre&gt;&lt;code&gt;enter atx_heading { 97 + print(&amp;quot;&amp;lt;h&amp;quot;); 98 + print(depth); 99 + print(&amp;quot;&amp;gt;&amp;quot;); 100 + } 101 + leave atx_heading { 102 + print(&amp;quot;&amp;lt;/h&amp;quot;); 103 + print(depth); 104 + print(&amp;quot;&amp;gt;\n&amp;quot;); 105 + } 106 + 107 + enter inline { 108 + print(text(node)); 109 + }&lt;/code&gt;&lt;/pre&gt; 110 + &lt;p&gt;But an explanation is included nonetheless:&lt;/p&gt; 111 + &lt;pre&gt;&lt;code&gt;document ... depth = 0 112 + | section &amp;lt;-------- enter section (1) ... depth = 1 113 + | | atx_heading &amp;lt;- enter atx_heading ... print &amp;quot;&amp;lt;h1&amp;gt;&amp;quot; 114 + | | | inline &amp;lt;--- enter inline ... print .. 115 + | | | &amp;lt;----------- leave atx_heading ... print &amp;quot;&amp;lt;/h1&amp;gt;&amp;quot; 116 + | | paragraph 117 + | | | inline &amp;lt;--- enter inline ... print .. 118 + | | section &amp;lt;----- enter section (2) ... depth = 2 119 + | | | atx_heading enter atx_heading ... print &amp;quot;&amp;lt;h2&amp;gt;&amp;quot; 120 + | | | | inline &amp;lt;- enter inline ... print .. 121 + | | | | &amp;lt;-------- leave atx_heading ... print &amp;quot;&amp;lt;/h2&amp;gt;&amp;quot; 122 + | | | paragraph 123 + | | | | inline &amp;lt;- enter inline ... print .. 124 + | | | &amp;lt;----------- leave section (2) ... depth = 1 125 + | | &amp;lt;-------------- leave section (1) ... depth = 0 &lt;/code&gt;&lt;/pre&gt; 126 + &lt;p&gt;The &lt;a 127 + href="https://git.peppe.rs/languages/tbsp/tree/examples"&gt;examples&lt;/a&gt; 128 + directory contains a complete markdown-to-html converter, along with a 129 + few other motivating examples.&lt;/p&gt; 130 + &lt;h3 id="usage"&gt;Usage&lt;/h3&gt; 131 + &lt;p&gt;The &lt;code&gt;tbsp&lt;/code&gt; evaluator is written in rust, use cargo to 132 + build and run:&lt;/p&gt; 133 + &lt;pre&gt;&lt;code&gt;cargo build --release 134 + ./target/release/tbsp --help&lt;/code&gt;&lt;/pre&gt; 135 + &lt;p&gt;&lt;code&gt;tbsp&lt;/code&gt; requires three inputs:&lt;/p&gt; 136 + &lt;ul&gt; 137 + &lt;li&gt;a &lt;code&gt;tbsp&lt;/code&gt; program, referred to as “program file”&lt;/li&gt; 138 + &lt;li&gt;a language&lt;/li&gt; 139 + &lt;li&gt;an input file or some input text at stdin&lt;/li&gt; 140 + &lt;/ul&gt; 141 + &lt;p&gt;You can run the interpreter like so (this program prints an overview 142 + of a rust file):&lt;/p&gt; 143 + &lt;pre&gt;&lt;code&gt;$ ./target/release/tbsp \ 144 + -f./examples/code-overview/overview.tbsp \ 145 + -l rust \ 146 + src/main.rs 147 + module 148 + └╴struct Cli 149 + └╴trait Cli 150 + └╴fn program 151 + └╴fn language 152 + └╴fn file 153 + └╴fn try_consume_stdin 154 + └╴fn main&lt;/code&gt;&lt;/pre&gt;</description> 155 + <link>https://peppe.rs/posts/introducing_tablespoon/</link> 156 + <pubDate>Thu, 01 Aug 2024 19:18:00 +0000</pubDate> 157 + <guid>https://peppe.rs/posts/introducing_tablespoon/</guid> 158 + </item> 159 + <item> 15 160 <title>Snip Snap</title> 16 161 <description>&lt;p&gt;I regularly switch between exactly two things while working, a 17 162 “current” and an “alternate” item; a lot of tools I use seem to support
+17
docs/posts/index.html
··· 27 27 <tr> 28 28 <td class=table-post> 29 29 <div class="date"> 30 + 01/08 — 2024 31 + </div> 32 + <a href="/posts/introducing_tablespoon" class="post-link"> 33 + <span class="post-link">Introducing Tablespoon</span> 34 + </a> 35 + </td> 36 + <td class=table-stats> 37 + <span class="stats-number"> 38 + 4.5 39 + </span> 40 + <span class=stats-unit>min</span> 41 + </td> 42 + </tr> 43 + 44 + <tr> 45 + <td class=table-post> 46 + <div class="date"> 30 47 29/05 — 2024 31 48 </div> 32 49 <a href="/posts/snip_snap" class="post-link">
+211
docs/posts/introducing_tablespoon/index.html
··· 1 + <!DOCTYPE html> 2 + <html lang="en"> 3 + <head> 4 + <link rel="stylesheet" href="/style.css"> 5 + <link rel="stylesheet" href="/syntax.css"> 6 + <meta charset="UTF-8"> 7 + <meta name="viewport" content="initial-scale=1"> 8 + <meta content="#ffffff" name="theme-color"> 9 + <meta name="HandheldFriendly" content="true"> 10 + <meta property="og:title" content="Introducing Tablespoon"> 11 + <meta property="og:type" content="website"> 12 + <meta property="og:description" content="a static site {for, by, about} me "> 13 + <meta property="og:url" content="https://peppe.rs"> 14 + <link rel="icon" type="image/x-icon" href="/favicon.png"> 15 + <title>Introducing Tablespoon · peppe.rs</title> 16 + <body> 17 + <div class="posts"> 18 + <div class="post"> 19 + <a href="/" class="post-end-link">Home</a> 20 + <span>/</span> 21 + <a href="/posts" class="post-end-link">Posts</a> 22 + <span>/</span> 23 + <a class="post-end-link">Introducing Tablespoon</a> 24 + <a class="stats post-end-link" href="https://git.peppe.rs/web/site/plain/posts/introducing_tablespoon.md 25 + ">View Raw</a> 26 + <div class="separator"></div> 27 + <div class="date"> 28 + 01/08 — 2024 29 + <div class="stats"> 30 + <span class="stats-number"> 31 + 72.33 32 + </span> 33 + <span class="stats-unit">cm</span> 34 + &nbsp 35 + <span class="stats-number"> 36 + 4.5 37 + </span> 38 + <span class="stats-unit">min</span> 39 + </div> 40 + </div> 41 + <h1> 42 + Introducing Tablespoon 43 + </h1> 44 + <div class="post-text"> 45 + <p><a href="https://git.peppe.rs/languages/tbsp">tbsp</a> (tree-based 46 + source-processing language) is an awk-like language that operates on 47 + tree-sitter syntax trees. To motivate the need for such a program, we 48 + could begin by writing a markdown-to-html converter using 49 + <code>tbsp</code> and <a 50 + href="https://github.com/tree-sitter-grammars/tree-sitter-markdown">tree-sitter-md</a>. 51 + We need some markdown to begin with:</p> 52 + <pre><code># 1 heading 53 + 54 + content of first paragraph 55 + 56 + ## 1.1 heading 57 + 58 + content of nested paragraph</code></pre> 59 + <p>For future reference, this markdown is parsed like so by 60 + tree-sitter-md (visualization generated by <a 61 + href="https://git.peppe.rs/cli/tree-viz">tree-viz</a>):</p> 62 + <pre><code>document 63 + | section 64 + | | atx_heading 65 + | | | atx_h1_marker &quot;#&quot; 66 + | | | heading_content inline &quot;1 heading&quot; 67 + | | paragraph 68 + | | | inline &quot;content of first paragraph&quot; 69 + | | section 70 + | | | atx_heading 71 + | | | | atx_h2_marker &quot;##&quot; 72 + | | | | heading_content inline &quot;1.1 heading&quot; 73 + | | | paragraph 74 + | | | | inline &quot;content of nested paragraph&quot;</code></pre> 75 + <p>Onto the converter itself. Every <code>tbsp</code> program is written 76 + as a collection of stanzas. Typically, we start with a stanza like 77 + so:</p> 78 + <pre><code>BEGIN { 79 + int depth = 0; 80 + 81 + print(&quot;&lt;html&gt;\n&quot;); 82 + print(&quot;&lt;body&gt;\n&quot;); 83 + }</code></pre> 84 + <p>The stanza begins with a “pattern”, in this case, <code>BEGIN</code>, 85 + and is followed a block of code. This block specifically, is executed 86 + right at the beginning, before traversing the parse tree. In this 87 + stanza, we set a “depth” variable to keep track of nesting of markdown 88 + headers, and begin our html document by printing the 89 + <code>&lt;html&gt;</code> and <code>&lt;body&gt;</code> tags.</p> 90 + <p>We can follow this stanza with an <code>END</code> stanza, that is 91 + executed after the traversal:</p> 92 + <pre><code>END { 93 + print(&quot;&lt;/body&gt;\n&quot;); 94 + print(&quot;&lt;/html&gt;\n&quot;); 95 + }</code></pre> 96 + <p>In this stanza, we close off the tags we opened at the start of the 97 + document. We can move onto the interesting bits of the conversion 98 + now:</p> 99 + <pre><code>enter section { 100 + depth += 1; 101 + } 102 + leave section { 103 + depth -= 1; 104 + }</code></pre> 105 + <p>The above stanzas begin with <code>enter</code> and 106 + <code>leave</code> clauses, followed by the name of a tree-sitter node 107 + kind: <code>section</code>. The <code>section</code> identifier is 108 + visible in the tree-visualization above, it encompasses a 109 + markdown-section, and is created for every markdown header. To 110 + understand how <code>tbsp</code> executes above stanzas:</p> 111 + <pre><code>document ... depth = 0 112 + | section &lt;-------- enter section (1) ... depth = 1 113 + | | atx_heading 114 + | | | inline 115 + | | paragraph 116 + | | | inline 117 + | | section &lt;----- enter section (2) ... depth = 2 118 + | | | atx_heading 119 + | | | | inline 120 + | | | paragraph 121 + | | | | inline 122 + | | | &lt;----------- leave section (2) ... depth = 1 123 + | | &lt;-------------- leave section (1) ... depth = 0 </code></pre> 124 + <p>The following stanzas should be self-explanatory now:</p> 125 + <pre><code>enter atx_heading { 126 + print(&quot;&lt;h&quot;); 127 + print(depth); 128 + print(&quot;&gt;&quot;); 129 + } 130 + leave atx_heading { 131 + print(&quot;&lt;/h&quot;); 132 + print(depth); 133 + print(&quot;&gt;\n&quot;); 134 + } 135 + 136 + enter inline { 137 + print(text(node)); 138 + }</code></pre> 139 + <p>But an explanation is included nonetheless:</p> 140 + <pre><code>document ... depth = 0 141 + | section &lt;-------- enter section (1) ... depth = 1 142 + | | atx_heading &lt;- enter atx_heading ... print &quot;&lt;h1&gt;&quot; 143 + | | | inline &lt;--- enter inline ... print .. 144 + | | | &lt;----------- leave atx_heading ... print &quot;&lt;/h1&gt;&quot; 145 + | | paragraph 146 + | | | inline &lt;--- enter inline ... print .. 147 + | | section &lt;----- enter section (2) ... depth = 2 148 + | | | atx_heading enter atx_heading ... print &quot;&lt;h2&gt;&quot; 149 + | | | | inline &lt;- enter inline ... print .. 150 + | | | | &lt;-------- leave atx_heading ... print &quot;&lt;/h2&gt;&quot; 151 + | | | paragraph 152 + | | | | inline &lt;- enter inline ... print .. 153 + | | | &lt;----------- leave section (2) ... depth = 1 154 + | | &lt;-------------- leave section (1) ... depth = 0 </code></pre> 155 + <p>The <a 156 + href="https://git.peppe.rs/languages/tbsp/tree/examples">examples</a> 157 + directory contains a complete markdown-to-html converter, along with a 158 + few other motivating examples.</p> 159 + <h3 id="usage">Usage</h3> 160 + <p>The <code>tbsp</code> evaluator is written in rust, use cargo to 161 + build and run:</p> 162 + <pre><code>cargo build --release 163 + ./target/release/tbsp --help</code></pre> 164 + <p><code>tbsp</code> requires three inputs:</p> 165 + <ul> 166 + <li>a <code>tbsp</code> program, referred to as “program file”</li> 167 + <li>a language</li> 168 + <li>an input file or some input text at stdin</li> 169 + </ul> 170 + <p>You can run the interpreter like so (this program prints an overview 171 + of a rust file):</p> 172 + <pre><code>$ ./target/release/tbsp \ 173 + -f./examples/code-overview/overview.tbsp \ 174 + -l rust \ 175 + src/main.rs 176 + module 177 + └╴struct Cli 178 + └╴trait Cli 179 + └╴fn program 180 + └╴fn language 181 + └╴fn file 182 + └╴fn try_consume_stdin 183 + └╴fn main</code></pre> 184 + 185 + </div> 186 + 187 + <div class="intro"> 188 + Hi. 189 + <div class="hot-links"> 190 + <a href="/index.xml" class="feed-button">Subscribe</a> 191 + </div> 192 + <p>I'm Akshay, programmer and pixel-artist. 193 + I write <a href="https://git.peppe.rs">open-source stuff</a>. 194 + I also design fonts: 195 + <a href="https://git.peppe.rs/fonts/scientifica/about">scientifica</a>, 196 + <a href="https://git.peppe.rs/fonts/curie/about">curie</a>. 197 + </p> 198 + <p>Reach out at oppili@irc.rizon.net.</p> 199 + </div> 200 + 201 + <a href="/" class="post-end-link">Home</a> 202 + <span>/</span> 203 + <a href="/posts" class="post-end-link">Posts</a> 204 + <span>/</span> 205 + <a class="post-end-link">Introducing Tablespoon</a> 206 + <a class="stats post-end-link" href="https://git.peppe.rs/web/site/plain/posts/introducing_tablespoon.md 207 + ">View Raw</a> 208 + </div> 209 + </div> 210 + </body> 211 + </html>
+5 -2
docs/style.css
··· 52 52 } 53 53 } 54 54 55 - body { font-family: 'Inter', sans-serif; } 55 + body { 56 + font-family: 'Inter', sans-serif; 57 + font-feature-settings: 'liga' 1, 'calt' 1; /* fix for Chrome */ 58 + } 56 59 @supports (font-variation-settings: normal) { 57 60 body { 58 - font-family: 'Inter var', sans-serif; 61 + font-family: 'InterVariable', sans-serif; 59 62 font-feature-settings: 'ss01' 1, 'kern' 1, 'liga' 1, 'cv05' 1, 'tnum' 1; 60 63 } 61 64 }
+181
posts/introducing_tablespoon.md
··· 1 + [tbsp](https://git.peppe.rs/languages/tbsp) (tree-based 2 + source-processing language) is an awk-like language that 3 + operates on tree-sitter syntax trees. To motivate the need 4 + for such a program, we could begin by writing a 5 + markdown-to-html converter using `tbsp` and 6 + [tree-sitter-md](https://github.com/tree-sitter-grammars/tree-sitter-markdown). 7 + We need some markdown to begin with: 8 + 9 + 10 + # 1 heading 11 + 12 + content of first paragraph 13 + 14 + ## 1.1 heading 15 + 16 + content of nested paragraph 17 + 18 + 19 + For future reference, this markdown is parsed like so by 20 + tree-sitter-md (visualization generated by 21 + [tree-viz](https://git.peppe.rs/cli/tree-viz)): 22 + 23 + 24 + document 25 + | section 26 + | | atx_heading 27 + | | | atx_h1_marker "#" 28 + | | | heading_content inline "1 heading" 29 + | | paragraph 30 + | | | inline "content of first paragraph" 31 + | | section 32 + | | | atx_heading 33 + | | | | atx_h2_marker "##" 34 + | | | | heading_content inline "1.1 heading" 35 + | | | paragraph 36 + | | | | inline "content of nested paragraph" 37 + 38 + 39 + Onto the converter itself. Every `tbsp` program is written as 40 + a collection of stanzas. Typically, we start with a stanza 41 + like so: 42 + 43 + 44 + BEGIN { 45 + int depth = 0; 46 + 47 + print("<html>\n"); 48 + print("<body>\n"); 49 + } 50 + 51 + 52 + The stanza begins with a "pattern", in this case, `BEGIN`, 53 + and is followed a block of code. This block specifically, is 54 + executed right at the beginning, before traversing the parse 55 + tree. In this stanza, we set a "depth" variable to keep 56 + track of nesting of markdown headers, and begin our html 57 + document by printing the `<html>` and `<body>` tags. 58 + 59 + We can follow this stanza with an `END` stanza, that is 60 + executed after the traversal: 61 + 62 + 63 + END { 64 + print("</body>\n"); 65 + print("</html>\n"); 66 + } 67 + 68 + 69 + In this stanza, we close off the tags we opened at the start 70 + of the document. We can move onto the interesting bits of 71 + the conversion now: 72 + 73 + 74 + enter section { 75 + depth += 1; 76 + } 77 + leave section { 78 + depth -= 1; 79 + } 80 + 81 + 82 + The above stanzas begin with `enter` and `leave` clauses, 83 + followed by the name of a tree-sitter node kind: `section`. 84 + The `section` identifier is visible in the 85 + tree-visualization above, it encompasses a markdown-section, 86 + and is created for every markdown header. To understand how 87 + `tbsp` executes above stanzas: 88 + 89 + 90 + document ... depth = 0 91 + | section <-------- enter section (1) ... depth = 1 92 + | | atx_heading 93 + | | | inline 94 + | | paragraph 95 + | | | inline 96 + | | section <----- enter section (2) ... depth = 2 97 + | | | atx_heading 98 + | | | | inline 99 + | | | paragraph 100 + | | | | inline 101 + | | | <----------- leave section (2) ... depth = 1 102 + | | <-------------- leave section (1) ... depth = 0 103 + 104 + 105 + The following stanzas should be self-explanatory now: 106 + 107 + 108 + enter atx_heading { 109 + print("<h"); 110 + print(depth); 111 + print(">"); 112 + } 113 + leave atx_heading { 114 + print("</h"); 115 + print(depth); 116 + print(">\n"); 117 + } 118 + 119 + enter inline { 120 + print(text(node)); 121 + } 122 + 123 + 124 + But an explanation is included nonetheless: 125 + 126 + 127 + document ... depth = 0 128 + | section <-------- enter section (1) ... depth = 1 129 + | | atx_heading <- enter atx_heading ... print "<h1>" 130 + | | | inline <--- enter inline ... print .. 131 + | | | <----------- leave atx_heading ... print "</h1>" 132 + | | paragraph 133 + | | | inline <--- enter inline ... print .. 134 + | | section <----- enter section (2) ... depth = 2 135 + | | | atx_heading enter atx_heading ... print "<h2>" 136 + | | | | inline <- enter inline ... print .. 137 + | | | | <-------- leave atx_heading ... print "</h2>" 138 + | | | paragraph 139 + | | | | inline <- enter inline ... print .. 140 + | | | <----------- leave section (2) ... depth = 1 141 + | | <-------------- leave section (1) ... depth = 0 142 + 143 + 144 + The 145 + [examples](https://git.peppe.rs/languages/tbsp/tree/examples) 146 + directory contains a complete markdown-to-html converter, 147 + along with a few other motivating examples. 148 + 149 + ### Usage 150 + 151 + The `tbsp` evaluator is written in rust, use cargo to build 152 + and run: 153 + 154 + cargo build --release 155 + ./target/release/tbsp --help 156 + 157 + 158 + `tbsp` requires three inputs: 159 + 160 + - a `tbsp` program, referred to as "program file" 161 + - a language 162 + - an input file or some input text at stdin 163 + 164 + 165 + You can run the interpreter like so (this program prints an 166 + overview of a rust file): 167 + 168 + $ ./target/release/tbsp \ 169 + -f./examples/code-overview/overview.tbsp \ 170 + -l rust \ 171 + src/main.rs 172 + module 173 + └╴struct Cli 174 + └╴trait Cli 175 + └╴fn program 176 + └╴fn language 177 + └╴fn file 178 + └╴fn try_consume_stdin 179 + └╴fn main 180 + 181 +