Hello and welcome to the wonderful world of Sublime Text!
This is an interesting idea for a plugin, actually. I have a similar (non-sublime) related setup for writing small test C programs, tied together with a shell script that does the same sort of archiving and file manipulation. Now I have the urge to turn it into a Sublime plugin instead…
I’ve been using Sublime for just a bit less than a year at this point, so I am by no means an expert in this sort of thing. So basically, take everything I say with a grain of salt.
The only obvious thing I can see from what you have so far is that your file name for opening test.py
is not correct; as stated it’s relative to wherever directory happens to be the current one. In order to always hit the file that you want, you should build the path based on sublime.packages_path()
along with the name of your package and the rest of the file name.
If you create the folder inside of the User
folder, you’re adding something to the User
package, but if it’s outside of the User
folder (i.e. has the same parent) you’re creating a brand new package instead. From a terminology/logical perspective, one is creating a new package and one is just adding content to an existing package. (note also that a plugin
is technically the .py
file you created; the structure as a whole is a Package
).
That said, Sublime will not automatically load plugin .py
files that are not directly rooted at the base of a package file so as to allow you more control.
In your case that means that although it will consider PythonTestFile.py
as a plugin for your package, it will completely ignore test/test.py
even though it’s a py
file (which for you is exactly what you want).
Also, Packages are loaded in a defined order with User
always being loaded last. So anything you do inside of the User
package “wins” as far as overriding things are concerned. For your case that doesn’t matter, but if you were trying to e.g. change a key binding it would be possible for another plugin to “steal” that key from you if it gets loaded after your plugin does.
I would think that’s something of an ideological thing for the most part. Since you’ve put it inside a sub-folder of your plugin, Sublime will ignore it. You could make the argument that as not a part of your package it should be created in e.g. your home directory or in the temporary files location, or you could make the argument that as a file you don’t want laying around, it’s best kept inside of a location that is out of the way, and the location of your package is already well known.
A TextCommand
has an implicit self.view
the same way that WindowCommand
has self.window
. So when your command gets invoked, it will be told what view is the current view. You need to do your own check to determine if that view is one you want to do something with, though (more on this below).
Based on your design idea, I would say that you should have an EventListener
listen for on_close
or on_close_async
to detect when your test file is being closed, and at that point you can copy/move it to a history folder inside of your plugin.
Since you want the file to always be empty when you open it, you probably want to move the file on close and create it new every time you tell it to open. Something like the following might work for you as a jumping off point.
class PythonTestFileCommand(sublime_plugin.WindowCommand):
def run(self):
test_file = os.path.join(sublime.packages_path(), "PythonTestFile",
"test", "test.py")
test_view = self.window.new_file()
test_view.settings().set("is_python_test", True)
test_view.retarget(test_file)
test_view.assign_syntax("Packages/Python/Python.sublime-syntax")
test_view.run_command("insert_snippet", {
"name": "Packages/PythonTestFile/boilerplate.sublime-snippet"
})
test_view.run_command("save")
class PythonTestFileListener(sublime_plugin.EventListener):
def on_close(self, view):
if view.settings().get("is_python_test", False) is True:
print("The python test file just closed")
Here the command to open the test file creates a new file, sets a custom setting on it so that it can be detected as a test file later on when it’s closed, and then sets the file name to be the one that you want it to be. It then makes sure that it’s a python file, executes a snippet to populate some boiler plate code in there (e.g. maybe some imports you always use) and then saves the file. You could skip the snippet part if you literally want an always empty file, though.
The event listener can detect when the file is closed and then physically move it to the history location (e.g. a folder named history
inside of your plugin), making sure to make the file name unique (say with a date and time or a numeric suffix or something).
Then you would need to implement a WindowCommand
that collects the list of files inside of the history location and presents them to you in a quick panel so you can select an old test to open.