Welcome to mirror list, hosted at ThFree Co, Russian Federation.

dev.gajim.org/gajim/gajim.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorlovetox <philipp@hoerist.com>2022-08-21 00:36:28 +0300
committerlovetox <philipp@hoerist.com>2022-08-21 00:36:28 +0300
commit18ac20841f531939e0ab8d1e25711be04a460dd6 (patch)
tree711234ab627f434ebc968a8546c83b83b9ef25df
parent51ab5fe8c8678a1e2c199f072ba7edfc67b3af52 (diff)
refactor: Commands: Raise singals instead of exceptions
- Raise signals instead of exceptions - ChatStack: Connect directly to command signals - Add /help command
-rw-r--r--gajim/common/commands.py100
-rw-r--r--gajim/gtk/chat_stack.py27
-rw-r--r--gajim/gtk/message_actions_box.py16
3 files changed, 69 insertions, 74 deletions
diff --git a/gajim/common/commands.py b/gajim/common/commands.py
index 15b335470..109d4d724 100644
--- a/gajim/common/commands.py
+++ b/gajim/common/commands.py
@@ -52,12 +52,15 @@ def split_argument_string(string: str) -> list[str]:
return result
-def get_usage_from_command(cmd: argparse.ArgumentParser) -> str:
+def get_usage_from_command(cmd: argparse.ArgumentParser,
+ command_name: str
+ ) -> str:
+
with io.StringIO() as output:
cmd.print_usage(file=output)
usage = output.getvalue()
- usage = usage.split('[-h] ')[1]
+ usage = usage.split(f'ChatCommands {command_name}')[1]
return usage.strip()
@@ -69,7 +72,7 @@ class CommandError(Exception):
pass
-class CommandNotFoundError(Exception):
+class CommandFailed(Exception):
pass
@@ -82,7 +85,7 @@ class ChatCommands(Observable):
def __init__(self) -> None:
Observable.__init__(self)
self._parser = ArgumentParser(prog='ChatCommands')
- self._sub_parser = self._parser.add_subparsers()
+ self._sub_parser = self._parser.add_subparsers(title='Commands')
self._commands: dict[str, tuple[list[str], str]] = {}
self._create_commands()
@@ -95,6 +98,16 @@ class ChatCommands(Observable):
commands.sort(key=operator.itemgetter(0))
return commands
+ def _generate_help(self, used_in: str) -> str:
+ help_text = 'Commands:\n\n'
+ commands = self.get_commands(used_in)
+ for command in commands:
+ name, usage = command
+ if name == 'help':
+ continue
+ help_text += f' {name:<15} {usage}\n'
+ return help_text
+
def make_parser(self,
command_name: str,
callback: Callable[..., Any],
@@ -104,9 +117,11 @@ class ChatCommands(Observable):
it with the command name.
'''
- parser = self._sub_parser.add_parser(command_name, **kwargs)
- parser.set_defaults(command_name=command_name)
- self.connect(command_name, callback)
+ parser = self._sub_parser.add_parser(command_name,
+ add_help=False,
+ **kwargs)
+ parser.set_defaults(command_name=command_name,
+ exec=callback)
return parser
def add_command(self,
@@ -115,7 +130,7 @@ class ChatCommands(Observable):
cmd: argparse.ArgumentParser
) -> None:
- usage = get_usage_from_command(cmd)
+ usage = get_usage_from_command(cmd, command_name)
self._commands[command_name] = (used_in, usage)
def parse(self, type_: str, arg_string: str) -> None:
@@ -124,13 +139,33 @@ class ChatCommands(Observable):
command_name = arg_list[0]
command = self._commands.get(command_name)
if command is None or type_ not in command[0]:
- raise CommandNotFoundError(_('Unknown command: %s' % command_name))
+ self.notify('command-not-found',
+ _('Unknown command: %s' % command_name))
+ raise CommandFailed
+
+ try:
+ args = self._parser.parse_args(arg_list)
+ except ArgumentParserError as error:
+ self.notify('command-error', str(error))
+ raise CommandFailed
+
+ args.used_in = type_
+
+ try:
+ result = args.exec(args)
+ except CommandError as error:
+ self.notify('command-error', str(error))
+ raise CommandFailed
- args = self._parser.parse_args(arg_list)
+ if result is None:
+ result = _('Command executed successfully')
- self.notify(args.command_name, args)
+ self.notify('command-result', result)
def _create_commands(self) -> None:
+ parser = self.make_parser('help', self._help_command)
+ self.add_command('help', ['chat', 'groupchat', 'pm'], parser)
+
parser = self.make_parser('status', self._status_command)
parser.add_argument('status',
choices=['online', 'away', 'xa', 'dnd'])
@@ -164,12 +199,10 @@ class ChatCommands(Observable):
choices=['moderator', 'participant', 'visitor'])
self.add_command('role', ['groupchat'], parser)
- def _status_command(self,
- chat_commands: Any,
- signal_name: str,
- args: Any
- ) -> None:
+ def _help_command(self, args: Any) -> str:
+ return self._generate_help(args.used_in)
+ def _status_command(self, args: Any) -> None:
for client in app.get_clients():
if not app.settings.get_account_setting(client.account,
'sync_with_global_status'):
@@ -189,12 +222,7 @@ class ChatCommands(Observable):
'joined this group chat'))
return contact
- def _invite_command(self,
- chat_commands: Any,
- signal_name: str,
- args: Any
- ) -> None:
-
+ def _invite_command(self, args: Any) -> None:
contact = self._check_if_joined()
try:
@@ -242,20 +270,10 @@ class ChatCommands(Observable):
{jid: {'affiliation': affiliation,
'reason': reason}})
- def _ban_command(self,
- chat_commands: Any,
- signal_name: str,
- args: Any
- ) -> None:
-
+ def _ban_command(self, args: Any) -> None:
self._change_affiliation(args.who, 'outcast', args.reason)
- def _affiliate_command(self,
- chat_commands: Any,
- signal_name: str,
- args: Any
- ) -> None:
-
+ def _affiliate_command(self, args: Any) -> None:
self._change_affiliation(args.who, args.affiliation, None)
def _change_role(self, nick: str, role: str, reason: Optional[str]) -> None:
@@ -278,18 +296,8 @@ class ChatCommands(Observable):
role,
reason)
- def _kick_command(self,
- chat_commands: Any,
- signal_name: str,
- args: Any
- ) -> None:
-
+ def _kick_command(self, args: Any) -> None:
self._change_role(args.who, 'none', args.reason)
- def _role_command(self,
- chat_commands: Any,
- signal_name: str,
- args: Any
- ) -> None:
-
+ def _role_command(self, args: Any) -> None:
self._change_role(args.who, args.role, None)
diff --git a/gajim/gtk/chat_stack.py b/gajim/gtk/chat_stack.py
index f33f8d6aa..21faf766e 100644
--- a/gajim/gtk/chat_stack.py
+++ b/gajim/gtk/chat_stack.py
@@ -34,6 +34,7 @@ from gajim.common import app
from gajim.common import events
from gajim.common import helpers
from gajim.common import preview_helpers
+from gajim.common.commands import ChatCommands
from gajim.common.i18n import _
from gajim.common.const import CallType
from gajim.common.modules.contacts import BareContact
@@ -76,10 +77,10 @@ class ChatStack(Gtk.Stack, EventHelper):
self._chat_banner = ChatBanner()
self._chat_control = ChatControl()
self._message_action_box = MessageActionsBox()
- self._message_action_box.connect('command-error',
- self._on_command_error)
- self._message_action_box.connect('command-not-found',
- self._on_command_not_found)
+
+ app.commands.connect('command-error', self._on_command_signal)
+ app.commands.connect('command-not-found', self._on_command_signal)
+ app.commands.connect('command-result', self._on_command_signal)
box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL)
box.add(self._chat_banner)
@@ -741,18 +742,14 @@ class ChatStack(Gtk.Stack, EventHelper):
self._message_action_box.clear()
self._chat_control.clear()
- def _on_command_error(self,
- message_actions_box: MessageActionsBox,
- error: str) -> None:
-
- self._chat_control.add_command_output(error, True)
-
- def _on_command_not_found(self,
- message_actions_box: MessageActionsBox,
- error: str
- ) -> None:
+ def _on_command_signal(self,
+ chat_commands: ChatCommands,
+ signal_name: str,
+ text: str
+ ) -> None:
- self._chat_control.add_command_output(error, True)
+ is_error = signal_name != 'command-result'
+ self._chat_control.add_command_output(text, is_error)
class ChatPlaceholderBox(Gtk.Box):
diff --git a/gajim/gtk/message_actions_box.py b/gajim/gtk/message_actions_box.py
index bdeb2510b..42a6be24b 100644
--- a/gajim/gtk/message_actions_box.py
+++ b/gajim/gtk/message_actions_box.py
@@ -37,9 +37,7 @@ from nbxmpp.protocol import JID
from gajim.common import app
from gajim.common import events
from gajim.common import ged
-from gajim.common.commands import ArgumentParserError
-from gajim.common.commands import CommandError
-from gajim.common.commands import CommandNotFoundError
+from gajim.common.commands import CommandFailed
from gajim.common.i18n import _
from gajim.common.client import Client
from gajim.common.const import SimpleClientState
@@ -67,12 +65,6 @@ log = logging.getLogger('gajim.gui.messageactionsbox')
class MessageActionsBox(Gtk.Grid, ged.EventHelper):
-
- __gsignals__ = {
- 'command-error': (GObject.SignalFlags.RUN_FIRST, None, (str,)),
- 'command-not-found': (GObject.SignalFlags.RUN_FIRST, None, (str,))
- }
-
def __init__(self) -> None:
Gtk.Grid.__init__(self)
ged.EventHelper.__init__(self)
@@ -544,10 +536,8 @@ class MessageActionsBox(Gtk.Grid, ged.EventHelper):
not message.startswith('/me ')):
try:
app.commands.parse(self._contact.type_string, message)
- except (ArgumentParserError, CommandError) as error:
- self.emit('command-error', error)
- except CommandNotFoundError as error:
- self.emit('command-not-found', error)
+ except CommandFailed:
+ pass
else:
self.msg_textview.clear()
return True