RSSAmplifier

Blog

pbrisbin dot com

Recent content on pbrisbin dot com

pbrisbin.comRSS feed ↗108 posts

Latest posts

Stow

I recently migrated my dotfiles from rcm to GNU Stow . I didn’t
really have a reason, I wasn’t unhappy with rcm at all, but I saw Stow mentioned
somewhere and felt like trying it out. After migrating, I still don’t have
strong feelings – both tools are appropriately good and boring – but I can at
least now speak to the differences and maybe that would…

URI Encoding

I had to URI-encode the components of a URL in node the other day. You’d think
this would be trivial, particularly in the language of the browser. Turns out,
not so much. I ended up deep-diving the relevant RFCs, so I thought I’d
summarize here to save you (well, future me) the effort. 
 Let’s get into it. 
 The URL in Question 🔗 Given…

Codeberg

GitHub’s enshittification has gotten entirely out of hand. Not only are they so
obviously and unethically exfiltrating all of my code into their
drain-lake-give-wrong-answer box, but they’re simultaneously forcing the
business they’ve illegally built on it down my throat in every part of the UI
that still functions, which is becoming fewer and fewer these days.…

Setup Actions Don't Scale

I see a lot of this-setup or setup-that GitHub actions around. They all wrap
the @actions/tool-cache library to install some pre-compiled binary. If
 tool-cache exists, why do we need all these separate actions? What happens if
I can’t find a -setup action for the tool I want to use? What if there are
multiple? Do I need to write yet-another curl | tar or gh release download…

Endo Configo

Semigroups are, quite possibly, my favorite part of Haskell. I’m constantly
surprised how much business logic can be expressed by a single foldMap using
the correct Semigroup. My co-worker Evan has said as much , and
better. 
 One perhaps unfamiliar Semigroup is Endo . Don’t let the heady name confuse you
too much, it’s a newtype over (a -> a) , any…

Haskell Coverage Reports

Test coverage is a tricky topic. I’m of the opinion that 100% test coverage is
not a useful goal. Some take this opinion and discard the idea of tracking
coverage altogether. However, there are interesting things you can do with test
coverage information in the context of a Pull Request, such as asking if the
lines introduced in the Pull Request are covered by tests, or if…

Reader for Free

This may be obvious or well-known to some, but I discovered the other day that
you can make a MonadReader env instance for any MonadState env m trivially.
This makes total sense conceptually, since State is just Reader with the extra
ability to modify. 
 I’m going to talk it through at length, how it works and why I needed it, but if
you’re just interested in…

Phantom Types and Globbing Bugs

I love concrete examples that illustrate the day-to-day of the professional
Haskell programmer, and show the inspiration for that entirely-untrue quip, “if
it compiles, it works”. What is true is some variation of “if it compiles, any
logic encoded in the types is correct”. That statement is a tautology (if a
program type checks, it means the types are…

An Opinionated Guide to Options Parsing in Shell

Some may say that you shouldn’t write shell beyond a certain, very low bar of
complexity. If you reach for arrays, certainly associative arrays (gasp!), or
if your script approaches 20, 50, or 100 (how dare you!) lines, maybe you want a
“real” language. 
 Everyone’s bar is different, but I’d wager actual options parsing is above it
for most. I…

Caching Docker Layers on CI

For as long as I’ve built Docker images on CI, I’ve fought the layer caching
problem. Working on Haskell projects of many dependencies, an un-cached
multi-stage build can take close to an hour. That’s a deal-breaker for
deployments, where ten minutes is a reasonable maximum. 
 At some point, Circle quietly released a docker_layer_caching flag in their
…

GoogleEmail2 Deprecation

I maintain an Auth plugin for authenticating with Google OAuth2
in a Yesod application. This plugin has always had functionality overlap with
the GoogleEmail2 plugin in the yesod-auth package. Our
Google plugin was present, removed (due to said overlap), then returned again,
along with some discussion about deprecating GoogleEmail2 in
favor of it. What was missing was the…

Haskell Project Checklist

The following are all the things I want in place for a Haskell project. This is
primarily a copy-paste-able reference for myself, but I’ve also tried to explain
or generalize some things to make it useful for anyone first bootstrapping a
Haskell project. 
 NOTE : if you were brought here after googling something like “how to Haskell
on Circle 2.0”,…

Selecting URLs via Keyboard in XTerm

In a recent effort to keep my latest laptop more standard and less customized,
I’ve been experimenting with XTerm over my usual choice of rxvt-unicode. XTerm
is installed with the xorg group, expected by the template ~/.xinitrc , and
is the terminal opened by most window managers’ default keybindings. 
 The only downside so far has been the inability to select and open…

Deleting Git Tags with Style

Deleting Git tags that have already been pushed to your remote is something I
have to google literally every time I do it; why the invocation is so arcane, I
don’t know. Finally, I decided to automate it with a custom sub-command: 
 ~/.local/bin/git-delete-tag 
 #!/bin/sh
 for tag ; do 
 git tag -d ' $tag ' 
 git push origin :refs/tags/ ' $tag ' 
 done 
…

tee-io Lessons Learned

A while back, I launched a side project called tee-io . It’s sort of like a
live pastebin. You use its API to create a command and then send it
buffered output , usually a line at a time. Creating the command gives you a
URL where you can watch the output come in in real time. We use it at work to
monitor the commands run by our bot instead of waiting for the…

Regular Expression Evaluation via Finite Automata

While reading Understanding Computation again last night, I was going back
through the chapter where Tom Stuart describes deterministic and
non-deterministic finite automata. These simple state machines seem like little
more than a teaching tool, but he eventually uses them as the implementation for
a regular expression matcher. I thought seeing this concrete use for such…

Applicative Functors

Every time I read Learn You a Haskell , I get something new out of it.
This most recent time through, I think I’ve finally gained some insight into the
 Applicative type class. 
 I’ve been writing Haskell for some time and have developed an intuition and
explanation for Monad . This is probably because monads are so prevalent in
Haskell code that you can’t…

Writing JSON APIs with Yesod

Lately at work, I’ve been fortunate enough to work on a JSON API which I
was given the freedom to write in Yesod . I was a bit hesitant at
first since my only Yesod experience has been richer html-based sites
and I wasn’t sure what support (if any) there was for strictly JSON
APIs. Rails has a number of conveniences for writing concise controllers
and standing up…

Random Numbers without Mutation

In lecture 5A of Structure & Interpretation of Computer Programs,
Gerald Sussman introduces the idea of assignments, side effects and
state. Before that, they had been working entirely in purely functional
Lisp which could be completely evaluated and reasoned about using the
substitution model. He states repeatedly that this is a horrible thing
as it requires a far more complex…

Automated Unit Testing in Haskell

Hspec is a BDD library for writing Rspec-style tests in Haskell.
In this post, I’m going to describe setting up a Haskell project using
this test framework. What we’ll end up with is a series of tests which
can be run individually (at the module level), or all together (as part
of packaging). Then I’ll briefly mention Guard (a Ruby tool) and how
we can use…

Using Notify-OSD for XMonad Notifications

In my continuing efforts to strip my computing experience of any
non-essential parts, I’ve decided to ditch my statusbars. My desktop is
now solely a grid of tiled terminals (and a browser). It’s quite nice.
The only thing I slightly missed, however, was notifications when one
of my windows set Urgency. This used to trigger a bright yellow color
for that workspace…

On Staticness

For almost 7 years, now I’ve had a desktop at home, running, serving
(among many things) my personal blog. Doing so is how I learned much of
what I now know about programming and system administration. It gave me
a reason to learn HTML, then PHP, then finally Haskell. It taught me
Postgres, Apache, then lighttpd, then nginx. Without maintaining this
site myself, on my own…

Mocking Bash

Have you ever wanted to mock a program on your system so you could write
fast and reliable tests around a shell script which calls it? Yeah, I
didn’t think so. 
 Well I did, so here’s how I did it. 
 Cram 🔗 Verification testing of shell scripts is surprisingly easy. Thanks to
Unix, most shell scripts have limited interfaces with their environment.
Assertions…

Email Encryption

The recent hullabaloo with Snowden and the NSA is very scary. I agree
with most Americans that The Government is doing some pretty evil things
these days. That said, I also believe that we as cloud users are
primarily responsible for the privacy of our own data. Thankfully, the
problem of transmitting or storing data via a 3rd party without granting
that party access to said…

The Advent of IO

What if we wanted to write a Haskell program to behave something like&#xA;this: &#xA; $ runhaskell hello.hs&#xA;Hello who?&#xA;&#xA;$ runhaskell hello.hs Pat&#xA;Hello Pat&#xA;&#xA;$ runhaskell hello.hs -u Pat&#xA;Hello PAT&#xA; One implementation may look like this: &#xA; main :: IO () &#xA; main = do &#xA; args <- getArgs&#xA; &#xA; let name = case args of &#xA; ( '-u' : n : _ ) -> map toUpper…

Cloud Music: A Comparison

For the longest time, my interaction with music was via MPD. I had a&#xA;substantial collection playing on my always-on desktop. I could connect&#xA;from anywhere to control the playlist and pick up the stream via its&#xA;HTTP output. I had effectively built my own cloud music service. &#xA; While that was great, there were a few annoyances: &#xA; First, I had to juggle two interfaces while…

Parsing DATABASE_URL

A while back, I made a post about deploying yesod apps to heroku.&#xA;The method used back then is no longer required (thank God!) and&#xA;deploying to heroku is super simple these days. So simple, in fact, that&#xA;I won&rsquo;t reiterate those instructions here, this post is about something&#xA;a bit more specific. &#xA; Chances are, your app is using a database. And you probably don&rsquo;t…

For the Library Authors

Recently, Yesod released version 1.2. You can read the announcement&#xA; here , the changelog here , and a detailed&#xA;blog post about the subsite rewrite here . These resources do&#xA;a great job of getting users&rsquo; apps up on 1.2. This post won&rsquo;t rehash&#xA;those, it is instead intended for those of you (like myself) who&#xA;maintain libraries dependent on Yesod. &#xA; The large…

Faster Mail

I hear and see a lot of passing complaints about dealing with a large&#xA;amount of mail. I myself subscribe to a few mailing lists which get&#xA;quite a bit of traffic and these are usually the first to be ignored&#xA;when I get behind. Once a backlog of unread mail piles up it can be hard&#xA;to get any traction. The sad part is I enjoy that content, so I&#xA;definitely don&rsquo;t want to be…

Disable All The Caps

If you&rsquo;re like me and absolutely abhor the Caps Lock key, you&rsquo;ve&#xA;probably figured out some way to replace it with a more suitable&#xA;function. I myself have settled on the following command to make it a&#xA;duplicate Ctrl key: &#xA; $ setxkbmap -option ctrl:nocaps&#xA; This works great when placed in ~/.xinitrc and run as X starts, but&#xA;what about USB keyboards which are…

Aurget v4

Aurget was one of the first programs I ever wrote. It&rsquo;s seen decent&#xA;adoption as far as AUR helpers go and it&rsquo;s gradually increased its&#xA;feature set over the past number of years. &#xA; The codebase had gotten a bit krufty and hard to follow. I decided to&#xA;refactor to more isolated functions which didn&rsquo;t rely on so many global&#xA;variables. This directed refactor has…

Chromebook

I&rsquo;ve heard rumors that a Google Chromebook can make a surprisingly&#xA;sweet machine for a developer. As someone that works exclusively in the&#xA;console, it&rsquo;s easy enough to SSH into a server to do the actual work.&#xA;Since my apps are either command line tools or web sites, I can easily&#xA;test them remotely as well. I only need something with a terminal and&#xA;browser&hellip;…

Chruby

Once I start my new job at thoughtbot , I&rsquo;ll be working on a variety&#xA;of ruby and rails projects at the same time. This, combined with the&#xA;current 2.0 transition, means I once again need a ruby version&#xA;management tool. &#xA; Chruby is the third (by my count) &ldquo;new hotness&rdquo; when it comes to&#xA;these python-inspired virtualenv clones. First there was rvm which&#xA;has a…

Hard Mode

Recently, while watching Corey Haines and Aaron Patterson&#xA; pair-program , I heard Mr. Haines mention vim&rsquo;s &ldquo;hard mode&rdquo;.&#xA;Apparently, this is when you disable the motion commands h, j, k, and l. &#xA; It&rsquo;s absurd how great this exercise is for increasing your knowledge of&#xA;vim. There are so many better ways to do everything . Just like&#xA;complete novices might…

Testing POROs In Rails

A lot of smarter people than I have come up with the idea that moving&#xA;your business logic out of framework based classes and into Plain Old&#xA;Ruby Objects (POROs) is a Good Thing. &#xA; Being less tied to your framework makes upgrades easier. It also means&#xA;you can test these objects without loading rails. That&rsquo;s really the only&#xA;way to get super fast unit tests. It&rsquo;s also…

Systemd-User

&#xA; BIG FAT WARNING &#xA; One thing to note, and the reason why I&rsquo;m no longer using this setup:&#xA;screen sessions started from within X cannot survive X restarts. If you&#xA;don&rsquo;t know what that means, don&rsquo;t worry about it; if you do, you&rsquo;ve been&#xA;warned. &#xA;&#xA; &#xA;&#xA; A while back, Arch switched to systemd for its init system. It&rsquo;s&#xA;pretty enjoyable…

Git-SVN

If you work on a project that&rsquo;s been around for a while, chances are it&#xA;might still be using SVN for version control. Even if you can&rsquo;t get&#xA;buy-in from Management or Ops to move to Git, you can still get most of&#xA;the benefits by learning the ins and outs of the git svn sub command. &#xA; Initial Clone 🔗 $ git svn clone --stdlayout svn://svn.example.com/project&#xA; Using…

Easy Change

&#xA; for each desired change, make the change easy (warning: this may be&#xA;hard), then make the easy change &#xA; — Kent Beck, September 25, 2012 &#xA; Here&rsquo;s some code from our main application helper. It provides a small&#xA;method for redirecting the user based on a goto parameter. It uses two&#xA;helpers itself to append google analytics parameters to the url before&#xA;redirecting.…

Dvd2iso

My latest bash-to-ruby rewrite was dvdcopy to dvd2iso. I changed the&#xA;name both to disambiguate, and because my primary use case was no longer&#xA;to duplicate disc to disc, but to just generate the ISO. It&rsquo;s very&#xA;simple to just burn that ISO back to disc if I feel like it. &#xA; The benefits of the new script are: &#xA; &#xA; Less and simpler code &#xA; Coded at a higher level &#xA;…

Developing Web Applications with Yesod

&#xA;The following was written for [issue 7][issue] of Web & PHP magazine.&#xA;Please, if you enjoy this article (or my articles in general), take the&#xA;two minutes to register there and download the full PDF to show your&#xA;support.&#xA; &#xA;&#xA; Why Haskell? 🔗 There&rsquo;s much more to Haskell than just the buzz-words like laziness and&#xA;parallelism &ndash; which are completely…

Extension by Module

Ruby&rsquo;s open classes are great for adding behavior to existing objects.&#xA;Though it&rsquo;s a language feature, there to be used, I&rsquo;d argue that the&#xA;majority of times it is used, Open classes weren&rsquo;t the most appropriate&#xA;tool. &#xA; First of all, you may be setting yourself (and other developers) up for&#xA;confusion. Not knowing where methods come from or why a method…

Fake S3

Fake S3 is a gem designed to run a small server on localhost that&#xA;will correctly handle AWS/S3 GETs and PUTs (among others) while using&#xA;the local filesystem as the storage backend. This has a number of&#xA;benefits for anyone working on an application with AWS integration. &#xA; Probably the biggest benefit is offline development. There&rsquo;s also a&#xA;lower configuration burden as…

Deploying Yesod Apps On Heroku

&#xA; Update This post describes compiling a Yesod application locally&#xA;using a VM to achieve the compilation on a Heroku-like machine, then&#xA;pushing the binary up to Heroku to be run. This is an annoying route&#xA;which is no longer necessary (as mentioned in the comments), so don&rsquo;t&#xA;follow it. Instead follow [this][] guide.&#xA; &#xA;&#xA; The following are the steps I followed to…

Sharpening Your Tools

Regardless of what editor you choose or how deeply you decide to extend&#xA;or configure it, the most important thing for a professional programmer&#xA;regarding her tool set is awareness. &#xA; You need to be acutely aware of situations where you do something&#xA;repeatedly or slowly that you should automate or speed up. Quality&#xA;editors like vim or emacs expose powerful constructs for doing…

Be Assertive with Sane Exception Handling

I&rsquo;m a big fan of Avdi Grimm&rsquo;s thoughts about writing confident ruby. I&#xA;think it&rsquo;s important to not clutter things with a bunch of nil-checks or&#xA;exception handling. When you&rsquo;re focused in at the method level you&#xA;should trust that your objects are valid and the methods you&rsquo;re calling&#xA;behave. &#xA; &#xA; In this post I use the term &ldquo;assertive&rdquo;…

Raury

tl;dr: it&rsquo;s just like aurget but more stable and faster &#xA; Developing aurget was getting cumbersome. Whenever something went wrong,&#xA;it was very difficult to track down or figure out. The lack of standard&#xA;tools for things like uri escaping or json parsing was getting a bit&#xA;annoying, and the structure of the code just annoyed me. There was also&#xA;a lack of confidence when…

Vagrant

Despite the enormous increase in popularity lately, it seems some people&#xA;still don&rsquo;t know about this project or how it can improve your&#xA;development work-flow. &#xA; So, what is it and why should you care? &#xA; Vagrant is a convenience tool for doing Virtual Machine based&#xA;development. The obvious benefits that you get by using VMs for&#xA;development are: &#xA; &#xA; Isolation -…

Console TDD with String IO

If you write console based applications in ruby, chances are you&rsquo;re&#xA;going to want to get some test coverage on that eventually. StringIO &#xA;is a great class to use when you want to assert that your application&#xA;outputs the correct stuff to the screen. &#xA; We can modify the global variable $stdout to be an instance of&#xA; StringIO for the duration of our tests. Any method that…

Yesod Deployments with Keter

Keter is Michael Snoyman&rsquo;s answer to the Yesod deployment&#xA;&ldquo;problem&rdquo;. This is something I&rsquo;ve been looking for a good solution to&#xA;for some time now and keter does a really great job. &#xA; Keter is meant to run as a service. It sets up its own workspace and&#xA;watches for keter &ldquo;bundles&rdquo; to be dropped into an incoming/ directory.&#xA;A keter bundle is…

Maybe In Ruby

Sometimes it&rsquo;s fun to do something completely useless. &#xA; Recently, I wrote a post about how awesome the Maybe type&#xA;is in Haskell. In the post, I talked about Functors and Monads and how&#xA;Maybe can help us understand them. &#xA; Shortly thereafter, I was bored on the train one day and decided to&#xA;implement Maybe and its functor instance in ruby. &#xA; &#xA;In this post…