]> Sergey Matveev's repositories - mmc.git/blob - doc/arch.texi
Quick file display
[mmc.git] / doc / arch.texi
1 @node Architecture
2 @unnumbered Architecture
3
4 Brief scheme of commands, utilities and files involved is below.
5 @file{F} means files/FIFOs/directories creation and altering.
6 @file{R} means running of external programs.
7
8 @verbatim
9 cmd/start
10   F tmux.conf
11   R tmux -f tmux.conf
12     R tail -f debug | tai64n
13     R for { cat users/status ; sleep 5 }
14     R fzf **(/) | cmd/newwin
15     R cmd/catfile
16       R fzf **(.) | fmt
17     R cmd/mmc | tai64n
18      F users/status
19      F users/.../{id,email,name,|in,out.rec,|status,last}
20      F chans/.../{id,info,out.rec,|users,last}
21      F file/{|get,|out}
22      R cmd/notify
23        R tmux display-message ...
24      R cmd/newwin
25        R cmd/rd/colourized
26          R cmd/rd < .../out.rec | spc
27        R cmd/wr
28          R for { rlwrap cat > .../in }
29
30 cmd/download
31   R echo ... > file/get
32   R tar xf < file/out
33
34 cmd/sb ... > history.rec
35 @end verbatim
36
37 @url{https://tools.suckless.org/ii/usage/, ii} IRC client's page has
38 many links to similar kind of chat software. There is some long-living
39 program, that deals with the messaging protocol and communicates with
40 other programs through the FIFO files.
41
42 There are user chats and group chats, both in IRC, XMPP and MM worlds.
43 Each user and channel have corresponding directory having the same name.
44 It contains @file{in} and @file{out} named pipes. Anything you write to
45 @file{in} will be send as a message to corresponding user/channel.
46 Reading from @file{out} will give you incoming messages from that
47 user/channel. That is the basic idea of the backend.
48
49 All you need is to write the frontend that will give you convenient
50 ability to deal with all that bunch of files. That is the most
51 complicated part of course. I do not like idea of having the single
52 window with consolidation of all chats, like using @command{multitail}
53 on several pipes. I do not like idea of purely CLI utility like
54 @url{https://github.com/agl/xmpp-client, github.com/agl/xmpp-client},
55 @url{https://en.wikipedia.org/wiki/MICQ, mICQ} or
56 @url{https://www.gnu.org/software/freetalk/, GNU Freetalk}, where you
57 have to carefully be aware of whom you are typing now. I like
58 @command{irssi} and @command{mcabber}, where you have got separate
59 window with per-user/channel output and input. We must have ability to
60 hide/close those windows/tabs/panes, automatically open them if they got
61 incoming events and we must be alerted about those events, at least by
62 bell character.
63
64 @url{https://github.com/tmux/tmux/wiki, tmux} is a perfect tool for
65 dynamic windows/tabs/panes management. It already has all necessary
66 functions to detect bell/alarms. It have ability to easily create you
67 own keybindings and already have massive amount of convenient hotkeys to
68 quickly navigate among all that windows. It already has history buffer
69 and ability to search in it. And it is likely to be already used by the
70 end user.
71
72 Messages have to be saved on filesystem. Unlike IRC, MM messages are
73 often multiline and can have additional metadata like unique identifiers
74 and attached files. So each message is a more complicated entity than
75 text string with appended timestamp and sender information. Each time
76 chat window is opened, I want to see tail of the corresponding history.
77 So instead of using FIFO that is @command{tee}-ed to ordinary
78 long-living file, I decided to use append-only
79 @url{https://www.gnu.org/software/recutils/, GNU Recutils}'es recfile.
80 And an additional program that translates it to convenient human
81 readable lines, also acting like @command{tail -f}.
82
83 It is crucial to read message you want to send not line by line, to be
84 able to send multiline messages in a single post. Closing the FIFO file
85 can be treated as the end of the message. To be able to use rich line
86 editing capabilities or even external editor, you can use great
87 @url{https://github.com/hanslub42/rlwrap, rlwrap} utility in an endless
88 loop.
89
90 So how all that decisions are composed together?
91
92 @itemize
93
94 @item @command{cmd/start} creates @file{debug} and @file{users/status}
95 FIFOs, prepares configuration file for @command{tmux} (actually there is
96 just single path to the command replaced with the real one) and runs it
97 with single window split on two three parts: one just shows debug
98 messages (all raw MM messages), other shows colourized list of
99 non-offline users, another one runs @command{cmd/mmc} itself.
100
101 @item @command{cmd/mmc} logs in to the server, fetches a list of all
102 known users and channels I am subscribed to. Then it creates necessary
103 @file{users/NAME} and @file{chans/NAME} directories with some basic
104 regular information files (like identifiers and email addresses) with
105 various FIFOs.
106
107 @item Reading @file{users/.../status} shows you current user's status.
108 @file{chans/.../users} shows currently subscribed users.
109
110 @item @file{out.rec} is append-only database of passed messages.
111 @file{last} contains the identifier of the last received message. After
112 you log in, it is used to fetch newly appeared messages while you were
113 offline.
114
115 @item If some user changes its status, or someone is typing, then
116 @command{cmd/mmc} calls @command{cmd/notify} command with corresponding
117 message. Currently that handler just asks @command{tmux} to
118 @command{display-message} for 1.5 seconds.
119
120 @item If new message comes in, then @command{cmd/mmc} calls
121 @command{cmd/newwin} and tells what window it has to open.
122 @command{cmd/newwin} checks if @command{tmux} has opened it already.
123 Newly created window has the name of the user/channel and is split on
124 two parts:
125     @itemize
126     @item
127     one part contains the output of @command{cmd/rd} piped through
128     @url{http://supercat.nosredna.net/, supercat} (@command{spc}) for
129     colourizing.
130     @item
131     other part holds an endless cycle of @command{rlwrap}-ed
132     @command{cat} piped to corresponding @file{in} FIFO.
133     @end itemize
134
135 @item Also you can manually open desired chat window by pressing
136 predefined keybinding, that will show you
137 @command{https://github.com/junegunn/fzf, fzf}-backed list of all known
138 users and channels.
139
140 @item @command{cmd/rd} reads @file{out.rec} file and prints last ten
141 messages (by default) in human readable form. It does not close that
142 file, but regularly checks if it is updated, to immediately print the
143 newly appeared messages. It print bell character with each message, so
144 it sets an alert for window in @command{tmux}.
145
146 @end itemize
147
148 Outside that running @command{tmux} user can use @command{cmd/download}
149 utility to download specified file's identifier. It sends it identifier
150 to @file{file/get} and reads the archive with that file from
151 @file{file/out}. File is sent inside
152 @url{https://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html#tag_20_92_13_01,
153 pax archive} to keep its original name and MM's file identifier.