vis

a vi-like editor based on Plan 9's structural regular expressions

git clone https://9o.is/git/vis.git

org.lua

(3810B)


      1 -- Copyright 2025 Matěj Cepl (@mcepl everywhere). See LICENSE.
      2 -- Copyright 2012 joten
      3 -- Org agenda LPeg lexer.
      4 
      5 local lexer = lexer
      6 local word_match = lexer.word_match
      7 local P, R, S, V = lpeg.P, lpeg.R, lpeg.S, lpeg.V
      8 
      9 local lex = lexer.new(...)
     10 
     11 --[[Overview. Used examples.
     12 * Heading 1-5 (8)
     13 	TODO special color, bold
     14 	DONE special color, bold
     15 	[#priority]
     16 	:tag: bold
     17 <date> / [date] like heading 3, underlined
     18 	keywords: CLOSED: DEADLINE: SCHEDULED: like heading 3, not underlined
     19 | table | like heading 1
     20 [[link][description] ]
     21 formatting:
     22 	*bold*
     23 	/italic/
     24 	_underline_
     25 	+strike+
     26 --]]
     27 
     28 -- Font formats.
     29 lex:add_rule('bold', lex:tag('BOLD', '*' * lexer.word * '*'))
     30 lex:add_rule('italic', lex:tag('ITALIC', '/' * lexer.word * '/'))
     31 lex:add_rule('underline', lex:tag('UNDERLINE', '_' * lexer.alnum * '_'))
     32 
     33 -- ToDos.
     34 lex:add_rule('todo', lex:tag('TODO', lex:word_match('TODO')))
     35 lex:add_rule('done', lex:tag('DONE', lex:word_match('DONE')))
     36 lex:add_rule('wontfix', lex:tag('WONTFIX', lex:word_match('WONTFIX')))
     37 
     38 -- DateTime.
     39 local DD = lexer.digit * lexer.digit
     40 local time_range = (' ' * DD * ':' * DD)^0 * ('-' * DD * ':' * DD)^0
     41 local repeater = (' +' * lexer.integer * S('dwmy'))^0
     42 local alarm = (' -' * lexer.integer * S('dwmy'))^0
     43 local pattern_datetime1 = S('<[')^-1 * 'date' * 'wday' * time_range * repeater * alarm * S('>]')^-1
     44 local pattern_datetime2 = lexer.starts_line('weekday') * lexer.space^1 * DD * '. ' * 'month' *
     45 	lexer.space^1 * DD * DD
     46 local datetime = pattern_datetime1 + pattern_datetime2
     47 
     48 lex:add_rule('current_date', lex:tag('CURRENT_DATE',
     49 	lexer.starts_line(lex:word_match('weekday')) * lexer.space^1 * DD * '. ' * lex:word_match('month') *
     50 		lexer.space^1 * DD * DD * '|'))
     51 lex:add_rule('time', lex:tag(lexer.CLASS, DD * ':' * DD))
     52 lex:add_rule('week', lex:tag('UNDERLINE', lexer.starts_line('KW ' * DD * lexer.space^25) +
     53 	lexer.starts_line('Wk ' * DD * lexer.space^25)))
     54 lex:add_rule('datetime', lex:tag(lexer.NUMBER, lex:word_match('datetime')))
     55 
     56 -- Heading patterns.
     57 local function h(n)
     58 	return lex:tag(string.format('%s.h%s', lexer.HEADING, n),
     59 		lexer.starts_line(P(string.rep('*', n)) * ' '))
     60 end
     61 lex:add_rule('header', h(6) + h(5) + h(4) + h(3) + h(2) + h(1))
     62 
     63 -- Links.
     64 local orgmode_link = '[[' * (lexer.nonnewline - ' ' - ']')^1 * ']' *
     65 	('[' * (lexer.nonnewline - ']')^1 * ']')^0 * ']'
     66 lex:add_rule('link', lex:tag(lexer.LINK, orgmode_link))
     67 
     68 -- Strings.
     69 lex:add_rule('string', lex:tag(lexer.STRING, P('L')^-1 * lexer.range('"')))
     70 
     71 -- Comments.
     72 local line_comment = lexer.starts_line(lexer.to_eol('# '))
     73 local block_comment = lexer.range(lexer.starts_line('#+BEGIN_COMMENT'),
     74 	lexer.starts_line('#+END_COMMENT'))
     75 lex:add_rule('comment', lex:tag(lexer.COMMENT, block_comment + line_comment))
     76 
     77 -- Word lists.
     78 lex:set_word_list('TODO', {'TODO', 'DELEGATED', 'WAITING'})
     79 
     80 lex:set_word_list('DONE', {'DONE'})
     81 
     82 lex:set_word_list('WONTFIX', {'WONTFIX', 'INVALID'})
     83 
     84 lex:set_word_list('wday', {
     85 	'Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun', 'Po',
     86 	'Út', 'St', 'Čt', 'Pá', 'So', 'Ne'
     87 })
     88 
     89 lex:set_word_list('weekday', {
     90 	'Montag', 'Dienstag', 'Mittwoch', 'Donnerstag', 'Freitag', 'Samstag', 'Sonntag', 'Monday',
     91 	'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday', 'Sunday', 'Pondělí', 'Úterý',
     92 	'Středa', 'Čtvrtek', 'Pátek', 'Sobota', 'Neděle'
     93 })
     94 
     95 lex:set_word_list('month', {
     96 	'Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', 'Juli', 'August', 'September', 'Oktober',
     97 	'November', 'Dezember', 'January', 'February', 'March', 'April', 'May', 'June', 'July', 'August',
     98 	'September', 'October', 'November', 'December', 'Leden', 'Únor', 'Březen', 'Duben', 'Květen',
     99 	'Červen', 'Červenec', 'Srpen', 'Září', 'Říjen', 'Listopad', 'Prosince'
    100 })
    101 
    102 lexer.property['scintillua.comment'] = '#'
    103 
    104 return lex