【问题标题】:Perform action before save (`on_pre_save`)保存前执行操作(`on_pre_save`)
【发布时间】:2017-04-07 13:53:20
【问题描述】:
import sublime_plugin

class Test(sublime_plugin.EventListener):

    def on_pre_save(self, view):
        view.set_syntax_file("Packages/Python/Python.tmLanguage")

这是一个简单的例子。从逻辑上讲(从我的角度来看),它应该在保存之前更改语法,因此文件应该保存为<filename>.py

但实际上,在保存操作之后会改变语法。所以,如果我最初使用js 文件,它将被保存为js,而不是py

我想知道为什么on_pre_save 的工作方式如此奇怪,或者换句话说,on_pre_saveon_post_save 之间有什么区别。另外,这是我的实际兴趣,如何在保存之前执行一些任意 (1) 操作?

(1) 我专门使用了“任意”这个词,因为我的意思不只是语法变化。这可能是不同的东西。例如,将字体从 Consolas 更改为 Times New Roman。

【问题讨论】:

    标签: sublimetext2 sublimetext3 sublimetext sublime-text-plugin


    【解决方案1】:

    on_pre_save 事件发生在文件缓冲区写入磁盘之前,它允许您在磁盘上的文件更改之前执行您可能想要执行的任何操作,例如对缓冲区的内容进行一些更改(例如“保存时重新格式化”)。

    on_post_save 事件发生在文件缓冲区写入磁盘之后,允许您在保存操作后执行您可能想要采取的任何操作,例如检查缓冲区的“最终”内容(例如“lint on save”,如果通过外部工具完成,则需要将更改保存在磁盘上,而不仅仅是在内存中。

    在任何一种情况下,文件的文件名在事件发生时都已被用户选择。对于一个新文件,这意味着on_pre_save 直到他们选择了文件的名称和位置之后才会发生。对于现有文件,save 只是使用相同的文件名重新保存。

    要回答您的问题,您可以在on_pre_save 中执行您想要的大多数“任意”事情,以便在保存发生之前发生。如果您真的愿意,也可以在这种情况下更改文件名。

    但是请注意,在不先询问用户的情况下从用户名下更改文件名绝对是糟糕的用户体验。此外,如果您将文件名更改为 on_pre_save 中已经存在的文件,sublime 会盲目地覆盖该文件而不会发出警告,这也是 Bad Mojo。

    对于要更改文件在磁盘上的名称和位置的内容,更合适的方法是让用户必须明确调用一个命令来实现这一点,以便他们完全了解正在发生的事情.


    根据评论中的要求并为了完整起见,这里有一个示例,可以满足您希望上面的示例代码执行的操作。

    这里要注意的重要一点是,您必须非常小心触发此事件的情况。如上所述,您的插件将无法保存任何类型的文件,因为它会交换改为 python 文件。

    在本例中,它被限制为仅对文本文件生效,将其转换为 python 文件。但是请注意,如果该位置已经有一个具有该名称的 python 文件,它将覆盖它而不会警告您它即将发生。

    对这段代码要格外小心;很容易意外地阻止自己以正确的名称保存文件,例如,这可能会阻止您使用 Sublime 修复代码以及其他令人讨厌的问题。

    import sublime_plugin
    import os
    
    class TestListener(sublime_plugin.EventListener):
        def on_pre_save(self, view):
            # This part is extremely important because as mentioned above it's
            # entirely disconcerting for your save operation to gank your
            # filename and make it suddenly be something else without any
            # warning. If you're not careful you might destroy your ability to
            # use sublime to fix your plugin, for example.
            if not view.file_name().endswith(".txt"):
                print("Doing nothing for: ", view.file_name())
                return
    
            # HUGE WARNING: This CAN and WILL willfully clobber over any file
            # that already happens to exist without any warning to you
            # whatsoever, and is most decidedly a Bad Idea(tm)
            python_name = os.path.splitext(view.file_name())[0] + ".py"
            view.retarget(python_name)
    

    【讨论】:

    • 谢谢!也许你可以添加一些例子?我的意思是,你说这是可能的,但就我而言,它不起作用。
    • 我编辑了答案,但我不能说这部分足够:谨慎使用此代码。 :)
    • 再次感谢。我会尽量小心:)
    猜你喜欢
    • 2023-03-16
    • 2021-12-10
    • 1970-01-01
    • 2021-06-14
    • 2016-01-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多