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/fold/foldgutter.css',
'cm/mode/markdown/markdown',
'cm/mode/gfm/gfm',
'cm/addon/mode/loadmode',
'cm/mode/meta',
'cm/addon/mode/overlay',
@ -80,7 +80,7 @@ define([
} catch (e) { console.error(e); }
};
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; }
forceDrawPreview();
}, 150);
@ -98,7 +98,7 @@ define([
previewTo = setTimeout(function () {
$codeMirror.removeClass('transition');
}, 500);
if (CodeMirror.highlightMode !== 'markdown') {
if (['markdown', 'gfm'].indexOf(CodeMirror.highlightMode) === -1) {
$previewContainer.show();
}
$previewContainer.toggle();
@ -132,7 +132,7 @@ define([
});
var modeChange = function (mode) {
if (mode === "markdown") {
if (['markdown', 'gfm'].indexOf(mode) !== -1) {
$previewButton.show();
framework._.sfCommon.getPadAttribute('previewMode', function (e, data) {
if (e) { return void console.error(e); }
@ -293,7 +293,7 @@ define([
framework.onReady(function (newPad) {
if (newPad && !CodeMirror.highlightMode) {
CodeMirror.setMode('markdown', evModeChange.fire);
CodeMirror.setMode('gfm', evModeChange.fire);
//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,
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', {
type: 'radio',
name: 'cp-share-editable',
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('label', Messages.share_linkOptions),
@ -258,13 +258,13 @@ define([
type: 'checkbox',
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('input#cp-share-present', {
type: 'checkbox',
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'),
UI.dialog.selectable('', { id: 'cp-share-link-preview' })
@ -366,7 +366,7 @@ define([
});
}
common.getAttribute(['general', 'share'], function (err, val) {
val = val || {};
val = val || {};
if (val.edit === false) {
$(link).find('#cp-share-editable-false').attr('checked', true);
}
@ -530,7 +530,7 @@ define([
var meta;
if (Array.isArray(parsed) && typeof(parsed[3]) === "object") {
meta = parsed[3].metadata; // pad
} else if (parsed.info) {
} else if (parsed.info) {
meta = parsed.info; // poll
} else {
meta = parsed.metadata;
@ -572,7 +572,7 @@ define([
UI.confirm(msg, function (yes) {
if (!yes) { return; }
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;
UI.alert(cMsg, undefined, true);
callback();
@ -702,7 +702,7 @@ define([
},
'heading': {
apply: function (str) {
return '\n'+clean(str).split('\n').map(function (line) {
return '\n'+clean(str).split('\n').map(function (line) {
return '# '+line;
}).join('\n')+'\n';
},
@ -714,7 +714,7 @@ define([
},
'quote': {
apply: function (str) {
return '\n\n'+str.split('\n').map(function (line) {
return '\n\n'+str.split('\n').map(function (line) {
return '> '+line;
}).join('\n')+'\n\n';
},
@ -722,7 +722,7 @@ define([
},
'nlist': {
apply: function (str) {
return '\n'+clean(str).split('\n').map(function (line) {
return '\n'+clean(str).split('\n').map(function (line) {
return '1. '+line;
}).join('\n')+'\n';
},
@ -730,7 +730,7 @@ define([
},
'list': {
apply: function (str) {
return '\n'+clean(str).split('\n').map(function (line) {
return '\n'+clean(str).split('\n').map(function (line) {
return '* '+line;
}).join('\n')+'\n';
},
@ -738,8 +738,8 @@ define([
},
'check': {
apply: function (str) {
return '\n' + clean(str).split('\n').map(function (line) {
return '* [ ] ' + line;
return '\n' + clean(str).split('\n').map(function (line) {
return '* [ ] ' + line;
}).join('\n') + '\n';
},
icon: 'fa-check-square-o'
@ -1673,13 +1673,13 @@ define([
value: 1,
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', {
type: 'radio',
name: 'cp-creation-owned',
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);
@ -1701,13 +1701,13 @@ define([
value: 0,
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', {
type: 'radio',
name: 'cp-creation-expire',
value: 1
}),
h('label', { 'for': 'cp-creation-expire-true' }, [
h('label', { 'for': 'cp-creation-expire-true' }, [
Messages.creation_expireTrue,
h('span.cp-creation-expire-picker', [
h('input#cp-creation-expire-val', {

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

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

Loading…
Cancel
Save