How to set key-bindings in Sublime that change values of settings? - sublimetext3

I'm looking to bind the "alt+f11" binding to toggle "draw_centered", which centers the text as in Distraction-free mode. I'm not sure how to get it to work though.
Heres my keybinds so far:
//if draw_centered == true, set to false
{ "keys": ["alt+f11"], "command": "set_setting", "args":
{
"setting": "draw_centered",
"value": "true",
},
"context":
[
{ "key": "setting.draw_centered", "operator": "equal", "operand": false}
]
},
//if draw_centered == false, set to true
{ "keys": ["alt+f11"], "command": "set_setting", "args":
{
"setting": "draw_centered",
"value": "false",
},
"context":
[
{ "key": "setting.draw_centered", "operator": "equal", "operand": true}
]
}
I couldn't find a command that automatically toggled "draw_centered", so I had to resort to building some sort of advanced command. I'm having a bit of trouble understanding the documentation on keybindings, but I tried to follow the "Contexts" example. Could anyone point to what I'm doing wrong?

Thanks sergioFC for the tip about toggle_setting! I got it to work with this code:
{ "keys": ["alt+f11"], "command": "toggle_setting", "args":
{
"setting": "draw_centered",
}
}
EDIT: I discovered a bug with this. After using the key-combination "alt-f11" now, the distraction-free mode isn't behaving like it should. It now follows the draw_centered state that I am in when I switch from normal to distraction-free mode.
For example: if I have a file opened and click 'alt-f11' so I am left-aligned (i.e. draw_centered = false) , the window will remain left-aligned when I enter distraction-free mode. Any ideas as to why this is and how to fix it?

A little late, but it took me a while to find out how to do something similar and this was the most closest question to what I was trying to achieve.
toggle_setting only works in the current view(file you are working on), it also won't work in other options like show_encoding, because these aren't too related to the view specifically rather than being more part of the panel spectrum.
After digging a couple of hours I found an old plugin called Cycle Settings, this one was for Sublime 2, but after a little tweaking it worked as expected.
(I remember that there was an option to create packages directly in sublime, but don't remember where..)
Go to Preferences/Browse Packages... and create a new file there
"Cycle Settings/cycle_setting.py" and the following code there:
"""
Cycle Setting plugin for Sublime Text 3.
Copyright 2011 Jesse McCarthy <http://jessemccarthy.net/>
Adds a command that can be called from a key binding to toggle or
cycle through values for a setting.
The Software may be used under the MIT (aka X11) license or Simplified
BSD (aka FreeBSD) license. See LICENSE
"""
import sublime, sublime_plugin
class CycleSettingCommand(sublime_plugin.TextCommand):
def run(self, edit, setting, options):
"""Cycle $setting to next of $options"""
index = len(options)
if not index :
return
settings = sublime.load_settings('Preferences.sublime-settings')
value = settings.get(setting)
if value in options :
index = options.index(value)
index += 1
if index >= len(options) :
index = 0
value = options[index]
settings.set(setting, value)
sublime.save_settings('Preferences.sublime-settings')
self.view.set_status(
'cycle_setting',
"Setting '{setting}' cycled to value '{value}'".format(**locals())
)
Now, lets use our new command for bindings
Go to Preferences/Key Bindings
[
{
"keys": ["f5"],
"command": "cycle_setting",
"args": {
"setting": "draw_centered",
"options": [true, false]
}
},
{
"keys": ["shift+f5"],
"command": "cycle_setting",
"args": {
"setting": "default_line_ending",
"options": ["system", "windows", "unix"]
}
}
]
What our command is doing is cycling through the options array and saving the current one in the cycle to User/Preferences.sublime-settings.
I hope this helps someone else, I actually spend a while trying to find how to achieve this with many commands for external plugins and at this rate I was soon going to run out of key combinations, regards!

Related

Convert - -(double dash) to -> automatically in SublimeText 3

During my work I use -> many times and on a hungarian keyboard there is no dedicated > button, so I have to use 3 keys to enter this and sometimes I also misstype.
Is there a way to convert -- (double dash) automatically a ->? Snippet is not so good because it requires a TAB to convert.
Thanks
It's possible to do this with a simple key binding such as the following:
{
"keys": ["-", "-"],
"command": "insert", "args": {
"characters": "->"
},
},
Now when you type -- as soon as you hit the second - it triggers and replaces the text with -> like you want.
Note however that this would apply to every usage of the text -- in every file. This could be constrained to some degree by using a context in the key binding that makes it apply only in certain files, such as this one that ensures that the binding is only valid in plain text files:
{
"keys": ["-", "-"],
"command": "insert", "args": {
"characters": "->"
},
"context": [
{
"key": "selector",
"operator": "equal",
"operand": "text.plain",
"match_all": true
},
],
},
This can be applied to any scope you want; use Tools > Developer > Show Scope Name... from the menu while editing a file to determine the scope that you need (generally you probably want only the first scope item).
Either way, this makes it impossible to type -- directly without including a deliberate long pause between the two - characters or doing a backspace. That may or may not be an issue.

Sublime - Keyboard shortcut to go to first selection of 'Find in Files'

When I search in Sublime Text using 'Find in Files' for a keyword, I always have to use my mouse to click the selection I want to go to in that file. Is there any way I can use my keyboard to make the selection jump instead? Or if there's any plugins that do this?
By default you can navigate between all of the results of a find operation by using the menu items in Find > Find Results or their associated key bindings (visible in the menu). Doing that, the results go in order forward or backward, which may or may not be desirable if there are many results.
There aren't any navigation keys for jumping around inside the find in files output apart from the usual file navigation, but you can add such with a plugin:
import sublime
import sublime_plugin
class JumpToFindMatchCommand(sublime_plugin.TextCommand):
"""
In a find in files result, skip the cursor to the next or previous find
match, based on the location of the first cursor in the view.
"""
def run(self, edit, forward=True):
# Find the location of all matches and specify the one to navigate to
# if there aren't any in the location of travel.
matches = self.view.find_by_selector("constant.numeric.line-number.match")
fallback = matches[0] if forward else matches[-1]
# Get the position of the first caret.
cur = self.view.sel()[0].begin()
# Navigate the found locations and focus the first one that comes
# before or after the cursor location, if any.
pick = lambda p: (cur < p.begin()) if forward else (cur > p.begin())
for pos in matches if forward else reversed(matches):
if pick(pos):
return self.focus(pos)
# not found; Focus the fallback location.
self.focus(fallback)
def focus(self, location):
# Focus the found location in the window
self.view.show(location, True)
# Set the cursor to that location.
self.view.sel().clear()
self.view.sel().add(location.begin())
This implements a new command jump_to_find_match that takes an optional argument of forward to determine if the jump should be forward or backward, and will focus the view on the next or previous find result based on the cursor location of the first cursor in the file, wrapping as needed.
In combination with this plugin, key bindings such as the following can be set up to use the command. Here we're using the Tab and Shift+Tab keys; the context in each ensures that the binding is only active while in find results.
{
"keys": ["tab"],
"command": "jump_to_find_match",
"args": {
"forward": true
},
"context": [
{ "key": "selector", "operator": "equal", "operand": "text.find-in-files", "match_all": true },
],
},
{
"keys": ["shift+tab"],
"command": "jump_to_find_match",
"args": {
"forward": false
},
"context": [
{ "key": "selector", "operator": "equal", "operand": "text.find-in-files", "match_all": true },
],
},
That will allow you to navigate between the matches in the find panel, but you would still have to use the mouse in order to actually jump to the match location in the related file.
To do that by keyboard, you can use this plugin, which implements a command that simulates a double click at the location of the cursor. A key binding such as the following triggers the command in response to the Enter key, as long as the cursor is on a find match:
{
"keys": ["enter"],
"command": "double_click_at_caret",
"context": [
{ "key": "selector", "operator": "equal", "operand": "text.find-in-files", "match_all": true },
],
},
F4 is the answer you are looking for. Shift+F4 searches backwards. Corresponding next_result and prev_result are part of default keybinding.
{ "keys": ["f4"], "command": "next_result" },
{ "keys": ["shift+f4"], "command": "prev_result" },
Try to use the Use buffer button to open the results in a new tab.

Emmet plugin's expansion doesn't work for Sublime Text 3

I successfully installed Emmet via Package Control.
When I type ul and press Tab, I get <ul></ul>.
When I type ul.class and press Tab, I get ul.body_class but I want it to generate <ul class="class"></ul>.
What am I doing wrong?
I have read posts saying to try Ctl+E instead of Tab as the trigger key, but that doesn't do anything.
Try using Ctrl+Space instead. If that doesn't work, you can try changing the keybinding by putting the following in your User key bindings file which can be found by doing Preferences -> Key Bindings — User:
[
{"keys": ["tab"], "args": {"action": "expand_abbreviation"}, "command": "run_emmet_action", "context": [{"key": "emmet_action_enabled.expand_abbreviation"}]}
]
and then just change "tab" to whatever keybinding you want. Check to see if that works.
After reading your question, I installed Emmet in the Windows version of Sublime Text 3 today and had the same problem. Within my search for the solution, I found the following:
http://docs.emmet.io/actions/expand-abbreviation/#comment-1272517661
In Windows I opened the Default Emmet Preferences. By going to:
Preferences > Package Settings > Emmet > Setting - Default
and
Preferences > Package Settings > Emmet > Key Bindings - Default
As I was closing the settings files, I was prompted to save the setting files. I clicked OK to save and then restarted Sublime Text 3.
After Sublime Text 3 reloaded:
I created a new html file and was able to type ul.class, tabbed and it expanded to <ul class></ul>
It was funny, I never ran into that problem with Sublime on my Mac. If you had to do the same process on Mac, you go to Preferences > Package Settings > Emmet ...
I was facing same issue. Just pasted the below code in "Preferences -> Key Bindings — User:".
{
"keys": ["tab"],
"command": "expand_abbreviation_by_tab",
// put comma-separated syntax selectors for which
// you want to expandEmmet abbreviations into "operand" key
// instead of SCOPE_SELECTOR.
// Examples: source.js, text.html - source
"context": [
{
"operand": "SCOPE_SELECTOR",
"operator": "equal",
"match_all": true,
"key": "selector"
},
// run only if there's no selected text
{
"match_all": true,
"key": "selection_empty"
},
// don't work if there are active tabstops
{
"operator": "equal",
"operand": false,
"match_all": true,
"key": "has_next_field"
},
// don't work if completion popup is visible and you
// want to insert completion with Tab. If you want to
// expand Emmet with Tab even if popup is visible --
// remove this section
{
"operand": false,
"operator": "equal",
"match_all": true,
"key": "auto_complete_visible"
},
{
"match_all": true,
"key": "is_abbreviation"
}
]
}
Github: See for more description
I check the emmet default key is ctrl+e, so I add this to my Key Bindings - User:
{"keys": ["tab"], "args": {"action": "expand_abbreviation"}, "command": "run_emmet_action", "context": [{"key": "emmet_action_enabled.expand_abbreviation"}]}
I will have shared this as a comment directly where I feel like but 50 reps was required. Any ways. Here is what I did that made mine work for me.
From #saadq's answer, do this:
[
//other user key bindings should be here, followed by
{"keys": ["tab"], "args": {"action": "expand_abbreviation"}, "command": "run_emmet_action", "context": [{"key": "emmet_action_enabled.expand_abbreviation"}]}
]
The point is to have other bindings appear before it so that whatever binding overwriting it will be overwritten again.

How to switch to command mode after press "Save" hotkey in Sublime Text 3?

SUBJ.
I recently switched to Sublime from vim and trying to configure Sublime Text 3 in the way which I used to.
If I add binding, like below:
{ "keys": ["super+s"], "command": "exit_insert_mode", "context":
[
{ "key": "setting.command_mode", "operand": false },
{ "key": "setting.is_widget", "operand": false }
]
}
it switches mode to command, but do not save changes.
What you have specified overrides the existing save key binding, so it is behaving as expected. You will need to use a plugin or a macro to get the behavior you want. A macro would require you to save an additional file, so that's up to you. For a plugin solution, you should be able to use https://github.com/skuroda/ImprovedMacros to get the behavior you want. Replaying commands is based on some work I found on the ST forums. Never got around to finding a good way to record actions better though. That aside, there are install instructions in the README. I believe the following will work as your key binding with the plugin installed
{
"keys": ["super+s"], "command": "run_multiple_commands",
"args": {
"commands": [{
"context": "view",
"command": "save"
},{
"context": "view",
"command": "exit_insert_mode"
}]
},
"context": [
{ "key": "setting.command_mode", "operand": false },
{ "key": "setting.is_widget", "operand": false }
]
}

Sublime Text 2 config - Let space save the file

Sublime Text 2 already supports normal Vim bindings. However, I'd like to have it support saving the current file when pressing space in command mode.
This key binding has become one of my number one features I love about vim.
However, when trying to write this key binding, Sublime Text 2 seems to ignore it:
{ "keys": ["space"], "command": "save",
"context":
[
{ "key": "setting.command_mode", "operand": true }
]
}
Sublime Text 2 seems to not recognize "space".
It much rather has to be like this:
{ "keys": [" "], "command": "save",
"context":
[
{ "key": "setting.command_mode" }
]
}

Resources