let alias = [ label "alias" . store word_re ]
Every kind of Alias entry, see user_alias, runas_alias, host_alias and cmnd_alias
let alias = user_alias | runas_alias | host_alias | cmnd_alias
Alias entry, a list of comma-separated alias_entry_single fields
let alias_entry ( kw:string ) (field:string) (sto:lens) = [ indent . key kw . sep_cont . alias_entry_single field sto . ( sep_col . alias_entry_single field sto )* . eol ]
Single alias_entry, named using alias_name and listing alias_list
let alias_entry_single ( field:string ) (sto:lens) = [ label "alias" . alias_name . sep_eq . alias_list field sto ]
Generic alias field to gather all Alias definitions
let alias_field ( kw:string ) (sto:lens) = [ label kw . sto ]
List of alias_fields, separated by commas
let alias_list ( kw:string ) (sto:lens) = alias_field kw sto . ( sep_com . alias_field kw sto )*
Name of an alias_entry_single
let alias_name = [ label "name" . store /[A-Z][A-Z0-9_]*/ ]
let alpha = /[A-Za-z]{3}/
let alphanum = num | alpha
Arguments are key=value stanzas
let argument = let argument_re = Rx.word | /"[^\n"]*"/ in Build.key_value Rx.word Sep.equal (store argument_re)
A block is a standard Build.named_block of lines
let block = Build.named_block Rx.word line
We would really like to say “the body can contain any of a list of a list of attributes, each of them at most once”; but that would require that we build a lens that matches the permutation of all attributes; with around 40 individual attributes, that’s not computationally feasible, even if we didn’t have to worry about how to write that down.
let body ( attr:lens ) = Util.del_str "\n{\n" . (empty|comment|attr)* . del /[ \t]*}[ \t]*\n/ "}\n"
Cmnd_Alias, see alias_field
let cmnd_alias = alias_entry "Cmnd_Alias" "command" sto_to_com_cmnd
Command specification for spec, with optional runas_spec and any amount of tag_specs
let cmnd_spec = [ label "command" . runas_spec? . tag_spec* . sto_to_com_cmnd ]
A list of comma-separated cmnd_specs
let cmnd_spec_list = cmnd_spec . ( sep_com . cmnd_spec )*
let comment = Util.comment
Map comments into “#comment” nodes
let comment ( pat:regexp ) (default:string) = [ label "#comment" . sep pat default . sto_to_eol? . eol ]
Map comments in “#comment” nodes
let comment = let sto_to_eol = store /( [^ \t\n].*[^ \t\n]|[^ \t\n] )/ in [ label "#comment" . del /[ \t]*#[ \t]*/ "# " . sto_to_eol . eol ]
Map comments into “#comment” nodes
let comment = [ indent . label "#comment" . del /#[ \t]*/ "# " . store /([^ \t\n].*[^ \t\n]|[^ \t\n])/ . eol ]
let comment = Util.comment
Default value for comment pattern
let comment_default = ";"
Default regexp for comment pattern
let comment_re = /[;#]/
let dayofmonth = [ label "dayofmonth" . store num ]
let dayofweek = [ label "dayofweek" . store alphanum ]
let default_depth = entry_int "DefaultDepth" /[dD]efault[dD]epth/
Type definition for defaults
let default_type = let value = store /[@:>][^ \t\n\\\\]+/ in [ label "type" . value ]
A Defaults entry
let defaults = [ indent . key "Defaults" . default_type? . sep_cont . parameter_list . eol ]
Delete an even number of ‘!’
let del_negate = del /( !! )*/ ""
Delete optional whitespace
let del_opt_ws = del /[ \t]*/
Delete a string and default to it
let del_str ( s:string ) = del s s
Delete mandatory whitespace
let del_ws = del /[ \t]+/
Delete mandatory whitespace, default to single space
let del_ws_spc = del_ws " "
Delete mandatory whitespace, default to single tab
let del_ws_tab = del_ws "\t"
let device = entry_str "Device" /[dD]evice/
let display = [ indent . del "SubSection" "SubSection" . sep_spc . sep_dquote . key "Display" . sep_dquote . eol . display_entry* . indent . del "EndSubSection" "EndSubSection" . eol ]
Known values for entries in the Display subsection
let display_entry = entry_int "Depth" /[dD]epth/ | entry_int "FbBpp" /[fF]b[bB]pp/ | entry_rgb "Weight" /[wW]eight/ | entry_xy "Virtual" /[vV]irtual/ | entry_xy "ViewPort" /[vV]iew[pP]ort/ | display_modes | entry_str "Visual" /[vV]isual/ | entry_rgb "Black" /[bB]lack/ | entry_rgb "White" /[wW]hite/ | entry_str "Options" /[oO]ptions/ | empty | comment
let display_modes = [ indent . del /[mM]odes/ "Modes" . label "Modes" . [ label "mode" . sep_spc . quoted_string_val ]+ . eol ]
let driver = entry_str "Driver" /[dD]river/
let empty = Util.empty
Empty line, an eol subnode
let empty = [ eol ]
Map empty lines
let empty = [ del /[ \t]*#?[ \t]*\n/ "\n" ]
Map empty lines, including empty comments
let empty = [ del /[ \t]*#?[ \t]*\n/ "\n" ]
let empty = Util.empty
This is a list of all patterns which have specific handlers, and should therefore not be matched by the generic handler
let entries_re = /( [oO]ption|[sS]creen|[iI]nput[dD]evice|[dD]river|[sS]ub[sS]ection|[dD]isplay|[iI]dentifier|[vV]ideo[rR]am|[dD]efault[dD]epth|[dD]evice )/
A crontab entry
let entry = [ label "entry" . indent . ( time | schedule ) . sep_spc . user . sep_spc . store Rx.space_in . eol ]
Generic INI File entry
let entry ( kw:regexp ) (sep:lens) (comment:lens) = [ key kw . sep . sto_to_comment? . (comment|eol) ] | comment
An entry without a specific handler.
let entry_generic = [ indent . key generic_entry_re . sep_spc . store to_eol . eol ]
This matches an entry which takes a single integer for an argument
let entry_int ( canon:string ) (re:regexp) = [ indent . del re canon . label canon . sep_spc . store int . eol ]
Default regexp for entry keyword
let entry_re = ( /[A-Za-z][A-Za-z0-9\._-]+/ )
This matches an entry which takes 3 integers as arguments representing red, green and blue components
let entry_rgb ( canon:string ) (re:regexp) = [ indent . del re canon . label canon . [ label "red" . sep_spc . store int ] . [ label "green" . sep_spc . store int ] . [ label "blue" . sep_spc . store int ] . eol ]
This matches an entry which takes a single quoted string
let entry_str ( canon:string ) (re:regexp) = [ indent . del re canon . label canon . sep_spc . quoted_string_val . eol ]
This matches an entry which takes 2 integers as arguments representing X and Y coordinates
let entry_xy ( canon:string ) (re:regexp) = [ indent . del re canon . label canon . [ label "x" . sep_spc . store int ] . [ label "y" . sep_spc . store int ] . eol ]
let eol = Util.eol
End of line, inherited from Util.eol
let eol = Util.eol
let eol = del /[ \t]*( # )?[ \t]*\n/ "\n"
let eol = del /[ \t]*\n/ "\n"
Delete end of line, including optional trailing whitespace
let eol = del /[ \t]*\n/ "\n"
let eol = Util.eol
let generic_entry_re = /[^# \t\n\/]+/ - entries_re
Host_Alias, see alias_field
let host_alias = alias_entry "Host_Alias" "host" sto_to_com
let hour = [ label "hour" . store num ]