Contents

Introduction

This page provides some notes about one of the programs in the examples directory, namely flowterm. It is an experimental replacement for terminal emulator programs like xterm and konsole.

Tabs

The program presents one or more tabs to the user, each of which contains an independent shell process. Each tab contains a split pane. To the left (or top if so oriented), is a list of the contents of the shell process's current directory. To the right (or bottom) is a fairly conventional terminal emulator, albeit one with some important extensions.

Clickable links

The most significant thing that flowterm does differently to conventional terminal emulators like xterm, is the provision of clickable hyperlinks to files and other objects. For example, look at the following image, showing the output of ls.

As the mouse pointer moves over the filename output by ls, the mouse pointer changes and the link is highlighted. Left-clicking on the link opens the system-registered application for viewing that particular file type; right-clicking brings up a context menu, and middle-clicking inserts the filename into the terminal.

This effect is achieved by a combination of two things. Firstly, the terminal emulator understands special escape sequences which encapsulate file links in much the same way as a web browser understands HTML anchor tags. Secondly, a small collection of programs, including ls, have been modified to produce these special escape sequences, and thus provide the desired links in the terminal. To continue the web analogy, if the terminal is the browser, then these programs are the equivalent of web servers, but instead of producing HTML containing anchor tags, they produce their normal textual output, but containing embedded link escape sequences.

The modified programs include ls, grep and find. Although the selection of programs cannot be complete, it is large enough to considerably improve the usability of the shell.

These modified programs are provided in a separate download; the section flowterm extras below explains more.

Graphical completion

Another frustation of using the shell which flowterm tries to address is filename completion (in fact completion in general, not just files). Users of bash will certainly be familiar with how annoying its completion facility can be. To alleviate this distress, another escape sequence is employed, and bash is modified to send this escape sequence when tab completion occurs (in fact, bash is not modified, rather its readline library, which is statically linked into it, is modified instead).

With this modification, a popup list appears to implement tab completion, as shown in the following image :-

The user may now use the mouse or the cursor keys in order to select from the list in the normal way.

Toolbar

The various items in the toolbar should be mostly self-explanatory.

Going from left to right, we have the close tab button, the goto home directory button, go up one level button and refresh directory button.

Then come buttons to go backward and forward in the history, and to display the history as a drop-down list (the egg timer icon).

Next is the "columns focus" button, which is a toggle button. When set, it allows the list to take the keyboard focus. The cursor keys can then be used to navigate, and the return key used to "open" the currently selected item (equivalent to left-clicking).

The drop-down edit list is a filter, which restricts the files (and optionally directories) on view in the list. The contents of the drop-down provides a convenient list of file extensions in the current directory.

The three buttons to the right of the filter drop-down are used to control the sort used in the list, which is by default alphabetic in descending order. The small arrow in the corner of the button indicates which sort is in use, and whether it is ascending or descending. Clicking on the button with the arrow toggles the order between ascending and descending, whilst clicking on one of the other buttons sets the sort to the corresponding button, leaving the order unchanged.

Next to the sort buttons comes the favourites button. This is a list of directories, which can be edited via the "Favourite dirs..." item in the File menu.

Finally, to the right of that comes the file trail. This shows the current directory. Clicking on one of the file names in the trail changes the directory. Also, clicking on one of the slash separators pops up the list of directories for that location. Selecting from one goes to that directory. The following image shows that in action :-

Right-clicking on one of the entries brings up the file context menu.

Popup menus

Both the file list and terminal portions of the tab have popup menus. They appear either by clicking in an area without links, or via the menu bar at the top of the window.

The terminal menu is shown below.

The first four items relate to copy and paste. "Paste escaped" is the same as "Paste", but applies shell escaping to the pasted text. Reorient toggles the horizontal/vertical orientation of the split. Horizontal orientation is especially useful if you have a directory containing many very long file names. The "Maximize" option makes the terminal take up all of the tab's space. After a maximize, a "Restore" option is shown, which restores the split to the usual dual view. "Search" opens a text entry box at the bottom of the window, allowing the terminal scrollback text to be searched. "Log" asks for a file name and thereafter copies all output to the terminal to the log file.

The file list's popup menu is as follows :-

The first two items indicate that the date or size should be shown alongside the name. To reduce clutter, this is only applied to directory entries if the "Sort dirs" or "Mix files & dirs" option is checked. "Mix files & dirs" means sort and display files and directories together; normally directories come first. "Show hidden files" is self-explanatory. "Sort dirs" means apply the same sort to directories as to files; normally they are just sorted by alphabetical order regardless of the sort option selected in the toolbar. "Filter dirs" means apply the filename filter to directories as well as files. The "Reorient", "Maximize" and "Restore" options have the corresponding effect for the list pane as for the terminal pane.

When a URL link (or an entry in the file list) is right-clicked, a file context menu such as the following is shown. Some entries may not appear, depending on the type of the link. The clicked URL turns red.

"Copy" will copy the filename to the clipboard. No escape characters are added, so to paste this into the shell, use the "Paste escaped" option described above. "Copy URL" copies the source URL to the clipboard. "Copy command" copies the text of the shell command that a left-click would run, to the clipboard. "Open with" is a submenu listing all of the system's dekstop applications which can recognise this file or URL type. For files, "Rename" opens a window where the file can be renamed. This is the only file manager-like option which flowterm provides.

Right-clicking on a tab header brings up the following context menu :-

"New" opens a new tab with default settings in the tab to the right of the one clicked. "Close" obviously closes the tab, and "Clone" opens a new tab to the right of the one clicked, but reproduces as much of that tab's settings (history, current directory and so on) in the new tab as possible.

The other items, under the separator, provide the standard file context menu for the current directory of the tab.

Apart from the places just mentioned above, the file context menu also appears on a right click in several other places as well :-

Mouse bindings

Generally speaking, wherever it is possible to right click on a filename and get the file context menu, it is also possible to middle click and insert the shell-escaped form of the file path. For the sake of brevity, the path inserted is a relative one if is below the current directory, but the absolute path can be inserted instead if shift is held down whilst pressing the middle button.

To take an example of how this might be used, suppose that you have two tabs open and wish to copy a file from the directory of one to the directory of the other. In the first tab, you could type "cp " and then middle click the source file in the file list, and then middle click on the second tab's tab header to insert the destination directory, and then press return.

When moving the mouse in the terminal, if either control key is held down then links are not recognized. This enables the text inside the links to be copied.

The flowterm-extras programs

This is a collection of common utility programs, modified to provide output containing escape sequences recognised by the flowterm. For example, a version of ls is provided which turns each file output into a clickable link to a file: URL.

To build the flowterm-extras programs, proceeds as follows.

Firstly, download the .tar.gz file, from the following link :-

flowterm-extras.tar.gz (25MB)

It is best to extract this file in your home directory, since it will then be found automatically by flowterm. (If you extract it somewhere else, then you will need to provide the -x option to tell flowterm where).

In any case, extract it as follows :-

tar xfz flowterm-extras.tar.gz

This will create a flowterm-extras directory. Cd into that directory, and run

./build.sh

A considerable amount of output will be produced, but if everything was successful, the message "Finished OK" will be printed. In that case, a directory bin will have been created, containing the resulting executables. The build.sh script doesn't actually install anything outside of its directory, and can simply be deleted if you no longer have any use for it.

Escape sequences

There are two special escape sequences recognised by the terminal, as follows.

This takes the form

\e[!"url"Lvisible-text\e[!L

where \e is the escape character (ascii 27), url is a URL, (with the normal percent encoding), and visible-text is the text which appears on the screen to represent the clickable URL. In fact, the above actually represents two separate escape sequences; the second comes after the visible-text, in order to denote its endpoint. If you're familiar with HTML, then you will see the similarity with an anchor tag. The first escape sequence mirrors the opening <A HREF=URL> tag, and the second the closing </A> tag, whilst visible-text fulfils the same role as the content between the tags.

Most URLs in these escape sequences will be file URLs, but as explained below, other types of URLs, including custom ones, are allowed too. These can be particularly useful when they are placed in simple "favourites" files which, when printed to the terminal, provide a selection of clickable links to launch applications, open new tabs, and so on.

Some examples of a link escape sequences are :-

\e[!"file:///some/file/or/other.txt?line=120"LA file with an associated line number\e[!L
\e[!"http://www.google.com"LA link to google\e[!L
\e[!"launch:konqueror"LOpen konqueror\e[!L

The popup escape sequence

This escape sequence is used to provide a more friendly and usable name completion system. The sequence takes the form :-

\e[!"k1";"i1";"k2";"i2";"k3";"i3",....,"kn";"in"P

In other words, there are n pairs of string parameters. All parameters are URL encoded. On receipt of this escape sequence, the terminal pops up a list, showing each of the k parameters. When one is selected, its corresponding i parameter is sent to the output, as though it had been typed.

Unlike the link escape sequence, this sequence only really makes sense when it is generated by a program.

URL schemes

file:

A file URL has the following syntax :-

file://[host]/path[?line=line-no]

If the path (which includes the / to its left), is a directory then clicking on the link sends a cd command to the shell process in order to change its current working directory.

Otherwise, the file associations database is searched to find an application to launch to view the file. If found, then the application is launched by forking a new process.

The optional host element is just used to check whether the URL refers to a file on the host running flowterm. If not, then there is no point trying to launch an application for it, and an error message is shown in the message bar.

The line-no is passed to the application if its desktop entry file contains an entry ExecLine=..., as opposed to the normal Exec=.... The ExecLine string may contain an escape sequence %L into which the line number is substituted. Both the ExecLine entry and the %L escape are entirely non-standard unfortunately, so you must create your own .desktop file in order to make use of them. An example which I use to launch emacs is :-

[Desktop Entry]
Version=1.0
Encoding=UTF-8
Name=GNU Emacs
GenericName=Text Editor
Comment=View and edit files
MimeType=text/english;text/plain;text/x-makefile;
Exec=emacs %F
ExecLine=emacs +%L %F
Icon=emacs
Type=Application
Terminal=false
Categories=Utility;Development;TextEditor;
InitialPreference=20

This is placed in my ~/.local/share/applications directory. The effect of launching this desktop entry file with the URL

file:///home/rparlett/prog.c?line=124

is then to launch the program

emacs +124 /home/rparlett/prog.c

launch:

A launch URL has the following syntax :-

launch:command-string[?wd=working-dir]

Both command-string and working-dir portions are URL encoded. When clicked, a launch URL forks a new process, sets its current directory to working-dir (or the user's home directory if working-dir was omitted), and then runs command-string, which may include bash shell syntax.

An example of a launch URL is :-

launch:qemu-system-x86_64 -hda ubuntu.img -m 3G -vga vmware?wd=/mnt/disk/qemu-stuff

text:

A text URL has the following syntax :-

text:string

The string is URL encoded. The effect of clicking on such a link is simply to send the string to the input of the forked shell process. In other words, the effect is the same as if the string had been typed at the keyboard.

An example might be :-

text:hello world

If we were to click on a link with this URL, then "hello world" would be sent to the shell process, which would then echo it back so it appeared on the screen (unless it was running a command at the time).

run:

A run URL has the following syntax :-

run:command-string

The command-string is URL encoded. The effect of clicking on such a link is, like a text URL, simply to send the string to the input of the forked shell process, with a carriage return appended, causing the command to be run (unless the shell process is doing something else).

An example :-

run:ps -a

Clicking on a link with this URL would run the command "ps -a".

Note that the difference between a launch URL and a run URL is that a launch URL forks a new process which runs independently of the shell, whilst run just sends the command string to the shell for execution as though it had been typed at the keyboard.

tab:

A tab URL enables new tabs to be opened and configured when it is clicked. It has the following syntax :-

tab:arg1[;arg2][;arg3]...

Each "argument" is URL encoded. Each argument is either a directory name, which opens a new tab with that directory as a starting point, or a string beginning with ":" which configures the tab just opened using a tab option, as described below. An empty string argument just opens a new tab, without setting its directory. If any configuration options come before a directory argument, then they apply to the currently selected tab.

An example of a tab URL is :-

tab:/mnt/disk/films;:reorient;:sort-date;:select

When clicked, this URL opens a new tab, changes its directory to /mnt/disk/films, toggles the orientation of the split, sets the sort to date order, and selects the tab.

Another example is :-

tab::re-orient

This doesn't open a new tab, because the first item after the tab: is a tab command (ie it begins with a :), so it operates on the current tab, and reorients the split setting. URLs like this can be quite useful when linked to custom key settings.

clone:

This is rather like tab:, but clones the current tab's settings in a new tab. Then, any additional given tab commands are applied to the new tab. The syntax is :-

clone:cmd1[;cmd2][;cmd3]...

For example :-

clone:adjacent;select

Note that, unlike tab:, the commands shouldn't be prefixed with ':' (as they don't need to be distinguished from directories).

Other URL schemes

All other URL schemes are handled by looking up the desktop entry matching the mime type x-scheme-handler/[scheme]. The matching application is then launched in a forked process.

Favourites files and other useful tips

It is very easy and useful to create small shell script files which simply output links which can be clicked on. These links can be file: URLs, in order to change to particular directories, or launch specific files. They could also use some of the custom schemes mentioned above, which can launch applications, open new tabs, and so on.

For example, if I created the following file, called it favs, and put it somewhere on my path (and made it executable)

#!/bin/bash
cat <<EOF
\e[!"tab:/mnt/sg1/music;:reorient;:sort-date;:mix-entries;:select"LMusic tab\e[!L
\e[!"launch:qemu-system-x86_64 -hda caldera.img -m 3G -net nic -net bridge -enable-kvm?wd=/mnt/qemu-stuff"Lcaldera emulation\e[!L
\e[!"launch:xterm -e ssh rparlett@somehost"Lssh to somehost\e[!L
\e[!"file:///tmp"Lcd to /tmp\e[!L
EOF

then whenever I typed favs at the prompt, the above links would be printed, and I would simply have to click on one of them to perform the desired action.

Note that creating the above file with a text editor does present one problem, namely how to input the escape character (ascii 27), shown in the above as the two characters \e. In emacs, this character can be input by typing control-q, and then pressing the escape key.

The FLOWTERM environment variable

One problem that faces programs that output the special link and popup escape sequences (such as the flowterm-extras programs), is the question of what kind of terminal the program is connected to. It is obviously undesirable to output these escape sequences on a conventional terminal, since the output will be garbled. However, detecting the type of the terminal is awkward. Therefore, a simple environment variable, FLOWTERM, is used by programs to determine whether or not to output the special escape sequences. The following values are used :-

The last option can be useful when using a pipeline. For example, assuming FLOWTERM is 1, the output of

ls -t | head

will not contain escape sequences, since ls will detect that its output is a pipe, rather than a tty. (For the same reason, if you use colour ls output, you won't see colours either).

To fix this, set FLOWTERM to 2 when invoking ls, thus :-

FLOWTERM=2 ls -t | head

Limitations

The terminal emulation is missing a few features which are found in xterm :-

The file handling parts of the program, including the file list and the file trail, assume UTF-8 encoding of filenames, and will ignore files in other encodings.

The insertion of shell-escaped strings (for example on a mouse middle-press of a filename) assumes a shell that is compatible with bash's escape syntax. This includes zsh, and ksh, but csh isn't compatible unfortunately. Nor, oddly enough, is bash run in its sh-compatible form (ie, started with the command sh). The $'\ch' escape combination appears to be a bash-ism.

The coordination between the file list and the terminal emulator also has some limitations. The list's current directory is kept synchronized with the shell process's current directory, as read from the file /proc/<pid>/cwd, where pid is the shell process's process id. This means that the list doesn't synchronize with a sub-shell process. For example, if you start another shell program, such as zsh, as in

bash $ zsh
$ cd /tmp

then the list won't synchronize to /tmp, since the original bash process is still in whatever directory it was in when zsh started. If you know you won't return to bash, you can instead type

bash $ exec zsh
$ cd /tmp

Then it will work as desired, since zsh has taken over (and replaced) the bash shell's process.

The screen program also suffers from the same problem, since it starts its own processes. Also, since it implements its own internal terminal emulation, it cannot understand understand the special escape sequences used by flowterm. Therefore it is desirable to set FLOWTERM to zero (or unset it) before launching screen.

$ FLOWTERM=0 screen

In view of these limitations, there is in fact no advantage to running screen in flowterm, and it may just as well be started in a conventional terminal emulator program :-

$ FLOWTERM=0 xterm -e screen &

Tab options

Tab options are string commands used to configure or control particular tabs. They can be used in three places :-

The following tab options are allowed. Parameters are optional for some commands. A null value is specified by omitting the parameter. Commands taking a FLAG (yes/no) parameter typically toggle their setting when the parameter is omitted. So for example :max_term will toggle the maximized state of the terminal, where as :max_term=on will just maximize it.

The following commands only apply to the currently active tab (not new tabs).

Command line options

flowterm accepts the following command-line options :-

In addition to these options, one or more tabs can be configured on the command line. Passing a directory name as an argument will add a new tab with that directory as a starting point. Passing a string beginning with ":" will then configure that tab using a tab option. Arguments beginning with a ":" that come before the first directory are applied to all tabs, except those that are cloned from other tabs.

For example, the following example starts the program with four tabs with various options :-

flowterm :fg=blue :font=typewriter \
         ~ :title=Home \
         ~/objecticon \
         /mnt/disk/Documents :reorient :sort-date :mix-entries \
         /mnt/disk/Music :reorient :sort-date

Note that the first two options (configuring foreground colour and font), will apply to all four opened tabs (and any new tabs added later).

Custom key settings

The :key tab option is used to make custom key settings. The syntax is :-

:key=KEY,BITS,MASK,COMMAND

KEY specifies the key, and must take one of three forms :-

To decide which of the above to use, try running the grabtest example program, and typing the key. The event code is shown in the window, and will either be a string, a ucs string, or a key code.

BITS and MASK both take the same format, and specify which modifier key or keys is to be held down (or not) for this key binding. Exactly those keys in BITS among those in MASK must be down. The format is a string consisting of the following characters :-

For example, the combination C,CS would mean the control would be down, and the shift key would not be down, and the state of the meta keys is ignored.

When several settings are made on one key, an error is signalled if they are inconsistent; ie more than one could match a particular key combination. For example the two combinations S,S and CS,CS are erroneous since both match the case when control and shift are down. A correct version would use S,CS for the first one.

The grabtest program also shows which modifiers are set when a key is pressed.

COMMAND is one of the tab options listed above, but without the : prefix. The command is applied when the key is pressed.

Clearing key settings

To clear all settings for a particular key, use the form

:key=KEY

To clear one particular setting matching a particular bit/mask combination, use

:key=KEY,BITS,MASK

Finally, to reset the key table to its default (empty) form, use

:reset-keys

This would be useful if, for example one used default settings for the function keys, but wanted a tab which didn't have those settings, perhaps to run a particular application that had its own use for the function keys. This tab would be opened via a tab: URL like

tab:;:reset-keys

Examples

Here are some examples of custom key settings, shown using bash shell syntax for escapes and quotes, where necessary. To experiment, just run flowterm with the setting as a parameter and try pressing the key.

Startup script

Here is my own personal flowterm startup script. It opens four tabs in various directories, including, of course, ~/objecticon!

Download startterminal.sh

#!/bin/bash
~/objecticon/examples/flowterm -lfw 2 \
                               -t $HOSTNAME \
                               -width 125 \
                               -height 45 \
                               :key=INSERT,C,*,copy \
                               :key=INSERT,S,*,paste \
                               :key=PGUP,S,*,pgup \
                               :key=PGDN,S,*,pgdn \
                               :key=HOME,S,*,top \
                               :key=END,S,*,bottom \
                               :key=F1,0,*,new-tab \
                               :key=F1,C,*,max-term \
                               :key=F1,S,*,max-list \
                               :key=F2,0,*,clone-tab \
                               :key=F2,S,*,reorient \
                               :key=F3,0,*,close-tab \
                               :key=F3,S,*,focus-filter \
                               :key=F4,0,*,open-history \
                               :key=F5,0,*,tab-left \
                               :key=F6,0,*,tab-right \
                               :key=F7,0,*,prev \
                               :key=F8,0,*,next \
                               :key=F9,0,*,open-favourites \
                               :key=F10,0,*,copy \
                               :key=F10,S,*,paste \
                               :key=F11,0,*,move-tab-left \
                               :key=F12,0,*,move-tab-right \
                               :key=PAUSE,0,*,up \
                               ~ \
                               ~/objecticon \
                               /mnt/sg1/Documents :reorient :sort-date :mix-entries :fav-dir=/mnt/sg3/Documents \
                               /mnt/sg1/videos/music :reorient :sort-date :list-height=500 :fav-dir=/mnt/sg3/videos/music
Contents