feat(SublimeText2.EditorPackages): cache packages
3
EthanBrown.SublimeText2.EditorPackages/tools/PackageCache/BracketHighlighter/.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
*.pyc
|
||||
|
||||
.DS_Store
|
@@ -0,0 +1,68 @@
|
||||
# Version 1.9.0
|
||||
- Add experimental CFML support (defaulted off)
|
||||
- Add auto-detection of self-closing tags (defaulted on)
|
||||
|
||||
# Version 1.8.0
|
||||
- Add new commands: "Show Bracket String Escape Mode" and "Toggle Bracket String Escape Mode". Default is "regex"
|
||||
|
||||
# Version 1.7.2
|
||||
- Feed general bracket type to bracket plugins
|
||||
- Adjust bracket select plugin to better handle HTML tags
|
||||
|
||||
# Version 1.7.1
|
||||
- Reorganize some settings
|
||||
- Limit auto-highlight selections by configurable threshold setting
|
||||
|
||||
# Version 1.7.0
|
||||
- Hide parent quote highlighting when child quotes are highlighted
|
||||
- Allow the searching for brackets in non-quoted code scoped as strings (like regex)
|
||||
- Add setting "highlight_string_brackets_only" which allows never highlighting quotes but leaves internal string bracket highlighting on
|
||||
- deprecate "enable_forward_slash_regex_strings" in favor of "find_brackets_in any_strings"
|
||||
|
||||
# Version 1.6.2
|
||||
- Fix adjacent_only with multi_select
|
||||
|
||||
# Version 1.6.1
|
||||
- Suppress string highlighting when adjacent_only is set, but allow internal string brackets to still get highlighted with adjacent_only settings if match_string_brackets is true
|
||||
|
||||
# Version 1.6.0
|
||||
- Add setting to match only when cursor is between brackets
|
||||
|
||||
# Version 1.5.3
|
||||
- Allow turning off gutter icons for multi-select via settings
|
||||
- Fix multi-select detection
|
||||
- Default the internal settings if setting is not found
|
||||
|
||||
# Version 1.5.2
|
||||
- Use tiny icons when line height is less than 16
|
||||
- Use no icon if icon cannot be found
|
||||
- Optimize png icons
|
||||
|
||||
# Version 1.5.1
|
||||
- Ignore selection/edit events inside the main routine
|
||||
|
||||
# Version 1.5.0
|
||||
- More responsive highlighting (thanks tito); delay setting no longer needed
|
||||
- Organize bracket plugins
|
||||
- Included more configurable custom gutter icons
|
||||
|
||||
# Version 1.4.1
|
||||
- Make adjusment to regex modifier code to correctly count back modifiers in perl
|
||||
|
||||
# Version 1.4.0
|
||||
- Account for perl regex, substitutions, and translations surrounded by "/" for string bracket matching
|
||||
- Account for regex modifiers when matching regex surrounded by "/" in javascript and perl
|
||||
|
||||
# Version 1.3.0
|
||||
- Fixed escaped brackets in string handling. Also a bit more efficient.
|
||||
|
||||
# Version 1.2.0
|
||||
- Fix angle bracket avoidance when finding brackets inside strings, and make it cleaner
|
||||
|
||||
# Version 1.1.0
|
||||
- Add python raw string support for quote highlighting
|
||||
- Add highlighting of brackets in strings; will work in all strings, but mainly meant for regex. True by default
|
||||
- Add support for targetting regex strings like in javascript that are scoped as strings, but are not quoted, but use '/'s. True by default
|
||||
|
||||
# Version 1.0.0
|
||||
- All previous work and releases
|
@@ -0,0 +1,152 @@
|
||||
[
|
||||
// Toggle Global Enable
|
||||
{
|
||||
"caption": "BracketHighlighter: Toggle Global Enable",
|
||||
"command": "bh_toggle_enable"
|
||||
},
|
||||
// Search to end of file for bracket
|
||||
{
|
||||
"caption": "BracketHighlighter: Match Brackets (ignore threshold)",
|
||||
"command": "bh_key",
|
||||
"args": {"lines" : true}
|
||||
},
|
||||
// Remove brackets
|
||||
{
|
||||
"caption": "BracketHighlighter: Remove Brackets",
|
||||
"command": "bh_remove_brackets"
|
||||
},
|
||||
// Go to left bracket
|
||||
{
|
||||
"caption": "BracketHighlighter: Jump to Left Bracket",
|
||||
"command": "bh_key",
|
||||
"args":
|
||||
{
|
||||
"lines" : true,
|
||||
"plugin":
|
||||
{
|
||||
"type": ["__all__"],
|
||||
"command": "bh_modules.bracketselect",
|
||||
"args": {"select": "left"}
|
||||
}
|
||||
}
|
||||
},
|
||||
// Go to right bracket
|
||||
{
|
||||
"caption": "BracketHighlighter: Jump to Right Bracket",
|
||||
"command": "bh_key",
|
||||
"args":
|
||||
{
|
||||
"lines" : true,
|
||||
"plugin":
|
||||
{
|
||||
"type": ["__all__"],
|
||||
"command": "bh_modules.bracketselect",
|
||||
"args": {"select": "right"}
|
||||
}
|
||||
}
|
||||
},
|
||||
// Select text between brackets
|
||||
{
|
||||
"caption": "BracketHighlighter: Select Bracket Content",
|
||||
"command": "bh_key",
|
||||
"args":
|
||||
{
|
||||
"lines" : true,
|
||||
"plugin":
|
||||
{
|
||||
"type": ["__all__"],
|
||||
"command": "bh_modules.bracketselect"
|
||||
}
|
||||
}
|
||||
},
|
||||
// Fold contents between brackets
|
||||
{
|
||||
"caption": "BracketHighlighter: Fold Bracket Content",
|
||||
"command": "bh_key",
|
||||
"args":
|
||||
{
|
||||
"plugin": {
|
||||
"type": ["__all__"],
|
||||
"command" : "bh_modules.foldbracket"
|
||||
}
|
||||
}
|
||||
},
|
||||
{ "caption": "-" },
|
||||
// Toggle between string and regex escape mode for string brackets
|
||||
{
|
||||
"caption": "BracketHighlighter: Toggle String Bracket Escape Mode",
|
||||
"command": "bh_toggle_string_escape_mode"
|
||||
},
|
||||
// Toggle high visibility mode
|
||||
{
|
||||
"caption": "BracketHighlighter: Toggle High Visibility Mode",
|
||||
"command": "bh_toggle_high_visibility"
|
||||
},
|
||||
{ "caption": "-" },
|
||||
// Select tag name of HTML/XML tag (both opening name and closing)
|
||||
{
|
||||
"caption": "BracketHighlighter: Select Tag Name (closing and opening)",
|
||||
"command": "bh_key",
|
||||
"args":
|
||||
{
|
||||
"plugin":
|
||||
{
|
||||
"type": ["cfml", "html", "angle"],
|
||||
"command": "bh_modules.tagnameselect"
|
||||
}
|
||||
}
|
||||
},
|
||||
// Select the attribute to the right of the cursor (will wrap inside the tag)
|
||||
{
|
||||
"caption": "BracketHighlighter: Select Next Attribute (right)",
|
||||
"command": "bh_key",
|
||||
"args":
|
||||
{
|
||||
"plugin":
|
||||
{
|
||||
"type": ["cfml", "html", "angle"],
|
||||
"command": "bh_modules.tagattrselect",
|
||||
"args": {"direction": "right"}
|
||||
}
|
||||
}
|
||||
},
|
||||
// Select the attribute to the left of the cursor (will wrap inside the tag)
|
||||
{
|
||||
"caption": "BracketHighlighter: Select Next Attribute (left)",
|
||||
"command": "bh_key",
|
||||
"args":
|
||||
{
|
||||
"plugin":
|
||||
{
|
||||
"type": ["cfml", "html", "angle"],
|
||||
"command": "bh_modules.tagattrselect",
|
||||
"args": {"direction": "left"}
|
||||
}
|
||||
}
|
||||
},
|
||||
// Convert single quote string to double quoted string and vice versa
|
||||
// Will handle escaping or unescaping quotes within the string
|
||||
{
|
||||
"caption": "BracketHighlighter: Swap Quotes",
|
||||
"command": "bh_key",
|
||||
"args":
|
||||
{
|
||||
"lines" : true,
|
||||
"plugin":
|
||||
{
|
||||
"type": ["single_quote", "double_quote", "py_single_quote", "py_double_quote"],
|
||||
"command": "bh_modules.swapquotes"
|
||||
}
|
||||
}
|
||||
},
|
||||
// Swap Brackets
|
||||
{
|
||||
"caption": "BracketHighlighter: Swap Brackets",
|
||||
"command": "swap_brackets"
|
||||
},
|
||||
// Surround selection with brackets from quick panel
|
||||
{
|
||||
"caption": "BracketHighlighter: Wrap Selections with Brackets",
|
||||
"command": "wrap_brackets"
|
||||
}
|
||||
]
|
@@ -0,0 +1,16 @@
|
||||
[
|
||||
// Navigate tabstops in wrapped selection
|
||||
{
|
||||
"keys": ["tab"],
|
||||
"command": "bh_next_wrap_sel",
|
||||
"context":
|
||||
[
|
||||
{
|
||||
"operand": true,
|
||||
"operator": "equal",
|
||||
"match_all": true,
|
||||
"key": "bh_wrapping"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
@@ -0,0 +1,153 @@
|
||||
[
|
||||
// Toggle Global Enable
|
||||
{
|
||||
"keys": ["ctrl+alt+super+e"],
|
||||
"command": "bh_toggle_enable"
|
||||
},
|
||||
// Search to end of file for bracket
|
||||
{
|
||||
"keys": ["ctrl+alt+super+b"],
|
||||
"command": "bh_key",
|
||||
"args":
|
||||
{
|
||||
"lines" : true
|
||||
}
|
||||
},
|
||||
// Go to left bracket
|
||||
{
|
||||
"keys": ["ctrl+alt+super+up"],
|
||||
"command": "bh_key",
|
||||
"args":
|
||||
{
|
||||
"lines" : true,
|
||||
"plugin":
|
||||
{
|
||||
"type": ["__all__"],
|
||||
"command": "bh_modules.bracketselect",
|
||||
"args": {"select": "left"}
|
||||
}
|
||||
}
|
||||
},
|
||||
// Go to right bracket
|
||||
{
|
||||
"keys": ["ctrl+alt+super+down"],
|
||||
"command": "bh_key",
|
||||
"args":
|
||||
{
|
||||
"lines" : true,
|
||||
"plugin":
|
||||
{
|
||||
"type": ["__all__"],
|
||||
"command": "bh_modules.bracketselect",
|
||||
"args": {"select": "right"}
|
||||
}
|
||||
}
|
||||
},
|
||||
// Remove brackets
|
||||
{
|
||||
"keys": ["ctrl+alt+super+r"],
|
||||
"command": "bh_remove_brackets"
|
||||
},
|
||||
// Toggle string escape mode for sub bracket search in strings
|
||||
{
|
||||
"keys": ["ctrl+alt+super+x"],
|
||||
"command": "bh_toggle_string_escape_mode"
|
||||
},
|
||||
// Select text between brackets
|
||||
{
|
||||
"keys": ["ctrl+alt+super+s"],
|
||||
"command": "bh_key",
|
||||
"args":
|
||||
{
|
||||
"lines" : true,
|
||||
"plugin":
|
||||
{
|
||||
"type": ["__all__"],
|
||||
"command": "bh_modules.bracketselect"
|
||||
}
|
||||
}
|
||||
},
|
||||
// Select tag name of HTML/XML tag (both opening name and closing)
|
||||
{
|
||||
"keys": ["ctrl+alt+super+t"],
|
||||
"command": "bh_key",
|
||||
"args":
|
||||
{
|
||||
"plugin":
|
||||
{
|
||||
"type": ["cfml", "html", "angle"],
|
||||
"command": "bh_modules.tagnameselect"
|
||||
}
|
||||
}
|
||||
},
|
||||
// Select the attribute to the right of the cursor (will wrap inside the tag)
|
||||
{
|
||||
"keys": ["ctrl+alt+super+right"],
|
||||
"command": "bh_key",
|
||||
"args":
|
||||
{
|
||||
"plugin":
|
||||
{
|
||||
"type": ["cfml", "html", "angle"],
|
||||
"command": "bh_modules.tagattrselect",
|
||||
"args": {"direction": "right"}
|
||||
}
|
||||
}
|
||||
},
|
||||
// Select the attribute to the left of the cursor (will wrap inside the tag)
|
||||
{
|
||||
"keys": ["ctrl+alt+super+left"],
|
||||
"command": "bh_key",
|
||||
"args":
|
||||
{
|
||||
"plugin":
|
||||
{
|
||||
"type": ["cfml", "html", "angle"],
|
||||
"command": "bh_modules.tagattrselect",
|
||||
"args": {"direction": "left"}
|
||||
}
|
||||
}
|
||||
},
|
||||
// Convert single quote string to double quoted string and vice versa
|
||||
// Will handle escaping or unescaping quotes within the string
|
||||
{
|
||||
"keys": ["ctrl+alt+super+q"],
|
||||
"command": "bh_key",
|
||||
"args":
|
||||
{
|
||||
"lines" : true,
|
||||
"plugin":
|
||||
{
|
||||
"type": ["single_quote", "double_quote", "py_single_quote", "py_double_quote"],
|
||||
"command": "bh_modules.swapquotes"
|
||||
}
|
||||
}
|
||||
},
|
||||
// Fold contents between brackets
|
||||
{
|
||||
"keys": ["ctrl+alt+super+["],
|
||||
"command": "bh_key",
|
||||
"args":
|
||||
{
|
||||
"plugin": {
|
||||
"type": ["__all__"],
|
||||
"command" : "bh_modules.foldbracket"
|
||||
}
|
||||
}
|
||||
},
|
||||
// Swap brackets with another type
|
||||
{
|
||||
"keys": ["ctrl+alt+super+e"],
|
||||
"command": "swap_brackets"
|
||||
},
|
||||
// Surround selection with brackets from quick panel
|
||||
{
|
||||
"keys": ["ctrl+alt+super+w"],
|
||||
"command": "wrap_brackets"
|
||||
},
|
||||
// Toggle high visibility mode
|
||||
{
|
||||
"keys": ["ctrl+alt+super+v"],
|
||||
"command": "bh_toggle_high_visibility"
|
||||
}
|
||||
]
|
@@ -0,0 +1,260 @@
|
||||
[
|
||||
{
|
||||
"id": "tools",
|
||||
"caption": "Tools",
|
||||
"children":
|
||||
[
|
||||
{
|
||||
"id": "packages",
|
||||
"caption": "Packages",
|
||||
"children":
|
||||
[
|
||||
{
|
||||
"id": "brackethighlighter",
|
||||
"caption": "BracketHighlighter",
|
||||
"children":
|
||||
[
|
||||
// Toggle Global Enable
|
||||
{
|
||||
"caption": "BracketHighlighter: Toggle Global Enable",
|
||||
"command": "bh_toggle_enable"
|
||||
},
|
||||
{ "caption": "-" },
|
||||
// Search to end of file for bracket
|
||||
{
|
||||
"caption": "Match Brackets (ignore threshold)",
|
||||
"command": "bh_key",
|
||||
"args": {"lines" : true}
|
||||
},
|
||||
// Remove brackets
|
||||
{
|
||||
"caption": "Remove Brackets",
|
||||
"command": "bh_remove_brackets"
|
||||
},
|
||||
// Go to left bracket
|
||||
{
|
||||
"caption": "Jump to Left Bracket",
|
||||
"command": "bh_key",
|
||||
"args":
|
||||
{
|
||||
"lines" : true,
|
||||
"plugin":
|
||||
{
|
||||
"type": ["__all__"],
|
||||
"command": "bh_modules.bracketselect",
|
||||
"args": {"select": "left"}
|
||||
}
|
||||
}
|
||||
},
|
||||
// Go to right bracket
|
||||
{
|
||||
"caption": "Jump to Right Bracket",
|
||||
"command": "bh_key",
|
||||
"args":
|
||||
{
|
||||
"lines" : true,
|
||||
"plugin":
|
||||
{
|
||||
"type": ["__all__"],
|
||||
"command": "bh_modules.bracketselect",
|
||||
"args": {"select": "right"}
|
||||
}
|
||||
}
|
||||
},
|
||||
// Select text between brackets
|
||||
{
|
||||
"caption": "Select Bracket Content",
|
||||
"command": "bh_key",
|
||||
"args":
|
||||
{
|
||||
"lines" : true,
|
||||
"plugin":
|
||||
{
|
||||
"type": ["__all__"],
|
||||
"command": "bh_modules.bracketselect"
|
||||
}
|
||||
}
|
||||
},
|
||||
// Fold contents between brackets
|
||||
{
|
||||
"caption": "Fold Bracket Content",
|
||||
"command": "bh_key",
|
||||
"args":
|
||||
{
|
||||
"plugin": {
|
||||
"type": ["__all__"],
|
||||
"command" : "bh_modules.foldbracket"
|
||||
}
|
||||
}
|
||||
},
|
||||
{ "caption": "-" },
|
||||
// Toggle between string and regex escape mode for string brackets
|
||||
{
|
||||
"caption": "Toggle String Bracket Escape Mode",
|
||||
"command": "bh_toggle_string_escape_mode"
|
||||
},
|
||||
// Toggle high visibility mode
|
||||
{
|
||||
"caption": "Toggle High Visibility Mode",
|
||||
"command": "bh_toggle_high_visibility"
|
||||
},
|
||||
{ "caption": "-" },
|
||||
// Select tag name of HTML/XML tag (both opening name and closing)
|
||||
{
|
||||
"caption": "Select Tag Name (closing and opening)",
|
||||
"command": "bh_key",
|
||||
"args":
|
||||
{
|
||||
"plugin":
|
||||
{
|
||||
"type": ["cfml", "html", "angle"],
|
||||
"command": "bh_modules.tagnameselect"
|
||||
}
|
||||
}
|
||||
},
|
||||
// Select the attribute to the right of the cursor (will wrap inside the tag)
|
||||
{
|
||||
"caption": "Select Next Attribute (right)",
|
||||
"command": "bh_key",
|
||||
"args":
|
||||
{
|
||||
"plugin":
|
||||
{
|
||||
"type": ["cfml", "html", "angle"],
|
||||
"command": "bh_modules.tagattrselect",
|
||||
"args": {"direction": "right"}
|
||||
}
|
||||
}
|
||||
},
|
||||
// Select the attribute to the left of the cursor (will wrap inside the tag)
|
||||
{
|
||||
"caption": "Select Next Attribute (left)",
|
||||
"command": "bh_key",
|
||||
"args":
|
||||
{
|
||||
"plugin":
|
||||
{
|
||||
"type": ["cfml", "html", "angle"],
|
||||
"command": "bh_modules.tagattrselect",
|
||||
"args": {"direction": "left"}
|
||||
}
|
||||
}
|
||||
},
|
||||
{ "caption": "-" },
|
||||
// Convert single quote string to double quoted string and vice versa
|
||||
// Will handle escaping or unescaping quotes within the string
|
||||
{
|
||||
"caption": "Swap Quotes",
|
||||
"command": "bh_key",
|
||||
"args":
|
||||
{
|
||||
"lines" : true,
|
||||
"plugin":
|
||||
{
|
||||
"type": ["single_quote", "double_quote", "py_single_quote", "py_double_quote"],
|
||||
"command": "bh_modules.swapquotes"
|
||||
}
|
||||
}
|
||||
},
|
||||
// Swap brackets
|
||||
{
|
||||
"caption": "Swap Brackets",
|
||||
"command": "swap_brackets"
|
||||
},
|
||||
// Surround selection with brackets from quick panel
|
||||
{
|
||||
"caption": "Wrap Selections with Brackets",
|
||||
"command": "wrap_brackets"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"caption": "Preferences",
|
||||
"mnemonic": "n",
|
||||
"id": "preferences",
|
||||
"children":
|
||||
[
|
||||
{
|
||||
"caption": "Package Settings",
|
||||
"mnemonic": "P",
|
||||
"id": "package-settings",
|
||||
"children":
|
||||
[
|
||||
{
|
||||
"caption": "Bracket Highlighter",
|
||||
"children":
|
||||
[
|
||||
{
|
||||
"command": "open_file",
|
||||
"args": {"file": "${packages}/BracketHighlighter/bh_core.sublime-settings"},
|
||||
"caption": "Bracket Settings – Default"
|
||||
},
|
||||
{
|
||||
"command": "open_file",
|
||||
"args": {"file": "${packages}/User/bh_core.sublime-settings"},
|
||||
"caption": "Bracket Settings – User"
|
||||
},
|
||||
{ "caption": "-" },
|
||||
{
|
||||
"command": "open_file",
|
||||
"args": {"file": "${packages}/BracketHighlighter/bh_wrapping.sublime-settings"},
|
||||
"caption": "Wrap Settings – Default"
|
||||
},
|
||||
{
|
||||
"command": "open_file",
|
||||
"args": {"file": "${packages}/User/bh_wrapping.sublime-settings"},
|
||||
"caption": "Wrap Settings – User"
|
||||
},
|
||||
{ "caption": "-" },
|
||||
{
|
||||
"command": "open_file",
|
||||
"args": {"file": "${packages}/BracketHighlighter/bh_swapping.sublime-settings"},
|
||||
"caption": "Swap Settings – Default"
|
||||
},
|
||||
{
|
||||
"command": "open_file",
|
||||
"args": {"file": "${packages}/User/bh_swapping.sublime-settings"},
|
||||
"caption": "Swap Settings – User"
|
||||
},
|
||||
{ "caption": "-" },
|
||||
{
|
||||
"command": "open_file",
|
||||
"args": {"file": "${packages}/BracketHighlighter/Example.sublime-keymap"},
|
||||
"caption": "Example Key Bindings"
|
||||
},
|
||||
{
|
||||
"command": "open_file",
|
||||
"args": {
|
||||
"file": "${packages}/User/Default (Windows).sublime-keymap",
|
||||
"platform": "Windows"
|
||||
},
|
||||
"caption": "Key Bindings – User"
|
||||
},
|
||||
{
|
||||
"command": "open_file",
|
||||
"args": {
|
||||
"file": "${packages}/User/Default (OSX).sublime-keymap",
|
||||
"platform": "OSX"
|
||||
},
|
||||
"caption": "Key Bindings – User"
|
||||
},
|
||||
{
|
||||
"command": "open_file",
|
||||
"args": {
|
||||
"file": "${packages}/User/Default (Linux).sublime-keymap",
|
||||
"platform": "Linux"
|
||||
},
|
||||
"caption": "Key Bindings – User"
|
||||
},
|
||||
{ "caption": "-" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
@@ -0,0 +1,372 @@
|
||||
{
|
||||
//Debug logging
|
||||
"debug_enable": false,
|
||||
|
||||
// Path to find icons at
|
||||
"icon_path": "BracketHighlighter/icons",
|
||||
|
||||
// When only either the left or right bracket can be found
|
||||
// this defines if the unmatched bracket should be shown.
|
||||
"show_unmatched" : true,
|
||||
|
||||
// High visibilty style and color for high visibility mode
|
||||
// (solid|outline|underline)
|
||||
"high_visibility_style": "outline",
|
||||
// (scope|__default__|__bracket__)
|
||||
"high_visibility_color": "__bracket__",
|
||||
|
||||
// Match brackets only when the cursor is touching the inside of the bracket
|
||||
"match_only_adjacent": false,
|
||||
|
||||
// Character threshold to search
|
||||
"search_threshold": 5000,
|
||||
|
||||
// Set mode for string escapes to ignore (regex|string)
|
||||
"bracket_string_escape_mode": "string",
|
||||
|
||||
// Set max number of multi-select brackets that will be searched automatically
|
||||
"auto_selection_threshold" : 10,
|
||||
|
||||
// Disable gutter icons when doing multi-select
|
||||
"no_multi_select_icons": false,
|
||||
|
||||
// Rules that define the finding and matching of brackets
|
||||
// that are contained in a common scope.
|
||||
// Useful for bracket pairs that are the same but
|
||||
// share a common scope. Brackets are found by
|
||||
// Finding the extent of the scope and using regex
|
||||
// to look at the beginning and end to identify bracket.
|
||||
// Use only if they cannot be targeted with traditional bracket
|
||||
// rules.
|
||||
"scope_brackets": [
|
||||
// Quotes
|
||||
{
|
||||
"name": "py_single_quote",
|
||||
"open": "u?r?((?:'')?')",
|
||||
"close": "((?:'')?')",
|
||||
"style": "single_quote",
|
||||
"scopes": ["string"],
|
||||
"language_filter": "whitelist",
|
||||
"language_list": ["Python"],
|
||||
"sub_bracket_search": "true",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"name": "py_double_quote",
|
||||
"open": "u?r?((?:\"\")?\")",
|
||||
"close": "((?:\"\")?\")",
|
||||
"style": "double_quote",
|
||||
"scopes": ["string"],
|
||||
"language_filter": "whitelist",
|
||||
"language_list": ["Python"],
|
||||
"sub_bracket_search": "true",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"name": "single_quote",
|
||||
"open": "(')",
|
||||
"close": "(')",
|
||||
"style": "single_quote",
|
||||
"scopes": ["string"],
|
||||
"language_filter": "blacklist",
|
||||
"language_list": ["Plain text"],
|
||||
"sub_bracket_search": "true",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"name": "double_quote",
|
||||
"open": "(\")",
|
||||
"close": "(\")",
|
||||
"style": "double_quote",
|
||||
"scopes": ["string"],
|
||||
"language_filter": "blacklist",
|
||||
"language_list": ["Plain text"],
|
||||
"sub_bracket_search": "true",
|
||||
"enabled": true
|
||||
},
|
||||
// Regex for different Languages
|
||||
{
|
||||
"name": "jsregex",
|
||||
"open": " *(/)",
|
||||
"close": "(/)[igm]*",
|
||||
"style": "regex",
|
||||
"scopes": ["string"],
|
||||
"language_filter": "whitelist",
|
||||
"language_list": ["JavaScript"],
|
||||
"sub_bracket_search": "true",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"name": "perlregex",
|
||||
"open": "(?:m|s|tr)(.|\n)",
|
||||
"close": "(.|\n)(?:[igmos]*)",
|
||||
"style": "regex",
|
||||
"scopes": ["string.regexp"],
|
||||
"language_filter": "whitelist",
|
||||
"language_list": ["Perl"],
|
||||
"sub_bracket_search": "true",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"name": "rubyregex",
|
||||
"open": " *(/)",
|
||||
"close": "(/)[imxo]*",
|
||||
"style": "regex",
|
||||
"scopes": ["string"],
|
||||
"language_filter": "whitelist",
|
||||
"language_list": ["Ruby"],
|
||||
"sub_bracket_search": "true",
|
||||
"enabled": true
|
||||
},
|
||||
// Markdown
|
||||
{
|
||||
"name": "mditalic",
|
||||
"open": "(\\*|_)",
|
||||
"close": "(\\*|_)",
|
||||
"style": "default",
|
||||
"scopes": ["markup.italic"],
|
||||
"language_filter": "whitelist",
|
||||
"language_list": ["Markdown"],
|
||||
"sub_bracket_search": "true",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"name": "mdbold",
|
||||
"open": "(\\*\\*|__)",
|
||||
"close": "(\\*\\*|__)",
|
||||
"style": "default",
|
||||
"scopes": ["markup.bold"],
|
||||
"language_filter": "whitelist",
|
||||
"language_list": ["Markdown"],
|
||||
"sub_bracket_search": "true",
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
|
||||
// Rule definitions for finding and matching brackets.
|
||||
// Brackets are found by using regex and can use scope
|
||||
// qualifiers exclude certain matches.
|
||||
// Once all matches are found, the closest pair surrounding
|
||||
// the cursor are selected.
|
||||
"brackets": [
|
||||
// Basic brackets
|
||||
{
|
||||
"name": "curly",
|
||||
"open": "(\\{)",
|
||||
"close": "(\\})",
|
||||
"style": "curly",
|
||||
"scope_exclude": ["string", "comment"],
|
||||
"scope_exclude_exceptions": ["string.other.math.block.environment.latex"],
|
||||
"language_filter": "blacklist",
|
||||
"language_list": ["Plain text"],
|
||||
"find_in_sub_search": "true",
|
||||
"ignore_string_escape": true,
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"name": "round",
|
||||
"open": "(\\()",
|
||||
"close": "(\\))",
|
||||
"style": "round",
|
||||
"scope_exclude_exceptions": ["string.other.math.block.environment.latex"],
|
||||
"scope_exclude": ["string", "comment"],
|
||||
"language_filter": "blacklist",
|
||||
"language_list": ["Plain text"],
|
||||
"find_in_sub_search": "true",
|
||||
"ignore_string_escape": true,
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"name": "square",
|
||||
"open": "(\\[)",
|
||||
"close": "(\\])",
|
||||
"style": "square",
|
||||
"scope_exclude": ["string", "comment"],
|
||||
"scope_exclude_exceptions": ["string.other.math.block.environment.latex"],
|
||||
"language_filter": "blacklist",
|
||||
"language_list": ["Plain text"],
|
||||
"find_in_sub_search": "true",
|
||||
"ignore_string_escape": true,
|
||||
"enabled": true
|
||||
},
|
||||
// HTML
|
||||
{
|
||||
"name": "html",
|
||||
"open": "(<)(?=[\\w\\:\\-]+(?:(?:\\s+[\\w\\-:]+(?:\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^>\\s]+))?)*)\\s*\\/?>|\\/[\\w\\:\\-]+[^>]*>)",
|
||||
"close": "(?<=<)(?:[\\w\\:\\-]+(?:(?:\\s+[\\w\\-:]+(?:\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^>\\s]+))?)*)\\s*\\/?|\\/[\\w\\:\\-]+[^>]*)(>)",
|
||||
"style": "tag",
|
||||
"scope_exclude": ["string", "comment"],
|
||||
"language_filter": "whitelist",
|
||||
"language_list": ["HTML", "HTML 5", "XML", "PHP"],
|
||||
"plugin_library": "bh_modules.tags",
|
||||
"find_in_sub_search": "only",
|
||||
"enabled": false
|
||||
},
|
||||
// CFML
|
||||
{
|
||||
"name": "cfml",
|
||||
"open": "(<)(?=[\\w\\:\\-]+(?:(?:\\s+[\\w\\-\\.:]+(?:\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^>\\s]+))?)*|(?:(?<=cfif)|(?<=cfelseif))[^>]+)\\s*\\/?>|\\/[\\w\\:\\-]+[^>]*>)",
|
||||
"close": "(?<=<)(?:[\\w\\:\\-]+(?:(?:\\s+[\\w\\-\\.:]+(?:\\s*=\\s*(?:\"[^\"]*\"|'[^']*'|[^>\\s]+))?)*|(?:(?<=cfif)|(?<=cfelseif))[^>]+)\\s*\\/?|\\/[\\w\\:\\-]+[^>]*)(>)",
|
||||
"style": "tag",
|
||||
"scope_exclude": ["string", "comment"],
|
||||
"language_filter": "whitelist",
|
||||
"language_list": ["HTML+CFML", "ColdFusion", "ColdFusionCFC"],
|
||||
"plugin_library": "bh_modules.tags",
|
||||
"find_in_sub_search": "only",
|
||||
"enabled": false
|
||||
},
|
||||
// Angle
|
||||
{
|
||||
"name": "angle",
|
||||
"open": "(<)",
|
||||
"close": "(>)",
|
||||
"style": "angle",
|
||||
"scope_exclude": ["string", "comment", "keyword.operator"],
|
||||
"language_filter": "whitelist",
|
||||
"language_list": ["HTML", "HTML 5", "XML", "PHP", "HTML+CFML", "ColdFusion", "ColdFusionCFC"],
|
||||
"plugin_library": "bh_modules.tags",
|
||||
"enabled": true
|
||||
},
|
||||
// CSSedit groups
|
||||
{
|
||||
"name": "cssedit_groups",
|
||||
"open": "(/\\* *@group .*\\*/)",
|
||||
"close": "(/\\* *@end *\\*/)",
|
||||
"style": "default",
|
||||
"scope_exclude": [],
|
||||
"language_filter": "whitelist",
|
||||
"language_list": ["CSS"],
|
||||
"enabled": true
|
||||
},
|
||||
// Ruby conditional statements
|
||||
{
|
||||
"name": "ruby",
|
||||
"open": "(^\\s*\\b(?:if|case|until|unless|while|begin|class|module|def\\b\\s*[a-zA-Z_\\d]+)|\\bdo)\\b",
|
||||
"close": "\\b(end)\\b",
|
||||
"style": "default",
|
||||
"scope_exclude": ["string", "comment"],
|
||||
"plugin_library": "bh_modules.rubykeywords",
|
||||
"language_filter": "whitelist",
|
||||
"language_list": ["Ruby", "Ruby on Rails", "HTML (Rails)"],
|
||||
"enabled": true
|
||||
},
|
||||
// C/C++ compile switches
|
||||
{
|
||||
"name": "c_compile_switch",
|
||||
"open": "(\\#(?:if|ifdef|ifndef))\\b",
|
||||
"close": "(\\#endif)\\b",
|
||||
"style": "default",
|
||||
"scope_exclude": ["string", "comment"],
|
||||
"language_filter": "whitelist",
|
||||
"language_list": ["C++", "C", "Objective-C"],
|
||||
"enabled": true
|
||||
},
|
||||
// PHP conditional keywords
|
||||
{
|
||||
"name": "php_keywords",
|
||||
"open": "(?:^\\s*|<\\?(?:php)?\\s*)?\\b(if|foreach|for|while|switch)\\b(?=.*:\\s*(?:\\?>\\s*)?$)",
|
||||
"close": "(?:^\\s*|<\\?(?:php)?\\s*)?\\b(endif|endfor|endforeach|endwhile|endswitch)\\b(?=\\s*;\\s*(?:\\?>\\s*)?$)",
|
||||
"style": "default",
|
||||
"language_filter": "whitelist",
|
||||
"scope_exclude": ["string", "comment"],
|
||||
"plugin_library": "bh_modules.phpkeywords",
|
||||
"language_list": ["HTML", "HTML 5", "XML", "PHP", "HTML+CFML", "ColdFusion", "ColdFusionCFC"],
|
||||
"enabled": true
|
||||
},
|
||||
// Erlang conditional statements
|
||||
{
|
||||
"name": "erlang",
|
||||
"open": "\\s*(\\b(?:if|case|begin|try|fun(?=\\s*\\()|receive)\\b)",
|
||||
"close": "\\b(end)\\b",
|
||||
"style": "default",
|
||||
"scope_exclude": ["string", "comment"],
|
||||
"language_filter": "whitelist",
|
||||
"language_list": ["Erlang", "HTML (Erlang)"],
|
||||
"enabled": true
|
||||
}
|
||||
],
|
||||
|
||||
// Define region highlight styles
|
||||
"bracket_styles": {
|
||||
// "default" and "unmatched" styles are special
|
||||
// styles. If they are not defined here,
|
||||
// they will be generated internally with
|
||||
// internal defaults.
|
||||
|
||||
// "default" style defines attributes that
|
||||
// will be used for any style that does not
|
||||
// explicitly define that attribute. So if
|
||||
// a style does not define a color, it will
|
||||
// use the color from the "default" style.
|
||||
"default": {
|
||||
"icon": "dot",
|
||||
"color": "brackethighlighter.default",
|
||||
"style": "underline"
|
||||
},
|
||||
|
||||
// This particular style is used to highlight
|
||||
// unmatched bracekt pairs. It is a special
|
||||
// style.
|
||||
"unmatched": {
|
||||
"icon": "question",
|
||||
// "color": "brackethighlighter.unmatched",
|
||||
"style": "outline"
|
||||
},
|
||||
// User defined region styles
|
||||
"curly": {
|
||||
"icon": "curly_bracket"
|
||||
// "color": "brackethighlighter.curly",
|
||||
// "style": "underline"
|
||||
},
|
||||
"round": {
|
||||
"icon": "round_bracket"
|
||||
// "color": "brackethighlighter.round",
|
||||
// "style": "underline"
|
||||
},
|
||||
"square": {
|
||||
"icon": "square_bracket"
|
||||
// "color": "brackethighlighter.square",
|
||||
// "style": "underline"
|
||||
},
|
||||
"angle": {
|
||||
"icon": "angle_bracket"
|
||||
// "color": "brackethighlighter.angle",
|
||||
// "style": "underline"
|
||||
},
|
||||
"tag": {
|
||||
"icon": "tag",
|
||||
// "color": "brackethighlighter.tag",
|
||||
"style": "outline"
|
||||
},
|
||||
"single_quote": {
|
||||
"icon": "single_quote"
|
||||
// "color": "brackethighlighter.quote",
|
||||
// "style": "underline"
|
||||
},
|
||||
"double_quote": {
|
||||
"icon": "double_quote"
|
||||
// "color": "brackethighlighter.quote",
|
||||
// "style": "underline"
|
||||
},
|
||||
"regex": {
|
||||
"icon": "regex"
|
||||
// "color": "brackethighlighter.quote",
|
||||
// "style": "underline"
|
||||
}
|
||||
},
|
||||
|
||||
/* Plugin settings */
|
||||
|
||||
// Style to use for matched tags
|
||||
"tag_style": "tag",
|
||||
|
||||
// Scopes to exclude from tag searches
|
||||
"tag_scope_exclude": ["string", "comment"],
|
||||
|
||||
// Determine which style of tag-matching to use in which syntax
|
||||
"tag_mode": {
|
||||
"xhtml": ["XML"],
|
||||
"html": ["HTML", "HTML 5", "PHP"],
|
||||
"cfml": ["HTML+CFML", "ColdFusion", "ColdFusionCFC"]
|
||||
}
|
||||
}
|
@@ -0,0 +1 @@
|
||||
|
@@ -0,0 +1,41 @@
|
||||
import bh_plugin
|
||||
import re
|
||||
import sublime
|
||||
|
||||
|
||||
class BracketRemove(bh_plugin.BracketPluginCommand):
|
||||
def decrease_indent_level(self, edit, row_first, row_last):
|
||||
tab_size = self.view.settings().get("tab_size", 4)
|
||||
indents = re.compile(r"^(?:\t| {%d}| *)((?:\t| {%d}| )*)([\s\S]*)" % (tab_size, tab_size))
|
||||
if not self.single_line:
|
||||
for x in reversed(range(row_first, row_last + 1)):
|
||||
line = self.view.full_line(self.view.text_point(x, 0))
|
||||
text = self.view.substr(line)
|
||||
m = indents.match(text)
|
||||
if m:
|
||||
self.view.replace(edit, line, m.group(1) + m.group(2))
|
||||
|
||||
def run(self, edit, name, remove_content=False, remove_indent=False, remove_block=False):
|
||||
if remove_content:
|
||||
self.view.replace(edit, sublime.Region(self.left.begin, self.right.end), "")
|
||||
else:
|
||||
row_first = self.view.rowcol(self.left.end)[0] + 1
|
||||
row_last = self.view.rowcol(self.right.begin)[0] - 1
|
||||
self.single_line = not row_first <= row_last
|
||||
if remove_block and not self.single_line:
|
||||
self.view.replace(edit, self.view.full_line(self.right.toregion()), "")
|
||||
else:
|
||||
self.view.replace(edit, self.right.toregion(), "")
|
||||
if remove_indent:
|
||||
self.decrease_indent_level(edit, row_first, row_last)
|
||||
if remove_block and not self.single_line:
|
||||
self.view.replace(edit, self.view.full_line(self.left.toregion()), "")
|
||||
else:
|
||||
self.view.replace(edit, self.left.toregion(), "")
|
||||
|
||||
self.left = None
|
||||
self.right = None
|
||||
|
||||
|
||||
def plugin():
|
||||
return BracketRemove
|
@@ -0,0 +1,33 @@
|
||||
import bh_plugin
|
||||
import sublime
|
||||
|
||||
DEFAULT_TAGS = ["cfml", "html", "angle"]
|
||||
|
||||
|
||||
class SelectBracket(bh_plugin.BracketPluginCommand):
|
||||
def run(self, edit, name, select='', tags=DEFAULT_TAGS):
|
||||
left, right = self.left, self.right
|
||||
first, last = left.end, right.begin
|
||||
if select == 'left':
|
||||
if name in tags and left.size() > 1:
|
||||
first, last = left.begin + 1, left.begin + 1
|
||||
else:
|
||||
first, last = left.end, left.end
|
||||
elif select == 'right':
|
||||
if left.end != right.end:
|
||||
if name in tags and left.size() > 1:
|
||||
first, last = right.begin + 1, right.begin + 1
|
||||
else:
|
||||
first, last = right.begin, right.begin
|
||||
else:
|
||||
# There is no second bracket, so just select the first
|
||||
if name in tags and left.size() > 1:
|
||||
first, last = left.begin + 1, left.begin + 1
|
||||
else:
|
||||
first, last = right.end, right.end
|
||||
|
||||
self.selection = [sublime.Region(first, last)]
|
||||
|
||||
|
||||
def plugin():
|
||||
return SelectBracket
|
@@ -0,0 +1,16 @@
|
||||
import bh_plugin
|
||||
import sublime
|
||||
|
||||
|
||||
class FoldBrackets(bh_plugin.BracketPluginCommand):
|
||||
def run(self, edit, name):
|
||||
content = sublime.Region(self.left.end, self.right.begin)
|
||||
new_content = [content]
|
||||
if content.size > 0:
|
||||
if self.view.fold(content) == False:
|
||||
new_content = self.view.unfold(content)
|
||||
self.selection = new_content
|
||||
|
||||
|
||||
def plugin():
|
||||
return FoldBrackets
|
@@ -0,0 +1,2 @@
|
||||
def compare(name, first, second, bfr):
|
||||
return "end" + bfr[first.begin:first.end].lower() == bfr[second.begin:second.end].lower()
|
@@ -0,0 +1,12 @@
|
||||
import re
|
||||
|
||||
|
||||
def post_match(view, name, style, first, second, center, bfr, threshold):
|
||||
if first is not None:
|
||||
# Strip whitespace from the beginning of first bracket
|
||||
open_bracket = bfr[first.begin:first.end]
|
||||
if open_bracket != "do":
|
||||
m = re.match(r"^(\s*\b)[\w\W]*", open_bracket)
|
||||
if m:
|
||||
first = first.move(first.begin + m.end(1), first.end)
|
||||
return first, second, style
|
@@ -0,0 +1,14 @@
|
||||
import sublime
|
||||
from bh_plugin import ImportModule as ImpMod
|
||||
BracketRemove = ImpMod.import_from("bh_modules.bracketremove", "BracketRemove")
|
||||
|
||||
|
||||
class SwapBrackets(BracketRemove):
|
||||
def run(self, edit, name, remove_content=False, remove_indent=False, remove_block=False):
|
||||
offset = self.left.toregion().size()
|
||||
self.selection = [sublime.Region(self.left.begin, self.right.begin - offset)]
|
||||
super(SwapBrackets, self).run(edit, name)
|
||||
|
||||
|
||||
def plugin():
|
||||
return SwapBrackets
|
@@ -0,0 +1,46 @@
|
||||
import bh_plugin
|
||||
import sublime
|
||||
|
||||
|
||||
class SwapQuotes(bh_plugin.BracketPluginCommand):
|
||||
def escaped(self, idx):
|
||||
view = self.view
|
||||
escaped = False
|
||||
while idx >= 0 and view.substr(idx) == '\\':
|
||||
escaped = ~escaped
|
||||
idx -= 1
|
||||
return escaped
|
||||
|
||||
def run(self, edit, name):
|
||||
view = self.view
|
||||
quote = view.substr(self.left.begin)
|
||||
if quote != "'" and quote != '"':
|
||||
return
|
||||
new = "'" if (quote == '"') else '"'
|
||||
old = quote
|
||||
begin = self.left.end
|
||||
end = self.right.begin
|
||||
content_end = self.right.begin
|
||||
|
||||
view.replace(edit, self.left.toregion(), view.substr(self.left.toregion()).replace(old, new))
|
||||
view.replace(edit, self.right.toregion(), view.substr(self.right.toregion()).replace(old, new))
|
||||
|
||||
offset = 0
|
||||
while begin < end + offset:
|
||||
char = view.substr(begin)
|
||||
if char == old and self.escaped(begin - 1):
|
||||
view.replace(edit, sublime.Region(begin - 1, begin), '')
|
||||
offset -= 1
|
||||
content_end -= 1
|
||||
elif char == new and not self.escaped(begin - 1):
|
||||
view.insert(edit, begin, "\\")
|
||||
offset += 1
|
||||
content_end += 1
|
||||
begin += 1
|
||||
|
||||
self.right = self.right.move(content_end, end + offset)
|
||||
self.selection = [sublime.Region(content_end)]
|
||||
|
||||
|
||||
def plugin():
|
||||
return SwapQuotes
|
@@ -0,0 +1,54 @@
|
||||
import bh_plugin
|
||||
|
||||
|
||||
class SelectAttr(bh_plugin.BracketPluginCommand):
|
||||
def run(self, edit, name, direction='right'):
|
||||
if self.left.size() <= 1:
|
||||
return
|
||||
tag_name = r'[\w\:\-]+'
|
||||
attr_name = r'''([\w\-\.:]+)(?:\s*=\s*(?:(?:"((?:\.|[^"])*)")|(?:'((?:\.|[^'])*)')|([^>\s]+)))?'''
|
||||
tname = self.view.find(tag_name, self.left.begin)
|
||||
current = self.selection[0].b
|
||||
region = self.view.find(attr_name, tname.b)
|
||||
selection = self.selection
|
||||
|
||||
if direction == 'left':
|
||||
last = None
|
||||
|
||||
# Keep track of last attr
|
||||
if region != None and current <= region.b and region.b < self.left.end:
|
||||
last = region
|
||||
|
||||
while region != None and region.b < self.left.end:
|
||||
# Select attribute until you have closest to the left of selection
|
||||
if current > region.b:
|
||||
selection = [region]
|
||||
last = None
|
||||
# Update last attr
|
||||
elif last != None:
|
||||
last = region
|
||||
region = self.view.find(attr_name, region.b)
|
||||
# Wrap right
|
||||
if last != None:
|
||||
selection = [last]
|
||||
else:
|
||||
first = None
|
||||
# Keep track of first attr
|
||||
if region != None and region.b < self.left.end:
|
||||
first = region
|
||||
|
||||
while region != None and region.b < self.left.end:
|
||||
# Select closest attr to the right of the selection
|
||||
if current < region.b:
|
||||
selection = [region]
|
||||
first = None
|
||||
break
|
||||
region = self.view.find(attr_name, region.b)
|
||||
# Wrap left
|
||||
if first != None:
|
||||
selection = [first]
|
||||
self.selection = selection
|
||||
|
||||
|
||||
def plugin():
|
||||
return SelectAttr
|
@@ -0,0 +1,14 @@
|
||||
import bh_plugin
|
||||
|
||||
|
||||
class TagNameSelect(bh_plugin.BracketPluginCommand):
|
||||
def run(self, edit, name):
|
||||
if self.left.size() > 1:
|
||||
tag_name = '[\w\:\-]+'
|
||||
region1 = self.view.find(tag_name, self.left.begin)
|
||||
region2 = self.view.find(tag_name, self.right.begin)
|
||||
self.selection = [region1, region2]
|
||||
|
||||
|
||||
def plugin():
|
||||
return TagNameSelect
|
@@ -0,0 +1,243 @@
|
||||
import re
|
||||
from collections import namedtuple
|
||||
import sublime
|
||||
from os.path import basename
|
||||
|
||||
FLAGS = re.MULTILINE | re.IGNORECASE
|
||||
HTML_START = re.compile(r'''<([\w\:\-]+)((?:\s+[\w\-:]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^>\s]+))?)*)\s*(\/?)>''', FLAGS)
|
||||
CFML_START = re.compile(r'''<([\w\:\-]+)((?:\s+[\w\-\.:]+(?:\s*=\s*(?:"[^"]*"|'[^']*'|[^>\s]+))?)*|(?:(?<=cfif)|(?<=cfelseif))[^>]+)\s*(\/?)>''', FLAGS)
|
||||
START_TAG = {
|
||||
"html": HTML_START,
|
||||
"xhtml": HTML_START,
|
||||
"cfml": CFML_START
|
||||
}
|
||||
END_TAG = re.compile(r'<\/([\w\:\-]+)[^>]*>', FLAGS)
|
||||
|
||||
self_closing_tags = set("colgroup dd dt li options p td tfoot th thead tr".split())
|
||||
single_tags = set("area base basefont br col frame hr img input isindex link meta param embed".split())
|
||||
|
||||
|
||||
class TagEntry(namedtuple('TagEntry', ['begin', 'end', 'name', 'self_closing', 'single'], verbose=False)):
|
||||
def move(self, begin, end):
|
||||
return self._replace(begin=begin, end=end)
|
||||
|
||||
|
||||
def compare_languge(language, lang_list):
|
||||
found = False
|
||||
for l in lang_list:
|
||||
if language == l.lower():
|
||||
found = True
|
||||
break
|
||||
return found
|
||||
|
||||
|
||||
def get_tag_mode(view, tag_mode_config):
|
||||
default_mode = None
|
||||
syntax = view.settings().get('syntax')
|
||||
language = basename(syntax).replace('.tmLanguage', '').lower() if syntax != None else "plain text"
|
||||
for mode in ["html", "xhtml", "cfml"]:
|
||||
if compare_languge(language, tag_mode_config.get(mode, [])):
|
||||
return mode
|
||||
return default_mode
|
||||
|
||||
|
||||
def post_match(view, name, style, first, second, center, bfr, threshold):
|
||||
left, right = first, second
|
||||
threshold = [0, len(bfr)] if threshold is None else threshold
|
||||
tag_settings = sublime.load_settings("bh_core.sublime-settings")
|
||||
tag_mode = get_tag_mode(view, tag_settings.get("tag_mode", {}))
|
||||
tag_style = tag_settings.get("tag_style", "angle")
|
||||
bracket_style = style
|
||||
|
||||
if first is not None and tag_mode is not None:
|
||||
matcher = TagMatch(view, bfr, threshold, first, second, center, tag_mode)
|
||||
left, right = matcher.match()
|
||||
if not matcher.no_tag:
|
||||
bracket_style = tag_style
|
||||
|
||||
return left, right, bracket_style
|
||||
|
||||
|
||||
class TagSearch(object):
|
||||
def __init__(self, view, bfr, window, center, pattern, match_type):
|
||||
self.start = window[0]
|
||||
self.end = window[1]
|
||||
self.center = center
|
||||
self.pattern = pattern
|
||||
self.match_type = match_type
|
||||
self.bfr = bfr
|
||||
self.prev_match = None
|
||||
self.return_prev = False
|
||||
self.done = False
|
||||
self.view = view
|
||||
self.scope_exclude = sublime.load_settings("bh_core.sublime-settings").get("tag_scope_exclude")
|
||||
|
||||
def scope_check(self, pt):
|
||||
illegal_scope = False
|
||||
for exclude in self.scope_exclude:
|
||||
illegal_scope |= bool(self.view.score_selector(pt, exclude))
|
||||
return illegal_scope
|
||||
|
||||
def reset_end_state(self):
|
||||
self.done = False
|
||||
self.prev_match = None
|
||||
self.return_prev = False
|
||||
|
||||
def remember(self):
|
||||
self.return_prev = True
|
||||
self.done = False
|
||||
|
||||
def get_tags(self, bracket_code):
|
||||
if self.done:
|
||||
return
|
||||
if self.return_prev:
|
||||
self.return_prev = False
|
||||
yield self.prev_match
|
||||
for m in self.pattern.finditer(self.bfr, self.start, self.end):
|
||||
name = m.group(1).lower()
|
||||
if not self.match_type:
|
||||
single = bool(m.group(3) != "" or name in single_tags)
|
||||
self_closing = name in self_closing_tags or name.startswith("cf")
|
||||
else:
|
||||
single = False
|
||||
self_closing = False
|
||||
start = m.start(0)
|
||||
end = m.end(0)
|
||||
if not self.scope_check(start):
|
||||
self.prev_match = TagEntry(start, end, name, self_closing, single)
|
||||
self.start = end
|
||||
yield self.prev_match
|
||||
self.done = True
|
||||
|
||||
|
||||
class TagMatch(object):
|
||||
def __init__(self, view, bfr, threshold, first, second, center, mode):
|
||||
self.view = view
|
||||
self.bfr = bfr
|
||||
self.mode = mode
|
||||
tag, tag_type, tag_end = self.get_first_tag(first[0])
|
||||
self.left, self.right = None, None
|
||||
self.window = None
|
||||
self.no_tag = False
|
||||
if tag and first[0] < center < tag_end:
|
||||
if tag.single:
|
||||
self.left = tag
|
||||
self.right = tag
|
||||
else:
|
||||
if tag_type == "open":
|
||||
self.left = tag
|
||||
self.window = (tag_end, len(bfr) if threshold is None else threshold[1])
|
||||
else:
|
||||
self.right = tag
|
||||
self.window = (0 if threshold is None else threshold[0], first[0])
|
||||
else:
|
||||
self.left = first
|
||||
self.right = second
|
||||
self.no_tag = True
|
||||
|
||||
def get_first_tag(self, offset):
|
||||
tag = None
|
||||
tag_type = None
|
||||
self_closing = False
|
||||
single = False
|
||||
m = START_TAG[self.mode].match(self.bfr[offset:])
|
||||
end = None
|
||||
if m:
|
||||
name = m.group(1).lower()
|
||||
single = bool(m.group(3) != "" or name in single_tags)
|
||||
if self.mode == "html":
|
||||
self_closing = name in self_closing_tags
|
||||
elif self.mode == "cfml":
|
||||
self_closing = name in self_closing_tags or name.startswith("cf")
|
||||
start = m.start(0) + offset
|
||||
end = m.end(0) + offset
|
||||
tag = TagEntry(start, end, name, self_closing, single)
|
||||
tag_type = "open"
|
||||
self.center = end
|
||||
else:
|
||||
m = END_TAG.match(self.bfr[offset:])
|
||||
if m:
|
||||
name = m.group(1).lower()
|
||||
start = m.start(0) + offset
|
||||
end = m.end(0) + offset
|
||||
tag = TagEntry(start, end, name, self_closing, single)
|
||||
tag_type = "close"
|
||||
self.center = offset
|
||||
return tag, tag_type, end
|
||||
|
||||
def compare_tags(self, left, right):
|
||||
return left.name == right.name
|
||||
|
||||
def resolve_self_closing(self, stack, c):
|
||||
found_tag = None
|
||||
b = stack[-1]
|
||||
if self.compare_tags(b, c):
|
||||
found_tag = b
|
||||
stack.pop()
|
||||
else:
|
||||
while b is not None and b.self_closing:
|
||||
stack.pop()
|
||||
if len(stack):
|
||||
b = stack[-1]
|
||||
if self.compare_tags(b, c):
|
||||
found_tag = b
|
||||
stack.pop()
|
||||
break
|
||||
else:
|
||||
b = None
|
||||
return found_tag
|
||||
|
||||
def match(self):
|
||||
stack = []
|
||||
|
||||
# No tags to search for
|
||||
if self.no_tag or (self.left and self.right):
|
||||
return self.left, self.right
|
||||
|
||||
# Init tag matching objects
|
||||
osearch = TagSearch(self.view, self.bfr, self.window, self.center, START_TAG[self.mode], 0)
|
||||
csearch = TagSearch(self.view, self.bfr, self.window, self.center, END_TAG, 1)
|
||||
|
||||
# Searching for opening or closing tag to match
|
||||
match_type = 0 if self.right else 1
|
||||
|
||||
# Match the tags
|
||||
for c in csearch.get_tags(match_type):
|
||||
if len(stack) and osearch.done:
|
||||
if self.resolve_self_closing(stack, c):
|
||||
continue
|
||||
for o in osearch.get_tags(match_type):
|
||||
if o.end <= c.begin:
|
||||
if not o.single:
|
||||
stack.append(o)
|
||||
continue
|
||||
else:
|
||||
osearch.remember()
|
||||
break
|
||||
|
||||
if len(stack):
|
||||
if self.resolve_self_closing(stack, c):
|
||||
continue
|
||||
elif match_type == 0 and not osearch.done:
|
||||
continue
|
||||
if match_type == 1:
|
||||
if self.left is None or self.compare_tags(self.left, c):
|
||||
self.right = c
|
||||
elif self.left.self_closing:
|
||||
self.right = self.left
|
||||
break
|
||||
|
||||
if match_type == 0:
|
||||
# Find the rest of the the unmatched left side open brackets
|
||||
# approaching the cursor if all closing brackets were matched
|
||||
# Select the most recent open bracket on the stack.
|
||||
for o in osearch.get_tags(0):
|
||||
if not o.single:
|
||||
stack.append(o)
|
||||
if len(stack):
|
||||
self.left = self.resolve_self_closing(stack, self.right)
|
||||
elif self.right is None and self.left is not None and self.left.self_closing:
|
||||
# Account for the opening tag that was found being a self closing
|
||||
self.right = self.left
|
||||
|
||||
return self.left, self.right
|
@@ -0,0 +1,140 @@
|
||||
import sublime
|
||||
from os.path import normpath, join
|
||||
import imp
|
||||
from collections import namedtuple
|
||||
import sys
|
||||
import traceback
|
||||
import warnings
|
||||
|
||||
|
||||
class BracketRegion (namedtuple('BracketRegion', ['begin', 'end'], verbose=False)):
|
||||
"""
|
||||
Bracket Regions for plugins
|
||||
"""
|
||||
|
||||
def move(self, begin, end):
|
||||
"""
|
||||
Move bracket region to different points
|
||||
"""
|
||||
|
||||
return self._replace(begin=begin, end=end)
|
||||
|
||||
def size(self):
|
||||
"""
|
||||
Get the size of the region
|
||||
"""
|
||||
|
||||
return abs(self.begin - self.end)
|
||||
|
||||
def toregion(self):
|
||||
"""
|
||||
Convert to sublime region
|
||||
"""
|
||||
|
||||
return sublime.Region(self.begin, self.end)
|
||||
|
||||
|
||||
def is_bracket_region(obj):
|
||||
"""
|
||||
Check if object is a BracketRegion
|
||||
"""
|
||||
|
||||
return isinstance(obj, BracketRegion)
|
||||
|
||||
|
||||
class ImportModule(object):
|
||||
@classmethod
|
||||
def import_module(cls, module_name, loaded=None):
|
||||
# Pull in built-in and custom plugin directory
|
||||
if module_name.startswith("bh_modules."):
|
||||
path_name = join(sublime.packages_path(), "BracketHighlighter", normpath(module_name.replace('.', '/')))
|
||||
else:
|
||||
path_name = join(sublime.packages_path(), normpath(module_name.replace('.', '/')))
|
||||
path_name += ".py"
|
||||
if loaded is not None and module_name in loaded:
|
||||
module = sys.modules[module_name]
|
||||
else:
|
||||
with warnings.catch_warnings(record=True) as w:
|
||||
# Ignore warnings about plugin folder not being a python package
|
||||
warnings.simplefilter("always")
|
||||
module = imp.new_module(module_name)
|
||||
sys.modules[module_name] = module
|
||||
source = None
|
||||
with open(path_name) as f:
|
||||
source = f.read().replace('\r', '')
|
||||
cls.__execute_module(source, module_name)
|
||||
w = filter(lambda i: issubclass(i.category, UserWarning), w)
|
||||
return module
|
||||
|
||||
@classmethod
|
||||
def __execute_module(cls, source, module_name):
|
||||
exec(compile(source, module_name, 'exec'), sys.modules[module_name].__dict__)
|
||||
|
||||
@classmethod
|
||||
def import_from(cls, module_name, attribute):
|
||||
return getattr(cls.import_module(module_name), attribute)
|
||||
|
||||
|
||||
class BracketPlugin(object):
|
||||
"""
|
||||
Class for preparing and running plugins
|
||||
"""
|
||||
|
||||
def __init__(self, plugin, loaded):
|
||||
"""
|
||||
Load plugin module
|
||||
"""
|
||||
|
||||
self.enabled = False
|
||||
self.args = plugin['args'] if ("args" in plugin) else {}
|
||||
self.plugin = None
|
||||
if 'command' in plugin:
|
||||
plib = plugin['command']
|
||||
try:
|
||||
module = ImportModule.import_module(plib, loaded)
|
||||
self.plugin = getattr(module, 'plugin')()
|
||||
loaded.add(plib)
|
||||
self.enabled = True
|
||||
except Exception:
|
||||
print 'BracketHighlighter: Load Plugin Error: %s\n%s' % (plugin['command'], traceback.format_exc())
|
||||
|
||||
def is_enabled(self):
|
||||
"""
|
||||
Check if plugin is enabled
|
||||
"""
|
||||
|
||||
return self.enabled
|
||||
|
||||
def run_command(self, view, name, left, right, selection):
|
||||
"""
|
||||
Load arguments into plugin and run
|
||||
"""
|
||||
|
||||
plugin = self.plugin()
|
||||
setattr(plugin, "left", left)
|
||||
setattr(plugin, "right", right)
|
||||
setattr(plugin, "view", view)
|
||||
setattr(plugin, "selection", selection)
|
||||
edit = view.begin_edit()
|
||||
self.args["edit"] = edit
|
||||
self.args["name"] = name
|
||||
try:
|
||||
plugin.run(**self.args)
|
||||
left, right, selection = plugin.left, plugin.right, plugin.selection
|
||||
except Exception:
|
||||
print "BracketHighlighter: Plugin Run Error:\n%s" % str(traceback.format_exc())
|
||||
view.end_edit(edit)
|
||||
return left, right, selection
|
||||
|
||||
|
||||
class BracketPluginCommand(object):
|
||||
"""
|
||||
Bracket Plugin base class
|
||||
"""
|
||||
|
||||
def run(self, bracket, content, selection):
|
||||
"""
|
||||
Runs the plugin class
|
||||
"""
|
||||
|
||||
pass
|
@@ -0,0 +1,51 @@
|
||||
import sublime_plugin
|
||||
from collections import namedtuple
|
||||
|
||||
MENU = namedtuple("Menu", "simple content block block_indent")(
|
||||
"Remove Brackets",
|
||||
"Remove Brackets and Content",
|
||||
"Remove Brackets: Block",
|
||||
"Remove Brackets: Indented Block"
|
||||
)
|
||||
|
||||
|
||||
class BhRemoveBracketsCommand(sublime_plugin.WindowCommand):
|
||||
"""
|
||||
Command to remove current highlighted brackets and optionally content
|
||||
"""
|
||||
|
||||
def remove_brackets(self, value):
|
||||
"""
|
||||
Perform removal of brackets
|
||||
"""
|
||||
|
||||
if value != -1:
|
||||
menu_item = MENU[value]
|
||||
indent = menu_item == MENU.block_indent
|
||||
block = menu_item == MENU.block or menu_item == MENU.block_indent
|
||||
content = menu_item == MENU.content
|
||||
|
||||
self.window.run_command(
|
||||
"bh_key",
|
||||
{
|
||||
"plugin": {
|
||||
"type": ["__all__"],
|
||||
"command": "bh_modules.bracketremove",
|
||||
"args": {
|
||||
"remove_indent": indent,
|
||||
"remove_block": block,
|
||||
"remove_content": content
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
def run(self):
|
||||
"""
|
||||
Show menu of removal options
|
||||
"""
|
||||
|
||||
self.window.show_quick_panel(
|
||||
list(MENU),
|
||||
self.remove_brackets
|
||||
)
|
@@ -0,0 +1,44 @@
|
||||
import sublime_plugin
|
||||
import bh_wrapping
|
||||
|
||||
|
||||
class SwapBrackets(bh_wrapping.WrapBrackets):
|
||||
def wrap(self, wrap_entry):
|
||||
if wrap_entry < 0:
|
||||
return
|
||||
|
||||
self._style = ["inline"]
|
||||
|
||||
self.brackets = self._brackets[wrap_entry]
|
||||
self.wrap_brackets(0)
|
||||
|
||||
|
||||
class SwapBracketsCommand(sublime_plugin.WindowCommand):
|
||||
def swap_brackets(self, value):
|
||||
if value < 0:
|
||||
return
|
||||
|
||||
self.brackets = self.wrap._brackets[value]
|
||||
|
||||
self.window.run_command(
|
||||
"bh_key",
|
||||
{
|
||||
"plugin": {
|
||||
"type": ["__all__"],
|
||||
"command": "bh_modules.swapbrackets"
|
||||
}
|
||||
}
|
||||
)
|
||||
self.wrap.wrap(value)
|
||||
|
||||
def run(self):
|
||||
view = self.window.active_view()
|
||||
if view is None:
|
||||
return
|
||||
self.wrap = SwapBrackets(view, "bh_swapping.sublime-settings", "swapping")
|
||||
|
||||
if len(self.wrap._menu):
|
||||
self.window.show_quick_panel(
|
||||
self.wrap._menu,
|
||||
self.swap_brackets
|
||||
)
|
@@ -0,0 +1,46 @@
|
||||
{
|
||||
"swapping": [
|
||||
{
|
||||
"enabled": true, "language_list": [], "language_filter": "whitelist", "entries": [
|
||||
{"name": "<> Angle", "brackets": ["<", ">${BH_SEL}"]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled": true, "language_list": ["Plain text"], "language_filter": "blacklist", "entries": [
|
||||
{"name": "{} Curly", "brackets": ["{", "}${BH_SEL}"]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled": true, "language_list": ["Plain text"], "language_filter": "blacklist", "entries": [
|
||||
{"name": "() Round", "brackets": ["(", ")${BH_SEL}"]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled": true, "language_list": ["Plain text"], "language_filter": "blacklist", "entries": [
|
||||
{"name": "[] Square", "brackets": ["[", "]${BH_SEL}"]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled": true, "language_list": ["HTML", "HTML 5", "XML", "PHP", "HTML+CFML", "ColdFusion", "ColdFusionCFC"], "language_filter": "whitelist", "entries": [
|
||||
{"name": "HTML/XML Tag", "brackets": ["<${BH_SEL:NAME}>", "</${BH_SEL:NAME}>"]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled": true, "language_list": ["Markdown"], "language_filter": "whitelist", "entries": [
|
||||
{"name": "Mardown: Bold", "brackets": ["**", "**${BH_SEL}"]},
|
||||
{"name": "Mardown: Italic", "brackets": ["_", "_${BH_SEL}"]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled": true, "language_list": ["C++", "C"], "language_filter": "whitelist", "entries": [
|
||||
{"name": "C/C++: #if", "brackets": ["#if ${BH_SEL}", "#endif"]},
|
||||
{"name": "C/C++: #if, #else", "brackets": ["#if${BH_SEL}", "#else\n${BH_TAB:/* CODE */}\n#endif"]},
|
||||
{"name": "C/C++: #if, #elif", "brackets": ["#if${BH_SEL}", "#elif ${BH_TAB:/* CONDITION */}\n${BH_TAB:/* CODE */}\n#endif"]},
|
||||
{"name": "C/C++: #ifdef", "brackets": ["#ifdef${BH_SEL}", "#endif"]},
|
||||
{"name": "C/C++: #ifdef, #else", "brackets": ["#ifdef${BH_SEL}", "#else\n${BH_TAB:/* CODE */}\n#endif"]},
|
||||
{"name": "C/C++: #ifndef", "brackets": ["#ifndef${BH_SEL}", "#endif"]},
|
||||
{"name": "C/C++: #ifndef, #else", "brackets": ["#ifndef${BH_SEL}", "#else\n${BH_TAB:/* CODE */}\n#endif"]}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
@@ -0,0 +1,368 @@
|
||||
import sublime
|
||||
import sublime_plugin
|
||||
from os.path import basename
|
||||
import re
|
||||
|
||||
|
||||
BH_TABSTOPS = re.compile(r"(\$\{BH_(SEL|TAB)(?:\:([^\}]+))?\})")
|
||||
TAB_REGION = "bh_plugin_wrapping_tabstop"
|
||||
SEL_REGION = "bh_plugin_wrapping_select"
|
||||
OUT_REGION = "bh_plugin_wrapping_outlier"
|
||||
|
||||
VALID_INSERT_STYLES = (
|
||||
("inline", "Inline Insert"),
|
||||
("block", "Block Insert"),
|
||||
("indent_block", "Indented Block Insert")
|
||||
)
|
||||
|
||||
|
||||
def exclude_entry(enabled, filter_type, language_list, language):
|
||||
"""
|
||||
Exclude bracket wrapping entry by filter
|
||||
"""
|
||||
|
||||
exclude = True
|
||||
if enabled:
|
||||
# Black list languages
|
||||
if filter_type == 'blacklist':
|
||||
exclude = False
|
||||
if language != None:
|
||||
for item in language_list:
|
||||
if language == item.lower():
|
||||
exclude = True
|
||||
break
|
||||
#White list languages
|
||||
elif filter_type == 'whitelist':
|
||||
if language != None:
|
||||
for item in language_list:
|
||||
if language == item.lower():
|
||||
exclude = False
|
||||
break
|
||||
return exclude
|
||||
|
||||
|
||||
class TextInsertion(object):
|
||||
"""
|
||||
Wrapper class for inserting text
|
||||
"""
|
||||
|
||||
def __init__(self, view, edit):
|
||||
"""
|
||||
Store view and edit objects
|
||||
"""
|
||||
|
||||
self.view = view
|
||||
self.edit = edit
|
||||
|
||||
def insert(self, pt, text):
|
||||
"""
|
||||
Peform insertion
|
||||
"""
|
||||
|
||||
return self.view.insert(self.edit, pt, text)
|
||||
|
||||
|
||||
class WrapBrackets(object):
|
||||
"""
|
||||
Wrap the current selection(s) with the defined wrapping options
|
||||
"""
|
||||
|
||||
def __init__(self, view, setting_file, attribute):
|
||||
self.view = view
|
||||
self._menu = []
|
||||
self._brackets = []
|
||||
self._insert = []
|
||||
self._style = []
|
||||
self.read_wrap_entries(setting_file, attribute)
|
||||
|
||||
def inline(self, edit, sel):
|
||||
"""
|
||||
Inline wrap
|
||||
"""
|
||||
|
||||
ti = TextInsertion(self.view, edit)
|
||||
|
||||
offset1 = ti.insert(sel.begin(), self.brackets[0])
|
||||
self.insert_regions.append(sublime.Region(sel.begin(), sel.begin() + offset1))
|
||||
offset2 = ti.insert(sel.end() + offset1, self.brackets[1])
|
||||
self.insert_regions.append(sublime.Region(sel.end() + offset1, sel.end() + offset1 + offset2))
|
||||
|
||||
def block(self, edit, sel, indent=False):
|
||||
"""
|
||||
Wrap brackets around selection and block off the content
|
||||
"""
|
||||
|
||||
# Calculate number of lines between brackets
|
||||
self.calculate_lines(sel)
|
||||
# Calculate the current indentation of first bracket
|
||||
self.calculate_indentation(sel)
|
||||
|
||||
ti = TextInsertion(self.view, edit)
|
||||
|
||||
line_offset = 0
|
||||
first_end = 0
|
||||
second_end = 0
|
||||
second_start = sel.end()
|
||||
|
||||
for b in reversed(self.brackets[1].split('\n')):
|
||||
second_end += ti.insert(sel.end(), "\n" + self.indent_to_col + b)
|
||||
num_open_lines = self.brackets[0].count('\n')
|
||||
for b in reversed(self.brackets[0].split('\n')):
|
||||
if line_offset == num_open_lines:
|
||||
line = b + "\n"
|
||||
else:
|
||||
line = self.indent_to_col + b + "\n"
|
||||
first_end += ti.insert(sel.begin(), line)
|
||||
line_offset += 1
|
||||
self.insert_regions.append(sublime.Region(sel.begin(), sel.begin() + first_end))
|
||||
|
||||
if indent:
|
||||
second_start += self.indent_content(ti, line_offset)
|
||||
else:
|
||||
pt = self.view.text_point(self.first_line + line_offset, 0)
|
||||
second_start += ti.insert(pt, self.indent_to_col)
|
||||
|
||||
self.insert_regions.append(sublime.Region(first_end + second_start, first_end + second_start + second_end))
|
||||
|
||||
def indent_content(self, ti, line_offset):
|
||||
"""
|
||||
Indent the block content
|
||||
"""
|
||||
|
||||
first = True
|
||||
offset = 0
|
||||
for l in range(line_offset, self.total_lines + line_offset):
|
||||
pt = self.view.text_point(self.first_line + l, 0)
|
||||
if first:
|
||||
offset += ti.insert(pt, self.indent_to_col + "\t")
|
||||
first = False
|
||||
else:
|
||||
offset += ti.insert(pt, "\t")
|
||||
return offset
|
||||
|
||||
def calculate_lines(self, sel):
|
||||
"""
|
||||
Calculate lines between brackets
|
||||
"""
|
||||
|
||||
self.first_line, self.col_position = self.view.rowcol(sel.begin())
|
||||
last_line = self.view.rowcol(sel.end())[0]
|
||||
self.total_lines = last_line - self.first_line + 1
|
||||
|
||||
def calculate_indentation(self, sel):
|
||||
"""
|
||||
Calculate how much lines should be indented
|
||||
"""
|
||||
|
||||
tab_size = self.view.settings().get("tab_size", 4)
|
||||
tab_count = self.view.substr(sublime.Region(sel.begin() - self.col_position, sel.begin())).count('\t')
|
||||
spaces = self.col_position - tab_count
|
||||
self.indent_to_col = "\t" * tab_count + "\t" * (spaces / tab_size) + " " * (spaces % tab_size if spaces >= tab_size else spaces)
|
||||
|
||||
def select(self, edit):
|
||||
"""
|
||||
Select defined regions after wrapping
|
||||
"""
|
||||
|
||||
self.view.sel().clear()
|
||||
map(lambda x: self.view.sel().add(x), self.insert_regions)
|
||||
|
||||
final_sel = []
|
||||
initial_sel = []
|
||||
for s in self.view.sel():
|
||||
string = self.view.substr(s)
|
||||
matches = [m for m in BH_TABSTOPS.finditer(string)]
|
||||
multi_offset = 0
|
||||
if matches:
|
||||
for m in matches:
|
||||
r = sublime.Region(s.begin() + multi_offset + m.start(1), s.begin() + multi_offset + m.end(1))
|
||||
if m.group(3):
|
||||
replace = m.group(3)
|
||||
self.view.erase(edit, r)
|
||||
added = self.view.insert(edit, r.begin(), replace)
|
||||
final_sel.append(sublime.Region(s.begin() + multi_offset + m.start(1), s.begin() + multi_offset + m.start(1) + added))
|
||||
multi_offset += added - r.size()
|
||||
else:
|
||||
self.view.erase(edit, r)
|
||||
final_sel.append(sublime.Region(s.begin() + multi_offset + m.start(1)))
|
||||
multi_offset -= r.size()
|
||||
if m.group(2) == "SEL":
|
||||
initial_sel.append(final_sel[-1])
|
||||
|
||||
if len(initial_sel) != len(final_sel):
|
||||
self.view.add_regions(TAB_REGION, final_sel, "", "", sublime.HIDDEN)
|
||||
|
||||
# Re-position cursor
|
||||
self.view.sel().clear()
|
||||
if len(initial_sel):
|
||||
map(lambda x: self.view.sel().add(x), initial_sel)
|
||||
elif len(final_sel):
|
||||
self.view.sel().add(final_sel[0])
|
||||
|
||||
def read_wrap_entries(self, setting_file, attribute):
|
||||
"""
|
||||
Read wrap entries from the settings file
|
||||
"""
|
||||
|
||||
settings = sublime.load_settings(setting_file)
|
||||
syntax = self.view.settings().get('syntax')
|
||||
language = basename(syntax).replace('.tmLanguage', '').lower() if syntax != None else "plain text"
|
||||
wrapping = settings.get(attribute, [])
|
||||
for i in wrapping:
|
||||
if not exclude_entry(i["enabled"], i["language_filter"], i["language_list"], language):
|
||||
for j in i.get("entries", []):
|
||||
try:
|
||||
menu_entry = j["name"]
|
||||
bracket_entry = j["brackets"]
|
||||
insert_style = j.get("insert_style", ["inline"])
|
||||
self._menu.append(menu_entry)
|
||||
self._brackets.append(bracket_entry)
|
||||
self._insert.append(insert_style)
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
def wrap_brackets(self, value):
|
||||
"""
|
||||
Wrap selection(s) with defined brackets
|
||||
"""
|
||||
|
||||
if value < 0:
|
||||
return
|
||||
|
||||
# Use new edit object since the main run has already exited
|
||||
# and the old edit is more than likely closed now
|
||||
edit = self.view.begin_edit()
|
||||
|
||||
# Wrap selections with brackets
|
||||
style = self._style[value]
|
||||
self.insert_regions = []
|
||||
|
||||
for sel in self.view.sel():
|
||||
# Determine indentation style
|
||||
if style == "indent_block":
|
||||
self.block(edit, sel, True)
|
||||
elif style == "block":
|
||||
self.block(edit, sel)
|
||||
else:
|
||||
self.inline(edit, sel)
|
||||
|
||||
self.select(edit)
|
||||
|
||||
self.view.end_edit(edit)
|
||||
|
||||
def wrap_style(self, value):
|
||||
"""
|
||||
Choose insert style for wrapping.
|
||||
"""
|
||||
|
||||
if value < 0:
|
||||
return
|
||||
|
||||
style = []
|
||||
|
||||
self.brackets = self._brackets[value]
|
||||
for s in VALID_INSERT_STYLES:
|
||||
if s[0] in self._insert[value]:
|
||||
self._style.append(s[0])
|
||||
style.append(s[1])
|
||||
|
||||
if len(style) > 1:
|
||||
self.view.window().show_quick_panel(
|
||||
style,
|
||||
self.wrap_brackets
|
||||
)
|
||||
else:
|
||||
self.wrap_brackets(0)
|
||||
|
||||
|
||||
class WrapBracketsCommand(sublime_plugin.TextCommand, WrapBrackets):
|
||||
def run(self, edit):
|
||||
"""
|
||||
Display the wrapping menu
|
||||
"""
|
||||
|
||||
self._menu = []
|
||||
self._brackets = []
|
||||
self._insert = []
|
||||
self._style = []
|
||||
self.read_wrap_entries("bh_wrapping.sublime-settings", "wrapping")
|
||||
|
||||
if len(self._menu):
|
||||
self.view.window().show_quick_panel(
|
||||
self._menu,
|
||||
self.wrap_style
|
||||
)
|
||||
|
||||
|
||||
class BhNextWrapSelCommand(sublime_plugin.TextCommand):
|
||||
"""
|
||||
Navigate wrapping tab stop regions
|
||||
"""
|
||||
|
||||
def run(self, edit):
|
||||
"""
|
||||
Look for the next wrapping tab stop region
|
||||
"""
|
||||
|
||||
regions = self.view.get_regions(SEL_REGION) + self.view.get_regions(OUT_REGION)
|
||||
if len(regions):
|
||||
self.view.sel().clear()
|
||||
map(lambda x: self.view.sel().add(x), regions)
|
||||
|
||||
# Clean up unneed sections
|
||||
self.view.erase_regions(SEL_REGION)
|
||||
self.view.erase_regions(OUT_REGION)
|
||||
|
||||
|
||||
class BhWrapListener(sublime_plugin.EventListener):
|
||||
"""
|
||||
Listen for wrapping tab stop tabbing
|
||||
"""
|
||||
|
||||
def on_query_context(self, view, key, operator, operand, match_all):
|
||||
"""
|
||||
Mark the next regions to navigate to.
|
||||
"""
|
||||
|
||||
accept_query = False
|
||||
if key == "bh_wrapping":
|
||||
select = []
|
||||
outlier = []
|
||||
regions = view.get_regions(TAB_REGION)
|
||||
tabstop = []
|
||||
sels = view.sel()
|
||||
|
||||
if len(regions) == 0:
|
||||
return False
|
||||
|
||||
for s in sels:
|
||||
count = 0
|
||||
found = False
|
||||
for r in regions[:]:
|
||||
if found:
|
||||
select.append(r)
|
||||
tabstop.append(r)
|
||||
del regions[count]
|
||||
break
|
||||
if r.begin() <= s.begin() <= r.end():
|
||||
del regions[count]
|
||||
found = True
|
||||
continue
|
||||
count += 1
|
||||
if not found:
|
||||
outlier.append(s)
|
||||
tabstop += regions
|
||||
|
||||
if len(tabstop) == len(select):
|
||||
if len(tabstop):
|
||||
tabstop = []
|
||||
accept_query = True
|
||||
elif len(tabstop) != 0:
|
||||
accept_query = True
|
||||
|
||||
# Mark regions to make the "next" command aware of what to do
|
||||
view.add_regions(SEL_REGION, select, "", "", sublime.HIDDEN)
|
||||
view.add_regions(OUT_REGION, outlier, "", "", sublime.HIDDEN)
|
||||
view.add_regions(TAB_REGION, tabstop, "", "", sublime.HIDDEN)
|
||||
|
||||
return accept_query
|
@@ -0,0 +1,71 @@
|
||||
{
|
||||
"wrapping": [
|
||||
{
|
||||
"enabled": true, "language_list": [], "language_filter": "whitelist", "entries": [
|
||||
{"name": "<> Angle", "brackets": ["<", ">${BH_SEL}"]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled": true, "language_list": ["Plain text"], "language_filter": "blacklist", "entries": [
|
||||
{"name": "{} Curly", "brackets": ["{", "}${BH_SEL}"]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled": true, "language_list": ["Plain text"], "language_filter": "blacklist", "entries": [
|
||||
{"name": "() Round", "brackets": ["(", ")${BH_SEL}"]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled": true, "language_list": ["Plain text"], "language_filter": "blacklist", "entries": [
|
||||
{"name": "[] Square", "brackets": ["[", "]${BH_SEL}"]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled": true, "language_list": ["Plain text"], "language_filter": "blacklist", "entries": [
|
||||
{"name": "'' Single Quotes", "brackets": ["'", "'${BH_SEL}"], "insert_style": ["inline"]},
|
||||
{"name": "\"\" Double Quotes", "brackets": ["\"", "\"${BH_SEL}"], "insert_style": ["inline"]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled": true, "language_list": ["Python"], "language_filter": "whitelist", "entries": [
|
||||
{"name": "'''''' Triple Single Quotes", "brackets": ["'''", "'''${BH_SEL}"], "insert_style": ["inline", "block"]},
|
||||
{"name": "\"\"\"\"\"\" Triple Double Quotes", "brackets": ["\"\"\"", "\"\"\"${BH_SEL}"], "insert_style": ["inline", "block"]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled": true, "language_list": ["HTML", "HTML 5", "XML", "PHP", "HTML+CFML", "ColdFusion", "ColdFusionCFC"], "language_filter": "whitelist", "entries": [
|
||||
{"name": "HTML/XML Tag", "brackets": ["<${BH_SEL:NAME}>", "</${BH_SEL:NAME}>"], "insert_style": ["inline", "block", "indent_block"]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled": true, "language_list": ["Markdown"], "language_filter": "whitelist", "entries": [
|
||||
{"name": "Mardown: Bold", "brackets": ["**", "**${BH_SEL}"]},
|
||||
{"name": "Mardown: Italic", "brackets": ["_", "_${BH_SEL}"]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled": true, "language_list": ["C++", "C"], "language_filter": "whitelist", "entries": [
|
||||
{"name": "C/C++: #if", "brackets": ["#if ${BH_SEL:/* CONDITION */}", "#endif"], "insert_style": ["block"]},
|
||||
{"name": "C/C++: #if, #else", "brackets": ["#if ${BH_SEL:/* CONDITION */}", "#else\n${BH_TAB:/* CODE */}\n#endif"], "insert_style": ["block"]},
|
||||
{"name": "C/C++: #if, #elif", "brackets": ["#if ${BH_SEL:/* CONDITION */}", "#elif ${BH_TAB:/* CONDITION */}\n${BH_TAB:/* CODE */}\n#endif"], "insert_style": ["block"]},
|
||||
{"name": "C/C++: #ifdef", "brackets": ["#ifdef ${BH_SEL:/* DEFINE */}", "#endif"], "insert_style": ["block"]},
|
||||
{"name": "C/C++: #ifdef, #else", "brackets": ["#ifdef ${BH_SEL:/* DEFINE */}", "#else\n${BH_TAB:/* CODE */}\n#endif"], "insert_style": ["block"]},
|
||||
{"name": "C/C++: #ifndef", "brackets": ["#ifndef ${BH_SEL:/* DEFINE */}", "#endif"], "insert_style": ["block"]},
|
||||
{"name": "C/C++: #ifndef, #else", "brackets": ["#ifndef ${BH_SEL:/* DEFINE */}", "#else\n${BH_TAB:/* CODE */}\n#endif"], "insert_style": ["block"]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled": true, "language_list": ["Ruby"], "language_filter": "whitelist", "entries": [
|
||||
{"name": "Ruby: if", "brackets": ["if ${BH_SEL:CONDITION}", "end"], "insert_style": ["indent_block"]},
|
||||
{"name": "Ruby: until", "brackets": ["until ${BH_SEL:CONDITION}", "end"], "insert_style": ["indent_block"]},
|
||||
{"name": "Ruby: while", "brackets": ["while ${BH_SEL:CONDITION}", "end"], "insert_style": ["indent_block"]},
|
||||
{"name": "Ruby: def", "brackets": ["def ${BH_SEL:NAME}", "end"], "insert_style": ["indent_block"]}
|
||||
]
|
||||
},
|
||||
{
|
||||
"enabled": true, "language_list": ["CSS"], "language_filter": "whitelist", "entries": [
|
||||
{"name": "CSS: @group", "brackets": ["/* @group ${BH_SEL:NAME} */", "/* @end */"], "insert_style": ["block"]}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
After Width: | Height: | Size: 217 B |
After Width: | Height: | Size: 155 B |
After Width: | Height: | Size: 143 B |
After Width: | Height: | Size: 155 B |
After Width: | Height: | Size: 138 B |
After Width: | Height: | Size: 191 B |
After Width: | Height: | Size: 108 B |
After Width: | Height: | Size: 118 B |
After Width: | Height: | Size: 220 B |
After Width: | Height: | Size: 215 B |
After Width: | Height: | Size: 242 B |
After Width: | Height: | Size: 173 B |
After Width: | Height: | Size: 156 B |
After Width: | Height: | Size: 173 B |
After Width: | Height: | Size: 145 B |
After Width: | Height: | Size: 211 B |
After Width: | Height: | Size: 167 B |
After Width: | Height: | Size: 148 B |
After Width: | Height: | Size: 158 B |
After Width: | Height: | Size: 125 B |
After Width: | Height: | Size: 131 B |
After Width: | Height: | Size: 163 B |
After Width: | Height: | Size: 133 B |
After Width: | Height: | Size: 134 B |
After Width: | Height: | Size: 169 B |
After Width: | Height: | Size: 133 B |
After Width: | Height: | Size: 134 B |
After Width: | Height: | Size: 167 B |
After Width: | Height: | Size: 176 B |
After Width: | Height: | Size: 158 B |
After Width: | Height: | Size: 125 B |
After Width: | Height: | Size: 131 B |
After Width: | Height: | Size: 270 B |
After Width: | Height: | Size: 188 B |
After Width: | Height: | Size: 148 B |
After Width: | Height: | Size: 190 B |
After Width: | Height: | Size: 147 B |
After Width: | Height: | Size: 206 B |
After Width: | Height: | Size: 137 B |
After Width: | Height: | Size: 111 B |
After Width: | Height: | Size: 104 B |
After Width: | Height: | Size: 141 B |
After Width: | Height: | Size: 114 B |
After Width: | Height: | Size: 103 B |
After Width: | Height: | Size: 124 B |
After Width: | Height: | Size: 114 B |
After Width: | Height: | Size: 103 B |
After Width: | Height: | Size: 124 B |
After Width: | Height: | Size: 101 B |
After Width: | Height: | Size: 97 B |
After Width: | Height: | Size: 111 B |
After Width: | Height: | Size: 98 B |
After Width: | Height: | Size: 112 B |
After Width: | Height: | Size: 127 B |
After Width: | Height: | Size: 244 B |
After Width: | Height: | Size: 166 B |
After Width: | Height: | Size: 306 B |
After Width: | Height: | Size: 215 B |
@@ -0,0 +1 @@
|
||||
{"url": "https://github.com/facelessuser/BracketHighlighter", "version": "2013.03.27.09.00.08", "description": "Bracket and tag highlighter for Sublime Text 2"}
|
@@ -0,0 +1,470 @@
|
||||
# About
|
||||
This is a fork of pyparadigm's _SublimeBrackets_ and _SublimeTagmatcher_ (both are no longer available). I forked this to fix some issues I had and to add some features I wanted. I also wanted to improve the efficiency of the matching. This cuts down on the parallel searching that is now streamlined in one search. Since then, I have rewritten the entire code base to bring more flexibility, speed, and features.
|
||||
|
||||
<img src="http://dl.dropbox.com/u/342698/BracketHighlighter/Example1.png" border="0">
|
||||
|
||||
## Sublime Text 3 Support?
|
||||
ST3 support is found here (at the present time): https://github.com/facelessuser/BracketHighlighter/tree/BH2ST3
|
||||
|
||||
## Overview
|
||||
Bracket Highlighter matches a variety of brackets such as: ```[]```, ```()```, ```{}```, ```""```, ```''```, ```<tag></tag>```, and even custom brackets.
|
||||
|
||||
# FeatureList
|
||||
- Customizable to highlight almost any bracket
|
||||
- Customizable bracket highlight style
|
||||
- High visibility bracket highlight mode
|
||||
- Selectively disable or enable specific matching of tags, brackets, or quotes
|
||||
- Selectively whitelist or blacklist matching of specific tags, brackets, or quotes based on language
|
||||
- When bound to a shortcut, allow option to show line count and char count between match in the status bar
|
||||
- Highlight basic brackets within strings
|
||||
- Works with multi-select
|
||||
- Configurable custom gutter icons
|
||||
- Toggle bracket escape mode for string brackets (regex|string)
|
||||
- Bracket plugins that can jump between bracket ends, select content, remove brackets and/or content, wrap selectios with brackets, swap brackets, swap quotes (handling quote escaping between the main quotes), fold/unfold conent between brackets, toggle through tag attribute selecection, select both the opening and closing tag name to change both simultaneously.
|
||||
|
||||
# General Use
|
||||
In general BracketHighligher (BH) will automatically highlight brackets (or defined bracket like start and end blocks) its between. By default, BH will but opening and closing icons in the gutter of the corresponding line containing open or closising bracket. BH, by default, will underline the closing and opening bracket as well.
|
||||
|
||||
## Built-in Supported brackets
|
||||
Currently BH supports the following brackets out of the box:
|
||||
|
||||
- round
|
||||
- square
|
||||
- curly
|
||||
- angle
|
||||
- single and double quotes
|
||||
- python single and double quotes (unicode and raw)
|
||||
- python tripple single and double quotes (unicode and raw)
|
||||
- Javascript regex
|
||||
- Perl regex
|
||||
- Ruby regex
|
||||
- Markdown italic
|
||||
- Markdown bold
|
||||
- CSSedit groups
|
||||
- Ruby conditional statements
|
||||
- C/C++ compiler switches
|
||||
- PHP conditional keywords
|
||||
- Erlang conditional statements
|
||||
- HTML/ColdFusion/XML tags
|
||||
|
||||
BH also supports highlighting basic sub brackets ```(), [], {}``` within supported regex and strings.
|
||||
|
||||
## Additional Features
|
||||
BH has a couple of additonal features built-in.
|
||||
|
||||
### Toggle Global Enable (bh_toggle_enable)
|
||||
This command enables and disables BH globally
|
||||
|
||||
### Toggle String Bracket Escape Mode (bh_toggle_string_escape_mode)
|
||||
This toggles BH's recognition mode of escaped sub brackets in strings and regex. The modes are string escape mode and regex escape mode.
|
||||
|
||||
### Settings
|
||||
When changing settings, you should copy the entire ```bh_core.sublime-settings``` to your ```User``` folder before changing. Style and color will be discussed in greater depth in the ```Configuring Highlight Style``` section.
|
||||
|
||||
These are the basic settings you can change:
|
||||
```javascript
|
||||
//Debug logging
|
||||
"debug_enable": false,
|
||||
|
||||
// When only either the left or right bracket can be found
|
||||
// this defines if the unmatched bracket should be shown.
|
||||
"show_unmatched" : true,
|
||||
|
||||
// High visibilty style and color for high visibility mode
|
||||
// (solid|outline|underline)
|
||||
"high_visibility_style": "outline",
|
||||
// (scope|__default__|__bracket__)
|
||||
"high_visibility_color": "__bracket__",
|
||||
|
||||
// Match brackets only when the cursor is touching the inside of the bracket
|
||||
"match_only_adjacent": false,
|
||||
|
||||
// Character threshold to search
|
||||
"search_threshold": 5000,
|
||||
|
||||
// Set mode for string escapes to ignore (regex|string)
|
||||
"bracket_string_escape_mode": "string",
|
||||
|
||||
// Set max number of multi-select brackets that will be searched automatically
|
||||
"auto_selection_threshold" : 10,
|
||||
|
||||
// Disable gutter icons when doing multi-select
|
||||
"no_multi_select_icons": false,
|
||||
```
|
||||
|
||||
### Bracket Plugins
|
||||
Bh is also extendable via plugins and provides an number of plugins by default. See ```Bracket Plugins``` to learn more about the included plugins.
|
||||
|
||||
## Bracket Plugin
|
||||
BH provides a number of built in Bracket Plugins that take advantage of BH's matching to provide additional features. Most plugin features are available via the Tools->Packages->BracketHighlighter menu or the command palette. To see how to configure shortcuts, see the ```Example.sublime-settings``` file.
|
||||
|
||||
### Bracket Select Plugin
|
||||
This plugin changes the selection inside between the brackets. It can select the content or move the bracket to the opening and closing bracket. Behavior is slightly modified for tags.
|
||||
|
||||
### Bracket Remove Plugin
|
||||
Removes the surrounding brackets.
|
||||
|
||||
### Fold Bracket Plugin
|
||||
Folds the content of the current surrounding brackets.
|
||||
|
||||
### Swap Quotes Plugin
|
||||
Swap the quotes style of surrounding quotes from double to single or vice versa. It also handlings escaping and unescaping of sub quotes.
|
||||
|
||||
### Tag Plugin
|
||||
Plugin used to help highlight tags
|
||||
|
||||
Additional tag settings found in ```bh_core.sublime-settings```:
|
||||
```javascript
|
||||
/* Plugin settings */
|
||||
|
||||
// Style to use for matched tags
|
||||
"tag_style": "tag",
|
||||
|
||||
// Scopes to exclude from tag searches
|
||||
"tag_scope_exclude": ["string", "comment"],
|
||||
|
||||
// Determine which style of tag-matching to use in which syntax
|
||||
"tag_mode": {
|
||||
"xhtml": ["XML"],
|
||||
"html": ["HTML", "HTML 5", "PHP"],
|
||||
"cfml": ["HTML+CFML", "ColdFusion", "ColdFusionCFC"]
|
||||
}
|
||||
```
|
||||
|
||||
### Tag Attribute Select Plugin
|
||||
Cycle through selecting tag attributes of tags.
|
||||
|
||||
### Tag Name Select Plugin
|
||||
Select the opening and closing tag name of current tag.
|
||||
|
||||
### Bracket Wrapping Plugin
|
||||
Wrap the current selection with supported bracket of your choice. Wrapping definitions are configured in ```bh_wrapping.sublime-settings```.
|
||||
|
||||
### Bracket Swapping Plugin
|
||||
Swap the current surrounding bracket with supported bracket of your choice. Swapping definitions are configured in ```bh_swapping.sublime-settings```.
|
||||
|
||||
## Shortcuts
|
||||
By default BH provides no shortcuts to avoid shortcut conflicts, but you can view the included ```Example.sublime-keymaps``` file to get an idea how to set up your own.
|
||||
|
||||
# Customizing BracketHighligher
|
||||
BH is extremely flexible and be customized and extended to fit a User's needs. The first step is to copy the ```bh_core.sublime-settings``` to your ```User``` folder.
|
||||
|
||||
## Configuring Brackets
|
||||
BH has been written to allow users to define any brackets they would like to have highlighted. There are two kinds of brackets you can define ```scope_brackets``` (search file for scope regions and then use regex to test for opening and closing brackets) and ```brackets``` (use regex to find opening and closing brackets). ```bracket``` type should usually be the preferred type. ```scope_brackets``` are usually used for brackets whose opening and closing are the same and not distinguishable form one another by regex; scope brackets must be contained in a continuous scope region like string for quotes etc.
|
||||
|
||||
### Configuring Brackets
|
||||
Brackets are defined under ```brackets``` in ```bh_core.sublime-settings```.
|
||||
|
||||
Angle and Curly bracket will be used as an eample (not all options may be shown in these examples):
|
||||
|
||||
```javascript
|
||||
{
|
||||
"name": "angle",
|
||||
"open": "(<)",
|
||||
"close": "(>)",
|
||||
"style": "angle",
|
||||
"scope_exclude": ["string", "comment", "keyword.operator"],
|
||||
"language_filter": "whitelist",
|
||||
"language_list": ["HTML", "HTML 5", "XML", "PHP", "HTML+CFML", "ColdFusion", "ColdFusionCFC"],
|
||||
"plugin_library": "bh_modules.tags",
|
||||
"enabled": true
|
||||
},
|
||||
{
|
||||
"name": "curly",
|
||||
"open": "(\\{)",
|
||||
"close": "(\\})",
|
||||
"style": "curly",
|
||||
"scope_exclude": ["string", "comment"],
|
||||
"scope_exclude_exceptions": ["string.other.math.block.environment.latex"],
|
||||
"language_filter": "blacklist",
|
||||
"language_list": ["Plain text"],
|
||||
"find_in_sub_search": "true",
|
||||
"ignore_string_escape": true,
|
||||
"enabled": true
|
||||
},
|
||||
```
|
||||
|
||||
- **name**: the name of the bracket (should be unique)
|
||||
- **open**: defines the opening bracket (one and only one captureing group must be present)
|
||||
- **close**: defines the closing bracket (one and only one captureing group must be present)
|
||||
- **style**: Name of style definition to be used to highlight the brackets. See ```Configuring Bracket Styles``` for more info.
|
||||
- **scope_exclude**: Scopes where the opening and closing brackets should be ignored.
|
||||
- **language_filter**: This works in conjunction with ```language_list```. It specifies whether ```language_list``` is a ```blacklist``` or ```whitelist```.
|
||||
- **language_list**: an array of tmLanguage file names that should be avoided or included for highlighting. Looks to ```language_filter``` to determine if avoidance or inclusion is used.
|
||||
- **enabled**: disable or enable rule
|
||||
- **scope_exclude_exceptions (optional)***: used to ignore exluding of sub scopes such as in the curly example above where ```string``` is excluded, but not ```string.other.math.block.environment.latex```.
|
||||
- **plugin_library (optional)**: defines plugin to use for determining matches (see Bracket Plugin API for more info on matching plugins)
|
||||
- **find_in_sub_search (optional)**: this rule should be included when doing sub bracket matching in ```scope_brackets``` (like finding round brackets between quotes etc.). The setting must be as string and can be either (true|false|only); only means this bracket is only matched as a sub bracket of a ```scope_bracket```.
|
||||
- **ignore_string_escape (optional)**: Do not ignore sub brackets found in strings and regex when escaped, but use internal escape logic to determine if the brackets should be ignored based on whether regex or string escape mode is set.
|
||||
|
||||
### Configuring Scope Brackets
|
||||
Scope Brackets are defined under ```scope_brackets``` in ```bh_core.sublime-settings```.
|
||||
|
||||
Python Single Quote bracket will be used as an eample (not all options are shown in this example):
|
||||
|
||||
```javascript
|
||||
{
|
||||
"name": "py_single_quote",
|
||||
"open": "u?r?((?:'')?')",
|
||||
"close": "((?:'')?')",
|
||||
"style": "single_quote",
|
||||
"scopes": ["string"],
|
||||
"language_filter": "whitelist",
|
||||
"language_list": ["Python"],
|
||||
"sub_bracket_search": "true",
|
||||
"enabled": true
|
||||
},
|
||||
```
|
||||
|
||||
- **name**: the name of the bracket (should be unique)
|
||||
- **open**: defines the opening bracket (one and only one captureing group must be present)
|
||||
- **close**: defines the closing bracket (one and only one captureing group must be present)
|
||||
- **style**: Name of style definition to be used to highlight the brackets. See ```Configuring Bracket Styles``` for more info.
|
||||
- **scopes**: scope that should be searched to find the opening and closing brackets.
|
||||
- **language_filter**: This works in conjunction with ```language_list```. It specifies whether ```language_list``` is a ```blacklist``` or ```whitelist```.
|
||||
- **language_list**: an array of tmLanguage file names that should be avoided or included for highlighting. Looks to ```language_filter``` to determine if avoidance or inclusion is used.
|
||||
- **sub_bracket_search**: should this scope bracket also search for sub brackets (like curly brackets in strings etc.).
|
||||
- **enabled**: disable or enable rule
|
||||
- **plugin_library (optional)**: defines plugin to use for determining matches (see Bracket Plugin API for more info on matching plugins)
|
||||
|
||||
## Configuring Highlight Style
|
||||
Each bracket definition (described in ```Configuring Scope Brackets``` and ```Configuring Brackets```) has a ```style``` setting that you give a style definition to. Style definitions are defined under ```bracket_styles``` in ```bh_core.sublime-settings```.
|
||||
|
||||
There are two special style definitions whose names are reserved: ```default``` and ```unmatched```, but you can configure them. All other custom style definitions follow the same pattern (see ```curly``` below and compare to the special style defintions; format is the same) All custom styles follow this pattern. See description below:
|
||||
|
||||
```javascript
|
||||
// "default" style defines attributes that
|
||||
// will be used for any style that does not
|
||||
// explicitly define that attribute. So if
|
||||
// a style does not define a color, it will
|
||||
// use the color from the "default" style.
|
||||
"default": {
|
||||
"icon": "dot",
|
||||
"color": "brackethighlighter.default",
|
||||
"style": "underline"
|
||||
},
|
||||
|
||||
// This particular style is used to highlight
|
||||
// unmatched bracekt pairs. It is a special
|
||||
// style.
|
||||
"unmatched": {
|
||||
"icon": "question",
|
||||
// "color": "brackethighlighter.unmatched",
|
||||
"style": "outline"
|
||||
},
|
||||
// User defined region styles
|
||||
"curly": {
|
||||
"icon": "curly_bracket"
|
||||
// "color": "brackethighlighter.curly",
|
||||
// "style": "underline"
|
||||
},
|
||||
```
|
||||
|
||||
- **icon**: icon to show in gutter. Available options are (angle|round|curly|square|tag|star|dot|bookmark|question|quote|double_quote|single_quote|single_quote_offset|double_quote_offset|none)
|
||||
- **color**: scope to define color
|
||||
- **style**: higlight style. Available options are (solid|outline|underline|none)
|
||||
|
||||
As shown in the example above, if an option is omitted, it will use the setting in ```default```. So ```curly```, in this example, defines ```icon```, but will use ```default``` for the ```color``` and ```style```.
|
||||
|
||||
To customize the color for ```curly``` you can create your own custom scope.
|
||||
|
||||
Add this to your color scheme:
|
||||
```XML
|
||||
<dict>
|
||||
<key>name</key>
|
||||
<string>Bracket Curly</string>
|
||||
<key>scope</key>
|
||||
<string>brackethighlighter.curly</string>
|
||||
<key>settings</key>
|
||||
<dict>
|
||||
<key>foreground</key>
|
||||
<string>#CC99CC</string>
|
||||
</dict>
|
||||
</dict>
|
||||
```
|
||||
|
||||
And then use the scope:
|
||||
```javascript
|
||||
"curly": {
|
||||
"icon": "curly_bracket"
|
||||
"color": "brackethighlighter.curly",
|
||||
// "style": "underline"
|
||||
},
|
||||
```
|
||||
|
||||
# Bracket Plugin API
|
||||
There are two kinds of plugins that can be written ```definition``` plugins (plugins attached to bracket definitions via the ```plugin_library``` option) or ```run instance``` plugins (plugins that are that are fed in the BracketHighligher via the command parameter ```plugin```).
|
||||
|
||||
Bracket plugins use ```BracketRegions```. ```BracketRegions``` are simple objects containing a begin pt and end pt of a bracket.
|
||||
|
||||
Class:
|
||||
|
||||
- **BracketRegion(begin_pt, end_pt)**
|
||||
|
||||
Attributes of BracketRegion:
|
||||
|
||||
- **begin**: the start pt of the BracketRegion
|
||||
- **end**: the end pt of the BracketRegion
|
||||
|
||||
Methods of BracketRegion:
|
||||
|
||||
- **size()**: returns size of region
|
||||
- **move(begin_pt, end_pt)**: returns a new BracketRegion object with the points moved as specified by the parameters
|
||||
- **toregion**: returns a sublime Region() object
|
||||
|
||||
## 'Defintion' Plugins
|
||||
These are plugins that are attached to the bracket definition and aid in processing the brackets. These kids of plugins have two methods you can provide ```post_match``` and/or ```compare```.
|
||||
|
||||
### compare
|
||||
```compare``` is run when comparing the opening bracket with closing brackets. This allows you to provide logic to accept or regect a the pairing of an opening bracket with a closing bracket. You should not change the text in the view during this operation.
|
||||
|
||||
The ```compare``` method receives the following paramters:
|
||||
|
||||
- **name**: the name of the bracket definition being evaluated
|
||||
- **first**: a bracket region for the opening bracket
|
||||
- **second**: a bracket region for the closing bracket
|
||||
- **bfr**: the file buffer
|
||||
|
||||
Returns:
|
||||
|
||||
- **Boolean**: indicating whether the the comparison yields a suitable match
|
||||
|
||||
Example (from phphekywords.py):
|
||||
```python
|
||||
def compare(name, first, second, bfr):
|
||||
return "end" + bfr[first.begin:first.end].lower() == bfr[second.begin:second.end].lower()
|
||||
```
|
||||
|
||||
### post_match
|
||||
```post_match``` is run after the brackets have been matched. You can do things like alter the highlighting region and change the bracket_style if needed. You should not change the text in the view during this operation.
|
||||
|
||||
The ```post_match``` method receives the following parameters:
|
||||
|
||||
- **name**: the name of the bracket definition being evaluated
|
||||
- **style**: the style definition name that is to be used to highlight the region
|
||||
- **first**: a bracket region for the opening bracket
|
||||
- **second**: a bracket region for the closing bracket
|
||||
- **center**: position (pt) of cursor (in retrospect, probably not the most intuitive name; not sure why I named it such)
|
||||
- **bfr**: the file buffer
|
||||
- **threshold**: the calculated search window of the buffer that is being searched
|
||||
|
||||
Returns:
|
||||
|
||||
- **BracketRegion**: opening bracket region
|
||||
- **BracketRegion**: closing bracekt region
|
||||
- **style**: the name of the style definition to use
|
||||
|
||||
Example (from rubykeywords.py):
|
||||
```python
|
||||
import re
|
||||
|
||||
|
||||
def post_match(view, name, style, first, second, center, bfr, threshold):
|
||||
if first is not None:
|
||||
# Strip whitespace from the beginning of first bracket
|
||||
open_bracket = bfr[first.begin:first.end]
|
||||
if open_bracket != "do":
|
||||
m = re.match(r"^(\s*\b)[\w\W]*", open_bracket)
|
||||
if m:
|
||||
first = first.move(first.begin + m.end(1), first.end)
|
||||
return first, second, style
|
||||
```
|
||||
|
||||
Example (snippet from tags.py)
|
||||
```python
|
||||
def post_match(view, name, style, first, second, center, bfr, threshold):
|
||||
left, right = first, second
|
||||
threshold = [0, len(bfr)] if threshold is None else threshold
|
||||
tag_settings = sublime.load_settings("bh_core.sublime-settings")
|
||||
tag_mode = get_tag_mode(view, tag_settings.get("tag_mode", {}))
|
||||
tag_style = tag_settings.get("tag_style", "angle")
|
||||
bracket_style = style
|
||||
|
||||
if first is not None and tag_mode is not None:
|
||||
matcher = TagMatch(view, bfr, threshold, first, second, center, tag_mode)
|
||||
left, right = matcher.match()
|
||||
if not matcher.no_tag:
|
||||
bracket_style = tag_style
|
||||
|
||||
return left, right, bracket_style
|
||||
```
|
||||
|
||||
## Run Instance Plugins
|
||||
```Run instance``` plugins are fed into the command executing a BracketHighlighter match via the ```plugin``` parameter.
|
||||
|
||||
Example of run instance plugin getting called:
|
||||
```javascript
|
||||
// Go to left bracket
|
||||
{
|
||||
"caption": "BracketHighlighter: Jump to Left Bracket",
|
||||
"command": "bh_key",
|
||||
"args":
|
||||
{
|
||||
"lines" : true,
|
||||
"plugin":
|
||||
{
|
||||
"type": ["__all__"],
|
||||
"command": "bh_modules.bracketselect",
|
||||
"args": {"select": "left"}
|
||||
}
|
||||
}
|
||||
},
|
||||
```
|
||||
|
||||
The ```plugin``` paramter is a dictionary that contains 3 parameters to define what plugin should get run, with what arguments, and on what bracket defintion.
|
||||
|
||||
- **type**: an array containing the bracket definition names that the plugin should be run on. Use ```__all__``` for all bracket definitions.
|
||||
- **command**: the plugin to run. For internal plugins, they are referenced by ```bh_modules.<plugin name>```. For custom plugins, you should use the folder path releative to ```Packages```. So if I had a plugin called ```myplugin.py``` in my ```User``` folder, I would use ```User.myplugin```.
|
||||
- **args**: a dictionary contianing the arguments to feed into the plugin.
|
||||
|
||||
You create ```run instance``` plugins by deriving a class from the ```BracketPluginCommand``` class. Then you provide a method called ```plugin``` that returns the class.
|
||||
|
||||
Class:
|
||||
|
||||
- **BracketPluginCommand()**
|
||||
|
||||
Parameters of BracketPluginCommand:
|
||||
|
||||
- **edit**: sublime edit object
|
||||
- **name**: name of tag definition being evaluated
|
||||
|
||||
Attributes of BracketPluginCommand:
|
||||
|
||||
- **view**: the sublime view containg the bracket (don't change this)
|
||||
- **left**: a bracket region for the opening bracket (can be changed)
|
||||
- **right**: a bracket region for the closing bracket (can be changed)
|
||||
- **selection**: an array containing the selection that triggered the match (can be changed)
|
||||
|
||||
Methods of BracketPluginCommand:
|
||||
|
||||
- **run(edit, name, <args>)**: (edit is a sublime edit object and name is the bracket definition being evaluated)
|
||||
|
||||
Example (from foldbracket.py):
|
||||
```python
|
||||
import BracketHighlighter.bh_plugin as bh_plugin
|
||||
import sublime
|
||||
|
||||
|
||||
class FoldBrackets(bh_plugin.BracketPluginCommand):
|
||||
def run(self, edit, name):
|
||||
content = sublime.Region(self.left.end, self.right.begin)
|
||||
new_content = [content]
|
||||
if content.size() > 0:
|
||||
if self.view.fold(content) == False:
|
||||
new_content = self.view.unfold(content)
|
||||
self.selection = new_content
|
||||
|
||||
|
||||
def plugin():
|
||||
return FoldBrackets
|
||||
```
|
||||
|
||||
# Credits
|
||||
- pyparadigm: for his original efforts with SublimeBrackets and SublimeTagmatcher which originally BracketHighlighter was built off of and the inspiration behind the current implementation.
|
||||
- BoundInCode: for his Tag icon
|
||||
|
||||
# Version 2.0.0
|
||||
- Re-write of BracketHighlighter
|
||||
|
||||
# Version Older
|
||||
- See [Complete Changelog](https://github.com/facelessuser/BracketHighlighter/blob/BH2/CHANGELOG.md)
|