Merge remote-tracking branch 'upstream/master'

This commit is contained in:
Smirnov O. A 2015-01-14 11:06:22 +03:00
commit 0a7d192b3d
43 changed files with 5074 additions and 889 deletions

View file

@ -169,13 +169,44 @@ function loadDoc(name, callback) {
}); });
} }
function saveDoc(name, callback) {
var doc = fileCache[name] || name;
if (!doc || !doc.session)
return callback("Unknown document: " + name);
var path = doc.path;
var parts = path.split("/");
if (parts[0] == "docs")
path = "demo/kitchen-sink/" + path;
else if (parts[0] == "ace")
path = "lib/" + path;
upload(path, doc.session.getValue(), callback);
}
function upload(url, data, callback) {
url = net.qualifyURL(url);
if (!/https?:/.test(url))
return callback(new Error("Unsupported url scheme"));
var xhr = new XMLHttpRequest();
xhr.open("PUT", url, true);
xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
callback(!/^2../.test(xhr.status));
}
};
xhr.send(data);
};
module.exports = { module.exports = {
fileCache: fileCache, fileCache: fileCache,
docs: sort(prepareDocList(docs)), docs: sort(prepareDocList(docs)),
ownSource: prepareDocList(ownSource), ownSource: prepareDocList(ownSource),
hugeDocs: prepareDocList(hugeDocs), hugeDocs: prepareDocList(hugeDocs),
initDoc: initDoc, initDoc: initDoc,
loadDoc: loadDoc loadDoc: loadDoc,
saveDoc: saveDoc,
}; };
module.exports.all = { module.exports.all = {
"Mode Examples": module.exports.docs, "Mode Examples": module.exports.docs,

View file

@ -0,0 +1,171 @@
%abc-2.1
H:This file contains some example English tunes
% note that the comments (like this one) are to highlight usages
% and would not normally be included in such detail
O:England % the origin of all tunes is England
X:1 % tune no 1
T:Dusty Miller, The % title
T:Binny's Jig % an alternative title
C:Trad. % traditional
R:DH % double hornpipe
M:3/4 % meter
K:G % key
B>cd BAG|FA Ac BA|B>cd BAG|DG GB AG:|
Bdd gfg|aA Ac BA|Bdd gfa|gG GB AG:|
BG G/2G/2G BG|FA Ac BA|BG G/2G/2G BG|DG GB AG:|
W:Hey, the dusty miller, and his dusty coat;
W:He will win a shilling, or he spend a groat.
W:Dusty was the coat, dusty was the colour;
W:Dusty was the kiss, that I got frae the miller.
X:2
T:Old Sir Simon the King
C:Trad.
S:Offord MSS % from Offord manuscript
N:see also Playford % reference note
M:9/8
R:SJ % slip jig
N:originally in C % transcription note
K:G
D|GFG GAG G2D|GFG GAG F2D|EFE EFE EFG|A2G F2E D2:|
D|GAG GAB d2D|GAG GAB c2D|[1 EFE EFE EFG|[A2G] F2E D2:|\ % no line-break in score
M:12/8 % change of meter
[2 E2E EFE E2E EFG|\ % no line-break in score
M:9/8 % change of meter
A2G F2E D2|]
X:3
T:William and Nancy
T:New Mown Hay
T:Legacy, The
C:Trad.
O:England; Gloucs; Bledington % place of origin
B:Sussex Tune Book % can be found in these books
B:Mally's Cotswold Morris vol.1 2
D:Morris On % can be heard on this record
P:(AB)2(AC)2A % play the parts in this order
M:6/8
K:G
[P:A] D|"G"G2G GBd|"C"e2e "G"dBG|"D7"A2d "G"BAG|"C"E2"D7"F "G"G2:|
[P:B] d|"G"e2d B2d|"C"gfe "G"d2d| "G"e2d B2d|"C"gfe "D7"d2c|
"G"B2B Bcd|"C"e2e "G"dBG|"D7"A2d "G"BAG|"C"E2"D7"F "G"G2:|
% changes of meter, using inline fields
[T:Slows][M:4/4][L:1/4][P:C]"G"d2|"C"e2 "G"d2|B2 d2|"Em"gf "A7"e2|"D7"d2 "G"d2|\
"C"e2 "G"d2|[M:3/8][L:1/8] "G"B2 d |[M:6/8] "C"gfe "D7"d2c|
"G"B2B Bcd|"C"e2e "G"dBG|"D7"A2d "G"BAG|"C"E2"D7"F "G"G2:|
X:4
T:South Downs Jig
R:jig
S:Robert Harbron
M:6/8
L:1/8
K:G
|: d | dcA G3 | EFG AFE | DEF GAB | cde d2d |
dcA G3 | EFG AFE | DEF GAB | cAF G2 :|
B | Bcd e2c | d2B c2A | Bcd e2c | [M:9/8]d2B c2B A3 |
[M:6/8]DGF E3 | cBA FED | DEF GAB |1 cAF G2 :|2 cAF G3 |]
X:5
T:Atholl Brose
% in this example, which reproduces Highland Bagpipe gracing,
% the large number of grace notes mean that it is more convenient to be specific about
% score line-breaks (using the $ symbol), rather than using code line breaks to indicate them
I:linebreak $
K:D
{gcd}c<{e}A {gAGAG}A2 {gef}e>A {gAGAG}Ad|
{gcd}c<{e}A {gAGAG}A>e {ag}a>f {gef}e>d|
{gcd}c<{e}A {gAGAG}A2 {gef}e>A {gAGAG}Ad|
{g}c/d/e {g}G>{d}B {gf}gG {dc}d>B:|$
{g}c<e {gf}g>e {ag}a>e {gf}g>e|
{g}c<e {gf}g>e {ag}a2 {GdG}a>d|
{g}c<e {gf}g>e {ag}a>e {gf}g>f|
{gef}e>d {gf}g>d {gBd}B<{e}G {dc}d>B|
{g}c<e {gf}g>e {ag}a>e {gf}g>e|
{g}c<e {gf}g>e {ag}a2 {GdG}ad|
{g}c<{GdG}e {gf}ga {f}g>e {g}f>d|
{g}e/f/g {Gdc}d>c {gBd}B<{e}G {dc}d2|]
X:6
T:Untitled Reel
C:Trad.
K:D
eg|a2ab ageg|agbg agef|g2g2 fgag|f2d2 d2:|\
ed|cecA B2ed|cAcA E2ed|cecA B2ed|c2A2 A2:|
K:G
AB|cdec BcdB|ABAF GFE2|cdec BcdB|c2A2 A2:|
X:7
T:Kitchen Girl
C:Trad.
K:D
[c4a4] [B4g4]|efed c2cd|e2f2 gaba|g2e2 e2fg|
a4 g4|efed cdef|g2d2 efed|c2A2 A4:|
K:G
ABcA BAGB|ABAG EDEG|A2AB c2d2|e3f edcB|ABcA BAGB|
ABAG EGAB|cBAc BAG2|A4 A4:|
%abc-2.1
%%pagewidth 21cm
%%pageheight 29.7cm
%%topspace 0.5cm
%%topmargin 1cm
%%botmargin 0cm
%%leftmargin 1cm
%%rightmargin 1cm
%%titlespace 0cm
%%titlefont Times-Bold 32
%%subtitlefont Times-Bold 24
%%composerfont Times 16
%%vocalfont Times-Roman 14
%%staffsep 60pt
%%sysstaffsep 20pt
%%musicspace 1cm
%%vocalspace 5pt
%%measurenb 0
%%barsperstaff 5
%%scale 0.7
X: 1
T: Canzonetta a tre voci
C: Claudio Monteverdi (1567-1643)
M: C
L: 1/4
Q: "Andante mosso" 1/4 = 110
%%score [1 2 3]
V: 1 clef=treble name="Soprano"sname="A"
V: 2 clef=treble name="Alto" sname="T"
V: 3 clef=bass middle=d name="Tenor" sname="B"
%%MIDI program 1 75 % recorder
%%MIDI program 2 75
%%MIDI program 3 75
K: Eb
% 1 - 4
[V: 1] |:z4 |z4 |f2ec |_ddcc |
w: Son que-sti~i cre-spi cri-ni~e
w: Que-sti son gli~oc-chi che mi-
[V: 2] |:c2BG|AAGc|(F/G/A/B/)c=A|B2AA |
w: Son que-sti~i cre-spi cri-ni~e que - - - - sto~il vi-so e
w: Que-sti son~gli oc-chi che mi-ran - - - - do fi-so mi-
[V: 3] |:z4 |f2ec|_ddcf |(B/c/_d/e/)ff|
w: Son que-sti~i cre-spi cri-ni~e que - - - - sto~il
w: Que-sti son~gli oc-chi che mi-ran - - - - do
% 5 - 9
[V: 1] cAB2 |cAAA |c3B|G2!fermata!Gz ::e4|
w: que-sto~il vi-so ond' io ri-man-go~uc-ci-so. Deh,
w: ran-do fi-so, tut-to re-stai con-qui-so.
[V: 2] AAG2 |AFFF |A3F|=E2!fermata!Ez::c4|
w: que-sto~il vi-so ond' io ri-man-go~uc-ci-so. Deh,
w: ran-do fi-so tut-to re-stai con-qui-so.
[V: 3] (ag/f/e2)|A_ddd|A3B|c2!fermata!cz ::A4|
w: vi - - - so ond' io ti-man-go~uc-ci-so. Deh,
w: fi - - - so tut-to re-stai con-qui-so.
% 10 - 15
[V: 1] f_dec |B2c2|zAGF |\
w: dim-me-lo ben mi-o, che que-sto\
=EFG2 |1F2z2:|2F8|] % more notes
w: sol de-si-o_. % more lyrics
[V: 2] ABGA |G2AA|GF=EF |(GF3/2=E//D//E)|1F2z2:|2F8|]
w: dim-me-lo ben mi-o, che que-sto sol de-si - - - - o_.
[V: 3] _dBc>d|e2AF|=EFc_d|c4 |1F2z2:|2F8|]
w: dim-me-lo ben mi-o, che que-sto sol de-si-o_.

View file

@ -20,7 +20,7 @@ class Range
end end
end end
{:id => 34, :key => "value"} {:id => ?", :key => "value"}
herDocs = [<<'FOO', <<BAR, <<-BAZ, <<-`EXEC`] #comment herDocs = [<<'FOO', <<BAR, <<-BAZ, <<-`EXEC`] #comment

View file

@ -53,16 +53,16 @@ require("ace/commands/default_commands").commands.push({
return; return;
} }
var rowCount = 10; var rowCount = 10;
var w = { var w = {
row: row, row: row,
// rowCount: rowCount, // rowCount: rowCount,
fixedWidth: true, fixedWidth: true,
el: dom.createElement("div"), el: dom.createElement("div"),
editor: editor editor: inlineEditor
}; };
var el = w.el; var el = w.el;
el.appendChild(inlineEditor.container); el.appendChild(inlineEditor.container);
if (!editor.session.widgetManager) { if (!editor.session.widgetManager) {
editor.session.widgetManager = new LineWidgets(editor.session); editor.session.widgetManager = new LineWidgets(editor.session);

View file

@ -196,8 +196,7 @@ console.log(addResult);
<p><span class="expand_arrow">&gt;</span> <a href="https://github.com/ajaxorg/ace/tree/master/lib/ace/theme" target="_blank">See all themes</a></p> <p><span class="expand_arrow">&gt;</span> <a href="https://github.com/ajaxorg/ace/tree/master/lib/ace/theme" target="_blank">See all themes</a></p>
<h2>Setting the Programming Language Mode</h2> <h2>Setting the Programming Language Mode</h2>
<p>By default, the editor supports plain text mode. All other language modes are available as separate modules, loaded on demand like this:</p> <p>By default, the editor supports plain text mode. All other language modes are available as separate modules, loaded on demand like this:</p>
<pre><code class="javascript">editor.getSession().setMode("ace/mode/javascript"); <pre><code class="javascript">editor.getSession().setMode("ace/mode/javascript");</code></pre>
</code></pre>
<!--h2>One Editor, Multiple Sessions</h2> <!--h2>One Editor, Multiple Sessions</h2>
<p>Ace keeps everything about the state of the editor (selection, scroll position, etc.) <p>Ace keeps everything about the state of the editor (selection, scroll position, etc.)
in <code class="javascript">editor.session</code>. This means you can grab the in <code class="javascript">editor.session</code>. This means you can grab the

View file

@ -40,9 +40,10 @@ var dom = require("./lib/dom");
var snippetManager = require("./snippets").snippetManager; var snippetManager = require("./snippets").snippetManager;
var Autocomplete = function() { var Autocomplete = function() {
this.autoInsert = true; this.autoInsert = false;
this.autoSelect = true; this.autoSelect = true;
this.exactMatch = false; this.exactMatch = false;
this.gatherCompletionsId = 0;
this.keyboardHandler = new HashHandler(); this.keyboardHandler = new HashHandler();
this.keyboardHandler.bindKeys(this.commands); this.keyboardHandler.bindKeys(this.commands);
@ -59,7 +60,6 @@ var Autocomplete = function() {
}; };
(function() { (function() {
this.gatherCompletionsId = 0;
this.$init = function() { this.$init = function() {
this.popup = new AcePopup(document.body || document.documentElement); this.popup = new AcePopup(document.body || document.documentElement);
@ -84,6 +84,8 @@ var Autocomplete = function() {
this.popup.setData(this.completions.filtered); this.popup.setData(this.completions.filtered);
editor.keyBinding.addKeyboardHandler(this.keyboardHandler);
var renderer = editor.renderer; var renderer = editor.renderer;
this.popup.setRow(this.autoSelect ? 0 : -1); this.popup.setRow(this.autoSelect ? 0 : -1);
if (!keepPopupPosition) { if (!keepPopupPosition) {
@ -115,10 +117,9 @@ var Autocomplete = function() {
this.changeTimer.cancel(); this.changeTimer.cancel();
this.hideDocTooltip(); this.hideDocTooltip();
if (this.popup && this.popup.isOpen) { this.gatherCompletionsId += 1;
this.gatherCompletionsId += 1; if (this.popup && this.popup.isOpen)
this.popup.hide(); this.popup.hide();
}
if (this.base) if (this.base)
this.base.detach(); this.base.detach();
@ -261,7 +262,6 @@ var Autocomplete = function() {
editor.completer = this; editor.completer = this;
} }
editor.keyBinding.addKeyboardHandler(this.keyboardHandler);
editor.on("changeSelection", this.changeListener); editor.on("changeSelection", this.changeListener);
editor.on("blur", this.blurListener); editor.on("blur", this.blurListener);
editor.on("mousedown", this.mousedownListener); editor.on("mousedown", this.mousedownListener);
@ -408,10 +408,10 @@ Autocomplete.startCommand = {
exec: function(editor) { exec: function(editor) {
if (!editor.completer) if (!editor.completer)
editor.completer = new Autocomplete(); editor.completer = new Autocomplete();
editor.completer.autoInsert = editor.completer.autoInsert = false;
editor.completer.autoSelect = true; editor.completer.autoSelect = true;
editor.completer.showPopup(editor); editor.completer.showPopup(editor);
// needed for firefox on mac // prevent ctrl-space opening context menu on firefox on mac
editor.completer.cancelContextMenu(); editor.completer.cancelContextMenu();
}, },
bindKey: "Ctrl-Space|Ctrl-Shift-Space|Alt-Space" bindKey: "Ctrl-Space|Ctrl-Shift-Space|Alt-Space"

View file

@ -893,17 +893,17 @@ var EditSession = function(text, mode) {
config.loadModule(["mode", path], function(m) { config.loadModule(["mode", path], function(m) {
if (this.$modeId !== path) if (this.$modeId !== path)
return cb && cb(); return cb && cb();
if (this.$modes[path] && !options) if (this.$modes[path] && !options) {
return this.$onChangeMode(this.$modes[path]); this.$onChangeMode(this.$modes[path]);
if (m && m.Mode) { } else if (m && m.Mode) {
m = new m.Mode(options); m = new m.Mode(options);
if (!options) { if (!options) {
this.$modes[path] = m; this.$modes[path] = m;
m.$id = path; m.$id = path;
} }
this.$onChangeMode(m); this.$onChangeMode(m);
cb && cb();
} }
cb && cb();
}.bind(this)); }.bind(this));
// set mode to text until loading is finished // set mode to text until loading is finished

View file

@ -545,9 +545,12 @@ var Editor = function(renderer, session) {
return; return;
} }
if (token.type.indexOf("tag-open") != -1) if (token.type.indexOf("tag-open") != -1) {
token = iterator.stepForward(); token = iterator.stepForward();
if (!token)
return;
}
var tag = token.value; var tag = token.value;
var depth = 0; var depth = 0;
var prevToken = iterator.stepBackward(); var prevToken = iterator.stepBackward();

View file

@ -140,7 +140,7 @@ var loadSnippetFile = function(id) {
function getCompletionPrefix(editor) { function getCompletionPrefix(editor) {
var pos = editor.getCursorPosition(); var pos = editor.getCursorPosition();
var line = editor.session.getLine(pos.row); var line = editor.session.getLine(pos.row);
var prefix = util.retrievePrecedingIdentifier(line, pos.column); var prefix;
// Try to find custom prefixes on the completers // Try to find custom prefixes on the completers
editor.completers.forEach(function(completer) { editor.completers.forEach(function(completer) {
if (completer.identifierRegexps) { if (completer.identifierRegexps) {
@ -150,7 +150,7 @@ function getCompletionPrefix(editor) {
}); });
} }
}); });
return prefix; return prefix || util.retrievePrecedingIdentifier(line, pos.column);
} }
var doLiveAutocomplete = function(e) { var doLiveAutocomplete = function(e) {
@ -158,8 +158,6 @@ var doLiveAutocomplete = function(e) {
var text = e.args || ""; var text = e.args || "";
var hasCompleter = editor.completer && editor.completer.activated; var hasCompleter = editor.completer && editor.completer.activated;
// We don't want to autocomplete with no prefix // We don't want to autocomplete with no prefix
if (e.command.name === "backspace") { if (e.command.name === "backspace") {
if (hasCompleter && !getCompletionPrefix(editor)) if (hasCompleter && !getCompletionPrefix(editor))
@ -174,7 +172,6 @@ var doLiveAutocomplete = function(e) {
editor.completer = new Autocomplete(); editor.completer = new Autocomplete();
} }
// Disable autoInsert // Disable autoInsert
editor.completer.autoSelect = false;
editor.completer.autoInsert = false; editor.completer.autoInsert = false;
editor.completer.showPopup(editor); editor.completer.showPopup(editor);
} }

View file

@ -43,6 +43,7 @@ Mode.prototype.supportsFile = function(filename) {
// todo firstlinematch // todo firstlinematch
var supportedModes = { var supportedModes = {
ABAP: ["abap"], ABAP: ["abap"],
ABC: ["abc"],
ActionScript:["as"], ActionScript:["as"],
ADA: ["ada|adb"], ADA: ["ada|adb"],
Apache_Conf: ["^htaccess|^htgroups|^htpasswd|^conf|htaccess|htgroups|htpasswd"], Apache_Conf: ["^htaccess|^htgroups|^htpasswd|^conf|htaccess|htgroups|htpasswd"],

View file

@ -102,6 +102,11 @@ var TextInput = function(parentNode, host) {
function resetSelection(isEmpty) { function resetSelection(isEmpty) {
if (inComposition) if (inComposition)
return; return;
// this prevents infinite recursion on safari 8
// see https://github.com/ajaxorg/ace/issues/2114
inComposition = true;
if (inputHandler) { if (inputHandler) {
selectionStart = 0; selectionStart = 0;
selectionEnd = isEmpty ? 0 : text.value.length - 1; selectionEnd = isEmpty ? 0 : text.value.length - 1;
@ -113,6 +118,8 @@ var TextInput = function(parentNode, host) {
try { try {
text.setSelectionRange(selectionStart, selectionEnd); text.setSelectionRange(selectionStart, selectionEnd);
} catch(e){} } catch(e){}
inComposition = false;
} }
function resetValue() { function resetValue() {

View file

@ -2118,11 +2118,9 @@ dom.importCssString(".normal-mode .ace_cursor{\
newHead = copyCursor(origHead); newHead = copyCursor(origHead);
} }
if (vim.visualMode) { if (vim.visualMode) {
if (!(vim.visualBlock && newHead.ch === Infinity)) {
if (!(vim.visualBlock && motion === "moveToEol")) {
newHead = clipCursorToContent(cm, newHead, vim.visualBlock); newHead = clipCursorToContent(cm, newHead, vim.visualBlock);
} }
if (newAnchor) { if (newAnchor) {
newAnchor = clipCursorToContent(cm, newAnchor, true); newAnchor = clipCursorToContent(cm, newAnchor, true);
} }

View file

@ -13,7 +13,7 @@
[1, +1, -1, 12_345, 0.000_1, [1, +1, -1, 12_345, 0.000_1,
_, 3_1, 1_2, 1_.0, 0._1]; _, 3_1, 1_2, 1_.0, 0._1];
{:id => 34, :key => "value"} {:id => ?", :key => "value", anotherKey: [x, y?]}
=begin =begin
=end =end

File diff suppressed because it is too large Load diff

View file

@ -139,7 +139,7 @@
["text"," "], ["text"," "],
["punctuation.separator.key-value","=>"], ["punctuation.separator.key-value","=>"],
["text"," "], ["text"," "],
["constant.numeric","34"], ["string.character","?\""],
["text",", "], ["text",", "],
["constant.other.symbol.ruby",":key"], ["constant.other.symbol.ruby",":key"],
["text"," "], ["text"," "],
@ -148,7 +148,15 @@
["string.start","\""], ["string.start","\""],
["string","value"], ["string","value"],
["string.end","\""], ["string.end","\""],
["paren.rparen","}"] ["text",", "],
["identifier","anotherKey"],
["text",": "],
["paren.lparen","["],
["identifier","x"],
["text",", "],
["identifier","y"],
["text","?"],
["paren.rparen","]}"]
],[ ],[
"start" "start"
],[ ],[

View file

@ -126,7 +126,7 @@ var AbapHighlightRules = function() {
{token : "string", regex : "`", next : "start"}, {token : "string", regex : "`", next : "start"},
{defaultToken : "string"} {defaultToken : "string"}
] ]
} };
}; };
oop.inherits(AbapHighlightRules, TextHighlightRules); oop.inherits(AbapHighlightRules, TextHighlightRules);

58
lib/ace/mode/abc.js Normal file
View file

@ -0,0 +1,58 @@
/* ***** BEGIN LICENSE BLOCK *****
* Distributed under the BSD license:
*
* Copyright (c) 2012, 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
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * 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
* DISCLAIMED. IN NO EVENT SHALL AJAX.ORG B.V. BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ***** END LICENSE BLOCK ***** */
/*
THIS FILE WAS AUTOGENERATED BY mode.tmpl.js
*/
define(function (require, exports, module) {
"use strict";
var oop = require("../lib/oop");
var TextMode = require("./text").Mode;
var ABCHighlightRules = require("./abc_highlight_rules").ABCHighlightRules;
// TODO: pick appropriate fold mode
var FoldMode = require("./folding/cstyle").FoldMode;
var Mode = function () {
this.HighlightRules = ABCHighlightRules;
this.foldingRules = new FoldMode();
};
oop.inherits(Mode, TextMode);
(function () {
// this.lineCommentStart = ""%.*"";
// this.blockComment = {start: ""/*"", end: ""*/""};
// Extra logic goes here.
this.$id = "ace/mode/abc"
}).call(Mode.prototype);
exports.Mode = Mode;
});

View file

@ -0,0 +1,114 @@
/* This file was partially autogenerated from https://github.com/jimhawkridge/SublimeABC
Modifications
- more classes to express the abc semantic
- added syntax highlighting for Zupfnoter conventions (https://github.com/bwl21/zupfnoter)
- separate note pitch and note duration - even if it looks the same
***********************************************************************************************/
define(function (require, exports, module) {
"use strict";
var oop = require("../lib/oop");
var TextHighlightRules = require("./text_highlight_rules").TextHighlightRules;
var ABCHighlightRules = function () {
// regexp must not have capturing parentheses. Use (?:) instead.
// regexps are ordered -> the first match is used
this.$rules = {
start: [
{
token: ['zupfnoter.information.comment.line.percentage', 'information.keyword', 'in formation.keyword.embedded'],
regex: '(%%%%)(hn\\.[a-z]*)(.*)',
comment: 'Instruction Comment'
},
{
token: ['information.comment.line.percentage', 'information.keyword.embedded'],
regex: '(%%)(.*)',
comment: 'Instruction Comment'
},
{
token: 'comment.line.percentage',
regex: '%.*',
comment: 'Comments'
},
{
token: 'barline.keyword.operator',
regex: '[\\[:]*[|:][|\\]:]*(?:\\[?[0-9]+)?|\\[[0-9]+',
comment: 'Bar lines'
},
{
token: ['information.keyword.embedded', 'information.argument.string.unquoted'],
regex: '(\\[[A-Za-z]:)([^\\]]*\\])',
comment: 'embedded Header lines'
},
{
token: ['information.keyword', 'information.argument.string.unquoted'],
regex: '^([A-Za-z]:)([^%\\\\]*)',
comment: 'Header lines'
},
{
token: ['text', 'entity.name.function', 'string.unquoted', 'text'],
regex: '(\\[)([A-Z]:)(.*?)(\\])',
comment: 'Inline fields'
},
{
token: ['accent.constant.language', 'pitch.constant.numeric', 'duration.constant.numeric'],
regex: '([\\^=_]*)([A-Ga-gz][,\']*)([0-9]*/*[><0-9]*)',
comment: 'Notes'
},
{
token: 'zupfnoter.jumptarget.string.quoted',
regex: '[\\"!]\\^\\:.*?[\\"!]',
comment: 'Zupfnoter jumptarget'
}, {
token: 'zupfnoter.goto.string.quoted',
regex: '[\\"!]\\^\\@.*?[\\"!]',
comment: 'Zupfnoter goto'
},
{
token: 'zupfnoter.annotation.string.quoted',
regex: '[\\"!]\\^\\!.*?[\\"!]',
comment: 'Zupfnoter annoation'
},
{
token: 'zupfnoter.annotationref.string.quoted',
regex: '[\\"!]\\^\\#.*?[\\"!]',
comment: 'Zupfnoter annotation reference'
},
{
token: 'chordname.string.quoted',
regex: '[\\"!]\\^.*?[\\"!]',
comment: 'abc chord'
},
{
token: 'string.quoted',
regex: '[\\"!].*?[\\"!]',
comment: 'abc annotation'
}
]
};
// this.embedRules(JsonHighlightRules, "json-")
this.normalizeRules();
};
ABCHighlightRules.metaData = {
fileTypes: ['abc'],
name: 'ABC',
scopeName: 'text.abcnotation'
};
oop.inherits(ABCHighlightRules, TextHighlightRules);
exports.ABCHighlightRules = ABCHighlightRules;
});

View file

@ -116,11 +116,11 @@ oop.inherits(Mode, TextMode);
var worker = new WorkerClient(["ace"], "ace/mode/coffee_worker", "Worker"); var worker = new WorkerClient(["ace"], "ace/mode/coffee_worker", "Worker");
worker.attachToDocument(session.getDocument()); worker.attachToDocument(session.getDocument());
worker.on("error", function(e) { worker.on("annotate", function(e) {
session.setAnnotations([e.data]); session.setAnnotations(e.data);
}); });
worker.on("ok", function(e) { worker.on("terminate", function() {
session.clearAnnotations(); session.clearAnnotations();
}); });

View file

@ -49,13 +49,13 @@ oop.inherits(Worker, Mirror);
this.onUpdate = function() { this.onUpdate = function() {
var value = this.doc.getValue(); var value = this.doc.getValue();
var errors = [];
try { try {
coffee.parse(value).compile(); coffee.parse(value).compile();
} catch(e) { } catch(e) {
var loc = e.location; var loc = e.location;
if (loc) { if (loc) {
this.sender.emit("error", { errors.push({
row: loc.first_line, row: loc.first_line,
column: loc.first_column, column: loc.first_column,
endRow: loc.last_line, endRow: loc.last_line,
@ -64,9 +64,8 @@ oop.inherits(Worker, Mirror);
type: "error" type: "error"
}); });
} }
return;
} }
this.sender.emit("ok"); this.sender.emit("annotate", errors);
}; };
}).call(Worker.prototype); }).call(Worker.prototype);

View file

@ -81,7 +81,7 @@ oop.inherits(Mode, TextMode);
var worker = new WorkerClient(["ace"], "ace/mode/css_worker", "Worker"); var worker = new WorkerClient(["ace"], "ace/mode/css_worker", "Worker");
worker.attachToDocument(session.getDocument()); worker.attachToDocument(session.getDocument());
worker.on("csslint", function(e) { worker.on("annotate", function(e) {
session.setAnnotations(e.data); session.setAnnotations(e.data);
}); });

View file

@ -80,11 +80,11 @@ oop.inherits(Worker, Mirror);
this.onUpdate = function() { this.onUpdate = function() {
var value = this.doc.getValue(); var value = this.doc.getValue();
if (!value) if (!value)
return this.sender.emit("csslint", []); return this.sender.emit("annotate", []);
var infoRules = this.infoRules; var infoRules = this.infoRules;
var result = CSSLint.verify(value, this.ruleset); var result = CSSLint.verify(value, this.ruleset);
this.sender.emit("csslint", result.messages.map(function(msg) { this.sender.emit("annotate", result.messages.map(function(msg) {
return { return {
row: msg.line - 1, row: msg.line - 1,
column: msg.col - 1, column: msg.col - 1,

View file

@ -98,7 +98,7 @@ oop.inherits(Mode, TextMode);
var worker = new WorkerClient(["ace"], "ace/mode/javascript_worker", "JavaScriptWorker"); var worker = new WorkerClient(["ace"], "ace/mode/javascript_worker", "JavaScriptWorker");
worker.attachToDocument(session.getDocument()); worker.attachToDocument(session.getDocument());
worker.on("jslint", function(results) { worker.on("annotate", function(results) {
session.setAnnotations(results.data); session.setAnnotations(results.data);
}); });

File diff suppressed because it is too large Load diff

View file

@ -116,12 +116,10 @@ oop.inherits(JavaScriptWorker, Mirror);
this.onUpdate = function() { this.onUpdate = function() {
var value = this.doc.getValue(); var value = this.doc.getValue();
value = value.replace(/^#!.*\n/, "\n"); value = value.replace(/^#!.*\n/, "\n");
if (!value) { if (!value)
this.sender.emit("jslint", []); return this.sender.emit("annotate", []);
return;
}
var errors = [];
var errors = [];
// jshint reports many false errors // jshint reports many false errors
// report them as error only if code is actually invalid // report them as error only if code is actually invalid
var maxErrorLevel = this.isValidJS(value) ? "warning" : "error"; var maxErrorLevel = this.isValidJS(value) ? "warning" : "error";
@ -179,7 +177,7 @@ oop.inherits(JavaScriptWorker, Mirror);
} }
// console.log("lint time: " + (new Date() - start)); // console.log("lint time: " + (new Date() - start));
this.sender.emit("jslint", errors); this.sender.emit("annotate", errors);
}; };
}).call(JavaScriptWorker.prototype); }).call(JavaScriptWorker.prototype);

View file

@ -74,11 +74,11 @@ oop.inherits(Mode, TextMode);
var worker = new WorkerClient(["ace"], "ace/mode/json_worker", "JsonWorker"); var worker = new WorkerClient(["ace"], "ace/mode/json_worker", "JsonWorker");
worker.attachToDocument(session.getDocument()); worker.attachToDocument(session.getDocument());
worker.on("error", function(e) { worker.on("annotate", function(e) {
session.setAnnotations([e.data]); session.setAnnotations(e.data);
}); });
worker.on("ok", function() { worker.on("terminate", function() {
session.clearAnnotations(); session.clearAnnotations();
}); });

View file

@ -46,21 +46,20 @@ oop.inherits(JsonWorker, Mirror);
this.onUpdate = function() { this.onUpdate = function() {
var value = this.doc.getValue(); var value = this.doc.getValue();
var errors = [];
try { try {
if (value) if (value)
parse(value); parse(value);
} catch (e) { } catch (e) {
var pos = this.doc.indexToPosition(e.at-1); var pos = this.doc.indexToPosition(e.at-1);
this.sender.emit("error", { errors.push({
row: pos.row, row: pos.row,
column: pos.column, column: pos.column,
text: e.message, text: e.message,
type: "error" type: "error"
}); });
return;
} }
this.sender.emit("ok"); this.sender.emit("annotate", errors);
}; };
}).call(JsonWorker.prototype); }).call(JsonWorker.prototype);

View file

@ -58,7 +58,7 @@ module.exports = {
worker.setValue("{}"); worker.setValue("{}");
worker.deferredUpdate.call(); worker.deferredUpdate.call();
assert.equal(this.sender.events[0][0], "ok"); assert.equal(this.sender.events[0][1].length, 0);
}, },
"test check for syntax error": function() { "test check for syntax error": function() {
@ -71,11 +71,12 @@ module.exports = {
worker.deferredUpdate.call(); worker.deferredUpdate.call();
var event = this.sender.events[0]; var event = this.sender.events[0];
assert.equal(event[0], "error"); assert.equal(event[0], "annotate");
assert.equal(event[1].type, "error"); assert.equal(event[1].length, 1);
assert.equal(event[1].text, "Bad string"); assert.equal(event[1][0].type, "error");
assert.equal(event[1].row, 1); assert.equal(event[1][0].text, "Bad string");
assert.equal(event[1].column, 0); assert.equal(event[1][0].row, 1);
assert.equal(event[1][0].column, 0);
}, },
@ -85,11 +86,11 @@ module.exports = {
worker.deferredUpdate.call(); worker.deferredUpdate.call();
var event = this.sender.events[0]; var event = this.sender.events[0];
assert.equal(event[0], "error"); assert.equal(event[0], "annotate");
assert.equal(event[1].type, "error"); assert.equal(event[1][0].type, "error");
assert.equal(event[1].text, "Unexpected 'x'"); assert.equal(event[1][0].text, "Unexpected 'x'");
assert.equal(event[1].row, 0); assert.equal(event[1][0].row, 0);
assert.equal(event[1].column, 0); assert.equal(event[1][0].column, 0);
} }
}; };

View file

@ -52,8 +52,7 @@ define(function(require, exports, module){
}(require('../mode/text').Mode)); }(require('../mode/text').Mode));
keywordend = '(?![$\\w]|-[A-Za-z]|\\s*:(?![:=]))'; keywordend = '(?![$\\w]|-[A-Za-z]|\\s*:(?![:=]))';
stringfill = { stringfill = {
token: 'string', defaultToken: 'string'
regex: '.+'
}; };
LiveScriptMode.Rules = { LiveScriptMode.Rules = {
start: [ start: [
@ -146,7 +145,7 @@ define(function(require, exports, module){
next: 'key' next: 'key'
}, { }, {
token: 'keyword.operator', token: 'keyword.operator',
regex: '\\S+' regex: '[\\^!|&%+\\-]+'
}, { }, {
token: 'text', token: 'text',
regex: '\\s+' regex: '\\s+'
@ -164,8 +163,7 @@ define(function(require, exports, module){
token: 'comment.regex', token: 'comment.regex',
regex: '\\s+(?:#.*)?' regex: '\\s+(?:#.*)?'
}, { }, {
token: 'string.regex', defaultToken: 'string.regex'
regex: '\\S+'
} }
], ],
key: [ key: [
@ -178,7 +176,7 @@ define(function(require, exports, module){
next: 'start' next: 'start'
}, { }, {
token: 'text', token: 'text',
regex: '.', regex: '',
next: 'start' next: 'start'
} }
], ],
@ -188,8 +186,7 @@ define(function(require, exports, module){
regex: '.*?\\*/', regex: '.*?\\*/',
next: 'start' next: 'start'
}, { }, {
token: 'comment.doc', defaultToken: 'comment.doc'
regex: '.+'
} }
], ],
qdoc: [ qdoc: [

View file

@ -148,11 +148,11 @@ oop.inherits(Mode, TextMode);
var worker = new WorkerClient(["ace"], "ace/mode/lua_worker", "Worker"); var worker = new WorkerClient(["ace"], "ace/mode/lua_worker", "Worker");
worker.attachToDocument(session.getDocument()); worker.attachToDocument(session.getDocument());
worker.on("error", function(e) { worker.on("annotate", function(e) {
session.setAnnotations([e.data]); session.setAnnotations(e.data);
}); });
worker.on("ok", function(e) { worker.on("terminate", function() {
session.clearAnnotations(); session.clearAnnotations();
}); });

View file

@ -46,24 +46,23 @@ oop.inherits(Worker, Mirror);
this.onUpdate = function() { this.onUpdate = function() {
var value = this.doc.getValue(); var value = this.doc.getValue();
var errors = [];
// var t=Date.now()
// var t=Date.now()
try { try {
luaparse.parse(value); luaparse.parse(value);
} catch(e) { } catch(e) {
if (e instanceof SyntaxError) { if (e instanceof SyntaxError) {
this.sender.emit("error", { errors.push({
row: e.line - 1, row: e.line - 1,
column: e.column, column: e.column,
text: e.message, text: e.message,
type: "error" type: "error"
}); });
} }
// console.log( t-Date.now())
return;
} }
// console.log( t-Date.now()) // console.log( t-Date.now())
this.sender.emit("ok"); this.sender.emit("annotate", errors);
}; };
}).call(Worker.prototype); }).call(Worker.prototype);

View file

@ -143,11 +143,11 @@ oop.inherits(Mode, HtmlMode);
if (this.inlinePhp) if (this.inlinePhp)
worker.call("setOptions", [{inline: true}]); worker.call("setOptions", [{inline: true}]);
worker.on("error", function(e) { worker.on("annotate", function(e) {
session.setAnnotations(e.data); session.setAnnotations(e.data);
}); });
worker.on("ok", function() { worker.on("terminate", function() {
session.clearAnnotations(); session.clearAnnotations();
}); });

View file

@ -69,11 +69,7 @@ oop.inherits(PhpWorker, Mirror);
// console.log("lint time: " + (new Date() - start)); // console.log("lint time: " + (new Date() - start));
if (errors.length) { this.sender.emit("annotate", errors);
this.sender.emit("error", errors);
} else {
this.sender.emit("ok");
}
}; };
}).call(PhpWorker.prototype); }).call(PhpWorker.prototype);

View file

@ -288,6 +288,9 @@ var RubyHighlightRules = function() {
return stack[0]; return stack[0];
return currentState; return currentState;
} }
}, {
token : "string.character",
regex : "\\B\\?."
}, { }, {
token : "keyword.operator", token : "keyword.operator",
regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)" regex : "!|\\$|%|&|\\*|\\-\\-|\\-|\\+\\+|\\+|~|===|==|=|!=|!==|<=|>=|<<=|>>=|>>>=|<>|<|>|!|&&|\\|\\||\\?\\:|\\*=|%=|\\+=|\\-=|&=|\\^=|\\b(?:in|instanceof|new|delete|typeof|void)"

7
lib/ace/snippets/abc.js Normal file
View file

@ -0,0 +1,7 @@
define(function(require, exports, module) {
"use strict";
exports.snippetText = require("../requirejs/text!./abc.snippets");
exports.scope = "abc";
});

View file

@ -0,0 +1,31 @@
snippet zupfnoter.print
%%%%hn.print {"startpos": ${1:pos_y}, "t":"${2:title}", "v":[${3:voices}], "s":[[${4:syncvoices}1,2]], "f":[${5:flowlines}], "sf":[${6:subflowlines}], "j":[${7:jumplines}]}
snippet zupfnoter.note
%%%%hn.note {"pos": [${1:pos_x},${2:pos_y}], "text": "${3:text}", "style": "${4:style}"}
snippet zupfnoter.annotation
%%%%hn.annotation {"id": "${1:id}", "pos": [${2:pos}], "text": "${3:text}"}
snippet zupfnoter.lyrics
%%%%hn.lyrics {"pos": [${1:x_pos},${2:y_pos}]}
snippet zupfnoter.legend
%%%%hn.legend {"pos": [${1:x_pos},${2:y_pos}]}
snippet zupfnoter.target
"^:${1:target}"
snippet zupfnoter.goto
"^@${1:target}@${2:distance}"
snippet zupfnoter.annotationref
"^#${1:target}"
snippet zupfnoter.annotation
"^!${1:text}@${2:x_offset},${3:y_offset}"

View file

@ -750,7 +750,7 @@ var VirtualRenderer = function(container, theme) {
* @returns {Boolean} * @returns {Boolean}
**/ **/
this.getVScrollBarAlwaysVisible = function() { this.getVScrollBarAlwaysVisible = function() {
return this.$hScrollBarAlwaysVisible; return this.$vScrollBarAlwaysVisible;
}; };
/** /**

113
static.js
View file

@ -10,37 +10,100 @@ var http = require("http")
// compatibility with node 0.6 // compatibility with node 0.6
if (!fs.exists) if (!fs.exists)
fs.exists = path.exists; fs.exists = path.exists;
http.createServer(function(request, response) { var allowSave = process.argv.indexOf("--allow-save") != -1;
var uri = url.parse(request.url).pathname http.createServer(function(req, res) {
, filename = path.join(process.cwd(), uri); var uri = url.parse(req.url).pathname
, filename = path.join(process.cwd(), uri);
fs.exists(filename, function(exists) {
if(!exists) { if (req.method == "PUT") {
response.writeHead(404, {"Content-Type": "text/plain"}); if (!allowSave)
response.write("404 Not Found\n"); return error(res, 404, "Saving not allowed pass --allow-save to enable");
response.end(); save(req, res, filename);
return;
} }
if (fs.statSync(filename).isDirectory()) filename += '/index.html'; fs.exists(filename, function(exists) {
if (!exists)
return error(res, 404, "404 Not Found\n");
fs.readFile(filename, "binary", function(err, file) { if (fs.statSync(filename).isDirectory()) {
if(err) { var files = fs.readdirSync(filename);
response.writeHead(500, {"Content-Type": "text/plain"}); res.writeHead(200, {"Content-Type": "text/html"});
response.write(err + "\n");
response.end(); files.push(".", "..");
return; var html = files.map(function(name) {
} var href = uri + "/" + name;
href = href.replace(/[\/\\]+/g, "/").replace(/\/$/g, "");
if (fs.statSync(filename + "/" + name + "/").isDirectory())
href += "/";
return "<a href='" + href + "'>" + name + "</a><br>";
});
var contentType = mime.lookup(filename) || "text/plain"; res._hasBody && res.write(html.join(""));
response.writeHead(200, {"Content-Type": contentType}); res.end();
response.write(file, "binary"); return;
response.end(); }
fs.readFile(filename, "binary", function(err, file) {
if (err) {
res.writeHead(500, { "Content-Type": "text/plain" });
res.write(err + "\n");
res.end();
return;
}
var contentType = mime.lookup(filename) || "text/plain";
res.writeHead(200, { "Content-Type": contentType });
res.write(file, "binary");
res.end();
});
}); });
});
}).listen(port, ip); }).listen(port, ip);
console.log("http://localhost:" + port); function error(res, status, message, error) {
console.error(error || message);
res.writeHead(status, { "Content-Type": "text/plain" });
res.write(message);
res.end();
}
function save(req, res, filePath) {
var data = "";
req.on("data", function(chunk) {
data += chunk;
});
req.on("error", function() {
error(res, 404, "Could't save file");
});
req.on("end", function() {
try {
fs.writeFileSync(filePath, data);
}
catch (e) {
return error(res, 404, "Could't save file", e);
}
res.statusCode = 200;
res.end("OK");
});
}
function getLocalIps() {
var os = require("os");
var interfaces = os.networkInterfaces ? os.networkInterfaces() : {};
var addresses = [];
for (var k in interfaces) {
for (var k2 in interfaces[k]) {
var address = interfaces[k][k2];
if (address.family === "IPv4" && !address.internal) {
addresses.push(address.address);
}
}
}
return addresses;
}
console.log("http://" + (ip == "0.0.0.0" ? getLocalIps()[0] : ip) + ":" + port);

136
static.py
View file

@ -32,7 +32,9 @@ import time
import string import string
import sys import sys
from os import path, stat, getcwd from os import path, stat, getcwd
from fnmatch import fnmatch
from wsgiref import util from wsgiref import util
from wsgiref.validate import validator
from wsgiref.headers import Headers from wsgiref.headers import Headers
from wsgiref.simple_server import make_server from wsgiref.simple_server import make_server
from optparse import OptionParser from optparse import OptionParser
@ -84,6 +86,8 @@ class Cling(object):
not_modified = StatusApp('304 Not Modified', "") not_modified = StatusApp('304 Not Modified', "")
moved_permanently = StatusApp('301 Moved Permanently') moved_permanently = StatusApp('301 Moved Permanently')
method_not_allowed = StatusApp('405 Method Not Allowed') method_not_allowed = StatusApp('405 Method Not Allowed')
success_no_content = StatusApp('204 No Content', "")
server_error = StatusApp('500 Internal Server Error')
def __init__(self, root, **kw): def __init__(self, root, **kw):
"""Just set the root and any other attribs passes via **kw.""" """Just set the root and any other attribs passes via **kw."""
@ -93,9 +97,6 @@ class Cling(object):
def __call__(self, environ, start_response): def __call__(self, environ, start_response):
"""Respond to a request when called in the usual WSGI way.""" """Respond to a request when called in the usual WSGI way."""
if environ['REQUEST_METHOD'] not in ('GET', 'HEAD'):
headers = [('Allow', 'GET, HEAD')]
return self.method_not_allowed(environ, start_response, headers)
path_info = environ.get('PATH_INFO', '') path_info = environ.get('PATH_INFO', '')
full_path = self._full_path(path_info) full_path = self._full_path(path_info)
if not self._is_under_root(full_path): if not self._is_under_root(full_path):
@ -109,6 +110,23 @@ class Cling(object):
return self.moved_permanently(environ, start_response, headers) return self.moved_permanently(environ, start_response, headers)
else: else:
full_path = self._full_path(path_info + self.index_file) full_path = self._full_path(path_info + self.index_file)
try:
sz = int(environ['CONTENT_LENGTH'])
except:
sz = 0
if environ['REQUEST_METHOD'] == 'PUT' and sz > 0:
for putglob in self.puttable:
if fnmatch(path_info, putglob):
data = environ['wsgi.input'].read(sz)
try:
with open(full_path, "wb") as f: f.write(data)
return self.success_no_content(environ, start_response)
except:
print sys.exc_info()[1]
return self.server_error(environ, start_response)
if environ['REQUEST_METHOD'] not in ('GET', 'HEAD'):
headers = [('Allow', 'GET, HEAD')]
return self.method_not_allowed(environ, start_response, headers)
content_type = self._guess_type(full_path) content_type = self._guess_type(full_path)
try: try:
etag, last_modified = self._conditions(full_path, environ) etag, last_modified = self._conditions(full_path, environ)
@ -191,52 +209,90 @@ def cling_wrap(package_name, dir_name, **kw):
def command(): def command():
parser = OptionParser(usage="%prog DIR [HOST][:][PORT]", usage = "%prog [--help] [-d DIR] [-l [HOST][:PORT]] [-p GLOB[,GLOB...]]"
version="static 0.3.6") parser = OptionParser(usage=usage, version="static 0.3.6")
parser.add_option("-d", "--dir", dest="rootdir", default=".",
help="Root directory to serve. Defaults to '.' .", metavar="DIR")
parser.add_option("-l", "--listen", dest="listen", default="127.0.0.1:8888",
help="Listen on this interface (given by its hostname or IP) and port."+
" HOST defaults to 127.0.0.1. PORT defaults to 8888. "+
"Leave HOST empty to listen on all interfaces (INSECURE!).",
metavar="[HOST][:PORT]")
parser.add_option("-p", "--puttable", dest="puttable", default="",
help="Comma or space-separated list of request paths for which to"+
" permit PUT requests. Each path is a glob pattern that may "+
"contain wildcard characters '*' and/or '?'. "+
"'*' matches any sequence of characters, including the empty"+
" string. '?' matches exactly 1 arbitrary character. "+
"NOTE: Both '*' and '?' match slashes and dots. "+
"I.e. --puttable=* makes every file under DIR writable!",
metavar="GLOB[,GLOB...]")
parser.add_option("--validate", dest="validate", action="store_true",
default=False,
help="Enable HTTP validation. You don't need this unless "+
"you're developing static.py itself.")
options, args = parser.parse_args() options, args = parser.parse_args()
if len(args) in (1, 2): if len(args) > 0:
if len(args) == 2:
parts = args[1].split(":")
if len(parts) == 1:
host = parts[0]
port = None
elif len(parts) == 2:
host, port = parts
else:
sys.exit("Invalid host:port specification.")
elif len(args) == 1:
host, port = None, None
if not host:
host = '0.0.0.0'
if not port:
port = 8888
try:
port = int(port)
except:
sys.exit("Invalid host:port specification.")
app = Cling(args[0])
try:
make_server(host, port, app).serve_forever()
except KeyboardInterrupt, ki:
print "Cio, baby!"
except:
sys.exit("Problem initializing server.")
else:
parser.print_help(sys.stderr) parser.print_help(sys.stderr)
sys.exit(1) sys.exit(1)
parts = options.listen.split(":")
if len(parts) == 1:
try: # if the the listen argument consists only of a port number
port = int(parts[0])
host = None
except: # could not parse as port number => must be a host IP or name
host = parts[0]
port = None
elif len(parts) == 2:
host, port = parts
else:
sys.exit("Invalid host:port specification.")
def test(): if not host:
from wsgiref.validate import validator host = '0.0.0.0'
app = Cling(getcwd()) if not port:
port = 8888
try: try:
print "Serving " + getcwd() + " to http://localhost:8888" port = int(port)
make_server('0.0.0.0', 8888, validator(app)).serve_forever() if port <= 0 or port > 65535: raise ValueError
except:
sys.exit("Invalid host:port specification.")
puttable = set(path.abspath(p) for p in
options.puttable.replace(","," ").split())
if puttable and host not in ('127.0.0.1', 'localhost'):
print("Permitting PUT access for non-localhost connections may be unwise.")
options.rootdir = path.abspath(options.rootdir)
for p in puttable:
if not p.startswith(options.rootdir):
sys.exit("puttable path '%s' not under root '%s'" % (p, options.rootdir))
# cut off root prefix from puttable paths
puttable = set(p[len(options.rootdir):] for p in puttable)
app = Cling(options.rootdir, puttable=puttable)
if options.validate:
app = validator(app)
try:
print "Serving %s to http://%s:%d" % (options.rootdir, host, port)
if puttable:
print("The following paths (relative to server root) may be "+
"OVERWRITTEN via HTTP PUT.")
for p in puttable:
print p
make_server(host, port, app).serve_forever()
except KeyboardInterrupt, ki: except KeyboardInterrupt, ki:
print ""
print "Ciao, baby!" print "Ciao, baby!"
except:
sys.exit("Problem initializing server: %s" % sys.exc_info()[1])
if __name__ == '__main__': if __name__ == '__main__':
test() command()

View file

@ -9,7 +9,7 @@ function main(displayName, extRe) {
var demoFileExt = extRe.split("|")[0] || name; var demoFileExt = extRe.split("|")[0] || name;
var demoFileName = demoFileExt[0] == "^" ? demoFileExt.substr(1) : name + "." + demoFileExt; var demoFileName = demoFileExt[0] == "^" ? demoFileExt.substr(1) : name + "." + demoFileExt;
var demoFilePath = lib.AceRoot + "demo/kitchen-sink/docs/" + demoFileName; var demoFilePath = lib.AceRoot + "demo/kitchen-sink/docs/" + demoFileName;
fs.writeFileSync(demoFilePath, "TODO add a nice demo!", "utf8"); fs.writeFileSync(demoFilePath, "TODO add a nice demo!\nTry to keep it short!", "utf8");
console.log("Created demo file at: " + path.normalize(demoFilePath)); console.log("Created demo file at: " + path.normalize(demoFilePath));
/** mode **/ /** mode **/

View file

@ -19,7 +19,7 @@
border-bottom: solid 1px; border-bottom: solid 1px;
} }
.separator-h { .separator-h {
padding: 0 20px; padding: 0 10px;
} }
#closeBtn { #closeBtn {
background: rgba(245, 146, 146, 0.5); background: rgba(245, 146, 146, 0.5);
@ -59,6 +59,7 @@
<select id="modeEl" size="1"></select> <select id="modeEl" size="1"></select>
<input type="button" value="&#10227;" title="sync" id="syncToMode"></select> <input type="button" value="&#10227;" title="sync" id="syncToMode"></select>
<span id="tablist"></span> <span id="tablist"></span>
<input type="button" value="Save" id="saveButton1"></select>
<span class="separator-h"></span> <span class="separator-h"></span>
<label for="autorunEl">live preview</label> <label for="autorunEl">live preview</label>
<input type="checkbox" label="autorun" id="autorunEl" checked> <input type="checkbox" label="autorun" id="autorunEl" checked>
@ -70,6 +71,7 @@
<label for="themeEl">Theme</label> <label for="themeEl">Theme</label>
<select id="themeEl" size="1" value="textmate"></select> <select id="themeEl" size="1" value="textmate"></select>
<span class="separator-h"></span> <span class="separator-h"></span>
<input type="button" value="Save" id="saveButton2"></select>
<label for="doc">Document</label> <label for="doc">Document</label>
<select id="doc" size="1"></select> <select id="doc" size="1"></select>
</div> </div>

View file

@ -53,6 +53,7 @@ util.bindDropdown("doc", function(value) {
doclist.loadDoc(value, function(session) { doclist.loadDoc(value, function(session) {
if (session) { if (session) {
editor2.setSession(session); editor2.setSession(session);
updateSaveButtonState(null, editor2);
} }
}); });
}); });
@ -60,6 +61,7 @@ util.bindDropdown("doc", function(value) {
var modeEl = document.getElementById("modeEl"); var modeEl = document.getElementById("modeEl");
util.fillDropdown(modeEl, modelist.modes); util.fillDropdown(modeEl, modelist.modes);
var modeSessions = {}; var modeSessions = {};
util.bindDropdown(modeEl, function(value) { util.bindDropdown(modeEl, function(value) {
if (modeSessions[value]) { if (modeSessions[value]) {
editor1.setSession(modeSessions[value]); editor1.setSession(modeSessions[value]);
@ -68,14 +70,17 @@ util.bindDropdown(modeEl, function(value) {
} }
var hp = "./lib/ace/mode/" + value + "_highlight_rules.js"; var hp = "./lib/ace/mode/" + value + "_highlight_rules.js";
net.get(hp, function(text) { net.get(hp, function(text) {
text = util.stripLeadingComments(text);
var session = new EditSession(text); var session = new EditSession(text);
session.setUndoManager(new UndoManager()); session.setUndoManager(new UndoManager());
modeSessions[value] = session; modeSessions[value] = session;
session.setMode("ace/mode/javascript"); session.setMode("ace/mode/javascript", function() {
if (session.getLine(0).match(/^\s*\//))
session.toggleFoldWidget(0); // fold licence comment
});
editor1.setSession(modeSessions[value]); editor1.setSession(modeSessions[value]);
updateSaveButtonState(null, editor1);
schedule(); schedule();
}); });
}); });
@ -85,6 +90,50 @@ document.getElementById("syncToMode").onclick = function() {
docEl.onchange(); docEl.onchange();
run(); run();
}; };
editor1.saveButton = document.getElementById("saveButton1");
editor2.saveButton = document.getElementById("saveButton2");
editor1.saveButton.editor = editor1;
editor2.saveButton.editor = editor2;
editor1.saveButton.onclick = function() {
doclist.saveDoc({
path: "./lib/ace/mode/" + modeEl.value + "_highlight_rules.js",
session: editor1.session
}, function(err) {
handleSaveResult(err, editor1);
});
};
editor1.commands.bindKey({
win: "Ctrl-S", mac: "Cmd-s"
}, editor1.saveButton.onclick);
editor2.saveButton.onclick = function() {
doclist.saveDoc(docEl.value, function(err) {
handleSaveResult(err, editor2);
});
};
editor2.commands.bindKey({
win: "Ctrl-S", mac: "Cmd-s"
}, editor2.saveButton.onclick);
function updateSaveButtonState(e, editor){
editor.saveButton.disabled = editor.session.getUndoManager().isClean();
}
editor1.on("input", updateSaveButtonState);
editor2.on("input", updateSaveButtonState);
function handleSaveResult(err, editor) {
if (err) {
return log(
"Write access to this file is disabled.\n"+
"To enable saving your changes to disk, clone the Ace repository\n"+
"and run the included web server with the --allow-write option\n"+
"`node static.js --allow-write` or `static.py --puttable=*`"
);
}
editor.session.getUndoManager().markClean();
updateSaveButtonState(null, editor);
}
document.getElementById("perfTest").onclick = function() { document.getElementById("perfTest").onclick = function() {
var lines = editor2.session.doc.getAllLines(); var lines = editor2.session.doc.getAllLines();
if (!lines.length) if (!lines.length)

View file

@ -135,6 +135,10 @@ var deps = {
}); });
} }
}, },
liveScript: {
path: "mode/livescript.js",
url: "https://raw.githubusercontent.com/gkz/LiveScript/master/lib/mode-ls.js"
},
coffee: { coffee: {
fetch: function(){ fetch: function(){
var rootHref = "https://raw.github.com/jashkenas/coffee-script/master/"; var rootHref = "https://raw.github.com/jashkenas/coffee-script/master/";