保存前执行操作(`on_pre_save`)

时间:2017-04-07 13:53:21

标签: sublimetext2 sublimetext3 sublimetext sublime-text-plugin

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。

1 个答案:

答案 0 :(得分:1)

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

on_post_save事件恰好在文件缓冲区写入磁盘后发生,允许您在保存操作后执行您可能要执行的任何操作,例如,一旦检查到缓冲区的内容,就会检查它的内容。 ; s&#34; final&#34; (例如&#34; lint on save&#34;,如果通过外部工具完成,则需要将更改放在磁盘上,而不仅仅是在内存中。)

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

要回答你的问题,你可以做任何事情&#34;任意&#34;你希望在on_pre_save中让它在发生保存之前发生的事情。如果你真的想要,也可以在那种情况下更改文件名。

但是请注意,在不首先询问用户的情况下从用户下面更改文件名肯定是糟糕的用户体验。此外,如果您将文件名更改为on_pre_save中已存在的文件,则会在没有警告的情况下盲目覆盖该文件,这也是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)