【问题标题】:Prompt user for a password and hide the input with Sublime Text提示用户输入密码并使用 Sublime Text 隐藏输入
【发布时间】:2020-03-19 07:02:48
【问题描述】:

我想要在 Sublime Text 2/3 插件中查询密码并使用 **** 隐藏输入的提示。这不起作用,甚至使 SublimeText 崩溃:

import sublime_plugin, sublime

class ExampleOneCommand(sublime_plugin.WindowCommand):
    def run(self):
        self.window.show_input_panel("Enter Password", "", self.on_done, self.getpwd, None)

    def getpwd(self, password):
        stars = "*" * len(password)
        self.window.show_input_panel("Enter Password", stars, self.on_input, self.getpwd, None)

    def on_done(self, password):
        pass

    def on_input(self, password):
        pass

如何正确操作?

【问题讨论】:

    标签: sublimetext3 sublimetext2 sublimetext sublime-text-plugin


    【解决方案1】:

    如上所述,当我调用您的命令时,它会使用RuntimeErrormaximum recursion depth reached 使插件主机崩溃。发生这种情况的原因可能最好用这个简单的例子来说明:

    class ExampleTwoCommand(sublime_plugin.WindowCommand):
        def run(self):
            self.window.show_input_panel("Sample", "Initial Text", None, self.on_change, None)
    
        def on_change(self, pwd):
            print('on_change("%s")' % pwd)
    

    如果您调用该命令,然后立即查看控制台而不与输入交互,您会看到:

    >>> window.run_command("example_two")
    on_change("Initial Text")
    

    所以本质上你的问题是当输入面板打开时,它告诉on_change()处理程序初始文本,你的命令通过立即再次打开输入面板来响应它,它做同样的事情然后kaboom。

    要解决这个问题,您需要设置一个防护装置来阻止这种情况的发生;例如:

    class ExampleThreeCommand(sublime_plugin.WindowCommand):
        def run(self):
            self.initial = ""
            self.window.show_input_panel("Sample", "", None, self.on_change, None)
    
        def on_change(self, pwd):
            if self.initial != pwd:
                stars = "*" * len(pwd)
                self.initial = pwd
                self.window.show_input_panel("Sample", stars, None, self.on_change, None)
    

    现在on_change() 处理程序只会在文本更改时重新打开输入处理程序。

    这样做的结果是最终返回给您的文本是您编辑的初始文本,因此当最终调用 on_done 时,它获取的文本将包含所有 * 字符,因为这里的操作。

    要解决这个问题,您需要检查on_change 中给出的password 以查看其中包含哪些字符不是* 字符以了解实际键入的内容,然后将其分开以便您保持用户正在编辑的文本。同样,如果密码的长度发生变化,您需要丢弃已保存的字符,因为有人从输入中删除了一个或多个字符。您还需要注意用户在面板内移动光标的情况(例如插入字符)。

    综上所述,执行所有这些操作的最简单示例如下,它使用password 设置告诉输入面板,无论输入什么,都应该被隐藏:

    class ExampleFourCommand(sublime_plugin.WindowCommand):
        def run(self):
            panel = self.window.show_input_panel("Enter Password", "", self.on_done, None, None)
            panel.settings().set("password", True)
    
        def on_done(self, password):
            sublime.message_dialog("Password entered: '%s'" % password)
    

    我不确定 Sublime Text 2 是否支持此设置;它在您输入密码时用于 Sublime Merge 的密码输入,因此可能是当时添加的。

    如果需要 Sublime Text 2 支持,那么下一个最好的方法是插件和相关键绑定的组合(我认为它应该在那里工作,但我没有要测试的副本):

    _password = ""
    class ExampleFiveCommand(sublime_plugin.WindowCommand):
        def run(self):
            panel = self.window.show_input_panel("Enter Password", "", self.on_done, None, None)
            panel.settings().set("password_input", True)
    
            global _password
            _password = ""
    
        def on_done(self, password):
            sublime.message_dialog("Password entered: '%s'" % _password)
    
    
    class PasswordInputCommand(sublime_plugin.TextCommand):
        def run(self, edit, character):
            global _password
            _password += character
            self.view.run_command("insert", {"characters": '*'})
    
        { "keys": ["<character>"], "command": "password_input", "context": [
            { "key": "setting.password_input", "operator": "equal", "operand": true },
        ],
        },
    

    这里的键绑定在您输入字符时执行自定义命令,但仅当视图具有设置 password_input 并将其设置为 true 时。相关命令以字符串形式记录实际密码,并打开输入面板应用设置。结果是,只要面板打开并且您在其中输入,自定义命令就会抓取文本并保留它。

    对于更完整的示例,您还需要绑定退格键,以防用户想要进行更正。您还可以使用视图中的选择来确定按下的字符在现有密码中的位置。

    不过,总的来说,password 设置是最干净的解决方案。

    【讨论】:

    • 对于最后一种选择,您不能简单地将插入的字符添加到 _password 变量中,因为它可能已插入到不同的位置,并且从技术上讲,输入面板也支持多项选择,尽管在密码提示中几乎不实用。然而,最值得注意的是,可能有一个选择在插入字符之前,这更令人讨厌。
    • 是的;我在 Perforce 包中看到的 PR example 天真地假设所做的唯一更改是在末尾添加字符或删除它们,因此如果您以某种方式移动选择,它会非常可怕地中断。总的来说,我认为password 设置是最好的解决方案。
    • 非常感谢@OdatNurd 这个解决方案。 ExampleFourCommand 在 ST3 上完美运行。虽然不在 ST2 上。 ExampleFiveCommand 几乎可以在 ST2 上运行,但是如果您输入 abc&lt;backspace&gt;&lt;backspace&gt;&lt;backspace&gt;def,它将输出 abcdef,而它应该只输出 def
    • 是的,在这种情况下,您需要使用相同的上下文和可以调整密码的命令对退格键进行额外绑定。尽管正如上面评论中提到的@FichteFoll,整个事情通常需要更智能,因为也可以更改输入中的光标位置。在这种情况下,改变发生在视图末尾的假设也是错误的。
    • 我一般建议完全放弃 ST2。在这个时代试图维持对它的支持只会阻碍你。
    猜你喜欢
    • 2011-10-17
    • 2011-12-06
    • 2021-04-17
    • 2016-01-30
    • 2013-08-19
    • 2012-06-14
    • 2018-09-13
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多