diff --git a/CHANGELOG.md b/CHANGELOG.md index f765f80f..df67ccae 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,15 @@ # 更新日志 +## 1.8.33 + +### 改进 + +- 若快捷指令的 key 以 `^` 为前缀,则其会被替换为命令前缀之一,并发出警告 + +### 修复 + +- 修复解析快捷命令时处理换行的行为与正常行为不一致的问题 + ## 1.8.32 ### 修复 diff --git a/src/arclet/alconna/__init__.py b/src/arclet/alconna/__init__.py index d8247b22..0a6210c0 100644 --- a/src/arclet/alconna/__init__.py +++ b/src/arclet/alconna/__init__.py @@ -53,7 +53,7 @@ from .typing import Up as Up from .typing import StrMulti as StrMulti -__version__ = "1.8.32" +__version__ = "1.8.33" # backward compatibility AnyOne = ANY diff --git a/src/arclet/alconna/_internal/_analyser.py b/src/arclet/alconna/_internal/_analyser.py index 32600ee1..0b5afec8 100644 --- a/src/arclet/alconna/_internal/_analyser.py +++ b/src/arclet/alconna/_internal/_analyser.py @@ -357,7 +357,7 @@ def process(self, argv: Argv[TDC]) -> Arparma[TDC]: return self.export(argv, True, e) argv.context[SHORTCUT_TRIGGER] = _next try: - rest, short, mat = command_manager.find_shortcut(self.command, [_next] + argv.release()) + rest, short, mat = command_manager.find_shortcut(self.command, [_next] + argv.release(no_split=True)) except ValueError as exc: if argv.fuzzy_match and (res := handle_head_fuzzy(self.command_header, _next, argv.fuzzy_threshold)): output_manager.send(self.command.name, lambda: res) diff --git a/src/arclet/alconna/_internal/_handlers.py b/src/arclet/alconna/_internal/_handlers.py index 96074b6a..f88d2082 100644 --- a/src/arclet/alconna/_internal/_handlers.py +++ b/src/arclet/alconna/_internal/_handlers.py @@ -725,12 +725,7 @@ def _handle_shortcut_data(argv: Argv, data: list): data.clear() break - def recover_quote(_unit): - if isinstance(_unit, str) and any(_unit.count(sep) for sep in argv.separators) and not (_unit[0] in ('"', "'") and _unit[0] == _unit[-1]): - return f'"{_unit}"' - return _unit - - return [recover_quote(unit) for i, unit in enumerate(data) if i not in record] + return [unit for i, unit in enumerate(data) if i not in record] INDEX_REG_SLOT = re.compile(r"\{(\d+)\}") diff --git a/src/arclet/alconna/manager.py b/src/arclet/alconna/manager.py index c6c3bba7..80f0db8b 100644 --- a/src/arclet/alconna/manager.py +++ b/src/arclet/alconna/manager.py @@ -5,6 +5,7 @@ import contextlib import re import shelve +import warnings import weakref from copy import copy from datetime import datetime @@ -257,6 +258,17 @@ def add_shortcut(self, target: Alconna, key: str | TPattern, source: Arparma | S _flags = key.flags if isinstance(source, dict): humanize = source.pop("humanized", None) + command = source.pop("command", str(target.command)) + if _key.startswith("^"): + warnings.warn( + "Shortcut Key should not start with '^', otherwise it will ignore the prefix automatically.", + UserWarning, + stacklevel=3 + ) + _key = _key[1:] + if target.prefixes and (_pf := next(filter(lambda x: isinstance(x, str), target.prefixes), None)): + command = f"{_pf}{command}" + source["prefix"] = False if source.get("prefix", False) and target.prefixes: prefixes = [] out = [] @@ -265,20 +277,20 @@ def add_shortcut(self, target: Alconna, key: str | TPattern, source: Arparma | S continue prefixes.append(prefix) _shortcut[1][f"{re.escape(prefix)}{_key}"] = InnerShortcutArgs( - **{**source, "command": argv.converter(prefix + source.get("command", str(target.command)))}, + **{**source, "command": argv.converter(prefix + command)}, flags=_flags, ) out.append( lang.require("shortcut", "add_success").format(shortcut=f"{prefix}{_key}", target=target.path) ) _shortcut[0][humanize or _key] = InnerShortcutArgs( - **{**source, "command": argv.converter(source.get("command", str(target.command))), "prefixes": prefixes}, + **{**source, "command": argv.converter(command), "prefixes": prefixes}, flags=_flags, ) target.formatter.update_shortcut(target) return "\n".join(out) _shortcut[0][humanize or _key] = _shortcut[1][_key] = InnerShortcutArgs( - **{**source, "command": argv.converter(source.get("command", str(target.command)))}, + **{**source, "command": argv.converter(command)}, flags=_flags, ) target.formatter.update_shortcut(target) diff --git a/tests/core_test.py b/tests/core_test.py index e8cf9ba1..afdeecdf 100644 --- a/tests/core_test.py +++ b/tests/core_test.py @@ -492,12 +492,12 @@ def test_shortcut(): assert res5.header_match.origin == "echo" assert res5.content == "print(123)" assert not alc16_1.parse("echo 123 456").matched - res6 = alc16_1.parse(["echo1", "123", "456 789"]) + res6 = alc16_1.parse(["echo1", "123 456 789"]) assert res6.header_match.origin == "echo1" - assert res6.content == "print('123\n456\n789')" + assert res6.content == "print('123 456 789')" res7 = alc16_1.parse([123]) assert not res7.matched - res8 = alc16_1.parse("echo \\'123\\'") + res8 = alc16_1.parse("echo '123'") assert res8.content == "print('123')" assert not alc16_1.parse("echo").matched assert alc16_1.parse("echo1").content == "print('')" @@ -609,6 +609,11 @@ def wrapper2(slot, content): assert alc16_13.parse("iorankx").rank == "x" assert alc16_13.parse("iorank").rank == "--all" + alc16_14 = Alconna(["/"], "core16_14", Args["bar", str]) + with pytest.warns(UserWarning): + alc16_14.shortcut("^test", {"args": ["abc"]}) + assert alc16_14.parse("test").bar == "abc" + def test_help(): from arclet.alconna import output_manager