diff --git a/lib/ace/mode/logicql.js b/lib/ace/mode/logicql.js index bc0c16c7..f63f1d0e 100644 --- a/lib/ace/mode/logicql.js +++ b/lib/ace/mode/logicql.js @@ -35,8 +35,9 @@ var oop = require("../lib/oop"); var TextMode = require("./text").Mode; var Tokenizer = require("../tokenizer").Tokenizer; var LogicQLHighlightRules = require("./logicql_highlight_rules").LogicQLHighlightRules; -// TODO: pick appropriate fold mode -var FoldMode = require("./folding/cstyle").FoldMode; +var FoldMode = require("./folding/coffee").FoldMode; +var TokenIterator = require("ace/token_iterator").TokenIterator; +var Range = require("ace/range").Range; var Mode = function() { var highlighter = new LogicQLHighlightRules(); @@ -48,6 +49,72 @@ oop.inherits(Mode, TextMode); (function() { this.lineCommentStart = "//"; this.blockComment = {start: "/*", end: "*/"}; + + this.getNextLineIndent = function(state, line, tab) { + var indent = this.$getIndent(line); + var match = line.match(); + if (/(-->|<--|<-|->)\s*$/.test(line)) + indent += tab; + return indent; + }; + + this.checkOutdent = function(state, line, input) { + if (input !== "\n" && input !== "\r\n") + return false; + + if (!/^\s+/.test(line)) + return false; + + return true; + }; + + this.autoOutdent = function(state, doc, row) { + var prevLine = doc.getLine(row); + var match = prevLine.match(/^\s+/); + var column = prevLine.lastIndexOf("."); + if (!match || row == 0 || column == -1) return 0; + + var line = doc.getLine(row + 1); + var startRange = this.getMatching(doc, {row: row, column: column}); + if (!startRange || startRange.start.row == row) return 0; + + column = match[0].length; + var indent = this.$getIndent(doc.getLine(startRange.start.row)); + doc.replace(new Range(row + 1, 0, row + 1, column), indent); + }; + + this.getMatching = function(session, row, column) { + if (row == undefined) + row = session.selection.lead + if (typeof row == "object") { + row = row.row; + column = row.column; + } + + var startToken = session.getTokenAt(row, column); + var KW_START = "keyword.start", KW_END = "keyword.end"; + var tok; + + if (startToken.type == KW_START) { + var it = new TokenIterator(session, row, column); + it.step = it.stepForward; + } else if (startToken.type == KW_END) { + var it = new TokenIterator(session, row, column); + it.step = it.stepBackward; + } else + return; + + while (tok = it.step()) { + if (tok.type == KW_START || tok.type == KW_END) + break; + } + if (!tok) + return; + + var col = it.getCurrentTokenColumn(); + var row = it.getCurrentTokenRow(); + return new Range(row, col, row, col + tok.value.length); + }; // Extra logic goes here. }).call(Mode.prototype); diff --git a/lib/ace/mode/logicql_highlight_rules.js b/lib/ace/mode/logicql_highlight_rules.js index 601c5bb2..eb59eda4 100644 --- a/lib/ace/mode/logicql_highlight_rules.js +++ b/lib/ace/mode/logicql_highlight_rules.js @@ -72,26 +72,17 @@ var LogicQLHighlightRules = function() { regex: '`[a-zA-Z_:]+(\\d|\\a)*\\b', //LogicBlox Symbol }, - { token: 'keyword.other', regex: '->', comment: 'Constraint' }, - { token: 'keyword.other', - regex: '-->', - //Level 1 Constraint - }, - { token: 'keyword.other', regex: '<-', comment: 'Rule' }, - { token: 'keyword.other', regex: '<--', comment: 'Level 1 Rule' }, - { token: 'keyword.other', regex: '\\.', comment: 'Terminator' }, - { token: 'keyword.other', regex: '!', comment: 'Negation' }, - { token: 'keyword.other', regex: ',', comment: 'Conjunction' }, - { token: 'keyword.other', regex: ';', comment: 'Disjunction' }, - { token: 'keyword.operator', - regex: '<=|>=|!=|<|>', - //Equality - }, + { token: 'keyword.start', regex: '->', comment: 'Constraint' }, + { token: 'keyword.start', regex: '-->', comment: 'Level 1 Constraint'}, + { token: 'keyword.start', regex: '<-', comment: 'Rule' }, + { token: 'keyword.start', regex: '<--', comment: 'Level 1 Rule' }, + { token: 'keyword.end', regex: '\\.', comment: 'Terminator' }, + { token: 'keyword.other', regex: '!', comment: 'Negation' }, + { token: 'keyword.other', regex: ',', comment: 'Conjunction' }, + { token: 'keyword.other', regex: ';', comment: 'Disjunction' }, + { token: 'keyword.operator', regex: '<=|>=|!=|<|>', comment: 'Equality'}, { token: 'keyword.other', regex: '@', comment: 'Equality' }, - { token: 'keyword.operator', - regex: '\\+|-|\\*|/', - //Arithmetic operations - }, + { token: 'keyword.operator', regex: '\\+|-|\\*|/', comment: 'Arithmetic operations'}, { token: 'keyword', regex: '::', comment: 'Colon colon' }, { token: 'support.function', regex: '\\b(agg\\s*<<)',