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