<?xml version="1.0" encoding="UTF-8"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
    <title>weblog.masukomi.org - crystal</title>
    <subtitle>Autistic, ADHD, Geek. The weblog of Kay Rhodes (masukomi).</subtitle>
    <link rel="self" type="application/atom+xml" href="https://weblog.masukomi.org/tags/crystal/atom.xml"/>
    <link rel="alternate" type="text/html" href="https://weblog.masukomi.org"/>
    <generator uri="https://www.getzola.org/">Zola</generator>
    <updated>2022-12-18T00:00:00-05:00</updated>
    <id>https://weblog.masukomi.org/tags/crystal/atom.xml</id>
    <entry xml:lang="en">
        <title>Rewriting Hey</title>
        <published>2022-12-18T00:00:00-05:00</published>
        <updated>2022-12-18T00:00:00-05:00</updated>
        
        <author>
          <name>
            masukomi
          </name>
        </author>
        
        <link rel="alternate" type="text/html" href="https://weblog.masukomi.org/2022/12/18/rewriting-hey/"/>
        <id>https://weblog.masukomi.org/2022/12/18/rewriting-hey/</id>
        
        <content type="html" xml:base="https://weblog.masukomi.org/2022/12/18/rewriting-hey/">&lt;div class=&quot;ox-hugo-toc toc&quot;&gt;
&lt;div class=&quot;heading&quot;&gt;Table of Contents&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://weblog.masukomi.org/2022/12/18/rewriting-hey/#overview&quot;&gt;Overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://weblog.masukomi.org/2022/12/18/rewriting-hey/#in-the-beginning&quot;&gt;In the Beginning&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://weblog.masukomi.org/2022/12/18/rewriting-hey/#final-totals&quot;&gt;Final Totals&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://weblog.masukomi.org/2022/12/18/rewriting-hey/#writing-in-chicken-scheme&quot;&gt;Writing in Chicken Scheme&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://weblog.masukomi.org/2022/12/18/rewriting-hey/#delusions-of-sharability&quot;&gt;Delusions of Sharability&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://weblog.masukomi.org/2022/12/18/rewriting-hey/#crystal-lang&quot;&gt;Crystal Lang&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://weblog.masukomi.org/2022/12/18/rewriting-hey/#final-totals&quot;&gt;Final Totals&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://weblog.masukomi.org/2022/12/18/rewriting-hey/#writing-in-crystal&quot;&gt;Writing in Crystal&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://weblog.masukomi.org/2022/12/18/rewriting-hey/#fast-forward-dot-dot-dot&quot;&gt;Fast-Forward…&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://weblog.masukomi.org/2022/12/18/rewriting-hey/#and-then-raku&quot;&gt;And then Raku&lt;/a&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://weblog.masukomi.org/2022/12/18/rewriting-hey/#final-totals&quot;&gt;Final Totals&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://weblog.masukomi.org/2022/12/18/rewriting-hey/#writing-in-raku&quot;&gt;Writing in Raku&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://weblog.masukomi.org/2022/12/18/rewriting-hey/#reflecting-on-the-rewrites&quot;&gt;Reflecting on the rewrites&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://weblog.masukomi.org/2022/12/18/rewriting-hey/#if-you-liked-that-dot-dot-dot&quot;&gt;If you liked that…&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://weblog.masukomi.org/2022/12/18/rewriting-hey/#p-dot-s-dot-what-about-the-email-app-with-the-same-name&quot;&gt;P.S. What about the email app with the same name?&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;!--endtoc--&gt;
&lt;h2 id=&quot;overview&quot;&gt;Overview&lt;/h2&gt;
&lt;p&gt;“Hey!” started as an Interruption Tracker, and now supports Time Tracking too. It has been through 3 iterations: &lt;a rel=&quot;external&quot; href=&quot;https://call-cc.org/&quot;&gt;Chicken Scheme&lt;/a&gt;, &lt;a rel=&quot;external&quot; href=&quot;https://crystal-lang.org/&quot;&gt;Crystal&lt;/a&gt;, and now &lt;a rel=&quot;external&quot; href=&quot;https://raku.org/&quot;&gt;Raku&lt;/a&gt;. This post is a high-level developer’s diary of what I wrote, why I rewrote it, and what I learned along the way.&lt;/p&gt;
&lt;h2 id=&quot;in-the-beginning&quot;&gt;In the Beginning&lt;/h2&gt;
&lt;p&gt;Once upon a time I was a tech lead, team lead, and eventually principal engineer. My days were &lt;em&gt;filled&lt;/em&gt; with interruptions. They were making it impossible to get anything done, and more importantly to me, they were a source of a lot of stress.&lt;/p&gt;
&lt;p&gt;I decided that if I was going to get a handle on the interruptions I needed to understand them. I needed to know &lt;em&gt;when&lt;/em&gt; they were happening so that I could plan focus time. I needed to know &lt;em&gt;who&lt;/em&gt; was interrupting me so that maybe I could talk to them about it. I needed to know &lt;em&gt;why&lt;/em&gt; I was being interrupted so that I could find things I could document better to preempt those interruptions.&lt;/p&gt;
&lt;p&gt;It started out as a little Chicken Scheme script that grew organically. It quickly became a hard-to-maintain hairball of code.&lt;/p&gt;
&lt;p&gt;But it worked, and it was good.&lt;/p&gt;
&lt;h3 id=&quot;final-totals&quot;&gt;Final Totals&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;~1300 lines of Scheme&lt;/li&gt;
&lt;li&gt;~2500 lines of JavaScript (mostly library stuff) to support some fancy “graph it via the web” stuff that never really worked out well.&lt;/li&gt;
&lt;li&gt;~1000 lines of HTML to hold the JavaScript graphing stuff.&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/masukomi/hey&quot;&gt;GitHub Repo Here&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;writing-in-chicken-scheme&quot;&gt;Writing in Chicken Scheme&lt;/h3&gt;
&lt;p&gt;I love Scheme. It really works for my brain. Chicken Scheme is one of the better schemes. It’s got a large collection of useful libraries. It also transpiles to C (or JavaScript actually). The end result is a fast tiny binary. As a bonus, you can generate C files so that your libraries can be called from almost any other language.&lt;/p&gt;
&lt;p&gt;As an example, my &lt;a rel=&quot;external&quot; href=&quot;https://github.com/masukomi/private_comments&quot;&gt;private_comments&lt;/a&gt; API web server runs in less than 7MB of RAM and I didn’t even &lt;em&gt;try&lt;/em&gt; to make it small.&lt;/p&gt;
&lt;p&gt;Unfortunately figuring anything out in Chicken Scheme felt like pulling teeth. There’s a ton of documentation, but it’s mostly useless. It assumes a ridiculous amount of knowledge and doesn’t explain anything. It feels like “Here’s the method signature. Have fun figuring out what it does.”&lt;/p&gt;
&lt;p&gt;Getting anything done in Chicken Scheme feels like a major accomplishment. It’s also incredibly draining because it’s so damn hard to figure out if you’re new. It’s not the language’s fault. The language is trivially easy, like all Schemes. It’s the documentation.&lt;/p&gt;
&lt;p&gt;These days I use Chicken Scheme very strategically. For example, &lt;a rel=&quot;external&quot; href=&quot;https://github.com/masukomi/heatmapper&quot;&gt;my CLI heatmap generation tool&lt;/a&gt; is written in Chicken Scheme because I wanted something &lt;em&gt;very&lt;/em&gt; fast. I also liked that folks could use the core library in any other language if they felt like dealing with their language’s C interface.&lt;/p&gt;
&lt;h3 id=&quot;delusions-of-sharability&quot;&gt;Delusions of Sharability&lt;/h3&gt;
&lt;p&gt;I should also note that I was working under a mistaken belief. I believed that it would  be possible to generate a binary for an OS that I could just hand to someone without them having to know anything about Chicken Scheme, or Go, or whatever it was written in.&lt;/p&gt;
&lt;p&gt;The truth is, you can’t. It’s theoretically possible. If you could fully statically link a binary, you’d have no worries. Unfortunately it turns out that that, practically speaking, that’s impossible on macOS. They really, &lt;em&gt;really&lt;/em&gt; want you to use dylibs. Excluding apps with a “hello world” level of complexity, I’m not sure you can do it.&lt;/p&gt;
&lt;p&gt;I spent a &lt;em&gt;lot&lt;/em&gt; of time and energy trying to make this happen, but ultimately had to abandon the hope.&lt;/p&gt;
&lt;h2 id=&quot;crystal-lang&quot;&gt;Crystal Lang&lt;/h2&gt;
&lt;p&gt;I’m a Ruby dev by trade, and Crystal is, essentially, just a compiled ruby with Static Typing. Or, it was at the time. These days it’s added concurrency and parallelism and is growing into its own thing.&lt;/p&gt;
&lt;p&gt;I wanted to rewrite it in a nice, organized, maintainable way. At the time Crystal was still pre-1.0 volatile, and didn’t have a ton of users or projects. There were, and I think, still are, multiple ORMs (Object Relational Mappings) competing with no clear winner.&lt;/p&gt;
&lt;p&gt;Unfortunately, they were very immature tools. So, I took one that I thought was good, and added in relations like “has many” and “belongs to”.&lt;/p&gt;
&lt;p&gt;I thought. I planned. I organized. I Object Oriented the 💩 out of it. I wrote and used &lt;a rel=&quot;external&quot; href=&quot;https://github.com/masukomi/sparker&quot;&gt;a sparkline library for Crystal&lt;/a&gt;. I wrote &lt;a rel=&quot;external&quot; href=&quot;https://github.com/masukomi/crystal_cli_graph&quot;&gt;a CLI bar chart library for Crystal&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;I added a CLI bar-chart graph of interruptions by hour so that I could easily see when I was being interrupted.&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;$ hey report interrupts_by_hour&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Interrupts By Hour:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                          ▁&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                          █&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                 ▁     ▁  █&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                 █     █  █&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                                 █     █  █     ▁&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                           ▁     █     █  █  ▁  █&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                           █     █     █  █  █  █&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                           █     █     █  █  █  █&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                           █  ▁  █     █  █  █  █&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                           █  █  █     █  █  █  █&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                           █  █  █     █  █  █  █&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                           █  █  █     █  █  █  █&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;                           █  █  █     █  █  █  █&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;▁  ▁  ▁  ▁  ▁  ▁  ▁  ▁  ▁  █  █  █  ▁  █  █  █  █  ▁  ▁  ▁&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;00 01 02 03 04 05 07 07 08 09 10 11 12 13 14 15 16 17 18 23&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Honestly? It was pretty damn good.&lt;/p&gt;
&lt;p&gt;But then, my life changed. I was completely burnt out from the constant interruptions. I was having random Panic Attacks over trivial things. My wife was burnt out too. We quit our jobs, cashed in the 401k and lived off of savings for the better part of a year. It set back our retirement, but gave us enough time to &lt;em&gt;begin&lt;/em&gt; recovering.&lt;/p&gt;
&lt;p&gt;I didn’t need Hey! anymore, so I wandered off.&lt;/p&gt;
&lt;h3 id=&quot;final-totals&quot;&gt;Final Totals&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;~1600 lines of Crystal in the core tool (including tests)&lt;/li&gt;
&lt;li&gt;~300 for the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/masukomi/crystal_cli_graph&quot;&gt;bar chart lib&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;~50 for the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/masukomi/sparker&quot;&gt;sparkline lib&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;~400 for the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/masukomi/crystal_fmt&quot;&gt;cli table generator&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;~150 lines for the &lt;a rel=&quot;external&quot; href=&quot;https://github.com/masukomi/sentence_options&quot;&gt;custom arguments parser&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;~300 lines of additions to the DB library (mostly macros)&lt;/li&gt;
&lt;li&gt;Total ~2800 lines of Crystal&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/masukomi/hey_2&quot;&gt;GitHub Repo Here&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;writing-in-crystal&quot;&gt;Writing in Crystal&lt;/h3&gt;
&lt;p&gt;Crystal’s a great language. I have nothing bad to say about it. I happily supported them on &lt;a rel=&quot;external&quot; href=&quot;https://opencollective.com/crystal-lang&quot;&gt;Open Collective&lt;/a&gt; for a long time. If you want to see what I think is a pretty well designed Crystal app, go look at &lt;a rel=&quot;external&quot; href=&quot;https://github.com/masukomi/oho&quot;&gt;oho&lt;/a&gt;. It’s the world’s greatest tool for converting colored terminal output to beautiful HTML. I’m pretty proud of it.&lt;/p&gt;
&lt;p&gt;These days though, Crystal isn’t my happy-place. I’ve spent too many years in Ruby. I want something different for my personal coding.&lt;/p&gt;
&lt;h2 id=&quot;fast-forward-dot-dot-dot&quot;&gt;Fast-Forward…&lt;/h2&gt;
&lt;p&gt;Fast-forward from 2016 to December 2022. I’m unemployed again, like so many of us (&lt;a rel=&quot;external&quot; href=&quot;https://masukomi.org/resume/kay_rhodes_resume.html&quot;&gt;Hire Me!&lt;/a&gt;), and while I’m actually getting &lt;em&gt;a lot&lt;/em&gt; done, I don’t &lt;em&gt;feel&lt;/em&gt; like I am. I’m being too hard on myself, and not giving myself the credit I deserve for accomplishing the things I have. I decide to start time tracking. I figured if I could look back and see how I actually spent the day I could have a better feeling for what &lt;em&gt;really&lt;/em&gt; happened. “I didn’t get anything done today on my work, but that’s because I spent a ton of time on all these other things that needed doing.”&lt;/p&gt;
&lt;p&gt;It turns out, I was right. In addition, the act of tracking my time makes me think about how I’m spending it, &lt;em&gt;as&lt;/em&gt; I’m spending it.&lt;/p&gt;
&lt;p&gt;I didn’t want to write a new time tracker. I just wanted to track my time. I knew there were multiple, good, off-the-shelf CLI time trackers.&lt;/p&gt;
&lt;p&gt;I tried using 3 of them, but they all frustrated me for one reason or another. Some tools wanted me to interface with it in a way that felt awkward or annoying. Some had annoying technical things.&lt;/p&gt;
&lt;p&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/TailorDev/Watson&quot;&gt;Watson&lt;/a&gt; came very close, but every time i needed to backdate a timer i had to type in explicit 4 digit 24 hour time. E.g. 08:30 not 8:30 and 18:47 not 6:47. It’s a little thing but I was doing it at least ten times a day and it annoyed me every time. Also, the ability to edit a timer was just broken.&lt;/p&gt;
&lt;p&gt;Then I realized… I already &lt;em&gt;have&lt;/em&gt; a time tracker that works with my 🧠. It just doesn’t support &lt;em&gt;end&lt;/em&gt; times.&lt;/p&gt;
&lt;p&gt;I checkout the Crystal repo. I compile. It goes 💥. It goes 💥 here. It goes 💥 there. It goes 💥 everywhere. The language has changed in notable ways which break my code, and break the code in libraries I was depending on.&lt;/p&gt;
&lt;p&gt;In Crystal’s defense, it was 0.33.0 when I ported Hey! to it and they were very clear about the fact that things would be changing before they hit 1.0.&lt;/p&gt;
&lt;p&gt;The compiler was very helpful in telling me what changes to make. Eventually though, I hit a case where it was complaining that I wasn’t implementing a method defined in an abstract class, and I &lt;em&gt;definitely&lt;/em&gt; was. At that point I gave up. I just don’t have the emotional spoons to go fixing problems I didn’t create in a side-project that I didn’t even want to write in the first place. I don’t particularly want to be writing in Crystal these days anyway.&lt;/p&gt;
&lt;p&gt;Maybe the Chicken Scheme version?&lt;/p&gt;
&lt;p&gt;Chicken Scheme has moved from v4 to v5 in the intervening years, but Chicken’s upgrade is relatively painless. I’ve already done it for a couple of projects. It’s mostly just a matter of changing some import statements.&lt;/p&gt;
&lt;p&gt;20 minutes later and I’ve got a working version of Hey! It’s a worse codebase, &lt;em&gt;but it complies!&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Hack. Hack. Hack.
Bug. Bug. Bug. I’m fighting with Chicken Scheme again.&lt;/p&gt;
&lt;p&gt;“Arrgh! I do not need this. This isn’t even a good codebase to begin with.”&lt;/p&gt;
&lt;p&gt;So, I step back. I ask myself what the &lt;em&gt;bare minimum&lt;/em&gt; feature set would be that would be good enough to use and not annoy me:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;the ability to start and stop a timer&lt;/li&gt;
&lt;li&gt;the ability to tag a timer&lt;/li&gt;
&lt;li&gt;the ability to backdate a timer because I frequently forget to start or stop them.&lt;/li&gt;
&lt;li&gt;no !@#$ 24hr time.&lt;/li&gt;
&lt;li&gt;a log of time spent.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That’s not actually that much…&lt;/p&gt;
&lt;h2 id=&quot;and-then-raku&quot;&gt;And then Raku&lt;/h2&gt;
&lt;p&gt;I create a new directory and start hacking. I’m still new to Raku, but overall I’m loving it.&lt;/p&gt;
&lt;p&gt;I started by writing about ~250 lines of ugly-ass no-apologies code. I had one goal: get it working in the shortest possible time. 250 lines gets me a DB layer and the ability to start and stop timers (no backdating).&lt;/p&gt;
&lt;p&gt;I try to run it. It goes 💥, but that’s to be expected. I have no tests &amp;amp; I’ve literally never compiled it. To my great surprise, the bugs are all little things like missing commas or semicolons. There’s &lt;em&gt;nothing&lt;/em&gt; notable.&lt;/p&gt;
&lt;p&gt;This is &lt;em&gt;huge&lt;/em&gt;. If a Raku newb like me can write ~250 lines of code and not have any notable bugs, it means they have done a damn good job of putting together a language.&lt;/p&gt;
&lt;p&gt;I’m chuffed. I keep hacking. Along the way, I’m noticing that lots of little nice-to-have’s are trivial to add while I’m there.&lt;/p&gt;
&lt;p&gt;I don’t bother with an ORM. I don’t bother with &lt;em&gt;any&lt;/em&gt; OOP (Object Oriented Programming). It’s just a collection of functions that query a SQLite DB with raw SQL and pass the resulting hashes around.&lt;/p&gt;
&lt;p&gt;The ecosystem of libraries gets me nice things like time durations as strings “2 hours and 33 minutes” or “2h33m”, and pretty tables. The pretty tables are &lt;a rel=&quot;external&quot; href=&quot;https://github.com/masukomi/Prettier-Table/&quot;&gt;my fork of another library&lt;/a&gt;, but I’m not including that in the totals because I didn’t write it for this project.&lt;/p&gt;
&lt;p&gt;I still don’t have the command line graphs implemented, and it looks like I’ll have to port that from Crystal. There isn’t a Sparkline library yet either, so add another ~300 lines of code before I’m done.&lt;/p&gt;
&lt;h3 id=&quot;final-totals&quot;&gt;Final Totals&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;~800 lines of Raku&lt;/li&gt;
&lt;li&gt;~100 lines of &lt;a rel=&quot;external&quot; href=&quot;https://github.com/pgrange/bash_unit&quot;&gt;bash_unit&lt;/a&gt; tests&lt;/li&gt;
&lt;li&gt;~300 lines of &lt;em&gt;future&lt;/em&gt; code&lt;/li&gt;
&lt;li&gt;Silly levels of satisfaction&lt;/li&gt;
&lt;li&gt;&lt;a rel=&quot;external&quot; href=&quot;https://github.com/masukomi/hey_3&quot;&gt;GitHub Repo Here&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id=&quot;writing-in-raku&quot;&gt;Writing in Raku&lt;/h3&gt;
&lt;p&gt;Notable things: I wrote precisely zero lines of code to process the command line arguments in a natural language fashion. I wrote zero lines of code to generate or wire up the CLI help doc shown below. Raku gave it to me “out of the box”.&lt;/p&gt;
&lt;p&gt;It took me about 5 lines to include a starter db with the package, check if you need it, and put it in place. That’s a combination of the language having a concept of resources in a bundle, &lt;a rel=&quot;external&quot; href=&quot;https://github.com/jonathanstowe/XDG-BaseDirectory&quot;&gt;a library that understands XDG Base Directory stuff&lt;/a&gt;, and &lt;a rel=&quot;external&quot; href=&quot;https://github.com/masukomi/XDG-GuaranteedResources&quot;&gt;my XDG::GuaranteeResources&lt;/a&gt; library that combines the two.&lt;/p&gt;
&lt;p&gt;Raku’s still got a very small community, but they are “knocking it out of the park” with useful libraries. And the language has been &lt;a rel=&quot;external&quot; href=&quot;https://raku.org/archive/doc/apocalypse.html&quot;&gt;incredibly well thought out&lt;/a&gt;. I have complaints, but they’re all nitpicks.&lt;/p&gt;
&lt;p&gt;Maybe it’s just that I started my professional programming career with Perl5. Whatever the reason Raku really works for my 🧠.&lt;/p&gt;
&lt;pre class=&quot;giallo z-l-code z-d-code&quot; &gt;&lt;code data-lang=&quot;plain&quot;&gt;&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;Usage:&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  hey start [&amp;lt;start_args&amp;gt; ...] -- Start a new timer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  hey stop [&amp;lt;stop_args&amp;gt; ...] -- stop an existing timer&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  hey log &amp;lt;number&amp;gt; &amp;lt;duration&amp;gt; -- see a log of recent timers&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  hey log-interrupts &amp;lt;number&amp;gt; &amp;lt;duration&amp;gt; -- see a log of recent interruptions&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  hey running -- lets you know if there are any timers running &amp;amp; what they are for&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  hey &amp;lt;name&amp;gt; [&amp;lt;start_args&amp;gt; ...] -- Record an interruption&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  hey kill timer &amp;lt;id&amp;gt; -- Remove an unwanted timer.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;  hey kill &amp;lt;name&amp;gt; -- Remove an unwanted person / thing from interruptions&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    [&amp;lt;start_args&amp;gt; ...]    optional time adjustment, project(s), &amp;amp; optional tags&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    [&amp;lt;stop_args&amp;gt; ...]     optional id, and optional time adjustments (e.g. 4 minutes ago)&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;number&amp;gt;              number of duration units&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;duration&amp;gt;            duration string. E.g. minutes, hours, days, etc.&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;name&amp;gt;                name of person / thing that interrupted you&lt;/span&gt;&lt;/span&gt;
&lt;span class=&quot;giallo-l&quot;&gt;&lt;span&gt;    &amp;lt;id&amp;gt;                  the id of the timer to delete.&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&quot;reflecting-on-the-rewrites&quot;&gt;Reflecting on the rewrites&lt;/h2&gt;
&lt;p&gt;Looking back at all this work. I find myself coming to an interesting conclusion. With regards to code written specifically for you:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;I believe that choosing subjectively good technology is more important than objectively good technology.&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;You have limited time to work on projects &lt;em&gt;for you&lt;/em&gt;. Don’t spend them in languages you don’t love. Write them with tools, and languages you &lt;em&gt;do&lt;/em&gt; love. Write them with tools that are exciting you. Rewrite them when you’ve moved on and you want to use them, but the idea of maintaining the old stuff is just draining.&lt;/p&gt;
&lt;p&gt;99% of the tools you write for you will never be looked at by anyone else. Even less of it will be &lt;em&gt;used&lt;/em&gt; by someone else. Don’t worry about what’s “good”. Do what makes &lt;em&gt;you&lt;/em&gt; feel good.&lt;/p&gt;
&lt;p&gt;Chicken Scheme made me feel good. Sometimes it still does. Crystal allowed my to do good things quickly, but it was never Joyful to me. I’m long past the days of Rubyish syntax being Joyful. I like it. It’s good, but I’ve written many many thousands of lines of it and the wonder and joy of it has worn off.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;[UPDATE] Since writing this I’ve thought a lot about the choices we make when coding specifically for ourselves vs coding for others. The result is the &lt;a rel=&quot;external&quot; href=&quot;https://weblog.masukomi.org/2023/02/10/duct-tape-baling-wire-methodology/&quot;&gt;Duct Tape &amp;amp; Baling Wire Methedology&lt;/a&gt;.&lt;/p&gt;
&lt;hr /&gt;
&lt;p&gt;Was it worth rewriting all those times?&lt;/p&gt;
&lt;p&gt;100%&lt;/p&gt;
&lt;p&gt;The first rewrite (Crystal) was in a language I was enjoying, but more importantly it was desperately needed. The original codebase was spaghetti. It had grown without planning, as so many tiny-but-useful tools do.&lt;/p&gt;
&lt;p&gt;The second rewrite (Raku) was because I didn’t have the emotional spoons to deal. Fixing problems someone else created, in a tool i didn’t want to be writing, in a language I didn’t want to use… ugh. I didn’t need that.&lt;/p&gt;
&lt;p&gt;However, this rewrite also ended up reinforcing my thoughts about how awesome Raku is, and teaching me some new tricks.&lt;/p&gt;
&lt;h2 id=&quot;if-you-liked-that-dot-dot-dot&quot;&gt;If you liked that…&lt;/h2&gt;
&lt;p&gt;If you found that interesting, you’re probably the kind of geek who writes a bunch of useful command line tools. If so, you should check out &lt;a rel=&quot;external&quot; href=&quot;https://tooloo.dev&quot;&gt;TooLoo&lt;/a&gt;. That’s my Open Source tool that helps you document your tools. Find them later. Use them more.&lt;/p&gt;
&lt;h2 id=&quot;p-dot-s-dot-what-about-the-email-app-with-the-same-name&quot;&gt;P.S. What about the email app with the same name?&lt;/h2&gt;
&lt;p&gt;Hey! was created before the email service. I figure this project is never going to become popular enough that I’ll have to worry about brand confusion. ;)&lt;/p&gt;
</content>
        
    </entry>
</feed>
