Bryan Garza

I’m a backend engineer interested in programming language theory, operating systems, and distributed systems. My favorite languages are Haskell and C.

~ GitHub, Contact, PGP key, PL quotes

All Posts (Archive)

What I Want From Window Managers (Switching from i3 to MATE) ( August 20, 2017)

I decided to try and switch to a different window manager, namely because I was tired of switching to the wrong workspace in i3. Even though I for the most part put the same applications on the same workspaces each time, I still spend too much time fumbling with which workspace I want. I tend to want at most 2 windows in view, usually as split columns. Occasionally I’ll want 3 windows visible at once, but for the most part my workflow is having one or two visible windows. I’ve put up with i3’s manual layouts for years, mostly because its i3bar supports system applets out-of-the-box and it’s too much effort to set up another window manager to work similarly, effort that could be spend working on something more productive.

Before I get into more detail, here’s some background on what window managers or desktop environments I’ve used:

  • GNOME 3: Sophomore year of high school I began to use Ubuntu
  • XFCE: I remember at some point I switched to Xubuntu
  • dwm: During junior year of high school, I switched to Arch Linux
  • xmonad: I dabbled in this one for a few months as well
  • i3wm: By the end of junior year I had switched to i3 for what I then considered to be “sane” multi-monitor support
  • Aqua: Throughout college I used OS X (this was before I understood the gravity and importance of privacy)
  • i3wm: I came back to using GNU/Linux a few months after finishing school, and naturally gravitated back to the last window manager I had used
  • MATE: As of writing this post, I’ve switched to a floating window manager, after analyzing my usual workflow

During the time that I used dwm/xmonad/i3 in high school, I was active in the Arch Linux forums, as well as the #archlinux IRC channel. Back then, I was still learning to program and spent much of my time ricing my setup. As time went on and I became a decent programmer, I realized how I just wanted things to work correctly without fiddling, and that spending hours tweaking color schemes and other settings was a waste of my time. Furthermore, using OS X was a total 180 from what I was previously used to, which required writing scripts for everything and manually binding to various keys, as well as manually triggering arandr commands to change my monitor layouts, etc.

When I switched back to GNU/Linux last year I knew that I wanted to maintain the level of ease that is in OS X, at least for the essentials. One of those thing is the use of alt-tab. This doesn’t really seem to be available in any tiling window managers. I started using rofi as a wannabe alt-tab switcher, but disliked having to type the beginning of a window’s name to switch to it.

One thing that drives me nuts to configure is status bars and applet trays. I really don’t see the point in setting them up, and tiling window managers that ship without a decent status bar get a hard pass from me.

My requirements, therefore, for switching to another window manager or desktop environment are that (1) there has to be an alt-tab switcher, (2) the status bar has to work out-of-the-box and support applets.

Having heard of MATE from a friend, I decided to give it a shot. First I installed the most minimal package from the Debian repositories, but then realized that even the full install didn’t include that many extras. I also installed mate-tweak to be able to change some extra settings.

The switch was also catalyzed by having read Why Tiling Window Manager Sucks by Xah Lee. I’ve always respected his expertise on emacs, ergonomics, and general GNU/Linux usage, and it got me thinking that perhaps I was taking the wrong approach to window management, too chord-centric and complicated for what should require a minimal number of window manager actions, namely split left, split right, maximize window, close window, and rotate to next application.

I removed most of the default MATE bindings, bound some of the Function keys to the previously mentioned most common window manager actions, and set up wmctrl to switch to specific applications. I also tried out Compiz for about an hour but it seemed buggy to me so I quickly went back to the “Marco (Compton GPU Compositor)” setting.

So far, my current setup is basically how I use Spectacle on OS X, but without using as many chords. Like I mentioned earlier, all I really want is to be able to put emacs on the left half, and either Chromium or urxvt on the right. For less used applications, I want to alt-tab to them. Simple as that. I don’t need the tiling (manual or automatic), because if I’m working on the x230, I don’t have much screen real estate anyways, and if I’m using the external monitor, well, I still don’t want to have more than 2 or 3 visible windows.

One unexpected side effect of switching to MATE is that monitors automatically work when plugged in. For i3, what I do is create an arandr script for each specific setup (HDMI only, HDMI with ThinkPad monitor on left, living room TV with ThinkPad on right, etc), and then launch said script with rofi. It’s not ideal, and sometimes X freaks out on me and I get a black screen, forcing me to switch to another tty to kill the X server. I don’t know if MATE will also have similar issues but at least when I plug in my external monitor, it’s automatically enabled and the placement is saved. When I unplug the external monitor, it works like it should, changing to only use the ThinkPad monitor, and when the ThinkPad is closed and I disconnect the monitor, the ThinkPad goes to sleep like it should.

I’m still using i3lock (it seems to work on any WM or DE without having to touch it).

The monitor support in MATE (or any other Desktop Environment, I’m assuming) is enough reason to switch from a tiling window manager, or to switch to a combination of Desktop Environment plus tiling wm. It’s 2017, no one should be using a tiling window manager standalone.

I’ve only had this setup for a day, and therefore haven’t fully explored the pros and cons of i3 vs MATE (or tiling window managers vs Desktop Environments in the large); later on I might write a follow-up post, but for now, these are my first impressions.

Leopold FC750R Mechanical Keyboard Review ( August 14, 2017)

I’ve been using the Leopold FC750R (the white PBT, brown Cherry MX model) over the past 6 months, both in the office and at home. I decided to get the tenkeyless model instead of the smaller variant, so that the arrow keys would not be tucked next to the right Control key and other modifiers.

Pros:

  • Side-printed keys, letters will never smudge or wear off
  • Feels well-built
  • Supposedly there’s a rubber mat at the bottom of the case, to dampen echo
  • Satisfying color; it’s an off-white/arctic color

Cons

  • Not programmable
  • Port for USB is tucked in a groove underneath instead of directly in the back, not good for those who use thick braided cables

For my next keyboard, I am thinking of buying/building a Planck. It’s much smaller, the keys are arranged in columns instead of staggered, and it’s programmable. I realized I need another keyboard for travel because I recently traveled to Los Angeles and brought my ThinkPad but not my keyboard. The desk at the hotel was way too tall, making it uncomfortable to type directly on the laptop keyboard. I resorted to sitting on the bed cross-legged with the ThinkPad on my lap, or on the desk chair. Needless to say, it would have been more comfortable to have an external keyboard on my lap and place the laptop on the desk. However, since this keyboard is somewhat hefty and large, I didn’t want to travel with it (I’ve been lugging it back and forth to the office for the past 6 months and that’s been fine though).

There are some dip switches but I didn’t toggle any of them. On OS X I use Karabiner to flip the function and media keys, as well as to make Control function as Escape when pressed by itself (since I changed Caps Lock to Control in the System Preferences).

About 1/3rd of the way down in this graphic you can see what the media keys are mapped to. They work out-of-the box in Linux.

Exploring Racket Forms: define and letrec ( March 11, 2016)

A couple weeks ago I was trying to understand why expressions like this were valid:

(define (future-bound)
  (define (f) (+ x 1))
  (define x 5)
  (f))

Why can you define the x after its usage in f? I initially thought that define desugared into nested let’s or perhaps let*, like this:

(let ([f (+ x 1)])
  (let ([x 5])
    f))

(let* ([f (+ x 1)]
       [x 5])
  f)

But neither made sense, since we still have the same problem of x being bound after f is bound. It turns out that define desugars into letrec:

(letrec ([f (λ () (+ x 1))]
         [x 5])
  (f))

This works because letrec initializes the bindings for each of the symbols, to something akin to undefined. After that, all bindings are initialized to their values at once. This allows bindings to reference others before those bindings’ definitions exist. The value of x in f is only looked up once f is evaluated. We’re referencing symbols statically, but the lookup is dynamic. That means anything any symbols referencing symbols that come after have to be wrapped in a lambda; if you try to look up too early, it won’t work.

; Trying to reference a value immediately
(letrec ([six (+ x 1)]
         [x 5])
  #t)

Result:

Error: struct:exn:fail:contract:variable

x: undefined;
 cannot use before initialization

You can see this fails at the point that we try to look up x during the binding of six. Now using a lambda (and with let since it behaves in the same way and this example only binds one symbol anyways):

; loophole?
(let ([f (λ () (+ x 1))])
  f)

Here, x isn’t bound anywhere, but f can still be bound and returned! But if we actually try to evaluate f, we’ll run into problems.

; => Error: struct:exn:fail:contract
(let ([f (λ () (+ x 1))])
  (f))

Dynamic Scope In Racket ( March 10, 2016)

One way to do dynamic scope is with fluid-let, which basically reassigns the value of a variable instead of creating a shadow, but though this is available in Scheme, it’s not available in Racket.

Racket has a form named parameterize, that allows you to pass variables dynamically, but forces you to set a default value.

(define x (make-parameter 2))

(define (incr-x) (+ (x) 1))

(define (dynamic-x)
  (parameterize ([x 5])
    (incr-x)))

make-parameter creates a function x that returns the value. Evaluating (x) results in 2.

(incr-x) ;=> 3

However, you can associate a new value to the x parameter using parameterize:

(dynamic-x) ;=> 6

An advantage of parameterize over imperative updates of parameter values is that the implementation is thread-safe, and continuation-friendly. There are a few other pluses in addition to that, which you can check out in the docs.

S-expressions as a Lightweight Serialization Format ( February 17, 2016)

I’ve been writing a desktop application that uses OCaml for the backend, and Racket for the GUI frontend. To communicate between the two, I call the OCaml program as a subprocess from Racket, and have s-expressions be the serialization mechanism that both languages can understand. Jane Street’s Core, along with the sexplib syntax extension mentioned in my previous post, offer an easy way to translate OCaml types to sexps that Racket can then read.

With a type like:

type book = {
  title        : string;
  authors      : string list;
  pubdate      : string;
  publishers   : string list;
  subjects     : string list
} with sexp

A sexp_of_book function is automatically generated.

Now racket can receive:

'((title "Purely functional data structures")
  (authors ("Chris Okasaki"))
  (pubdate 1999)
  (publishers ("Cambridge University Press"))
  (subjects ("Functional programming languages" "Data structures (Computer science)")))

I take this sexp, and create a book struct:

(struct book (title authors pubdate publishers subjects))

(define (isbn-lookup isbn)
  (let ([cmd (string-join (list homelib-binary isbn))])
    ((λ~>> process    ; -> '(stdout stdin proc-id stderr f)
           car
           read       ; from an input port
           (map cadr) ; (k v) -> v
           (apply book))
     cmd)))

Finally, we can test it out on the REPL to make sure it works:

racket@app.rkt> (isbn-lookup "0521663504")
#<book>

racket@app.rkt> (book-title (isbn-lookup "0521663504"))
"Purely functional data structures"

racket@app.rkt> (book-subjects (isbn-lookup "0521663504"))
'("Functional programming languages" "Data structures (Computer science)")

Similarly, I can work in the other direction, and pass Racket s-expressions to OCaml, and using sexplib, convert them back to OCaml types. What a time to be alive!

Adding Syntax Extensions To An OCaml Project ( February 8, 2016)

Here’s the set of steps needed to start using syntax extensions. I’ll be using sexplib as the example.

First, you have to add the extension to your .merlin file:

PKG core yojson lwt cohttp cohttp.lwt
EXT sexplib.syntax

Now Merlin’s minor mode won’t throw up errors when you save. Next up is compiling the project. I’m using Oasis. Add sexplib and its .syntax file to the BuildDepends in the _oasis file:

(other stuff)

Executable myprogram
  Path: src
  BuildTools: ocamlbuild
  MainIs: main.ml
  CompiledObject: best
  BuildDepends:
    core,
>   sexplib,
>   sexplib.syntax,
    threads,
    yojson,
    lwt,
    cohttp,
    cohttp.lwt

After that, call oasis to add in the new dependencies. I use

oasis setup -setup-update dynamic

Run make again, and the project should build using sexplib!

On The Importance Of Enforcing Invariants ( February 4, 2016)

Something that comes up early on when learning OCaml is the topic of abstract types. Comparable to “encapsulation” in object-oriented programming, one purpose of abstract types is to protect the programmer from misusing a module’s types. By abstracting the type, for example, presenting a Number.t instead of a plain int type, the underlying implementation can be swapped out, without affecting code using the module. Only by using the module can the user create a value of that type, because only the module knows that Number.t = int, and has ability to create that type.

Abstract types guarantee that the user can never access the concrete type directly This is known as “enforcing invariants”, preserving certain properties about the type, so that you can now assume they will always be true, i.e., invariant. Placing this restriction on library users increases the level of type safety significantly.

On the other hand, sometimes you do want to have concrete types in your interface, and that’s okay too. It gives more flexibility to the user, since they can construct those types by hand, and have more detail about the internals of the module.

Universal Quantification in OCaml ( February 2, 2016)

The difference between OCaml’s type signatures and type annotations is quite subtle. First of all, signatures are what you put in the mli files, whereas annotations are inline with your code. When you write a function like:

let foo : 'a -> 'a = fun x -> 0

the type of foo resolves to int -> int, because 'a is serving as a unification variable and not a type parameter. In order to force the compiler to not constrain the function to the concrete type int, you need to annotate:

let foo : 'a. 'a -> 'a = fun x -> 0

Essentially, this means “for all types ‘a”, and now we are dealing with a type parameter instead, forcing the compiler to keep the function polymorphic. The mli files work with type parameters by default, so if you are writing type signatures there you might not run into this problem. However, sometimes your function will not typecheck (because it’s unclear) until you annotate it with the type ascription, and you’ll need to do that before the mli can be checked by the compiler.

There’s some more info about this on SO and Jane Street’s blog.

Automating Blog Posts With Org-mode ( January 31, 2016)

The best way to get me writing is to remove all barriers that slow me down. This especially includes the setup of creating a new post in org-mode and writing its index entry. It might be really easy but it’s annoying to have to do this every time for each new post. So I whipped up some elisp that does all of this for me. It just takes the title, keywords, and description of the post, and takes care of the rest.

(defun bryan/blog-new-post (title keywords description)
  "Create a new post"
  (interactive "sTitle: \nsKeywords: \nsDescription: ")
  ;; (message "Keywords are: %s" keywords)
  (let* ((filename-prepared (string-trim
                             (replace-regexp-in-string " " "-" (downcase title))))
         (relfile (concat filename-prepared ".org"))
         (relfile-html (concat "./" filename-prepared ".html"))
         (absfile (concat bryan/blog-blogdir relfile))
         (date (format-time-string "[%Y-%m-%d %a]"))
         (date-day-not-padded (string-trim (format-time-string "%e")))
         (mon (format-time-string "%B"))
         (yr (format-time-string "%Y"))
         (date-human-readable
          (concat "(" mon (format " %s, " date-day-not-padded) yr ")"))
         (my-html-link-and-span
          `(,(html-a
              :href relfile-html title)
            ,(html-span " ")
            ,(html-span
              :class "timestamp-wrapper"
              (html-span
               :class "timestamp"
               date-human-readable)))))

    (with-current-buffer (find-file-noselect bryan/blog-indexfile)
      (goto-char (point-min))
      (search-forward ">@@")
      (insert "\n#+BEGIN_HTML\n")
      (html-lite-write-tree-single-line
       (butlast
        (html-div
         :class "outline-3"
         (html-h3
          my-html-link-and-span))))
      (insert "\n#+END_HTML\n")
      (insert (format "#+INCLUDE: \"%s\" :lines \"11-\"" relfile))
      (insert (bryan/org-escape-html "</div>"))
      (with-temp-message (format "Writing to %s" bryan/blog-indexfile)
        (save-buffer))
      (message "Writing file...done"))

    (with-temp-buffer
      (-each `(,(format "#+TITLE: %s\n" title)
               ,(format "#+DATE: %s\n" date)
               ,(format "#+KEYWORDS: %s\n" keywords)
               ,(format "#+DESCRIPTION: %s\n" description)
               "#+OPTIONS: title:nil\n\n"
               "#+BEGIN_HTML\n")
        #'insert)
      (html-lite-write-tree-single-line
       (html-header
        (html-h1 :class "title" my-html-link-and-span)))
      (insert "\n#+END_HTML\n\n")
      (when (file-writable-p absfile)
        (write-region (point-min)
                      (point-max)
                      absfile)))
    (find-file absfile))
  (goto-char (point-max))
  (message "Generated template"))

Basic Graph Traversal in OCaml ( January 28, 2016)

This is my solution to Cracking The Coding Interview problem 4.2. The problem is: Given a directed graph, design an algorithm to find out whether there is a route between two nodes.

Keep in mind that I’ve only been writing OCaml for a few weeks. There is probably a more elegant solution. Once my OCaml is more advanced, I’ll make a new post. This solution does BFS traversal, returning None early when it can’t traverse any further and hasn’t reached the destination node.

module Graph =
struct
  type node   = int
  type graph  = { nodes : node list; edges : (node*node) list }
  let mk = { nodes=[] ; edges= [] }

  let mk_outgoing g =
    fun n ->
      let keep ((left,_) as edge) acc = if left = n then [edge] @ acc else acc in
      let next_to = List.fold_right g.edges ~f:keep ~init:[] in
      Int.Set.of_list (List.map next_to ~f:snd)

  let bfs_traverse_until g root ~f:action =
    let outgoing = mk_outgoing g
    and visited  = Int.Set.empty
    and to_visit = Queue.create () in
    Queue.enqueue to_visit root;
    let rec loop visited =
      Option.value_map
        (Queue.dequeue to_visit)
        ~default:None
        ~f:(fun id ->
            if action id then Some id
            else begin
              if not (Int.Set.mem visited id) then
                let children = Int.Set.diff (outgoing id) visited in
                Int.Set.iter children ~f:(fun n -> Queue.enqueue to_visit n);
                let visited' = Int.Set.add visited id in
                loop visited'
              else
                loop visited
            end
          )
    in loop visited

  let route g n1 n2 =
    Option.is_some (bfs_traverse_until g n1 ~f:(fun node -> node = n2))
end

let my_graph : Graph.graph =
  { Graph.nodes = [1;2;3;4;5;6;7;8;9;10]
  ; Graph.edges = [(1,2); (1,3); (1,5); (1,8); (1,9)
                  ;(2,3); (2,10); (2,7)
                  ;(3,8)
                  ;(4,6); (4,10)
                  ;(5,4); (5,6)
                  ;(6,3)
                  ;(7,8); (7,10); (7,1)
                  ;(8,9); (8,6)
                  ;(9,6); (9,3)
                  ;(10,9); (10,8)] }

Here’s how I tested it:

utop[2]> Graph.route;;
- : Graph.graph -> int -> int -> bool = <fun>
utop[4]> Graph.route my_graph 1 10;;
- : bool = true
utop[5]> Graph.route my_graph 10 1;;
- : bool = false
utop[6]> Graph.route my_graph 3 9;;
- : bool = true
utop[7]> Graph.route my_graph 4 7;;
- : bool = false