<?xml version="1.0" encoding="UTF-8" ?>
<rss version="2.0">
    <channel>
      <title>~dennisleexyz</title>
      <link>https://dennislee.xyz</link>
      <description>Recent notes on ~dennisleexyz</description>
      <generator>Quartz -- quartz.jzhao.xyz</generator>
      <item>
    <title>3D Model Sites</title>
    <link>https://dennislee.xyz/3d-model-sites</link>
    <guid>https://dennislee.xyz/3d-model-sites</guid>
    <description><![CDATA[ &lt;p&gt;This is a feature comparison matrix of popular 3D model hosting websites focused on 3D printing. Based on the video by &lt;a href=&quot;https://www.youtube.com/@TeachingTech&quot; class=&quot;external&quot;&gt;Teaching Tech - YouTube&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;, with additions of my own.&lt;/p&gt;
&lt;blockquote class=&quot;callout quote&quot; data-callout=&quot;quote&quot;&gt;
&lt;div class=&quot;callout-title&quot;&gt;
                  &lt;div class=&quot;callout-icon&quot;&gt;&lt;/div&gt;
                  &lt;div class=&quot;callout-title-inner&quot;&gt;&lt;p&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=4ZeHY44B8PU&quot; class=&quot;external&quot;&gt;Comparing 3D printing model websites objectively to find a winner&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/p&gt;&lt;/div&gt;
                  
                &lt;/div&gt;
&lt;/blockquote&gt;







































































































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;Thingiverse&lt;/th&gt;&lt;th&gt;Printables&lt;/th&gt;&lt;th&gt;MyMiniFactory&lt;/th&gt;&lt;th&gt;Cults3D&lt;/th&gt;&lt;th&gt;Thangs&lt;/th&gt;&lt;th&gt;Creality Cloud&lt;/th&gt;&lt;th&gt;MakerWorld&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Free models&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Paid models&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;⚠️&lt;/td&gt;&lt;td&gt;⚠️&lt;/td&gt;&lt;td&gt;⚠️&lt;/td&gt;&lt;td&gt;⚠️&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=4ZeHY44B8PU&amp;#x26;t=328s&quot; class=&quot;external&quot;&gt;Ads&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=4ZeHY44B8PU&amp;#x26;t=399s&quot; class=&quot;external&quot;&gt;Meta/Smart search&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;⚠️&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;⚠️&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;⚠️&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=4ZeHY44B8PU&amp;#x26;t=476s&quot; class=&quot;external&quot;&gt;Contests&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;⚠️&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=4ZeHY44B8PU&amp;#x26;t=518s&quot; class=&quot;external&quot;&gt;Companion app&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;⚠️&lt;/td&gt;&lt;td&gt;⚠️&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;⚠️&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=4ZeHY44B8PU&amp;#x26;t=607s&quot; class=&quot;external&quot;&gt;Cloud printing&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;⚠️&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=4ZeHY44B8PU&amp;#x26;t=692s&quot; class=&quot;external&quot;&gt;Rewards&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;⚠️&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=4ZeHY44B8PU&amp;#x26;t=750s&quot; class=&quot;external&quot;&gt;Communities&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=4ZeHY44B8PU&amp;#x26;t=810s&quot; class=&quot;external&quot;&gt;Blog/guides/articles&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Download w/o login&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;td&gt;❌&lt;/td&gt;&lt;td&gt;⚠️&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;SCAD Customizer&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;MakerWorld requires login to download all files. When not logged in, you can only download files individually after completing a challenge.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;rewards&quot;&gt;Rewards&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#rewards&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;h3 id=&quot;printables&quot;&gt;Printables&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#printables&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://help.prusa3d.com/article/how-do-prusameters-on-printables-work_365065&quot; class=&quot;external&quot;&gt;https://help.prusa3d.com/article/how-do-prusameters-on-printables-work_365065&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.printables.com/prusameter&quot; class=&quot;external&quot;&gt;https://www.printables.com/prusameter&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.printables.com/prusameter/rewards&quot; class=&quot;external&quot;&gt;https://www.printables.com/prusameter/rewards&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h4 id=&quot;earn&quot;&gt;Earn&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#earn&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;


















































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;title&lt;/th&gt;&lt;th&gt;description&lt;/th&gt;&lt;th&gt;points&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Completed profile&lt;/td&gt;&lt;td&gt;avatar, bio, location, languages&lt;/td&gt;&lt;td&gt;20&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Publish a model&lt;/td&gt;&lt;td&gt;up to 10 new models in total&lt;/td&gt;&lt;td&gt;10&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Create a collection&lt;/td&gt;&lt;td&gt;up to 3 non-empty collections&lt;/td&gt;&lt;td&gt;5&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Upload a make&lt;/td&gt;&lt;td&gt;up to 100 Prusameters per calendar month&lt;/td&gt;&lt;td&gt;1-10&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;Model reaches 30 downloads and 3 likes&lt;/td&gt;&lt;td&gt;10&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;Model reaches 100 downloads and 10 likes&lt;/td&gt;&lt;td&gt;+50&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;Model reaches 200 downloads and 15 likes&lt;/td&gt;&lt;td&gt;+100&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;Model reaches 400 downloads and 20 likes&lt;/td&gt;&lt;td&gt;+200&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h4 id=&quot;redeem&quot;&gt;Redeem&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#redeem&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;











































































































































































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;title&lt;/th&gt;&lt;th&gt;description&lt;/th&gt;&lt;th&gt;points&lt;/th&gt;&lt;th&gt;USD&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Prusament PLA&lt;/td&gt;&lt;td&gt;The voucher can be applied to any regular PLA Prusament 1 kg except rPLA and Refill. Only one voucher can be used per order. It is not possible to combine several vouchers into one.&lt;/td&gt;&lt;td&gt;350&lt;/td&gt;&lt;td&gt;$29.99&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Prusament PETG&lt;/td&gt;&lt;td&gt;The voucher can be applied to any regular PETG Prusament 1 kg except PETG Carbon Fiber, Tungsten, V0, Matte Black, and Refill. Only one voucher can be used per order. It is not possible to combine several vouchers into one.&lt;/td&gt;&lt;td&gt;350&lt;/td&gt;&lt;td&gt;$29.99&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Prusament ASA&lt;/td&gt;&lt;td&gt;The voucher can be applied to any regular ASA Prusament 850 g. Only one voucher can be used per order. It is not possible to combine several vouchers into one.&lt;/td&gt;&lt;td&gt;350&lt;/td&gt;&lt;td&gt;$29.99&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Prusa CORE One&lt;/td&gt;&lt;td&gt;3D printer: Original Prusa CORE One Kit! Only one voucher can be used per order. It is not possible to combine several vouchers into one.&lt;/td&gt;&lt;td&gt;29000&lt;/td&gt;&lt;td&gt;$949.00&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Original Prusa MK4S&lt;/td&gt;&lt;td&gt;3D printer kit: Original Prusa MK4S! Only one voucher can be used per order. It is not possible to combine several vouchers into one.&lt;/td&gt;&lt;td&gt;25000&lt;/td&gt;&lt;td&gt;$729.00&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Original Prusa MINI+&lt;/td&gt;&lt;td&gt;3D printer Original Prusa MINI+ kit - smart and compact 3D printing workhorse. Only one voucher can be used per order. It is not possible to combine several vouchers into one.&lt;/td&gt;&lt;td&gt;10000&lt;/td&gt;&lt;td&gt;$429.00&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Prusa Art - Set of 3 Posters&lt;/td&gt;&lt;td&gt;You can choose Technical Art or Infill Art.&lt;/td&gt;&lt;td&gt;300&lt;/td&gt;&lt;td&gt;$20.99&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Original Prusa Heatbed Mousepad&lt;/td&gt;&lt;td&gt;Only one voucher can be used per order. It is not possible to combine several vouchers into one.&lt;/td&gt;&lt;td&gt;240&lt;/td&gt;&lt;td&gt;$14.99&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Prusament Refill&lt;/td&gt;&lt;td&gt;The voucher can be applied to PLA or PETG Prusament Refill. Only one voucher can be used per order. It is not possible to combine several vouchers into one.&lt;/td&gt;&lt;td&gt;340&lt;/td&gt;&lt;td&gt;$26.99&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Official Printables T-shirt&lt;/td&gt;&lt;td&gt;You can choose any size. Only one voucher can be used per order. It is not possible to combine several vouchers into one.&lt;/td&gt;&lt;td&gt;200&lt;/td&gt;&lt;td&gt;$24.99&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Prusament Dragon T-shirt&lt;/td&gt;&lt;td&gt;You can choose any size. Only one voucher can be used per order. It is not possible to combine several vouchers into one.&lt;/td&gt;&lt;td&gt;300&lt;/td&gt;&lt;td&gt;$24.99&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Original Prusa T-shirt MK4 Blueprint&lt;/td&gt;&lt;td&gt;You can choose any size. Only one voucher can be used per order. It is not possible to combine several vouchers into one.&lt;/td&gt;&lt;td&gt;300&lt;/td&gt;&lt;td&gt;$24.99&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Original Prusa T-shirt PrusaSlicer&lt;/td&gt;&lt;td&gt;You can choose any size. Only one voucher can be used per order. It is not possible to combine several vouchers into one.&lt;/td&gt;&lt;td&gt;300&lt;/td&gt;&lt;td&gt;$24.99&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Original Prusa T-shirt Classic or Jo’s Edition&lt;/td&gt;&lt;td&gt;You can choose any size. Only one voucher can be used per order. It is not possible to combine several vouchers into one.&lt;/td&gt;&lt;td&gt;240&lt;/td&gt;&lt;td&gt;$19.99&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Original Prusa Hoodie&lt;/td&gt;&lt;td&gt;You can choose any size. Only one voucher can be used per order. It is not possible to combine several vouchers into one.&lt;/td&gt;&lt;td&gt;600&lt;/td&gt;&lt;td&gt;$43.99&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Original Prusa Snapback&lt;/td&gt;&lt;td&gt;You can choose any Prusa Snapback. Only one voucher can be used per order. It is not possible to combine several vouchers into one.&lt;/td&gt;&lt;td&gt;375&lt;/td&gt;&lt;td&gt;$29.99&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Original Prusa Beanie&lt;/td&gt;&lt;td&gt;Only one voucher can be used per order. It is not possible to combine several vouchers into one.&lt;/td&gt;&lt;td&gt;280&lt;/td&gt;&lt;td&gt;$18.99&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Original PrusaSlicer Mug&lt;/td&gt;&lt;td&gt;Only one voucher can be used per order. It is not possible to combine several vouchers into one.&lt;/td&gt;&lt;td&gt;250&lt;/td&gt;&lt;td&gt;$19.99&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;$40 voucher for Prusa 3D printer&lt;/td&gt;&lt;td&gt;A $40 voucher that can be redeemed when purchasing a Prusa 3D printer CORE One, MK4S, XL, MINI+, SL1S (including kit versions). Does not apply to upgrades and conversion kit. Only one voucher can be used per transaction, and it’s not possible to combine multiple vouchers into one.&lt;/td&gt;&lt;td&gt;350&lt;/td&gt;&lt;td&gt;$40.00&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;$100 voucher for Prusa 3D printer&lt;/td&gt;&lt;td&gt;A $100 voucher that can be redeemed when purchasing a Prusa 3D printer CORE One, MK4S, XL, MINI+, SL1S (including kit versions). Does not apply to upgrades and conversion kit. Only one voucher can be used per transaction, and it’s not possible to combine multiple vouchers into one.&lt;/td&gt;&lt;td&gt;1000&lt;/td&gt;&lt;td&gt;$100.00&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;$200 voucher for Prusa 3D printer&lt;/td&gt;&lt;td&gt;A $200 voucher that can be redeemed when purchasing a Prusa 3D printer CORE One, MK4S, XL, MINI+, SL1S (including kit versions). Does not apply to upgrades and conversion kit. Only one voucher can be used per transaction, and it’s not possible to combine multiple vouchers into one.&lt;/td&gt;&lt;td&gt;3000&lt;/td&gt;&lt;td&gt;$200.00&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;$400 voucher for Prusa 3D printer&lt;/td&gt;&lt;td&gt;A $400 voucher that can be redeemed when purchasing a Prusa 3D printer CORE One, MK4S, XL, MINI+, SL1S (including kit versions). Does not apply to upgrades and conversion kit. Only one voucher can be used per transaction, and it’s not possible to combine multiple vouchers into one.&lt;/td&gt;&lt;td&gt;7000&lt;/td&gt;&lt;td&gt;$400.00&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;2× Prusament spool&lt;/td&gt;&lt;td&gt;Voucher for 2 pcs Prusament PLA, PETG, ASA on 1kg or 850g spool of any regular color except rPLA, PETG Carbon Fiber, Tungsten, V0, Matte Black, and Refill. Only one voucher can be used per order. It is not possible to combine several vouchers into one.&lt;/td&gt;&lt;td&gt;700&lt;/td&gt;&lt;td&gt;$59.98&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3× Prusament spool&lt;/td&gt;&lt;td&gt;Voucher for 3 pcs Prusament PLA, PETG, ASA on 1kg or 850g spool of any regular color except rPLA, PETG Carbon Fiber, Tungsten, V0, Matte Black, and Refill. Only one voucher can be used per order. It is not possible to combine several vouchers into one.&lt;/td&gt;&lt;td&gt;1050&lt;/td&gt;&lt;td&gt;$89.97&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3D Printing and Modeling for Beginners (MK4)&lt;/td&gt;&lt;td&gt;Online course&lt;/td&gt;&lt;td&gt;90&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3D Printing and Modeling for Beginners (MINI+)&lt;/td&gt;&lt;td&gt;Online course&lt;/td&gt;&lt;td&gt;90&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Basics of Product Photography&lt;/td&gt;&lt;td&gt;Online course&lt;/td&gt;&lt;td&gt;350&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Design Principles for 3D Printed Parts&lt;/td&gt;&lt;td&gt;Online course&lt;/td&gt;&lt;td&gt;180&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3D Modeling in Fusion 360&lt;/td&gt;&lt;td&gt;Online course&lt;/td&gt;&lt;td&gt;350&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;3D Printing and Modeling for Beginners (MK3S+)&lt;/td&gt;&lt;td&gt;Online course&lt;/td&gt;&lt;td&gt;90&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Donating Prusament to Education&lt;/td&gt;&lt;td&gt;Join us in supporting education and donate your Prusameters to benefit students. Your Prusameters will be converted into donated Prusament spools. Thank you for your donation!&lt;/td&gt;&lt;td&gt;200&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Basics of 3D Printing with Josef Prusa&lt;/td&gt;&lt;td&gt;You can choose language variation. Only one voucher can be used per order. It is not possible to combine several vouchers into one.&lt;/td&gt;&lt;td&gt;65&lt;/td&gt;&lt;td&gt;$4.99&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h3 id=&quot;makerworld&quot;&gt;MakerWorld&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#makerworld&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://makerworld.com/en/points&quot; class=&quot;external&quot;&gt;https://makerworld.com/en/points&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h4 id=&quot;earn-1&quot;&gt;Earn&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#earn-1&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;





































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;title&lt;/th&gt;&lt;th&gt;description&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Upload a Model&lt;/td&gt;&lt;td&gt;Each new upload can earn 10 points, and up to 50 points in total.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Upload a Print Profile&lt;/td&gt;&lt;td&gt;Each new upload can earn 3 points, and up to 15 points in total.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-Quality Model Reward&lt;/td&gt;&lt;td&gt;1 Successful Print = 2 Downloads&lt;br&gt;&lt;br&gt;3 downloads are counted when a user downloads and successfully prints a model.&lt;br&gt;&lt;br&gt;The high-quality model reward has no time constraints; points are earned upon reaching specific download milestones.&lt;br&gt;The points reward is progressive for each model at 4 milestones.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;1~50&lt;/td&gt;&lt;td&gt;15 points per 10 downloads&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;51~500&lt;/td&gt;&lt;td&gt;12 points per 25 downloads&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;501~1000&lt;/td&gt;&lt;td&gt;20 points per 50 downloads&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&gt;1000&lt;/td&gt;&lt;td&gt;30 points per 100 downloads&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;High-Quality Print Profile Reward&lt;/td&gt;&lt;td&gt;1 Successful Print = 2 Downloads&lt;br&gt;&lt;br&gt;3 downloads are counted when a user downloads and successfully prints a print profile.&lt;br&gt;&lt;br&gt;The high-quality print profile reward has no time constraints; points are earned upon reaching specific download milestones.&lt;br&gt;In order to receive points, each print profile needs to keep the average rating ≥4 stars, then you will earn points at each milestone.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;1~50&lt;/td&gt;&lt;td&gt;3 points per 10 downloads&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;51~500&lt;/td&gt;&lt;td&gt;3 points per 25 downloads&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;501~1000&lt;/td&gt;&lt;td&gt;5 points per 50 downloads&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&gt;1000&lt;/td&gt;&lt;td&gt;8 points per 100 downloads&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Create models using MakerLab&lt;/td&gt;&lt;td&gt;You can earn up to 10 points.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Rate Print Profiles&lt;/td&gt;&lt;td&gt;If your rating is one of the first five ratings for a print profile, you can earn up to 10 points.&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Complete personal profile&lt;/td&gt;&lt;td&gt;Completed your personal information and upload an avatar to earn 20 points.&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h4 id=&quot;redeem-1&quot;&gt;Redeem&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#redeem-1&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h4&gt;





































































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;title&lt;/th&gt;&lt;th&gt;description&lt;/th&gt;&lt;th&gt;points&lt;/th&gt;&lt;th&gt;USD&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Gift Card for $40&lt;/td&gt;&lt;td&gt;This gift card is only valid for use in the US and cannot be changed after it has been redeemed.&lt;/td&gt;&lt;td&gt;490&lt;/td&gt;&lt;td&gt;$40&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Maker’s Essential Kit A&lt;/td&gt;&lt;td&gt;This discount code will provide a 99% discount on the purchase of this item in AU and cannot be changed after it has been redeemed.&lt;/td&gt;&lt;td&gt;1200&lt;/td&gt;&lt;td&gt;$165&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://us.store.bambulab.com/products/led-lamp-kit-001?id=41806987395208&quot; class=&quot;external&quot;&gt;LED Lamp Kit 001&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;This discount code will provide a 99% discount on the purchase of this item in the US and cannot be changed after it has been redeemed.&lt;/td&gt;&lt;td&gt;132&lt;/td&gt;&lt;td&gt;$12.87&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://us.store.bambulab.com/products/wireless-mouse-components-kit-002?id=41806859403400&quot; class=&quot;external&quot;&gt;Wireless Mouse Components Kit 002&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;This discount code will provide a 99% discount on the purchase of this item in the US and cannot be changed after it has been redeemed.&lt;/td&gt;&lt;td&gt;132&lt;/td&gt;&lt;td&gt;$12.87&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://us.store.bambulab.com/products/marble-run-components-kit-003&quot; class=&quot;external&quot;&gt;Marble Run Components Kit 003&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;This discount code will provide a 99% discount on the purchase of this item in the US and cannot be changed after it has been redeemed.&lt;/td&gt;&lt;td&gt;110&lt;/td&gt;&lt;td&gt;$10.89&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://us.store.bambulab.com/products/engine-model-components-kit-005&quot; class=&quot;external&quot;&gt;Engine Model Components Kit 005&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;This discount code will provide a 99% discount on the purchase of this item in the US and cannot be changed after it has been redeemed.&lt;/td&gt;&lt;td&gt;110&lt;/td&gt;&lt;td&gt;$10.89&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://us.store.bambulab.com/products/jet-engine-model-components-kit-006?id=41806959804552&quot; class=&quot;external&quot;&gt;Jet Engine Model Components Kit 006&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;This discount code will provide a 99% discount on the purchase of this item in the US and cannot be changed after it has been redeemed.&lt;/td&gt;&lt;td&gt;275&lt;/td&gt;&lt;td&gt;$26.73&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://us.store.bambulab.com/products/triple-axis-tourbillon-model-components-kit-007&quot; class=&quot;external&quot;&gt;Triple-axis Tourbillon Model Components Kit 007&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;This discount code will provide a 99% discount on the purchase of this item in the US and cannot be changed after it has been redeemed.&lt;/td&gt;&lt;td&gt;440&lt;/td&gt;&lt;td&gt;$43.56&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://us.store.bambulab.com/products/boat-model-components-kit-010?id=41823193727112&quot; class=&quot;external&quot;&gt;Boat Model Components Kit 010&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;This discount code will provide a 99% discount on the purchase of this item in the US and cannot be changed after it has been redeemed.&lt;/td&gt;&lt;td&gt;55&lt;/td&gt;&lt;td&gt;$5.4351&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://us.store.bambulab.com/products/clock-components-kit-011&quot; class=&quot;external&quot;&gt;Clock Components Kit 011&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;This discount code will provide a 99% discount on the purchase of this item in the US and cannot be changed after it has been redeemed.&lt;/td&gt;&lt;td&gt;88&lt;/td&gt;&lt;td&gt;$8.91&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://us.store.bambulab.com/products/makers-beginner-kit&quot; class=&quot;external&quot;&gt;Maker’s Beginner Kit&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;This discount code will provide a 99% discount on the purchase of this item in the US and cannot be changed after it has been redeemed (Please note that the product does not include the 3D printed parts as shown in the main image).&lt;/td&gt;&lt;td&gt;110&lt;/td&gt;&lt;td&gt;$10.8801&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Lichtenstein Castle&lt;/td&gt;&lt;td&gt;MakerWorld exclusive model is available for you to redeem.&lt;/td&gt;&lt;td&gt;50&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Panzerkampfwagen IV Tank&lt;/td&gt;&lt;td&gt;MakerWorld exclusive model (a digital 3D model file rather than physical prints)&lt;/td&gt;&lt;td&gt;100&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;MakerLab Credits x 10&lt;/td&gt;&lt;td&gt;for MakerLab AI apps&lt;/td&gt;&lt;td&gt;1&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;MakerLab Credits x 100&lt;/td&gt;&lt;td&gt;for MakerLab AI apps&lt;/td&gt;&lt;td&gt;10&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;h5 id=&quot;redeem-cash&quot;&gt;&lt;a href=&quot;https://makerworld.com/en/points?type=redeemCash&quot; class=&quot;external&quot;&gt;Redeem Cash&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#redeem-cash&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h5&gt;
&lt;p&gt;Exclusive points, earned through exclusive models, can be redeemed for cash or valuable items in our points shop.&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;Cash redemption is limited to exclusive points, with an exchange rate of 1 exclusive point for 0.066 USD.&lt;/li&gt;
&lt;li&gt;The minimum redemption amount is 100 USD, while the maximum is 1000 USD.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id=&quot;creality-cloud&quot;&gt;Creality Cloud&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#creality-cloud&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;&lt;a href=&quot;https://www.crealitycloud.com/mission-center/eshop&quot; class=&quot;external&quot;&gt;https://www.crealitycloud.com/mission-center/eshop&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;imports&quot;&gt;Imports&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#imports&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;These are the supported import paths to copy models from one site to another. The services are provided by the destination website.&lt;/p&gt;
&lt;pre&gt;&lt;button class=&quot;expand-button&quot; aria-label=&quot;Expand mermaid diagram&quot; data-view-component&gt;&lt;svg width=&quot;16&quot; height=&quot;16&quot; viewBox=&quot;0 0 16 16&quot; fill=&quot;currentColor&quot;&gt;&lt;path fill-rule=&quot;evenodd&quot; d=&quot;M3.72 3.72a.75.75 0 011.06 1.06L2.56 7h10.88l-2.22-2.22a.75.75 0 011.06-1.06l3.5 3.5a.75.75 0 010 1.06l-3.5 3.5a.75.75 0 11-1.06-1.06l2.22-2.22H2.56l2.22 2.22a.75.75 0 11-1.06 1.06l-3.5-3.5a.75.75 0 010-1.06l3.5-3.5z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/button&gt;&lt;code class=&quot;mermaid&quot; data-clipboard=&quot;&amp;#x22;graph TD;\nThingiverse--&gt;Cults3D;\nThingiverse--&gt;Printables;\nThingiverse--&gt;MakerWorld;\nPrintables--&gt;MakerWorld;\ncrealitycloud.cn--&gt;crealitycloud.com;&amp;#x22;&quot;&gt;graph TD;
Thingiverse--&gt;Cults3D;
Thingiverse--&gt;Printables;
Thingiverse--&gt;MakerWorld;
Printables--&gt;MakerWorld;
crealitycloud.cn--&gt;crealitycloud.com;
&lt;/code&gt;&lt;div id=&quot;mermaid-container&quot; role=&quot;dialog&quot;&gt;&lt;div id=&quot;mermaid-space&quot;&gt;&lt;div class=&quot;mermaid-content&quot;&gt;&lt;/div&gt;&lt;/div&gt;&lt;/div&gt;&lt;/pre&gt; ]]></description>
    <pubDate>Thu, 24 Apr 2025 18:16:32 GMT</pubDate>
  </item><item>
    <title>FOSS CNC Cutting</title>
    <link>https://dennislee.xyz/cnc</link>
    <guid>https://dennislee.xyz/cnc</guid>
    <description><![CDATA[ &lt;h2 id=&quot;software&quot;&gt;Software&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#software&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Laser/vinyl cutter software that is FOSS or at least doesn’t require Windows/macOS.&lt;/p&gt;













































































































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;Print and Cut&lt;/th&gt;&lt;th&gt;CLI&lt;/th&gt;&lt;th&gt;Devices&lt;/th&gt;&lt;th&gt;Platforms&lt;/th&gt;&lt;th&gt;License&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://silhouette-web.com/&quot; class=&quot;external&quot;&gt;Silhouette Web&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;✓&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;web&lt;/td&gt;&lt;td&gt;unfree&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/fablabnbg/inkscape-silhouette&quot; class=&quot;external&quot;&gt;inkscape-silhouette&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/fablabnbg/inkscape-silhouette/blob/main/USERGUIDE.md#adding-print-and-cut-layers&quot; class=&quot;external&quot;&gt;✓&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;a href=&quot;https://github.com/fablabnbg/inkscape-silhouette/issues/82&quot; class=&quot;external&quot;&gt;*&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/fablabnbg/inkscape-silhouette#cli&quot; class=&quot;external&quot;&gt;✓&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;details&gt;Silhouette Portrait&lt;br&gt;Silhouette Portrait 2 (working confirmed)&lt;br&gt;Silhouette Portrait 3&lt;br&gt;Silhouette Portrait 4 (working confirmed)&lt;br&gt;Silhouette Cameo&lt;br&gt;Silhouette Cameo 2&lt;br&gt;Silhouette Cameo 3&lt;br&gt;Silhouette Cameo 4&lt;br&gt;Silhouette Cameo 4 Plus&lt;br&gt;Silhouette Cameo 4 Pro&lt;br&gt;Silhouette Cameo 5&lt;br&gt;Silhouette Cameo 5 Plus&lt;br&gt;Silhouette Curio (partial success confirmed in #36)&lt;br&gt;Craft Robo CC200-20&lt;br&gt;Craft Robo CC300-20&lt;br&gt;Silhouette SD 1&lt;br&gt;Silhouette SD 2&lt;br&gt;&lt;/details&gt;&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://inkscape.org/release/dev/platforms/&quot; class=&quot;external&quot;&gt;Inkscape&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; + Python&lt;/td&gt;&lt;td&gt;GPL-2.0&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/Timmmm/robocut&quot; class=&quot;external&quot;&gt;robocut&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;✓&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;details&gt;Graphtec CraftRobo CC200-20&lt;br&gt;Graphtec CraftRobo CC300-20&lt;br&gt;Silhouette SD&lt;br&gt;Silhouette SD 2&lt;br&gt;Silhouette Cameo&lt;br&gt;Silhouette Cameo 3&lt;br&gt;Silhouette Portrait&lt;br&gt;&lt;/details&gt;&lt;/td&gt;&lt;td&gt;Windows&lt;br&gt;OSX&lt;br&gt;Linux&lt;/td&gt;&lt;td&gt;GPL-3.0&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://grid.space/kiri/&quot; class=&quot;external&quot;&gt;Kiri:Moto&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;NodeJS&lt;br&gt;Electron&lt;/td&gt;&lt;td&gt;MIT&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/camrein/EzGraver&quot; class=&quot;external&quot;&gt;EzGraver&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/camrein/EzGraver#command-line-interface&quot; class=&quot;external&quot;&gt;✓&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;NEJE laser engravers&lt;/td&gt;&lt;td&gt;Linux / OSX&lt;br&gt;Windows&lt;/td&gt;&lt;td&gt;MIT&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/aquamorta/kkengraver&quot; class=&quot;external&quot;&gt;kkengraver&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/aquamorta/kkengraver#preliminaries&quot; class=&quot;external&quot;&gt;✓&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;KKMoon 3000 laser engraver (3000mW)&lt;/td&gt;&lt;td&gt;python / web&lt;/td&gt;&lt;td&gt;GPL-3.0&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://laserweb.yurl.ch/&quot; class=&quot;external&quot;&gt;LaserWeb/CNCWeb&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://laserweb.yurl.ch/22-documentation/54-supported-firmwares&quot; class=&quot;external&quot;&gt;Supported firmwares - LaserWeb / CNCWeb&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Windows, OSX and Linux (on x86/x64 CPU)&lt;/td&gt;&lt;td&gt;AGPL-3.0&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://visicut.org/&quot; class=&quot;external&quot;&gt;Visicut&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;many lasercutters, such as the Epilog Zing/Mini/Helix, LAOS, Smoothieboard, LTT, K40 and &lt;a href=&quot;https://github.com/t-oster/VisiCut/wiki/Supported-Hardware&quot; class=&quot;external&quot;&gt;some more&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;.&lt;/td&gt;&lt;td&gt;Linux, Mac and Windows&lt;/td&gt;&lt;td&gt;LGPL-3.0&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://lightburnsoftware.com/&quot; class=&quot;external&quot;&gt;LightBurn&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;most Ruida, Trocen, TopWisdom, and GCode based controllers, as well as EZCad-based galvo fiber, CO2, and UV lasers using either EZCad2 or EZCad2-Lite boards.&lt;/td&gt;&lt;td&gt;PC or Mac&lt;/td&gt;&lt;td&gt;unfree&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.codelv.com/projects/inkcut/&quot; class=&quot;external&quot;&gt;Inkcut&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://www.codelv.com/projects/inkcut/docs/supported-devices/&quot; class=&quot;external&quot;&gt;Supported Devices - Docs - Inkcut - CodeLV&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Windows, Mac, Linux, and Raspberry Pi&lt;/td&gt;&lt;td&gt;GPL-3.0&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/arkypita/LaserGRBL&quot; class=&quot;external&quot;&gt;LaserGRBL&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/grbl/grbl/&quot; class=&quot;external&quot;&gt;Grbl v0.9&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; and &lt;a href=&quot;https://github.com/gnea/grbl/&quot; class=&quot;external&quot;&gt;Grbl v1.1&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;Windows&lt;/td&gt;&lt;td&gt;GPL-3.0-or-later&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://lasermagic.ci-yow.com/&quot; class=&quot;external&quot;&gt;LaserMagic&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/AxelTB/nejePrint&quot; class=&quot;external&quot;&gt;nejePrint&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;Neje Laser engraver&lt;/td&gt;&lt;td&gt;Python3&lt;/td&gt;&lt;td&gt;MIT&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/cncjs/cncjs&quot; class=&quot;external&quot;&gt;cncjs&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;CNC controllers running &lt;a href=&quot;https://github.com/grbl/grbl&quot; class=&quot;external&quot;&gt;Grbl&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;, &lt;a href=&quot;https://github.com/MarlinFirmware/Marlin&quot; class=&quot;external&quot;&gt;Marlin&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;, &lt;a href=&quot;https://github.com/Smoothieware/Smoothieware&quot; class=&quot;external&quot;&gt;Smoothieware&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;, or &lt;a href=&quot;https://github.com/synthetos/TinyG&quot; class=&quot;external&quot;&gt;TinyG&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;.&lt;/td&gt;&lt;td&gt;web&lt;/td&gt;&lt;td&gt;MIT&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://linuxcnc.org/&quot; class=&quot;external&quot;&gt;LinuxCNC&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;http://wiki.linuxcnc.org/cgi-bin/wiki.pl?LinuxCNC_Supported_Hardware&quot; class=&quot;external&quot;&gt;LinuxCNC Documentation Wiki: LinuxCNC Supported Hardware&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;GPL-2.0&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/t-oster/LibLaserCut&quot; class=&quot;external&quot;&gt;LibLaserCut&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;details&gt;Older Epilog Lasers (Zing/Mini/Helix),&lt;br&gt;SmoothieBoard (&lt;a href=&quot;http://www.smoothieware.org&quot; class=&quot;external&quot;&gt;www.smoothieware.org&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;),&lt;br&gt;generic GCode,&lt;br&gt;the LAOS board (&lt;a href=&quot;http://www.laoslaser.org&quot; class=&quot;external&quot;&gt;www.laoslaser.org&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;),&lt;br&gt;K40,&lt;br&gt;generic GRBL based boards,&lt;br&gt;LTT iLaser 4000,&lt;br&gt;generic HPGL plotters&lt;br&gt;and many more.&lt;br&gt;&lt;br&gt;A detailed list of tested devices can be found in the VisiCut wiki: &lt;a href=&quot;https://github.com/t-oster/VisiCut/wiki/Supported-Hardware&quot; class=&quot;external&quot;&gt;https://github.com/t-oster/VisiCut/wiki/Supported-Hardware&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;br&gt;&lt;/details&gt;&lt;/td&gt;&lt;td&gt;java&lt;/td&gt;&lt;td&gt;LGPL-3.0&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://pbmelo.github.io/tutorials/2023/08/11/linuxcnc-with-laser-cutters.html&quot; class=&quot;external&quot;&gt;CNC laser cutting on Linux | Pedro’s blog&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://librearts.org/2012/06/vinyl-cutting-on-linux-the-real-deal/&quot; class=&quot;external&quot;&gt;Libre Arts - Free tools for vinyl cutting on Linux&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://old.reddit.com/r/linuxquestions/comments/8f8nua/linuxcompatible_vinyl_cutters/&quot; class=&quot;external&quot;&gt;Linux-compatible vinyl cutters? : linuxquestions&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://old.reddit.com/r/VinylCutting/comments/mj77jw/linux_compatible_plotters/&quot; class=&quot;external&quot;&gt;Linux compatible plotters? : VinylCutting&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;hardware&quot;&gt;Hardware&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#hardware&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Compatible hardware.&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://www.amazon.com/OMTech-Engraving-LaserGRBL-Compatible-Adjustable/dp/B0CYPKRTLX&quot; class=&quot;external&quot;&gt;https://www.amazon.com/OMTech-Engraving-LaserGRBL-Compatible-Adjustable/dp/B0CYPKRTLX&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h3 id=&quot;silhouette&quot;&gt;Silhouette&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#silhouette&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;

































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;&lt;a href=&quot;https://www.silhouette101.com/archives/everything-to-know-about-the-electrostatic-mat&quot; class=&quot;external&quot;&gt;Electrostatic Mat&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/th&gt;&lt;th&gt;&lt;a href=&quot;https://www.silhouette101.com/archives/cutting-without-a-mat-2&quot; class=&quot;external&quot;&gt;Pop-Out Cut&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/th&gt;&lt;th&gt;&lt;a href=&quot;https://silhouette-web.com/&quot; class=&quot;external&quot;&gt;Silhouette Web&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/th&gt;&lt;th&gt;&lt;a href=&quot;https://silhouetteamerica.freshdesk.com/support/solutions/articles/35000273078-features-cutting-machines-#Intelligent-Path-Technology%E2%84%A2-(IPT)&quot; class=&quot;external&quot;&gt;Intelligent Path Technology&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.silhouette101.com/archives/everything-to-know-about-the-cameo-5&quot; class=&quot;external&quot;&gt;Cameo 5&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;sup&gt;&lt;a href=&quot;#user-content-fn-/portrait4&quot; id=&quot;user-content-fnref-/portrait4&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot; class=&quot;internal alias&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Cameo 4&lt;sup&gt;&lt;a href=&quot;#user-content-fn-/portrait3&quot; id=&quot;user-content-fnref-/portrait3&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot; class=&quot;internal alias&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Cameo 3&lt;sup&gt;&lt;a href=&quot;#user-content-fn-/portrait2&quot; id=&quot;user-content-fnref-/portrait2&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot; class=&quot;internal alias&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;✅&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;




















&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;Max Cutting Size&lt;br&gt;(with a cutting mat)&lt;/th&gt;&lt;th&gt;Max Cutting Size&lt;br&gt;(without a cutting mat)&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Cameo&lt;/td&gt;&lt;td&gt;12 in. x 24 in. (30.5 cm x 61 cm)&lt;/td&gt;&lt;td&gt;12 in. x 60 ft. (30.5 cm x 18.3 m)&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Portrait&lt;/td&gt;&lt;td&gt;8 in. x 12 in. (20.3 cm x 30.5 cm)&lt;/td&gt;&lt;td&gt;8 in. x 60 ft. (20.3 cm x 18.3 m)&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://silhouetteamerica.freshdesk.com/support/solutions/articles/35000273078-features-cutting-machines-&quot; class=&quot;external&quot;&gt;Features (Cutting machines) : Silhouette America Support&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.silhouette101.com/archives/machine-comparison-chart&quot; class=&quot;external&quot;&gt;Machine Comparison Chart&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://www.silhouette101.com/wp-content/uploads/2021/02/comparison-chart-2021.pdf&quot; class=&quot;external&quot;&gt;comparison-chart-2021&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;section data-footnotes=&quot;&quot; class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#footnote-label&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-/portrait4&quot;&gt;
&lt;p&gt;and Portrait 4 &lt;a href=&quot;#user-content-fnref-/portrait4&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref internal alias&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-/portrait3&quot;&gt;
&lt;p&gt;and &lt;a href=&quot;https://www.silhouette101.com/archives/introduction-to-the-silhouette-portrait-3&quot; class=&quot;external&quot;&gt;Portrait 3&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-/portrait3&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 2&quot; class=&quot;data-footnote-backref internal alias&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-/portrait2&quot;&gt;
&lt;p&gt;and Portrait 2 &lt;a href=&quot;#user-content-fnref-/portrait2&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 3&quot; class=&quot;data-footnote-backref internal alias&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt; ]]></description>
    <pubDate>Thu, 27 Mar 2025 20:32:58 GMT</pubDate>
  </item><item>
    <title>awk(1)</title>
    <link>https://dennislee.xyz/awk</link>
    <guid>https://dennislee.xyz/awk</guid>
    <description><![CDATA[ &lt;p&gt;&lt;em&gt;awk&lt;/em&gt;(1) feature comparison matrix&lt;/p&gt;

































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;&lt;code&gt;--csv&lt;/code&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/onetrueawk/awk&quot; class=&quot;external&quot;&gt;One true awk&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;br&gt;&lt;a href=&quot;https://man.openbsd.org/awk&quot; class=&quot;external&quot;&gt;OpenBSD&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://github.com/onetrueawk/awk#csv&quot; class=&quot;external&quot;&gt;2ndEdition&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;sup&gt;&lt;a href=&quot;#user-content-fn-2ndedition&quot; id=&quot;user-content-fnref-2ndedition&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot; class=&quot;internal alias&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;br&gt;&lt;a href=&quot;https://man.openbsd.org/awk#csv&quot; class=&quot;external&quot;&gt;7.4&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;sup&gt;&lt;a href=&quot;#user-content-fn-openbsd-7.4&quot; id=&quot;user-content-fnref-openbsd-7.4&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot; class=&quot;internal alias&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://man.netbsd.org/awk.1&quot; class=&quot;external&quot;&gt;NetBSD&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://man.freebsd.org/cgi/man.cgi?query=awk&quot; class=&quot;external&quot;&gt;FreeBSD&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/9799919799/utilities/awk.html&quot; class=&quot;external&quot;&gt;POSIX&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://busybox.net/downloads/BusyBox.html&quot; class=&quot;external&quot;&gt;BusyBox&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;a href=&quot;https://www.gnu.org/software/gawk/&quot; class=&quot;external&quot;&gt;Gawk&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/td&gt;&lt;td&gt;&lt;a href=&quot;https://www.gnu.org/software/gawk/manual/html_node/Comma-Separated-Fields.html&quot; class=&quot;external&quot;&gt;5.3.0&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;sup&gt;&lt;a href=&quot;#user-content-fn-gawk-5.3.0&quot; id=&quot;user-content-fnref-gawk-5.3.0&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot; class=&quot;internal alias&quot;&gt;3&lt;/a&gt;&lt;/sup&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;section data-footnotes=&quot;&quot; class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#footnote-label&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-2ndedition&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/onetrueawk/awk/releases/tag/2ndEdition&quot; class=&quot;external&quot;&gt;Release 2ndEdition · onetrueawk/awk&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-2ndedition&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref internal alias&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-openbsd-7.4&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://www.openbsd.org/74.html&quot; class=&quot;external&quot;&gt;OpenBSD 7.4&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-openbsd-7.4&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 2&quot; class=&quot;data-footnote-backref internal alias&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-gawk-5.3.0&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://lists.gnu.org/archive/html/info-gnu/2023-11/msg00000.html&quot; class=&quot;external&quot;&gt;Gawk 5.3.0&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-gawk-5.3.0&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 3&quot; class=&quot;data-footnote-backref internal alias&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt; ]]></description>
    <pubDate>Mon, 24 Mar 2025 04:04:27 GMT</pubDate>
  </item><item>
    <title>Shebangs</title>
    <link>https://dennislee.xyz/shebangs</link>
    <guid>https://dennislee.xyz/shebangs</guid>
    <description><![CDATA[ &lt;ul&gt;
&lt;li&gt;The only FHS paths for executables that NixOS populates by default are &lt;code&gt;/bin/sh&lt;/code&gt; and &lt;code&gt;/usr/bin/env&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;#!/usr/bin/env&lt;/code&gt; is one of the shebangs &lt;a href=&quot;https://docs.python.org/3/using/windows.html#shebang-lines&quot; class=&quot;external&quot;&gt;Python&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; builds in support for on Windows.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;However, multiple arguments (such as in &lt;code&gt;#!/usr/bin/env awk -f&lt;/code&gt;) may be problematic due to, in this case, the entire &lt;code&gt;awk -f&lt;/code&gt; being treated as a single argument. &lt;a href=&quot;https://lists.gnu.org/archive/html/info-gnu/2018-07/msg00001.html&quot; class=&quot;external&quot;&gt;GNU coreutils 8.30&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; (2018) added the &lt;code&gt;env -S&lt;/code&gt; to split multiple parameters, so &lt;code&gt;#!/usr/bin/env -S awk -f&lt;/code&gt; will execute &lt;code&gt;awk -f&lt;/code&gt; as intended. This had already been present in &lt;a href=&quot;https://man.freebsd.org/cgi/man.cgi?query=env&quot; class=&quot;external&quot;&gt;FreeBSD&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; (since 6.0; 2005) and macOS versions. But it’s not &lt;a href=&quot;https://pubs.opengroup.org/onlinepubs/9799919799/utilities/env.html&quot; class=&quot;external&quot;&gt;POSIX&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;, and not in &lt;a href=&quot;https://man.netbsd.org/env.1&quot; class=&quot;external&quot;&gt;NetBSD&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;, &lt;a href=&quot;https://man.openbsd.org/env&quot; class=&quot;external&quot;&gt;OpenBSD&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;, &lt;a href=&quot;https://busybox.net/downloads/BusyBox.html&quot; class=&quot;external&quot;&gt;BusyBox&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;, &lt;a href=&quot;https://heirloom.sourceforge.net/man/env.1.html&quot; class=&quot;external&quot;&gt;Heirloom&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I’ve written things like &lt;code&gt;#!/bin/awk -f&lt;/code&gt; in the past, but due to my use of NixOS I thought to move to &lt;code&gt;#!/usr/bin/env -S&lt;/code&gt; despite its incompatibility with some other platforms. I imagine a certain hat-and-sunglasses-wearing blue whale telling me off for this, should he ever read this post. However, I did end up finding some other more portable solutions suggested. This is the one I ended up going with, e.g. in &lt;a href=&quot;https://github.com/dennisleexyz/allegro/blob/master/pp/csv&quot; class=&quot;external&quot;&gt;allegro&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre tabindex=&quot;0&quot; data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot;&gt;&lt;code data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#6A737D;--shiki-dark:#6A737D&quot;&gt;#!/bin/sh  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt;exec&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; awk&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; &quot;$(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;sed&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; 1,2d &quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt;$0&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt;&quot;)&quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; &quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt;$@&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt;&quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E1E4E8&quot;&gt;  &lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#6A737D;--shiki-dark:#6A737D&quot;&gt;# ex: ft=awk&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2 id=&quot;further-reading&quot;&gt;Further reading&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#further-reading&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/1418245/invoking-a-script-which-has-an-awk-shebang-with-parameters-vars&quot; class=&quot;external&quot;&gt;https://stackoverflow.com/questions/1418245/invoking-a-script-which-has-an-awk-shebang-with-parameters-vars&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://stackoverflow.com/questions/4303128/how-to-use-multiple-arguments-for-awk-with-a-shebang-i-e&quot; class=&quot;external&quot;&gt;https://stackoverflow.com/questions/4303128/how-to-use-multiple-arguments-for-awk-with-a-shebang-i-e&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://unix.stackexchange.com/questions/399690/multiple-arguments-in-shebang&quot; class=&quot;external&quot;&gt;https://unix.stackexchange.com/questions/399690/multiple-arguments-in-shebang&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt; ]]></description>
    <pubDate>Fri, 21 Mar 2025 07:48:42 GMT</pubDate>
  </item><item>
    <title>Shell prompt with exit code color</title>
    <link>https://dennislee.xyz/shell-prompt</link>
    <guid>https://dennislee.xyz/shell-prompt</guid>
    <description><![CDATA[ &lt;p&gt;I believe this is what they call “prompt engineering”.&lt;/p&gt;
&lt;code style=&quot;display:grid&quot;&gt;
	&lt;span&gt;
		&lt;b&gt;&lt;font color=&quot;green&quot;&gt;username@hostname&lt;/font&gt;&lt;/b&gt;&lt;font color=&quot;gray&quot;&gt;:&lt;/font&gt;&lt;b&gt;&lt;font color=&quot;blue&quot;&gt;~/pwd&lt;/font&gt;&lt;/b&gt;
		rm /
	&lt;/span&gt;
	&lt;span&gt;
		rm: cannot remove &#039;/&#039;: Is a directory
	&lt;/span&gt;
	&lt;span&gt;
		&lt;b&gt;&lt;font color=&quot;green&quot;&gt;username@hostname&lt;/font&gt;&lt;/b&gt;&lt;font color=&quot;red&quot;&gt;:&lt;/font&gt;&lt;b&gt;&lt;font color=&quot;blue&quot;&gt;~/pwd&lt;/font&gt;&lt;/b&gt;
		^C
	&lt;/span&gt;
	&lt;span&gt;
		&lt;b&gt;&lt;font color=&quot;green&quot;&gt;username@hostname&lt;/font&gt;&lt;/b&gt;&lt;font color=&quot;#af5f00&quot;&gt;:&lt;/font&gt;&lt;b&gt;&lt;font color=&quot;blue&quot;&gt;~/pwd&lt;/font&gt;&lt;/b&gt;
	&lt;/span&gt;
&lt;/code&gt;
&lt;p&gt;I set the color of the colon &lt;code&gt;:&lt;/code&gt; to the &lt;a href=&quot;https://en.wikipedia.org/wiki/ANSI_escape_code#8-bit&quot; class=&quot;external&quot;&gt;8-bit color&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; corresponding to the &lt;a href=&quot;https://en.wikipedia.org/wiki/Exit_status&quot; class=&quot;external&quot;&gt;Exit status&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; of the last executed command (&lt;code&gt;$?&lt;/code&gt;). &lt;code&gt;0&lt;/code&gt; is success, which maps to black, which is usually the background color, which makes it invisible until copied and pasted somewhere else. Any other value (&lt;code&gt;1-255&lt;/code&gt;) makes it visible.&lt;/p&gt;
&lt;p&gt;Everything else is pretty basic.&lt;/p&gt;
&lt;h2 id=&quot;bash&quot;&gt;bash&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#bash&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;code&gt;
PS1=&#039;&lt;b&gt;&lt;font color=&quot;green&quot;&gt;\[\e[1;32m\]\u@\h&lt;/font&gt;&lt;/b&gt;&lt;font color=&quot;gray&quot;&gt;\[\e[38;5;$?m\]:&lt;/font&gt;&lt;b&gt;&lt;font color=&quot;blue&quot;&gt;\[\e[34m\]\w\[\e[0m\]&lt;/font&gt;&lt;/b&gt; &#039;
&lt;/code&gt;
&lt;p&gt;You might see &lt;code&gt;\033&lt;/code&gt; for octal character &lt;code&gt;33&lt;/code&gt; instead of &lt;code&gt;\e&lt;/code&gt; for escape. Hexadecimal &lt;code&gt;\x1b&lt;/code&gt; and decimal &lt;code&gt;\27&lt;/code&gt; didn’t work.&lt;/p&gt;
&lt;p&gt;The outer enclosing square brackets &lt;code&gt;\[\]&lt;/code&gt; around each escape sequence may appear to be optional at first, but after testing, I found that omitting them causes weird behavior.&lt;/p&gt;
&lt;h2 id=&quot;zsh&quot;&gt;zsh&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#zsh&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;code&gt;
PS1=&#039;&lt;b&gt;%B&lt;font color=&quot;green&quot;&gt;%F{green}%n@%m&lt;/font&gt;&lt;/b&gt;%b&lt;font color=&quot;gray&quot;&gt;%F{%?}:&lt;/font&gt;&lt;b&gt;%B&lt;font color=&quot;blue&quot;&gt;%F{blue}%~%f&lt;/font&gt;&lt;/b&gt;%b &#039;
&lt;/code&gt;
&lt;hr&gt;





































































































&lt;table&gt;&lt;thead&gt;&lt;tr&gt;&lt;th&gt;&lt;/th&gt;&lt;th&gt;bash&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot; class=&quot;internal alias&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/th&gt;&lt;th&gt;zsh&lt;sup&gt;&lt;a href=&quot;#user-content-fn-2&quot; id=&quot;user-content-fnref-2&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot; class=&quot;internal alias&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;&lt;/th&gt;&lt;th&gt;&lt;/th&gt;&lt;/tr&gt;&lt;/thead&gt;&lt;tbody&gt;&lt;tr&gt;&lt;td&gt;Start boldface mode&lt;br&gt;Set foreground color green&lt;/td&gt;&lt;td&gt;&lt;code&gt;\e[1;32m&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Start boldface mode&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;%B&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Set foreground color green&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;%F{green}&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;username of the current user&lt;/td&gt;&lt;td&gt;&lt;code&gt;\u&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;%n&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;username&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;literal &lt;code&gt;@&lt;/code&gt; character&lt;/td&gt;&lt;td&gt;&lt;code&gt;@&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;@&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;@&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;hostname up to the first ’.‘.&lt;/td&gt;&lt;td&gt;&lt;code&gt;\h&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;%m&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;hostname&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;stop boldface mode&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;%b&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Set foreground color &lt;code&gt;$?&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;\e[38;5;$?m&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;%F{%?}&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;literal &lt;code&gt;:&lt;/code&gt; character&lt;/td&gt;&lt;td&gt;&lt;code&gt;:&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;:&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;:&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;Set foreground color blue&lt;/td&gt;&lt;td&gt;&lt;code&gt;\e[34m&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;%F{blue}&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;&lt;code&gt;$PWD&lt;/code&gt; with &lt;code&gt;$HOME&lt;/code&gt; replaced by a ’~‘.&lt;/td&gt;&lt;td&gt;&lt;code&gt;\w&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;%~&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;~/pwd&lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;All attributes become turned off&lt;/td&gt;&lt;td&gt;&lt;code&gt;\e[0m&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;stop using a different foreground color&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;%f&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;stop boldface mode&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt;%b&lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;/td&gt;&lt;/tr&gt;&lt;tr&gt;&lt;td&gt;literal space character&lt;/td&gt;&lt;td&gt;&lt;code&gt; &lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt; &lt;/code&gt;&lt;/td&gt;&lt;td&gt;&lt;code&gt; &lt;/code&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/tbody&gt;&lt;/table&gt;
&lt;section data-footnotes=&quot;&quot; class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#footnote-label&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-1&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Controlling-the-Prompt&quot; class=&quot;external&quot;&gt;https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Controlling-the-Prompt&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-1&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref internal alias&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-2&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://linux.die.net/man/1/zshmisc&quot; class=&quot;external&quot;&gt;&lt;code&gt;man zshmisc&lt;/code&gt;&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-2&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 2&quot; class=&quot;data-footnote-backref internal alias&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt; ]]></description>
    <pubDate>Sun, 02 Mar 2025 05:01:26 GMT</pubDate>
  </item><item>
    <title>Monitor shelf</title>
    <link>https://dennislee.xyz/monitorshelf</link>
    <guid>https://dennislee.xyz/monitorshelf</guid>
    <description><![CDATA[ &lt;p&gt;I noticed that the desktop monitors at my workstation were too low, causing me to hunch over. I used &lt;a href=&quot;https://www.ergotron.com/en-us/tools/workspace-planner&quot; class=&quot;external&quot;&gt;ergotron.com’s workspace planner&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; to determine the optimal shelf height based on the heights of myself, the chair, and the desk.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./monitorshelffront.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The wood was mounted to a sawhorse and cut to size using a circular saw.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./monitorshelfhole.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;Using a drill press, I drilled a large (1” diameter) hole in the back to pass cables through for clean cable management.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./monitorshelfleft.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The room underneath acts as extra storage space.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./monitorshelfright.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;The 1x4 in the back lends structural support to prevent the top piece from flexing under the weight of the monitors. It is attached to the legs with screws.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;./monitorshelfunder.jpg&quot; alt=&quot;&quot;&gt;&lt;/p&gt;
&lt;p&gt;I then drilled holes into the wood to drive in the screws used to hold the legs in place using these corner braces.&lt;/p&gt; ]]></description>
    <pubDate>Wed, 05 Jan 2022 19:41:36 GMT</pubDate>
  </item><item>
    <title>LineageOS 17 to 18 clean flash</title>
    <link>https://dennislee.xyz/lineageos-17-to-18-clean-flash</link>
    <guid>https://dennislee.xyz/lineageos-17-to-18-clean-flash</guid>
    <description><![CDATA[ &lt;p&gt;I recently updated my OnePlus One from LineageOS with microG version 17
(Android 10) to version 18 (Android 11). Dirty flashing the new system on top
of my existing data resulted in a bootloop, so I had to wipe everything and
clean flash it.&lt;/p&gt;
&lt;p&gt;Also, apparently Magisk’s install process has changed since I last installed
it. Now instead of just flashing the zip on top right after installing the ROM
in recovery, you have to extract the boot.img from the ROM zip, patch it from
the Magisk app in userspace, then flash the patched boot image in recovery.&lt;/p&gt;
&lt;h2 id=&quot;data-transfer&quot;&gt;Data Transfer&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#data-transfer&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;First I updated my system to the latest LineageOS 17.1 released in March before
the first 18.1 builds started coming. I hadn’t been keeping up with these
updates because the automatic install wasn’t working and it was annoying to do
it manually (especially since the updater downloads the ROM zips to /data, not
sdcard), but it worked this time. I had just installed the latest TWRP 3.5 and
maybe that had something to do with it (I don’t use Lineage Recovery due to a
lack of functionality).&lt;/p&gt;
&lt;p&gt;I installed a newer 17.1 before going to 18.1 in order to use the new SeedVault
backup and restore system. SeedVault was made by CalyxOS which is more hardened
than LineageOS. Unfortunately my device doesn’t support Calyx but I want to get
one that does (or a PinePhone) when my current one finally becomes unusable.
SeedVault uses the exact same API as Google’s proprietary system that backs up
to Google Drive, but it stores backups to either local storage (internal or
external) or Nextcloud.&lt;/p&gt;
&lt;p&gt;After I restored the SeedVault backup onto the new install I also had to
restore manual backups from Contacts and Signal using their respective built-in
backup and restore functionality at the app level. It seems like the contacts
storage implementation changed between these particular system versions, so
maybe I won’t have to do that part next time.&lt;/p&gt;
&lt;p&gt;I also made and will continue using oandbackups (only user apps, and only data,
to save space), because some apps like to exclude themselves from being backed
up using Google’s APIs which is inconvenient. However these don’t necessarily
always work either, for example with Fennec (Firefox) and some things with
cryptographic security like the aforementioned Signal. In the past I also had
issues with andOTP’s secure 2-factor authentication storage, but with pass-otp
these are handled just like my regular password manager storage. For Fennec
just sign in to sync, for other apps use their export/import functions if they
exist. Also make a full Nandroid backup any time you’re about to wipe your data
just in case you need to go back for something. (And delete any downloaded
updates from the LineageOS updater before this, or they will waste space in
your Nandroid!)&lt;/p&gt;
&lt;p&gt;I used to use Slight backup from F-Droid for call logs and SMS/MMS messages,
but SeedVault did the trick there no problem.&lt;/p&gt; ]]></description>
    <pubDate>Fri, 06 Aug 2021 02:31:39 GMT</pubDate>
  </item><item>
    <title>ZFS fault tolerance</title>
    <link>https://dennislee.xyz/zfs-fault-tolerance</link>
    <guid>https://dennislee.xyz/zfs-fault-tolerance</guid>
    <description><![CDATA[ &lt;h2 id=&quot;snapshots&quot;&gt;Snapshots&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#snapshots&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The root directory of a ZFS filesystem contains an invisible folder
&lt;code&gt;.zfs/&lt;/code&gt;. This differs from a regular “hidden” folder in that it doesn’t
show up with &lt;code&gt;ls -A&lt;/code&gt; and other such operations.&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot; class=&quot;internal alias&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;p&gt;Inside &lt;code&gt;.zfs/snapshot/&lt;/code&gt;, every available snapshot is represented in a
directory. A snapshot is just a complete representation of the entire
file system as it existed at a particular point in time. So you can
recover an earlier version of something just by pulling it from one of
these snapshots.&lt;/p&gt;
&lt;p&gt;I won’t go into the details here, but snapshots are very computationally
cheap, unlike if you tried to recreate something like this with &lt;em&gt;cp&lt;/em&gt;(1)
and &lt;em&gt;rsync&lt;/em&gt;(1) or whatever. So it’s advised to create many of them and
create them often to maximize their usefulness.&lt;/p&gt;
&lt;p&gt;Debian has a couple scripts in its official repositories that completely
automate periodically creating new snapshots and removing older ones:
&lt;em&gt;zfs-auto-snapshot&lt;/em&gt;(8) in &lt;code&gt;contrib&lt;/code&gt; and &lt;code&gt;zfsnap&lt;/code&gt; in &lt;code&gt;main&lt;/code&gt;. Personally,
I use the former.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;zfs-auto-snapshot&lt;/em&gt;(8) package installs its default cron jobs
automatically, so it’s not necessary to configure anything. It does
&lt;code&gt;frequent&lt;/code&gt; snapshots every 15 minutes (keeping the 4 most recent ones)
and also &lt;code&gt;hourly&lt;/code&gt;, &lt;code&gt;daily&lt;/code&gt;, &lt;code&gt;weekly&lt;/code&gt;, and &lt;code&gt;monthly&lt;/code&gt; ones. It seems like
&lt;code&gt;zfsnap&lt;/code&gt; does not come with cron jobs.&lt;/p&gt;
&lt;h2 id=&quot;degraded-arrays&quot;&gt;Degraded arrays&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#degraded-arrays&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;In a mirrored layout, ZFS will carry on if a disk fails. Here’s what I
did in my testing of this:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre tabindex=&quot;0&quot; data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot;&gt;&lt;code data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt;cd&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; data&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt;echo&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; &#039;This is a file.&#039;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#F97583&quot;&gt; &gt;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; file.txt&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;cat&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; file.txt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;This is a file.
&lt;/code&gt;&lt;/pre&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre tabindex=&quot;0&quot; data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot;&gt;&lt;code data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;shutdown&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; -h&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; now&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#6A737D;--shiki-dark:#6A737D&quot;&gt;# Unplug one of the hard drives&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#6A737D;--shiki-dark:#6A737D&quot;&gt;# Power on&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt;cd&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; data&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;cat&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; file.txt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;This is a file.
&lt;/code&gt;&lt;/pre&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre tabindex=&quot;0&quot; data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot;&gt;&lt;code data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt;echo&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; &#039;This is a change I made.&#039;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#F97583&quot;&gt; &gt;&gt;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; file.txt&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;cat&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; file.txt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;This is a file.
This is a change I made.
&lt;/code&gt;&lt;/pre&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre tabindex=&quot;0&quot; data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot;&gt;&lt;code data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;shutdown&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; -h&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; now&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#6A737D;--shiki-dark:#6A737D&quot;&gt;# Reattach the unplugged hard drive&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#6A737D;--shiki-dark:#6A737D&quot;&gt;# Power on&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt;cd&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; data&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;cat&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; file.txt&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;This is a file.
This is a change I made.
&lt;/code&gt;&lt;/pre&gt;
&lt;section data-footnotes=&quot;&quot; class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#footnote-label&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-1&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://unix.stackexchange.com/q/332192&quot; class=&quot;external&quot;&gt;https://unix.stackexchange.com/q/332192&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-1&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref internal alias&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt; ]]></description>
    <pubDate>Sat, 11 Jul 2020 03:34:13 GMT</pubDate>
  </item><item>
    <title>ZFS on different size drives</title>
    <link>https://dennislee.xyz/zfs-different-size-drives</link>
    <guid>https://dennislee.xyz/zfs-different-size-drives</guid>
    <description><![CDATA[ &lt;p&gt;This is how I set up a mirrored &lt;a href=&quot;https://openzfs.github.io/openzfs-docs/Project%20and%20Community/&quot; class=&quot;external&quot;&gt;ZFS&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; file system on a system with one 500
GB HDD and one 250 GB HDD.&lt;/p&gt;
&lt;p&gt;At this point, I have done the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Install the latest stable version of &lt;a href=&quot;https://devuan.org/&quot; class=&quot;external&quot;&gt;Devuan&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; to half of the 500 GB
drive.&lt;/li&gt;
&lt;li&gt;Create a 250 GB partition (the size of the other drive) covering the
rest of the 500 GB drive.&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://openzfs.github.io/openzfs-docs/Getting%20Started/&quot; class=&quot;external&quot;&gt;Install ZFS&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre tabindex=&quot;0&quot; data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot;&gt;&lt;code data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;lsblk&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; -o&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; NAME,FSTYPE,SIZE,TYPE,MOUNTPOINT&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;NAME   FSTYPE   SIZE MOUNTPOINT
sda           465.8G
├─sda1 vfat     512M /boot/efi
├─sda2 btrfs    229G /
├─sda3 swap     3.5G [SWAP]
└─sda4 ext4   232.9G
sdb           232.9G
└─sdb1 ext4   232.9G
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Optional: you can &lt;em&gt;wipefs&lt;/em&gt;(8) to remove the file system information (but
not data) from the 250 GB partition and disk. The setup will work
whether or not you do this.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre tabindex=&quot;0&quot; data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot;&gt;&lt;code data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; wipefs&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; /dev/sda4&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; wipefs&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; -a&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; /dev/sdb&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;lsblk&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; -o&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; NAME,FSTYPE,SIZE,TYPE,MOUNTPOINT&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;NAME   FSTYPE   SIZE MOUNTPOINT
sda           465.8G
├─sda1 vfat     512M /boot/efi
├─sda2 btrfs    229G /
├─sda3 swap     3.5G [SWAP]
└─sda4        232.9G
sdb           232.9G
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Before creating the ZFS pool, find the unique IDs of the relevant
drives. Don’t use those short identifiers with the letters (&lt;code&gt;/dev/sdX&lt;/code&gt;)
because the system might assign them differently on a future reboot.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre tabindex=&quot;0&quot; data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot;&gt;&lt;code data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;ls&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; -ls&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; /dev/disk/by-id/&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#F97583&quot;&gt; |&lt;/span&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt; awk&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; &#039;{print $10,$11,$12}&#039;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;ata-HGST_HTS725050A7E630_TF755AWHHA2J9M -&gt; ../../sda
ata-HGST_HTS725050A7E630_TF755AWHHA2J9M-part1 -&gt; ../../sda1
ata-HGST_HTS725050A7E630_TF755AWHHA2J9M-part2 -&gt; ../../sda2
ata-HGST_HTS725050A7E630_TF755AWHHA2J9M-part3 -&gt; ../../sda3
ata-HGST_HTS725050A7E630_TF755AWHHA2J9M-part4 -&gt; ../../sda4
ata-ST250DM000-1BD141_5VY93J76 -&gt; ../../sdb
wwn-0x5000c5005ce4e07d -&gt; ../../sdb
wwn-0x5000cca77fd2acb2 -&gt; ../../sda
wwn-0x5000cca77fd2acb2-part1 -&gt; ../../sda1
wwn-0x5000cca77fd2acb2-part2 -&gt; ../../sda2
wwn-0x5000cca77fd2acb2-part3 -&gt; ../../sda3
wwn-0x5000cca77fd2acb2-part4 -&gt; ../../sda4
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Apparently there are 2 sets of IDs linked to the same disks. I’ll just
show the &lt;code&gt;wwn-&lt;/code&gt; ones because they’re shorter.&lt;/p&gt;
&lt;p&gt;The following creates a mirrored &lt;code&gt;zpool&lt;/code&gt; (software RAID, basically)
named &lt;code&gt;tank&lt;/code&gt; with the 250 GB partition and disk.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre tabindex=&quot;0&quot; data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot;&gt;&lt;code data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; zpool&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; create&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; tank&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; mirror&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; wwn-0x5000cca77fd2acb2-part4&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; wwn-0x5000c5005ce4e07d&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;lsblk&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; -bo&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; NAME,FSTYPE,SIZE,TYPE,MOUNTPOINT&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;NAME   FSTYPE             SIZE TYPE MOUNTPOINT
sda               500107862016 disk
├─sda1 vfat          536870912 part /boot/efi
├─sda2 btrfs      245809283072 part /
├─sda3 swap         3700424704 part [SWAP]
└─sda4 zfs_member 250059350016 part
sdb               250059350016 disk
├─sdb1 zfs_member 250049724416 part
└─sdb9                 8388608 part
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;ZFS will automatically mount &lt;code&gt;tank&lt;/code&gt; to &lt;code&gt;/tank&lt;/code&gt; (persisting across
reboots), but there are options to change the mount point or handle
mounting manually with &lt;code&gt;fstab&lt;/code&gt;, &lt;em&gt;mount&lt;/em&gt;(8), &lt;em&gt;umount&lt;/em&gt;(8) and such. When
I create the &lt;code&gt;data&lt;/code&gt; file system inside &lt;code&gt;tank&lt;/code&gt;, I will change its mount
point. &lt;code&gt;data&lt;/code&gt; doesn’t have to be mounted inside of &lt;code&gt;tank&lt;/code&gt;’s mount point,
as you will see.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre tabindex=&quot;0&quot; data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot;&gt;&lt;code data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; zfs&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; create&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; tank/data&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; zfs&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; set&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; mountpoint=/home/dennis/data&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; tank/data&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; zfs&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; get&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; mountpoint&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; tank/data&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;NAME       PROPERTY    VALUE              SOURCE
tank/data  mountpoint  /home/dennis/data  local
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;At this point, &lt;code&gt;/home/dennis/data&lt;/code&gt; will be owned by &lt;code&gt;root:root&lt;/code&gt;, which
is probably not desired (I mounted it inside my &lt;code&gt;~&lt;/code&gt; for a reason!).
Let’s fix that.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre tabindex=&quot;0&quot; data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot;&gt;&lt;code data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt;cd&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; /home/dennis&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;sudo&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; chown&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; -R&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; dennis:dennis&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; data&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;ls&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; -l&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;pre&gt;&lt;code&gt;drwxr-xr-x 2 dennis dennis 2 Jul  8 20:36 data/
&lt;/code&gt;&lt;/pre&gt; ]]></description>
    <pubDate>Thu, 09 Jul 2020 05:43:32 GMT</pubDate>
  </item><item>
    <title>One weird trick to debloat apt-based distros</title>
    <link>https://dennislee.xyz/apt-recommended</link>
    <guid>https://dennislee.xyz/apt-recommended</guid>
    <description><![CDATA[ &lt;p&gt;In &lt;em&gt;apt&lt;/em&gt;(1), the package manager for Debian and its derivatives,
packages may have “optional” and “recommended” dependencies. By default,
the recommended dependencies are installed automatically, as if they are
required.&lt;/p&gt;
&lt;p&gt;This led to an absurd situation on my minimal server installation of
Devuan. When I went to install &lt;code&gt;openssh-server&lt;/code&gt;, it wanted to pull in
almost 200MB of other random packages, including a bunch of graphical
desktop packages for X11!&lt;/p&gt;
&lt;p&gt;If you don’t want these recommended packages, here’s how to stop them
from being installed. Create the following file:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;/etc/apt/apt.conf.d/99_norecommends
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;and add these contents to it.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;APT::Install-Recommends &quot;false&quot;;
APT::AutoRemove::RecommendsImportant &quot;false&quot;;
APT::AutoRemove::SuggestsImportant &quot;false&quot;;
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Then do &lt;code&gt;apt autoremove&lt;/code&gt; to remove already installed recommends.&lt;/p&gt;
&lt;p&gt;Just for fun, here’s what my &lt;code&gt;autoremove&lt;/code&gt; prompt looks like after
installing just &lt;code&gt;openssh-server&lt;/code&gt;, &lt;em&gt;mosh&lt;/em&gt;(1), and &lt;code&gt;man-db&lt;/code&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;The following packages will be REMOVED:
  adwaita-icon-theme apparmor at-spi2-core bzip2 dbus dbus-x11
  dconf-gsettings-backend dconf-service dictionaries-common efibootmgr
  elogind emacsen-common file fontconfig fontconfig-config
  fonts-dejavu-core glib-networking glib-networking-common
  glib-networking-services grub-efi-amd64-signed
  gsettings-desktop-schemas gtk-update-icon-cache hicolor-icon-theme
  iamerican ibritish ienglish-common ispell krb5-locales libapparmor1
  libatk-bridge2.0-0 libatk1.0-0 libatk1.0-data libatspi2.0-0
  libavahi-client3 libavahi-common-data libavahi-common3
  libcairo-gobject2 libcairo2 libcolord2 libcroco3 libcups2 libdatrie1
  libdbus-1-3 libdconf1 libepoxy0 libfontconfig1 libfribidi0
  libgdk-pixbuf2.0-0 libgdk-pixbuf2.0-bin libgdk-pixbuf2.0-common
  libglib2.0-0 libglib2.0-data libgraphite2-3 libgtk-3-0 libgtk-3-bin
  libgtk-3-common libharfbuzz0b libicu63 libjbig0 libjpeg62-turbo
  libjson-glib-1.0-0 libjson-glib-1.0-common liblcms2-2 libmagic-mgc
  libmagic1 libmpdec2 libpam-elogind libpango-1.0-0 libpangocairo-1.0-0
  libpangoft2-1.0-0 libpixman-1-0 libpolkit-agent-1-0
  libpolkit-backend-1-0 libpolkit-backend-elogind-1-0
  libpolkit-gobject-1-0 libpolkit-gobject-elogind-1-0 libproxy1v5
  libpsl5 libpython3-stdlib libpython3.7-minimal libpython3.7-stdlib
  libreadline7 librest-0.7-0 librsvg2-2 librsvg2-common
  libsoup-gnome2.4-1 libsoup2.4-1 libsqlite3-0 libthai-data libthai0
  libtiff5 libwayland-client0 libwayland-cursor0 libwayland-egl1
  libwebp6 libx11-6 libx11-data libxau6 libxcb-render0 libxcb-shm0
  libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxdmcp6 libxext6
  libxfixes3 libxi6 libxinerama1 libxkbcommon0 libxml2 libxmuu1
  libxrandr2 libxrender1 libxtst6 mime-support os-prober policykit-1
  policykit-1-gnome publicsuffix python3 python3-minimal python3.7
  python3.7-minimal shared-mime-info util-linux-locales wamerican
  x11-common xauth xdg-user-dirs xz-utils
0 upgraded, 0 newly installed, 131 to remove and 0 not upgraded.
After this operation, 211 MB disk space will be freed.
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;a href=&quot;https://askubuntu.com/a/399078&quot; class=&quot;external&quot;&gt;https://askubuntu.com/a/399078&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/p&gt; ]]></description>
    <pubDate>Wed, 08 Jul 2020 05:58:22 GMT</pubDate>
  </item><item>
    <title>Thunderbird profile anatomy</title>
    <link>https://dennislee.xyz/thunderbird-profile-anatomy</link>
    <guid>https://dennislee.xyz/thunderbird-profile-anatomy</guid>
    <description><![CDATA[ &lt;p&gt;These are the folders I save when backing up profiles for Thunderbird
and Thunderbird-based email clients.&lt;/p&gt;
&lt;h2 id=&quot;extensions&quot;&gt;Extensions&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#extensions&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The following 2 items are sufficient for fully restoring extensions.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;extensions/
├── example@mozdev.org.xpi
├── {xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx}.xpi
└── [[:graph:]]+\.xpi
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This folder stores extension files for all installed extensions (except
ones which are pre-installed).&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;extensions.ini
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;List of enabled extensions. Human-readable format.&lt;/p&gt;
&lt;h2 id=&quot;authenticationlogging-in&quot;&gt;Authentication/logging in&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#authenticationlogging-in&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;The following 2 files must be combined with a proper &lt;code&gt;prefs.js&lt;/code&gt; or
&lt;code&gt;user.js&lt;/code&gt; to fully restore logins.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;key4.db
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Server authentication credentials. If you delete this, you will be
prompted to log in to your account(s) again the next time you open the
program, but everything else will remain intact.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;logins.json
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Stores information about which accounts are currently logged in.&lt;/p&gt;
&lt;h2 id=&quot;mailbox-storage&quot;&gt;Mailbox storage&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#mailbox-storage&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;Mail/
└── Local Folders/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Folder for locally-stored mail.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ImapMail/
├── imap.example.com/
└── mail.example.net/
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Folder for saving offline copies of mail which is synced with an IMAP
server.&lt;/p&gt;
&lt;h2 id=&quot;settings-storage&quot;&gt;Settings storage&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#settings-storage&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;pre&gt;&lt;code&gt;prefs.js
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Stores all user preferences, including information about accounts. This
file is edited by changing settings from within the graphical
environment.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;user.js
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Can store any user preference, but values defined here will always take
precedence over those stored in &lt;code&gt;prefs.js&lt;/code&gt; when the program is started.&lt;/p&gt; ]]></description>
    <pubDate>Sun, 05 Jul 2020 02:57:52 GMT</pubDate>
  </item><item>
    <title>Suckless software howto</title>
    <link>https://dennislee.xyz/suckless-howto</link>
    <guid>https://dennislee.xyz/suckless-howto</guid>
    <description><![CDATA[ &lt;p&gt;How do you download, patch, configure, and install suckless software?&lt;/p&gt;
&lt;h2 id=&quot;downloading&quot;&gt;Downloading&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#downloading&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Released versions are listed for download under the homepage for each
program. These download links are also provided on the suckless homepage
and news (RSS/Atom) feed when they announce the release of a new
version.&lt;/p&gt;
&lt;p&gt;Programs can also be downloaded via &lt;code&gt;git clone&lt;/code&gt;, for the latest
development versions and for version control history. See
&lt;a href=&quot;https://git.suckless.org/&quot; class=&quot;external&quot;&gt;https://git.suckless.org/&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;patching&quot;&gt;Patching&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#patching&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Find and download patches on the suckless website listed under each
program. The commands and strategies below are discussed in order of
preference.&lt;/p&gt;
&lt;h3 id=&quot;git1-commands&quot;&gt;&lt;em&gt;git&lt;/em&gt;(1) commands&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#git1-commands&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This section assumes that you downloaded the program’s source code as a
&lt;em&gt;git&lt;/em&gt;(1) repository (which is recommended), using &lt;code&gt;git clone&lt;/code&gt; or
similar. If not, skip to the next section.&lt;/p&gt;
&lt;p&gt;First, try using&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre tabindex=&quot;0&quot; data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot;&gt;&lt;code data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; am&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#F97583&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt;patc&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E1E4E8&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt;.diff&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;to apply a patch and commit it automatically. This only works with
patches that were formatted for/with &lt;em&gt;git&lt;/em&gt;(1), though. Unfortunately,
that’s not the case for all of the patches, so if &lt;code&gt;git am&lt;/code&gt; fails, try&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre tabindex=&quot;0&quot; data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot;&gt;&lt;code data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; apply&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#F97583&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt;patc&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E1E4E8&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt;.diff&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;which will apply the patch and stage the changes.&lt;/p&gt;
&lt;p&gt;To reverse a patch, use&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre tabindex=&quot;0&quot; data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot;&gt;&lt;code data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; reset&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; --hard&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; HEAD^&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;if the patch was commited. (This is the case if you ran &lt;code&gt;git am&lt;/code&gt; or
commited manually.) If the patch was not commited (you used
&lt;code&gt;git apply&lt;/code&gt; and did not commit manually), use the following.&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre tabindex=&quot;0&quot; data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot;&gt;&lt;code data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;git&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; revert&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; .&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h3 id=&quot;patch1-commands&quot;&gt;&lt;em&gt;patch&lt;/em&gt;(1) commands&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#patch1-commands&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;This is only recommended if you cannot use the &lt;em&gt;git&lt;/em&gt;(1) commands (as
mentioned above).&lt;/p&gt;
&lt;p&gt;Use the following. The &lt;code&gt;--merge&lt;/code&gt; flag on &lt;em&gt;patch&lt;/em&gt;(1) is to handle
conflicts more easily (in the same way as &lt;em&gt;git&lt;/em&gt;(1) handles conflicts).&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre tabindex=&quot;0&quot; data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot;&gt;&lt;code data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;patch&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; -i&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; --merge&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#F97583&quot;&gt; &amp;#x3C;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt;patc&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E1E4E8&quot;&gt;h&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#F97583&quot;&gt;&gt;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt;.diff&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;h2 id=&quot;configuration&quot;&gt;Configuration&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#configuration&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are 3 files named &lt;code&gt;config&lt;/code&gt;. What are the differences?&lt;/p&gt;
&lt;h3 id=&quot;configmk&quot;&gt;&lt;code&gt;config.mk&lt;/code&gt;&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#configmk&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Configuration for the Makefile. The &lt;code&gt;.mk&lt;/code&gt; extension/suffix denotes
Makefile syntax, for a file meant to be &lt;code&gt;include&lt;/code&gt;d in a Makefile.&lt;/p&gt;
&lt;h3 id=&quot;configdefh&quot;&gt;&lt;code&gt;config.def.h&lt;/code&gt;&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#configdefh&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Stores &lt;em&gt;&lt;strong&gt;def&lt;/strong&gt;&lt;/em&gt;ault values for all of the configuration options; a
template. Often modified by patches; they add the default values for
their own custom config options to this file. Used to generate &lt;code&gt;config.h&lt;/code&gt;.&lt;/p&gt;
&lt;h3 id=&quot;configh&quot;&gt;&lt;code&gt;config.h&lt;/code&gt;&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#configh&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Intended to be edited by the end user: they provide their own values for
each of the configuration options. If it does not exist, it is copied
from &lt;code&gt;config.def.h&lt;/code&gt; when running &lt;code&gt;make&lt;/code&gt;/&lt;code&gt;make all&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;However, if it does exist, it is not modified. This can cause problems
when applying patches after &lt;code&gt;config.h&lt;/code&gt; is already generated. The program
is built from &lt;code&gt;config.h&lt;/code&gt;, not &lt;code&gt;config.def.h&lt;/code&gt;, so after applying the
patch you may not have the config options required by the patch. In that
case, compilation will fail with errors!&lt;/p&gt;
&lt;h2 id=&quot;installing&quot;&gt;Installing&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#installing&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Programs are installed by running &lt;em&gt;make&lt;/em&gt;(1) targets, which are defined
in the &lt;code&gt;Makefile&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;To compile, run &lt;code&gt;make&lt;/code&gt; or &lt;code&gt;make all&lt;/code&gt;. This will
output the compiled program to the current working folder, where it can
be run; if I compiled &lt;em&gt;st&lt;/em&gt;(1), I could run it with &lt;code&gt;./st&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Installing a program makes it available from anywhere, not just a single
directory, and makes it available to all users. Run &lt;code&gt;sudo make install&lt;/code&gt;
to install.&lt;/p&gt;
&lt;p&gt;If you do not have administrative privileges, you may want to (instead
of installing) place the compiled executable somewhere in your &lt;code&gt;$PATH&lt;/code&gt;
so that the program can be started easily from any location.&lt;/p&gt; ]]></description>
    <pubDate>Sun, 28 Jun 2020 05:27:32 GMT</pubDate>
  </item><item>
    <title>Hugo date/slug from filename à la Jekyll</title>
    <link>https://dennislee.xyz/hugo-date-and-slug-from-filename</link>
    <guid>https://dennislee.xyz/hugo-date-and-slug-from-filename</guid>
    <description><![CDATA[ &lt;p&gt;OK, so this is now the 3rd post in this saga about automatic Hugo front
matter from filenames. This supersedes my &lt;a href=&quot;./jekyll-vs-hugo&quot; class=&quot;internal alias&quot; data-slug=&quot;jekyll-vs-hugo&quot;&gt;1st&lt;/a&gt; and &lt;a href=&quot;./change-hugo-automatic-title-and-slug&quot; class=&quot;internal alias&quot; data-slug=&quot;change-hugo-automatic-title-and-slug&quot;&gt;2nd&lt;/a&gt; posts on
the subject.&lt;/p&gt;
&lt;p&gt;I now have exactly the behavior of Jekyll, where you name files in the
format &lt;code&gt;YYYY-MM-DD-title-slug.md&lt;/code&gt; and the post date is automatically
detected as &lt;code&gt;YYYY-MM-DD&lt;/code&gt; and the slug as &lt;code&gt;title-slug&lt;/code&gt;. &lt;em&gt;Without&lt;/em&gt;
explicitly specifying any extra front matter in each individual post!
Here’s how:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre tabindex=&quot;0&quot; data-language=&quot;toml&quot; data-theme=&quot;github-light github-dark&quot;&gt;&lt;code data-language=&quot;toml&quot; data-theme=&quot;github-light github-dark&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#6A737D;--shiki-dark:#6A737D&quot;&gt;# config.toml&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E1E4E8&quot;&gt;[&lt;/span&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;frontmatter&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E1E4E8&quot;&gt;	date = [&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt;&quot;:filename&quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt;&quot;:default&quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E1E4E8&quot;&gt;, &lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt;&quot;:fileModTime&quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E1E4E8&quot;&gt;]&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The important piece is the initial &lt;code&gt;&quot;:filename&quot;&lt;/code&gt;. This is what enables
the behavior described above. If it doesn’t work, it falls back on the
subsequent options. &lt;code&gt;&quot;:default&quot;&lt;/code&gt; is a shortcut for the default detection
behavior.&lt;/p&gt;
&lt;p&gt;I’ve also added &lt;code&gt;&quot;:fileModTime&quot;&lt;/code&gt; as the last option which
is exactly what it sounds like. I have it last because in my experience,
while it’s better than nothing, the file system is not quite trustworthy
for determining when you actually last modified a file. Sometimes just
moving between file systems and storage formats, or having some program
open it in write mode without actually making any changes can trigger
it.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;&lt;strong&gt;Source:&lt;/strong&gt; &lt;a href=&quot;https://gohugo.io/getting-started/configuration/#configure-front-matter&quot; class=&quot;external&quot;&gt;Configure Hugo | Hugo&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/em&gt;&lt;/p&gt; ]]></description>
    <pubDate>Thu, 25 Jun 2020 00:31:49 GMT</pubDate>
  </item><item>
    <title>Editing AUR PKGBUILDs</title>
    <link>https://dennislee.xyz/editing-aur-pkgbuilds</link>
    <guid>https://dennislee.xyz/editing-aur-pkgbuilds</guid>
    <description><![CDATA[ &lt;p&gt;I recently installed &lt;a href=&quot;https://binaryoutcast.com/projects/interlink/&quot; class=&quot;external&quot;&gt;Interlink&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; from the &lt;a href=&quot;https://aur.archlinux.org/&quot; class=&quot;external&quot;&gt;AUR&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;. I’ll be writing
about the choice of email client in a future post, but this post is
about how I dealt with the broken &lt;a href=&quot;https://aur.archlinux.org/packages/interlink-bin/&quot; class=&quot;external&quot;&gt;AUR package for Interlink&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; and how
you can deal with broken AUR packages in general.&lt;/p&gt;
&lt;h2 id=&quot;the-problem&quot;&gt;The Problem&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#the-problem&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;First I tried just a simple &lt;code&gt;yay -S interlink-bin&lt;/code&gt;, but that gave me
this:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;curl: (22) The requested URL returned error: 404 Not Found
==&gt; ERROR: Failure while downloading http://repository.binaryoutcast.com/projects/interlink/releases/latest/interlink-52.9.7433.linux-x86_64-gtk3.tar.xz
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Ok, so it tried to download a file that doesn’t exist. It gives us the
path to the file, so I went to &lt;a href=&quot;http://repository.binaryoutcast.com/projects/interlink/releases/latest/&quot; class=&quot;external&quot;&gt;the file’s parent folder&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; to see if I
could figure out what the problem was. It appears that the developer has
released version &lt;em&gt;52.9.7463&lt;/em&gt;, and &lt;strong&gt;removed&lt;/strong&gt; &lt;em&gt;52.9.7433&lt;/em&gt;, the one we
were looking for! I flagged the package as “Out of Date” on the AUR
page.&lt;/p&gt;
&lt;h2 id=&quot;the-solution&quot;&gt;The Solution&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#the-solution&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;I use &lt;em&gt;yay&lt;/em&gt; as an &lt;a href=&quot;https://wiki.archlinux.org/index.php/AUR_helpers&quot; class=&quot;external&quot;&gt;AUR helper&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;. It has an option called &lt;code&gt;--editmenu&lt;/code&gt;,
which gives you the option to edit the &lt;a href=&quot;https://wiki.archlinux.org/index.php/PKGBUILD&quot; class=&quot;external&quot;&gt;PKGBUILD&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; before installing.
Let’s try it:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre tabindex=&quot;0&quot; data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot;&gt;&lt;code data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#6F42C1;--shiki-dark:#B392F0&quot;&gt;yay&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; -S&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt; interlink-bin&lt;/span&gt;&lt;span style=&quot;--shiki-light:#005CC5;--shiki-dark:#79B8FF&quot;&gt; --editmenu&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;hr&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre tabindex=&quot;0&quot; data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot;&gt;&lt;code data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E1E4E8&quot;&gt;pkgver&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt;52.9.7433&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E1E4E8&quot;&gt;source_x86_64&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt;&quot;http://repository.binaryoutcast.com/projects/interlink/releases/latest/interlink-&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E1E4E8&quot;&gt;$pkgver&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt;.linux-x86_64-gtk3.tar.xz&quot;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;OK, so we just have to fix the &lt;code&gt;pkgver&lt;/code&gt; and it’ll grab the right file!&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;==&gt; Validating source_x86_64 files with sha256sums...
    interlink-52.9.7463.linux-x86_64-gtk3.tar.xz ... FAILED
==&gt; ERROR: One or more files did not pass the validity check!
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Oh. OK, how about we just delete the &lt;code&gt;sha256sums&lt;/code&gt; and
&lt;code&gt;sha256sums_x86_64&lt;/code&gt; checksums from the file. That way, it can’t fail
because there’s nothing to check, right?&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;==&gt; ERROR: Integrity checks are missing for: source_x86_64 source
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Oh. So, is there a way to tell it to skip &lt;a href=&quot;https://wiki.archlinux.org/index.php/PKGBUILD#Integrity&quot; class=&quot;external&quot;&gt;integrity checks&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; on the
downloaded file? Turns out, there is.&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot; class=&quot;internal alias&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre tabindex=&quot;0&quot; data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot;&gt;&lt;code data-language=&quot;sh&quot; data-theme=&quot;github-light github-dark&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E1E4E8&quot;&gt;sha256sums&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt;&#039;SKIP&#039;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E1E4E8&quot;&gt;sha256sums_x86_64&lt;/span&gt;&lt;span style=&quot;--shiki-light:#D73A49;--shiki-dark:#F97583&quot;&gt;=&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E1E4E8&quot;&gt;(&lt;/span&gt;&lt;span style=&quot;--shiki-light:#032F62;--shiki-dark:#9ECBFF&quot;&gt;&#039;SKIP&#039;&lt;/span&gt;&lt;span style=&quot;--shiki-light:#24292E;--shiki-dark:#E1E4E8&quot;&gt;)&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;And with that, the package installs!&lt;/p&gt;
&lt;section data-footnotes=&quot;&quot; class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#footnote-label&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-1&quot;&gt;
&lt;p&gt;&lt;a href=&quot;https://invidio.us/watch?v=iUz28vbWgVw&amp;#x26;t=581&quot; class=&quot;external&quot;&gt;Creating Packages For The Arch User Repository (AUR) - DistroTube - Invidious&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; &lt;a href=&quot;#user-content-fnref-1&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref internal alias&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt; ]]></description>
    <pubDate>Mon, 22 Jun 2020 05:23:41 GMT</pubDate>
  </item><item>
    <title>Change Hugo automatic title/slug</title>
    <link>https://dennislee.xyz/change-hugo-automatic-title-and-slug</link>
    <guid>https://dennislee.xyz/change-hugo-automatic-title-and-slug</guid>
    <description><![CDATA[ &lt;p&gt;&lt;strong&gt;Update 2020-05-24:&lt;/strong&gt; This post has been superseded by a newer post.
The newer post can be found &lt;a href=&quot;./hugo-date-and-slug-from-filename&quot; class=&quot;internal alias&quot; data-slug=&quot;hugo-date-and-slug-from-filename&quot;&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;In &lt;a href=&quot;./jekyll-vs-hugo&quot; class=&quot;internal alias&quot; data-slug=&quot;jekyll-vs-hugo&quot;&gt;a previous post&lt;/a&gt; I complained about the format to automatically
generated titles and slugs in Hugo.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Hugo makes me specify title and date manually, even when using the
aforementioned format. And if I want punctuation in my title (like
in this post), I even have to specify the &lt;em&gt;slug&lt;/em&gt; manually, because
otherwise it auto-generates the slug &lt;em&gt;with the punctuation intact&lt;/em&gt;!&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;But what I didn’t know was that you can actually customize this! There
is this optional folder in either your theme’s or your site’s root
folder called &lt;code&gt;/archetypes/&lt;/code&gt; (the latter takes precedence over the
former) where the default &lt;a href=&quot;https://gohugo.io/content-management/front-matter/&quot; class=&quot;external&quot;&gt;front matter&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; is stored. Here’s what my
&lt;code&gt;/archetypes/default.md&lt;/code&gt; looks like now:&lt;/p&gt;
&lt;figure data-rehype-pretty-code-figure=&quot;&quot;&gt;&lt;pre tabindex=&quot;0&quot; data-language=&quot;go-html-template&quot; data-theme=&quot;github-light github-dark&quot;&gt;&lt;code data-language=&quot;go-html-template&quot; data-theme=&quot;github-light github-dark&quot; style=&quot;display: grid;&quot;&gt;&lt;span data-line=&quot;&quot;&gt;&lt;span&gt;---&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span&gt;title: &quot;{{ replaceRE &quot;[[:^alpha:]]&quot; &quot; &quot; .Name | humanize }}&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span&gt;date: {{ .Date }}&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span&gt;slug: &quot;{{ replaceRE &quot;[[:^alpha:]]&quot; &quot;-&quot; .Name | replaceRE &quot;-{2,}&quot; &quot;-&quot; | replaceRE &quot;^-&quot; &quot;&quot; | lower }}&quot;&lt;/span&gt;&lt;/span&gt;
&lt;span data-line=&quot;&quot;&gt;&lt;span&gt;---&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/figure&gt;
&lt;p&gt;The &lt;code&gt;title: &lt;/code&gt;&lt;a href=&quot;https://gohugo.io/templates/introduction/&quot; class=&quot;external&quot;&gt;template&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; (using &lt;a href=&quot;https://github.com/google/re2/wiki/Syntax&quot; class=&quot;external&quot;&gt;regexp&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;) replaces any non-alphabetic
character in the filename with a space, then &lt;a href=&quot;https://en.wikipedia.org/wiki/Vertical_bar#Pipe&quot; class=&quot;external&quot;&gt;pipes&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; the result into
the &lt;a href=&quot;https://gohugo.io/functions/humanize/&quot; class=&quot;external&quot;&gt;humanize&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; function to use sentence case. Hugo seems to trim
extra leading whitespace automatically, so that is not accounted for
here.&lt;/p&gt;
&lt;p&gt;For the slug, every non-alphabetic character is replaced with &lt;code&gt;-&lt;/code&gt;. Then,
sequences of 2 or more &lt;code&gt;-&lt;/code&gt; are replaced with a single &lt;code&gt;-&lt;/code&gt;. Then, a
leading &lt;code&gt;-&lt;/code&gt; is replaced with nothing. Finally, all letters are converted
to lowercase.&lt;/p&gt;
&lt;p&gt;That’s all for now. Don’t worry, the next post will actually be about
something other than Hugo!&lt;/p&gt; ]]></description>
    <pubDate>Sun, 21 Jun 2020 01:52:07 GMT</pubDate>
  </item><item>
    <title>Projects</title>
    <link>https://dennislee.xyz/projects</link>
    <guid>https://dennislee.xyz/projects</guid>
    <description><![CDATA[ &lt;h2 id=&quot;canvas-tuis-installer&quot;&gt;&lt;a href=&quot;https://github.com/GideonWolfe/canvas-tui/&quot; class=&quot;external&quot;&gt;canvas-tui&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;’s installer&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#canvas-tuis-installer&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Improved cross-platform compatibility by conforming to the POSIX
standard.&lt;/li&gt;
&lt;li&gt;Made to respect user preferences by supporting the XDG base directory
specification.&lt;/li&gt;
&lt;li&gt;Corrected some shell syntax to fix corner cases.&lt;/li&gt;
&lt;/ul&gt; ]]></description>
    <pubDate>Sun, 21 Jun 2020 01:52:07 GMT</pubDate>
  </item><item>
    <title>Jekyll to Hugo</title>
    <link>https://dennislee.xyz/jekyll-vs-hugo</link>
    <guid>https://dennislee.xyz/jekyll-vs-hugo</guid>
    <description><![CDATA[ &lt;p&gt;The first version of this site used &lt;a href=&quot;https://jekyllrb.com/&quot; class=&quot;external&quot;&gt;Jekyll&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; as a static site
generator, but now I’m using &lt;a href=&quot;https://gohugo.io/&quot; class=&quot;external&quot;&gt;Hugo&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;.&lt;/p&gt;
&lt;h2 id=&quot;why&quot;&gt;Why?&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#why&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Here are some reasons why I switched to Hugo (and why I like it more
than Jekyll) in no particular order:&lt;/p&gt;
&lt;h3 id=&quot;build-dependencies&quot;&gt;Build Dependencies&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#build-dependencies&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;When using Jekyll, you have to pull in all of
these different packages using &lt;a href=&quot;https://rubygems.org/&quot; class=&quot;external&quot;&gt;RubyGems&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;, a package manager for
&lt;a href=&quot;https://www.ruby-lang.org/&quot; class=&quot;external&quot;&gt;Ruby&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;. Dare I say… &lt;em&gt;bloat&lt;/em&gt;? In contrast, Hugo is just a single
package, with an optional dependency for syntax
highlighting code blocks (in pure HTML&lt;sup&gt;&lt;a href=&quot;#user-content-fn-1&quot; id=&quot;user-content-fnref-1&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot; class=&quot;internal alias&quot;&gt;1&lt;/a&gt;&lt;/sup&gt;)!&lt;/p&gt;
&lt;p&gt;And this isn’t just a speed concern either (although it is, having to
download a bunch of large packages before being able to do &lt;em&gt;literally
anything&lt;/em&gt;). Having so many dependencies very often put me in
&lt;em&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Dependency_hell&quot; class=&quot;external&quot;&gt;dependency hell&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/em&gt; when working with things like templates and
plugins and themes from different sources.  Oh, and speaking of themes:&lt;/p&gt;
&lt;h3 id=&quot;themes&quot;&gt;Themes&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#themes&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The way Hugo handles theming is far saner than the way Jekyll does. In
Jekyll, you use either the default &lt;a href=&quot;https://jekyll.github.io/minima/&quot; class=&quot;external&quot;&gt;minima theme&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; or install a
different one (via RubyGems), and then if you want to customize parts of
the theme, you place modified versions of the relevant files locally in
your site which then take precedence over the default ones. But if
you’re installing the theme in packaged form, where are the files that
you’re basing your edits on?&lt;/p&gt;
&lt;p&gt;In contrast, Hugo themes are always just a subfolder of &lt;code&gt;/themes/&lt;/code&gt;. So
just go there and make your edits with the full context around you.
Without the pointless separation between source and packaged forms, the
separation between user-specific and general data is far easier to
achieve and mantain.&lt;/p&gt;
&lt;h3 id=&quot;speed&quot;&gt;Speed&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#speed&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The build process with Hugo is just faster. Chad compiled
language vs. virgin interpreted language.&lt;/p&gt;
&lt;h3 id=&quot;namingorganization&quot;&gt;Naming/Organization&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#namingorganization&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;The names of all of the important files and
folders in Jekyll all begin with a leading &lt;code&gt;_&lt;/code&gt;, like &lt;code&gt;_config.yml&lt;/code&gt;. I
don’t know how someone ever thought this was a good idea. Maybe
they needed to make them stand out because there’s too much stuff that
goes in the root folder (up to 6 or so files for the package
management alone, in some extreme cases!), plus the favicon and any page
that doesn’t belong in &lt;code&gt;/_posts/&lt;/code&gt;).&lt;/p&gt;
&lt;p&gt;Anyway, Hugo has none of the above problems (all pages go
in &lt;code&gt;/content/&lt;/code&gt;, favicon in &lt;code&gt;/static/&lt;/code&gt;,…).&lt;/p&gt;
&lt;h3 id=&quot;blogdown&quot;&gt;blogdown&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#blogdown&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;I recently found out about this thing called &lt;a href=&quot;https://bookdown.org/yihui/blogdown/&quot; class=&quot;external&quot;&gt;blogdown&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;, which
generates webpages from &lt;a href=&quot;https://rmarkdown.rstudio.com/index.html&quot; class=&quot;external&quot;&gt;R Markdown&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;. It has some support for Jekyll
and &lt;a href=&quot;https://hexo.io/&quot; class=&quot;external&quot;&gt;Hexo&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;, but mostly targets Hugo. I don’t know if I’ll actually use
this, but it’s nice to know I have the option.&lt;/p&gt;
&lt;h3 id=&quot;hugo-actually-has-more-features&quot;&gt;Hugo actually has more features!&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#hugo-actually-has-more-features&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;Hugo has internationalization (i18n) functionality built in. Jekyll
doesn’t. If you’re still going to use Jekyll though, try &lt;a href=&quot;https://www.sylvaindurand.org/making-jekyll-multilingual/&quot; class=&quot;external&quot;&gt;this&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;Hugo actually lets you change the structure of your site beyond just
putting posts in &lt;code&gt;/_posts/&lt;/code&gt; and everything else in &lt;code&gt;/&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Hugo’s local webserver (used when you are testing your site) has
live-reloading built in (via injected JavaScript). So you don’t have
to keep refreshing manually.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id=&quot;why-not&quot;&gt;Why not?&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#why-not&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;But there are, unfortunately, some things I’m missing in Hugo:&lt;/p&gt;
&lt;h3 id=&quot;structureorganization&quot;&gt;Structure/Organization&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#structureorganization&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;With Jekyll, you put a file named like &lt;code&gt;YYYY-MM-DD-slug&lt;/code&gt; into &lt;code&gt;/_posts/&lt;/code&gt;
and it sets the date and title automatically. Hugo makes me specify
title and date manually, even when using the aforementioned format.&lt;sup&gt;&lt;a href=&quot;#user-content-fn-2&quot; id=&quot;user-content-fnref-2&quot; data-footnote-ref=&quot;&quot; aria-describedby=&quot;footnote-label&quot; class=&quot;internal alias&quot;&gt;2&lt;/a&gt;&lt;/sup&gt;
And if I want punctuation in my title (like in this post), I even have
to specify the &lt;em&gt;slug&lt;/em&gt; manually, because otherwise it auto-generates the
slug &lt;em&gt;with the punctuation intact&lt;/em&gt;! At least Hugo has
&lt;a href=&quot;https://gohugo.io/getting-started/quick-start/#step-4-add-some-content&quot; class=&quot;external&quot;&gt;some nice automation functionality for creating new pages&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;, though…
&lt;strong&gt;Update 2020-05-24:&lt;/strong&gt; Actually, this can be fixed completely, see
&lt;a href=&quot;./hugo-date-and-slug-from-filename&quot; class=&quot;internal alias&quot; data-slug=&quot;hugo-date-and-slug-from-filename&quot;&gt;my newer post&lt;/a&gt; for details.&lt;/p&gt;
&lt;h2 id=&quot;jekyll-literally-actually-btfo-forever-with-facts-and-logic&quot;&gt;Jekyll literally actually BTFO forever with FACTS and LOGIC&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#jekyll-literally-actually-btfo-forever-with-facts-and-logic&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;There are a few reasons I decided to use Jekyll at first, but after
using Hugo, I no longer think any of them are good reasons:&lt;/p&gt;
&lt;h3 id=&quot;portability&quot;&gt;Portability&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#portability&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Originally I had this website hosted on &lt;a href=&quot;https://about.gitlab.com/stages-devops-lifecycle/pages/&quot; class=&quot;external&quot;&gt;GitLab Pages&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; (which supports
literally any static site generator), but I figured I might want to
switch to &lt;a href=&quot;https://pages.github.com/&quot; class=&quot;external&quot;&gt;GitHub Pages&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; (which only supports Jekyll) at some point. It
turns out I was right about that, but I was wrong to let it influence my
static site generator decision. You see, there’s this thing called
&lt;a href=&quot;https://www.netlify.com/&quot; class=&quot;external&quot;&gt;Netlify&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;, and you can just give it your website (via &lt;a href=&quot;https://github.com/&quot; class=&quot;external&quot;&gt;GitHub&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;,
&lt;a href=&quot;https://gitlab.com/&quot; class=&quot;external&quot;&gt;GitLab&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;, &lt;a href=&quot;https://bitbucket.org/&quot; class=&quot;external&quot;&gt;Bitbucket&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;, or direct file transfer) and it’ll
automatically rebuild whenever something changes. And yes, it even
supports private repositiories, unlike GitHub Pages! I have more to say
about Netlify and about GitHub vs. GitLab, but that’s better saved for
separate posts.&lt;/p&gt;
&lt;h3 id=&quot;extensibility-plugins&quot;&gt;Extensibility (Plugins)&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#extensibility-plugins&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;It’s true: Jekyll has plugins and Hugo doesn’t. But I haven’t actually
thought of something Hugo can’t do that Jekyll accomplishes with
plugins. As mentioned before, Hugo already has internationalization/i18n
built in. The only Jekyll plugin I ever actually used was
&lt;a href=&quot;https://github.com/vwochnik/jekyll-email-protect&quot; class=&quot;external&quot;&gt;jekyll-email-protect&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;. But in that case, you can just generate the
obfuscated email offline and use that (which is better anyway if you
ever want to make the source repository of your website public, as I
have). &lt;a href=&quot;https://en.wikipedia.org/wiki/Percent-encoding&quot; class=&quot;external&quot;&gt;Percent encoding&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; for the link, &lt;a href=&quot;https://en.wikipedia.org/wiki/List_of_XML_and_HTML_character_entity_references#Character_reference_overview&quot; class=&quot;external&quot;&gt;code points&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt; for the text.&lt;/p&gt;
&lt;h3 id=&quot;flexibility&quot;&gt;Flexibility&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#flexibility&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h3&gt;
&lt;p&gt;Uhh, I put this here when I was writing other parts of the page to
remind myself of something, but now I don’t remember what I was supposed
to write here. Oh well.&lt;/p&gt;
&lt;h2 id=&quot;conclusion&quot;&gt;Conclusion&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#conclusion&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Well, I’ve already spent a lot more time writing this than I expected.
Hopefully I didn’t forget anything. Later I’ll post more about website
building. I’ll tell you about non-garbage static site themes that are
&lt;em&gt;actually good&lt;/em&gt; and don’t require tons of JavaScript for basic
functionality or anything while still looking A E S T H E T I C and
stuff.&lt;/p&gt;
&lt;section data-footnotes=&quot;&quot; class=&quot;footnotes&quot;&gt;&lt;h2 class=&quot;sr-only&quot; id=&quot;footnote-label&quot;&gt;Footnotes&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#footnote-label&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;ol&gt;
&lt;li id=&quot;user-content-fn-1&quot;&gt;
&lt;p&gt;I’ll probably write more in the future about why this is important. &lt;a href=&quot;#user-content-fnref-1&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 1&quot; class=&quot;data-footnote-backref internal alias&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li id=&quot;user-content-fn-2&quot;&gt;
&lt;p&gt;I’m still going to use the format regardless because it makes organization easier in the filesystem (making my site more portable is a bonus). &lt;a href=&quot;#user-content-fnref-2&quot; data-footnote-backref=&quot;&quot; aria-label=&quot;Back to reference 2&quot; class=&quot;data-footnote-backref internal alias&quot;&gt;↩&lt;/a&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;/section&gt; ]]></description>
    <pubDate>Sat, 13 Jun 2020 22:15:33 GMT</pubDate>
  </item><item>
    <title>Dennis Lee</title>
    <link>https://dennislee.xyz/</link>
    <guid>https://dennislee.xyz/</guid>
    <description><![CDATA[ &lt;script type=&quot;module&quot; src=&quot;repos.js&quot;&gt;&lt;/script&gt;
&lt;table&gt;&lt;/table&gt;
&lt;p&gt;Table automatically generated using the GitHub API as the source of truth. &lt;a href=&quot;https://github.com/dennisleexyz/dennislee.xyz/blob/master/content/repos.js&quot; class=&quot;external&quot;&gt;Source&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/p&gt;
&lt;h2 id=&quot;athena-defense&quot;&gt;&lt;a href=&quot;https://github.com/taylornoh/Athena-Defense-App&quot; class=&quot;external&quot;&gt;Athena Defense&lt;svg aria-hidden=&quot;true&quot; class=&quot;external-icon&quot; style=&quot;max-width:0.8em;max-height:0.8em&quot; viewBox=&quot;0 0 512 512&quot;&gt;&lt;path d=&quot;M320 0H288V64h32 82.7L201.4 265.4 178.7 288 224 333.3l22.6-22.6L448 109.3V192v32h64V192 32 0H480 320zM32 32H0V64 480v32H32 456h32V480 352 320H424v32 96H64V96h96 32V32H160 32z&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;a role=&quot;anchor&quot; aria-hidden tabindex=&quot;-1&quot; data-no-popover href=&quot;#athena-defense&quot; class=&quot;internal&quot;&gt;&lt;svg width=&quot;18&quot; height=&quot;18&quot; viewBox=&quot;0 0 24 24&quot; fill=&quot;none&quot; stroke=&quot;currentColor&quot; stroke-width=&quot;2&quot; stroke-linecap=&quot;round&quot; stroke-linejoin=&quot;round&quot;&gt;&lt;path d=&quot;M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71&quot;&gt;&lt;/path&gt;&lt;path d=&quot;M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71&quot;&gt;&lt;/path&gt;&lt;/svg&gt;&lt;/a&gt;&lt;/h2&gt;
&lt;p&gt;Awarded Best Use of Twilio API Project at UC Riverside Rose Hacks.&lt;/p&gt;
&lt;p&gt;Athena Defense is a Android mobile app for women who may find themselves in a
dangerous situation. With just one click of a button, your location will be
sent to emergency contacts or even the police station.&lt;/p&gt;
&lt;p&gt;&lt;img src=&quot;https://github.com/taylornoh/Athena-Defense-App/blob/e424867/Athena_Mockup_Designs.png?raw=true&quot; alt=&quot;&quot;&gt;&lt;/p&gt; ]]></description>
    <pubDate>Sat, 13 Jun 2020 01:37:45 GMT</pubDate>
  </item>
    </channel>
  </rss>