There is a certain digital Zen experience that is achieved sitting in front of a terminal command prompt with a desktop free of icons and other GUI-enabled distractions. If you are my age, a green fluorescent terminus font glowing on a liquid black screen brings fond memories of late nights spent as an undergraduate programming on VMS minicomputers. My father, who spent much of his life repairing radio equipment, once told me that he lost interest in radios when the transition from tubes to transistors occurred – in his view they had become lifeless . For me, a similar ethos surrounds the command prompt. So, I recently put aside my mouse and attempted to turn back time and become GUI-free once again. Thus far, I can report that I am enjoying the experience immensely, due in large part to the rock-solid performance of the tried-and-true software tools of the unix environment and a few exceptional newer ones.

In this post, written in an xterm terminal emulator using emacs25-nox in markdown mode and the jekyll static web page generator, I will attempt to outline the software that I installed and configured to create a command line environment allowing me to do everything from checking my google calendar to reading my gmail without touching a web browser. As a bonus, every component of software I am using is open source – most use the GNU GPL. Stick it to the man! I assume the reader has basic familiarity with unix and has already installed a unix operating system but is perhaps still more GUI-reliant than she/he would prefer.

Centering in the terminal emulator

A terminal emulator, as the name suggests, mimics the behavior of the teletype terminals or ttys that were repurposed in the 1960s to allow direct interaction with early mainframes and mini computers via commands typed on a keyboard and echoed to a screen. The unix environments that I work in (OS X and Debian linux) come with perfectly adequate terminal emulation applications pre-installed. The most important trait is stability; the terminal will be the foundation for all your work – you obviously don’t want a terminal to crash in the middle of writing that critical piece of code. Avoid new software releases here unless you are a compulsive risk-taker. The default terminal does not have to be boring. You can use the preferences option in the menu bar to pimp your terminal, changing fonts and colors. I installed one newer terminal emulator in Debian – the terminator – which has nice features for creating new tabbed consoles and splitting consoles into frames (much the way that the emacs editor can split a screen into panels). There is a version of the terminator for OS X written in Python which is not stable in my experience and I do not recommend it. To install terminator in Debian or Ubuntu you can use the command line tool aptitude for package management:

sudo apt-get install terminator                                                                                                                                      

The terminator configuration file can be edited directly and is by default located in the hidden folder .config in your home directory. For example,

(15:49 bruce@pI:~)$ tree ~/.config/terminator                                                                                                                        
/home/bruce/.config/terminator                                                                                                                                       
└── config                                                                                                                                                           

If your are a traditionalist and/or want a light, stable high-performance terminal with an admirable pedigree, I strongly recommend installing xterm which is my personal favorite terminal emulator:

 sudo apt-get xterm                                                                                                                                                  

The xterm program has been around since the mid-1980s and is highly configurable. I don’t recommend going too deep into the configuration options (which can be pretty arcane) unless you happen to be an X windows Guru. However, some configuration is necessary as the default font is pretty tiny. Here I outline some simple customizations for xterm, which is the terminal I use most. It is possible to configure xterm in many ways, including command line options at start-up or by choosing from the configuration menus initialized by pressing Control-(left|right|middle)-mouse-key with the cursor in the xterm window. A third strategy, which I prefer, is to create a ~/.Xresources file containing configuration options. This file is automatically read to set your configuration options each time you start xterm. Here is the content of my .Xresources file:

 (19:57 bruce@pI:~)$ cat ~/.Xresources                                                                                                                               
 ! Use a nice truetype font and size by default...                                                                                                                   
 xterm*faceName: DejaVu Sans Mono                                                                                                                                    
 xterm*faceSize: 10                                                                                                                                                  
 ! Every shell is a login shell by default (for inclusion of all necessary environment variables)                                                                    
 xterm*loginshell: true                                                                                                                                              
 ! I like a LOT of scrollback...                                                                                                                                     
 xterm*savelines: 5000                                                                                                                                               
 ! double-click to select whole URLs :D                                                                                                                              
 xterm*charClass: 33:48,36-47:48,58-59:48,61:48,63-64:48,95:48,126:48                                                                                                
 xterm*vt100*geometry: 100x40                                                                                                                                        
 xterm*eightBitInput: false                                                                                                                                          
 ! black text on gold background...                                                                                                                                  
 xterm*foreground: black                                                                                                                                             
 xterm*background: #ffaf00                                                                                                                                           

The effect of most options should be apparent from the comments (preceded by !). The obscure statement xterm*eightBitInput: false is needed to get proper behavior from the TAB-F key command in emacs. For the options specified in .Xresources to take effect the changes must be updated in the X windows resources database by issuing the command:

xrdb -merge .Xresources                                                                                                                                              

The resulting terminal is shown below. Beauty incarnate!

xterm

If you want a one-off change in terminal colors you can provide command line options to xterm on start-up such as xterm -bg black -fg white. For more convenience, I define a function alias in my shell configuration file. If you use the bash shell add the following line to .bashrc

function bwterm() { command uxterm -fg black -bg white "$@" & }                                                                                                      

Now you can start a black and white xterm session by typing bwterm instead of xterm. Before moving on, a few comments on the desktop – most people’s are too busy. Clean desk clean mind right? I prefer no menus or icons visible on my desktop. To achieve this, in the Debian Xfce GUI, choose Applications/Setting/Desktop and within the menu box choose the Icons tab and uncheck all default icons.

icons

To automatically hide menus choose Applications/Settings/Panel and for each panel choose the option Automatically hide the panel: Always which will cause the panels to disappear unless the mouse is held near the edge of the screen.

panels

The other method to reduce desktop clutter is behavioral. Use multiple workspaces, partitioning them for different purposes. Learn the hotkeys for moving among workspaces. If you have a traditional keyboard the function keys are convenient for this purpose. In Xfce Ctrl+F(N) represents the action Go to workspace N (1-9), Alt+Insert adds a workspace and Alt+Delete deletes a workspace. The commands Ctrl+Alt+> and Ctrl+Alt+< move to the adjacent workspaces at the right and left of the current workspace, respectively. In general, learn and regularly use as many hotkey combinations as possible – it improves your memory and helps prevent repetitive stress injury.

The Tao of Emacs for everything

Unix users are passionate about their terminal-based editors and, in particular, the 40+ year war between users of vi and Emacs, each claiming their preferred editor to be superior, continues. According to Wikipedia users are split about 50-50 between vi and Emacs. I happen to be an Emacs user – have been for 25+ years – and have no plans to switch. So, while I encourage those who are undecided to try both editors and choose their poison, I will only discuss Emacs here. My goal will be to document the Emacs system that I needed to configure to allow it to be my principal work tool (for writing emails, editing source code, writing manuscripts in LaTeX, checking my calendar, logging to-do lists, etc).

Software minimalism

I have always been attracted by the idea, central to Emacs, of doing almost everything in one editor. To work efficiently in any editor requires learning a lot of key combinations, commands and macros, configuration options, and so on. I certainly do not want to have to learn to use multiple different editing environments for different purposes – not if I can avoid it. Call me lazy, but I would rather spend my time at the computer terminal learning new programming languages, or doing work. The manual for GNU Emacs, which is my preferred Emacs distribution, describes Emacs as the advanced, self-documenting, customizable, extensible editor. The customizable and extensible features of Emacs are what allow for the possibility of using it as the one editor of everything. The risk with Emacs is overextension. There are literally tens of thousands of emacs packages that extend the program using the programming language ELISP. Some are old, some are new, some are maintained, others are not. It is easy to become overzealous installing extensions that are not stable, useful or supported.

Having learned the necessity of researching packages by painful experience, I tend to spend quite a bit of time Googling the packages available for a particular purpose before even opening the package manager – I suggest that you do the same to avoid package bloat and a lot of time wasted configuring extensions that ultimately lack utility. Extension packages can be loaded from within Emacs using the command M-x list-packages and by default the relatively small ELPA archive is available which contains the built-in (pre-installed) packages as well as other standard packages that are well established. The MELPA archive can be loaded as well by placing the lines

(require 'package) ;; You might already have this line                                                                                                               
(add-to-list 'package-archives                                                                                                                                       
         '("melpa" . "https://melpa.org/packages/"))                                                                                                                 
(when (< emacs-major-version 24)                                                                                                                                     
;; For important compatibility libraries like cl-lib                                                                                                                 
(add-to-list 'package-archives '("gnu" . "http://elpa.gnu.org/packages/")))                                                                                          
(package-initialize) ;; You might already have this line                                                                                                             

in either the file ~/.emacs.d/init.el or .emacs depending how your system is configured (OS X uses .emacs and Debian uses init.el). Many extensions (hereafter called modes) exist in the built-in modes of the GNU Emacs distribution. For example, modes for editing code in most commonly-used programming languages are built-in and auto-loading. For example, when I open a C++ file I see nice syntax highlighting in C++ mode: cpp The built-in GNU Emacs modes cover most of my work-related needs (programming, etc) but I needed to add some packages for specific tasks. These were my specific needs:

  1. Display my schedule from Google calendar.
  2. Maintain organizing outlines for research projects
  3. Create to-do lists with due dates.
  4. Display daily agenda including both to-do items and calendar events.

The package that I decided to use to tie all these items together was org. This package is well-established and maintained and is part of the default ELPA repository. Org includes a planning outlining markup-type language (org) and **TODO flags that can be placed in any documents. The org-agenda function can display a global list of to-dos contained in one or more files which seemed like a great way to track progress on multiple projects. Org can also optionally combine to-dos with other events from a calendar.org file to provide a daily agenda. Perfect for my needs. Org files can be translated into HTML, LaTeX or Markdown if needed which is helpful in sharing progress reports with colleagues.

A disadvantage of org is that the org language is not widely used so you will not be directly sharing your org docs with anyone other than Emacs geeks. I can live with that since there are so many export formats. I work on several different computers and wanted my org files accessible on all of them. Initially I used a shared Dropbox folder for this, and that was fine until I decided that I wanted to be able to work on a Google Cloud virtual machine sometimes as well. Dropbox was not an option there. So, I decided to use a git repository for my files instead. This gives me the added bonus of revision history. I created the folder ~/gitrepos/orgmode and set it up as a git repository. For an explanation of how to do this see. To configure org I added the following lines to my Emacs configuration file:

(setq org-default-notes-file "~/gitrepos/orgmode/notes.org")                                                                                                         
(define-key global-map "\C-cc" 'org-capture)                                                                                                                         
;; Log done state in TODOs                                                                                                                                           
(setq org-log-done t)                                                                                                                                                
;; Set Org-Capture templates                                                                                                                                         
(setq org-capture-templates                                                                                                                                          
      `(("t" "todo" entry (file+headline "~/gitrepos/orgmode/notes.org" "Tasks")                                                                                     
     "** TODO %^{Task} %?")))                                                                                                                                        
(setq org-agenda-files (list "~/gitrepos/orgmode/notes.org"                                                                                                          
                 "~/gitrepos/orgmode/calendar.org"                                                                                                                   
                 "~/gitrepos/orgmode/worktodo.org"                                                                                                                   
                 "~/gitrepos/orgmode/personaltodo.org"                                                                                                               
                 ))                                                                                                                                                  
;; Set key combos                                                                                                                                                    
(define-key global-map "\C-ca" 'org-agenda)                                                                                                                          
(define-key org-mode-map (kbd "C-c t") 'org-insert-todo-heading)                                                                                                     

Emacs configuration files are written in a variant of the lisp programming language. You don’t need to learn lisp to write one however, just follow this example (and others available online) modifying the paths for files. Comments in lisp files begin one or two semicolons. The lines (setq org-default-notes-file "~/gitrepos/orgmode/notes.org") and (define-key global-map "\C-cc" 'org-capture) define the default location for notes “captured” by the org-capture function and the key map for capturing, in this case Control+c c. The line (setq org-log-done t) causes org to add a time stamp when a to-do item is completed. The statements

(setq org-capture-templates                                                                                                                                          
      `(("t" "todo" entry (file+headline "~/gitrepos/orgmode/notes.org" "Tasks")                                                                                     
     "** TODO %^{Task} %?")))                                                                                                                                        
(setq org-agenda-files (list "~/gitrepos/orgmode/notes.org"                                                                                                          
                 "~/gitrepos/orgmode/calendar.org"                                                                                                                   
                 "~/gitrepos/orgmode/worktodo.org"                                                                                                                   
                 "~/gitrepos/orgmode/personaltodo.org"                                                                                                               
                 ))                                                                                                                                                  

define an option to create a new to-do item when org-capture is applied and provide a list of the files that org-agenda will search when constructing a global to-do list, etc. Finally, the statements

(define-key global-map "\C-ca" 'org-agenda)                                                                                                                          
(define-key org-mode-map (kbd "C-c t") 'org-insert-todo-heading)                                                                                                     

define key combination Control+c a to open org-agenda and Control+c t to insert a to-do item in an org file. I decided to use the packages calfw and calfw-org to display my calendar. These packages are available in the MELPA archive.

To display a Google calendar it must first be imported into a local file (mine is named calendar.org). Initially, I tried the org-gcal package for this which allows both importing and exporting of calendars. However, I found it unreliable and was happy enough entering events through the browser and just incorporating my calendar for display-only use in org. So, I instead wrote a shell script to retrieve my secret calendar as an ical file from Google and then translate it into an org file. The bash script is

#!/bin/bash

wget -P ~/gitrepos/orgmode/ https://calendar.google.com/calendar/ical/<insert address for your private file basic.ics>
~/bin/ical2org.py ~/gitrepos/orgmode/basic.ics ~/gitrepos/orgmode/calendar.org
rm -f ~/gitrepos/orgmode/basic.ics

You will need to install the python script ical2org for this script. You may also need to install wget. Once you have created this script put it in a directory in your shell path (I use ~/bin) and make it executable. If the file with your shell script is called gical usechmod +x gical. Now you can just type gical to update your calendar.org file. I work on different machines and want to share my org files across machines. As mentioned above, I use git for this purpose and created a .gitignore file in the orgmode directory containing the single line calendar.org so that my calendar.org file is not archived.

Web sites from the command line

For a few years now I have been running WordPress to host my website. I find it a huge improvement over Drupal and other CMSs I have tried but I would prefer something simpler with the need for less frequent updates. Also, my web hosting service NearlyFreeSpeech charges extra for dynamic content, and an SQL database seems like overkill for my simple needs. After exploring options, I decided to move to Jekyll. Jekyll is a system (written in the Ruby language) for generating static websites using content written in Markdown (or Textile), configuration files written in YAML, layout and stylesheets written in HTML and CSS, and templates written in Liquid. This is the system used for web pages on github and also allows the option of free and convenient hosting of your website on github if desired. Although this tool uses a lot of other tools that are probably unfamiliar if you do not develop web pages for a living it is surprisingly easy to construct a simple blog-oriented website using the default Minima theme. The 4 line quick-start instructions from the Jekyll website say it all:

gem install jekyll bundler                                                                                                                                           
jekyll new my-awesome-site                                                                                                                                           
cd my-awesome-site                                                                                                                                                   
bundle exec jekyll serve                                                                                                                                             

The Ruby installer system gem is used here on the first line to install the Jeckyll system. You will need to have ruby installed your machine. You can check for Ruby using ruby -vwhich will print the version of Ruby installed on your system. the second line creates a default website template in a folder my-awesome-site and the fourth line creates the site and starts a local webserver at localhost:4000 that you can visit to preview your site. Everything needed to generate your website is in a series of nicely organized folders and you can use git to archive the site. Executing Jekyll generates a static website that you can simply upload to your server (using sftp for example). Unfortunately, the Minima theme was a bit too simple for my needs. There are two basic types of webpages: posts and pages. By default all pages are added to a set of navigation links displayed in the header. I wanted subpages referenced in other ways. There is a new option one can place in the in the _config.yml file

header_pages:                                                                                                                                                        
 - page1.html                                                                                                                                                        
 - page2.html                                                                                                                                                        

That explicitly allows pages to be specified for display in the menu but for some reason I could not get that working so I had to add the directory and file include\header.html to the site root directory and modify a portion of the Liquid script in the minima header.html file to be

        <div class="trigger">                                                                                                                                        
          { for path in page_paths }                                                                                                                                 
            { assign my_page = site.pages | where: "path", path | first }                                                                                            
      { if my_page.inmenu==1 }                                                                                                                                       
          { if my_page.title }                                                                                                                                       
            <a class="page-link" href=""></a>                                                            
            { endif }                                                                                                                                                
        { endif }                                                                                                                                                    
          { endfor }                                                                                                                                                 
        </div>                                                                                                                                                       

I have removed the % character from the control statements here to allow the code to be displayed. To include a file in the menu you add inmenu: 1 to the YAML front matter in the file, to exclude it add inmenu: 0. Now install the Markdown mode package for Emacs and you are all set to write and process your web pages at the command line. I also added a jekyll plugin for processing bibliographies in latex format to produce a publication list for display in html. This allows one to, for example, download a bib file generated from your Google Scholar page and transform it into a formatted list of publications. To do this, you create a subdirectory named _bibliography in the root directory of the website and place the bibtex formatted file, for example myrefs.bib, in that directory. Then add the following to the Gemfile in the site root:

group :jekyll_plugins do                                                                                                                                             
   gem "jekyll-feed", "~> 0.6"                                                                                                                                       
   gem "jekyll-scholar"                                                                                                                                              
end                                                                                                                                                                  

Add the plugin to the plugins directory list in the _config.yml file as well:

plugins_dir: [jekyll-scholar]                                                                                                                                        

To display the references on a page add the code snippet below to the Markdown file,

{ bibliography --file myrefs  }                                                                                                                                      

Here again the % symbols have been removed to allow the code to be displayed. There are lots of options for the format of the bibliography, this example uses the de\ fault. See the documentation for the jekyll-scholar plugin for more details.