Philipp Hörist pushed to branch master at gajim / gajim
Commits:
-
18ac2084
by lovetox at 2022-08-20T23:36:28+02:00
3 changed files:
Changes:
| ... | ... | @@ -52,12 +52,15 @@ def split_argument_string(string: str) -> list[str]: |
| 52 | 52 | return result
|
| 53 | 53 | |
| 54 | 54 | |
| 55 | -def get_usage_from_command(cmd: argparse.ArgumentParser) -> str:
|
|
| 55 | +def get_usage_from_command(cmd: argparse.ArgumentParser,
|
|
| 56 | + command_name: str
|
|
| 57 | + ) -> str:
|
|
| 58 | + |
|
| 56 | 59 | with io.StringIO() as output:
|
| 57 | 60 | cmd.print_usage(file=output)
|
| 58 | 61 | usage = output.getvalue()
|
| 59 | 62 | |
| 60 | - usage = usage.split('[-h] ')[1]
|
|
| 63 | + usage = usage.split(f'ChatCommands {command_name}')[1]
|
|
| 61 | 64 | return usage.strip()
|
| 62 | 65 | |
| 63 | 66 | |
| ... | ... | @@ -69,7 +72,7 @@ class CommandError(Exception): |
| 69 | 72 | pass
|
| 70 | 73 | |
| 71 | 74 | |
| 72 | -class CommandNotFoundError(Exception):
|
|
| 75 | +class CommandFailed(Exception):
|
|
| 73 | 76 | pass
|
| 74 | 77 | |
| 75 | 78 | |
| ... | ... | @@ -82,7 +85,7 @@ class ChatCommands(Observable): |
| 82 | 85 | def __init__(self) -> None:
|
| 83 | 86 | Observable.__init__(self)
|
| 84 | 87 | self._parser = ArgumentParser(prog='ChatCommands')
|
| 85 | - self._sub_parser = self._parser.add_subparsers()
|
|
| 88 | + self._sub_parser = self._parser.add_subparsers(title='Commands')
|
|
| 86 | 89 | self._commands: dict[str, tuple[list[str], str]] = {}
|
| 87 | 90 | |
| 88 | 91 | self._create_commands()
|
| ... | ... | @@ -95,6 +98,16 @@ def get_commands(self, used_in: str) -> list[tuple[str, str]]: |
| 95 | 98 | commands.sort(key=operator.itemgetter(0))
|
| 96 | 99 | return commands
|
| 97 | 100 | |
| 101 | + def _generate_help(self, used_in: str) -> str:
|
|
| 102 | + help_text = 'Commands:\n\n'
|
|
| 103 | + commands = self.get_commands(used_in)
|
|
| 104 | + for command in commands:
|
|
| 105 | + name, usage = command
|
|
| 106 | + if name == 'help':
|
|
| 107 | + continue
|
|
| 108 | + help_text += f' {name:<15} {usage}\n'
|
|
| 109 | + return help_text
|
|
| 110 | + |
|
| 98 | 111 | def make_parser(self,
|
| 99 | 112 | command_name: str,
|
| 100 | 113 | callback: Callable[..., Any],
|
| ... | ... | @@ -104,9 +117,11 @@ def make_parser(self, |
| 104 | 117 | it with the command name.
|
| 105 | 118 | '''
|
| 106 | 119 | |
| 107 | - parser = self._sub_parser.add_parser(command_name, **kwargs)
|
|
| 108 | - parser.set_defaults(command_name=command_name)
|
|
| 109 | - self.connect(command_name, callback)
|
|
| 120 | + parser = self._sub_parser.add_parser(command_name,
|
|
| 121 | + add_help=False,
|
|
| 122 | + **kwargs)
|
|
| 123 | + parser.set_defaults(command_name=command_name,
|
|
| 124 | + exec=callback)
|
|
| 110 | 125 | return parser
|
| 111 | 126 | |
| 112 | 127 | def add_command(self,
|
| ... | ... | @@ -115,7 +130,7 @@ def add_command(self, |
| 115 | 130 | cmd: argparse.ArgumentParser
|
| 116 | 131 | ) -> None:
|
| 117 | 132 | |
| 118 | - usage = get_usage_from_command(cmd)
|
|
| 133 | + usage = get_usage_from_command(cmd, command_name)
|
|
| 119 | 134 | self._commands[command_name] = (used_in, usage)
|
| 120 | 135 | |
| 121 | 136 | def parse(self, type_: str, arg_string: str) -> None:
|
| ... | ... | @@ -124,13 +139,33 @@ def parse(self, type_: str, arg_string: str) -> None: |
| 124 | 139 | command_name = arg_list[0]
|
| 125 | 140 | command = self._commands.get(command_name)
|
| 126 | 141 | if command is None or type_ not in command[0]:
|
| 127 | - raise CommandNotFoundError(_('Unknown command: %s' % command_name))
|
|
| 142 | + self.notify('command-not-found',
|
|
| 143 | + _('Unknown command: %s' % command_name))
|
|
| 144 | + raise CommandFailed
|
|
| 145 | + |
|
| 146 | + try:
|
|
| 147 | + args = self._parser.parse_args(arg_list)
|
|
| 148 | + except ArgumentParserError as error:
|
|
| 149 | + self.notify('command-error', str(error))
|
|
| 150 | + raise CommandFailed
|
|
| 151 | + |
|
| 152 | + args.used_in = type_
|
|
| 153 | + |
|
| 154 | + try:
|
|
| 155 | + result = args.exec(args)
|
|
| 156 | + except CommandError as error:
|
|
| 157 | + self.notify('command-error', str(error))
|
|
| 158 | + raise CommandFailed
|
|
| 128 | 159 | |
| 129 | - args = self._parser.parse_args(arg_list)
|
|
| 160 | + if result is None:
|
|
| 161 | + result = _('Command executed successfully')
|
|
| 130 | 162 | |
| 131 | - self.notify(args.command_name, args)
|
|
| 163 | + self.notify('command-result', result)
|
|
| 132 | 164 | |
| 133 | 165 | def _create_commands(self) -> None:
|
| 166 | + parser = self.make_parser('help', self._help_command)
|
|
| 167 | + self.add_command('help', ['chat', 'groupchat', 'pm'], parser)
|
|
| 168 | + |
|
| 134 | 169 | parser = self.make_parser('status', self._status_command)
|
| 135 | 170 | parser.add_argument('status',
|
| 136 | 171 | choices=['online', 'away', 'xa', 'dnd'])
|
| ... | ... | @@ -164,12 +199,10 @@ def _create_commands(self) -> None: |
| 164 | 199 | choices=['moderator', 'participant', 'visitor'])
|
| 165 | 200 | self.add_command('role', ['groupchat'], parser)
|
| 166 | 201 | |
| 167 | - def _status_command(self,
|
|
| 168 | - chat_commands: Any,
|
|
| 169 | - signal_name: str,
|
|
| 170 | - args: Any
|
|
| 171 | - ) -> None:
|
|
| 202 | + def _help_command(self, args: Any) -> str:
|
|
| 203 | + return self._generate_help(args.used_in)
|
|
| 172 | 204 | |
| 205 | + def _status_command(self, args: Any) -> None:
|
|
| 173 | 206 | for client in app.get_clients():
|
| 174 | 207 | if not app.settings.get_account_setting(client.account,
|
| 175 | 208 | 'sync_with_global_status'):
|
| ... | ... | @@ -189,12 +222,7 @@ def _check_if_joined(self) -> GroupchatContact: |
| 189 | 222 | 'joined this group chat'))
|
| 190 | 223 | return contact
|
| 191 | 224 | |
| 192 | - def _invite_command(self,
|
|
| 193 | - chat_commands: Any,
|
|
| 194 | - signal_name: str,
|
|
| 195 | - args: Any
|
|
| 196 | - ) -> None:
|
|
| 197 | - |
|
| 225 | + def _invite_command(self, args: Any) -> None:
|
|
| 198 | 226 | contact = self._check_if_joined()
|
| 199 | 227 | |
| 200 | 228 | try:
|
| ... | ... | @@ -242,20 +270,10 @@ def _change_affiliation(self, |
| 242 | 270 | {jid: {'affiliation': affiliation,
|
| 243 | 271 | 'reason': reason}})
|
| 244 | 272 | |
| 245 | - def _ban_command(self,
|
|
| 246 | - chat_commands: Any,
|
|
| 247 | - signal_name: str,
|
|
| 248 | - args: Any
|
|
| 249 | - ) -> None:
|
|
| 250 | - |
|
| 273 | + def _ban_command(self, args: Any) -> None:
|
|
| 251 | 274 | self._change_affiliation(args.who, 'outcast', args.reason)
|
| 252 | 275 | |
| 253 | - def _affiliate_command(self,
|
|
| 254 | - chat_commands: Any,
|
|
| 255 | - signal_name: str,
|
|
| 256 | - args: Any
|
|
| 257 | - ) -> None:
|
|
| 258 | - |
|
| 276 | + def _affiliate_command(self, args: Any) -> None:
|
|
| 259 | 277 | self._change_affiliation(args.who, args.affiliation, None)
|
| 260 | 278 | |
| 261 | 279 | def _change_role(self, nick: str, role: str, reason: Optional[str]) -> None:
|
| ... | ... | @@ -278,18 +296,8 @@ def _change_role(self, nick: str, role: str, reason: Optional[str]) -> None: |
| 278 | 296 | role,
|
| 279 | 297 | reason)
|
| 280 | 298 | |
| 281 | - def _kick_command(self,
|
|
| 282 | - chat_commands: Any,
|
|
| 283 | - signal_name: str,
|
|
| 284 | - args: Any
|
|
| 285 | - ) -> None:
|
|
| 286 | - |
|
| 299 | + def _kick_command(self, args: Any) -> None:
|
|
| 287 | 300 | self._change_role(args.who, 'none', args.reason)
|
| 288 | 301 | |
| 289 | - def _role_command(self,
|
|
| 290 | - chat_commands: Any,
|
|
| 291 | - signal_name: str,
|
|
| 292 | - args: Any
|
|
| 293 | - ) -> None:
|
|
| 294 | - |
|
| 302 | + def _role_command(self, args: Any) -> None:
|
|
| 295 | 303 | self._change_role(args.who, args.role, None) |
| ... | ... | @@ -34,6 +34,7 @@ |
| 34 | 34 | from gajim.common import events
|
| 35 | 35 | from gajim.common import helpers
|
| 36 | 36 | from gajim.common import preview_helpers
|
| 37 | +from gajim.common.commands import ChatCommands
|
|
| 37 | 38 | from gajim.common.i18n import _
|
| 38 | 39 | from gajim.common.const import CallType
|
| 39 | 40 | from gajim.common.modules.contacts import BareContact
|
| ... | ... | @@ -76,10 +77,10 @@ def __init__(self): |
| 76 | 77 | self._chat_banner = ChatBanner()
|
| 77 | 78 | self._chat_control = ChatControl()
|
| 78 | 79 | self._message_action_box = MessageActionsBox()
|
| 79 | - self._message_action_box.connect('command-error',
|
|
| 80 | - self._on_command_error)
|
|
| 81 | - self._message_action_box.connect('command-not-found',
|
|
| 82 | - self._on_command_not_found)
|
|
| 80 | + |
|
| 81 | + app.commands.connect('command-error', self._on_command_signal)
|
|
| 82 | + app.commands.connect('command-not-found', self._on_command_signal)
|
|
| 83 | + app.commands.connect('command-result', self._on_command_signal)
|
|
| 83 | 84 | |
| 84 | 85 | box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
|
| 85 | 86 | box.add(self._chat_banner)
|
| ... | ... | @@ -741,18 +742,14 @@ def clear(self) -> None: |
| 741 | 742 | self._message_action_box.clear()
|
| 742 | 743 | self._chat_control.clear()
|
| 743 | 744 | |
| 744 | - def _on_command_error(self,
|
|
| 745 | - message_actions_box: MessageActionsBox,
|
|
| 746 | - error: str) -> None:
|
|
| 747 | - |
|
| 748 | - self._chat_control.add_command_output(error, True)
|
|
| 749 | - |
|
| 750 | - def _on_command_not_found(self,
|
|
| 751 | - message_actions_box: MessageActionsBox,
|
|
| 752 | - error: str
|
|
| 753 | - ) -> None:
|
|
| 745 | + def _on_command_signal(self,
|
|
| 746 | + chat_commands: ChatCommands,
|
|
| 747 | + signal_name: str,
|
|
| 748 | + text: str
|
|
| 749 | + ) -> None:
|
|
| 754 | 750 | |
| 755 | - self._chat_control.add_command_output(error, True)
|
|
| 751 | + is_error = signal_name != 'command-result'
|
|
| 752 | + self._chat_control.add_command_output(text, is_error)
|
|
| 756 | 753 | |
| 757 | 754 | |
| 758 | 755 | class ChatPlaceholderBox(Gtk.Box):
|
| ... | ... | @@ -37,9 +37,7 @@ |
| 37 | 37 | from gajim.common import app
|
| 38 | 38 | from gajim.common import events
|
| 39 | 39 | from gajim.common import ged
|
| 40 | -from gajim.common.commands import ArgumentParserError
|
|
| 41 | -from gajim.common.commands import CommandError
|
|
| 42 | -from gajim.common.commands import CommandNotFoundError
|
|
| 40 | +from gajim.common.commands import CommandFailed
|
|
| 43 | 41 | from gajim.common.i18n import _
|
| 44 | 42 | from gajim.common.client import Client
|
| 45 | 43 | from gajim.common.const import SimpleClientState
|
| ... | ... | @@ -67,12 +65,6 @@ |
| 67 | 65 | |
| 68 | 66 | |
| 69 | 67 | class MessageActionsBox(Gtk.Grid, ged.EventHelper):
|
| 70 | - |
|
| 71 | - __gsignals__ = {
|
|
| 72 | - 'command-error': (GObject.SignalFlags.RUN_FIRST, None, (str,)),
|
|
| 73 | - 'command-not-found': (GObject.SignalFlags.RUN_FIRST, None, (str,))
|
|
| 74 | - }
|
|
| 75 | - |
|
| 76 | 68 | def __init__(self) -> None:
|
| 77 | 69 | Gtk.Grid.__init__(self)
|
| 78 | 70 | ged.EventHelper.__init__(self)
|
| ... | ... | @@ -544,10 +536,8 @@ def _on_msg_textview_key_press_event(self, |
| 544 | 536 | not message.startswith('/me ')):
|
| 545 | 537 | try:
|
| 546 | 538 | app.commands.parse(self._contact.type_string, message)
|
| 547 | - except (ArgumentParserError, CommandError) as error:
|
|
| 548 | - self.emit('command-error', error)
|
|
| 549 | - except CommandNotFoundError as error:
|
|
| 550 | - self.emit('command-not-found', error)
|
|
| 539 | + except CommandFailed:
|
|
| 540 | + pass
|
|
| 551 | 541 | else:
|
| 552 | 542 | self.msg_textview.clear()
|
| 553 | 543 | return True
|