diff --git a/frame.js b/frame.js index 9ff4b7b5..db7edda3 100644 --- a/frame.js +++ b/frame.js @@ -158,7 +158,7 @@ Volcanos("onengine", {help: "解析引擎", list: [], _init: function(can, meta, "studio": {name: "研发 studio", action: [ {name: "route", help: "路由器", index: "web.route"}, {name: "tmux", help: "命令行", index: "web.code.tmux.session"}, - {name: "vimer", help: "编辑器", index: "web.code.vimer", args: ["src/", "main.go"]}, + {name: "vimer", help: "编辑器", index: "web.code.inner", args: ["src/", "main.go"]}, {name: "repos", help: "代码库", index: "web.code.git.status"}, {name: "total", help: "统计量", index: "web.code.git.total"}, {name: "plan", help: "任务表", index: "web.team.plan"}, @@ -393,12 +393,12 @@ Volcanos("onappend", {help: "渲染引擎", list: [], _init: function(can, meta, }]) return ui.item.Meta = item, ui.item }, - tree: function(can, msg, target, cb) { + tree: function(can, msg, field, split, target, cb) { var list = {}; msg.Table(function(value) { - value.path && can.core.List(value.path.split("/"), function(item, index, array) { - var last = array.slice(0, index).join("/") - var name = array.slice(0, index+1).join("/") - list[name] || (list[name] = can.page.Append(can, list[last]||target, [{view: ["item", "div", item+(index==array.length-1?"":"/")], onclick: function(event) { + value[field] && can.core.List(value[field].split(split), function(item, index, array) { + var last = array.slice(0, index).join(split) + var name = array.slice(0, index+1).join(split) + list[name] || (list[name] = can.page.Append(can, list[last]||target, [{view: ["item", "div", item+(index==array.length-1?"":split)], onclick: function(event) { var hide = list[name].style.display == "none" can.page.Modify(can, list[name], {style: {display: hide? "": "none"}}) index == array.length - 1 && typeof cb == "function" && cb(event, value) diff --git a/lib/core.js b/lib/core.js index 7aa17bc0..7d7842b1 100644 --- a/lib/core.js +++ b/lib/core.js @@ -1,4 +1,14 @@ var core = Volcanos("core", {help: "核心模块", + Copy: function(to, from, fields) { + var list = [] + for (var i = 2; i < arguments.length; i++) { + list.push(arguments[i]) + } + + for (var i = 0; i < list.length; i++) { + to[list[i]] = from[list[i]] + } + }, Item: shy("迭代器", function(obj, cb) {var list = []; for (var k in obj) { var res = typeof cb == "function"? cb(k, obj[k]): k diff --git a/lib/page.js b/lib/page.js index d07017bf..9d1ff97c 100644 --- a/lib/page.js +++ b/lib/page.js @@ -16,6 +16,9 @@ var page = Volcanos("page", {help: "网页模块", return list.indexOf(value) == -1? value: undefined; }).join(" ").trim(); }, + set: function(can, obj, key, condition) { + condition? can.page.ClassList.add(can, obj, key): can.page.ClassList.del(can, obj, key) + }, neg: function(can, obj, key) { this.has(can, obj, key)? this.del(can, obj, key): this.add(can, obj, key) }, @@ -182,9 +185,11 @@ var page = Volcanos("page", {help: "网页模块", Remove: shy("删除节点", function(can, target) { target && target.parentNode && target.parentNode.removeChild(target) }), - Toggle: function(can, target) { var hide = target.style.display == "none" - can.page.Modify(can, target, {style: {display: hide? "": "none"}}) - return hide + Toggle: function(can, target, show, hide) { + var status = target.style.display == "none" + can.page.Modify(can, target, {style: {display: status? "": "none"}}) + status? typeof show == "function" && show(): typeof hide == "function" && hide() + return status }, AppendTable: shy("添加表格", function(can, target, msg, list, cb) { diff --git a/plugin/local/code/inner.css b/plugin/local/code/inner.css index 5101bdf3..892d4732 100644 --- a/plugin/local/code/inner.css +++ b/plugin/local/code/inner.css @@ -20,9 +20,6 @@ body.white fieldset.editor div.output table { body.white fieldset.editor div.output table tr { background:#0b2c5400; } -fieldset.editor>div.output { - background-color:#173d40ab; -} fieldset.editor { background:#0b2c54ab; } @@ -107,24 +104,19 @@ fieldset.editor>div.output table.content td.text span.string { color:magenta; } -fieldset.editor>div.output pre.display { - padding:6px; border:solid 1px red; - max-height:120px; overflow:auto; - position:sticky; bottom:0; - display:none; - clear:both; - margin:0; -} -fieldset.editor>div.output pre.display:hover { - background-color:black; - max-height:640px; - z-index:10; +fieldset.editor>div.output div.display div.output { + overflow:auto; + color:white; } fieldset.editor>div.output div.search { background-color:#060627ab; color:white; padding:6px; border:solid 1px red; clear:both; + color:white; +} +fieldset.editor>div.output div.search table { + color:white; } fieldset.editor>div.output div.search div.tags { height:220px; overflow:auto; diff --git a/plugin/local/code/inner.js b/plugin/local/code/inner.js index ed22dccd..60372ff2 100644 --- a/plugin/local/code/inner.js +++ b/plugin/local/code/inner.js @@ -2,23 +2,18 @@ Volcanos("onimport", {help: "导入数据", _init: function(can, msg, list, cb, can.ui = can.page.Appends(can, target, [ {type: "table", list: [{type: "tr", list: [ {type: "td", list: [{view: "project", style: {"max-height": window.innerHeight-300, display: "none"}} ]}, - {type: "td", list: [{view: "profile", style: {"max-height": window.innerHeight-300, "min-width": window.innerWidth-300}, list: [ - {view: ["content", "table"]}, - ]} ], onscroll: function(event) { - }}, + {type: "td", list: [{view: "profile", style: {"max-height": window.innerHeight-300}, list: [ + {view: ["content", "table"]}, + ]} ], style: {"min-width": parseInt(can.Conf("width"))-100, "max-width": parseInt(can.Conf("width"))-60}, + }, ]}, ]}, - {view: "display", style: {display: "none", "max-height": "200"}, list: [{view: "action", list: [ - {button: ["关闭", function(event) { - can.page.Modify(can, can.ui.display, {style: {display: "none"}}) - }]}, - ]}, {view: "output"} ]}, {view: "search", style: {display: "none"}, list: [{view: "action", list: [ {input: ["word", function(event) { if (event.key == "Enter") { can.onaction.searchLine(event, can, can.ui.word.value) } - }], onfocus: function(event) { + }], value: "main", onfocus: function(event) { event.target.setSelectionRange(0, -1) }}, {button: ["搜索", function(event) { @@ -36,15 +31,15 @@ Volcanos("onimport", {help: "导入数据", _init: function(can, msg, list, cb, ]}, ]) - can.tabview = {}, can.history = [] - can.tabview[can.Option("path")+can.Option("file")] = msg + can.history = can.history || [] + can.tabview = {}, can.tabview[can.Option("path")+can.Option("file")] = msg msg.Option({path: can.Option("path"), file: can.Option("file"), line: can.Option("line")||1}) can.onimport.tabview(can, can.Option("path"), can.Option("file"), can.Option("line")||1) return typeof cb == "function" && cb(msg) }, - tabview: function(can, path, file, line) { + tabview: function(can, path, file, line, cb) { var push = {path: path, file: file, line: line} - !can.core.Eq(can.history[can.history.length-1], push) && can.history.push(push) + can.core.Eq(can.history[can.history.length-1], push) || can.history.push(push) function show() { can._msg && can._msg.Option("line", can.Option("line")) @@ -52,6 +47,7 @@ Volcanos("onimport", {help: "导入数据", _init: function(can, msg, list, cb, can.Option({path: path, file: file, line: line||parseInt(can._msg.Option("line"))||1}) can.onsyntax._init(can, can._msg) + typeof cb == "function" && cb() } if (can.tabview[path+file]) { return show() } @@ -59,16 +55,17 @@ Volcanos("onimport", {help: "导入数据", _init: function(can, msg, list, cb, msg.Option({path: path, file: file, line: line||1}) can.tabview[path+file] = msg - var name = file.split("/").pop() - can.page.EnableDrop(can, can._action, "div.file", can.page.Append(can, can._action, [{view: ["file", "div", name], title: file, onclick: function(event) { - can.onimport.tabview(can, path, file) - }}]).first).click() + can.page.EnableDrop(can, can._action, "div.file", can.page.Append(can, can._action, [ + {view: ["file", "div", file.split("/").pop()], title: file, onclick: function(event) { + can.onimport.tabview(can, path, file, "", cb) + }} + ]).first).click() }, true) }, project: function(can, path, cb) { can.Option({path: path}) - var msg = can.request({}); msg.Option("dir_deep", "true") - can.run(msg._event, ["action", "render", "dir", "", path+"/"], function(msg) { can.ui.project.innerHTML = "" - can.onappend.tree(can, msg, can.ui.project, function(event, value) { + var msg = can.request({}); msg.Option("dir_root", path), msg.Option("dir_deep", "true") + can.run(msg._event, ["action", "dir", "./"], function(msg) { can.ui.project.innerHTML = "" + can.onappend.tree(can, msg, "path", "/", can.ui.project, function(event, value) { can.onimport.tabview(can, can.Option("path"), value.path) }), typeof cb == "function" && cb() }, true) @@ -76,39 +73,33 @@ Volcanos("onimport", {help: "导入数据", _init: function(can, msg, list, cb, }, ["/plugin/local/code/inner.css"]) Volcanos("onsyntax", {help: "语法高亮", list: ["keyword", "prefix", "line"], _init: function(can, msg) { can._msg = msg can.page.Select(can, can._action, "div.file", function(item) { - item.title == msg.Option("file")? can.page.ClassList.add(can, item, "select"): - can.page.ClassList.del(can, item, "select") + can.page.ClassList.set(can, item, "select", item.title == msg.Option("file")) }) // caches save - can.core.List(["content"], function(item) { - can.Cache(can.file+item, can.ui[item], { - scrollTop: can.ui.profile.parentNode.scrollTop, - current: can.current, - max: can.max, - }) - }) - // caches load + can.core.List(["content"], function(item) { can.Cache(can.file+item, can.ui[item], { + scrollTop: can.ui.profile.parentNode.scrollTop, + current: can.current, + max: can.max, + }) }) + can.file = can.base.Path(msg.Option("path"), msg.Option("file")) can.parse = can.base.Ext(can.file) can.Status("模式", "normal") + // caches load var cache = false; can.core.List(["content"], function(item) { var p = can.Cache(can.file+item, can.ui[item]); if (p != undefined) { cache = true can.ui.profile.parentNode.scrollTo(0, p.scrollTop) can.onaction.selectLine(can, p.current.target) can.max = p.max } - }); if (cache) { - return - } - + }); if (cache) { return } function init(p) { can.max = 0, can.core.List(can.ls = msg.Result().split("\n"), function(item) { can.onaction.appendLine(can, item) - }) - can.onaction.selectLine(can, can.Option("line")||1) + }), can.onaction.selectLine(can, can.Option("line")||1) } // plugin @@ -142,44 +133,19 @@ Volcanos("onsyntax", {help: "语法高亮", list: ["keyword", "prefix", "line"], }, }) Volcanos("onaction", {help: "控件交互", list: [], - "刷新": function(event, can) { - can.run(event, [can.Option("path"), can.Option("file")]) - }, - "编辑": function(event, can) { can.onkeymap && can.onkeymap._insert(can) }, - "返回": function(event, can) { var last = can.history.pop(); last = can.history.pop() last && can.onimport.tabview(can, last.path, last.file, last.line) }, - - "运行": function(event, can) { - can.page.Modify(can, can.ui.display, {innerHTML: "", style: {display: "none"}}) - can.run(event, ["action", "engine", can.parse, can.Option("file"), can.Option("path")], function(msg) { - (msg.Result() || msg.append && msg.append.length > 0) && can.page.Modify(can, can.ui.display, {innerHTML: "", style: {display: "block"}}) - can.onappend.table(can, can.ui.display, "table", msg) - can.onappend.board(can, can.ui.display, "board", msg) - }, true) + project: function(event, can) { + can.page.Toggle(can, can.ui.project, function() { + can.onimport.project(can, can.Option("path")) + }) }, - - "save": function(event, can) { - var msg = can.request(event); msg.Option("content", can.onexport.content(can)) - can.run(event, ["action", "save", can.parse, can.Option("file"), can.Option("path")], function(msg) { - can.user.toast(can, "保存成功") - }, true) - }, - "project": function(event, can) { - var hide = can.ui.project.style.display == "none" - hide? can.onimport.project(can, can.Option("path"), function() { - can.page.Modify(can, can.ui.project, {style: {display: ""}}) - }): ( - can.page.Modify(can, can.ui.project, {style: {display: "none"}}) - ) - // can.onaction.selectLine(can, can.current) - }, - - "search": function(event, can) { var hide = can.ui.search.style.display == "none" - can.page.Modify(can, can.ui.search, {style: {display: hide? "": "none"}}) - hide && can.onaction.searchLine(event, can, "") + search: function(event, can) { + can.page.Toggle(can, can.ui.search, function() { + // can.onaction.searchLine(event, can, "") + }) }, appendLine: function(can, value) { var index = ++can.max @@ -207,12 +173,6 @@ Volcanos("onaction", {help: "控件交互", list: [], }, onclick: function(event) { can.onaction.selectLine(can, line) - if (can.ui.editor) { - can.ui.editor.focus() - can.ui.editor.setSelectionRange(0, 0) - can.onkeymap && can.onkeymap._mode(can, "insert") - // can.ui.editor.setSelectionRange(event.offsetX/10, event.offsetX/10) - } }, ondblclick: function(event) { return var s = document.getSelection() @@ -275,42 +235,33 @@ Volcanos("onaction", {help: "控件交互", list: [], height: function() { return line.offsetHeight }, prev: function() { return line.previousSibling }, next: function() { return line.nextSibling }, - text: function(what) { - what != undefined && can.onaction.modifyLine(can, line, what) + text: function(text) { + text != undefined && can.onaction.modifyLine(can, line, text) return item.innerText }, target: line, } - can.ui.editor && can.page.Modify(can, can.ui.editor, {className: "editor "+can.mode, value: item.innerText, style: { - height: item.offsetHeight, width: item.offsetWidth, - left: item.offsetLeft, top: item.offsetTop, - }}) - can.ui.command && can.page.Modify(can, can.ui.command, {className: "command "+can.mode, value: item.innerText, style: { - height: item.offsetHeight, width: item.offsetWidth, - left: item.offsetLeft, top: item.offsetTop + can.ui.profile.offsetHeight-100, - }}) + can.onkeymap && can.onkeymap.selectLine(can, line, item) }) }, searchLine: function(event, can, value) { value = value.trim() can.page.Modify(can, can.ui.search, {style: {display: ""}}) value = can.ui.word.value = value || can.ui.word.value || "main" - var msg = can.request(event); msg.Option("_path", can.Option("path")) - value && can.run(event, ["action", "search", can.parse, value, ""], function(msg) { can.ui.tags.innerHTML = "" - can.onappend.table(can, can.ui.tags, "table", msg, function(value, key, index, line) { - value = value.replace("<", "<").replace(">", ">") - value = value.replace("./", "") - can.Status("标签数", index+1) + var toast = can.user.toast(can, value, "搜索中...", 1000000) + value && can.run(event, ["action", "search", can.parse, value, can.Option("path")], function(msg) { can.ui.tags.innerHTML = "" + toast.Close() + + can.onappend.table(can, can.ui.tags, "table", msg, function(value, key, index, line) { can.Status("标签数", index+1) + value = value.replace("<", "<").replace(">", ">"), value = value.replace("./", "") return {text: ["", "td"], list: [{text: [value, "div"]}], onclick: function(event) { - line.line && can.onimport.tabview(can, can.Option("path"), line.file.replace("./", ""), parseInt(line.line)) + line.line && can.onimport.tabview(can, can.Option("path"), line.file.replace("./", ""), parseInt(line.line), function() { + var pos = can.current.offset()-can.current.target.offsetTop + can.current.scroll(0, -pos) + }) }} }) - can.page.Select(can, can.ui.tags, "tr", function(item, index) { - index == 1 && can.page.Select(can, item, "td", function(item, index) { - index == 0 && item.innerText && item.click() - }) - }) }, true) }, }) @@ -319,9 +270,9 @@ Volcanos("onexport", {help: "导出数据", list: ["模式", "按键", "文件 return (parseInt(index))+"/"+parseInt(total)+" = "+parseInt((index)*100/total)+"%" }, content: function(can) { - return can.page.Select(can, can._output, "table.content>td.text", function(item) { + return can.page.Select(can, can._output, "table.content td.text", function(item) { return item.innerText - }).join("\n") + }).join("\n")+"\n" }, }) diff --git a/plugin/local/code/vimer.js b/plugin/local/code/vimer.js index a537ae20..8be893f1 100644 --- a/plugin/local/code/vimer.js +++ b/plugin/local/code/vimer.js @@ -7,6 +7,8 @@ Volcanos("onimport", {help: "导入数据", list: [], _init: function(can, msg, can.Timer(1, function() { can.current.text(can.ui.editor.value) }) + }, onfocus: function(event) { + can.current.scroll(-1000, 0) }, onblur: function(event) { can.current.text(can.ui.editor.value) }, onclick: function(event) { @@ -15,16 +17,49 @@ Volcanos("onimport", {help: "导入数据", list: [], _init: function(can, msg, {view: ["command", "input"], onkeydown: function(event) { can.onkeymap.parse(event, can, "command") }}, - ]) + ]); can.core.Copy(can.ui, ui, "editor", "command"), can.onkeymap._init(can, "insert") + + var ui = can.page.Append(can, target, [ + {view: "display", style: {display: "none"}, list: [{view: "action", list: [ + {button: ["关闭", function(event) { + can.page.Modify(can, can.ui.display, {style: {display: "none"}}) + } ]}, + ]}, + {view: "output", style: {"max-height": "200"}}, + ]}, + ]); can.core.Copy(can.ui, ui, "display", "output") - can.ui.editor = ui.editor - can.ui.command = ui.command - can.onkeymap._init(can, "insert") typeof cb == "function" && cb() }, target) }) }, }, ["/plugin/local/code/vimer.css"]) +Volcanos("onaction", {help: "控件交互", list: [], + _merge: function(can, sub) { for (var k in sub) { + can.onaction.hasOwnProperty(k) || (can.onaction[k] = sub[k]) + }; return true }, + + save: function(event, can) { + var msg = can.request(event); msg.Option("content", can.onexport.content(can)) + can.run(event, ["action", "save", can.parse, can.Option("file"), can.Option("path")], function(msg) { + can.user.toast(can, "保存成功") + }, true) + }, + "编辑": function(event, can) { can.onkeymap && can.onkeymap._insert(can) }, + "刷新": function(event, can) { + can.run(event, [can.Option("path"), can.Option("file")]) + }, + "运行": function(event, can) { + can.page.Modify(can, can.ui.display, {innerHTML: "", style: {display: "none"}}) + can.run(event, ["action", "engine", can.parse, can.Option("file"), can.Option("path")], function(msg) { + (msg.Result() || msg.append && msg.append.length > 0) && can.page.Modify(can, can.ui.display, {innerHTML: "", style: {display: "block"}}) + can.onappend.table(can, can.ui.display, "table", msg) + can.onappend.board(can, can.ui.display, "board", msg) + }, true) + }, + + +}) Volcanos("onkeymap", {help: "键盘交互", list: ["command", "normal", "insert"], _init: function(can, mode) { can.history = [] can.core.List(can.onkeymap.list, function(item) { var engine = {} @@ -55,10 +90,12 @@ Volcanos("onkeymap", {help: "键盘交互", list: ["command", "normal", "insert" }, _remote: function(event, can, key, arg, cb) { - can.page.Modify(can, can.ui.display, {innerHTML: "", style: {display: "none"}}) + can.page.Modify(can, can.ui.display, {style: {display: "none"}}) var msg = can.request(event); msg.Option("content", can.onexport.content(can)) - can.run(event, arg||["action", key, can.Option("path"), can.Option("file")], cb||function(msg) { - (msg.Result() || msg.append && msg.append.length > 0) && can.page.Modify(can, can.ui.display, {innerHTML: "", style: {display: "block"}}) + can.run(event, arg||["action", key, can.parse, can.Option("file"), can.Option("path")], cb||function(msg) { + can.page.Modify(can, can.ui.display, {style: {display: "block"}}) + + can.ui.output.innerHTML = "" can.onappend.table(can, can.ui.output, "table", msg, function(value, key, index) { return {text: [value, "td"]} }) @@ -67,7 +104,7 @@ Volcanos("onkeymap", {help: "键盘交互", list: ["command", "normal", "insert" }, _engine: { e: function(event, can, line, ls) { can.onimport.tabview(can, can.Option("path"), ls[1]) }, - w: function(event, can) { can.onaction["保存"](event, can, "保存") }, + w: function(event, can) { can.onaction["save"](event, can, "save") }, r: function(event, can) { can.onaction["运行"](event, can, "运行") }, }, @@ -120,12 +157,18 @@ Volcanos("onkeymap", {help: "键盘交互", list: ["command", "normal", "insert" can.onkeymap.parse({key: ""}, can, "normal") }, + H: function(event, can) { + can.ui.editor.setSelectionRange(0, 0) + }, h: function(event, can) { - can.ui.editor.setSelectionnRange(can.ui.editor.selectionStart-1, can.ui.editor.selectionStart-1) + can.ui.editor.setSelectionRange(can.ui.editor.selectionStart-1, can.ui.editor.selectionStart-1) }, l: function(event, can) { can.ui.editor.setSelectionRange(can.ui.editor.selectionStart+1, can.ui.editor.selectionStart+1) }, + L: function(event, can) { + can.ui.editor.setSelectionRange(-1, -1) + }, j: function(event, can) { can.onaction.selectLine(can, can.current.next()) var pos = can.current.offset()+can.current.window()-can.ui.editor.offsetTop; if (pos < 5*can.current.height()) { @@ -239,14 +282,29 @@ Volcanos("onkeymap", {help: "键盘交互", list: ["command", "normal", "insert" }, }, + selectLine: function(can, line, item) { + can.page.Modify(can, can.ui.editor, {className: "editor "+can.mode, value: item.innerText, style: { + height: item.offsetHeight, width: item.offsetWidth, + left: item.offsetLeft, top: item.offsetTop, + }}) + can.page.Modify(can, can.ui.command, {className: "command "+can.mode, value: item.innerText, style: { + height: item.offsetHeight, width: item.offsetWidth, + left: item.offsetLeft, top: item.offsetTop + can.ui.profile.offsetHeight-100, + }}) + + can.ui.editor.focus() + can.ui.editor.setSelectionRange(0, 0) + can.onkeymap._mode(can, "insert") + // can.ui.editor.setSelectionRange(event.offsetX/10, event.offsetX/10) + }, insertLine: function(can, value, before) { var line = can.onaction.appendLine(can, value) before && can.ui.content.insertBefore(line, before) can.onaction.rerankLine(can) return line }, - deleteLine: function(can, target) { - can.page.Remove(can, target) + deleteLine: function(can, line) { + can.page.Remove(can, line) can.onaction.rerankLine(can) }, })