Writing a Terminal Application in 2019
Tags: ruby, tools, cli
Published: 2019-06-06 19:39:59

---
title: Writing a Terminal Application in 2019
published: true
description: My motivations, struggles, and progress in making a fully-featured terminal application using Ruby
tags: Ruby, Tools, CLI
series: tknbn
---

I'm building an application that lives and runs inside of the terminal! This will be a blog series that documents my process, struggles, wins, and motivations for doing so when most of us live in feature-rich graphical user interfaces.

## What's Wrong With a GUI?

Nothing is "wrong" with a GUI (graphical user interface). These are the types of applications we're (most likely) most familiar with interacting with these days. Examples would be the browser with which you're likely reading this (unless you use lynx, w3m, or another terminal browser client), your development environment if you're using a tool like [Atom](atom.io) or [VS Code](code.visualstudio.com), photo editors, video editing programs, etc. These are applications that run in their own window and have full, rich graphics, colours, and interactivity.

So why am I creating a TUI (text/terminal user interface) application? Short story is that I'd like to. There are a lot of benefits that come with an application that runs entirely on text within a shell - portability, speed, and vastly lower system resources. Most modern browsers use astronomical amounts of RAM, and depending on what they're doing can also tie up your CPU. How you define "astronomical amounts of RAM" is probably different from how I do, but nobody can deny that their browser is often RAM-hungry. I also value things that run offline. In addition to not needing to be connected to the Internet to even run, it is not affected by any number of security threats that are present with Internet-connected applications.

I also value protection of data. I believe that a user's data is their own, and they should own and be in control of it. Many either don't agree or don't care, but in a world where software users have little power in how their data is collected and used, I place high value on being able to own and control one's own data. When using my application, your data will live on your machine. You own it, it's yours, I don't (and can't) see or touch it. I think that's beautiful.

## What Am I Making?

I am aiming to make a simplified version of a Kanban board manager - something akin to Trello. These tools are extremely useful for planning out and organizing work on projects, and are especially useful for managing a software project. I like using them, but everything I can find is Internet-connected. Most of these (like Trello) are proprietary applications, and I have no idea *where* my data lives, who owns it, and how it's being used. There are ways to find this information occasionally, but they can be complicated and tedious. Complicated and tedious are not things that I value when trying to plan out my projects.

There are Free and Open Source solutions available, and many of these will allow you to set up, configure, and own your own server instance. [Taiga](taiga.io) is one option that I have been using and enjoying lately. But even in creating your own server, you need to be connected to run this application - either via the Internet to a hosted server instance, or locally on your own machine. Both of these are not ideal, as they are either Internet-connected, or are RAM-hungry. If I'm running both a server **AND** a browser instance to connect to said server, I have solved almost no problems and am using even more RAM than before. 

## The Tools

I have chosen to use the [Curses library](https://rubygems.org/gems/curses/versions/1.3.1) for Ruby. I chose [Ruby](https://www.ruby-lang.org/en/) because I love it, and it's a great language. Also my students were building their command-line applications using Ruby, so I wanted to build a project using similar technologies in a similar fashion. I chose Curses because there are a number of applications I use and love that use either Curses or [ncurses](https://www.gnu.org/software/ncurses/ncurses.html). 

Ncurses is software that allowed terminal applications to have more advanced interfaces and features and served as a precursor to modern GUI environments. It is an improvement over the earlier BSD Curses implementation (that is now deprecated). It supports creating sub-windows, forms, creating scroll-able menus, colours, highlighting, and many other features.

## The Current Struggles

I have never used Curses/Ncurses prior to diving into this project. The existing [Ruby documentation](https://www.rubydoc.info/gems/curses) for the Curses library seems to assume a prior familiarity with the C implementation of Curses, as it is more or less a list of methods and signatures. This makes discovery of features and knowing the abilities/limitations of the library difficult. I found [this tutorial](https://stac47.github.io/ruby/curses/tutorial/2014/01/21/ruby-and-curses-tutorial.html) from another friendly developer that was extremely helpful in just getting off the ground.

Beyond that, I have been finding examples of programs in C that do what I want to do, reading and understanding them (as best I can, I don't know C beyond a cursory understanding), and trying to match those features to methods available in the Ruby docs. It's been a fairly slow process and discovery takes a while, but it's been working! My goal in this blog series will be to illuminate some various features of the Ruby Curses library and hopefully make breaking into writing rad terminal applications with Ruby less intimidating. 

## Show Me The Code!

At the time of writing this (June 6, 2019), this application is very bare-bones. It lives on [here on GitHub](https://github.com/aspenjames/tknbn), is licensed under the [GNUGPL v.3](https://www.gnu.org/licenses/gpl-3.0.en.html), and as such is free for you to (more or less) do what you like with it. Fork it, improve it, redistribute it, read it, copy it, etc. 

Most of my current work is in the `curses-playground` branch, and as the name suggests, it's a playground. I'm leaving some descriptive comments, but it's far from structured or DRY. Once I get an MVP working there, I'm going to restructure and rewrite onto `master`. Is this ideal? No. Is it working for me? Yes. Should you program this way? Up to you! 

I chose to have a space to just dump code and play around with the library, because that's the way I learn best. I like to break things and find limitations, write sloppy code, and clean it all up later. It really helps me to get out of reading forever and into actually building something, but that may not be the ideal path for everyone. I'm interested in hearing other folks' workflows, I'm not particularly interested in anyone's opinion of my own. Do what makes you happy!