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
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.
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
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
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.
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.
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.
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
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 :-
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.
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
To build the flowterm-extras programs, proceeds as follows.
Firstly, download the
.tar.gz file, from the following link :-
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
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
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.
There are two special escape sequences recognised by the terminal, as follows.
This takes the form
\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
This escape sequence is used to provide a more friendly and usable name completion system. The sequence takes the form :-
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.
A file URL has the following syntax :-
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.
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.
line-no is passed to the application if its desktop entry file contains an entry
ExecLine=..., as opposed to the normal
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
is then to launch the program
emacs +124 /home/rparlett/prog.c
A launch URL has the following syntax :-
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
A text URL has the following syntax :-
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 :-
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).
A run URL has the following syntax :-
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 :-
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.
A tab URL enables new tabs to be opened and configured when it is clicked. It has the following syntax :-
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 :-
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 :-
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.
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 :-
For example :-
Note that, unlike
tab:, the commands shouldn't be prefixed with ':' (as they don't need to be distinguished from directories).
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.
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.
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
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
2 when invoking
ls, thus :-
FLOWTERM=2 ls -t | head
The terminal emulation is missing a few features which are found in
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
csh isn't compatible unfortunately. Nor, oddly enough, is
bash run in its
sh-compatible form (ie, started with the command
$'\ch' escape combination appears to be a
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
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.
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
$ FLOWTERM=0 screen
In view of these limitations, there is in fact no advantage to running
flowterm, and it may just as well be started in a conventional terminal emulator program :-
$ FLOWTERM=0 xterm -e screen &
Tab options are string commands used to configure or control particular tabs. They can be used in three places :-
tab:URL, to configure and open a new tab, or modify the current tab.
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.
sort-name, but sort by date (newest first is "no", oldest first is "yes").
sort-name, but sort by size (biggest first is "no", smallest first is "yes").
The following commands only apply to the currently active tab (not new tabs).
flowterm accepts the following command-line options :-
flowterm-extrasdirectory; by default
flowterm-extrasin your home directory. This directory's
binsubdirectory is added to the front of the
-xoption is ignored.
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).
The :key tab option is used to make custom key settings. The syntax is :-
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.
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 :-
*: Equivalent to CSM45, ie all modifier keys.
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.
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.
To clear all settings for a particular key, use the form
To clear one particular setting matching a particular bit/mask combination, use
Finally, to reset the key table to its default (empty) form, use
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
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.
Copy to clipboard when
F10 is pressed.
Quit the program on control Q.
x11 means string character 17 (decimal), which the
grabtest program shows as the key code generated on control Q.
F9 is pressed.
Open and select a new tab on shift
F9, with directory
/tmp and horizontal split orientation. Note this one requires shell quotes around it because of the semicolons.
Copy to clipboard when
F10 is pressed, and show a message in the status bar. This shows how to do several actions on a single key, by using a
Run the command
ls -l when
F9 is pressed.
Another way to do this would be
a URL is used since they are percent encoded, and this allows the space and carriage return to be easily specified.
Send control-C when the Pause button is pressed.
Clear the screen when
F9 is pressed.
Increase/decrease the terminal font size with
Provide movement within the terminal history with shifted page up, down, home and end. (This needs four separate
:key=PGUP,S,*,pgup :key=PGDN,S,*,pgdn :key=HOME,S,*,top :key=END,S,*,bottom
Provide copy and paste on control-insert and shift-insert respectively. This is a setting commonly found in other terminal emulators, and needs two commands.
Here is my own personal
flowterm startup script. It opens four tabs in various directories, including, of course,
#!/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