<?xml version="1.0" encoding="utf-8"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/"><channel><title>sglavoie.com – Tag: Software</title><link>https://www.sglavoie.com/tags/software/</link><description>Posts and writings by Sébastien Lavoie. Customization setups and articles on productivity for developers who like minimalism.</description><language>en</language><atom:link href="https://www.sglavoie.com/tags/software/feed.xml" rel="self" type="application/rss+xml"/><lastBuildDate>Sun, 30 Mar 2025 11:18:00 -0600</lastBuildDate><item><title>Reading notes: A Philosophy of Software Design, 2nd Edition</title><link>https://www.sglavoie.com/posts/book-summary-philosophy-software-design-2nd-edition/</link><description>A Philosophy of Software Design, 2nd Edition by John Osterhout beautifully covers the nature of complexity in software. It provides clear strategies to keep complexity as low as possible while giving real-world examples along the way from his own work (e.g., RAMCloud or the Tcl programming language). He also gathered, for instance, interesting sources of various designs for a GUI text editor from his students, highlighting essential points to keep in mind while designing software.</description><content:encoded>&lt;hr&gt;
&lt;h2 id="nature-of-complexity"&gt;Nature of complexity&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;Change amplification: The first symptom of complexity is that a seemingly simple change requires code modifications in many different places.&amp;rdquo;&lt;/em&gt; (e.g., refactoring a project to inject dependencies in tests, because the system was hard to test in the first place)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;Cognitive load: The second symptom of complexity is cognitive load, which refers to how much a developer needs to know in order to complete a task.&amp;rdquo;&lt;/em&gt; (e.g., close a file where it is opened whenever possible, instead of leaking context and pushing the responsibility onto the caller)&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;Unknown unknowns: The third symptom of complexity is that it is not obvious which pieces of code must be modified to complete a task, or what information a developer must have to carry out the task successfully.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;One of the most important goals of good design is for a system to be obvious.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="strategic-vs-tactical-programming"&gt;Strategic vs. tactical programming&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;it&amp;rsquo;s worth taking a little extra time to find a simple design for each new class; rather than implementing the first idea that comes to mind, try a couple of alternative designs and pick the cleanest one. Try to imagine a few ways in which the system might need to be changed in the future and make sure that will be easy with your design&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="modules-should-be-deep"&gt;Modules should be deep&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Modular design
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;In general, if a developer needs to know a particular piece of information in order to use a module, then that information is part of the module&amp;rsquo;s interface.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Abstractions
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;The key to designing abstractions is to understand what is important, and to look for designs that minimize the amount of information that is important&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;A deep module is one in which the interface is small and the implementation is large.
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;Deep modules such as Unix I/O and garbage collectors provide powerful abstractions because they are easy to use, yet they hide significant implementation complexity.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Shallow modules
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;A shallow module is one whose interface is complicated relative to the functionality it provides.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="information-hiding"&gt;Information hiding&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;If a piece of information is hidden, there are no dependencies on that information outside the module containing the information, so a design change related to that information will affect only the one module&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Information leakage
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;If the affected classes are relatively small and closely tied to the leaked information, it may make sense to merge them into a single class.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;When designing modules, focus on the knowledge that&amp;rsquo;s needed to perform each task, not the order in which tasks occur.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;it&amp;rsquo;s important to avoid exposing internal data structures as much as possible&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;The best features are the ones you get without even knowing they exist.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;As a software designer, your goal should be to minimize the amount of information needed outside a module; for example, if a module can automatically adjust its configuration, that is better than exposing configuration parameters&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;think about the different pieces of knowledge that are needed to carry out the tasks of your application, and design each module to encapsulate one or a few of those pieces of knowledge. This will produce a clean and simple design with deep modules.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="general-purpose-modules-are-deeper"&gt;General-Purpose Modules are Deeper&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;specialization leads to complexity&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Generality leads to better information hiding&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;Eliminate special cases in code&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="different-layer-different-abstraction"&gt;Different Layer, Different Abstraction&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;A pass-through method is one that does nothing except pass its arguments to another method, usually with the same API as the pass-through method. This typically indicates that there is not a clean division of responsibility between the classes.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="pull-complexity-downwards"&gt;Pull Complexity Downwards&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Figure out complexity in the library instead of pushing it up to the user.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;quot;[&amp;hellip;] you should avoid configuration parameters as much as possible. Before exporting a configuration parameter, ask yourself: will users (or higher-level modules) be able to determine a better value than we can determine here?&amp;quot;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="better-together-or-better-apart"&gt;Better Together Or Better Apart?&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;Bring together if information is shared&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;Bring together if it will simplify the interface&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;Bring together to eliminate duplication&amp;rdquo;&lt;/em&gt;
&lt;ul&gt;
&lt;li&gt;Use &lt;code&gt;goto&lt;/code&gt; to exit nested code blocks early as long as it&amp;rsquo;s not too complex.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;On Splitting long methods: &lt;em&gt;&amp;ldquo;If you make a split of this form and then find yourself flipping back and forth between the parent and child to understand how they work together, that is a red flag (&amp;ldquo;Conjoined Methods&amp;rdquo;) indicating that the split was probably a bad idea.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;If the caller has to invoke each of the separate methods, passing state back and forth between them, then splitting is not a good idea.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="define-errors-out-of-existence"&gt;Define Errors Out Of Existence&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;The key overall lesson from this chapter is to &lt;strong&gt;reduce the number of places where exceptions must be handled&lt;/strong&gt;; in some cases the semantics of operations can be modified so that the normal behavior handles all situations and there is no exceptional condition to report [&amp;hellip;].&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;The best way to eliminate exception handling complexity is to &lt;strong&gt;define your APIs so that there are no exceptions to handle&lt;/strong&gt;: define errors out of existence&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;E.g., the Java &lt;code&gt;substring&lt;/code&gt; method could remove its &lt;code&gt;IndexOutOfBoundsException&lt;/code&gt; by automatically rounding the index to the nearest valid value.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;quot;&lt;strong&gt;Exception masking&lt;/strong&gt; doesn&amp;rsquo;t work in all situations, but it is a powerful tool in the situations where it works. It results in deeper classes, since it reduces the class&amp;rsquo;s interface (fewer exceptions for users to be aware of) and adds functionality in the form of the code that masks the exception. Exception masking is an example of pulling complexity downward.&amp;quot;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;The idea behind exception aggregation is to handle many exceptions with a single piece of code; rather than writing distinct handlers for many individual exceptions, handle them all in one place with a single handler.&amp;rdquo;&lt;/em&gt; (e.g., a web server dispatching different types of requests and catching all sorts of errors).&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;In most applications there will be certain errors that are not worth trying to handle. Typically, these errors are difficult or impossible to handle and don&amp;rsquo;t occur very often. The simplest thing to do in response to these errors is to print diagnostic information and then abort the application.&amp;rdquo;&lt;/em&gt; (e.g., out-of-memory errors).&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="design-it-twice"&gt;Design it Twice&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;The initial design experiments will probably result in a significantly better design, which will more than pay for the time spent designing it twice&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;The process of devising and comparing multiple approaches will teach you about the factors that make designs better or worse. Over time, this will make it easier for you to rule out bad designs and hone in on really great ones.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="why-write-comments-the-four-excuses"&gt;Why Write Comments? The Four Excuses&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;Good code is self-documenting.&lt;/em&gt; Comments serve as precisions on abstractions.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;I don&amp;rsquo;t have time to write comments.&lt;/em&gt; The benefits of having documentation quickly offset the cost of writing it.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Comments get out of date and become misleading.&lt;/em&gt; Keep the documentation close to where it needs to be, so you update it.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;All the comments I have seen are worthless.&lt;/em&gt; Be the change you want to see.&lt;/li&gt;
&lt;li&gt;Benefits of well-written comments
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;The overall idea behind comments is to capture information that was in the mind of the designer but couldn&amp;rsquo;t be represented in the code.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;One of the purposes of comments is to make it it unnecessary to read the code.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="comments-should-describe-things-that-arent-obvious-from-the-code"&gt;Comments Should Describe Things that Aren&amp;rsquo;t Obvious from the Code&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Don&amp;rsquo;t repeat the code&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;Lower-level comments add precision&amp;rdquo;&lt;/em&gt;
&lt;ul&gt;
&lt;li&gt;Focus on what the variable represents, not how it is modified (the latter is explained by the code).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;Higher-level comments enhance intuition&amp;rdquo;&lt;/em&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;What is the simplest thing you can say that explains everything in the code? What is the most important thing about this code?&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Interface documentation&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;Implementation comments: what and why, not how&amp;rdquo;&lt;/em&gt;
&lt;ul&gt;
&lt;li&gt;Describe at a more abstract level to help understand what is happening and why. The code tells the how.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Cross-module design decisions
&lt;ul&gt;
&lt;li&gt;One possible solution is to use a &lt;code&gt;designNotes.md&lt;/code&gt; file or similar to jot down all major decisions, and point to it from the code (e.g., &lt;em&gt;See &lt;code&gt;topic&lt;/code&gt; in designNotes&lt;/em&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="choosing-names"&gt;Choosing names&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Great names are &lt;em&gt;&amp;ldquo;precise, unambiguous, and intuitive.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Use names consistently: make it so that a concept is expressed in the same words regardless of the context in which it is found if it makes sense to do so.&lt;/li&gt;
&lt;li&gt;Avoid extra words: no more Hungarian Notation with modern IDEs.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="use-comments-as-part-of-the-design-process"&gt;Use comments as part of the design process&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Delayed comments are bad comments
&lt;ul&gt;
&lt;li&gt;You won&amp;rsquo;t remember exactly what you had in mind and why you did things if you delay writing documentation: design decisions will get lost.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Write the comments first
&lt;ul&gt;
&lt;li&gt;No backlog of unwritten comments.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;it produces better comments.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Comments are a design tool
&lt;ul&gt;
&lt;li&gt;Writing them at the beginning &lt;em&gt;&amp;ldquo;improves the system design.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;If a method or variable requires a long comment, it is a red flag that you don&amp;rsquo;t have a good abstraction.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Early comments are fun comments
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;If you are programming strategically, where your main goal is a great design rather than just writing code that works, then writing comments should be fun, since that&amp;rsquo;s how you identify the best designs.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;I&amp;rsquo;m looking for the design that can be expressed completely and clearly in the fewest words. The simpler the comments, the better I feel about my design.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Are early comments expensive?
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;Writing the comments first will mean that the abstractions will be more stable before you start writing code.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;In contrast, if you write the code first, the abstractions will probably evolve as you code, which will require more code revisions than the comments-first approach.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="modifying-existing-code"&gt;Modifying existing code&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;Whenever you modify any code, try to find a way to improve the system design at least a little bit in the process. If you&amp;rsquo;re not making the design better, you are probably making it worse.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Maintaining comments: keep the comments near the code
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;The farther a comment is from its associated code, the less likely it is that it will be updated properly.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;In general, the farther a comment is from the code it describes, the more abstract it should be (this reduces the likelihood that the comment will be invalidated by code changes).&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Comments belong in the code, not the commit log
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;An example is a commit message describing a subtle problem that motivated a code change. If this isn&amp;rsquo;t documented in the code, then a developer might come along later and undo the change without realizing that they have re-created a bug.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Maintaining comments: avoid duplication&lt;/li&gt;
&lt;li&gt;Maintaining comments: check the diffs
&lt;ul&gt;
&lt;li&gt;Review changes during the pre-commit phase to make sure documentation stays up-to-date with the code changes.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Higher-level comments are easier to maintain
&lt;ul&gt;
&lt;li&gt;Most helpful comments do not repeat the code, they provide an abstraction that can&amp;rsquo;t be expressed easily by the code alone.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="consistency"&gt;Consistency&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Similar things are done in a similar way.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;Consistency creates cognitive leverage: once you have learned how something is done in one place, you can use that knowledge to immediately understand other places that use the same approach.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Ensuring consistency
&lt;ul&gt;
&lt;li&gt;Document most important conventions.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;the value of consistency over inconsistency is almost always greater than the value of one approach over another.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="code-should-be-obvious"&gt;Code should be obvious&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;the best way to determine the obviousness of code is through code reviews&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;If someone reading your code says it&amp;rsquo;s not obvious, then it&amp;rsquo;s not obvious, no matter how clear it may seem to you&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;Things that make code more obvious
&lt;ul&gt;
&lt;li&gt;Good names&lt;/li&gt;
&lt;li&gt;Consistency&lt;/li&gt;
&lt;li&gt;Judicious use of white space&lt;/li&gt;
&lt;li&gt;Blank lines&lt;/li&gt;
&lt;li&gt;Comments&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Things that make code less obvious
&lt;ul&gt;
&lt;li&gt;Event-driven programming&lt;/li&gt;
&lt;li&gt;Generic containers&lt;/li&gt;
&lt;li&gt;Different types for declaration and allocation&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="software-trends"&gt;Software trends&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Object-oriented programming and inheritance
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;In order for an interface to have many implementations, it must capture the essential features of all the underlying implementations while steering clear of the details that differ between the implementations; this notion is at the heart of abstraction.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;Class hierarchies that use implementation inheritance extensively tend to have high complexity.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;Before using implementation inheritance, consider whether an approach based on composition can provide the same benefits.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Agile development
&lt;ul&gt;
&lt;li&gt;May encourage a more tactical approach to programming. Balance is required.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Test-driven development
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;it focuses attention on getting specific features working, rather than finding the best design&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;One place where it makes sense to write the tests first is when fixing bugs. Before fixing a bug, write a unit test that fails because of the bug.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Design patterns
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;As with many ideas in software design, the notion that design patterns are good doesn’t necessarily mean that more design patterns are better.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Getters and setters
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;It’s better to avoid getters and setters (or any exposure of implementation data) as much as possible.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="designing-for-performance"&gt;Designing for performance&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;How to think about performance
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;The key is to develop an awareness of which operations are fundamentally expensive.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Measure before (and after) modifying
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;the goal is to identify a small number of very specific places where the system is currently spending a lot of time, and where you have ideas for improvement.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;If the changes didn’t make a measurable difference in performance, then back them out (unless they made the system simpler).&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Design around the critical path
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;When redesigning for performance, try to minimize the number of special cases you must check.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;Complicated code tends to be slow because it does extraneous or redundant work.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="decide-what-matters"&gt;Decide what matters&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;Minimize what matters&lt;/li&gt;
&lt;li&gt;How to emphasize things that matter
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;important things should appear in places where they are more likely to be seen, such as interface documentation, names, or parameters to heavily used methods.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;repetition: key ideas appear over and over again.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;The things that matter the most should be at the heart of the system, where they determine the structure of things around them.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Mistakes
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;treat too many things as important. When this happens, unimportant things clutter up the design, adding complexity and increasing cognitive load.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;fail to recognize that something is important. This mistake leads to situations where important information is hidden, or important functionality is not available so developers must continually recreate it.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;Thinking more broadly
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;the best way to make a document easy to read is to identify a few key concepts at the beginning and structure the remainder of the document around them. When discussing the details of a system, it helps to tie them back to the overall concepts.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;Focusing on what is important is also a great life philosophy: identify a few things that matter most to you, and try to spend as much of your energy as possible on those things.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&amp;ldquo;The reward for being a good designer is that you get to spend a larger fraction of your time in the design phase, which is fun. Poor designers spend most of their time chasing bugs in complicated and brittle code.&amp;rdquo;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;</content:encoded><dc:creator>Sébastien Lavoie</dc:creator><pubDate>Sun, 30 Mar 2025 11:18:00 -0600</pubDate><guid isPermaLink="false">https://www.sglavoie.com/posts/book-summary-philosophy-software-design-2nd-edition/</guid><category>learnings</category><category>books</category><category>design</category><category>software</category><category>skimming-notes</category></item><item><title>Systematic reviews</title><link>https://www.sglavoie.com/posts/systematic-reviews/</link><description>I find learning about productivity fascinating, yet I’m aware that in the end, a simple set of rules and systems is what works best for me. These systems will continue to evolve over time, but I have found that the simpler they are, the more likely I am to stick with them. This post describes my current digital take on dealing with everyday life.</description><content:encoded>&lt;hr&gt;
&lt;h2 id="introduction"&gt;Introduction&lt;/h2&gt;
&lt;p&gt;I used to think that merely using better or more sophisticated tools would magically make me more productive, blaming external factors and technology on my own lack of ability to achieve my dreams. But I&amp;rsquo;ve come to realize that it was only an escape into the procrastination playground to avoid facing hard work. Working &lt;em&gt;on&lt;/em&gt; a system is not the same as working &lt;em&gt;in&lt;/em&gt; a system. The former is a form of procrastination, while the latter is the actual work that needs to be done.&lt;/p&gt;
&lt;p&gt;While there are great approaches including &lt;a href="https://es.wikipedia.org/wiki/Zettelkasten"&gt;Zettelkasten&lt;/a&gt; and the &lt;a href="https://gettingthingsdone.com/"&gt;Getting Things Done&lt;/a&gt; methodology, I have found that I work optimally with simpler systems that are easier to maintain, which reduce cognitive load and friction (less to think about and no complicated setup when inputting information either). I used to be an avid user of &lt;a href="https://todoist.com/"&gt;Todoist&lt;/a&gt; where I would implement GTD almost as a pure devotee, making the most of all its (relatively) advanced features, but that was a double-edged sword as dealing with timezone and synchronization issues was more than enough to derail me from the path, sometimes with dire repercussions when tasks would suddenly disappear or be scheduled at the wrong time.&lt;/p&gt;
&lt;p&gt;Needless to say, I have since moved on to a simpler system that is more robust and that I can trust. I am not technologically turning back, but I have found &lt;a href="https://todoist.com/productivity-methods/weekly-review"&gt;Todoist&amp;rsquo;s weekly review process&lt;/a&gt; to be quite effective and easy to follow, so I have decided to adopt it as a basis for my own system, which I will be describing briefly in this post.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="a-whirlwind-tour-of-the-system"&gt;A whirlwind tour of the system&lt;/h2&gt;
&lt;p&gt;What follows is nothing revolutionary, but the simplicity of it just stuck with me. From prior research on the topic as I was &lt;a href="https://github.com/sglavoie/cm3070-final-project"&gt;building a todo application&lt;/a&gt;, it really stood out to me that the most effective systems were the simplest ones, especially when the different components can be neatly decoupled from each other while working well together as a whole. Arguably, the Apple ecosystem has done a great job at this &amp;ndash; although I&amp;rsquo;m still enthusiastic about creating a single software destination to manage one&amp;rsquo;s life even more efficiently ;).&lt;/p&gt;
&lt;p&gt;In reality, I just stuck with the default offerings for maximum compatibility and ease of use, but the truth is that the existing applications I have been in touch with do not fully address all my needs. As I&amp;rsquo;m not willing to try to bend reality to my will, I have decided to bend my will to reality for the time being and work with what I have. But I digress.&lt;/p&gt;
&lt;div class="image"&gt;
&lt;img src="https://www.sglavoie.com/images/posts/0037_systematic_reviews/overviewReview.svg" alt="Overview of flow for systematic reviews" /&gt;
&lt;/div&gt;
&lt;p&gt;&lt;em&gt;&lt;a href="https://www.sglavoie.com/files/posts/0037_systematic_reviews/systematic_reviews_overview.plantuml"&gt;PlantUML source of this diagram&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;So the main idea here is very simple: twice a day, a daily review occurs and once a week, a more thorough weekly review is performed. Then, at the end of every month and every year, an even more thorough exploration happens both to reflect on the past and plan for the future.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="daily-review"&gt;Daily review&lt;/h2&gt;
&lt;div class="image"&gt;
&lt;img style="max-width: 60%" src="https://www.sglavoie.com/images/posts/0037_systematic_reviews/dailyReview.svg" alt="Flow for systematic daily reviews" /&gt;
&lt;/div&gt;
&lt;p&gt;&lt;em&gt;&lt;a href="https://www.sglavoie.com/files/posts/0037_systematic_reviews/systematic_reviews_daily.plantuml"&gt;PlantUML source of this diagram&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;The purpose behind the daily review is twofold:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;To make sure that the day is planned out and that the most important tasks are completed.&lt;/li&gt;
&lt;li&gt;To do a mindful check on one&amp;rsquo;s wellbeing and re-adjust as needed.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Point &lt;em&gt;1.&lt;/em&gt; is self-explanatory. It serves as a good reminder that task estimation skills are not perfect and that one should not be too hard on oneself if things do not go as planned. Point &lt;em&gt;2.&lt;/em&gt; is a bit more subtle, but it is important to frequently take a step back and reflect on one&amp;rsquo;s current state of mind and body. That may include taking a break, going for a walk, or even taking a nap. The point is to be mindful of one&amp;rsquo;s current state and to take action to improve it if needed. In that department, I like to exercise early in the morning, both to expose my eyes to sunlight and to get my blood flowing (more on this in the excellent &lt;a href="https://hubermanlab.com/"&gt;Huberman Lab podcast&lt;/a&gt;!). Besides sleeping well and eating healthy, I have found that this is the best way to ensure that I am in a good state of mind to tackle the day&amp;rsquo;s challenges.&lt;/p&gt;
&lt;h2 id="make-relevant-context-accessible"&gt;Make relevant context accessible&lt;/h2&gt;
&lt;p&gt;One thing I like to do to stay on top of priorities is to &amp;ldquo;pin&amp;rdquo; a couple of active notes I&amp;rsquo;m using from Apple Notes directly inside the list of widgets shown when swiping left with two fingers on the touch pad (or clicking on the clock in the top-right corner). There, I quickly see notes like &lt;strong&gt;Working notes&lt;/strong&gt; (to accompany the projects I&amp;rsquo;m currently working on), &lt;strong&gt;Standup&lt;/strong&gt; so I can share updates with my team, &lt;strong&gt;@next_action&lt;/strong&gt; which contains a list of stuff I plan to work on next without having to clutter my todo app and another one such as &lt;strong&gt;Ideas&lt;/strong&gt; which I use as a scratchpad to empty my mind of any thoughts that might be distracting me from the task at hand or that might be useful later on.&lt;/p&gt;
&lt;div class="image"&gt;
&lt;img style="max-width: 670px" src="https://www.sglavoie.com/images/posts/0037_systematic_reviews/apple_widgets.png" alt="Apple widgets, shown when swiping left with the touch pad" /&gt;
&lt;/div&gt;
&lt;p&gt;Another major component of the way I organize tasks (currently with Apple Reminders) is to rely on smart lists and split them by areas of responsibilities. So while I may create tasks under specific lists, I tend to simply schedule everything that&amp;rsquo;s either recurring or that will need attention in the near future, storing the remaining ideas and potential tasks in Apple Notes.&lt;/p&gt;
&lt;div class="image"&gt;
&lt;img style="max-width: 462px" src="https://www.sglavoie.com/images/posts/0037_systematic_reviews/apple_reminders_daily_focus.png" alt="Apple Reminders: Daily focus lists" /&gt;
&lt;/div&gt;
&lt;p&gt;So in this case, everything being scheduled for today or that has been flagged manually will appear in the &lt;strong&gt;Today&lt;/strong&gt; list. Anything else that has a deadline in the near future will appear in the &lt;strong&gt;Scheduled&lt;/strong&gt; list. Then, I simply divide my set of &lt;em&gt;work in progress&lt;/em&gt; (&lt;strong&gt;WIP&lt;/strong&gt;) tasks into work and personal and will drag and drop tasks from other lists/projects as needed to re-prioritize them. To avoid having a large list of items in the &lt;strong&gt;WIP&lt;/strong&gt; lists, I use two separate lists to keep track of the &lt;strong&gt;Next&lt;/strong&gt; actions: these are tasks that do not require immediate attention but used to be scheduled as being more urgent, since priorities will often need to shift under a set of constantly new circumstances.&lt;/p&gt;
&lt;p&gt;These tasks will be dragged out of other lists as needed &amp;ndash; either from the backlog of tasks or from the &lt;strong&gt;WIP&lt;/strong&gt; tasks to declutter other lists. They will be prioritized as the &lt;strong&gt;Next&lt;/strong&gt; actions to ensure that once the &lt;strong&gt;WIP&lt;/strong&gt; is done, there is a continuity to the system. Just as with other lists, order matters, so that the most important tasks are at the top and the least important ones are at the bottom. This is a simple way to ensure that the most important tasks are always visible and that the least important ones are not forgotten.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="weekly-review"&gt;Weekly review&lt;/h2&gt;
&lt;p&gt;The weekly review is a bit more involved, but it is still quite simple. The main idea is to take a step back and reflect on the past week, while planning for the next one. This is where I like to take a look at my calendar and make sure that I have not forgotten anything important. Given the current set of tools I use, I don&amp;rsquo;t really implement &lt;a href="https://www.mindtools.com/a9bt6jr/timeboxing"&gt;timeboxing&lt;/a&gt; as I find that I just tend to miss stuff I put into the calendar if it&amp;rsquo;s not an &amp;ldquo;all-day&amp;rdquo; event. Brace yourself, here it goes.&lt;/p&gt;
&lt;div class="image"&gt;
&lt;img src="https://www.sglavoie.com/images/posts/0037_systematic_reviews/weeklyReview.svg" alt="Flow for systematic weekly reviews" /&gt;
&lt;/div&gt;
&lt;p&gt;&lt;em&gt;&lt;a href="https://www.sglavoie.com/files/posts/0037_systematic_reviews/systematic_reviews_weekly.plantuml"&gt;PlantUML source of this diagram&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;This probably looks more intimidating than it really is. I usually go through the whole process in under an hour. That may sound like a lot, but it really helps to declutter my mind while giving me the assurance I did my best to plan for the upcoming week. I also like to do this on Sunday mornings, so that I can start the week with clear focus. All in all, I find that this is a great investment and it becomes especially true if I adhere to doing it in the mornings right after I have a delicious cup of freshly ground coffee (but at least 90 to 120 minutes after waking up: again, see Huberman to get fantastic explanations on why this is ideal).&lt;/p&gt;
&lt;h2 id="automatic-reviews"&gt;Automatic reviews&lt;/h2&gt;
&lt;p&gt;Once more, nothing too fancy is happening here, but having &lt;em&gt;smart lists&lt;/em&gt; makes it very easy to review what is coming up. In this case, it&amp;rsquo;s mostly empty as it excludes all the work in progress, which makes it more useful as well since these are already accessible from their own lists, so the review section really highlights anything that is salient and non-recurring.&lt;/p&gt;
&lt;div class="image"&gt;
&lt;img style="max-width: 538px" src="https://www.sglavoie.com/images/posts/0037_systematic_reviews/apple_reminders_reviews.png" alt="Tags and smart lists from Apple Reminders to review the week" /&gt;
&lt;/div&gt;
&lt;hr&gt;
&lt;h2 id="monthly-and-yearly-reviews"&gt;Monthly and yearly reviews&lt;/h2&gt;
&lt;p&gt;I can see the benefit in asking more questions and taking more time to plan ahead up to a point, but life is totally unpredictable and I find that it is not worth spending too much time planning for the future. Ultimately, everything is ephemeral: interests, hobbies or even relationships come and go. So my current approach is simply to repeat the weekly process with an emphasis on the things I might have neglected a bit more, such as planning new projects, dissolving old ones that no longer require attention and making sure that I am still on track with my goals at a higher level.&lt;/p&gt;
&lt;p&gt;These moments also form a great opportunity to look at finances and make sure that I am not spending too much money on things that do not bring me joy or that I do not need. They also serve as a reminder to take a step back and reflect on the bigger picture, taking a break to look at all the progress that has been made so far. This becomes easier when things are tracked down by writing, and so I maintain a private GitHub repository called &lt;code&gt;life-trail&lt;/code&gt; in which I write down a summary of my weekly reviews, keep track of the most important lessons I have learned and main events that happened in my life. This is heavily inspired from having gone through the &lt;a href="https://www.selfauthoring.com/"&gt;Self Authoring Program&lt;/a&gt;, which I highly recommend to anyone interested in bringing more meaning into their life.&lt;/p&gt;
&lt;p&gt;While (I think) I&amp;rsquo;d love to know for sure where I spend every minute of the day, I tend to track my time with &lt;a href="https://toggl.com/"&gt;Toggl&lt;/a&gt; only when I&amp;rsquo;m at the computer or reading books on my pretty old Nook e-ink reader. It doesn&amp;rsquo;t paint the full picture, yet it is not cumbersome to use and provides the kinds of insights I am looking for while forcing me to be more mindful about the actions I take moment to moment.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;I have tried many different methodologies to get more organized and, after getting no further than where I used to be, I have reached the following conclusion, which can be elegantly summed up with Nike&amp;rsquo;s tagline: &lt;em&gt;Just Do It&lt;/em&gt;. While one might have lofty goals, it all means nothing if one does not take action towards attaining them. This is why I have decided to adopt a more systematic approach in all aspects of life. This is not to say that I will not be using any tools, but rather that I will be using them with a focus on pragmatism and manifesting actual results.&lt;/p&gt;
&lt;h2 id="more-resources-and-references"&gt;More resources and references&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="https://hubermanlab.com/"&gt;Huberman Lab podcast&lt;/a&gt; - Andrew Huberman.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.sglavoie.com/posts/building-task-planner-react-native/"&gt;ProductiviDo&lt;/a&gt; - GitHub.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.selfauthoring.com/"&gt;Self Authoring Program&lt;/a&gt; - Jordan Peterson.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.goodreads.com/book/show/18079767-solving-the-procrastination-puzzle"&gt;Solving the Procrastination Puzzle: A Concise Guide to Strategies for Change&lt;/a&gt; - Timothy A. Pychyl.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://todoist.com/productivity-methods/weekly-review"&gt;The Weekly Review&lt;/a&gt; - Todoist.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.mindtools.com/a9bt6jr/timeboxing"&gt;Timeboxing&lt;/a&gt; - MindTools.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://toggl.com/"&gt;Toggl&lt;/a&gt; - Toggl Time tracking.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://www.readworknotes.com/"&gt;Work Notes by Sam Matla&lt;/a&gt; - Sam Matla.&lt;/li&gt;
&lt;/ul&gt;</content:encoded><dc:creator>Sébastien Lavoie</dc:creator><pubDate>Sun, 14 May 2023 15:58:00 -0600</pubDate><guid isPermaLink="false">https://www.sglavoie.com/posts/systematic-reviews/</guid><category>workflow</category><category>processes</category><category>planning</category><category>software</category></item><item><title>My Current Set of Tools and Customizations</title><link>https://www.sglavoie.com/posts/my-current-set-of-tools-and-customizations/</link><description>I like to keep track of the tools I use and see the shifts that occur over time — may it be switching from a graphical interface to a command-line one or finding a totally new workflow for an existing need. Without further ado, here’s the list!</description><content:encoded>&lt;table&gt;
 &lt;thead&gt;
 &lt;tr&gt;
 &lt;th&gt;Category&lt;/th&gt;
 &lt;th&gt;#1 tool&lt;/th&gt;
 &lt;th&gt;Alternatives&lt;/th&gt;
 &lt;/tr&gt;
 &lt;/thead&gt;
 &lt;tbody&gt;
 &lt;tr&gt;
 &lt;td&gt;3d animation&lt;/td&gt;
 &lt;td&gt;blender&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;audio editing&lt;/td&gt;
 &lt;td&gt;audacity&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;backup (script)&lt;/td&gt;
 &lt;td&gt;rsync&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;clipboard manager&lt;/td&gt;
 &lt;td&gt;copyq&lt;/td&gt;
 &lt;td&gt;clipman&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;cloud&lt;/td&gt;
 &lt;td&gt;dropbox-cli&lt;/td&gt;
 &lt;td&gt;google drive&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;code completion&lt;/td&gt;
 &lt;td&gt;coc.nvim&lt;/td&gt;
 &lt;td&gt;ale&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;code snippets&lt;/td&gt;
 &lt;td&gt;github gists&lt;/td&gt;
 &lt;td&gt;gitlab snippets&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;cursor hider&lt;/td&gt;
 &lt;td&gt;unclutter&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;desktop environment&lt;/td&gt;
 &lt;td&gt;xfce&lt;/td&gt;
 &lt;td&gt;gnome&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;diagram generation&lt;/td&gt;
 &lt;td&gt;plantuml&lt;/td&gt;
 &lt;td&gt;mermaid-js&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;dotfiles management&lt;/td&gt;
 &lt;td&gt;git bare repo&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;dynamic menu&lt;/td&gt;
 &lt;td&gt;dmenu&lt;/td&gt;
 &lt;td&gt;rofi&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;ebook manager&lt;/td&gt;
 &lt;td&gt;calibre&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;encrypted paste bin&lt;/td&gt;
 &lt;td&gt;paste.sh&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;file manager&lt;/td&gt;
 &lt;td&gt;thunar&lt;/td&gt;
 &lt;td&gt;pcmanfm, nautilus&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;file renamer&lt;/td&gt;
 &lt;td&gt;pyrenamer&lt;/td&gt;
 &lt;td&gt;thunar bulk rename&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;flowchart design&lt;/td&gt;
 &lt;td&gt;draw.io&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;fonts monospace&lt;/td&gt;
 &lt;td&gt;jetbrains mono&lt;/td&gt;
 &lt;td&gt;iosevka&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;fonts monospace&lt;/td&gt;
 &lt;td&gt;source code pro&lt;/td&gt;
 &lt;td&gt;inconsolata&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;fonts sansserif&lt;/td&gt;
 &lt;td&gt;lato&lt;/td&gt;
 &lt;td&gt;dejavu&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;gif screen recorder&lt;/td&gt;
 &lt;td&gt;peek&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;image editing (raster)&lt;/td&gt;
 &lt;td&gt;gimp&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;image editing (vector)&lt;/td&gt;
 &lt;td&gt;inkscape&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;interface design&lt;/td&gt;
 &lt;td&gt;figma&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;irc chat&lt;/td&gt;
 &lt;td&gt;hexchat&lt;/td&gt;
 &lt;td&gt;pidgin&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;latex typesetting&lt;/td&gt;
 &lt;td&gt;latex workshop&lt;/td&gt;
 &lt;td&gt;vimtex&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;linux distribution&lt;/td&gt;
 &lt;td&gt;xubuntu&lt;/td&gt;
 &lt;td&gt;debian, manjaro&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;memorizing&lt;/td&gt;
 &lt;td&gt;anki&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;mind mapping&lt;/td&gt;
 &lt;td&gt;freeplane&lt;/td&gt;
 &lt;td&gt;draw.io&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;music player&lt;/td&gt;
 &lt;td&gt;audacious&lt;/td&gt;
 &lt;td&gt;clementine&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;note-taking&lt;/td&gt;
 &lt;td&gt;vimwiki&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;notifications&lt;/td&gt;
 &lt;td&gt;xfce&lt;/td&gt;
 &lt;td&gt;dunst&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;office suite&lt;/td&gt;
 &lt;td&gt;libreoffice&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;operating system&lt;/td&gt;
 &lt;td&gt;gnu/linux&lt;/td&gt;
 &lt;td&gt;macOS&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;paragraph formatter&lt;/td&gt;
 &lt;td&gt;par&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;partition manager&lt;/td&gt;
 &lt;td&gt;gparted&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;password manager&lt;/td&gt;
 &lt;td&gt;keepassxc&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;pdf editing (minimal)&lt;/td&gt;
 &lt;td&gt;pdfarranger&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;pdf viewer&lt;/td&gt;
 &lt;td&gt;atril&lt;/td&gt;
 &lt;td&gt;evince, zathura&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;publishing&lt;/td&gt;
 &lt;td&gt;scribus&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;python documentation&lt;/td&gt;
 &lt;td&gt;sphinx&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;python formatter&lt;/td&gt;
 &lt;td&gt;black&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;python ide&lt;/td&gt;
 &lt;td&gt;pycharm&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;python linter&lt;/td&gt;
 &lt;td&gt;pylint&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;python refactoring&lt;/td&gt;
 &lt;td&gt;rope&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;python test suite&lt;/td&gt;
 &lt;td&gt;pytest&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;python virtualenv manager&lt;/td&gt;
 &lt;td&gt;venv module&lt;/td&gt;
 &lt;td&gt;virtualenvwrapper.sh&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;screen locker&lt;/td&gt;
 &lt;td&gt;slock&lt;/td&gt;
 &lt;td&gt;xflock4&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;screen recorder&lt;/td&gt;
 &lt;td&gt;obs studio&lt;/td&gt;
 &lt;td&gt;simplescreenrecorder&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;screenshot software&lt;/td&gt;
 &lt;td&gt;flameshot&lt;/td&gt;
 &lt;td&gt;xfce4-screenshooter&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;security&lt;/td&gt;
 &lt;td&gt;gnupg2&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;sound system&lt;/td&gt;
 &lt;td&gt;pulseaudio&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;source code explorer&lt;/td&gt;
 &lt;td&gt;sourcetrail&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;sql client&lt;/td&gt;
 &lt;td&gt;dbeaver&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;sql database&lt;/td&gt;
 &lt;td&gt;postgres&lt;/td&gt;
 &lt;td&gt;mysql, sqlite&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;sql viewer&lt;/td&gt;
 &lt;td&gt;sqlitebrowser&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;static website generator&lt;/td&gt;
 &lt;td&gt;pelican&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;task management&lt;/td&gt;
 &lt;td&gt;todoist&lt;/td&gt;
 &lt;td&gt;google keep&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;terminal calculator&lt;/td&gt;
 &lt;td&gt;ipython&lt;/td&gt;
 &lt;td&gt;bc&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;terminal clipboard&lt;/td&gt;
 &lt;td&gt;xclip&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;terminal coursera downloader&lt;/td&gt;
 &lt;td&gt;coursera-dl&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;terminal disk usage&lt;/td&gt;
 &lt;td&gt;ncdu&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;terminal emulator&lt;/td&gt;
 &lt;td&gt;kitty&lt;/td&gt;
 &lt;td&gt;st, xfce4-terminal&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;terminal file archiver&lt;/td&gt;
 &lt;td&gt;p7zip&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;terminal file lister&lt;/td&gt;
 &lt;td&gt;exa&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;terminal file lister tree-style&lt;/td&gt;
 &lt;td&gt;tree&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;terminal file manager&lt;/td&gt;
 &lt;td&gt;vifm&lt;/td&gt;
 &lt;td&gt;nnn&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;terminal file manager (minimal)&lt;/td&gt;
 &lt;td&gt;lf&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;terminal file viewer&lt;/td&gt;
 &lt;td&gt;bat&lt;/td&gt;
 &lt;td&gt;cat&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;terminal fuzzy finder&lt;/td&gt;
 &lt;td&gt;fzf&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;terminal markup converter&lt;/td&gt;
 &lt;td&gt;pandoc&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;terminal network downloader&lt;/td&gt;
 &lt;td&gt;wget&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;terminal network tool&lt;/td&gt;
 &lt;td&gt;curl&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;terminal partition manager&lt;/td&gt;
 &lt;td&gt;parted&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;terminal search tool&lt;/td&gt;
 &lt;td&gt;the silver searcher&lt;/td&gt;
 &lt;td&gt;locate&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;terminal session recorder&lt;/td&gt;
 &lt;td&gt;asciinema&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;terminal shell&lt;/td&gt;
 &lt;td&gt;zsh&lt;/td&gt;
 &lt;td&gt;bash&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;terminal system monitor&lt;/td&gt;
 &lt;td&gt;bashtop&lt;/td&gt;
 &lt;td&gt;glances, htop&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;terminal youtube downloader&lt;/td&gt;
 &lt;td&gt;youtube-dl&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;text editor&lt;/td&gt;
 &lt;td&gt;neovim&lt;/td&gt;
 &lt;td&gt;vim, vs code&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;torrent&lt;/td&gt;
 &lt;td&gt;transmission&lt;/td&gt;
 &lt;td&gt;deluge&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;version control stats&lt;/td&gt;
 &lt;td&gt;gitstats&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;version control system&lt;/td&gt;
 &lt;td&gt;git&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;video player&lt;/td&gt;
 &lt;td&gt;smplayer&lt;/td&gt;
 &lt;td&gt;vlc&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;visual plotting&lt;/td&gt;
 &lt;td&gt;geogebra&lt;/td&gt;
 &lt;td&gt;&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;wallpaper browser/setter&lt;/td&gt;
 &lt;td&gt;nitrogen&lt;/td&gt;
 &lt;td&gt;feh&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;web browser&lt;/td&gt;
 &lt;td&gt;google-chrome&lt;/td&gt;
 &lt;td&gt;firefox, brave&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;window manager&lt;/td&gt;
 &lt;td&gt;i3&lt;/td&gt;
 &lt;td&gt;dwm&lt;/td&gt;
 &lt;/tr&gt;
 &lt;tr&gt;
 &lt;td&gt;window manager status bar&lt;/td&gt;
 &lt;td&gt;i3blocks&lt;/td&gt;
 &lt;td&gt;i3status&lt;/td&gt;
 &lt;/tr&gt;
 &lt;/tbody&gt;
&lt;/table&gt;
&lt;hr&gt;
&lt;p&gt;For a more granular selection of open source projects I&amp;rsquo;ve used and like (Vim plugins, color schemes, command-line tools, etc.), you can also have a look at &lt;a href="https://github.com/sglavoie?tab=stars"&gt;the GitHub repositories I&amp;rsquo;ve starred&lt;/a&gt; over time.&lt;/p&gt;</content:encoded><dc:creator>Sébastien Lavoie</dc:creator><pubDate>Sat, 06 Jun 2020 10:41:00 -0500</pubDate><guid isPermaLink="false">https://www.sglavoie.com/posts/my-current-set-of-tools-and-customizations/</guid><category>tools</category><category>customization</category><category>software</category></item><item><title>Suckless: Minimalist Tools That Work Great</title><link>https://www.sglavoie.com/posts/suckless-minimalist-tools-that-work-great/</link><description>I have been using a few different tools from suckless.org for a while and I must say that once everything is configured properly, they are a joy to use. Some tools, like dmenu and slock, seem simple on the surface, but they allow to simplify your workflow by quite a bit. Another one, st, is a truly fantastic and lightweight terminal!</description><content:encoded>&lt;hr&gt;
&lt;h2 id="what-are-suckless-tools"&gt;What are Suckless tools?&lt;/h2&gt;
&lt;p&gt;From the &lt;a href="https://suckless.org/"&gt;official website&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
 &lt;p&gt;Home of &lt;a href="https://dwm.suckless.org/"&gt;dwm&lt;/a&gt;,
&lt;a href="https://tools.suckless.org/dmenu"&gt;dmenu&lt;/a&gt; and other quality software
with a focus on simplicity, clarity, and frugality.&lt;/p&gt;

&lt;/blockquote&gt;&lt;p&gt;There are also other incredible pieces of software that are worth
mentioning, including &lt;a href="https://st.suckless.org/"&gt;st&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Here, I will only go over the tools I use frequently, but keep in mind
that everything from Suckless&amp;hellip; Sucks less.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="st--simple-terminal"&gt;st — Simple Terminal&lt;/h2&gt;
&lt;p&gt;I did not know what to expect from this terminal and I found it delivers what I need! Configuring it is quite different than other terminals like &lt;a href="https://konsole.kde.org/"&gt;Konsole&lt;/a&gt; or &lt;a href="https://help.gnome.org/users/gnome-terminal/stable/"&gt;GNOME Terminal&lt;/a&gt;: you just edit a text file and compile the software before you can even use it. It may seem tedious at first, but compiling such a small piece of software is very fast and it needs to be done on seldom occasions when you may want to adjust a setting.&lt;/p&gt;
&lt;p&gt;I have experienced rendering issues when scaling the text with other terminals (including Konsole), where some weird flickering would happen at certain font sizes. &lt;a href="https://st.suckless.org/"&gt;Simple Terminal&lt;/a&gt; just works without hassle. It doesn&amp;rsquo;t have much bells and whistles out of the box, but it can be &lt;em&gt;patched&lt;/em&gt; to extend its functionality if you know what you are doing. I don&amp;rsquo;t, so my compiled version remains pretty basic although I must say I like the simplicity of it very much.&lt;/p&gt;
&lt;h3 id="configuration"&gt;Configuration&lt;/h3&gt;
&lt;p&gt;I didn&amp;rsquo;t have to adapt the configuration file very much. I ended up changing mainly the following lines:&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;cpp&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;font&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;Consolas:pixelsize=18:antialias=true:autohint=true&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;shell&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;/bin/zsh&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/* Terminal colors (16 first used in escape sequence) */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;colorname&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="cm"&gt;/* 8 normal colors */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;#1c1c1c&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* black */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;#ff005b&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* red */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;#70e502&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* green */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;#fcdd11&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* yellow */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;#00a0ea&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* blue */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;#bd1efc&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* magenta */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;#14ecfc&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* cyan */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;#ededed&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* white */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="cm"&gt;/* 8 bright colors */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;#666666&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* black */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;9&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;#ff00a0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* red */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;#5dff00&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* green */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;11&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;#ff9f00&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* yellow */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;12&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;#71a9fc&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* blue */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;#d571fc&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* magenta */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;#6cf2fc&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* cyan */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;15&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;#fcfcfc&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* white */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="cm"&gt;/* special colors */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;#0a0500&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* background */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;257&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;#e0e0e0&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="cm"&gt;/* foreground */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * Default colors (colorname index)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * foreground, background, cursor
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;defaultfg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;257&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;defaultbg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;defaultcs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;257&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;defaultrcs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;256&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * Colors used, when the specific fg == defaultfg. So in reverse mode this
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * will reverse too. Another logic would only make the simple feature too
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * complex.
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;defaultitalic&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;defaultunderline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * Default shape of cursor
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * 2: Block (&amp;#34;█&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * 4: Underline (&amp;#34;_&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * 6: Bar (&amp;#34;|&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * 7: Snowman (&amp;#34;☃&amp;#34;)
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;cursorshape&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * Default columns and rows numbers
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;cols&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;80&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;rows&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;24&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="dmenu"&gt;dmenu&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://tools.suckless.org/dmenu/"&gt;dmenu&lt;/a&gt; can be configured in the same way as Simple Terminal by editing a text file and compiling the software. I like to use many keyboard shortcuts, but I find that for launching applications I don&amp;rsquo;t use that often or to launch custom Bash or Python scripts on the fly, nothing beats the simplicity of &lt;strong&gt;dmenu&lt;/strong&gt;.&lt;/p&gt;
&lt;h3 id="configuration-1"&gt;Configuration&lt;/h3&gt;
&lt;p&gt;This one is very easy to configure and doesn&amp;rsquo;t really require any attention at all besides defining where you want it to appear on the screen and what colors you prefer. Here are some smalls changes I made to the configuration in &lt;code&gt;config.h&lt;/code&gt; before compiling it:&lt;/p&gt;
&lt;div class="code-block"&gt;
 &lt;div class="code-block__bar" data-pagefind-ignore&gt;
 &lt;span class="code-block__lang"&gt;cpp&lt;/span&gt;
 &lt;button class="code-block__wrap" type="button" aria-pressed="false" hidden&gt;Wrap&lt;/button&gt;
 
 &lt;/div&gt;
 &lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cpp" data-lang="cpp"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;topbar&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* -b option; if 0, dmenu appears at bottom */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/* -fn option overrides fonts[0]; default X11 font or font set */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;fonts&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="s"&gt;&amp;#34;Consolas:size=12&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;NULL&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="cm"&gt;/* -p option; prompt to the left of input field */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;colors&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SchemeLast&lt;/span&gt;&lt;span class="p"&gt;][&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="cm"&gt;/* fg bg */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SchemeNorm&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;#D8D8D8&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;#000000&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SchemeSel&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;#000000&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;#ff7400&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;	&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;SchemeOut&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;#000000&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;#34;#00ffff&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;},&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/* -l option; if nonzero, dmenu uses vertical list with given number of lines */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;lines&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt;/*
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * Characters not considered part of a word while deleting words
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; * for example: &amp;#34; /?\&amp;#34;&amp;amp;[]&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="cm"&gt; */&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt; &lt;span class="n"&gt;worddelimiters&lt;/span&gt;&lt;span class="p"&gt;[]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;#34; &amp;#34;&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;h2 id="slock"&gt;slock&lt;/h2&gt;
&lt;p&gt;What can be said about slock? It just works and never gets in your way. Set it and really forget it. From the official page:&lt;/p&gt;
&lt;blockquote&gt;
 &lt;p&gt;This is the simplest X screen locker we are aware of.&lt;/p&gt;

&lt;/blockquote&gt;&lt;p&gt;Again, its simplicity is charming and nothing really needs to be changed in &lt;code&gt;config.h&lt;/code&gt; apart from colors and setting the correct username and group name to lock and unlock the screen.&lt;/p&gt;
&lt;hr&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;This was a lighting fast overview of some of the tools I now use on a daily basis. Suckless tools caught my attention and kept it! They offer other specialized software like a web browser, a tool for presentation from the terminal, IRC client and others&amp;hellip; but the ones described here are really those which I now can&amp;rsquo;t live without.&lt;/p&gt;
&lt;p&gt;I was originally inspired to seek out those tools thanks to &lt;a href="https://lukesmith.xyz/"&gt;Luke Smith&lt;/a&gt;, a &lt;a href="https://www.youtube.com/channel/UC2eYFnH61tmytImy1mTYvhA"&gt;fantastic YouTuber&lt;/a&gt;.&lt;/p&gt;</content:encoded><dc:creator>Sébastien Lavoie</dc:creator><pubDate>Sun, 12 May 2019 22:50:00 -0500</pubDate><guid isPermaLink="false">https://www.sglavoie.com/posts/suckless-minimalist-tools-that-work-great/</guid><category>tools</category><category>productivity</category><category>software</category><category>web</category></item><item><title>Surfing with qutebrowser — a Keyboard-Driven Web Browser</title><link>https://www.sglavoie.com/posts/surfing-with-qutebrowser-a-keyboard-driven-web-browser/</link><description>I recently started using this software as my main web browser and, as a Vim (Neovim) user, I must say I am finding the adventure quite compelling!</description><content:encoded>&lt;hr&gt;
&lt;h2 id="what-is-qutebrowser"&gt;What is qutebrowser?&lt;/h2&gt;
&lt;p&gt;&lt;a href="https://qutebrowser.org/"&gt;qutebrowser&lt;/a&gt; is a web browser that makes
great use of &lt;strong&gt;Vim&lt;/strong&gt; commands to navigate. From its website:&lt;/p&gt;
&lt;blockquote&gt;
 &lt;p&gt;qutebrowser is a keyboard-focused browser with a minimal GUI. It’s
based on Python and PyQt5 and free software, licensed under the GPL.
It was inspired by other browsers/addons like dwb and
Vimperator/Pentadactyl.&lt;/p&gt;

&lt;/blockquote&gt;&lt;hr&gt;
&lt;h3 id="why-use-it"&gt;Why use it?&lt;/h3&gt;
&lt;h4 id="perfect-companion-to-any-vim-user"&gt;Perfect companion to any Vim user&lt;/h4&gt;
&lt;p&gt;The first notable feature of &lt;strong&gt;qutebrowser&lt;/strong&gt; is obviously how well
the use of keyboard shortcuts is integrated with the experience of
using the software (there is a useful key binding cheatsheet on the
&lt;a href="https://qutebrowser.org/"&gt;homepage&lt;/a&gt;). Search bindings (&lt;code&gt;/&lt;/code&gt;, &lt;code&gt;n&lt;/code&gt;/&lt;code&gt;N&lt;/code&gt;,
&lt;code&gt;?&lt;/code&gt;), visual mode (&lt;code&gt;v&lt;/code&gt;), tabs (&lt;code&gt;gt&lt;/code&gt;, &lt;code&gt;T&lt;/code&gt;), copy (&lt;code&gt;yy&lt;/code&gt;), open URLs
(&lt;code&gt;o&lt;/code&gt;/&lt;code&gt;O&lt;/code&gt;), &lt;code&gt;J&lt;/code&gt; and &lt;code&gt;K&lt;/code&gt; for switching tabs, etc. Many key bindings will
look familiar to Vim users.&lt;/p&gt;
&lt;p&gt;It even features a &lt;em&gt;command mode&lt;/em&gt;, accessible by typing &lt;code&gt;:&lt;/code&gt;, just like
with Vim. Settings can be set from there directly, help can be accessed
by typing &lt;code&gt;:help [command/setting]&lt;/code&gt;, the configuration file can be
customized on the fly, the position and size of tabs can be set in many
ways, history and settings page can be accessed and navigated through
like any other page (&lt;code&gt;hjkl&lt;/code&gt;, &lt;code&gt;Ctrl + d&lt;/code&gt;, &lt;code&gt;Ctrl + u&lt;/code&gt;, &lt;code&gt;gg&lt;/code&gt;, &lt;code&gt;G&lt;/code&gt;), etc.&lt;/p&gt;
&lt;p&gt;Even though it is based on Python which is a &amp;ldquo;&lt;em&gt;slow&lt;/em&gt;&amp;rdquo; language, most of
the libraries and the web engine rely on C++ and the end result is a
fast and powerful browser that&amp;rsquo;s totally customizable&amp;hellip; Not unlike Vim.&lt;/p&gt;
&lt;h4 id="minimal-interface--more-space"&gt;Minimal interface ⇒ more space&lt;/h4&gt;
&lt;p&gt;Until I upgrade my laptop to a larger screen (≥ 17 inches), my
current setup with its 15 diagonal inches benefits tremendously
from configuring all applications to use pixels as efficiently as
possible — which is why I now use exclusively [i3 as a window
manager](/posts/2019/01/08/using-i3-as-a-window-manager-for-increased-pr
oductivity/).&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;qutebrowser&lt;/strong&gt; doesn&amp;rsquo;t even have a menu bar. By default, it only
displays a small tab bar at the top (which can be moved to another
side or removed) and a thin status bar at the bottom to see the URL,
the current position in the page expressed in percentage, the number
assigned to the current tab, etc. There is also a fullscreen mode
available like in most other web browsers with the key &lt;code&gt;F11&lt;/code&gt;, which will
remove any window decoration and leave you in a (possibly) productive
mode.&lt;/p&gt;
&lt;h4 id="history-bookmarks-and-quickmarks"&gt;History, bookmarks and quickmarks&lt;/h4&gt;
&lt;p&gt;The history page (&lt;code&gt;:history&lt;/code&gt;), while being minimal like all the rest,
loads extremely fast and is a joy to navigate. The bookmarks page (&lt;code&gt;Sb&lt;/code&gt;)
is equally simple yet useful. The way I like to open a bookmark is in
a new tab by typing &lt;code&gt;gB&lt;/code&gt; (&lt;strong&gt;g&lt;/strong&gt;o &lt;strong&gt;b&lt;/strong&gt;ookmark as a mnemonic. Note that
usually all uppercase letters open or do some action in a new space,
such as a window or a tab).&lt;/p&gt;
&lt;p&gt;Where &lt;strong&gt;qutebrowser&lt;/strong&gt; shines in my opinion is with quickmarks. This is
a simple but genius way to find what you are looking for: you type &lt;code&gt;b&lt;/code&gt;
(or &lt;code&gt;B&lt;/code&gt; for new tab) to open a list of pages that are defined with a
keyword, you type that keyword (or can type anything to search for a
page), move around with arrow keys if necessary to select a page, type
&lt;code&gt;Enter&lt;/code&gt; and there you go. As far as I know, Google Chrome doesn&amp;rsquo;t offer
the equivalent (only keywords for search engines). Firefox allows to add
keywords for any bookmark that you have, but there is no good way to
search around for keywords, define them quickly, remove them quickly,
etc. &lt;strong&gt;qutebrowser&lt;/strong&gt; comes with a set of commands that serve just this
purpose (&lt;code&gt;:quickmark-add&lt;/code&gt;, &lt;code&gt;quickmark-del&lt;/code&gt;, etc.), apart from adding
them very quickly by typing &lt;code&gt;m&lt;/code&gt; for quickmarks and &lt;code&gt;M&lt;/code&gt; for bookmarks.&lt;/p&gt;
&lt;h4 id="hinting-system"&gt;Hinting system&lt;/h4&gt;
&lt;p&gt;You may have tried extensions for other web browsers such as Vimium,
Vimperator, or Vimium-FF that let you navigate with Vim shortcuts. They
usually use the letter &lt;code&gt;f&lt;/code&gt; for &lt;strong&gt;f&lt;/strong&gt;ollowing links. Some text appear on
the screen for each visible link and you type the letters that match the
link you want to see. The best way to get how it works is just to try it
out, really.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://www.sglavoie.com/images/posts/0007_surfing-with-qutebrowser/qutebrowser_hints.png"&gt;&lt;img src="https://www.sglavoie.com/images/posts/0007_surfing-with-qutebrowser/qutebrowser_hints.png" alt="qutebrowser-hints" class="max-size-img-post"&gt;&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Well, &lt;strong&gt;qutebrowser&lt;/strong&gt; takes those features and make them even greater!
There is, for example, a &lt;em&gt;rapid hinting mode&lt;/em&gt; you can access by typing
&lt;code&gt;f&lt;/code&gt; followed by &lt;code&gt;Ctrl + r&lt;/code&gt; and it will open links in the background
for as long as you type any matching &lt;em&gt;hint&lt;/em&gt; provided as a letter or
combination of two letters when there are many visible links on the
page. This is especially useful when doing some research to avoid
breaking the rhythm on the current reading while preparing more
resources to be available.&lt;/p&gt;
&lt;hr&gt;
&lt;h3 id="whats-the-best-place-to-start-learning-about-it"&gt;What&amp;rsquo;s the best place to start learning about it?&lt;/h3&gt;
&lt;p&gt;The &lt;a href="https://qutebrowser.org/doc/help/"&gt;help page&lt;/a&gt; on the website
contains all the information you really need. I did stumble upon the
following resources, which I would recommend to read in order of
appearance:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://qutebrowser.org/doc/quickstart.html"&gt;Quickstart Guide&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;[Key bindings
cheatsheet](&lt;a href="https://raw.githubusercontent.com/qutebrowser/qutebrowser/ma"&gt;https://raw.githubusercontent.com/qutebrowser/qutebrowser/ma&lt;/a&gt;
ster/doc/img/cheatsheet-big.png).&lt;/li&gt;
&lt;li&gt;&lt;a href="https://qutebrowser.org/doc/faq.html"&gt;FAQ&lt;/a&gt;, which is interesting
but not indispensable. It did help me take a step forward in trying out
&lt;strong&gt;qutebrowser&lt;/strong&gt; though.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Open inside qutebrowser&lt;/em&gt;: &lt;a href="qute://help/settings.html#bindings.default"&gt;default
keybindings&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;em&gt;Open inside qutebrowser&lt;/em&gt;: &lt;a href="qute://settings/"&gt;settings page&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;&lt;a href="https://qutebrowser.org/doc/help/commands.html"&gt;List of commands&lt;/a&gt;.&lt;/li&gt;
&lt;/ol&gt;
&lt;hr&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;&lt;strong&gt;qutebrowser&lt;/strong&gt; has been around for a while and is very stable. It is
ideal for any Vim user and is a great option for anyone interested in
efficiency and/or in trying out alternatives. Because I am very fond
of relying on the keyboard as much as possible and because I love to
program in Python, I have grown to like this web browser very quickly.
This is clearly a tool designed for a specific type of user in mind and
who knows, you might be one of those.&lt;/p&gt;</content:encoded><dc:creator>Sébastien Lavoie</dc:creator><pubDate>Mon, 11 Feb 2019 14:46:00 -0600</pubDate><guid isPermaLink="false">https://www.sglavoie.com/posts/surfing-with-qutebrowser-a-keyboard-driven-web-browser/</guid><category>tools</category><category>productivity</category><category>software</category><category>web</category></item></channel></rss>