aboutsummaryrefslogtreecommitdiff
path: root/docs/posts
diff options
context:
space:
mode:
authorAkshay <[email protected]>2023-02-12 06:43:49 +0000
committerAkshay <[email protected]>2023-02-12 06:43:49 +0000
commit366df8852f503523cc4f9046d82ba9a99dd51d7f (patch)
tree635884dd5700cdc2a22a8885031aa67816bbe1b0 /docs/posts
parent57a1fc656e05e1fcf07e4cff3dc988c6b5c2bc59 (diff)
new art: lapse
Diffstat (limited to 'docs/posts')
-rw-r--r--docs/posts/SDL2_devlog/index.html240
-rw-r--r--docs/posts/WPA_woes/index.html13
-rw-r--r--docs/posts/a_reference_counted_afterlife/index.html40
-rw-r--r--docs/posts/auto-currying_rust_functions/index.html496
-rw-r--r--docs/posts/bash_harder_with_vim/index.html22
-rw-r--r--docs/posts/bye_bye_BDFs/index.html28
-rw-r--r--docs/posts/call_to_ARMs/index.html49
-rw-r--r--docs/posts/color_conundrum/index.html36
-rw-r--r--docs/posts/curing_a_case_of_git-UX/index.html180
-rw-r--r--docs/posts/font_size_fallacies/index.html79
-rw-r--r--docs/posts/get_better_at_yanking_and_putting_in_vim/index.html5
-rw-r--r--docs/posts/gripes_with_go/index.html85
-rw-r--r--docs/posts/hold_position!/index.html20
-rw-r--r--docs/posts/index.html14
-rw-r--r--docs/posts/lightweight_linting/index.html212
-rw-r--r--docs/posts/lotus58/index.html83
-rw-r--r--docs/posts/my_setup/index.html25
-rw-r--r--docs/posts/nixOS/index.html74
-rw-r--r--docs/posts/novice_nix:_flake_templates/index.html171
-rw-r--r--docs/posts/onivim_sucks/index.html39
-rw-r--r--docs/posts/pixel_art_in_GIMP/index.html101
-rw-r--r--docs/posts/programming_on_34_keys/index.html157
-rw-r--r--docs/posts/rapid_refactoring_with_vim/index.html119
-rw-r--r--docs/posts/self-hosting_git/index.html67
-rw-r--r--docs/posts/static_sites_with_bash/index.html36
-rw-r--r--docs/posts/termux_tandem/index.html29
-rw-r--r--docs/posts/turing_complete_type_systems/index.html24
27 files changed, 1816 insertions, 628 deletions
diff --git a/docs/posts/SDL2_devlog/index.html b/docs/posts/SDL2_devlog/index.html
index 0e76515..e31f399 100644
--- a/docs/posts/SDL2_devlog/index.html
+++ b/docs/posts/SDL2_devlog/index.html
@@ -42,25 +42,60 @@
42 SDL2 Devlog 42 SDL2 Devlog
43 </h1> 43 </h1>
44 <div class="post-text"> 44 <div class="post-text">
45 <p>I have been working on an editor for the <a href="https://git.peppe.rs/graphics/obi/about">One Bit Image</a> file format in Rust and SDL2. This entry in my blog follows my progress on the editor. The days are listed in reverse chronological order, begin from the bottom, if this is your first time on this page.</p> 45 <p>I have been working on an editor for the <a
46href="https://git.peppe.rs/graphics/obi/about">One Bit Image</a> file
47format in Rust and SDL2. This entry in my blog follows my progress on
48the editor. The days are listed in reverse chronological order, begin
49from the bottom, if this is your first time on this page.</p>
46<h3 id="day-20">Day 20</h3> 50<h3 id="day-20">Day 20</h3>
47<p>More <code>lisp</code> stuff! I added a new brush, for rectangular selections. While selection doesn’t do much on its own, the selected area can be passed onto a <code>lisp</code> procedure, for example, a procedure to draw horizontal black and white lines:</p> 51<p>More <code>lisp</code> stuff! I added a new brush, for rectangular
52selections. While selection doesn’t do much on its own, the selected
53area can be passed onto a <code>lisp</code> procedure, for example, a
54procedure to draw horizontal black and white lines:</p>
48<figure> 55<figure>
49<video src="https://u.peppe.rs/frU.mp4" controls=""><a href="https://u.peppe.rs/frU.mp4">Day 20</a></video><figcaption aria-hidden="true">Day 20</figcaption> 56<video src="https://u.peppe.rs/frU.mp4" controls=""><a
57href="https://u.peppe.rs/frU.mp4">Day 20</a></video>
58<figcaption aria-hidden="true">Day 20</figcaption>
50</figure> 59</figure>
51<h3 id="day-19">Day 19</h3> 60<h3 id="day-19">Day 19</h3>
52<p>Attempted <a href="https://peppe.rs/art/conduit.png">some isometric art</a> within the editor. The angles displayed alongside the line brush are handly, however, having only a rectangular grid did not help. I implemented an isometric grid today. Isometric grids in pixel art differ in that the tangent of the isometric angle is exactly 0.5! For every pixel down, you go exactly two pixels sideways. The math works out really well in the drawing procedures too, dealing with floating points is a pain.</p> 61<p>Attempted <a href="https://peppe.rs/art/conduit.png">some isometric
62art</a> within the editor. The angles displayed alongside the line brush
63are handly, however, having only a rectangular grid did not help. I
64implemented an isometric grid today. Isometric grids in pixel art differ
65in that the tangent of the isometric angle is exactly 0.5! For every
66pixel down, you go exactly two pixels sideways. The math works out
67really well in the drawing procedures too, dealing with floating points
68is a pain.</p>
53<figure> 69<figure>
54<img src="https://u.peppe.rs/1Kb.png" alt="Day 19" /><figcaption aria-hidden="true">Day 19</figcaption> 70<img src="https://u.peppe.rs/1Kb.png" alt="Day 19" />
71<figcaption aria-hidden="true">Day 19</figcaption>
55</figure> 72</figure>
56<h3 id="day-18">Day 18</h3> 73<h3 id="day-18">Day 18</h3>
57<p>I added basic support for guides, they can be added and activated from the <code>lisp</code> REPL. Another long standing improvement I wanted to make was reworking the pixmap drawing procedure. The old procedure draws a square for each pixel in the pixmap, coloured according to its value in the pixmap. Naturally, this means, for an <strong>NxN</strong> pixmap, there are <strong>N²</strong> calls to SDL! I reworked this procedure to compress each line of the pixmap using RLE (run length encoding), and call out to SDL for each run in the line. This drastically improved drawing speeds on larger grids. The following is a comparison between the two procedures, the leftmost picture is the rendered image, the middle picture is the optimized drawing procedure (draws each run instead of pixel), and the right most picture is the primitive drawing procedure (draws each pixel):</p> 74<p>I added basic support for guides, they can be added and activated
75from the <code>lisp</code> REPL. Another long standing improvement I
76wanted to make was reworking the pixmap drawing procedure. The old
77procedure draws a square for each pixel in the pixmap, coloured
78according to its value in the pixmap. Naturally, this means, for an
79<strong>NxN</strong> pixmap, there are <strong>N²</strong> calls to SDL!
80I reworked this procedure to compress each line of the pixmap using RLE
81(run length encoding), and call out to SDL for each run in the line.
82This drastically improved drawing speeds on larger grids. The following
83is a comparison between the two procedures, the leftmost picture is the
84rendered image, the middle picture is the optimized drawing procedure
85(draws each run instead of pixel), and the right most picture is the
86primitive drawing procedure (draws each pixel):</p>
58<figure> 87<figure>
59<img src="https://u.peppe.rs/U4B.png" alt="Day 18" /><figcaption aria-hidden="true">Day 18</figcaption> 88<img src="https://u.peppe.rs/U4B.png" alt="Day 18" />
89<figcaption aria-hidden="true">Day 18</figcaption>
60</figure> 90</figure>
61<h3 id="day-17">Day 17</h3> 91<h3 id="day-17">Day 17</h3>
62<p>I decided to give the text-only statusline a touch up, by adding a active color and dither level preview. Aligning the “widget” to the right of statusline involved a lot more than I thought, so I created a ghetto CSS-like rectangle placement system to position containers inside containers:</p> 92<p>I decided to give the text-only statusline a touch up, by adding a
63<div class="sourceCode" id="cb1"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="co">// roughly something like this</span></span> 93active color and dither level preview. Aligning the “widget” to the
94right of statusline involved a lot more than I thought, so I created a
95ghetto CSS-like rectangle placement system to position containers inside
96containers:</p>
97<div class="sourceCode" id="cb1"><pre
98class="sourceCode rust"><code class="sourceCode rust"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="co">// roughly something like this</span></span>
64<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">let</span> statusline <span class="op">=</span> </span> 99<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="kw">let</span> statusline <span class="op">=</span> </span>
65<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a> <span class="pp">Container::</span>new(<span class="pp">Offset::</span>Left(<span class="dv">0</span>)<span class="op">,</span> <span class="pp">Offset::</span>Bottom(<span class="dv">40</span>))</span> 100<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a> <span class="pp">Container::</span>new(<span class="pp">Offset::</span>Left(<span class="dv">0</span>)<span class="op">,</span> <span class="pp">Offset::</span>Bottom(<span class="dv">40</span>))</span>
66<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span>width(<span class="pp">Size::</span>Max)</span> 101<span id="cb1-4"><a href="#cb1-4" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span>width(<span class="pp">Size::</span>Max)</span>
@@ -77,14 +112,20 @@
77<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>)<span class="op">;</span></span></code></pre></div> 112<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a>)<span class="op">;</span></span></code></pre></div>
78<p>The result (brush preview on the bottom right):</p> 113<p>The result (brush preview on the bottom right):</p>
79<figure> 114<figure>
80<video src="https://u.peppe.rs/OtU.mp4" controls=""><a href="https://u.peppe.rs/OtU.mp4">Day 17</a></video><figcaption aria-hidden="true">Day 17</figcaption> 115<video src="https://u.peppe.rs/OtU.mp4" controls=""><a
116href="https://u.peppe.rs/OtU.mp4">Day 17</a></video>
117<figcaption aria-hidden="true">Day 17</figcaption>
81</figure> 118</figure>
82<h3 id="day-16">Day 16</h3> 119<h3 id="day-16">Day 16</h3>
83<p>The embedded lisp is coming along nicely, users can load a custom <code>rc.lisp</code>, which is evaluated on startup. To disable to grid on start, for example:</p> 120<p>The embedded lisp is coming along nicely, users can load a custom
84<div class="sourceCode" id="cb2"><pre class="sourceCode scheme"><code class="sourceCode scheme"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="co">;;; rc.lisp</span></span> 121<code>rc.lisp</code>, which is evaluated on startup. To disable to grid
122on start, for example:</p>
123<div class="sourceCode" id="cb2"><pre
124class="sourceCode scheme"><code class="sourceCode scheme"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="co">;;; rc.lisp</span></span>
85<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>(toggle-grid)</span></code></pre></div> 125<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a>(toggle-grid)</span></code></pre></div>
86<p>Some aliases to switch between brushes:</p> 126<p>Some aliases to switch between brushes:</p>
87<div class="sourceCode" id="cb3"><pre class="sourceCode scheme"><code class="sourceCode scheme"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="co">;;; rc.lisp</span></span> 127<div class="sourceCode" id="cb3"><pre
128class="sourceCode scheme"><code class="sourceCode scheme"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="co">;;; rc.lisp</span></span>
88<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>(<span class="ex">define</span><span class="fu"> </span>(brush kind)</span> 129<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>(<span class="ex">define</span><span class="fu"> </span>(brush kind)</span>
89<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a> (<span class="kw">cond</span></span> 130<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a> (<span class="kw">cond</span></span>
90<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a> ((<span class="kw">eq?</span> kind &#39;f) (brush-fill))</span> 131<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a> ((<span class="kw">eq?</span> kind &#39;f) (brush-fill))</span>
@@ -92,90 +133,195 @@
92<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a> ((<span class="kw">eq?</span> kind &#39;l) (brush-line))</span> 133<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a> ((<span class="kw">eq?</span> kind &#39;l) (brush-line))</span>
93<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a> ((<span class="kw">eq?</span> kind &#39;l+) (brush-line-extend))</span> 134<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a> ((<span class="kw">eq?</span> kind &#39;l+) (brush-line-extend))</span>
94<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a> (<span class="kw">else</span> (brush-circle))))</span></code></pre></div> 135<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a> (<span class="kw">else</span> (brush-circle))))</span></code></pre></div>
95<p>The following script draws a straight line along a given axis, at a given distance from the canvas boundary:</p> 136<p>The following script draws a straight line along a given axis, at a
137given distance from the canvas boundary:</p>
96<figure> 138<figure>
97<video src="https://u.peppe.rs/b3i.mp4" controls=""><a href="https://u.peppe.rs/b3i.mp4">Day 16</a></video><figcaption aria-hidden="true">Day 16</figcaption> 139<video src="https://u.peppe.rs/b3i.mp4" controls=""><a
140href="https://u.peppe.rs/b3i.mp4">Day 16</a></video>
141<figcaption aria-hidden="true">Day 16</figcaption>
98</figure> 142</figure>
99<h3 id="day-15">Day 15</h3> 143<h3 id="day-15">Day 15</h3>
100<p>I began writing a standard library for the lisp, in lisp. It includes basic list operations: <code>car</code>, <code>cdr</code>, <code>null?</code>, <code>list</code>, higher order functions: <code>map</code>, <code>filter</code>, <code>fold</code>:</p> 144<p>I began writing a standard library for the lisp, in lisp. It includes
101<div class="sourceCode" id="cb4"><pre class="sourceCode lisp"><code class="sourceCode commonlisp"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>(define (member? item ls)</span> 145basic list operations: <code>car</code>, <code>cdr</code>,
146<code>null?</code>, <code>list</code>, higher order functions:
147<code>map</code>, <code>filter</code>, <code>fold</code>:</p>
148<div class="sourceCode" id="cb4"><pre
149class="sourceCode lisp"><code class="sourceCode commonlisp"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a>(define (member? item ls)</span>
102<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a> (fold <span class="dv">#f</span></span> 150<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a> (fold <span class="dv">#f</span></span>
103<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a> (<span class="kw">lambda</span> (acc x) (<span class="kw">or</span> acc (eq? item x)))</span> 151<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a> (<span class="kw">lambda</span> (acc x) (<span class="kw">or</span> acc (eq? item x)))</span>
104<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a> ls))</span></code></pre></div> 152<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a> ls))</span></code></pre></div>
105<h3 id="day-14">Day 14</h3> 153<h3 id="day-14">Day 14</h3>
106<p>I attempted a <a href="https://peppe.rs/art/ramen_noodles.png">small art piece</a> using the editor, while it was largely usable, I felt a certain lack of feedback. The brushes just didn’t relay as much info as I’d have liked, for example, the approximate points of the line or the angle made by the line against the x-axis. Unfortunately, the existing infrastructure around brushes and line drawing didn’t easily allow for this either. I went ahead and reimplemented brushes, and added a new flood fill brush too:</p> 154<p>I attempted a <a href="https://peppe.rs/art/ramen_noodles.png">small
155art piece</a> using the editor, while it was largely usable, I felt a
156certain lack of feedback. The brushes just didn’t relay as much info as
157I’d have liked, for example, the approximate points of the line or the
158angle made by the line against the x-axis. Unfortunately, the existing
159infrastructure around brushes and line drawing didn’t easily allow for
160this either. I went ahead and reimplemented brushes, and added a new
161flood fill brush too:</p>
107<figure> 162<figure>
108<video src="https://u.peppe.rs/8q.mp4" controls=""><a href="https://u.peppe.rs/8q.mp4">Day 14</a></video><figcaption aria-hidden="true">Day 14</figcaption> 163<video src="https://u.peppe.rs/8q.mp4" controls=""><a
164href="https://u.peppe.rs/8q.mp4">Day 14</a></video>
165<figcaption aria-hidden="true">Day 14</figcaption>
109</figure> 166</figure>
110<h3 id="day-13">Day 13</h3> 167<h3 id="day-13">Day 13</h3>
111<p>I added a few more forms to the <code>lisp</code> evaluator. It handles recursion, definitions, variable mutation and more. The prelude contains 20 subroutines so far, including comparision and logic operators. The REPL interface on the SDL side requires some UX tweaks; environment based completion, readline motions sound doable.</p> 168<p>I added a few more forms to the <code>lisp</code> evaluator. It
169handles recursion, definitions, variable mutation and more. The prelude
170contains 20 subroutines so far, including comparision and logic
171operators. The REPL interface on the SDL side requires some UX tweaks;
172environment based completion, readline motions sound doable.</p>
112<figure> 173<figure>
113<video src="https://u.peppe.rs/u3.mp4" controls=""><a href="https://u.peppe.rs/u3.mp4">Day 13</a></video><figcaption aria-hidden="true">Day 13</figcaption> 174<video src="https://u.peppe.rs/u3.mp4" controls=""><a
175href="https://u.peppe.rs/u3.mp4">Day 13</a></video>
176<figcaption aria-hidden="true">Day 13</figcaption>
114</figure> 177</figure>
115<h3 id="day-12">Day 12</h3> 178<h3 id="day-12">Day 12</h3>
116<p>I lifted most of <a href="https://github.com/murarth/ketos">murarth/ketos</a> into the editor. <code>ketos</code>’s implementation of <code>lisp</code> is too vast for my use case. For example, the editor does not need data types to handle raw strings or byte strings. I have got a basic evaluator running inside the SDL2 context (notice the <code>lisp</code> REPL at the bottom of the window). Over the following days, I intend to create a set of prelude functions to manipulate the pixmap. Users can implement their own brushes, dithering patterns, keybinds and more (hopefully).</p> 179<p>I lifted most of <a
180href="https://github.com/murarth/ketos">murarth/ketos</a> into the
181editor. <code>ketos</code>’s implementation of <code>lisp</code> is too
182vast for my use case. For example, the editor does not need data types
183to handle raw strings or byte strings. I have got a basic evaluator
184running inside the SDL2 context (notice the <code>lisp</code> REPL at
185the bottom of the window). Over the following days, I intend to create a
186set of prelude functions to manipulate the pixmap. Users can implement
187their own brushes, dithering patterns, keybinds and more
188(hopefully).</p>
117<figure> 189<figure>
118<video src="https://u.peppe.rs/y0.mp4" controls=""><a href="https://u.peppe.rs/y0.mp4">Day 12</a></video><figcaption aria-hidden="true">Day 12</figcaption> 190<video src="https://u.peppe.rs/y0.mp4" controls=""><a
191href="https://u.peppe.rs/y0.mp4">Day 12</a></video>
192<figcaption aria-hidden="true">Day 12</figcaption>
119</figure> 193</figure>
120<h3 id="day-11">Day 11</h3> 194<h3 id="day-11">Day 11</h3>
121<p>I intend to supplement the editor with scripting language and an inbuilt REPL for the same. I began by implementing a text box widget from scratch, with history and readline like editing:</p> 195<p>I intend to supplement the editor with scripting language and an
196inbuilt REPL for the same. I began by implementing a text box widget
197from scratch, with history and readline like editing:</p>
122<figure> 198<figure>
123<video src="https://u.peppe.rs/Mh.mp4" controls=""><a href="https://u.peppe.rs/Mh.mp4">Day 11</a></video><figcaption aria-hidden="true">Day 11</figcaption> 199<video src="https://u.peppe.rs/Mh.mp4" controls=""><a
200href="https://u.peppe.rs/Mh.mp4">Day 11</a></video>
201<figcaption aria-hidden="true">Day 11</figcaption>
124</figure> 202</figure>
125<h3 id="day-10">Day 10</h3> 203<h3 id="day-10">Day 10</h3>
126<p>I started reading up on dithering methods and half-toning, I wanted to create a dithering brush that would automatically produce popular dithering patterns. The method that caught my eye (and also the one used most often in pixel art), was Bayer’s ordered dithering. When applied to a black and white image, each pixel, based on its intensity, is mapped to a 4x4 grid of pixels. A completely empty (completely black) 4x4 grid represents zero intensity, and a filled 4x4 grid represents full intensity. Bayer’s ordered dithering can produce 15 steps of intensity between zero and full (by switching on exactly 1 pixel more at each level), thus, being able to draw 17 “shades” from white to black. Creating a dithering brush from here was fairly trivial. Our pixmap is supposed to represent the final dithered image, it must be divided into 4x4 grids. Each grid is colored based on the intensity of the brush passing over it:</p> 204<p>I started reading up on dithering methods and half-toning, I wanted
205to create a dithering brush that would automatically produce popular
206dithering patterns. The method that caught my eye (and also the one used
207most often in pixel art), was Bayer’s ordered dithering. When applied to
208a black and white image, each pixel, based on its intensity, is mapped
209to a 4x4 grid of pixels. A completely empty (completely black) 4x4 grid
210represents zero intensity, and a filled 4x4 grid represents full
211intensity. Bayer’s ordered dithering can produce 15 steps of intensity
212between zero and full (by switching on exactly 1 pixel more at each
213level), thus, being able to draw 17 “shades” from white to black.
214Creating a dithering brush from here was fairly trivial. Our pixmap is
215supposed to represent the final dithered image, it must be divided into
2164x4 grids. Each grid is colored based on the intensity of the brush
217passing over it:</p>
127<figure> 218<figure>
128<img src="https://u.peppe.rs/Mn.png" alt="Day 10" /><figcaption aria-hidden="true">Day 10</figcaption> 219<img src="https://u.peppe.rs/Mn.png" alt="Day 10" />
220<figcaption aria-hidden="true">Day 10</figcaption>
129</figure> 221</figure>
130<h3 id="day-9">Day 9</h3> 222<h3 id="day-9">Day 9</h3>
131<p>I started working towards an interface. I like the idea of a largely read-only HUD, i. e., an interface that simply describes the state of the application. Changes to this state are initiated via keybinds or text commands. I am proud of the symmetry indicator; <code>-</code> for horizontal symmetry, <code>|</code> for vertical symmetry, <code>+</code> for radial symmetry.</p> 223<p>I started working towards an interface. I like the idea of a largely
224read-only HUD, i. e., an interface that simply describes the state of
225the application. Changes to this state are initiated via keybinds or
226text commands. I am proud of the symmetry indicator; <code>-</code> for
227horizontal symmetry, <code>|</code> for vertical symmetry,
228<code>+</code> for radial symmetry.</p>
132<figure> 229<figure>
133<img src="https://u.peppe.rs/hx.png" alt="Day 9" /><figcaption aria-hidden="true">Day 9</figcaption> 230<img src="https://u.peppe.rs/hx.png" alt="Day 9" />
231<figcaption aria-hidden="true">Day 9</figcaption>
134</figure> 232</figure>
135<h3 id="day-8">Day 8</h3> 233<h3 id="day-8">Day 8</h3>
136<p>One of my favourite features of GIMP was symmetric editing. I added some coordinate geometry primitives to my pixmap abstraction, allowing for mirroring and reflecting figures about lines or points. The result was an ergonomic function that applies symmetry to any painting operation, (undo/redo works as expected):</p> 234<p>One of my favourite features of GIMP was symmetric editing. I added
137<div class="sourceCode" id="cb5"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">let</span> line <span class="op">=</span> <span class="kw">self</span><span class="op">.</span>pixmap<span class="op">.</span>get_line(start<span class="op">,</span> end)<span class="op">;</span></span> 235some coordinate geometry primitives to my pixmap abstraction, allowing
236for mirroring and reflecting figures about lines or points. The result
237was an ergonomic function that applies symmetry to any painting
238operation, (undo/redo works as expected):</p>
239<div class="sourceCode" id="cb5"><pre
240class="sourceCode rust"><code class="sourceCode rust"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">let</span> line <span class="op">=</span> <span class="kw">self</span><span class="op">.</span>pixmap<span class="op">.</span>get_line(start<span class="op">,</span> end)<span class="op">;</span></span>
138<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="kw">let</span> sym_line <span class="op">=</span> <span class="kw">self</span><span class="op">.</span>symmetry<span class="op">.</span>apply(<span class="op">&amp;</span>line)<span class="op">;</span></span> 241<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a><span class="kw">let</span> sym_line <span class="op">=</span> <span class="kw">self</span><span class="op">.</span>symmetry<span class="op">.</span>apply(<span class="op">&amp;</span>line)<span class="op">;</span></span>
139<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="kw">for</span> point on line<span class="op">.</span>extend(sym_line) <span class="op">{</span></span> 242<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a><span class="cf">for</span> point on line<span class="op">.</span>extend(sym_line) <span class="op">{</span></span>
140<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a> <span class="co">// draw to window</span></span> 243<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a> <span class="co">// draw to window</span></span>
141<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div> 244<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
142<figure> 245<figure>
143<video src="https://u.peppe.rs/B1.mp4" controls=""><a href="https://u.peppe.rs/B1.mp4">Day 8</a></video><figcaption aria-hidden="true">Day 8</figcaption> 246<video src="https://u.peppe.rs/B1.mp4" controls=""><a
247href="https://u.peppe.rs/B1.mp4">Day 8</a></video>
248<figcaption aria-hidden="true">Day 8</figcaption>
144</figure> 249</figure>
145<h3 id="day-7">Day 7</h3> 250<h3 id="day-7">Day 7</h3>
146<p>Bresenham saves the day again! This time, I implemented his line drawing algorithm, to, well, draw lines. Each point on the line is then “buffed” based on the active brush size. Today’s changes fit in very well with the undo system and the brush size feature. Creating the right abstractions, one at a time :)</p> 251<p>Bresenham saves the day again! This time, I implemented his line
252drawing algorithm, to, well, draw lines. Each point on the line is then
253“buffed” based on the active brush size. Today’s changes fit in very
254well with the undo system and the brush size feature. Creating the right
255abstractions, one at a time :)</p>
147<figure> 256<figure>
148<video src="https://u.peppe.rs/xt.mp4" controls=""><a href="https://u.peppe.rs/xt.mp4">Day 7</a></video><figcaption aria-hidden="true">Day 7</figcaption> 257<video src="https://u.peppe.rs/xt.mp4" controls=""><a
258href="https://u.peppe.rs/xt.mp4">Day 7</a></video>
259<figcaption aria-hidden="true">Day 7</figcaption>
149</figure> 260</figure>
150<h3 id="day-6">Day 6</h3> 261<h3 id="day-6">Day 6</h3>
151<p>I extended Bresenham’s algorithm to draw not just circle outlines, but also generate their fills. Unlike Bresenham’s algorithm, this variant generates points for two quadrants at once, these points are mirrored over the dividing axis to generate the other two quadrants.</p> 262<p>I extended Bresenham’s algorithm to draw not just circle outlines,
263but also generate their fills. Unlike Bresenham’s algorithm, this
264variant generates points for two quadrants at once, these points are
265mirrored over the dividing axis to generate the other two quadrants.</p>
152<figure> 266<figure>
153<img src="https://u.peppe.rs/f3.png" alt="Day 6" /><figcaption aria-hidden="true">Day 6</figcaption> 267<img src="https://u.peppe.rs/f3.png" alt="Day 6" />
268<figcaption aria-hidden="true">Day 6</figcaption>
154</figure> 269</figure>
155<h3 id="day-5">Day 5</h3> 270<h3 id="day-5">Day 5</h3>
156<p>I discovered and implemented Bresenham’s algorithm for efficient circle drawing. The algorithm allowed for sized circular brushes, something I really liked from GIMP. Very convenient that the Wikipedia page for Bresenham’s algorithm also includes a section about optimizing for integer based arithmetic. I managed to abstract out another giant component of the application, the pixmap. Any image is just a grid of pixels (a pixmap), where the pixel’s value is decided by the application (1-bit in my case). I could potentially extend the application to a 24-bit image editor!</p> 271<p>I discovered and implemented Bresenham’s algorithm for efficient
272circle drawing. The algorithm allowed for sized circular brushes,
273something I really liked from GIMP. Very convenient that the Wikipedia
274page for Bresenham’s algorithm also includes a section about optimizing
275for integer based arithmetic. I managed to abstract out another giant
276component of the application, the pixmap. Any image is just a grid of
277pixels (a pixmap), where the pixel’s value is decided by the application
278(1-bit in my case). I could potentially extend the application to a
27924-bit image editor!</p>
157<figure> 280<figure>
158<video src="https://u.peppe.rs/Kh.mp4" controls=""><a href="https://u.peppe.rs/Kh.mp4">Day 5</a></video><figcaption aria-hidden="true">Day 5</figcaption> 281<video src="https://u.peppe.rs/Kh.mp4" controls=""><a
282href="https://u.peppe.rs/Kh.mp4">Day 5</a></video>
283<figcaption aria-hidden="true">Day 5</figcaption>
159</figure> 284</figure>
160<h3 id="day-4">Day 4</h3> 285<h3 id="day-4">Day 4</h3>
161<p>I created a generic “undo stack” data structure that allows for infinite “undos” and “redos”. Every modification operation to the grid is persisted to the application state. A couple of keybinds allow the user to revert and re-apply these operations! I expect abstracting this component will come in handy down the line.</p> 286<p>I created a generic “undo stack” data structure that allows for
287infinite “undos” and “redos”. Every modification operation to the grid
288is persisted to the application state. A couple of keybinds allow the
289user to revert and re-apply these operations! I expect abstracting this
290component will come in handy down the line.</p>
162<figure> 291<figure>
163<video src="https://u.peppe.rs/w5.mp4" controls=""><a href="https://u.peppe.rs/w5.mp4">Day 4</a></video><figcaption aria-hidden="true">Day 4</figcaption> 292<video src="https://u.peppe.rs/w5.mp4" controls=""><a
293href="https://u.peppe.rs/w5.mp4">Day 4</a></video>
294<figcaption aria-hidden="true">Day 4</figcaption>
164</figure> 295</figure>
165<h3 id="day-3">Day 3</h3> 296<h3 id="day-3">Day 3</h3>
166<p>I implemented the bare minimum required to call the program an “editor”. The application displays a grid, tracks mouse events, paints white to the canvas on left click, and black to the canvas on right click. I created a make-shift MVC architecture à la Elm in Rust.</p> 297<p>I implemented the bare minimum required to call the program an
298“editor”. The application displays a grid, tracks mouse events, paints
299white to the canvas on left click, and black to the canvas on right
300click. I created a make-shift MVC architecture à la Elm in Rust.</p>
167<figure> 301<figure>
168<video src="https://u.peppe.rs/GF.mp4" controls=""><a href="https://u.peppe.rs/GF.mp4">Day 3</a></video><figcaption aria-hidden="true">Day 3</figcaption> 302<video src="https://u.peppe.rs/GF.mp4" controls=""><a
303href="https://u.peppe.rs/GF.mp4">Day 3</a></video>
304<figcaption aria-hidden="true">Day 3</figcaption>
169</figure> 305</figure>
170<h3 id="day-2">Day 2</h3> 306<h3 id="day-2">Day 2</h3>
171<p>I started figuring out event handling today. Implemented a couple of keybinds to zoom in/out of the drawing area. Conversions of SDL2 coordinates (measured in signed 32 bit integers) to my internal “drawing area” coordinates (measured in unsigned 32 bit integers) is very annoying. Hopefully the unchecked conversions won’t haunt me later.</p> 307<p>I started figuring out event handling today. Implemented a couple of
308keybinds to zoom in/out of the drawing area. Conversions of SDL2
309coordinates (measured in signed 32 bit integers) to my internal “drawing
310area” coordinates (measured in unsigned 32 bit integers) is very
311annoying. Hopefully the unchecked conversions won’t haunt me later.</p>
172<figure> 312<figure>
173<video src="https://u.peppe.rs/L4.mp4" controls=""><a href="https://u.peppe.rs/L4.mp4">Day 2</a></video><figcaption aria-hidden="true">Day 2</figcaption> 313<video src="https://u.peppe.rs/L4.mp4" controls=""><a
314href="https://u.peppe.rs/L4.mp4">Day 2</a></video>
315<figcaption aria-hidden="true">Day 2</figcaption>
174</figure> 316</figure>
175<h3 id="day-1">Day 1</h3> 317<h3 id="day-1">Day 1</h3>
176<p>Getting started with Rust and SDL2 is very straightforward. The <code>rust-sdl2</code> library contains some detailed examples that allowed me to get all the way to drawing a grid from a <code>Vec&lt;bool&gt;</code>:</p> 318<p>Getting started with Rust and SDL2 is very straightforward. The
319<code>rust-sdl2</code> library contains some detailed examples that
320allowed me to get all the way to drawing a grid from a
321<code>Vec&lt;bool&gt;</code>:</p>
177<figure> 322<figure>
178<img src="https://u.peppe.rs/Ma.png" alt="Day 1" /><figcaption aria-hidden="true">Day 1</figcaption> 323<img src="https://u.peppe.rs/Ma.png" alt="Day 1" />
324<figcaption aria-hidden="true">Day 1</figcaption>
179</figure> 325</figure>
180 326
181 </div> 327 </div>
diff --git a/docs/posts/WPA_woes/index.html b/docs/posts/WPA_woes/index.html
index 55b2630..0a2e44c 100644
--- a/docs/posts/WPA_woes/index.html
+++ b/docs/posts/WPA_woes/index.html
@@ -28,7 +28,7 @@
28 12/10 — 2019 28 12/10 — 2019
29 <div class="stats"> 29 <div class="stats">
30 <span class="stats-number"> 30 <span class="stats-number">
31 18.37 31 18.38
32 </span> 32 </span>
33 <span class="stats-unit">cm</span> 33 <span class="stats-unit">cm</span>
34 &nbsp 34 &nbsp
@@ -42,8 +42,12 @@
42 WPA Woes 42 WPA Woes
43 </h1> 43 </h1>
44 <div class="post-text"> 44 <div class="post-text">
45 <p>I finally got around to installing Void GNU/Linux on my main computer. Rolling release, non-systemd, need I say more?</p> 45 <p>I finally got around to installing Void GNU/Linux on my main
46<p>As with all GNU/Linux distributions, wireless networks had me in a fix. If you can see this post, it means I’ve managed to get online. It turns out, <code>wpa_supplicant</code> was detecting the wrong interface by default (does it ever select the right one?). Let us fix that:</p> 46computer. Rolling release, non-systemd, need I say more?</p>
47<p>As with all GNU/Linux distributions, wireless networks had me in a
48fix. If you can see this post, it means I’ve managed to get online. It
49turns out, <code>wpa_supplicant</code> was detecting the wrong interface
50by default (does it ever select the right one?). Let us fix that:</p>
47<pre><code>$ sudo rm -r /var/service/wpa_supplicant 51<pre><code>$ sudo rm -r /var/service/wpa_supplicant
48$ sudo killall dhcpcd</code></pre> 52$ sudo killall dhcpcd</code></pre>
49<p>What is the right interface though?</p> 53<p>What is the right interface though?</p>
@@ -51,7 +55,8 @@ $ sudo killall dhcpcd</code></pre>
51 ... 55 ...
52 Interface wlp2s0 56 Interface wlp2s0
53 ...</code></pre> 57 ...</code></pre>
54<p>Aha! Let us run <code>wpa_supplicant</code> on that interface, as a background process:</p> 58<p>Aha! Let us run <code>wpa_supplicant</code> on that interface, as a
59background process:</p>
55<pre><code>$ sudo wpa_supplicant -B -i wlp2s0 -c /etc/wpa_supplicant/wpa_supplicant.conf 60<pre><code>$ sudo wpa_supplicant -B -i wlp2s0 -c /etc/wpa_supplicant/wpa_supplicant.conf
56$ sudo dhcpcd -B wlp2s0 61$ sudo dhcpcd -B wlp2s0
57$ ping google.com 62$ ping google.com
diff --git a/docs/posts/a_reference_counted_afterlife/index.html b/docs/posts/a_reference_counted_afterlife/index.html
index 67016a6..a796393 100644
--- a/docs/posts/a_reference_counted_afterlife/index.html
+++ b/docs/posts/a_reference_counted_afterlife/index.html
@@ -28,7 +28,7 @@
28 02/08 — 2022 28 02/08 — 2022
29 <div class="stats"> 29 <div class="stats">
30 <span class="stats-number"> 30 <span class="stats-number">
31 19.57 31 19.58
32 </span> 32 </span>
33 <span class="stats-unit">cm</span> 33 <span class="stats-unit">cm</span>
34 &nbsp 34 &nbsp
@@ -42,9 +42,11 @@
42 A Reference Counted Afterlife 42 A Reference Counted Afterlife
43 </h1> 43 </h1>
44 <div class="post-text"> 44 <div class="post-text">
45 <p>I took interest in the Egyptian rendition of the afterlife recently.</p> 45 <p>I took interest in the Egyptian rendition of the afterlife
46recently.</p>
46<h3 id="parts-of-the-soul">Parts of the Soul</h3> 47<h3 id="parts-of-the-soul">Parts of the Soul</h3>
47<p>Ancient Egyptians believed that the soul comprised of several components:</p> 48<p>Ancient Egyptians believed that the soul comprised of several
49components:</p>
48<ul> 50<ul>
49<li><em>ren</em></li> 51<li><em>ren</em></li>
50<li><em>ka</em></li> 52<li><em>ka</em></li>
@@ -52,18 +54,34 @@
52<li><em>ba</em></li> 54<li><em>ba</em></li>
53<li><em>sheut</em></li> 55<li><em>sheut</em></li>
54</ul> 56</ul>
55<p>Egyptians emphasized on preserving the different parts of the soul. Mummification for example, served to preserve the physical part of the soul. The other components have their respective preservation strategies.</p> 57<p>Egyptians emphasized on preserving the different parts of the soul.
56<p>Of all of these bits, I find <em>ren</em>, which simply means <em>name</em>, to be the most interesting. <em>Ba</em>, the human-headed chicken that represents <em>personality</em>, is a close favourite.</p> 58Mummification for example, served to preserve the physical part of the
57<p><em>Ren</em> is the name given to a person at birth. Egyptians believed that this portion of the soul would continue to live on for as long as it was spoken. If you were someone worthy of continued existence, your name would be inscribed all over the place. If you were the type to snatch away bread from children, your name would be condemned from memory, forgotten.</p> 59soul. The other components have their respective preservation
60strategies.</p>
61<p>Of all of these bits, I find <em>ren</em>, which simply means
62<em>name</em>, to be the most interesting. <em>Ba</em>, the human-headed
63chicken that represents <em>personality</em>, is a close favourite.</p>
64<p><em>Ren</em> is the name given to a person at birth. Egyptians
65believed that this portion of the soul would continue to live on for as
66long as it was spoken. If you were someone worthy of continued
67existence, your name would be inscribed all over the place. If you were
68the type to snatch away bread from children, your name would be
69condemned from memory, forgotten.</p>
58<h3 id="garbage-collection">Garbage-collection</h3> 70<h3 id="garbage-collection">Garbage-collection</h3>
59<p>The concept of <em>ren</em> seems to be perfectly analogous to reference counted garbage-collection.</p> 71<p>The concept of <em>ren</em> seems to be perfectly analogous to
72reference counted garbage-collection.</p>
60<ul> 73<ul>
61<li>A name (<em>ren</em>) is assigned to an object (person) on initialization (at birth)</li> 74<li>A name (<em>ren</em>) is assigned to an object (person) on
75initialization (at birth)</li>
62<li>Names are used to refer to objects</li> 76<li>Names are used to refer to objects</li>
63<li>Objects go out of existence when there are no more references to them</li> 77<li>Objects go out of existence when there are no more references to
78them</li>
64</ul> 79</ul>
65<p>The concept of <em>ren</em> seems to model human-memory. The similarity with garbage-collection is now easily explained, because garbage-collection models a program’s memory.</p> 80<p>The concept of <em>ren</em> seems to model human-memory. The
66<p>Perhaps some cheeky Egyptian has attained immortality by creating a <em>ren</em>-cycle.</p> 81similarity with garbage-collection is now easily explained, because
82garbage-collection models a program’s memory.</p>
83<p>Perhaps some cheeky Egyptian has attained immortality by creating a
84<em>ren</em>-cycle.</p>
67 85
68 </div> 86 </div>
69 87
diff --git a/docs/posts/auto-currying_rust_functions/index.html b/docs/posts/auto-currying_rust_functions/index.html
index 0d6fc77..7b05aeb 100644
--- a/docs/posts/auto-currying_rust_functions/index.html
+++ b/docs/posts/auto-currying_rust_functions/index.html
@@ -28,7 +28,7 @@
28 09/05 — 2020 28 09/05 — 2020
29 <div class="stats"> 29 <div class="stats">
30 <span class="stats-number"> 30 <span class="stats-number">
31 356.43 31 356.44
32 </span> 32 </span>
33 <span class="stats-unit">cm</span> 33 <span class="stats-unit">cm</span>
34 &nbsp 34 &nbsp
@@ -42,13 +42,22 @@
42 Auto-currying Rust Functions 42 Auto-currying Rust Functions
43 </h1> 43 </h1>
44 <div class="post-text"> 44 <div class="post-text">
45 <p>This post contains a gentle introduction to procedural macros in Rust and a guide to writing a procedural macro to curry Rust functions. The source code for the entire library can be found <a href="https://github.com/nerdypepper/cutlass">here</a>. It is also available on <a href="https://crates.io/crates/cutlass">crates.io</a>.</p> 45 <p>This post contains a gentle introduction to procedural macros in Rust
46<p>The following links might prove to be useful before getting started:</p> 46and a guide to writing a procedural macro to curry Rust functions. The
47source code for the entire library can be found <a
48href="https://github.com/nerdypepper/cutlass">here</a>. It is also
49available on <a
50href="https://crates.io/crates/cutlass">crates.io</a>.</p>
51<p>The following links might prove to be useful before getting
52started:</p>
47<ul> 53<ul>
48<li><a href="https://doc.rust-lang.org/reference/procedural-macros.html">Procedural Macros</a></li> 54<li><a
55href="https://doc.rust-lang.org/reference/procedural-macros.html">Procedural
56Macros</a></li>
49<li><a href="https://en.wikipedia.org/wiki/Currying">Currying</a></li> 57<li><a href="https://en.wikipedia.org/wiki/Currying">Currying</a></li>
50</ul> 58</ul>
51<p>Or you can pretend you read them, because I have included a primer here :)</p> 59<p>Or you can pretend you read them, because I have included a primer
60here :)</p>
52<h3 id="contents">Contents</h3> 61<h3 id="contents">Contents</h3>
53<ol type="1"> 62<ol type="1">
54<li><a href="#currying">Currying</a><br /> 63<li><a href="#currying">Currying</a><br />
@@ -73,7 +82,12 @@
73<li><a href="#conclusion">Conclusion</a></li> 82<li><a href="#conclusion">Conclusion</a></li>
74</ol> 83</ol>
75<h3 id="currying">Currying</h3> 84<h3 id="currying">Currying</h3>
76<p>Currying is the process of transformation of a function call like <code>f(a, b, c)</code> to <code>f(a)(b)(c)</code>. A curried function returns a concrete value only when it receives all its arguments! If it does recieve an insufficient amount of arguments, say 1 of 3, it returns a <em>curried function</em>, that returns after receiving 2 arguments.</p> 85<p>Currying is the process of transformation of a function call like
86<code>f(a, b, c)</code> to <code>f(a)(b)(c)</code>. A curried function
87returns a concrete value only when it receives all its arguments! If it
88does recieve an insufficient amount of arguments, say 1 of 3, it returns
89a <em>curried function</em>, that returns after receiving 2
90arguments.</p>
77<pre><code>curry(f(a, b, c)) = h(a)(b)(c) 91<pre><code>curry(f(a, b, c)) = h(a)(b)(c)
78 92
79h(x) = g &lt;- curried function that takes upto 2 args (g) 93h(x) = g &lt;- curried function that takes upto 2 args (g)
@@ -82,49 +96,86 @@ k(z) = v &lt;- a value (v)
82 96
83Keen readers will conclude the following, 97Keen readers will conclude the following,
84h(x)(y)(z) = g(y)(z) = k(z) = v</code></pre> 98h(x)(y)(z) = g(y)(z) = k(z) = v</code></pre>
85<p>Mathematically, if <code>f</code> is a function that takes two arguments <code>x</code> and <code>y</code>, such that <code>x ϵ X</code>, and <code>y ϵ Y</code> , we write it as:</p> 99<p>Mathematically, if <code>f</code> is a function that takes two
100arguments <code>x</code> and <code>y</code>, such that
101<code>x ϵ X</code>, and <code>y ϵ Y</code> , we write it as:</p>
86<pre><code>f: (X × Y) -&gt; Z</code></pre> 102<pre><code>f: (X × Y) -&gt; Z</code></pre>
87<p>where <code>×</code> denotes the Cartesian product of set <code>X</code> and <code>Y</code>, and curried <code>f</code> (denoted by <code>h</code> here) is written as:</p> 103<p>where <code>×</code> denotes the Cartesian product of set
104<code>X</code> and <code>Y</code>, and curried <code>f</code> (denoted
105by <code>h</code> here) is written as:</p>
88<pre><code>h: X -&gt; (Y -&gt; Z)</code></pre> 106<pre><code>h: X -&gt; (Y -&gt; Z)</code></pre>
89<h3 id="procedural-macros">Procedural Macros</h3> 107<h3 id="procedural-macros">Procedural Macros</h3>
90<p>These are functions that take code as input and spit out modified code as output. Powerful stuff. Rust has three kinds of proc-macros:</p> 108<p>These are functions that take code as input and spit out modified
109code as output. Powerful stuff. Rust has three kinds of proc-macros:</p>
91<ul> 110<ul>
92<li>Function like macros<br /> 111<li>Function like macros<br />
93</li> 112</li>
94<li>Derive macros: <code>#[derive(...)]</code>, used to automatically implement traits for structs/enums<br /> 113<li>Derive macros: <code>#[derive(...)]</code>, used to automatically
114implement traits for structs/enums<br />
95</li> 115</li>
96<li>and Attribute macros: <code>#[test]</code>, usually slapped onto functions</li> 116<li>and Attribute macros: <code>#[test]</code>, usually slapped onto
117functions</li>
97</ul> 118</ul>
98<p>We will be using Attribute macros to convert a Rust function into a curried Rust function, which we should be able to call via: <code>function(arg1)(arg2)</code>.</p> 119<p>We will be using Attribute macros to convert a Rust function into a
120curried Rust function, which we should be able to call via:
121<code>function(arg1)(arg2)</code>.</p>
99<h3 id="definitions">Definitions</h3> 122<h3 id="definitions">Definitions</h3>
100<p>Being respectable programmers, we define the input to and the output from our proc-macro. Here’s a good non-trivial function to start out with:</p> 123<p>Being respectable programmers, we define the input to and the output
101<div class="sourceCode" id="cb4"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> add(x<span class="op">:</span> <span class="dt">u32</span><span class="op">,</span> y<span class="op">:</span> <span class="dt">u32</span><span class="op">,</span> z<span class="op">:</span> <span class="dt">u32</span>) <span class="op">-&gt;</span> <span class="dt">u32</span> <span class="op">{</span></span> 124from our proc-macro. Here’s a good non-trivial function to start out
102<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a> <span class="kw">return</span> x <span class="op">+</span> y <span class="op">+</span> z<span class="op">;</span></span> 125with:</p>
126<div class="sourceCode" id="cb4"><pre
127class="sourceCode rust"><code class="sourceCode rust"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> add(x<span class="op">:</span> <span class="dt">u32</span><span class="op">,</span> y<span class="op">:</span> <span class="dt">u32</span><span class="op">,</span> z<span class="op">:</span> <span class="dt">u32</span>) <span class="op">-&gt;</span> <span class="dt">u32</span> <span class="op">{</span></span>
128<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> x <span class="op">+</span> y <span class="op">+</span> z<span class="op">;</span></span>
103<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div> 129<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
104<p>Hmm, what would our output look like? What should our proc-macro generate ideally? Well, if we understood currying correctly, we should accept an argument and return a function that accepts an argument and returns … you get the point. Something like this should do:</p> 130<p>Hmm, what would our output look like? What should our proc-macro
105<div class="sourceCode" id="cb5"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> add_curried1(x<span class="op">:</span> <span class="dt">u32</span>) <span class="op">-&gt;</span> <span class="op">?</span> <span class="op">{</span></span> 131generate ideally? Well, if we understood currying correctly, we should
106<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a> <span class="kw">return</span> <span class="kw">fn</span> add_curried2 (y<span class="op">:</span> <span class="dt">u32</span>) <span class="op">-&gt;</span> <span class="op">?</span> <span class="op">{</span></span> 132accept an argument and return a function that accepts an argument and
107<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">return</span> <span class="kw">fn</span> add_curried3 (z<span class="op">:</span> <span class="dt">u32</span>) <span class="op">-&gt;</span> <span class="dt">u32</span> <span class="op">{</span></span> 133returns … you get the point. Something like this should do:</p>
108<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a> <span class="kw">return</span> x <span class="op">+</span> y <span class="op">+</span> z<span class="op">;</span></span> 134<div class="sourceCode" id="cb5"><pre
135class="sourceCode rust"><code class="sourceCode rust"><span id="cb5-1"><a href="#cb5-1" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> add_curried1(x<span class="op">:</span> <span class="dt">u32</span>) <span class="op">-&gt;</span> <span class="op">?</span> <span class="op">{</span></span>
136<span id="cb5-2"><a href="#cb5-2" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> <span class="kw">fn</span> add_curried2 (y<span class="op">:</span> <span class="dt">u32</span>) <span class="op">-&gt;</span> <span class="op">?</span> <span class="op">{</span></span>
137<span id="cb5-3"><a href="#cb5-3" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> <span class="kw">fn</span> add_curried3 (z<span class="op">:</span> <span class="dt">u32</span>) <span class="op">-&gt;</span> <span class="dt">u32</span> <span class="op">{</span></span>
138<span id="cb5-4"><a href="#cb5-4" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> x <span class="op">+</span> y <span class="op">+</span> z<span class="op">;</span></span>
109<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span> 139<span id="cb5-5"><a href="#cb5-5" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
110<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span> 140<span id="cb5-6"><a href="#cb5-6" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
111<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div> 141<span id="cb5-7"><a href="#cb5-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
112<p>A couple of things to note:</p> 142<p>A couple of things to note:</p>
113<p><strong>Return types</strong><br /> 143<p><strong>Return types</strong><br />
114We have placed <code>?</code>s in place of return types. Let’s try to fix that. <code>add_curried3</code> returns the ‘value’, so <code>u32</code> is accurate. <code>add_curried2</code> returns <code>add_curried3</code>. What is the type of <code>add_curried3</code>? It is a function that takes in a <code>u32</code> and returns a <code>u32</code>. So a <code>fn(u32) -&gt; u32</code> will do right? No, I’ll explain why in the next point, but for now, we will make use of the <code>Fn</code> trait, our return type is <code>impl Fn(u32) -&gt; u32</code>. This basically tells the compiler that we will be returning something function-like, a.k.a, behaves like a <code>Fn</code>. Cool!</p> 144We have placed <code>?</code>s in place of return types. Let’s try to
115<p>If you have been following along, you should be able to tell that the return type of <code>add_curried1</code> is:</p> 145fix that. <code>add_curried3</code> returns the ‘value’, so
146<code>u32</code> is accurate. <code>add_curried2</code> returns
147<code>add_curried3</code>. What is the type of
148<code>add_curried3</code>? It is a function that takes in a
149<code>u32</code> and returns a <code>u32</code>. So a
150<code>fn(u32) -&gt; u32</code> will do right? No, I’ll explain why in
151the next point, but for now, we will make use of the <code>Fn</code>
152trait, our return type is <code>impl Fn(u32) -&gt; u32</code>. This
153basically tells the compiler that we will be returning something
154function-like, a.k.a, behaves like a <code>Fn</code>. Cool!</p>
155<p>If you have been following along, you should be able to tell that the
156return type of <code>add_curried1</code> is:</p>
116<pre><code>impl Fn(u32) -&gt; (impl Fn(u32) -&gt; u32)</code></pre> 157<pre><code>impl Fn(u32) -&gt; (impl Fn(u32) -&gt; u32)</code></pre>
117<p>We can drop the parentheses because <code>-&gt;</code> is right associative:</p> 158<p>We can drop the parentheses because <code>-&gt;</code> is right
159associative:</p>
118<pre><code>impl Fn(u32) -&gt; impl Fn(u32) -&gt; u32 160<pre><code>impl Fn(u32) -&gt; impl Fn(u32) -&gt; u32
119</code></pre> 161</code></pre>
120<p><strong>Accessing environment</strong><br /> 162<p><strong>Accessing environment</strong><br />
121A function cannot access it’s environment. Our solution will not work. <code>add_curried3</code> attempts to access <code>x</code>, which is not allowed! A closure<a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a> however, can. If we are returning a closure, our return type must be <code>impl Fn</code>, and not <code>fn</code>. The difference between the <code>Fn</code> trait and function pointers is beyond the scope of this post.</p> 163A function cannot access it’s environment. Our solution will not work.
164<code>add_curried3</code> attempts to access <code>x</code>, which is
165not allowed! A closure<a href="#fn1" class="footnote-ref" id="fnref1"
166role="doc-noteref"><sup>1</sup></a> however, can. If we are returning a
167closure, our return type must be <code>impl Fn</code>, and not
168<code>fn</code>. The difference between the <code>Fn</code> trait and
169function pointers is beyond the scope of this post.</p>
122<h3 id="refinement">Refinement</h3> 170<h3 id="refinement">Refinement</h3>
123<p>Armed with knowledge, we refine our expected output, this time, employing closures:</p> 171<p>Armed with knowledge, we refine our expected output, this time,
124<div class="sourceCode" id="cb8"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> add(x<span class="op">:</span> <span class="dt">u32</span>) <span class="op">-&gt;</span> <span class="kw">impl</span> <span class="bu">Fn</span>(<span class="dt">u32</span>) <span class="op">-&gt;</span> <span class="kw">impl</span> <span class="bu">Fn</span>(<span class="dt">u32</span>) <span class="op">-&gt;</span> <span class="dt">u32</span> <span class="op">{</span></span> 172employing closures:</p>
125<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a> <span class="kw">return</span> <span class="kw">move</span> <span class="op">|</span>y<span class="op">|</span> <span class="kw">move</span> <span class="op">|</span>z<span class="op">|</span> x <span class="op">+</span> y <span class="op">+</span> z<span class="op">;</span></span> 173<div class="sourceCode" id="cb8"><pre
174class="sourceCode rust"><code class="sourceCode rust"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> add(x<span class="op">:</span> <span class="dt">u32</span>) <span class="op">-&gt;</span> <span class="kw">impl</span> <span class="bu">Fn</span>(<span class="dt">u32</span>) <span class="op">-&gt;</span> <span class="kw">impl</span> <span class="bu">Fn</span>(<span class="dt">u32</span>) <span class="op">-&gt;</span> <span class="dt">u32</span> <span class="op">{</span></span>
175<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> <span class="kw">move</span> <span class="op">|</span>y<span class="op">|</span> <span class="kw">move</span> <span class="op">|</span>z<span class="op">|</span> x <span class="op">+</span> y <span class="op">+</span> z<span class="op">;</span></span>
126<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div> 176<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
127<p>Alas, that does not compile either! It errors out with the following message:</p> 177<p>Alas, that does not compile either! It errors out with the following
178message:</p>
128<pre><code>error[E0562]: `impl Trait` not allowed outside of function 179<pre><code>error[E0562]: `impl Trait` not allowed outside of function
129and inherent method return types 180and inherent method return types
130 --&gt; src/main.rs:17:37 181 --&gt; src/main.rs:17:37
@@ -132,21 +183,33 @@ and inherent method return types
132 | fn add(x: u32) -&gt; impl Fn(u32) -&gt; impl Fn(u32) -&gt; u32 183 | fn add(x: u32) -&gt; impl Fn(u32) -&gt; impl Fn(u32) -&gt; u32
133 | ^^^^^^^^^^^^^^^^^^^ 184 | ^^^^^^^^^^^^^^^^^^^
134</code></pre> 185</code></pre>
135<p>You are allowed to return an <code>impl Fn</code> only inside a function. We are currently returning it from another return! Or at least, that was the most I could make out of the error message.</p> 186<p>You are allowed to return an <code>impl Fn</code> only inside a
136<p>We are going to have to cheat a bit to fix this issue; with type aliases and a convenient nightly feature <a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a>:</p> 187function. We are currently returning it from another return! Or at
137<div class="sourceCode" id="cb10"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="at">#![</span>feature<span class="at">(</span>type_alias_impl_trait<span class="at">)]</span> <span class="co">// allows us to use `impl Fn` in type aliases!</span></span> 188least, that was the most I could make out of the error message.</p>
189<p>We are going to have to cheat a bit to fix this issue; with type
190aliases and a convenient nightly feature <a href="#fn2"
191class="footnote-ref" id="fnref2"
192role="doc-noteref"><sup>2</sup></a>:</p>
193<div class="sourceCode" id="cb10"><pre
194class="sourceCode rust"><code class="sourceCode rust"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="at">#![</span>feature<span class="at">(</span>type_alias_impl_trait<span class="at">)]</span> <span class="co">// allows us to use `impl Fn` in type aliases!</span></span>
138<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a></span> 195<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a></span>
139<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> T0 <span class="op">=</span> <span class="dt">u32</span><span class="op">;</span> <span class="co">// the return value when zero args are to be applied</span></span> 196<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> T0 <span class="op">=</span> <span class="dt">u32</span><span class="op">;</span> <span class="co">// the return value when zero args are to be applied</span></span>
140<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> T1 <span class="op">=</span> <span class="kw">impl</span> <span class="bu">Fn</span>(<span class="dt">u32</span>) <span class="op">-&gt;</span> T0<span class="op">;</span> <span class="co">// the return value when one arg is to be applied</span></span> 197<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> T1 <span class="op">=</span> <span class="kw">impl</span> <span class="bu">Fn</span>(<span class="dt">u32</span>) <span class="op">-&gt;</span> T0<span class="op">;</span> <span class="co">// the return value when one arg is to be applied</span></span>
141<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> T2 <span class="op">=</span> <span class="kw">impl</span> <span class="bu">Fn</span>(<span class="dt">u32</span>) <span class="op">-&gt;</span> T1<span class="op">;</span> <span class="co">// the return value when two args are to be applied</span></span> 198<span id="cb10-5"><a href="#cb10-5" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> T2 <span class="op">=</span> <span class="kw">impl</span> <span class="bu">Fn</span>(<span class="dt">u32</span>) <span class="op">-&gt;</span> T1<span class="op">;</span> <span class="co">// the return value when two args are to be applied</span></span>
142<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a></span> 199<span id="cb10-6"><a href="#cb10-6" aria-hidden="true" tabindex="-1"></a></span>
143<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> add(x<span class="op">:</span> <span class="dt">u32</span>) <span class="op">-&gt;</span> T2 <span class="op">{</span></span> 200<span id="cb10-7"><a href="#cb10-7" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> add(x<span class="op">:</span> <span class="dt">u32</span>) <span class="op">-&gt;</span> T2 <span class="op">{</span></span>
144<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a> <span class="kw">return</span> <span class="kw">move</span> <span class="op">|</span>y<span class="op">|</span> <span class="kw">move</span> <span class="op">|</span>z<span class="op">|</span> x <span class="op">+</span> y <span class="op">+</span> z<span class="op">;</span></span> 201<span id="cb10-8"><a href="#cb10-8" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> <span class="kw">move</span> <span class="op">|</span>y<span class="op">|</span> <span class="kw">move</span> <span class="op">|</span>z<span class="op">|</span> x <span class="op">+</span> y <span class="op">+</span> z<span class="op">;</span></span>
145<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div> 202<span id="cb10-9"><a href="#cb10-9" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
146<p>Drop that into a cargo project, call <code>add(4)(5)(6)</code>, cross your fingers, and run <code>cargo +nightly run</code>. You should see a 15 unless you forgot to print it!</p> 203<p>Drop that into a cargo project, call <code>add(4)(5)(6)</code>, cross
204your fingers, and run <code>cargo +nightly run</code>. You should see a
20515 unless you forgot to print it!</p>
147<h3 id="the-in-betweens">The In-Betweens</h3> 206<h3 id="the-in-betweens">The In-Betweens</h3>
148<p>Let us write the magical bits that take us from function to curried function.</p> 207<p>Let us write the magical bits that take us from function to curried
149<p>Initialize your workspace with <code>cargo new --lib currying</code>. Proc-macro crates are libraries with exactly one export, the macro itself. Add a <code>tests</code> directory to your crate root. Your directory should look something like this:</p> 208function.</p>
209<p>Initialize your workspace with <code>cargo new --lib currying</code>.
210Proc-macro crates are libraries with exactly one export, the macro
211itself. Add a <code>tests</code> directory to your crate root. Your
212directory should look something like this:</p>
150<pre><code>. 213<pre><code>.
151├── Cargo.toml 214├── Cargo.toml
152├── src 215├── src
@@ -156,9 +219,11 @@ and inherent method return types
156<h4 id="dependencies">Dependencies</h4> 219<h4 id="dependencies">Dependencies</h4>
157<p>We will be using a total of 3 external crates:</p> 220<p>We will be using a total of 3 external crates:</p>
158<ul> 221<ul>
159<li><a href="https://docs.rs/proc-macro2/1.0.12/proc_macro2/">proc_macro2</a></li> 222<li><a
223href="https://docs.rs/proc-macro2/1.0.12/proc_macro2/">proc_macro2</a></li>
160<li><a href="https://docs.rs/syn/1.0.18/syn/index.html">syn</a></li> 224<li><a href="https://docs.rs/syn/1.0.18/syn/index.html">syn</a></li>
161<li><a href="https://docs.rs/quote/1.0.4/quote/index.html">quote</a></li> 225<li><a
226href="https://docs.rs/quote/1.0.4/quote/index.html">quote</a></li>
162</ul> 227</ul>
163<p>Here’s a sample <code>Cargo.toml</code>:</p> 228<p>Here’s a sample <code>Cargo.toml</code>:</p>
164<pre><code># Cargo.toml 229<pre><code># Cargo.toml
@@ -173,10 +238,12 @@ features = [&quot;full&quot;]
173 238
174[lib] 239[lib]
175proc-macro = true # this is important!</code></pre> 240proc-macro = true # this is important!</code></pre>
176<p>We will be using an external <code>proc-macro2</code> crate as well as an internal <code>proc-macro</code> crate. Not confusing at all!</p> 241<p>We will be using an external <code>proc-macro2</code> crate as well
242as an internal <code>proc-macro</code> crate. Not confusing at all!</p>
177<h4 id="the-attribute-macro">The attribute macro</h4> 243<h4 id="the-attribute-macro">The attribute macro</h4>
178<p>Drop this into <code>src/lib.rs</code>, to get the ball rolling.</p> 244<p>Drop this into <code>src/lib.rs</code>, to get the ball rolling.</p>
179<div class="sourceCode" id="cb13"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="co">// src/lib.rs</span></span> 245<div class="sourceCode" id="cb13"><pre
246class="sourceCode rust"><code class="sourceCode rust"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="co">// src/lib.rs</span></span>
180<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a></span> 247<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a></span>
181<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a><span class="kw">use</span> <span class="pp">proc_macro::</span>TokenStream<span class="op">;</span> <span class="co">// 1</span></span> 248<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a><span class="kw">use</span> <span class="pp">proc_macro::</span>TokenStream<span class="op">;</span> <span class="co">// 1</span></span>
182<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a><span class="kw">use</span> <span class="pp">quote::</span>quote<span class="op">;</span></span> 249<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a><span class="kw">use</span> <span class="pp">quote::</span>quote<span class="op">;</span></span>
@@ -190,17 +257,49 @@ proc-macro = true # this is important!</code></pre>
190<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a></span> 257<span id="cb13-12"><a href="#cb13-12" aria-hidden="true" tabindex="-1"></a></span>
191<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> generate_curry(parsed<span class="op">:</span> ItemFn) <span class="op">-&gt;</span> <span class="pp">proc_macro2::</span>TokenStream <span class="op">{}</span></span></code></pre></div> 258<span id="cb13-13"><a href="#cb13-13" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> generate_curry(parsed<span class="op">:</span> ItemFn) <span class="op">-&gt;</span> <span class="pp">proc_macro2::</span>TokenStream <span class="op">{}</span></span></code></pre></div>
192<p><strong>1. Imports</strong></p> 259<p><strong>1. Imports</strong></p>
193<p>A <code>Tokenstream</code> holds (hopefully valid) Rust code, this is the type of our input and output. Note that we are importing this type from <code>proc_macro</code> and not <code>proc_macro2</code>.</p> 260<p>A <code>Tokenstream</code> holds (hopefully valid) Rust code, this is
194<p><code>quote!</code> from the <code>quote</code> crate is a macro that allows us to quickly produce <code>TokenStream</code>s. Much like the LISP <code>quote</code> procedure, you can use the <code>quote!</code> macro for symbolic transformations.</p> 261the type of our input and output. Note that we are importing this type
195<p><code>ItemFn</code> from the <code>syn</code> crate holds the parsed <code>TokenStream</code> of a Rust function. <code>parse_macro_input!</code> is a helper macro provided by <code>syn</code>.</p> 262from <code>proc_macro</code> and not <code>proc_macro2</code>.</p>
263<p><code>quote!</code> from the <code>quote</code> crate is a macro that
264allows us to quickly produce <code>TokenStream</code>s. Much like the
265LISP <code>quote</code> procedure, you can use the <code>quote!</code>
266macro for symbolic transformations.</p>
267<p><code>ItemFn</code> from the <code>syn</code> crate holds the parsed
268<code>TokenStream</code> of a Rust function.
269<code>parse_macro_input!</code> is a helper macro provided by
270<code>syn</code>.</p>
196<p><strong>2. The lone export</strong></p> 271<p><strong>2. The lone export</strong></p>
197<p>Annotate the only <code>pub</code> of our crate with <code>#[proc_macro_attribute]</code>. This tells rustc that <code>curry</code> is a procedural macro, and allows us to use it as <code>#[crate_name::curry]</code> in other crates. Note the signature of the <code>curry</code> function. <code>_attr</code> is the <code>TokenStream</code> representing the attribute itself, <code>item</code> refers to the thing we slapped our macro into, in this case a function (like <code>add</code>). The return value is a modified <code>TokenStream</code>, this will contain our curried version of <code>add</code>.</p> 272<p>Annotate the only <code>pub</code> of our crate with
273<code>#[proc_macro_attribute]</code>. This tells rustc that
274<code>curry</code> is a procedural macro, and allows us to use it as
275<code>#[crate_name::curry]</code> in other crates. Note the signature of
276the <code>curry</code> function. <code>_attr</code> is the
277<code>TokenStream</code> representing the attribute itself,
278<code>item</code> refers to the thing we slapped our macro into, in this
279case a function (like <code>add</code>). The return value is a modified
280<code>TokenStream</code>, this will contain our curried version of
281<code>add</code>.</p>
198<p><strong>3. The helper macro</strong></p> 282<p><strong>3. The helper macro</strong></p>
199<p>A <code>TokenStream</code> is a little hard to work with, which is why we have the <code>syn</code> crate, which provides types to represent Rust tokens. An <code>RArrow</code> struct to represent the return arrow on a function and so on. One of those types is <code>ItemFn</code>, that represents an entire Rust function. The <code>parse_macro_input!</code> automatically puts the input to our macro into an <code>ItemFn</code>. What a gentleman!</p> 283<p>A <code>TokenStream</code> is a little hard to work with, which is
284why we have the <code>syn</code> crate, which provides types to
285represent Rust tokens. An <code>RArrow</code> struct to represent the
286return arrow on a function and so on. One of those types is
287<code>ItemFn</code>, that represents an entire Rust function. The
288<code>parse_macro_input!</code> automatically puts the input to our
289macro into an <code>ItemFn</code>. What a gentleman!</p>
200<p><strong>4. Returning <code>TokenStream</code>s </strong></p> 290<p><strong>4. Returning <code>TokenStream</code>s </strong></p>
201<p>We haven’t filled in <code>generate_curry</code> yet, but we can see that it returns a <code>proc_macro2::TokenStream</code> and not a <code>proc_macro::TokenStream</code>, so drop a <code>.into()</code> to convert it.</p> 291<p>We haven’t filled in <code>generate_curry</code> yet, but we can see
202<p>Lets move on, and fill in <code>generate_curry</code>, I would suggest keeping the documentation for <a href="https://docs.rs/syn/1.0.19/syn/struct.ItemFn.html"><code>syn::ItemFn</code></a> and <a href="https://docs.rs/syn/1.0.19/syn/struct.Signature.html"><code>syn::Signature</code></a> open.</p> 292that it returns a <code>proc_macro2::TokenStream</code> and not a
203<div class="sourceCode" id="cb14"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="co">// src/lib.rs</span></span> 293<code>proc_macro::TokenStream</code>, so drop a <code>.into()</code> to
294convert it.</p>
295<p>Lets move on, and fill in <code>generate_curry</code>, I would
296suggest keeping the documentation for <a
297href="https://docs.rs/syn/1.0.19/syn/struct.ItemFn.html"><code>syn::ItemFn</code></a>
298and <a
299href="https://docs.rs/syn/1.0.19/syn/struct.Signature.html"><code>syn::Signature</code></a>
300open.</p>
301<div class="sourceCode" id="cb14"><pre
302class="sourceCode rust"><code class="sourceCode rust"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="co">// src/lib.rs</span></span>
204<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a></span> 303<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a></span>
205<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> generate_curry(parsed<span class="op">:</span> ItemFn) <span class="op">-&gt;</span> <span class="pp">proc_macro2::</span>TokenStream <span class="op">{</span></span> 304<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> generate_curry(parsed<span class="op">:</span> ItemFn) <span class="op">-&gt;</span> <span class="pp">proc_macro2::</span>TokenStream <span class="op">{</span></span>
206<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a> <span class="kw">let</span> fn_body <span class="op">=</span> parsed<span class="op">.</span>block<span class="op">;</span> <span class="co">// function body</span></span> 305<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a> <span class="kw">let</span> fn_body <span class="op">=</span> parsed<span class="op">.</span>block<span class="op">;</span> <span class="co">// function body</span></span>
@@ -210,7 +309,9 @@ proc-macro = true # this is important!</code></pre>
210<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a> <span class="kw">let</span> fn_args <span class="op">=</span> sig<span class="op">.</span>inputs<span class="op">;</span> <span class="co">// comma separated args</span></span> 309<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a> <span class="kw">let</span> fn_args <span class="op">=</span> sig<span class="op">.</span>inputs<span class="op">;</span> <span class="co">// comma separated args</span></span>
211<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a> <span class="kw">let</span> fn_return_type <span class="op">=</span> sig<span class="op">.</span>output<span class="op">;</span> <span class="co">// return type</span></span> 310<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a> <span class="kw">let</span> fn_return_type <span class="op">=</span> sig<span class="op">.</span>output<span class="op">;</span> <span class="co">// return type</span></span>
212<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div> 311<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
213<p>We are simply extracting the bits of the function, we will be reusing the original function’s visibility and name. Take a look at what <code>syn::Signature</code> can tell us about a function:</p> 312<p>We are simply extracting the bits of the function, we will be reusing
313the original function’s visibility and name. Take a look at what
314<code>syn::Signature</code> can tell us about a function:</p>
214<pre><code> .-- syn::Ident (ident) 315<pre><code> .-- syn::Ident (ident)
215 / 316 /
216 fn add(x: u32, y: u32) -&gt; u32 317 fn add(x: u32, y: u32) -&gt; u32
@@ -220,42 +321,77 @@ syn::token::Fn --&#39; / \ (output)
220 Punctuated&lt;FnArg, Comma&gt; (inputs)</code></pre> 321 Punctuated&lt;FnArg, Comma&gt; (inputs)</code></pre>
221<p>Enough analysis, lets produce our first bit of Rust code.</p> 322<p>Enough analysis, lets produce our first bit of Rust code.</p>
222<h4 id="function-body">Function Body</h4> 323<h4 id="function-body">Function Body</h4>
223<p>Recall that the body of a curried <code>add</code> should look like this:</p> 324<p>Recall that the body of a curried <code>add</code> should look like
224<div class="sourceCode" id="cb16"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="kw">return</span> <span class="kw">move</span> <span class="op">|</span>y<span class="op">|</span> <span class="kw">move</span> <span class="op">|</span>z<span class="op">|</span> x <span class="op">+</span> y <span class="op">+</span> z<span class="op">;</span></span></code></pre></div> 325this:</p>
326<div class="sourceCode" id="cb16"><pre
327class="sourceCode rust"><code class="sourceCode rust"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> <span class="kw">move</span> <span class="op">|</span>y<span class="op">|</span> <span class="kw">move</span> <span class="op">|</span>z<span class="op">|</span> x <span class="op">+</span> y <span class="op">+</span> z<span class="op">;</span></span></code></pre></div>
225<p>And in general:</p> 328<p>And in general:</p>
226<div class="sourceCode" id="cb17"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="kw">return</span> <span class="kw">move</span> <span class="op">|</span>arg2<span class="op">|</span> <span class="kw">move</span> <span class="op">|</span>arg3<span class="op">|</span> <span class="op">...</span> <span class="op">|</span>argN<span class="op">|</span> <span class="op">&lt;</span>function body here<span class="op">&gt;</span></span></code></pre></div> 329<div class="sourceCode" id="cb17"><pre
227<p>We already have the function’s body, provided by <code>fn_body</code>, in our <code>generate_curry</code> function. All that’s left to add is the <code>move |arg2| move |arg3| ...</code> stuff, for which we need to extract the argument identifiers (doc: <a href="https://docs.rs/syn/1.0.18/syn/punctuated/struct.Punctuated.html">Punctuated</a>, <a href="https://docs.rs/syn/1.0.18/syn/enum.FnArg.html">FnArg</a>, <a href="https://docs.rs/syn/1.0.18/syn/struct.PatType.html">PatType</a>):</p> 330class="sourceCode rust"><code class="sourceCode rust"><span id="cb17-1"><a href="#cb17-1" aria-hidden="true" tabindex="-1"></a><span class="cf">return</span> <span class="kw">move</span> <span class="op">|</span>arg2<span class="op">|</span> <span class="kw">move</span> <span class="op">|</span>arg3<span class="op">|</span> <span class="op">...</span> <span class="op">|</span>argN<span class="op">|</span> <span class="op">&lt;</span>function body here<span class="op">&gt;</span></span></code></pre></div>
228<div class="sourceCode" id="cb18"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="co">// src/lib.rs</span></span> 331<p>We already have the function’s body, provided by
332<code>fn_body</code>, in our <code>generate_curry</code> function. All
333that’s left to add is the <code>move |arg2| move |arg3| ...</code>
334stuff, for which we need to extract the argument identifiers (doc: <a
335href="https://docs.rs/syn/1.0.18/syn/punctuated/struct.Punctuated.html">Punctuated</a>,
336<a href="https://docs.rs/syn/1.0.18/syn/enum.FnArg.html">FnArg</a>, <a
337href="https://docs.rs/syn/1.0.18/syn/struct.PatType.html">PatType</a>):</p>
338<div class="sourceCode" id="cb18"><pre
339class="sourceCode rust"><code class="sourceCode rust"><span id="cb18-1"><a href="#cb18-1" aria-hidden="true" tabindex="-1"></a><span class="co">// src/lib.rs</span></span>
229<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a><span class="kw">use</span> <span class="pp">syn::punctuated::</span>Punctuated<span class="op">;</span></span> 340<span id="cb18-2"><a href="#cb18-2" aria-hidden="true" tabindex="-1"></a><span class="kw">use</span> <span class="pp">syn::punctuated::</span>Punctuated<span class="op">;</span></span>
230<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a><span class="kw">use</span> <span class="pp">syn::</span><span class="op">{</span>parse_macro_input<span class="op">,</span> FnArg<span class="op">,</span> Pat<span class="op">,</span> ItemFn<span class="op">,</span> Block<span class="op">};</span></span> 341<span id="cb18-3"><a href="#cb18-3" aria-hidden="true" tabindex="-1"></a><span class="kw">use</span> <span class="pp">syn::</span><span class="op">{</span>parse_macro_input<span class="op">,</span> FnArg<span class="op">,</span> Pat<span class="op">,</span> ItemFn<span class="op">,</span> Block<span class="op">};</span></span>
231<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a></span> 342<span id="cb18-4"><a href="#cb18-4" aria-hidden="true" tabindex="-1"></a></span>
232<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> extract_arg_idents(fn_args<span class="op">:</span> Punctuated<span class="op">&lt;</span>FnArg<span class="op">,</span> <span class="pp">syn::token::</span>Comma<span class="op">&gt;</span>) <span class="op">-&gt;</span> <span class="dt">Vec</span><span class="op">&lt;</span><span class="dt">Box</span><span class="op">&lt;</span>Pat<span class="op">&gt;&gt;</span> <span class="op">{</span> </span> 343<span id="cb18-5"><a href="#cb18-5" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> extract_arg_idents(fn_args<span class="op">:</span> Punctuated<span class="op">&lt;</span>FnArg<span class="op">,</span> <span class="pp">syn::token::</span>Comma<span class="op">&gt;</span>) <span class="op">-&gt;</span> <span class="dt">Vec</span><span class="op">&lt;</span><span class="dt">Box</span><span class="op">&lt;</span>Pat<span class="op">&gt;&gt;</span> <span class="op">{</span> </span>
233<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a> <span class="kw">return</span> fn_args<span class="op">.</span>into_iter()<span class="op">.</span>map(extract_arg_pat)<span class="op">.</span><span class="pp">collect::</span><span class="op">&lt;</span><span class="dt">Vec</span><span class="op">&lt;</span>_<span class="op">&gt;&gt;</span>()<span class="op">;</span></span> 344<span id="cb18-6"><a href="#cb18-6" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> fn_args<span class="op">.</span>into_iter()<span class="op">.</span>map(extract_arg_pat)<span class="op">.</span><span class="pp">collect::</span><span class="op">&lt;</span><span class="dt">Vec</span><span class="op">&lt;</span>_<span class="op">&gt;&gt;</span>()<span class="op">;</span></span>
234<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div> 345<span id="cb18-7"><a href="#cb18-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
235<p>Alright, so we are iterating over function args (<code>Punctuated</code> is a collection that you can iterate over) and mapping an <code>extract_arg_pat</code> to every item. What’s <code>extract_arg_pat</code>?</p> 346<p>Alright, so we are iterating over function args
236<div class="sourceCode" id="cb19"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="co">// src/lib.rs</span></span> 347(<code>Punctuated</code> is a collection that you can iterate over) and
348mapping an <code>extract_arg_pat</code> to every item. What’s
349<code>extract_arg_pat</code>?</p>
350<div class="sourceCode" id="cb19"><pre
351class="sourceCode rust"><code class="sourceCode rust"><span id="cb19-1"><a href="#cb19-1" aria-hidden="true" tabindex="-1"></a><span class="co">// src/lib.rs</span></span>
237<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a></span> 352<span id="cb19-2"><a href="#cb19-2" aria-hidden="true" tabindex="-1"></a></span>
238<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> extract_arg_pat(a<span class="op">:</span> FnArg) <span class="op">-&gt;</span> <span class="dt">Box</span><span class="op">&lt;</span>Pat<span class="op">&gt;</span> <span class="op">{</span></span> 353<span id="cb19-3"><a href="#cb19-3" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> extract_arg_pat(a<span class="op">:</span> FnArg) <span class="op">-&gt;</span> <span class="dt">Box</span><span class="op">&lt;</span>Pat<span class="op">&gt;</span> <span class="op">{</span></span>
239<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a> <span class="kw">match</span> a <span class="op">{</span></span> 354<span id="cb19-4"><a href="#cb19-4" aria-hidden="true" tabindex="-1"></a> <span class="cf">match</span> a <span class="op">{</span></span>
240<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a> <span class="pp">FnArg::</span>Typed(p) <span class="op">=&gt;</span> p<span class="op">.</span>pat<span class="op">,</span></span> 355<span id="cb19-5"><a href="#cb19-5" aria-hidden="true" tabindex="-1"></a> <span class="pp">FnArg::</span>Typed(p) <span class="op">=&gt;</span> p<span class="op">.</span>pat<span class="op">,</span></span>
241<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a> _ <span class="op">=&gt;</span> <span class="pp">panic!</span>(<span class="st">&quot;Not supported on types with `self`!&quot;</span>)<span class="op">,</span></span> 356<span id="cb19-6"><a href="#cb19-6" aria-hidden="true" tabindex="-1"></a> _ <span class="op">=&gt;</span> <span class="pp">panic!</span>(<span class="st">&quot;Not supported on types with `self`!&quot;</span>)<span class="op">,</span></span>
242<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span> 357<span id="cb19-7"><a href="#cb19-7" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
243<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div> 358<span id="cb19-8"><a href="#cb19-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
244<p><code>FnArg</code> is an enum type as you might have guessed. The <code>Typed</code> variant encompasses args that are written as <code>name: type</code> and the other variant, <code>Reciever</code> refers to <code>self</code> types. Ignore those for now, keep it simple.</p> 359<p><code>FnArg</code> is an enum type as you might have guessed. The
245<p>Every <code>FnArg::Typed</code> value contains a <code>pat</code>, which is in essence, the name of the argument. The type of the arg is accessible via <code>p.ty</code> (we will be using this later).</p> 360<code>Typed</code> variant encompasses args that are written as
246<p>With that done, we should be able to write the codegen for the function body:</p> 361<code>name: type</code> and the other variant, <code>Reciever</code>
247<div class="sourceCode" id="cb20"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="co">// src/lib.rs</span></span> 362refers to <code>self</code> types. Ignore those for now, keep it
363simple.</p>
364<p>Every <code>FnArg::Typed</code> value contains a <code>pat</code>,
365which is in essence, the name of the argument. The type of the arg is
366accessible via <code>p.ty</code> (we will be using this later).</p>
367<p>With that done, we should be able to write the codegen for the
368function body:</p>
369<div class="sourceCode" id="cb20"><pre
370class="sourceCode rust"><code class="sourceCode rust"><span id="cb20-1"><a href="#cb20-1" aria-hidden="true" tabindex="-1"></a><span class="co">// src/lib.rs</span></span>
248<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a></span> 371<span id="cb20-2"><a href="#cb20-2" aria-hidden="true" tabindex="-1"></a></span>
249<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> generate_body(fn_args<span class="op">:</span> <span class="op">&amp;</span>[<span class="dt">Box</span><span class="op">&lt;</span>Pat<span class="op">&gt;</span>]<span class="op">,</span> body<span class="op">:</span> <span class="dt">Box</span><span class="op">&lt;</span>Block<span class="op">&gt;</span>) <span class="op">-&gt;</span> <span class="pp">proc_macro2::</span>TokenStream <span class="op">{</span></span> 372<span id="cb20-3"><a href="#cb20-3" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> generate_body(fn_args<span class="op">:</span> <span class="op">&amp;</span>[<span class="dt">Box</span><span class="op">&lt;</span>Pat<span class="op">&gt;</span>]<span class="op">,</span> body<span class="op">:</span> <span class="dt">Box</span><span class="op">&lt;</span>Block<span class="op">&gt;</span>) <span class="op">-&gt;</span> <span class="pp">proc_macro2::</span>TokenStream <span class="op">{</span></span>
250<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a> <span class="pp">quote!</span> <span class="op">{</span></span> 373<span id="cb20-4"><a href="#cb20-4" aria-hidden="true" tabindex="-1"></a> <span class="pp">quote!</span> <span class="op">{</span></span>
251<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a> <span class="kw">return</span> #( <span class="kw">move</span> <span class="op">|</span>#fn_args<span class="op">|</span> )<span class="op">*</span> #body</span> 374<span id="cb20-5"><a href="#cb20-5" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> #( <span class="kw">move</span> <span class="op">|</span>#fn_args<span class="op">|</span> )<span class="op">*</span> #body</span>
252<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span> 375<span id="cb20-6"><a href="#cb20-6" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
253<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div> 376<span id="cb20-7"><a href="#cb20-7" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
254<p>That is some scary looking syntax! Allow me to explain. The <code>quote!{ ... }</code> returns a <code>proc_macro2::TokenStream</code>, if we wrote <code>quote!{ let x = 1 + 2; }</code>, it wouldn’t create a new variable <code>x</code> with value 3, it would literally produce a stream of tokens with that expression.</p> 377<p>That is some scary looking syntax! Allow me to explain. The
255<p>The <code>#</code> enables variable interpolation. <code>#body</code> will look for <code>body</code> in the current scope, take its value, and insert it in the returned <code>TokenStream</code>. Kinda like quasi quoting in LISPs, you have written one.</p> 378<code>quote!{ ... }</code> returns a
256<p>What about <code>#( move |#fn_args| )*</code>? That is repetition. <code>quote</code> iterates through <code>fn_args</code>, and drops a <code>move</code> behind each one, it then places pipes (<code>|</code>), around it.</p> 379<code>proc_macro2::TokenStream</code>, if we wrote
257<p>Let us test our first bit of codegen! Modify <code>generate_curry</code> like so:</p> 380<code>quote!{ let x = 1 + 2; }</code>, it wouldn’t create a new variable
258<div class="sourceCode" id="cb21"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="co">// src/lib.rs</span></span> 381<code>x</code> with value 3, it would literally produce a stream of
382tokens with that expression.</p>
383<p>The <code>#</code> enables variable interpolation. <code>#body</code>
384will look for <code>body</code> in the current scope, take its value,
385and insert it in the returned <code>TokenStream</code>. Kinda like quasi
386quoting in LISPs, you have written one.</p>
387<p>What about <code>#( move |#fn_args| )*</code>? That is repetition.
388<code>quote</code> iterates through <code>fn_args</code>, and drops a
389<code>move</code> behind each one, it then places pipes
390(<code>|</code>), around it.</p>
391<p>Let us test our first bit of codegen! Modify
392<code>generate_curry</code> like so:</p>
393<div class="sourceCode" id="cb21"><pre
394class="sourceCode rust"><code class="sourceCode rust"><span id="cb21-1"><a href="#cb21-1" aria-hidden="true" tabindex="-1"></a><span class="co">// src/lib.rs</span></span>
259<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a></span> 395<span id="cb21-2"><a href="#cb21-2" aria-hidden="true" tabindex="-1"></a></span>
260<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">fn</span> generate_curry(parsed<span class="op">:</span> ItemFn) <span class="op">-&gt;</span> TokenStream <span class="op">{</span></span> 396<span id="cb21-3"><a href="#cb21-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">fn</span> generate_curry(parsed<span class="op">:</span> ItemFn) <span class="op">-&gt;</span> TokenStream <span class="op">{</span></span>
261<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a> <span class="kw">let</span> fn_body <span class="op">=</span> parsed<span class="op">.</span>block<span class="op">;</span></span> 397<span id="cb21-4"><a href="#cb21-4" aria-hidden="true" tabindex="-1"></a> <span class="kw">let</span> fn_body <span class="op">=</span> parsed<span class="op">.</span>block<span class="op">;</span></span>
@@ -272,10 +408,11 @@ syn::token::Fn --&#39; / \ (output)
272<span id="cb21-15"><a href="#cb21-15" aria-hidden="true" tabindex="-1"></a><span class="op">+</span> <span class="kw">let</span> curried_body <span class="op">=</span> generate_body(<span class="op">&amp;</span>arg_idents[<span class="dv">1</span><span class="op">..</span>]<span class="op">,</span> fn_body<span class="op">.</span>clone())<span class="op">;</span></span> 408<span id="cb21-15"><a href="#cb21-15" aria-hidden="true" tabindex="-1"></a><span class="op">+</span> <span class="kw">let</span> curried_body <span class="op">=</span> generate_body(<span class="op">&amp;</span>arg_idents[<span class="dv">1</span><span class="op">..</span>]<span class="op">,</span> fn_body<span class="op">.</span>clone())<span class="op">;</span></span>
273<span id="cb21-16"><a href="#cb21-16" aria-hidden="true" tabindex="-1"></a><span class="op">+</span> <span class="pp">println!</span>(<span class="st">&quot;{}&quot;</span><span class="op">,</span> curried_body)<span class="op">;</span></span> 409<span id="cb21-16"><a href="#cb21-16" aria-hidden="true" tabindex="-1"></a><span class="op">+</span> <span class="pp">println!</span>(<span class="st">&quot;{}&quot;</span><span class="op">,</span> curried_body)<span class="op">;</span></span>
274<span id="cb21-17"><a href="#cb21-17" aria-hidden="true" tabindex="-1"></a></span> 410<span id="cb21-17"><a href="#cb21-17" aria-hidden="true" tabindex="-1"></a></span>
275<span id="cb21-18"><a href="#cb21-18" aria-hidden="true" tabindex="-1"></a> <span class="kw">return</span> <span class="pp">TokenStream::</span>new()<span class="op">;</span></span> 411<span id="cb21-18"><a href="#cb21-18" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> <span class="pp">TokenStream::</span>new()<span class="op">;</span></span>
276<span id="cb21-19"><a href="#cb21-19" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span></code></pre></div> 412<span id="cb21-19"><a href="#cb21-19" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span></code></pre></div>
277<p>Add a little test to <code>tests/</code>:</p> 413<p>Add a little test to <code>tests/</code>:</p>
278<div class="sourceCode" id="cb22"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="co">// tests/smoke.rs</span></span> 414<div class="sourceCode" id="cb22"><pre
415class="sourceCode rust"><code class="sourceCode rust"><span id="cb22-1"><a href="#cb22-1" aria-hidden="true" tabindex="-1"></a><span class="co">// tests/smoke.rs</span></span>
279<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a></span> 416<span id="cb22-2"><a href="#cb22-2" aria-hidden="true" tabindex="-1"></a></span>
280<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span><span class="pp">currying::</span>curry<span class="at">]</span></span> 417<span id="cb22-3"><a href="#cb22-3" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span><span class="pp">currying::</span>curry<span class="at">]</span></span>
281<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> add(x<span class="op">:</span> <span class="dt">u32</span><span class="op">,</span> y<span class="op">:</span> <span class="dt">u32</span><span class="op">,</span> z<span class="op">:</span> <span class="dt">u32</span>) <span class="op">-&gt;</span> <span class="dt">u32</span> <span class="op">{</span></span> 418<span id="cb22-4"><a href="#cb22-4" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> add(x<span class="op">:</span> <span class="dt">u32</span><span class="op">,</span> y<span class="op">:</span> <span class="dt">u32</span><span class="op">,</span> z<span class="op">:</span> <span class="dt">u32</span>) <span class="op">-&gt;</span> <span class="dt">u32</span> <span class="op">{</span></span>
@@ -286,17 +423,23 @@ syn::token::Fn --&#39; / \ (output)
286<span id="cb22-9"><a href="#cb22-9" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> works() <span class="op">{</span></span> 423<span id="cb22-9"><a href="#cb22-9" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> works() <span class="op">{</span></span>
287<span id="cb22-10"><a href="#cb22-10" aria-hidden="true" tabindex="-1"></a> <span class="pp">assert!</span>(<span class="cn">true</span>)<span class="op">;</span></span> 424<span id="cb22-10"><a href="#cb22-10" aria-hidden="true" tabindex="-1"></a> <span class="pp">assert!</span>(<span class="cn">true</span>)<span class="op">;</span></span>
288<span id="cb22-11"><a href="#cb22-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div> 425<span id="cb22-11"><a href="#cb22-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
289<p>You should find something like this in the output of <code>cargo test</code>:</p> 426<p>You should find something like this in the output of
427<code>cargo test</code>:</p>
290<pre><code>return move | y | move | z | { x + y + z }</code></pre> 428<pre><code>return move | y | move | z | { x + y + z }</code></pre>
291<p>Glorious <code>println!</code> debugging!</p> 429<p>Glorious <code>println!</code> debugging!</p>
292<h4 id="function-signature">Function signature</h4> 430<h4 id="function-signature">Function signature</h4>
293<p>This section gets into the more complicated bits of the macro, generating type aliases and the function signature. By the end of this section, we should have a full working auto-currying macro!</p> 431<p>This section gets into the more complicated bits of the macro,
294<p>Recall what our generated type aliases should look like, for our <code>add</code> function:</p> 432generating type aliases and the function signature. By the end of this
295<div class="sourceCode" id="cb24"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> T0 <span class="op">=</span> <span class="dt">u32</span><span class="op">;</span></span> 433section, we should have a full working auto-currying macro!</p>
434<p>Recall what our generated type aliases should look like, for our
435<code>add</code> function:</p>
436<div class="sourceCode" id="cb24"><pre
437class="sourceCode rust"><code class="sourceCode rust"><span id="cb24-1"><a href="#cb24-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> T0 <span class="op">=</span> <span class="dt">u32</span><span class="op">;</span></span>
296<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> T1 <span class="op">=</span> <span class="kw">impl</span> <span class="bu">Fn</span>(<span class="dt">u32</span>) <span class="op">-&gt;</span> T0<span class="op">;</span></span> 438<span id="cb24-2"><a href="#cb24-2" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> T1 <span class="op">=</span> <span class="kw">impl</span> <span class="bu">Fn</span>(<span class="dt">u32</span>) <span class="op">-&gt;</span> T0<span class="op">;</span></span>
297<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> T2 <span class="op">=</span> <span class="kw">impl</span> <span class="bu">Fn</span>(<span class="dt">u32</span>) <span class="op">-&gt;</span> T1<span class="op">;</span></span></code></pre></div> 439<span id="cb24-3"><a href="#cb24-3" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> T2 <span class="op">=</span> <span class="kw">impl</span> <span class="bu">Fn</span>(<span class="dt">u32</span>) <span class="op">-&gt;</span> T1<span class="op">;</span></span></code></pre></div>
298<p>In general:</p> 440<p>In general:</p>
299<div class="sourceCode" id="cb25"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> T0 <span class="op">=</span> <span class="op">&lt;</span><span class="kw">return</span> <span class="kw">type</span>&gt;<span class="op">;</span></span> 441<div class="sourceCode" id="cb25"><pre
442class="sourceCode rust"><code class="sourceCode rust"><span id="cb25-1"><a href="#cb25-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> T0 <span class="op">=</span> <span class="op">&lt;</span><span class="cf">return</span> <span class="kw">type</span>&gt;<span class="op">;</span></span>
300<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> T1 <span class="op">=</span> <span class="kw">impl</span> <span class="bu">Fn</span>(<span class="op">&lt;</span><span class="kw">type</span> of arg N&gt;) -&gt; T0<span class="op">;</span></span> 443<span id="cb25-2"><a href="#cb25-2" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> T1 <span class="op">=</span> <span class="kw">impl</span> <span class="bu">Fn</span>(<span class="op">&lt;</span><span class="kw">type</span> of arg N&gt;) -&gt; T0<span class="op">;</span></span>
301<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> T2 <span class="op">=</span> <span class="kw">impl</span> <span class="bu">Fn</span>(<span class="op">&lt;</span><span class="kw">type</span> of arg N - 1&gt;) -&gt; T1<span class="op">;</span></span> 444<span id="cb25-3"><a href="#cb25-3" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> T2 <span class="op">=</span> <span class="kw">impl</span> <span class="bu">Fn</span>(<span class="op">&lt;</span><span class="kw">type</span> of arg N - 1&gt;) -&gt; T1<span class="op">;</span></span>
302<span id="cb25-4"><a href="#cb25-4" aria-hidden="true" tabindex="-1"></a><span class="op">.</span></span> 445<span id="cb25-4"><a href="#cb25-4" aria-hidden="true" tabindex="-1"></a><span class="op">.</span></span>
@@ -308,42 +451,59 @@ syn::token::Fn --&#39; / \ (output)
308<li>all our inputs (arguments)</li> 451<li>all our inputs (arguments)</li>
309<li>the output (the return type)</li> 452<li>the output (the return type)</li>
310</ul> 453</ul>
311<p>To fetch the types of all our inputs, we can simply reuse the bits we wrote to fetch the names of all our inputs! (doc: <a href="https://docs.rs/syn/1.0.18/syn/enum.Type.html">Type</a>)</p> 454<p>To fetch the types of all our inputs, we can simply reuse the bits we
312<div class="sourceCode" id="cb26"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a><span class="co">// src/lib.rs</span></span> 455wrote to fetch the names of all our inputs! (doc: <a
456href="https://docs.rs/syn/1.0.18/syn/enum.Type.html">Type</a>)</p>
457<div class="sourceCode" id="cb26"><pre
458class="sourceCode rust"><code class="sourceCode rust"><span id="cb26-1"><a href="#cb26-1" aria-hidden="true" tabindex="-1"></a><span class="co">// src/lib.rs</span></span>
313<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a></span> 459<span id="cb26-2"><a href="#cb26-2" aria-hidden="true" tabindex="-1"></a></span>
314<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a><span class="kw">use</span> <span class="pp">syn::</span><span class="op">{</span>parse_macro_input<span class="op">,</span> Block<span class="op">,</span> FnArg<span class="op">,</span> ItemFn<span class="op">,</span> Pat<span class="op">,</span> ReturnType<span class="op">,</span> Type<span class="op">};</span></span> 460<span id="cb26-3"><a href="#cb26-3" aria-hidden="true" tabindex="-1"></a><span class="kw">use</span> <span class="pp">syn::</span><span class="op">{</span>parse_macro_input<span class="op">,</span> Block<span class="op">,</span> FnArg<span class="op">,</span> ItemFn<span class="op">,</span> Pat<span class="op">,</span> ReturnType<span class="op">,</span> Type<span class="op">};</span></span>
315<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a></span> 461<span id="cb26-4"><a href="#cb26-4" aria-hidden="true" tabindex="-1"></a></span>
316<span id="cb26-5"><a href="#cb26-5" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> extract_type(a<span class="op">:</span> FnArg) <span class="op">-&gt;</span> <span class="dt">Box</span><span class="op">&lt;</span>Type<span class="op">&gt;</span> <span class="op">{</span></span> 462<span id="cb26-5"><a href="#cb26-5" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> extract_type(a<span class="op">:</span> FnArg) <span class="op">-&gt;</span> <span class="dt">Box</span><span class="op">&lt;</span>Type<span class="op">&gt;</span> <span class="op">{</span></span>
317<span id="cb26-6"><a href="#cb26-6" aria-hidden="true" tabindex="-1"></a> <span class="kw">match</span> a <span class="op">{</span></span> 463<span id="cb26-6"><a href="#cb26-6" aria-hidden="true" tabindex="-1"></a> <span class="cf">match</span> a <span class="op">{</span></span>
318<span id="cb26-7"><a href="#cb26-7" aria-hidden="true" tabindex="-1"></a> <span class="pp">FnArg::</span>Typed(p) <span class="op">=&gt;</span> p<span class="op">.</span>ty<span class="op">,</span> <span class="co">// notice `ty` instead of `pat`</span></span> 464<span id="cb26-7"><a href="#cb26-7" aria-hidden="true" tabindex="-1"></a> <span class="pp">FnArg::</span>Typed(p) <span class="op">=&gt;</span> p<span class="op">.</span>ty<span class="op">,</span> <span class="co">// notice `ty` instead of `pat`</span></span>
319<span id="cb26-8"><a href="#cb26-8" aria-hidden="true" tabindex="-1"></a> _ <span class="op">=&gt;</span> <span class="pp">panic!</span>(<span class="st">&quot;Not supported on types with `self`!&quot;</span>)<span class="op">,</span></span> 465<span id="cb26-8"><a href="#cb26-8" aria-hidden="true" tabindex="-1"></a> _ <span class="op">=&gt;</span> <span class="pp">panic!</span>(<span class="st">&quot;Not supported on types with `self`!&quot;</span>)<span class="op">,</span></span>
320<span id="cb26-9"><a href="#cb26-9" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span> 466<span id="cb26-9"><a href="#cb26-9" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
321<span id="cb26-10"><a href="#cb26-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span> 467<span id="cb26-10"><a href="#cb26-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
322<span id="cb26-11"><a href="#cb26-11" aria-hidden="true" tabindex="-1"></a></span> 468<span id="cb26-11"><a href="#cb26-11" aria-hidden="true" tabindex="-1"></a></span>
323<span id="cb26-12"><a href="#cb26-12" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> extract_arg_types(fn_args<span class="op">:</span> Punctuated<span class="op">&lt;</span>FnArg<span class="op">,</span> <span class="pp">syn::token::</span>Comma<span class="op">&gt;</span>) <span class="op">-&gt;</span> <span class="dt">Vec</span><span class="op">&lt;</span><span class="dt">Box</span><span class="op">&lt;</span>Type<span class="op">&gt;&gt;</span> <span class="op">{</span></span> 469<span id="cb26-12"><a href="#cb26-12" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> extract_arg_types(fn_args<span class="op">:</span> Punctuated<span class="op">&lt;</span>FnArg<span class="op">,</span> <span class="pp">syn::token::</span>Comma<span class="op">&gt;</span>) <span class="op">-&gt;</span> <span class="dt">Vec</span><span class="op">&lt;</span><span class="dt">Box</span><span class="op">&lt;</span>Type<span class="op">&gt;&gt;</span> <span class="op">{</span></span>
324<span id="cb26-13"><a href="#cb26-13" aria-hidden="true" tabindex="-1"></a> <span class="kw">return</span> fn_args<span class="op">.</span>into_iter()<span class="op">.</span>map(extract_type)<span class="op">.</span><span class="pp">collect::</span><span class="op">&lt;</span><span class="dt">Vec</span><span class="op">&lt;</span>_<span class="op">&gt;&gt;</span>()<span class="op">;</span></span> 470<span id="cb26-13"><a href="#cb26-13" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> fn_args<span class="op">.</span>into_iter()<span class="op">.</span>map(extract_type)<span class="op">.</span><span class="pp">collect::</span><span class="op">&lt;</span><span class="dt">Vec</span><span class="op">&lt;</span>_<span class="op">&gt;&gt;</span>()<span class="op">;</span></span>
325<span id="cb26-14"><a href="#cb26-14" aria-hidden="true" tabindex="-1"></a></span> 471<span id="cb26-14"><a href="#cb26-14" aria-hidden="true" tabindex="-1"></a></span>
326<span id="cb26-15"><a href="#cb26-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div> 472<span id="cb26-15"><a href="#cb26-15" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
327<p>A good reader would have looked at the docs for output member of the <code>syn::Signature</code> struct. It has the type <code>syn::ReturnType</code>. So there is no extraction to do here right? There are actually a couple of things we have to ensure here:</p> 473<p>A good reader would have looked at the docs for output member of the
474<code>syn::Signature</code> struct. It has the type
475<code>syn::ReturnType</code>. So there is no extraction to do here
476right? There are actually a couple of things we have to ensure here:</p>
328<ol type="1"> 477<ol type="1">
329<li><p>We need to ensure that the function returns! A function that does not return is pointless in this case, and I will tell you why, in the <a href="#notes">Notes</a> section.</p></li> 478<li><p>We need to ensure that the function returns! A function that does
330<li><p>A <code>ReturnType</code> encloses the arrow of the return as well, we need to get rid of that. Recall:</p> 479not return is pointless in this case, and I will tell you why, in the <a
331<div class="sourceCode" id="cb27"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> T0 <span class="op">=</span> <span class="dt">u32</span></span> 480href="#notes">Notes</a> section.</p></li>
481<li><p>A <code>ReturnType</code> encloses the arrow of the return as
482well, we need to get rid of that. Recall:</p>
483<div class="sourceCode" id="cb27"><pre
484class="sourceCode rust"><code class="sourceCode rust"><span id="cb27-1"><a href="#cb27-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> T0 <span class="op">=</span> <span class="dt">u32</span></span>
332<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a><span class="co">// and not</span></span> 485<span id="cb27-2"><a href="#cb27-2" aria-hidden="true" tabindex="-1"></a><span class="co">// and not</span></span>
333<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> T0 <span class="op">=</span> <span class="op">-&gt;</span> <span class="dt">u32</span></span></code></pre></div></li> 486<span id="cb27-3"><a href="#cb27-3" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> T0 <span class="op">=</span> <span class="op">-&gt;</span> <span class="dt">u32</span></span></code></pre></div></li>
334</ol> 487</ol>
335<p>Here is the snippet that handles extraction of the return type (doc: <a href="https://docs.rs/syn/1.0.19/syn/enum.ReturnType.html">syn::ReturnType</a>):</p> 488<p>Here is the snippet that handles extraction of the return type (doc:
336<div class="sourceCode" id="cb28"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a><span class="co">// src/lib.rs</span></span> 489<a
490href="https://docs.rs/syn/1.0.19/syn/enum.ReturnType.html">syn::ReturnType</a>):</p>
491<div class="sourceCode" id="cb28"><pre
492class="sourceCode rust"><code class="sourceCode rust"><span id="cb28-1"><a href="#cb28-1" aria-hidden="true" tabindex="-1"></a><span class="co">// src/lib.rs</span></span>
337<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a></span> 493<span id="cb28-2"><a href="#cb28-2" aria-hidden="true" tabindex="-1"></a></span>
338<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> extract_return_type(a<span class="op">:</span> ReturnType) <span class="op">-&gt;</span> <span class="dt">Box</span><span class="op">&lt;</span>Type<span class="op">&gt;</span> <span class="op">{</span></span> 494<span id="cb28-3"><a href="#cb28-3" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> extract_return_type(a<span class="op">:</span> ReturnType) <span class="op">-&gt;</span> <span class="dt">Box</span><span class="op">&lt;</span>Type<span class="op">&gt;</span> <span class="op">{</span></span>
339<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a> <span class="kw">match</span> a <span class="op">{</span></span> 495<span id="cb28-4"><a href="#cb28-4" aria-hidden="true" tabindex="-1"></a> <span class="cf">match</span> a <span class="op">{</span></span>
340<span id="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a> <span class="pp">ReturnType::</span>Type(_<span class="op">,</span> p) <span class="op">=&gt;</span> p<span class="op">,</span></span> 496<span id="cb28-5"><a href="#cb28-5" aria-hidden="true" tabindex="-1"></a> <span class="pp">ReturnType::</span>Type(_<span class="op">,</span> p) <span class="op">=&gt;</span> p<span class="op">,</span></span>
341<span id="cb28-6"><a href="#cb28-6" aria-hidden="true" tabindex="-1"></a> _ <span class="op">=&gt;</span> <span class="pp">panic!</span>(<span class="st">&quot;Not supported on functions without return types!&quot;</span>)<span class="op">,</span></span> 497<span id="cb28-6"><a href="#cb28-6" aria-hidden="true" tabindex="-1"></a> _ <span class="op">=&gt;</span> <span class="pp">panic!</span>(<span class="st">&quot;Not supported on functions without return types!&quot;</span>)<span class="op">,</span></span>
342<span id="cb28-7"><a href="#cb28-7" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span> 498<span id="cb28-7"><a href="#cb28-7" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
343<span id="cb28-8"><a href="#cb28-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div> 499<span id="cb28-8"><a href="#cb28-8" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
344<p>You might notice that we are making extensive use of the <code>panic!</code> macro. Well, that is because it is a good idea to quit on receiving an unsatisfactory <code>TokenStream</code>.</p> 500<p>You might notice that we are making extensive use of the
345<p>With all our types ready, we can get on with generating type aliases:</p> 501<code>panic!</code> macro. Well, that is because it is a good idea to
346<div class="sourceCode" id="cb29"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a><span class="co">// src/lib.rs</span></span> 502quit on receiving an unsatisfactory <code>TokenStream</code>.</p>
503<p>With all our types ready, we can get on with generating type
504aliases:</p>
505<div class="sourceCode" id="cb29"><pre
506class="sourceCode rust"><code class="sourceCode rust"><span id="cb29-1"><a href="#cb29-1" aria-hidden="true" tabindex="-1"></a><span class="co">// src/lib.rs</span></span>
347<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a></span> 507<span id="cb29-2"><a href="#cb29-2" aria-hidden="true" tabindex="-1"></a></span>
348<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a><span class="kw">use</span> <span class="pp">quote::</span><span class="op">{</span>quote<span class="op">,</span> format_ident<span class="op">};</span></span> 508<span id="cb29-3"><a href="#cb29-3" aria-hidden="true" tabindex="-1"></a><span class="kw">use</span> <span class="pp">quote::</span><span class="op">{</span>quote<span class="op">,</span> format_ident<span class="op">};</span></span>
349<span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a></span> 509<span id="cb29-4"><a href="#cb29-4" aria-hidden="true" tabindex="-1"></a></span>
@@ -357,7 +517,7 @@ syn::token::Fn --&#39; / \ (output)
357<span id="cb29-12"><a href="#cb29-12" aria-hidden="true" tabindex="-1"></a> <span class="kw">let</span> <span class="kw">mut</span> type_aliases <span class="op">=</span> <span class="pp">vec!</span>[<span class="pp">quote!</span> <span class="op">{</span> <span class="kw">type</span> #type_t0 <span class="op">=</span> #fn_return_type <span class="op">}</span>]<span class="op">;</span></span> 517<span id="cb29-12"><a href="#cb29-12" aria-hidden="true" tabindex="-1"></a> <span class="kw">let</span> <span class="kw">mut</span> type_aliases <span class="op">=</span> <span class="pp">vec!</span>[<span class="pp">quote!</span> <span class="op">{</span> <span class="kw">type</span> #type_t0 <span class="op">=</span> #fn_return_type <span class="op">}</span>]<span class="op">;</span></span>
358<span id="cb29-13"><a href="#cb29-13" aria-hidden="true" tabindex="-1"></a></span> 518<span id="cb29-13"><a href="#cb29-13" aria-hidden="true" tabindex="-1"></a></span>
359<span id="cb29-14"><a href="#cb29-14" aria-hidden="true" tabindex="-1"></a> <span class="co">// 3</span></span> 519<span id="cb29-14"><a href="#cb29-14" aria-hidden="true" tabindex="-1"></a> <span class="co">// 3</span></span>
360<span id="cb29-15"><a href="#cb29-15" aria-hidden="true" tabindex="-1"></a> <span class="kw">for</span> (i<span class="op">,</span> t) <span class="kw">in</span> (<span class="dv">1</span><span class="op">..</span>)<span class="op">.</span>zip(fn_arg_types<span class="op">.</span>into_iter()<span class="op">.</span>rev()) <span class="op">{</span></span> 520<span id="cb29-15"><a href="#cb29-15" aria-hidden="true" tabindex="-1"></a> <span class="cf">for</span> (i<span class="op">,</span> t) <span class="kw">in</span> (<span class="dv">1</span><span class="op">..</span>)<span class="op">.</span>zip(fn_arg_types<span class="op">.</span>into_iter()<span class="op">.</span>rev()) <span class="op">{</span></span>
361<span id="cb29-16"><a href="#cb29-16" aria-hidden="true" tabindex="-1"></a> <span class="kw">let</span> p <span class="op">=</span> <span class="pp">format_ident!</span>(<span class="st">&quot;_{}_{}&quot;</span><span class="op">,</span> fn_name<span class="op">,</span> <span class="pp">format!</span>(<span class="st">&quot;T{}&quot;</span><span class="op">,</span> i <span class="op">-</span> <span class="dv">1</span>))<span class="op">;</span></span> 521<span id="cb29-16"><a href="#cb29-16" aria-hidden="true" tabindex="-1"></a> <span class="kw">let</span> p <span class="op">=</span> <span class="pp">format_ident!</span>(<span class="st">&quot;_{}_{}&quot;</span><span class="op">,</span> fn_name<span class="op">,</span> <span class="pp">format!</span>(<span class="st">&quot;T{}&quot;</span><span class="op">,</span> i <span class="op">-</span> <span class="dv">1</span>))<span class="op">;</span></span>
362<span id="cb29-17"><a href="#cb29-17" aria-hidden="true" tabindex="-1"></a> <span class="kw">let</span> n <span class="op">=</span> <span class="pp">format_ident!</span>(<span class="st">&quot;_{}_{}&quot;</span><span class="op">,</span> fn_name<span class="op">,</span> <span class="pp">format!</span>(<span class="st">&quot;T{}&quot;</span><span class="op">,</span> i))<span class="op">;</span></span> 522<span id="cb29-17"><a href="#cb29-17" aria-hidden="true" tabindex="-1"></a> <span class="kw">let</span> n <span class="op">=</span> <span class="pp">format_ident!</span>(<span class="st">&quot;_{}_{}&quot;</span><span class="op">,</span> fn_name<span class="op">,</span> <span class="pp">format!</span>(<span class="st">&quot;T{}&quot;</span><span class="op">,</span> i))<span class="op">;</span></span>
363<span id="cb29-18"><a href="#cb29-18" aria-hidden="true" tabindex="-1"></a></span> 523<span id="cb29-18"><a href="#cb29-18" aria-hidden="true" tabindex="-1"></a></span>
@@ -366,45 +526,70 @@ syn::token::Fn --&#39; / \ (output)
366<span id="cb29-21"><a href="#cb29-21" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span>)<span class="op">;</span></span> 526<span id="cb29-21"><a href="#cb29-21" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span>)<span class="op">;</span></span>
367<span id="cb29-22"><a href="#cb29-22" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span> 527<span id="cb29-22"><a href="#cb29-22" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
368<span id="cb29-23"><a href="#cb29-23" aria-hidden="true" tabindex="-1"></a></span> 528<span id="cb29-23"><a href="#cb29-23" aria-hidden="true" tabindex="-1"></a></span>
369<span id="cb29-24"><a href="#cb29-24" aria-hidden="true" tabindex="-1"></a> <span class="kw">return</span> type_aliases<span class="op">;</span></span> 529<span id="cb29-24"><a href="#cb29-24" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> type_aliases<span class="op">;</span></span>
370<span id="cb29-25"><a href="#cb29-25" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div> 530<span id="cb29-25"><a href="#cb29-25" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
371<p><strong>1. The return value</strong><br /> 531<p><strong>1. The return value</strong><br />
372We are returning a <code>Vec&lt;proc_macro2::TokenStream&gt;</code>, i. e., a list of <code>TokenStream</code>s, where each item is a type alias.</p> 532We are returning a <code>Vec&lt;proc_macro2::TokenStream&gt;</code>, i.
533e., a list of <code>TokenStream</code>s, where each item is a type
534alias.</p>
373<p><strong>2. Format identifier?</strong><br /> 535<p><strong>2. Format identifier?</strong><br />
374I’ve got some explanation to do on this line. Clearly, we are trying to write the first type alias, and initialize our <code>TokenStream</code> vector with <code>T0</code>, because it is different from the others:</p> 536I’ve got some explanation to do on this line. Clearly, we are trying to
375<div class="sourceCode" id="cb30"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> T0 <span class="op">=</span> something</span> 537write the first type alias, and initialize our <code>TokenStream</code>
538vector with <code>T0</code>, because it is different from the
539others:</p>
540<div class="sourceCode" id="cb30"><pre
541class="sourceCode rust"><code class="sourceCode rust"><span id="cb30-1"><a href="#cb30-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> T0 <span class="op">=</span> something</span>
376<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a><span class="co">// the others are of the form</span></span> 542<span id="cb30-2"><a href="#cb30-2" aria-hidden="true" tabindex="-1"></a><span class="co">// the others are of the form</span></span>
377<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> Tr <span class="op">=</span> <span class="kw">impl</span> <span class="bu">Fn</span>(something) <span class="op">-&gt;</span> something</span></code></pre></div> 543<span id="cb30-3"><a href="#cb30-3" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> Tr <span class="op">=</span> <span class="kw">impl</span> <span class="bu">Fn</span>(something) <span class="op">-&gt;</span> something</span></code></pre></div>
378<p><code>format_ident!</code> is similar to <code>format!</code>. Instead of returning a formatted string, it returns a <code>syn::Ident</code>. Therefore, <code>type_t0</code> is actually an identifier for, in the case of our <code>add</code> function, <code>_add_T0</code>. Why is this formatting important? Namespacing.</p> 544<p><code>format_ident!</code> is similar to <code>format!</code>.
379<p>Picture this, we have two functions, <code>add</code> and <code>subtract</code>, that we wish to curry with our macro:</p> 545Instead of returning a formatted string, it returns a
380<div class="sourceCode" id="cb31"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>curry<span class="at">]</span></span> 546<code>syn::Ident</code>. Therefore, <code>type_t0</code> is actually an
547identifier for, in the case of our <code>add</code> function,
548<code>_add_T0</code>. Why is this formatting important? Namespacing.</p>
549<p>Picture this, we have two functions, <code>add</code> and
550<code>subtract</code>, that we wish to curry with our macro:</p>
551<div class="sourceCode" id="cb31"><pre
552class="sourceCode rust"><code class="sourceCode rust"><span id="cb31-1"><a href="#cb31-1" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>curry<span class="at">]</span></span>
381<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> add(<span class="op">...</span>) <span class="op">-&gt;</span> <span class="dt">u32</span> <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span> 553<span id="cb31-2"><a href="#cb31-2" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> add(<span class="op">...</span>) <span class="op">-&gt;</span> <span class="dt">u32</span> <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span>
382<span id="cb31-3"><a href="#cb31-3" aria-hidden="true" tabindex="-1"></a></span> 554<span id="cb31-3"><a href="#cb31-3" aria-hidden="true" tabindex="-1"></a></span>
383<span id="cb31-4"><a href="#cb31-4" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>curry<span class="at">]</span></span> 555<span id="cb31-4"><a href="#cb31-4" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>curry<span class="at">]</span></span>
384<span id="cb31-5"><a href="#cb31-5" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> sub(<span class="op">...</span>) <span class="op">-&gt;</span> <span class="dt">u32</span> <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span></code></pre></div> 556<span id="cb31-5"><a href="#cb31-5" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> sub(<span class="op">...</span>) <span class="op">-&gt;</span> <span class="dt">u32</span> <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span></code></pre></div>
385<p>Here is the same but with macros expanded:</p> 557<p>Here is the same but with macros expanded:</p>
386<div class="sourceCode" id="cb32"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> T0 <span class="op">=</span> <span class="dt">u32</span><span class="op">;</span></span> 558<div class="sourceCode" id="cb32"><pre
559class="sourceCode rust"><code class="sourceCode rust"><span id="cb32-1"><a href="#cb32-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> T0 <span class="op">=</span> <span class="dt">u32</span><span class="op">;</span></span>
387<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> T1 <span class="op">=</span> <span class="kw">impl</span> <span class="bu">Fn</span>(<span class="dt">u32</span>) <span class="op">-&gt;</span> T0<span class="op">;</span></span> 560<span id="cb32-2"><a href="#cb32-2" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> T1 <span class="op">=</span> <span class="kw">impl</span> <span class="bu">Fn</span>(<span class="dt">u32</span>) <span class="op">-&gt;</span> T0<span class="op">;</span></span>
388<span id="cb32-3"><a href="#cb32-3" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> add( <span class="op">...</span> ) <span class="op">-&gt;</span> T1 <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span> 561<span id="cb32-3"><a href="#cb32-3" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> add( <span class="op">...</span> ) <span class="op">-&gt;</span> T1 <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span>
389<span id="cb32-4"><a href="#cb32-4" aria-hidden="true" tabindex="-1"></a></span> 562<span id="cb32-4"><a href="#cb32-4" aria-hidden="true" tabindex="-1"></a></span>
390<span id="cb32-5"><a href="#cb32-5" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> T0 <span class="op">=</span> <span class="dt">u32</span><span class="op">;</span></span> 563<span id="cb32-5"><a href="#cb32-5" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> T0 <span class="op">=</span> <span class="dt">u32</span><span class="op">;</span></span>
391<span id="cb32-6"><a href="#cb32-6" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> T1 <span class="op">=</span> <span class="kw">impl</span> <span class="bu">Fn</span>(<span class="dt">u32</span>) <span class="op">-&gt;</span> T0<span class="op">;</span></span> 564<span id="cb32-6"><a href="#cb32-6" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> T1 <span class="op">=</span> <span class="kw">impl</span> <span class="bu">Fn</span>(<span class="dt">u32</span>) <span class="op">-&gt;</span> T0<span class="op">;</span></span>
392<span id="cb32-7"><a href="#cb32-7" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> sub( <span class="op">...</span> ) <span class="op">-&gt;</span> T1 <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span></code></pre></div> 565<span id="cb32-7"><a href="#cb32-7" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> sub( <span class="op">...</span> ) <span class="op">-&gt;</span> T1 <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span></code></pre></div>
393<p>We end up with two definitions of <code>T0</code>! Now, if we do the little <code>format_ident!</code> dance we did up there:</p> 566<p>We end up with two definitions of <code>T0</code>! Now, if we do the
394<div class="sourceCode" id="cb33"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> _add_T0 <span class="op">=</span> <span class="dt">u32</span><span class="op">;</span></span> 567little <code>format_ident!</code> dance we did up there:</p>
568<div class="sourceCode" id="cb33"><pre
569class="sourceCode rust"><code class="sourceCode rust"><span id="cb33-1"><a href="#cb33-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> _add_T0 <span class="op">=</span> <span class="dt">u32</span><span class="op">;</span></span>
395<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> _add_T1 <span class="op">=</span> <span class="kw">impl</span> <span class="bu">Fn</span>(<span class="dt">u32</span>) <span class="op">-&gt;</span> _add_T0<span class="op">;</span></span> 570<span id="cb33-2"><a href="#cb33-2" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> _add_T1 <span class="op">=</span> <span class="kw">impl</span> <span class="bu">Fn</span>(<span class="dt">u32</span>) <span class="op">-&gt;</span> _add_T0<span class="op">;</span></span>
396<span id="cb33-3"><a href="#cb33-3" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> add( <span class="op">...</span> ) <span class="op">-&gt;</span> _add_T1 <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span> 571<span id="cb33-3"><a href="#cb33-3" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> add( <span class="op">...</span> ) <span class="op">-&gt;</span> _add_T1 <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span>
397<span id="cb33-4"><a href="#cb33-4" aria-hidden="true" tabindex="-1"></a></span> 572<span id="cb33-4"><a href="#cb33-4" aria-hidden="true" tabindex="-1"></a></span>
398<span id="cb33-5"><a href="#cb33-5" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> _sub_T0 <span class="op">=</span> <span class="dt">u32</span><span class="op">;</span></span> 573<span id="cb33-5"><a href="#cb33-5" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> _sub_T0 <span class="op">=</span> <span class="dt">u32</span><span class="op">;</span></span>
399<span id="cb33-6"><a href="#cb33-6" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> _sub_T1 <span class="op">=</span> <span class="kw">impl</span> <span class="bu">Fn</span>(<span class="dt">u32</span>) <span class="op">-&gt;</span> _sub_T0<span class="op">;</span></span> 574<span id="cb33-6"><a href="#cb33-6" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> _sub_T1 <span class="op">=</span> <span class="kw">impl</span> <span class="bu">Fn</span>(<span class="dt">u32</span>) <span class="op">-&gt;</span> _sub_T0<span class="op">;</span></span>
400<span id="cb33-7"><a href="#cb33-7" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> sub( <span class="op">...</span> ) <span class="op">-&gt;</span> _sub_T1 <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span></code></pre></div> 575<span id="cb33-7"><a href="#cb33-7" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> sub( <span class="op">...</span> ) <span class="op">-&gt;</span> _sub_T1 <span class="op">{</span> <span class="op">...</span> <span class="op">}</span></span></code></pre></div>
401<p>Voilà! The type aliases don’t tread on each other. Remember to import <code>format_ident</code> from the <code>quote</code> crate.</p> 576<p>Voilà! The type aliases don’t tread on each other. Remember to import
577<code>format_ident</code> from the <code>quote</code> crate.</p>
402<p><strong>3. The TokenStream Vector</strong></p> 578<p><strong>3. The TokenStream Vector</strong></p>
403<p>We iterate over our types in reverse order (<code>T0</code> is the last return, <code>T1</code> is the second last, so on), assign a number to each iteration with <code>zip</code>, generate type names with <code>format_ident</code>, push a <code>TokenStream</code> with the help of <code>quote</code> and variable interpolation.</p> 579<p>We iterate over our types in reverse order (<code>T0</code> is the
404<p>If you are wondering why we used <code>(1..).zip()</code> instead of <code>.enumerate()</code>, it’s because we wanted to start counting from 1 instead of 0 (we are already done with <code>T0</code>!).</p> 580last return, <code>T1</code> is the second last, so on), assign a number
581to each iteration with <code>zip</code>, generate type names with
582<code>format_ident</code>, push a <code>TokenStream</code> with the help
583of <code>quote</code> and variable interpolation.</p>
584<p>If you are wondering why we used <code>(1..).zip()</code> instead of
585<code>.enumerate()</code>, it’s because we wanted to start counting from
5861 instead of 0 (we are already done with <code>T0</code>!).</p>
405<h4 id="getting-it-together">Getting it together</h4> 587<h4 id="getting-it-together">Getting it together</h4>
406<p>I promised we’d have a fully working macro by the end of last section. I lied, we have to tie everything together in our <code>generate_curry</code> function:</p> 588<p>I promised we’d have a fully working macro by the end of last
407<div class="sourceCode" id="cb34"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a><span class="co">// src/lib.rs</span></span> 589section. I lied, we have to tie everything together in our
590<code>generate_curry</code> function:</p>
591<div class="sourceCode" id="cb34"><pre
592class="sourceCode rust"><code class="sourceCode rust"><span id="cb34-1"><a href="#cb34-1" aria-hidden="true" tabindex="-1"></a><span class="co">// src/lib.rs</span></span>
408<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a></span> 593<span id="cb34-2"><a href="#cb34-2" aria-hidden="true" tabindex="-1"></a></span>
409<span id="cb34-3"><a href="#cb34-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">fn</span> generate_curry(parsed<span class="op">:</span> ItemFn) <span class="op">-&gt;</span> <span class="pp">proc_macro2::</span>TokenStream <span class="op">{</span></span> 594<span id="cb34-3"><a href="#cb34-3" aria-hidden="true" tabindex="-1"></a> <span class="kw">fn</span> generate_curry(parsed<span class="op">:</span> ItemFn) <span class="op">-&gt;</span> <span class="pp">proc_macro2::</span>TokenStream <span class="op">{</span></span>
410<span id="cb34-4"><a href="#cb34-4" aria-hidden="true" tabindex="-1"></a> <span class="kw">let</span> fn_body <span class="op">=</span> parsed<span class="op">.</span>block<span class="op">;</span></span> 595<span id="cb34-4"><a href="#cb34-4" aria-hidden="true" tabindex="-1"></a> <span class="kw">let</span> fn_body <span class="op">=</span> parsed<span class="op">.</span>block<span class="op">;</span></span>
@@ -428,20 +613,39 @@ I’ve got some explanation to do on this line. Clearly, we are trying to write
428<span id="cb34-22"><a href="#cb34-22" aria-hidden="true" tabindex="-1"></a></span> 613<span id="cb34-22"><a href="#cb34-22" aria-hidden="true" tabindex="-1"></a></span>
429<span id="cb34-23"><a href="#cb34-23" aria-hidden="true" tabindex="-1"></a><span class="op">+</span> <span class="kw">let</span> return_type <span class="op">=</span> <span class="pp">format_ident!</span>(<span class="st">&quot;_{}_{}&quot;</span><span class="op">,</span> <span class="op">&amp;</span>fn_name<span class="op">,</span> <span class="pp">format!</span>(<span class="st">&quot;T{}&quot;</span><span class="op">,</span> type_aliases<span class="op">.</span>len() <span class="op">-</span> <span class="dv">1</span>))<span class="op">;</span></span> 614<span id="cb34-23"><a href="#cb34-23" aria-hidden="true" tabindex="-1"></a><span class="op">+</span> <span class="kw">let</span> return_type <span class="op">=</span> <span class="pp">format_ident!</span>(<span class="st">&quot;_{}_{}&quot;</span><span class="op">,</span> <span class="op">&amp;</span>fn_name<span class="op">,</span> <span class="pp">format!</span>(<span class="st">&quot;T{}&quot;</span><span class="op">,</span> type_aliases<span class="op">.</span>len() <span class="op">-</span> <span class="dv">1</span>))<span class="op">;</span></span>
430<span id="cb34-24"><a href="#cb34-24" aria-hidden="true" tabindex="-1"></a></span> 615<span id="cb34-24"><a href="#cb34-24" aria-hidden="true" tabindex="-1"></a></span>
431<span id="cb34-25"><a href="#cb34-25" aria-hidden="true" tabindex="-1"></a><span class="op">+</span> <span class="kw">return</span> <span class="pp">quote!</span> <span class="op">{</span></span> 616<span id="cb34-25"><a href="#cb34-25" aria-hidden="true" tabindex="-1"></a><span class="op">+</span> <span class="cf">return</span> <span class="pp">quote!</span> <span class="op">{</span></span>
432<span id="cb34-26"><a href="#cb34-26" aria-hidden="true" tabindex="-1"></a><span class="op">+</span> #(#type_aliases)<span class="op">;*</span> <span class="op">;</span></span> 617<span id="cb34-26"><a href="#cb34-26" aria-hidden="true" tabindex="-1"></a><span class="op">+</span> #(#type_aliases)<span class="op">;*</span> <span class="op">;</span></span>
433<span id="cb34-27"><a href="#cb34-27" aria-hidden="true" tabindex="-1"></a><span class="op">+</span> #vis <span class="kw">fn</span> #fn_name (#first_ident<span class="op">:</span> #first_type) <span class="op">-&gt;</span> #return_type <span class="op">{</span></span> 618<span id="cb34-27"><a href="#cb34-27" aria-hidden="true" tabindex="-1"></a><span class="op">+</span> #vis <span class="kw">fn</span> #fn_name (#first_ident<span class="op">:</span> #first_type) <span class="op">-&gt;</span> #return_type <span class="op">{</span></span>
434<span id="cb34-28"><a href="#cb34-28" aria-hidden="true" tabindex="-1"></a><span class="op">+</span> #curried_body <span class="op">;</span></span> 619<span id="cb34-28"><a href="#cb34-28" aria-hidden="true" tabindex="-1"></a><span class="op">+</span> #curried_body <span class="op">;</span></span>
435<span id="cb34-29"><a href="#cb34-29" aria-hidden="true" tabindex="-1"></a><span class="op">+</span> <span class="op">}</span></span> 620<span id="cb34-29"><a href="#cb34-29" aria-hidden="true" tabindex="-1"></a><span class="op">+</span> <span class="op">}</span></span>
436<span id="cb34-30"><a href="#cb34-30" aria-hidden="true" tabindex="-1"></a><span class="op">+</span> <span class="op">};</span></span> 621<span id="cb34-30"><a href="#cb34-30" aria-hidden="true" tabindex="-1"></a><span class="op">+</span> <span class="op">};</span></span>
437<span id="cb34-31"><a href="#cb34-31" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span></code></pre></div> 622<span id="cb34-31"><a href="#cb34-31" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span></code></pre></div>
438<p>Most of the additions are self explanatory, I’ll go through the return statement with you. We are returning a <code>quote!{ ... }</code>, so a <code>proc_macro2::TokenStream</code>. We are iterating through the <code>type_aliases</code> variable, which you might recall, is a <code>Vec&lt;TokenStream&gt;</code>. You might notice the sneaky semicolon before the <code>*</code>. This basically tells <code>quote</code>, to insert an item, then a semicolon, and then the next one, another semicolon, and so on. The semicolon is a separator. We need to manually insert another semicolon at the end of it all, <code>quote</code> doesn’t insert a separator at the end of the iteration.</p> 623<p>Most of the additions are self explanatory, I’ll go through the
439<p>We retain the visibility and name of our original function. Our curried function takes as args, just the first argument of our original function. The return type of our curried function is actually, the last type alias we create. If you think back to our manually curried <code>add</code> function, we returned <code>T2</code>, which was in fact, the last type alias we created.</p> 624return statement with you. We are returning a
440<p>I am sure, at this point, you are itching to test this out, but before that, let me introduce you to some good methods of debugging proc-macro code.</p> 625<code>quote!{ ... }</code>, so a <code>proc_macro2::TokenStream</code>.
626We are iterating through the <code>type_aliases</code> variable, which
627you might recall, is a <code>Vec&lt;TokenStream&gt;</code>. You might
628notice the sneaky semicolon before the <code>*</code>. This basically
629tells <code>quote</code>, to insert an item, then a semicolon, and then
630the next one, another semicolon, and so on. The semicolon is a
631separator. We need to manually insert another semicolon at the end of it
632all, <code>quote</code> doesn’t insert a separator at the end of the
633iteration.</p>
634<p>We retain the visibility and name of our original function. Our
635curried function takes as args, just the first argument of our original
636function. The return type of our curried function is actually, the last
637type alias we create. If you think back to our manually curried
638<code>add</code> function, we returned <code>T2</code>, which was in
639fact, the last type alias we created.</p>
640<p>I am sure, at this point, you are itching to test this out, but
641before that, let me introduce you to some good methods of debugging
642proc-macro code.</p>
441<h3 id="debugging-and-testing">Debugging and Testing</h3> 643<h3 id="debugging-and-testing">Debugging and Testing</h3>
442<p>Install <code>cargo-expand</code> via:</p> 644<p>Install <code>cargo-expand</code> via:</p>
443<pre><code>cargo install cargo-expand</code></pre> 645<pre><code>cargo install cargo-expand</code></pre>
444<p><code>cargo-expand</code> is a neat little tool that expands your macro in places where it is used, and lets you view the generated code! For example:</p> 646<p><code>cargo-expand</code> is a neat little tool that expands your
647macro in places where it is used, and lets you view the generated code!
648For example:</p>
445<pre class="shell"><code># create a bin package hello 649<pre class="shell"><code># create a bin package hello
446$ cargo new hello 650$ cargo new hello
447 651
@@ -463,10 +667,18 @@ fn main() {
463 )); 667 ));
464 }; 668 };
465}</code></pre> 669}</code></pre>
466<p>Writing proc-macros without <code>cargo-expand</code> is tantamount to driving a vehicle without rear view mirrors! Keep an eye on what is going on behind your back.</p> 670<p>Writing proc-macros without <code>cargo-expand</code> is tantamount
467<p>Now, your macro won’t always compile, you might just recieve the bee movie script as an error. <code>cargo-expand</code> will not work in such cases. I would suggest printing out your variables to inspect them. <code>TokenStream</code> implements <code>Display</code> as well as <code>Debug</code>. We don’t always have to be respectable programmers. Just print it.</p> 671to driving a vehicle without rear view mirrors! Keep an eye on what is
672going on behind your back.</p>
673<p>Now, your macro won’t always compile, you might just recieve the bee
674movie script as an error. <code>cargo-expand</code> will not work in
675such cases. I would suggest printing out your variables to inspect them.
676<code>TokenStream</code> implements <code>Display</code> as well as
677<code>Debug</code>. We don’t always have to be respectable programmers.
678Just print it.</p>
468<p>Enough of that, lets get testing:</p> 679<p>Enough of that, lets get testing:</p>
469<div class="sourceCode" id="cb37"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb37-1"><a href="#cb37-1" aria-hidden="true" tabindex="-1"></a><span class="co">// tests/smoke.rs</span></span> 680<div class="sourceCode" id="cb37"><pre
681class="sourceCode rust"><code class="sourceCode rust"><span id="cb37-1"><a href="#cb37-1" aria-hidden="true" tabindex="-1"></a><span class="co">// tests/smoke.rs</span></span>
470<span id="cb37-2"><a href="#cb37-2" aria-hidden="true" tabindex="-1"></a></span> 682<span id="cb37-2"><a href="#cb37-2" aria-hidden="true" tabindex="-1"></a></span>
471<span id="cb37-3"><a href="#cb37-3" aria-hidden="true" tabindex="-1"></a><span class="at">#![</span>feature<span class="at">(</span>type_alias_impl_trait<span class="at">)]</span></span> 683<span id="cb37-3"><a href="#cb37-3" aria-hidden="true" tabindex="-1"></a><span class="at">#![</span>feature<span class="at">(</span>type_alias_impl_trait<span class="at">)]</span></span>
472<span id="cb37-4"><a href="#cb37-4" aria-hidden="true" tabindex="-1"></a></span> 684<span id="cb37-4"><a href="#cb37-4" aria-hidden="true" tabindex="-1"></a></span>
@@ -479,55 +691,81 @@ fn main() {
479<span id="cb37-11"><a href="#cb37-11" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> works() <span class="op">{</span></span> 691<span id="cb37-11"><a href="#cb37-11" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> works() <span class="op">{</span></span>
480<span id="cb37-12"><a href="#cb37-12" aria-hidden="true" tabindex="-1"></a> <span class="pp">assert_eq!</span>(<span class="dv">15</span><span class="op">,</span> add(<span class="dv">4</span>)(<span class="dv">5</span>)(<span class="dv">6</span>))<span class="op">;</span></span> 692<span id="cb37-12"><a href="#cb37-12" aria-hidden="true" tabindex="-1"></a> <span class="pp">assert_eq!</span>(<span class="dv">15</span><span class="op">,</span> add(<span class="dv">4</span>)(<span class="dv">5</span>)(<span class="dv">6</span>))<span class="op">;</span></span>
481<span id="cb37-13"><a href="#cb37-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div> 693<span id="cb37-13"><a href="#cb37-13" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
482<p>Run <code>cargo +nightly test</code>. You should see a pleasing message:</p> 694<p>Run <code>cargo +nightly test</code>. You should see a pleasing
695message:</p>
483<pre><code>running 1 test 696<pre><code>running 1 test
484test tests::works ... ok</code></pre> 697test tests::works ... ok</code></pre>
485<p>Take a look at the expansion for our curry macro, via <code>cargo +nightly expand --tests smoke</code>:</p> 698<p>Take a look at the expansion for our curry macro, via
486<div class="sourceCode" id="cb39"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb39-1"><a href="#cb39-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> _add_T0 <span class="op">=</span> <span class="dt">u32</span><span class="op">;</span></span> 699<code>cargo +nightly expand --tests smoke</code>:</p>
700<div class="sourceCode" id="cb39"><pre
701class="sourceCode rust"><code class="sourceCode rust"><span id="cb39-1"><a href="#cb39-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> _add_T0 <span class="op">=</span> <span class="dt">u32</span><span class="op">;</span></span>
487<span id="cb39-2"><a href="#cb39-2" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> _add_T1 <span class="op">=</span> <span class="kw">impl</span> <span class="bu">Fn</span>(<span class="dt">u32</span>) <span class="op">-&gt;</span> _add_T0<span class="op">;</span></span> 702<span id="cb39-2"><a href="#cb39-2" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> _add_T1 <span class="op">=</span> <span class="kw">impl</span> <span class="bu">Fn</span>(<span class="dt">u32</span>) <span class="op">-&gt;</span> _add_T0<span class="op">;</span></span>
488<span id="cb39-3"><a href="#cb39-3" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> _add_T2 <span class="op">=</span> <span class="kw">impl</span> <span class="bu">Fn</span>(<span class="dt">u32</span>) <span class="op">-&gt;</span> _add_T1<span class="op">;</span></span> 703<span id="cb39-3"><a href="#cb39-3" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> _add_T2 <span class="op">=</span> <span class="kw">impl</span> <span class="bu">Fn</span>(<span class="dt">u32</span>) <span class="op">-&gt;</span> _add_T1<span class="op">;</span></span>
489<span id="cb39-4"><a href="#cb39-4" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> add(x<span class="op">:</span> <span class="dt">u32</span>) <span class="op">-&gt;</span> _add_T2 <span class="op">{</span></span> 704<span id="cb39-4"><a href="#cb39-4" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> add(x<span class="op">:</span> <span class="dt">u32</span>) <span class="op">-&gt;</span> _add_T2 <span class="op">{</span></span>
490<span id="cb39-5"><a href="#cb39-5" aria-hidden="true" tabindex="-1"></a> <span class="kw">return</span> (<span class="kw">move</span> <span class="op">|</span>y<span class="op">|</span> <span class="op">{</span></span> 705<span id="cb39-5"><a href="#cb39-5" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> (<span class="kw">move</span> <span class="op">|</span>y<span class="op">|</span> <span class="op">{</span></span>
491<span id="cb39-6"><a href="#cb39-6" aria-hidden="true" tabindex="-1"></a> <span class="kw">move</span> <span class="op">|</span>z<span class="op">|</span> <span class="op">{</span></span> 706<span id="cb39-6"><a href="#cb39-6" aria-hidden="true" tabindex="-1"></a> <span class="kw">move</span> <span class="op">|</span>z<span class="op">|</span> <span class="op">{</span></span>
492<span id="cb39-7"><a href="#cb39-7" aria-hidden="true" tabindex="-1"></a> <span class="kw">return</span> x <span class="op">+</span> y <span class="op">+</span> z<span class="op">;</span></span> 707<span id="cb39-7"><a href="#cb39-7" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> x <span class="op">+</span> y <span class="op">+</span> z<span class="op">;</span></span>
493<span id="cb39-8"><a href="#cb39-8" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span> 708<span id="cb39-8"><a href="#cb39-8" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
494<span id="cb39-9"><a href="#cb39-9" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span>)<span class="op">;</span></span> 709<span id="cb39-9"><a href="#cb39-9" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span>)<span class="op">;</span></span>
495<span id="cb39-10"><a href="#cb39-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span> 710<span id="cb39-10"><a href="#cb39-10" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
496<span id="cb39-11"><a href="#cb39-11" aria-hidden="true" tabindex="-1"></a></span> 711<span id="cb39-11"><a href="#cb39-11" aria-hidden="true" tabindex="-1"></a></span>
497<span id="cb39-12"><a href="#cb39-12" aria-hidden="true" tabindex="-1"></a><span class="co">// a bunch of other stuff generated by #[test] and assert_eq!</span></span></code></pre></div> 712<span id="cb39-12"><a href="#cb39-12" aria-hidden="true" tabindex="-1"></a><span class="co">// a bunch of other stuff generated by #[test] and assert_eq!</span></span></code></pre></div>
498<p>A sight for sore eyes.</p> 713<p>A sight for sore eyes.</p>
499<p>Here is a more complex example that generates ten multiples of the first ten natural numbers:</p> 714<p>Here is a more complex example that generates ten multiples of the
500<div class="sourceCode" id="cb40"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb40-1"><a href="#cb40-1" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>curry<span class="at">]</span></span> 715first ten natural numbers:</p>
716<div class="sourceCode" id="cb40"><pre
717class="sourceCode rust"><code class="sourceCode rust"><span id="cb40-1"><a href="#cb40-1" aria-hidden="true" tabindex="-1"></a><span class="at">#[</span>curry<span class="at">]</span></span>
501<span id="cb40-2"><a href="#cb40-2" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> product(x<span class="op">:</span> <span class="dt">u32</span><span class="op">,</span> y<span class="op">:</span> <span class="dt">u32</span>) <span class="op">-&gt;</span> <span class="dt">u32</span> <span class="op">{</span></span> 718<span id="cb40-2"><a href="#cb40-2" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> product(x<span class="op">:</span> <span class="dt">u32</span><span class="op">,</span> y<span class="op">:</span> <span class="dt">u32</span>) <span class="op">-&gt;</span> <span class="dt">u32</span> <span class="op">{</span></span>
502<span id="cb40-3"><a href="#cb40-3" aria-hidden="true" tabindex="-1"></a> x <span class="op">*</span> y</span> 719<span id="cb40-3"><a href="#cb40-3" aria-hidden="true" tabindex="-1"></a> x <span class="op">*</span> y</span>
503<span id="cb40-4"><a href="#cb40-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span> 720<span id="cb40-4"><a href="#cb40-4" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
504<span id="cb40-5"><a href="#cb40-5" aria-hidden="true" tabindex="-1"></a></span> 721<span id="cb40-5"><a href="#cb40-5" aria-hidden="true" tabindex="-1"></a></span>
505<span id="cb40-6"><a href="#cb40-6" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> multiples() <span class="op">-&gt;</span> <span class="dt">Vec</span><span class="op">&lt;</span><span class="dt">Vec</span><span class="op">&lt;</span><span class="dt">u32</span><span class="op">&gt;&gt;{</span></span> 722<span id="cb40-6"><a href="#cb40-6" aria-hidden="true" tabindex="-1"></a><span class="kw">fn</span> multiples() <span class="op">-&gt;</span> <span class="dt">Vec</span><span class="op">&lt;</span><span class="dt">Vec</span><span class="op">&lt;</span><span class="dt">u32</span><span class="op">&gt;&gt;{</span></span>
506<span id="cb40-7"><a href="#cb40-7" aria-hidden="true" tabindex="-1"></a> <span class="kw">let</span> v <span class="op">=</span> (<span class="dv">1</span><span class="op">..=</span><span class="dv">10</span>)<span class="op">.</span>map(product)<span class="op">;</span></span> 723<span id="cb40-7"><a href="#cb40-7" aria-hidden="true" tabindex="-1"></a> <span class="kw">let</span> v <span class="op">=</span> (<span class="dv">1</span><span class="op">..=</span><span class="dv">10</span>)<span class="op">.</span>map(product)<span class="op">;</span></span>
507<span id="cb40-8"><a href="#cb40-8" aria-hidden="true" tabindex="-1"></a> <span class="kw">return</span> (<span class="dv">1</span><span class="op">..=</span><span class="dv">10</span>)</span> 724<span id="cb40-8"><a href="#cb40-8" aria-hidden="true" tabindex="-1"></a> <span class="cf">return</span> (<span class="dv">1</span><span class="op">..=</span><span class="dv">10</span>)</span>
508<span id="cb40-9"><a href="#cb40-9" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span>map(<span class="op">|</span>x<span class="op">|</span> v<span class="op">.</span>clone()<span class="op">.</span>map(<span class="op">|</span>f<span class="op">|</span> f(x))<span class="op">.</span>collect())</span> 725<span id="cb40-9"><a href="#cb40-9" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span>map(<span class="op">|</span>x<span class="op">|</span> v<span class="op">.</span>clone()<span class="op">.</span>map(<span class="op">|</span>f<span class="op">|</span> f(x))<span class="op">.</span>collect())</span>
509<span id="cb40-10"><a href="#cb40-10" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span>collect()<span class="op">;</span></span> 726<span id="cb40-10"><a href="#cb40-10" aria-hidden="true" tabindex="-1"></a> <span class="op">.</span>collect()<span class="op">;</span></span>
510<span id="cb40-11"><a href="#cb40-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div> 727<span id="cb40-11"><a href="#cb40-11" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre></div>
511<h3 id="notes">Notes</h3> 728<h3 id="notes">Notes</h3>
512<p>I didn’t quite explain why we use <code>move |arg|</code> in our closure. This is because we want to take ownership of the variable supplied to us. Take a look at this example:</p> 729<p>I didn’t quite explain why we use <code>move |arg|</code> in our
513<div class="sourceCode" id="cb41"><pre class="sourceCode rust"><code class="sourceCode rust"><span id="cb41-1"><a href="#cb41-1" aria-hidden="true" tabindex="-1"></a><span class="kw">let</span> v <span class="op">=</span> add(<span class="dv">5</span>)<span class="op">;</span></span> 730closure. This is because we want to take ownership of the variable
731supplied to us. Take a look at this example:</p>
732<div class="sourceCode" id="cb41"><pre
733class="sourceCode rust"><code class="sourceCode rust"><span id="cb41-1"><a href="#cb41-1" aria-hidden="true" tabindex="-1"></a><span class="kw">let</span> v <span class="op">=</span> add(<span class="dv">5</span>)<span class="op">;</span></span>
514<span id="cb41-2"><a href="#cb41-2" aria-hidden="true" tabindex="-1"></a><span class="kw">let</span> g<span class="op">;</span></span> 734<span id="cb41-2"><a href="#cb41-2" aria-hidden="true" tabindex="-1"></a><span class="kw">let</span> g<span class="op">;</span></span>
515<span id="cb41-3"><a href="#cb41-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span> 735<span id="cb41-3"><a href="#cb41-3" aria-hidden="true" tabindex="-1"></a><span class="op">{</span></span>
516<span id="cb41-4"><a href="#cb41-4" aria-hidden="true" tabindex="-1"></a> <span class="kw">let</span> x <span class="op">=</span> <span class="dv">5</span><span class="op">;</span></span> 736<span id="cb41-4"><a href="#cb41-4" aria-hidden="true" tabindex="-1"></a> <span class="kw">let</span> x <span class="op">=</span> <span class="dv">5</span><span class="op">;</span></span>
517<span id="cb41-5"><a href="#cb41-5" aria-hidden="true" tabindex="-1"></a> g <span class="op">=</span> v(x)<span class="op">;</span></span> 737<span id="cb41-5"><a href="#cb41-5" aria-hidden="true" tabindex="-1"></a> g <span class="op">=</span> v(x)<span class="op">;</span></span>
518<span id="cb41-6"><a href="#cb41-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span> 738<span id="cb41-6"><a href="#cb41-6" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
519<span id="cb41-7"><a href="#cb41-7" aria-hidden="true" tabindex="-1"></a><span class="pp">println!</span>(<span class="st">&quot;{}&quot;</span><span class="op">,</span> g(<span class="dv">2</span>))<span class="op">;</span></span></code></pre></div> 739<span id="cb41-7"><a href="#cb41-7" aria-hidden="true" tabindex="-1"></a><span class="pp">println!</span>(<span class="st">&quot;{}&quot;</span><span class="op">,</span> g(<span class="dv">2</span>))<span class="op">;</span></span></code></pre></div>
520<p>Variable <code>x</code> goes out of scope before <code>g</code> can return a concrete value. If we take ownership of <code>x</code> by <code>move</code>ing it into our closure, we can expect this to work reliably. In fact, rustc understands this, and forces you to use <code>move</code>.</p> 740<p>Variable <code>x</code> goes out of scope before <code>g</code> can
521<p>This usage of <code>move</code> is exactly why <strong>a curried function without a return is useless</strong>. Every variable we pass to our curried function gets moved into its local scope. Playing with these variables cannot cause a change outside this scope. Returning is our only method of interaction with anything beyond this function.</p> 741return a concrete value. If we take ownership of <code>x</code> by
742<code>move</code>ing it into our closure, we can expect this to work
743reliably. In fact, rustc understands this, and forces you to use
744<code>move</code>.</p>
745<p>This usage of <code>move</code> is exactly why <strong>a curried
746function without a return is useless</strong>. Every variable we pass to
747our curried function gets moved into its local scope. Playing with these
748variables cannot cause a change outside this scope. Returning is our
749only method of interaction with anything beyond this function.</p>
522<h3 id="conclusion">Conclusion</h3> 750<h3 id="conclusion">Conclusion</h3>
523<p>Currying may not seem to be all that useful. Curried functions are unwieldy in Rust because the standard library is not built around currying. If you enjoy the possibilities posed by currying, consider taking a look at Haskell or Scheme.</p> 751<p>Currying may not seem to be all that useful. Curried functions are
524<p>My original intention with <a href="https://peppe.rs">peppe.rs</a> was to post condensed articles, a micro blog, but this one turned out extra long.</p> 752unwieldy in Rust because the standard library is not built around
753currying. If you enjoy the possibilities posed by currying, consider
754taking a look at Haskell or Scheme.</p>
755<p>My original intention with <a href="https://peppe.rs">peppe.rs</a>
756was to post condensed articles, a micro blog, but this one turned out
757extra long.</p>
525<p>Perhaps I should call it a ‘macro’ blog :)</p> 758<p>Perhaps I should call it a ‘macro’ blog :)</p>
526<section class="footnotes" role="doc-endnotes"> 759<section id="footnotes" class="footnotes footnotes-end-of-document"
760role="doc-endnotes">
527<hr /> 761<hr />
528<ol> 762<ol>
529<li id="fn1" role="doc-endnote"><p><a href="https://doc.rust-lang.org/book/ch13-01-closures.html">https://doc.rust-lang.org/book/ch13-01-closures.html</a><a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li> 763<li id="fn1"><p><a
530<li id="fn2" role="doc-endnote"><p><a href="https://caniuse.rs">caniuse.rs</a> contains an indexed list of features and their status.<a href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li> 764href="https://doc.rust-lang.org/book/ch13-01-closures.html">https://doc.rust-lang.org/book/ch13-01-closures.html</a><a
765href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
766<li id="fn2"><p><a href="https://caniuse.rs">caniuse.rs</a> contains an
767indexed list of features and their status.<a href="#fnref2"
768class="footnote-back" role="doc-backlink">↩︎</a></p></li>
531</ol> 769</ol>
532</section> 770</section>
533 771
diff --git a/docs/posts/bash_harder_with_vim/index.html b/docs/posts/bash_harder_with_vim/index.html
index 099733a..96210d5 100644
--- a/docs/posts/bash_harder_with_vim/index.html
+++ b/docs/posts/bash_harder_with_vim/index.html
@@ -28,7 +28,7 @@
28 31/07 — 2019 28 31/07 — 2019
29 <div class="stats"> 29 <div class="stats">
30 <span class="stats-number"> 30 <span class="stats-number">
31 24.37 31 24.38
32 </span> 32 </span>
33 <span class="stats-unit">cm</span> 33 <span class="stats-unit">cm</span>
34 &nbsp 34 &nbsp
@@ -42,18 +42,26 @@
42 Bash Harder With Vim 42 Bash Harder With Vim
43 </h1> 43 </h1>
44 <div class="post-text"> 44 <div class="post-text">
45 <p>Bash is tricky, don’t let your editor get in your way. Here’s a couple of neat additions you could make to your <code>vimrc</code> for a better shell programming experience.</p> 45 <p>Bash is tricky, don’t let your editor get in your way. Here’s a
46couple of neat additions you could make to your <code>vimrc</code> for a
47better shell programming experience.</p>
46<h3 id="man-pages-inside-vim">Man pages inside vim</h3> 48<h3 id="man-pages-inside-vim">Man pages inside vim</h3>
47<p>Source this script to get started:</p> 49<p>Source this script to get started:</p>
48<pre><code>runtime ftplugin/man.vim</code></pre> 50<pre><code>runtime ftplugin/man.vim</code></pre>
49<p>Now, you can open manpages inside vim with <code>:Man</code>! It adds nicer syntax highlighting and the ability to jump around with <code>Ctrl-]</code> and <code>Ctrl-T</code>.</p> 51<p>Now, you can open manpages inside vim with <code>:Man</code>! It adds
50<p>By default, the manpage is opened in a horizontal split, I prefer using a new tab:</p> 52nicer syntax highlighting and the ability to jump around with
53<code>Ctrl-]</code> and <code>Ctrl-T</code>.</p>
54<p>By default, the manpage is opened in a horizontal split, I prefer
55using a new tab:</p>
51<pre><code>let g:ft_man_open_mode = &#39;tab&#39;</code></pre> 56<pre><code>let g:ft_man_open_mode = &#39;tab&#39;</code></pre>
52<h3 id="scratchpad-to-test-your-commands">Scratchpad to test your commands</h3> 57<h3 id="scratchpad-to-test-your-commands">Scratchpad to test your
53<p>I often test my <code>sed</code> substitutions, here is a sample from the script used to generate this site:</p> 58commands</h3>
59<p>I often test my <code>sed</code> substitutions, here is a sample from
60the script used to generate this site:</p>
54<pre><code># a substitution to convert snake_case to Title Case With Spaces 61<pre><code># a substitution to convert snake_case to Title Case With Spaces
55echo &quot;$1&quot; | sed -E -e &quot;s/\..+$//g&quot; -e &quot;s/_(.)/ \u\1/g&quot; -e &quot;s/^(.)/\u\1/g&quot;</code></pre> 62echo &quot;$1&quot; | sed -E -e &quot;s/\..+$//g&quot; -e &quot;s/_(.)/ \u\1/g&quot; -e &quot;s/^(.)/\u\1/g&quot;</code></pre>
56<p>Instead of dropping into a new shell, just test it out directly from vim!</p> 63<p>Instead of dropping into a new shell, just test it out directly from
64vim!</p>
57<ul> 65<ul>
58<li>Yank the line into a register:</li> 66<li>Yank the line into a register:</li>
59</ul> 67</ul>
diff --git a/docs/posts/bye_bye_BDFs/index.html b/docs/posts/bye_bye_BDFs/index.html
index 4b2682c..8b9584f 100644
--- a/docs/posts/bye_bye_BDFs/index.html
+++ b/docs/posts/bye_bye_BDFs/index.html
@@ -42,12 +42,30 @@
42 Bye Bye BDFs 42 Bye Bye BDFs
43 </h1> 43 </h1>
44 <div class="post-text"> 44 <div class="post-text">
45 <p>Glyph Bitmap Distribution Format is no more, as the creators of <a href="https://pango.org">Pango</a>, one of the most widely used text rendering libraries, <a href="https://blogs.gnome.org/mclasen/2019/05/25/pango-future-directions/">announced</a> their plans for Pango 1.44.</p> 45 <p>Glyph Bitmap Distribution Format is no more, as the creators of <a
46<p>Until recently, Pango used FreeType to draw fonts. They will be moving over to <a href="https://harfbuzz.org">Harfbuzz</a>, an evolution of FreeType.</p> 46href="https://pango.org">Pango</a>, one of the most widely used text
47rendering libraries, <a
48href="https://blogs.gnome.org/mclasen/2019/05/25/pango-future-directions/">announced</a>
49their plans for Pango 1.44.</p>
50<p>Until recently, Pango used FreeType to draw fonts. They will be
51moving over to <a href="https://harfbuzz.org">Harfbuzz</a>, an evolution
52of FreeType.</p>
47<p><em>Why?</em></p> 53<p><em>Why?</em></p>
48<p>In short, FreeType was hard to work with. It required complex logic, and provided no advantage over Harfbuzz (other than being able to fetch opentype metrics with ease).</p> 54<p>In short, FreeType was hard to work with. It required complex logic,
49<p>Upgrading to Pango v1.44 will break your GTK applications (if you use a <code>bdf</code>/<code>pcf</code> bitmap font). Harfbuzz <em>does</em> support bitmap-only OpenType fonts, <code>otb</code>s. Convert your existing fonts over to <code>otb</code>s using <a href="https://fontforge.github.io">FontForge</a>. It is to be noted that applications such as <code>xterm</code> and <code>rxvt</code> use <code>xft</code> (X FreeType) to render fonts, and will remain unaffected by the update.</p> 55and provided no advantage over Harfbuzz (other than being able to fetch
50<p>Both <a href="https://github.com/nerdypepper/scientifica">scientifica</a> and <a href="https://github.com/nerdypepper/curie">curie</a> will soon ship with bitmap-only OpenType font formats.</p> 56opentype metrics with ease).</p>
57<p>Upgrading to Pango v1.44 will break your GTK applications (if you use
58a <code>bdf</code>/<code>pcf</code> bitmap font). Harfbuzz <em>does</em>
59support bitmap-only OpenType fonts, <code>otb</code>s. Convert your
60existing fonts over to <code>otb</code>s using <a
61href="https://fontforge.github.io">FontForge</a>. It is to be noted that
62applications such as <code>xterm</code> and <code>rxvt</code> use
63<code>xft</code> (X FreeType) to render fonts, and will remain
64unaffected by the update.</p>
65<p>Both <a
66href="https://github.com/nerdypepper/scientifica">scientifica</a> and <a
67href="https://github.com/nerdypepper/curie">curie</a> will soon ship
68with bitmap-only OpenType font formats.</p>
51 69
52 </div> 70 </div>
53 71
diff --git a/docs/posts/call_to_ARMs/index.html b/docs/posts/call_to_ARMs/index.html
index 3331107..1b13213 100644
--- a/docs/posts/call_to_ARMs/index.html
+++ b/docs/posts/call_to_ARMs/index.html
@@ -33,7 +33,7 @@
33 <span class="stats-unit">cm</span> 33 <span class="stats-unit">cm</span>
34 &nbsp 34 &nbsp
35 <span class="stats-number"> 35 <span class="stats-number">
36 2.2 36 2.3
37 </span> 37 </span>
38 <span class="stats-unit">min</span> 38 <span class="stats-unit">min</span>
39 </div> 39 </div>
@@ -42,37 +42,60 @@
42 Call To ARMs 42 Call To ARMs
43 </h1> 43 </h1>
44 <div class="post-text"> 44 <div class="post-text">
45 <p>My 4th semester involves ARM programming. And proprietary tooling (Keil C). But we don’t do that here.</p> 45 <p>My 4th semester involves ARM programming. And proprietary tooling
46(Keil C). But we don’t do that here.</p>
46<h3 id="building">Building</h3> 47<h3 id="building">Building</h3>
47<p>Assembling and linking ARM binaries on non-ARM architecture devices is fairly trivial. I went along with the GNU cross bare metal toolchain binutils, which provides <code>arm-as</code> and <code>arm-ld</code> (among a bunch of other utils that I don’t care about for now).</p> 48<p>Assembling and linking ARM binaries on non-ARM architecture devices
49is fairly trivial. I went along with the GNU cross bare metal toolchain
50binutils, which provides <code>arm-as</code> and <code>arm-ld</code>
51(among a bunch of other utils that I don’t care about for now).</p>
48<p>Assemble <code>.s</code> files with:</p> 52<p>Assemble <code>.s</code> files with:</p>
49<pre class="shell"><code>arm-none-eabi-as main.s -g -march=armv8.1-a -o main.out</code></pre> 53<pre class="shell"><code>arm-none-eabi-as main.s -g -march=armv8.1-a -o main.out</code></pre>
50<p>The <code>-g</code> flag generates extra debugging information that <code>gdb</code> picks up. The <code>-march</code> option establishes target architecture.</p> 54<p>The <code>-g</code> flag generates extra debugging information that
55<code>gdb</code> picks up. The <code>-march</code> option establishes
56target architecture.</p>
51<p>Link <code>.o</code> files with:</p> 57<p>Link <code>.o</code> files with:</p>
52<pre class="shell"><code>arm-none-eabi-ld main.out -o main</code></pre> 58<pre class="shell"><code>arm-none-eabi-ld main.out -o main</code></pre>
53<h3 id="running-and-debugging">Running (and Debugging)</h3> 59<h3 id="running-and-debugging">Running (and Debugging)</h3>
54<p>Things get interesting here. <code>gdb</code> on your x86 machine cannot read nor execute binaries compiled for ARM. So, we simulate an ARM processor using <code>qemu</code>. Now qemu allows you to run <code>gdbserver</code> on startup. Connecting our local <code>gdb</code> instance to <code>gdbserver</code> gives us a view into the program’s execution. Easy!</p> 60<p>Things get interesting here. <code>gdb</code> on your x86 machine
55<p>Run <code>qemu</code>, with <code>gdbserver</code> on port <code>1234</code>, with our ARM binary, <code>main</code>:</p> 61cannot read nor execute binaries compiled for ARM. So, we simulate an
62ARM processor using <code>qemu</code>. Now qemu allows you to run
63<code>gdbserver</code> on startup. Connecting our local <code>gdb</code>
64instance to <code>gdbserver</code> gives us a view into the program’s
65execution. Easy!</p>
66<p>Run <code>qemu</code>, with <code>gdbserver</code> on port
67<code>1234</code>, with our ARM binary, <code>main</code>:</p>
56<pre class="shell"><code>qemu-arm -singlestep -g 1234 main</code></pre> 68<pre class="shell"><code>qemu-arm -singlestep -g 1234 main</code></pre>
57<p>Start up <code>gdb</code> on your machine, and connect to <code>qemu</code>’s <code>gdbserver</code>:</p> 69<p>Start up <code>gdb</code> on your machine, and connect to
70<code>qemu</code>’s <code>gdbserver</code>:</p>
58<pre><code>(gdb) set architecture armv8-a 71<pre><code>(gdb) set architecture armv8-a
59(gdb) target remote localhost:1234 72(gdb) target remote localhost:1234
60(gdb) file main 73(gdb) file main
61Reading symbols from main... # yay!</code></pre> 74Reading symbols from main... # yay!</code></pre>
62<h3 id="gdb-enhanced">GDB Enhanced</h3> 75<h3 id="gdb-enhanced">GDB Enhanced</h3>
63<p><code>gdb</code> is cool, but it’s not nearly as comfortable as well fleshed out emulators/IDEs like Keil. Watching registers, CPSR and memory chunks update <em>is</em> pretty fun.</p> 76<p><code>gdb</code> is cool, but it’s not nearly as comfortable as well
64<p>I came across <code>gdb</code>’s TUI mode (hit <code>C-x C-a</code> or type <code>tui enable</code> at the prompt). TUI mode is a godsend. It highlights the current line of execution, shows you disassembly outputs, updated registers, active breakpoints and more.</p> 77fleshed out emulators/IDEs like Keil. Watching registers, CPSR and
78memory chunks update <em>is</em> pretty fun.</p>
79<p>I came across <code>gdb</code>’s TUI mode (hit <code>C-x C-a</code>
80or type <code>tui enable</code> at the prompt). TUI mode is a godsend.
81It highlights the current line of execution, shows you disassembly
82outputs, updated registers, active breakpoints and more.</p>
65<p><em>But</em>, it is an absolute eyesore.</p> 83<p><em>But</em>, it is an absolute eyesore.</p>
66<p>Say hello to <a href="https://github.com/hugsy/gef">GEF</a>! “GDB Enhanced Features” teaches our old dog some cool new tricks. Here are some additions that made my ARM debugging experience loads better:</p> 84<p>Say hello to <a href="https://github.com/hugsy/gef">GEF</a>! “GDB
85Enhanced Features” teaches our old dog some cool new tricks. Here are
86some additions that made my ARM debugging experience loads better:</p>
67<ul> 87<ul>
68<li>Memory watches</li> 88<li>Memory watches</li>
69<li>Register watches, with up to 7 levels of deref (overkill, I agree)</li> 89<li>Register watches, with up to 7 levels of deref (overkill, I
90agree)</li>
70<li>Stack tracing</li> 91<li>Stack tracing</li>
71</ul> 92</ul>
72<p>And it’s pretty! See for yourself:</p> 93<p>And it’s pretty! See for yourself:</p>
73<p><a href="https://u.peppe.rs/wq.png"><img src="https://u.peppe.rs/wq.png" /></a></p> 94<p><a href="https://u.peppe.rs/wq.png"><img
95src="https://u.peppe.rs/wq.png" /></a></p>
74<h3 id="editing">Editing</h3> 96<h3 id="editing">Editing</h3>
75<p>Vim, with <code>syntax off</code> because it dosen’t handle GNU ARM syntax too well.</p> 97<p>Vim, with <code>syntax off</code> because it dosen’t handle GNU ARM
98syntax too well.</p>
76 99
77 </div> 100 </div>
78 101
diff --git a/docs/posts/color_conundrum/index.html b/docs/posts/color_conundrum/index.html
index 6c493c2..eeba49b 100644
--- a/docs/posts/color_conundrum/index.html
+++ b/docs/posts/color_conundrum/index.html
@@ -33,7 +33,7 @@
33 <span class="stats-unit">cm</span> 33 <span class="stats-unit">cm</span>
34 &nbsp 34 &nbsp
35 <span class="stats-number"> 35 <span class="stats-number">
36 1.3 36 1.4
37 </span> 37 </span>
38 <span class="stats-unit">min</span> 38 <span class="stats-unit">min</span>
39 </div> 39 </div>
@@ -42,14 +42,32 @@
42 Color Conundrum 42 Color Conundrum
43 </h1> 43 </h1>
44 <div class="post-text"> 44 <div class="post-text">
45 <p>This piece aims to highlight (pun intended) some of the reasons behind my <a href="https://u.peppe.rs/bF.png">color free</a> editor setup.</p> 45 <p>This piece aims to highlight (pun intended) some of the reasons
46<p>Imagine highlighting an entire book because <em>all</em> of it is important. That is exactly what (most) syntax highlighting does. It is difficult for the human eye to filter out noise in rainbow barf. Use color to draw attention, not diverge it.</p> 46behind my <a href="https://u.peppe.rs/bF.png">color free</a> editor
47<p>At the same time, a book devoid of color is <em>boring!</em> What is the takeaway from this 10 line paragraph? What are the technical terms used?</p> 47setup.</p>
48<p>Prose and code are certainly different, but the fickle minded human eye is the same. The eye constantly looks for a frame of reference, a focal point. It grows tired when it can’t find one.</p> 48<p>Imagine highlighting an entire book because <em>all</em> of it is
49<p>The following comparison does a better job of explaining (none, ample and over-the-top highlighting, from left to right):</p> 49important. That is exactly what (most) syntax highlighting does. It is
50<p><a href="https://u.peppe.rs/lt.png"><img src="https://u.peppe.rs/lt.png" /></a></p> 50difficult for the human eye to filter out noise in rainbow barf. Use
51<p>Without highlighting (far left), it is hard to differentiate between comments and code! The florid color scheme (far right) is no good either, it contains too many attention grabbers. The center sample is a healthy balance of both. Function calls and constants stand out, and repetitive keywords and other noise (<code>let</code>, <code>as</code>) are mildly dimmed out. Comments and non-code text (sign column, status text) are dimmed further.</p> 51color to draw attention, not diverge it.</p>
52<p>I’ll stop myself before I rant about color contrast and combinations.</p> 52<p>At the same time, a book devoid of color is <em>boring!</em> What is
53the takeaway from this 10 line paragraph? What are the technical terms
54used?</p>
55<p>Prose and code are certainly different, but the fickle minded human
56eye is the same. The eye constantly looks for a frame of reference, a
57focal point. It grows tired when it can’t find one.</p>
58<p>The following comparison does a better job of explaining (none, ample
59and over-the-top highlighting, from left to right):</p>
60<p><a href="https://u.peppe.rs/lt.png"><img
61src="https://u.peppe.rs/lt.png" /></a></p>
62<p>Without highlighting (far left), it is hard to differentiate between
63comments and code! The florid color scheme (far right) is no good
64either, it contains too many attention grabbers. The center sample is a
65healthy balance of both. Function calls and constants stand out, and
66repetitive keywords and other noise (<code>let</code>, <code>as</code>)
67are mildly dimmed out. Comments and non-code text (sign column, status
68text) are dimmed further.</p>
69<p>I’ll stop myself before I rant about color contrast and
70combinations.</p>
53 71
54 </div> 72 </div>
55 73
diff --git a/docs/posts/curing_a_case_of_git-UX/index.html b/docs/posts/curing_a_case_of_git-UX/index.html
index 9c4761c..140436a 100644
--- a/docs/posts/curing_a_case_of_git-UX/index.html
+++ b/docs/posts/curing_a_case_of_git-UX/index.html
@@ -33,7 +33,7 @@
33 <span class="stats-unit">cm</span> 33 <span class="stats-unit">cm</span>
34 &nbsp 34 &nbsp
35 <span class="stats-number"> 35 <span class="stats-number">
36 9.5 36 9.6
37 </span> 37 </span>
38 <span class="stats-unit">min</span> 38 <span class="stats-unit">min</span>
39 </div> 39 </div>
@@ -42,51 +42,86 @@
42 Curing A Case Of Git-UX 42 Curing A Case Of Git-UX
43 </h1> 43 </h1>
44 <div class="post-text"> 44 <div class="post-text">
45 <p>Git worktrees are great, but they fall behind the venerable <code>git checkout</code> sometimes. I attempted to fix that with <a href="https://github.com/junegunn/fzf">fzf</a> and a bit of bash.</p> 45 <p>Git worktrees are great, but they fall behind the venerable
46<p><a href="https://asciinema.org/a/D297ztKRzpE4gAHbPTPmkqYps"><img src="https://asciinema.org/a/D297ztKRzpE4gAHbPTPmkqYps.svg" /></a></p> 46<code>git checkout</code> sometimes. I attempted to fix that with <a
47<p>Fear not if you haven’t heard of “worktrees”, I have included a primer here.<br /> 47href="https://github.com/junegunn/fzf">fzf</a> and a bit of bash.</p>
48<p><a href="https://asciinema.org/a/D297ztKRzpE4gAHbPTPmkqYps"><img
49src="https://asciinema.org/a/D297ztKRzpE4gAHbPTPmkqYps.svg" /></a></p>
50<p>Fear not if you haven’t heard of “worktrees”, I have included a
51primer here.<br />
48<a href="#what-makes-them-clunky">Skip the primer -&gt;</a>.</p> 52<a href="#what-makes-them-clunky">Skip the primer -&gt;</a>.</p>
49<h3 id="why-worktrees">Why Worktrees?</h3> 53<h3 id="why-worktrees">Why Worktrees?</h3>
50<p>Picture this. You are whacking away on a feature branch. Halfway there, in fact. Your friend asks you fix something urgently. You proceed to do one of three things:</p> 54<p>Picture this. You are whacking away on a feature branch. Halfway
55there, in fact. Your friend asks you fix something urgently. You proceed
56to do one of three things:</p>
51<ul> 57<ul>
52<li>create a temporary branch, make a WIP commit, begin working on the fix</li> 58<li>create a temporary branch, make a WIP commit, begin working on the
59fix</li>
53<li>stash away your changes, begin working on the fix</li> 60<li>stash away your changes, begin working on the fix</li>
54<li>unfriend said friend for disturbing your flow</li> 61<li>unfriend said friend for disturbing your flow</li>
55</ul> 62</ul>
56<p>All of these options are … subpar. With the temporary branch, you are forced to create a partial, non-working commit, and then reset said commit once done with the fix. With the stash approach, you are required to now keep a mental model of the stash, be aware of untracked files that don’t get stashed by default, etc. Why won’t git just let you work on two things at the same time without <em>thinking</em> so much?</p> 63<p>All of these options are … subpar. With the temporary branch, you are
57<p>That is exactly what worktrees let you do. Worktrees let you have more than one checkout at a time, each checkout in a separate directory. Like creating a new clone, but safer (it disallows checking out the same branch twice) and a lot more space efficient (the new working tree is “linked” to the “main” worktree, and a good amount of stuff is shared). When your friend asks you to make the fix, you proceed like so:</p> 64forced to create a partial, non-working commit, and then reset said
65commit once done with the fix. With the stash approach, you are required
66to now keep a mental model of the stash, be aware of untracked files
67that don’t get stashed by default, etc. Why won’t git just let you work
68on two things at the same time without <em>thinking</em> so much?</p>
69<p>That is exactly what worktrees let you do. Worktrees let you have
70more than one checkout at a time, each checkout in a separate directory.
71Like creating a new clone, but safer (it disallows checking out the same
72branch twice) and a lot more space efficient (the new working tree is
73“linked” to the “main” worktree, and a good amount of stuff is shared).
74When your friend asks you to make the fix, you proceed like so:</p>
58<ol type="1"> 75<ol type="1">
59<li>Create a new working tree with:</li> 76<li>Create a new working tree with:</li>
60</ol> 77</ol>
61<div class="sourceCode" id="cb1"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="co"># git worktree add -b &lt;branch-name&gt; &lt;path&gt; &lt;from&gt;</span></span> 78<div class="sourceCode" id="cb1"><pre
79class="sourceCode bash"><code class="sourceCode bash"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="co"># git worktree add -b &lt;branch-name&gt; &lt;path&gt; &lt;from&gt;</span></span>
62<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="fu">git</span> worktree add <span class="at">-b</span> fix-stuff /path/to/tree master</span></code></pre></div> 80<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a><span class="fu">git</span> worktree add <span class="at">-b</span> fix-stuff /path/to/tree master</span></code></pre></div>
63<ol start="2" type="1"> 81<ol start="2" type="1">
64<li><code>cd</code> into <code>/path/to/tree</code></li> 82<li><code>cd</code> into <code>/path/to/tree</code></li>
65<li>Fix, test, commit, push, party</li> 83<li>Fix, test, commit, push, party</li>
66<li>Go back to your work, <code>cd -</code></li> 84<li>Go back to your work, <code>cd -</code></li>
67</ol> 85</ol>
68<p>Easy as cake. You didn’t have to settle for a partially working commit, you didn’t to deal with this “stash” thing, <em>and</em> you didn’t have to unfriend your friend. Treating each branch as a directory just <em>feels</em> more intuitive, more UNIX-y.</p> 86<p>Easy as cake. You didn’t have to settle for a partially working
69<p>A few weeks later, you find yourself singing in praise of worktrees, working on several things simultaneously. And at the same time, cursing them for being a little … clunky.</p> 87commit, you didn’t to deal with this “stash” thing, <em>and</em> you
88didn’t have to unfriend your friend. Treating each branch as a directory
89just <em>feels</em> more intuitive, more UNIX-y.</p>
90<p>A few weeks later, you find yourself singing in praise of worktrees,
91working on several things simultaneously. And at the same time, cursing
92them for being a little … clunky.</p>
70<h3 id="what-makes-them-clunky">What makes them clunky?</h3> 93<h3 id="what-makes-them-clunky">What makes them clunky?</h3>
71<p>Worktrees are great at what they claim to do. They stay out of the way when you need a checkout posthaste. However, as you start using them regularly, you realize they are not as flexible as <code>git checkout</code> or <code>git switch</code>.</p> 94<p>Worktrees are great at what they claim to do. They stay out of the
95way when you need a checkout posthaste. However, as you start using them
96regularly, you realize they are not as flexible as
97<code>git checkout</code> or <code>git switch</code>.</p>
72<h4 id="branch-hopping">Branch-hopping</h4> 98<h4 id="branch-hopping">Branch-hopping</h4>
73<p>You can <code>git checkout &lt;branch&gt;</code> from anywhere within a git repository. You can’t “jump” to a worktree in the same fashion. The closest you can get, is to run <code>git worktree list</code>, copy the path corresponding to your branch, and <code>cd</code> into it.</p> 99<p>You can <code>git checkout &lt;branch&gt;</code> from anywhere within
100a git repository. You can’t “jump” to a worktree in the same fashion.
101The closest you can get, is to run <code>git worktree list</code>, copy
102the path corresponding to your branch, and <code>cd</code> into it.</p>
74<p>Branch-hopping with the good ol’ git-checkout:</p> 103<p>Branch-hopping with the good ol’ git-checkout:</p>
75<div class="sourceCode" id="cb2"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="co"># anywhere, anytime</span></span> 104<div class="sourceCode" id="cb2"><pre
105class="sourceCode bash"><code class="sourceCode bash"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="co"># anywhere, anytime</span></span>
76<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="ex">λ</span> git checkout feature/is-ascii-octdigit</span></code></pre></div> 106<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a><span class="ex">λ</span> git checkout feature/is-ascii-octdigit</span></code></pre></div>
77<p>Meanwhile, in worktree world:</p> 107<p>Meanwhile, in worktree world:</p>
78<div class="sourceCode" id="cb3"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="co"># keeping these paths in your head is hard</span></span> 108<div class="sourceCode" id="cb3"><pre
109class="sourceCode bash"><code class="sourceCode bash"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="co"># keeping these paths in your head is hard</span></span>
79<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="ex">λ</span> git worktree list</span> 110<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a><span class="ex">λ</span> git worktree list</span>
80<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="ex">~/worktrees/rustc/master</span> eac6c33bc63 [master]</span> 111<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="ex">~/worktrees/rustc/master</span> eac6c33bc63 <span class="pp">[</span><span class="ss">master</span><span class="pp">]</span></span>
81<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="ex">~/worktrees/rustc/improve-std-char-docs</span> 94cba88553e [improve-std-char-docs]</span> 112<span id="cb3-4"><a href="#cb3-4" aria-hidden="true" tabindex="-1"></a><span class="ex">~/worktrees/rustc/improve-std-char-docs</span> 94cba88553e <span class="pp">[</span><span class="ss">improve</span><span class="pp">-</span><span class="ss">std</span><span class="pp">-</span><span class="ss">char</span><span class="pp">-</span><span class="ss">docs</span><span class="pp">]</span></span>
82<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="ex">~/worktrees/rustc/is-ascii-octdigit</span> bc57be3af7a [feature/is-ascii-octdigit]</span> 113<span id="cb3-5"><a href="#cb3-5" aria-hidden="true" tabindex="-1"></a><span class="ex">~/worktrees/rustc/is-ascii-octdigit</span> bc57be3af7a <span class="pp">[</span><span class="ss">feature/is</span><span class="pp">-</span><span class="ss">ascii</span><span class="pp">-</span><span class="ss">octdigit</span><span class="pp">]</span></span>
83<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="ex">~/my/other/path/oh/god</span> op57or3ns7n [fix/some-error]</span> 114<span id="cb3-6"><a href="#cb3-6" aria-hidden="true" tabindex="-1"></a><span class="ex">~/my/other/path/oh/god</span> op57or3ns7n <span class="pp">[</span><span class="ss">fix/some</span><span class="pp">-</span><span class="ss">error</span><span class="pp">]</span></span>
84<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a></span> 115<span id="cb3-7"><a href="#cb3-7" aria-hidden="true" tabindex="-1"></a></span>
85<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a><span class="ex">λ</span> cd ~/worktrees/rustc/is-ascii-octdigit</span></code></pre></div> 116<span id="cb3-8"><a href="#cb3-8" aria-hidden="true" tabindex="-1"></a><span class="ex">λ</span> cd ~/worktrees/rustc/is-ascii-octdigit</span></code></pre></div>
86<h4 id="branch-previewing">Branch-previewing</h4> 117<h4 id="branch-previewing">Branch-previewing</h4>
87<p>You can “preview” branches with <code>git branch -v</code>. However, to get an idea of what “recent activity” on a worktree looks like, you might need some juggling. You can’t glean much info about a worktree in a jiffy.</p> 118<p>You can “preview” branches with <code>git branch -v</code>. However,
119to get an idea of what “recent activity” on a worktree looks like, you
120might need some juggling. You can’t glean much info about a worktree in
121a jiffy.</p>
88<p>Branch-previewing with the good ol’ git-branch:</p> 122<p>Branch-previewing with the good ol’ git-branch:</p>
89<div class="sourceCode" id="cb4"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ex">λ</span> git branch <span class="at">-v</span></span> 123<div class="sourceCode" id="cb4"><pre
124class="sourceCode bash"><code class="sourceCode bash"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="ex">λ</span> git branch <span class="at">-v</span></span>
90<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="ex">+</span> feature/is-ascii-octdigit bc57be3af7a introduce {char, u8}::is_ ...</span> 125<span id="cb4-2"><a href="#cb4-2" aria-hidden="true" tabindex="-1"></a><span class="ex">+</span> feature/is-ascii-octdigit bc57be3af7a introduce {char, u8}::is_ ...</span>
91<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="ex">+</span> improve-std-char-docs 94cba88553e add whitespace in assert ...</span> 126<span id="cb4-3"><a href="#cb4-3" aria-hidden="true" tabindex="-1"></a><span class="ex">+</span> improve-std-char-docs 94cba88553e add whitespace in assert ...</span>
92<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="ex">*</span> master eac6c33bc63 Auto merge of <span class="co">#100869 - n ...</span></span></code></pre></div> 127<span id="cb4-4"><a href="#cb4-4" aria-hidden="true" tabindex="-1"></a><span class="ex">*</span> master eac6c33bc63 Auto merge of <span class="co">#100869 - n ...</span></span></code></pre></div>
@@ -105,41 +140,60 @@ aa857eb953e Auto merge of #100537 - petrochenkov:pic ...
105 140
106# extra work to make the branch &lt;-&gt; worktree correspondence</code></pre> 141# extra work to make the branch &lt;-&gt; worktree correspondence</code></pre>
107<h4 id="shell-completions">Shell completions</h4> 142<h4 id="shell-completions">Shell completions</h4>
108<p>Lastly, you can bank on shell completions to fill in your branch whilst using <code>git checkout</code>. Worktrees have no such conveniences.</p> 143<p>Lastly, you can bank on shell completions to fill in your branch
144whilst using <code>git checkout</code>. Worktrees have no such
145conveniences.</p>
109<p>We can mend these minor faults with fzf.</p> 146<p>We can mend these minor faults with fzf.</p>
110<h3 id="unclunkifying-worktrees">Unclunkifying worktrees</h3> 147<h3 id="unclunkifying-worktrees">Unclunkifying worktrees</h3>
111<p>I’d suggest looking up <a href="https://github.com/junegunn/fzf">fzf</a> (or <a href="https://github.com/lotabout/skim">skim</a> or <a href="https://github.com/jhawthorn/fzy">fzy</a>). These things make it cake-easy to add interactivity to your shell. Onto fixing the first minor fault, the inability to “jump” to a worktree from anywhere within a git repository.</p> 148<p>I’d suggest looking up <a
112<p>I have a little function called <code>gwj</code> which stands for “git worktree jump”. The idea is to list all the worktrees, select one with fzf, and <code>cd</code> to it upon selection:</p> 149href="https://github.com/junegunn/fzf">fzf</a> (or <a
113<div class="sourceCode" id="cb6"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="fu">gwj ()</span> <span class="kw">{</span></span> 150href="https://github.com/lotabout/skim">skim</a> or <a
151href="https://github.com/jhawthorn/fzy">fzy</a>). These things make it
152cake-easy to add interactivity to your shell. Onto fixing the first
153minor fault, the inability to “jump” to a worktree from anywhere within
154a git repository.</p>
155<p>I have a little function called <code>gwj</code> which stands for
156“git worktree jump”. The idea is to list all the worktrees, select one
157with fzf, and <code>cd</code> to it upon selection:</p>
158<div class="sourceCode" id="cb6"><pre
159class="sourceCode bash"><code class="sourceCode bash"><span id="cb6-1"><a href="#cb6-1" aria-hidden="true" tabindex="-1"></a><span class="fu">gwj ()</span> <span class="kw">{</span></span>
114<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a> <span class="bu">local</span> <span class="va">out</span></span> 160<span id="cb6-2"><a href="#cb6-2" aria-hidden="true" tabindex="-1"></a> <span class="bu">local</span> <span class="va">out</span></span>
115<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a> <span class="va">out</span><span class="op">=</span><span class="va">$(</span><span class="fu">git</span> worktree list <span class="kw">|</span> <span class="ex">fzf</span> <span class="kw">|</span> <span class="fu">awk</span> <span class="st">&#39;{print $1}&#39;</span><span class="va">)</span></span> 161<span id="cb6-3"><a href="#cb6-3" aria-hidden="true" tabindex="-1"></a> <span class="va">out</span><span class="op">=</span><span class="va">$(</span><span class="fu">git</span> worktree list <span class="kw">|</span> <span class="ex">fzf</span> <span class="kw">|</span> <span class="fu">awk</span> <span class="st">&#39;{print $1}&#39;</span><span class="va">)</span></span>
116<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a> <span class="bu">cd</span> <span class="va">$out</span></span> 162<span id="cb6-4"><a href="#cb6-4" aria-hidden="true" tabindex="-1"></a> <span class="bu">cd</span> <span class="va">$out</span></span>
117<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="kw">}</span></span></code></pre></div> 163<span id="cb6-5"><a href="#cb6-5" aria-hidden="true" tabindex="-1"></a><span class="kw">}</span></span></code></pre></div>
118<p>That is all of it really. Head into a git repository:</p> 164<p>That is all of it really. Head into a git repository:</p>
119<div class="sourceCode" id="cb7"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="co"># here, &quot;master&quot; is a directory, which contains my main</span></span> 165<div class="sourceCode" id="cb7"><pre
166class="sourceCode bash"><code class="sourceCode bash"><span id="cb7-1"><a href="#cb7-1" aria-hidden="true" tabindex="-1"></a><span class="co"># here, &quot;master&quot; is a directory, which contains my main</span></span>
120<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="co"># worktree: a checkout of the master branch on rust-lang/rust </span></span> 167<span id="cb7-2"><a href="#cb7-2" aria-hidden="true" tabindex="-1"></a><span class="co"># worktree: a checkout of the master branch on rust-lang/rust </span></span>
121<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="ex">λ</span> cd ~/worktrees/rustc/master/library/core/src</span> 168<span id="cb7-3"><a href="#cb7-3" aria-hidden="true" tabindex="-1"></a><span class="ex">λ</span> cd ~/worktrees/rustc/master/library/core/src</span>
122<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="ex">λ</span> <span class="co"># hack away</span></span></code></pre></div> 169<span id="cb7-4"><a href="#cb7-4" aria-hidden="true" tabindex="-1"></a><span class="ex">λ</span> <span class="co"># hack away</span></span></code></pre></div>
123<p>Preferably one with a few worktrees:</p> 170<p>Preferably one with a few worktrees:</p>
124<div class="sourceCode" id="cb8"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="ex">λ</span> git worktree list</span> 171<div class="sourceCode" id="cb8"><pre
125<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="ex">~/worktrees/rustc/master</span> eac6c33bc63 [master]</span> 172class="sourceCode bash"><code class="sourceCode bash"><span id="cb8-1"><a href="#cb8-1" aria-hidden="true" tabindex="-1"></a><span class="ex">λ</span> git worktree list</span>
126<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="ex">~/worktrees/rustc/improve-std-char-docs</span> 94cba88553e [improve-std-char-docs]</span> 173<span id="cb8-2"><a href="#cb8-2" aria-hidden="true" tabindex="-1"></a><span class="ex">~/worktrees/rustc/master</span> eac6c33bc63 <span class="pp">[</span><span class="ss">master</span><span class="pp">]</span></span>
127<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a><span class="ex">~/worktrees/rustc/is-ascii-octdigit</span> bc57be3af7a [feature/is-ascii-octdigit]</span></code></pre></div> 174<span id="cb8-3"><a href="#cb8-3" aria-hidden="true" tabindex="-1"></a><span class="ex">~/worktrees/rustc/improve-std-char-docs</span> 94cba88553e <span class="pp">[</span><span class="ss">improve</span><span class="pp">-</span><span class="ss">std</span><span class="pp">-</span><span class="ss">char</span><span class="pp">-</span><span class="ss">docs</span><span class="pp">]</span></span>
128<p>And hit <code>gwj</code> (pretend that the pipe, |, is your cursor):</p> 175<span id="cb8-4"><a href="#cb8-4" aria-hidden="true" tabindex="-1"></a><span class="ex">~/worktrees/rustc/is-ascii-octdigit</span> bc57be3af7a <span class="pp">[</span><span class="ss">feature/is</span><span class="pp">-</span><span class="ss">ascii</span><span class="pp">-</span><span class="ss">octdigit</span><span class="pp">]</span></span></code></pre></div>
129<div class="sourceCode" id="cb9"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="ex">λ</span> gwj</span> 176<p>And hit <code>gwj</code> (pretend that the pipe, |, is your
177cursor):</p>
178<div class="sourceCode" id="cb9"><pre
179class="sourceCode bash"><code class="sourceCode bash"><span id="cb9-1"><a href="#cb9-1" aria-hidden="true" tabindex="-1"></a><span class="ex">λ</span> gwj</span>
130<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> <span class="kw">|</span></span> 180<span id="cb9-2"><a href="#cb9-2" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> <span class="kw">|</span></span>
131<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a> <span class="ex">4/4</span></span> 181<span id="cb9-3"><a href="#cb9-3" aria-hidden="true" tabindex="-1"></a> <span class="ex">4/4</span></span>
132<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> ~/worktrees/rustc/master <span class="ex">eac6c33bc63</span> [master]</span> 182<span id="cb9-4"><a href="#cb9-4" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> ~/worktrees/rustc/master <span class="ex">eac6c33bc63</span> <span class="pp">[</span><span class="ss">master</span><span class="pp">]</span></span>
133<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a> <span class="ex">~/worktrees/rustc/improve-std-char-docs</span> 94cba88553e [improve-std-char-docs]</span> 183<span id="cb9-5"><a href="#cb9-5" aria-hidden="true" tabindex="-1"></a> <span class="ex">~/worktrees/rustc/improve-std-char-docs</span> 94cba88553e <span class="pp">[</span><span class="ss">improve</span><span class="pp">-</span><span class="ss">std</span><span class="pp">-</span><span class="ss">char</span><span class="pp">-</span><span class="ss">docs</span><span class="pp">]</span></span>
134<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a> <span class="ex">~/worktrees/rustc/is-ascii-octdigit</span> bc57be3af7a [feature/is-ascii-octdigit]</span></code></pre></div> 184<span id="cb9-6"><a href="#cb9-6" aria-hidden="true" tabindex="-1"></a> <span class="ex">~/worktrees/rustc/is-ascii-octdigit</span> bc57be3af7a <span class="pp">[</span><span class="ss">feature/is</span><span class="pp">-</span><span class="ss">ascii</span><span class="pp">-</span><span class="ss">octdigit</span><span class="pp">]</span></span></code></pre></div>
135<p>Approximately type in your branch of choice:</p> 185<p>Approximately type in your branch of choice:</p>
136<div class="sourceCode" id="cb10"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="ex">λ</span> gwj</span> 186<div class="sourceCode" id="cb10"><pre
187class="sourceCode bash"><code class="sourceCode bash"><span id="cb10-1"><a href="#cb10-1" aria-hidden="true" tabindex="-1"></a><span class="ex">λ</span> gwj</span>
137<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> docs<span class="kw">|</span></span> 188<span id="cb10-2"><a href="#cb10-2" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> docs<span class="kw">|</span></span>
138<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a> <span class="ex">4/4</span></span> 189<span id="cb10-3"><a href="#cb10-3" aria-hidden="true" tabindex="-1"></a> <span class="ex">4/4</span></span>
139<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> ~/worktrees/rustc/improve-std-char-docs <span class="ex">94cba88553e</span> [improve-std-char-docs]</span></code></pre></div> 190<span id="cb10-4"><a href="#cb10-4" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> ~/worktrees/rustc/improve-std-char-docs <span class="ex">94cba88553e</span> <span class="pp">[</span><span class="ss">improve</span><span class="pp">-</span><span class="ss">std</span><span class="pp">-</span><span class="ss">char</span><span class="pp">-</span><span class="ss">docs</span><span class="pp">]</span></span></code></pre></div>
140<p>And hit enter. You should find yourself in the selected worktree.</p> 191<p>And hit enter. You should find yourself in the selected worktree.</p>
141<p>Onward, to the next fault, lack of preview-bility. We can utilize fzf’s aptly named <code>--preview</code> flag, to, well, preview our worktree before performing a selection:</p> 192<p>Onward, to the next fault, lack of preview-bility. We can utilize
142<div class="sourceCode" id="cb11"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="fu">gwj ()</span> <span class="kw">{</span></span> 193fzf’s aptly named <code>--preview</code> flag, to, well, preview our
194worktree before performing a selection:</p>
195<div class="sourceCode" id="cb11"><pre
196class="sourceCode bash"><code class="sourceCode bash"><span id="cb11-1"><a href="#cb11-1" aria-hidden="true" tabindex="-1"></a><span class="fu">gwj ()</span> <span class="kw">{</span></span>
143<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a> <span class="bu">local</span> <span class="va">out</span></span> 197<span id="cb11-2"><a href="#cb11-2" aria-hidden="true" tabindex="-1"></a> <span class="bu">local</span> <span class="va">out</span></span>
144<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a> <span class="va">out</span><span class="op">=</span><span class="va">$(</span></span> 198<span id="cb11-3"><a href="#cb11-3" aria-hidden="true" tabindex="-1"></a> <span class="va">out</span><span class="op">=</span><span class="va">$(</span></span>
145<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a> <span class="fu">git</span> worktree list <span class="kw">|</span></span> 199<span id="cb11-4"><a href="#cb11-4" aria-hidden="true" tabindex="-1"></a> <span class="fu">git</span> worktree list <span class="kw">|</span></span>
@@ -148,8 +202,10 @@ aa857eb953e Auto merge of #100537 - petrochenkov:pic ...
148<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a> <span class="va">)</span></span> 202<span id="cb11-7"><a href="#cb11-7" aria-hidden="true" tabindex="-1"></a> <span class="va">)</span></span>
149<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a> <span class="bu">cd</span> <span class="va">$out</span></span> 203<span id="cb11-8"><a href="#cb11-8" aria-hidden="true" tabindex="-1"></a> <span class="bu">cd</span> <span class="va">$out</span></span>
150<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a><span class="kw">}</span></span></code></pre></div> 204<span id="cb11-9"><a href="#cb11-9" aria-hidden="true" tabindex="-1"></a><span class="kw">}</span></span></code></pre></div>
151<p>Once again, hit <code>gwj</code> inside a git repository with linked worktrees:</p> 205<p>Once again, hit <code>gwj</code> inside a git repository with linked
152<div class="sourceCode" id="cb12"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="ex">λ</span> gwj</span> 206worktrees:</p>
207<div class="sourceCode" id="cb12"><pre
208class="sourceCode bash"><code class="sourceCode bash"><span id="cb12-1"><a href="#cb12-1" aria-hidden="true" tabindex="-1"></a><span class="ex">λ</span> gwj</span>
153<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="ex">╭─────────────────────────────────────────────────────────╮</span></span> 209<span id="cb12-2"><a href="#cb12-2" aria-hidden="true" tabindex="-1"></a><span class="ex">╭─────────────────────────────────────────────────────────╮</span></span>
154<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a><span class="ex">│</span> eac6c33bc63 Auto merge of 100869 nnethercote:replace... │</span> 210<span id="cb12-3"><a href="#cb12-3" aria-hidden="true" tabindex="-1"></a><span class="ex">│</span> eac6c33bc63 Auto merge of 100869 nnethercote:replace... │</span>
155<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a><span class="ex">│</span> b32223fec10 Auto merge of 100707 dzvon:fix-typo, r=d... │</span> 211<span id="cb12-4"><a href="#cb12-4" aria-hidden="true" tabindex="-1"></a><span class="ex">│</span> b32223fec10 Auto merge of 100707 dzvon:fix-typo, r=d... │</span>
@@ -167,9 +223,16 @@ aa857eb953e Auto merge of #100537 - petrochenkov:pic ...
167<span id="cb12-16"><a href="#cb12-16" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> /home/np/worktrees/compiler/master <span class="ex">eac6c...</span></span> 223<span id="cb12-16"><a href="#cb12-16" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> /home/np/worktrees/compiler/master <span class="ex">eac6c...</span></span>
168<span id="cb12-17"><a href="#cb12-17" aria-hidden="true" tabindex="-1"></a> <span class="ex">/home/np/worktrees/compiler/improve-std-char-docs</span> 94cba...</span> 224<span id="cb12-17"><a href="#cb12-17" aria-hidden="true" tabindex="-1"></a> <span class="ex">/home/np/worktrees/compiler/improve-std-char-docs</span> 94cba...</span>
169<span id="cb12-18"><a href="#cb12-18" aria-hidden="true" tabindex="-1"></a> <span class="ex">/home/np/worktrees/compiler/is-ascii-octdigit</span> bc57b...</span></code></pre></div> 225<span id="cb12-18"><a href="#cb12-18" aria-hidden="true" tabindex="-1"></a> <span class="ex">/home/np/worktrees/compiler/is-ascii-octdigit</span> bc57b...</span></code></pre></div>
170<p>A fancy preview of the last 10 commits on the branch that the selected worktree corresponds to. In other words, sight for sore eyes. Our little script is already shaping up to be useful, you hit <code>gwj</code>, browse through your worktrees, preview each one and automatically <code>cd</code> to your selection. But we are not done yet.</p> 226<p>A fancy preview of the last 10 commits on the branch that the
171<p>The last fault was lack shell completions. A quick review of what a shell completion really does:</p> 227selected worktree corresponds to. In other words, sight for sore eyes.
172<div class="sourceCode" id="cb13"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="ex">λ</span> git checkout f<span class="op">&lt;</span>tab<span class="op">&gt;</span></span> 228Our little script is already shaping up to be useful, you hit
229<code>gwj</code>, browse through your worktrees, preview each one and
230automatically <code>cd</code> to your selection. But we are not done
231yet.</p>
232<p>The last fault was lack shell completions. A quick review of what a
233shell completion really does:</p>
234<div class="sourceCode" id="cb13"><pre
235class="sourceCode bash"><code class="sourceCode bash"><span id="cb13-1"><a href="#cb13-1" aria-hidden="true" tabindex="-1"></a><span class="ex">λ</span> git checkout f<span class="op">&lt;</span>tab<span class="op">&gt;</span></span>
173<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a><span class="ex">feature/is-ascii-octdigit</span></span> 236<span id="cb13-2"><a href="#cb13-2" aria-hidden="true" tabindex="-1"></a><span class="ex">feature/is-ascii-octdigit</span></span>
174<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a><span class="ex">fix/some-error</span></span> 237<span id="cb13-3"><a href="#cb13-3" aria-hidden="true" tabindex="-1"></a><span class="ex">fix/some-error</span></span>
175<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a><span class="ex">format-doc-tests</span></span> 238<span id="cb13-4"><a href="#cb13-4" aria-hidden="true" tabindex="-1"></a><span class="ex">format-doc-tests</span></span>
@@ -177,16 +240,22 @@ aa857eb953e Auto merge of #100537 - petrochenkov:pic ...
177<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a><span class="ex">λ</span> git checkout feat<span class="op">&lt;</span>tab<span class="op">&gt;</span></span> 240<span id="cb13-6"><a href="#cb13-6" aria-hidden="true" tabindex="-1"></a><span class="ex">λ</span> git checkout feat<span class="op">&lt;</span>tab<span class="op">&gt;</span></span>
178<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a></span> 241<span id="cb13-7"><a href="#cb13-7" aria-hidden="true" tabindex="-1"></a></span>
179<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a><span class="ex">λ</span> git checkout feature/is-ascii-octdigit</span></code></pre></div> 242<span id="cb13-8"><a href="#cb13-8" aria-hidden="true" tabindex="-1"></a><span class="ex">λ</span> git checkout feature/is-ascii-octdigit</span></code></pre></div>
180<p>Each time you hit “tab”, the shell produces a few “completion candidates”, and once you have just a single candidate left, the shell inserts that for you directly into your edit line. Of course, this process varies from shell to shell.</p> 243<p>Each time you hit “tab”, the shell produces a few “completion
181<p>fzf narrows down your options as you type into the prompt, but you still have to:</p> 244candidates”, and once you have just a single candidate left, the shell
245inserts that for you directly into your edit line. Of course, this
246process varies from shell to shell.</p>
247<p>fzf narrows down your options as you type into the prompt, but you
248still have to:</p>
182<ol type="1"> 249<ol type="1">
183<li>Type <code>gwj</code></li> 250<li>Type <code>gwj</code></li>
184<li>Hit enter</li> 251<li>Hit enter</li>
185<li>Type out a query and narrow down your search</li> 252<li>Type out a query and narrow down your search</li>
186<li>Hit enter</li> 253<li>Hit enter</li>
187</ol> 254</ol>
188<p>We can speed that up a bit, have fzf narrow down the candidates on startup, just like our shell does:</p> 255<p>We can speed that up a bit, have fzf narrow down the candidates on
189<div class="sourceCode" id="cb14"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="fu">gwj ()</span> <span class="kw">{</span></span> 256startup, just like our shell does:</p>
257<div class="sourceCode" id="cb14"><pre
258class="sourceCode bash"><code class="sourceCode bash"><span id="cb14-1"><a href="#cb14-1" aria-hidden="true" tabindex="-1"></a><span class="fu">gwj ()</span> <span class="kw">{</span></span>
190<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a> <span class="bu">local</span> <span class="va">out</span> <span class="va">query</span></span> 259<span id="cb14-2"><a href="#cb14-2" aria-hidden="true" tabindex="-1"></a> <span class="bu">local</span> <span class="va">out</span> <span class="va">query</span></span>
191<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a> <span class="va">query</span><span class="op">=</span><span class="st">&quot;</span><span class="va">${1</span><span class="op">:-</span> <span class="va">}</span><span class="st">&quot;</span></span> 260<span id="cb14-3"><a href="#cb14-3" aria-hidden="true" tabindex="-1"></a> <span class="va">query</span><span class="op">=</span><span class="st">&quot;</span><span class="va">${1</span><span class="op">:-</span> <span class="va">}</span><span class="st">&quot;</span></span>
192<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a> <span class="va">out</span><span class="op">=</span><span class="va">$(</span></span> 261<span id="cb14-4"><a href="#cb14-4" aria-hidden="true" tabindex="-1"></a> <span class="va">out</span><span class="op">=</span><span class="va">$(</span></span>
@@ -196,8 +265,12 @@ aa857eb953e Auto merge of #100537 - petrochenkov:pic ...
196<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a> <span class="va">)</span></span> 265<span id="cb14-8"><a href="#cb14-8" aria-hidden="true" tabindex="-1"></a> <span class="va">)</span></span>
197<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a> <span class="bu">cd</span> <span class="va">$out</span></span> 266<span id="cb14-9"><a href="#cb14-9" aria-hidden="true" tabindex="-1"></a> <span class="bu">cd</span> <span class="va">$out</span></span>
198<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a><span class="kw">}</span></span></code></pre></div> 267<span id="cb14-10"><a href="#cb14-10" aria-hidden="true" tabindex="-1"></a><span class="kw">}</span></span></code></pre></div>
199<p>The change is extremely tiny, blink-and-you’ll-miss-it kinda tiny. We added a little <code>--query</code> flag, that allows you to prefill the prompt, and the <code>-1</code> flag, that avoids the interactive finder if only one match exists on startup:</p> 268<p>The change is extremely tiny, blink-and-you’ll-miss-it kinda tiny. We
200<div class="sourceCode" id="cb15"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="co"># skip through the fzf prompt:</span></span> 269added a little <code>--query</code> flag, that allows you to prefill the
270prompt, and the <code>-1</code> flag, that avoids the interactive finder
271if only one match exists on startup:</p>
272<div class="sourceCode" id="cb15"><pre
273class="sourceCode bash"><code class="sourceCode bash"><span id="cb15-1"><a href="#cb15-1" aria-hidden="true" tabindex="-1"></a><span class="co"># skip through the fzf prompt:</span></span>
201<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a><span class="ex">λ</span> gwj master</span> 274<span id="cb15-2"><a href="#cb15-2" aria-hidden="true" tabindex="-1"></a><span class="ex">λ</span> gwj master</span>
202<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a><span class="co"># cd -- ~/worktrees/rustc/master</span></span> 275<span id="cb15-3"><a href="#cb15-3" aria-hidden="true" tabindex="-1"></a><span class="co"># cd -- ~/worktrees/rustc/master</span></span>
203<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a></span> 276<span id="cb15-4"><a href="#cb15-4" aria-hidden="true" tabindex="-1"></a></span>
@@ -212,8 +285,11 @@ aa857eb953e Auto merge of #100537 - petrochenkov:pic ...
212<span id="cb15-13"><a href="#cb15-13" aria-hidden="true" tabindex="-1"></a> <span class="ex">2/2</span></span> 285<span id="cb15-13"><a href="#cb15-13" aria-hidden="true" tabindex="-1"></a> <span class="ex">2/2</span></span>
213<span id="cb15-14"><a href="#cb15-14" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> /home/np/worktrees/compiler/improve-const-perf <span class="ex">eac6c...</span></span> 286<span id="cb15-14"><a href="#cb15-14" aria-hidden="true" tabindex="-1"></a><span class="op">&gt;</span> /home/np/worktrees/compiler/improve-const-perf <span class="ex">eac6c...</span></span>
214<span id="cb15-15"><a href="#cb15-15" aria-hidden="true" tabindex="-1"></a> <span class="ex">/home/np/worktrees/compiler/improve-std-char-docs</span> 94cba...</span></code></pre></div> 287<span id="cb15-15"><a href="#cb15-15" aria-hidden="true" tabindex="-1"></a> <span class="ex">/home/np/worktrees/compiler/improve-std-char-docs</span> 94cba...</span></code></pre></div>
215<p>Throw some error handling in there, hook up a similar script to improve the UX of <code>git worktree remove</code>, go wild. A few more helpers I’ve got:</p> 288<p>Throw some error handling in there, hook up a similar script to
216<div class="sourceCode" id="cb16"><pre class="sourceCode bash"><code class="sourceCode bash"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="co"># gwa /path/to/branch-name</span></span> 289improve the UX of <code>git worktree remove</code>, go wild. A few more
290helpers I’ve got:</p>
291<div class="sourceCode" id="cb16"><pre
292class="sourceCode bash"><code class="sourceCode bash"><span id="cb16-1"><a href="#cb16-1" aria-hidden="true" tabindex="-1"></a><span class="co"># gwa /path/to/branch-name</span></span>
217<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a><span class="co"># creates a new branch and &quot;switches&quot; to it</span></span> 293<span id="cb16-2"><a href="#cb16-2" aria-hidden="true" tabindex="-1"></a><span class="co"># creates a new branch and &quot;switches&quot; to it</span></span>
218<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a><span class="kw">function</span><span class="fu"> gwa ()</span> <span class="kw">{</span></span> 294<span id="cb16-3"><a href="#cb16-3" aria-hidden="true" tabindex="-1"></a><span class="kw">function</span><span class="fu"> gwa ()</span> <span class="kw">{</span></span>
219<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a> <span class="fu">git</span> worktree add <span class="st">&quot;</span><span class="va">$1</span><span class="st">&quot;</span> <span class="kw">&amp;&amp;</span> <span class="bu">cd</span> <span class="st">&quot;</span><span class="va">$1</span><span class="st">&quot;</span></span> 295<span id="cb16-4"><a href="#cb16-4" aria-hidden="true" tabindex="-1"></a> <span class="fu">git</span> worktree add <span class="st">&quot;</span><span class="va">$1</span><span class="st">&quot;</span> <span class="kw">&amp;&amp;</span> <span class="bu">cd</span> <span class="st">&quot;</span><span class="va">$1</span><span class="st">&quot;</span></span>
diff --git a/docs/posts/font_size_fallacies/index.html b/docs/posts/font_size_fallacies/index.html
index 9577376..51f5b4b 100644
--- a/docs/posts/font_size_fallacies/index.html
+++ b/docs/posts/font_size_fallacies/index.html
@@ -28,12 +28,12 @@
28 17/03 — 2020 28 17/03 — 2020
29 <div class="stats"> 29 <div class="stats">
30 <span class="stats-number"> 30 <span class="stats-number">
31 32.36 31 32.37
32 </span> 32 </span>
33 <span class="stats-unit">cm</span> 33 <span class="stats-unit">cm</span>
34 &nbsp 34 &nbsp
35 <span class="stats-number"> 35 <span class="stats-number">
36 3.2 36 3.3
37 </span> 37 </span>
38 <span class="stats-unit">min</span> 38 <span class="stats-unit">min</span>
39 </div> 39 </div>
@@ -42,34 +42,75 @@
42 Font Size Fallacies 42 Font Size Fallacies
43 </h1> 43 </h1>
44 <div class="post-text"> 44 <div class="post-text">
45 <p>I am not an expert with fonts, but I do have some experience <a href="#fn1" class="footnote-ref" id="fnref1" role="doc-noteref"><sup>1</sup></a>, and common sense. This post aims to debunk some misconceptions about font sizes!</p> 45 <p>I am not an expert with fonts, but I do have some experience <a
46<p>11 px on your display is <em>probably not</em> 11 px on my display. Let’s do some quick math. I have two displays, 1366x768 @ 21" and another with 1920x1080 @ 13", call them <code>A</code> and <code>B</code> for now.</p> 46href="#fn1" class="footnote-ref" id="fnref1"
47<p>Display <code>A</code> has 1,049,088 pixels. A pixel is a square, of side say, <code>s</code> cm. The total area covered by my 21" display is about 1,066 cm^2 (41x26). Thus,</p> 47role="doc-noteref"><sup>1</sup></a>, and common sense. This post aims to
48debunk some misconceptions about font sizes!</p>
49<p>11 px on your display is <em>probably not</em> 11 px on my display.
50Let’s do some quick math. I have two displays, 1366x768 @ 21” and
51another with 1920x1080 @ 13”, call them <code>A</code> and
52<code>B</code> for now.</p>
53<p>Display <code>A</code> has 1,049,088 pixels. A pixel is a square, of
54side say, <code>s</code> cm. The total area covered by my 21” display is
55about 1,066 cm^2 (41x26). Thus,</p>
48<pre><code>Display A 56<pre><code>Display A
49Dimensions: 1366x768 @ 21&quot; (41x26 sq. cm) 57Dimensions: 1366x768 @ 21&quot; (41x26 sq. cm)
501,049,088 s^2 = 1066 581,049,088 s^2 = 1066
51 s = 0.0318 cm (side of a pixel on Display A)</code></pre> 59 s = 0.0318 cm (side of a pixel on Display A)</code></pre>
52<p>Bear with me, as I repeat the number crunching for Display <code>B</code>:</p> 60<p>Bear with me, as I repeat the number crunching for Display
61<code>B</code>:</p>
53<pre><code>Display B 62<pre><code>Display B
54Dimensions: 1920x1080 @ 13&quot; (29.5x16.5 sq. cm) 63Dimensions: 1920x1080 @ 13&quot; (29.5x16.5 sq. cm)
552,073,600 s^2 = 486.75 642,073,600 s^2 = 486.75
56 s = 0.0153 cm (side of a pixel on Display B)</code></pre> 65 s = 0.0153 cm (side of a pixel on Display B)</code></pre>
57<p>The width of a pixel on Display <code>A</code> is <em>double</em> the width of a pixel on Display <code>B</code>. The area occupied by a pixel on Display <code>A</code> is <em>4 times</em> the area occupied by a pixel on Display <code>B</code>.</p> 66<p>The width of a pixel on Display <code>A</code> is <em>double</em> the
67width of a pixel on Display <code>B</code>. The area occupied by a pixel
68on Display <code>A</code> is <em>4 times</em> the area occupied by a
69pixel on Display <code>B</code>.</p>
58<p><em>The size of a pixel varies from display to display!</em></p> 70<p><em>The size of a pixel varies from display to display!</em></p>
59<p>A 5x11 bitmap font on Display <code>A</code> would be around 4 mm tall whereas the same bitmap font on Display <code>B</code> would be around 1.9 mm tall. A 11 px tall character on <code>B</code> is visually equivalent to a 5 px character on <code>A</code>. When you view a screenshot of Display <code>A</code> on Display <code>B</code>, the contents are shrunk down by a factor of 2!</p> 71<p>A 5x11 bitmap font on Display <code>A</code> would be around 4 mm
60<p>So screen resolution is not enough, how else do we measure size? Pixel Density! Keen readers will realize that the 5^th grade math problem we solved up there showcases pixel density, or, pixels per cm (PPCM). Usually we deal with pixels per inch (PPI).</p> 72tall whereas the same bitmap font on Display <code>B</code> would be
61<p><strong>Note:</strong> PPI is not to be confused with DPI <a href="#fn2" class="footnote-ref" id="fnref2" role="doc-noteref"><sup>2</sup></a> (dots per inch). DPI is defined for printers.</p> 73around 1.9 mm tall. A 11 px tall character on <code>B</code> is visually
62<p>In our example, <code>A</code> is a 75 ppi display and <code>B</code> is around 165 ppi <a href="#fn3" class="footnote-ref" id="fnref3" role="doc-noteref"><sup>3</sup></a>. A low ppi display appears to be ‘pixelated’, because the pixels are more prominent, much like Display <code>A</code>. A higher ppi usually means you can view larger images and render crispier fonts. The average desktop display can stuff 100-200 pixels per inch. Smart phones usually fall into the 400-600 ppi (XXXHDPI) category. The human eye fails to differentiate detail past 300 ppi.</p> 74equivalent to a 5 px character on <code>A</code>. When you view a
63<p><em>So … streaming an 8K video on a 60" TV provides the same clarity as a HD video on a smart phone?</em></p> 75screenshot of Display <code>A</code> on Display <code>B</code>, the
64<p>Absolutely. Well, clarity is subjective, but the amount of detail you can discern on mobile displays has always been limited. Salty consumers of the Xperia 1 <a href="#fn4" class="footnote-ref" id="fnref4" role="doc-noteref"><sup>4</sup></a> will say otherwise.</p> 76contents are shrunk down by a factor of 2!</p>
65<p>Maybe I will talk about font rendering in another post, but thats all for now. Don’t judge a font size by its screenshot.</p> 77<p>So screen resolution is not enough, how else do we measure size?
66<section class="footnotes" role="doc-endnotes"> 78Pixel Density! Keen readers will realize that the 5^th grade math
79problem we solved up there showcases pixel density, or, pixels per cm
80(PPCM). Usually we deal with pixels per inch (PPI).</p>
81<p><strong>Note:</strong> PPI is not to be confused with DPI <a
82href="#fn2" class="footnote-ref" id="fnref2"
83role="doc-noteref"><sup>2</sup></a> (dots per inch). DPI is defined for
84printers.</p>
85<p>In our example, <code>A</code> is a 75 ppi display and <code>B</code>
86is around 165 ppi <a href="#fn3" class="footnote-ref" id="fnref3"
87role="doc-noteref"><sup>3</sup></a>. A low ppi display appears to be
88‘pixelated’, because the pixels are more prominent, much like Display
89<code>A</code>. A higher ppi usually means you can view larger images
90and render crispier fonts. The average desktop display can stuff 100-200
91pixels per inch. Smart phones usually fall into the 400-600 ppi
92(XXXHDPI) category. The human eye fails to differentiate detail past 300
93ppi.</p>
94<p><em>So … streaming an 8K video on a 60” TV provides the same clarity
95as a HD video on a smart phone?</em></p>
96<p>Absolutely. Well, clarity is subjective, but the amount of detail you
97can discern on mobile displays has always been limited. Salty consumers
98of the Xperia 1 <a href="#fn4" class="footnote-ref" id="fnref4"
99role="doc-noteref"><sup>4</sup></a> will say otherwise.</p>
100<p>Maybe I will talk about font rendering in another post, but thats all
101for now. Don’t judge a font size by its screenshot.</p>
102<section id="footnotes" class="footnotes footnotes-end-of-document"
103role="doc-endnotes">
67<hr /> 104<hr />
68<ol> 105<ol>
69<li id="fn1" role="doc-endnote"><p>https://github.com/nerdypepper/scientifica<a href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li> 106<li id="fn1"><p>https://github.com/nerdypepper/scientifica<a
70<li id="fn2" role="doc-endnote"><p>https://en.wikipedia.org/wiki/Dots_per_inch<a href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li> 107href="#fnref1" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
71<li id="fn3" role="doc-endnote"><p>https://www.sven.de/dpi/<a href="#fnref3" class="footnote-back" role="doc-backlink">↩︎</a></p></li> 108<li id="fn2"><p>https://en.wikipedia.org/wiki/Dots_per_inch<a
72<li id="fn4" role="doc-endnote"><p>https://en.wikipedia.org/wiki/Sony_Xperia_1<a href="#fnref4" class="footnote-back" role="doc-backlink">↩︎</a></p></li> 109href="#fnref2" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
110<li id="fn3"><p>https://www.sven.de/dpi/<a href="#fnref3"
111class="footnote-back" role="doc-backlink">↩︎</a></p></li>
112<li id="fn4"><p>https://en.wikipedia.org/wiki/Sony_Xperia_1<a
113href="#fnref4" class="footnote-back" role="doc-backlink">↩︎</a></p></li>
73</ol> 114</ol>
74</section> 115</section>
75 116
diff --git a/docs/posts/get_better_at_yanking_and_putting_in_vim/index.html b/docs/posts/get_better_at_yanking_and_putting_in_vim/index.html
index 469afe5..c6d3368 100644
--- a/docs/posts/get_better_at_yanking_and_putting_in_vim/index.html
+++ b/docs/posts/get_better_at_yanking_and_putting_in_vim/index.html
@@ -28,7 +28,7 @@
28 30/07 — 2019 28 30/07 — 2019
29 <div class="stats"> 29 <div class="stats">
30 <span class="stats-number"> 30 <span class="stats-number">
31 10.78 31 10.79
32 </span> 32 </span>
33 <span class="stats-unit">cm</span> 33 <span class="stats-unit">cm</span>
34 &nbsp 34 &nbsp
@@ -44,7 +44,8 @@
44 <div class="post-text"> 44 <div class="post-text">
45 <p>a couple of nifty tricks to help you copy-paste better:</p> 45 <p>a couple of nifty tricks to help you copy-paste better:</p>
46<ol type="1"> 46<ol type="1">
47<li><p>reselecting previously selected text (i use this to fix botched selections):</p> 47<li><p>reselecting previously selected text (i use this to fix botched
48selections):</p>
48<pre><code>gv &quot; :h gv for more 49<pre><code>gv &quot; :h gv for more
49 &quot; you can use `o` in visual mode to go to the `Other` end of the selection 50 &quot; you can use `o` in visual mode to go to the `Other` end of the selection
50 &quot; use a motion to fix the selection</code></pre></li> 51 &quot; use a motion to fix the selection</code></pre></li>
diff --git a/docs/posts/gripes_with_go/index.html b/docs/posts/gripes_with_go/index.html
index 1551fe6..74d6995 100644
--- a/docs/posts/gripes_with_go/index.html
+++ b/docs/posts/gripes_with_go/index.html
@@ -28,7 +28,7 @@
28 01/08 — 2020 28 01/08 — 2020
29 <div class="stats"> 29 <div class="stats">
30 <span class="stats-number"> 30 <span class="stats-number">
31 76.71 31 76.72
32 </span> 32 </span>
33 <span class="stats-unit">cm</span> 33 <span class="stats-unit">cm</span>
34 &nbsp 34 &nbsp
@@ -42,17 +42,24 @@
42 Gripes With Go 42 Gripes With Go
43 </h1> 43 </h1>
44 <div class="post-text"> 44 <div class="post-text">
45 <p>You’ve read a lot of posts about the shortcomings of the Go programming language, so what’s one more.</p> 45 <p>You’ve read a lot of posts about the shortcomings of the Go
46programming language, so what’s one more.</p>
46<ol type="1"> 47<ol type="1">
47<li><a href="#lack-of-sum-types">Lack of sum types</a></li> 48<li><a href="#lack-of-sum-types">Lack of sum types</a></li>
48<li><a href="#type-assertions">Type assertions</a></li> 49<li><a href="#type-assertions">Type assertions</a></li>
49<li><a href="#date-and-time">Date and Time</a></li> 50<li><a href="#date-and-time">Date and Time</a></li>
50<li><a href="#statements-over-expressions">Statements over Expressions</a></li> 51<li><a href="#statements-over-expressions">Statements over
51<li><a href="#erroring-out-on-unused-variables">Erroring out on unused variables</a></li> 52Expressions</a></li>
53<li><a href="#erroring-out-on-unused-variables">Erroring out on unused
54variables</a></li>
52<li><a href="#error-handling">Error handling</a></li> 55<li><a href="#error-handling">Error handling</a></li>
53</ol> 56</ol>
54<h3 id="lack-of-sum-types">Lack of Sum types</h3> 57<h3 id="lack-of-sum-types">Lack of Sum types</h3>
55<p>A “Sum” type is a data type that can hold one of many states at a given time, similar to how a boolean can hold a true or a false, not too different from an <code>enum</code> type in C. Go lacks <code>enum</code> types unfortunately, and you are forced to resort to crafting your own substitute.</p> 58<p>A “Sum” type is a data type that can hold one of many states at a
59given time, similar to how a boolean can hold a true or a false, not too
60different from an <code>enum</code> type in C. Go lacks
61<code>enum</code> types unfortunately, and you are forced to resort to
62crafting your own substitute.</p>
56<p>A type to represent gender for example:</p> 63<p>A type to represent gender for example:</p>
57<div class="sourceCode" id="cb1"><pre class="sourceCode go"><code class="sourceCode go"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> Gender <span class="dt">int</span></span> 64<div class="sourceCode" id="cb1"><pre class="sourceCode go"><code class="sourceCode go"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="kw">type</span> Gender <span class="dt">int</span></span>
58<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span> 65<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a></span>
@@ -67,17 +74,18 @@
67<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a><span class="co">// Oops! We have to implement String() for Gender ...</span></span> 74<span id="cb1-11"><a href="#cb1-11" aria-hidden="true" tabindex="-1"></a><span class="co">// Oops! We have to implement String() for Gender ...</span></span>
68<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a></span> 75<span id="cb1-12"><a href="#cb1-12" aria-hidden="true" tabindex="-1"></a></span>
69<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> <span class="op">(</span>g Gender<span class="op">)</span> String<span class="op">()</span> <span class="dt">string</span> <span class="op">{</span></span> 76<span id="cb1-13"><a href="#cb1-13" aria-hidden="true" tabindex="-1"></a><span class="kw">func</span> <span class="op">(</span>g Gender<span class="op">)</span> String<span class="op">()</span> <span class="dt">string</span> <span class="op">{</span></span>
70<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a> <span class="kw">switch</span> <span class="op">(</span>g<span class="op">)</span> <span class="op">{</span></span> 77<span id="cb1-14"><a href="#cb1-14" aria-hidden="true" tabindex="-1"></a> <span class="cf">switch</span> <span class="op">(</span>g<span class="op">)</span> <span class="op">{</span></span>
71<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a> <span class="kw">case</span> <span class="dv">0</span><span class="op">:</span> <span class="kw">return</span> <span class="st">&quot;Male&quot;</span></span> 78<span id="cb1-15"><a href="#cb1-15" aria-hidden="true" tabindex="-1"></a> <span class="cf">case</span> <span class="dv">0</span><span class="op">:</span> <span class="cf">return</span> <span class="st">&quot;Male&quot;</span></span>
72<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a> <span class="kw">case</span> <span class="dv">1</span><span class="op">:</span> <span class="kw">return</span> <span class="st">&quot;Female&quot;</span></span> 79<span id="cb1-16"><a href="#cb1-16" aria-hidden="true" tabindex="-1"></a> <span class="cf">case</span> <span class="dv">1</span><span class="op">:</span> <span class="cf">return</span> <span class="st">&quot;Female&quot;</span></span>
73<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a> <span class="kw">default</span><span class="op">:</span> <span class="kw">return</span> <span class="st">&quot;Other&quot;</span></span> 80<span id="cb1-17"><a href="#cb1-17" aria-hidden="true" tabindex="-1"></a> <span class="cf">default</span><span class="op">:</span> <span class="cf">return</span> <span class="st">&quot;Other&quot;</span></span>
74<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span> 81<span id="cb1-18"><a href="#cb1-18" aria-hidden="true" tabindex="-1"></a> <span class="op">}</span></span>
75<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span> 82<span id="cb1-19"><a href="#cb1-19" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span>
76<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a></span> 83<span id="cb1-20"><a href="#cb1-20" aria-hidden="true" tabindex="-1"></a></span>
77<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a><span class="co">// You can accidentally do stupid stuff like:</span></span> 84<span id="cb1-21"><a href="#cb1-21" aria-hidden="true" tabindex="-1"></a><span class="co">// You can accidentally do stupid stuff like:</span></span>
78<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>gender <span class="op">:=</span> Male <span class="op">+</span> <span class="dv">1</span></span></code></pre></div> 85<span id="cb1-22"><a href="#cb1-22" aria-hidden="true" tabindex="-1"></a>gender <span class="op">:=</span> Male <span class="op">+</span> <span class="dv">1</span></span></code></pre></div>
79<p>The Haskell equivalent of the same:</p> 86<p>The Haskell equivalent of the same:</p>
80<div class="sourceCode" id="cb2"><pre class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Gender</span> <span class="ot">=</span> <span class="dt">Male</span></span> 87<div class="sourceCode" id="cb2"><pre
88class="sourceCode haskell"><code class="sourceCode haskell"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="kw">data</span> <span class="dt">Gender</span> <span class="ot">=</span> <span class="dt">Male</span></span>
81<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> <span class="dt">Female</span></span> 89<span id="cb2-2"><a href="#cb2-2" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> <span class="dt">Female</span></span>
82<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> <span class="dt">Other</span></span> 90<span id="cb2-3"><a href="#cb2-3" aria-hidden="true" tabindex="-1"></a> <span class="op">|</span> <span class="dt">Other</span></span>
83<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a> <span class="kw">deriving</span> (<span class="dt">Show</span>)</span> 91<span id="cb2-4"><a href="#cb2-4" aria-hidden="true" tabindex="-1"></a> <span class="kw">deriving</span> (<span class="dt">Show</span>)</span>
@@ -88,7 +96,7 @@
88<p>Type assertions in Go allow you to do:</p> 96<p>Type assertions in Go allow you to do:</p>
89<div class="sourceCode" id="cb3"><pre class="sourceCode go"><code class="sourceCode go"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">var</span> x <span class="kw">interface</span><span class="op">{}</span> <span class="op">=</span> <span class="dv">7</span></span> 97<div class="sourceCode" id="cb3"><pre class="sourceCode go"><code class="sourceCode go"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="kw">var</span> x <span class="kw">interface</span><span class="op">{}</span> <span class="op">=</span> <span class="dv">7</span></span>
90<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>y<span class="op">,</span> goodToGo <span class="op">:=</span> x<span class="op">.(</span><span class="dt">int</span><span class="op">)</span></span> 98<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>y<span class="op">,</span> goodToGo <span class="op">:=</span> x<span class="op">.(</span><span class="dt">int</span><span class="op">)</span></span>
91<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="kw">if</span> goodToGo <span class="op">{</span></span>