├── .gitignore ├── Autocompletion.sublime-commands ├── Default (Linux).sublime-keymap ├── Default (OSX).sublime-keymap ├── Default (Windows).sublime-keymap ├── autocompletion.py ├── demo ├── demo.js └── test.js ├── license.md ├── nesting.py ├── readme.md ├── utility.py └── word.py /.gitignore: -------------------------------------------------------------------------------- 1 | package-metadata.json 2 | *.pyc -------------------------------------------------------------------------------- /Autocompletion.sublime-commands: -------------------------------------------------------------------------------- 1 | [ 2 | // word (fuzzy) 3 | 4 | { 5 | "caption": "AutocompletionFuzzy: Complete word forward (fuzzy)", 6 | "command": "autocompletion", 7 | "args": { 8 | "backward": false, 9 | "handler": "AutocompletionFuzzy.word.create_fuzzy_completion", 10 | } 11 | }, 12 | 13 | { 14 | "caption": "AutocompletionFuzzy: Complete word backward (fuzzy)", 15 | "command": "autocompletion", 16 | "args": { 17 | "backward": true, 18 | "handler": "AutocompletionFuzzy.word.create_fuzzy_completion", 19 | } 20 | }, 21 | 22 | // word (not fuzzy) 23 | 24 | { 25 | "caption": "AutocompletionFuzzy: Complete word forward", 26 | "command": "autocompletion", 27 | "args": { 28 | "backward": false, 29 | "handler": "AutocompletionFuzzy.word.create_completion", 30 | } 31 | }, 32 | 33 | { 34 | "caption": "AutocompletionFuzzy: Complete word backward", 35 | "command": "autocompletion", 36 | "args": { 37 | "backward": true, 38 | "handler": "AutocompletionFuzzy.word.create_completion", 39 | } 40 | }, 41 | 42 | // subword 43 | 44 | { 45 | "caption": "AutocompletionFuzzy: Complete subword forward", 46 | "command": "autocompletion", 47 | "args": { 48 | "handler": "AutocompletionFuzzy.word.create_completion", 49 | "backward": false, 50 | "word": "[A-Z]?[a-z]+$|[A-Z]+$", 51 | "search": "(__WORD__(?:[a-z]+|[A-Z]+))" 52 | }, 53 | }, 54 | 55 | { 56 | "caption": "AutocompletionFuzzy: Complete subword backward", 57 | "command": "autocompletion", 58 | "args": { 59 | "handler": "AutocompletionFuzzy.word.create_completion", 60 | "backward": true, 61 | "word": "[A-Z]?[a-z]+$|[A-Z]+$", 62 | "search": "(__WORD__(?:[a-z]+|[A-Z]+))" 63 | } 64 | }, 65 | 66 | // long word (fuzzy) 67 | 68 | { 69 | "caption": "AutocompletionFuzzy: Complete long word forward (fuzzy)", 70 | "command": "autocompletion", 71 | "args": { 72 | "handler": "AutocompletionFuzzy.word.create_fuzzy_completion", 73 | "backward": false, 74 | "word": "[\\w\\.\\\\/]+((::|->)[\\w\\.\\\\/\\-]+)*$", 75 | "delimeter": "([\\w/\\-\\.$\\\\]|::|->)*", 76 | "last_delimeter": "([\\w/\\-\\.$\\\\]|::|->)*\\w", 77 | "search": "(?:[^\\w/]|^)([_\\\\]*__FUZZY__)", 78 | } 79 | }, 80 | 81 | { 82 | "caption": "AutocompletionFuzzy: Complete long word forward (fuzzy)", 83 | "command": "autocompletion", 84 | "args": { 85 | "backward": true, 86 | "handler": "AutocompletionFuzzy.word.create_fuzzy_completion", 87 | "word": "[\\w\\.\\\\/]+((::|->)[\\w\\.\\\\/\\-]+)*$", 88 | "delimeter": "([\\w/\\-\\.$\\\\]|::|->)*", 89 | "last_delimeter": "([\\w/\\-\\.$\\\\]|::|->)*\\w", 90 | "search": "(?:[^\\w/]|^)([_\\\\]*__FUZZY__)", 91 | } 92 | }, 93 | 94 | // long word (not fuzzy) 95 | 96 | { 97 | "caption": "AutocompletionFuzzy: Complete long word forward", 98 | "command": "autocompletion", 99 | "args": { 100 | "backward": false, 101 | "handler": "AutocompletionFuzzy.word.create_completion", 102 | "word": "[$\\w/\\.\\\\/]+((::|->)[\\w\\.\\\\/\\-]+)*$", 103 | "search": "(?:\\W|^)(__WORD__[$\\w\\.\\\\/]+((::|->)[\\w\\.\\\\/\\-$]+)*\\w)", 104 | } 105 | }, 106 | 107 | { 108 | "caption": "AutocompletionFuzzy: Complete long word backward", 109 | "args": { 110 | "backward": true, 111 | "handler": "AutocompletionFuzzy.word.create_completion", 112 | "word": "[$\\w\\.\\\\/]+((::|->)[\\w\\.\\\\/\\-]+)*$", 113 | "search": "(?:\\W|^)(__WORD__[$\\w\\.\\\\/]+((::|->)[\\w\\.\\\\/\\-$]+)*\\w)" 114 | } 115 | }, 116 | 117 | // nesting (fuzzy) 118 | 119 | { 120 | "caption": "AutocompletionFuzzy: Complete nesting forward (fuzzy)", 121 | "command": "autocompletion", 122 | "args": { 123 | "handler": "AutocompletionFuzzy.nesting.create_fuzzy_completion", 124 | "backward": false, 125 | } 126 | }, 127 | 128 | { 129 | "caption": "AutocompletionFuzzy: Complete nesting backward (fuzzy)", 130 | "command": "autocompletion", 131 | "args": { 132 | "handler": "AutocompletionFuzzy.nesting.create_fuzzy_completion", 133 | "b longackward": true, 134 | } 135 | }, 136 | 137 | // nesting (not fuzzy) 138 | 139 | { 140 | "caption": "AutocompletionFuzzy: Complete nesting forward", 141 | "command": "autocompletion", 142 | "args": { 143 | "handler long": "AutocompletionFuzzy.nesting.create_completion", 144 | "backward": false, 145 | } 146 | }, 147 | 148 | { 149 | "caption": "AutocompletionFuzzy: Complete nesting backward", 150 | "command": "autocompletion", 151 | "args": { 152 | "handler": "AutocompletionFuzzy.nesting.create_completion", 153 | "backward": true, 154 | } 155 | }, 156 | 157 | // line 158 | 159 | { 160 | "caption": "AutocompletionFuzzy: Complete line forward", 161 | "command": "autocompletion", 162 | "args": { 163 | "backward": false, 164 | "handler": "AutocompletionFuzzy.word.create_completion", 165 | "word": "[$\\w\\.\\\\/]+((::|->)[\\w\\.\\\\/\\-]+)*$", 166 | "search": "(?:\\W|^)(__WORD__.*?)\n", 167 | } 168 | }, 169 | 170 | { 171 | "caption": "AutocompletionFuzzy: Complete line backward", 172 | "command": "autocompletion", 173 | "args": { 174 | "backward": true, 175 | "handler": "AutocompletionFuzzy.word.create_completion", 176 | "word": "[$\\w\\.\\\\/]+((::|->)[\\w\\.\\\\/\\-]+)*$", 177 | "search": "(?:\\W|^)(__WORD__.*?)\n", 178 | } 179 | }, 180 | 181 | ] -------------------------------------------------------------------------------- /Default (Linux).sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | // word (fuzzy) 3 | 4 | { 5 | "keys": ["ctrl+p"], 6 | "command": "autocompletion", 7 | "args": { 8 | "backward": false, 9 | "handler": "AutocompletionFuzzy.word.create_fuzzy_completion", 10 | }, 11 | "context": [ 12 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 13 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 14 | ], 15 | }, 16 | 17 | { 18 | "keys": ["ctrl+o"], 19 | "command": "autocompletion", 20 | "args": { 21 | "backward": true, 22 | "handler": "AutocompletionFuzzy.word.create_fuzzy_completion", 23 | }, 24 | "context": [ 25 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 26 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 27 | ], 28 | }, 29 | 30 | // word (not fuzzy) 31 | 32 | // { 33 | // "keys": ["ctrl+p"], 34 | // "command": "autocompletion", 35 | // "args": { 36 | // "backward": false, 37 | // "handler": "AutocompletionFuzzy.word.create_completion", 38 | // } 39 | // }, 40 | 41 | // { 42 | // "keys": ["ctrl+o"], 43 | // "command": "autocompletion", 44 | // "args": { 45 | // "backward": true, 46 | // "handler": "AutocompletionFuzzy.word.create_completion", 47 | // } 48 | // }, 49 | 50 | // subword 51 | 52 | { 53 | "keys": ["ctrl+shift+p"], 54 | "command": "autocompletion", 55 | "args": { 56 | "handler": "AutocompletionFuzzy.word.create_completion", 57 | "backward": false, 58 | "word": "[A-Z]?[a-z]+$|[A-Z]+$", 59 | "search": "(__WORD__(?:[a-z]+|[A-Z]+))" 60 | }, 61 | "context": [ 62 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 63 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 64 | ], 65 | }, 66 | 67 | { 68 | "keys": ["ctrl+shift+o"], 69 | "command": "autocompletion", 70 | "args": { 71 | "handler": "AutocompletionFuzzy.word.create_completion", 72 | "backward": true, 73 | "word": "[A-Z]?[a-z]+$|[A-Z]+$", 74 | "search": "(__WORD__(?:[a-z]+|[A-Z]+))" 75 | }, 76 | "context": [ 77 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 78 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 79 | ], 80 | }, 81 | 82 | // long word (fuzzy) 83 | 84 | { 85 | "keys": ["ctrl+alt+p"], 86 | "command": "autocompletion", 87 | "args": { 88 | "handler": "AutocompletionFuzzy.word.create_fuzzy_completion", 89 | "backward": false, 90 | "word": "[\\w\\.\\\\/]+((::|->|://)[\\w\\.\\\\/\\-]+)*$", 91 | "delimeter": "([\\w/\\-\\.$\\\\]|::|->|://)*", 92 | "last_delimeter": "([\\w/\\-\\.$\\\\]|::|->|://)*\\w", 93 | "search": "(?:[^\\w/]|^)([_\\\\]*__FUZZY__)", 94 | }, 95 | "context": [ 96 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 97 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 98 | ], 99 | }, 100 | 101 | { 102 | "keys": ["ctrl+alt+o"], 103 | "command": "autocompletion", 104 | "args": { 105 | "backward": true, 106 | "handler": "AutocompletionFuzzy.word.create_fuzzy_completion", 107 | "word": "[\\w\\.\\\\/]+((::|->|://)[\\w\\.\\\\/\\-]+)*$", 108 | "delimeter": "([\\w/\\-\\.$\\\\]|::|->|://)*", 109 | "last_delimeter": "([\\w/\\-\\.$\\\\]|::|->|://)*\\w", 110 | "search": "(?:[^\\w/]|^)([_\\\\]*__FUZZY__)", 111 | }, 112 | "context": [ 113 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 114 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 115 | ], 116 | }, 117 | 118 | // long word (not fuzzy) 119 | 120 | // { 121 | // "keys": ["ctrl+alt+p"], 122 | // "command": "autocompletion", 123 | // "args": { 124 | // "backward": false, 125 | // "handler": "AutocompletionFuzzy.word.create_completion", 126 | // "word": "[$\\w/\\.\\\\/]+((::|->)[\\w\\.\\\\/\\-]+)*$", 127 | // "search": "(?:\\W|^)(__WORD__[$\\w\\.\\\\/]+((::|->)[\\w\\.\\\\/\\-$]+)*\\w)", 128 | // } 129 | // }, 130 | 131 | // {"keys": ["ctrl+alt+o"], "command": "autocompletion", 132 | // "args": { 133 | // "backward": true, 134 | // "handler": "AutocompletionFuzzy.word.create_completion", 135 | // "word": "[$\\w\\.\\\\/]+((::|->)[\\w\\.\\\\/\\-]+)*$", 136 | // "search": "(?:\\W|^)(__WORD__[$\\w\\.\\\\/]+((::|->)[\\w\\.\\\\/\\-$]+)*\\w)", 137 | // } 138 | // }, 139 | 140 | // nesting (fuzzy) 141 | 142 | { 143 | "keys": ["alt+p"], 144 | "command": "autocompletion", 145 | "args": { 146 | "handler": "AutocompletionFuzzy.nesting.create_fuzzy_completion", 147 | "backward": false, 148 | }, 149 | "context": [ 150 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 151 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 152 | ], 153 | }, 154 | 155 | { 156 | "keys": ["alt+o"], 157 | "command": "autocompletion", 158 | "args": { 159 | "handler": "AutocompletionFuzzy.nesting.create_fuzzy_completion", 160 | "backward": true, 161 | }, 162 | "context": [ 163 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 164 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 165 | ], 166 | }, 167 | 168 | // nesting (not fuzzy) 169 | 170 | // { 171 | // "keys": ["alt+p"], 172 | // "command": "autocompletion", 173 | // "args": { 174 | // "handler": "AutocompletionFuzzy.nesting.create_completion", 175 | // "backward": false, 176 | // } 177 | // }, 178 | 179 | // { 180 | // "keys": ["alt+o"], 181 | // "command": "autocompletion", 182 | // "args": { 183 | // "handler": "AutocompletionFuzzy.nesting.create_completion", 184 | // "backward": true, 185 | // } 186 | // }, 187 | 188 | // line 189 | 190 | { 191 | "keys": ["alt+shift+p"], 192 | "command": "autocompletion", 193 | "args": { 194 | "backward": false, 195 | "handler": "AutocompletionFuzzy.word.create_completion", 196 | "word": "[$\\w\\.\\\\/]+((::|->)[\\w\\.\\\\/\\-]+)*$", 197 | "search": "(?:\\W|^)(__WORD__.*?)\n", 198 | }, 199 | "context": [ 200 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 201 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 202 | ], 203 | }, 204 | 205 | { 206 | "keys": ["alt+shift+o"], 207 | "command": "autocompletion", 208 | "args": { 209 | "backward": true, 210 | "handler": "AutocompletionFuzzy.word.create_completion", 211 | "word": "[$\\w\\.\\\\/]+((::|->)[\\w\\.\\\\/\\-]+)*$", 212 | "search": "(?:\\W|^)(__WORD__.*?)\n", 213 | }, 214 | "context": [ 215 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 216 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 217 | ], 218 | }, 219 | 220 | { 221 | "keys": ["ctrl+з"], 222 | "command": "autocompletion", 223 | "args": { 224 | "backward": false, 225 | "handler": "AutocompletionFuzzy.word.create_fuzzy_completion", 226 | }, 227 | "context": [ 228 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 229 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 230 | ], 231 | }, 232 | 233 | { 234 | "keys": ["ctrl+щ"], 235 | "command": "autocompletion", 236 | "args": { 237 | "backward": true, 238 | "handler": "AutocompletionFuzzy.word.create_fuzzy_completion", 239 | }, 240 | "context": [ 241 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 242 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 243 | ], 244 | }, 245 | ] -------------------------------------------------------------------------------- /Default (OSX).sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | // word (fuzzy) 3 | 4 | { 5 | "keys": ["ctrl+p"], 6 | "command": "autocompletion", 7 | "args": { 8 | "backward": false, 9 | "handler": "AutocompletionFuzzy.word.create_fuzzy_completion", 10 | }, 11 | "context": [ 12 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 13 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 14 | ], 15 | }, 16 | 17 | { 18 | "keys": ["ctrl+o"], 19 | "command": "autocompletion", 20 | "args": { 21 | "backward": true, 22 | "handler": "AutocompletionFuzzy.word.create_fuzzy_completion", 23 | }, 24 | "context": [ 25 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 26 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 27 | ], 28 | }, 29 | 30 | // word (not fuzzy) 31 | 32 | // { 33 | // "keys": ["ctrl+p"], 34 | // "command": "autocompletion", 35 | // "args": { 36 | // "backward": false, 37 | // "handler": "AutocompletionFuzzy.word.create_completion", 38 | // } 39 | // }, 40 | 41 | // { 42 | // "keys": ["ctrl+o"], 43 | // "command": "autocompletion", 44 | // "args": { 45 | // "backward": true, 46 | // "handler": "AutocompletionFuzzy.word.create_completion", 47 | // } 48 | // }, 49 | 50 | // subword 51 | 52 | { 53 | "keys": ["ctrl+shift+p"], 54 | "command": "autocompletion", 55 | "args": { 56 | "handler": "AutocompletionFuzzy.word.create_completion", 57 | "backward": false, 58 | "word": "[A-Z]?[a-z]+$|[A-Z]+$", 59 | "search": "(__WORD__(?:[a-z]+|[A-Z]+))" 60 | }, 61 | "context": [ 62 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 63 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 64 | ], 65 | }, 66 | 67 | { 68 | "keys": ["ctrl+shift+o"], 69 | "command": "autocompletion", 70 | "args": { 71 | "handler": "AutocompletionFuzzy.word.create_completion", 72 | "backward": true, 73 | "word": "[A-Z]?[a-z]+$|[A-Z]+$", 74 | "search": "(__WORD__(?:[a-z]+|[A-Z]+))" 75 | }, 76 | "context": [ 77 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 78 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 79 | ], 80 | }, 81 | 82 | // long word (fuzzy) 83 | 84 | { 85 | "keys": ["ctrl+alt+p"], 86 | "command": "autocompletion", 87 | "args": { 88 | "handler": "AutocompletionFuzzy.word.create_fuzzy_completion", 89 | "backward": false, 90 | "word": "[\\w\\.\\\\/]+((::|->|://)[\\w\\.\\\\/\\-]+)*$", 91 | "delimeter": "([\\w/\\-\\.$\\\\]|::|->|://)*", 92 | "last_delimeter": "([\\w/\\-\\.$\\\\]|::|->|://)*\\w", 93 | "search": "(?:[^\\w/]|^)([_\\\\]*__FUZZY__)", 94 | }, 95 | "context": [ 96 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 97 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 98 | ], 99 | }, 100 | 101 | { 102 | "keys": ["ctrl+alt+o"], 103 | "command": "autocompletion", 104 | "args": { 105 | "backward": true, 106 | "handler": "AutocompletionFuzzy.word.create_fuzzy_completion", 107 | "word": "[\\w\\.\\\\/]+((::|->|://)[\\w\\.\\\\/\\-]+)*$", 108 | "delimeter": "([\\w/\\-\\.$\\\\]|::|->|://)*", 109 | "last_delimeter": "([\\w/\\-\\.$\\\\]|::|->|://)*\\w", 110 | "search": "(?:[^\\w/]|^)([_\\\\]*__FUZZY__)", 111 | }, 112 | "context": [ 113 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 114 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 115 | ], 116 | }, 117 | 118 | // long word (not fuzzy) 119 | 120 | // { 121 | // "keys": ["ctrl+alt+p"], 122 | // "command": "autocompletion", 123 | // "args": { 124 | // "backward": false, 125 | // "handler": "AutocompletionFuzzy.word.create_completion", 126 | // "word": "[$\\w/\\.\\\\/]+((::|->)[\\w\\.\\\\/\\-]+)*$", 127 | // "search": "(?:\\W|^)(__WORD__[$\\w\\.\\\\/]+((::|->)[\\w\\.\\\\/\\-$]+)*\\w)", 128 | // } 129 | // }, 130 | 131 | // {"keys": ["ctrl+alt+o"], "command": "autocompletion", 132 | // "args": { 133 | // "backward": true, 134 | // "handler": "AutocompletionFuzzy.word.create_completion", 135 | // "word": "[$\\w\\.\\\\/]+((::|->)[\\w\\.\\\\/\\-]+)*$", 136 | // "search": "(?:\\W|^)(__WORD__[$\\w\\.\\\\/]+((::|->)[\\w\\.\\\\/\\-$]+)*\\w)", 137 | // } 138 | // }, 139 | 140 | // nesting (fuzzy) 141 | 142 | { 143 | "keys": ["alt+p"], 144 | "command": "autocompletion", 145 | "args": { 146 | "handler": "AutocompletionFuzzy.nesting.create_fuzzy_completion", 147 | "backward": false, 148 | }, 149 | "context": [ 150 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 151 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 152 | ], 153 | }, 154 | 155 | { 156 | "keys": ["alt+o"], 157 | "command": "autocompletion", 158 | "args": { 159 | "handler": "AutocompletionFuzzy.nesting.create_fuzzy_completion", 160 | "backward": true, 161 | }, 162 | "context": [ 163 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 164 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 165 | ], 166 | }, 167 | 168 | // nesting (not fuzzy) 169 | 170 | // { 171 | // "keys": ["alt+p"], 172 | // "command": "autocompletion", 173 | // "args": { 174 | // "handler": "AutocompletionFuzzy.nesting.create_completion", 175 | // "backward": false, 176 | // } 177 | // }, 178 | 179 | // { 180 | // "keys": ["alt+o"], 181 | // "command": "autocompletion", 182 | // "args": { 183 | // "handler": "AutocompletionFuzzy.nesting.create_completion", 184 | // "backward": true, 185 | // } 186 | // }, 187 | 188 | // line 189 | 190 | { 191 | "keys": ["alt+shift+p"], 192 | "command": "autocompletion", 193 | "args": { 194 | "backward": false, 195 | "handler": "AutocompletionFuzzy.word.create_completion", 196 | "word": "[$\\w\\.\\\\/]+((::|->)[\\w\\.\\\\/\\-]+)*$", 197 | "search": "(?:\\W|^)(__WORD__.*?)\n", 198 | }, 199 | "context": [ 200 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 201 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 202 | ], 203 | }, 204 | 205 | { 206 | "keys": ["alt+shift+o"], 207 | "command": "autocompletion", 208 | "args": { 209 | "backward": true, 210 | "handler": "AutocompletionFuzzy.word.create_completion", 211 | "word": "[$\\w\\.\\\\/]+((::|->)[\\w\\.\\\\/\\-]+)*$", 212 | "search": "(?:\\W|^)(__WORD__.*?)\n", 213 | }, 214 | "context": [ 215 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 216 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 217 | ], 218 | }, 219 | 220 | { 221 | "keys": ["ctrl+з"], 222 | "command": "autocompletion", 223 | "args": { 224 | "backward": false, 225 | "handler": "AutocompletionFuzzy.word.create_fuzzy_completion", 226 | }, 227 | "context": [ 228 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 229 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 230 | ], 231 | }, 232 | 233 | { 234 | "keys": ["ctrl+щ"], 235 | "command": "autocompletion", 236 | "args": { 237 | "backward": true, 238 | "handler": "AutocompletionFuzzy.word.create_fuzzy_completion", 239 | }, 240 | "context": [ 241 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 242 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 243 | ], 244 | }, 245 | ] -------------------------------------------------------------------------------- /Default (Windows).sublime-keymap: -------------------------------------------------------------------------------- 1 | [ 2 | // word (fuzzy) 3 | 4 | { 5 | "keys": ["ctrl+p"], 6 | "command": "autocompletion", 7 | "args": { 8 | "backward": false, 9 | "handler": "AutocompletionFuzzy.word.create_fuzzy_completion", 10 | }, 11 | "context": [ 12 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 13 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 14 | ], 15 | }, 16 | 17 | { 18 | "keys": ["ctrl+o"], 19 | "command": "autocompletion", 20 | "args": { 21 | "backward": true, 22 | "handler": "AutocompletionFuzzy.word.create_fuzzy_completion", 23 | }, 24 | "context": [ 25 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 26 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 27 | ], 28 | }, 29 | 30 | // word (not fuzzy) 31 | 32 | // { 33 | // "keys": ["ctrl+p"], 34 | // "command": "autocompletion", 35 | // "args": { 36 | // "backward": false, 37 | // "handler": "AutocompletionFuzzy.word.create_completion", 38 | // } 39 | // }, 40 | 41 | // { 42 | // "keys": ["ctrl+o"], 43 | // "command": "autocompletion", 44 | // "args": { 45 | // "backward": true, 46 | // "handler": "AutocompletionFuzzy.word.create_completion", 47 | // } 48 | // }, 49 | 50 | // subword 51 | 52 | { 53 | "keys": ["ctrl+shift+p"], 54 | "command": "autocompletion", 55 | "args": { 56 | "handler": "AutocompletionFuzzy.word.create_completion", 57 | "backward": false, 58 | "word": "[A-Z]?[a-z]+$|[A-Z]+$", 59 | "search": "(__WORD__(?:[a-z]+|[A-Z]+))" 60 | }, 61 | "context": [ 62 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 63 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 64 | ], 65 | }, 66 | 67 | { 68 | "keys": ["ctrl+shift+o"], 69 | "command": "autocompletion", 70 | "args": { 71 | "handler": "AutocompletionFuzzy.word.create_completion", 72 | "backward": true, 73 | "word": "[A-Z]?[a-z]+$|[A-Z]+$", 74 | "search": "(__WORD__(?:[a-z]+|[A-Z]+))" 75 | }, 76 | "context": [ 77 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 78 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 79 | ], 80 | }, 81 | 82 | // long word (fuzzy) 83 | 84 | { 85 | "keys": ["ctrl+alt+p"], 86 | "command": "autocompletion", 87 | "args": { 88 | "handler": "AutocompletionFuzzy.word.create_fuzzy_completion", 89 | "backward": false, 90 | "word": "[\\w\\.\\\\/]+((::|->|://)[\\w\\.\\\\/\\-]+)*$", 91 | "delimeter": "([\\w/\\-\\.$\\\\]|::|->|://)*", 92 | "last_delimeter": "([\\w/\\-\\.$\\\\]|::|->|://)*\\w", 93 | "search": "(?:[^\\w/]|^)([_\\\\]*__FUZZY__)", 94 | }, 95 | "context": [ 96 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 97 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 98 | ], 99 | }, 100 | 101 | { 102 | "keys": ["ctrl+alt+o"], 103 | "command": "autocompletion", 104 | "args": { 105 | "backward": true, 106 | "handler": "AutocompletionFuzzy.word.create_fuzzy_completion", 107 | "word": "[\\w\\.\\\\/]+((::|->|://)[\\w\\.\\\\/\\-]+)*$", 108 | "delimeter": "([\\w/\\-\\.$\\\\]|::|->|://)*", 109 | "last_delimeter": "([\\w/\\-\\.$\\\\]|::|->|://)*\\w", 110 | "search": "(?:[^\\w/]|^)([_\\\\]*__FUZZY__)", 111 | }, 112 | "context": [ 113 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 114 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 115 | ], 116 | }, 117 | 118 | // long word (not fuzzy) 119 | 120 | // { 121 | // "keys": ["ctrl+alt+p"], 122 | // "command": "autocompletion", 123 | // "args": { 124 | // "backward": false, 125 | // "handler": "AutocompletionFuzzy.word.create_completion", 126 | // "word": "[$\\w/\\.\\\\/]+((::|->)[\\w\\.\\\\/\\-]+)*$", 127 | // "search": "(?:\\W|^)(__WORD__[$\\w\\.\\\\/]+((::|->)[\\w\\.\\\\/\\-$]+)*\\w)", 128 | // } 129 | // }, 130 | 131 | // {"keys": ["ctrl+alt+o"], "command": "autocompletion", 132 | // "args": { 133 | // "backward": true, 134 | // "handler": "AutocompletionFuzzy.word.create_completion", 135 | // "word": "[$\\w\\.\\\\/]+((::|->)[\\w\\.\\\\/\\-]+)*$", 136 | // "search": "(?:\\W|^)(__WORD__[$\\w\\.\\\\/]+((::|->)[\\w\\.\\\\/\\-$]+)*\\w)", 137 | // } 138 | // }, 139 | 140 | // nesting (fuzzy) 141 | 142 | { 143 | "keys": ["alt+p"], 144 | "command": "autocompletion", 145 | "args": { 146 | "handler": "AutocompletionFuzzy.nesting.create_fuzzy_completion", 147 | "backward": false, 148 | }, 149 | "context": [ 150 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 151 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 152 | ], 153 | }, 154 | 155 | { 156 | "keys": ["alt+o"], 157 | "command": "autocompletion", 158 | "args": { 159 | "handler": "AutocompletionFuzzy.nesting.create_fuzzy_completion", 160 | "backward": true, 161 | }, 162 | "context": [ 163 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 164 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 165 | ], 166 | }, 167 | 168 | // nesting (not fuzzy) 169 | 170 | // { 171 | // "keys": ["alt+p"], 172 | // "command": "autocompletion", 173 | // "args": { 174 | // "handler": "AutocompletionFuzzy.nesting.create_completion", 175 | // "backward": false, 176 | // } 177 | // }, 178 | 179 | // { 180 | // "keys": ["alt+o"], 181 | // "command": "autocompletion", 182 | // "args": { 183 | // "handler": "AutocompletionFuzzy.nesting.create_completion", 184 | // "backward": true, 185 | // } 186 | // }, 187 | 188 | // line 189 | 190 | { 191 | "keys": ["alt+shift+p"], 192 | "command": "autocompletion", 193 | "args": { 194 | "backward": false, 195 | "handler": "AutocompletionFuzzy.word.create_completion", 196 | "word": "[$\\w\\.\\\\/]+((::|->)[\\w\\.\\\\/\\-]+)*$", 197 | "search": "(?:\\W|^)(__WORD__.*?)\n", 198 | }, 199 | "context": [ 200 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 201 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 202 | ], 203 | }, 204 | 205 | { 206 | "keys": ["alt+shift+o"], 207 | "command": "autocompletion", 208 | "args": { 209 | "backward": true, 210 | "handler": "AutocompletionFuzzy.word.create_completion", 211 | "word": "[$\\w\\.\\\\/]+((::|->)[\\w\\.\\\\/\\-]+)*$", 212 | "search": "(?:\\W|^)(__WORD__.*?)\n", 213 | }, 214 | "context": [ 215 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 216 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 217 | ], 218 | }, 219 | 220 | { 221 | "keys": ["ctrl+з"], 222 | "command": "autocompletion", 223 | "args": { 224 | "backward": false, 225 | "handler": "AutocompletionFuzzy.word.create_fuzzy_completion", 226 | }, 227 | "context": [ 228 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 229 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 230 | ], 231 | }, 232 | 233 | { 234 | "keys": ["ctrl+щ"], 235 | "command": "autocompletion", 236 | "args": { 237 | "backward": true, 238 | "handler": "AutocompletionFuzzy.word.create_fuzzy_completion", 239 | }, 240 | "context": [ 241 | {"key": "setting.sublime_enhanced_keybindings", "operator": "equal", "operand": true}, 242 | {"key": "overlay_visible", "operator": "equal", "operand": false}, 243 | ], 244 | }, 245 | ] -------------------------------------------------------------------------------- /autocompletion.py: -------------------------------------------------------------------------------- 1 | import sublime 2 | import sublime_plugin 3 | import importlib 4 | 5 | clean_required = False 6 | _completion = None 7 | 8 | def _set_current_completion(completion): 9 | global _completion 10 | _completion = completion 11 | 12 | def _get_current_completion(): 13 | global _completion 14 | return _completion 15 | 16 | def _call_handler(handler, **args): 17 | module_name, method_name = handler.rsplit('.', 1) 18 | module = importlib.import_module(module_name) 19 | result = getattr(module, method_name)(**args) 20 | return result 21 | 22 | def _create_completion(handler, view, backward, args = {}): 23 | handler_args = args.copy() 24 | handler_args.update({ 25 | 'backward': backward, 26 | 'view': view 27 | }) 28 | 29 | completions = _call_handler(handler, **handler_args) 30 | if completions == None: 31 | return None 32 | 33 | completion = { 34 | 'type': handler + str(args), 35 | 'backward': backward, 36 | 'current': 0, 37 | 'completions': completions, 38 | 'position': view.sel()[0].b - len(completions[0]['completion']), 39 | } 40 | 41 | return completion 42 | 43 | class Autocompletion(sublime_plugin.TextCommand): 44 | def run(self, edit, handler, backward = True, **args): 45 | sels = self.view.sel() 46 | if len(sels) == 0: 47 | return 48 | 49 | completion = _get_current_completion() 50 | if self._is_new_completion_needed(handler, completion, backward, args): 51 | completion = _create_completion(handler, self.view, backward, args) 52 | if completion == None: 53 | return 54 | _set_current_completion(completion) 55 | self._highlight(completion) 56 | 57 | current_index, current, new = self._get_backward_completion(completion, 58 | backward) 59 | 60 | for selection in sels: 61 | self._complete(edit, completion, selection, current_index, current, new, 62 | backward) 63 | 64 | self._highlight_current(completion) 65 | 66 | def _is_new_completion_needed(self, handler, completion, backward, args): 67 | if completion == None: 68 | return True 69 | 70 | if completion['type'] != handler + str(args): 71 | return True 72 | 73 | _is_completion_valid = self._is_completion_valid(completion, 74 | self.view.sel()[0], completion['current'], backward) 75 | 76 | if not _is_completion_valid: 77 | return True 78 | 79 | current = completion['completions'][completion['current']]['completion'] 80 | if self.view.sel()[0].b - len(current) != completion['position']: 81 | return True 82 | 83 | return False 84 | 85 | def _is_completion_valid(self, completion, selection, index, backward): 86 | if index == 0: 87 | if not completion['backward'] and backward: 88 | return False 89 | 90 | if completion['backward'] and not backward: 91 | return False 92 | 93 | current = completion['completions'][index]['completion'] 94 | region = sublime.Region(selection.b - len(current), selection.b) 95 | last = self.view.substr(region) 96 | 97 | return last == current 98 | 99 | def _get_backward_completion(self, completion, backward): 100 | current_index = completion['current'] 101 | current = completion['completions'][current_index]['completion'] 102 | 103 | if completion['backward']: 104 | backward = not backward 105 | 106 | if backward: 107 | completion['current'] -= 1 108 | if completion['current'] < 0: 109 | completion['current'] = 0 110 | else: 111 | completion['current'] += 1 112 | if completion['current'] > len(completion['completions']) - 1: 113 | completion['current'] = len(completion['completions']) - 1 114 | 115 | new = completion['completions'][completion['current']]['completion'] 116 | return current_index, current, new 117 | 118 | def _complete(self, edit, completion, selection, index, current, new, 119 | backward): 120 | if not self._is_completion_valid(completion, selection, index, backward): 121 | return 122 | 123 | region = sublime.Region(selection.b - len(current), selection.b) 124 | self.view.replace(edit, region, new) 125 | 126 | def _highlight(self, completion): 127 | regions, completions = [], completion['completions'] 128 | 129 | global clean_required 130 | clean_required = True 131 | 132 | for index, current in enumerate(completions): 133 | if index == 0: 134 | continue 135 | 136 | highlights = current['highlights'] 137 | 138 | self.view.add_regions('autocompletion_' + str(index), highlights) 139 | if completion['backward']: 140 | highlights = reversed(highlights) 141 | 142 | regions += highlights 143 | if len(regions) > 100: 144 | regions = regions[:100] 145 | break 146 | 147 | self.view.add_regions('autocompletion', regions, '?', '', 148 | sublime.DRAW_EMPTY | sublime.DRAW_OUTLINED) 149 | 150 | def _highlight_current(self, completion): 151 | global clean_required 152 | clean_required = True 153 | 154 | if completion['current'] == 0: 155 | self.view.erase_regions('autocompletion_current') 156 | return 157 | 158 | highlights = self.view.get_regions('autocompletion_' + 159 | str(completion['current'])) 160 | 161 | self.view.add_regions('autocompletion_current', highlights, 'string', '') 162 | 163 | class CancelCompletion(sublime_plugin.TextCommand): 164 | def run(self, edit): 165 | global completion 166 | completion = None 167 | 168 | class ClearHighlights(sublime_plugin.EventListener): 169 | def on_selection_modified_async(self, view): 170 | last_command, _, _ = view.command_history(0) 171 | if last_command == 'autocompletion': 172 | return 173 | 174 | global clean_required 175 | if not clean_required: 176 | return 177 | 178 | clean_required = False 179 | 180 | view.erase_regions('autocompletion') 181 | view.erase_regions('autocompletion_current') -------------------------------------------------------------------------------- /demo/demo.js: -------------------------------------------------------------------------------- 1 | function action(argument) { 2 | // simple case 3 | return argument; 4 | } 5 | 6 | function calculate(key, value) { 7 | var value_combined = [key, value]; 8 | var value_chained = key + value; 9 | var value_result = key * value_chained; 10 | var value_action = action(value_result) + key; 11 | 12 | // jumping between matches 13 | return value_combined; 14 | } 15 | 16 | function execute(arg1, arg2) { 17 | // parenthesis completion 18 | return calculate(arg1, arg2); 19 | } 20 | 21 | // line completion 22 | action(value_result) + key; -------------------------------------------------------------------------------- /demo/test.js: -------------------------------------------------------------------------------- 1 | function action(argument) { 2 | // simple case 3 | return argument; 4 | } 5 | 6 | function calculate(key, value) { 7 | var value_combined = [key, value]; 8 | var value_chained = key + value; 9 | var value_result = key * value_chained; 10 | var value_action = action(value_result) + key; 11 | 12 | // jumping between matches 13 | return value_combined; 14 | } 15 | 16 | function execute(arg1, arg2) { 17 | // parenthesis completion 18 | return calculate(arg1, arg2); 19 | } 20 | 21 | // line completion 22 | action(value_result) + key; -------------------------------------------------------------------------------- /license.md: -------------------------------------------------------------------------------- 1 | # License 2 | 3 | The MIT License (MIT) 4 | 5 | Copyright (c) 2014 Leonid Shagabutdinov 6 | 7 | Permission is hereby granted, free of charge, to any person obtaining a copy 8 | of this software and associated documentation files (the "Software"), to deal 9 | in the Software without restriction, including without limitation the rights 10 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 11 | copies of the Software, and to permit persons to whom the Software is 12 | furnished to do so, subject to the following conditions: 13 | 14 | The above copyright notice and this permission notice shall be included in all 15 | copies or substantial portions of the Software. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 20 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 21 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 22 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 23 | SOFTWARE. -------------------------------------------------------------------------------- /nesting.py: -------------------------------------------------------------------------------- 1 | import sublime 2 | 3 | try: 4 | from Expression import expression 5 | from AutocompletionFuzzy import utility 6 | from AutocompletionFuzzy.word import _set_fuzzy_expression 7 | except ImportError as error: 8 | sublime.error_message("Dependency import failed; please read readme for " + 9 | "Autocompletion plugin for installation instructions; to disable this " + 10 | "message remove this plugin; message: " + str(error)) 11 | raise error 12 | 13 | import re 14 | 15 | WORD = r'\$?[\w\-]+$' # r'[$\w\.\\/]+((::|->)[$\w\.\\/\-]+)*$' 16 | SEARCH = r'(?:\W|^)(__WORD__[$\w\.\\/]*((::|->|-)[$\w\.\\/]+)*)' 17 | 18 | def create_completion(view, backward, word = WORD, search = SEARCH): 19 | completions = utility.initiate_completions(view, word) 20 | completions, words, word = completions 21 | if word == None: 22 | return None 23 | 24 | text = view.substr(sublime.Region(0, view.size())) 25 | search = search.replace('__WORD__', word) 26 | 27 | 28 | return _find_completions(view, backward, completions, words, word, search) 29 | 30 | FUZZY_WORD = WORD 31 | FUZZY_DELIMETER = r'([\w\-\.$\\]|::|->)*' 32 | FUZZY_LAST_DELIMETER = FUZZY_DELIMETER + r'\w' 33 | FUZZY_SEARCH = r'(?:[^\w$]|^)([_\\]*__FUZZY__)' 34 | 35 | def create_fuzzy_completion(view, backward, word = FUZZY_WORD, 36 | delimeter = FUZZY_DELIMETER, last_delimeter = FUZZY_LAST_DELIMETER, 37 | search = FUZZY_SEARCH): 38 | 39 | completions, words, word = utility.initiate_completions(view, word) 40 | if word == None: 41 | return None 42 | 43 | text, point_range, shift = utility.get_text(view, backward) 44 | 45 | search = _set_fuzzy_expression(search, word, delimeter, last_delimeter) 46 | 47 | return _find_completions(view, backward, completions, words, word, search) 48 | 49 | def _find_completions(view, backward, completions, words, word, search): 50 | lookup_arguments = True 51 | for sel in view.sel(): 52 | if expression.get_nesting(view, sel.b, 1024 * 5) == None: 53 | lookup_arguments = False 54 | break 55 | 56 | point = view.sel()[0].b 57 | cursor = None 58 | if backward: 59 | point -= len(word) 60 | cursor = 'end' 61 | 62 | matches = expression.find_matches(view, point, search, {'backward': backward, 63 | 'nesting': True, 'string': True, 'cursor': cursor,}) 64 | 65 | for match in matches: 66 | start = match.start(1) 67 | 68 | call_end = _get_call_end(view, match) 69 | if call_end != None: 70 | _append_region(view, completions, words, sublime.Region(start, call_end)) 71 | 72 | if lookup_arguments: 73 | arg_end = _get_argument_end(view, match) 74 | if arg_end != None: 75 | _append_region(view, completions, words, sublime.Region(start, arg_end)) 76 | 77 | return completions 78 | 79 | def _get_argument_end(view, match): 80 | nesting = expression.get_nesting(view, match.start(1) + 1, 1024 * 5) 81 | if nesting == None: 82 | return None 83 | 84 | return nesting[1] 85 | 86 | def _get_call_end(view, match): 87 | _, point, _, _ = expression.lookup(view, match.end(1), r'^\s*([\(\[])', 88 | {'nesting': True, 'range': [0, 52], 'limit': 1}) 89 | 90 | if point == None: 91 | return 92 | 93 | nesting = expression.get_nesting(view, point + 1, [1, 1024 * 5]) 94 | if nesting == None: 95 | return None 96 | 97 | return nesting[1] + 1 98 | 99 | def _append_region(view, completions, words, region): 100 | complete = view.substr(region) 101 | completion = utility.get_completion(completions, words, complete) 102 | utility.append_region(completion, [0, view.size()], 0, region.a, region.b) -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # Sublime Autocompletion plugin 2 | 3 | This is really glorious plugin that reduce plain typing considerably while 4 | coding. 5 | 6 | 7 | ### Demo 8 | 9 | ![Demo](https://github.com/shagabutdinov/sublime-enhanced-demos/raw/master/autocompletion.gif "Demo") 10 | 11 | 12 | ### Installation 13 | 14 | * Package Control: plugin is avaiable under `AutocompletionFuzzy` in sublime's `package-control`. 15 | * GIT: plugin should be cloned under `AutocompletionFuzzy` name. 16 | 17 | 18 | ### Features 19 | 20 | Provides 8 different types of autocompletion: 21 | 22 | 1. Complete word - basic completion; completes word that occurenced in text and 23 | opened files. 24 | 25 | 2. Complete word (fuzzy) - like "complete word" but uses fuzzy match over words. 26 | 27 | 3. Complete subword - completes snake_case and CamelCase words parts. 28 | 29 | 4. Complete long word - complete long words: class names with namespaces 30 | (Class::Name), method calls (object.method), filenames (file/name.py), urls 31 | (http://...). 32 | 33 | 5. Complete long word (fuzzy) - line "complete long word" but uses fuzzy match 34 | over words. 35 | 36 | 6. Complete nesting - completes over and into brackets: can complete full method 37 | call (method(arg1, arg2)), method arguments (arg1, arg2), array ([value1, 38 | value2]) and everything that has brackets over it or after it. 39 | 40 | 7. Complete nesting (fuzzy) - like "complete nesting" but uses fuzzy match. 41 | 42 | 8. Complete line - competes whole line. 43 | 44 | However it maps only 6 types of autocompletion. Not fuzzy completions aren't 45 | mapped to keyboard shortcuts by default. See "installation" section if you would 46 | like map non-fuzzy completion behavior. 47 | 48 | All lists are build in order of first occurence of word. That makes autocomplete 49 | very predictable and easy to use. 50 | 51 | Words completion works over all files opened. Nesting completion works only in 52 | current file (because of performance issues) 53 | 54 | 55 | ### Installation 56 | 57 | This plugin is part of [sublime-enhanced](http://github.com/shagabutdinov/sublime-enhanced) 58 | plugin set. You can install sublime-enhanced and this plugin will be installed 59 | automatically. 60 | 61 | If you would like to install this package separately check "Installing packages 62 | separately" section of [sublime-enhanced](http://github.com/shagabutdinov/sublime-enhanced) 63 | package. 64 | 65 | If you don't like fuzzy behavior you should rebind keyboard shortcuts after 66 | installation in the "Autocompletion/Default (OSNAME).sublime-keymap" file 67 | (non-fuzzy behavior are commented by default). 68 | 69 | 70 | ### Usage 71 | 72 | Type a one of two characters of the beginning of word. Than hit keyboard 73 | shortcut or run command to complete the word. You can run same command again to 74 | complete next/previous occurence. 75 | 76 | If you like fuzzy completion it is really useful to type a start character and 77 | following character from the middle of word to receive more accurate completion. 78 | E.g. for complete local_variable type "lv" and hit keyboard shortcut. First 79 | character of word should always be character of completion. However if word 80 | starts with underscore (_) it possible to type next character, e.g. for complete 81 | _local_variable same "lv" will work. 82 | 83 | 84 | ### Commands 85 | 86 | | Description | Keyboard shortcuts | Command palette | 87 | |-------------------------------------|--------------------|--------------------------------------------------------| 88 | | Complete word forward (fuzzy) | ctrl+p | Autocompletion: complete word forward (fuzzy) | 89 | | Complete word backward (fuzzy) | ctrl+o | Autocompletion: complete word backward (fuzzy) | 90 | | Complete word forward | | Autocompletion: complete word forward | 91 | | Complete word backward | | Autocompletion: complete word backward | 92 | | Complete subword forward | ctrl+shift+p | Autocompletion: complete subword forward | 93 | | Complete subword backward | ctrl+shift+o | Autocompletion: complete word backward | 94 | | Complete long word forward (fuzzy) | ctrl+alt+p | Autocompletion: complete long word forward (fuzzy) | 95 | | Complete long word backward (fuzzy) | ctrl+alt+o | Autocompletion: complete long word backward (fuzzy) | 96 | | Complete long word forward | | Autocompletion: complete long word forward | 97 | | Complete long word backward | | Autocompletion: complete long word backward | 98 | | Complete nesting forward (fuzzy) | alt+p | Autocompletion: complete nesting forward (fuzzy) | 99 | | Complete nesting backward (fuzzy) | alt+o | Autocompletion: complete nesting backward (fuzzy) | 100 | | Complete nesting forward | | Autocompletion: complete nesting forward | 101 | | Complete nesting backward | | Autocompletion: complete nesting backward | 102 | | Complete line forward | alt+shift+p | Autocompletion: complete line forward | 103 | | Complete line backward | alt+shift+o | Autocompletion: complete line backward | 104 | 105 | 106 | ### Dependencies 107 | 108 | * [Expression](https://github.com/shagabutdinov/sublime-expression) 109 | -------------------------------------------------------------------------------- /utility.py: -------------------------------------------------------------------------------- 1 | import sublime 2 | import re 3 | 4 | def get_word_info(view, expression): 5 | line_region = view.line(view.sel()[0].b) 6 | previous = view.substr(sublime.Region(line_region.begin(), view.sel()[0].b)) 7 | word_match = re.search(expression, previous) 8 | if word_match == None: 9 | return None, [] 10 | 11 | word = word_match.group(0) 12 | word_region = sublime.Region( 13 | line_region.begin() + word_match.start(0), 14 | line_region.begin() + word_match.end(0) 15 | ) 16 | 17 | return word, [word_region] 18 | 19 | def initiate_completions(view, expression): 20 | word, word_region = get_word_info(view, expression) 21 | completions = [{'completion': word, 'highlights': word_region}] 22 | return completions, [word], word 23 | 24 | def get_completion(completions, words, word): 25 | if word in words: 26 | completion = completions[words.index(word)] 27 | else: 28 | completion = {'completion': word, 'highlights': []} 29 | completions.append(completion) 30 | words.append(word) 31 | 32 | return completion 33 | 34 | def append_region(completion, point_range, shift, start, end): 35 | if point_range[0] <= start and end <= point_range[1]: 36 | region = sublime.Region(start + shift, end + shift) 37 | completion['highlights'].append(region) 38 | 39 | def find_matches(text, backward, search, word): 40 | search = search.replace('__WORD__', re.escape(word)) 41 | matches = re.finditer(search, text) 42 | 43 | if backward: 44 | matches = reversed(list(matches)) 45 | 46 | return matches 47 | 48 | def get_text(view, backward): 49 | point = view.sel()[0].b 50 | 51 | if backward: 52 | region = sublime.Region(0, point) 53 | else: 54 | region = sublime.Region(point, view.size()) 55 | 56 | text = view.substr(region) 57 | 58 | if backward: 59 | views = sublime.active_window().views() 60 | else: 61 | views = reversed(sublime.active_window().views()) 62 | 63 | size = 0 64 | texts = [] 65 | for current_view in views: 66 | if current_view.id() == view.id(): 67 | break 68 | 69 | current_text = current_view.substr(sublime.Region(0, current_view.size())) 70 | size += len(current_text) + 1 71 | texts.append(current_text) 72 | 73 | if len(texts) > 0: 74 | if backward: 75 | text = "\n".join(texts) + "\n" + text 76 | else: 77 | text = text + "\n" + "\n".join(reversed(texts)) 78 | 79 | start, end = region.a, region.b 80 | if backward: 81 | start += size 82 | end += size 83 | else: 84 | start -= point 85 | end -= point 86 | 87 | if backward: 88 | shift = 0 89 | else: 90 | shift = point 91 | 92 | return text, [start, end], shift - start -------------------------------------------------------------------------------- /word.py: -------------------------------------------------------------------------------- 1 | import re 2 | 3 | from AutocompletionFuzzy import utility 4 | 5 | def create_completion(view, backward, word = r'[\w\-]+$', 6 | search = r'(?:[^\w]|^)(__WORD__[\w\-]*\w)'): 7 | 8 | completions, words, word = utility.initiate_completions(view, word) 9 | if word == None: 10 | return None 11 | 12 | text, point_range, shift = utility.get_text(view, backward) 13 | 14 | for match in utility.find_matches(text, backward, search, word): 15 | completion = utility.get_completion(completions, words, match.group(1)) 16 | utility.append_region(completion, point_range, shift, match.start(1), 17 | match.end(1)) 18 | 19 | return completions 20 | 21 | def create_fuzzy_completion(view, backward, word = r'[\w\-]+$', 22 | delimeter = r'[\w\-]*', last_delimeter = r'[\w\-]*\w', 23 | search = r'(?:[^\w]|^)([_\\]*__FUZZY__)'): 24 | 25 | completions, words, word = utility.initiate_completions(view, word) 26 | if word == None: 27 | return None 28 | 29 | text, point_range, shift = utility.get_text(view, backward) 30 | 31 | search = _set_fuzzy_expression(search, word, delimeter, last_delimeter) 32 | 33 | for match in utility.find_matches(text, backward, search, word): 34 | completion = utility.get_completion(completions, words, match.group(1)) 35 | utility.append_region(completion, point_range, shift, match.start(1), 36 | match.end(1)) 37 | 38 | return completions 39 | 40 | def _set_fuzzy_expression(search, word, delimeter, last_delimeter): 41 | fuzzy = '' 42 | for char in word[:-1]: 43 | fuzzy += re.escape(char) + delimeter 44 | 45 | fuzzy += (r'(' + re.escape(word[-1]) + last_delimeter + '|' + 46 | re.escape(word[-1]) + r')') 47 | 48 | return search.replace('__FUZZY__', fuzzy) 49 | --------------------------------------------------------------------------------