This commit is contained in:
nightwing 2013-03-12 13:49:14 +04:00
commit 943e690bf6
5 changed files with 148 additions and 121 deletions

View file

@ -3,7 +3,7 @@
* *
* Copyright (c) 2010, Ajax.org B.V. * Copyright (c) 2010, Ajax.org B.V.
* All rights reserved. * All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met: * modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright * * Redistributions of source code must retain the above copyright
@ -14,7 +14,7 @@
* * Neither the name of Ajax.org B.V. nor the * * Neither the name of Ajax.org B.V. nor the
* names of its contributors may be used to endorse or promote products * names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission. * derived from this software without specific prior written permission.
* *
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * 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 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
@ -35,7 +35,7 @@ var oop = require("./lib/oop");
var EventEmitter = require("./lib/event_emitter").EventEmitter; var EventEmitter = require("./lib/event_emitter").EventEmitter;
/** /**
* *
* Defines the floating pointer in the document. Whenever text is inserted or deleted before the cursor, the position of the cursor is updated. * Defines the floating pointer in the document. Whenever text is inserted or deleted before the cursor, the position of the cursor is updated.
* *
* @class Anchor * @class Anchor
@ -53,7 +53,7 @@ var EventEmitter = require("./lib/event_emitter").EventEmitter;
var Anchor = exports.Anchor = function(doc, row, column) { var Anchor = exports.Anchor = function(doc, row, column) {
this.document = doc; this.document = doc;
if (typeof column == "undefined") if (typeof column == "undefined")
this.setPosition(row.row, row.column); this.setPosition(row.row, row.column);
else else
@ -66,7 +66,7 @@ var Anchor = exports.Anchor = function(doc, row, column) {
(function() { (function() {
oop.implement(this, EventEmitter); oop.implement(this, EventEmitter);
/** /**
* Returns an object identifying the `row` and `column` position of the current anchor. * Returns an object identifying the `row` and `column` position of the current anchor.
* @returns {Object} * @returns {Object}
@ -75,28 +75,28 @@ var Anchor = exports.Anchor = function(doc, row, column) {
this.getPosition = function() { this.getPosition = function() {
return this.$clipPositionToDocument(this.row, this.column); return this.$clipPositionToDocument(this.row, this.column);
}; };
/** /**
* *
* Returns the current document. * Returns the current document.
* @returns {Document} * @returns {Document}
**/ **/
this.getDocument = function() { this.getDocument = function() {
return this.document; return this.document;
}; };
/** /**
* Fires whenever the anchor position changes. * Fires whenever the anchor position changes.
* *
* Both of these objects have a `row` and `column` property corresponding to the position. * Both of these objects have a `row` and `column` property corresponding to the position.
* *
* Events that can trigger this function include [[Anchor.setPosition `setPosition()`]]. * Events that can trigger this function include [[Anchor.setPosition `setPosition()`]].
* *
* @event change * @event change
* @param {Object} e An object containing information about the anchor position. It has two properties: * @param {Object} e An object containing information about the anchor position. It has two properties:
* - `old`: An object describing the old Anchor position * - `old`: An object describing the old Anchor position
* - `value`: An object describing the new Anchor position * - `value`: An object describing the new Anchor position
* *
* *
**/ **/
@ -104,60 +104,57 @@ var Anchor = exports.Anchor = function(doc, row, column) {
this.onChange = function(e) { this.onChange = function(e) {
var delta = e.data; var delta = e.data;
var range = delta.range; var range = delta.range;
if (range.start.row == range.end.row && range.start.row != this.row) if (range.start.row == range.end.row && range.start.row != this.row)
return; return;
if (range.start.row > this.row) if (range.start.row > this.row)
return; return;
if (range.start.row == this.row && range.start.column > this.column) if (range.start.row == this.row && range.start.column > this.column)
return; return;
var row = this.row; var row = this.row;
var column = this.column; var column = this.column;
var start = range.start;
var end = range.end;
if (delta.action === "insertText") { if (delta.action === "insertText") {
if (range.start.row === row && range.start.column <= column) { if (start.row === row && start.column <= column) {
if (range.start.row === range.end.row) { if (start.row === end.row) {
column += range.end.column - range.start.column; column += end.column - start.column;
} else {
column -= start.column;
row += end.row - start.row;
} }
else { } else if (start.row !== end.row && start.row < row) {
column -= range.start.column; row += end.row - start.row;
row += range.end.row - range.start.row;
}
}
else if (range.start.row !== range.end.row && range.start.row < row) {
row += range.end.row - range.start.row;
} }
} else if (delta.action === "insertLines") { } else if (delta.action === "insertLines") {
if (range.start.row <= row) { if (start.row <= row) {
row += range.end.row - range.start.row; row += end.row - start.row;
} }
} } else if (delta.action === "removeText") {
else if (delta.action == "removeText") { if (start.row === row && start.column < column) {
if (range.start.row == row && range.start.column < column) { if (end.column >= column)
if (range.end.column >= column) column = start.column;
column = range.start.column;
else else
column = Math.max(0, column - (range.end.column - range.start.column)); column = Math.max(0, column - (end.column - start.column));
} else if (range.start.row !== range.end.row && range.start.row < row) { } else if (start.row !== end.row && start.row < row) {
if (range.end.row == row) { if (end.row === row)
column = Math.max(0, column - range.end.column) + range.start.column; column = Math.max(0, column - end.column) + start.column;
} row -= (end.row - start.row);
row -= (range.end.row - range.start.row); } else if (end.row === row) {
} row -= end.row - start.row;
else if (range.end.row == row) { column = Math.max(0, column - end.column) + start.column;
row -= range.end.row - range.start.row;
column = Math.max(0, column - range.end.column) + range.start.column;
} }
} else if (delta.action == "removeLines") { } else if (delta.action == "removeLines") {
if (range.start.row <= row) { if (start.row <= row) {
if (range.end.row <= row) if (end.row <= row)
row -= range.end.row - range.start.row; row -= end.row - start.row;
else { else {
row = range.start.row; row = start.row;
column = 0; column = 0;
} }
} }
@ -166,13 +163,13 @@ var Anchor = exports.Anchor = function(doc, row, column) {
this.setPosition(row, column, true); this.setPosition(row, column, true);
}; };
/** /**
* Sets the anchor position to the specified row and column. If `noClip` is `true`, the position is not clipped. * Sets the anchor position to the specified row and column. If `noClip` is `true`, the position is not clipped.
* @param {Number} row The row index to move the anchor to * @param {Number} row The row index to move the anchor to
* @param {Number} column The column index to move the anchor to * @param {Number} column The column index to move the anchor to
* @param {Boolean} noClip Identifies if you want the position to be clipped * @param {Boolean} noClip Identifies if you want the position to be clipped
* *
* *
* *
**/ **/
@ -183,19 +180,18 @@ var Anchor = exports.Anchor = function(doc, row, column) {
row: row, row: row,
column: column column: column
}; };
} } else {
else {
pos = this.$clipPositionToDocument(row, column); pos = this.$clipPositionToDocument(row, column);
} }
if (this.row == pos.row && this.column == pos.column) if (this.row == pos.row && this.column == pos.column)
return; return;
var old = { var old = {
row: this.row, row: this.row,
column: this.column column: this.column
}; };
this.row = pos.row; this.row = pos.row;
this.column = pos.column; this.column = pos.column;
this._emit("change", { this._emit("change", {
@ -203,7 +199,7 @@ var Anchor = exports.Anchor = function(doc, row, column) {
value: pos value: pos
}); });
}; };
/** /**
* When called, the `'change'` event listener is removed. * When called, the `'change'` event listener is removed.
* *
@ -212,18 +208,16 @@ var Anchor = exports.Anchor = function(doc, row, column) {
this.detach = function() { this.detach = function() {
this.document.removeEventListener("change", this.$onChange); this.document.removeEventListener("change", this.$onChange);
}; };
/** /**
* Clips the anchor position to the specified row and column. * Clips the anchor position to the specified row and column.
* @param {Number} row The row index to clip the anchor to * @param {Number} row The row index to clip the anchor to
* @param {Number} column The column index to clip the anchor to * @param {Number} column The column index to clip the anchor to
* *
*
*
**/ **/
this.$clipPositionToDocument = function(row, column) { this.$clipPositionToDocument = function(row, column) {
var pos = {}; var pos = {};
if (row >= this.document.getLength()) { if (row >= this.document.getLength()) {
pos.row = Math.max(0, this.document.getLength() - 1); pos.row = Math.max(0, this.document.getLength() - 1);
pos.column = this.document.getLine(pos.row).length; pos.column = this.document.getLine(pos.row).length;
@ -236,13 +230,13 @@ var Anchor = exports.Anchor = function(doc, row, column) {
pos.row = row; pos.row = row;
pos.column = Math.min(this.document.getLine(pos.row).length, Math.max(0, column)); pos.column = Math.min(this.document.getLine(pos.row).length, Math.max(0, column));
} }
if (column < 0) if (column < 0)
pos.column = 0; pos.column = 0;
return pos; return pos;
}; };
}).call(Anchor.prototype); }).call(Anchor.prototype);
}); });

View file

@ -2241,7 +2241,8 @@ config.defineOptions(Editor.prototype, "editor", {
useWorker: "session", useWorker: "session",
useSoftTabs: "session", useSoftTabs: "session",
tabSize: "session", tabSize: "session",
wrap: "session" wrap: "session",
foldStyle: "session"
}); });
exports.Editor = Editor; exports.Editor = Editor;

View file

@ -36,7 +36,8 @@ var HashHandler = require("./keyboard/hash_handler").HashHandler;
var Tokenizer = require("./tokenizer").Tokenizer; var Tokenizer = require("./tokenizer").Tokenizer;
var SnippetManager = function() { var SnippetManager = function() {
this.snippets = []; this.snippetMap = {};
this.snippetNameMap = {};
}; };
(function() { (function() {
@ -52,10 +53,17 @@ var SnippetManager = function() {
} }
SnippetManager.$tokenizer = new Tokenizer({ SnippetManager.$tokenizer = new Tokenizer({
start: [ start: [
{regex: /\\[$}`\\]/, token: function(val, state, stack) { {regex: /\\./, token: function(val, state, stack) {
if (val[1] == "}" && !stack.length) if (stack.escapes == null)
return [val]; stack.escapes = "`$\\";
return [val[1]]; var ch = val[1];
if (
stack.escapes.indexOf(ch) == -1 ||
(ch == "}" && stack.length)
) {
val = ch;
}
return [val];
}}, }},
{regex: /}/, token: function(val, state, stack) { {regex: /}/, token: function(val, state, stack) {
return [stack.length ? stack.shift() : val]; return [stack.length ? stack.shift() : val];
@ -85,14 +93,12 @@ var SnippetManager = function() {
stack[0].code = val.splice(1, -1); stack[0].code = val.splice(1, -1);
return ""; return "";
}, next: "start"}, }, next: "start"},
{regex: ":[+-?]", token: "", next: "start"},
{regex: ":|", token: "", next: "start"} {regex: ":|", token: "", next: "start"}
], ],
formatString: [ formatString: [
{regex: /\\[ulULEnt/]/, token: "escape"}, {regex: /\\[ulULEnt/]/, token: "escape"},
{include: "$"} {include: "$"}
],
formatStringVar: [
] ]
}); });
SnippetManager.prototype.getTokenizer = function() { SnippetManager.prototype.getTokenizer = function() {
@ -144,7 +150,7 @@ var SnippetManager = function() {
// returns string formatted according to http://manual.macromates.com/en/regular_expressions#replacement_string_syntax_format_strings // returns string formatted according to http://manual.macromates.com/en/regular_expressions#replacement_string_syntax_format_strings
this.tmStrFormat = function(str, regex, fmt, flags) { this.tmStrFormat = function(str, regex, fmt, flags) {
var re = new RegExp(regex, flags.replace(/[^gi]/, "")); var re = new RegExp(regex, flags.replace(/[^gi]/, ""));
var fmtTokens = this.getTokenizer().getLineTokens(fmt, "formatString"); var fmtTokens = this.getTokenizer().getLineTokens(fmt, "formatString");
return str.replace(re, function() { return str.replace(re, function() {
@ -320,35 +326,54 @@ var SnippetManager = function() {
}; };
this.snippetMap = {}; this.snippetMap = {};
this.snippetNameMap = {};
this.register = function(snippets, scope) { this.register = function(snippets, scope) {
var snippetMap = this.snippetMap; var snippetMap = this.snippetMap;
var snippetNameMap = this.snippetNameMap;
function wrapRegexp(src) {
if (src && !/^\^?\(.*\)\$?$|^\\b$/.test(src))
src = "(?:" + src + ")"
return src || "";
}
function guardedRegexp(re, guard, opening) {
re = wrapRegexp(re);
guard = wrapRegexp(guard);
if (opening) {
re = guard + re;
if (re && re[re.length - 1] != "$")
re = re + "$";
} else {
re = re + guard;
if (re && re[0] != "^")
re = "^" + re;
}
return new RegExp(re);
}
function addSnippet(s) { function addSnippet(s) {
if (!s.scope) if (!s.scope)
s.scope = scope || "_"; s.scope = scope || "_";
if (!snippetMap[s.scope]) scope = s.scope
snippetMap[s.scope] = []; if (!snippetMap[scope]) {
snippetMap[s.scope].push(s); snippetMap[scope] = [];
snippetNameMap[scope] = {};
}
snippetMap[scope].push(s);
if (s.name)
snippetNameMap[scope][s.name] = s;
if (s.tabTrigger) { if (s.tabTrigger && !s.trigger) {
if (/^\w/.test(s.tabTrigger)) if (!s.guard && /^\w/.test(s.tabTrigger))
s.guard = "\\b"; s.guard = "\\\\b";
s.trigger = lang.escapeRegExp(s.tabTrigger); s.trigger = lang.escapeRegExp(s.tabTrigger);
} }
s.startRe = (s.guard || "") + (s.trigger || ""); s.startRe = guardedRegexp(s.trigger, s.guard, true);
if (s.startRe && s.startRe[s.startRe - 1] != "$") s.triggerRe = new RegExp(s.trigger, "", true);
s.startRe += "$";
if (s.startRe) s.endRe = guardedRegexp(s.endTrigger, s.endGuard, true);
s.startRe = new RegExp(s.startRe); s.endTriggerRe = new RegExp(s.endTrigger, "", true);
s.endRe = (s.endGuard || "") + (s.endTrigger || "");
if (s.endRe && s.endRe[0] != "^")
s.endRe = "^" + s.endRe;
if (s.endRe)
s.endRe = new RegExp(s.endRe);
if (s.trigger)
s.triggerRe = new RegExp(s.trigger + "$");
if (s.endTrigger)
s.endTriggerRe = new RegExp("^" + s.endTrigger);
}; };
if (snippets.content) if (snippets.content)
@ -379,10 +404,9 @@ var SnippetManager = function() {
snippet.endTrigger = val[3]; snippet.endTrigger = val[3];
snippet.endGuard = val[4]; snippet.endGuard = val[4];
} else if (key == "snippet") { } else if (key == "snippet") {
val = val.split(/^(\S*)(?:\s(.*))?$/); snippet.tabTrigger = val.split(/^(\S*)(?:\s(.*))?$/)[1];
snippet.tabTrigger = val[1];
if (!snippet.name) if (!snippet.name)
snippet.name = val[2]; snippet.name = val;
} else { } else {
snippet[key] = val; snippet[key] = val;
} }
@ -432,7 +456,8 @@ var TabstopManager = function(editor) {
this.onChange = function(e) { this.onChange = function(e) {
var changeRange = e.data.range; var changeRange = e.data.range;
if (e.data.action[0] == "i"){ var isInsert = e.data.action[0] == "i";
if (isInsert) {
var start = changeRange.start; var start = changeRange.start;
var end = changeRange.end; var end = changeRange.end;
} else { } else {
@ -446,14 +471,16 @@ var TabstopManager = function(editor) {
var colDiff = end.column - start.column; var colDiff = end.column - start.column;
var ranges = this.ranges; var ranges = this.ranges;
console.log(e.data)
for (var i = 0; i < ranges.length; i++) { for (var i = 0; i < ranges.length; i++) {
var r = ranges[i]; var r = ranges[i];
if (r.end.row < startRow) if (r.end.row < changeRange.start.row)
continue; continue;
var b=r.clone()
if (Range.comparePoints(changeRange.start, r.start) < 0 if (Range.comparePoints(changeRange.start, r.start) < 0
&& Range.comparePoints(changeRange.end, r.end) > 0) { && Range.comparePoints(changeRange.end, r.end) > 0) {
this.removeRange(r); this.removeRange(r);
console.log(1)
i--; i--;
continue; continue;
} }
@ -470,6 +497,9 @@ var TabstopManager = function(editor) {
if (r.end.row >= startRow) { if (r.end.row >= startRow) {
r.end.row += lineDif; r.end.row += lineDif;
} }
console.log(b+r+"")
if (Range.comparePoints(r.start, r.end) > 0)
this.removeRange(r);
} }
}; };
this.onChangeSelection = function() { this.onChangeSelection = function() {
@ -506,7 +536,7 @@ var TabstopManager = function(editor) {
this.addTabstopMarkers(ts); this.addTabstopMarkers(ts);
this.index = index; this.index = index;
ts = this.tabstops[this.index]; ts = this.tabstops[this.index];
if (!ts) if (!ts || !ts.length)
return; return;
this.selectedTabstop = ts; this.selectedTabstop = ts;

View file

@ -1,6 +1,6 @@
# Prototype # Prototype
snippet proto snippet proto
${1:class_name}.prototype.${2:method_name} = function(${3:first_argument}) { ${1:class_name}.prototype.${2:method_name} = function(${3irst_argument}) {
${4:// body...} ${4:// body...}
}; };
# Function # Function
@ -9,17 +9,17 @@ snippet fun
${3:// body...} ${3:// body...}
} }
# Anonymous Function # Anonymous Function
regex /\b(\()?/f//(\))?/ regex /(=)\s*|(:)\s*|(\()|\b/f/(\))?/
name f name f
function($1) { function${M1||M2||M3? ${1:functionName $: }}($2) {
${0:$TM_SELECTED_TEXT} ${0:$TM_SELECTED_TEXT}
}; }${M1?;}${M2?,}${M3?)}
# Immediate function # Immediate function
trigger \(?f\( trigger \(?f\(
endTrigger \)? endTrigger \)?
snippet f( snippet f(
(function(${1}) { (function(${1}) {
${3:/* code */} ${0:${TM_SELECTED_TEXT:/* code */}}
}(${1})); }(${1}));
# if # if
snippet if snippet if
@ -72,8 +72,9 @@ snippet do
} while (${1:/* condition */}); } while (${1:/* condition */});
# Object Method # Object Method
snippet :f snippet :f
regex /([,{[])|^\s*/:f/
${1:method_name}: function(${2:attribute}) { ${1:method_name}: function(${2:attribute}) {
${4} ${0}
}${3:,} }${3:,}
# setTimeout function # setTimeout function
snippet timeout snippet timeout
@ -105,6 +106,7 @@ snippet /**
* *
*/ */
snippet @par snippet @par
regex /^\s*\*\s*/@(para?m?)?/
@param {${1:type}} ${2:name} ${3:description} @param {${1:type}} ${2:name} ${3:description}
snippet @ret snippet @ret
@return {${1:type}} ${2:description} @return {${1:type}} ${2:description}
@ -176,14 +178,14 @@ snippet for-
snippet for ?in snippet for ?in
regex /^\s*/for (\w+\b)?( \d+)( \d+)?/ regex /^\s*/for\b\s*(\w+\b)?(\s*\d+\b)(\s*\d*)/
78789
regex /^\s*/for (\w+) in (\w+)/ regex /^\s*/for (\w+) in (\w+)/
${include:for $1=$M1,$2=$M2} ${include:for $1=$M1,$2=$M2}44
regex /^\s*/for (\w*) (\w+)(.l?e?n?[ght]{0,3})/ regex /^\s*/for\b( \w+\b)?( \w+\b)(\.l?e?n?[ght]{0,3})/
${include:for $1=$M1,$2=$M2} ${include:for $1=$M1,$2=$M2}44
regex /^\s*/for (\w+) in (\w+)/ regex /^\s*/for (\w+) in (\w+)/
${include:for $1=$M1,$2=$M2} ${include:for $1=$M1,$2=$M2}44
#modules #modules
@ -200,5 +202,5 @@ guard ^\s*
$0 $0
snippet Req snippet Req
guard ^\s* guard ^\s*
var ${1/.*\/(.)/\u$1/} = require("${1}").${1_0}; var ${1/.*\/(.)/\u$1/} = require("${1}").${1!0};
$0 $0

View file

@ -277,7 +277,7 @@ var Tokenizer = function(rules) {
tokens.push(token); tokens.push(token);
token = {type: type, value: value}; token = {type: type, value: value};
} }
} else { } else if (type) {
if (token.type) if (token.type)
tokens.push(token); tokens.push(token);
token = {type: null, value: ""}; token = {type: null, value: ""};