diff --git a/src/parser/index.ts b/src/parser/index.ts new file mode 100644 index 0000000..295a365 --- /dev/null +++ b/src/parser/index.ts @@ -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; +} + diff --git a/src/parser/task.ts b/src/parser/task.ts new file mode 100644 index 0000000..9fcd408 --- /dev/null +++ b/src/parser/task.ts @@ -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("dependency").find(x => x.type === '🆔')?.deps?.[0]; + } + + #features (feature: ParsedTask['meta'][0]['feature']): T[] { + return this.#parsed.meta.filter(x => x.feature === feature) as T[] + } + + get dependsOn(): string[] { + return this.#features("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}]` + } +} \ No newline at end of file diff --git a/src/types/grammar/task.ts b/src/types/grammar/task.ts new file mode 100644 index 0000000..e32f4cd --- /dev/null +++ b/src/types/grammar/task.ts @@ -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; +} \ No newline at end of file diff --git a/src/types/task.ts b/src/types/task.ts new file mode 100644 index 0000000..f863711 --- /dev/null +++ b/src/types/task.ts @@ -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'; \ No newline at end of file