Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get user input before saving a file in Sublime Text

I'm making a plugin in Sublime Text that prompts the user for a password to encrypt a file before it's saved. There's a hook in the API that's executed before a save is executed, so my naïve implementation is:

class TranscryptEventListener(sublime_plugin.EventListener):
    def on_pre_save(self, view):
        # If document is set to encode on save
        if view.settings().get('ON_SAVE'):
            self.view = view
            # Prompt user for password
            message = "Create a Password:"
            view.window().show_input_panel(message, "", self.on_done, None, None)

    def on_done(self, password):
        self.view.run_command("encode", {password": password})

The problem with this is, by the time the input panel appears for the user to enter their password, the document has already been saved (despite the trigger being 'on_pre_save'). Then once the user hits enter, the document is encrypted fine, but the situation is that there's a saved plaintext file, and a modified buffer filled with the encrypted text.

So I need to make Sublime Text wait until the user's input the password before carrying out the save. Is there a way to do this?

At the moment I'm just manually re-saving once the encryption has been done:

def on_pre_save(self, view, encode=False):
    if view.settings().get('ON_SAVE') and not view.settings().get('ENCODED'):
        self.view = view
        message = "Create a Password:"
        view.window().show_input_panel(message, "", self.on_done, None, None)

def on_done(self, password):
    self.view.run_command("encode", {password": password})
    self.view.settings().set('ENCODED', True)
    self.view.run_command('save')
    self.view.settings().set('ENCODED', False)

but this is messy and if the user cancels the encryption then the plaintext file gets saved, which isn't ideal. Any thoughts?

Edit: I think I could do it cleanly by overriding the default save command. I hoped to do this by using the on_text_command or on_window_command triggers, but it seems that the save command doesn't trigger either of these (maybe it's an application command? But there's no on_application_command). Is there just no way to override the save function?

Edit: I've ended up just overriding the default key binding to a TextCommand, and there seem to be no problems.

like image 439
EddieJessup Avatar asked Oct 01 '22 14:10

EddieJessup


1 Answers

You would need to create a new command that overrides the existing save behavior to do what you want. As you've seen, the show_input_panel command is asynchronous. Thus, the command is "finished" after it creates the input panel. Rather than using on_pre_save you may want to try creating a TextCommand to do the save. Again, the downside to this is you would have to override the existing key binding. I suppose you could use the command listeners that are available in ST3, though I don't know if you are trying to create a plugin that is compatible with ST2 also.

like image 107
skuroda Avatar answered Nov 15 '22 08:11

skuroda