Brief scheme of commands, utilities and files involved is below. F means files/FIFOs/directories creation and altering. R means running of external programs.
cmd/start F tmux.conf R tmux -f tmux.conf R tail -f debug | tai64n R for { cat users/status ; sleep 5 } R cmd/mmc | tai64n F users/status F users/.../{id,email,name,|in,out.rec,|status,last} F chans/.../{id,info,out.rec,|users,last} F file/{|get,|out} R cmd/notify R tmux display-message ... R cmd/newwin R cmd/rd/colourized R cmd/rd < .../out.rec | spc R cmd/wr R for { rlwrap cat > .../in } R fzf **(/) | cmd/newwin R tmux capture-pane | fzf | cmd/dl R cmd/catfile R fzf **(.) | fmt cmd/dl R echo ... > file/get R tar xf < file/out cmd/sb ... > history.rec
ii IRC client’s page has many links to similar kind of chat software. There is some long-living program, that deals with the messaging protocol and communicates with other programs through the FIFO files.
There are user chats and group chats, both in IRC, XMPP and MM worlds. Each user and channel have corresponding directory having the same name. It contains in and out named pipes. Anything you write to in will be send as a message to corresponding user/channel. Reading from out will give you incoming messages from that user/channel. That is the basic idea of the backend.
All you need is to write the frontend that will give you convenient
ability to deal with all that bunch of files. That is the most
complicated part of course. I do not like idea of having the single
window with consolidation of all chats, like using multitail
on several pipes. I do not like idea of purely CLI utility like
github.com/agl/xmpp-client,
mICQ or
GNU Freetalk, where you
have to carefully be aware of whom you are typing now. I like
irssi
and mcabber
, where you have got separate
window with per-user/channel output and input. We must have ability to
hide/close those windows/tabs/panes, automatically open them if they got
incoming events and we must be alerted about those events, at least by
bell character.
tmux is a perfect tool for dynamic windows/tabs/panes management. It already has all necessary functions to detect bell/alarms. It have ability to easily create you own keybindings and already have massive amount of convenient hotkeys to quickly navigate among all that windows. It already has history buffer and ability to search in it. And it is likely to be already used by the end user.
Messages have to be saved on filesystem. Unlike IRC, MM messages are
often multiline and can have additional metadata like unique identifiers
and attached files. So each message is a more complicated entity than
text string with appended timestamp and sender information. Each time
chat window is opened, I want to see tail of the corresponding history.
So instead of using FIFO that is tee
-ed to ordinary
long-living file, I decided to use append-only
GNU Recutils’es recfile.
And an additional program that translates it to convenient human
readable lines, also acting like tail -f
.
It is crucial to read message you want to send not line by line, to be able to send multiline messages in a single post. Closing the FIFO file can be treated as the end of the message. To be able to use rich line editing capabilities or even external editor, you can use great rlwrap utility in an endless loop.
So how all that decisions are composed together?
cmd/start
creates debug and users/status
FIFOs, prepares configuration file for tmux
(actually there is
just single path to the command replaced with the real one) and runs it
with single window split on two three parts: one just shows debug
messages (all raw MM messages), other shows colourized list of
non-offline users, another one runs cmd/mmc
itself.
cmd/mmc
logs in to the server, fetches a list of all
known users and channels I am subscribed to. Then it creates necessary
users/NAME and chans/NAME directories with some basic
regular information files (like identifiers and email addresses) with
various FIFOs.
cmd/mmc
calls cmd/notify
command with corresponding
message. Currently that handler just asks tmux
to
display-message
for 1.5 seconds.
cmd/mmc
calls
cmd/newwin
and tells what window it has to open.
cmd/newwin
checks if tmux
has opened it already.
Newly created window has the name of the user/channel and is split on
two parts:
cmd/rd
piped through
supercat (spc
) for
colourizing.
rlwrap
-ed
cat
piped to corresponding in FIFO.
cmd/rd
reads out.rec file and prints last ten
messages (by default) in human readable form. It does not close that
file, but regularly checks if it is updated, to immediately print the
newly appeared messages. It print bell character with each message, so
it sets an alert for window in tmux
.
Outside that running tmux
user can use cmd/dl
utility to download specified file’s identifier. It sends it identifier
to file/get and reads the archive with that file from
file/out. File is sent inside
pax archive to keep its original name and MM’s file identifier.