diff options
Diffstat (limited to 'tiddlers/plugin-org-gtd-library.tid')
| -rw-r--r-- | tiddlers/plugin-org-gtd-library.tid | 141 |
1 files changed, 141 insertions, 0 deletions
diff --git a/tiddlers/plugin-org-gtd-library.tid b/tiddlers/plugin-org-gtd-library.tid new file mode 100644 index 0000000..af41028 --- /dev/null +++ b/tiddlers/plugin-org-gtd-library.tid @@ -0,0 +1,141 @@ +title: $:/plugins/local/org-gtd/library.js +type: application/javascript +module-type: library + +/*\ +title: $:/plugins/local/org-gtd/library.js +type: application/javascript +module-type: library +\*/ +(function() { +"use strict"; + +var TODO_STATES = ["TODO","NEXT","WAIT","DONE"], + TODO_LOOKUP = Object.create(null), + HEADING_PATTERN = /^(\*+)\s+(?:(TODO|NEXT|WAIT|DONE)\s+)?(.*)$/, + TAG_PATTERN = /\s+:([A-Za-z0-9_@#%+.-]+(?::[A-Za-z0-9_@#%+.-]+)*):\s*$/, + DATE_PATTERN = /\b(SCHEDULED|DEADLINE):\s*<([0-9]{4}-[0-9]{2}-[0-9]{2})(?:\s+[^>]*)?>/g; + +TODO_STATES.forEach(function(state) { + TODO_LOOKUP[state] = true; +}); + +function parseHeading(line,lineIndex) { + var match = HEADING_PATTERN.exec(line), + tagMatch, + title, + tags = []; + if(!match) { + return null; + } + title = match[3]; + tagMatch = TAG_PATTERN.exec(title); + if(tagMatch) { + tags = tagMatch[1].split(":"); + title = title.substring(0,tagMatch.index).trim(); + } + return { + level: match[1].length, + state: match[2] || "", + title: title, + tags: tags, + line: lineIndex, + sourceLine: lineIndex + 1, + endLine: lineIndex, + scheduled: "", + deadline: "" + }; +} + +function parse(text) { + var lines = (text || "").split("\n"), + headings = [], + current = null; + lines.forEach(function(line,index) { + var heading = parseHeading(line,index), + match; + if(heading) { + if(current) { + current.endLine = index - 1; + } + headings.push(heading); + current = heading; + return; + } + if(current) { + DATE_PATTERN.lastIndex = 0; + while((match = DATE_PATTERN.exec(line)) !== null) { + if(match[1] === "SCHEDULED") { + current.scheduled = match[2]; + } else { + current.deadline = match[2]; + } + } + } + }); + if(current) { + current.endLine = lines.length - 1; + } + for(var index = 0; index < headings.length; index++) { + var heading = headings[index], + nextIndex = index + 1; + while(nextIndex < headings.length && headings[nextIndex].level > heading.level) { + nextIndex++; + } + heading.subtreeEndLine = nextIndex < headings.length ? headings[nextIndex].line - 1 : lines.length - 1; + } + return {lines: lines,headings: headings}; +} + +function headingAtLine(parsed,line) { + var result = null; + parsed.headings.forEach(function(heading) { + if(heading.line <= line && heading.subtreeEndLine >= line) { + if(!result || heading.level >= result.level) { + result = heading; + } + } + }); + return result; +} + +function cycleState(line) { + var heading = parseHeading(line,0), + stars, + nextState, + rest; + if(!heading) { + return null; + } + stars = new Array(heading.level + 1).join("*"); + if(heading.state) { + nextState = TODO_STATES[(TODO_STATES.indexOf(heading.state) + 1) % TODO_STATES.length]; + rest = line.replace(/^(\*+)\s+(?:TODO|NEXT|WAIT|DONE)\s+/,"$1 " + nextState + " "); + } else { + rest = line.replace(/^(\*+)\s+/,"$1 TODO "); + } + return {line: rest,state: nextState || "TODO",level: stars.length}; +} + +function dateToTime(value) { + var match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value || ""), + date; + if(!match) { + return NaN; + } + date = new Date(Number(match[1]),Number(match[2]) - 1,Number(match[3])); + if(date.getFullYear() !== Number(match[1]) || date.getMonth() !== Number(match[2]) - 1 || date.getDate() !== Number(match[3])) { + return NaN; + } + return date.getTime(); +} + +exports.TODO_STATES = TODO_STATES; +exports.TODO_LOOKUP = TODO_LOOKUP; +exports.parseHeading = parseHeading; +exports.parse = parse; +exports.headingAtLine = headingAtLine; +exports.cycleState = cycleState; +exports.dateToTime = dateToTime; + +})(); |
