diff --git a/lib/ace/editor.js b/lib/ace/editor.js index 72484840..e77bab90 100644 --- a/lib/ace/editor.js +++ b/lib/ace/editor.js @@ -1800,6 +1800,10 @@ var Editor = function(renderer, session) { * **/ this.navigateUp = function(times) { + if (this.selection.isMultiLine() && !this.selection.isBackwards()) { + var selectionStart = this.selection.anchor.getPosition(); + return this.moveCursorToPosition(selectionStart); + } this.selection.clearSelection(); times = times || 1; this.selection.moveCursorBy(-times, 0); @@ -1812,6 +1816,10 @@ var Editor = function(renderer, session) { * **/ this.navigateDown = function(times) { + if (this.selection.isMultiLine() && this.selection.isBackwards()) { + var selectionEnd = this.selection.anchor.getPosition(); + return this.moveCursorToPosition(selectionEnd); + } this.selection.clearSelection(); times = times || 1; this.selection.moveCursorBy(times, 0); @@ -2220,4 +2228,4 @@ config.defineOptions(Editor.prototype, "editor", { }); exports.Editor = Editor; -}); +}); \ No newline at end of file diff --git a/lib/ace/keyboard/hash_handler.js b/lib/ace/keyboard/hash_handler.js index e56b0b13..fc323837 100644 --- a/lib/ace/keyboard/hash_handler.js +++ b/lib/ace/keyboard/hash_handler.js @@ -73,7 +73,7 @@ function HashHandler(config, platform) { if(!key) return; if (typeof command == "function") { - this.addCommand({exec: command, bindKey: key, name: key}); + this.addCommand({exec: command, bindKey: key, name: command.name || key}); return; } diff --git a/lib/ace/mode/_test/text_ruby.txt b/lib/ace/mode/_test/text_ruby.txt index c52fe4c3..1343a270 100644 --- a/lib/ace/mode/_test/text_ruby.txt +++ b/lib/ace/mode/_test/text_ruby.txt @@ -12,4 +12,23 @@ #test: float tokenizer [1, +1, -1, 12_345, 0.000_1, _, 3_1, 1_2, 1_.0, 0._1]; - \ No newline at end of file + +{:id => 34, :key => "value"} + +=begin +=end + +=begin x +=end- +=end x + + herDocs = [<<'FOO', <"], + ["text"," "], + ["constant.numeric","34"], + ["text",", "], + ["constant.other.symbol.ruby",":key"], + ["text"," "], + ["punctuation.separator.key-value","=>"], + ["text"," "], + ["string","\"value\""], + ["paren.rparen","}"] +],[ + "start" +],[ + "comment", + ["comment","=begin"] +],[ + "start", + ["comment","=end"] +],[ + "start" +],[ + "comment", + ["comment","=begin x"] +],[ + "comment", + ["comment","=end-"] +],[ + "start", + ["comment","=end x"] +],[ + "start" +],[ + ["heredoc","FOO","heredoc","BAR","indentedHeredoc","BAZ","indentedHeredoc","EXEC"], + ["text"," "], + ["identifier","herDocs"], + ["text"," "], + ["keyword.operator","="], + ["text"," "], + ["paren.lparen","["], + ["constant","<<"], + ["string","'"], + ["support.class","FOO"], + ["string","'"], + ["text",", "], + ["constant","<<"], + ["string",""], + ["support.class","BAR"], + ["string",""], + ["text",", "], + ["constant","<<-"], + ["string",""], + ["support.class","BAZ"], + ["string",""], + ["text",", "], + ["constant","<<-"], + ["string","`"], + ["support.class","EXEC"], + ["string","`"], + ["paren.rparen","]"], + ["text"," "], + ["comment","#comment"] +],[ + ["heredoc","FOO","heredoc","BAR","indentedHeredoc","BAZ","indentedHeredoc","EXEC"], + ["string"," FOO #{literal}"] +],[ + ["heredoc","BAR","indentedHeredoc","BAZ","indentedHeredoc","EXEC"], + ["support.class","FOO"] +],[ + ["heredoc","BAR","indentedHeredoc","BAZ","indentedHeredoc","EXEC"], + ["string"," BAR #{fact(10)}"] +],[ + ["indentedHeredoc","BAZ","indentedHeredoc","EXEC"], + ["support.class","BAR"] +],[ + ["indentedHeredoc","BAZ","indentedHeredoc","EXEC"], + ["string"," BAZ indented"] +],[ + ["indentedHeredoc","EXEC"], + ["string"," "], + ["support.class","BAZ"] +],[ + ["indentedHeredoc","EXEC"], + ["string"," echo hi"] +],[ + "start", + ["string"," "], + ["support.class","EXEC"] +],[ + "start", + ["support.function","puts"], + ["text"," "], + ["identifier","herDocs"] ]] \ No newline at end of file diff --git a/lib/ace/mode/php_highlight_rules.js b/lib/ace/mode/php_highlight_rules.js index 3be84f56..95bec4b3 100644 --- a/lib/ace/mode/php_highlight_rules.js +++ b/lib/ace/mode/php_highlight_rules.js @@ -3,7 +3,7 @@ * * Copyright (c) 2010, Ajax.org B.V. * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright @@ -14,7 +14,7 @@ * * Neither the name of Ajax.org B.V. nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -930,6 +930,12 @@ var PhpLangHighlightRules = function() { "HP_(?:BINDIR|CONFIG_FILE_(?:PATH|SCAN_DIR)|DATADIR|E(?:OL|XTENSION_DIR)|INT_(?:MAX|SIZE)|" + "L(?:IBDIR|OCALSTATEDIR)|O(?:S|UTPUT_HANDLER_(?:CONT|END|START))|PREFIX|S(?:API|HLIB_SUFFIX|YSCONFDIR)|" + "VERSION))|__COMPILER_HALT_OFFSET__)\\b" + }, { + token : ["keyword", "text", "support.class"], + regex : "\\b(new)(\\s+)(\\w+)" + }, { + token : ["support.class", "keyword.operator"], + regex : "\\b(\\w+)(::)" }, { token : "constant.language", // constants regex : "\\b(?:A(?:B(?:DAY_(?:1|2|3|4|5|6|7)|MON_(?:1(?:0|1|2|)|2|3|4|5|6|7|8|9))|LT_DIGITS|M_STR|" + @@ -982,7 +988,7 @@ var PhpLangHighlightRules = function() { next: "heredoc" }, { token : "keyword.operator", - regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)" + regex : "::|!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)" }, { token : "paren.lparen", regex : "[[({]" diff --git a/lib/ace/mode/ruby_highlight_rules.js b/lib/ace/mode/ruby_highlight_rules.js index 99841aaf..17b9ce36 100644 --- a/lib/ace/mode/ruby_highlight_rules.js +++ b/lib/ace/mode/ruby_highlight_rules.js @@ -134,7 +134,7 @@ var RubyHighlightRules = function() { regex : "#.*$" }, { token : "comment", // multi line comment - regex : "^=begin\\s", + regex : "^=begin(?:$|\\s.*$)", next : "comment" }, { token : "string.regexp", @@ -231,7 +231,7 @@ var RubyHighlightRules = function() { "comment" : [ { token : "comment", // closing comment - regex : "^=end\\s.*$", + regex : "^=end(?:$|\\s.*$)", next : "start" }, { token : "comment", // comment spanning whole line diff --git a/lib/ace/mouse/dragdrop.js b/lib/ace/mouse/dragdrop.js index b5c5b167..3d279a98 100644 --- a/lib/ace/mouse/dragdrop.js +++ b/lib/ace/mouse/dragdrop.js @@ -3,7 +3,7 @@ * * Copyright (c) 2010, Ajax.org B.V. * All rights reserved. - * + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright @@ -14,7 +14,7 @@ * * Neither the name of Ajax.org B.V. nor the * names of its contributors may be used to endorse or promote products * derived from this software without specific prior written permission. - * + * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE @@ -36,7 +36,7 @@ var event = require("../lib/event"); var DragdropHandler = function(mouseHandler) { var editor = mouseHandler.editor; var dragSelectionMarker, x, y; - var timerId, range, isBackwards; + var timerId, range; var dragCursor, counter = 0; var mouseTarget = editor.container; @@ -44,18 +44,11 @@ var DragdropHandler = function(mouseHandler) { if (editor.getReadOnly()) return; var types = e.dataTransfer.types; - if (types && Array.prototype.indexOf.call(types, 'Files') !== -1) + if (types && Array.prototype.indexOf.call(types, "text/plain") === -1) return; + if (!dragSelectionMarker) + addDragMarker(); counter++; - if (!dragSelectionMarker) { - range = editor.getSelectionRange(); - isBackwards = editor.selection.isBackwards(); - var style = editor.getSelectionStyle(); - dragSelectionMarker = editor.session.addMarker(range, "ace_selection", style); - editor.clearSelection(); - clearInterval(timerId); - timerId = setInterval(onDragInterval, 20); - } return event.preventDefault(e); }); @@ -63,50 +56,66 @@ var DragdropHandler = function(mouseHandler) { if (editor.getReadOnly()) return; var types = e.dataTransfer.types; - if (types && Array.prototype.indexOf.call(types, 'Files') !== -1) + if (types && Array.prototype.indexOf.call(types, "text/plain") === -1) return; + if (onMouseMoveTimer !== null) + onMouseMoveTimer = null; x = e.clientX; y = e.clientY; return event.preventDefault(e); }); - + var onDragInterval = function() { dragCursor = editor.renderer.screenToTextCoordinates(x, y); editor.moveCursorToPosition(dragCursor); editor.renderer.scrollCursorIntoView(); }; - - event.addListener(mouseTarget, "dragleave", function(e) { - if (editor.getReadOnly()) - return; - var types = e.dataTransfer.types; - if (types && Array.prototype.indexOf.call(types, 'Files') !== -1) - return; - counter--; - if (counter > 0) - return; - clearInterval(timerId); - editor.session.removeMarker(dragSelectionMarker); - dragSelectionMarker = null; - editor.selection.setSelectionRange(range, isBackwards); - return event.preventDefault(e); - }); - - event.addListener(mouseTarget, "drop", function(e) { - if (editor.getReadOnly()) - return; - counter = 0; - clearInterval(timerId); - editor.session.removeMarker(dragSelectionMarker); - dragSelectionMarker = null; + event.addListener(mouseTarget, "dragleave", function(e) { + counter--; + if (counter <= 0 && dragSelectionMarker) { + clearDragMarker(); + return event.preventDefault(e); + } + }); + + event.addListener(mouseTarget, "drop", function(e) { + if (!dragSelectionMarker) + return; range.end = editor.session.insert(dragCursor, e.dataTransfer.getData('Text')); range.start = dragCursor; + clearDragMarker(); editor.focus(); - editor.selection.setSelectionRange(range); return event.preventDefault(e); }); + function addDragMarker() { + range = editor.selection.toOrientedRange(); + dragSelectionMarker = editor.session.addMarker(range, "ace_selection", editor.getSelectionStyle()); + editor.clearSelection(); + clearInterval(timerId); + timerId = setInterval(onDragInterval, 20); + counter = 0; + event.addListener(document, "mousemove", onMouseMove); + } + function clearDragMarker() { + clearInterval(timerId); + editor.session.removeMarker(dragSelectionMarker); + dragSelectionMarker = null; + editor.selection.fromOrientedRange(range); + counter = 0; + event.removeListener(document, "mousemove", onMouseMove); + } + // sometimes other code on the page can stop dragleave event leaving editor stuck in the drag state + var onMouseMoveTimer = null; + function onMouseMove() { + if (onMouseMoveTimer == null) { + onMouseMoveTimer = setTimeout(function() { + if (onMouseMoveTimer != null && dragSelectionMarker) + clearDragMarker(); + }, 20); + } + } }; exports.DragdropHandler = DragdropHandler; diff --git a/tool/tmlanguage.js b/tool/tmlanguage.js index 0c2e4ef7..d6e5fd03 100644 --- a/tool/tmlanguage.js +++ b/tool/tmlanguage.js @@ -1,4 +1,4 @@ -var fs = require("fs"); +var fs = require("fs"); var util = require("util"); var lib = require("./lib"); var parseLanguage = lib.parsePlist; @@ -29,7 +29,7 @@ function processRepository(r) { var stateObj = [processPattern(r[key])]; else if (p.patterns && !p.repository) var stateObj = processPatterns(p.patterns); - else + else var stateObj = [processPattern(r[key])]; if (stateObj) @@ -46,12 +46,12 @@ function processPattern(p) { } else if (p.begin && p.end) { var rule = simpleRule(p.begin, p.name, p.beginCaptures || p.captures) - + var next = processPatterns(p.patterns || []); var endRule = simpleRule(p.end, p.name, p.endCaptures || p.captures); endRule.next = "pop"; next.push(endRule); - + if (p.name || p.contentName) next.push({defaultToken: p.name || p.contentName}); @@ -63,7 +63,7 @@ function processPattern(p) { else if (p.include) { var rule = {include: p.include}; } - + if (p.comment) rule.comment = (rule.comment || "") + p.comment; @@ -74,7 +74,8 @@ function processPattern(p) { function simpleRule(regex, name, captures) { name = name || "text"; var rule = {}; - + + var origRegex = regex regex = transformRegExp(regex, rule); if (captures) { var tokenArray = []; @@ -91,9 +92,10 @@ function simpleRule(regex, name, captures) { rule.todo = "fix grouping"; } } - + try {new RegExp(regex);} catch(e) { rule.TODO = "FIXME: regexp doesn't have js equivalent"; + rule.originalRegex = origRegex } rule.token = name; rule.regex = regex; @@ -111,26 +113,29 @@ function removeXFlag(str) { if (s[0] == "\\") return /[#\s]/.test(s[1]) ? s[1] : s; return ""; - }); + }).substr(4); } return str; } function transformRegExp(str, rule) { str = removeXFlag(str); + //str = str.replace(/\\n\$|\$\\n/g, '$'); str = str.replace(/\\n(?!\?).?/g, '$'); // replace newlines by $ except if its postfixed by ? - if (/\(\?[i]\:/g.test(str)) { + if (/\(\?[i]\:|\(?\w*i\w*\)/g.test(str)) { str = str.replace(/\(\?[ims\-]\:/g, "(?:"); // checkForInvariantRegex + str = str.replace(/\(\?[imsx\-]\)/g, ""); rule && (rule.caseInsensitive = true); } + str = str.replace(/(\\[xu]){([a-fA-F\d]+)}/g, '$1$2'); return str; } -// +// function extractPatterns(tmRules) { var patterns = processRules(tmRules); return lib.restoreJSONComments(lib.formatJSON(patterns, " ")); - + } @@ -140,21 +145,22 @@ var modeTemplate = fs.readFileSync(__dirname + "/mode.tmpl.js", "utf8"); var modeHighlightTemplate = fs.readFileSync(__dirname + "/mode_highlight_rules.tmpl.js", "utf8"); function convertLanguageFile(name) { - var tmLanguage = fs.readFileSync(process.cwd() + "/" + name, "utf8"); + var path = /^(\/|\w:)/.test(name) ? name : process.cwd() + "/" + name + var tmLanguage = fs.readFileSync(path, "utf8"); parseLanguage(tmLanguage, function(language) { var languageHighlightFilename = language.name.replace(/[-_]/g, "").toLowerCase(); var languageNameSanitized = language.name.replace(/-/g, ""); - + var languageHighlightFile = __dirname + "/../lib/ace/mode/" + languageHighlightFilename + "_highlight_rules.js"; var languageModeFile = __dirname + "/../lib/ace/mode/" + languageHighlightFilename + ".js"; - + console.log("Converting " + name + " to " + languageHighlightFile); - + if (devMode) { console.log(util.inspect(language.patterns, false, 4)); console.log(util.inspect(language.repository, false, 4)); } - + var languageMode = lib.fillTemplate(modeTemplate, { language: languageNameSanitized, languageHighlightFilename: languageHighlightFilename