WrapCommand
A Command Wrapper providing an unified and easy to use interface regarding variable expansion.
Details
Installs
- Total 780
- Win 433
- Mac 228
- Linux 119
| Nov 29 | Nov 28 | Nov 27 | Nov 26 | Nov 25 | Nov 24 | Nov 23 | Nov 22 | Nov 21 | Nov 20 | Nov 19 | Nov 18 | Nov 17 | Nov 16 | Nov 15 | Nov 14 | Nov 13 | Nov 12 | Nov 11 | Nov 10 | Nov 9 | Nov 8 | Nov 7 | Nov 6 | Nov 5 | Nov 4 | Nov 3 | Nov 2 | Nov 1 | Oct 31 | Oct 30 | Oct 29 | Oct 28 | Oct 27 | Oct 26 | Oct 25 | Oct 24 | Oct 23 | Oct 22 | Oct 21 | Oct 20 | Oct 19 | Oct 18 | Oct 17 | Oct 16 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Windows | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| Mac | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
| Linux | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Readme
- Source
- bitbucket.org
Wrap Command
A Command Wrapper for providing an unified easy to use and powerful interface for Sublime Text 2 and Sublime Text 3 commands.
Example:
{
"command": "wrap_command",
"args": {
"command": "open_file":
"args": {"file": "${input:File to open}"}
}
}
This will prompt user for input and then runs command open_file.
Motivation
While trying to setup build systems and configuring packages, I noticed that there are more or less powerful opportunities to specify arguments, depending on the package.
For example, I tried to setup a build system for a django app collection, where the build system runs the test:
manage.py test <APPLICATION NAME>
But this was only partly possible:
{
"selector": "source.python",
"cmd": ["python", "manage.py", "test", "${file_path/.*[\\/\\\\]//}" ],
"file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
"working_dir": "${project_path:}/webapps"
}
Problem is that this works only for files at application's root folder.
Solution
I created a new package WrapCommand providing command wrap_command. Problem above would be solved like this:
{
"selector": "source.python",
// we wrap the default "exec" target with with "wrap_command"
"target": "wrap_command",
"wrap_command": "exec",
// make sure we have wanted evaluation order
"order": ["f", "django_site", "django_app"],
// get normed filename
"f": "${n:$file_path}",
// get normed django-site (folder where manage..py is located)
"django_site": "${n:${d:${back:$f;manage.py}}}",
// extract django app name from filename
"django_app": "${s:${django_site}/([^/]+).*;$1;$f}",
"args": {
"cmd": ["python", "manage.py", "test", "${django_app}"]
"working_dir": "${django_site}",
}
"file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)"
"name": "Run"
}
I have to admit that it does not look nice, but it does the job. You will find output on console useful, while setting up such patterns.
I mostly do not use Build Systems, but rather commands in SublimeREPL, for easy debugging:
{
"command": "wrap_command",
"caption": ":django manage test",
"args": {
"wrap_command": "repl_open",
"order": ["f", "django_site", "django_app"],
"f": "${n:$file_path}",
"django_site": "${n:${d:${back:$f;manage.py}}}",
"django_app": "${s:${django_site}/([^/]+).*;$1;$f}",
"args": {
"type": "subprocess",
"encoding": "utf8",
"cmd": ["python", "-i", "-u", "manage.py", "test", "${django_app}"],
"cwd": "${django_site}",
"syntax": "Packages/Python/Python.tmLanguage",
"external_id": "python",
"extend_env": {"PYTHONIOENCODING": "utf-8"}
}
}
}
Settings
WrapCommand interpretes following settings:
| Name | Type | Default | Description |
|---|---|---|---|
| wrap_command_debug | boolean | false | toggle debug logging to console helpfull to trace expansions. |
Options
- select
Select an argument set:
{ "select": "${ext:$file_name}" "foo": { "wrap_command": "echo", ... } "bar": { "wrap_command": "echo", ... } }Please note, that first all arguments will be evaluated and only right before calling the command, the selection will be applied. You may override the wrap_command parameter in selected arguments.
Default is to select "args".
- wrap_command
- The command to run. This key may also be in arguments section. It will be removed from arguments passed to command to run.
- order
Variables specified in order are evaluated first, in given order.
You may specify the order of argument parsing (or only a part of it). This is useful, if you use named captures, you want to reuse later, or you use other argument's values. In following examples there is a platform independent path separator:
{ "order": ["sep"], // make sure $sep can be used in // other configs like args "sep": "(?:\\\\|/)", // file separator pattern "wrap_command": "exec" "args": { ... } }- args
- The wrapped command's arguments.
- *
- Any other argument may be used for either name an argument set, which can be selected by select or to predefine a value. Each argument will be available as variable after processing.
Argument Expansion
Variables
First there are supported build system variables as specified in documentation for buildsystems.
| $file_path | The directory of the current file, e. g., C:\Files. |
| $file | The full path to the current file, e. g., C:\Files\Chapter1.txt. |
| $file_name | The name portion of the current file, e. g., Chapter1.txt. |
| $file_extension | The extension portion of the current file, e. g., txt. |
| $file_base_name | The name only portion of the current file, e. g., Document. |
| $packages | The full path to the Packages folder. |
| $project | The full path to the current project file. |
| $project_path | The directory of the current project file. |
| $project_name | The name portion of the current project file. |
| $project_extension | The extension portion of the current project file. |
| $project_base_name | The name only portion of the current project file. |
Apart from these, there are following more variables available:
| $installed_packages | what sublime.installed_packages() returns |
| $settings_path | Directory of your Settings directory, where session files reside. |
| $session_file | Full path of session file. |
| $auto_session_file | Full path of auto session file. |
| $session | dictionary of data stored in session |
| $auto_session | dictionary of data stored in auto session |
| $settings | dictionary of settings |
| $project_buildsystems | list of buildsystems |
| $project_folders | list of project folders |
| $project_settings | dictionary of project settings. |
| $env | dictionary of environment |
You probably noticed that there are also complex types available. You can access them like you usually access such data:
$session[dictionary]
will provide the path to your dictionary file, like specified in your settings.
So you can access cmd of first buildsystem of your project:
$project_buildsystems[0][cmd]
All of these values you can also access in ${} notation, which is:
${project_buildsystems[0][cmd]}
If a variable does not exist, you can provide a default:
${project_buildsystems[0][cmd]:Default}
Shortcuts
There are some shortcuts for easier Access:
| $PB | $project_buildsystems |
| $PS | $project_settings |
| $PF | $project_folders |
| $S | $settings |
Anonymous Regex Captures
All variables $0, $1, $2, ..., $9 are automatically expanded to \\1, \\2, etc., for having more convenient capture parameters. So instead:
{ "foo": "${s:f(oo);\\\\1}" }
You can write:
{ "foo": "${s:f(oo);$1}" }
List Interpolation
In commands you often are more interested in a list of values than only at a single string:
{ "cmd": [ "echo", "${project_folders}" ] }
Will expand to:
{ "cmd": [ "echo", "folder1/foo;folder2/bar" ] }
This is maybe not what you want. Consider list interpolation sigil "@":
{ "cmd": [ "echo", "@{project_folders}" ] }
In context of a list, this will expand to:
{ "cmd": [ "echo", "folder1/foo", "folder2/bar" ]}
Functions
Apart from variables, you can also evaluate little functions on these Variables. There may be more useful functions, but these shall be enough for now.
- basename, base, b
Get the basename of a file. Please note that here the extension of the file is included:
${b:foo/bar.txt} -> bar.txt- Arguments:
- path of a file
- count
Count variables of a list or characters of a string:
${count:a;b;c} -> 3- Argunents:
- any
- dirname, dir, d
Get directory part of a filename:
${d:foo/bar.txt} -> foo- Arguments:
- path of a file
- escape, esc, e
Escape the given value (or values) for further processing. (";" and "" are escaped, such that you can use it further as arguments). This is useful for e.g. map function.
${e:foo;bar} -> foo;bar- Arguments:
- any
- Returns:
- string
- exists
Test if given file exists:
${exists:$packages/WrapCommand} -> true ${exists:does/not/exist} ->If something does not exist, an empty string is returned.
- Arguments:
- path of file
- extension, ext
Return file's extension:
${ext:foo/bar.txt} -> txt- Arguments:
- path of file
- filter
Filter some elements out of a list:
${filter:oo;foo;gloo;fue;glue} -> foo;gloo- Arguments:
- pattern
- list to filter
- find
Return a list of files whose path match a regular expression:
${find:$packages;\\.sublime-commands$} -> sublime command filesResulting list contains file paths relative to given root.
- Arguments:
- root where to start search
- pattern
- find_back, back
Return a list of files whose path match a regular expression. Difference to find is that the search is done backwards in path. It will be returned the first non-empty set of files in a parent directory.
Resulting list contains absolute path names.
- Arguments:
- root where to start
- pattern
- has
Check if a variable has an item:
${has:var[item]}Please note that ${has:$var[item]} is something different.
- Arguments:
- An itemgetter
- if
If the first arguments evaluates to a true (non-empty) value, the second argument is returned, else third argument is returned if given or "":
${if:condition;then;else} -> then ${if:;then;else} -> else- Arguments:
- Condition
- result for non-empty condition
- result for empty condition
- input, in
Get some user input:
${in:User Prompt} -> Open a user input ${in:User Prompt;default} -> Open a user input- Arguments:
- caption of input
- default value (optional)
It is not possible to use ${in:foo} in a nested way:
${exists:${input:Filename}} THIS DOES NOT WORK AS EXPECTED, result will be the user's input- join
Join all parts of list using the first parameter as joining string:
${join: ;first;second;third} -> first second third- Arguments:
- Joining string
- any other args
- length, len
Return length of string:
${length:foo} -> 3- Arguments:
- a string
- list
Create a list:
${list:first;second;third} -> Explicitely create a list- Arguments:
- list items
- map
Map a function to multiple values:
${map:${e:s:/$;;$_};first/;second;third/}This example will remove trailing slashes, if present. Please note that the first parameter will be evaluated by map for each following parameter, replacing $_ with parameter's value.
The escape function must be used, to have a nice way of writing this, otherwise you had to escape all ";" and "$".
The upper command is actually the same like:
${list:${s:/$;;first/};${s:/$;;second};${s:/$;;third/}}If your mapping function only takes one parameter, you can omit the escaping:
${map:abspath;$_;first;second;third}- Arguments:
- map function without "${}" around
- list to map
- match, m
Match a string. If match contains named captures, variable dictionary is updated with these captures for later use:
${m:f(?P<o>oo);foobar} -> foo ${m:f(?P<o>oo);foobar}$o -> fooooReturns the matched string.
- Arguments:
- pattern
- string to match
- normpath, norm, n
Normalize a path:
${norm:foo//bar} -> foo/bar- Arguments:
- pattern
- select, select
Open a Quick Panel for a user selection:
${sel:first;second;third} -> Open a panel and user can select between first, second, third ${sel:first\nmore info;second\n;third\nalso more info} -> Open a panel and user can select between first, second, third with displayed more info- Arguments:
- values displayed in quick panel
It is not possible to use ${sel:foo} in a nested way:
${exists:${sel:Filename}} THIS DOES NOT WORK AS EXPECTED, result will be the user's inputHere the recommended usage for opening either "foo.txt" or "bar.txt":
{ "command": "wrap_command", "args": { "command": "open_file", "args": {"file": "${sel:foo.txt;bar.txt}"} } }If you have to manipulate result you got from user:
{ "command": "wrap_command", "args": { "command": "open_file", "filename": "${sel:foo.txt;bar.txt}", "args": {"file": "${s:\\.txt;\\.cpp;${filename}}"} } }- subst, s
Substitute matched patterns with value:
${s:foo;bar;foobar} -> barbar ${s:f(oo);bar\1;foobar} -> baroobar ${s:f(oo);bar$1;foobar} -> baroobarPlease note that in JSON context, you have to escape "\":
{ foo: "${s:f(oo);bar\\1;foobar}" }- Arguments:
- pattern
- replacement
- string to process
Adding a custom function
In sublime text 2 context, this is pretty easy:
import expander @expander.modifier('my', 'funcs', 'names') def _myfunc(*args): return args
Changes
Added functions for collecting user input.