Add support for org-mode in th code app

pull/1/head
yflory 7 years ago
parent 6a906e3770
commit bc9a88fbe9

@ -15,7 +15,7 @@ define([
'css!cm/addon/dialog/dialog.css', 'css!cm/addon/dialog/dialog.css',
'css!cm/addon/fold/foldgutter.css', 'css!cm/addon/fold/foldgutter.css',
'cm/mode/markdown/markdown', 'cm/mode/gfm/gfm',
'cm/addon/mode/loadmode', 'cm/addon/mode/loadmode',
'cm/mode/meta', 'cm/mode/meta',
'cm/addon/mode/overlay', 'cm/addon/mode/overlay',
@ -80,7 +80,7 @@ define([
} catch (e) { console.error(e); } } catch (e) { console.error(e); }
}; };
var drawPreview = Util.throttle(function () { var drawPreview = Util.throttle(function () {
if (CodeMirror.highlightMode !== 'markdown') { return; } if (['markdown', 'gfm'].indexOf(CodeMirror.highlightMode) === -1) { return; }
if (!$previewButton.is('.cp-toolbar-button-active')) { return; } if (!$previewButton.is('.cp-toolbar-button-active')) { return; }
forceDrawPreview(); forceDrawPreview();
}, 150); }, 150);
@ -98,7 +98,7 @@ define([
previewTo = setTimeout(function () { previewTo = setTimeout(function () {
$codeMirror.removeClass('transition'); $codeMirror.removeClass('transition');
}, 500); }, 500);
if (CodeMirror.highlightMode !== 'markdown') { if (['markdown', 'gfm'].indexOf(CodeMirror.highlightMode) === -1) {
$previewContainer.show(); $previewContainer.show();
} }
$previewContainer.toggle(); $previewContainer.toggle();
@ -132,7 +132,7 @@ define([
}); });
var modeChange = function (mode) { var modeChange = function (mode) {
if (mode === "markdown") { if (['markdown', 'gfm'].indexOf(mode) !== -1) {
$previewButton.show(); $previewButton.show();
framework._.sfCommon.getPadAttribute('previewMode', function (e, data) { framework._.sfCommon.getPadAttribute('previewMode', function (e, data) {
if (e) { return void console.error(e); } if (e) { return void console.error(e); }
@ -293,7 +293,7 @@ define([
framework.onReady(function (newPad) { framework.onReady(function (newPad) {
if (newPad && !CodeMirror.highlightMode) { if (newPad && !CodeMirror.highlightMode) {
CodeMirror.setMode('markdown', evModeChange.fire); CodeMirror.setMode('gfm', evModeChange.fire);
//console.log("%s => %s", CodeMirror.highlightMode, CodeMirror.$language.val()); //console.log("%s => %s", CodeMirror.highlightMode, CodeMirror.$language.val());
} }

@ -0,0 +1,156 @@
define([
'cm/lib/codemirror',
'cm/addon/mode/simple'
], function (CodeMirror) {
CodeMirror.__mode = 'orgmode';
CodeMirror.defineSimpleMode("orgmode", {
start: [
{regex: /^(^\*{1,6}\s)(TODO|DOING|WAITING|NEXT){0,1}(CANCELLED|CANCEL|DEFERRED|DONE|REJECTED|STOP|STOPPED){0,1}(.*)$/, token: ["header org-level-star", "header org-todo", "header org-done", "header"]},
{regex: /(^\+[^\/]*\+)/, token: ["strikethrough"]},
{regex: /(^\*[^\/]*\*)/, token: ["strong"]},
{regex: /(^\/[^\/]*\/)/, token: ["em"]},
{regex: /(^\_[^\/]*\_)/, token: ["link"]},
{regex: /(^\~[^\/]*\~)/, token: ["comment"]},
{regex: /(^\=[^\/]*\=)/, token: ["comment"]},
{regex: /\[\[[^\[\]]*\]\[[^\[\]]*\]\]/, token: "url"}, // links
{regex: /\[[xX\s]?\]/, token: 'qualifier'}, // checkbox
{regex: /\#\+BEGIN_[A-Z]*/, token: "comment", next: "env"}, // comments
{regex: /:?[A-Z_]+\:.*/, token: "comment"}, // property drawers
{regex: /(\#\+[A-Z_]*)(\:.*)/, token: ["keyword", 'qualifier']}, // environments
{regex: /(CLOCK\:|SHEDULED\:)(\s.+)/, token: ["comment", "keyword"]}
],
env: [
{regex: /.*?\#\+END_[A-Z]*/, token: "comment", next: "start"},
{regex: /.*/, token: "comment"}
]
});
CodeMirror.registerHelper("fold", "orgmode", function(cm, start) {
function headerLevel (lineNo) {
var line = cm.getLine(lineNo);
var match = /^\*+/.exec(line);
if (match && match.length === 1 && /header/.test(cm.getTokenTypeAt(CodeMirror.Pos(lineNo, 0)))) {
return match[0].length;
}
return null;
}
// init
var levelToMatch = headerLevel(start.line);
// no folding needed
if(levelToMatch === null) { return; }
// find folding limits
var lastLine = cm.lastLine();
var end = start.line;
while (end < lastLine){
end += 1;
var level = headerLevel(end);
if (level && level <= levelToMatch) {
end = end - 1;
break;
}
}
return {
from: CodeMirror.Pos(start.line, cm.getLine(start.line).length),
to: CodeMirror.Pos(end, cm.getLine(end).length)
};
});
CodeMirror.registerGlobalHelper("fold", "drawer", function(mode) {
return mode.name === 'orgmode' ? true : false;
}, function(cm, start) {
function isBeginningOfADrawer(lineNo) {
var line = cm.getLine(lineNo);
var match = /^\:.*\:$/.exec(line);
if(match && match.length === 1 && match[0] !== ':END:'){
return true;
}
return false;
}
function isEndOfADrawer(lineNo){
var line = cm.getLine(lineNo);
return line.trim() === ':END:' ? true : false;
}
var drawer = isBeginningOfADrawer(start.line);
if (drawer === false) { return; }
// find folding limits
var lastLine = cm.lastLine();
var end = start.line;
while(end < lastLine){
end += 1;
if (isEndOfADrawer(end)) {
break;
}
}
return {
from: CodeMirror.Pos(start.line, cm.getLine(start.line).length),
to: CodeMirror.Pos(end, cm.getLine(end).length)
};
});
CodeMirror.afterInit = function(editor){
function fold(cm, start){
cm.foldCode(start, null, "fold");
}
function unfold(cm, start){
cm.foldCode(start, null, "unfold");
}
function isFold(cm, start){
var line = start.line;
var marks = cm.findMarks(CodeMirror.Pos(line, 0), CodeMirror.Pos(line + 1, 0));
for (var i = 0; i < marks.length; ++i) {
if (marks[i].__isFold && marks[i].find().from.line === line) { return marks[i]; }
}
return false;
}
var state = {
stab: 'OVERVIEW'
};
editor.setOption("extraKeys", {
"Tab": function(cm) {
var pos = cm.getCursor();
return isFold(cm, pos) ? unfold(cm, pos) : fold(cm, pos);
},
"Shift-Tab": function(cm){
if(state.stab === "SHOW_ALL"){
// fold everything that can be fold
state.stab = 'OVERVIEW';
cm.operation(function() {
for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++){
fold(cm, CodeMirror.Pos(i, 0));
}
});
}else{
// unfold all headers
state.stab = 'SHOW_ALL';
cm.operation(function() {
for (var i = cm.firstLine(), e = cm.lastLine(); i <= e; i++){
if(/header/.test(cm.getTokenTypeAt(CodeMirror.Pos(i, 0))) === true){
unfold(cm, CodeMirror.Pos(i, 0));
}
}
});
}
}
});
editor.on('touchstart', function(cm){
setTimeout(function () {
return isFold(cm, cm.getCursor()) ? unfold(cm, cm.getCursor()) : fold(cm, cm.getCursor());
}, 150);
});
// fold everything except headers by default
editor.operation(function() {
for (var i = 0; i < editor.lineCount() ; i++) {
if(/header/.test(editor.getTokenTypeAt(CodeMirror.Pos(i, 0))) === false){
fold(editor, CodeMirror.Pos(i, 0));
}
}
});
};
});

@ -243,13 +243,13 @@ define([
value: 1, value: 1,
checked: 'checked' checked: 'checked'
}), }),
h('label', { 'for': 'cp-share-editable-true' }, Messages.share_linkEdit), h('label', { 'for': 'cp-share-editable-true' }, Messages.share_linkEdit),
h('input#cp-share-editable-false.cp-share-editable-value', { h('input#cp-share-editable-false.cp-share-editable-value', {
type: 'radio', type: 'radio',
name: 'cp-share-editable', name: 'cp-share-editable',
value: 0 value: 0
}), }),
h('label', { 'for': 'cp-share-editable-false' }, Messages.share_linkView), h('label', { 'for': 'cp-share-editable-false' }, Messages.share_linkView),
h('br'), h('br'),
h('br'), h('br'),
h('label', Messages.share_linkOptions), h('label', Messages.share_linkOptions),
@ -258,13 +258,13 @@ define([
type: 'checkbox', type: 'checkbox',
name: 'cp-share-embed' name: 'cp-share-embed'
}), }),
h('label', { 'for': 'cp-share-embed' }, Messages.share_linkEmbed), h('label', { 'for': 'cp-share-embed' }, Messages.share_linkEmbed),
h('br'), h('br'),
h('input#cp-share-present', { h('input#cp-share-present', {
type: 'checkbox', type: 'checkbox',
name: 'cp-share-present' name: 'cp-share-present'
}), }),
h('label', { 'for': 'cp-share-present' }, Messages.share_linkPresent), h('label', { 'for': 'cp-share-present' }, Messages.share_linkPresent),
h('br'), h('br'),
h('br'), h('br'),
UI.dialog.selectable('', { id: 'cp-share-link-preview' }) UI.dialog.selectable('', { id: 'cp-share-link-preview' })
@ -366,7 +366,7 @@ define([
}); });
} }
common.getAttribute(['general', 'share'], function (err, val) { common.getAttribute(['general', 'share'], function (err, val) {
val = val || {}; val = val || {};
if (val.edit === false) { if (val.edit === false) {
$(link).find('#cp-share-editable-false').attr('checked', true); $(link).find('#cp-share-editable-false').attr('checked', true);
} }
@ -530,7 +530,7 @@ define([
var meta; var meta;
if (Array.isArray(parsed) && typeof(parsed[3]) === "object") { if (Array.isArray(parsed) && typeof(parsed[3]) === "object") {
meta = parsed[3].metadata; // pad meta = parsed[3].metadata; // pad
} else if (parsed.info) { } else if (parsed.info) {
meta = parsed.info; // poll meta = parsed.info; // poll
} else { } else {
meta = parsed.metadata; meta = parsed.metadata;
@ -572,7 +572,7 @@ define([
UI.confirm(msg, function (yes) { UI.confirm(msg, function (yes) {
if (!yes) { return; } if (!yes) { return; }
sframeChan.query('Q_MOVE_TO_TRASH', null, function (err) { sframeChan.query('Q_MOVE_TO_TRASH', null, function (err) {
if (err) { return void callback(err); } if (err) { return void callback(err); }
var cMsg = common.isLoggedIn() ? Messages.movedToTrash : Messages.deleted; var cMsg = common.isLoggedIn() ? Messages.movedToTrash : Messages.deleted;
UI.alert(cMsg, undefined, true); UI.alert(cMsg, undefined, true);
callback(); callback();
@ -702,7 +702,7 @@ define([
}, },
'heading': { 'heading': {
apply: function (str) { apply: function (str) {
return '\n'+clean(str).split('\n').map(function (line) { return '\n'+clean(str).split('\n').map(function (line) {
return '# '+line; return '# '+line;
}).join('\n')+'\n'; }).join('\n')+'\n';
}, },
@ -714,7 +714,7 @@ define([
}, },
'quote': { 'quote': {
apply: function (str) { apply: function (str) {
return '\n\n'+str.split('\n').map(function (line) { return '\n\n'+str.split('\n').map(function (line) {
return '> '+line; return '> '+line;
}).join('\n')+'\n\n'; }).join('\n')+'\n\n';
}, },
@ -722,7 +722,7 @@ define([
}, },
'nlist': { 'nlist': {
apply: function (str) { apply: function (str) {
return '\n'+clean(str).split('\n').map(function (line) { return '\n'+clean(str).split('\n').map(function (line) {
return '1. '+line; return '1. '+line;
}).join('\n')+'\n'; }).join('\n')+'\n';
}, },
@ -730,7 +730,7 @@ define([
}, },
'list': { 'list': {
apply: function (str) { apply: function (str) {
return '\n'+clean(str).split('\n').map(function (line) { return '\n'+clean(str).split('\n').map(function (line) {
return '* '+line; return '* '+line;
}).join('\n')+'\n'; }).join('\n')+'\n';
}, },
@ -738,8 +738,8 @@ define([
}, },
'check': { 'check': {
apply: function (str) { apply: function (str) {
return '\n' + clean(str).split('\n').map(function (line) { return '\n' + clean(str).split('\n').map(function (line) {
return '* [ ] ' + line; return '* [ ] ' + line;
}).join('\n') + '\n'; }).join('\n') + '\n';
}, },
icon: 'fa-check-square-o' icon: 'fa-check-square-o'
@ -1673,13 +1673,13 @@ define([
value: 1, value: 1,
checked: 'checked' checked: 'checked'
}), }),
h('label', { 'for': 'cp-creation-owned-true' }, Messages.creation_ownedTrue), h('label', { 'for': 'cp-creation-owned-true' }, Messages.creation_ownedTrue),
h('input#cp-creation-owned-false.cp-creation-owned-value', { h('input#cp-creation-owned-false.cp-creation-owned-value', {
type: 'radio', type: 'radio',
name: 'cp-creation-owned', name: 'cp-creation-owned',
value: 0 value: 0
}), }),
h('label', { 'for': 'cp-creation-owned-false' }, Messages.creation_ownedFalse) h('label', { 'for': 'cp-creation-owned-false' }, Messages.creation_ownedFalse)
]); ]);
$creation.append(owned); $creation.append(owned);
@ -1701,13 +1701,13 @@ define([
value: 0, value: 0,
checked: 'checked' checked: 'checked'
}), }),
h('label', { 'for': 'cp-creation-expire-false' }, Messages.creation_expireFalse), h('label', { 'for': 'cp-creation-expire-false' }, Messages.creation_expireFalse),
h('input#cp-creation-expire-true.cp-creation-expire-value', { h('input#cp-creation-expire-true.cp-creation-expire-value', {
type: 'radio', type: 'radio',
name: 'cp-creation-expire', name: 'cp-creation-expire',
value: 1 value: 1
}), }),
h('label', { 'for': 'cp-creation-expire-true' }, [ h('label', { 'for': 'cp-creation-expire-true' }, [
Messages.creation_expireTrue, Messages.creation_expireTrue,
h('span.cp-creation-expire-picker', [ h('span.cp-creation-expire-picker', [
h('input#cp-creation-expire-val', { h('input#cp-creation-expire-val', {

@ -1,126 +1,127 @@
define(function () { define([
'/code/orgmode.js'
], function () {
var Modes = {}; var Modes = {};
// mode language (extension) // mode language (extension)
var list = Modes.list = [ var list = Modes.list = [
"apl apl .apl", "APL apl .apl",
"asciiarmor asciiarmor", "ASCII-Armor asciiarmor",
"asn.1 asn.1", "ASN.1 asn.1",
"asterisk asterisk", "Asterisk asterisk",
"brainfuck brainfuck .b", "Brainfuck brainfuck .b",
"clike clike", "C-like clike",
"clojure clojure", "Clojure clojure",
"cmake cmake", "CMake cmake",
"cobol cobol", "COBOL cobol",
"coffeescript coffeescript", "CoffeeScript coffeescript",
"commonlisp commonlisp", "Common_Lisp commonlisp",
"crystal crystal", "Crystal crystal",
"css css .css", "CSS css .css",
"cypher cypher", "Cypher cypher",
"d d", "D d",
"dart dart", "Dart dart",
"diff diff", "Diff diff",
"django django", "Django django",
"dockerfile dockerfile", "Dockerfile dockerfile",
"dtd dtd", "DTD dtd",
"dylan dylan", "Dylan dylan",
"ebnf ebnf", "EBNF ebnf",
"ecl ecl", "ECL ecl",
"eiffel eiffel", "Eiffel eiffel",
"elm elm .elm", "Elm elm .elm",
"erlang erlang", "Erlang erlang",
"factor factor", "Factor factor",
"fcl fcl", "FCL fcl",
"forth forth", "Forth forth",
"fortran fortran", "Fortran fortran",
"gas gas", "GAS gas",
"gfm gfm .md", "Gherkin gherkin",
"gherkin gherkin", "Go go",
"go go", "Groovy groovy",
"groovy groovy", "Haml haml",
"haml haml", "Handlebars handlebars",
"handlebars handlebars", "Haskell haskell .hs",
"haskell haskell .hs", "Haskell-Literate haskell-literate",
"haskell-literate haskell-literate", "Haxe haxe",
"haxe haxe", "HTML htmlmixed .html",
"htmlembedded htmlembedded", "HTTP http",
"htmlmixed htmlmixed .html", "IDL idl",
"http http", "JADE jade",
"idl idl", "JavaScript javascript .js",
"index.html index.html", "Jinja2 jinja2",
"jade jade", "JSX jsx .jsx",
"javascript javascript .js", "Julia julia",
"jinja2 jinja2", "LiveScript livescript",
"jsx jsx .jsx", "Lua lua",
"julia julia", "Markdown gfm .md",
"livescript livescript", //"markdown markdown .md",
"lua lua", "Mathematica mathematica",
"markdown markdown .md", "mIRC mirc",
"mathematica mathematica", "ML mllike",
"mirc mirc", "Modelica modelica",
"mllike mllike", "MscGen mscgen",
"modelica modelica", "MUMPS mumps",
"mscgen mscgen", "Nginx nginx",
"mumps mumps", "NSIS nsis",
"nginx nginx", "N-Triples ntriples",
"nsis nsis", "Octave octave",
"ntriples ntriples", "Org-mode orgmode .org",
"octave octave", "Oz oz",
"oz oz", "Pascal pascal",
"pascal pascal", "PEG.js pegjs",
"pegjs pegjs", "Perl perl",
"perl perl", "PHP php",
"php php", "Pig pig",
"pig pig", "Properties properties",
"properties properties", "Protocol_Buffers protobuf",
"protobuf protobuf", "Puppet puppet",
"puppet puppet", "Python python .py",
"python python .py", "Q q",
"q q", "R r",
"r r", "RPM rpm",
"rpm rpm", "RST rst",
"rst rst", "Ruby ruby",
"ruby ruby", "Rust rust",
"rust rust", "Sass sass",
"sass sass", "Scheme scheme .scm",
"scheme scheme .scm", "Shell shell .sh",
"shell shell .sh", "Sieve sieve",
"sieve sieve", "Slim slim",
"slim slim", "Smalltalk smalltalk",
"smalltalk smalltalk", "Smarty smarty",
"smarty smarty", "Solr solr",
"solr solr", "Soy soy",
"soy soy", "SPARQL sparql",
"sparql sparql", "Spreadsheet spreadsheet",
"spreadsheet spreadsheet", "SQL sql",
"sql sql", "sTeX stex",
"stex stex", "Stylus stylus",
"stylus stylus", "Swift swift",
"swift swift", "Tcl tcl",
"tcl tcl", "Text text .txt",
"text text .txt", "Textile textile",
"textile textile", "TiddlyWiki tiddlywiki",
"tiddlywiki tiddlywiki", "Tiki tiki",
"tiki tiki", "TOML toml",
"toml toml", "Tornado tornado",
"tornado tornado",
"troff troff", "troff troff",
"ttcn ttcn", "TTCN ttcn",
"ttcn-cfg ttcn-cfg", "TTCN-cfg ttcn-cfg",
"turtle turtle", "Turtle turtle",
"twig twig", "Twig twig",
"vb vb", "Visual_Basic vb",
"vbscript vbscript", "VBScript vbscript",
"velocity velocity", "Velocity velocity",
"verilog verilog", "Verilog verilog",
"vhdl vhdl", "VHDL vhdl",
"vue vue", "Vue vue",
"xml xml", "XML xml",
//"xwiki xwiki21", //"xwiki xwiki21",
"xquery xquery", "XQuery xquery",
"yaml yaml .yaml", "YAML yaml .yaml",
"yaml-frontmatter yaml-frontmatter", "YAML_Frontmatter yaml-frontmatter",
"z80 z80" "Z80 z80"
].map(function (line) { ].map(function (line) {
var kv = line.split(/\s/); var kv = line.split(/\s/);
return { return {

@ -146,6 +146,7 @@ define([
var setMode = exp.setMode = function (mode, cb) { var setMode = exp.setMode = function (mode, cb) {
exp.highlightMode = mode; exp.highlightMode = mode;
if (mode === 'markdown') { mode = 'gfm'; }
if (mode !== "text") { if (mode !== "text") {
CMeditor.autoLoadMode(editor, mode); CMeditor.autoLoadMode(editor, mode);
} }

Loading…
Cancel
Save