|
| 1 | +Overview |
| 2 | +======== |
| 3 | + |
| 4 | +NOTE: This is not an introduction to XMPP, but to poezio |
| 5 | + |
| 6 | + |
| 7 | +Global overview |
| 8 | +--------------- |
| 9 | + |
| 10 | +Poezio is an application that has three main layers, mostly separated in three |
| 11 | +different python modules: _core_, _tabs_, and _windows_. An UML diagram of |
| 12 | +Poezio would be inneficient, cluttered, or incomplete, so there is none, if |
| 13 | +that bugs you. |
| 14 | + |
| 15 | +image::../../images/layers.png["The application layers", title="Layers"] |
| 16 | + |
| 17 | +_Core_ is mostly a “global” object containing the state of the application at |
| 18 | +any time, it contains the global commands, the xmpp event handlers, the list |
| 19 | +of open tabs, etc. Most objects in poezio have a self.core attribute |
| 20 | +referencing the _Core_ (it’s a singleton, so there is never more than one |
| 21 | +instance). _Core_ also contains the main loop of the application, which then |
| 22 | +dispatchs the I/O events (keypress) to the appropriate methods. |
| 23 | + |
| 24 | + |
| 25 | +But the main loop is not the most important thing in poezio; because it is an |
| 26 | +IM client, it is essentially event-driven. The event part is handled by |
| 27 | +SleekXMPP, which is the library we chose after moving away from xmpppy. |
| 28 | + |
| 29 | + |
| 30 | +_Tabs_ are the second layer of poezio, but the first dealing with the UI: each |
| 31 | +_Tab_ is a layout of several _windows_, it contains tab-specific commands, |
| 32 | +tab-specific keybinds, and it has methods in order for core to |
| 33 | +interact with it, and some methods are only proxies for the methods of a |
| 34 | +_window_ |
| 35 | + |
| 36 | +Example scenario: If someone presses the key PageUp, then Core will call the |
| 37 | +appropriate method on the current _Tab_, which will in turn, if it implements the |
| 38 | +method (inherited empty from the Tab class), call a scrolling method from the |
| 39 | +appropriate _window_. |
| 40 | + |
| 41 | +All tabs types inherit from the class _Tab_, and the _Tabs_ featuring |
| 42 | +chat functionnality will inherit fro _ChatTab_ (which inherits from _Tab_). |
| 43 | + |
| 44 | +Examples of _Tabs_: MUCTab, XMLTab, RosterTab, MUCListTab, etc… |
| 45 | + |
| 46 | +Event handlers |
| 47 | +-------------- |
| 48 | + |
| 49 | +The events handlers are registered right at the start of poezio, and then |
| 50 | +when a matching stanza is received, the handler is called in a separate thread |
| 51 | +from the main loop. The handlers are in _Core_, and then they call the |
| 52 | +appropriate methods in the corresponding _tabs_. |
| 53 | + |
| 54 | +Example scenario: if a message is received from a MUC, then the _Core_ handler |
| 55 | +will identify the _Tab_, and call the relevant handler from this _Tab_, this tab |
| 56 | +will in turn, add the message to the buffer, which will then add it to the |
| 57 | +relevant _windows_. |
| 58 | + |
| 59 | +NOTE: All the _windows_ that deal with received or generated text are linked |
| 60 | +to a _text_buffer_, in order to rebuild all the display lines from an the |
| 61 | +sources if necessary. This also enables us to have several _windows_ |
| 62 | +presenting the same text, even if they are not of the same size and layout. |
| 63 | + |
| 64 | + |
| 65 | +Commands and completion |
| 66 | +----------------------- |
| 67 | + |
| 68 | +Commands are quite straightforward: those are methods that take a string as a |
| 69 | +parameter, and they do stuff. |
| 70 | + |
| 71 | +From an user point of view, the methods are entered like that: |
| 72 | + |
| 73 | +================================== |
| 74 | + |
| 75 | + /command arg1 arg2 |
| 76 | + |
| 77 | +or |
| 78 | + |
| 79 | + /command "arg1 with spaces" arg2 |
| 80 | + |
| 81 | +================================== |
| 82 | + |
| 83 | +However, when creating a command, you wil deal with _one_ str, no matter what. |
| 84 | +There are utilities to deal with it (common.shell_split), but it is not always |
| 85 | +necessary. Commands are registered in the _commands_ dictionnary of a tab |
| 86 | +structured as key (command name) -> tuple(command function, help string, completion). |
| 87 | + |
| 88 | + |
| 89 | +Completions are a bit tricky, but it’s easy once you get used to it: |
| 90 | + |
| 91 | +They take an _Input_ (a _windows_ class) as a parameter, named the_input |
| 92 | +everywhere in the sources. To effectively have a completion, you have to call |
| 93 | +_the_input.auto_completion()_ at the end of the function. |
| 94 | + |
| 95 | +*the_input.auto_completion(completion_list, after='', quote=True)*: |
| 96 | +Set the input to iterate over _completion_list_ when the user hits tab, insert |
| 97 | +_after_ after the completed item, and surround the item with double quotes or |
| 98 | +not. |
| 99 | + |
| 100 | +There is no method to find the current argument in the input (although the |
| 101 | +feature is planned), so you have to assume the current argument is the last, |
| 102 | +and guess it by splitting the string an checking for end-space. |
| 103 | + |
| 104 | +You can look for examples in the sources, all the possible cases are |
| 105 | +covered (single-argument, complex arguments with spaces, several arguments, |
| 106 | +etc…) |
0 commit comments