Compare commits
2 Commits
f1f87bc8e8
...
cf21e4c7a7
| Author | SHA1 | Date | |
|---|---|---|---|
|
cf21e4c7a7
|
|||
|
739a5d9721
|
@@ -1,6 +1,119 @@
|
|||||||
start = task
|
start = _ @(task / line) _
|
||||||
|
|
||||||
task = "-" _ "[" status:. "]" { return status; }
|
/**************************************************************************************************************************************/
|
||||||
|
|
||||||
|
line = data:.+ {
|
||||||
|
return {
|
||||||
|
type: "line",
|
||||||
|
data: data.join("")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************************************************************************/
|
||||||
|
|
||||||
|
task = "-" _ "[" status:. "]" _ label:label meta:meta* {
|
||||||
|
return {
|
||||||
|
type: "task",
|
||||||
|
data: {
|
||||||
|
status,
|
||||||
|
label,
|
||||||
|
meta
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
label = text:([^⏬🔽🔼⏫🔺➕⏳🛫📅✅❌🔁🏁🆔⛔⏰]*) {
|
||||||
|
return text.join("").trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
meta = _ @(date / recurrence / delete / priority / dependency / reminder) _
|
||||||
|
|
||||||
|
/**************************************************************************************************************************************/
|
||||||
|
|
||||||
|
priority = priority:priorityIcon {
|
||||||
|
return {
|
||||||
|
feature: "priority",
|
||||||
|
priority
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************************************************************************/
|
||||||
|
|
||||||
|
delete = type:deleteIcon _ action:[a-zA-Z]+ {
|
||||||
|
return {
|
||||||
|
feature: "delete",
|
||||||
|
action: action.join("").trim()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************************************************************************/
|
||||||
|
|
||||||
|
reminder = reminderIcon _ time:(longTime / shortTime)? {
|
||||||
|
return {
|
||||||
|
feature: "reminder",
|
||||||
|
time
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
longTime = hour:[0-9]|1..2| ":" minute:[0-9]|1..2| {
|
||||||
|
return `${hour.join("").padStart(2, '0')}:${minute.join("").padStart(2, '0')}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
shortTime = hour:[0-9]|1..2| {
|
||||||
|
return `${hour.join("").padStart(2, '0')}:00`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************************************************************************/
|
||||||
|
|
||||||
|
recurrence = type:recurrenceIcon _ rec:[a-zA-Z0-9 ]+ {
|
||||||
|
return {
|
||||||
|
feature: "recurrence",
|
||||||
|
rule: rec.join("").trim()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************************************************************************/
|
||||||
|
|
||||||
|
date = type:dateIcon _ date:dateLiteral {
|
||||||
|
return {
|
||||||
|
feature: "date",
|
||||||
|
type,
|
||||||
|
date
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
dateLiteral = year:([0-9]|4|) "-" month:([0-9]|1..2|) "-" day:([0-9]|1..2|) {
|
||||||
|
return `${year.join("")}-${month.join("").padStart(2, '0')}-${day.join("").padStart(2, '0')}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************************************************************************/
|
||||||
|
|
||||||
|
dependency = type:dependencyIcon _ deps:([a-zA-Z0-9]+)|..,(_ "," _)| {
|
||||||
|
return {
|
||||||
|
feature: "dependency",
|
||||||
|
type,
|
||||||
|
deps: deps.map(x => x.join(""))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************************************************************************************/
|
||||||
|
|
||||||
|
allIcons = dependencyIcon / recurrenceIcon / deleteIcon / reminderIcon / dateIcon / priority
|
||||||
|
dependencyIcon = "🆔" / "⛔"
|
||||||
|
recurrenceIcon = "🔁"
|
||||||
|
deleteIcon = "🏁"
|
||||||
|
reminderIcon = "⏰"
|
||||||
|
dateIcon = "➕"
|
||||||
|
/"⏳"
|
||||||
|
/"🛫"
|
||||||
|
/"📅"
|
||||||
|
/"✅"
|
||||||
|
/"❌"
|
||||||
|
priorityIcon = "⏬"
|
||||||
|
/"🔽"
|
||||||
|
/"🔼"
|
||||||
|
/"⏫"
|
||||||
|
/"🔺"
|
||||||
|
|
||||||
_ "whitespace"
|
_ "whitespace"
|
||||||
= [ \t\n\r]*
|
= [ \t\r]*
|
||||||
15
src/parser/index.ts
Normal file
15
src/parser/index.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import {parse as rawParse} from "../generated/grammar/task";
|
||||||
|
import { ParseResult } from "../types/grammar/task";
|
||||||
|
import { Task } from "../types/task";
|
||||||
|
import { LazyTask } from "./task";
|
||||||
|
|
||||||
|
export function parse(line: string): Task|undefined {
|
||||||
|
const item = rawParse(line) as ParseResult;
|
||||||
|
|
||||||
|
if (item.type === 'task') {
|
||||||
|
return new LazyTask(item.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
88
src/parser/task.ts
Normal file
88
src/parser/task.ts
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
import { ParsedTask, ParsedTaskDate, ParsedTaskDependency, ParsedTaskMeta } from "../types/grammar/task";
|
||||||
|
import { Task, TaskPriority } from "../types/task";
|
||||||
|
|
||||||
|
export class LazyTask implements Task {
|
||||||
|
#parsed: ParsedTask;
|
||||||
|
#dates: ParsedTaskDate[];
|
||||||
|
|
||||||
|
constructor(task: ParsedTask) {
|
||||||
|
this.#parsed = task;
|
||||||
|
this.#dates = task.meta.filter(x => x.feature === 'date');
|
||||||
|
}
|
||||||
|
|
||||||
|
get status(): string {
|
||||||
|
return this.#parsed.status;
|
||||||
|
}
|
||||||
|
|
||||||
|
get label(): string {
|
||||||
|
return this.#parsed.label;
|
||||||
|
}
|
||||||
|
|
||||||
|
get priority(): TaskPriority {
|
||||||
|
const priority = this.#parsed.meta.find(x => x.feature === 'priority')?.priority;
|
||||||
|
|
||||||
|
if(!priority) {
|
||||||
|
return "normal";
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
'⏬': 'lowest',
|
||||||
|
'🔽': 'low',
|
||||||
|
'🔼': 'medium',
|
||||||
|
'⏫': 'high',
|
||||||
|
'🔺': 'highest'
|
||||||
|
}[priority] as TaskPriority;
|
||||||
|
}
|
||||||
|
|
||||||
|
get createdDate(): string|undefined {
|
||||||
|
return this.#dates.find(d => d.type === '➕')?.date;
|
||||||
|
}
|
||||||
|
|
||||||
|
get startDate(): string|undefined {
|
||||||
|
return this.#dates.find(d => d.type === '🛫')?.date;
|
||||||
|
}
|
||||||
|
|
||||||
|
get scheduledDate(): string|undefined {
|
||||||
|
return this.#dates.find(d => d.type === '⏳')?.date;
|
||||||
|
}
|
||||||
|
|
||||||
|
get dueDate(): string|undefined {
|
||||||
|
return this.#dates.find(d => d.type === '📅')?.date;
|
||||||
|
}
|
||||||
|
|
||||||
|
get completedDate(): string|undefined {
|
||||||
|
return this.#dates.find(d => d.type === '✅')?.date;
|
||||||
|
}
|
||||||
|
|
||||||
|
get cancelledDate(): string|undefined {
|
||||||
|
return this.#dates.find(d => d.type === '❌')?.date;
|
||||||
|
}
|
||||||
|
|
||||||
|
get recurrencyRule(): string|undefined {
|
||||||
|
return this.#parsed.meta.find(x => x.feature === 'recurrence')?.rule;
|
||||||
|
}
|
||||||
|
|
||||||
|
get onDelete(): string|undefined {
|
||||||
|
return this.#parsed.meta.find(x => x.feature === 'delete')?.action;
|
||||||
|
}
|
||||||
|
|
||||||
|
get id(): string|undefined {
|
||||||
|
return this.#features<ParsedTaskDependency>("dependency").find(x => x.type === '🆔')?.deps?.[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
#features <T = ParsedTaskMeta>(feature: ParsedTask['meta'][0]['feature']): T[] {
|
||||||
|
return this.#parsed.meta.filter(x => x.feature === feature) as T[]
|
||||||
|
}
|
||||||
|
|
||||||
|
get dependsOn(): string[] {
|
||||||
|
return this.#features<ParsedTaskDependency>("dependency").find(x => x.type === '⛔')?.deps || [];
|
||||||
|
}
|
||||||
|
|
||||||
|
get reminder(): string|undefined {
|
||||||
|
return this.#parsed.meta.find(x => x.feature === 'reminder')?.time;
|
||||||
|
}
|
||||||
|
|
||||||
|
toString() {
|
||||||
|
return `Task[status=${this.status}, label=${this.label}, priority=${this.priority}, created=${this.createdDate}, start=${this.startDate}, scheduled=${this.scheduledDate}, due=${this.dueDate}, completed=${this.completedDate}, cancelled=${this.cancelledDate}, recurrence=${this.recurrencyRule}, onDelete=${this.onDelete}, id=${this.id}, dependsOn=${this.dependsOn}, reminder=${this.reminder}]`
|
||||||
|
}
|
||||||
|
}
|
||||||
53
src/types/grammar/task.ts
Normal file
53
src/types/grammar/task.ts
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
export type ParseResult = {
|
||||||
|
type: 'line';
|
||||||
|
data: string;
|
||||||
|
} | {
|
||||||
|
type: 'task';
|
||||||
|
data: ParsedTask;
|
||||||
|
};
|
||||||
|
|
||||||
|
export type ParsedTask = {
|
||||||
|
status: string;
|
||||||
|
label: string;
|
||||||
|
meta: ParsedTaskMeta[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ParsedTaskMeta =
|
||||||
|
| ParsedTaskPriority
|
||||||
|
| ParsedTaskRecurrence
|
||||||
|
| ParsedTaskDelete
|
||||||
|
| ParsedTaskDate
|
||||||
|
| ParsedTaskDependency
|
||||||
|
| ParsedTaskReminder;
|
||||||
|
|
||||||
|
export type ParsedTaskPriority = {
|
||||||
|
feature: 'priority';
|
||||||
|
priority: '⏬'|'🔽'|'🔼'|'⏫'|'🔺';
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ParsedTaskRecurrence = {
|
||||||
|
feature: 'recurrence';
|
||||||
|
rule: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ParsedTaskDelete = {
|
||||||
|
feature: 'delete';
|
||||||
|
action: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ParsedTaskDate = {
|
||||||
|
feature: 'date';
|
||||||
|
type: '➕'|'⏳'|'🛫'|'📅'|'✅'|'❌';
|
||||||
|
date: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ParsedTaskDependency = {
|
||||||
|
feature: 'dependency';
|
||||||
|
type: '🆔'|'⛔';
|
||||||
|
deps: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ParsedTaskReminder = {
|
||||||
|
feature: 'reminder';
|
||||||
|
time: string;
|
||||||
|
}
|
||||||
24
src/types/task.ts
Normal file
24
src/types/task.ts
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
export type Task = {
|
||||||
|
status: string;
|
||||||
|
label: string;
|
||||||
|
priority: TaskPriority;
|
||||||
|
createdDate?: string;
|
||||||
|
startDate?: string;
|
||||||
|
scheduledDate?: string;
|
||||||
|
dueDate?: string;
|
||||||
|
completedDate?: string;
|
||||||
|
cancelledDate?: string;
|
||||||
|
recurrencyRule?: string;
|
||||||
|
onDelete?: string;
|
||||||
|
id?: string;
|
||||||
|
dependsOn?: string[];
|
||||||
|
reminder?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type TaskPriority =
|
||||||
|
| 'lowest'
|
||||||
|
| 'low'
|
||||||
|
| 'normal'
|
||||||
|
| 'medium'
|
||||||
|
| 'high'
|
||||||
|
| 'highest';
|
||||||
Reference in New Issue
Block a user