From 3f9d543a0c4d9173ab8e3266d766c5c5472d8120 Mon Sep 17 00:00:00 2001 From: piratf Date: Sat, 31 Jan 2026 14:25:39 +0800 Subject: [PATCH 1/6] =?UTF-8?q?feat(interactive):=20=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E4=BA=A4=E4=BA=92=E6=A8=A1=E5=BC=8F=20#=20=E5=91=BD=E4=BB=A4?= =?UTF-8?q?=E5=92=8C=20tab=20=E8=A1=A5=E5=85=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 主要变更: - 在交互模式中支持 #help, #install, #uninstall, #update 命令 - 添加 readline tab 补全支持(优雅降级) - 输入单独的 # 显示可用命令列表 - 更新 help 和交互模式提示信息 技术实现: - 使用条件导入 readline(Windows 可选 pyreadline3) - 在 CLI.__init__ 中初始化命令列表 - 添加 _command_completer 方法处理补全逻辑 - 添加 _show_command_list 方法显示命令列表 - 添加 _interactive_help 方法显示交互命令帮助 测试覆盖: - 命令列表初始化测试 - 命令补全函数测试 - 显示命令列表测试 - 交互命令帮助测试 - 单独 # 输入处理测试 - readline 导入降级测试 --- remark/cli/commands.py | 91 +++++++++++++++++++-- tests/unit/test_cli_commands.py | 137 ++++++++++++++++++++++++++++++++ 2 files changed, 220 insertions(+), 8 deletions(-) diff --git a/remark/cli/commands.py b/remark/cli/commands.py index 759c6fb..9ca072e 100644 --- a/remark/cli/commands.py +++ b/remark/cli/commands.py @@ -9,6 +9,16 @@ import threading import urllib.error +# 尝试导入 readline 用于 tab 补全 +# Unix/Linux 系统通常有内置 readline +# Windows 用户可以安装 pyreadline3 获得相同功能 +try: + import readline +except ImportError: + # Windows 系统如果没有安装 pyreadline3,readline 不可用 + # 这不会影响基本功能,只是没有 tab 补全 + readline = None + from remark.core.folder_handler import FolderCommentHandler from remark.gui import remark_dialog from remark.i18n import _ as _, set_language @@ -43,6 +53,14 @@ def __init__(self): self.handler = FolderCommentHandler() self.pending_update = None self._update_check_done = threading.Event() + # 初始化交互模式命令列表 + self._interactive_commands_list = ["#help", "#install", "#uninstall", "#update"] + self._interactive_commands = { + "#help": self._interactive_help, + "#install": self.install_menu, + "#uninstall": self.uninstall_menu, + "#update": self.check_update_now, + } # 先检查缓存,只有在需要检查时才启动后台线程 if should_check_update(): self._start_update_checker() @@ -246,20 +264,39 @@ def interactive_mode(self) -> None: """交互模式""" version = get_version() print(_("Windows Folder Remark Tool v{version}").format(version=version)) - print(_("Tip: Press Ctrl + C to exit") + os.linesep) + print(_("Tip: Press Ctrl + C to exit")) + print(_("Tip: Use #help to see available commands")) + + # 设置 readline 补全(如果可用) + if readline: + readline.set_completer(self._command_completer) + readline.parse_and_bind("tab: complete") + readline.set_completer_delims("") # 允许补全包含 # 的命令 - input_path_msg = _("Enter folder path (or drag here): ") + input_path_msg = "\n" + _("Enter folder path (or drag here): ") input_comment_msg = _("Enter remark:") while True: try: - path = input(input_path_msg).replace('"', "").strip() + user_input = input(input_path_msg).replace('"', "").strip() + + # 处理交互命令 + if user_input in self._interactive_commands: + self._interactive_commands[user_input]() + print() + continue + + # 用户输入单独的 #,显示可用命令列表 + if user_input == "#": + self._show_command_list() + print() + continue - if not os.path.exists(path): + if not os.path.exists(user_input): print(_("Path does not exist, please re-enter")) continue - if not os.path.isdir(path): + if not os.path.isdir(user_input): print(_("This is a 'file', currently only supports adding remarks to 'folders'")) continue @@ -268,13 +305,46 @@ def interactive_mode(self) -> None: print(_("Remark cannot be empty")) comment = input(input_comment_msg) - self.add_comment(path, comment) + self.add_comment(user_input, comment) except KeyboardInterrupt: - print(_(" ❤ Thank you for using")) + print("\n" + _(" ❤ Thank you for using")) break print(os.linesep + _("Continue processing or press Ctrl + C to exit") + os.linesep) + def _command_completer(self, text: str, state: int) -> str | None: + """readline tab 补全函数""" + # 获取当前输入的行 + try: + import readline + line = readline.get_line_buffer() + except Exception: + line = text + + # 如果输入以 # 开头,补全命令 + if line.startswith("#") or text.startswith("#"): + options = [cmd for cmd in self._interactive_commands_list if cmd.startswith(text)] + if state < len(options): + return options[state] + return None + + def _show_command_list(self) -> None: + """显示可用命令列表""" + print(_("Available commands:")) + for cmd in self._interactive_commands_list: + print(f" {cmd}") + print(_("Tip: Press Tab to complete commands (if readline is available)")) + + def _interactive_help(self) -> None: + """显示交互模式帮助信息""" + print(_("Interactive Commands:")) + print(_(" #help Show this help message")) + print(_(" #install Install right-click menu")) + print(_(" #uninstall Uninstall right-click menu")) + print(_(" #update Check for updates")) + print(os.linesep) + print(_("Or simply enter a folder path to add remarks")) + def show_help(self) -> None: """显示帮助信息""" print(_("Windows Folder Remark Tool")) @@ -287,8 +357,13 @@ def show_help(self) -> None: print(_(" --update Check for updates")) print(_(" --gui GUI mode (called from right-click menu)")) print(_(" --delete Delete remark")) - print(_(" --view View remark")) + print(_(" --view View remark")) print(_(" --help, -h Show help information")) + print(_("Interactive Commands (available in interactive mode):")) + print(_(" #help Show interactive help")) + print(_(" #install Install right-click menu")) + print(_(" #uninstall Uninstall right-click menu")) + print(_(" #update Check for updates")) print(_("Examples:")) print(_(' [Add remark] python remark.py "C:\\\\MyFolder" "My Folder"')) print(_(' [Delete remark] python remark.py --delete "C:\\\\MyFolder"')) diff --git a/tests/unit/test_cli_commands.py b/tests/unit/test_cli_commands.py index 3707583..acc8b9d 100644 --- a/tests/unit/test_cli_commands.py +++ b/tests/unit/test_cli_commands.py @@ -425,3 +425,140 @@ def test_get_version_fallback(self): ) version = get_version() assert version == "unknown" + + +@pytest.mark.unit +class TestInteractiveCommands: + """交互模式命令测试""" + + @pytest.fixture(autouse=True) + def disable_background_update_check(self, monkeypatch): + """禁用后台更新检查""" + monkeypatch.setattr( + "remark.cli.commands.CLI._start_update_checker", + lambda self: None, + ) + + def test_interactive_commands_list_initialized(self): + """测试交互命令列表正确初始化""" + cli = CLI() + # 进入交互模式会初始化命令列表 + assert hasattr(cli, "_interactive_commands_list") + assert hasattr(cli, "_interactive_commands") + expected_commands = ["#help", "#install", "#uninstall", "#update"] + assert cli._interactive_commands_list == expected_commands + + def test_command_completer_with_hash_prefix(self): + """测试命令补全函数处理 # 开头的输入""" + cli = CLI() + + # 测试补全 #h 开头 + result = cli._command_completer("#h", 0) + assert result == "#help" + + # 测试补全 #i 开头 + result = cli._command_completer("#i", 0) + assert result == "#install" + + # 测试补全 #u 开头(有多个选项) + result = cli._command_completer("#u", 0) + assert result in ["#uninstall", "#update"] + + # 测试补全不存在的命令 + result = cli._command_completer("#x", 0) + assert result is None + + def test_command_completer_returns_multiple_options(self): + """测试命令补全返回多个选项""" + cli = CLI() + + # 测试 #u 开头有多个选项 + result = cli._command_completer("#u", 0) + assert result in ["#uninstall", "#update"] + + # 继续获取下一个选项 + result = cli._command_completer("#u", 1) + assert result in ["#uninstall", "#update"] + + # 超出选项数量返回 None + result = cli._command_completer("#u", 2) + assert result is None + + # #install 是唯一的 #i 开头命令 + result = cli._command_completer("#i", 0) + assert result == "#install" + + # #help 是唯一的 #h 开头命令 + result = cli._command_completer("#h", 0) + assert result == "#help" + + def test_show_command_list(self, capsys): + """测试显示命令列表""" + cli = CLI() + cli._show_command_list() + captured = capsys.readouterr() + assert "Available commands" in captured.out + assert "#help" in captured.out + assert "#install" in captured.out + assert "#uninstall" in captured.out + assert "#update" in captured.out + + def test_interactive_help_shows_commands(self, capsys): + """测试 #help 命令显示所有可用命令""" + cli = CLI() + cli._interactive_help() + captured = capsys.readouterr() + assert "Interactive Commands" in captured.out + assert "#help" in captured.out + assert "#install" in captured.out + assert "#uninstall" in captured.out + assert "#update" in captured.out + + @pytest.mark.skipif(os.name != "nt", reason="Windows only") + def test_interactive_mode_handles_hash_only(self, fs, monkeypatch, capsys): + """测试交互模式处理单独的 # 输入""" + fs.create_dir("/test/folder") + cli = CLI() + + # Mock input: 先输入 # 然后输入 Ctrl+C 退出 + input_count = [0] + + def mock_input(prompt): + input_count[0] += 1 + if input_count[0] == 1: + return "#" + else: + raise KeyboardInterrupt() + + monkeypatch.setattr("builtins.input", mock_input) + + cli.interactive_mode() + + captured = capsys.readouterr() + # 应该显示可用命令列表 + assert "Available commands" in captured.out + + def test_readline_import_graceful_fallback(self, monkeypatch): + """测试 readline 导入失败时优雅降级""" + # 模拟 readline 不可用 + import builtins + original_import = builtins.__import__ + + def mock_import(name, *args, **kwargs): + if name == "readline": + raise ImportError("readline not available") + return original_import(name, *args, **kwargs) + + with monkeypatch.context() as m: + m.setattr("builtins.__import__", mock_import) + # 重新导入模块 + import importlib + import sys + if "remark.cli.commands" in sys.modules: + del sys.modules["remark.cli.commands"] + if "remark.cli" in sys.modules: + del sys.modules["remark.cli"] + + # 重新导入,应该不会因为 readline 不可用而失败 + import remark.cli.commands as commands_module + assert commands_module.readline is None From 8bebcdde63f6364bfb0f90093013d235d18da225 Mon Sep 17 00:00:00 2001 From: piratf Date: Sat, 31 Jan 2026 14:44:39 +0800 Subject: [PATCH 2/6] =?UTF-8?q?fix(i18n):=20=E8=A1=A5=E5=85=A8=E4=BA=A4?= =?UTF-8?q?=E4=BA=92=E5=91=BD=E4=BB=A4=E7=9A=84=E4=B8=AD=E6=96=87=E7=BF=BB?= =?UTF-8?q?=E8=AF=91=E5=B9=B6=E6=94=B9=E8=BF=9B=20i18n=20=E6=A3=80?= =?UTF-8?q?=E6=9F=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修复问题: - 补全所有交互命令相关字符串的中文翻译 - 改进 pre-commit hook 以正确检测空翻译 - 添加 scripts/check_i18n.py 脚本验证翻译完整性 - 更新测试以支持中英文输出 主要变更: - locale/zh/LC_MESSAGES/messages.po: 添加缺失的中文翻译 - scripts/check_i18n.py: 新增翻译完整性检查脚本 - .pre-commit-config.yaml: 使用新脚本检查翻译 - tests/unit/test_cli_commands.py: 测试支持双语输出 --- .pre-commit-config.yaml | 2 +- locale/zh/LC_MESSAGES/messages.mo | Bin 10087 -> 10638 bytes locale/zh/LC_MESSAGES/messages.po | 321 +++++++++++++++++------------- messages.pot | 266 +++++++++++++------------ remark/cli/commands.py | 27 +-- scripts/check_i18n.py | 43 ++++ tests/unit/test_cli_commands.py | 10 +- 7 files changed, 389 insertions(+), 280 deletions(-) create mode 100644 scripts/check_i18n.py diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f9a0f42..d280611 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -77,7 +77,7 @@ repos: - id: check-i18n-completeness name: Check i18n completeness - entry: bash -c 'pybabel update -i messages.pot -d locale --check' + entry: bash -c 'pybabel update -i messages.pot -d locale && python scripts/check_i18n.py locale/*/LC_MESSAGES/messages.po' language: system types: [python] stages: [pre-commit] diff --git a/locale/zh/LC_MESSAGES/messages.mo b/locale/zh/LC_MESSAGES/messages.mo index 95fb5d694ce8628b16c996fbc1906096f571c38d..2765e0f9f6b8bd58da71574322bf480803fb70d1 100644 GIT binary patch delta 3009 zcmZ|Pd2AGA7{KALl+ae7T4=!*3S+@qO3Mwxa+OQu5;>X%2;$NXcEfge?Jkf?U@;M) zTvdm|NTF2PSfU(Z4aF8H7)%T?#6&Rx(Mae{7XuPCD1YGbdv^x9h-^}x?>^r58`@sl zu^{+kw~o6Mzt{Qe&0k%-)Y^Y}2}%v6nvXqj8BWC2*auHwDqgbv8FQ)sgISoH$XuL* z{c$Z0#sm1AQbF}Kg=`w`VkY)YQmP-0$MNVyS+E9Wp$jMr+(ns}^Mq1kaW2XRTkZNW zTuA+u10&cS;P29E}ClG45+wCE_Qk}ftQ6*;9DE`MpP^7hK~7qMGH{PwZ$yc}CA-42jPeNAV-fB}3H9$d z0~4rB#(5~Y+==7xBFcuH*-Z|Zg|hBgl<`F<8-9R1I@N*_@wQarFB>Lv9S)@i;v5{0 z({U@N<2N`BZ{bWF&Tdj)kFwEult=p$N-8=MUy3RpnWCm5XH<)EGL3TWJ#^I>zhz+T!)hCuk89S zD4%bz2gjEIBT;g{6lLH#WG_{Nalfi1$h zDC-a|AphV^ql*iYEvd=}7gIvR)g!%>r4yQ8sMkEsBP(GK1{39W&KuN_OlvI3+^5{&= z$4p+T181Q`>}{0PoJ9%scPJa*!tp4lm&i@XCjU|>vKxFT6Dv_B)Sw*jIF7{YDC5(~ z$BQ@&hvQnDjYm-~au0cTst*r=q8f{`Zn13zN@S~YMq4-dm<9>eW!pBC@B9u*1PVwf zMfD1H!c7B=E1l*TZzKeQg}xGJK-WCpH50WZiw1j^Iy9we{YrJWPkZRMpwzoYb9n-K zxwAOnTCHm`3+ZSHC=|dJpO>w?T%S*hTUR3pVU3^e!r2Ql-Z-- zD$jq17kXUAkfe;{m@d0%a=%s9`D2!zQmPlP)K+-QHLK4rCwMUIk>1d@#I(53`J`zb zjFc{A-6ySfy4=p?Ze1((mX$d@C4Psou1h4eyQ?>TM*HQb*qvIA^T7m{=b`wNc}w&G z4mBetWcOz|jO>(Ad2`D(zpKpWuF!NDqd7UWyM%(z87S2PUd>rjqLu4q&hnLhV?#=6 z$eU8svEY8>d==%ov&8N4=) zyIqxSg5S$ia29g zdM{&2`b?uVyLaLLz9#eiGi`NEtxa{UP49(I9tm$bBw2d!>a1?_aGllH+EQ!2c~nN+ zzmd_D(Kq;@riG7GMhox`}5c{%i3pIPx^ z?2AX6Z=c#6u5Pee%!b{y3Um^EaGxp{YF!^So?-%%eqV}v)> zo4Yr)HlGOBeHLjv8b0%uxv$=AYz}WZ5U$%~h8jX|W$lljYQ;#4c?()=bA9XS77iGF z1(DkN@Wuv?^O&c@X^iyj{!^;nA$1PT+*TPg&AOs8?M{1HE2CyjeOvX`*ieMVX6MEI E3sO*+wg3PC delta 2407 zcmZ|Pe@xV69KiACfC*kAKT`QEUqn5Ah@LAb34ai?)Ft@?H9E;o_==~;!MGD)gl9zq z2I|^ZX_2Ozx}vS9&S9=7WYr(8xz<{;8TJnx*jD7`YUNhFKX>2A{^)jhujl#P^YimO z-#fm2vfO_wG3u1!<>r&l=Y>eA{rmcUmQpLJj^P4~i&knIF2%Ljf(!8q&cjhm#h=W2 zOpH?j#{L`#w zTa~Jyz6a&^OSlSu!R468YNTF?Ma-`Z3NrCEWYH>Sj#9}Ok7<~T8Mq#0XVsX5M^F~n ziwXF-`TKV$?eCzB6Bipc2c>^0+Hp6|XMS~zg6!-(N=mO`K3eC7QlyG-8TDN#1GHl( z14vUff;sp#uEXEafyHr3krdU7lJavXM>veKfg9-0qA*QCR-6zYZny%a{xnJk>dbf- z%8vSRK8|1>j-ni4Bx#TdY$$hO4RVTVJIWF5Mj7u#l=f#5$iG~=s|0r8EqoA*5|!GB zoA7ZwiE?H)umlrmBomdREJ#Ng_y|h-K9mW^(1sDLMlzg-GT&BYD&?6+{x?%NO5jPn zjw!f+?X5>UZo(#%39h0{Jchj0UA~w@SqVOh3sLI3kOxK`#3!&3<>;>968skBuKnSs z&}m_X9LP!n-E4<7s3EMtZ?Fh$tV&k?9FlF-igZ;yX8b&If7LL`&c8xg@Ey}wW|x%b z;ws#Xk{N%8Sr{25ag+hqusVr1V=fM(WaLM*V>TD6 z1S?Q3<*UdM_|+Q}ilKPNVeu z4SDocJZY2-WuV0ErW;Y_+bjAh9HEeceJHo|5|Vv&(~SR$^8Cm1(91xpQ7+j|lnD-? zET9c(s$N0Kz*{JH;WLy>jiVev1m`NZe=Yjua&4thfSp*3gD5GwgOc)mMv)YkqD=S< zuEv8X3+gu=F};b>?=DJvD_36bKn50KIZD6wC8}0!pm2u3Ll{KaK`LpG0ZL4_p`>g- z%0k;w{`o#M9Y%RfucPcV#TLFZkKioo&)bZ==*@;RZe7AMt--B3y}H(@dv&*7?K2KV zH|^aLj)fzd!(Px@=WK4PD%O;BM?;O%r)!@2!)rB17uqxuXDOQE>A5hke|KuFiUNLlG*bu zT0udROFyiY$T(|4efZibp>VrExphOtEXO{VTdy)s&Z#$&Vkd2Nhul6FThkiqyUR_1GT zYx!E4=BwBAW|uFpEUC+4j3q}~9u5p8@3R;^S*3~7pY%)(T)y3LEZF=0?W0}6?tUXH zwKhp&q1u1*YMjVPFSJS`CryTcs<1L@@vF^*tw$N0yCRmQ!A6-HI&=%R@Wed8a! zGjU>I>gA!yzV>i;b7!Gl6bJIP9g)ew*Ukk`b%r-Kv+=2cQ^u8Sdmwf3nMfllCoNEu HlV|xGg{P}o diff --git a/locale/zh/LC_MESSAGES/messages.po b/locale/zh/LC_MESSAGES/messages.po index b67eeb1..a959acb 100644 --- a/locale/zh/LC_MESSAGES/messages.po +++ b/locale/zh/LC_MESSAGES/messages.po @@ -7,7 +7,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2026-01-29 22:34+0800\n" +"POT-Creation-Date: 2026-01-31 14:42+0800\n" "PO-Revision-Date: 2026-01-29 22:35+0800\n" "Last-Translator: FULL NAME \n" "Language: zh\n" @@ -18,26 +18,26 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.17.0\n" -#: remark/cli/commands.py:55 +#: remark/cli/commands.py:73 #, python-brace-format msgid "Path does not exist: {path}" msgstr "路径不存在: {path}" -#: remark/cli/commands.py:58 +#: remark/cli/commands.py:76 #, python-brace-format msgid "Path is not a folder: {path}" msgstr "路径不是文件夹: {path}" -#: remark/cli/commands.py:80 +#: remark/cli/commands.py:98 #, python-brace-format msgid "Current version: {version}" msgstr "当前版本: {version}" -#: remark/cli/commands.py:81 +#: remark/cli/commands.py:99 msgid "Checking for updates..." msgstr "正在检查更新..." -#: remark/cli/commands.py:86 +#: remark/cli/commands.py:104 #, python-brace-format msgid "" "\n" @@ -46,17 +46,17 @@ msgstr "" "\n" "发现新版本: {tag_name}" -#: remark/cli/commands.py:87 remark/cli/commands.py:115 +#: remark/cli/commands.py:105 remark/cli/commands.py:133 #, python-brace-format msgid "Update notes: {notes}" msgstr "更新说明: {notes}" -#: remark/cli/commands.py:88 remark/cli/commands.py:116 +#: remark/cli/commands.py:106 remark/cli/commands.py:134 #, python-brace-format msgid "Full changelog: {url}" msgstr "完整更新日志: {url}" -#: remark/cli/commands.py:89 +#: remark/cli/commands.py:107 msgid "" "\n" "Update now? [Y/n]: " @@ -64,11 +64,11 @@ msgstr "" "\n" "是否立即更新? [Y/n]: " -#: remark/cli/commands.py:94 +#: remark/cli/commands.py:112 msgid "Already at the latest version" msgstr "已是最新版本" -#: remark/cli/commands.py:111 +#: remark/cli/commands.py:129 #, python-brace-format msgid "" "\n" @@ -77,334 +77,339 @@ msgstr "" "\n" "发现新版本: {tag_name} (当前版本: {version})" -#: remark/cli/commands.py:117 +#: remark/cli/commands.py:135 msgid "Update now? [Y/n]: " msgstr "是否立即更新? [Y/n]: " -#: remark/cli/commands.py:124 +#: remark/cli/commands.py:142 msgid "Downloading new version..." msgstr "正在下载新版本..." -#: remark/cli/commands.py:131 +#: remark/cli/commands.py:149 msgid "Download complete, preparing update..." msgstr "下载完成,准备更新..." -#: remark/cli/commands.py:135 +#: remark/cli/commands.py:153 msgid "Update program has started, the application will exit..." msgstr "更新程序已启动,程序即将退出..." -#: remark/cli/commands.py:136 +#: remark/cli/commands.py:154 msgid "Please wait a few moments, the update will complete automatically." msgstr "请等待几秒钟,更新将自动完成。" -#: remark/cli/commands.py:142 +#: remark/cli/commands.py:160 msgid "Download failed: Connection reset by server" msgstr "下载失败:连接被服务器断开" -#: remark/cli/commands.py:143 +#: remark/cli/commands.py:161 msgid "Please try again later, or visit the following link to download manually:" msgstr "请稍后重试,或访问以下链接手动下载:" -#: remark/cli/commands.py:146 +#: remark/cli/commands.py:164 msgid "Download failed: Request timeout" msgstr "下载失败:请求超时" -#: remark/cli/commands.py:147 remark/cli/commands.py:151 +#: remark/cli/commands.py:165 remark/cli/commands.py:169 msgid "" "Please check your network connection, or visit the following link to " "download manually:" msgstr "请检查网络连接,或访问以下链接手动下载:" -#: remark/cli/commands.py:150 +#: remark/cli/commands.py:168 msgid "Download failed: Unable to connect to server" msgstr "下载失败:无法连接到服务器" -#: remark/cli/commands.py:154 +#: remark/cli/commands.py:172 msgid "Download failed, please check your network or download manually" msgstr "下载失败,请检查网络连接或手动下载更新" -#: remark/cli/commands.py:157 +#: remark/cli/commands.py:175 #, python-brace-format msgid "Update failed: {error}" msgstr "更新失败: {error}" -#: remark/cli/commands.py:158 +#: remark/cli/commands.py:176 #, python-brace-format msgid "Manual download: {url}" msgstr "手动下载: {url}" -#: remark/cli/commands.py:175 +#: remark/cli/commands.py:193 msgid "Right-click menu installed successfully" msgstr "右键菜单安装成功" -#: remark/cli/commands.py:177 +#: remark/cli/commands.py:195 msgid "Usage Instructions:" msgstr "使用说明:" -#: remark/cli/commands.py:178 +#: remark/cli/commands.py:196 msgid " Windows 10: Right-click folder to see 'Add Folder Remark'" msgstr " Windows 10: 右键文件夹可直接看到「添加文件夹备注」" -#: remark/cli/commands.py:179 +#: remark/cli/commands.py:197 msgid "" " Windows 11: Right-click folder → Click 'Show more options' → Add Folder" " Remark" msgstr " Windows 11: 右键文件夹 → 点击「显示更多选项」→ 添加文件夹备注" -#: remark/cli/commands.py:182 +#: remark/cli/commands.py:200 msgid "Right-click menu installation failed" msgstr "右键菜单安装失败" -#: remark/cli/commands.py:188 +#: remark/cli/commands.py:206 msgid "Right-click menu uninstalled" msgstr "右键菜单已卸载" -#: remark/cli/commands.py:191 +#: remark/cli/commands.py:209 msgid "Right-click menu uninstallation failed" msgstr "右键菜单卸载失败" -#: remark/cli/commands.py:218 remark/storage/desktop_ini.py:309 +#: remark/cli/commands.py:236 remark/storage/desktop_ini.py:309 #, python-brace-format msgid "Warning: desktop.ini file encoding is {encoding}, not standard UTF-16." msgstr "警告: desktop.ini 文件编码为 {encoding},不是标准的 UTF-16。" -#: remark/cli/commands.py:219 remark/storage/desktop_ini.py:310 +#: remark/cli/commands.py:237 remark/storage/desktop_ini.py:310 msgid "unknown" msgstr "未知" -#: remark/cli/commands.py:221 +#: remark/cli/commands.py:239 msgid "This may cause Chinese and other special characters to display abnormally." msgstr "这可能导致中文等特殊字符显示异常。" -#: remark/cli/commands.py:225 +#: remark/cli/commands.py:243 msgid "Fix encoding to UTF-16? [Y/n]: " msgstr "是否修复编码为 UTF-16?[Y/n]: " -#: remark/cli/commands.py:228 +#: remark/cli/commands.py:246 msgid "Fixed to UTF-16 encoding" msgstr "已修复为 UTF-16 编码" -#: remark/cli/commands.py:230 +#: remark/cli/commands.py:248 msgid "Failed to fix encoding" msgstr "修复失败" -#: remark/cli/commands.py:233 +#: remark/cli/commands.py:251 msgid "Skip encoding fix" msgstr "跳过编码修复" -#: remark/cli/commands.py:236 remark/storage/desktop_ini.py:335 +#: remark/cli/commands.py:254 remark/storage/desktop_ini.py:335 msgid "Please enter Y or n" msgstr "请输入 Y 或 n" -#: remark/cli/commands.py:241 +#: remark/cli/commands.py:259 #, python-brace-format msgid "Current remark: {remark}" msgstr "当前备注: {remark}" -#: remark/cli/commands.py:243 remark/core/folder_handler.py:85 +#: remark/cli/commands.py:261 remark/core/folder_handler.py:85 msgid "This folder has no remark" msgstr "该文件夹没有备注" -#: remark/cli/commands.py:248 +#: remark/cli/commands.py:266 #, python-brace-format msgid "Windows Folder Remark Tool v{version}" msgstr "Windows 文件夹备注工具 v{version}" -#: remark/cli/commands.py:249 +#: remark/cli/commands.py:267 msgid "Tip: Press Ctrl + C to exit" msgstr "提示: 按 Ctrl + C 退出程序" -#: remark/cli/commands.py:251 +#: remark/cli/commands.py:268 +msgid "Tip: Use #help to see available commands" +msgstr "提示: 使用 #help 查看可用命令" + +#: remark/cli/commands.py:276 msgid "Enter folder path (or drag here): " msgstr "请输入文件夹路径(或拖动到这里): " -#: remark/cli/commands.py:252 +#: remark/cli/commands.py:277 msgid "Enter remark:" msgstr "请输入备注:" -#: remark/cli/commands.py:259 +#: remark/cli/commands.py:296 msgid "Path does not exist, please re-enter" msgstr "路径不存在,请重新输入" -#: remark/cli/commands.py:263 +#: remark/cli/commands.py:300 msgid "This is a 'file', currently only supports adding remarks to 'folders'" msgstr "这是一个「文件」,当前仅支持为「文件夹」添加备注" -#: remark/cli/commands.py:268 +#: remark/cli/commands.py:305 msgid "Remark cannot be empty" msgstr "备注不要为空哦" -#: remark/cli/commands.py:274 +#: remark/cli/commands.py:311 msgid " ❤ Thank you for using" msgstr " ❤ 感谢使用" -#: remark/cli/commands.py:276 +#: remark/cli/commands.py:313 msgid "Continue processing or press Ctrl + C to exit" msgstr "继续处理或按 Ctrl + C 退出程序" -#: remark/cli/commands.py:280 +#: remark/cli/commands.py:327 +msgid "Available commands:" +msgstr "可用命令:" + +#: remark/cli/commands.py:331 remark/cli/commands.py:345 +msgid "Tip: Press Tab to complete commands" +msgstr "提示: 按 Tab 补全命令" + +#: remark/cli/commands.py:333 remark/cli/commands.py:347 +msgid "Tip: Install pyreadline3 for Tab completion (pip install pyreadline3)" +msgstr "提示: 安装 pyreadline3 以使用 Tab 补全(pip install pyreadline3)" + +#: remark/cli/commands.py:337 +msgid "Interactive Commands:" +msgstr "交互命令:" + +#: remark/cli/commands.py:338 +msgid " #help Show this help message" +msgstr " #help 显示此帮助信息" + +#: remark/cli/commands.py:339 +msgid " #install Install right-click menu" +msgstr " #install 安装右键菜单" + +#: remark/cli/commands.py:340 +msgid " #uninstall Uninstall right-click menu" +msgstr " #uninstall 卸载右键菜单" + +#: remark/cli/commands.py:341 +msgid " #update Check for updates" +msgstr " #update 检查更新" + +#: remark/cli/commands.py:343 +msgid "Or simply enter a folder path to add remarks" +msgstr "或者直接输入文件夹路径来添加备注" + +#: remark/cli/commands.py:351 msgid "Windows Folder Remark Tool" msgstr "Windows 文件夹备注工具" -#: remark/cli/commands.py:281 +#: remark/cli/commands.py:352 msgid "Usage:" msgstr "使用方法:" -#: remark/cli/commands.py:282 +#: remark/cli/commands.py:353 msgid " Interactive mode: python remark.py" msgstr " 交互模式: python remark.py" -#: remark/cli/commands.py:283 +#: remark/cli/commands.py:354 msgid " Command line mode: python remark.py [options] [arguments]" msgstr " 命令行模式: python remark.py [选项] [参数]" -#: remark/cli/commands.py:284 +#: remark/cli/commands.py:355 msgid "Options:" msgstr "选项:" -#: remark/cli/commands.py:285 +#: remark/cli/commands.py:356 msgid " --install Install right-click menu" msgstr " --install 安装右键菜单" -#: remark/cli/commands.py:286 +#: remark/cli/commands.py:357 msgid " --uninstall Uninstall right-click menu" msgstr " --uninstall 卸载右键菜单" -#: remark/cli/commands.py:287 +#: remark/cli/commands.py:358 msgid " --update Check for updates" msgstr " --update 检查更新" -#: remark/cli/commands.py:288 +#: remark/cli/commands.py:359 msgid " --gui GUI mode (called from right-click menu)" msgstr " --gui <路径> GUI 模式(右键菜单调用)" -#: remark/cli/commands.py:289 +#: remark/cli/commands.py:360 msgid " --delete Delete remark" msgstr " --delete <路径> 删除备注" -#: remark/cli/commands.py:290 -msgid " --view View remark" +#: remark/cli/commands.py:361 +#, fuzzy +msgid " --view View remark" msgstr " --view <路径> 查看备注" -#: remark/cli/commands.py:291 +#: remark/cli/commands.py:362 msgid " --help, -h Show help information" msgstr " --help, -h 显示帮助信息" -#: remark/cli/commands.py:292 +#: remark/cli/commands.py:363 +msgid "Interactive Commands (available in interactive mode):" +msgstr "交互命令(在交互模式中可用):" + +#: remark/cli/commands.py:364 +msgid " #help Show interactive help" +msgstr " #help 显示交互帮助" + +#: remark/cli/commands.py:365 +msgid " #install Install right-click menu" +msgstr " #install 安装右键菜单" + +#: remark/cli/commands.py:366 +msgid " #uninstall Uninstall right-click menu" +msgstr " #uninstall 卸载右键菜单" + +#: remark/cli/commands.py:367 +msgid " #update Check for updates" +msgstr " #update 检查更新" + +#: remark/cli/commands.py:368 msgid "Examples:" msgstr "示例:" -#: remark/cli/commands.py:293 +#: remark/cli/commands.py:369 msgid " [Add remark] python remark.py \"C:\\\\MyFolder\" \"My Folder\"" msgstr " [添加备注] python remark.py \"C:\\\\MyFolder\" \"这是我的文件夹\"" -#: remark/cli/commands.py:294 +#: remark/cli/commands.py:370 msgid " [Delete remark] python remark.py --delete \"C:\\\\MyFolder\"" msgstr " [删除备注] python remark.py --delete \"C:\\\\MyFolder\"" -#: remark/cli/commands.py:295 +#: remark/cli/commands.py:371 msgid " [View current remark] python remark.py --view \"C:\\\\MyFolder\"" msgstr " [查看当前备注] python remark.py --view \"C:\\\\MyFolder\"" -#: remark/cli/commands.py:296 +#: remark/cli/commands.py:372 msgid " [Install right-click menu] python remark.py --install" msgstr " [安装右键菜单] python remark.py --install" -#: remark/cli/commands.py:297 +#: remark/cli/commands.py:373 msgid " [Check for updates] python remark.py --update" msgstr " [检查更新] python remark.py --update" -#: remark/cli/commands.py:313 +#: remark/cli/commands.py:430 msgid "Error: Path does not exist or not quoted" msgstr "错误: 路径不存在或未使用引号" -#: remark/cli/commands.py:314 +#: remark/cli/commands.py:431 msgid "Hint: Use quotes when path contains spaces" msgstr "提示: 路径包含空格时请使用引号" -#: remark/cli/commands.py:315 +#: remark/cli/commands.py:432 msgid " windows-folder-remark \"C:\\\\My Documents\" \"Remark content\"" msgstr " windows-folder-remark \"C:\\\\My Documents\" \"备注内容\"" -#: remark/cli/commands.py:320 +#: remark/cli/commands.py:437 #, python-brace-format msgid "Detected path: {path}" msgstr "检测到路径: {path}" -#: remark/cli/commands.py:323 +#: remark/cli/commands.py:440 remark/cli/commands.py:482 msgid "Error: This is a file, the tool can only set remarks for folders" msgstr "错误: 这是一个文件,工具只能为文件夹设置备注" -#: remark/cli/commands.py:328 +#: remark/cli/commands.py:445 #, python-brace-format msgid "Remark content: {remark}" msgstr "备注内容: {remark}" -#: remark/cli/commands.py:330 +#: remark/cli/commands.py:447 msgid "(Will view existing remark)" msgstr "(将查看现有备注)" -#: remark/cli/commands.py:332 +#: remark/cli/commands.py:449 msgid "Continue? [Y/n]: " msgstr "是否继续? [Y/n]: " -#: remark/cli/commands.py:338 -msgid "Detected multiple possible paths, please select:" -msgstr "检测到多个可能的路径,请选择:" - -#: remark/cli/commands.py:340 -msgid " [file]" -msgstr " [文件]" - -#: remark/cli/commands.py:341 -#, python-brace-format -msgid "" -"\n" -"[{index}] Path: {path}{type_mark}" -msgstr "" -"\n" -"[{index}] 路径: {path}{type_mark}" - -#: remark/cli/commands.py:343 -#, python-brace-format -msgid " Remaining remarks: {remarks}" -msgstr " 剩余备注: {remarks}" - -#: remark/cli/commands.py:345 -msgid " (Will view existing remark)" -msgstr " (将查看现有备注)" - -#: remark/cli/commands.py:346 -msgid "" -"\n" -"[0] Cancel" -msgstr "" -"\n" -"[0] 取消" - -#: remark/cli/commands.py:349 -#, python-brace-format -msgid "" -"\n" -"Please select [0-{max}]: " -msgstr "" -"\n" -"请选择 [0-{max}]: " - -#: remark/cli/commands.py:355 -msgid "" -"\n" -"Error: This is a file, the tool can only set remarks for folders, please " -"reselect" -msgstr "" -"\n" -"错误: 这是一个文件,工具只能为文件夹设置备注,请重新选择" - -#: remark/cli/commands.py:358 -msgid "Invalid selection, please try again" -msgstr "无效选择,请重试" - -#: remark/cli/commands.py:419 +#: remark/cli/commands.py:568 msgid "" "\n" "Operation cancelled" @@ -412,7 +417,7 @@ msgstr "" "\n" "操作已取消" -#: remark/cli/commands.py:422 +#: remark/cli/commands.py:571 #, python-brace-format msgid "An error occurred: {error}" msgstr "发生错误: {error}" @@ -518,3 +523,49 @@ msgstr "错误: 此工具为 Windows 系统中的文件/文件夹添加备注, #, python-brace-format msgid "Current system: {system}" msgstr "当前系统: {system}" + +#~ msgid "Detected multiple possible paths, please select:" +#~ msgstr "检测到多个可能的路径,请选择:" + +#~ msgid " [file]" +#~ msgstr " [文件]" + +#~ msgid "" +#~ "\n" +#~ "[{index}] Path: {path}{type_mark}" +#~ msgstr "" +#~ "\n" +#~ "[{index}] 路径: {path}{type_mark}" + +#~ msgid " Remaining remarks: {remarks}" +#~ msgstr " 剩余备注: {remarks}" + +#~ msgid " (Will view existing remark)" +#~ msgstr " (将查看现有备注)" + +#~ msgid "" +#~ "\n" +#~ "[0] Cancel" +#~ msgstr "" +#~ "\n" +#~ "[0] 取消" + +#~ msgid "" +#~ "\n" +#~ "Please select [0-{max}]: " +#~ msgstr "" +#~ "\n" +#~ "请选择 [0-{max}]: " + +#~ msgid "" +#~ "\n" +#~ "Error: This is a file, the tool" +#~ " can only set remarks for folders," +#~ " please reselect" +#~ msgstr "" +#~ "\n" +#~ "错误: 这是一个文件,工具只能为文件夹设置备注,请重新选择" + +#~ msgid "Invalid selection, please try again" +#~ msgstr "无效选择,请重试" + diff --git a/messages.pot b/messages.pot index a572213..600e4cb 100644 --- a/messages.pot +++ b/messages.pot @@ -8,7 +8,7 @@ msgid "" msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" -"POT-Creation-Date: 2026-01-29 22:53+0800\n" +"POT-Creation-Date: 2026-01-31 14:42+0800\n" "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" "Last-Translator: FULL NAME \n" "Language-Team: LANGUAGE \n" @@ -17,385 +17,397 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Generated-By: Babel 2.17.0\n" -#: remark/cli/commands.py:55 +#: remark/cli/commands.py:73 #, python-brace-format msgid "Path does not exist: {path}" msgstr "" -#: remark/cli/commands.py:58 +#: remark/cli/commands.py:76 #, python-brace-format msgid "Path is not a folder: {path}" msgstr "" -#: remark/cli/commands.py:80 +#: remark/cli/commands.py:98 #, python-brace-format msgid "Current version: {version}" msgstr "" -#: remark/cli/commands.py:81 +#: remark/cli/commands.py:99 msgid "Checking for updates..." msgstr "" -#: remark/cli/commands.py:86 +#: remark/cli/commands.py:104 #, python-brace-format msgid "" "\n" "New version found: {tag_name}" msgstr "" -#: remark/cli/commands.py:87 remark/cli/commands.py:115 +#: remark/cli/commands.py:105 remark/cli/commands.py:133 #, python-brace-format msgid "Update notes: {notes}" msgstr "" -#: remark/cli/commands.py:88 remark/cli/commands.py:116 +#: remark/cli/commands.py:106 remark/cli/commands.py:134 #, python-brace-format msgid "Full changelog: {url}" msgstr "" -#: remark/cli/commands.py:89 +#: remark/cli/commands.py:107 msgid "" "\n" "Update now? [Y/n]: " msgstr "" -#: remark/cli/commands.py:94 +#: remark/cli/commands.py:112 msgid "Already at the latest version" msgstr "" -#: remark/cli/commands.py:111 +#: remark/cli/commands.py:129 #, python-brace-format msgid "" "\n" "New version available: {tag_name} (Current version: {version})" msgstr "" -#: remark/cli/commands.py:117 +#: remark/cli/commands.py:135 msgid "Update now? [Y/n]: " msgstr "" -#: remark/cli/commands.py:124 +#: remark/cli/commands.py:142 msgid "Downloading new version..." msgstr "" -#: remark/cli/commands.py:131 +#: remark/cli/commands.py:149 msgid "Download complete, preparing update..." msgstr "" -#: remark/cli/commands.py:135 +#: remark/cli/commands.py:153 msgid "Update program has started, the application will exit..." msgstr "" -#: remark/cli/commands.py:136 +#: remark/cli/commands.py:154 msgid "Please wait a few moments, the update will complete automatically." msgstr "" -#: remark/cli/commands.py:142 +#: remark/cli/commands.py:160 msgid "Download failed: Connection reset by server" msgstr "" -#: remark/cli/commands.py:143 +#: remark/cli/commands.py:161 msgid "Please try again later, or visit the following link to download manually:" msgstr "" -#: remark/cli/commands.py:146 +#: remark/cli/commands.py:164 msgid "Download failed: Request timeout" msgstr "" -#: remark/cli/commands.py:147 remark/cli/commands.py:151 +#: remark/cli/commands.py:165 remark/cli/commands.py:169 msgid "" "Please check your network connection, or visit the following link to " "download manually:" msgstr "" -#: remark/cli/commands.py:150 +#: remark/cli/commands.py:168 msgid "Download failed: Unable to connect to server" msgstr "" -#: remark/cli/commands.py:154 +#: remark/cli/commands.py:172 msgid "Download failed, please check your network or download manually" msgstr "" -#: remark/cli/commands.py:157 +#: remark/cli/commands.py:175 #, python-brace-format msgid "Update failed: {error}" msgstr "" -#: remark/cli/commands.py:158 +#: remark/cli/commands.py:176 #, python-brace-format msgid "Manual download: {url}" msgstr "" -#: remark/cli/commands.py:175 +#: remark/cli/commands.py:193 msgid "Right-click menu installed successfully" msgstr "" -#: remark/cli/commands.py:177 +#: remark/cli/commands.py:195 msgid "Usage Instructions:" msgstr "" -#: remark/cli/commands.py:178 +#: remark/cli/commands.py:196 msgid " Windows 10: Right-click folder to see 'Add Folder Remark'" msgstr "" -#: remark/cli/commands.py:179 +#: remark/cli/commands.py:197 msgid "" " Windows 11: Right-click folder → Click 'Show more options' → Add Folder" " Remark" msgstr "" -#: remark/cli/commands.py:182 +#: remark/cli/commands.py:200 msgid "Right-click menu installation failed" msgstr "" -#: remark/cli/commands.py:188 +#: remark/cli/commands.py:206 msgid "Right-click menu uninstalled" msgstr "" -#: remark/cli/commands.py:191 +#: remark/cli/commands.py:209 msgid "Right-click menu uninstallation failed" msgstr "" -#: remark/cli/commands.py:218 remark/storage/desktop_ini.py:309 +#: remark/cli/commands.py:236 remark/storage/desktop_ini.py:309 #, python-brace-format msgid "Warning: desktop.ini file encoding is {encoding}, not standard UTF-16." msgstr "" -#: remark/cli/commands.py:219 remark/storage/desktop_ini.py:310 +#: remark/cli/commands.py:237 remark/storage/desktop_ini.py:310 msgid "unknown" msgstr "" -#: remark/cli/commands.py:221 +#: remark/cli/commands.py:239 msgid "This may cause Chinese and other special characters to display abnormally." msgstr "" -#: remark/cli/commands.py:225 +#: remark/cli/commands.py:243 msgid "Fix encoding to UTF-16? [Y/n]: " msgstr "" -#: remark/cli/commands.py:228 +#: remark/cli/commands.py:246 msgid "Fixed to UTF-16 encoding" msgstr "" -#: remark/cli/commands.py:230 +#: remark/cli/commands.py:248 msgid "Failed to fix encoding" msgstr "" -#: remark/cli/commands.py:233 +#: remark/cli/commands.py:251 msgid "Skip encoding fix" msgstr "" -#: remark/cli/commands.py:236 remark/storage/desktop_ini.py:335 +#: remark/cli/commands.py:254 remark/storage/desktop_ini.py:335 msgid "Please enter Y or n" msgstr "" -#: remark/cli/commands.py:241 +#: remark/cli/commands.py:259 #, python-brace-format msgid "Current remark: {remark}" msgstr "" -#: remark/cli/commands.py:243 remark/core/folder_handler.py:85 +#: remark/cli/commands.py:261 remark/core/folder_handler.py:85 msgid "This folder has no remark" msgstr "" -#: remark/cli/commands.py:248 +#: remark/cli/commands.py:266 #, python-brace-format msgid "Windows Folder Remark Tool v{version}" msgstr "" -#: remark/cli/commands.py:249 +#: remark/cli/commands.py:267 msgid "Tip: Press Ctrl + C to exit" msgstr "" -#: remark/cli/commands.py:251 +#: remark/cli/commands.py:268 +msgid "Tip: Use #help to see available commands" +msgstr "" + +#: remark/cli/commands.py:276 msgid "Enter folder path (or drag here): " msgstr "" -#: remark/cli/commands.py:252 +#: remark/cli/commands.py:277 msgid "Enter remark:" msgstr "" -#: remark/cli/commands.py:259 +#: remark/cli/commands.py:296 msgid "Path does not exist, please re-enter" msgstr "" -#: remark/cli/commands.py:263 +#: remark/cli/commands.py:300 msgid "This is a 'file', currently only supports adding remarks to 'folders'" msgstr "" -#: remark/cli/commands.py:268 +#: remark/cli/commands.py:305 msgid "Remark cannot be empty" msgstr "" -#: remark/cli/commands.py:274 +#: remark/cli/commands.py:311 msgid " ❤ Thank you for using" msgstr "" -#: remark/cli/commands.py:276 +#: remark/cli/commands.py:313 msgid "Continue processing or press Ctrl + C to exit" msgstr "" -#: remark/cli/commands.py:280 +#: remark/cli/commands.py:327 +msgid "Available commands:" +msgstr "" + +#: remark/cli/commands.py:331 remark/cli/commands.py:345 +msgid "Tip: Press Tab to complete commands" +msgstr "" + +#: remark/cli/commands.py:333 remark/cli/commands.py:347 +msgid "Tip: Install pyreadline3 for Tab completion (pip install pyreadline3)" +msgstr "" + +#: remark/cli/commands.py:337 +msgid "Interactive Commands:" +msgstr "" + +#: remark/cli/commands.py:338 +msgid " #help Show this help message" +msgstr "" + +#: remark/cli/commands.py:339 +msgid " #install Install right-click menu" +msgstr "" + +#: remark/cli/commands.py:340 +msgid " #uninstall Uninstall right-click menu" +msgstr "" + +#: remark/cli/commands.py:341 +msgid " #update Check for updates" +msgstr "" + +#: remark/cli/commands.py:343 +msgid "Or simply enter a folder path to add remarks" +msgstr "" + +#: remark/cli/commands.py:351 msgid "Windows Folder Remark Tool" msgstr "" -#: remark/cli/commands.py:281 +#: remark/cli/commands.py:352 msgid "Usage:" msgstr "" -#: remark/cli/commands.py:282 +#: remark/cli/commands.py:353 msgid " Interactive mode: python remark.py" msgstr "" -#: remark/cli/commands.py:283 +#: remark/cli/commands.py:354 msgid " Command line mode: python remark.py [options] [arguments]" msgstr "" -#: remark/cli/commands.py:284 +#: remark/cli/commands.py:355 msgid "Options:" msgstr "" -#: remark/cli/commands.py:285 +#: remark/cli/commands.py:356 msgid " --install Install right-click menu" msgstr "" -#: remark/cli/commands.py:286 +#: remark/cli/commands.py:357 msgid " --uninstall Uninstall right-click menu" msgstr "" -#: remark/cli/commands.py:287 +#: remark/cli/commands.py:358 msgid " --update Check for updates" msgstr "" -#: remark/cli/commands.py:288 +#: remark/cli/commands.py:359 msgid " --gui GUI mode (called from right-click menu)" msgstr "" -#: remark/cli/commands.py:289 +#: remark/cli/commands.py:360 msgid " --delete Delete remark" msgstr "" -#: remark/cli/commands.py:290 -msgid " --view View remark" +#: remark/cli/commands.py:361 +msgid " --view View remark" msgstr "" -#: remark/cli/commands.py:291 +#: remark/cli/commands.py:362 msgid " --help, -h Show help information" msgstr "" -#: remark/cli/commands.py:292 +#: remark/cli/commands.py:363 +msgid "Interactive Commands (available in interactive mode):" +msgstr "" + +#: remark/cli/commands.py:364 +msgid " #help Show interactive help" +msgstr "" + +#: remark/cli/commands.py:365 +msgid " #install Install right-click menu" +msgstr "" + +#: remark/cli/commands.py:366 +msgid " #uninstall Uninstall right-click menu" +msgstr "" + +#: remark/cli/commands.py:367 +msgid " #update Check for updates" +msgstr "" + +#: remark/cli/commands.py:368 msgid "Examples:" msgstr "" -#: remark/cli/commands.py:293 +#: remark/cli/commands.py:369 msgid " [Add remark] python remark.py \"C:\\\\MyFolder\" \"My Folder\"" msgstr "" -#: remark/cli/commands.py:294 +#: remark/cli/commands.py:370 msgid " [Delete remark] python remark.py --delete \"C:\\\\MyFolder\"" msgstr "" -#: remark/cli/commands.py:295 +#: remark/cli/commands.py:371 msgid " [View current remark] python remark.py --view \"C:\\\\MyFolder\"" msgstr "" -#: remark/cli/commands.py:296 +#: remark/cli/commands.py:372 msgid " [Install right-click menu] python remark.py --install" msgstr "" -#: remark/cli/commands.py:297 +#: remark/cli/commands.py:373 msgid " [Check for updates] python remark.py --update" msgstr "" -#: remark/cli/commands.py:313 +#: remark/cli/commands.py:430 msgid "Error: Path does not exist or not quoted" msgstr "" -#: remark/cli/commands.py:314 +#: remark/cli/commands.py:431 msgid "Hint: Use quotes when path contains spaces" msgstr "" -#: remark/cli/commands.py:315 +#: remark/cli/commands.py:432 msgid " windows-folder-remark \"C:\\\\My Documents\" \"Remark content\"" msgstr "" -#: remark/cli/commands.py:320 +#: remark/cli/commands.py:437 #, python-brace-format msgid "Detected path: {path}" msgstr "" -#: remark/cli/commands.py:323 +#: remark/cli/commands.py:440 remark/cli/commands.py:482 msgid "Error: This is a file, the tool can only set remarks for folders" msgstr "" -#: remark/cli/commands.py:328 +#: remark/cli/commands.py:445 #, python-brace-format msgid "Remark content: {remark}" msgstr "" -#: remark/cli/commands.py:330 +#: remark/cli/commands.py:447 msgid "(Will view existing remark)" msgstr "" -#: remark/cli/commands.py:332 +#: remark/cli/commands.py:449 msgid "Continue? [Y/n]: " msgstr "" -#: remark/cli/commands.py:338 -msgid "Detected multiple possible paths, please select:" -msgstr "" - -#: remark/cli/commands.py:340 -msgid " [file]" -msgstr "" - -#: remark/cli/commands.py:341 -#, python-brace-format -msgid "" -"\n" -"[{index}] Path: {path}{type_mark}" -msgstr "" - -#: remark/cli/commands.py:343 -#, python-brace-format -msgid " Remaining remarks: {remarks}" -msgstr "" - -#: remark/cli/commands.py:345 -msgid " (Will view existing remark)" -msgstr "" - -#: remark/cli/commands.py:346 -msgid "" -"\n" -"[0] Cancel" -msgstr "" - -#: remark/cli/commands.py:349 -#, python-brace-format -msgid "" -"\n" -"Please select [0-{max}]: " -msgstr "" - -#: remark/cli/commands.py:355 -msgid "" -"\n" -"Error: This is a file, the tool can only set remarks for folders, please " -"reselect" -msgstr "" - -#: remark/cli/commands.py:358 -msgid "Invalid selection, please try again" -msgstr "" - -#: remark/cli/commands.py:419 +#: remark/cli/commands.py:568 msgid "" "\n" "Operation cancelled" msgstr "" -#: remark/cli/commands.py:422 +#: remark/cli/commands.py:571 #, python-brace-format msgid "An error occurred: {error}" msgstr "" diff --git a/remark/cli/commands.py b/remark/cli/commands.py index 9ca072e..71450cc 100644 --- a/remark/cli/commands.py +++ b/remark/cli/commands.py @@ -314,18 +314,12 @@ def interactive_mode(self) -> None: def _command_completer(self, text: str, state: int) -> str | None: """readline tab 补全函数""" - # 获取当前输入的行 - try: - import readline - line = readline.get_line_buffer() - except Exception: - line = text - - # 如果输入以 # 开头,补全命令 - if line.startswith("#") or text.startswith("#"): - options = [cmd for cmd in self._interactive_commands_list if cmd.startswith(text)] - if state < len(options): - return options[state] + # 获取匹配的命令选项 + options = [cmd for cmd in self._interactive_commands_list if cmd.startswith(text)] + + # state 用于循环返回多个匹配项 + if state < len(options): + return options[state] return None def _show_command_list(self) -> None: @@ -333,7 +327,10 @@ def _show_command_list(self) -> None: print(_("Available commands:")) for cmd in self._interactive_commands_list: print(f" {cmd}") - print(_("Tip: Press Tab to complete commands (if readline is available)")) + if readline: + print(_("Tip: Press Tab to complete commands")) + else: + print(_("Tip: Install pyreadline3 for Tab completion (pip install pyreadline3)")) def _interactive_help(self) -> None: """显示交互模式帮助信息""" @@ -344,6 +341,10 @@ def _interactive_help(self) -> None: print(_(" #update Check for updates")) print(os.linesep) print(_("Or simply enter a folder path to add remarks")) + if readline: + print(_("Tip: Press Tab to complete commands")) + else: + print(_("Tip: Install pyreadline3 for Tab completion (pip install pyreadline3)")) def show_help(self) -> None: """显示帮助信息""" diff --git a/scripts/check_i18n.py b/scripts/check_i18n.py new file mode 100644 index 0000000..f6d32c9 --- /dev/null +++ b/scripts/check_i18n.py @@ -0,0 +1,43 @@ +#!/usr/bin/env python +"""检查翻译文件完整性""" + +import re +import sys + + +def check_po_file(path: str) -> bool: + """检查单个 .po 文件是否有空翻译""" + with open(path, "r", encoding="utf-8") as f: + lines = f.readlines() + + i = 0 + found_issue = False + while i < len(lines): + line = lines[i] + # 检查单行 msgid 后跟空 msgstr 的情况 + if re.match(r'^msgid ".+"$', line): + if i + 1 < len(lines): + next_line = lines[i + 1].strip() + # 如果下一行是 msgstr "" 且不是多行字符串的开始 + if next_line == 'msgstr ""': + # 检查是否真的是单行(再下一行不是以引号开头) + if i + 2 >= len(lines) or not lines[i + 2].strip().startswith('"'): + print(f"ERROR: {path}:{i + 2}: Empty translation: {line.strip()}") + found_issue = True + i += 1 + + return found_issue + + +if __name__ == "__main__": + all_ok = True + for path in sys.argv[1:]: + if check_po_file(path): + all_ok = False + + if not all_ok: + print("\nERROR: Empty translations found! Please add translations.", file=sys.stderr) + sys.exit(1) + + print("Translation check PASSED") + sys.exit(0) diff --git a/tests/unit/test_cli_commands.py b/tests/unit/test_cli_commands.py index acc8b9d..2994040 100644 --- a/tests/unit/test_cli_commands.py +++ b/tests/unit/test_cli_commands.py @@ -497,7 +497,8 @@ def test_show_command_list(self, capsys): cli = CLI() cli._show_command_list() captured = capsys.readouterr() - assert "Available commands" in captured.out + # 检查中文或英文输出 + assert "Available commands" in captured.out or "可用命令" in captured.out assert "#help" in captured.out assert "#install" in captured.out assert "#uninstall" in captured.out @@ -508,7 +509,8 @@ def test_interactive_help_shows_commands(self, capsys): cli = CLI() cli._interactive_help() captured = capsys.readouterr() - assert "Interactive Commands" in captured.out + # 检查中文或英文输出 + assert "Interactive Commands" in captured.out or "交互命令" in captured.out assert "#help" in captured.out assert "#install" in captured.out assert "#uninstall" in captured.out @@ -535,8 +537,8 @@ def mock_input(prompt): cli.interactive_mode() captured = capsys.readouterr() - # 应该显示可用命令列表 - assert "Available commands" in captured.out + # 应该显示可用命令列表(中文或英文) + assert "Available commands" in captured.out or "可用命令" in captured.out def test_readline_import_graceful_fallback(self, monkeypatch): """测试 readline 导入失败时优雅降级""" From e4f812aad9256244dd78e8bca86d3dc955c4c67f Mon Sep 17 00:00:00 2001 From: piratf Date: Sat, 31 Jan 2026 14:49:21 +0800 Subject: [PATCH 3/6] =?UTF-8?q?fix:=20=E5=B0=86=20pyreadline3=20=E6=89=93?= =?UTF-8?q?=E5=8C=85=E8=BF=9B=20exe=EF=BC=8C=E7=AE=80=E5=8C=96=E7=94=A8?= =?UTF-8?q?=E6=88=B7=E6=8F=90=E7=A4=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 修改原因: - 用户使用的是 exe 版本,不应该引导安装 Python 环境 - pyreadline3 约 683 KB,打包进 exe 是合理的 主要变更: - pyproject.toml: 添加 pyreadline3 到运行时依赖 - remark.spec: 添加 pyreadline3 到 hiddenimports - remark/cli/commands.py: 简化提示逻辑,移除安装提示 --- pyproject.toml | 6 ++++-- remark.spec | 4 ++++ remark/cli/commands.py | 16 ++++++---------- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 7c2aa5a..55bc455 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,8 +22,10 @@ classifiers = [ ] # 运行时依赖 -# 注意:仅使用 Python 标准库,无外部依赖 -dependencies = [] +# pyreadline3: Windows 下的 readline 实现,用于交互模式 Tab 补全 +dependencies = [ + "pyreadline3>=3.5.0", +] # 开发依赖 [project.optional-dependencies] diff --git a/remark.spec b/remark.spec index 9c946a7..dd3bf94 100644 --- a/remark.spec +++ b/remark.spec @@ -80,6 +80,10 @@ hiddenimports = collect_submodules('remark') + [ 'tkinter', 'packaging', 'packaging.version', + # pyreadline3 用于 Windows 下的 Tab 补全 + 'pyreadline3', + 'pyreadline3.clipboard', + 'pyreadline3.clipboard.win32_clipboard', ] # Collect locale translation files (.mo) diff --git a/remark/cli/commands.py b/remark/cli/commands.py index 71450cc..c4b2588 100644 --- a/remark/cli/commands.py +++ b/remark/cli/commands.py @@ -11,11 +11,11 @@ # 尝试导入 readline 用于 tab 补全 # Unix/Linux 系统通常有内置 readline -# Windows 用户可以安装 pyreadline3 获得相同功能 +# Windows 打包版本会自动包含 pyreadline3 try: import readline except ImportError: - # Windows 系统如果没有安装 pyreadline3,readline 不可用 + # 开发环境可能需要手动安装 pyreadline3 # 这不会影响基本功能,只是没有 tab 补全 readline = None @@ -327,10 +327,8 @@ def _show_command_list(self) -> None: print(_("Available commands:")) for cmd in self._interactive_commands_list: print(f" {cmd}") - if readline: - print(_("Tip: Press Tab to complete commands")) - else: - print(_("Tip: Install pyreadline3 for Tab completion (pip install pyreadline3)")) + # 打包版本已包含 pyreadline3,Tab 补全功能可用 + print(_("Tip: Press Tab to complete commands")) def _interactive_help(self) -> None: """显示交互模式帮助信息""" @@ -341,10 +339,8 @@ def _interactive_help(self) -> None: print(_(" #update Check for updates")) print(os.linesep) print(_("Or simply enter a folder path to add remarks")) - if readline: - print(_("Tip: Press Tab to complete commands")) - else: - print(_("Tip: Install pyreadline3 for Tab completion (pip install pyreadline3)")) + # 打包版本已包含 pyreadline3,Tab 补全功能可用 + print(_("Tip: Press Tab to complete commands")) def show_help(self) -> None: """显示帮助信息""" From 979041a303935a9a14e6365147cfd71bef97d24a Mon Sep 17 00:00:00 2001 From: piratf Date: Sat, 31 Jan 2026 16:55:16 +0800 Subject: [PATCH 4/6] =?UTF-8?q?refactor:=20=E7=A7=BB=E9=99=A4=20tab=20?= =?UTF-8?q?=E8=A1=A5=E5=85=A8=E5=8A=9F=E8=83=BD=EF=BC=8C=E4=BB=85=E4=BF=9D?= =?UTF-8?q?=E7=95=99=20#=20=E5=91=BD=E4=BB=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 原因: - pyreadline3 官方声明功能不完整("It is not complete") - Windows CMD 上 tab 补全实际上不可用 - 用户选择移除此功能 主要变更: - remark/cli/commands.py: 移除 readline 导入和 completer 代码 - pyproject.toml: 移除 pyreadline3 依赖 - remark.spec: 移除 pyreadline3 hiddenimports - tests/unit/test_cli_commands.py: 移除 3 个 readline 相关测试 保留功能: - 交互模式 #help、#install、#uninstall、#update 命令仍然可用 - 输入 # 显示可用命令列表功能仍然可用 --- pyproject.toml | 6 +-- remark.spec | 4 -- remark/cli/commands.py | 30 -------------- tests/unit/test_cli_commands.py | 69 --------------------------------- 4 files changed, 2 insertions(+), 107 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 55bc455..7c2aa5a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,10 +22,8 @@ classifiers = [ ] # 运行时依赖 -# pyreadline3: Windows 下的 readline 实现,用于交互模式 Tab 补全 -dependencies = [ - "pyreadline3>=3.5.0", -] +# 注意:仅使用 Python 标准库,无外部依赖 +dependencies = [] # 开发依赖 [project.optional-dependencies] diff --git a/remark.spec b/remark.spec index dd3bf94..9c946a7 100644 --- a/remark.spec +++ b/remark.spec @@ -80,10 +80,6 @@ hiddenimports = collect_submodules('remark') + [ 'tkinter', 'packaging', 'packaging.version', - # pyreadline3 用于 Windows 下的 Tab 补全 - 'pyreadline3', - 'pyreadline3.clipboard', - 'pyreadline3.clipboard.win32_clipboard', ] # Collect locale translation files (.mo) diff --git a/remark/cli/commands.py b/remark/cli/commands.py index c4b2588..24a7db9 100644 --- a/remark/cli/commands.py +++ b/remark/cli/commands.py @@ -9,16 +9,6 @@ import threading import urllib.error -# 尝试导入 readline 用于 tab 补全 -# Unix/Linux 系统通常有内置 readline -# Windows 打包版本会自动包含 pyreadline3 -try: - import readline -except ImportError: - # 开发环境可能需要手动安装 pyreadline3 - # 这不会影响基本功能,只是没有 tab 补全 - readline = None - from remark.core.folder_handler import FolderCommentHandler from remark.gui import remark_dialog from remark.i18n import _ as _, set_language @@ -267,12 +257,6 @@ def interactive_mode(self) -> None: print(_("Tip: Press Ctrl + C to exit")) print(_("Tip: Use #help to see available commands")) - # 设置 readline 补全(如果可用) - if readline: - readline.set_completer(self._command_completer) - readline.parse_and_bind("tab: complete") - readline.set_completer_delims("") # 允许补全包含 # 的命令 - input_path_msg = "\n" + _("Enter folder path (or drag here): ") input_comment_msg = _("Enter remark:") @@ -312,23 +296,11 @@ def interactive_mode(self) -> None: break print(os.linesep + _("Continue processing or press Ctrl + C to exit") + os.linesep) - def _command_completer(self, text: str, state: int) -> str | None: - """readline tab 补全函数""" - # 获取匹配的命令选项 - options = [cmd for cmd in self._interactive_commands_list if cmd.startswith(text)] - - # state 用于循环返回多个匹配项 - if state < len(options): - return options[state] - return None - def _show_command_list(self) -> None: """显示可用命令列表""" print(_("Available commands:")) for cmd in self._interactive_commands_list: print(f" {cmd}") - # 打包版本已包含 pyreadline3,Tab 补全功能可用 - print(_("Tip: Press Tab to complete commands")) def _interactive_help(self) -> None: """显示交互模式帮助信息""" @@ -339,8 +311,6 @@ def _interactive_help(self) -> None: print(_(" #update Check for updates")) print(os.linesep) print(_("Or simply enter a folder path to add remarks")) - # 打包版本已包含 pyreadline3,Tab 补全功能可用 - print(_("Tip: Press Tab to complete commands")) def show_help(self) -> None: """显示帮助信息""" diff --git a/tests/unit/test_cli_commands.py b/tests/unit/test_cli_commands.py index 2994040..7658b9d 100644 --- a/tests/unit/test_cli_commands.py +++ b/tests/unit/test_cli_commands.py @@ -448,50 +448,6 @@ def test_interactive_commands_list_initialized(self): expected_commands = ["#help", "#install", "#uninstall", "#update"] assert cli._interactive_commands_list == expected_commands - def test_command_completer_with_hash_prefix(self): - """测试命令补全函数处理 # 开头的输入""" - cli = CLI() - - # 测试补全 #h 开头 - result = cli._command_completer("#h", 0) - assert result == "#help" - - # 测试补全 #i 开头 - result = cli._command_completer("#i", 0) - assert result == "#install" - - # 测试补全 #u 开头(有多个选项) - result = cli._command_completer("#u", 0) - assert result in ["#uninstall", "#update"] - - # 测试补全不存在的命令 - result = cli._command_completer("#x", 0) - assert result is None - - def test_command_completer_returns_multiple_options(self): - """测试命令补全返回多个选项""" - cli = CLI() - - # 测试 #u 开头有多个选项 - result = cli._command_completer("#u", 0) - assert result in ["#uninstall", "#update"] - - # 继续获取下一个选项 - result = cli._command_completer("#u", 1) - assert result in ["#uninstall", "#update"] - - # 超出选项数量返回 None - result = cli._command_completer("#u", 2) - assert result is None - - # #install 是唯一的 #i 开头命令 - result = cli._command_completer("#i", 0) - assert result == "#install" - - # #help 是唯一的 #h 开头命令 - result = cli._command_completer("#h", 0) - assert result == "#help" - def test_show_command_list(self, capsys): """测试显示命令列表""" cli = CLI() @@ -539,28 +495,3 @@ def mock_input(prompt): captured = capsys.readouterr() # 应该显示可用命令列表(中文或英文) assert "Available commands" in captured.out or "可用命令" in captured.out - - def test_readline_import_graceful_fallback(self, monkeypatch): - """测试 readline 导入失败时优雅降级""" - # 模拟 readline 不可用 - import builtins - original_import = builtins.__import__ - - def mock_import(name, *args, **kwargs): - if name == "readline": - raise ImportError("readline not available") - return original_import(name, *args, **kwargs) - - with monkeypatch.context() as m: - m.setattr("builtins.__import__", mock_import) - # 重新导入模块 - import importlib - import sys - if "remark.cli.commands" in sys.modules: - del sys.modules["remark.cli.commands"] - if "remark.cli" in sys.modules: - del sys.modules["remark.cli"] - - # 重新导入,应该不会因为 readline 不可用而失败 - import remark.cli.commands as commands_module - assert commands_module.readline is None From 1b0e6bba85f0f5695662f49a727c5ddfd8680085 Mon Sep 17 00:00:00 2001 From: piratf Date: Sat, 31 Jan 2026 17:01:02 +0800 Subject: [PATCH 5/6] chore: bump version to 2.0.7 --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index 7c2aa5a..5afb1f4 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ [project] name = "windows-folder-remark" -version = "2.0.6" +version = "2.0.7" description = "Windows 文件夹备注工具" readme = "README.md" requires-python = ">=3.11" From 88c9d8f24f2aeaae8964d2148cbced8f5576c42c Mon Sep 17 00:00:00 2001 From: piratf Date: Sat, 31 Jan 2026 19:02:21 +0800 Subject: [PATCH 6/6] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E8=8B=B1=E6=96=87?= =?UTF-8?q?=E9=A6=96=E9=A1=B5=20Get=20Started=20=E9=93=BE=E6=8E=A5?= =?UTF-8?q?=E5=88=B0=E9=94=99=E8=AF=AF=E8=AF=AD=E8=A8=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 修改英文首页 Get Started 链接从 /guide/getting-started 改为 /en/guide/getting-started - 更新中英文首页版本号到 2.0.7 --- docs/en/index.md | 4 ++-- docs/index.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/en/index.md b/docs/en/index.md index 4b150e6..474fa8a 100644 --- a/docs/en/index.md +++ b/docs/en/index.md @@ -13,7 +13,7 @@ head: "programmingLanguage": "Python", "codeRepository": "https://github.com/piratf/windows-folder-remark", "url": "https://piratf.github.io/windows-folder-remark/en/", - "version": "2.0.6", + "version": "2.0.7", "license": "MIT", "offers": { "@type": "Offer", @@ -29,7 +29,7 @@ hero: actions: - theme: brand text: Get Started - link: /guide/getting-started + link: /en/guide/getting-started - theme: alt text: GitHub link: https://github.com/piratf/windows-folder-remark diff --git a/docs/index.md b/docs/index.md index cc223c7..334db8e 100644 --- a/docs/index.md +++ b/docs/index.md @@ -13,7 +13,7 @@ head: "programmingLanguage": "Python", "codeRepository": "https://github.com/piratf/windows-folder-remark", "url": "https://piratf.github.io/windows-folder-remark/", - "version": "2.0.6", + "version": "2.0.7", "license": "MIT", "offers": { "@type": "Offer",