Skip to content

Commit c2e4b98

Browse files
committed
copy scopes.js to lib_src
1 parent 71e7535 commit c2e4b98

File tree

1 file changed

+105
-0
lines changed

1 file changed

+105
-0
lines changed

lib_src/misc/scopes.js

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/** @babel */
2+
3+
import { Point, Range } from 'atom'
4+
5+
const juliaScopes = ['source.julia', 'source.embedded.julia']
6+
const openers = [
7+
'if', 'while', 'for', 'begin', 'function', 'macro', 'module', 'baremodule', 'type', 'immutable',
8+
'struct', 'mutable struct', 'try', 'let', 'do', 'quote', 'abstract type', 'primitive type'
9+
]
10+
const reopeners = [ 'else', 'elseif', 'catch', 'finally' ]
11+
12+
function isKeywordScope (scopes) {
13+
// Skip 'source.julia'
14+
return scopes.slice(1).some(scope => {
15+
return scope.indexOf('keyword') > -1
16+
})
17+
}
18+
19+
export function isStringScope (scopes) {
20+
let isString = false
21+
let isInterp = false
22+
for (const scope of scopes) {
23+
if (scope.indexOf('string') > -1) {
24+
isString = true
25+
}
26+
if (scope.indexOf('interpolation') > -1) {
27+
isInterp = true
28+
}
29+
}
30+
return isString && !isInterp
31+
}
32+
33+
function forRange (editor, range) {
34+
// this should happen here and not a top-level so that we aren't relying on
35+
// Atom to load packages in a specific order:
36+
const juliaGrammar = atom.grammars.grammarForScopeName('source.julia')
37+
38+
if (juliaGrammar === undefined) return []
39+
40+
const scopes = []
41+
let n_parens = 0
42+
let n_brackets = 0
43+
const text = editor.getTextInBufferRange(range)
44+
juliaGrammar.tokenizeLines(text).forEach(lineTokens => {
45+
lineTokens.forEach(token => {
46+
const { value } = token
47+
if (!isStringScope(token.scopes)) {
48+
if (n_parens > 0 && value === ')') {
49+
n_parens -= 1
50+
scopes.splice(scopes.lastIndexOf('paren'), 1)
51+
return
52+
} else if (n_brackets > 0 && value === ']') {
53+
n_brackets -= 1
54+
scopes.splice(scopes.lastIndexOf('bracket'), 1)
55+
return
56+
} else if (value === '(') {
57+
n_parens += 1
58+
scopes.push('paren')
59+
return
60+
} else if (value === '[') {
61+
n_brackets += 1
62+
scopes.push('bracket')
63+
return
64+
}
65+
}
66+
if (!(isKeywordScope(token.scopes))) return
67+
if (!(n_parens === 0 && n_brackets === 0)) return
68+
69+
const reopen = reopeners.includes(value)
70+
if (value === 'end' || reopen) scopes.pop()
71+
if (openers.includes(value) || reopen) scopes.push(value)
72+
})
73+
})
74+
return scopes
75+
}
76+
77+
export function forLines (editor, start, end) {
78+
const startPoint = new Point(start, 0)
79+
const endPoint = new Point(end, Infinity)
80+
const range = new Range(startPoint, endPoint)
81+
return forRange(editor, range)
82+
}
83+
84+
export function isCommentScope (scopes) {
85+
// Skip 'source.julia'
86+
return scopes.slice(1).some(scope => {
87+
return scope.indexOf('comment') > -1
88+
})
89+
}
90+
91+
/**
92+
* Returns `true` if the scope at `bufferPosition` in `editor` is valid code scope to be inspected.
93+
* Supposed to be used within Atom-IDE integrations, whose `grammarScopes` setting doesn't support
94+
* embedded scopes by default.
95+
*/
96+
export function isValidScopeToInspect (editor, bufferPosition) {
97+
const scopes = editor
98+
.scopeDescriptorForBufferPosition(bufferPosition)
99+
.getScopesArray()
100+
return scopes.some(scope => {
101+
return juliaScopes.includes(scope)
102+
}) ?
103+
!isCommentScope(scopes) && !isStringScope(scopes) :
104+
false
105+
}

0 commit comments

Comments
 (0)