import site.body

Life on the command line: Day To Day Console

As may be apparent by the theme of this site and its currently broken CSS for articles , I am an avid console user, most of my machines don't have X11 installed. I thought i would take the time to document how i do things and provide some tips and hints for anyone else looking to make the switch to what i have refined into a highly productive working environment

Despite popular opinion on the internet telling everyone to use tmux i am a screen user. the main reason behind using screen is that tmux does not have support (as far as i can tell) for 'daemon processes' in the status line. that is, processes that are not called every X seconds and their output displayed on screen but instead they live in the background and each time they emit a new line the placeholder on the status line is updated.

Why is this important? well i have a couple of scripts that give me real time notifications and spend most of their time blocking. many of them have expensive start up times (eg creating a connection to an imap server) that make them a better fit for a persistent process model

There are 2 i use at the moment:

  • cpumon: a real time cpu usage bar
  • checkmail: watches a maildir or mbox dir or connects to an IMAP server and checks for new mail

There are also another 2 that are in the planning stages and i have Initial code for:

  • ticker-messages: ticker tape like display that displays messages from libnotify/dbus
  • nm-console-applet: shows the network connectivity of your machine

There are ways i can emulate this daemon mode in tmux but i have not yet explored them fully (eg split up the window and have one window set to a single line at the bottom of the screen). as i have been having some rendering issues with screen as of late i may be exploring this option sooner rather than later

OK, so i am using screen. So, what does my environment look like then? well i normally leave the first 3 windows free as my 'working environment' with window 1 and 2 being my main windows and window 0 being used less often than the other 2 typically i would be coding on window 1, using window 2 for launching things and running the program being edited and window 0 being used for tailing of things like log output or when i need to quickly make a code change in another file

apart from the first 3 windows my environment is further supplemented with the following programs in the consecutive (4 to 14) windows

  • ipython: for when i need to do lifting that's heavier than bash can provide easily
  • newsbeuter: rss reader
  • elinks: web browsing
  • mcabber: console xmpp messenger
  • mcabber: console xmpp messenger
  • mcabber: console xmpp messenger
  • irssi: irc
  • ssh@tsurugi: My 'heavy lifting' machine and media display unit
  • ssh@tanto: My mail server (mutt crashes on arm for some reason)
  • ssh@gunto: My new 'heavy lifting' machine and media display unit
  • ssh@nodachi: My work machine running tmux

One thing that is not apparent here is that elinks is used as a front end for displaying most text based rich media on my machine. where some people would use less, i use 'elinks -remote ; screen -X select elinks'. this opens the file in elinks in a new tab and causes screen to switch to the 'elinks' window. i use this pattern so often that i have a bash script 'elinks-remote' that consists of the above command and $BROWSER in my environment is set to this command

i find this handy but it may not be to everyone's tastes. where i find it works best is where you want to quickly view a file and leave it open as reference while you tackle an issue. a prime example of this is referring to man pages. i have $MANOPT set to "-H" which will render the output to html and open it in the $BROWSER. this will then switch to elinks where i can find what i am looking for. i can then simply tap 'c' to close the tab or switch back to where i invoked man and continue working while still leaving the man page open for reference.

i find this to be extremely handy. what is even more useful is being able to have multiple man pages open in elinks and switching between them. while i could open a new tab and invoke man there, i have found in practice this is less effective than opening it in elinks as i can very quickly forget which new terminal refers to which man page and having man invoke elinks-remote breaks the flow less (for me anyway) than opening a new window

My rss viewer is a great time saver and makes it so that i don't have to guess what i have and have not read. it makes it easy to glance at a feed for a site and select what i want to view and avoids having to wait for a page to download when i have to click 'next' for the next page

my rss viewer is Further optimized by having my open-url/browser option set to 'elinks -remote %' instead of elinks-remote. this allows me to 'queue' up a bunch of articles to be read sequentially from my rss reader and means i spend less time switching back and forward. just browse all my feeds and open everything that looks interesting, mark everything else as read and then switch to my browser

to further supplement elinks as my PAGER of choice i have added some additional entries to my mailcap file to render the following formats:

  • pdf
  • svg
  • png/jpeg
  • Word documents
  • Excel files

Video and audio files can be viewed as well however i typically download them and put them in the background and view them on a seperate machine that runs nothing but wayland and mpv (mplayer fork) (see 'Gunto' above)

for image viewing i have tried a number of options fbv, fbi, and fim. in most cases i found they conflicted with fbterm or did not like being run from inside screen. however fim worked flawlessly and had a number of useful modes (such as being able to mark files in a series and viewing images side by side) that put it far ahead of the other options

the svg viewer uses the command 'rsvg' to render a svg file to an image file. i have wrapped this in a command called 'fbsvg' that takes an svg file, renders it to stdout and then feeds this to my default image viewer. i don't encounter svg files too often but have found this to work extremely well and allowed me to reuse my image viewer to view other files

for pdf viewing i have 2 separate commands, one renders pdfs to html using pdftohtml (part of poppler) and the other renders pdfs to a series of images. i typically render long documents such as papers from universities (which can be 300 pages long) to html as it is significantly faster than rendering to an image and the content of these documents renders very nicely to html.

other documents such as image heavy slides tend to be a better fit for rendering to a series of png files however rendering to html it typically quick enough that i will preview it there.

the main issue with reading pdfs on the console is that all pages must be rendered before being handed over to elinks for displaying or the image viewer and on long pdfs this can take awhile on an atom cpu (i have had pdfs take 8 minutes to render to images in full). in the case of displaying to html, i can just open a new window and start the rendering job there and have it automatically open in elinks when done (and close the window with a little "&& exit 0" magic).

with rendering to images this is a little harder as an image will be written to the framebuffer as soon as rendering is done. i still use the 'open a new terminal and start the batch render' from the html renderer however the script itself blocks and waits for the image viewer to exit. this is vital as keyboard commands will only go tot eh image viewer when it is the open window. i use the screen updating with the first page as a notification, at which point i switch tot he batch job and read the pdf.

if i don't want to view the pdf and come back to it later i can either ctrl+left, ctrl+right to have fbterm redraw the screen or just request screen redraw its display. switching VTs is the best option however as screen does not necessarily update every character on the display during a refresh.

for word and excel documents there is the catdoc and xsl2csv files, the former providing a text stream and the latter a csv file which can then be opened in any terminal spreadsheet util (there are more than you think), loaded into ipython for processing or rendered to tables in html.

in all my scripts i try and reuse the existing ones, essential all the renders end up in one of two rendering pipelines, HTML or image/png. This makes tweaking for displaying content a lot easier as only one file has to be updated to affect the rendering of a file or the displaying of that file

I tend to have screen (or tmux as i don't need widgets on the remote end) on the machines i ssh into which presents an interesting problem, how does one send ctrl+a easily tot eh remote session when its bound locally? Unfortunately i like using ctrl+a for going to the beginning of the line so i had to find a new key binding for this first. In the end i settled with ctrl+h as its not a keyboard combo i use often, and the fact that 'j' next to it is free (another key i don't use often). This allows me to use ctrl+h to switch local windows and have a script at the remote end (intuitively called 'screen-remote' that does nothing but invoke screen with the args to the script and set the command escape sequence to ctrl+j ('-e ^Jj' for those who are interested) splitting things up like this has allowed me to nest screen sessions with ease up to 3 levels deep in some cases

Another limit i hit quickly was being limited to easily accessing and switching to 10 terminals at a time via ctrl+h, . This was overcome by adding the lines below to my screenrc file to let me switch to windows 11-20 by using ctrl+h, shift+. currently i am using windows 11 and up for ssh session but occasionally i have need of an extra terminal or two to fix something up and having these easily accessible via these buttons mean i tend to switch in and out of them more often.

bind ) select 10
bind ! select 11
bind @ select 12
bind \# select 13 # yes that escape is requried and took me longer than i care 
                  # to admit to discover and fix
bind $ select 14
bind % select 15
bind ^ select 16
bind & select 17
bind * select 18
bind ( select 19

I am currently using a chromebook that has a multitude of custom buttons where the 'Fx' keys are. On my X11 machines (shudder) i have these bound to useful functions such as open terminal, lock screen, close window. all a single button push away. once again this was fairly easy to script, i have some wrapper scripts for adjusting the backlight and volume but everything should be straight forward. mouse toggle is for enabling/disabling the touchpad as the only thing i use it for is copy/paste. as a mouse generates a lot of interrupts (up to 150/s) it prevents the cpu from sleeping and hence i find it to be a massive power hog when typing, hence a quick key binding to turn it on when i need it

# Quick Launches
bindkey -k k1 screen
bindkey -k k2 screen nano
bindkey -k k3 screen text11-run
bindkey -k k4 kill
bindkey -k k5 lockscreen
bindkey -k k6 exec ... backlight down
bindkey -k k7 exec ... backlight up
bindkey -k k8 exec ... wireless toggle
#bindkey -k k9 exec ... mouse toggle
#F10
bindkey -k k; exec ... volume down
#F11
bindkey -k F1 exec ... volume up
#F12
bindkey -k F2 exec ... volume toggle

There are a couple of gems in there, i use and abuse the F1 button as its now my primary way of opening a new terminal. The lockscreen is taken from my 'Text11' code and is a nicer Lockscreen for screen that has the login box centered and integrates fully with PAM allowing me to renew my kerberos tokens on login. Finally i have a 'run' command in the form of text11-run. If you have used the 'run' key binding in gnome you may be familiar with what this does. It opens a dialog and asks you which program you want to run. while it is easy to open a new terminal and run the command you want i find it a bit wasteful to run an instance of bash just to launch another program. text11-run also has some nice extra features such as providing a history of commands you have run and providing tab completion of programs. The eventual aim is to make this the core way to run an app or locate a file to launch with in an editor

All in all i am very happy with this environment, i am significantly faster and more productive working like this and have found after using this setup that a lot of the 'annoyances' of the web (eg adds, popups, stupid UIs) go away with elinks provided you are not visiting a blogger site (Requires JS and lots of it)