summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/plugin.py12
-rw-r--r--src/plugin_manager.py31
-rw-r--r--src/tabs.py25
3 files changed, 68 insertions, 0 deletions
diff --git a/src/plugin.py b/src/plugin.py
index 40f96871..4dd88697 100644
--- a/src/plugin.py
+++ b/src/plugin.py
@@ -93,6 +93,18 @@ class BasePlugin(object, metaclass=SafetyMetaclass):
"""
return self.plugin_manager.del_command(self.__module__, name)
+ def add_tab_command(self, tab_type, name, handler, help, completion=None):
+ """
+ Add a command only for a type of tab.
+ """
+ return self.plugin_manager.add_tab_command(self.__module__, tab_type, name, handler, help, completion)
+
+ def del_tab_command(self, tab_type, name):
+ """
+ Delete a command added through add_tab_command.
+ """
+ return self.plugin_manager.del_tab_command(self.__module__, tab_type, name)
+
def add_event_handler(self, event_name, handler, position=0):
"""
Add an event handler to the event event_name.
diff --git a/src/plugin_manager.py b/src/plugin_manager.py
index 83ae53d5..36887084 100644
--- a/src/plugin_manager.py
+++ b/src/plugin_manager.py
@@ -1,6 +1,7 @@
import imp
import os
import sys
+import tabs
from config import config
from gettext import gettext as _
@@ -34,6 +35,7 @@ class PluginManager(object):
self.plugins = {} # module name -> plugin object
self.commands = {} # module name -> dict of commands loaded for the module
self.event_handlers = {} # module name -> list of event_name/handler pairs loaded for the module
+ self.tab_commands = {} #module name -> dict of tab types; tab type -> commands loaded by the module
def load(self, name):
if name in self.plugins:
@@ -59,6 +61,7 @@ class PluginManager(object):
self.modules[name] = module
self.commands[name] = {}
+ self.tab_commands[name] = {}
self.event_handlers[name] = []
self.plugins[name] = module.Plugin(self, self.core, plugins_conf_dir)
self.core.information('Plugin %s loaded' % name, 'Info')
@@ -68,12 +71,17 @@ class PluginManager(object):
try:
for command in self.commands[name].keys():
del self.core.commands[command]
+ for tab in list(self.tab_commands[name].keys()):
+ for command in self.tab_commands[name][tab]:
+ self.del_tab_command(name, getattr(tabs, tab), command[0])
+ del self.tab_commands[name][tab]
for event_name, handler in self.event_handlers[name]:
self.del_event_handler(name, event_name, handler)
self.plugins[name].unload()
del self.plugins[name]
del self.commands[name]
+ del self.tab_commands[name]
del self.event_handlers[name]
self.core.information('Plugin %s unloaded' % name, 'Info')
except Exception as e:
@@ -86,6 +94,29 @@ class PluginManager(object):
if name in self.core.commands:
del self.core.commands[name]
+ def add_tab_command(self, module_name, tab_type, name, handler, help, completion=None):
+ commands = self.tab_commands[module_name]
+ t = tab_type.__name__
+ if not t in commands:
+ commands[t] = []
+ commands[t].append((name, handler, help, completion))
+ for tab in self.core.tabs:
+ if isinstance(tab, tab_type):
+ tab.add_plugin_command(name, handler, help, completion)
+
+ def del_tab_command(self, module_name, tab_type, name):
+ commands = self.tab_commands[module_name]
+ t = tab_type.__name__
+ if not t in commands:
+ return
+ for command in commands[t]:
+ if command[0] == name:
+ commands[t].remove(command)
+ del tab_type.plugin_commands[name]
+ for tab in self.core.tabs:
+ if isinstance(tab, tab_type) and name in tab.commands:
+ del tab.commands[name]
+
def add_command(self, module_name, name, handler, help, completion=None):
if name in self.core.commands:
raise Exception(_("Command '%s' already exists") % (name,))
diff --git a/src/tabs.py b/src/tabs.py
index 64eda75a..f037a368 100644
--- a/src/tabs.py
+++ b/src/tabs.py
@@ -91,6 +91,7 @@ class Tab(object):
# and use them in on_input
self.commands = {} # and their own commands
+
@property
def core(self):
if not Tab.tab_core:
@@ -220,6 +221,18 @@ class Tab(object):
def on_input(self, key):
pass
+ def add_plugin_command(self, name, handler, help, completion=None):
+ if name in self.plugin_commands or name in self.commands:
+ return
+ self.plugin_commands[name] = (handler, help, completion)
+ self.commands[name] = (handler, help, completion)
+ self.update_commands()
+
+ def update_commands(self):
+ for c in self.plugin_commands:
+ if not c in self.commands:
+ self.commands[name] = self.plugin_commands[c]
+
def on_lose_focus(self):
"""
called when this tab loses the focus.
@@ -275,6 +288,7 @@ class ChatTab(Tab):
Also, ^M is already bound to on_enter
And also, add the /say command
"""
+ plugin_commands = {}
def __init__(self):
Tab.__init__(self)
self._text_buffer = TextBuffer()
@@ -295,6 +309,7 @@ class ChatTab(Tab):
_("""Usage: /say <message>\nSay: Just send the message.
Useful if you want your message to begin with a '/'."""), None)
self.chat_state = None
+ self.update_commands()
def last_words_completion(self):
"""
@@ -402,6 +417,7 @@ class MucTab(ChatTab):
It contains an userlist, an input, a topic, an information and a chat zone
"""
message_type = 'groupchat'
+ plugin_commands = {}
def __init__(self, jid, nick):
ChatTab.__init__(self)
self.own_nick = nick
@@ -445,6 +461,7 @@ class MucTab(ChatTab):
self.commands['clear'] = (self.command_clear,
_('Usage: /clear\nClear: Clear the current buffer.'), None)
self.resize()
+ self.update_commands()
def scroll_user_list_up(self):
self.user_win.scroll_up()
@@ -1185,6 +1202,7 @@ class PrivateTab(ChatTab):
The tab containg a private conversation (someone from a MUC)
"""
message_type = 'chat'
+ plugin_commands = {}
def __init__(self, name, nick):
ChatTab.__init__(self)
self.own_nick = nick
@@ -1203,6 +1221,7 @@ class PrivateTab(ChatTab):
self.resize()
self.parent_muc = self.core.get_tab_by_name(JID(name).bare, MucTab)
self.on = True
+ self.update_commands()
def completion(self):
self.complete_commands(self.input)
@@ -1380,6 +1399,7 @@ class RosterInfoTab(Tab):
"""
A tab, splitted in two, containing the roster and infos
"""
+ plugin_commands = {}
def __init__(self):
Tab.__init__(self)
self.name = "Roster"
@@ -1414,6 +1434,7 @@ class RosterInfoTab(Tab):
self.commands['import'] = (self.command_import, _("Usage: /import [/path/to/file]\nImport: Import your contacts from /path/to/file if specified, or $HOME/poezio_contacts if not."), None)
self.commands['clear_infos'] = (self.command_clear_infos, _("Usage: /clear_infos\nClear Infos: Use this command to clear the info buffer."), None)
self.resize()
+ self.update_commands()
def resize(self):
if not self.visible:
@@ -1863,6 +1884,7 @@ class ConversationTab(ChatTab):
"""
The tab containg a normal conversation (not from a MUC)
"""
+ plugin_commands = {}
message_type = 'chat'
def __init__(self, jid):
ChatTab.__init__(self)
@@ -1881,6 +1903,7 @@ class ConversationTab(ChatTab):
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.commands['info'] = (self.command_info, _('Usage: /info\nInfo: Get the status of the contact.'), None)
self.resize()
+ self.update_commands()
def completion(self):
self.complete_commands(self.input)
@@ -2029,6 +2052,7 @@ class MucListTab(Tab):
A tab listing rooms from a specific server, displaying various information,
scrollable, and letting the user join them, etc
"""
+ plugin_commands = {}
def __init__(self, server):
Tab.__init__(self)
self.state = 'normal'
@@ -2059,6 +2083,7 @@ class MucListTab(Tab):
self.listview.refresh()
self.tab_win.refresh()
self.input.refresh()
+ self.update_commands()
def resize(self):
if not self.visible: