starting to come together I realized I'm going to have to seperate selection and filter state And do actions based on that, some how show that different context depending on which action is selected
163 lines
3.6 KiB
Plaintext
163 lines
3.6 KiB
Plaintext
{
|
|
function makeCommand(type, filters, parts) {
|
|
|
|
const validParts = parts || [];
|
|
// Extract pure description (without attributes)
|
|
const description = validParts
|
|
.filter(part => part.type === 'text')
|
|
.map(part => part.value)
|
|
.join(' ')
|
|
.trim();
|
|
|
|
// Collect all attributes
|
|
const attributes = validParts
|
|
.filter(part => part.type !== 'text')
|
|
.filter(part => part !== null);
|
|
|
|
const project = validParts
|
|
.filter(part => part.type === 'project')
|
|
.map(part => part.value)
|
|
.join('')
|
|
.trim();
|
|
|
|
const tags = validParts
|
|
.filter(part => part.type === 'tag')
|
|
.map(part => part.value);
|
|
|
|
|
|
// Store original parts for reconstruction
|
|
const originalParts = validParts.filter(part => part !== null);
|
|
let validFilters;
|
|
if (!!filters) {
|
|
validFilters = filters.flat();
|
|
} else {
|
|
validFilters = [];
|
|
}
|
|
|
|
return {
|
|
type: type,
|
|
description: description || [],
|
|
attributes: attributes || [],
|
|
filters: validFilters,
|
|
project: project,
|
|
tags: JSON.stringify(tags),
|
|
parts: parts || [],
|
|
reconstruct: function() {
|
|
const filterStr = this.filters.map(f => f.reconstruct()).join(',');
|
|
const partsStr = this.parts.map(p => p.reconstruct()).join(' ');
|
|
return [filterStr, this.type, partsStr].filter(Boolean).join(' ');
|
|
}
|
|
};
|
|
}
|
|
}
|
|
|
|
Start = AddCommand / DoneCommand / ExplicitFilterCommand / ImplicitFilterCommand
|
|
|
|
// ADD COMMAND
|
|
AddCommand = "add" _ parts:(Part / _)+ EOF {
|
|
return makeCommand('add', null, parts.filter(p => p !== null));
|
|
}
|
|
|
|
// DONE COMMAND
|
|
DoneCommand = "done" _ filters:Filters EOF {
|
|
return makeCommand('done', filters, null);
|
|
}
|
|
|
|
ExplicitFilterCommand = filters:Filters _ "filter" _* moreFilters:Filters* EOF {
|
|
return makeCommand('filter', [...filters, ...moreFilters], null);
|
|
}
|
|
|
|
ImplicitFilterCommand = filters:Filters+ EOF {
|
|
return makeCommand('filter', filters, null);
|
|
}
|
|
|
|
Filters = first:Filter rest:(_ Filter)* {
|
|
return [first, ...rest.map(r => r[1])];
|
|
}
|
|
|
|
|
|
IdRange = start:Integer "-" end:Integer {
|
|
const ids = [];
|
|
for (let i = start; i <= end; i++) {
|
|
ids.push(i);
|
|
}
|
|
return ids;
|
|
}
|
|
|
|
SingleId = id:Integer {
|
|
return [id];
|
|
}
|
|
|
|
Filter = IdFilter / Tag / Project / Priority / Due
|
|
|
|
IdFilter = first:(IdRange / SingleId) rest:("," (IdRange / SingleId))* trailing:"," ? {
|
|
const ids = [first, ...rest.map(r => r[1])].flat();
|
|
return {
|
|
type: 'id',
|
|
ids: ids,
|
|
reconstruct: function() { return this.ids.join(','); }
|
|
};
|
|
}
|
|
|
|
Part = Attribute / TextPart
|
|
|
|
TextPart = chars:Word {
|
|
return {
|
|
type: "text",
|
|
value: chars,
|
|
reconstruct: function() { return this.value; }
|
|
};
|
|
}
|
|
|
|
Attribute = Due / Tag / Project / Priority
|
|
|
|
Due = "@" value:TimeValue {
|
|
return {
|
|
type: "due",
|
|
value: value,
|
|
reconstruct: function() { return `@${this.value}`; }
|
|
};
|
|
}
|
|
|
|
Project = ("pro:" / "project:" / "+") value:Word {
|
|
return {
|
|
type: "project",
|
|
value: value,
|
|
reconstruct: function() { return `+${this.value}`; }
|
|
};
|
|
}
|
|
|
|
Priority = "priority:" value:[HML] {
|
|
return {
|
|
type: "priority",
|
|
value: value,
|
|
reconstruct: function() { return `priority:${this.value}`; }
|
|
};
|
|
}
|
|
|
|
Tag = "#" value:Word {
|
|
return {
|
|
type: "tag",
|
|
value: value,
|
|
reconstruct: function() { return `#${this.value}`; }
|
|
};
|
|
}
|
|
|
|
Integer = digits:[0-9]+ {
|
|
return parseInt(digits.join(''), 10);
|
|
}
|
|
|
|
TimeValue = chars:[0-9:]+ ("am" / "pm")? {
|
|
return chars.join('') + (text() || '');
|
|
}
|
|
|
|
Word = chars:[a-zA-Z0-9_-]+ {
|
|
return chars.join('');
|
|
}
|
|
|
|
_ = [ \t]+ {
|
|
return null;
|
|
}
|
|
|
|
EOF = !.
|