diff --git a/doc/site/js/main.js b/doc/site/js/main.js index 365ab05c..b52d6f6b 100644 --- a/doc/site/js/main.js +++ b/doc/site/js/main.js @@ -7,9 +7,12 @@ $(function() { editor.container.style.opacity = ""; embedded_editor = ace.edit("embedded_ace_code"); embedded_editor.container.style.opacity = ""; - editor.getSession().setMode("ace/mode/javascript"); - editor.getSession().setMode("ace/mode/javascript"); - embedded_editor.getSession().setMode("ace/mode/html"); + editor.session.setMode("ace/mode/javascript"); + editor.session.setMode("ace/mode/javascript"); + embedded_editor.session.setMode("ace/mode/html"); + + embedded_editor.setAutoScrollEditorIntoView(true); + editor.setAutoScrollEditorIntoView(true); $("ul.menu-list li").click(function(e) { if (e.target.tagName === "LI") { diff --git a/index.html b/index.html index 8895546a..5446ac38 100644 --- a/index.html +++ b/index.html @@ -944,6 +944,11 @@ oop.inherits(FoldMode, BaseFoldMode); style="position: relative; left: 3px; width: 96px;top: -12px;"> Slim Text +
  • + + Decor +
  • Sky Edit
  • diff --git a/lib/ace/edit_session.js b/lib/ace/edit_session.js index 697d0508..f6744907 100644 --- a/lib/ace/edit_session.js +++ b/lib/ace/edit_session.js @@ -2445,7 +2445,7 @@ config.defineOptions(EditSession.prototype, "session", { }, newLineMode: { set: function(val) {this.doc.setNewLineMode(val)}, - get: function() {return this.doc.getNewLineMode(newLineMode)}, + get: function() {return this.doc.getNewLineMode()}, handlesSet: true } }); diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 4bab091d..b331f2ac 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -2136,7 +2136,7 @@ var Editor = function(renderer, session) { * @param {Boolean} enable default true **/ this.setAutoScrollEditorIntoView = function(enable) { - if (enable === true) + if (enable === false) return; var rect; var self = this; @@ -2178,7 +2178,7 @@ var Editor = function(renderer, session) { } }); this.setAutoScrollEditorIntoView = function(enable) { - if (enable === false) + if (enable === true) return; delete this.setAutoScrollEditorIntoView; this.removeEventListener("changeSelection", onChangeSelection); diff --git a/lib/ace/ext/searchbox.css b/lib/ace/ext/searchbox.css index c8fd126a..e00508fb 100644 --- a/lib/ace/ext/searchbox.css +++ b/lib/ace/ext/searchbox.css @@ -35,6 +35,9 @@ margin-bottom: 4px; overflow: hidden; } +.ace_search_form.ace_nomatch { + outline: 1px solid red; +} .ace_search_field { background-color: white; @@ -111,4 +114,44 @@ } .ace_replacebtn.next { width: 27px +} + +.ace_button { + margin-left: 2px; + cursor: pointer; + -webkit-user-select: none; + -moz-user-select: none; + -o-user-select: none; + -ms-user-select: none; + user-select: none; + overflow: hidden; + opacity: 0.7; + border: 1px solid rgba(100,100,100,0.23); + padding: 1px; + -moz-box-sizing: border-box; + box-sizing: border-box; + color: black; +} + +.ace_button:hover { + background-color: #eee; + opacity:1; +} +.ace_button:active { + background-color: #ddd; +} + +.ace_button.checked { + border-color: #3399ff; + opacity:1; +} + +.ace_search_options{ + margin-bottom: 3px; + text-align: right; + -webkit-user-select: none; + -moz-user-select: none; + -o-user-select: none; + -ms-user-select: none; + user-select: none; } \ No newline at end of file diff --git a/lib/ace/ext/searchbox.js b/lib/ace/ext/searchbox.js index e2d97366..71cab2ac 100644 --- a/lib/ace/ext/searchbox.js +++ b/lib/ace/ext/searchbox.js @@ -52,6 +52,11 @@ var html = '\ +
    \ + .*\ + Aa\ + \\b\ +
    \ '.replace(/>\s+/g, ">"); var SearchBox = function(editor, range, showReplaceForm) { @@ -75,6 +80,10 @@ var SearchBox = function(editor, range, showReplaceForm) { this.searchBox = sb.querySelector(".ace_search_form"); this.replaceBox = sb.querySelector(".ace_replace_form"); + this.searchOptions = sb.querySelector(".ace_search_options"); + this.regExpOption = sb.querySelector("[action=toggleRegexpMode]"); + this.caseSensitiveOption = sb.querySelector("[action=toggleCaseSensitive]"); + this.wholeWordOption = sb.querySelector("[action=toggleWholeWords]"); this.searchInput = this.searchBox.querySelector(".ace_search_field"); this.replaceInput = this.replaceBox.querySelector(".ace_search_field"); @@ -90,6 +99,8 @@ var SearchBox = function(editor, range, showReplaceForm) { var action = t.getAttribute("action"); if (action && _this[action]) _this[action](); + else if (_this.$searchBarKb.commands[action]) + _this.$searchBarKb.commands[action].exec(_this); event.stopPropagation(e); }); @@ -157,14 +168,47 @@ var SearchBox = function(editor, range, showReplaceForm) { (sb.activeInput == sb.replaceInput ? sb.searchInput : sb.replaceInput).focus(); } }); - + + this.$searchBarKb.addCommands([{ + name: "toggleRegexpMode", + bindKey: {win: "Alt-R|Alt-/", mac: "Ctrl-Alt-R|Ctrl-Alt-/"}, + exec: function(sb) { + sb.regExpOption.checked = !sb.regExpOption.checked; + sb.$syncOptions(); + } + }, { + name: "toggleCaseSensitive", + bindKey: {win: "Alt-C|Alt-I", mac: "Ctrl-Alt-R|Ctrl-Alt-I"}, + exec: function(sb) { + sb.caseSensitiveOption.checked = !sb.caseSensitiveOption.checked; + sb.$syncOptions(); + } + }, { + name: "toggleWholeWords", + bindKey: {win: "Alt-B|Alt-W", mac: "Ctrl-Alt-B|Ctrl-Alt-W"}, + exec: function(sb) { + sb.wholeWordOption.checked = !sb.wholeWordOption.checked; + sb.$syncOptions(); + } + }]); + + this.$syncOptions = function() { + dom.setCssClass(this.regExpOption, "checked", this.regExpOption.checked); + dom.setCssClass(this.wholeWordOption, "checked", this.wholeWordOption.checked); + dom.setCssClass(this.caseSensitiveOption, "checked", this.caseSensitiveOption.checked); + this.find(false, false); + }; this.find = function(skipCurrent, backwards) { - this.editor.find(this.searchInput.value, { + var range = this.editor.find(this.searchInput.value, { skipCurrent: skipCurrent, backwards: backwards, - wrap: true + wrap: true, + regExp: this.regExpOption.checked, + caseSensitive: this.caseSensitiveOption.checked, + wholeWord: this.wholeWordOption.checked }); + dom.setCssClass(this.searchBox, "ace_nomatch", !range && this.searchInput.value); this.editor.session.highlight(this.editor.$search.$options.re); }; this.findNext = function() { @@ -175,7 +219,6 @@ var SearchBox = function(editor, range, showReplaceForm) { }; this.replace = function() { this.editor.replace(this.replaceInput.value); - this.findNext(); }; this.replaceAll = function() { this.editor.replaceAll(this.replaceInput.value); diff --git a/lib/ace/mode/logiql.js b/lib/ace/mode/logiql.js index cdf6b607..c640bd42 100644 --- a/lib/ace/mode/logiql.js +++ b/lib/ace/mode/logiql.js @@ -38,11 +38,15 @@ var LogiQLHighlightRules = require("./logiql_highlight_rules").LogiQLHighlightRu var FoldMode = require("./folding/coffee").FoldMode; var TokenIterator = require("../token_iterator").TokenIterator; var Range = require("../range").Range; +var CstyleBehaviour = require("./behaviour/cstyle").CstyleBehaviour; +var MatchingBraceOutdent = require("./matching_brace_outdent").MatchingBraceOutdent; var Mode = function() { var highlighter = new LogiQLHighlightRules(); this.foldingRules = new FoldMode(); this.$tokenizer = new Tokenizer(highlighter.getRules()); + this.$outdent = new MatchingBraceOutdent(); + this.$behaviour = new CstyleBehaviour(); }; oop.inherits(Mode, TextMode); @@ -62,12 +66,15 @@ oop.inherits(Mode, TextMode); return indent; var match = line.match(); - if (/(-->|<--|<-|->)\s*$/.test(line)) + if (/(-->|<--|<-|->|{)\s*$/.test(line)) indent += tab; return indent; }; this.checkOutdent = function(state, line, input) { + if (this.$outdent.checkOutdent(line, input)) + return true; + if (input !== "\n" && input !== "\r\n") return false; @@ -78,6 +85,8 @@ oop.inherits(Mode, TextMode); }; this.autoOutdent = function(state, doc, row) { + if (this.$outdent.autoOutdent(doc, row)) + return; var prevLine = doc.getLine(row); var match = prevLine.match(/^\s+/); var column = prevLine.lastIndexOf(".") + 1; diff --git a/lib/ace/mode/logiql_highlight_rules.js b/lib/ace/mode/logiql_highlight_rules.js index 66fa642c..17ceab0c 100644 --- a/lib/ace/mode/logiql_highlight_rules.js +++ b/lib/ace/mode/logiql_highlight_rules.js @@ -98,7 +98,7 @@ var LogiQLHighlightRules = function() { //All the lang system predicates }, { token: [ 'storage.type', 'text' ], - regex: '(export|sealed|clauses|block|alias)\\s*\\((?=`)', + regex: '(export|sealed|clauses|block|alias)(\\s*\\()(?=`)', //Module keywords }, { token: 'entity.name', diff --git a/lib/ace/tokenizer.js b/lib/ace/tokenizer.js index 33a50936..189b671b 100644 --- a/lib/ace/tokenizer.js +++ b/lib/ace/tokenizer.js @@ -75,8 +75,12 @@ var Tokenizer = function(rules) { var adjustedregex = rule.regex; var matchcount = new RegExp("(?:(" + adjustedregex + ")|(.))").exec("a").length - 2; if (Array.isArray(rule.token)) { - if (rule.token.length == 1) { + if (rule.token.length == 1 || matchcount == 1) { rule.token = rule.token[0]; + } else if (matchcount - 1 != rule.token.length) { + throw new Error("number of classes and regexp groups in '" + + rule.token + "'\n'" + rule.regex + "' doesn't match\n" + + (matchcount - 1) + "!=" + rule.token.length); } else { rule.tokenArray = rule.token; rule.onMatch = this.$arrayTokens; @@ -143,11 +147,6 @@ var Tokenizer = function(rules) { var values = this.splitRegex.exec(str); var tokens = []; var types = this.tokenArray; - if (types.length != values.length - 1) { - if (window.console) - console.error(types , values, str, this.splitRegex, this); - return [{type: "error.invalid", value: str}]; - } for (var i = 0, l = types.length; i < l; i++) { if (values[i + 1]) tokens[tokens.length] = { diff --git a/lib/ace/tokenizer_dev.js b/lib/ace/tokenizer_dev.js index e8a4dd84..4321035c 100644 --- a/lib/ace/tokenizer_dev.js +++ b/lib/ace/tokenizer_dev.js @@ -29,6 +29,7 @@ * ***** END LICENSE BLOCK ***** */ define(function(require, exports, module) { +var BaseTokenizer = require("./tokenizer").Tokenizer; // tokenizing lines longer than this makes editor very slow var MAX_TOKEN_COUNT = 1000; @@ -39,101 +40,7 @@ var MAX_TOKEN_COUNT = 1000; **/ var Tokenizer = function(rules) { - this.states = rules; - - this.regExps = {}; - this.matchMappings = {}; - for (var key in this.states) { - var state = this.states[key]; - var ruleRegExps = []; - var matchTotal = 0; - var mapping = this.matchMappings[key] = {defaultToken: "default.text"}; - var flag = "g"; - - for (var i = 0; i < state.length; i++) { - var rule = state[i]; - if (rule.defaultToken) - mapping.defaultToken = rule.defaultToken; - if (rule.caseInsensitive) - flag = "gi"; - if (rule.regex == null) - continue; - - if (rule.regex instanceof RegExp) - rule.regex = rule.regex.toString().slice(1, -1); - - // Count number of matching groups. 2 extra groups from the full match - // And the catch-all on the end (used to force a match); - var adjustedregex = rule.regex; - var matchcount = new RegExp("(?:(" + adjustedregex + ")|(.))").exec("a").length - 2; - if (Array.isArray(rule.token)) { - if (rule.token.length == 1) { - rule.token = rule.token[0]; - } else { - rule.tokenArray = rule.token; - rule.token = this.$arrayTokens; - } - } - - if (matchcount > 1) { - if (/\\\d/.test(rule.regex)) { - // Replace any backreferences and offset appropriately. - adjustedregex = rule.regex.replace(/\\([0-9]+)/g, function (match, digit) { - return "\\" + (parseInt(digit, 10) + matchTotal + 1); - }); - } else { - matchcount = 1; - adjustedregex = this.removeCapturingGroups(rule.regex); - } - if (!rule.splitRegex) - rule.splitRegex = this.createSplitterRegexp(rule.regex, flag); - } - - mapping[matchTotal] = i; - matchTotal += matchcount; - - ruleRegExps.push(adjustedregex); - } - - this.regExps[key] = new RegExp("(" + ruleRegExps.join(")|(") + ")|($)", flag); - } -}; - -(function() { - this.$arrayTokens = function(str) { - if (!str) - return []; - var values = str.split(this.splitRegex) - var tokens = []; - var types = this.tokenArray; - if (types.length != values.length - 2) { - if (window.console) - console.error(types.length , values.length - 2, str, this.splitRegex); - return [{type: "error.invalid", value: str}]; - } - for (var i = 0; i < types.length; i++) { - if (values[i + 1]) { - tokens[tokens.length] = { - type: types[i], - value: values[i + 1] - }; - } - } - return tokens; - }; - - this.removeCapturingGroups = function(src) { - var r = src.replace( - /\[(?:\\.|[^\]])*?\]|\\.|\(\?[:=!]|(\()/g, - function(x, y) {return y ? "(?:" : x;} - ); - return r; - }; - - this.createSplitterRegexp = function(src, flag) { - src = src.replace(/\(\?=([^()]|\\.)*?\)$/, ""); - return new RegExp(src, flag); - }; + BaseTokenizer.call(this, rules); /** * Returns an object containing two properties: `tokens`, which contains all the tokens; and `state`, the current state. @@ -202,10 +109,10 @@ var Tokenizer = function(rules) { rule = state[mapping[i]]; - // compute token type - type = typeof rule.token == "function" - ? rule.token(value, currentState, stack) - : rule.token; + if (rule.onMatch) + type = rule.onMatch(value, currentState, stack); + else + type = rule.token; if (rule.next) { if (typeof rule.next == "string") @@ -268,7 +175,7 @@ var Tokenizer = function(rules) { }; }; -}).call(Tokenizer.prototype); +}; exports.Tokenizer = Tokenizer; });