Automatically loading a Sublime workspace on startup - sublimetext3

I posted a question here: Easier access to Sublime macros
That was brilliant and worked perfectly! But there is one last thing I can't figure out. How do I set it so Sublime loads a saved workspace automatically whenever it is opened? Because I have my macros folder in the sidebar but I want it there automatically every time I start Sublime, I added the folder and saved the workspace but when I close Sublime the folder is gone and I have to go to project->open-recent->myworkspace
Is there a way to either load a workspace automatically upon starting Sublime or automatically adding a folder to the project when starting Sublime?

If the appropriate folder is open in the side bar and you have the hot_exit setting turned on (which it is by default), then quitting Sublime and restarting it should keep the folder there, and the same should be true for individual windows if they are referencing a project or workspace.
It's not uncommon to run afoul of the distinction that closing the last window is not the same thing as quitting Sublime depending on the platform that you're on, which can cause Sublime to record in the session that there were no windows open when it quit.
However based on the comments on your question it sounds more like this isn't actually your issue and you'd instead like a way to have a specific folder or folders added to newly created windows and projects instead, so that your macros folder is just always available.
This is possible via a plugin, which can adjust the folders in a particular window as appropriate. This can be semi-mostly automated (more on that below). Here's the plugin we need for this:
import sublime
import sublime_plugin
class AddAdditionalFoldersCommand(sublime_plugin.WindowCommand):
"""
Adds all of the folders from the `additional_folders` setting in the user
preferences to the current window, if they are not already present there.
"""
def run(self):
# Get the list of folders from the settings
settings = sublime.load_settings("Preferences.sublime-settings")
additional = settings.get("additional_folders", [])
# Get the project data and associated folders from the current window,
# with sensible defaults if the window has no project data yet
project_data = self.window.project_data() or {}
project_folders = project_data.get("folders", [])
# Add in any additional folders that are not already present
for folder in additional:
if not any(o["path"] == folder for o in project_folders):
project_folders.append({"path": folder})
# Update project data
project_data["folders"] = project_folders
self.window.set_project_data(project_data)
class AdditionalFolderListener(sublime_plugin.EventListener):
"""
Listens to see if a new window has been created, and if so add additional
folders if desired.
"""
def on_post_window_command(self, window, command_name, args):
if command_name == "new_window":
settings = sublime.load_settings("Preferences.sublime-settings")
if settings.get("auto_add_additional_folders", False):
window = sublime.active_window()
window.run_command("add_additional_folders")
To use this, you also need to add some settings to your Preferences.sublime-settings file (change the values as appropriate):
// When true, the folders in "additional_folders" will be
// automatically added when a new window is created.
"auto_add_additional_folders": true,
// Additional folders to add; these must be absolute paths
"additional_folders": [
"/home/odatnurd/.config/sublime-text-3/Packages/User/macros"
],
This does two things:
When you run the add_additional_folders command, all of the folders from the list configured in the additional_folders setting will be added to the current window so long as they are not already present (otherwise the same folder would appear more than once).
When a new window is created, if the auto_add_additional_folders setting is true (it defaults to false in the code for safety), then the command will be executed automatically for the new window.
Cycling back to the above post, the "semi-mostly automated" part of this is because in order to work, the new_window command has to be invoked for the event handler to be able to know that a new window was created.
This will be the case if you use the menu item or key binding to create a new window, but that command isn't executed if you open an existing project or workspace. It's also possible for windows to be created without using this command, such as if you quit Sublime with no windows and it creates a new one by default, or on MacOS if there are no windows and you click the dock icon.
Thus depending on how you use Sublime you may want to bind add_additional_folders to a key so that you can invoke it manually as needed. You can also create a file named something like AdditionalFolders.sublime-commands in your User package with the following content to add the command to the command palette. You can adjust the caption to suit; also the name of the file is not important so long as the extension is correct.
[
{ "caption": "Add Additional Folders", "command": "add_additional_folders" },
]
Final Notes:
Despite the name of the API used here, this will work in all windows even if they don't have a project associated with them (or they just have a workspace associated with them) because all windows inherently carry project data
It's been hinted that the next version of Sublime will have additional events that make it easier to detect new windows. The above covers up to build 3211; if you're reading this and there is a newer build available, the above could possibly be made smarter.

Related

index.sublime-project and index.sublime-workspace files

I have a directory named project, and I navigated to Project > Add Folder to Project... in order to see the directory tree in my left sidebar. I noticed that doing this creates a file called index.sublime-project with the following content:
{
"folders":
[
{
"path": "."
}
]
}
I also noticed that there is another file in my directory called index.sublime-workspace, although this one does not appear in the tree view on the left sidebar of Sublime. It is only visible through windows explorer when I navigated to the Project directory.
What is the purpose of these files? Can I prevent them from being created every time I add folder to project?
Adding directories to the window using Project > Add Folder to Project is indeed one of the ways to open a folder (the others being to drag and drop a folder onto the window and File > Open Folder).
However, doing so do not create those files. To create them, you would need to use the Project > Save Project menu item. So you may have accidentally done that without realizing it. In theory a plugin could also create those files for you, though that seems unlikely (anything is possible though).
In any case, assuming you don't want them it's entirely safe to remove them.
A sublime-project file is a file that allows you to open folders in the side bar and then do things like apply settings that apply only to files in that window, alter what files and folders appear, and so on.
A sublime-workspace file is a localized session information for a particular window. Usually, they associated with a sublime-project file but they don't have to be. They store the state of the window, open files, etc so that you can close a window and then recall it later with the same state.

How do I add items to a menu in Sublime 3?

I want to add a couple of items to the Edit menu in Sublime 3. In fact, I just want to copy the Find and the Replace menu items from the Find menu. Call me lazy, but I just want to use the same Alt-E menu shortcuts I've grown accustomed to across so many other programs. I don't like making the mental switch from Alt-E to Alt-I when I switch from Sublime to anything else.
Anyway, from the sublime documentation I read that I can create a file Main.sublime-menu in the Packages/Default (or Packages/User) directory. The JSON format is easy enough to follow. But the problem is that there is no such file by default. If I add one (and I did) then sumblime replaces the entire main menu, which is not the result I want.
I don't want to replace the entire menu, I just want to add two entries to the Edit menu. Ideally, I would like to copy & paste the Find and Replace entries from the Find menu. That would save me the time of figuring out the command names.
Resource files that ship with Sublime are stored in sublime-package files that exist in a special folder stored in the installation folder of Sublime (where the executable is), which keeps them safe from modification because Sublime will replace them wholesale when it updates.
You can view the content of any resource file currently known to Sublime by using the View Package File command from the command palette. It will show you a list of every resource, and you can filter the list the same as the command palette entries to drill down to find what you need:
Choosing an item from this list will open the file for you to look at. If it's coming from a sublime-package file, it will be a read-only buffer that you can't modify to remind you that you can't edit the file. Resources that come from your Packages folder directly will be editable, however (such as your User package).
The Default package is where things like the default settings, key bindings and menus are defined. So although what you see in the list depends on the packages you have installed, the item you want here is Default/Main.sublime-menu.
Note that if your intention is to just add some items, you want to put your modifications into your User package. Any items you add here will augment the existing menu; that is, you can only add items, you can't modify or remove them.
If you put the file into the Default package folder (which you may or may not have to create), the file you create will override the one that's provided inside of the sublime-package file. You would do this if you want to remove entries, change what command they execute, etc.
If you go that route, note that Sublime will use this file forever even if a future update modifies the file. In that case I would recommend the OverrideAudit package (disclaimer: I am the author of said package) as it will warn you when that happens.
If this is your intention, OverrideAudit's Create Override command will allow you to seamlessly open the file and save it to create the override, saving you the trouble of finding the right place to put the file.

Sublime Text 3: import projects list from folder/files to OpenRecent list

I save several projects in a same folder by manual click Project -> Save Project As...
and I used to use cmd + ctrl + p to open Switch Projectlist to switch between projects
and everything's works fine.
but today, I accidentally remove my Switch Project list in by click Project -> Open Recent -> Clear Items, so my Switch Project list is empty now...
I know I could add them back through reopen ALL my projects. due to the number of projects is pretty a lot, that will be kind of annoying to add them back one by one.
I wanna know if there's a smarter way to do that for me.
maybe import all my *.sublime-project files from folder or something.
thanks
Short of manually opening every project, I don't think there is any way to do something like this directly. There isn't a command or plugin endpoint that I'm aware of that lets you open a project by name or filename, so it's not possible to create a plugin to do the work, and Sublime doesn't have the ability to pre-load the list of packages directly either.
That said, it is possible to manually update the list of recent projects, but whether or not that is more or less work than opening all of the projects is something to consider.
If you use Preferences > Browse Packages from the menu or the command palette, a file browser will open on your Packages folder. From there go up one directory level and go inside of the Local folder, where you will find a Session.sublime_session file.
Sublime saves it's state into this file when you quit it, and uses it to restore state when you start it again. Here you will find all of the saved information, such as the windows and files that were open and so on.
Changing this file will change the data that Sublime loads, so you can modify the session file to set up the data that you want. You need to make sure that you modify the file while Sublime is not running or your changes will be ignored and clobbered away. Also it's a good idea to make a backup of the file before you start in case things go pear shaped.
Down near the bottom of the file you will find a top level key named workspaces, and inside of it a recent_workspaces key:
"workspaces":
{
"recent_workspaces":
[
"/home/tmartin/local/src/OverrideAudit/OverrideAudit.sublime-workspace",
]
}
This is where the list of recent projects is stored for use in the menu and the quick switch project command. Particular things to notice are that the entries are naming sublime-workspace files, and that the paths are absolute.
NOTE: On windows, the filenames stored in the session file are in a format like /C/Users/tmartin and not c:\users\tmartin; on that platform you need to make sure that you adjust the paths accordingly. As long as there is already at least one entry in the list when you look at the session file, you can easily see how to construct the paths that you need.
Despite the name of the commands and menu items, what you're actually switching between is different workspaces. Every sublime-project is associated with a sublime-workspace file, which acts as a dedicated sublime_session file for that particular project. This mapping is one-to-many in that you can have multiple workspaces for the same project file, allowing you to reference the same paths in multiple windows but have different window layouts.
While Sublime is not running you can edit this file to add in the full paths to all of your workspace files; when you start Sublime up the list will be populated (every sublime-workspace file knows what sublime-project it is associated with).
What remains is whether or not it's quick to come up with the list of files in a way that you can easily paste them into the session file.

Is it possible to share SublimeText preferences *and* override one specific pref?

I share Sublime prefs between two machines (home, work) using Git.
My monitor at work has a higher DPI than my monitor at home, so in one of the two machines I'd like to override font_size.
I was hoping for:
The possibility to override using a command-line flag (to do something like subl --override-pref font_size=15), like kitty --override does.
Another level of prefs cascading below User.
, but I don't think any of this exists in Sublime. Language-specific config is not what I'm looking for, I want something global, but only in one of the two machines.
Ideas? Workarounds? Thanks.
The general mechanism at play for settings files is that when Sublime loads a sublime-settings file by name, it pulls all of the similarly named files across all of the known packages and combines them together (the same also happens for many other resource files) with content from later files overriding anything that appears in an earlier file.
The order that's imposed here is lexically by package, with Default always being first and User always being last. That's why the default settings are in the Default package and your custom settings are in the User package. Additionally syntax specific settings also apply (as do settings specific to projects).
Apart from this mechanism there's no direct way to override settings without some sort of manual intervention on your part. Potential solutions for this sort of problem include the following examples:
Don't sync the Preferences.sublime-settings file
If the file isn't synced across multiple machines, then this problem becomes moot because each machine can easily have it's own unique settings. The downside to that is that each machine then has it's own unique settings, which is a pain in the butt if you often move from machine to machine and things don't quite work the same way.
Use separate git branches
An alternative here if you're using git such as you are is to try and keep separate branches per host or per host type (like hi_dpi and reg_dpi or some such). Then on each machine check out the appropriate branch.
The obvious downsides here are having to try and cross-sync desired settings changes (for both User as well as any packages you might install) between branches, which is less than ideal unless you really love git.
Use extra Preferences.sublime-settings files
Here the idea is that you don't include the font_size setting in your User/Preferences.sublime-settings file at all. Instead, you use Browse Packages from the command palette to open the Packages folder, then create a new folder there with some arbitrary name. Inside of that folder include a Preferences.sublime-settings file that contains only the font_size setting.
Doing this on multiple machines, you can sync the settings in your User folder across machines without also syncing the preference that contains the font_size. As a note, if you create the file while Sublime is already running, you may need to quit and restart to get it to notice that the settings file exists; this only applies the one time, though.
Use a plugin
Looking at the link provided above, the ultimate trump card for any setting is a setting that's been applied directly to a view. Given that, you can use a plugin that selectively always applies a specific font size to any newly created or opened file:
import sublime
import sublime_plugin
import socket
class CustomFontListener(sublime_plugin.EventListener):
hostname = socket.gethostname()
def on_new(self, view):
if self.hostname in ("host1", "host1.example.com", "host2"):
view.settings().set("font_size", 20)
on_load = on_new
Now any time you open a file or create a new buffer, if the current hostname is in the list you've configured the view will immediately get an appropriate font_size applied; otherwise the one from the preferences would be used instead.
You could also extend this to be configurable via it's own settings file, apply a different font size depending on the host name, etc.
Settings in views are persisted in the sublime-session file and also in the workspace files associated with sublime-project files, so these settings will remain in place even across restarts.
Something to keep in mind is that the internal commands for changing the font size (via Preferences > Font or via the mouse wheel keyboard shortcuts) work by writing a new font_size to your user preferences.
If you're using separate preference files, then doing this will add font_size to your User settings and you will need to manually remove it and modify the other settings file.
If you're using the plugin, then these shortcuts won't seem to do anything because it applies a font_size that overrides the User preference, but in fact as outlined above your preferences file end up being changed and you may not notice right away.
So whichever way you go, if you tend to use those you may need to make manual adjustments to settings files in the aftermath. It's also possible to create smarter versions of those commands as well, if this is the sort of thing that happens often.

Can the size of Sublimes's paste history be increased?

Sublime Text 3's paste_from_history command is great, but I would like a longer history than 15 entries. Can this be configured?
This can't be configured directly, but you can modify the command itself to change the size of the history to achieve the same effect, if you would like.
To do so you need to create an override on the Default/paste_from_history.py plugin file, which tells Sublime to use your modified version of the file instead of the one that it ships with.
The easiest way to do so would be to use the PackageResourceViewer package. From the command palette, choose PackageResourceViewer: Open Resource (make sure you don't accidentally use the command with Extract in the name) and select first Default and then paste_from_history.py.
This will open the packed version of the file and set things up so that you can edit it and easily make an override. The part you want to change is on line 12, where LIST_LIMIT is defined to be 15:
class ClipboardHistory():
"""
Stores the current paste history
"""
LIST_LIMIT = 15
def __init__(self):
self.storage = []
You can change that number to the size that your desired value and save the file. As soon as you save, Sublime will reload the plugin and make your changes live (note that this clears the clipboard history).
Behind the scenes, what this is doing is creating a folder named Default in your Packages folder (Preferences > Browse Packages shows you where that is), with the modified file stored inside.
As long as that file exists, while Sublime is loading packages it will ignore the version it ships with and use your modified copy instead. Removing your copy and restarting Sublime will revert back to the defaults.
Sublime won't warn you if a future update changes the shipped file; it will still always use your modified copy. If you want to be warned when this happens, the OverrideAudit package can come in handy. It will automatically detect when a file you're overriding is updated and warn you so that you can see if you need to incorporate any changes.

Resources