From 0f7ec35c971a1b3f9408d3f4a70935c5f65bb818 Mon Sep 17 00:00:00 2001 From: mathieui Date: Sun, 25 Sep 2011 18:25:50 +0200 Subject: [PATCH 01/12] Remove /pubsub command for the time being --- src/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core.py b/src/core.py index b93678ab..230253de 100644 --- a/src/core.py +++ b/src/core.py @@ -125,7 +125,7 @@ class Core(object): 'connect': (self.command_reconnect, _('Usage: /connect\nConnect: disconnect from the remote server if you are currently connected and then connect to it again'), None), 'server_cycle': (self.command_server_cycle, _('Usage: /server_cycle [domain] [message]\nServer Cycle: disconnect and reconnects in all the rooms in domain.'), None), 'bind': (self.command_bind, _('Usage: /bind \nBind: bind a key to an other key or to a “command”. For example "/bind ^H KEY_UP" makes Control + h do the same same than the Up key.'), None), - 'pubsub': (self.command_pubsub, _('Usage: /pubsub \nPubsub: Open a pubsub browser on the given domain'), None), +# nope 'pubsub': (self.command_pubsub, _('Usage: /pubsub \nPubsub: Open a pubsub browser on the given domain'), None), } self.key_func = { From 7ee5f251d927a5e0d5da352810e7686b56eb2b57 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sun, 25 Sep 2011 19:30:09 +0200 Subject: [PATCH 02/12] Restaure that --- src/tabs.py | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/tabs.py b/src/tabs.py index 88d8ad7f..2a7c3dc2 100644 --- a/src/tabs.py +++ b/src/tabs.py @@ -1002,6 +1002,7 @@ class PrivateTab(ChatTab): #self.commands['info'] = (self.command_info, _('Usage: /info\nInfo: Display some information about the user in the MUC: '), None) self.commands['unquery'] = (self.command_unquery, _("Usage: /unquery\nUnquery: close the tab"), None) self.commands['part'] = (self.command_unquery, _("Usage: /part\nPart: close the tab"), None) + self.commands['version'] = (self.command_version, _('Usage: /version\nVersion: get the software version of the current interlocutor (usually its XMPP client and Operating System)'), None) self.resize() self.on = True @@ -1033,6 +1034,21 @@ class PrivateTab(ChatTab): """ self.core.close_tab() + def command_version(self, arg): + """ + /version + """ + def callback(res): + if not res: + return self.core.information('Could not get the software version from %s' % (jid,), 'Warning') + version = '%s is running %s version %s on %s' % (jid, + res.get('name') or _('an unknown software'), + res.get('version') or _('unknown'), + res.get('os') or _('on an unknown platform')) + self.core.information(version, 'Info') + jid = self.get_room().name + self.core.xmpp.plugin['xep_0092'].get_version(jid, callback=callback) + def resize(self): if self.core.information_win_size >= self.height-3 or not self.visible: return From 24dda3ff25603f81a178cc157dd002d5d7f3feda Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sun, 25 Sep 2011 19:31:42 +0200 Subject: [PATCH 03/12] and that --- src/tabs.py | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/tabs.py b/src/tabs.py index 2a7c3dc2..f46087fd 100644 --- a/src/tabs.py +++ b/src/tabs.py @@ -999,11 +999,12 @@ class PrivateTab(ChatTab): # keys self.key_func['^I'] = self.completion # commands - #self.commands['info'] = (self.command_info, _('Usage: /info\nInfo: Display some information about the user in the MUC: '), None) + self.commands['info'] = (self.command_info, _('Usage: /info\nInfo: Display some information about the user in the MUC: '), None) self.commands['unquery'] = (self.command_unquery, _("Usage: /unquery\nUnquery: close the tab"), None) self.commands['part'] = (self.command_unquery, _("Usage: /part\nPart: close the tab"), None) self.commands['version'] = (self.command_version, _('Usage: /version\nVersion: get the software version of the current interlocutor (usually its XMPP client and Operating System)'), None) self.resize() + self.parent_muc = self.core.get_tab_by_name(JID(room.name).bare, MucTab) self.on = True def completion(self): @@ -1049,6 +1050,16 @@ class PrivateTab(ChatTab): jid = self.get_room().name self.core.xmpp.plugin['xep_0092'].get_version(jid, callback=callback) + def command_info(self, arg): + """ + /info + """ + if arg: + self.parent_muc.command_info(arg) + else: + user = JID(self.get_room().name).resource + self.parent_muc.command_info(user) + def resize(self): if self.core.information_win_size >= self.height-3 or not self.visible: return From d5a013dd6a35cce610add92767335e0daafc3f9c Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Sun, 25 Sep 2011 19:36:08 +0200 Subject: [PATCH 04/12] Fixes the refresh issue when the user of a private conversation leaves/joins --- src/tabs.py | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/tabs.py b/src/tabs.py index f46087fd..f25006a8 100644 --- a/src/tabs.py +++ b/src/tabs.py @@ -1151,22 +1151,25 @@ class PrivateTab(ChatTab): """ The user left the associated MUC """ + self.deactivate() if not status_message: self.get_room().add_message(_('\x191}%(spec)s \x193}%(nick)s\x195} has left the room') % {'nick':from_nick.replace('"', '\\"'), 'spec':get_theme().CHAR_QUIT.replace('"', '\\"')}) else: self.get_room().add_message(_('\x191}%(spec)s \x193}%(nick)s\x195} has left the room (%(status)s)"') % {'nick':from_nick.replace('"', '\\"'), 'spec':get_theme().CHAR_QUIT, 'status': status_message.replace('"', '\\"')}) - self.deactivate() - self.refresh() - self.core.doupdate() + if self.core.current_tab() is self: + self.refresh() + self.core.doupdate() def user_rejoined(self, nick): """ The user (or at least someone with the same nick) came back in the MUC """ - self.get_room().add_message('\x194}%(spec)s \x193}%(nick)s\x195} joined the room' % {'nick':nick, 'spec':get_theme().CHAR_JOIN}) self.activate() - self.refresh() - self.core.doupdate() + self.get_room().add_message('\x194}%(spec)s \x193}%(nick)s\x195} joined the room' % {'nick':nick, 'spec':get_theme().CHAR_JOIN}) + if self.core.current_tab() is self: + self.refresh() + self.core.doupdate() + def activate(self): self.on = True From 6037c4be65fd1a85e8500e830e61eef4837a815a Mon Sep 17 00:00:00 2001 From: mathieui Date: Sun, 25 Sep 2011 20:28:57 +0200 Subject: [PATCH 05/12] Fix some more presence leaks --- src/tabs.py | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/tabs.py b/src/tabs.py index f25006a8..1b0406f2 100644 --- a/src/tabs.py +++ b/src/tabs.py @@ -799,7 +799,8 @@ class MucTab(ChatTab): room.users.append(new_user) if from_nick == room.own_nick: room.joined = True - self.send_chat_state('active') + if self.core.current_tab() == self and self.core.status.show not in ('xa', 'away'): + self.send_chat_state('active') new_user.color = get_theme().COLOR_OWN_NICK room.add_message(_("\x195}Your nickname is \x193}%s") % (from_nick)) if '170' in status_codes: @@ -1021,7 +1022,8 @@ class PrivateTab(ChatTab): msg['body'] = xhtml.clean_text(line) msg['xhtml_im'] = xhtml.poezio_colors_to_html(line) if config.get('send_chat_states', 'true') == 'true' and self.remote_wants_chatstates is not False: - msg['chat_state'] = 'active' + needed = 'inactive' if self.core.status.show in ('xa', 'away') else 'active' + msg['chat_state'] = needed msg.send() self.core.add_message_to_text_buffer(self.get_room(), line, None, self.core.own_nick or self.get_room().own_nick) logger.log_message(JID(self.get_name()).bare, self.core.own_nick, line) @@ -1557,7 +1559,8 @@ class ConversationTab(ChatTab): msg['body'] = xhtml.clean_text(line) msg['xhtml_im'] = xhtml.poezio_colors_to_html(line) if config.get('send_chat_states', 'true') == 'true' and self.remote_wants_chatstates is not False: - msg['chat_state'] = 'active' + needed = 'inactive' if self.core.status.show in ('xa', 'away') else 'active' + msg['chat_state'] = needed msg.send() self.core.add_message_to_text_buffer(self.get_room(), line, None, self.core.own_nick) logger.log_message(JID(self.get_name()).bare, self.core.own_nick, line) From 4f96907653d80cf39ae5ae63cdfc45ccb40d7e62 Mon Sep 17 00:00:00 2001 From: mathieui Date: Mon, 26 Sep 2011 01:12:15 +0200 Subject: [PATCH 06/12] Fix the DataFormTab (was broken with the new theming method) --- src/data_forms.py | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/data_forms.py b/src/data_forms.py index 176c4669..4fcb41cf 100644 --- a/src/data_forms.py +++ b/src/data_forms.py @@ -16,6 +16,7 @@ import curses from windows import g_lock import windows from tabs import Tab +from theming import to_curses_attr class DataFormsTab(Tab): """ @@ -32,7 +33,6 @@ class DataFormsTab(Tab): for field in self._form: self.fields.append(field) self.topic_win = windows.Topic() - self.tab_win = windows.GlobalInfoBar() self.form_win = FormWin(form, self.height-4, self.width, 1, 0) self.help_win = windows.HelpText("Ctrl+Y: send form, Ctrl+G: cancel") self.help_win_dyn = windows.HelpText() @@ -86,7 +86,7 @@ class FieldInput(object): """ def __init__(self, field): self._field = field - self.color = 14 + self.color = (14, -1) def set_color(self, color): self.color = color @@ -146,7 +146,7 @@ class BooleanWin(FieldInput, windows.Win): def refresh(self): with g_lock: - self._win.attron(curses.color_pair(self.color)) + self._win.attron(to_curses_attr(self.color)) self.addnstr(0, 0, ' '*(8), self.width) self.addstr(0, 2, "%s"%self.value) self.addstr(0, 8, '→') @@ -155,7 +155,7 @@ class BooleanWin(FieldInput, windows.Win): self.addstr(0, 8, '') else: self.addstr(0, 0, '') - self._win.attroff(curses.color_pair(self.color)) + self._win.attroff(to_curses_attr(self.color)) self._refresh() def reply(self): @@ -210,7 +210,7 @@ class TextMultiWin(FieldInput, windows.Win): def refresh(self): if not self.edition_input: with g_lock: - self._win.attron(curses.color_pair(self.color)) + self._win.attron(to_curses_attr(self.color)) self.addnstr(0, 0, ' '*self.width, self.width) option = self.options[self.val_pos] self.addstr(0, self.width//2-len(option)//2, option) @@ -218,7 +218,7 @@ class TextMultiWin(FieldInput, windows.Win): self.addstr(0, 0, '←') if self.val_pos < len(self.options)-1: self.addstr(0, self.width-1, '→') - self._win.attroff(curses.color_pair(self.color)) + self._win.attroff(to_curses_attr(self.color)) self._refresh() else: self.edition_input.refresh() @@ -262,7 +262,7 @@ class ListMultiWin(FieldInput, windows.Win): def refresh(self): with g_lock: - self._win.attron(curses.color_pair(self.color)) + self._win.attron(to_curses_attr(self.color)) self.addnstr(0, 0, ' '*self.width, self.width) if self.val_pos > 0: self.addstr(0, 0, '←') @@ -271,7 +271,7 @@ class ListMultiWin(FieldInput, windows.Win): option = self.options[self.val_pos] self.addstr(0, self.width//2-len(option)//2, option[0]['label']) self.addstr(0, 2, '✔' if option[1] else '☐') - self._win.attroff(curses.color_pair(self.color)) + self._win.attroff(to_curses_attr(self.color)) self._refresh() def reply(self): @@ -308,7 +308,7 @@ class ListSingleWin(FieldInput, windows.Win): def refresh(self): with g_lock: - self._win.attron(curses.color_pair(self.color)) + self._win.attron(to_curses_attr(self.color)) self.addnstr(0, 0, ' '*self.width, self.width) if self.val_pos > 0: self.addstr(0, 0, '←') @@ -316,7 +316,7 @@ class ListSingleWin(FieldInput, windows.Win): self.addstr(0, self.width-1, '→') option = self.options[self.val_pos]['label'] self.addstr(0, self.width//2-len(option)//2, option) - self._win.attroff(curses.color_pair(self.color)) + self._win.attroff(to_curses_attr(self.color)) self._refresh() def reply(self): @@ -334,7 +334,7 @@ class TextSingleWin(FieldInput, windows.Input): self.text = field.getValue() if isinstance(field.getValue(), str)\ else "" self.pos = len(self.text) - self.color = 14 + self.color = (14, -1) def reply(self): self._field['label'] = '' @@ -351,15 +351,15 @@ class TextPrivateWin(TextSingleWin): with g_lock: self._win.erase() if self.color: - self._win.attron(curses.color_pair(self.color)) + self._win.attron(to_curses_attr(self.color)) self.addstr('*'*len(self.text[self.line_pos:self.line_pos+self.width-1])) if self.color: (y, x) = self._win.getyx() size = self.width-x - self.addnstr(' '*size, size, curses.color_pair(self.color)) + self.addnstr(' '*size, size, to_curses_attr(self.color)) self.addstr(0, self.pos, '') if self.color: - self._win.attroff(curses.color_pair(self.color)) + self._win.attroff(to_curses_attr(self.color)) self._refresh() def get_help_message(self): @@ -428,7 +428,7 @@ class FormWin(object): return if self.current_input == len(self.inputs) - 1 or self.current_input >= self.height-1: return - self.inputs[self.current_input]['input'].set_color(14) + self.inputs[self.current_input]['input'].set_color((14, -1)) self.current_input += 1 jump = 0 while self.current_input+jump != len(self.inputs) - 1 and self.inputs[self.current_input+jump]['input'].is_dummy(): @@ -436,14 +436,14 @@ class FormWin(object): if self.inputs[self.current_input+jump]['input'].is_dummy(): return self.current_input += jump - self.inputs[self.current_input]['input'].set_color(13) + self.inputs[self.current_input]['input'].set_color((13, -1)) def go_to_previous_input(self): if not self.inputs: return if self.current_input == 0: return - self.inputs[self.current_input]['input'].set_color(14) + self.inputs[self.current_input]['input'].set_color((14, -1)) self.current_input -= 1 jump = 0 while self.current_input-jump > 0 and self.inputs[self.current_input+jump]['input'].is_dummy(): @@ -451,7 +451,7 @@ class FormWin(object): if self.inputs[self.current_input+jump]['input'].is_dummy(): return self.current_input -= jump - self.inputs[self.current_input]['input'].set_color(13) + self.inputs[self.current_input]['input'].set_color((13, -1)) def on_input(self, key): if not self.inputs: @@ -480,7 +480,7 @@ class FormWin(object): break inp['input'].refresh() if self.current_input < self.height-1: - self.inputs[self.current_input]['input'].set_color(13) + self.inputs[self.current_input]['input'].set_color((13, -1)) self.inputs[self.current_input]['input'].refresh() def refresh_current_input(self): From a80338f25ba1f63a31e0675eb213a06ec9172032 Mon Sep 17 00:00:00 2001 From: mathieui Date: Mon, 26 Sep 2011 09:35:58 +0200 Subject: [PATCH 07/12] [teisenbe] Make the data forms more usable (highlight of the selected row) + theme colors instead of hardcoded ones --- src/data_forms.py | 45 ++++++++++++++++++++++++++++++++++++--------- 1 file changed, 36 insertions(+), 9 deletions(-) diff --git a/src/data_forms.py b/src/data_forms.py index 4fcb41cf..873aef85 100644 --- a/src/data_forms.py +++ b/src/data_forms.py @@ -16,7 +16,7 @@ import curses from windows import g_lock import windows from tabs import Tab -from theming import to_curses_attr +from theming import to_curses_attr, get_theme class DataFormsTab(Tab): """ @@ -114,6 +114,27 @@ class FieldInput(object): """ return '' +class ColoredLabel(windows.Win): + def __init__(self, text): + self.text = text + self.color = get_theme().COLOR_NORMAL_TEXT + windows.Win.__init__(self) + + def resize(self, height, width, y, x): + self._resize(height, width, y, x) + + def set_color(self, color): + self.color = color + self.refresh() + + def refresh(self): + with g_lock: + self._win.attron(to_curses_attr(self.color)) + self.addstr(0, 0, self.text) + self._win.attroff(to_curses_attr(self.color)) + self._refresh() + + class DummyInput(FieldInput, windows.Win): """ Used for fields that do not require any input ('fixed') @@ -399,7 +420,7 @@ class FormWin(object): if field['type'] == 'fixed': label = field.getValue() inp = input_class(field) - self.inputs.append({'label':label, + self.inputs.append({'label':ColoredLabel(label), 'description': desc, 'input':inp}) @@ -428,7 +449,8 @@ class FormWin(object): return if self.current_input == len(self.inputs) - 1 or self.current_input >= self.height-1: return - self.inputs[self.current_input]['input'].set_color((14, -1)) + self.inputs[self.current_input]['input'].set_color(get_theme().COLOR_NORMAL_TEXT) + self.inputs[self.current_input]['label'].set_color(get_theme().COLOR_NORMAL_TEXT) self.current_input += 1 jump = 0 while self.current_input+jump != len(self.inputs) - 1 and self.inputs[self.current_input+jump]['input'].is_dummy(): @@ -436,14 +458,16 @@ class FormWin(object): if self.inputs[self.current_input+jump]['input'].is_dummy(): return self.current_input += jump - self.inputs[self.current_input]['input'].set_color((13, -1)) + self.inputs[self.current_input]['input'].set_color(get_theme().COLOR_SELECTED_ROW) + self.inputs[self.current_input]['label'].set_color(get_theme().COLOR_SELECTED_ROW) def go_to_previous_input(self): if not self.inputs: return if self.current_input == 0: return - self.inputs[self.current_input]['input'].set_color((14, -1)) + self.inputs[self.current_input]['input'].set_color(get_theme().COLOR_NORMAL_TEXT) + self.inputs[self.current_input]['label'].set_color(get_theme().COLOR_NORMAL_TEXT) self.current_input -= 1 jump = 0 while self.current_input-jump > 0 and self.inputs[self.current_input+jump]['input'].is_dummy(): @@ -451,7 +475,8 @@ class FormWin(object): if self.inputs[self.current_input+jump]['input'].is_dummy(): return self.current_input -= jump - self.inputs[self.current_input]['input'].set_color((13, -1)) + self.inputs[self.current_input]['input'].set_color(get_theme().COLOR_SELECTED_ROW) + self.inputs[self.current_input]['label'].set_color(get_theme().COLOR_SELECTED_ROW) def on_input(self, key): if not self.inputs: @@ -466,8 +491,7 @@ class FormWin(object): for name, field in self._form.getFields(): if field['type'] == 'hidden': continue - label = self.inputs[i]['label'] - self._win.addstr(y, 0, label) + self.inputs[i]['label'].resize(1, self.width//3, y + 1, 0) self.inputs[i]['input'].resize(1, self.width//3, y+1, 2*self.width//3) # TODO: display the field description y += 1 @@ -479,9 +503,12 @@ class FormWin(object): if i >= self.height: break inp['input'].refresh() + inp['label'].refresh() if self.current_input < self.height-1: - self.inputs[self.current_input]['input'].set_color((13, -1)) + self.inputs[self.current_input]['input'].set_color(get_theme().COLOR_SELECTED_ROW) self.inputs[self.current_input]['input'].refresh() + self.inputs[self.current_input]['label'].set_color(get_theme().COLOR_SELECTED_ROW) + self.inputs[self.current_input]['label'].refresh() def refresh_current_input(self): self.inputs[self.current_input]['input'].refresh() From ff3c40c5b47b311b7f4d3f157c9d5bd63fe99b39 Mon Sep 17 00:00:00 2001 From: mathieui Date: Mon, 26 Sep 2011 10:40:04 +0200 Subject: [PATCH 08/12] Fixes a bug when the user leaves a MucTab, goes to a privatetab and /join with no args (it joined the muc, but did not open a new tab) --- src/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core.py b/src/core.py index 3c4af5d9..766be909 100644 --- a/src/core.py +++ b/src/core.py @@ -1275,7 +1275,7 @@ class Core(object): t = self.current_tab() if not isinstance(t, tabs.MucTab) and not isinstance(t, tabs.PrivateTab): return - room = t.get_name() + room = JID(t.get_name()).bare nick = t.get_room().own_nick else: info = JID(args[0]) From 092da9d5b2f9cd902555073e1330adb18a6e52b5 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Tue, 27 Sep 2011 15:27:42 +0200 Subject: [PATCH 09/12] test commit --- README | 1 + 1 file changed, 1 insertion(+) diff --git a/README b/README index 49d31384..e91aed62 100644 --- a/README +++ b/README @@ -97,3 +97,4 @@ the Creative Commons BY license (http://creativecommons.org/licenses/by/2.0/) FlashCode (weechat dev) - Useful advices on how to use ncurses efficiently = Project = Gajim - send_vcard method and common.py + From d93ac5c1ba6f97f961312852f39072a5a1e5b532 Mon Sep 17 00:00:00 2001 From: mathieui Date: Tue, 27 Sep 2011 19:14:15 +0200 Subject: [PATCH 10/12] Backed out changeset 087bfa4fc8be --- README | 1 - 1 file changed, 1 deletion(-) diff --git a/README b/README index e91aed62..49d31384 100644 --- a/README +++ b/README @@ -97,4 +97,3 @@ the Creative Commons BY license (http://creativecommons.org/licenses/by/2.0/) FlashCode (weechat dev) - Useful advices on how to use ncurses efficiently = Project = Gajim - send_vcard method and common.py - From cb4f095291493ae59eeb21b186432c507af006fa Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Thu, 29 Sep 2011 00:18:08 +0200 Subject: [PATCH 11/12] [zorun] update man, add key bindings descriptions, etc --- data/poezio.1 | 158 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 156 insertions(+), 2 deletions(-) diff --git a/data/poezio.1 b/data/poezio.1 index 769bab60..235ee950 100644 --- a/data/poezio.1 +++ b/data/poezio.1 @@ -1,9 +1,9 @@ .\" Copyright 2010 Le Coz Florent .\" This man page is distributed under the GPLv3 license. .\" See COPYING file -.TH "Poezio" "1" "August 1, 2010" "Poezio dev team" "" +.TH "Poezio" "1" "September 26, 2011" "Poezio dev team" "" .SH "NAME" -Poezio \- a ncurses jabber client +Poezio \- a ncurses jabber client written in python3 .SH "SYNOPSIS" .B poezio [\-f \fICONFIG_FILE\fR] [\-d \fIDEBUG_FILE\fR] [\-h] .SH "DESCRIPTION" @@ -20,10 +20,164 @@ Log debug from both poezio and SleekXMPP in \fIDEBUG_FILE\fR. Debug contains inc .TP \fB\-h\fR Display an help message + +.SH "TABS" +A \fItab\fR, in Poezio, is the base structure of the interface. A tab may contains one or more \fIwindows\fR, and can be of different types: +.RS +.TP 6 +.I Roster \fRtab +It contains a list of your contacts on the left, as well as an info window on the right. +.TP +.I MUC \fRtab +MUC stands for "Multi-User Chat". +.TP +.I Conversation \fRtab +It is used for one-to-one communication, usually when using a real Jabber account. +.TP +.I Private \fRtab +It is used to privately communicate with someone in a MUC. + +.SH "KEY BINDINGS" +While most of the keyboard shortcuts are common to all types of tabs, some of them are tab-specific. +.SS Text edition +These shortcuts work in any kind of tab; most of them are identical to emacs' ones. +.RS +.TP 8 +.B Ctrl+A +Move the cursor to the begining of the line. +.TP +.B Ctrl+E +Move the cursor to the end of the line. +.TP +.B Ctrl+W +Delete the word before the cursor. +.TP +.B Ctrl+K +Delete the text from the cursor to the end of the line and save it in the clipboard. +.TP +.B Ctrl+U +Delete the text from the beginning of the line to the cursor and save it in the clipboard. +.TP +.B Ctrl+Y +Insert the text in the clipboard after the cursor. +.TP +.B Ctrl+D +Delete the char after the cursor (same as the Suppr key) + +.SS Navigation keybindings +.RS +.TP 8 +.B F5, Ctrl+N +Go to the previous tab. +.TP +.B F6, Ctrl+P +Go to the next tab. +.TP +.B Alt+ +Go to the specified tab (from 0 to 9) +.TP +.B Alt+J +Go to the specified tab (from 00 to 99) +.TP +.B Alt+Z +Go to the last visited tab. +.TP +.B Alt+E +Go to the next important tab (private message, highlight, simple message) +.TP +.B F7 +Decrease the information window size. +.TP +.B F8 +Increase the information window size. +.TP +.B Alt+R +Go to the roster. +.TP +.B Ctrl+L +Redraw the screen. +.TP +.B Up, Down +Browse the history of the last messages or commands you've entered. + +.SS Roster keybindings +.RS +.TP 8 +.B o +Hide or show the offline contacts. +.TP +.B s +Search through your contact list. +.TP +.B Ctrl+G +Cancel a search. + +.SS MUC-specific keybindings +.RS +.TP 8 +.B Alt+V +Move the line separator at the bottom of the text window. +.TP +.B Tab +Complete the nickname that you're typing. If nothing has been entered, insert the nickname of the last user who spoke. +.TP +.B Alt+/ +Complete the word that you're typing, based on the list of the recently said words in the conversation. + +.SH "COMMANDS" +Most commands support tab completion, both for their names and for their arguments. You can use the \fI/help\fR command to list all available commands, and \fI/help \fR for a complete description of . + +The following is a basic description of the most widely used commands; you should refer to \fI/help\fR inside poezio for more documentation. \fI\fR denotes a obligatory argument, while \fI[bar]\fR is an optional argument (without argument, the \fI/remove\fR command, for example, acts on the currently selected contact) +.SS Roster commands +.RS +.TP 5 +.B /add +Add a JID to your roster. +.TP +.B /remove [jid] +Remove a contact from your roster. +.TP +.B /accept [jid] +Accept a JID that wants to subscribe to your presence. +.TP +.B /deny [jid] +The opposite of \fI/accept\fR. + +.SS MUC-specific commands +.RS +.TP 5 +.B /recolor +Change the color of the nicknames in the conversation. Useful when a few people are talking and their random color happen to be the same: using this command will let you differentiate them more easily. +.TP +.B /kick +Kick the specified user from the room. +.TP +.B /show [message] +Change your status, and status message, in the current room. You can use “avail”, “busy”, “away” and “xa” as your status, followed by an optional message. +.TP +.B /ignore +Ignore the specified user. +.TP +.B /topic [topic text] +View or change the topic of the room. +.TP +.B /query +Talk privately with the specified participant. +.TP +.B /part +Leave the current room. + .SH "BUGS" Sure. + +.SH "KNOWN ISSUES" +If you're using a terminal multiplexer such as \fIscreen\fR or \fItmux\fR, it may be setting $TERM to "screen", which breaks 256-color support. Consider setting your $TERM to something like "screen-256color". + .SH "FEEDBACK" You are encouraged to report bugs or feature requests on http://dev.louiz.org/project/poezio. You can also find us on the Jabber chatroom poezio@kikoo.louiz.org + .SH "AUTHORS" Written by Florent Le Coz + +Later completed by Baptiste Jonglez From 31cad9a4ac79d2fd759b1add7ed20b15b705de85 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Thu, 29 Sep 2011 00:19:33 +0200 Subject: [PATCH 12/12] Fix that resize bug AGAIN --- src/tabs.py | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/tabs.py b/src/tabs.py index 1b0406f2..63fd2c96 100644 --- a/src/tabs.py +++ b/src/tabs.py @@ -681,6 +681,7 @@ class MucTab(ChatTab): """ if not self.visible: return + self.need_resize = False text_width = (self.width//10)*9 self.topic_win.resize(1, self.width, 0, 0) self.v_separator.resize(self.height-3, 1, 1, 9*(self.width//10)) @@ -1065,6 +1066,7 @@ class PrivateTab(ChatTab): def resize(self): if self.core.information_win_size >= self.height-3 or not self.visible: return + self.need_resize = False self.text_win.resize(self.height-3-self.core.information_win_size, self.width, 0, 0) self.text_win.rebuild_everything(self._room) self.info_header.resize(1, self.width, self.height-3-self.core.information_win_size, 0) @@ -1217,6 +1219,7 @@ class RosterInfoTab(Tab): def resize(self): if not self.visible: return + self.need_resize = False roster_width = self.width//2 info_width = self.width-roster_width-1 self.v_separator.resize(self.height-2, 1, 0, roster_width) @@ -1574,6 +1577,7 @@ class ConversationTab(ChatTab): def resize(self): if self.core.information_win_size >= self.height-3 or not self.visible: return + self.need_resize = False self.text_win.resize(self.height-4-self.core.information_win_size, self.width, 1, 0) self.text_win.rebuild_everything(self._room) self.upper_bar.resize(1, self.width, 0, 0) @@ -1691,6 +1695,7 @@ class MucListTab(Tab): def resize(self): if not self.visible: return + self.need_resize = False self.upper_message.resize(1, self.width, 0, 0) column_size = {'node-part': (self.width-5)//4, 'name': (self.width-5)//4*3, @@ -1825,6 +1830,7 @@ class SimpleTextTab(Tab): def resize(self): if not self.visible: return + self.need_resize = False self.text_win.resize(self.height-2, self.width, 0, 0) self.input.resize(1, self.width, self.height-1, 0)