Skip to content

Commit 42f06ac

Browse files
authored
Add support for syntax highlighting and completions of extends values (#407)
* Syntax: Add highlighting for `extends` values Add special scopes for `extends`'s values to be able to provide completions and easily identify/find them. * Syntax: Auto-complete base syntaxes
1 parent db7bf1a commit 42f06ac

File tree

4 files changed

+121
-1
lines changed

4 files changed

+121
-1
lines changed

Package/PackageDev.sublime-settings

+7
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@
3030
// settings file for this to take effect.
3131
"settings.show_quick_edit_icon": true,
3232

33+
// List of patterns for syntax not to be displayed in completions.
34+
// Each theme containing one of the list's strings is hidden.
35+
"settings.exclude_syntax_patterns": [
36+
"*.tmLanguage",
37+
"Packages/zzz A File Icon zzz/**"
38+
],
39+
3340
// Whether or not to keep the scope suffix in the suggested test scopes
3441
// i.e. if the base scope is text.html.markdown
3542
// then suggest meta.example.markdown (true) vs meta.example (false).

Package/Sublime Text Syntax Definition/Sublime Text Syntax Definition.sublime-syntax

+47
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ contexts:
133133
captures:
134134
1: string.unquoted.plain.out.yaml storage.type.extends.sublime-syntax
135135
2: punctuation.separator.key-value.yaml
136+
push: expect_extends_list
136137

137138
- match: ((?:hidden_)?file_extensions)\s*(:)(?=\s|$)
138139
captures:
@@ -162,6 +163,52 @@ contexts:
162163

163164
- include: scope:source.yaml
164165

166+
expect_extends_list:
167+
- meta_content_scope: meta.extends.sublime-syntax
168+
- include: comment
169+
- include: yaml-tags-anchors
170+
# array-like context list
171+
- match: \[
172+
scope: punctuation.definition.array.begin.sublime-syntax
173+
set:
174+
- meta_scope: meta.extends.sublime-syntax meta.flow-sequence.yaml
175+
- match: \]
176+
scope: punctuation.definition.array.end.sublime-syntax
177+
pop: true
178+
- match: ','
179+
scope: punctuation.separator.array-element.sublime-syntax
180+
- match: '{{plain_scalar_but_not_block_key}}'
181+
push: extended_syntax_file
182+
- include: comment
183+
- include: yaml-tags-anchors
184+
# multi-line context list
185+
- match: ^([ ]+)(?=-\s*{{plain_scalar_but_not_block_key}})
186+
set:
187+
- meta_scope: meta.extends.sublime-syntax meta.block-sequence.yaml
188+
# pop off at none-empty line with different indention than first item
189+
- match: ^(?!(\s*$|\1-))
190+
pop: true
191+
- match: '{{plain_scalar_but_not_block_key}}'
192+
push: extended_syntax_file
193+
- include: comment
194+
- include: yaml-block-sequence
195+
- match: \S.*$
196+
scope: invalid.illegal.extends.sublime-syntax
197+
# maybe single include
198+
- match: '{{plain_scalar_but_not_block_key}}'
199+
set:
200+
- meta_scope: meta.extends.sublime-syntax meta.path.sublime-syntax string.unquoted.plain.out.yaml
201+
- include: extended_syntax_file
202+
- match: ^(?=\s*$)
203+
pop: 1
204+
205+
extended_syntax_file:
206+
- meta_scope: meta.path.sublime-syntax string.unquoted.plain.out.yaml
207+
- match: '{{_flow_scalar_end_plain_in}}'
208+
pop: true
209+
- match: /
210+
scope: punctuation.separator.path.sublime-syntax
211+
165212
variables_block:
166213
- meta_scope: meta.block.variables.sublime-syntax
167214
- include: comment

Package/Sublime Text Syntax Definition/syntax_test_sublime-syntax.yaml

+20-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,26 @@ version: 2
1313
extends: Packages/Default/Text.sublime-syntax
1414
#^^^^^^ string.unquoted.plain.out.yaml storage.type.extends.sublime-syntax
1515
# ^ punctuation.separator.key-value.yaml
16-
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ string.unquoted.plain.out.yaml
16+
# ^ meta.extends - meta.path
17+
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.extends.sublime-syntax meta.path.sublime-syntax string.unquoted.plain.out.yaml
18+
# ^ punctuation.separator.path.sublime-syntax
19+
# ^ punctuation.separator.path.sublime-syntax
20+
# ^ - meta.extends - meta.path
21+
extends: [ Text.sublime-syntax , Source.sublime-syntax ]
22+
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.extends.sublime-syntax meta.flow-sequence.yaml
23+
# ^ - meta.path
24+
# ^^^^^^^^^^^^^^^^^^^ meta.path.sublime-syntax string.unquoted.plain.out.yaml
25+
# ^^^ - meta.path
26+
# ^^^^^^^^^^^^^^^^^^^^^ meta.path.sublime-syntax string.unquoted.plain.out.yaml
27+
# ^^ - meta.path
28+
extends:
29+
- Packages/Default/Text.sublime-syntax
30+
# <- meta.extends.sublime-syntax meta.block-sequence.yaml
31+
#^^^ meta.extends.sublime-syntax meta.block-sequence.yaml
32+
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.extends.sublime-syntax meta.block-sequence.yaml meta.path.sublime-syntax string.unquoted.plain.out.yaml
33+
# ^ punctuation.separator.path.sublime-syntax
34+
# ^ punctuation.separator.path.sublime-syntax
35+
# ^ meta.extends.sublime-syntax meta.block-sequence.yaml - meta.path
1736
file_extensions: [a, b]
1837
#^^^^^^^^^^^^^^ string.unquoted.plain.out.yaml entity.name.tag.yaml
1938
# ^^^^^^ meta.flow-sequence.yaml, meta.sequence.flow.yaml

plugins/syntax_dev/completions.py

+47
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
import logging
22
import re
33
from collections import namedtuple
4+
from fnmatch import fnmatch
5+
from sublime_lib.resource_path import ResourcePath
46

57
import sublime
68
import sublime_plugin
@@ -266,6 +268,12 @@ def match_selector(selector, offset=0):
266268
):
267269
result = self._complete_branch_point()
268270

271+
elif match_selector(
272+
"meta.extends",
273+
-1,
274+
):
275+
result = self._complete_syntax_file()
276+
269277
# Auto-completion for variables in match patterns using 'variables' keys
270278
elif match_selector("keyword.other.variable"):
271279
result = self._complete_variable()
@@ -299,6 +307,45 @@ def _complete_context(self, prefix, locations):
299307
kind=TPL_CONTEXT.kind,
300308
)
301309

310+
def _complete_syntax_file(self):
311+
completions = []
312+
kind = (sublime.KIND_ID_VARIABLE, 's', 'Syntax')
313+
314+
settings = sublime.load_settings("PackageDev.sublime-settings")
315+
excludes = settings.get("settings.exclude_syntax_patterns", [])
316+
if not isinstance(excludes, list):
317+
excludes = []
318+
319+
try:
320+
my_folder = str(ResourcePath.from_file_path(self.view.file_name()).parent)
321+
except (TypeError, ValueError):
322+
my_folder = ""
323+
324+
for syntax in sublime.list_syntaxes():
325+
if any(fnmatch(syntax.path, pattern) for pattern in excludes):
326+
continue
327+
# add relative resource path completion (file name of siblings)
328+
if my_folder:
329+
folder, file = syntax.path.rsplit("/", 1)
330+
if folder == my_folder:
331+
completions.append(
332+
sublime.CompletionItem(
333+
trigger=file,
334+
kind=kind,
335+
annotation="hidden" if syntax.hidden else ""
336+
)
337+
)
338+
# add full resource path
339+
completions.append(
340+
sublime.CompletionItem(
341+
trigger=syntax.path,
342+
kind=kind,
343+
annotation="hidden" if syntax.hidden else ""
344+
)
345+
)
346+
347+
return completions
348+
302349
def _complete_keyword(self, prefix, locations):
303350

304351
def match_selector(selector, offset=0):

0 commit comments

Comments
 (0)