Philipp Hörist pushed to branch master at gajim / gajim

Commits:

3 changed files:

Changes:

  • gajim/common/commands.py
    ... ... @@ -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)

  • gajim/gtk/chat_stack.py
    ... ... @@ -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):
    

  • gajim/gtk/message_actions_box.py
    ... ... @@ -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