From 2076fef6899025c482d0eb282653828a1b9af167 Mon Sep 17 00:00:00 2001 From: Koen Lageveen Date: Tue, 13 Nov 2018 21:32:12 +0100 Subject: [PATCH 1/9] solve the selector-or-property conundrum todo: - fix the tests - check auto-complete - check ; insertion --- LESS.sublime-syntax | 591 ++++++++++++++++++++++++------------------ syntax_test_less.less | 118 ++++++++- 2 files changed, 451 insertions(+), 258 deletions(-) diff --git a/LESS.sublime-syntax b/LESS.sublime-syntax index 91fb365..7c61156 100644 --- a/LESS.sublime-syntax +++ b/LESS.sublime-syntax @@ -28,6 +28,8 @@ variables: combinators: '(?:>{1,3}|[~+])' + element_names: '\b(a|abbr|acronym|address|applet|area|article|aside|audio|b|base|basefont|bdi|bdo|big|blockquote|body|br|button|canvas|caption|cite|code|col|colgroup|content|data|datalist|dd|del|details|dfn|dir|dialog|div|dl|dt|element|em|embed|eventsource|fieldset|figure|figcaption|footer|form|frame|frameset|h[1-6]|head|header|hgroup|hr|html|i|iframe|img|input|ins|isindex|kbd|keygen|label|legend|li|link|main|map|mark|menu|meta|meter|nav|noframes|noscript|object|ol|optgroup|option|output|p|param|picture|pre|progress|q|rp|rt|rtc|s|samp|script|section|select|shadow|small|source|span|strike|strong|style|sub|summary|sup|svg|table|tbody|td|template|textarea|tfoot|th|thead|time|title|tr|track|tt|u|ul|var|video|wbr|xmp|circle|clipPath|defs|ellipse|filter|foreignObject|g|glyph|glyphRef|image|line|linearGradient|marker|mask|path|pattern|polygon|polyline|radialGradient|rect|stop|switch|symbol|text|textPath|tref|tspan|use)\b' + counter_styles: |- (?xi: arabic-indic | armenian | bengali | cambodian | circle @@ -64,171 +66,325 @@ variables: | [\x{10000}-\x{EFFFF}] ) + pseudo_elements: |- + (?x: + (:{1,2})(?:before|after|first-line|first-letter) # CSS1 & CSS2 require : or :: + | (::)(-(?:moz|ms|webkit)-)?(?:{{ident}}) # CSS3 requires :: + )\b + + regular_pseudo_classes: '\b(active|any-link|blank|checked|current|default|defined|disabled|drop|empty|enabled|first|first-child|first-of-type|fullscreen|future|focus|focus-visible|focus-within|host|hover|indeterminate|in-range|invalid|last-child|last-of-type|left|link|local-link|only-child|only-of-type|optional|out-of-range|past|placeholder-shown|read-only|read-write|required|right|root|scope|target|target-within|user-invalid|valid|visited)\b(?![-])' + + contexts: main: - include: comment-block - include: comment-line - - include: pseudo-elements - - include: pseudo-classes + - include: selectors - include: properties + - include: custom-element-selectors + # - include: custom-property-name - include: keyframe-operators - - include: selector - include: at-rules - - include: less-variable-declaration - - include: comma-delimiter + # - include: less-map-keys - match: '\{' scope: punctuation.section.property-list.begin.css - match: '\}' scope: punctuation.section.property-list.end.css - selector: - - include: comma-delimiter - - match: '({{combinators}})(?![>~+])' - scope: punctuation.separator.combinator.css - - match: \* + selectors: + # wild card + - match: '\*' scope: entity.name.tag.wildcard.css push: - meta_scope: meta.selector.css - - match: \s*(?=$) - pop: true - - match: '\{' - scope: punctuation.section.property-list.begin.css - pop: true - - match: '(?=\))' - pop: true - - include: pseudo-elements - - include: pseudo-classes - - include: selector + - include: selector-parts + # ampersand - match: '&' - scope: meta.selector.css keyword.operator.ampersand.less + scope: keyword.operator.ampersand.less push: + - match: '{{ident}}*' + scope: entity.other.attribute-name.css - meta_scope: meta.selector.css - - match: \s*(?=$) - pop: true - - match: '\{' - scope: punctuation.section.property-list.begin.css - pop: true - - match: '(?=\))' - pop: true - - match: '(-+|_+)[a-zA-Z_][a-zA-Z0-9_-]*' - scope: meta.selector.css entity.other.attribute-name.css - - include: pseudo-elements - - include: pseudo-classes - - include: selector - - match: '(\.){{ident}}*' + - include: selector-parts + # standard elements + pseudo elements + - match: '({{element_names}})({{pseudo_elements}})' + scope: pseudo.jetser.unit captures: - 0: entity.other.attribute-name.class.css - 1: punctuation.definition.entity.css + 1: entity.name.tag.css + 3: entity.other.pseudo-element.css + 4: punctuation.definition.entity.css + 5: punctuation.definition.entity.css + 6: support.type.vendor-prefix.css push: - meta_scope: meta.selector.css - - match: \s*(?=$) - pop: true - - match: '(?=[{)])' - pop: true - - match: '(-+|_+)[a-zA-Z_][a-zA-Z0-9_-]*' - scope: entity.other.attribute-name.class.css - - include: less-interpolation - - include: pseudo-elements - - include: pseudo-classes - - include: less-mixin - - include: selector - - match: '(\#){{ident}}*' + - include: selector-parts + # standard elements + pseudoclasses + - match: '({{element_names}})((:)({{regular_pseudo_classes}}))' captures: - 0: entity.other.attribute-name.id.css - 1: punctuation.definition.entity.css + 1: entity.name.tag.css + 3: entity.other.pseudo-class.css + 4: punctuation.definition.entity.css push: - meta_scope: meta.selector.css - - match: \s*(?=$) - pop: true - - match: '(?=[{)])' - pop: true - - match: '(-+|_+)[a-zA-Z_][a-zA-Z0-9_-]*' - scope: entity.other.attribute-name.id.css - - include: less-interpolation - - include: pseudo-elements - - include: pseudo-classes - - include: less-mixin - - include: selector - - match: '\b([a-z](?:{{custom_element_chars}})*-(?:{{custom_element_chars}})*)\b' + - include: selector-parts + - match: '({{element_names}})((:)(dir|lang))(?=\()' captures: - 0: entity.name.tag.custom.css + 1: entity.name.tag.css + 3: meta.function-call.cssentity.other.pseudo-class.css + 4: punctuation.definition.entity.css push: - meta_scope: meta.selector.css - - match: \s*(?=$) - pop: true - - match: '(?=[{)])' - pop: true - - include: less-interpolation - - include: pseudo-elements - - include: pseudo-classes - - include: selector - - match: '\b(a|abbr|acronym|address|applet|area|article|aside|audio|b|base|basefont|bdi|bdo|big|blockquote|body|br|button|canvas|caption|cite|code|col|colgroup|content|data|datalist|dd|del|details|dfn|dir|dialog|div|dl|dt|element|em|embed|eventsource|fieldset|figure|figcaption|footer|form|frame|frameset|h[1-6]|head|header|hgroup|hr|html|i|iframe|img|input|ins|isindex|kbd|keygen|label|legend|li|link|main|map|mark|menu|meta|meter|nav|noframes|noscript|object|ol|optgroup|option|output|p|param|picture|pre|progress|q|rp|rt|rtc|s|samp|script|section|select|shadow|small|source|span|strike|strong|style|sub|summary|sup|svg|table|tbody|td|template|textarea|tfoot|th|thead|time|title|tr|track|tt|u|ul|var|video|wbr|xmp|circle|clipPath|defs|ellipse|filter|foreignObject|g|glyph|glyphRef|image|line|linearGradient|marker|mask|path|pattern|polygon|polyline|radialGradient|rect|stop|switch|symbol|text|textPath|tref|tspan|use)\b' + - match: '\(' + scope: punctuation.definition.group.begin.css + push: + - meta_scope: meta.function-call.css meta.group.css + - match: '(?=\))' + pop: true + - include: unquoted-string + - match: '\)' + scope: meta.group.css punctuation.definition.group.end.css + - include: selector-parts + - match: '({{element_names}})((:)(matches|not|has))(?=\()' + captures: + 1: entity.name.tag.css + 3: meta.function-call.css entity.other.pseudo-class.css + 4: punctuation.definition.entity.css + push: + - meta_scope: meta.selector.css + - match: '\(' + scope: punctuation.definition.group.begin.css + push: + - meta_scope: meta.function-call.css meta.group.css + - match: '(?=\))' + pop: true + - include: selectors + - match: '\)' + scope: meta.group.css punctuation.definition.group.end.css + - include: selector-parts + - match: '({{element_names}})((:)(drop))(?=\()' + captures: + 1: entity.name.tag.css + 3: meta.function-call.css entity.other.pseudo-class.css + 4: punctuation.definition.entity.css + push: + - meta_scope: meta.selector.css + - match: '\(' + scope: punctuation.definition.group.begin.css + push: + - meta_scope: meta.function-call.css meta.group.css + - match: '(?=\))' + pop: true + - match: \b(active|valid|invalid)\b + scope: keyword.other.pseudo-class.css + - match: '\)' + scope: meta.group.css punctuation.definition.group.end.css + - include: selector-parts + - match: '({{element_names}})((:)(nth-last-child|nth-child|nth-last-of-type|nth-of-type))(?=\()' + captures: + 1: entity.name.tag.css + 3: meta.function-call.css entity.other.pseudo-class.css + 4: punctuation.definition.entity.css + push: + - meta_scope: meta.selector.css + - match: '\(' + scope: punctuation.definition.group.begin.css + push: + - meta_scope: meta.function-call.css meta.group.css + - match: '(?=\))' + pop: true + - match: \b(even|odd)\b + scope: keyword.other.pseudo-class.css + - match: '(?:[-+]?(?:\d+)?(n)(\s*[-+]\s*\d+)?|[-+]?\s*\d+)' + scope: constant.numeric.css + captures: + 1: keyword.other.unit.css + - match: '\)' + scope: meta.group.css punctuation.definition.group.end.css + - include: selector-parts + + - match: '{{element_names}}(?![-:])' + # stop this at word break and not -, plus : is for pseudos scope: entity.name.tag.css push: - meta_scope: meta.selector.css - - match: \s*(?=$) - pop: true - - match: '(?=[{)])' - pop: true - - include: pseudo-elements - - include: pseudo-classes - - include: selector + - include: selector-parts + # classes / mixins + - match: '(\.)(?={{ident}})' + captures: + 1: entity.other.attribute-name.class.css punctuation.definition.entity.css + push: + - meta_scope: meta.selector.css + - match: '{{ident}}' + scope: entity.other.attribute-name.class.css + - include: less-interpolation + - include: less-mixin-params + - include: selector-parts + # id's / mixins + - match: '(\#)(?={{ident}})' + captures: + 1: entity.other.attribute-name.id.css punctuation.definition.entity.css + push: + - meta_scope: meta.selector.css + - match: '{{ident}}' + scope: entity.other.attribute-name.id.css + - include: less-interpolation + - include: less-mixin-params + - include: selector-parts + # attributes - match: '(?=\[)' push: - - meta_scope: meta.selector.css - - match: \s*(?=$) - pop: true - - match: '(?=[{)])' - pop: true - - match: '\[' - scope: punctuation.definition.entity.css - push: - - meta_scope: meta.attribute-selector.css - - include: qualified-name - - match: '({{ident}})' - scope: entity.other.attribute-name.css - - match: '\s*([~*|^$]?=)\s*' - captures: - 1: keyword.operator.attribute-selector.css - push: - - match: '[^\s\]\[''"]' - scope: string.unquoted.css - - include: literal-string - - match: '(?=(\s|\]))' - pop: true - - match: '(?:\s+([iI]))?' # case insensitive flag - captures: - 1: keyword.other.css - - match: '\]' - scope: punctuation.definition.entity.css - pop: true - - include: less-interpolation - - include: pseudo-elements - - include: pseudo-classes - - include: selector - - include: less-operators + - meta_scope: meta.selector.css + - match: '\[' + scope: punctuation.definition.entity.css + push: + - meta_scope: meta.attribute-selector.css + - match: '\]' + scope: punctuation.definition.entity.css + pop: true + - include: qualified-name + - match: '({{ident}})' + scope: entity.other.attribute-name.css + - match: '\s*([~*|^$]?=)\s*' + captures: + 1: keyword.operator.attribute-selector.css + push: + - match: '[^\s\]\[''"]' + scope: string.unquoted.css + - include: literal-string + - match: '(?=(\s|\]))' + pop: true + - match: '(?:\s+([iI]))?' # case insensitive flag + captures: + 1: keyword.other.css + - include: selector-parts - include: pseudo-elements - include: pseudo-classes - properties: + selector-parts: + - match: '\s*(,)\s*' + captures: + 1: punctuation.separator.css + pop: true + - match: '\s*({{combinators}})(?![>~+])\s*' + captures: + 1: punctuation.separator.combinator.css + pop: true + - match: '\s*(?=\{)' + pop: true + - match: '(?=[.#\[])' # look ahead for classes, id's and attr's + pop: true + - match: '(?=\))' # if passed as a parameter + pop: true + - match: '(?=;)' # if passed as a parameter default value + pop: true - include: comment-block - - match: "-(?:webkit|moz|ms|o)-" - scope: meta.property-name.css support.type.vendor-prefix.css - - include: custom-property-name - - match: '\b(var-)({{ident}})(?=\s)' - scope: meta.property-name.css invalid.deprecated.custom-property.css + - include: pseudo-elements + - include: pseudo-classes + - match: '(?=\s)' + pop: true + + pseudo-elements: + - match: '{{pseudo_elements}}' + scope: entity.other.pseudo-element.css captures: - 1: keyword.other.custom-property.prefix.css - 2: support.type.custom-property.name.css - - match: \bfont(-family)?(?!-)\b + 1: punctuation.definition.entity.css + 2: punctuation.definition.entity.css + 3: support.type.vendor-prefix.css + + pseudo-classes: + - match: '(:)(dir|lang)(?=\()' + scope: entity.other.pseudo-class.css + captures: + 1: punctuation.definition.entity.css + push: + - meta_scope: meta.function-call.css + - include: function-notation-terminator + - match: '\(' + scope: punctuation.definition.group.begin.css + push: + - meta_scope: meta.group.css + - match: '(?=\))' + pop: true + - include: unquoted-string + + - match: '(:)(matches|not|has)(?=\()' + scope: entity.other.pseudo-class.css + captures: + 1: punctuation.definition.entity.css + push: + - meta_scope: meta.function-call.css + - include: function-notation-terminator + - match: '\(' + scope: punctuation.definition.group.begin.css + push: + - meta_scope: meta.group.css + - match: '(?=\))' + pop: true + - match: ',' + scope: punctuation.separator.css + - include: selectors + + - match: '(:)(drop)(?=\()' + scope: entity.other.pseudo-class.css + captures: + 1: punctuation.definition.entity.css + push: + - meta_scope: meta.function-call.css + - include: function-notation-terminator + - match: '\(' + scope: punctuation.definition.group.begin.css + push: + - meta_scope: meta.group.css + - match: '(?=\))' + pop: true + - match: \b(active|valid|invalid)\b + scope: keyword.other.pseudo-class.css + + - match: '(:)(nth-last-child|nth-child|nth-last-of-type|nth-of-type)(?=\()' + scope: entity.other.pseudo-class.css + captures: + 1: punctuation.definition.entity.css + push: + - meta_scope: meta.function-call.css + - include: function-notation-terminator + - match: '\(' + scope: punctuation.definition.group.begin.css + push: + - meta_scope: meta.group.css + - match: '(?=\))' + pop: true + - match: \b(even|odd)\b + scope: keyword.other.pseudo-class.css + - match: '(?:[-+]?(?:\d+)?(n)(\s*[-+]\s*\d+)?|[-+]?\s*\d+)' + scope: constant.numeric.css + captures: + 1: keyword.other.unit.css + + - match: '(:)({{regular_pseudo_classes}})' + scope: entity.other.pseudo-class.css + captures: + 1: punctuation.definition.entity.css + + custom-element-selectors: + - match: '\b([a-z](?:{{custom_element_chars}})*-(?:{{custom_element_chars}})*)\b' + captures: + 0: entity.name.tag.custom.css + push: + - meta_scope: meta.selector.css + - include: selector-parts + + + + + properties: + - include: comment-block + - match: '\bfont(-family)?(?!-)\b(?=\s*:)' scope: meta.property-name.css support.type.property-name.css push: - - match: (:)([ \t]*) - captures: - 1: punctuation.separator.key-value.css - 2: meta.property-value.css + - match: ':' + scope: punctuation.separator.key-value.css push: - meta_content_scope: meta.property-value.css - match: '\s*(;)|(?=[})])' @@ -316,17 +472,43 @@ contexts: | blend-mode|azimuth|pause-after|pause-before|pause|pitch-range|pitch | text-height|system|negative|prefix|suffix|range|pad|fallback | additive-symbols|symbols|speak-as|speak|grid-gap - )\b(?=\s*:[^:]*(;|\n)) + )\b(?=\s*:) scope: meta.property-name.css support.type.property-name.css - - match: (:)([ \t]*) + push: + - include: property-value-wrapper + - match: '(-(?:webkit|moz|ms|o)-)({{ident}})(?=\s*:)' + captures: + 0: meta.property-name.css + 1: support.type.vendor-prefix.css + 2: support.type.property-name.css + push: + - include: property-value-wrapper + - match: '(@)([a-zA-Z0-9_-][\w-]*)(?=\s*:)' captures: - 1: punctuation.separator.key-value.css - 2: meta.property-value.css + 0: variable.declaration.less + 1: punctuation.definition.variable.less + push: + - include: property-value-wrapper + - match: '(--)({{nmchar}}+)' + captures: + 0: meta.property-name.css support.type.custom-property.css + 1: punctuation.definition.custom-property.css + 2: support.type.custom-property.name.css + push: + - include: property-value-wrapper + + property-value-wrapper: + - match: '\s*(;)' + pop: true + captures: + 1: punctuation.terminator.rule.css + - match: '(?=\s*($|[;})]))' + pop: true + - match: ':' + scope: punctuation.separator.key-value.css push: - meta_content_scope: meta.property-value.css - - match: '\s*(;)|(?=[})])' - captures: - 1: punctuation.terminator.rule.css + - match: '(?=\s*($|[;})]))' pop: true - include: property-values @@ -565,12 +747,28 @@ contexts: - include: numeric-values - - less-variable-declaration: - - match: '(@)([a-zA-Z0-9_-][\w-]*)' + less-map-keys: + - match: '({{ident}})\s*(?=:)' captures: - 0: variable.declaration.less - 1: punctuation.definition.variable.less + 1: variable.declaration.map-key.less + + less-mixin-params: + - match: '\(' + scope: punctuation.definition.group.begin.css + push: + - meta_scope: meta.function.parameters.less + - match: ';' + scope: punctuation.separator.comma.less + - match: ':' + scope: punctuation.separator.key-value.less + - include: selectors + - include: less-variables + - include: less-functions + - include: property-values + - include: literal-string + - match: '\)' + scope: punctuation.definition.group.end.css + pop: true less-variables: - include: less-interpolation @@ -634,26 +832,6 @@ contexts: - match: /|$|%|\*|\-\-|\-|\+\+|\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\|\||\?\:|%=|\+=|\-=|&=|\bnot\b|\bor\b|\band\b|\bwhen\b scope: keyword.operator.less - less-mixin: - - match: '\(' - scope: punctuation.definition.group.begin.css - push: - - meta_scope: meta.function.parameters.less - - include: less-variables - - include: less-functions - - include: property-values - - include: literal-string - - include: selector - - match: '\{' - scope: punctuation.section.property-list.begin.css - push: - - match: '\}' - scope: punctuation.section.property-list.end.css - pop: true - - include: main - - match: '\)' - scope: punctuation.definition.group.end.css - pop: true @@ -821,101 +999,6 @@ contexts: - match: \b(?i:sans-serif|serif|monospace|fantasy|cursive|system-ui)\b(?=\s*[;,\n}]) scope: support.constant.font-name.css - custom-property-name: - - match: '(--)({{nmchar}}+)' - captures: - 0: meta.property-name.css support.type.custom-property.css - 1: punctuation.definition.custom-property.css - 2: support.type.custom-property.name.css - - - - pseudo-elements: - - match: |- - (?x: - (:{1,2})(?:before|after|first-line|first-letter) # CSS1 & CSS2 require : or :: - | (::)(-(?:moz|ms|webkit)-)?(?:{{ident}}) # CSS3 requires :: - )\b - scope: entity.other.pseudo-element.css - captures: - 1: punctuation.definition.entity.css - 2: punctuation.definition.entity.css - 3: support.type.vendor-prefix.css - - pseudo-classes: - - match: '(:)(dir|lang)(?=\()' - scope: entity.other.pseudo-class.css - captures: - 1: punctuation.definition.entity.css - push: - - meta_scope: meta.function-call.css - - include: function-notation-terminator - - match: '\(' - scope: punctuation.definition.group.begin.css - push: - - meta_scope: meta.group.css - - match: '(?=\))' - pop: true - - include: unquoted-string - - - match: '(:)(matches|not|has)(?=\()' - scope: entity.other.pseudo-class.css - captures: - 1: punctuation.definition.entity.css - push: - - meta_scope: meta.function-call.css - - include: function-notation-terminator - - match: '\(' - scope: punctuation.definition.group.begin.css - push: - - meta_scope: meta.group.css - - match: '(?=\))' - pop: true - - include: pseudo-classes - - include: selector - - - match: '(:)(drop)(?=\()' - scope: entity.other.pseudo-class.css - captures: - 1: punctuation.definition.entity.css - push: - - meta_scope: meta.function-call.css - - include: function-notation-terminator - - match: '\(' - scope: punctuation.definition.group.begin.css - push: - - meta_scope: meta.group.css - - match: '(?=\))' - pop: true - - match: \b(active|valid|invalid)\b - scope: keyword.other.pseudo-class.css - - - match: '(:)(nth-last-child|nth-child|nth-last-of-type|nth-of-type)(?=\()' - scope: entity.other.pseudo-class.css - captures: - 1: punctuation.definition.entity.css - push: - - meta_scope: meta.function-call.css - - include: function-notation-terminator - - match: '\(' - scope: punctuation.definition.group.begin.css - push: - - meta_scope: meta.group.css - - match: '(?=\))' - pop: true - - match: \b(even|odd)\b - scope: keyword.other.pseudo-class.css - - match: '(?:[-+]?(?:\d+)?(n)(\s*[-+]\s*\d+)?|[-+]?\s*\d+)' - scope: constant.numeric.css - captures: - 1: keyword.other.unit.css - - - match: '(:)({{ident}})' - scope: entity.other.pseudo-class.css - captures: - 1: punctuation.definition.entity.css - - builtin-functions: - include: attr-function @@ -1343,7 +1426,11 @@ contexts: - include: comma-delimiter - include: less-variables - include: less-functions - - include: custom-property-name + - match: '(--)({{nmchar}}+)' + captures: + 0: meta.property-name.css support.type.custom-property.css + 1: punctuation.definition.custom-property.css + 2: support.type.custom-property.name.css filter-functions: - match: '\b(blur)(?=\()' diff --git a/syntax_test_less.less b/syntax_test_less.less index 9b24b35..551bde2 100755 --- a/syntax_test_less.less +++ b/syntax_test_less.less @@ -1,5 +1,44 @@ // SYNTAX TEST "Packages/LESS/LESS.sublime-syntax" +/* +Correctly differentiate between properties and selectors, +especially with pseudo-stuff because of the : +*/ + +*, +& + h1, +&:active #unit h1 + div, +&-element + h1, +[data-type="text"], +span::before[data-type="text"], +selector-ish::before[data-type="text"]:not(:first-child), +.selector:hover selector-ish.selector::before { + *, + & + h1, + &:active + h1, + &-element + h1, + [data-type="text"], + span::before[data-type="text"], + filter::before[data-type="text"], + selector-ish::before[data-type="text"]:not(:first-child), + #selec-tor:hover, selector-ish::before { + color: rgba(100, 120, 12, 95%); + background-color: blue; + line-height: ~"calc(@{space} + 4px)"; + span:hover {} + filter:not(.empty) {} + filter:drop-shadow(0 0 2px rgba(0, 0, 0, 0.3)); + filter:blue; + filter: drop-shadow(0 0 2px rgba(0, 0, 0, 0.3)) + } + color: rgba(100, 120, 12, 95%); + background-color: blue +} + + + + + :root, // <- entity.other.pseudo-class.css punctuation.definition.entity.css // ^^ entity.other.pseudo-class.css @@ -34,8 +73,9 @@ // ^^^^^^^ entity.other.pseudo-class.css // ^ punctuation.definition.entity.css - #id@{interopol} - background: bla + #id@{interopol}bla, + custom-element@{interopol}test, + background: blue // ^ meta.property-name.css } @@ -157,7 +197,7 @@ html::before { filter: drop-shadow(0 0 2px rgba(0, 0, 0, 0.3)); // ^ support.type.property-name.css - .fade-in(@selector) { + .fade-in(h1) { @keyframes fade-in-animation { // ^ meta.at-rule.keyframe.css keyword.control.at-rule.keyframe.css punctuation.definition.keyword.css // ^ meta.at-rule.keyframe.css entity.other.animation-name.css @@ -179,6 +219,22 @@ html::before { } } } + + +/* + Mixins + http://lesscss.org/features/#mixins-feature +*/ +.border-radius(@color: h1; @padding; @margin: 2) { + -webkit-border-radius: @radius; + -moz-border-radius: @radius; + border-radius: @radius; +} + + +/* +Attribute selectors +*/ a[data-property="text"] { // ^^^^^^^^^^^^^^^^^^^^^^ meta.attribute-selector.css // ^ punctuation.definition.entity.css @@ -206,6 +262,11 @@ html::before { // ^ meta.attribute-selector.css keyword.other.css a[value*="text" I] { // ^ meta.attribute-selector.css keyword.operator.attribute-selector.css + + + + + color: @link-color; // ^ punctuation.definition.variable.less color: @@color; // variable variables @@ -217,7 +278,7 @@ html::before { .mixin { /* */ } // ^ punctuation.definition.entity.css // ^^^^^^ meta.selector.css - .mixin() { /* */ } + #mixin(@color-param, @position-param) { /* */ } // ^ punctuation.definition.entity.css // ^^^^^^ meta.selector.css .border-radius(@radius: 5px) { @@ -259,8 +320,8 @@ html::before { .@{varname}--subclass#another-variable@{variable}id[data-attr="text"] { color: @orangy; } // ^ entity.other.attribute-name.class.css // ^ entity.other.attribute-name.id.css punctuation.definition.entity.css -// ^ entity.other.attribute-name.id.css variable.other.less punctuation.definition.variable.less -// ^ entity.other.attribute-name.id.css +// ^ entity.other.attribute-name.id.css +// ^ entity.other.attribute-name.id.css } #@{varname}--subclass { color: @orangy; } // ^ entity.other.attribute-name.id.css @@ -342,6 +403,7 @@ html::before { height: 48px; border-radius: 50%; background: url(data:@{image}/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7); +// ^ support.type.property-name.css // ^ meta.property-value.css meta.group.css punctuation.definition.group.begin.css // ^ meta.property-value.css meta.group.css string.unquoted.css // ^ meta.property-value.css meta.group.css variable.other.less punctuation.definition.string.begin.less @@ -387,6 +449,50 @@ html::before { // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.group.css string.unquoted.css +/* + Maps + http://lesscss.org/#maps +*/ +@sizes: { + mobile: 320px; +//^^^^^^ meta.group.map.less variable.declaration.map.less +// ^^^^^ constant.numeric.css +// ^ punctuation.separator.key-value.less +// ^ punctuation.terminator.rule + tablet: 768px; + desktop: 1024px; +} +@config: { + @options: { + library-on: true +// ^^^^^^^^^^ meta.group.map.less variable.declaration.map.less + } +} +#colors() { + primary: blue; + secondary: green; +} +#library() { + .colors() { primary: grey; } +} + +.button { + color: #colors[primary]; + border: 1px solid #colors[secondary]; +} +.navbar { + display: block; + + @media (min-width: @sizes[tablet]) { + display: inline-block; + } +} +& when (@config[@options][library-on] = true) { + .produce-ruleset { + prop: val; + } +} + // http://lesscss.org/features/#detached-rulesets-feature header { background-color: blue; From 4b5a41693d1ae84a39fbd57d7d94326dfefcca39 Mon Sep 17 00:00:00 2001 From: Koen Lageveen Date: Wed, 14 Nov 2018 08:05:28 +0100 Subject: [PATCH 2/9] pass most mixin tests --- LESS.sublime-syntax | 38 ++++++++++++------ syntax_test_less.less | 93 ++++++++++++++++++++++--------------------- 2 files changed, 73 insertions(+), 58 deletions(-) diff --git a/LESS.sublime-syntax b/LESS.sublime-syntax index 7c61156..d363749 100644 --- a/LESS.sublime-syntax +++ b/LESS.sublime-syntax @@ -82,14 +82,11 @@ contexts: - include: selectors - include: properties - include: custom-element-selectors - # - include: custom-property-name - include: keyframe-operators - include: at-rules + - include: curly-braces # - include: less-map-keys - - match: '\{' - scope: punctuation.section.property-list.begin.css - - match: '\}' - scope: punctuation.section.property-list.end.css + selectors: @@ -210,7 +207,7 @@ contexts: - meta_scope: meta.selector.css - include: selector-parts # classes / mixins - - match: '(\.)(?={{ident}})' + - match: '(\.)(?={{ident}}|@)' captures: 1: entity.other.attribute-name.class.css punctuation.definition.entity.css push: @@ -221,7 +218,7 @@ contexts: - include: less-mixin-params - include: selector-parts # id's / mixins - - match: '(\#)(?={{ident}})' + - match: '(\#)(?={{ident}}|@)' captures: 1: entity.other.attribute-name.id.css punctuation.definition.entity.css push: @@ -498,10 +495,11 @@ contexts: - include: property-value-wrapper property-value-wrapper: - - match: '\s*(;)' + - match: '(\s*)(;)' pop: true captures: - 1: punctuation.terminator.rule.css + 1: meta.property-value.css + 2: punctuation.terminator.rule.css - match: '(?=\s*($|[;})]))' pop: true - match: ':' @@ -753,19 +751,28 @@ contexts: 1: variable.declaration.map-key.less less-mixin-params: - - match: '\(' - scope: punctuation.definition.group.begin.css + - match: \s*(not|or|and|when)\b + captures: + 1: keyword.operator.logic.mixin.less + - match: '\s*(\()' + captures: + 1: punctuation.definition.group.begin.css push: - meta_scope: meta.function.parameters.less - match: ';' scope: punctuation.separator.comma.less - match: ':' scope: punctuation.separator.key-value.less - - include: selectors + - include: comment-block + - include: comment-line - include: less-variables - include: less-functions + - include: properties - include: property-values + - include: selectors - include: literal-string + - include: less-operators + - include: curly-braces - match: '\)' scope: punctuation.definition.group.end.css pop: true @@ -2089,6 +2096,13 @@ contexts: + curly-braces: + - match: '\{' + scope: punctuation.section.property-list.begin.css + - match: '\}' + scope: punctuation.section.property-list.end.css + + comment-block: - match: /\* scope: punctuation.definition.comment.css diff --git a/syntax_test_less.less b/syntax_test_less.less index 551bde2..b36c206 100755 --- a/syntax_test_less.less +++ b/syntax_test_less.less @@ -106,6 +106,19 @@ filter {} // ^ - entity.name.tag.css filter{} // ^ entity.name.tag.css +.use-mixin { +// ^^^^^^^ meta.selector.css entity.other.attribute-name.class.css + &--bem {} +// ^^^^^ meta.selector.css entity.other.attribute-name +//^ keyword.operator.ampersand.less + &_bem {} +// ^^^^ meta.selector.css entity.other.attribute-name +// ^ meta.selector.css +} +.accordion__copy, +// ^^^^^^^^^^^^^ meta.selector.css entity.other.attribute-name.class.css +.accordion__copy--open {} +// ^^^^^^^^^^^^^^^^^^^ meta.selector.css entity.other.attribute-name.class.css #main h1+.sub { // <- entity.other.attribute-name.id.css punctuation.definition.entity.css // ^^ entity.other.attribute-name.id.css @@ -232,6 +245,40 @@ html::before { } +/* +Guarded Namespaces and Mixins +http://lesscss.org/features/#mixins-feature-guarded-namespaces +*/ + +#namespace when not (@mode = huge) { +// ^ meta.function.parameters.less keyword.operator.less + +.a-test-mixin(@color: black; /*@margin: 10px;*/ @padding: 20px) when (lightness(@a) >= 50%) { +// ^^^^^^^^^^^^^^^^^^ comment.block.css +// ^^ punctuation.definition.comment.css +// ^^ punctuation.definition.comment.css +// ^^ keyword.operator +// ^^ meta.function.parameters.less variable.other.less +// ^ punctuation.definition.variable.less + .nested { + @media screen and (max-width: 100px) { + .mixin(@a) when not (isnumber(@a)) and (@a > 0) ... } +// ^^ keyword.operator +// ^^^^^^^^ meta.function-call.less support.function.less + } + } + color: mix(@grey4, @grey5); +// ^ meta.property-value.css meta.function-call.less support.function.less + background: mix(@white, mix(@grey4, @grey5)); +// ^ meta.property-value.css meta.function-call.less support.function.less + background-color: linear-gradient(@white, mix(@grey4, mix(@grey4, @grey5))); +// ^ meta.property-value.css meta.function-call.less support.function.less + padding: @padding; +} +.mixin(@a) when not (isnumber(@a)) and (@a > 0) ... } +// ^ meta.function.parameters.less keyword.operator.less + + /* Attribute selectors */ @@ -326,48 +373,6 @@ Attribute selectors #@{varname}--subclass { color: @orangy; } // ^ entity.other.attribute-name.id.css -.use-mixin { -// ^^^^^^^ meta.selector.css entity.other.attribute-name.class.css - &--bem {} -// ^^^^^ meta.selector.css entity.other.attribute-name -//^ keyword.operator.ampersand.less - &_bem {} -// ^^^^ meta.selector.css entity.other.attribute-name -// ^ meta.selector.css -} -.accordion__copy, -// ^^^^^^^^^^^^^ meta.selector.css entity.other.attribute-name.class.css -.accordion__copy--open {} -// ^^^^^^^^^^^^^^^^^^^ meta.selector.css entity.other.attribute-name.class.css - -#namespace when (@mode = huge) { -// ^ meta.function.parameters.less keyword.operator.less - -.a-test-mixin(@color: black; /*@margin: 10px;*/ @padding: 20px) when (lightness(@a) >= 50%) { -// ^^^^^^^^^^^^^^^^^^ comment.block.css -// ^^ punctuation.definition.comment.css -// ^^ punctuation.definition.comment.css -// ^^ keyword.operator.less -// ^^ meta.function.parameters.less variable.other.less -// ^ punctuation.definition.variable.less - .nested { - @media screen and (max-width: 100px) { - .mixin(@a) when not (isnumber(@a)) and (@a > 0) ... } -// ^^ keyword.operator.less -// ^^^^^^^^ meta.function-call.less support.function.less - } - } - color: mix(@grey4, @grey5); -// ^ meta.property-value.css meta.function-call.less support.function.less - background: mix(@white, mix(@grey4, @grey5)); -// ^ meta.property-value.css meta.function-call.less support.function.less - background-color: linear-gradient(@white, mix(@grey4, mix(@grey4, @grey5))); -// ^ meta.property-value.css meta.function-call.less support.function.less - padding: @padding; -} -.mixin(@a) when not (isnumber(@a)) and (@a > 0) ... } -// ^ meta.function.parameters.less keyword.operator.less - @media only tv /*awesome*/ and (-webkit-max-width: @pixels) and (max-pixel-ratio: 1920/1200) and (min-aspect-ratio: portrait) { } // ^ meta.at-rule.media.css keyword.operator.logic.media.css // ^ meta.at-rule.media.css @@ -823,10 +828,6 @@ header { // ^^ punctuation.definition.custom-property // ^^^^^^^^ support.type.custom-property.name.css -.test-deprecated-var { var-deprecated- } -// ^^^^^^^^^^^^^^^ invalid.deprecated.custom-property.css -// ^^^^ keyword.other.custom-property.prefix.css - .test-types { top: 20; // ^^ constant.numeric.css From b74d27de2ffb19e0c3be26bdadcc36434e20762c Mon Sep 17 00:00:00 2001 From: Koen Lageveen Date: Wed, 14 Nov 2018 08:32:05 +0100 Subject: [PATCH 3/9] first pass at really fixing map values --- LESS.sublime-syntax | 134 +++++++++++++++++++++++++++++++++++++----- syntax_test_less.less | 14 +++-- 2 files changed, 128 insertions(+), 20 deletions(-) diff --git a/LESS.sublime-syntax b/LESS.sublime-syntax index d363749..e847902 100644 --- a/LESS.sublime-syntax +++ b/LESS.sublime-syntax @@ -65,6 +65,8 @@ variables: | [\x{FDF0}-\x{FFFD}] | [\x{10000}-\x{EFFFF}] ) + custom_elements: '\b([a-z](?:{{custom_element_chars}})*-(?:{{custom_element_chars}})*)\b(?!{{ident}})' + pseudo_elements: |- (?x: @@ -81,11 +83,11 @@ contexts: - include: comment-line - include: selectors - include: properties - - include: custom-element-selectors - include: keyframe-operators + - include: custom-element-selectors + - include: less-map-values - include: at-rules - include: curly-braces - # - include: less-map-keys @@ -199,7 +201,7 @@ contexts: - match: '\)' scope: meta.group.css punctuation.definition.group.end.css - include: selector-parts - + # standard elements - match: '{{element_names}}(?![-:])' # stop this at word break and not -, plus : is for pseudos scope: entity.name.tag.css @@ -259,6 +261,112 @@ contexts: - include: pseudo-classes + custom-element-selectors: + # custom elements + pseudo elements + - match: '({{custom_elements}})({{pseudo_elements}})' + scope: pseudo.jetser.unit + captures: + 1: entity.name.tag.custom.css + 3: entity.other.pseudo-element.css + 4: punctuation.definition.entity.css + 5: punctuation.definition.entity.css + 6: support.type.vendor-prefix.css + push: + - meta_scope: meta.selector.css + - include: selector-parts + # custom elements + pseudoclasses + - match: '({{custom_elements}})((:)({{regular_pseudo_classes}}))' + captures: + 1: entity.name.tag.custom.css + 3: entity.other.pseudo-class.css + 4: punctuation.definition.entity.css + push: + - meta_scope: meta.selector.css + - include: selector-parts + - match: '({{custom_elements}})((:)(dir|lang))(?=\()' + captures: + 1: entity.name.tag.custom.css + 3: meta.function-call.cssentity.other.pseudo-class.css + 4: punctuation.definition.entity.css + push: + - meta_scope: meta.selector.css + - match: '\(' + scope: punctuation.definition.group.begin.css + push: + - meta_scope: meta.function-call.css meta.group.css + - match: '(?=\))' + pop: true + - include: unquoted-string + - match: '\)' + scope: meta.group.css punctuation.definition.group.end.css + - include: selector-parts + - match: '({{custom_elements}})((:)(matches|not|has))(?=\()' + captures: + 1: entity.name.tag.custom.css + 3: meta.function-call.css entity.other.pseudo-class.css + 4: punctuation.definition.entity.css + push: + - meta_scope: meta.selector.css + - match: '\(' + scope: punctuation.definition.group.begin.css + push: + - meta_scope: meta.function-call.css meta.group.css + - match: '(?=\))' + pop: true + - include: selectors + - match: '\)' + scope: meta.group.css punctuation.definition.group.end.css + - include: selector-parts + - match: '({{custom_elements}})((:)(drop))(?=\()' + captures: + 1: entity.name.tag.custom.css + 3: meta.function-call.css entity.other.pseudo-class.css + 4: punctuation.definition.entity.css + push: + - meta_scope: meta.selector.css + - match: '\(' + scope: punctuation.definition.group.begin.css + push: + - meta_scope: meta.function-call.css meta.group.css + - match: '(?=\))' + pop: true + - match: \b(active|valid|invalid)\b + scope: keyword.other.pseudo-class.css + - match: '\)' + scope: meta.group.css punctuation.definition.group.end.css + - include: selector-parts + - match: '({{custom_elements}})((:)(nth-last-child|nth-child|nth-last-of-type|nth-of-type))(?=\()' + captures: + 1: entity.name.tag.custom.css + 3: meta.function-call.css entity.other.pseudo-class.css + 4: punctuation.definition.entity.css + push: + - meta_scope: meta.selector.css + - match: '\(' + scope: punctuation.definition.group.begin.css + push: + - meta_scope: meta.function-call.css meta.group.css + - match: '(?=\))' + pop: true + - match: \b(even|odd)\b + scope: keyword.other.pseudo-class.css + - match: '(?:[-+]?(?:\d+)?(n)(\s*[-+]\s*\d+)?|[-+]?\s*\d+)' + scope: constant.numeric.css + captures: + 1: keyword.other.unit.css + - match: '\)' + scope: meta.group.css punctuation.definition.group.end.css + - include: selector-parts + # custom elements + - match: '{{custom_elements}}(?![-:])' + captures: + 0: entity.name.tag.custom.css + push: + - meta_scope: meta.selector.css + - include: selector-parts + + + selector-parts: - match: '\s*(,)\s*' captures: @@ -364,15 +472,6 @@ contexts: captures: 1: punctuation.definition.entity.css - custom-element-selectors: - - match: '\b([a-z](?:{{custom_element_chars}})*-(?:{{custom_element_chars}})*)\b' - captures: - 0: entity.name.tag.custom.css - push: - - meta_scope: meta.selector.css - - include: selector-parts - - properties: @@ -494,6 +593,12 @@ contexts: push: - include: property-value-wrapper + less-map-values: + - match: '{{ident}}' + scope: variable.declaration.map.less + push: + - include: property-value-wrapper + property-value-wrapper: - match: '(\s*)(;)' pop: true @@ -745,10 +850,7 @@ contexts: - include: numeric-values - less-map-keys: - - match: '({{ident}})\s*(?=:)' - captures: - 1: variable.declaration.map-key.less + less-mixin-params: - match: \s*(not|or|and|when)\b diff --git a/syntax_test_less.less b/syntax_test_less.less index b36c206..a2ad3ca 100755 --- a/syntax_test_less.less +++ b/syntax_test_less.less @@ -32,7 +32,8 @@ selector-ish::before[data-type="text"]:not(:first-child), filter: drop-shadow(0 0 2px rgba(0, 0, 0, 0.3)) } color: rgba(100, 120, 12, 95%); - background-color: blue + background-color: blue; + testbackground-color: blue; } @@ -457,12 +458,13 @@ Attribute selectors /* Maps http://lesscss.org/#maps + http://lesscss.org/features/#maps-feature */ @sizes: { mobile: 320px; -//^^^^^^ meta.group.map.less variable.declaration.map.less +//^^^^^^ variable.declaration.map.less // ^^^^^ constant.numeric.css -// ^ punctuation.separator.key-value.less +// ^ punctuation.separator.key-value // ^ punctuation.terminator.rule tablet: 768px; desktop: 1024px; @@ -470,7 +472,7 @@ Attribute selectors @config: { @options: { library-on: true -// ^^^^^^^^^^ meta.group.map.less variable.declaration.map.less +// ^^^^^^^^^^ variable.declaration.map.less } } #colors() { @@ -539,6 +541,10 @@ header { + + + + // ------------ A selection of tests from the default CSS package: ------------- From 69026cd667f88484f2274c361099acafd6305ad7 Mon Sep 17 00:00:00 2001 From: Koen Lageveen Date: Wed, 14 Nov 2018 17:09:44 +0100 Subject: [PATCH 4/9] implement basic maps lookups --- LESS.sublime-syntax | 33 ++++++++++++++++++++++++++++++++- syntax_test_less.less | 24 +++++++++++++++++++++++- 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/LESS.sublime-syntax b/LESS.sublime-syntax index e847902..369c294 100644 --- a/LESS.sublime-syntax +++ b/LESS.sublime-syntax @@ -852,8 +852,18 @@ contexts: + less-map-lookups: + - match: '\[' + scope: punctuation.section.brackets.begin.less + - match: '\]' + scope: meta.brackets.less punctuation.section.brackets.end.less + pop: true + - include: less-variables + - match: '{{ident}}' + scope: variable.other.less + less-mixin-params: - - match: \s*(not|or|and|when)\b + - match: '\s*(not|or|and|when)\b' captures: 1: keyword.operator.logic.mixin.less - match: '\s*(\()' @@ -880,6 +890,27 @@ contexts: pop: true less-variables: + - match: '(\.)\S+(?=\[)' + captures: + 0: entity.other.attribute-name.class.less + 1: punctuation.definition.entity.less + push: + - meta_content_scope: meta.brackets.less + - include: less-map-lookups + - match: '(#)\S+(?=\[)' + captures: + 0: entity.other.attribute-name.id.less + 1: punctuation.definition.entity.less + push: + - meta_content_scope: meta.brackets.less + - include: less-map-lookups + - match: '(@)\S+(?=\[)' + captures: + 0: variable.other.less + 1: punctuation.definition.variable.less + push: + - meta_content_scope: meta.brackets.less + - include: less-map-lookups - include: less-interpolation - match: '(@{1,2})([a-zA-Z0-9_-][\w-]*)' captures: diff --git a/syntax_test_less.less b/syntax_test_less.less index a2ad3ca..6afcb80 100755 --- a/syntax_test_less.less +++ b/syntax_test_less.less @@ -485,12 +485,29 @@ Attribute selectors .button { color: #colors[primary]; - border: 1px solid #colors[secondary]; +// ^^^^^^^ entity.other.attribute-name.id +// ^ punctuation.definition.entity +// ^^^^^^^^^ meta.brackets.less +// ^ punctuation.section.brackets.begin +// ^ punctuation.section.brackets.end +// ^^^^^^ variable.other.less + border: 1px solid .colors[@secondary]; +// ^^^^^^^ entity.other.attribute-name.class +// ^ punctuation.definition.entity +// ^^^^^^^^^ meta.brackets.less +// ^ punctuation.section.brackets.begin +// ^ punctuation.section.brackets.end +// ^^^^^^ variable.other.less +// ^ punctuation.definition.variable } .navbar { display: block; @media (min-width: @sizes[tablet]) { +// ^^^^^^^^ meta.brackets.less +// ^ punctuation.section.brackets.begin +// ^ punctuation.section.brackets.end +// ^^^^^^ variable.other.less display: inline-block; } } @@ -499,6 +516,11 @@ Attribute selectors prop: val; } } +.button { + @colors: #library.colors(); + color: @colors[primary]; + border-color: @colors[secondary]; +} // http://lesscss.org/features/#detached-rulesets-feature header { From a36662f9975fe9f8a1e4a6ae6c2d27d9a40d8378 Mon Sep 17 00:00:00 2001 From: Koen Lageveen Date: Wed, 14 Nov 2018 20:10:07 +0100 Subject: [PATCH 5/9] pass test for unquoted font string --- LESS.sublime-syntax | 6 ++++-- syntax_test_less.less | 46 ++++++++++++++++++++++++++++++++++++------- 2 files changed, 43 insertions(+), 9 deletions(-) diff --git a/LESS.sublime-syntax b/LESS.sublime-syntax index 369c294..5834ab2 100644 --- a/LESS.sublime-syntax +++ b/LESS.sublime-syntax @@ -614,6 +614,8 @@ contexts: - match: '(?=\s*($|[;})]))' pop: true - include: property-values + - match: '{{ident}}' # e.g. animation-name + scope: string.unquoted.css property-values: - match: \!\s*important @@ -632,8 +634,6 @@ contexts: - include: literal-string - include: less-variables - include: less-functions - - match: '{{ident}}' # e.g. animation-name - scope: string.unquoted.css - include: less-operators @@ -885,6 +885,8 @@ contexts: - include: literal-string - include: less-operators - include: curly-braces + - match: '{{ident}}' # pretty much everything else + scope: string.unquoted.css - match: '\)' scope: punctuation.definition.group.end.css pop: true diff --git a/syntax_test_less.less b/syntax_test_less.less index 6afcb80..768e461 100755 --- a/syntax_test_less.less +++ b/syntax_test_less.less @@ -223,6 +223,7 @@ html::before { .@{selector} { animation : progress-fade-in-animation .15s ease-in; // ^ meta.property-value.css +// ^ string.unquoted.css // ^ meta.property-name.css support.type.property-name.css animation: progress-fade-in-animation .15s ease-in; // ^ source.css.less punctuation.separator.key-value.css @@ -239,7 +240,7 @@ html::before { Mixins http://lesscss.org/features/#mixins-feature */ -.border-radius(@color: h1; @padding; @margin: 2) { +.border-radius(@color: h1; @padding; @margin: 2;) { -webkit-border-radius: @radius; -moz-border-radius: @radius; border-radius: @radius; @@ -253,7 +254,7 @@ http://lesscss.org/features/#mixins-feature-guarded-namespaces #namespace when not (@mode = huge) { // ^ meta.function.parameters.less keyword.operator.less - +// ^ string.unquoted .a-test-mixin(@color: black; /*@margin: 10px;*/ @padding: 20px) when (lightness(@a) >= 50%) { // ^^^^^^^^^^^^^^^^^^ comment.block.css // ^^ punctuation.definition.comment.css @@ -477,6 +478,8 @@ Attribute selectors } #colors() { primary: blue; +// ^^^^^ variable.declaration.map.less +// ^ punctuation.separator.key-value secondary: green; } #library() { @@ -516,13 +519,42 @@ Attribute selectors prop: val; } } -.button { - @colors: #library.colors(); - color: @colors[primary]; - border-color: @colors[secondary]; + + +/* +Aliasing Mixins +http://lesscss.org/features/#mixins-feature-mixin-aliasing-feature +*/ +#theme.dark.navbar { + .colors(light) { + primary: purple; + } + .colors(dark) { + primary: black; + secondary: grey; + } + .box { + @alias: #library.rules(); + @alias(); + } +} + +.navbar { + @colors: #theme.dark.navbar.colors(dark); + background: @colors[primary]; + border: 1px solid @colors[secondary]; + .button { + @colors: #library.colors(); + color: @colors[primary]; + border-color: @colors[secondary]; + } } -// http://lesscss.org/features/#detached-rulesets-feature + +/* +Detached Rulesets +http://lesscss.org/features/#detached-rulesets-feature +*/ header { background-color: blue; From cbbd6f60c812867fcd5328e0a6e98d0241d51f18 Mon Sep 17 00:00:00 2001 From: Koen Lageveen Date: Wed, 14 Nov 2018 20:52:47 +0100 Subject: [PATCH 6/9] support mixin aliasing --- LESS.sublime-syntax | 120 ++++++++++++++++++++++++++++++++++++++---- syntax_test_less.less | 37 ++++++++++++- 2 files changed, 145 insertions(+), 12 deletions(-) diff --git a/LESS.sublime-syntax b/LESS.sublime-syntax index 5834ab2..d0fe446 100644 --- a/LESS.sublime-syntax +++ b/LESS.sublime-syntax @@ -593,12 +593,6 @@ contexts: push: - include: property-value-wrapper - less-map-values: - - match: '{{ident}}' - scope: variable.declaration.map.less - push: - - include: property-value-wrapper - property-value-wrapper: - match: '(\s*)(;)' pop: true @@ -635,6 +629,7 @@ contexts: - include: less-variables - include: less-functions - include: less-operators + - include: less-aliases at-rules: @@ -848,10 +843,17 @@ contexts: - include: less-variables - include: less-functions - include: numeric-values + - include: less-aliases + less-map-values: + - match: '{{ident}}' + scope: variable.declaration.map.less + push: + - include: property-value-wrapper + less-map-lookups: - match: '\[' scope: punctuation.section.brackets.begin.less @@ -859,6 +861,7 @@ contexts: scope: meta.brackets.less punctuation.section.brackets.end.less pop: true - include: less-variables + - include: less-aliases - match: '{{ident}}' scope: variable.other.less @@ -885,35 +888,80 @@ contexts: - include: literal-string - include: less-operators - include: curly-braces + - include: less-aliases - match: '{{ident}}' # pretty much everything else scope: string.unquoted.css - match: '\)' scope: punctuation.definition.group.end.css pop: true + less-aliases: + - match: '((\.){{ident}})(?=[.#])' + captures: + 1: entity.other.attribute-name.class.less + 2: punctuation.definition.entity.less + push: + - meta_scope: meta.alias.less + - include: less-mixin-params + - match: '(?=\[)' + push: + - meta_content_scope: meta.brackets.less + - include: less-map-lookups + - match: '(?=;|$)' + pop: true + - match: '(\.){{ident}}' + captures: + 0: entity.other.attribute-name.class.less + 1: punctuation.definition.entity.less + - match: '(#){{ident}}' + captures: + 0: entity.other.attribute-name.id.less + 1: punctuation.definition.entity.less + - match: '((\#){{ident}})(?=[.#])' + captures: + 1: entity.other.attribute-name.id.less + 2: punctuation.definition.entity.less + push: + - meta_scope: meta.alias.less + - include: less-mixin-params + - match: '(?=\[)' + push: + - meta_content_scope: meta.brackets.less + - include: less-map-lookups + - match: '(?=;|$)' + pop: true + - match: '(\.){{ident}}' + captures: + 0: entity.other.attribute-name.class.less + 1: punctuation.definition.entity.less + - match: '(#){{ident}}' + captures: + 0: entity.other.attribute-name.id.less + 1: punctuation.definition.entity.less + less-variables: - - match: '(\.)\S+(?=\[)' + - include: less-interpolation + - match: '(\.){{ident}}(?=\[)' captures: 0: entity.other.attribute-name.class.less 1: punctuation.definition.entity.less push: - meta_content_scope: meta.brackets.less - include: less-map-lookups - - match: '(#)\S+(?=\[)' + - match: '(#){{ident}}(?=\[)' captures: 0: entity.other.attribute-name.id.less 1: punctuation.definition.entity.less push: - meta_content_scope: meta.brackets.less - include: less-map-lookups - - match: '(@)\S+(?=\[)' + - match: '(@){{ident}}(?=\[)' captures: 0: variable.other.less 1: punctuation.definition.variable.less push: - meta_content_scope: meta.brackets.less - include: less-map-lookups - - include: less-interpolation - match: '(@{1,2})([a-zA-Z0-9_-][\w-]*)' captures: 0: variable.other.less @@ -958,6 +1006,7 @@ contexts: - include: numeric-values - include: literal-string - include: less-variables + - include: less-aliases - include: less-functions - include: less-operators @@ -1171,6 +1220,7 @@ contexts: - include: literal-string - include: filter-functions - include: less-variables + - include: less-aliases - include: less-functions - match: '\b(counter)(?=\()' @@ -1192,6 +1242,7 @@ contexts: pop: true - include: comma-delimiter - include: less-variables + - include: less-aliases - include: less-functions - match: '\b({{counter_styles}}|none)\b' scope: support.constant.property-value.counter-style.css @@ -1217,6 +1268,7 @@ contexts: - include: less-variables - include: less-functions - include: literal-string + - include: less-aliases - match: '\b({{counter_styles}}|none)\b' scope: support.constant.property-value.counter-style.css @@ -1237,6 +1289,7 @@ contexts: - include: less-variables - include: less-functions - include: literal-string + - include: less-aliases - include: image-type - match: '\b(format)(?=\()' @@ -1253,6 +1306,7 @@ contexts: - include: less-variables - include: less-functions - include: literal-string + - include: less-aliases - match: '\b(local)(?=\()' scope: support.function.font-face.css @@ -1268,6 +1322,7 @@ contexts: - include: less-variables - include: less-functions - include: unquoted-string + - include: less-aliases - match: '\b(matrix3d|scale3d|matrix|scale)(?=\()' scope: support.function.transform.css @@ -1285,6 +1340,7 @@ contexts: - include: less-functions - include: number-type - include: var-function + - include: less-aliases - match: '\b(translate(3d)?)(?=\()' scope: support.function.transform.css @@ -1304,6 +1360,7 @@ contexts: - include: length-type - include: number-type - include: var-function + - include: less-aliases - match: '\b(translate[XY])(?=\()' scope: support.function.transform.css @@ -1321,6 +1378,7 @@ contexts: - include: percentage-type - include: length-type - include: number-type + - include: less-aliases - match: '\b(rotate[XYZ]?|skew[XY])(?=\()' scope: support.function.transform.css @@ -1336,6 +1394,7 @@ contexts: - include: less-variables - include: less-functions - include: angle-type + - include: less-aliases - match: '\b(skew)(?=\()' scope: support.function.transform.css @@ -1352,6 +1411,7 @@ contexts: - include: less-variables - include: less-functions - include: angle-type + - include: less-aliases - match: '\b(translateZ|perspective)(?=\()' scope: support.function.transform.css @@ -1367,6 +1427,7 @@ contexts: - include: less-variables - include: less-functions - include: length-type + - include: less-aliases - match: '\b(rotate3d)(?=\()' scope: support.function.transform.css @@ -1384,6 +1445,7 @@ contexts: - include: less-functions - include: angle-type - include: number-type + - include: less-aliases - match: '\b(scale[XYZ])(?=\()' scope: support.function.transform.css @@ -1400,6 +1462,7 @@ contexts: - include: less-variables - include: less-functions - include: number-type + - include: less-aliases - match: '\b(cubic-bezier)(?=\()' scope: support.function.timing.css @@ -1416,6 +1479,7 @@ contexts: - include: less-variables - include: less-functions - include: number-type + - include: less-aliases - match: '\b(steps)(?=\()' scope: support.function.timing.css @@ -1432,6 +1496,7 @@ contexts: - include: less-variables - include: less-functions - include: integer-type + - include: less-aliases - match: (end|middle|start) scope: support.keyword.timing-direction.css @@ -1451,6 +1516,7 @@ contexts: - include: less-variables - include: less-functions - include: length-type + - include: less-aliases - match: '\b(inset)(?=\()' scope: support.function.shape.css @@ -1469,6 +1535,7 @@ contexts: - include: less-functions - include: length-type - include: percentage-type + - include: less-aliases - match: '\b(circle|ellipse)(?=\()' scope: support.function.shape.css @@ -1489,6 +1556,7 @@ contexts: - include: less-functions - include: length-type - include: percentage-type + - include: less-aliases - match: '\b(polygon)(?=\()' scope: support.function.shape.css @@ -1507,6 +1575,7 @@ contexts: - include: less-functions - include: length-type - include: percentage-type + - include: less-aliases - match: '\b(toggle)(?=\()' scope: support.function.toggle.css @@ -1528,6 +1597,7 @@ contexts: - include: numeric-values - include: color-values - include: literal-string + - include: less-aliases - match: '\b(repeat)(?=\()' scope: support.function.grid.css @@ -1548,6 +1618,7 @@ contexts: - include: minmax-function - include: integer-type - include: var-function + - include: less-aliases - match: \b(auto-fill|auto-fit)\b scope: support.keyword.repetitions.css - match: \b(max-content|min-content|auto)\b @@ -1568,6 +1639,7 @@ contexts: - include: comma-delimiter - include: less-variables - include: less-functions + - include: less-aliases - match: '(--)({{nmchar}}+)' captures: 0: meta.property-name.css support.type.custom-property.css @@ -1589,6 +1661,7 @@ contexts: - include: less-variables - include: less-functions - include: length-type + - include: less-aliases - match: '\b(brightness|contrast|grayscale|invert|opacity|saturate|sepia)(?=\()' scope: support.function.filter.css @@ -1605,6 +1678,7 @@ contexts: - include: less-functions - include: percentage-type - include: number-type + - include: less-aliases - match: '\b(drop-shadow)(?=\()' scope: support.function.filter.css @@ -1621,6 +1695,7 @@ contexts: - include: less-functions - include: length-type - include: color-values + - include: less-aliases - match: '\b(hue-rotate)(?=\()' scope: support.function.filter.css @@ -1636,6 +1711,7 @@ contexts: - include: less-variables - include: less-functions - include: angle-type + - include: less-aliases calc-function: - match: '\b(calc)(?=\()' @@ -1658,6 +1734,7 @@ contexts: - include: attr-function - include: less-variables - include: less-functions + - include: less-aliases - match: "[-/*+]" scope: keyword.operator.css - match: '\(' @@ -1680,6 +1757,7 @@ contexts: - include: less-functions - include: qualified-name - include: literal-string + - include: less-aliases - match: '({{ident}})' scope: entity.other.attribute-name.css push: @@ -1702,6 +1780,7 @@ contexts: - include: property-value-constants - include: numeric-values - include: color-values + - include: less-aliases url-function: - match: '\b(url)(?=\()' @@ -1719,6 +1798,7 @@ contexts: - include: less-functions - include: literal-string - include: unquoted-string + - include: less-aliases url-prefix-function: - match: '\b(url-prefix)(?=\()' @@ -1736,6 +1816,7 @@ contexts: - include: less-functions - include: literal-string - include: unquoted-string + - include: less-aliases domain-function: - match: '\b(domain)(?=\()' @@ -1753,6 +1834,7 @@ contexts: - include: less-functions - include: literal-string - include: unquoted-string + - include: less-aliases regexp-function: - match: '\b(regexp)(?=\()' @@ -1769,6 +1851,7 @@ contexts: - include: less-variables - include: less-functions - include: literal-string + - include: less-aliases image-function: - match: '\b(image)(?=\()' @@ -1789,6 +1872,7 @@ contexts: - include: color-values - include: comma-delimiter - include: unquoted-string + - include: less-aliases image-set-function: - match: '\b(image-set)(?=\()' @@ -1809,6 +1893,7 @@ contexts: - include: comma-delimiter - include: resolution-type - include: image-type + - include: less-aliases - match: '[0-9]+(x)' scope: constant.numeric.css captures: @@ -1834,6 +1919,7 @@ contexts: - include: color-values - include: percentage-type - include: length-type + - include: less-aliases - match: '\bto\b' scope: keyword.other.css - match: \b(top|right|bottom|left)\b @@ -1856,6 +1942,7 @@ contexts: - include: color-values - include: percentage-type - include: length-type + - include: less-aliases - match: '\b(at|circle|ellipse)\b' scope: keyword.other.css - match: |- @@ -1892,6 +1979,7 @@ contexts: - include: image-type - include: literal-string - include: unquoted-string + - include: less-aliases minmax-function: - match: '\b(minmax)(?=\()' @@ -1909,6 +1997,7 @@ contexts: - include: less-variables - include: less-functions - include: length-type + - include: less-aliases - match: \b(max-content|min-content)\b scope: support.constant.property-value.css @@ -1928,6 +2017,7 @@ contexts: - include: less-variables - include: percentage-type - include: number-type + - include: less-aliases - match: '\b(hsla?|hwb)(?=\()' scope: support.function.color.css @@ -1945,6 +2035,7 @@ contexts: - include: angle-type - include: percentage-type - include: number-type + - include: less-aliases - match: '\b(gray)(?=\()' scope: support.function.color.css @@ -1961,6 +2052,7 @@ contexts: - include: less-variables - include: percentage-type - include: number-type + - include: less-aliases - match: '\b(device-cmyk)(?=\()' scope: support.function.color.css @@ -1979,6 +2071,7 @@ contexts: - include: color-values - include: percentage-type - include: number-type + - include: less-aliases - match: '\b(color)(?=\()' scope: support.function.color.css @@ -1998,6 +2091,7 @@ contexts: - include: color-values - include: angle-type - include: number-type + - include: less-aliases color-adjuster-functions: - match: '\b(red|green|blue|alpha|a)(?=\()' @@ -2029,6 +2123,7 @@ contexts: - include: less-variables - include: color-adjuster-operators - include: angle-type + - include: less-aliases - match: '\b(saturation|lightness|whiteness|blackness|[slwb])(?=\()' scope: support.function.color.css @@ -2044,6 +2139,7 @@ contexts: - include: less-variables - include: color-adjuster-operators - include: percentage-type + - include: less-aliases - match: '\b(tint|shade)(?=\()' scope: support.function.color.css @@ -2058,6 +2154,7 @@ contexts: pop: true - include: less-variables - include: percentage-type + - include: less-aliases - match: '\b(blenda|blend)(?=\()' scope: support.function.color.css @@ -2076,6 +2173,7 @@ contexts: - include: color-values - include: percentage-type - include: var-function + - include: less-aliases color-adjuster-operators: - match: '[\-\+*](?=\s+)' @@ -2198,7 +2296,7 @@ contexts: unquoted-string: - match: '[^\s''"]' - scope: string.unquoted.css + scope: region.orangish string.unquoted.css literal-string: - match: "'" diff --git a/syntax_test_less.less b/syntax_test_less.less index 768e461..ad272ae 100755 --- a/syntax_test_less.less +++ b/syntax_test_less.less @@ -540,13 +540,48 @@ http://lesscss.org/features/#mixins-feature-mixin-aliasing-feature } .navbar { - @colors: #theme.dark.navbar.colors(dark); + @colors: .theme#dark.navbar.colors(dark); +// ^ punctuation.separator.key-value.css +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.property-value.css meta.alias.less +// ^ punctuation.definition.entity.less +// ^ punctuation.definition.entity.less +// ^ punctuation.definition.entity.less +// ^ punctuation.definition.entity.less +// ^ punctuation.definition.group.begin +// ^ punctuation.definition.group.end +// ^ punctuation.terminator.rule.css + @colors: .theme.dark.navbar#colors(dark); +// ^ punctuation.separator.key-value.css +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.property-value.css meta.alias.less +// ^ punctuation.definition.entity.less +// ^ punctuation.definition.entity.less +// ^ punctuation.definition.entity.less +// ^ punctuation.definition.entity.less +// ^ punctuation.definition.group.begin +// ^ punctuation.definition.group.end +// ^ punctuation.terminator.rule.css + @colors: #theme.dark.navbar#colors(dark); +// ^ punctuation.separator.key-value.css +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.property-value.css meta.alias.less +// ^ punctuation.definition.entity.less +// ^ punctuation.definition.entity.less +// ^ punctuation.definition.entity.less +// ^ punctuation.definition.entity.less +// ^ punctuation.definition.group.begin +// ^ punctuation.definition.group.end +// ^ punctuation.terminator.rule.css background: @colors[primary]; border: 1px solid @colors[secondary]; .button { @colors: #library.colors(); color: @colors[primary]; border-color: @colors[secondary]; + border-color: #library.colors[secondary]; +// ^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.property-value.css meta.alias.less +// ^ punctuation.terminator.rule.css - meta.alias.less +// ^^^^^^^^^^^ meta.brackets.less +// ^ punctuation.section.brackets.begin.less +// ^ punctuation.section.brackets.end.less } } From 7a687c685d4f515e794077d06902de037dabd2ea Mon Sep 17 00:00:00 2001 From: Koen Lageveen Date: Wed, 14 Nov 2018 20:58:47 +0100 Subject: [PATCH 7/9] add css guards --- LESS.sublime-syntax | 1 + syntax_test_less.less | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/LESS.sublime-syntax b/LESS.sublime-syntax index d0fe446..fd5f5d9 100644 --- a/LESS.sublime-syntax +++ b/LESS.sublime-syntax @@ -387,6 +387,7 @@ contexts: - include: comment-block - include: pseudo-elements - include: pseudo-classes + - include: less-mixin-params - match: '(?=\s)' pop: true diff --git a/syntax_test_less.less b/syntax_test_less.less index ad272ae..90e8a61 100755 --- a/syntax_test_less.less +++ b/syntax_test_less.less @@ -514,12 +514,38 @@ Attribute selectors display: inline-block; } } + +/* +CSS Guards +http://lesscss.org/features/#css-guards-feature +*/ + & when (@config[@options][library-on] = true) { +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.selector.css +// ^ keyword.operator.logic.mixin.less +// ^ meta.function.parameters.less punctuation.definition.group.begin .produce-ruleset { prop: val; } } +.my-optional-style() when (@my-option = true) { +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.selector.css +// ^ keyword.operator.logic.mixin.less +// ^ meta.function.parameters.less punctuation.definition.group.begin + button { + color: white; + } +} + +button when not (@my-option = true) { +// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ meta.selector.css +// ^ keyword.operator.logic.mixin.less +// ^ keyword.operator.logic.mixin.less +// ^ meta.function.parameters.less punctuation.definition.group.begin + color: white; +} + /* Aliasing Mixins From 069c3e8bb366c886d13f80655f96a44cf65ea4df Mon Sep 17 00:00:00 2001 From: Koen Lageveen Date: Thu, 15 Nov 2018 09:36:29 +0100 Subject: [PATCH 8/9] support , at begin of line --- LESS.sublime-syntax | 5 ++++- syntax_test_less.less | 3 +++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/LESS.sublime-syntax b/LESS.sublime-syntax index fd5f5d9..606a8e6 100644 --- a/LESS.sublime-syntax +++ b/LESS.sublime-syntax @@ -88,7 +88,10 @@ contexts: - include: less-map-values - include: at-rules - include: curly-braces - + - match: '\s*(,)\s*' + captures: + 1: punctuation.separator.css + pop: true selectors: diff --git a/syntax_test_less.less b/syntax_test_less.less index 90e8a61..9d88bbf 100755 --- a/syntax_test_less.less +++ b/syntax_test_less.less @@ -101,6 +101,9 @@ selector-ish::before[data-type="text"]:not(:first-child), filter, // ^^^ meta.selector.css entity.name.tag.css // ^ meta.selector.css punctuation.separator.css +filter +, .element +// <- punctuation.separator.css filter {} // ^ meta.selector.css // ^ entity.name.tag.css From d410b1fcf77b708734ac8a3836404e2396eb2f4d Mon Sep 17 00:00:00 2001 From: Koen Lageveen Date: Thu, 15 Nov 2018 09:37:35 +0100 Subject: [PATCH 9/9] fix completion and ; insertion needs a specific tweak compared to the CSS syntax, but implementation is (for now) a direct copy --- Comments.tmPreferences | 2 +- Default.sublime-keymap | 48 +++ Indentation Rules.tmPreferences | 2 +- LESS.sublime-syntax | 9 +- Snippets/abs.sublime-snippet | 2 +- Snippets/acos.sublime-snippet | 2 +- Snippets/alpha.sublime-snippet | 2 +- Snippets/argb.sublime-snippet | 2 +- Snippets/asin.sublime-snippet | 2 +- Snippets/atan.sublime-snippet | 2 +- Snippets/average.sublime-snippet | 2 +- Snippets/blue.sublime-snippet | 2 +- Snippets/ceil.sublime-snippet | 2 +- Snippets/color.sublime-snippet | 2 +- Snippets/contrast.sublime-snippet | 2 +- Snippets/convert.sublime-snippet | 2 +- Snippets/cos.sublime-snippet | 2 +- Snippets/darken.sublime-snippet | 2 +- Snippets/data-uri.sublime-snippet | 2 +- Snippets/desaturate.sublime-snippet | 2 +- Snippets/difference.sublime-snippet | 2 +- Snippets/e.sublime-snippet | 2 +- Snippets/escape.sublime-snippet | 2 +- Snippets/exclusion.sublime-snippet | 2 +- Snippets/extract.sublime-snippet | 2 +- Snippets/fade.sublime-snippet | 2 +- Snippets/fadein.sublime-snippet | 2 +- Snippets/fadeout.sublime-snippet | 2 +- Snippets/floor.sublime-snippet | 2 +- Snippets/format.sublime-snippet | 2 +- Snippets/green.sublime-snippet | 2 +- Snippets/greyscale.sublime-snippet | 2 +- Snippets/hardlight.sublime-snippet | 2 +- Snippets/hsl.sublime-snippet | 2 +- Snippets/hsla.sublime-snippet | 2 +- Snippets/hsv.sublime-snippet | 2 +- Snippets/hsva.sublime-snippet | 2 +- Snippets/hsvhue.sublime-snippet | 2 +- Snippets/hsvsaturation.sublime-snippet | 2 +- Snippets/hsvvalue.sublime-snippet | 2 +- Snippets/hue.sublime-snippet | 2 +- Snippets/length.sublime-snippet | 2 +- Snippets/lighten.sublime-snippet | 2 +- Snippets/lightness.sublime-snippet | 2 +- Snippets/luma.sublime-snippet | 2 +- Snippets/max.sublime-snippet | 2 +- Snippets/min.sublime-snippet | 2 +- Snippets/mix.sublime-snippet | 2 +- Snippets/mod.sublime-snippet | 2 +- Snippets/multiply.sublime-snippet | 2 +- Snippets/negation.sublime-snippet | 2 +- Snippets/overlay.sublime-snippet | 2 +- Snippets/percentage.sublime-snippet | 2 +- Snippets/pi.sublime-snippet | 2 +- Snippets/pow.sublime-snippet | 2 +- Snippets/red.sublime-snippet | 2 +- Snippets/replace.sublime-snippet | 2 +- Snippets/rgb.sublime-snippet | 2 +- Snippets/rgba.sublime-snippet | 2 +- Snippets/round.sublime-snippet | 2 +- Snippets/saturate.sublime-snippet | 2 +- Snippets/saturation.sublime-snippet | 2 +- Snippets/screen.sublime-snippet | 2 +- Snippets/sin.sublime-snippet | 2 +- Snippets/softlight.sublime-snippet | 2 +- Snippets/spin.sublime-snippet | 2 +- Snippets/sqrt.sublime-snippet | 2 +- Snippets/tan.sublime-snippet | 2 +- Snippets/unit.sublime-snippet | 2 +- less_completions.py | 517 +++++++++++++++++++++++++ syntax_test_less.less | 14 +- 71 files changed, 650 insertions(+), 72 deletions(-) create mode 100755 Default.sublime-keymap create mode 100755 less_completions.py diff --git a/Comments.tmPreferences b/Comments.tmPreferences index 62d9ea1..f87e45d 100644 --- a/Comments.tmPreferences +++ b/Comments.tmPreferences @@ -5,7 +5,7 @@ name Comments scope - source.css.less + source.less settings shellVariables diff --git a/Default.sublime-keymap b/Default.sublime-keymap new file mode 100755 index 0000000..68f60e4 --- /dev/null +++ b/Default.sublime-keymap @@ -0,0 +1,48 @@ +[ + { "keys": [":"], "command": "insert_snippet", "args": {"contents": ":$0;"}, "context": + [ + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "selector", "operator": "equal", "operand": "source.less - meta.selector.css", "match_all": true }, + { "key": "preceding_text", "operator": "not_regex_match", "operand": "^.*:", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^(?:\t| |\\}|$)", "match_all": true } + ] + }, + { "keys": [";"], "command": "move", "args": {"by": "characters", "forward": true}, "context": + [ + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "selector", "operator": "equal", "operand": "source.less - meta.selector.css", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^;", "match_all": true } + ] + }, + { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "res://Packages/Default/Delete Left Right.sublime-macro"}, "context": + [ + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "selector", "operator": "equal", "operand": "source.less - meta.selector.css", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": ":$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^;", "match_all": true } + ] + }, + + // Expand {|} to { | } when space is pressed + { "keys": [" "], "command": "insert_snippet", "args": {"contents": " $0 "}, "context": + [ + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "selector", "operator": "equal", "operand": "source.less - meta.selector.css", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "\\{$", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^\\}", "match_all": true }, + ] + }, + { "keys": ["backspace"], "command": "run_macro_file", "args": {"file": "res://Packages/Default/Delete Left Right.sublime-macro"}, "context": + [ + { "key": "setting.auto_match_enabled", "operator": "equal", "operand": true }, + { "key": "selection_empty", "operator": "equal", "operand": true, "match_all": true }, + { "key": "selector", "operator": "equal", "operand": "source.less - meta.selector.css", "match_all": true }, + { "key": "preceding_text", "operator": "regex_contains", "operand": "\\{ $", "match_all": true }, + { "key": "following_text", "operator": "regex_contains", "operand": "^ \\}", "match_all": true } + ] + }, +] diff --git a/Indentation Rules.tmPreferences b/Indentation Rules.tmPreferences index a2b7a41..d6b3874 100644 --- a/Indentation Rules.tmPreferences +++ b/Indentation Rules.tmPreferences @@ -4,7 +4,7 @@ name LESS Indent scope - source.css.less + source.less settings decreaseIndentPattern diff --git a/LESS.sublime-syntax b/LESS.sublime-syntax index 606a8e6..fec0f97 100644 --- a/LESS.sublime-syntax +++ b/LESS.sublime-syntax @@ -5,7 +5,7 @@ name: Less file_extensions: - less - css.less -scope: source.css.less +scope: source.less variables: unicode: '\\\h{1,6}[ \t\n\f]?' @@ -391,7 +391,9 @@ contexts: - include: pseudo-elements - include: pseudo-classes - include: less-mixin-params - - match: '(?=\s)' + - match: '\s*(?=$|//|/\*)' + pop: true + - match: '\s*(?=\b)' pop: true pseudo-elements: @@ -853,9 +855,10 @@ contexts: less-map-values: - - match: '{{ident}}' + - match: '{{ident}}(?=:\s*\b)' scope: variable.declaration.map.less push: + - meta_scope: meta.map-value.less - include: property-value-wrapper less-map-lookups: diff --git a/Snippets/abs.sublime-snippet b/Snippets/abs.sublime-snippet index bd89139..ee89d8b 100644 --- a/Snippets/abs.sublime-snippet +++ b/Snippets/abs.sublime-snippet @@ -4,5 +4,5 @@ abs(${1:number}) ]]> abs less math -source.css.less +source.less diff --git a/Snippets/acos.sublime-snippet b/Snippets/acos.sublime-snippet index d0302d4..ec025e0 100644 --- a/Snippets/acos.sublime-snippet +++ b/Snippets/acos.sublime-snippet @@ -4,5 +4,5 @@ acos(${1:number}) ]]> acos less math -source.css.less +source.less diff --git a/Snippets/alpha.sublime-snippet b/Snippets/alpha.sublime-snippet index dadc0f2..488a8d8 100644 --- a/Snippets/alpha.sublime-snippet +++ b/Snippets/alpha.sublime-snippet @@ -4,5 +4,5 @@ alpha(${1:color}) ]]> alpha less color-channel -source.css.less +source.less diff --git a/Snippets/argb.sublime-snippet b/Snippets/argb.sublime-snippet index 4068a61..d0e4753 100644 --- a/Snippets/argb.sublime-snippet +++ b/Snippets/argb.sublime-snippet @@ -4,5 +4,5 @@ argb(${1:color}) ]]> argb less color-definition -source.css.less +source.less diff --git a/Snippets/asin.sublime-snippet b/Snippets/asin.sublime-snippet index 77f68e4..01e639a 100644 --- a/Snippets/asin.sublime-snippet +++ b/Snippets/asin.sublime-snippet @@ -4,5 +4,5 @@ asin(${1:number}) ]]> asin less math -source.css.less +source.less diff --git a/Snippets/atan.sublime-snippet b/Snippets/atan.sublime-snippet index 8527275..ea1864a 100644 --- a/Snippets/atan.sublime-snippet +++ b/Snippets/atan.sublime-snippet @@ -4,5 +4,5 @@ atan(${1:number}) ]]> atan less math -source.css.less +source.less diff --git a/Snippets/average.sublime-snippet b/Snippets/average.sublime-snippet index dbff407..d2eb0c2 100644 --- a/Snippets/average.sublime-snippet +++ b/Snippets/average.sublime-snippet @@ -4,5 +4,5 @@ average(${1:color}, ${2:color}) ]]> average less color-blending -source.css.less +source.less diff --git a/Snippets/blue.sublime-snippet b/Snippets/blue.sublime-snippet index fd8e4bd..05ba839 100644 --- a/Snippets/blue.sublime-snippet +++ b/Snippets/blue.sublime-snippet @@ -4,5 +4,5 @@ blue(${1:color}) ]]> blue less color-channel -source.css.less +source.less diff --git a/Snippets/ceil.sublime-snippet b/Snippets/ceil.sublime-snippet index 88f5244..aab7a4f 100644 --- a/Snippets/ceil.sublime-snippet +++ b/Snippets/ceil.sublime-snippet @@ -4,5 +4,5 @@ ceil({1:number}) ]]> ceil less math -source.css.less +source.less diff --git a/Snippets/color.sublime-snippet b/Snippets/color.sublime-snippet index b3573ee..16c82c0 100644 --- a/Snippets/color.sublime-snippet +++ b/Snippets/color.sublime-snippet @@ -4,5 +4,5 @@ color({1:string}) ]]> color less misc -source.css.less +source.less diff --git a/Snippets/contrast.sublime-snippet b/Snippets/contrast.sublime-snippet index 0969639..cb9ee36 100644 --- a/Snippets/contrast.sublime-snippet +++ b/Snippets/contrast.sublime-snippet @@ -4,5 +4,5 @@ contrast(${1:color}, ${2:darkcolor/black}, ${3:lightcolor/white}, ${4:threshold} ]]> contrast less color-operations -source.css.less +source.less diff --git a/Snippets/convert.sublime-snippet b/Snippets/convert.sublime-snippet index 7315b70..047cff1 100644 --- a/Snippets/convert.sublime-snippet +++ b/Snippets/convert.sublime-snippet @@ -4,5 +4,5 @@ convert(${1:number}, ${2:units}) ]]> convert less math -source.css.less +source.less diff --git a/Snippets/cos.sublime-snippet b/Snippets/cos.sublime-snippet index 2650a38..6a6ab04 100644 --- a/Snippets/cos.sublime-snippet +++ b/Snippets/cos.sublime-snippet @@ -4,5 +4,5 @@ cos(${1:number}) ]]> cos less math -source.css.less +source.less diff --git a/Snippets/darken.sublime-snippet b/Snippets/darken.sublime-snippet index 433eccc..b9a1f37 100644 --- a/Snippets/darken.sublime-snippet +++ b/Snippets/darken.sublime-snippet @@ -4,5 +4,5 @@ darken(${1:color}, ${2:percentage}%) ]]> darken less color-operations -source.css.less +source.less diff --git a/Snippets/data-uri.sublime-snippet b/Snippets/data-uri.sublime-snippet index 12f837b..de40b05 100644 --- a/Snippets/data-uri.sublime-snippet +++ b/Snippets/data-uri.sublime-snippet @@ -4,5 +4,5 @@ data-uri(${1:url}) ]]> data-uri less misc -source.css.less +source.less diff --git a/Snippets/desaturate.sublime-snippet b/Snippets/desaturate.sublime-snippet index 14dfedc..599063e 100644 --- a/Snippets/desaturate.sublime-snippet +++ b/Snippets/desaturate.sublime-snippet @@ -4,5 +4,5 @@ desaturate(${1:color}, ${2:percentage}%) ]]> desaturate less color-operations -source.css.less +source.less diff --git a/Snippets/difference.sublime-snippet b/Snippets/difference.sublime-snippet index bc1a2ad..85d07bf 100644 --- a/Snippets/difference.sublime-snippet +++ b/Snippets/difference.sublime-snippet @@ -4,5 +4,5 @@ difference(${1:color}, ${2:color}) ]]> difference less color-blending -source.css.less +source.less diff --git a/Snippets/e.sublime-snippet b/Snippets/e.sublime-snippet index 83b7f65..1a18ea1 100644 --- a/Snippets/e.sublime-snippet +++ b/Snippets/e.sublime-snippet @@ -4,5 +4,5 @@ e({1:string}) ]]> e less string -source.css.less +source.less diff --git a/Snippets/escape.sublime-snippet b/Snippets/escape.sublime-snippet index 510c288..46ac9df 100644 --- a/Snippets/escape.sublime-snippet +++ b/Snippets/escape.sublime-snippet @@ -4,5 +4,5 @@ escape({1:string}) ]]> escape less string -source.css.less +source.less diff --git a/Snippets/exclusion.sublime-snippet b/Snippets/exclusion.sublime-snippet index 3fe0020..5861f0d 100644 --- a/Snippets/exclusion.sublime-snippet +++ b/Snippets/exclusion.sublime-snippet @@ -4,5 +4,5 @@ exclusion(${1:color}, ${1:color}) ]]> exclusion less color-blending -source.css.less +source.less diff --git a/Snippets/extract.sublime-snippet b/Snippets/extract.sublime-snippet index f9d1304..9b2f661 100644 --- a/Snippets/extract.sublime-snippet +++ b/Snippets/extract.sublime-snippet @@ -4,5 +4,5 @@ extract({1:list}, ${2:index}) ]]> extract less list -source.css.less +source.less diff --git a/Snippets/fade.sublime-snippet b/Snippets/fade.sublime-snippet index aa5c5a7..38fd159 100644 --- a/Snippets/fade.sublime-snippet +++ b/Snippets/fade.sublime-snippet @@ -4,5 +4,5 @@ fade(${1:color}, ${2:percentage}%) ]]> fade less color-operations -source.css.less +source.less diff --git a/Snippets/fadein.sublime-snippet b/Snippets/fadein.sublime-snippet index 83c7ee6..13877cd 100644 --- a/Snippets/fadein.sublime-snippet +++ b/Snippets/fadein.sublime-snippet @@ -4,5 +4,5 @@ fadein(${1:color}, ${2:percentage}%) ]]> fadein less color-operations -source.css.less +source.less diff --git a/Snippets/fadeout.sublime-snippet b/Snippets/fadeout.sublime-snippet index 7fdd718..5565d91 100644 --- a/Snippets/fadeout.sublime-snippet +++ b/Snippets/fadeout.sublime-snippet @@ -4,5 +4,5 @@ fadeout(${1:color}, ${2:percentage}%) ]]> fadeout less color-operations -source.css.less +source.less diff --git a/Snippets/floor.sublime-snippet b/Snippets/floor.sublime-snippet index a320652..50cc145 100644 --- a/Snippets/floor.sublime-snippet +++ b/Snippets/floor.sublime-snippet @@ -4,5 +4,5 @@ floor({1:number}) ]]> floor less math -source.css.less +source.less diff --git a/Snippets/format.sublime-snippet b/Snippets/format.sublime-snippet index 8175f0f..5cc3b87 100644 --- a/Snippets/format.sublime-snippet +++ b/Snippets/format.sublime-snippet @@ -4,5 +4,5 @@ ]]> format less string -source.css.less +source.less diff --git a/Snippets/green.sublime-snippet b/Snippets/green.sublime-snippet index 8392de5..901e5c4 100644 --- a/Snippets/green.sublime-snippet +++ b/Snippets/green.sublime-snippet @@ -4,5 +4,5 @@ green(${1:color}) ]]> green less color-channel -source.css.less +source.less diff --git a/Snippets/greyscale.sublime-snippet b/Snippets/greyscale.sublime-snippet index 73f5a3b..42db2a9 100644 --- a/Snippets/greyscale.sublime-snippet +++ b/Snippets/greyscale.sublime-snippet @@ -4,5 +4,5 @@ greyscale(${1:color}) ]]> greyscale less color-operations -source.css.less +source.less diff --git a/Snippets/hardlight.sublime-snippet b/Snippets/hardlight.sublime-snippet index 0fdff0b..f461a67 100644 --- a/Snippets/hardlight.sublime-snippet +++ b/Snippets/hardlight.sublime-snippet @@ -4,5 +4,5 @@ hardlight(${1:color}, ${2:color}) ]]> hardlight less color-blending -source.css.less +source.less diff --git a/Snippets/hsl.sublime-snippet b/Snippets/hsl.sublime-snippet index 70b512d..41b390a 100644 --- a/Snippets/hsl.sublime-snippet +++ b/Snippets/hsl.sublime-snippet @@ -4,5 +4,5 @@ hsl(${1:hue}, ${2:saturation}, ${3:lightness}) ]]> hsl less color-definition -source.css.less +source.less diff --git a/Snippets/hsla.sublime-snippet b/Snippets/hsla.sublime-snippet index 9cfe6cd..9761a48 100644 --- a/Snippets/hsla.sublime-snippet +++ b/Snippets/hsla.sublime-snippet @@ -4,5 +4,5 @@ hsla(${1:hue}, ${2:saturation}, ${3:lightness}, ${4:alpha}) ]]> hsla less color-definition -source.css.less +source.less diff --git a/Snippets/hsv.sublime-snippet b/Snippets/hsv.sublime-snippet index 56a944c..81089e5 100644 --- a/Snippets/hsv.sublime-snippet +++ b/Snippets/hsv.sublime-snippet @@ -4,5 +4,5 @@ hsv(${1:hue}, ${2:saturation}, ${3:value}) ]]> hsv less color-definition -source.css.less +source.less diff --git a/Snippets/hsva.sublime-snippet b/Snippets/hsva.sublime-snippet index b478d95..4cb8a11 100644 --- a/Snippets/hsva.sublime-snippet +++ b/Snippets/hsva.sublime-snippet @@ -4,5 +4,5 @@ hsva(${1:hue}, ${2:saturation}, ${3:value}, ${4:alpha}) ]]> hsva less color-definition -source.css.less +source.less diff --git a/Snippets/hsvhue.sublime-snippet b/Snippets/hsvhue.sublime-snippet index cc0d296..a088b88 100644 --- a/Snippets/hsvhue.sublime-snippet +++ b/Snippets/hsvhue.sublime-snippet @@ -4,5 +4,5 @@ hsvhue(${1:color}) ]]> hsvhue less color-channel -source.css.less +source.less diff --git a/Snippets/hsvsaturation.sublime-snippet b/Snippets/hsvsaturation.sublime-snippet index d4429a7..e14a987 100644 --- a/Snippets/hsvsaturation.sublime-snippet +++ b/Snippets/hsvsaturation.sublime-snippet @@ -4,5 +4,5 @@ hsvsaturation(${1:color}) ]]> hsvsaturation less color-channel -source.css.less +source.less diff --git a/Snippets/hsvvalue.sublime-snippet b/Snippets/hsvvalue.sublime-snippet index 5344c09..34589ca 100644 --- a/Snippets/hsvvalue.sublime-snippet +++ b/Snippets/hsvvalue.sublime-snippet @@ -4,5 +4,5 @@ hsvvalue(${1:color}) ]]> hsvvalue less color-channel -source.css.less +source.less diff --git a/Snippets/hue.sublime-snippet b/Snippets/hue.sublime-snippet index 57b0da2..192391e 100644 --- a/Snippets/hue.sublime-snippet +++ b/Snippets/hue.sublime-snippet @@ -4,5 +4,5 @@ hue(${1:color}) ]]> hue less color-channel -source.css.less +source.less diff --git a/Snippets/length.sublime-snippet b/Snippets/length.sublime-snippet index 60d55e9..b72065e 100644 --- a/Snippets/length.sublime-snippet +++ b/Snippets/length.sublime-snippet @@ -4,5 +4,5 @@ length({1:list}) ]]> length less list -source.css.less +source.less diff --git a/Snippets/lighten.sublime-snippet b/Snippets/lighten.sublime-snippet index f65c6c5..617150d 100644 --- a/Snippets/lighten.sublime-snippet +++ b/Snippets/lighten.sublime-snippet @@ -4,5 +4,5 @@ lighten(${1:color}, ${2:percentage}%) ]]> lighten less color-operations -source.css.less +source.less diff --git a/Snippets/lightness.sublime-snippet b/Snippets/lightness.sublime-snippet index 666e7d4..daf008c 100644 --- a/Snippets/lightness.sublime-snippet +++ b/Snippets/lightness.sublime-snippet @@ -4,5 +4,5 @@ lightness(${1:color}) ]]> lightness less color-channel -source.css.less +source.less diff --git a/Snippets/luma.sublime-snippet b/Snippets/luma.sublime-snippet index 5a5a7d2..d0e6b51 100644 --- a/Snippets/luma.sublime-snippet +++ b/Snippets/luma.sublime-snippet @@ -4,5 +4,5 @@ luma(${1:color}) ]]> luma less color-channel -source.css.less +source.less diff --git a/Snippets/max.sublime-snippet b/Snippets/max.sublime-snippet index 4670af7..e497478 100644 --- a/Snippets/max.sublime-snippet +++ b/Snippets/max.sublime-snippet @@ -4,5 +4,5 @@ max(${1:x}, ${1:y}) ]]> max less math -source.css.less +source.less diff --git a/Snippets/min.sublime-snippet b/Snippets/min.sublime-snippet index f0bfbbd..687573c 100644 --- a/Snippets/min.sublime-snippet +++ b/Snippets/min.sublime-snippet @@ -4,5 +4,5 @@ min(${1:x}, ${1:y}) ]]> min less math -source.css.less +source.less diff --git a/Snippets/mix.sublime-snippet b/Snippets/mix.sublime-snippet index f839363..0acf620 100644 --- a/Snippets/mix.sublime-snippet +++ b/Snippets/mix.sublime-snippet @@ -4,5 +4,5 @@ mix(${1:color}, ${2:color}, ${3:percentage}%) ]]> mix less color-operations -source.css.less +source.less diff --git a/Snippets/mod.sublime-snippet b/Snippets/mod.sublime-snippet index de92d7d..f20ab4b 100644 --- a/Snippets/mod.sublime-snippet +++ b/Snippets/mod.sublime-snippet @@ -4,5 +4,5 @@ mod(${1:number}, ${2:number}) ]]> mod less math -source.css.less +source.less diff --git a/Snippets/multiply.sublime-snippet b/Snippets/multiply.sublime-snippet index 2ade4e3..fc45aa5 100644 --- a/Snippets/multiply.sublime-snippet +++ b/Snippets/multiply.sublime-snippet @@ -4,5 +4,5 @@ multiply(${1:color}, ${1:color}) ]]> multiply less color-blending -source.css.less +source.less diff --git a/Snippets/negation.sublime-snippet b/Snippets/negation.sublime-snippet index 4444079..821322d 100644 --- a/Snippets/negation.sublime-snippet +++ b/Snippets/negation.sublime-snippet @@ -4,5 +4,5 @@ negation(${1:color}, ${2:color}) ]]> negation less color-blending -source.css.less +source.less diff --git a/Snippets/overlay.sublime-snippet b/Snippets/overlay.sublime-snippet index c914b33..c35d95b 100644 --- a/Snippets/overlay.sublime-snippet +++ b/Snippets/overlay.sublime-snippet @@ -4,5 +4,5 @@ overlay(${1:color}, ${2:color}) ]]> overlay less color-blending -source.css.less +source.less diff --git a/Snippets/percentage.sublime-snippet b/Snippets/percentage.sublime-snippet index 418afc4..83c5b48 100644 --- a/Snippets/percentage.sublime-snippet +++ b/Snippets/percentage.sublime-snippet @@ -4,5 +4,5 @@ percentage({1:number}) ]]> percentage less math -source.css.less +source.less diff --git a/Snippets/pi.sublime-snippet b/Snippets/pi.sublime-snippet index 6e58fe0..3bf3d25 100644 --- a/Snippets/pi.sublime-snippet +++ b/Snippets/pi.sublime-snippet @@ -4,5 +4,5 @@ pi() ]]> pi less math -source.css.less +source.less diff --git a/Snippets/pow.sublime-snippet b/Snippets/pow.sublime-snippet index 5cccab3..fd775a9 100644 --- a/Snippets/pow.sublime-snippet +++ b/Snippets/pow.sublime-snippet @@ -4,5 +4,5 @@ pow(${1:base}, ${2:exponent}) ]]> pow less math -source.css.less +source.less diff --git a/Snippets/red.sublime-snippet b/Snippets/red.sublime-snippet index 2aa801e..1ca95bc 100644 --- a/Snippets/red.sublime-snippet +++ b/Snippets/red.sublime-snippet @@ -4,5 +4,5 @@ red(${1:color}) ]]> red less color-channel -source.css.less +source.less diff --git a/Snippets/replace.sublime-snippet b/Snippets/replace.sublime-snippet index cb7466e..fac9845 100644 --- a/Snippets/replace.sublime-snippet +++ b/Snippets/replace.sublime-snippet @@ -4,5 +4,5 @@ replace({1:string}, ${2:pattern}, ${3:replacement}) ]]> replace less string -source.css.less +source.less diff --git a/Snippets/rgb.sublime-snippet b/Snippets/rgb.sublime-snippet index 50305be..1d5dde2 100644 --- a/Snippets/rgb.sublime-snippet +++ b/Snippets/rgb.sublime-snippet @@ -4,5 +4,5 @@ rgb(${1:r}, ${2:g}, ${3:b}) ]]> rgb less color-definition -source.css.less +source.less diff --git a/Snippets/rgba.sublime-snippet b/Snippets/rgba.sublime-snippet index a04023d..783aa94 100644 --- a/Snippets/rgba.sublime-snippet +++ b/Snippets/rgba.sublime-snippet @@ -4,5 +4,5 @@ rgba(${1:r}, ${2:g}, ${3:b}, ${4:a}) ]]> rgba less color-definition -source.css.less +source.less diff --git a/Snippets/round.sublime-snippet b/Snippets/round.sublime-snippet index b402a24..8f31681 100644 --- a/Snippets/round.sublime-snippet +++ b/Snippets/round.sublime-snippet @@ -4,5 +4,5 @@ round(${1:number}, ${2:places}) ]]> round less math -source.css.less +source.less diff --git a/Snippets/saturate.sublime-snippet b/Snippets/saturate.sublime-snippet index b427dad..7584ccb 100644 --- a/Snippets/saturate.sublime-snippet +++ b/Snippets/saturate.sublime-snippet @@ -4,5 +4,5 @@ saturate(${1:color}, ${2:percentage}%) ]]> saturate less color-operations -source.css.less +source.less diff --git a/Snippets/saturation.sublime-snippet b/Snippets/saturation.sublime-snippet index 3df2123..1d48f40 100644 --- a/Snippets/saturation.sublime-snippet +++ b/Snippets/saturation.sublime-snippet @@ -4,5 +4,5 @@ saturation(${1:color}) ]]> saturation less color-channel -source.css.less +source.less diff --git a/Snippets/screen.sublime-snippet b/Snippets/screen.sublime-snippet index 23c35a1..cd61845 100644 --- a/Snippets/screen.sublime-snippet +++ b/Snippets/screen.sublime-snippet @@ -4,5 +4,5 @@ screen(${1:color}, ${1:color}) ]]> screen less color-blending -source.css.less +source.less diff --git a/Snippets/sin.sublime-snippet b/Snippets/sin.sublime-snippet index ca721b1..799f71f 100644 --- a/Snippets/sin.sublime-snippet +++ b/Snippets/sin.sublime-snippet @@ -4,5 +4,5 @@ sin(${1:number}) ]]> sin less math -source.css.less +source.less diff --git a/Snippets/softlight.sublime-snippet b/Snippets/softlight.sublime-snippet index d8c4c65..3055e15 100644 --- a/Snippets/softlight.sublime-snippet +++ b/Snippets/softlight.sublime-snippet @@ -4,5 +4,5 @@ softlight(${1:color}, ${1:color}) ]]> softlight less color-blending -source.css.less +source.less diff --git a/Snippets/spin.sublime-snippet b/Snippets/spin.sublime-snippet index 0f63f2a..e3c971a 100644 --- a/Snippets/spin.sublime-snippet +++ b/Snippets/spin.sublime-snippet @@ -4,5 +4,5 @@ spin(${1:color}, ${2:angle}) ]]> spin less color-operations -source.css.less +source.less diff --git a/Snippets/sqrt.sublime-snippet b/Snippets/sqrt.sublime-snippet index a8e18d2..0e84803 100644 --- a/Snippets/sqrt.sublime-snippet +++ b/Snippets/sqrt.sublime-snippet @@ -4,5 +4,5 @@ sqrt(${1:number}) ]]> sqrt less math -source.css.less +source.less diff --git a/Snippets/tan.sublime-snippet b/Snippets/tan.sublime-snippet index 4012977..297cdf6 100644 --- a/Snippets/tan.sublime-snippet +++ b/Snippets/tan.sublime-snippet @@ -4,5 +4,5 @@ tan(${1:number}) ]]> tan less math -source.css.less +source.less diff --git a/Snippets/unit.sublime-snippet b/Snippets/unit.sublime-snippet index 431d0b2..4df695e 100644 --- a/Snippets/unit.sublime-snippet +++ b/Snippets/unit.sublime-snippet @@ -4,5 +4,5 @@ unit(${1:number}, ${2:units}) ]]> unit less math -source.css.less +source.less diff --git a/less_completions.py b/less_completions.py new file mode 100755 index 0000000..23d2cfd --- /dev/null +++ b/less_completions.py @@ -0,0 +1,517 @@ +import sublime, sublime_plugin +import re + + +# Prepare some common property values for when there is more than one way to +# specify a certain value type. The color value for example can be specified +# by `rgb()` or `hsl()` and so on. Example where `|` denotes the caret: +# +# color: rg| --> color: rgb(|); +# +# This is also helpful when multiple properties share the same value types. +COMMON_VALUES = { + 'animation_direction': [ + 'alternate', 'alternate-reverse', 'normal', 'reverse' + ], + 'absolute_size': [ + 'xx-small', 'x-small', 'small', 'medium', 'large', 'x-large', 'xx-large' + ], + 'absolute_weight': [ + '100', '200', '300', '400', '500', '600', '700', '800', '900' + ], + 'basic_shape': ['inset($1)', 'circle($1)', 'ellipse($1)', 'polygon($1)'], + 'blend_mode': [ + 'normal', 'multiply', 'screen', 'overlay', 'darken', 'lighten', + 'color-dodge', 'color-burn', 'hard-light', 'soft-light', 'difference', + 'exclusion', 'hue', 'saturation', 'color', 'luminosity' + ], + 'border_style': [ + 'none', 'hidden', 'dotted', 'dashed', 'solid', 'double', + 'groove', 'ridge', 'inset', 'outset' + ], + 'border_width': ['thin', 'medium', 'thick'], + 'break_before_after': [ + 'always', 'left', 'right', 'recto', 'verso', 'page', 'column', 'region' + ], + 'break_inside': [ + 'auto', 'avoid', 'avoid-page', 'avoid-column', 'avoid-region' + ], + 'color': ['currentColor', 'rgb($1)', 'rgba($1)', 'hsl($1)', 'hsla($1)', 'transparent'], + 'font_variant_alternates': [ + 'normal', 'historical-forms', 'stylistic($1)', 'styleset($1)', + 'character-variant($1)', 'swash($1)', 'ornaments($1)', 'annotation($1)' + ], + 'generic_name': [ + 'serif', 'sans-serif', 'cursive', 'fantasy', 'monospace' + ], + 'list_style_type': [ + 'none', 'inline', 'disc', 'circle', 'square', 'decimal', + 'decimal-leading-zero', 'arabic-indic', 'binary', 'bengali', + 'cambodian', 'khmer', 'devanagari', 'gujarati', 'gurmukhi', + 'kannada', 'lower-hexadecimal', 'lao', 'malayalam', 'mongolian', + 'myanmar', 'octal', 'oriya', 'persian', 'urdu', 'telugu', + 'tibetan', 'thai', 'upper-hexadecimal', 'lower-roman', + 'upper-roman', 'lower-greek', 'lower-alpha', 'lower-latin', + 'upper-alpha', 'upper-latin', 'afar', 'ethiopic-halehame-aa-et', + 'ethiopic-halehame-aa-er', 'amharic', 'ethiopic-halehame-am-et', + 'amharic-abegede', 'ethiopic-abegede-am-et', 'cjk-earthly-branch', + 'cjk-heavenly-stem', 'ethiopic', 'ethiopic-halehame-gez', + 'ethiopic-abegede', 'ethiopic-abegede-gez', 'hangul-consonant', + 'hangul', 'lower-norwegian', 'oromo', 'ethiopic-halehame-om-et', + 'sidama', 'ethiopic-halehame-sid-et', 'somali', + 'ethiopic-halehame-so-et', 'tigre', 'ethiopic-halehame-tig', + 'tigrinya-er', 'ethiopic-halehame-ti-er', 'tigrinya-er-abegede', + 'ethiopic-abegede-ti-er', 'tigrinya-et', 'ethiopic-halehame-ti-et', + 'tigrinya-et-abegede', 'ethiopic-abegede-ti-et', 'upper-greek', + 'upper-norwegian', 'asterisks', 'footnotes', 'hebrew', 'armenian', + 'lower-armenian', 'upper-armenian', 'georgian', 'cjk-ideographic', + 'hiragana', 'katakana', 'hiragana-iroha', 'katakana-iroha' + ], + 'position': ['top', 'right', 'bottom', 'left', 'center'], + 'relative_size': ['larger', 'smaller'], + 'relative_weight': ['bolder', 'lighter'], + 'repeat_style': [ + 'repeat', 'repeat-x', 'repeat-y', 'space', 'round', 'no-repeat' + ], + 'string': ['\"$1\"'], + 'timing_function': [ + 'ease', 'ease-in', 'ease-out', 'ease-in-out', 'linear', + 'cubic-bezier($1)', 'step-start', 'step-end', 'steps($1)' + ], + 'uri': ['url($1)'], +} + +PROPERTY_DICT = { + 'align-content': [ + 'center', 'flex-end', 'flex-start', 'space-around', 'space-between', + 'stretch' + ], + 'align-items': ['baseline', 'center', 'flex-end', 'flex-start', 'stretch'], + 'align-self': ['auto', 'baseline', 'center', 'flex-end', 'flex-start', 'stretch'], + 'alignment-baseline': [ + 'baseline', 'middle', 'auto', 'before-edge', 'after-edge', 'central', + 'text-before-edge', 'text-after-edge', 'ideographic', 'alphabetic', + 'hanging', 'mathematical' + ], + 'animation': [ + 'none', '', 'infinite', '', + 'forwards', 'backwards', 'both', 'running', 'paused' + ], + 'animation-name': ['none', ''], + 'animation-duration': ['