Sublime Text 3 Key Binding - Using variables - keyboard-shortcuts

I'm trying to make a key binding to open up my favorite git application with current Sublime Text 3 $project_path folder, but somehow Sublime Text 3 doesn't convert the variables into the actual path.
Below you can find my current keyboard bindings file.
[
{
"keys": ["super+ctrl+alt+g"],
"command": "exec",
"args":
{
"shell_cmd": "open -a Gitbox $project_path"
}
}
]
$project_path doesn't convert into the actual project path... What am I doing wrong? Should I use a "Build System" instead? I looked into build systems but the problem there is that you would have to select a scope of files (for example *.rb) and I want this keyboard shortcut to be valid for all my projects/files.
In textmate2 the same shortcut was easily achieved by creating a new "Command" in the Bundle Editor and assigning a shortcut to it. The command then would be:
#!/usr/bin/ruby
exec "open -a Gitbox '#{ENV['TM_PROJECT_DIRECTORY']}'"
So I'm trying to achieve this same thing in Sublime Text 3 but something is going wrong.
Thanks!

Edit:
In the meantime I've built a generic plugin which gives you the ability to open any external application with an key stroke or via the command palette.
The plugin can be found here: ExternalTools
You can easily install it via the command palette cmd+shift+p
In your case you can go to Preferences / Key Bindings and add the following:
{
"keys": ["super+ctrl+alt+g"],
"command": "external_tools_run",
"args": { "cmd": ["open", "-a", "Gitbox", "$project_path"] }
}
I still down't own a mac so there is a chance that it is not working properly. In this case I would be pleased if you can give me a feedback (see Issues).
Original Answer:
I have spend a few hours searching on the same problem. After all I decided to create a small plugin with my own place holders.
import sublime, sublime_plugin
class RunAppCommand(sublime_plugin.WindowCommand):
def run(self, app_args):
app_args = self.fill_placeholder(app_args)
self.window.run_command("exec", {"cmd": app_args } )
def fill_placeholder(self, args):
res = []
proj_folder = self.get_project_folder()
for arg in args:
arg = arg.replace("$PROJECT_FOLDER", proj_folder)
res.append(arg)
return res
def get_project_folder(self,default=None):
proj_folder = ""
if self.window.project_file_name():
proj = self.window.project_data()
proj_folder_obj = self.get_first(proj["folders"])
if proj_folder_obj:
proj_folder = proj_folder_obj["path"]
elif self.window.folders():
proj_folder = self.get_first(self.window.folders())
if not proj_folder:
sublime.status_message("No project folder located")
return default
return proj_folder
def get_first(self, iterable, default=None):
if iterable:
for item in iterable:
return item
return default
After you have saved the code above to Packages/User/RunApp.py you can make your command work just by adding the following to your Default.sublime-keymap:
{ "keys": ["super+ctrl+alt+g"], "command": "run_app", "args": { "app_args": ["open", "-a", "Gitbox", "$PROJECT_FOLDER"]}}
This may be not the best solution but it works for me.

Also spent some hours searching here - thanks to fboers example i could finally
create a plugin myself.
So here's my solution: exec2 - expands all the sublime-variables as it should be and then forwards it to exec.
Save this as Packages/Exec2/Exec2.py.
import sublime
import sublime_plugin
class Exec2Command(sublime_plugin.WindowCommand):
def run(self, cmd):
new_cmd = [sublime.expand_variables (value, self.window.extract_variables()) for value in cmd]
self.window.run_command("exec", {"cmd": new_cmd } )
Example for the keybinding:
{ "keys": ["ctrl+F7"], "command": "exec2", "args" : { "cmd": ["V:/v4_tools/v4Doccer.exe", "--mdi", "${file}"]} },

Related

In Scrapy, download files nested below the to of a yielded item dict

To download files in Scrapy, one adds the key 'fileurls' to the yielded item dict with a value of the urls to download. But my files are nested somewhere below the top level of the yielded dict. An item looks like this:
{
"title": "foo",
"files": {
"drawings": [
{
"caption": "bar",
"fileurl": "http://foo.com/foo/foo.pdf"
},
{
"caption": "second floor",
"fileurl": "http://foo.com/foo/bar.pdf"
}
],
"photos": [
{
"caption": "bar",
"fileurl": "http://foo.com/foo/baz.pdf"
}
]
}
}
Ideally, I'd like each file downloaded and have scrapy add its "file" element next to the "fileurl". But this does not seem to work automatically.
How can I achieve this? The current version of Scrapy is 1.6.0.
To do something like this, you will need to make your own subclass of scrapy's FilesPipeline.
To make the downloading happen, you'll need a custom get_media_requests method, which should get the URLs from your item and return an iterable of requests which will be used to download the files.
After that, you'll also need to modify the item_completed and/or the file_downloaded method to store the result in the exact way you want.
If you need more details than what's provided in the docs, take a look at the source and see how the existing pipeline works.

In Visual Studio Code is there a way to scope settings and keybindings to a language mode?

In VS Code, I am aware that you can create files containing global user keybindings and settings, and you can have workspace-specific files for keybindings and settings, but is it possible to define settings or keybindings specific to a language mode?
For instance, I want Alt + / to mean FSI: Send Line when I'm in F# mode, but not when I'm in markdown mode or JS mode.
And I want my tabs to be 2 spaces when I'm in Elm mode, but 4 spaces in C# mode.
I know you can define keybindings with a when clause like so:
{
"key": "alt+/",
"command": "fsi.SendLine",
"when": "resourceLangId == fsharp"
}
Is this the only way to achieve something like what I'm after?
It seems like it would make sense to be able to define settings/keybindings for mode X in their own files somewhere. I don't like having language mode behaviour scattered about in big global files like this.
To customize VS Code settings and keybindings based on the programming language, you can use language identifier, file extension or extension identifier.
For settings you can use language entry (in settings.json):
"[fsharp]": {
"editor.suggest.insertMode": "replace"
}
For keybindings you can use the following when clause contexts (in keybindings.json):
editorLangId True when the editor's associated language Id matches.
{
"key": "ctrl+e",
"command": "workbench.action.files.saveAs",
"when": "editorLangId == fsharp"
}
resourceLangId True when the Explorer or editor title language Id matches.
{
"key": "ctrl+e",
"command": "workbench.action.files.saveAs",
"when": "resourceLangId == fsharp"
}
resourceExtname True when the Explorer or editor filename extension matches.
{
"key": "ctrl+e",
"command": "workbench.action.files.saveAs",
"when": "resourceExtname == .fs"
}
extension True when the extension's ID matches.
{
"key": "ctrl+e",
"command": "workbench.action.files.saveAs",
"when": "extension == ionide.ionide-fsharp"
}
note:
I did not test all of these clauses, but editorLangId and resourceExtname work for me fine.
Visual Studio Code have stated that at this time (2016-10-19), language mode settings are not supported, but are being considered. (https://twitter.com/code/status/788301380557561857)
There are a couple of issues on the VS Code Github repository requesting variants of this feature.
https://github.com/Microsoft/vscode/issues/13532
https://github.com/Microsoft/vscode/issues/1073

Shortcut key to show unsaved changes in Sublime Text 3

How can I set the shortcut key for right key -> show unsaved changes in Sublime Text 3?
I have tried
{ "keys": ["alt+f10"], "command": "show_unsaved_change" },
but it does not work.
You have the wrong command name, the correct command name is diff_changes:
{ "keys": ["ctrl+alt+d"], "command": "diff_changes" }

How to move the cursor to the end of the tag in Sublime Text 2?

When I type the start of a tag, Sublime Text will auto-complete the end of the tag and position the cursor inside the tag.
<code>|</code>
I use | to represent the cursor. So when I finished the contents inside the tag, I want to move the cursor to the end of the tag like this:
<code>blabla</code>|
To do this, now I have to press Right button to move the cursor character by character, which is not efficient. Is there any shortcut to move the cursor to the end of the tag directly?
You could also create a macro. This may be valuable if your tags cover multiple lines. Save the following as something like move_to_end_tag.sublime-macro in Packages/User.
[
{
"args":
{
"to": "tag"
},
"command": "expand_selection"
},
{
"args":
{
"by": "characters",
"forward": true
},
"command": "move"
}
]
You can then create a keybinding for the action.
{
"keys": ["ctrl+shift+alt+right"],
"command": "run_macro_file",
"args": {"file": "res://Packages/User/move_to_end_tag.sublime-macro"}
}
Of course, you can change the keys to whatever you like.
I'm working in Sublime Text 3 rather than 2, but the End button (for me, between the delete and page down) does the trick for me.
I found that annoying as well. Personally, taking the End key binding and applying it to Shift+Space works well enough for my purposes.
If that's easier for you, you can add this line to your user key bindings:
{ "keys": ["shift+space"], "command": "move_to", "args": {"to": "eol", "extend": false} }
Using a macro as skuroda suggested is a good option as well since you end up with more control of the cursor placement.
For curly braces and parentheses you can use Control + M.
Not sure about angle brackets in markup though.

Sublime 3 - Set Key map for function Goto Definition

I want to create an Eclipse style shortcut Ctrl+MouseClick to open the function/method. Sublime Text 3 has already this function called goto_definition but it is bound to F12.
But I'm not sure how to create this binding. I looked here for documentation but it was too complex. Can you one help me out with this simple key binding?
Edit: Following this article I was told to do this: http://webtempest.com/better-definition-navigation-in-sublime-text-3/
[
{
"button": "button1",
"count": 1,
"modifiers": ["super", "shift"],
"press_command": "drag_select",
"command": "goto_definition"
}
]
This doesn't seem to work, ctrl+shift+click executes nothing.
For anyone else who wants to set Eclipse style goto definition, you need to create .sublime-mousemap file in Sublime User folder.
Windows - create Default (Windows).sublime-mousemap in %appdata%\Sublime Text 3\Packages\User
Linux - create Default (Linux).sublime-mousemap in ~/.config/sublime-text-3/Packages/User
Mac - create Default (OSX).sublime-mousemap in ~/Library/Application Support/Sublime Text 3/Packages/User
Now open that file and put the following configuration inside
[
{
"button": "button1",
"count": 1,
"modifiers": ["ctrl"],
"press_command": "drag_select",
"command": "goto_definition"
}
]
You can change modifiers key as you like.
Since Ctrl-button1 on Windows and Linux is used for multiple selections, adding a second modifier key like Alt might be a good idea if you want to use both features:
[
{
"button": "button1",
"count": 1,
"modifiers": ["ctrl", "alt"],
"press_command": "drag_select",
"command": "goto_definition"
}
]
Alternatively, you could use the right mouse button (button2) with Ctrl alone, and not interfere with any built-in functions.
To set go to definition to alt + d. From the Menu Preferences > Key Bindings-User. And then add the following JSON.
[
{ "keys": ["alt+d"], "command": "goto_definition" }
]
If you want to see how to do a proper definition go into Sublime Text->Preferences->Key Bindings - Default and search for the command you want to override.
{ "keys": ["f12"], "command": "goto_definition" },
{ "keys": ["super+alt+down"], "command": "goto_definition" }
Those are two that show in my Default.
On Mac I copied the second to override.
in Sublime Text -> Preferences -> Key Bindings - User I added this
/* Beginning of File */
[
{
"keys": ["super+shift+i"], "command": "goto_definition"
}
]
/* End of File */
This binds it to the Command + Shift + 1 combination on mac.
On a mac you have to set keybinding yourself. Simply go to
Sublime --> Preference --> Key Binding - User
and input the following:
{ "keys": ["shift+command+m"], "command": "goto_definition" }
This will enable keybinding of Shift + Command + M to enable goto definition. You can set the keybinding to anything you would like of course.
ctrl != super on windows and linux machines.
If the F12 version of "Goto Definition" produces results of several files, the "ctrl + shift + click" version might not work well. I found that bug when viewing golang project with GoSublime package.
I'm using Sublime portable version (for Windows) and this (placing the mousemap in SublimeText\Packages\User folder) did not work for me.
I had to place the mousemap file in SublimeText\Data\Packages\User folder to get it to work where SublimeText is the installation directory for my portable version. Data\Packages\User is where I found the keymap file as well.
One should not just configure the goto_definition shortcut -- you would also need a shortcut to go back(and forth) after you jump to the definition.
Hence, consider configuring all three shortcuts: goto_definition, jump_back, and jump_forward as follows in your Key Bindings config file :
// go to the definition
{ "keys": ["ctrl+i"], "command": "goto_definition" },
// go back to the previous location
{ "keys": ["ctrl+h"], "command": "jump_back" },
// go to the next location
{ "keys": ["ctrl+l"], "command": "jump_forward" },
I find these three commands especially useful while trying to read code quickly.