...making Linux just a little more fun!

Henry's Techno-Musings: My Help System

By Henry Grebler

Techno-Musings image

Preamble

If a doctor or an electrician came to your house empty-handed, you'd be a bit bemused, right? (I suppose, these days, if a doctor came to your house, you'd be astonished! But let's not get side-tracked.) You expect the professional and the tradesman to come with tools. How else is she going to do her job?

Yet, in the computer industry, people show up on their first day at work in a suit. And that's it. And, sometimes, not in a suit.

Strangely, not only are we not expected to bring our own tools, often the very idea of computer people relying on tools is considered a deficiency, a weakness. What?! You look phone numbers up in a directory! What a wuss! A real sysadmin would just memorise the phone book!

Context

I do not come to work empty-handed; I come with a large toolkit. Most of what I know fits into several classes. It also fits on a CD.

These are the components of my toolkit:

  1. HAL - Henry Abstraction Layer
  2. Muscle memory
  3. Help System
  4. History files

This article is about the third of these.

Motivation

Someone comes to me and asks, "What do you know about SAN, Henry?"

"I don't know," I reply. "Let's have a look."

	help san

I am presented with help on the Sandringham train timetable and nuisance calls, in addition to quite a lot of practical information on SAN accumulated over many years.

My help command is analogous to something which is a cross between apropos and some implementations of man. It has the wildcarding properties of apropos, but gives full answers like man rather than the headings returned by apropos.

It's different from man and complementary. man contains reference information; the information returned by help is more like what you might find in a HOWTO or a quick-start guide. man tends to contain complete information on a topic; the information returned by help is often fragmentary, incomplete and very basic.

Unlike man which is purely technical and only for the machine I'm on, help is not restricted to a single platform; nor is it restricted to technical matters. People who know me might be shocked to learn that I have help on Microsoft offerings. I also have help on how to use my bank accounts.

Invoking help

To use my help command, I type

	help string
where string is any string which I think might be relevant. For example,
	help rpm
should give me help on rpm.

My help directory

My help directory is $HOME/help. I was not very consistent at first. Arguably, I'm still not. From what I can see, my earliest entry is dated 14 Aug 1992.

These days, I work like this. Each entry is a file. Each file that I want to be able to look up has help_ as the first part of its filename. There may have been a reason for this, though, honestly, I don't recall. Perhaps I thought there could be other entries (non-text files like PDFs) that I would access some other way. I also had subdirectories. I guess I did not want them "getting in the way" when I was looking stuff up (so their names never began with help_). I don't use subdirectories very often these days; I can't recall the last time I did.

There's a subdir called FIREFOX which contains some html files; another called HTML which includes Quick_HTML_Reference.html; another called fedora-install-guide-en_US. But these subdirs are on the periphery of my help system.

The main game is the body of help_* files.

The "rules" are very simple:

My help command

My help command is implemented as a bash function defined in one of my many startup scripts (which form part of my HAL).
function help {
# Assume no arg means standard bash help

        if [ "$1" = "" ]
        then
                builtin help
                return
        fi
        echo 'For bash help, use builtin help'

# avoid backup files:   
        (set -x; less `ls ~/help/help_*${1}* | grep -v '~$'`)
        if [ $? -ne 0 ]
        then                    # try for bash help
                builtin help $1
        fi
}

The first few lines deal with the fact that I have appropriated bash's builtin help command. So, if I just type help, I get bash's help.

The line with the parentheses does the work. I'll come back to it.

The last 4 lines are supposed to help me coexist with bash. In theory, if I don't have help on the subject in my database, maybe I meant the bash command. In writing this up, I have discovered that this part doesn't work! This supports somebody's law that every non-trivial program has bugs.

It also supports the notion that something does not have to be perfect to be extremely useful. "Perfect is the enemy of good", as Ben said recently.

The main command

	less `ls ~/help/help_*${1}* | grep -v '~$'`

Let's start at the inside.

	ls ~/help/help_*${1}*

This lists all files in ~/help (ie $HOME/help) which start with help_ and have the specified string somewhere in the rest of the filename.

I use emacs as my editor. It creates backup files which have tilda (~) as the last character of the filename. I don't want to see these backup files; the grep removes them from the list.

The less command then displays the files left in the list, sometimes one file, often several.

Before I talk about my less command, I'll make one more comment about the line with the parentheses. It starts with set -x. Long ago, when I first met Unix (before Linux existed, I think), I read somewhere that Unix commands do their work quietly. That isn't how I like to operate; I like lots of confirmation: this is what I did, this is the command I used, these are the files on which I operated.

I don't expect others to share my preferences. Those who prefer silence can omit the set -x.

My 'less' command

Using less on several files would be vastly less useful without a little wrinkle.

I prefer to use less(1) as my $PAGER. However, standard less needs a little help. I want to be able to move from one file to the next and back quickly. By default, less uses :n and :p for this, but that's 3 keystrokes, and there is no way that 3 keystrokes can achieve what I want. I guess I could program the function keys to generate :n and :p, but there are issues with that.

I prefer to use the LEFTARROW and RIGHTARROW keys. By default, less uses these to mean "scroll horizontally", but I never want to be able to scroll horizontally in less, so I appropriate those keys.

I want RIGHTARROW to mean "next file" and LEFTARROW to mean "previous file".

If you want to do things my way, get hold of my .lesskey file and either copy it to your home directory or use it to edit your own .lesskey file - see lesskey(1). Either way, check what's there: you may not want everything I have. See below.

Then run lesskey to compile the .lesskey file into something less can use.

Analysis

In my view this is a wonderful example of appropriate technology. It's appropriate when all factors are taken into consideration. The most important factor is the customer. I designed this to be used by me, no one else. Of course, "design" is a gross overstatement; the mechanism grew organically.

Most of my interaction with computers is via the command line, typically running in an xterm. Whenever I can, I use bash. That's pretty nearly always: bash is the default shell on Linux (that which we think of as /bin/sh is really bash); it is now standard (/bin/bash) on recent versions of Solaris; and is readily available on BSD. When I'm not typing commands, it's probably because I've invoked emacs.

Whether I'm in emacs or in bash, most of the commands I use are the same.

So, editing a help file involves one of my bread-and-butter activities; nothing new to learn.

Probably the next most common thing I do is use less to browse files. It is my mail reader of choice (unless I absolutely can't use less). Consequently, reading my help files also involves one of my bread-and-butter activities.

Most importantly, it's wonderfully portable. I can take the whole help directory (and other stuff) on a CD wherever I go and copy it to local disk in no time.

The system is deliberately as unstructured as possible. There is a danger that if I make entering information too onerous, I won't do it. In many organisations, generally helpful information must be entered in some markup language. If I have to organise my help information at the time I'm recording it, I'm going to have to suspend doing whatever task I'm working on. That won't do.

Typically, I just swipe and paste text from where I'm working into a file. I'm just creating aids for myself - the equivalent of rough notes one might write on a scrap of paper.

If, some time later, I return to a help file because I'm working in the same area, I might clean the information a little. Or not.

The major purpose is to save time. If I spend a long time trying to work out how to do something, I don't want to have to repeat that exercise in the future.

Of course I'm human and fallible. Sometimes I'm so happy that I got the thing to work, I just jump in and use it; I forget to record useful information. But, hopefully, I'll catch it next time.

Typical use

Let's take an example. I've recently moved to FreeBSD. I'm a bit of a newbie. Let's see what I feel I need to know.

	ls -lat $HOME/help/help_*bsd* | grep -v '~' | cut -c 30-
 3897 Mar 21 07:35 /home/henryg/help/help_freew_bsd_diary
 3030 Mar 19 14:50 /home/henryg/help/help_bsd_build_notes
  100 Mar 19 11:12 /home/henryg/help/help_bsd
  113 Mar 17 16:38 /home/henryg/help/help_bsd_admin
  261 Mar 17 10:37 /home/henryg/help/help_bsd_build

So when I go help bsd, the effect is to load the above 5 files into less. Because I can use the left- and right-arrow keys to navigate from one file to the next, and because these keys auto-repeat, I can get to any file very quickly. Since I put this stuff in, it follows that I know what's there (more or less). The way my brain works these days, I'm much better at recognising and selecting than I am at recalling.

If I'm looking at a file with less, and I decide I want to modify the file in some way, I can simply type v and I'm in emacs ready to edit.

If all else fails, I can grep through the help files since they are just text files. Or I can list the help directory to see if any of the filenames trigger recognition.

This rarely happens, but let's say I'm looking for some info on xxx and help xxx doesn't produce anything useful. I resort to grep and find the info. Why didn't help xxx deliver the relevant file? I realise that I have "misfiled". For instance, I stored some info in help_audio but I subsequently look for it with help sound. Ok, simple solution:

	mv help_audio help_audio_sound
I can now find the relevant help by using either string (or a substring). For instance, either of these commands will deliver the above file (and possibly others):
        help aud
        help soun

I can "file" some information under a dozen categories (strings) virtually for free. I simply need to include more items in the name of the help file.

The contents of help files

Please remember that the information in a help file is what I believe will be useful to me at some time in the future. If you are interested in such a mechanism for yourself, I expect you to put into your help files the sort of information that you will find useful. That could be quite different.

Just so you get the flavour, here's the first part of help_rpm:

### For complicated stuff see help_rpm2
### For Uninstall see help_rpm_uninstall
------------------------------------------------------------------------

RPM=wxpythongtk-2.4.2.4-1.rhfc2.nr.i386.rpm

rpm --query -p $RPM   -i
rpm --query -p $RPM   -l | cut -d / -f1-3 | uniq | head
rpm --query -p $RPM   -l | wc
rpm --query -p $RPM   -l

# Test Install
#                               rpm -i --test $RPM      # Use the long option
rpm --install --test $RPM
# Really install
#                               rpm -i $RPM             # Use the long option
rpm --install $RPM

++++++++++++++++++++++++++++++++++++++++++++++++
Tough installs for extreme situations:

rpm -i $RPM --force
rpm -i $RPM --nodeps            # Don't check dependencies

Typically, to perform an install, I set the variable RPM, then copy and paste each of the rpm commands into an xterm. If I want, I can pretty much turn my brain off and run on autopilot.

More importantly, it saves me a lot of typing; it minimises typos; and it allows me to concentrate on more global matters, not the mechanics of an install.

One more example: here's help on the string pub. (Yours might tell you about watering holes.) I have two help files concerned with public transport: help_public_transport and help_aaa_public_transport. I created the first one first. It has some detailed information on bus routes. It's the one I usually don't want to see. So, when I created the second file I put aaa at the start of the string so that it will always show as the first file in less (because of the way ls works).

When I want to go somewhere by public transport, I visit Viclink Journey Planner. It's a marvellous resource, but it can be a little too general at times. To get answers more quickly, it helps to provide detailed strings, strings that I would never bother to remember and could probably never type correctly. So my help shows me the strings I need for the stations I frequent:

Gardenvale Railway Station (Brighton)

Ormond Railway Station (Ormond)
Caulfield Railway Station (Caulfield East)
Malvern Railway Station (Malvern) 
Armadale Railway Station (Armadale) 

Southern Cross Railway Station (Melbourne City) 
Richmond Railway Station (Richmond)
Flinders Street Railway Station (Melbourne City)
Melbourne Central Railway Station (Melbourne City)

I just paste the relevant strings into the form and get answers very quickly.

Extensions

After many years working with one organisation, recently I've been contracting to different companies. I am just in the process of working out how I want to handle this. I'm thinking that the stuff I gather while working at X Corp could go into directory help_X_Corp and the Y Corp stuff could go into help_Y_Corp. I started doing something along these lines at my last contract.

I'm leaning towards formalising this, using a modified form of the help command. The key line is:

	               v
	less `ls ~/help*/help_*${1}* | grep -v '~$'`
	               ^

I've added an extra asterisk to wildcard across ALL help directories.

In Conclusion

That's it in a nutshell. Anyone can adapt what I've done to suit him/herself. That's the beauty of computers and especially open source software: near infinite flexibility and customisation. It's such a shame that we waste the power on "look and feel" (skins and themes).

"Off the rack" fits most people reasonably well without fitting anyone perfectly. But anyone can adapt a system like this to suit as closely as desired - with enough effort.

It doesn't matter if you are a computer nerd or a neophyte. It doesn't really matter what OS you use (though Microsoft makes it harder). You need an editor and some way to select and display files. The only difficulty I can see is if your only access is through GUIs, because then you have to write (or get someone to write) the selection code (and maybe the display code). I guess the Microsoft way is to also use the editor (say Wordpad) as the display program. I'm not real keen on that, but others might prefer it.

If I'd wanted that functionality, I could have used emacs in place of less. I think I would have lost a lot if I'd done that.

Postscript

I wrote the above a few days ago. The next day, pricked by some of the points I made, I modified my help command. I've included it in Resources below.

Resources

#	.lesskey - less keybinding file

#  Henry Grebler    26 May 98  Add alternative left-scroll.
#  Henry Grebler    26 May 97  First cut.
#=============================================================================#

# Note on comments:

#     Blank lines and lines which start with a pound sign (#)  are
#     ignored, except for the special section header lines.

#=============================================================================#
# Note on usage:

# This file is the input file to lesskey. Without args, lesskey
# processes $HOME/.lesskey (a text file) to produce $HOME/.less (a
# binary file (which is the init file for less)).

#=============================================================================#

          x         quit
          X         quit
          \e[C        next-file
          \e[D        prev-file
          \eOC        next-file
          \eOD        prev-file

# By default, \e[ is left-scroll. However, the inclusion of \e[C above
# seems to have disabled \e[ (sort of understandable). So I add \e{ as
# a synonym for left-scroll (and add \e} as a synonym for right-scroll
# as an afterthought for consistency).

#          \e{         left-scroll
#          \e}         right-scroll

My latest help command:

function help {
# Assume no arg means standard help

        if [ "$1" = "" ]
        then
                builtin help
                return
        fi
        echo 'For bash help, use builtin help'

# avoid backup files:
        files=`ls ~/help*/help_*${1}* 2>/dev/null | grep -v "~$"`
        if [ "$files" = '' ]
        then                    # no matches: try for bash help
                builtin help $1
                return
        fi
        echo "$files"
        echo 'ls ~/help*/help_*'${1}'* | grep -v "~$"'
        less $files
}


Talkback: Discuss this article with The Answer Gang


[BIO]

Henry has spent his days working with computers, mostly for computer manufacturers or software developers. His early computer experience includes relics such as punch cards, paper tape and mag tape. It is his darkest secret that he has been paid to do the sorts of things he would have paid money to be allowed to do. Just don't tell any of his employers.

He has used Linux as his personal home desktop since the family got its first PC in 1996. Back then, when the family shared the one PC, it was a dual-boot Windows/Slackware setup. Now that each member has his/her own computer, Henry somehow survives in a purely Linux world.

He lives in a suburb of Melbourne, Australia.


Copyright © 2010, Henry Grebler. Released under the Open Publication License unless otherwise noted in the body of the article. Linux Gazette is not produced, sponsored, or endorsed by its prior host, SSC, Inc.

Published in Issue 174 of Linux Gazette, May 2010

Tux