diff options
-rw-r--r-- | doc/en/configure.txt | 56 | ||||
-rw-r--r-- | src/config.py | 18 | ||||
-rw-r--r-- | src/core.py | 9 | ||||
-rw-r--r-- | src/tabs.py | 64 |
4 files changed, 114 insertions, 33 deletions
diff --git a/doc/en/configure.txt b/doc/en/configure.txt index cad24be3..4e93a2c5 100644 --- a/doc/en/configure.txt +++ b/doc/en/configure.txt @@ -11,8 +11,9 @@ in the _keys_ documentation file. That file is read at each startup and the configuration is saved when poezio is closed. -This configuration file *requires* all the options to be in a section -named [Poezio]. +This configuration file *requires* all global options to be in a section +named [Poezio]. Some other options can be in optional sections and will +apply only to tabs having the option’s name. An option is formatted with the form ====================== @@ -29,6 +30,13 @@ and their default value. Configuration options --------------------- +Global section options +~~~~~~~~~~~~~~~~~~~~~~ + +These option have a sense when they are in the global section. Some of +them can also be in an optional configuration section, see the next +section of this documentation. + [horizontal] *server*:: anon.louiz.org @@ -67,8 +75,6 @@ Configuration options A password is needed only if you specified a jid. It will be ignored otherwise If you leave this empty, the password will be asked at each startup - - *rooms*:: poezio@muc.poezio.eu the rooms you will join automatically on startup, with associated nickname or not @@ -137,6 +143,10 @@ Configuration options Default setting means: - all quit and join notices will be displayed +*display_user_color_in_join_part*:: false + + If set to true, the color of the nick will be used in MUCs information + messages, instead of the default color from the theme. *information_buffer_popup_on*:: error roster warning help info @@ -309,3 +319,41 @@ Configuration options You can specify another directory to use. It will be created if it does not exist. +Optional section options +~~~~~~~~~~~~~~~~~~~~~~~~ +These option can appear in optional sections. These section are named +after a JID. These option will apply only for the given JID. For example +if an option appears in a section named [user@example.com], it will +apply only for the conversations with user@example.com. + +Note that some of these options can also appear in the global section, +they will be used as a fallback value when no JID-specific option is +found. + +.foo is _true_ for *user@example.com* but is _false_ for everyone else +============================================ +[source,conf] +------------- +[Poezio] +foo = false +[user@example.com] +foo = true +------------- +============================================ + +*disable_beep*:: false + + Disable the beeps triggered by this conversation. Works in MucTab, + PrivateTab and ConversationTab. + +*send_chat_states*:: true + + Lets you disable/enable chatstates per-JID. Works in MucTab, PrivateTab and ConversationTab. + +*display_user_color_in_join_part*:: false + +*hide_exit_join*:: -1 + +*hide_status_change*:: 120 + +*highlight_on*:: [empty] diff --git a/src/config.py b/src/config.py index 8bc0d863..af9c9fbe 100644 --- a/src/config.py +++ b/src/config.py @@ -46,10 +46,26 @@ class Config(RawConfigParser): res = self.getboolean(option, section) else: res = self.getstr(option, section) - except( NoOptionError, NoSectionError): + except (NoOptionError, NoSectionError): return default return res + def get_by_tabname(self, option, default, tabname, fallback=True): + """ + Try to get the value for the option. First we look in + a section named `tabname`, if the option is not present + in the section, we search for the global option if fallback is + True. And we return `default` as a fallback as a last resort. + """ + if tabname in self.sections(): + if option in self.options(tabname): + # We go the tab-specific option + return self.get(option, default, tabname) + if fallback: + # We fallback to the global option + return self.get(option, default) + return default + def __get(self, option, section=DEFSECTION): """ facility for RawConfigParser.get diff --git a/src/core.py b/src/core.py index 8704563c..b940bb73 100644 --- a/src/core.py +++ b/src/core.py @@ -687,7 +687,8 @@ class Core(object): else: conversation.remote_wants_chatstates = False if 'private' in config.get('beep_on', 'highlight private').split(): - curses.beep() + if config.get_by_tabname('disable_beep', 'false', jid.full, False).lower() != 'true': + curses.beep() logger.log_message(jid.full.replace('/', '\\'), nick_from, body) if conversation is self.current_tab(): self.refresh_window() @@ -745,7 +746,8 @@ class Core(object): conversation.remote_wants_chatstates = False logger.log_message(jid.bare, remote_nick, body) if 'private' in config.get('beep_on', 'highlight private').split(): - curses.beep() + if config.get_by_tabname('disable_beep', 'false', jid.bare, False).lower() != 'true': + curses.beep() if self.current_tab() is not conversation: conversation.state = 'private' self.refresh_tab_win() @@ -1207,7 +1209,8 @@ class Core(object): tab.info_header.refresh(tab, tab.text_win) self.refresh_tab_win() if 'message' in config.get('beep_on', 'highlight private').split(): - curses.beep() + if config.get_by_tabname('disable_beep', 'false', jid.bare, False).lower() != 'true': + curses.beep() def add_message_to_text_buffer(self, buff, txt, time=None, nickname=None, history=None): """ diff --git a/src/tabs.py b/src/tabs.py index f9940d82..e75989a7 100644 --- a/src/tabs.py +++ b/src/tabs.py @@ -440,7 +440,8 @@ class ChatTab(Tab): Send the "active" or "composing" chatstate, depending on the the current status of the input """ - if config.get('send_chat_states', 'true') == 'true' and self.remote_wants_chatstates: + name = self.general_jid + if config.get_by_tabname('send_chat_states', 'true', name, True) == 'true' and self.remote_wants_chatstates: needed = 'inactive' if self.core.status.show in ('xa', 'away') else 'active' self.cancel_paused_delay() if not empty_after: @@ -455,7 +456,7 @@ class ChatTab(Tab): we create a timed event that will put us to paused in a few seconds """ - if config.get('send_chat_states', 'true') != 'true': + if config.get_by_tabname('send_chat_states', 'true', self.general_jid, True) != 'true': return if self.timed_event_paused: # check the weakref @@ -546,6 +547,10 @@ class MucTab(ChatTab): self.update_commands() self.update_keys() + @property + def general_jid(self): + return self.get_name() + def completion_version(self, the_input): """Completion for /version""" compare_users = lambda x: x.last_talked @@ -880,7 +885,7 @@ class MucTab(ChatTab): if msg['body'].find('\x19') != -1: msg['xhtml_im'] = xhtml.poezio_colors_to_html(msg['body']) msg['body'] = xhtml.clean_text(msg['body']) - if config.get('send_chat_states', 'true') == 'true' and self.remote_wants_chatstates is not False: + if config.get_by_tabname('send_chat_states', 'true', self.general_jid, True) == 'true' and self.remote_wants_chatstates is not False: msg['chat_state'] = needed self.cancel_paused_delay() self.core.events.trigger('muc_say_after', msg, self) @@ -1002,7 +1007,7 @@ class MucTab(ChatTab): self.state = 'normal' self.text_win.remove_line_separator() self.text_win.add_line_separator() - if config.get('send_chat_states', 'true') == 'true' and not self.input.get_text(): + if config.get_by_tabname('send_chat_states', 'true', self.general_jid, True) == 'true' and not self.input.get_text(): self.send_chat_state('inactive') def on_gain_focus(self): @@ -1010,7 +1015,7 @@ class MucTab(ChatTab): if self.text_win.built_lines and self.text_win.built_lines[-1] is None: self.text_win.remove_line_separator() curses.curs_set(1) - if self.joined and config.get('send_chat_states', 'true') == 'true' and not self.input.get_text(): + if self.joined and config.get_by_tabname('send_chat_states', 'true', self.general_jid, True) == 'true' and not self.input.get_text(): self.send_chat_state('active') def on_scroll_up(self): @@ -1089,9 +1094,9 @@ class MucTab(ChatTab): user = User(from_nick, affiliation, show, status, role, jid) self.users.append(user) - hide_exit_join = config.get('hide_exit_join', -1) + hide_exit_join = config.get_by_tabname('hide_exit_join', -1, self.general_jid, True) if hide_exit_join != 0: - color = user.color[0] if config.get('display_user_color_in_join_part', '') == 'true' else 3 + color = user.color[0] if config.get_by_tabname('display_user_color_in_join_part', '', self.general_jid, True) == 'true' else 3 if not jid.full: self.add_message('\x194}%(spec)s \x19%(color)d}%(nick)s\x195} joined the room' % {'nick':from_nick, 'color':color, 'spec':get_theme().CHAR_JOIN}) else: @@ -1107,7 +1112,7 @@ class MucTab(ChatTab): if isinstance(_tab, PrivateTab) and JID(_tab.get_name()).bare == self.name: _tab.own_nick = new_nick user.change_nick(new_nick) - color = user.color[0] if config.get('display_user_color_in_join_part', '') == 'true' else 3 + color = user.color[0] if config.get_by_tabname('display_user_color_in_join_part', '', self.general_jid, True) == 'true' else 3 self.add_message('\x19%(color)d}%(old)s\x195} is now known as \x19%(color)d}%(new)s' % {'old':from_nick, 'new':new_nick, 'color':color}) # rename the private tabs if needed self.core.rename_private_tabs(self.name, from_nick, new_nick) @@ -1130,7 +1135,7 @@ class MucTab(ChatTab): else: kick_msg = _('\x191}%(spec)s \x193}You\x195} have been banned.') % {'spec':get_theme().CHAR_KICK} else: - color = user.color[0] if config.get('display_user_color_in_join_part', '') == 'true' else 3 + color = user.color[0] if config.get_by_tabname('display_user_color_in_join_part', '', self.general_jid, True) == 'true' else 3 if by: kick_msg = _('\x191}%(spec)s \x19%(color)d}%(nick)s\x195} has been banned by \x194}%(by)s') % {'spec':get_theme().CHAR_KICK, 'nick':from_nick, 'color':color, 'by':by} else: @@ -1157,10 +1162,10 @@ class MucTab(ChatTab): else: kick_msg = _('\x191}%(spec)s \x193}You\x195} have been kicked.') % {'spec':get_theme().CHAR_KICK} # try to auto-rejoin - if config.get('autorejoin', 'false') == 'true': + if config.get_by_tabname('autorejoin', 'false', self.general_jid, True) == 'true': muc.join_groupchat(self.core.xmpp, self.name, self.own_nick) else: - color = user.color[0] if config.get('display_user_color_in_join_part', '') == 'true' else 3 + color = user.color[0] if config.get_by_tabname('display_user_color_in_join_part', '', self.general_jid, True) == 'true' else 3 if by: kick_msg = _('\x191}%(spec)s \x19%(color)d}%(nick)s\x195} has been kicked by \x193}%(by)s') % {'spec':get_theme().CHAR_KICK.replace('"', '\\"'), 'nick':from_nick.replace('"', '\\"'), 'color':color, 'by':by.replace('"', '\\"')} else: @@ -1180,9 +1185,9 @@ class MucTab(ChatTab): self.core.disable_private_tabs(from_room) self.refresh_tab_win() self.core.doupdate() - hide_exit_join = config.get('hide_exit_join', -1) if config.get('hide_exit_join', -1) >= -1 else -1 + hide_exit_join = config.get_by_tabname('hide_exit_join', -1, self.general_jid, True) if config.get_by_tabname('hide_exit_join', -1, self.general_jid, True) >= -1 else -1 if hide_exit_join == -1 or user.has_talked_since(hide_exit_join): - color = user.color[0] if config.get('display_user_color_in_join_part', '') == 'true' else 3 + color = user.color[0] if config.get_by_tabname('display_user_color_in_join_part', '', self.general_jid, True) == 'true' else 3 if not jid.full: leave_msg = _('\x191}%(spec)s \x19%(color)d}%(nick)s\x195} has left the room') % {'nick':from_nick, 'color':color, 'spec':get_theme().CHAR_QUIT} else: @@ -1200,7 +1205,7 @@ class MucTab(ChatTab): # build the message display_message = False # flag to know if something significant enough # to be displayed has changed - color = user.color[0] if config.get('display_user_color_in_join_part', '') == 'true' else 3 + color = user.color[0] if config.get_by_tabname('display_user_color_in_join_part', '', self.general_jid, True) == 'true' else 3 if from_nick == self.own_nick: msg = _('\x193}You\x195} changed: ') else: @@ -1228,7 +1233,7 @@ class MucTab(ChatTab): if not display_message: return msg = msg[:-2] # remove the last ", " - hide_status_change = config.get('hide_status_change', -1) + hide_status_change = config.get_by_tabname('hide_status_change', -1, self.general_jid, True) if hide_status_change < -1: hide_status_change = -1 if (hide_status_change == -1 or \ @@ -1279,7 +1284,7 @@ class MucTab(ChatTab): self.state = 'highlight' color = get_theme().COLOR_HIGHLIGHT_NICK else: - highlight_words = config.get('highlight_on', '').split(':') + highlight_words = config.get_by_tabname('highlight_on', '', self.general_jid, True).split(':') for word in highlight_words: if word and word.lower() in txt.lower(): if self.state != 'current': @@ -1289,7 +1294,8 @@ class MucTab(ChatTab): if color: beep_on = config.get('beep_on', 'highlight private').split() if 'highlight' in beep_on and 'message' not in beep_on: - curses.beep() + if config.get_by_tabname('disable_beep', 'false', self.name, False).lower() != 'true': + curses.beep() return color def get_user_by_name(self, nick): @@ -1356,6 +1362,10 @@ class PrivateTab(ChatTab): self.update_commands() self.update_keys() + @property + def general_jid(self): + return self.get_name() + def completion(self): self.complete_commands(self.input) @@ -1373,7 +1383,7 @@ class PrivateTab(ChatTab): if msg['body'].find('\x19') != -1: msg['xhtml_im'] = xhtml.poezio_colors_to_html(msg['body']) msg['body'] = xhtml.clean_text(msg['body']) - if config.get('send_chat_states', 'true') == 'true' and self.remote_wants_chatstates is not False: + if config.get_by_tabname('send_chat_states', 'true', self.general_jid, True) == 'true' and self.remote_wants_chatstates is not False: needed = 'inactive' if self.core.status.show in ('xa', 'away') else 'active' msg['chat_state'] = needed self.core.events.trigger('private_say_after', msg, self) @@ -1457,14 +1467,14 @@ class PrivateTab(ChatTab): self.text_win.remove_line_separator() self.text_win.add_line_separator() tab = self.core.get_tab_by_name(JID(self.name).bare, MucTab) - if tab.joined and config.get('send_chat_states', 'true') == 'true' and not self.input.get_text(): + if tab.joined and config.get_by_tabname('send_chat_states', 'true', self.general_jid, True) == 'true' and not self.input.get_text(): self.send_chat_state('inactive') def on_gain_focus(self): self.state = 'current' curses.curs_set(1) tab = self.core.get_tab_by_name(JID(self.name).bare, MucTab) - if tab.joined and config.get('send_chat_states', 'true') == 'true' and not self.input.get_text(): + if tab.joined and config.get_by_tabname('send_chat_states', 'true', self.general_jid, True) == 'true' and not self.input.get_text(): self.send_chat_state('active') def on_scroll_up(self): @@ -1511,7 +1521,7 @@ class PrivateTab(ChatTab): self.activate() tab = self.core.get_tab_by_name(JID(self.name).bare, MucTab) color = 3 - if tab and config.get('display_user_color_in_join_part', ''): + if tab and config.get_by_tabname('display_user_color_in_join_part', '', self.general_jid, True): user = tab.get_user_by_name(nick) if user: color = user.color[0] @@ -2085,6 +2095,10 @@ class ConversationTab(ChatTab): self.update_commands() self.update_keys() + @property + def general_jid(self): + return JID(self.get_name()).bare + @staticmethod def add_information_element(plugin_name, callback): """ @@ -2112,7 +2126,7 @@ class ConversationTab(ChatTab): if msg['body'].find('\x19') != -1: msg['xhtml_im'] = xhtml.poezio_colors_to_html(msg['body']) msg['body'] = xhtml.clean_text(msg['body']) - if config.get('send_chat_states', 'true') == 'true' and self.remote_wants_chatstates is not False: + if config.get_by_tabname('send_chat_states', 'true', self.general_jid, True) == 'true' and self.remote_wants_chatstates is not False: needed = 'inactive' if self.core.status.show in ('xa', 'away') else 'active' msg['chat_state'] = needed self.core.events.trigger('conversation_say_after', msg, self) @@ -2202,7 +2216,7 @@ class ConversationTab(ChatTab): self.state = 'normal' self.text_win.remove_line_separator() self.text_win.add_line_separator() - if config.get('send_chat_states', 'true') == 'true' and (not self.input.get_text() or not self.input.get_text().startswith('//')): + if config.get_by_tabname('send_chat_states', 'true', self.general_jid, True) == 'true' and (not self.input.get_text() or not self.input.get_text().startswith('//')): if resource: self.send_chat_state('inactive') @@ -2219,7 +2233,7 @@ class ConversationTab(ChatTab): self.state = 'current' curses.curs_set(1) - if config.get('send_chat_states', 'true') == 'true' and (not self.input.get_text() or not self.input.get_text().startswith('//')): + if config.get_by_tabname('send_chat_states', 'true', self.general_jid, True) == 'true' and (not self.input.get_text() or not self.input.get_text().startswith('//')): if resource: self.send_chat_state('active') @@ -2241,7 +2255,7 @@ class ConversationTab(ChatTab): def on_close(self): Tab.on_close(self) - if config.get('send_chat_states', 'true') == 'true': + if config.get_by_tabname('send_chat_states', 'true', self.general_jid, True) == 'true': self.send_chat_state('gone') def add_message(self, txt, time=None, nickname=None, forced_user=None): |