diff options
Diffstat (limited to 'lua/lexers/todotxt.lua')
| -rw-r--r-- | lua/lexers/todotxt.lua | 54 |
1 files changed, 54 insertions, 0 deletions
diff --git a/lua/lexers/todotxt.lua b/lua/lexers/todotxt.lua new file mode 100644 index 0000000..a6d7565 --- /dev/null +++ b/lua/lexers/todotxt.lua @@ -0,0 +1,54 @@ +-- Copyright 2025 Chris Clark and Mitchell. See LICENSE. +-- todo.txt LPeg lexer. +-- https://github.com/too-much-todotxt/spec + +local lexer = lexer +local P, S = lpeg.P, lpeg.S + +local lex = lexer.new(...) + +-- Done/Complete items. +lex:add_rule('done', lex:tag(lexer.COMMENT, lexer.starts_line(lexer.to_eol('x ')))) + +-- Priority. +local priority = P(false) +for letter in string.gmatch('abcdefghijklmnopqrstuvwxyz', '.') do + local tag = lex:tag(lexer.LIST .. '.priority.' .. letter, + lexer.starts_line('(' .. letter:upper() .. ') ')) + priority = priority + tag +end +lex:add_rule('priority', priority) + +-- URLs, emails, and domain names. +-- Note: this is not part of todo.txt, but is an extension to make editing cleaner. +local nonspace = lexer.any - lexer.space +local email = lex:tag(lexer.LINK, + (nonspace - '@')^1 * '@' * (nonspace - '.')^1 * ('.' * (nonspace - S('.?'))^1)^1 * + ('?' * nonspace^1)^-1) +local host = lex:tag(lexer.LINK, + lexer.word_match('www ftp', true) * (nonspace - '.')^0 * '.' * (nonspace - '.')^1 * '.' * + (nonspace - S(',.'))^1) +local url = lex:tag(lexer.LINK, + (nonspace - '://')^1 * '://' * (nonspace - ',' - '.')^1 * ('.' * (nonspace - S(',./?#'))^1)^1 * + ('/' * (nonspace - S('./?#'))^0 * ('.' * (nonspace - S(',.?#'))^1)^0)^0 * + ('?' * (nonspace - '#')^1)^-1 * ('#' * nonspace^0)^-1) +local link = url + host + email +lex:add_rule('link', link) + +-- Key-value pairs. +local word = (lexer.any - lexer.space - P(':'))^1 +local key = lex:tag(lexer.KEYWORD, word) +local colon = lex:tag(lexer.OPERATOR, P(':')) +local value = lex:tag(lexer.STRING, word) +lex:add_rule('key_value', key * colon * value) + +-- Dates. +lex:add_rule('date', lex:tag(lexer.NUMBER, lexer.digit^4 * P('-') * lexer.digit^2 * P('-') * + lexer.digit^2 * (#lexer.space + P(-1)))) + +-- Project + +lex:add_rule('project', lex:tag(lexer.LABEL, lexer.range('+', lexer.space, true))) +-- Context @ +lex:add_rule('context', lex:tag(lexer.TYPE, lexer.range('@', lexer.space, true))) + +return lex |
