From e1808a8455aadc9fac300c68e397b712a030ae29 Mon Sep 17 00:00:00 2001 From: Florent Le Coz Date: Tue, 25 Nov 2014 16:58:26 +0100 Subject: Parse command arguments using a decorator and make things more consistent Avoid surprises with some commands accepting quoted arguments and some other not. fix #2555 --- src/core/commands.py | 292 +++++++++++++++++++++++--------------------- src/daemon.py | 3 +- src/decorators.py | 92 ++++++++++++++ src/tabs/basetabs.py | 17 ++- src/tabs/conversationtab.py | 29 +++-- src/tabs/muctab.py | 208 ++++++++++++++++++------------- src/tabs/privatetab.py | 17 ++- src/tabs/rostertab.py | 100 ++++++++------- src/tabs/xmltab.py | 36 ++++-- 9 files changed, 488 insertions(+), 306 deletions(-) diff --git a/src/core/commands.py b/src/core/commands.py index 4a8f7f19..712840d2 100644 --- a/src/core/commands.py +++ b/src/core/commands.py @@ -28,15 +28,16 @@ import multiuserchat as muc from plugin import PluginConfig from roster import roster from theming import dump_tuple, get_theme +from decorators import command_args_parser from . structs import Command, possible_show -def command_help(self, arg): +@command_args_parser.quoted(0, 1) +def command_help(self, args): """ - /help + /help [command_name] """ - args = arg.split() if not args: color = dump_tuple(get_theme().COLOR_HELP_COMMANDS) acc = [] @@ -67,7 +68,7 @@ def command_help(self, arg): msg = '\n'.join(buff) msg += _("\nType /help to know what each command does") - if args: + else: command = args[0].lstrip('/').strip() if command in self.current_tab().commands: @@ -84,7 +85,8 @@ def command_help(self, arg): msg = tup[1] self.information(msg, 'Help') -def command_runkey(self, arg): +@command_args_parser.quoted(1) +def command_runkey(self, args): """ /runkey """ @@ -93,7 +95,9 @@ def command_runkey(self, arg): if key == '^J': return '\n' return key - char = arg.strip() + if args is None: + return self.command_help('runkey') + char = args[0] func = self.key_func.get(char, None) if func: func() @@ -102,21 +106,20 @@ def command_runkey(self, arg): if res: self.refresh_window() -def command_status(self, arg): +@command_args_parser.quoted(1, 1, [None]) +def command_status(self, args): """ /status [msg] """ - args = common.shell_split(arg) - if len(args) < 1: - return + if args is None: + return self.command_help('status') + if not args[0] in possible_show.keys(): - self.command_help('status') - return + return self.command_help('status') + show = possible_show[args[0]] - if len(args) == 2: - msg = args[1] - else: - msg = None + msg = args[1] + pres = self.xmpp.make_presence() if msg: pres['status'] = msg @@ -136,19 +139,15 @@ def command_status(self, arg): if is_muctab and current.joined and show not in ('away', 'xa'): current.send_chat_state('active') -def command_presence(self, arg): +@command_args_parser.quoted(1, 2, [None, None]) +def command_presence(self, args): """ /presence [type] [status] """ - args = common.shell_split(arg) - if len(args) == 1: - jid, type, status = args[0], None, None - elif len(args) == 2: - jid, type, status = args[0], args[1], None - elif len(args) == 3: - jid, type, status = args[0], args[1], args[2] - else: - return + if args is None: + return self.command_help('presence') + + jid, type, status = args[0], args[1], args[2] if jid == '.' and isinstance(self.current_tab(), tabs.ChatTab): jid = self.current_tab().name if type == 'available': @@ -177,24 +176,26 @@ def command_presence(self, arg): if self.current_tab() in tab.privates: self.current_tab().send_chat_state(chatstate, True) -def command_theme(self, arg=''): +@command_args_parser.quoted(1) +def command_theme(self, args=None): """/theme """ - args = arg.split() - if args: - self.command_set('theme %s' % (args[0],)) + if args is None: + return self.command_help('theme') + self.command_set('theme %s' % (args[0],)) -def command_win(self, arg): +@command_args_parser.quoted(1) +def command_win(self, args): """ /win """ - arg = arg.strip() - if not arg: - self.command_help('win') - return + if args is None: + return self.command_help('win') + + nb = args[0] try: - nb = int(arg.split()[0]) + nb = int(nb) except ValueError: - nb = arg + pass if self.current_tab_nb == nb: return self.previous_tab_nb = self.current_tab_nb @@ -219,15 +220,15 @@ def command_win(self, arg): self.current_tab().on_gain_focus() self.refresh_window() -def command_move_tab(self, arg): +@command_args_parser.quoted(2) +def command_move_tab(self, args): """ /move_tab old_pos new_pos """ - args = common.shell_split(arg) - current_tab = self.current_tab() - if len(args) != 2: + if args is None: return self.command_help('move_tab') + current_tab = self.current_tab() if args[0] == '.': args[0] = current_tab.nb if args[1] == '.': @@ -259,16 +260,16 @@ def command_move_tab(self, arg): self.current_tab_nb = self.tabs.index(current_tab) self.refresh_window() -def command_list(self, arg): +@command_args_parser.quoted(0, 1) +def command_list(self, args): """ - /list + /list [server] Opens a MucListTab containing the list of the room in the specified server """ - arg = arg.split() - if len(arg) > 1: + if args is None: return self.command_help('list') - elif arg: - server = safeJID(arg[0]).server + elif args: + server = safeJID(args[0]).server else: if not isinstance(self.current_tab(), tabs.MucTab): return self.information('Please provide a server', 'Error') @@ -279,7 +280,8 @@ def command_list(self, arg): self.xmpp.plugin['xep_0030'].get_items(jid=server, callback=cb) -def command_version(self, arg): +@command_args_parser.quoted(1) +def command_version(self, args): """ /version """ @@ -296,9 +298,9 @@ def command_version(self, arg): res.get('os') or _('an unknown platform')) self.information(version, 'Info') - args = common.shell_split(arg) - if len(args) < 1: + if args is None: return self.command_help('version') + jid = safeJID(args[0]) if jid.resource or jid not in roster: fixes.get_version(self.xmpp, jid, callback=callback) @@ -308,11 +310,11 @@ def command_version(self, arg): else: fixes.get_version(self.xmpp, jid, callback=callback) -def command_join(self, arg, histo_length=None): +@command_args_parser.quoted(0, 2) +def command_join(self, args, histo_length=None): """ /join [room][/nick] [password] """ - args = common.shell_split(arg) password = None if len(args) == 0: tab = self.current_tab() @@ -409,11 +411,11 @@ def command_join(self, arg, histo_length=None): tab.refresh() self.doupdate() -def command_bookmark_local(self, arg=''): +@command_args_parser.quoted(0, 2) +def command_bookmark_local(self, args): """ /bookmark_local [room][/nick] [password] """ - args = common.shell_split(arg) nick = None password = None if not args and not isinstance(self.current_tab(), tabs.MucTab): @@ -470,15 +472,14 @@ def command_bookmark_local(self, arg=''): self.information(_('Your local bookmarks are now: %s') % [b for b in bookmark.bookmarks if b.method == 'local'], 'Info') -def command_bookmark(self, arg=''): +@command_args_parser.quoted(0, 3) +def command_bookmark(self, args): """ /bookmark [room][/nick] [autojoin] [password] """ - if not config.get('use_remote_bookmarks'): - self.command_bookmark_local(arg) - return - args = common.shell_split(arg) + return self.command_bookmark_local(" ".join(args)) + nick = None if not args and not isinstance(self.current_tab(), tabs.MucTab): return @@ -553,7 +554,8 @@ def command_bookmark(self, arg=''): if each.method in ('pep', 'privatexml'): remote.append(each) -def command_bookmarks(self, arg=''): +@command_args_parser.ignored +def command_bookmarks(self): """/bookmarks""" local = [] remote = [] @@ -568,9 +570,10 @@ def command_bookmarks(self, arg=''): self.information(_('Your local bookmarks are: %s') % local, _('Info')) -def command_remove_bookmark(self, arg=''): +@command_args_parser.quoted(0, 1) +def command_remove_bookmark(self, args): """/remove_bookmark [jid]""" - args = common.shell_split(arg) + if not args: tab = self.current_tab() if isinstance(tab, tabs.MucTab) and bookmark.get_by_jid(tab.name): @@ -589,11 +592,11 @@ def command_remove_bookmark(self, arg=''): else: self.information('No bookmark to remove', 'Info') -def command_set(self, arg): +@command_args_parser.quoted(1, 2) +def command_set(self, args): """ /set [module|][section]