Skip to content

Commit

Permalink
Highlight partial parses
Browse files Browse the repository at this point in the history
  • Loading branch information
tjvr committed May 12, 2017
1 parent 4dc557c commit a6eefb0
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 20 deletions.
4 changes: 2 additions & 2 deletions editor/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -200,8 +200,8 @@ Editor.prototype.cmOptions = {
case '_greenFlag': return 's-green'
case 'b0': return 'false'
case 'end': case 'else': return 's-control'
case 'string': case 's0': return 'string'
case 'number': case 'n0': return 'number'
case 's0': return 'string'
case 'n0': return 'number'
case '_': case '__': return ' '
}
const factory = rule.postprocess
Expand Down
48 changes: 33 additions & 15 deletions editor/mode.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ CodeMirror.defineMode('tosh', module.exports = function(cfg, modeCfg) {
})
completer.feed("")
const startColumn = completer.save()
const lexer = modeCfg.grammar.lexer

class State {
constructor(column, indent) {
Expand All @@ -116,28 +117,45 @@ CodeMirror.defineMode('tosh', module.exports = function(cfg, modeCfg) {
completer.restore(startCol)

// TODO handle previous error
let errorToken
let endCol
try {
completer.feed(line)

// TODO allow partial tokens

} catch (e) {
// TODO avoid lexing again
const lexer = modeCfg.grammar.lexer
lexer.reset(line, startCol.lexerState)
const ranges = []
var token
while (token = lexer.next()) {
const text = line.substr(token.offset, token.size)
ranges.push({className: 'error', text})
endCol = completer.save()

} catch (err) {
const isPartial = !/\s$/.test(line)
errorToken = err.token

endCol = completer.parser.table[completer.parser.current]

if (!isPartial) {
// TODO avoid lexing again
lexer.reset(line, startCol.lexerState)
const ranges = []
var token
while (token = lexer.next()) {
const text = line.substr(token.offset, token.size)
ranges.push({className: 'error', text})
}
ranges.reverse()
return ranges
}
ranges.reverse()
return ranges
}
const endCol = this.column = completer.save()
this.column = endCol

// TODO can we avoid running highlighting if CM is using processLine?
const ranges = []
if (errorToken) {
const text = line.slice(errorToken.offset)
ranges.push({className: /^["']/.test(text) ? 'string' : null, text})
}

if (startCol === endCol) {
return [{className: null, text: line}]
}

// TODO can we avoid running highlighting if CM is using processLine?
completer.highlight(startCol, endCol, (className, token) => {
const text = line.substr(token.offset, token.size)
if (text === '{') { this.indent++ }
Expand Down
12 changes: 9 additions & 3 deletions test/mode.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -182,14 +182,20 @@ describe('highlight', () => {
' [s-pen stamp]',
'[s-control }]')

MT('partial',
'sa')

MT('partial',
'[s-looks say] [s-motion x] pos')

MT('invalid',
'[error foo bar]')
'foo bar')

MT('open string',
'[error say ][string "]')
'[s-looks say] [string "]')

MT('open string',
'[error say ][string "foo]')
'[s-looks say] [string "foo]')

// make sure I don't try to be too efficient looking for open strings
MT('closed string',
Expand Down

0 comments on commit a6eefb0

Please sign in to comment.