From 19ea0fe979462838d93f58df13a7364ffa89f8f1 Mon Sep 17 00:00:00 2001 From: nightwing Date: Tue, 19 Mar 2013 18:27:09 +0400 Subject: [PATCH] add snippet editor to the demo --- demo/kitchen-sink/demo.js | 51 ++-- demo/kitchen-sink/doclist.js | 1 + demo/kitchen-sink/docs/tmSnippet.tmSnippet | 45 ++-- demo/kitchen-sink/modelist.js | 2 +- kitchen-sink.html | 15 +- lib/ace/mode/_test/tokens_tmsnippet.json | 259 +++++++++++++-------- lib/ace/mode/tmsnippet.js | 39 +++- lib/ace/snippets.js | 2 + lib/ace/snippets/javascript.snippets | 2 +- 9 files changed, 274 insertions(+), 142 deletions(-) diff --git a/demo/kitchen-sink/demo.js b/demo/kitchen-sink/demo.js index 81d7c024..a4ba5c53 100644 --- a/demo/kitchen-sink/demo.js +++ b/demo/kitchen-sink/demo.js @@ -120,14 +120,14 @@ env.editor.commands.addCommands([{ name: "snippet", bindKey: {win: "Alt-C", mac: "Command-Alt-C"}, exec: function(editor, needle) { - if (typeof needle == "object") { + if (typeof needle == "object") { editor.cmdLine.setValue("snippet ", 1); editor.cmdLine.focus(); return; } - var s = SnippetManager.getSnippetByName(needle, editor); - if (s) - SnippetManager.insertSnippet(editor, s.content); + var s = SnippetManager.getSnippetByName(needle, editor); + if (s) + SnippetManager.insertSnippet(editor, s.content); }, readOnly: true }, { @@ -169,7 +169,7 @@ commands.addCommand({ exec: function() {alert("Fake Save File");} }); -var keybindings = { +var keybindings = { ace: null, // Null = use "default" keymapping vim: require("ace/keyboard/vim").handler, emacs: "ace/keyboard/emacs", @@ -375,7 +375,7 @@ bindDropdown("split", function(value) { sp.setSplits(1); } else { var newEditor = (sp.getSplits() == 1); - sp.setOrientation(value == "below" ? sp.BELOW : sp.BESIDE); + sp.setOrientation(value == "below" ? sp.BELOW : sp.BESIDE); sp.setSplits(2); if (newEditor) { @@ -449,22 +449,33 @@ require("ace/placeholder").PlaceHolder; var SnippetManager = require("ace/snippets").SnippetManager var jsSnippets = require("ace/snippets/javascript"); -var testSnippet = "\ -\\begin{${1:document}}\n\ - ${2:$TM_SELECTED_TEXT:some ${3:latex}}\n\ - ${3:$TM_SELECTED_TEXT/a/b/c}\n\ - ${4:${TM_SELECTED_TEXT/(.)/\\u$1/c:7}}\n\ -\\end{$1}\n\ -$0"; -SnippetManager.register({ - content: testSnippet, - tabTrigger: "t", - name: "testSnippet" -}) -jsSnippets.snippets = SnippetManager.parseSnippetFile(jsSnippets.snippetText) -SnippetManager.register(jsSnippets.snippets, "javascript") window.SnippetManager = SnippetManager +function saveSnippets() { + jsSnippets.snippets = SnippetManager.parseSnippetFile(jsSnippets.snippetText); + SnippetManager.register(jsSnippets.snippets, "javascript") +} + +env.editSnippets = function() { + var sp = env.split; + sp.setSplits(1); + sp.setSplits(2); + sp.setOrientation(sp.BESIDE); + var editor = sp.$editors[1] + if (!env.snippetSession) { + var file = jsSnippets.snippetText; + env.snippetSession = doclist.initDoc(file, "", {}); + env.snippetSession.setMode("ace/mode/tmsnippet"); + env.snippetSession.setUseSoftTabs(false); + } + editor.on("blur", function() { + jsSnippets.snippetText = editor.getValue(); + saveSnippets(); + }) + editor.setSession(env.snippetSession, 1); + editor.focus(); +} + ace.commands.bindKey("Tab", function(editor) { var success = SnippetManager.expandWithTab(editor); if (!success) diff --git a/demo/kitchen-sink/doclist.js b/demo/kitchen-sink/doclist.js index 414acce0..eaf29275 100644 --- a/demo/kitchen-sink/doclist.js +++ b/demo/kitchen-sink/doclist.js @@ -54,6 +54,7 @@ function initDoc(file, path, doc) { var mode = modelist.getModeFromPath(path); session.modeName = mode.name; session.setMode(mode.mode); + return session; } diff --git a/demo/kitchen-sink/docs/tmSnippet.tmSnippet b/demo/kitchen-sink/docs/tmSnippet.tmSnippet index 6ea4117f..78282d18 100644 --- a/demo/kitchen-sink/docs/tmSnippet.tmSnippet +++ b/demo/kitchen-sink/docs/tmSnippet.tmSnippet @@ -1,19 +1,26 @@ -$$------------------------------------ -tabTrigger: t -name: Heading 3 -scope: language -content: ----------------------------- -\begin{${1:documnet}} - ${2:$TM_SELECTED_TEXT:some latex} - ${3:$TM_SELECTED_TEXT/a/b/c} - ${4:${TM_SELECTED_TEXT/(.)/\\u$1/g:7}} -\end{$1} -$0\\$$ -$$------------------------------------ -tabTrigger: ^3 -name: Heading 3 -scope: language -content: ----------------------------- - -${TM_CURRENT_LINE/./^/g} -$$------------------------------------ \ No newline at end of file +# Function +snippet fun + function ${1?:function_name}(${2:argument}) { + ${3:// body...} + } +# Anonymous Function +regex /((=)\s*|(:)\s*|(\()|\b)/f/(\))?/ +name f + function${M1?: ${1:functionName}}($2) { + ${0:$TM_SELECTED_TEXT} + }${M2?;}${M3?,}${M4?)} +# Immediate function +trigger \(?f\( +endTrigger \)? +snippet f( + (function(${1}) { + ${0:${TM_SELECTED_TEXT:/* code */}} + }(${1})); +# if +snippet if + if (${1:true}) { + ${0} + } + + + \ No newline at end of file diff --git a/demo/kitchen-sink/modelist.js b/demo/kitchen-sink/modelist.js index f35354dd..b3c686ef 100644 --- a/demo/kitchen-sink/modelist.js +++ b/demo/kitchen-sink/modelist.js @@ -98,7 +98,7 @@ var modesByName = { tex: ["Tex" , "tex"], text: ["Text" , "txt"], textile: ["Textile" , "textile"], - tmsnippet: ["tmSnippet" , "tmSnippet"], + tmsnippet: ["tmSnippet" , "tmSnippet"], toml: ["toml" , "toml"], typescript: ["Typescript" , "typescript|ts|str"], vbscript: ["VBScript" , "vbs"], diff --git a/kitchen-sink.html b/kitchen-sink.html index 33bc19a7..7068e779 100644 --- a/kitchen-sink.html +++ b/kitchen-sink.html @@ -13,20 +13,20 @@ - +
- +
@@ -151,7 +151,7 @@ - + @@ -265,10 +265,15 @@ + + +
+ +
- +
diff --git a/lib/ace/mode/_test/tokens_tmsnippet.json b/lib/ace/mode/_test/tokens_tmsnippet.json index 17eaeb47..f695403d 100644 --- a/lib/ace/mode/_test/tokens_tmsnippet.json +++ b/lib/ace/mode/_test/tokens_tmsnippet.json @@ -1,132 +1,209 @@ [[ "start", - ["doc,comment","$$------------------------------------"] + ["comment","# Function"] ],[ "start" ],[ "start", - ["text","tabTrigger: t"] + ["constant.language.escape","snippet"], + ["text"," fun"] ],[ "start" ],[ - "start", - ["text","name: Heading 3"] -],[ - "start" -],[ - "start", - ["text","scope: language"] -],[ - "start" -],[ - "start", - ["text","content: -----------------------------"] -],[ - "start" -],[ - "start", - ["text","\\begin{"], + "sn-start", + ["text","\tfunction "], ["markup.list","${"], ["constant.numeric","1"], - ["punctuation.operator",":"], - ["text","documnet"], + ["text","?:function_name"], ["markup.list","}"], - ["text","}"] -],[ - "start" -],[ - "start", - ["text"," "], + ["text","("], ["markup.list","${"], ["constant.numeric","2"], ["punctuation.operator",":"], - ["keyword","$TM_SELECTED_TEXT"], - ["text",":some latex"], - ["markup.list","}"] + ["text","argument"], + ["markup.list","}"], + ["text",") {"] ],[ "start" ],[ - "start", - ["text"," "], + "sn-start", + ["text","\t\t"], ["markup.list","${"], ["constant.numeric","3"], ["punctuation.operator",":"], + ["text","// body..."], + ["markup.list","}"] +],[ + "start" +],[ + "sn-start", + ["text","\t}"] +],[ + "start" +],[ + "start", + ["comment","# Anonymous Function"] +],[ + "start" +],[ + "start", + ["constant.language.escape","regex "], + ["keyword","/"], + ["text","((=)\\s*|(:)\\s*|(\\()|\\b)"], + ["keyword","/"], + ["text","f"], + ["keyword","/"], + ["text","(\\))?"], + ["keyword","/"] +],[ + "start" +],[ + "start", + ["constant.language.escape","name"], + ["text"," f"] +],[ + "start" +],[ + "sn-start", + ["text","\tfunction"], + ["markup.list","${"], + ["variable","M1"], + ["text","?: "], + ["markup.list","${"], + ["constant.numeric","1"], + ["punctuation.operator",":"], + ["text","functionName"], + ["markup.list","}}"], + ["text","("], + ["variable","$2"], + ["text",") {"] +],[ + "start" +],[ + "sn-start", + ["text","\t\t"], + ["markup.list","${"], + ["constant.numeric","0"], + ["punctuation.operator",":"], ["keyword","$TM_SELECTED_TEXT"], - ["text","/a/b/c"], + ["markup.list","}"] +],[ + "start" +],[ + "sn-start", + ["text","\t}"], + ["markup.list","${"], + ["variable","M2"], + ["text","?;"], + ["markup.list","}${"], + ["variable","M3"], + ["text","?,"], + ["markup.list","}${"], + ["variable","M4"], + ["text","?)"], ["markup.list","}"] ],[ "start" ],[ "start", - ["text"," "], + ["comment","# Immediate function"] +],[ + "start" +],[ + "start", + ["constant.language.escape","trigger"], + ["text"," \\(?f\\("] +],[ + "start" +],[ + "start", + ["constant.language.escape","endTrigger"], + ["text"," \\)?"] +],[ + "start" +],[ + "start", + ["constant.language.escape","snippet"], + ["text"," f("] +],[ + "start" +],[ + "sn-start", + ["text","\t(function("], ["markup.list","${"], - ["constant.numeric","4"], + ["constant.numeric","1"], + ["markup.list","}"], + ["text",") {"] +],[ + "start" +],[ + "sn-start", + ["text","\t\t"], + ["markup.list","${"], + ["constant.numeric","0"], ["punctuation.operator",":"], ["markup.list","${"], ["keyword","TM_SELECTED_TEXT"], - ["string.regex","/(.)/"], - ["string","\\"], - ["keyword","\\u"], - ["variable","$1"], - ["string.regex","/g:"], - ["text","7"], + ["punctuation.operator",":"], + ["text","/* code */"], ["markup.list","}}"] ],[ "start" ],[ - "start", - ["text","\\end{"], - ["variable","$1"], - ["text","}"] -],[ - "start" -],[ - "start", - ["variable","$0"], - ["constant.language.escape","\\\\"], - ["text","$$"] -],[ - "start" -],[ - "start", - ["doc,comment","$$------------------------------------"] -],[ - "start" -],[ - "start", - ["text","tabTrigger: ^3"] -],[ - "start" -],[ - "start", - ["text","name: Heading 3"] -],[ - "start" -],[ - "start", - ["text","scope: language"] -],[ - "start" -],[ - "start", - ["text","content: -----------------------------"] -],[ - "start" -],[ - "start" -],[ - "start" -],[ - "start", + "sn-start", + ["text","\t}("], ["markup.list","${"], - ["keyword","TM_CURRENT_LINE"], - ["string.regex","/./"], - ["string","^"], - ["string.regex","/g"], + ["constant.numeric","1"], + ["markup.list","}"], + ["text","));"] +],[ + "start" +],[ + "start", + ["comment","# if"] +],[ + "start" +],[ + "start", + ["constant.language.escape","snippet"], + ["text"," if"] +],[ + "start" +],[ + "sn-start", + ["text","\tif ("], + ["markup.list","${"], + ["constant.numeric","1"], + ["punctuation.operator",":"], + ["text","true"], + ["markup.list","}"], + ["text",") {"] +],[ + "start" +],[ + "sn-start", + ["text","\t\t"], + ["markup.list","${"], + ["constant.numeric","0"], ["markup.list","}"] ],[ "start" ],[ - "start", - ["doc,comment","$$------------------------------------"] + "sn-start", + ["text","\t}"] +],[ + "start" +],[ + "sn-start", + ["text","\t"] +],[ + "start" +],[ + "sn-start", + ["text","\t"] +],[ + "start" +],[ + "sn-start", + ["text","\t"] ]] \ No newline at end of file diff --git a/lib/ace/mode/tmsnippet.js b/lib/ace/mode/tmsnippet.js index 8f777719..d3e51863 100644 --- a/lib/ace/mode/tmsnippet.js +++ b/lib/ace/mode/tmsnippet.js @@ -20,7 +20,7 @@ var SnippetHighlightRules = function() { if (stack[1]) stack[1]++; else - stack.unshift("start", 1); + stack.unshift(state, 1); return this.tokenName; }, tokenName: "markup.list", regex: "\\${", next: "varDecl"}, {onMatch: function(value, state, stack) { @@ -31,7 +31,7 @@ var SnippetHighlightRules = function() { stack.splice(0,2); return this.tokenName; }, tokenName: "markup.list", regex: "}"}, - {token: "doc,comment", regex:/^\${2}-{5,}$/} + {token: "doc.comment", regex:/^\${2}-{5,}$/} ], "varDecl" : [ {regex: /\d+\b/, token: "constant.numeric"}, @@ -62,15 +62,44 @@ var SnippetHighlightRules = function() { ] }; }; - oop.inherits(SnippetHighlightRules, TextHighlightRules); exports.SnippetHighlightRules = SnippetHighlightRules; +var SnippetGroupHighlightRules = function() { + this.$rules = { + "start" : [ + {token: "text", regex: "^\\t", next: "sn-start"}, + {token:"invalid", regex: /^ \s*/}, + {token:"comment", regex: /^#.*/}, + {token:"constant.language.escape", regex: "^regex ", next: "regex"}, + {token:"constant.language.escape", regex: "^(trigger|endTrigger|name|snippet|guard|endGuard|tabTrigger|key)\\b"} + ], + "regex" : [ + {token:"text", regex: "\\."}, + {token:"keyword", regex: "/"}, + {token:"empty", regex: "$", next: "start"} + ] + }; + this.embedRules(SnippetHighlightRules, "sn-", [ + {token: "text", regex: "^\\t", next: "sn-start"}, + {onMatch: function(value, state, stack) { + stack.splice(stack.length); + return this.tokenName; + }, tokenName: "text", regex: "^(?!\t)", next: "start"}, + ]) + +}; + +oop.inherits(SnippetGroupHighlightRules, TextHighlightRules); + +exports.SnippetGroupHighlightRules = SnippetGroupHighlightRules; + +var FoldMode = require("./folding/coffee").FoldMode; var Mode = function() { - var highlighter = new SnippetHighlightRules(); - + var highlighter = new SnippetGroupHighlightRules(); + this.foldingRules = new FoldMode(); this.$tokenizer = new Tokenizer(highlighter.getRules()); }; oop.inherits(Mode, TextMode); diff --git a/lib/ace/snippets.js b/lib/ace/snippets.js index 3f227fe5..5b41f078 100644 --- a/lib/ace/snippets.js +++ b/lib/ace/snippets.js @@ -619,6 +619,8 @@ var TabstopManager = function(editor) { var anchor = this.editor.selection.anchor; var isEmpty = this.editor.selection.isEmpty(); for (var i = this.ranges.length; i--;) { + if (this.ranges[i].linked) + continue; var containsLead = this.ranges[i].contains(lead.row, lead.column); var containsAnchor = isEmpty || this.ranges[i].contains(anchor.row, anchor.column); if (containsLead && containsAnchor) diff --git a/lib/ace/snippets/javascript.snippets b/lib/ace/snippets/javascript.snippets index 313e6119..813876e2 100644 --- a/lib/ace/snippets/javascript.snippets +++ b/lib/ace/snippets/javascript.snippets @@ -1,6 +1,6 @@ # Prototype snippet proto - ${1:class_name}.prototype.${2:method_name} = function(${3irst_argument}) { + ${1:class_name}.prototype.${2:method_name} = function(${3:first_argument}) { ${4:// body...} }; # Function