Permalink
Switch branches/tags
Nothing to show
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
250 lines (221 sloc) 7.46 KB
require:
codemirror as CodeMirror
provide:
CodeMirror
CodeMirror.defineMode{"earlgrey"} with {config, parserConfig} ->
re = {
id = R```
start
in "a-zA-Z$_"
* [in "a-zA-Z$_0-9" or ["-", in "a-zA-Z$_0-9"]]
```
numr = R```
start
{+d}, in "rR"
{+ in"A-Za-z0-9_"}
?[".", {+ in "A-Za-z0-9_"}]
```
num = R```
start
{+ in "0-9_"}
?[".", {+d}]
?[in "eE", {? in "+-", + in "0-9_"}]
```
lowprio = R```
;; +" "
"=" or "=>" or "->" or "%" or ":"
\ or "with" or "where" or "each"
+" " or end
```
lowprio1 = R```
"=" or "=>" or "->" or "%" or ":"
+" " or end
```
lowprio2 = R```
"with" or "where" or "each"
+" " or end
```
op = R```
start
+ in "+\\-*/~^<>=%&|?!@#.:"
```
op2_open = R```
start
in "([{"
```
comma = R```
start, ","
```
op2_close = R```
start
in "}])"
```
op3 = R```
start
"with" or "where" or "when"
\ or "and" or "not" or "or"
\ or "in" or "mod"
\ or "each" or "as"
\ or "of" or "is"
[+ in "+\\-*/~^<>=%&|?!@#.:"] or boundary
```
op4 = R```
start
"`", {+ in "A-Za-z0-9_$"}, "`"
```
}
{
startState{} = {
mode = .code
previous = null
sol = true
nest = {{"", 0, 0, false}}
}
token{stream, state} =
if stream.sol{}:
if stream.match{R"===$"}:
return "sep"
else:
state.sol = true
index = state.nest.length - 1
match state.nest[index]:
{o, a, _, _} ->
state.nest[index] = {o, a, stream.indentation{}, false}
else ->
pass
else:
state.sol = false
spaces = stream.eatSpace{}
result = match state.mode:
.code ->
match stream.peek{}:
d and in {"\"", "'", "`"} ->
stream.next{}
state.mode = .string
state.strtype =
match d:
"\"" -> "string"
"'" -> "interpolated"
"`" -> "quote"
state.finisher = d
state.strtype
when stream.match{R";;"} ->
stream.skipToEnd{}
state.previous = .comment
"comment"
;; when stream.match{"___"} ->
;; state.previous = .id
;; "ellipsis"
when stream.match{R"\.[A-Za-z0-9_$\\-]+"} ->
state.previous = .id
"string"
when stream.match{R"@[A-Za-z0-9$\\-]+"} ->
state.previous = .id
"attribute"
when stream.match{R"#[A-Za-z0-9$\\-]+"} ->
state.previous = .id
"tag"
when stream.match{R"pass|else|return|break|continue|match"} ->
state.previous = .id
"keyword"
when stream.match{R"true|false|null|undefined|this"} ->
state.previous = .id
"special"
when stream.match{re.lowprio1} ->
state.previous = .lowprio
"operator"
when stream.match{re.lowprio2} ->
state.previous = .lowprio
"wordop"
when stream.match{re.op}
\ or stream.match{re.op4} ->
state.previous = .op
"operator"
when stream.match{re.op3} ->
state.previous = .op
"wordop"
match when stream.match{re.id} ->
match when R"lowprio|comma"? state.previous or state.sol ->
when stream.match{R" +(with|where|when|and|not|or|in|mod|each|as|of|is)( |$)", false} ->
state.previous = .id
"variable"
when stream.match{R" *:| +[A-Za-z0-9$\[\{\(\"]", false} ->
state.previous = .id
"keyword"
when stream.match{R" +[+\-*/~^<>=%&|?!@#.:']+[A-Za-z0-9$\[\{\(]", false} ->
state.previous = .id
"keyword"
else ->
state.previous = .id
"variable"
else ->
state.previous = .id
"variable"
when stream.match{re.numr} or stream.match{re.num} ->
state.previous = .id
"number"
when stream.match{re.op2_open, false} ->
opchar = stream.match{re.op2_open}[0]
state.previous = .lowprio
state.nest.push with
if stream.eol{}:
then: {
opchar
n
n + config.indentUnit
true
} where n = state.nest[state.nest.length - 1][2]
else: {
opchar
n
n + 1
true
} where n = stream.column{}
"open"
when stream.match{re.comma} ->
state.previous = .comma
"punctuation"
when stream.match{re.op2_close} ->
state.previous = .punct
if state.nest.length > 1:
state.nest.pop{}
"close"
else ->
stream.next{}
null
.string ->
stream.match{rx} where
sf = state.finisher
rx = new RegExp{"(\\\\" + sf + "|[^" + sf + "])+"}
match stream.eat{state.finisher}:
undefined? ->
state.strtype
else ->
state.mode = .code
state.previous = .id
state.strtype
result
indent{state, line} =
{_, outr, inner, first} = state.nest[index] where
index = state.nest.length - 1
add =
if [not first] and [state.previous == .lowprio or state.previous == .op]:
then: config.indentUnit
else: 0
match line:
R`start, in "]}"`? ->
outr + add
else ->
inner + add
blankLine{state} =
state.sol = true
index = state.nest.length - 1
match state.nest[index]:
{o, a, _, _} ->
state.nest[index] = {o, a, 0, false}
else ->
pass
null
lineComment = ";;"
electricInput = R`start, *" ", in "]})", end`
}