mirror of
https://github.com/pulsar-edit/pulsar.git
synced 2024-08-18 07:30:21 +03:00
Merge pull request #677 from savetheclocktower/tree-sitter-more-fixes
Tree-sitter running fixes (August edition)
This commit is contained in:
commit
69038a1c4c
@ -12,7 +12,7 @@ const MAX_ROWS_TO_SCAN_BACKWARD_TRAVERSAL = Object.freeze(Point(-MAX_ROWS_TO_SCA
|
||||
|
||||
module.exports =
|
||||
class BracketMatcherView {
|
||||
constructor (editor, editorElement, matchManager) {
|
||||
constructor(editor, editorElement, matchManager) {
|
||||
this.destroy = this.destroy.bind(this)
|
||||
this.updateMatch = this.updateMatch.bind(this)
|
||||
this.editor = editor
|
||||
@ -65,11 +65,11 @@ class BracketMatcherView {
|
||||
this.updateMatch()
|
||||
}
|
||||
|
||||
destroy () {
|
||||
destroy() {
|
||||
this.subscriptions.dispose()
|
||||
}
|
||||
|
||||
updateMatch () {
|
||||
updateMatch() {
|
||||
if (this.pairHighlighted) {
|
||||
this.editor.destroyMarker(this.startMarker.id)
|
||||
this.editor.destroyMarker(this.endMarker.id)
|
||||
@ -113,13 +113,13 @@ class BracketMatcherView {
|
||||
this.tagHighlighted = highlightTag
|
||||
}
|
||||
|
||||
selectMatchingBrackets () {
|
||||
selectMatchingBrackets() {
|
||||
if (!this.bracket1Range && !this.bracket2Range) return
|
||||
this.editor.setSelectedBufferRanges([this.bracket1Range, this.bracket2Range])
|
||||
this.matchManager.changeBracketsMode = true
|
||||
}
|
||||
|
||||
removeMatchingBrackets () {
|
||||
removeMatchingBrackets() {
|
||||
if (this.editor.hasMultipleCursors()) {
|
||||
this.editor.backspace()
|
||||
return
|
||||
@ -159,7 +159,7 @@ class BracketMatcherView {
|
||||
})
|
||||
}
|
||||
|
||||
findMatchingEndBracket (startBracketPosition, startBracket, endBracket) {
|
||||
findMatchingEndBracket(startBracketPosition, startBracket, endBracket) {
|
||||
if (startBracket === endBracket) return
|
||||
|
||||
if (this.hasSyntaxTree()) {
|
||||
@ -171,7 +171,7 @@ class BracketMatcherView {
|
||||
}
|
||||
}
|
||||
|
||||
findMatchingStartBracket (endBracketPosition, startBracket, endBracket) {
|
||||
findMatchingStartBracket(endBracketPosition, startBracket, endBracket) {
|
||||
if (startBracket === endBracket) return
|
||||
|
||||
if (this.hasSyntaxTree()) {
|
||||
@ -183,7 +183,7 @@ class BracketMatcherView {
|
||||
}
|
||||
}
|
||||
|
||||
findMatchingEndBracketWithSyntaxTree (bracketPosition, startBracket, endBracket) {
|
||||
findMatchingEndBracketWithSyntaxTree(bracketPosition, startBracket, endBracket) {
|
||||
let result
|
||||
const bracketEndPosition = bracketPosition.traverse([0, startBracket.length])
|
||||
this.editor.buffer.getLanguageMode().getSyntaxNodeContainingRange(
|
||||
@ -202,7 +202,7 @@ class BracketMatcherView {
|
||||
return result
|
||||
}
|
||||
|
||||
findMatchingStartBracketWithSyntaxTree (bracketPosition, startBracket, endBracket) {
|
||||
findMatchingStartBracketWithSyntaxTree(bracketPosition, startBracket, endBracket) {
|
||||
let result
|
||||
const bracketEndPosition = bracketPosition.traverse([0, startBracket.length])
|
||||
this.editor.buffer.getLanguageMode().getSyntaxNodeContainingRange(
|
||||
@ -221,7 +221,7 @@ class BracketMatcherView {
|
||||
return result
|
||||
}
|
||||
|
||||
findMatchingTagNameRangesWithSyntaxTree () {
|
||||
findMatchingTagNameRangesWithSyntaxTree() {
|
||||
const position = this.editor.getCursorBufferPosition()
|
||||
const {startTag, endTag} = this.findContainingTagsWithSyntaxTree(position)
|
||||
if (startTag && (startTag.range.containsPoint(position) || endTag.range.containsPoint(position))) {
|
||||
@ -244,7 +244,7 @@ class BracketMatcherView {
|
||||
}
|
||||
}
|
||||
|
||||
findMatchingTagsWithSyntaxTree () {
|
||||
findMatchingTagsWithSyntaxTree() {
|
||||
const position = this.editor.getCursorBufferPosition()
|
||||
const {startTag, endTag} = this.findContainingTagsWithSyntaxTree(position)
|
||||
if (startTag) {
|
||||
@ -254,7 +254,7 @@ class BracketMatcherView {
|
||||
}
|
||||
}
|
||||
|
||||
findContainingTagsWithSyntaxTree (position) {
|
||||
findContainingTagsWithSyntaxTree(position) {
|
||||
let startTag, endTag
|
||||
if (position.column === this.editor.buffer.lineLengthForRow(position.row)) position.column--;
|
||||
this.editor.buffer.getLanguageMode().getSyntaxNodeAtPosition(position, node => {
|
||||
@ -275,14 +275,14 @@ class BracketMatcherView {
|
||||
startTag = firstChild
|
||||
endTag = lastChild
|
||||
}
|
||||
return true
|
||||
}
|
||||
return true
|
||||
}
|
||||
})
|
||||
return {startTag, endTag}
|
||||
}
|
||||
|
||||
findMatchingEndBracketWithRegexSearch (startBracketPosition, startBracket, endBracket) {
|
||||
findMatchingEndBracketWithRegexSearch(startBracketPosition, startBracket, endBracket) {
|
||||
const scanRange = new Range(
|
||||
startBracketPosition.traverse(ONE_CHAR_FORWARD_TRAVERSAL),
|
||||
startBracketPosition.traverse(MAX_ROWS_TO_SCAN_FORWARD_TRAVERSAL)
|
||||
@ -308,7 +308,7 @@ class BracketMatcherView {
|
||||
return endBracketPosition
|
||||
}
|
||||
|
||||
findMatchingStartBracketWithRegexSearch (endBracketPosition, startBracket, endBracket) {
|
||||
findMatchingStartBracketWithRegexSearch(endBracketPosition, startBracket, endBracket) {
|
||||
const scanRange = new Range(
|
||||
endBracketPosition.traverse(MAX_ROWS_TO_SCAN_BACKWARD_TRAVERSAL),
|
||||
endBracketPosition
|
||||
@ -334,7 +334,7 @@ class BracketMatcherView {
|
||||
return startBracketPosition
|
||||
}
|
||||
|
||||
findPrecedingStartBracket (cursorPosition) {
|
||||
findPrecedingStartBracket(cursorPosition) {
|
||||
if (this.hasSyntaxTree()) {
|
||||
return this.findPrecedingStartBracketWithSyntaxTree(cursorPosition)
|
||||
} else {
|
||||
@ -342,7 +342,7 @@ class BracketMatcherView {
|
||||
}
|
||||
}
|
||||
|
||||
findPrecedingStartBracketWithSyntaxTree (cursorPosition) {
|
||||
findPrecedingStartBracketWithSyntaxTree(cursorPosition) {
|
||||
let result
|
||||
this.editor.buffer.getLanguageMode().getSyntaxNodeAtPosition(cursorPosition, node => {
|
||||
for (const child of node.children) {
|
||||
@ -359,7 +359,7 @@ class BracketMatcherView {
|
||||
return result
|
||||
}
|
||||
|
||||
findPrecedingStartBracketWithRegexSearch (cursorPosition) {
|
||||
findPrecedingStartBracketWithRegexSearch(cursorPosition) {
|
||||
const scanRange = new Range(Point.ZERO, cursorPosition)
|
||||
const startBracket = _.escapeRegExp(_.keys(this.matchManager.pairedCharacters).join(''))
|
||||
const endBracket = _.escapeRegExp(_.keys(this.matchManager.pairedCharactersInverse).join(''))
|
||||
@ -384,7 +384,7 @@ class BracketMatcherView {
|
||||
return startPosition
|
||||
}
|
||||
|
||||
createMarker (bufferRange) {
|
||||
createMarker(bufferRange) {
|
||||
const marker = this.editor.markBufferRange(bufferRange)
|
||||
this.editor.decorateMarker(marker, {type: 'highlight', class: 'bracket-matcher', deprecatedRegionClass: 'bracket-matcher'})
|
||||
if (atom.config.get('bracket-matcher.highlightMatchingLineNumber', {scope: this.editor.getRootScopeDescriptor()}) && this.gutter) {
|
||||
@ -393,7 +393,7 @@ class BracketMatcherView {
|
||||
return marker
|
||||
}
|
||||
|
||||
findCurrentPair () {
|
||||
findCurrentPair() {
|
||||
const currentPosition = this.editor.getCursorBufferPosition()
|
||||
const previousPosition = currentPosition.traverse(ONE_CHAR_BACKWARD_TRAVERSAL)
|
||||
const nextPosition = currentPosition.traverse(ONE_CHAR_FORWARD_TRAVERSAL)
|
||||
@ -422,7 +422,7 @@ class BracketMatcherView {
|
||||
return {position, matchPosition, bracket: currentBracket}
|
||||
}
|
||||
|
||||
goToMatchingBracket () {
|
||||
goToMatchingBracket() {
|
||||
if (!this.pairHighlighted) return this.gotoPrecedingStartBracket()
|
||||
const position = this.editor.getCursorBufferPosition()
|
||||
|
||||
@ -468,7 +468,7 @@ class BracketMatcherView {
|
||||
}
|
||||
}
|
||||
|
||||
gotoPrecedingStartBracket () {
|
||||
gotoPrecedingStartBracket() {
|
||||
if (this.pairHighlighted) return
|
||||
|
||||
const matchPosition = this.findPrecedingStartBracket(this.editor.getCursorBufferPosition())
|
||||
@ -522,7 +522,7 @@ class BracketMatcherView {
|
||||
})
|
||||
}
|
||||
|
||||
selectInsideBrackets () {
|
||||
selectInsideBrackets() {
|
||||
let endPosition, endRange, startPosition, startRange
|
||||
if (this.pairHighlighted) {
|
||||
startRange = this.startMarker.getBufferRange()
|
||||
@ -550,7 +550,7 @@ class BracketMatcherView {
|
||||
|
||||
// Insert at the current cursor position a closing tag if there exists an
|
||||
// open tag that is not closed afterwards.
|
||||
closeTag () {
|
||||
closeTag() {
|
||||
const cursorPosition = this.editor.getCursorBufferPosition()
|
||||
const preFragment = this.editor.getTextInBufferRange([Point.ZERO, cursorPosition])
|
||||
const postFragment = this.editor.getTextInBufferRange([cursorPosition, Point.INFINITY])
|
||||
@ -561,15 +561,15 @@ class BracketMatcherView {
|
||||
}
|
||||
}
|
||||
|
||||
isCursorOnCommentOrString () {
|
||||
isCursorOnCommentOrString() {
|
||||
return this.isScopeCommentedOrString(this.editor.getLastCursor().getScopeDescriptor().getScopesArray())
|
||||
}
|
||||
|
||||
isRangeCommentedOrString (range) {
|
||||
isRangeCommentedOrString(range) {
|
||||
return this.isScopeCommentedOrString(this.editor.scopeDescriptorForBufferPosition(range.start).getScopesArray())
|
||||
}
|
||||
|
||||
isScopeCommentedOrString (scopesArray) {
|
||||
isScopeCommentedOrString(scopesArray) {
|
||||
for (let scope of scopesArray.reverse()) {
|
||||
scope = scope.split('.')
|
||||
if (scope.includes('embedded') && scope.includes('source')) return false
|
||||
@ -579,7 +579,7 @@ class BracketMatcherView {
|
||||
return false
|
||||
}
|
||||
|
||||
hasSyntaxTree () {
|
||||
hasSyntaxTree() {
|
||||
return this.editor.buffer.getLanguageMode().getSyntaxNodeAtPosition
|
||||
}
|
||||
}
|
||||
|
@ -46,6 +46,16 @@
|
||||
(primitive_type) @storage.type.builtin.c
|
||||
(type_identifier) @storage.type.other.c
|
||||
|
||||
; These types are all reserved words; if we see an identifier with this name,
|
||||
; it must be a type.
|
||||
((identifier) @storage.type.builtin.c
|
||||
(#match? @storage.type.builtin.c "^(char|int|float|double|long)$"))
|
||||
|
||||
; Assume any identifier that ends in `_t` is a type. This convention is not
|
||||
; always followed, but it's a very strong indicator when it's present.
|
||||
((identifier) @storage.type.other.c
|
||||
(#match? @storage.type.other.c "_t$"))
|
||||
|
||||
[
|
||||
"enum"
|
||||
"long"
|
||||
@ -70,6 +80,10 @@
|
||||
((primitive_type) @support.type.stdint.c
|
||||
(#match? @support.type.stdint.c "^(int8_t|int16_t|int32_t|int64_t|uint8_t|uint16_t|uint32_t|uint64_t|int_least8_t|int_least16_t|int_least32_t|int_least64_t|uint_least8_t|uint_least16_t|uint_least32_t|uint_least64_t|int_fast8_t|int_fast16_t|int_fast32_t|int_fast64_t|uint_fast8_t|uint_fast16_t|uint_fast32_t|uint_fast64_t|intptr_t|uintptr_t|intmax_t|intmax_t|uintmax_t|uintmax_t)$"))
|
||||
|
||||
(enum_specifier
|
||||
name: (type_identifier) @variable.other.declaration.type.c)
|
||||
(type_definition
|
||||
declarator: (_) @variable.other.declaration.type.c)
|
||||
|
||||
; CAVEAT: tree-sitter-c doesn't identify placeholders like `%c` in strings.
|
||||
; Candidate for an injection grammar.
|
||||
@ -111,19 +125,19 @@
|
||||
declarator: (identifier) @variable.declaration.c)
|
||||
|
||||
(field_declaration
|
||||
(field_identifier) @variable.declaration.c)
|
||||
(field_identifier) @entity.other.attribute-name.c)
|
||||
|
||||
(field_declaration
|
||||
(pointer_declarator
|
||||
(field_identifier) @variable.declaration.c))
|
||||
(field_identifier) @entity.other.attribute-name.c))
|
||||
|
||||
(field_declaration
|
||||
(array_declarator
|
||||
(field_identifier) @variable.declaration.c))
|
||||
(field_identifier) @entity.other.attribute-name.c))
|
||||
|
||||
(init_declarator
|
||||
(pointer_declarator
|
||||
(identifier) @variable.declaration.c))
|
||||
(identifier) @entity.other.attribute-name.c))
|
||||
|
||||
(assignment_expression
|
||||
left: (identifier) @variable.other.assignment.c)
|
||||
@ -158,7 +172,7 @@
|
||||
; The "size" in `finfo->size`.
|
||||
(field_expression
|
||||
"->"
|
||||
field: (field_identifier) @variable.other.member.c)
|
||||
field: (field_identifier) @support.other.property.c)
|
||||
|
||||
|
||||
; FUNCTIONS
|
||||
|
@ -1 +0,0 @@
|
||||
;
|
@ -1,2 +1,3 @@
|
||||
|
||||
((function_declarator (identifier) @name))
|
||||
(function_declarator
|
||||
(identifier) @name) @definition.function
|
||||
|
@ -58,6 +58,17 @@
|
||||
(type_identifier) @storage.type.other.cpp
|
||||
; (struct_specifier) @storage.type.cpp
|
||||
|
||||
; These types are all reserved words; if we see an identifier with this name,
|
||||
; it must be a type.
|
||||
((identifier) @storage.type.builtin.cpp
|
||||
(#match? @storage.type.builtin.cpp "^(char|int|float|double|long)$"))
|
||||
|
||||
; Assume any identifier that ends in `_t` is a type. This convention is not
|
||||
; always followed, but it's a very strong indicator when it's present.
|
||||
((identifier) @storage.type.other.cpp
|
||||
(#match? @storage.type.other.cpp "_t$"))
|
||||
|
||||
|
||||
[
|
||||
"enum"
|
||||
"long"
|
||||
|
@ -1 +0,0 @@
|
||||
;
|
@ -1,2 +1,16 @@
|
||||
|
||||
((function_declarator (identifier) @name))
|
||||
(function_declarator
|
||||
(identifier) @name) @definition.function
|
||||
|
||||
(function_declarator
|
||||
declarator: (qualified_identifier) @name) @definition.function
|
||||
|
||||
(class_specifier
|
||||
name: (type_identifier) @name) @definition.class
|
||||
|
||||
(class_specifier
|
||||
body: (field_declaration_list
|
||||
(function_definition
|
||||
declarator: (function_declarator
|
||||
declarator: (field_identifier) @name)) @definition.method)
|
||||
(#set! symbol.contextNode "parent.parent.parent.parent.firstNamedChild"))
|
||||
|
@ -156,7 +156,7 @@
|
||||
; ------------------------
|
||||
|
||||
((plain_value) @support.constant.property-value.css
|
||||
(#match? @support.constant.property-value.css "^(above|absolute|active|add|additive|after-edge|alias|all|all-petite-caps|all-scroll|all-small-caps|alpha|alphabetic|alternate|alternate-reverse|always|antialiased|auto|auto-pos|available|avoid|avoid-column|avoid-page|avoid-region|backwards|balance|baseline|before-edge|below|bevel|bidi-override|blink|block|block-axis|block-start|block-end|bold|bolder|border|border-box|both|bottom|bottom-outside|break-all|break-word|bullets|butt|capitalize|caption|cell|center|central|char|circle|clip|clone|close-quote|closest-corner|closest-side|col-resize|collapse|color|color-burn|color-dodge|column|column-reverse|common-ligatures|compact|condensed|contain|content|content-box|contents|context-menu|contextual|copy|cover|crisp-edges|crispEdges|crosshair|cyclic|dark|darken|dashed|decimal|default|dense|diagonal-fractions|difference|digits|disabled|disc|discretionary-ligatures|distribute|distribute-all-lines|distribute-letter|distribute-space|dot|dotted|double|double-circle|downleft|downright|e-resize|each-line|ease|ease-in|ease-in-out|ease-out|economy|ellipse|ellipsis|embed|end|evenodd|ew-resize|exact|exclude|exclusion|expanded|extends|extra-condensed|extra-expanded|fallback|farthest-corner|farthest-side|fill|fill-available|fill-box|filled|fit-content|fixed|flat|flex|flex-end|flex-start|flip|flow-root|forwards|freeze|from-image|full-width|geometricPrecision|georgian|grab|grabbing|grayscale|grid|groove|hand|hanging|hard-light|help|hidden|hide|historical-forms|historical-ligatures|horizontal|horizontal-tb|hue|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|infinite|inherit|initial|inline|inline-axis|inline-block|inline-end|inline-flex|inline-grid|inline-list-item|inline-start|inline-table|inset|inside|inter-character|inter-ideograph|inter-word|intersect|invert|isolate|isolate-override|italic|jis04|jis78|jis83|jis90|justify|justify-all|kannada|keep-all|landscape|large|larger|left|light|lighten|lighter|line|line-edge|line-through|linear|linearRGB|lining-nums|list-item|local|loose|lowercase|lr|lr-tb|ltr|luminance|luminosity|main-size|mandatory|manipulation|manual|margin-box|match-parent|match-source|mathematical|max-content|medium|menu|message-box|middle|min-content|miter|mixed|move|multiply|n-resize|narrower|ne-resize|nearest-neighbor|nesw-resize|newspaper|no-change|no-clip|no-close-quote|no-common-ligatures|no-contextual|no-discretionary-ligatures|no-drop|no-historical-ligatures|no-open-quote|no-repeat|none|nonzero|normal|not-allowed|nowrap|ns-resize|numbers|numeric|nw-resize|nwse-resize|oblique|oldstyle-nums|open|open-quote|optimizeLegibility|optimizeQuality|optimizeSpeed|optional|ordinal|outset|outside|over|overlay|overline|padding|padding-box|page|painted|pan-down|pan-left|pan-right|pan-up|pan-x|pan-y|paused|petite-caps|pixelated|plaintext|pointer|portrait|pre|pre-line|pre-wrap|preserve-3d|progress|progressive|proportional-nums|proportional-width|proximity|radial|recto|region|relative|remove|repeat|repeat-[xy]|reset-size|reverse|revert|ridge|right|rl|rl-tb|round|row|row-resize|row-reverse|row-severse|rtl|ruby|ruby-base|ruby-base-container|ruby-text|ruby-text-container|run-in|running|s-resize|saturation|scale-down|screen|scroll|scroll-position|se-resize|semi-condensed|semi-expanded|separate|sesame|show|sideways|sideways-left|sideways-lr|sideways-right|sideways-rl|simplified|slashed-zero|slice|small|small-caps|small-caption|smaller|smooth|soft-light|solid|space|space-around|space-between|space-evenly|spell-out|square|sRGB|stacked-fractions|start|static|status-bar|swap|step-end|step-start|sticky|stretch|strict|stroke|stroke-box|style|sub|subgrid|subpixel-antialiased|subtract|super|sw-resize|symbolic|table|table-caption|table-cell|table-column|table-column-group|table-footer-group|table-header-group|table-row|table-row-group|tabular-nums|tb|tb-rl|text|text-after-edge|text-before-edge|text-bottom|text-top|thick|thin|titling-caps|top|top-outside|touch|traditional|transparent|triangle|ultra-condensed|ultra-expanded|under|underline|unicase|unset|upleft|uppercase|upright|use-glyph-orientation|use-script|verso|vertical|vertical-ideographic|vertical-lr|vertical-rl|vertical-text|view-box|visible|visibleFill|visiblePainted|visibleStroke|w-resize|wait|wavy|weight|whitespace|wider|words|wrap|wrap-reverse|x|x-large|x-small|xx-large|xx-small|y|zero|zoom-in|zoom-out)$"))
|
||||
(#match? @support.constant.property-value.css "^(above|absolute|active|add|additive|after-edge|alias|all|all-petite-caps|all-scroll|all-small-caps|alpha|alphabetic|alternate|alternate-reverse|always|antialiased|auto|auto-pos|available|avoid|avoid-column|avoid-page|avoid-region|backwards|balance|baseline|before-edge|below|bevel|bidi-override|blink|block|block-axis|block-start|block-end|bold|bolder|border|border-box|both|bottom|bottom-outside|break-all|break-word|bullets|butt|capitalize|caption|cell|center|central|char|circle|clip|clone|close-quote|closest-corner|closest-side|col-resize|collapse|color|color-burn|color-dodge|column|column-reverse|common-ligatures|compact|condensed|contain|content|content-box|contents|context-menu|contextual|copy|cover|crisp-edges|crispEdges|crosshair|cyclic|dark|darken|dashed|decimal|default|dense|diagonal-fractions|difference|digits|disabled|disc|discretionary-ligatures|distribute|distribute-all-lines|distribute-letter|distribute-space|dot|dotted|double|double-circle|downleft|downright|e-resize|each-line|ease|ease-in|ease-in-out|ease-out|economy|ellipse|ellipsis|embed|end|evenodd|ew-resize|exact|exclude|exclusion|expanded|extends|extra-condensed|extra-expanded|fallback|farthest-corner|farthest-side|fill|fill-available|fill-box|filled|fit-content|fixed|flat|flex|flex-end|flex-start|flip|flow-root|forwards|freeze|from-image|full-width|geometricPrecision|georgian|grab|grabbing|grayscale|grid|groove|hand|hanging|hard-light|help|hidden|hide|historical-forms|historical-ligatures|horizontal|horizontal-tb|hue|icon|ideograph-alpha|ideograph-numeric|ideograph-parenthesis|ideograph-space|ideographic|inactive|infinite|inherit|initial|inline|inline-axis|inline-block|inline-end|inline-flex|inline-grid|inline-list-item|inline-size|inline-start|inline-table|inset|inside|inter-character|inter-ideograph|inter-word|intersect|invert|isolate|isolate-override|italic|jis04|jis78|jis83|jis90|justify|justify-all|kannada|keep-all|landscape|large|larger|layout|left|light|lighten|lighter|line|line-edge|line-through|linear|linearRGB|lining-nums|list-item|local|loose|lowercase|lr|lr-tb|ltr|luminance|luminosity|main-size|mandatory|manipulation|manual|margin-box|match-parent|match-source|mathematical|max-content|medium|menu|message-box|middle|min-content|miter|mixed|move|multiply|n-resize|narrower|ne-resize|nearest-neighbor|nesw-resize|newspaper|no-change|no-clip|no-close-quote|no-common-ligatures|no-contextual|no-discretionary-ligatures|no-drop|no-historical-ligatures|no-open-quote|no-repeat|none|nonzero|normal|not-allowed|nowrap|ns-resize|numbers|numeric|nw-resize|nwse-resize|oblique|oldstyle-nums|open|open-quote|optimizeLegibility|optimizeQuality|optimizeSpeed|optional|ordinal|outset|outside|over|overlay|overline|padding|padding-box|page|paint|painted|pan-down|pan-left|pan-right|pan-up|pan-x|pan-y|paused|petite-caps|pixelated|plaintext|pointer|portrait|pre|pre-line|pre-wrap|preserve-3d|progress|progressive|proportional-nums|proportional-width|proximity|radial|recto|region|relative|remove|repeat|repeat-[xy]|reset-size|reverse|revert|ridge|right|rl|rl-tb|round|row|row-resize|row-reverse|row-severse|rtl|ruby|ruby-base|ruby-base-container|ruby-text|ruby-text-container|run-in|running|s-resize|saturation|scale-down|screen|scroll|scroll-position|se-resize|semi-condensed|semi-expanded|separate|sesame|show|sideways|sideways-left|sideways-lr|sideways-right|sideways-rl|simplified|size|slashed-zero|slice|small|small-caps|small-caption|smaller|smooth|soft-light|solid|space|space-around|space-between|space-evenly|spell-out|square|sRGB|stacked-fractions|start|static|status-bar|swap|step-end|step-start|sticky|stretch|strict|stroke|stroke-box|style|sub|subgrid|subpixel-antialiased|subtract|super|sw-resize|symbolic|table|table-caption|table-cell|table-column|table-column-group|table-footer-group|table-header-group|table-row|table-row-group|tabular-nums|tb|tb-rl|text|text-after-edge|text-before-edge|text-bottom|text-top|thick|thin|titling-caps|top|top-outside|touch|traditional|transparent|triangle|ultra-condensed|ultra-expanded|under|underline|unicase|unset|upleft|uppercase|upright|use-glyph-orientation|use-script|verso|vertical|vertical-ideographic|vertical-lr|vertical-rl|vertical-text|view-box|visible|visibleFill|visiblePainted|visibleStroke|w-resize|wait|wavy|weight|whitespace|wider|words|wrap|wrap-reverse|x|x-large|x-small|xx-large|xx-small|y|zero|zoom-in|zoom-out)$"))
|
||||
|
||||
; All property values that have special meaning in `font-family`.
|
||||
; TODO: Restrict these to be meaningful only when the property name is font-related?
|
||||
|
@ -3,15 +3,23 @@
|
||||
(switch_body)
|
||||
(class_body)
|
||||
(object)
|
||||
(formal_parameters)
|
||||
(template_string)
|
||||
(named_imports)
|
||||
] @fold
|
||||
|
||||
((arguments) @fold
|
||||
; When we've got
|
||||
;
|
||||
; function foo(
|
||||
; bar,
|
||||
; baz,
|
||||
; thud
|
||||
; )
|
||||
;
|
||||
; we want to be able to fold up the group of function parameters while
|
||||
; preserving the ability to collapse the function body.
|
||||
([(arguments) (formal_parameters)] @fold
|
||||
(#set! fold.adjustToEndOfPreviousRow true))
|
||||
|
||||
|
||||
; When we've got
|
||||
;
|
||||
; if (foo) {
|
||||
@ -32,7 +40,7 @@
|
||||
|
||||
((comment) @fold
|
||||
(#set! fold.endAt endPosition)
|
||||
(#set! fold.adjustEndColumn 0))
|
||||
(#set! fold.offsetEnd -2))
|
||||
|
||||
|
||||
; When you have…
|
||||
|
@ -543,10 +543,18 @@
|
||||
(#match? @punctuation.definition.comment.js "^\/\/")
|
||||
(#set! adjust.startAndEndAroundFirstMatchOf "^\/\/"))
|
||||
|
||||
((comment) @comment.block.documentation.js
|
||||
(#match? @comment.block.documentation.js "^/\\*\\*")
|
||||
(#set! capture.final true)
|
||||
(#set! highlight.invalidateOnChange true))
|
||||
|
||||
|
||||
; Block comments. `/* */`
|
||||
((comment) @comment.block.js
|
||||
(#match? @comment.block.js "^/\\*")
|
||||
(#match? @comment.block.js "\\*/$"))
|
||||
(#match? @comment.block.js "\\*/$")
|
||||
(#set! highlight.invalidateOnChange true))
|
||||
|
||||
|
||||
((comment) @punctuation.definition.comment.begin.js
|
||||
(#match? @punctuation.definition.comment.begin.js "^/\\*")
|
||||
@ -888,29 +896,43 @@
|
||||
; The interiors of functions (useful for snippets and commands).
|
||||
(method_definition
|
||||
body: (statement_block) @meta.block.function.js
|
||||
(#set! adjust.startAt firstChild.endPosition)
|
||||
(#set! adjust.endAt lastChild.startPosition)
|
||||
(#set! capture.final true))
|
||||
|
||||
(function_declaration
|
||||
body: (statement_block) @meta.block.function.js
|
||||
(#set! adjust.startAt firstChild.endPosition)
|
||||
(#set! adjust.endAt lastChild.startPosition)
|
||||
(#set! capture.final true))
|
||||
|
||||
(generator_function_declaration
|
||||
body: (statement_block) @meta.block.function.js
|
||||
(#set! adjust.startAt firstChild.endPosition)
|
||||
(#set! adjust.endAt lastChild.startPosition)
|
||||
(#set! capture.final true))
|
||||
|
||||
(function
|
||||
body: (statement_block) @meta.block.function.js
|
||||
(#set! adjust.startAt firstChild.endPosition)
|
||||
(#set! adjust.endAt lastChild.startPosition)
|
||||
(#set! capture.final true))
|
||||
|
||||
(generator_function
|
||||
body: (statement_block) @meta.block.function.js
|
||||
(#set! adjust.startAt firstChild.endPosition)
|
||||
(#set! adjust.endAt lastChild.startPosition)
|
||||
(#set! capture.final true))
|
||||
|
||||
; The interior of a class body (useful for snippets and commands).
|
||||
(class_body) @meta.block.class.js
|
||||
((class_body) @meta.block.class.js
|
||||
(#set! adjust.startAt firstChild.endPosition)
|
||||
(#set! adjust.endAt lastChild.startPosition))
|
||||
|
||||
; All other sorts of blocks.
|
||||
(statement_block) @meta.block.js
|
||||
((statement_block) @meta.block.js
|
||||
(#set! adjust.startAt firstChild.endPosition)
|
||||
(#set! adjust.endAt lastChild.startPosition))
|
||||
|
||||
; The inside of a parameter definition list.
|
||||
((formal_parameters) @meta.parameters.js
|
||||
@ -923,6 +945,20 @@
|
||||
(#set! adjust.endAt lastChild.startPosition))
|
||||
|
||||
|
||||
([
|
||||
(jsx_opening_element)
|
||||
(jsx_closing_element)
|
||||
] @meta.jsx.inside-tag.js
|
||||
(#set! adjust.startAt firstChild.endPosition))
|
||||
|
||||
((jsx_self_closing_element) @meta.jsx.inside-tag.js
|
||||
(#set! adjust.startAt firstChild.endPosition)
|
||||
(#set! adjust.endAt lastChild.startPosition))
|
||||
|
||||
((jsx_element) @meta.block.jsx.js
|
||||
(#set! adjust.startAt firstChild.endPosition)
|
||||
(#set! adjust.endAt lastChild.startPosition))
|
||||
|
||||
; MISC
|
||||
; ====
|
||||
|
||||
|
@ -94,23 +94,25 @@
|
||||
; =============================
|
||||
|
||||
; TODO: We might want to make this configurable behavior with the
|
||||
; `Config` scope test.
|
||||
; `config` scope test.
|
||||
|
||||
; Any of these at the end of a line indicate the next line should be indented…
|
||||
(["||" "&&" "?"] @indent
|
||||
(#is? test.lastTextOnRow true))
|
||||
|
||||
; …and the line after that should be dedented.
|
||||
; …and the line after that should be dedented…
|
||||
(binary_expression
|
||||
["||" "&&"]
|
||||
right: (_) @dedent.next
|
||||
(#is-not? test.startsOnSameRowAs parent.startPosition))
|
||||
|
||||
; …unless it's a ternary, in which case the dedent should wait until the
|
||||
; alternative clause.
|
||||
;
|
||||
; let foo = this.longTernaryCondition() ?
|
||||
; consequenceWhichIsItselfRatherLong :
|
||||
; alternativeThatIsNotBrief;
|
||||
;
|
||||
; …followed by a dedent.
|
||||
(ternary_expression
|
||||
alternative: (_) @dedent.next
|
||||
(#is-not? test.startsOnSameRowAs parent.startPosition))
|
||||
@ -153,5 +155,8 @@
|
||||
; JSX
|
||||
; ===
|
||||
|
||||
(jsx_opening_element ">") @indent
|
||||
(jsx_closing_element ">") @dedent
|
||||
|
||||
(jsx_opening_element ["<" ">"] @indent)
|
||||
(jsx_opening_element [">"] @dedent)
|
||||
|
||||
(jsx_closing_element ">" @dedent)
|
||||
|
@ -19,6 +19,7 @@
|
||||
((document) @punctuation.definition.end.comment.js.jsdoc
|
||||
(#set! adjust.startAndEndAroundFirstMatchOf "(?:\\*)?\\*/$"))
|
||||
|
||||
((inline_tag) @meta.inline-tag.js.jsdoc)
|
||||
|
||||
(tag_name) @storage.type.class.jsdoc
|
||||
|
||||
|
@ -2,8 +2,10 @@
|
||||
(comment)* @doc
|
||||
.
|
||||
(method_definition
|
||||
name: (property_identifier) @name) @definition.method
|
||||
(#not-eq? @name "constructor")
|
||||
name: (property_identifier) @name
|
||||
(#set! symbol.contextNode "parent.parent.parent.firstNamedChild")
|
||||
) @definition.method
|
||||
; (#not-eq? @name "constructor")
|
||||
(#strip! @doc "^[\\s\\*/]+|^[\\s\\*/]$")
|
||||
(#select-adjacent! @doc @definition.method)
|
||||
)
|
||||
@ -22,19 +24,6 @@
|
||||
name: (_) @name) @definition.class
|
||||
)
|
||||
|
||||
; (
|
||||
; (comment)* @doc
|
||||
; .
|
||||
; [
|
||||
; (class
|
||||
; name: (_) @name)
|
||||
; (class_declaration
|
||||
; name: (_) @name)
|
||||
; ] @definition.class
|
||||
; (#strip! @doc "^[\\s\\*/]+|^[\\s\\*/]$")
|
||||
; (#select-adjacent! @doc @definition.class)
|
||||
; )
|
||||
|
||||
(
|
||||
(comment)* @doc
|
||||
.
|
||||
@ -87,19 +76,19 @@
|
||||
key: (property_identifier) @name
|
||||
value: [(arrow_function) (function)]) @definition.function
|
||||
|
||||
; (
|
||||
; (call_expression
|
||||
; function: (identifier) @name) @reference.call
|
||||
; (#not-match? @name "^(require)$")
|
||||
; )
|
||||
;
|
||||
; (call_expression
|
||||
; function: (member_expression
|
||||
; property: (property_identifier) @name)
|
||||
; arguments: (_) @reference.call)
|
||||
;
|
||||
; (new_expression
|
||||
; constructor: (_) @name) @reference.class
|
||||
(
|
||||
(call_expression
|
||||
function: (identifier) @name) @reference.call
|
||||
(#not-match? @name "^(require)$")
|
||||
)
|
||||
|
||||
(call_expression
|
||||
function: (member_expression
|
||||
property: (property_identifier) @name)
|
||||
arguments: (_)) @reference.call
|
||||
|
||||
(new_expression
|
||||
constructor: (_) @name) @reference.class
|
||||
|
||||
(export_statement value: (assignment_expression left: (identifier) @name right: ([
|
||||
(number)
|
||||
|
@ -1,4 +1,4 @@
|
||||
exports.activate = function() {
|
||||
exports.activate = function () {
|
||||
if (!atom.grammars.addInjectionPoint) return;
|
||||
|
||||
atom.grammars.addInjectionPoint('source.js', {
|
||||
@ -70,41 +70,38 @@ exports.activate = function() {
|
||||
const TODO_PATTERN = /\b(TODO|FIXME|CHANGED|XXX|IDEA|HACK|NOTE|REVIEW|NB|BUG|QUESTION|COMBAK|TEMP|DEBUG|OPTIMIZE|WARNING)\b/;
|
||||
const HYPERLINK_PATTERN = /\bhttps?:/
|
||||
|
||||
for (const scopeName of ['source.js', 'source.ts', 'source.ts.tsx']) {
|
||||
atom.grammars.addInjectionPoint(scopeName, {
|
||||
type: 'comment',
|
||||
language(comment) {
|
||||
if (comment.text.startsWith('/**')) return 'jsdoc';
|
||||
},
|
||||
content(comment) {
|
||||
return comment;
|
||||
},
|
||||
languageScope: null,
|
||||
coverShallowerScopes: true
|
||||
});
|
||||
atom.grammars.addInjectionPoint('source.js', {
|
||||
type: 'comment',
|
||||
language(comment) {
|
||||
if (comment.text.startsWith('/**')) return 'jsdoc';
|
||||
},
|
||||
content(comment) {
|
||||
return comment;
|
||||
},
|
||||
languageScope: null,
|
||||
coverShallowerScopes: true
|
||||
});
|
||||
|
||||
// Experiment: better to have one layer with lots of nodes, or lots of
|
||||
// layers each managing one node?
|
||||
atom.grammars.addInjectionPoint(scopeName, {
|
||||
type: 'comment',
|
||||
// Experiment: better to have one layer with lots of nodes, or lots of
|
||||
// layers each managing one node?
|
||||
atom.grammars.addInjectionPoint('source.js', {
|
||||
type: 'comment',
|
||||
language: (node) => {
|
||||
return TODO_PATTERN.test(node.text) ? 'todo' : undefined;
|
||||
},
|
||||
content: (node) => node,
|
||||
languageScope: null
|
||||
});
|
||||
|
||||
for (let type of ['template_string', 'string_fragment', 'comment']) {
|
||||
atom.grammars.addInjectionPoint('source.js', {
|
||||
type,
|
||||
language: (node) => {
|
||||
return TODO_PATTERN.test(node.text) ? 'todo' : undefined;
|
||||
return HYPERLINK_PATTERN.test(node.text) ? 'hyperlink' : undefined;
|
||||
},
|
||||
content: (node) => node,
|
||||
languageScope: null
|
||||
});
|
||||
|
||||
for (let type of ['template_string', 'string_fragment', 'comment']) {
|
||||
atom.grammars.addInjectionPoint(scopeName, {
|
||||
type,
|
||||
language: (node) => {
|
||||
return HYPERLINK_PATTERN.test(node.text) ? 'hyperlink' : undefined;
|
||||
},
|
||||
content: (node) => node,
|
||||
languageScope: null
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -11,3 +11,13 @@
|
||||
'decreaseIndentPattern': '(?x)
|
||||
^ \\s* (\\s* /[*] .* [*]/ \\s*)* [}\\])]
|
||||
'
|
||||
|
||||
'.source.js .meta.block.jsx.js':
|
||||
'editor':
|
||||
'commentStart': '{/*'
|
||||
'commentEnd': '*/}'
|
||||
|
||||
'.source.js .meta.jsx.inside-tag.js':
|
||||
'editor':
|
||||
'commentStart': '{/*'
|
||||
'commentEnd': '*/}'
|
||||
|
@ -128,3 +128,18 @@
|
||||
'return':
|
||||
'prefix': 'ret'
|
||||
'body': 'return $1;$0'
|
||||
|
||||
'.source.js .meta.block.function.js':
|
||||
'Function':
|
||||
'prefix': 'fun'
|
||||
'body': 'function ${1:functionName}($2) {\n\t$0\n}'
|
||||
|
||||
'.source.js .meta.block.class.js':
|
||||
'Function':
|
||||
'prefix': 'fun'
|
||||
'body': '${1:functionName}($2) {\n\t$0\n}'
|
||||
|
||||
'.source.js .meta.object.js':
|
||||
'Function':
|
||||
'prefix': 'fun'
|
||||
'body': '${1:functionName}($2) {\n\t$0\n},'
|
||||
|
@ -4,6 +4,7 @@
|
||||
; Nested keys try to prepend the symbol name of their parent's key.
|
||||
(pair key: (string (string_content) @name
|
||||
(#is-not? test.descendantOfType "array")
|
||||
(#set! symbol.tag "property")
|
||||
(#set! symbol.prependSymbolForNode parent.parent.parent.previousNamedSibling.firstNamedChild)
|
||||
(#set! symbol.contextNode parent.parent.parent.previousNamedSibling.firstNamedChild)
|
||||
(#set! symbol.joiner ".")))
|
||||
|
@ -3,8 +3,6 @@
|
||||
; * No support for lookbehind as of March 2023 (waiting on
|
||||
; https://github.com/tree-sitter/tree-sitter-regex/pull/15)
|
||||
|
||||
(pattern) @string.regexp
|
||||
|
||||
(non_capturing_group) @meta.group.non-capturing.regexp
|
||||
|
||||
[
|
||||
|
@ -1,4 +1,4 @@
|
||||
exports.activate = function() {
|
||||
exports.activate = function () {
|
||||
if (!atom.grammars.addInjectionPoint) return;
|
||||
|
||||
atom.grammars.addInjectionPoint('source.ruby', {
|
||||
@ -19,6 +19,7 @@ exports.activate = function() {
|
||||
content(node) {
|
||||
return node;
|
||||
},
|
||||
languageScope: null,
|
||||
includeChildren: true,
|
||||
// coverShallowerScopes: false
|
||||
});
|
||||
|
25
packages/language-shellscript/lib/main.js
Normal file
25
packages/language-shellscript/lib/main.js
Normal file
@ -0,0 +1,25 @@
|
||||
exports.activate = () => {
|
||||
|
||||
const TODO_PATTERN = /\b(TODO|FIXME|CHANGED|XXX|IDEA|HACK|NOTE|REVIEW|NB|BUG|QUESTION|COMBAK|TEMP|DEBUG|OPTIMIZE|WARNING)\b/;
|
||||
const HYPERLINK_PATTERN = /\bhttps?:/
|
||||
|
||||
atom.grammars.addInjectionPoint('source.shell', {
|
||||
type: 'comment',
|
||||
language: (node) => {
|
||||
return TODO_PATTERN.test(node.text) ? 'todo' : undefined;
|
||||
},
|
||||
content: (node) => node,
|
||||
languageScope: null
|
||||
});
|
||||
|
||||
atom.grammars.addInjectionPoint('source.shell', {
|
||||
type: 'comment',
|
||||
language(node) {
|
||||
return HYPERLINK_PATTERN.test(node.text) ?
|
||||
'hyperlink' : undefined;
|
||||
},
|
||||
content: (node) => node,
|
||||
languageScope: null
|
||||
});
|
||||
|
||||
};
|
@ -1,13 +1,14 @@
|
||||
{
|
||||
"name": "language-shellscript",
|
||||
"version": "0.28.2",
|
||||
"main": "lib/main",
|
||||
"description": "ShellScript language support in Atom",
|
||||
"keywords": [
|
||||
"tree-sitter"
|
||||
],
|
||||
"engines": {
|
||||
"atom": "*",
|
||||
"node": "*"
|
||||
"node": ">=12"
|
||||
},
|
||||
"repository": "https://github.com/pulsar-edit/pulsar",
|
||||
"license": "MIT",
|
||||
|
@ -2,15 +2,23 @@
|
||||
(switch_body)
|
||||
(class_body)
|
||||
(object)
|
||||
(formal_parameters)
|
||||
(template_string)
|
||||
(named_imports)
|
||||
] @fold
|
||||
|
||||
((arguments) @fold
|
||||
; When we've got
|
||||
;
|
||||
; function foo(
|
||||
; bar,
|
||||
; baz,
|
||||
; thud
|
||||
; )
|
||||
;
|
||||
; we want to be able to fold up the group of function parameters while
|
||||
; preserving the ability to collapse the function body.
|
||||
([(arguments) (formal_parameters)] @fold
|
||||
(#set! fold.adjustToEndOfPreviousRow true))
|
||||
|
||||
|
||||
; When we've got
|
||||
;
|
||||
; if (foo) {
|
||||
@ -31,4 +39,4 @@
|
||||
|
||||
((comment) @fold
|
||||
(#set! fold.endAt endPosition)
|
||||
(#set! fold.adjustEndColumn 0))
|
||||
(#set! fold.offsetEnd -2))
|
||||
|
@ -9,6 +9,10 @@
|
||||
(import_specifier
|
||||
(identifier) @variable.other.assignment.import._LANG_)
|
||||
|
||||
; The "foo" in `import * as foo from './bar'`
|
||||
(namespace_import
|
||||
(identifier) @variable.other.assignment.import.namespace._LANG_)
|
||||
|
||||
; The "Foo" in `export { Foo }`
|
||||
(export_specifier
|
||||
name: (identifier) @variable.other.assignment.export._LANG_)
|
||||
@ -37,8 +41,19 @@
|
||||
(#match? @punctuation.definition.comment._LANG_ "^//")
|
||||
(#set! adjust.startAndEndAroundFirstMatchOf "^//"))
|
||||
|
||||
((comment) @comment.block.documentation._LANG_
|
||||
(#match? @comment.block.documentation._LANG_ "^/\\*\\*")
|
||||
(#set! capture.final true)
|
||||
(#set! highlight.invalidateOnChange true))
|
||||
|
||||
; Block comments. `/* */`
|
||||
((comment) @comment.block._LANG_
|
||||
(#match? @comment.block._LANG_ "^/\\*"))
|
||||
(#match? @comment.block._LANG_ "^/\\*")
|
||||
(#match? @comment.block._LANG_ "\\*/$")
|
||||
(#set! highlight.invalidateOnChange true))
|
||||
|
||||
; ((comment) @comment.block._LANG_
|
||||
; (#match? @comment.block._LANG_ "^/\\*"))
|
||||
|
||||
((comment) @punctuation.definition.comment.begin._LANG_
|
||||
(#match? @punctuation.definition.comment.begin._LANG_ "^/\\*")
|
||||
@ -65,7 +80,8 @@
|
||||
; =======
|
||||
|
||||
(class_declaration
|
||||
name: (type_identifier) @entity.name.type.class._LANG_)
|
||||
name: (type_identifier) @entity.name.type.class._LANG_
|
||||
(#set! capture.final true))
|
||||
|
||||
(extends_clause
|
||||
value: (_) @entity.other.inherited-class._LANG_)
|
||||
@ -90,12 +106,27 @@
|
||||
"set" @storage.setter._LANG_)
|
||||
|
||||
|
||||
; NAMESPACES
|
||||
; ==========
|
||||
|
||||
(internal_module
|
||||
name: (identifier) @entity.name.type.namespace._LANG_)
|
||||
|
||||
|
||||
; DECLARATIONS
|
||||
; ============
|
||||
|
||||
(function_signature
|
||||
name: (identifier) @entity.name.function.signature._LANG_)
|
||||
|
||||
|
||||
; INTERFACES
|
||||
; ==========
|
||||
|
||||
(interface_declaration
|
||||
name: (_) @entity.name.type.interface._LANG_)
|
||||
|
||||
|
||||
; TYPES
|
||||
; =====
|
||||
|
||||
@ -178,6 +209,8 @@
|
||||
(property_signature
|
||||
(property_identifier) @entity.other.attribute-name._LANG_)
|
||||
|
||||
|
||||
|
||||
; FUNCTIONS
|
||||
; =========
|
||||
|
||||
@ -259,6 +292,10 @@
|
||||
(required_parameter
|
||||
pattern: (identifier) @variable.parameter._LANG_)
|
||||
|
||||
(required_parameter
|
||||
pattern: (rest_pattern
|
||||
(identifier) @variable.parameter.rest._LANG_))
|
||||
|
||||
(required_parameter
|
||||
pattern: (object_pattern
|
||||
(shorthand_property_identifier_pattern) @variable.parameter.destructuring._LANG_)
|
||||
@ -269,6 +306,9 @@
|
||||
|
||||
(optional_parameter "?" @keyword.operator.type.optional._LANG_)
|
||||
|
||||
(type_predicate
|
||||
name: (identifier) @variable.other.type._LANG_
|
||||
"is" @keyword.operator.type.is._LANG_)
|
||||
|
||||
["var" "const" "let"] @storage.type._TYPE_._LANG_
|
||||
|
||||
@ -306,7 +346,16 @@
|
||||
(pair_pattern
|
||||
; TODO: This arguably isn't an object key.
|
||||
key: (_) @entity.other.attribute-name._LANG_
|
||||
value: (identifier) @variable.other.assignment.destructuring._LANG_))
|
||||
value: (identifier) @variable.other.assignment.destructuring._LANG_)
|
||||
(#set! capture.final true))
|
||||
|
||||
; A complex object alias destructuring:
|
||||
; The "bar" in `let { bar: { foo: troz } } = something`
|
||||
(object_pattern
|
||||
(pair_pattern
|
||||
; TODO: This arguably isn't an object key.
|
||||
key: (_) @entity.other.attribute-name._LANG_)
|
||||
(#set! capture.final true))
|
||||
|
||||
; A variable object alias destructuring with default value:
|
||||
; The "bar" and "foo" in `let { bar: foo = true } = something`
|
||||
|
@ -1,14 +1,124 @@
|
||||
; The closing brace of a switch statement's body should match the indentation of the line where the switch statement starts.
|
||||
; STATEMENT BLOCKS
|
||||
; ================
|
||||
|
||||
; More accurate indentation matching for all blocks delimited by braces.
|
||||
(statement_block "}" @match
|
||||
(#set! indent.matchIndentOf parent.firstChild.startPosition))
|
||||
|
||||
|
||||
; SWITCH STATEMENTS
|
||||
; =================
|
||||
|
||||
; The closing brace of a switch statement's body should match the indentation
|
||||
; of the line where the switch statement starts.
|
||||
(switch_statement
|
||||
body: (switch_body "}" @match
|
||||
(#is? test.last true))
|
||||
(#set! indent.matchIndentOf parent.parent.startPosition))
|
||||
(#set! indent.matchIndentOf parent.startPosition))
|
||||
|
||||
; 'case' and 'default' need to be indented one level more than their containing
|
||||
; `switch`.
|
||||
(["case" "default"] @match
|
||||
(#set! indent.matchIndentOf parent.parent.startPosition)
|
||||
(#set! indent.offsetIndent 1))
|
||||
; `switch`. TODO: Might need to make this configurable.
|
||||
(["case" "default"] @match
|
||||
(#set! indent.matchIndentOf parent.parent.startPosition)
|
||||
(#set! indent.offsetIndent 1))
|
||||
|
||||
|
||||
; ONE-LINE CONDITIONALS
|
||||
; =====================
|
||||
|
||||
; An `if` statement without an opening brace should indent the next line…
|
||||
(if_statement
|
||||
condition: (parenthesized_expression ")" @indent
|
||||
(#is? test.lastTextOnRow true)))
|
||||
; (as should a braceless `else`…)
|
||||
("else" @indent
|
||||
(#is? test.lastTextOnRow true))
|
||||
|
||||
; …and keep that indent level if the user types a comment before the
|
||||
; consequence…
|
||||
(if_statement
|
||||
consequence: (empty_statement) @match
|
||||
(#is-not? test.startsOnSameRowAs parent.startPosition)
|
||||
(#set! indent.matchIndentOf parent.startPosition)
|
||||
(#set! indent.offsetIndent 1))
|
||||
|
||||
; …and keep that indent level after the user starts typing…
|
||||
(if_statement
|
||||
condition: (_) @indent
|
||||
consequence: [
|
||||
(expression_statement)
|
||||
(return_statement)
|
||||
(continue_statement)
|
||||
(break_statement)
|
||||
(throw_statement)
|
||||
(debugger_statement)
|
||||
] @match
|
||||
; When an opening curly brace is unpaired, it might get interpreted as part
|
||||
; of an `expression_statement`, for some reason.
|
||||
(#not-match? @match "^\\s*{")
|
||||
(#set! indent.matchIndentOf parent.startPosition)
|
||||
(#set! indent.offsetIndent 1))
|
||||
|
||||
; …but dedent after exactly one statement.
|
||||
(if_statement
|
||||
condition: (_) @indent
|
||||
consequence: [
|
||||
(expression_statement)
|
||||
(return_statement)
|
||||
(continue_statement)
|
||||
(break_statement)
|
||||
(throw_statement)
|
||||
(debugger_statement)
|
||||
] @dedent.next
|
||||
; When an opening curly brace is unpaired, it might get interpreted as part
|
||||
; of an `expression_statement`, for some reason.
|
||||
(#not-match? @dedent.next "^\\s*{"))
|
||||
|
||||
(else_clause
|
||||
[
|
||||
(expression_statement)
|
||||
(return_statement)
|
||||
(continue_statement)
|
||||
(break_statement)
|
||||
(throw_statement)
|
||||
(debugger_statement)
|
||||
] @dedent.next
|
||||
(#is-not? test.startsOnSameRowAs parent.startPosition))
|
||||
|
||||
; HANGING INDENT ON SPLIT LINES
|
||||
; =============================
|
||||
|
||||
; TODO: We might want to make this configurable behavior with the
|
||||
; `config` scope test.
|
||||
|
||||
; Any of these at the end of a line indicate the next line should be indented…
|
||||
(["||" "&&" "?"] @indent
|
||||
(#is? test.lastTextOnRow true))
|
||||
|
||||
; …and the line after that should be dedented.
|
||||
(binary_expression
|
||||
["||" "&&"]
|
||||
right: (_) @dedent.next
|
||||
(#is-not? test.startsOnSameRowAs parent.startPosition))
|
||||
|
||||
; …unless it's a ternary, in which case the dedent should wait until the
|
||||
; alternative clause.
|
||||
;
|
||||
; let foo = this.longTernaryCondition() ?
|
||||
; consequenceWhichIsItselfRatherLong :
|
||||
; alternativeThatIsNotBrief;
|
||||
;
|
||||
(ternary_expression
|
||||
alternative: (_) @dedent.next
|
||||
(#is-not? test.startsOnSameRowAs parent.startPosition))
|
||||
|
||||
|
||||
; GENERAL
|
||||
; =======
|
||||
|
||||
; Weed out `}`s that should not signal dedents.
|
||||
(template_substitution "}" @_IGNORE_ (#set! capture.final true))
|
||||
|
||||
|
||||
[
|
||||
"{"
|
||||
@ -27,5 +137,4 @@
|
||||
(type_arguments "<" @indent)
|
||||
(type_arguments ">" @dedent)
|
||||
|
||||
|
||||
["case" "default"] @indent
|
||||
|
@ -38,3 +38,21 @@
|
||||
(#set! adjust.startAt lastChild.previousSibling.startPosition)
|
||||
(#set! adjust.endAt lastChild.endPosition)
|
||||
(#set! capture.final true))
|
||||
|
||||
|
||||
; META
|
||||
; ====
|
||||
|
||||
([
|
||||
(jsx_opening_element)
|
||||
(jsx_closing_element)
|
||||
] @meta.jsx.inside-tag.ts.tsx
|
||||
(#set! adjust.startAt firstChild.endPosition))
|
||||
|
||||
((jsx_self_closing_element) @meta.jsx.inside-tag.ts.tsx
|
||||
(#set! adjust.startAt firstChild.endPosition)
|
||||
(#set! adjust.endAt lastChild.startPosition))
|
||||
|
||||
((jsx_element) @meta.block.jsx.ts.tsx
|
||||
(#set! adjust.startAt firstChild.endPosition)
|
||||
(#set! adjust.endAt lastChild.startPosition))
|
||||
|
@ -2,5 +2,7 @@
|
||||
; JSX
|
||||
; ===
|
||||
|
||||
(jsx_opening_element) @indent
|
||||
(jsx_closing_element ">") @dedent
|
||||
(jsx_opening_element ["<" ">"] @indent)
|
||||
(jsx_opening_element [">"] @dedent)
|
||||
|
||||
(jsx_closing_element ">" @dedent)
|
||||
|
@ -1,5 +1,17 @@
|
||||
exports.activate = function() {
|
||||
exports.activate = function () {
|
||||
for (const scopeName of ['source.ts', 'source.tsx', 'source.flow']) {
|
||||
atom.grammars.addInjectionPoint(scopeName, {
|
||||
type: 'comment',
|
||||
language(comment) {
|
||||
if (comment.text.startsWith('/**')) return 'jsdoc';
|
||||
},
|
||||
content(comment) {
|
||||
return comment;
|
||||
},
|
||||
languageScope: null,
|
||||
// coverShallowerScopes: true
|
||||
});
|
||||
|
||||
atom.grammars.addInjectionPoint(scopeName, {
|
||||
type: 'call_expression',
|
||||
|
||||
@ -53,9 +65,31 @@ exports.activate = function() {
|
||||
},
|
||||
languageScope: null
|
||||
});
|
||||
|
||||
atom.grammars.addInjectionPoint(scopeName, {
|
||||
type: 'comment',
|
||||
language: (node) => {
|
||||
return TODO_PATTERN.test(node.text) ? 'todo' : undefined;
|
||||
},
|
||||
content: (node) => node,
|
||||
languageScope: null
|
||||
});
|
||||
|
||||
for (let type of ['template_string', 'string_fragment', 'comment']) {
|
||||
atom.grammars.addInjectionPoint(scopeName, {
|
||||
type,
|
||||
language: (node) => {
|
||||
return HYPERLINK_PATTERN.test(node.text) ? 'hyperlink' : undefined;
|
||||
},
|
||||
content: (node) => node,
|
||||
languageScope: null
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const TODO_PATTERN = /\b(TODO|FIXME|CHANGED|XXX|IDEA|HACK|NOTE|REVIEW|NB|BUG|QUESTION|COMBAK|TEMP|DEBUG|OPTIMIZE|WARNING)\b/;
|
||||
const HYPERLINK_PATTERN = /\bhttps?:/
|
||||
const STYLED_REGEX = /\bstyled\b/i;
|
||||
|
||||
function languageStringForTemplateTag(tag) {
|
||||
|
@ -11,9 +11,9 @@
|
||||
^ \\s* (\\s* /[*] .* [*]/ \\s*)* [}\\])]
|
||||
'
|
||||
|
||||
'.meta.tag.tsx':
|
||||
'.meta.tag.tsx, .meta.block.jsx.ts.tsx':
|
||||
'editor':
|
||||
'commentStart': '{/* ',
|
||||
'commentEnd': ' */}',
|
||||
'increaseIndentPattern': "{[^}\"']*$|\\[[^\\]\"']*$|\\([^)\"']*$|<[a-zA-Z][^/]*$|^\\s*>$",
|
||||
'decreaseIndentPattern': "^\\s*(\\s*/[*].*[*]/\\s*)*[}\\])]|^\\s*(</|/>)"
|
||||
'decreaseIndentPattern': "^\\s*(\\s*/[*].*[*]/\\s*)*[}\\])]|^\\s*(</|/>)"
|
||||
|
@ -4,11 +4,11 @@
|
||||
|
||||
(block_mapping_pair
|
||||
key: (_) @entity.name.tag.yaml
|
||||
(#set! test.final true))
|
||||
(#set! capture.final true))
|
||||
|
||||
(flow_pair
|
||||
key: (_) @entity.name.tag.yaml
|
||||
(#set! test.final true))
|
||||
(#set! capture.final true))
|
||||
|
||||
|
||||
; COMMENTS
|
||||
@ -35,6 +35,14 @@
|
||||
|
||||
((string_scalar) @string.quoted.yaml)
|
||||
|
||||
(single_quote_scalar) @string.quoted.single.yaml
|
||||
|
||||
((single_quote_scalar) @punctuation.definition.string.begin.yaml
|
||||
(#set! adjust.endAfterFirstMatchOf "^'"))
|
||||
|
||||
((single_quote_scalar) @punctuation.definition.string.end.yaml
|
||||
(#set! adjust.startBeforeFirstMatchOf "'$"))
|
||||
|
||||
(double_quote_scalar) @string.quoted.double.yaml
|
||||
|
||||
((double_quote_scalar) @punctuation.definition.string.begin.yaml
|
||||
|
@ -1,4 +1,4 @@
|
||||
(":" @indent
|
||||
(#set! test.onlyIfLastTextOnRow true))
|
||||
(#is? test.lastTextOnRow true))
|
||||
|
||||
["|" ">"] @indent
|
||||
|
@ -1,6 +1,6 @@
|
||||
|
||||
(block_mapping_pair
|
||||
key: (_) @name
|
||||
(#set! test.final true)
|
||||
(#set! capture.final true)
|
||||
(#set! symbol.prependSymbolForNode parent.parent.parent.parent.parent.parent.parent.firstNamedChild)
|
||||
(#set! symbol.joiner "."))
|
||||
|
@ -228,7 +228,7 @@ describe('ScopeResolver', () => {
|
||||
let bar = "this is a line below a comment"
|
||||
`);
|
||||
// Prevent an exception from being thrown before we can even check the
|
||||
// scopeResovler.
|
||||
// scopeResolver.
|
||||
spyOn(languageMode, 'isRowCommented').andReturn(false);
|
||||
await languageMode.ready;
|
||||
|
||||
|
@ -16,6 +16,11 @@ function comparePoints(a, b) {
|
||||
}
|
||||
}
|
||||
|
||||
function rangeSpecToString (range) {
|
||||
let [sp, ep] = [range.startPosition, range.endPosition];
|
||||
return `(${sp.row}, ${sp.column}) - (${ep.row}, ${ep.column})`;
|
||||
}
|
||||
|
||||
function resolveNodeDescriptor(node, descriptor) {
|
||||
let parts = descriptor.split('.');
|
||||
let result = node;
|
||||
@ -266,6 +271,20 @@ class ScopeResolver {
|
||||
return ScopeResolver.CAPTURE_SETTINGS[prop](...args);
|
||||
}
|
||||
|
||||
warnAboutExceededRange(range, capture) {
|
||||
let msg = ['Cannot extend past original range of capture!'];
|
||||
|
||||
msg.push(`Scope name: ${capture.name}`);
|
||||
msg.push(`Original range: ${rangeSpecToString(capture.node)}`);
|
||||
msg.push(`Adjusted range: ${rangeSpecToString(range)}`);
|
||||
|
||||
if (atom.inDevMode()) {
|
||||
throw new Error(msg.join('\n'));
|
||||
}
|
||||
|
||||
console.warn(msg.join('\n'));
|
||||
}
|
||||
|
||||
// Given a capture and possible predicate data, determines the buffer range
|
||||
// that this capture wants to cover.
|
||||
determineCaptureRange(capture) {
|
||||
@ -299,7 +318,7 @@ class ScopeResolver {
|
||||
}
|
||||
|
||||
if (this.rangeExceedsBoundsOfCapture(range, capture)) {
|
||||
throw new Error('Cannot extend past original range of capture');
|
||||
this.warnAboutExceededRange(range, capture);
|
||||
}
|
||||
|
||||
// Any invalidity in the returned range means we shouldn't store this
|
||||
|
@ -45,6 +45,8 @@ module.exports = class WASMTreeSitterGrammar {
|
||||
commentEndString: params.comments && params.comments.end
|
||||
};
|
||||
|
||||
this.commentMetadata = params.comments;
|
||||
|
||||
this.shouldObserveQueryFiles = atom.inDevMode() && !atom.inSpecMode();
|
||||
this.getLanguage();
|
||||
|
||||
@ -69,6 +71,50 @@ module.exports = class WASMTreeSitterGrammar {
|
||||
return id;
|
||||
}
|
||||
|
||||
// Retrieve the comment delimiters for this grammar.
|
||||
//
|
||||
// Traditionally, grammars specified only the delimiters needed for the
|
||||
// “Toggle Line Comments” command — either a line comment (if it existed) or
|
||||
// a block comment. But other features might want to know _all_ of a
|
||||
// language's possible comment delimiters, so we've devised new config values.
|
||||
getCommentDelimiters() {
|
||||
let meta = this.commentMetadata;
|
||||
if (!meta) { return null; }
|
||||
|
||||
let result = {};
|
||||
|
||||
// The new convention is to specify a `line` property and start/end
|
||||
// properties.
|
||||
let { line, block } = this.commentMetadata;
|
||||
|
||||
// Failing that, we can deliver at least a partial result by inspecting the
|
||||
// older convention. If `start` exists but not `end`, we know `start` must
|
||||
// be a line comment delimiter.
|
||||
if (!line && meta.start && !meta.end) {
|
||||
line = meta.start;
|
||||
}
|
||||
// Likewise, if both `start` and `end` exist, we know they must be block
|
||||
// comment delimiters.
|
||||
if (!block && meta.start && meta.end) {
|
||||
block = { start: meta.start, end: meta.end };
|
||||
}
|
||||
|
||||
// Strip all whitespace from delimiters. Whatever is consuming them can
|
||||
// decide if it wants whitespace.
|
||||
if (line) {
|
||||
line = line.strip();
|
||||
result.line = line;
|
||||
}
|
||||
|
||||
if (block) {
|
||||
block.start = block.start?.strip();
|
||||
block.end = block.end?.strip();
|
||||
result.block = block;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
classNameForScopeId(id) {
|
||||
return this.classNamesById.get(id);
|
||||
}
|
||||
@ -127,7 +173,7 @@ module.exports = class WASMTreeSitterGrammar {
|
||||
this.observeQueryFile(filePaths, key);
|
||||
}
|
||||
}
|
||||
Promise.all(promises).then(() => resolve());
|
||||
return Promise.all(promises).then(() => resolve());
|
||||
}).then(() => {
|
||||
this._queryFilesLoaded = true;
|
||||
this._loadQueryFilesPromise = null;
|
||||
@ -254,7 +300,9 @@ module.exports = class WASMTreeSitterGrammar {
|
||||
await this.getLanguage();
|
||||
this.queryCache.delete(queryType);
|
||||
this[queryType] = contents;
|
||||
return await this.getQuery(queryType);
|
||||
let query = await this.getQuery(queryType);
|
||||
this.emitter.emit('did-change-query-file', { filePath: '', queryType });
|
||||
return query;
|
||||
}
|
||||
|
||||
// Observe a particular query file on disk so that it can immediately be
|
||||
|
@ -1056,19 +1056,42 @@ class WASMTreeSitterLanguageMode {
|
||||
Section - Comments
|
||||
*/
|
||||
|
||||
// TODO: I know that old tree-sitter moved toward placing this data on the
|
||||
// grammar itself, but I would prefer to invert the order of these lookups.
|
||||
// As a config setting it can be scoped and overridden, but as a grammar
|
||||
// property it's just a fact of life that can't be worked around.
|
||||
//
|
||||
// TODO: Also, this should be revisited soon so that we can give the
|
||||
// `snippets` package the ability to ask about all of a grammar's comment
|
||||
// tokens — both line and block.
|
||||
// Returns the correct comment delimiters for the given buffer position. This
|
||||
// may be defined on the grammar itself, but it can also be defined as a
|
||||
// scope-specific setting for scenarios where a language has different
|
||||
// comment delimiters for different contexts.
|
||||
//
|
||||
// TODO: Our understanding of the correct delimiters for a given buffer
|
||||
// position is only as granular as the entire buffer row. This can bite us in
|
||||
// edge cases like JSX. It's the right decision if the user toggles a comment
|
||||
// with an empty selection, but if specific buffer text is selected, we
|
||||
// should look up the right delmiters for that specific range. This will
|
||||
// require a new branch in the “Editor: Toggle Line Comments” command.
|
||||
commentStringsForPosition(position) {
|
||||
// First ask the grammar for its comment strings.
|
||||
const range = this.firstNonWhitespaceRange(position.row) ||
|
||||
new Range(position, position);
|
||||
|
||||
// Ask the config system if it has a setting for this scope. This allows
|
||||
// for overrides from the grammar default.
|
||||
const scope = this.scopeDescriptorForPosition(range.start);
|
||||
const commentStartEntries = this.config.getAll(
|
||||
'editor.commentStart', { scope });
|
||||
const commentEndEntries = this.config.getAll(
|
||||
'editor.commentEnd', { scope });
|
||||
|
||||
const commentStartEntry = commentStartEntries[0];
|
||||
const commentEndEntry = commentEndEntries.find(entry => (
|
||||
entry.scopeSelector === commentStartEntry.scopeSelector
|
||||
));
|
||||
|
||||
if (commentStartEntry) {
|
||||
return {
|
||||
commentStartString: commentStartEntry && commentStartEntry.value,
|
||||
commentEndString: commentEndEntry && commentEndEntry.value
|
||||
};
|
||||
}
|
||||
|
||||
// Fall back to looking up this information on the grammar.
|
||||
const { grammar } = this.getSyntaxNodeAndGrammarContainingRange(range);
|
||||
|
||||
if (grammar) {
|
||||
@ -1079,22 +1102,6 @@ class WASMTreeSitterLanguageMode {
|
||||
return commentStrings;
|
||||
}
|
||||
}
|
||||
|
||||
// Fall back to a lookup through the config system.
|
||||
const scope = this.scopeDescriptorForPosition(position);
|
||||
const commentStartEntries = this.config.getAll(
|
||||
'editor.commentStart', { scope });
|
||||
const commentEndEntries = this.config.getAll(
|
||||
'editor.commentEnd', { scope });
|
||||
|
||||
const commentStartEntry = commentStartEntries[0];
|
||||
const commentEndEntry = commentEndEntries.find(entry => (
|
||||
entry.scopeSelector === commentStartEntry.scopeSelector
|
||||
));
|
||||
return {
|
||||
commentStartString: commentStartEntry && commentStartEntry.value,
|
||||
commentEndString: commentEndEntry && commentEndEntry.value
|
||||
};
|
||||
}
|
||||
|
||||
isRowCommented(row) {
|
||||
@ -1124,7 +1131,7 @@ class WASMTreeSitterLanguageMode {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return indentLength / tabLength;
|
||||
return Math.floor(indentLength / tabLength);
|
||||
}
|
||||
|
||||
// Get the suggested indentation level for an existing line in the buffer.
|
||||
@ -1642,6 +1649,11 @@ class WASMTreeSitterLanguageMode {
|
||||
}
|
||||
}
|
||||
|
||||
if (!indentTree) {
|
||||
console.error(`No indent tree!`, controllingLayer.inspect());
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const indents = indentsQuery.captures(
|
||||
indentTree.rootNode,
|
||||
{ row: row, column: 0 },
|
||||
@ -2821,10 +2833,10 @@ class GrammarLoadError extends Error {
|
||||
constructor(grammar, queryType) {
|
||||
super(`Grammar ${grammar.scopeName} failed to load its ${queryType}. Please fix this error or contact the maintainer.`);
|
||||
this.name = 'GrammarLoadError';
|
||||
this.queryType = queryType;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Manages all aspects of a given language's parsing duties over a given region
|
||||
// of the buffer.
|
||||
//
|
||||
@ -2898,6 +2910,13 @@ class LanguageLayer {
|
||||
}).catch((err) => {
|
||||
if (err.name === 'GrammarLoadError') {
|
||||
console.warn(err.message);
|
||||
if (err.queryType === 'highlightsQuery') {
|
||||
// TODO: Warning?
|
||||
grammar.highlightsQuery = grammar.setQueryForTest(
|
||||
'highlightsQuery',
|
||||
`; (placeholder)`
|
||||
);
|
||||
}
|
||||
} else {
|
||||
throw err;
|
||||
}
|
||||
@ -2921,12 +2940,17 @@ class LanguageLayer {
|
||||
if (depth === 0) {
|
||||
languageScope = this.grammar.scopeName;
|
||||
} else {
|
||||
// Injections can control the base scope name of the grammar being
|
||||
// injected.
|
||||
languageScope = injectionPoint.languageScope;
|
||||
// Honor an explicit `null`, but fall back to the default scope name
|
||||
// otherwise.
|
||||
|
||||
// The `languageScope` parameter can be a function.
|
||||
if (typeof languageScope === 'function') {
|
||||
languageScope = languageScope(this.grammar);
|
||||
}
|
||||
|
||||
// Honor an explicit `null`, but fall back to the default scope name
|
||||
// otherwise.
|
||||
if (languageScope === undefined) {
|
||||
languageScope = this.grammar.scopeName;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user