Minimal Coding with Spacemacs and Olivetti

Written by Pete Corey on Sep 10, 2018.

As I mentioned on Twitter, I’ve been experimenting lately with using a visually minimal Spacemacs setup. I’ve been using this new setup every day for several weeks, and I’m absolutely in love with it.

Want screenshots and an overview of how it works? Read on!

But First, Screenshots

Olivetti is an Emacs package designed to create a distraction-free writing experience within your editor. Most of Olivetti’s screenshots show it in the context of editing markdown. That makes sense, as the term “distraction-free writing” is usually applied to the context of writing prose.

But what if I want a “distraction-free writing” environment for writing code?

It turns out that Olivetti is still perfectly suited for the job. Check out a few screenshots of my current Spacemacs setup. Note that the screenshots below capture my entire screen, from edge to edge. There’s nothing behind the curtain here:

Spacemacs with Olivetti.

I’ve configured Olivetti to only activate when in prog-mode, or in text-mode. This means that things like Spacemac’s home buffer, and inline terminals retain their original layouts. This distinction has been working beautifully for me so far:

Spacemacs with multiterm.

Using Olivetti within Spacemacs

To get Olivetti working with Spacemacs, I needed an Olivetti layer. Unfortunately, an out-of-the-box Spacemacs layer doesn’t exist for Olivetti. Thankfully, the process of creating a custom, private layer isn’t a difficult one.

We can create a new private layer from within Spacemacs by running the configuration-layer/create-layer command with M-x (or SPC + :). Let’s call our layer olivetti. This creates a new ~/.emacs.d/private/olivetti folder and populates a packages.el file with some boilerplate.

We’ll replace the contents of packages.el with the following:


(defconst olivetti-packages
  '(olivetti))

(defun olivetti/init-olivetti ()
  (use-package olivetti))

This tells Spacemacs that we need the olivetti package, and to use the package once it’s been loaded.

Once that’s done, we need to edit our Spacemacs configuration file (SPC f e d), and add an olivetti entry under our dotspacemacs-configuration-layers list to instruct Spacemacs to load our new private layer.


(defun dotspacemacs/layers ()
  (setq-default
   ...
   dotspacemacs-configuration-layers
   '(
     ...
     olivetti
     )))

Finally, we need to configure Olivetti to run in prog-mode and text-mode. We can do this in our dotspacemacs/user-config callback:


(add-hook 'text-mode-hook (lambda ()
                            (interactive)
                            (message "Olivetti text-mode-hook")
                            (olivetti-set-width 81)
                            (hidden-mode-line-mode)
                            (spacemacs/toggle-vi-tilde-fringe-off)
                            (olivetti-mode 1)))
(add-hook 'prog-mode-hook (lambda ()
                            (interactive)
                            (message "Olivetti prog-mode-hook")
                            (olivetti-set-width 81)
                            (hidden-mode-line-mode)
                            (spacemacs/toggle-vi-tilde-fringe-off)
                            (olivetti-mode 1)))

I use this opportunity to tune Olivetti and Spacemacs to my liking. Feel free to make any changes you deem necessary.

With that, we’re good to go!

How To Not Get Lost

The key to not getting lost without any visual indicators is to always know where you are!

That may sound like a truism, but visually paring down my code editing environment has made me realize that there is no substitute for deep understanding and mastery of your tools. I don’t need a modeline to tell me which mode I’m in if I already know. I don’t need a constant reminder of which line I’m on, when I can navigate directly to any given line with :.

Many of the visual indicators that modern editors provide are really just noise. I’m not going to say that noise is never helpful, but you can almost always get by without it.

If you’re interested in seeing exactly how my Spacemacs is set up, you can see my entire .spacemacs file here. It’s very ugly. I’m warning you now.

Using Facades to Simplify Elixir Modules

Written by Pete Corey on Sep 3, 2018.

A common trend I see in Elixir projects is that modules tend to become large. Sometimes very large. This isn’t necessarily an issue, but it goes against some deep seated heuristics I have for building software.

As my Chord project started to get complex, I repeatedly found myself reaching for a pattern to keep my module size and complexity down, while still maintaining a friendly and approachable API.

Let’s dig into some examples.

What’s the problem?

The Chord module is the heart of my Chord project. Using Chord you can generate guitar chord voicings, generate possible fingerings for a given voicing, and even calculate the distances between various chord voicings and fingerings.

It’s conceivable that lots of this functionality should live directly under the Chord module. For example, we’d want to be able to ask for Chord.voicings/1, or Chord.fingerings/1, or even convert a chord into a chord chart with Chord.to_string/1.

The problem is that each of these pieces of functionality comes along with a non-trivial implementation. If we put our voicings/1, fingerings/1, and to_string/1 functions in the Chord module, their implementations would likely live in the Chord module as well. In my mind, this would quickly turn Chord into an unmaintainable mess.

There has to be a better way.

What’s the solution?

It turns out there is a better way. And, like most better ways, it turns out that the solution to our problem is obviously simple.

Let’s use our voicings/1 function as an example. Rather than defining our voicings/1 function and implementation within our Chord module, we’ll create a Chord.Voicing module and define our voicings/1 function there.


defmodule Chord.Voicing do
  def voicings(notes, notes_in_chord \\ nil),
    do: ...
end

Now our Chord.Voicing module is entirely concerned with the act of generating chord voicings for a given set of notes.

However, we still want this functionality available through our Chord module. To accomplish this, we simply need to write a Chord.voicings/1 function that matches the signature of our Chord.Voicing.voicings/1 module and passes the call straight through to our Chord.Voicing module:


defmodule Chord do
  def voicings(notes, notes_in_chord \\ nil),
    do: Chord.Voicing.voicings(notes, notes_in_chord)
end

We can continue on with this pattern by creating a new module to implement each of our features: Chord.Fingering, Chord.Renderer. From there we can flesh our our Chord module to wire our convenience functions up to their actual implementations:


defmodule Chord do
  def voicings(notes, notes_in_chord \\ nil),
    do: Chord.Voicing.voicings(notes, notes_in_chord)

  def to_string(chord, chord_name \\ nil),
    do: Chord.Renderer.to_string(chord, chord_name)

  def fingerings(chord),
    do: Chord.Fingering.fingerings(chord)
end

Beautiful.

Enter Delegates

Using the above pattern, we might make a mistake when passing the arguments from our first function head into the function in our implementation module (I’ve done it before).

Thankfully, Elixir gives us a way to prevent this mistake:


defmodule Chord do
  defdelegate voicings(notes, notes_in_chord \\ nil), to: Chord.Voicing
  defdelegate to_string(chord, chord_name \\ nil), to: Chord.Renderer
  defdelegate fingerings(chord), to: Chord.Fingering
end

Using the defdelegate macro, we can define the interface for each of our voicings/2, to_string/2, and fingerings/1 functions in our Chord module, and point each of these function heads to their implementation module.

Elixir automatically wires each of the delegated functions together, preventing any mindless developer mistakes from creeping into our codebase.

What’s in a name?

In the previous example, the Chord module is essentially acting as a “facade” that wraps and hides the complexity of our Chord.Voicing, Chord.Fingering, and Chord.Renderer modules.

I use the term “facade” loosely, and in real-life, I don’t use it at all. The “facade pattern”, and honestly all classic Gang of Four design patterns, carry baggage that I like to think I’ve let go of in my transition into the world of functional programming.

Another less weighty way to think of Chord is as an “API module”. It’s sole purpose is to act as an “application programming interface” within our application.

What would you call this kind of pattern?

Computing Fingering Distance with Dr. Levenshtein

Written by Pete Corey on Aug 27, 2018.

Jumping off after our previous two articles on Voice Leading with Elixir, and Algorithmically Fingering Guitar Chords with Elixir, we’re left with a series of chord voicings ranked according to how well they voice lead from our starting chord, and the set of all possible fingerings for each of these voicings.

Given that our starting chord has a known fingering, which fingering of each of these “best” voicings is the “easiest” to play after our starting chord?

This is an interesting question, and gives us the opportunity to flex our algorithmic muscles again. This time we’ll be basing our solution on a modified version of the Levenshtein distance algorithm for finding the “edit distance” between two strings.

What is “Fingering Distance”?

The term “fingering distance” is my way of referring to how difficult it is to transition from playing one chord on the guitar to another. For example, going from playing a Dm chord on the middle four strings to an Em chord is easy. We just have to slide the shape up two frets.

However, starting on that same Dm chord and playing an Em chord on the top four strings is a more difficult transition. We need to change positions on the fretboard, and every finger in the chord needs to be moved.


The family of “edit distance” algorithms tackles a similar problem. How difficult is it to transform one string into another, given a set of operations with fixed costs?

The Levenshtein distance algorithm is an example of an “edit distance” algorithm with three operations: insertion, deletion, and substitution. The Levenshtein distance between kitten and sitting is 3, where the k is substituted for an s, and e is substituted for i, and the g is inserted at the end of the word.

In the classic Levenshtein distance algorithm each of the three basic operations has a unit cost (a cost of 1). This doesn’t always have to be the case. We can modify the algorithm to use our own set of operations, like “place finger”, “lift finger”, “move finger”, and “slide finger” to model how we transition from one chord to another. These operations might have a variable weight, depending on the operation and how far each finger has to move:

  • Placing and lifting a finger both seem similarly difficult. Let’s give both of these operations a constant unit cost.

  • Moving from the fifth fret, fifth string to the fifth fret, fourth string seems fairly simple, but moving from the fifth fret, fifth string to the second fret, third string would be more difficult. We’ll give the “move finger” operation a weight dependent on the distance we have to move.

  • Sliding a finger up or down a string seems to be special sub-case of the “move finger” operation. I would argue that sliding a finger from any fret to any other fret on a string is roughly the same difficult. We’ll give the “slide finger” operation a constant unit cost.

Let’s use this as a jumping off point for building our “fingering distance” calculator.

Calculating Fingering Distance

Let’s start by defining a new module that will hold our new distance/2 function:


defmodule Chord.Distance.Fingering do
  def distance(chord, chord),
    do: 0
end

Obviously, if we pass in two identical chords, the distance between them is 0.

A more interesting case occurs when we’re comparing a chord with one or more notes to an empty list. The total distance between these two “chords” is our “place finger” cost applied to each of the remaining notes in our chord:


def distance(chord, []),
  do:
    chord
    |> Enum.reject(&(&1 == nil))
    |> length

We’ll need to handle the inverse case as well:


def distance([], chord),
  do:
    chord
    |> Enum.reject(&(&1 == nil))
    |> length

The real meat of the algorithm comes into play when it’s time to determine the distance between two non-empty chords:


def distance([note_a | rest_a] = chord_a, [note_b | rest_b] = chord_b),
  do:
    Enum.min([
      distance(rest_a, chord_b) + 1,
      distance(chord_a, rest_b) + 1,
      distance(rest_a, rest_b) + note_distance(note_a, note_b)
    ])

As you can see, our distance/2 function is recursive. At every level of recursion, we calculate the distance required to transform chord_a into chord_b by first:

  • Lifting a finger from chord_a.
  • Lifting a finger from chord_b.
  • Moving note_a to note_b.

The initial choice with the lowest final cost is the choice we pick. Our decision ripples up through our stack until we’re left with the final, minimal cost of transitioning from chord_a to chord_b.

Thank you, Dr. Levenshtein!

Calculating Note Distance

As we’ve seen, both placing and lifting a finger have constant unit costs. The real magic of our fingering distance algorithm happens in the note_distance/2 helper function, where we calculating the cost of moving fingers between frets ands strings.

We’ll start with some trivial base cases. If the two notes we’re comparing are the same, the distance between them is 0:


def note_distance(note, note),
  do: 0

If the first “note” is nil, we’re actually being asked for the cost of placing a finger:


def note_distance(nil, _),
  do: 1

Similarly, if the second “note” is nil, we’re being asked how much it costs to lift a finger:


def note_distance(_, nil),
  do: 1

Now things are getting interesting. If we’re asked for the distance between two notes that live on the same string, we’ll report back the unit cost, as we discussed earlier:


def note_distance({_, _, string}, {_, _, string}),
  do: 1

However, if the two notes live on different strings, we’ll treat out guitar’s fretboard like a grid, or city block, and return the “manhattan distance” between the two notes:


def note_distance({fret_a, _, string_a}, {fret_b, _, string_b}),
  do: abs(fret_a - fret_b) + abs(string_a - string_b)

And that’s really all there is to it.

A Few Examples

Going back to our previous examples, going from our Dm on the middle four string set to an Em on the same string should have a cost of 4. We’re just sliding each finger up two frets:


Chord.Distance.Fingering.distance(
  [nil, {5, 1}, {7, 3}, {7, 4}, {6, 2}, nil],
  [nil, {7, 1}, {9, 3}, {9, 4}, {8, 2}, nil]
)

And we do get 4!

The cost of transitioning from that same Dm chord to an Em on the upper four string set should be higher than 4:


Chord.Distance.Fingering.distance(
  [nil, {5, 1}, {7, 3}, {7, 4}, {6, 2}, nil],
  [nil, nil, {2, 1}, {4, 3}, {5, 4}, {3, 2}]
)

And it is! We get a distance of 6.

The Next Best Chord

And now for the grand finale. Let’s say we want to find the set of Cmaj7 voicings that have the best voice leading between our starting G7 chord. This is old hat from our previous articles:


[0, 4, 7, 11]
|> Chord.voicings(4)
|> Enum.map(&{Chord.Distance.Semitone.distance(&1, [nil, 10, 12, 10, 12, nil]), &1})
|> Enum.uniq()
|> Enum.sort()
|> Enum.chunk_by(&elem(&1, 0))
|> List.first()
|> Enum.map(&elem(&1, 1))

But now let’s take each of those voicings and find the best fingering for each with regards to how we’re fingering our G7 chord:


|> Enum.map(fn chord ->
  chord
  |> Chord.fingerings()
  |> Enum.uniq()
  |> Enum.map(
    &{Chord.Distance.Fingering.distance(&1, [nil, {10, 1}, {12, 3}, {10, 1}, {12, 4}, nil]), &1}
  )
  |> Enum.sort()
  |> Enum.map(&elem(&1, 1))
  |> List.first()
end)

Finally, we’ll take each fingered chord and render it to the console:

Our final chords.

Awesome!

Final Thoughts

If you can’t tell, I’m in love with this project. I’ve been playing with it quite a bit in my free time, and I’ve managed to coax it into generating entire progressions for me that sound and play beautifully.

If you’re interested in seeing me put more work into this, and potentially develop it into a fully-functional web application, let me know on Twitter.

If you want to check out the full source code, be sure to check out the Chord project on Github.