Sublime Forum

Open key .sublime-keymap with `edit_settings` with specific platform in mind

#1

I maintain GitSavvy and we have mostly platfrom agnostic command but some are not super/ctrl.

We have a command to open the settings

{
    "caption": "Preferences: GitSavvy Settings",
    "command": "edit_settings",
    "args": {
        "base_file": "${packages}/GitSavvy/GitSavvy.sublime-settings",
        "default": "// Settings in here override those in \"GitSavvy/GitSavvy.sublime-settings\",\n\n{\n\t$0\n}\n"}
},

We want to add something simular to keybindings

{
    "caption": "Preferences: GitSavvy Key Bindings",
    "command": "edit_settings",
    "args": {
        "base_file": "${packages}/GitSavvy/Default.sublime-keymap",
        "default": "// Add your custom shortcuts here\n// GitSavvy adds key binding to both general and platform specific\n\n{\n\t$0\n}\n"
    }
},

The problem here is that all the platform specif aren’t there.

As a Package developer who do we solve https://github.com/divmain/GitSavvy/issues/884#issuecomment-372127280

0 Likes

#2

I’ve been curious about this in the past in my own packages. I noticed that the Default package only specifies platform specific key bindings and not just a default.

As such it’s possible that the official stance on this is that your key bindings should always be in platform specific files. although I don’t know for sure. I’m not sure that there are very many key bindings that are identical across all three platforms, for example, so it may fall outside of the use case.

That said, this opens a settings window with GitSavvy/Default.sublime-keymap on the left and the user specific key bindings (always platform specific) in the right.

window.run_command("edit_settings", {"base_file": "${packages}/GitSavvy/Default.sublime-keymap"})

The following opens the settings with the platform specific key bindings on the left (e.g. GitSavvy/Default (Windows).sublime-keymap) and the user settings on the right.

window.run_command("edit_settings", {"base_file": "${packages}/GitSavvy/Default (${platform}).sublime-keymap"})

The path of least resistance would be to just have three files and have maintenance headaches. Second up would be possibly adding in two commands for this instead of one, depending on the time you want to spend and/or the likelyhood of the user wanting to fiddle one set of binds more than the other.

The potential best-case scenario user-wise would be to create your own custom command to do this that would open both of the packaged files on the left and the user settings on the right. The code for the command is in Default/settings.py as a starting point.

0 Likes

#3

Alternatively, you could do something along the lines of this crude proof of concept to catch the editing command finishing after the user picks your menu item and then loading the platform independent details in the left hand side.

import sublime
import sublime_plugin


class KeyboardSettingsListener(sublime_plugin.EventListener):
    def on_post_window_command(self, window, command, args):
        if command == "edit_settings":
            base = args.get("base_file", "")
            if base.endswith("sublime-keymap") and "/GitSavvy/Default" in base:
                w = sublime.active_window()
                w.focus_group(0)
                w.run_command("open_file", {"file": "${packages}/GitSavvy/Default.sublime-keymap"})
                w.focus_group(1)
>>> window.run_command("edit_settings", {"base_file": "${packages}/GitSavvy/Default (${platform}).sublime-keymap"})
1 Like

#4

The primary modifier maps to super on macOX and control on the other platforms. It appears that this is the prominent difference between the platform-specific bindings.

0 Likes

#5

I like it. And now it easily accessible.

Thanks for the help

0 Likes

#6
0 Likes

#7

A lot of developers seem to use edit_settings or open_file to open a single settings file and neglect to open both the default / base and user file which is possible with edit_settings meaning you have to open > navigate to the package menu > navigate to the appropriate entry > and select it - twice to open the 2 files…

I highly recommend opening the default and user file at the same time and calling it settings so users don’t need to re-navigate for the same thing, or just to view what options are available to them when they go to edit the user settings…

I developed something to further extend it, and it is still in the works alongside a few other projects… edit_settings_plus allows you to open unlimited number of files in the same settings style with with or without write protection for default files - and the ability to open a single group only if that’s how you want to open files…

I made it because my plugin has many different files and I didn’t want my users to have to spend a minute simply fumbling with the menu in order to open all of the settings files, and then having to drag them to a single window… or make some hack to open all of them and hardcode it someway… and I wanted a lot more expandable variables than are available to us by default ( edit_settings doesn’t even give us access to the sublime.extract_variables( ) which has a lot of useful data )…

I recommend setting up your layout so - if you don’t have many files to open: open them all in one go ( with my file linking system when a user clicks Preferences in the base group - Preferences in the User group is displayed on the right and vice versa - so they don’t need to fumble in order to see what values are available to them, by default )…

I still need to work on a few things - but it’s about ready for testers ( need to add res:// support and some other things ) but take a look and let me know what you think :slight_smile:

Original post:

Here’s my edit settings plus command to open all 12 files… Preferences Base / User, Preferences (PLATFORM) Base / User, Key Bindings Base / User, Key Bindings (PLATFORM) Base / User, Mouse Bindings Base / User, Mouse Bindings (PLATFORM) Base / User…

The command I use is ( Oh, you can open up 2 files max at a time with edit_settings using base_file for the left side, and user_file for the right / user side… default, the var for the default contents is used for the user file if contents don’t exist ):

##
## Command - Open ALL Sublime Base / User Preferences - Keymaps included...
##
class acms_menu_settings_open_all_sublime_prefs( sublime_plugin.WindowCommand ):
	## Defaults
	__default_prefs__				= '//\n// Sublime Text - Configuration - User\n//\n{\n\t$0\n}\n'
	__default_prefs_platform__		= '//\n// Sublime Text - ${platform} Configuration - User\n//\n{\n\t$0\n}\n'
	__default_keymap__				= '//\n// Sublime Text - Base KeyMap Configuration - User\n//\n{\n\t$0\n}\n'
	__default_keymap_platform__		= '//\n// Sublime Text - ${platform}  KeyMap Configuration - User\n//\n{\n\t$0\n}\n'
	__default_mousemap__			= '//\n// Sublime Text - Base MouseMap Configuration - User\n//\n{\n\t$0\n}\n'
	__default_mousemap_platform__	= '//\n// Sublime Text - ${platform}  MouseMap Configuration - User\n//\n{\n\t$0\n}\n'
	__default_syntax_settings__		= '//\n// Acecool - Code Mapping System - ${syntax} Syntax Configuration - User\n//\n{\n\t$0\n}\n'

	## Syntax File Links
	__syntax_python__				= 'Packages/Python/Python.sublime-syntax'
	__syntax_javascript__			= 'Packages/JavaScript/JavaScript.sublime-syntax'

	## The Menu Entry Caption
	def description( self ):
		return 'Sublime Text Preferences - ALL 14 + Syntax Def & Config'

	## Whether or not the menu item is enabled
	def is_enabled( self ):		return self.window.active_view( ) is not None

	## Run the command
	def run( self ):
		## Run the command
		self.window.run_command(
			## Command is edit_settings_plus with the following args
			'edit_settings_plus',
			{
				## Developer set to True means the base / left group is not read only - removing the arg defaults to False so you can't edit the base / left group files... only use them for reference...
				'developer':	True,

				## Debugging set to True enables all print statements to show what's happening in the world of edit_settings_plus
				##'debugging':	True,


				## 
				## Note: If you use arg file_list: { ... } where each entry as ... is a { } containing base_file, user_file, and default ( all OPTIONAL ) you can add syntax arg to force a particular syntax highlighter on a file... more options later...
				## 	You can use the arguments base_file and user_file as a single file, None, or a List of files
				## 	( and they do not need to match the lengths of the others - although for default it should match, even if you use None if a later file needs default data you will need None to occupy the space of each one which doesn't up to the last one you want to have default data... )
				## 
				## Note: I've left both uncommented to show what they look like when aligned nicely vertical vs horizontal... I used helper vars to save space..
				## 

				## 
				## Files included are * 2: Preferences, Preferences (PLATFORM), KeyMap, KeyMap (PLATFORM), MouseMap, MouseMap (PLATFORM), Syntax Definition File and Syntax User Settings - so 14 files...
				## 
				'base_file':	[ '${default}/Preferences.sublime-settings',	'${default}/Preferences (${platform}).sublime-settings',	'${default}/Default.sublime-keymap',		'${default}/Default (${platform}).sublime-keymap',		'${default}/Default.sublime-keymap',		'${default}/Default (${platform}).sublime-mousemap',	'${syntax_path}' ],
				'user_file':	[ '${user}/Preferences.sublime-settings',		'${user}/Preferences (${platform}).sublime-settings', 		'${user}/Default.sublime-keymap',			'${user}/Default (${platform}).sublime-keymap',			'${user}/Default.sublime-mousemap',			'${user}/Default (${platform}).sublime-mousemap',		'${user}/${syntax}.sublime-settings' ],
				'default':		[ self.__default_prefs,							self.__default_prefs_platform,								self.__default_keymap,						self.__default_keymap_platform,							self.__default_mousemap,					self.__default_mousemap_platform,						self.__default_syntax_settings ]


				##
				## Note: The following isn't required - it serves as an example to show what this would look like if file_list was used instead of the 3 default args for edit_settings above...
				##
				'file_list':
				[
					## Base / Left Group File												User / Right Group File												Default contents for the User / Right Group File if it doesn't exist!
					{ 'base_file': '${default}/Preferences.sublime-settings',				'user_file': '${user}/Preferences.sublime-settings',				'default': self.__default_prefs__ },
					{ 'base_file': '${default}/Preferences (${platform}).sublime-settings',	'user_file': '${user}/Preferences (${platform}).sublime-settings',	'default': self.__default_prefs_platform__ },
					{ 'base_file': '${default}/Default.sublime-keymap',						'user_file': '${user}/Default.sublime-keymap',						'default': self.__default_keymap__ },
					{ 'base_file': '${default}/Default (${platform}).sublime-keymap',		'user_file': '${user}/Default (${platform}).sublime-keymap',		'default': self.__default_keymap_platform__ },
					{ 'base_file': '${default}/Default.sublime-keymap',						'user_file': '${user}/Default.sublime-mousemap',					'default': self.__default_mousemap__ },
					{ 'base_file': '${default}/Default (${platform}).sublime-mousemap',		'user_file': '${user}/Default (${platform}).sublime-mousemap',		'default': self.__default_mousemap_platform__ },

					## Note: Because I added syntax here, both of these syntax files will be highlighted using the JavaScript definitions... If I wanted each to be highlighted differently I would need to put base_file and syntax on one line, and the next user_file, default, and syntax args in their own Dicts.
					## I am planning on adding user_syntax and base_syntax args so they can be on a single line... I may even add the args to work outside of the file_list system...
					{ 'base_file': '${syntax_path}',										'user_file': '${user}/${syntax}.sublime-settings',					'default': self.__default_syntax_settings__		'syntax': self.__syntax_javascript__ },
				]
			}
		)

// One call to open all relevant files… This is so useful that I’m surprised it isn’t included by default in Sublime Text… Seriously - being limited to a single user and base file is very limiting especially if your plugin has custom settings files and you want the default settings files to open up ( if you allow the default preferences file to override them, and in most cases it does this automatically? )

// One Extended Args System to create a TON of useful arguments / expandable variables to shorten the length of each file name ( I plan on adding more - at the least I’ll probably add single arg for full path to all of the default files, and all of the default files in the user dir )…

This is the current list:

//
// Acecool - Code Mapping System - Extracted Vars Example
//
// Note: Because of our use of several sources - some values may be identical and some vars may be shortened - treat these as aliases...
//
{
	//
	// Acecool Library / Extract Vars
	// sublime.active_window( ).extract_variables( )
	//
	${version_sublime}		3143
	${platform}				Windows
	${architecture}			x64
	${arch}					x64

	// Important Paths
	${cache}				C:\Users\Acecool\AppData\Local\Sublime Text 3\Cache
	${packages_installed}	C:\Users\Acecool\AppData\Roaming\Sublime Text 3\Installed Packages
	${packages}				C:\Users\Acecool\AppData\Roaming\Sublime Text 3\Packages
	${user}					C:\Users\Acecool\AppData\Roaming\Sublime Text 3\Packages\User
	${default}				C:\Users\Acecool\AppData\Roaming\Sublime Text 3\Packages\Default
	${package}				C:\Users\Acecool\AppData\Roaming\Sublime Text 3\Packages\AcecoolCodeMappingSystem
	${user_package}			C:\Users\Acecool\AppData\Roaming\Sublime Text 3\Packages\User\AcecoolCodeMappingSystem

	// Active File when edit_settings_plus was called Data:
	${file_path}			C:\AcecoolGit\acecooldev_sublimetext3\AppData\Sublime Text 3\Packages\AcecoolCodeMappingSystem
	${file}					C:\AcecoolGit\acecooldev_sublimetext3\AppData\Sublime Text 3\Packages\AcecoolCodeMappingSystem\AcecoolCodeMappingSystemPlugin.py
	${file_name}			AcecoolCodeMappingSystemPlugin.py
	${file_base_name}		AcecoolCodeMappingSystemPlugin
	${file_extension}		py
	${extension}			py
	${ext}					py

	// Active File Syntax Information
	${syntax}				Python
	${language}				Python
	${lang}					Python
	${user_syntax}			C:\Users\Acecool\AppData\Roaming\Sublime Text 3\Packages\User\Python.sublime-settings
	${syntax_ext}			sublime-syntax
	${syntax_file}			Python.sublime-syntax
	${syntax_path}			Python/Python.sublime-syntax

	// Menu > Project / Sublime Text Window Session Data
	${folder}				C:\AcecoolGit\acecooldev_sublimetext3\AppData\Sublime Text 3\Packages\AcecoolCodeMappingSystem
	${project}				C:\AcecoolGit\AcecoolCodeMappingSystem.sublime-project
	${project_path}			C:\AcecoolGit
	${project_name}			AcecoolCodeMappingSystem.sublime-project
	${project_base_name}	AcecoolCodeMappingSystem
	${project_extension}	sublime-project

	// Misc
	${repo}					https://bitbucket.org/Acecool/acecooldev_sublimetext3
}

This isn’t me posting about something I have and no one else - I am planning on releasing edit_settings_plus because of the lack of functionality edit_settings has - and I plan on extending a lot of the other default commands too with my extended expandable vars…

The things I have left on edit_settings_plus before final release is: Finish res:// vs path to… detection for files… Finish making sure it is 100% stand-alone… and adding micro-caching to the file linker ( when you click on a file in one group, the same name file in the other group gets focused too ) so it doesn’t need to loop through the other group each time you click - maximum of once… and standardize the expandable vars to make it look more vanilla and possibly add some more - waiting on thread responses…

This is edit_settings_plus as it currently stands - Note, there are still things left to do but it is incredibly useful…

If you want to try it out and give me your opinions, that’d be great…

Default commands are ( You will need to add them to a context menu, main menu, or package commands file for them to show up and be usable )…:

##
## Developer Command - Opens an empty file containing a list of all of the expandable vars, and their values from the window where it was called from
##
## Add to Main / Context sublime-menu using - It'll be named '[ edit_settings_plus ] Show all Expandable Vars - Simple'
##	and will open an empty non-existent document showing each variable, and it's return value...
##
##			{ "command": "edit_settings_plus_show_all_expandable_vars_simple" },
##


##
## Developer Command - Opens an empty file containing a list of all of the expandable vars, and their values from the window where it was called from
##
## Add to Main / Context sublime-menu using - It'll be named '[ edit_settings_plus ] Show all Expandable Vars'
##	and will open an empty non-existent document showing each variable and it's return value, in a heavily commented / described form...
##
##			{ "command": "edit_settings_plus_show_all_expandable_vars" },
##

##
## Command - Open ALL Sublime Base / User Preferences - Keymaps included...
##
## Add to Main / Context sublime-menu using - It'll be named 'Sublime Text Prefferences - ALL 14 + Syntax Def & Config':
##
##			{ "command": "edit_settings_plus_menu_open_all_sublime_prefs" },
##

Note: The 16 file opener may not open ALL default files ( if they do not exist in the file system they won’t be opened )… I still need to add support to check res:// locations before giving up… But it is nearing its release so I may as well allow testers :slight_smile:

The included 3 commands give an idea of whats possible… and give a nice / easy list of variables which can be used ( to grow soon )…

I also have some housecleaning to do, and other tasks as mentioned… but hopefully this helps…

Oh - for the package detector to work - the file needs to be in the package you want to detect - otherwise you’ll need to manually add a package var… I’ve added commented out version as an example… for repo to display anything other than my repo, you’ll need to use the arg too…

0 Likes