提示用户输入密码并使用 Sublime Text 隐藏输入
Prompt user for a password and hide the input with Sublime Text
我想要在 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
如何正确操作?
如上所述,当我调用您的命令时,它使插件主机崩溃,RuntimeError
为 maximum 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()
处理程序关于初始文本,你的命令通过立即再次打开输入面板来响应它,这做同样的事情然后是咔嚓声。
要解决这个问题,您需要有一个保护措施来阻止这种情况的发生;例如:
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
时,它获得的文本将包含所有 [=由于此处的操作,21=] 个字符。
要解决这个问题,您需要检查 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
设置是最干净的解决方案。
我想要在 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
如何正确操作?
如上所述,当我调用您的命令时,它使插件主机崩溃,RuntimeError
为 maximum 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()
处理程序关于初始文本,你的命令通过立即再次打开输入面板来响应它,这做同样的事情然后是咔嚓声。
要解决这个问题,您需要有一个保护措施来阻止这种情况的发生;例如:
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
时,它获得的文本将包含所有 [=由于此处的操作,21=] 个字符。
要解决这个问题,您需要检查 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
设置是最干净的解决方案。