lectures.alex.balgavy.eu

Lecture notes from university.
git clone git://git.alex.balgavy.eu/lectures.alex.balgavy.eu.git
Log | Files | Refs | Submodules

Makefile.sublime-syntax (21730B)


      1 %YAML 1.2
      2 # http://www.sublimetext.com/docs/3/syntax.html
      3 # https://www.gnu.org/software/make/manual/make.html
      4 --- #---------------------------------------------------------------------------
      5 # Converted from Makefile Improved by Kay-Uwe (Kiwi) Lorenz
      6 # Includes a few improvement like special-target, a bit more shell command,
      7 # better variable recognition, fix ifeq/ifneq missing highlight ...
      8 # Rewritten by Raoul Wols on May 2017.
      9 #
     10 # All number references refer to the "Make manual" (see link above).
     11 name: Makefile
     12 file_extensions:
     13   - make
     14   - GNUmakefile
     15   - makefile
     16   - Makefile
     17   - makefile.am
     18   - Makefile.am
     19   - makefile.in
     20   - Makefile.in
     21   - OCamlMakefile
     22   - mak
     23   - mk
     24 first_line_match: |-
     25   (?xi:
     26     ^\#! .* \bmake\b |                     # shebang
     27     ^\# \s* -\*- [^*]* makefile [^*]* -\*- # editorconfig
     28   )
     29 scope: source.makefile
     30 #-------------------------------------------------------------------------------
     31 variables:
     32 
     33   varassign: (\?|\+|::?)?=
     34   shellassign: '!='
     35   startdirective: ifn?(def|eq)
     36   include: '[s-]?include'
     37   ruleassign: :(?!=)
     38   function_call_token_begin: \$\$?\(
     39 
     40   # The big "rule lookahead". What we want to do is here is detect if the
     41   # line that we are parsing is going to define a rule. So we need to check
     42   # if we have something of the form <rule-name> : <rule-prerequisites>
     43   # However matters become complicated by the fact that we can have arbitrary
     44   # variable substitutions anywhere. We try to remedy this by hacking in a
     45   # regex that matches up to four levels of nested parentheses, and ignores
     46   # whatever's inside the parentheses.
     47   nps: '[^()]*'
     48   open: '(?:\('
     49   close: '\))?'       # ignore this invalid.illegal
     50   just_eat: |         # WARNING: INSANITY FOLLOWS!
     51     (?x)              # ignore whitespace in this regex
     52       {{nps}}         #       level 0
     53       {{open}}        # start level 1                      __
     54         {{nps}}       #       level 1          _______    /*_>-<
     55         {{open}}      # start level 2      ___/ _____ \__/ /
     56           {{nps}}     #       level 2     <____/     \____/
     57           {{open}}    # start level 3     is like snek... (by Valerie Haecky)
     58             {{nps}}   #       level 3
     59             {{open}}  # start level 4
     60               {{nps}} #       level 4
     61             {{close}} #   end level 4
     62             {{nps}}   #       level 3
     63           {{close}}   #   end level 3
     64           {{nps}}     #       level 2
     65           {{open}}    # start level 3
     66             {{nps}}   #       level 3
     67             {{open}}  # start level 4
     68               {{nps}} #       level 4
     69             {{close}} #   end level 4
     70             {{nps}}   #       level 3
     71           {{close}}   #   end level 3
     72           {{nps}}     #       level 2
     73         {{close}}     #   end level 2
     74         {{nps}}       #       level 1
     75         {{open}}      # start level 2
     76           {{nps}}     #       level 2
     77           {{open}}    # start level 3
     78             {{nps}}   #       level 3
     79             {{open}}  # start level 4
     80               {{nps}} #       level 4
     81             {{close}} #   end level 4
     82             {{nps}}   #       level 3
     83           {{close}}   #   end level 3
     84           {{nps}}     #       level 2
     85           {{open}}    # start level 3
     86             {{nps}}   #       level 3
     87             {{open}}  # start level 4
     88               {{nps}} #       level 4
     89             {{close}} #   end level 4
     90             {{nps}}   #       level 3
     91           {{close}}   #   end level 3
     92           {{nps}}     #       level 2
     93           {{open}}    # start level 3
     94             {{nps}}   #       level 3
     95             {{open}}  # start level 4
     96               {{nps}} #       level 4
     97             {{close}} #   end level 4
     98             {{nps}}   #       level 3
     99           {{close}}   #   end level 3
    100           {{nps}}     #       level 2
    101         {{close}}     #   end level 2
    102         {{nps}}       #       level 1
    103       {{close}}       #   end level 1
    104       {{nps}}         #       level 0
    105   rule_lookahead: '{{just_eat}}{{ruleassign}}{{just_eat}}'
    106 
    107   var_lookahead_base: '{{just_eat}}({{varassign}}|{{shellassign}}){{just_eat}}'
    108   # Just as with rules we want to look ahead if we are going to define a var.
    109   # However, due to the possibility of "target-specific" variables (see 6.11),
    110   # we want to NOT match if there's a {{ruleassign}} before a {{varassign}}.
    111   var_lookahead: (?!{{rule_lookahead}}){{var_lookahead_base}}
    112 
    113   first_assign_then_colon: |
    114     (?x)
    115       {{just_eat}}
    116         {{varassign}}
    117       {{just_eat}}
    118         {{ruleassign}}
    119       {{just_eat}}
    120 
    121 #-------------------------------------------------------------------------------
    122 contexts:
    123 
    124   # 3.1 What Makefiles Contain
    125   # Makefiles contain five kinds of things: explicit rules, implicit rules,
    126   # variable definitions, directives, and comments.
    127   main:
    128     - include: comments
    129     - include: variable-definitions
    130     - match: (?={{rule_lookahead}})
    131       push: expect-rule
    132     - include: variable-substitutions
    133     - include: control-flow
    134     - match: ^\s*(endef)
    135       captures:
    136         1: invalid.illegal.stray.endef.makefile
    137 
    138   inside-control-flow:
    139     - meta_scope: meta.group.makefile
    140     - match: "'"
    141       scope: punctuation.definition.string.begin.makefile
    142       push:
    143         - meta_scope: meta.string.makefile string.quoted.single.makefile
    144         - match: "'"
    145           scope: punctuation.definition.string.end.makefile
    146           pop: true
    147         - include: escape-literals
    148         - include: line-continuation
    149         - include: variable-substitutions
    150     - match: '"'
    151       scope: punctuation.definition.string.begin.makefile
    152       push:
    153         - meta_scope: meta.string.makefile string.quoted.double.makefile
    154         - match: '"'
    155           scope: punctuation.definition.string.end.makefile
    156           pop: true
    157         - include: escape-literals
    158         - include: line-continuation
    159         - include: variable-substitutions
    160     - match: \(
    161       scope: punctuation.section.group.begin.makefile
    162       push:
    163         - match: \)
    164           scope: punctuation.section.group.end.makefile
    165           pop: true
    166         - include: variable-substitutions
    167         - match: \,
    168           scope: punctuation.separator.makefile
    169     - match: \)
    170       scope: invalid.illegal.stray.paren.makefile
    171     - include: continuation-or-pop-on-line-end
    172 
    173   control-flow:
    174     - match: ^\s*(vpath)\s
    175       captures:
    176         1: keyword.control.vpath.makefile
    177       push:
    178         - include: highlight-wildcard-sign
    179         - match: \s
    180           set:
    181             - meta_content_scope: meta.string.makefile string.unquoted.makefile
    182             - include: pop-on-line-end
    183         - include: pop-on-line-end
    184     - match: ^\s*(vpath)$
    185       captures: keyword.control.vpath.makefile
    186     - match: ^\s*({{include}})\s+
    187       captures:
    188         1: keyword.control.import.makefile
    189       push:
    190         - meta_content_scope: meta.string.makefile string.unquoted.makefile
    191         - include: continuation-or-pop-on-line-end
    192         - include: variable-substitutions
    193         - include: comments
    194     - match: \b{{startdirective}}\b
    195       scope: keyword.control.conditional.makefile
    196       push: inside-control-flow
    197     - match: ^\s*(else)\b
    198       captures:
    199         1: keyword.control.conditional.makefile
    200       push:
    201         - include: control-flow
    202         - include: comments
    203         - include: pop-on-line-end
    204     - match: ^\s*(endif)\b
    205       captures:
    206         1: keyword.control.conditional.makefile
    207       push:
    208         - include: comments
    209         - include: pop-on-line-end
    210 
    211   highlight-percentage-sign:
    212     - match: \%
    213       scope: variable.language.makefile
    214 
    215   highlight-wildcard-sign:
    216     - match: \*
    217       scope: variable.language.wildcard.makefile
    218 
    219   expect-rule:
    220     # Anything before the colon is part of the rule's name.
    221     - meta_scope: meta.function.makefile entity.name.function.makefile
    222     - include: line-continuation
    223     - include: variable-substitutions
    224     - include: highlight-percentage-sign
    225     - match: (?= *::?[^=]+[!:?]?=)
    226       set:
    227         - match: ::?
    228           scope: keyword.operator.assignment.makefile
    229           set:
    230             - include: variable-definitions
    231             - include: variable-substitutions
    232             - include: continuation-or-pop-on-line-end
    233     - match: (?= *::?)
    234       set:
    235         - match: (::?)\s*
    236           captures:
    237             1: keyword.operator.assignment.makefile
    238           set:
    239             - meta_content_scope:
    240                 meta.function.arguments.makefile
    241                 string.unquoted.makefile
    242             - include: line-continuation
    243             - include: variable-substitutions
    244             - include: highlight-percentage-sign
    245             - match: (?=#)
    246               set:
    247                 - match: \#
    248                   scope: punctuation.definition.comment.makefile
    249                   set:
    250                     - meta_scope: comment.line.number-sign.makefile
    251                     - match: $
    252                       set: recipe-junction-between-spaces-or-tabs
    253             - match: $
    254               set: recipe-junction-between-spaces-or-tabs
    255             - match: (?=\s*;)
    256               set:
    257                 - match: ;
    258                   scope: punctuation.terminator.makefile
    259                   set: recipe-inline
    260 
    261   recipe-junction-between-spaces-or-tabs:
    262     - meta_content_scope: meta.function.body.makefile
    263     - include: comments
    264     - match: ^\s*({{startdirective}})
    265       captures:
    266         1: keyword.control.conditional.makefile
    267       push:
    268         - include: inside-control-flow
    269         - include: recipe-junction-between-spaces-or-tabs
    270     - match: ^(?=[ ]+([-@]{1,2})?)
    271       set: recipe-with-spaces
    272     - match: ^(?=\t([-@]{1,2})?)
    273       set: recipe-with-tabs
    274     - match: ^
    275       pop: true
    276 
    277   recipe-inline:
    278     - meta_content_scope: meta.function.body.makefile source.shell.embedded.makefile
    279     - include: recipe-junction-between-spaces-or-tabs
    280     - include: control-flow
    281     - match: $
    282       set: recipe-junction-between-spaces-or-tabs
    283     - include: shell-content
    284 
    285   recipe-with-spaces:
    286     - meta_content_scope: meta.function.body.makefile
    287     - match: ^([ ]+)([-@]{1,2})?
    288       captures:
    289         2: constant.language.makefile
    290       push: shell-common
    291     - match: ^(\t)([-@]{1,2})?
    292       captures:
    293         1: invalid.illegal.inconsistent.expected.spaces.makefile
    294         2: constant.language.makefile
    295     - include: recipe-common
    296     - match: ^(?![ ]+)
    297       pop: true
    298 
    299   recipe-with-tabs:
    300     - meta_content_scope: meta.function.body.makefile
    301     - match: ^\t([-@]{1,2})?
    302       captures:
    303         1: constant.language.makefile
    304       push: shell-common
    305     - match: ^([ ]+)([-@]{1,2})?
    306       captures:
    307         1: invalid.illegal.inconsistent.expected.tab.makefile
    308         2: constant.language.makefile
    309     - include: recipe-common
    310     - match: ^(?!\t)
    311       pop: true
    312 
    313   recipe-common:
    314     - include: control-flow
    315     - match: ^\n
    316 
    317   shell-common:
    318     - meta_content_scope: source.shell.embedded.makefile
    319     - include: pop-on-line-end
    320     - include: shell-content
    321 
    322   shell-content:
    323     - include: Packages/Makefile/Makefile Shell.sublime-syntax
    324       apply_prototype: true
    325 
    326   line-continuation:
    327     - match: (\\)([ ]*)$\n?
    328       captures:
    329         1: punctuation.separator.continuation.line.makefile
    330       # make sure to resume parsing at next line
    331       push:
    332         - match: (?=\S|^\s*$)
    333           pop: true
    334 
    335   pop-on-line-end:
    336     - match: $
    337       pop: true
    338 
    339   continuation-or-pop-on-line-end:
    340     - include: line-continuation
    341     - include: pop-on-line-end
    342 
    343   quoted-string:
    344     - match: "'"
    345       scope: punctuation.definition.string.begin.makefile
    346       push:
    347         - meta_include_prototype: false
    348         - meta_scope: meta.string.makefile string.quoted.single.makefile
    349         - match: "'"
    350           scope: punctuation.definition.string.end.makefile
    351           pop: true
    352         - include: escape-literals
    353         - include: line-continuation
    354         - include: variable-substitutions
    355     - match: '"'
    356       scope: punctuation.definition.string.begin.makefile
    357       push:
    358         - meta_include_prototype: false
    359         - meta_scope: meta.string.makefile string.quoted.double.makefile
    360         - match: '"'
    361           scope: punctuation.definition.string.end.makefile
    362           pop: true
    363         - include: escape-literals
    364         - include: line-continuation
    365         - include: variable-substitutions
    366 
    367   escape-literals:
    368     - match: \\.
    369       scope: constant.character.escape.makefile
    370 
    371   comments-pop-on-line-end:
    372     - include: line-continuation
    373     - match: $\n?
    374       pop: true
    375 
    376   comments:
    377     # This hack is here in order to circumvent false-positives for the big
    378     # rule lookahead. For example, if this match is not present, then things
    379     # like
    380     #
    381     #     # A comment with a : colon
    382     #
    383     # will match the rule-lookahead.
    384     - match: (?=^\s*#)
    385       push:
    386         - match: \#
    387           scope: punctuation.definition.comment.makefile
    388           set:
    389             - meta_scope: comment.line.number-sign.makefile
    390             - include: comments-pop-on-line-end
    391     # This is the "normal" comment parsing logic, but not sufficient in every
    392     # case (see above).
    393     - match: \#
    394       scope: punctuation.definition.comment.makefile
    395       push:
    396         - meta_scope: comment.line.number-sign.makefile
    397         - include: comments-pop-on-line-end
    398 
    399   inside-function-call:
    400     - meta_content_scope: meta.function-call.arguments.makefile
    401     - match: \)
    402       scope: keyword.other.block.end.makefile
    403       pop: true
    404     - match: \(
    405       push: textual-parenthesis-balancer
    406     - match: \,
    407       scope: punctuation.separator.makefile
    408     # eat escaped or unbalanced quotation marks in front of the `,` separator
    409     # to highlight them as ordinary part of the surrounding unquoted string
    410     - match: '\\[''""]|[''""](?=\s*,)'
    411     - include: variable-substitutions
    412     - include: quoted-string
    413 
    414   function-invocations:
    415     - match: ({{function_call_token_begin}})(call)\s
    416       captures:
    417         0: meta.function-call.makefile
    418         1: keyword.other.block.begin.makefile
    419         2: constant.language.call.makefile
    420       push:
    421         - meta_content_scope:
    422             meta.function-call.makefile
    423             variable.function.makefile
    424         - match: (?=\))
    425           set: inside-function-call
    426         - match: (?=,)
    427           set:
    428             - meta_content_scope: meta.function-call.makefile
    429             - match: \,
    430               scope: punctuation.separator.makefile
    431               set: inside-function-call
    432         - include: variable-substitutions
    433     - match: ({{function_call_token_begin}})(patsubst|filter)\s
    434       captures:
    435         0: meta.function-call.makefile
    436         1: keyword.other.block.begin.makefile
    437         2: support.function.builtin.makefile
    438       push:
    439         - meta_content_scope: meta.function-call.arguments.makefile
    440         - include: highlight-percentage-sign
    441         - include: inside-function-call
    442     - match: ({{function_call_token_begin}})(wildcard)\s
    443       captures:
    444         0: meta.function-call.makefile
    445         1: keyword.other.block.begin.makefile
    446         2: support.function.builtin.makefile
    447       push:
    448         - meta_content_scope: meta.function-call.arguments.makefile
    449         - include: inside-function-call
    450         - include: highlight-wildcard-sign
    451     - match: ({{function_call_token_begin}})(info|warning|error)\s
    452       captures:
    453         0: meta.function-call.makefile
    454         1: keyword.other.block.begin.makefile
    455         2: support.function.builtin.makefile
    456       push:
    457         - meta_content_scope: meta.function-call.arguments.makefile
    458         - match: \)
    459           scope: keyword.other.block.end.makefile
    460           pop: true
    461         - match: \(
    462           push: textual-parenthesis-balancer
    463         - match: \,
    464           scope: punctuation.separator.makefile
    465         - include: variable-substitutions
    466     - match: | # multiline string
    467         (?x)   # ignore whitespace
    468         ({{function_call_token_begin}})
    469           (
    470             subst|
    471             strip|
    472             findstring|
    473             filter-out|
    474             sort|
    475             word|
    476             wordlist|
    477             words|
    478             firstword|
    479             lastword|
    480             dir|
    481             notdir|
    482             suffix|
    483             basename|
    484             addsuffix|
    485             addprefix|
    486             join|
    487             realpath|
    488             abspath|
    489             if|
    490             or|
    491             and|
    492             foreach|
    493             file|
    494             value|
    495             eval|
    496             origin|
    497             flavor|
    498             guile
    499           )
    500           \s
    501       captures:
    502         0: meta.function-call.makefile
    503         1: keyword.other.block.begin.makefile
    504         2: support.function.builtin.makefile
    505       push: inside-function-call
    506     - match: ({{function_call_token_begin}})(shell)\s
    507       captures:
    508         1: keyword.other.block.begin.makefile
    509         2: support.function.builtin.makefile
    510       push:
    511         - meta_content_scope: source.shell.embedded.makefile
    512         - match: \)
    513           scope: keyword.other.block.end.makefile
    514           pop: true
    515         - include: shell-content
    516 
    517   variable-definitions:
    518     - match: \s*(override)\b
    519       captures:
    520         1: keyword.control.makefile
    521       set:
    522         - match: \bdefine\b
    523           scope: keyword.control.makefile
    524           push: inside-define-directive-context
    525         - include: variable-definitions
    526         - include: continuation-or-pop-on-line-end
    527     - match: \s*(define)\b
    528       captures:
    529         1: keyword.control.makefile
    530       push: inside-define-directive-context
    531     - match: ^\s*(export)\b
    532       captures:
    533         1: keyword.control.makefile
    534       push:
    535         - meta_content_scope: variable.other.makefile
    536         - include: continuation-or-pop-on-line-end
    537         - include: variable-substitutions
    538         - match: (\?|\+|::?)?=
    539           scope: keyword.operator.assignment.makefile
    540           set: [value-to-be-defined, eat-whitespace-then-pop]
    541     - match: (?={{var_lookahead}}|{{first_assign_then_colon}})
    542       push:
    543         - meta_content_scope: variable.other.makefile
    544         - match: (?=\s*!=)
    545           set:
    546             - match: '!='
    547               scope: keyword.operator.assignment.makefile
    548               set: shell-common
    549         - match: (?=\s*(!|\?|\+|::?)?=)
    550           set:
    551             - match: (!|\?|\+|::?)?=
    552               scope: keyword.operator.assignment.makefile
    553               set: [value-maybe-shellscript, eat-whitespace-then-pop]
    554             - include: variable-substitutions
    555             - include: continuation-or-pop-on-line-end
    556         - include: variable-substitutions
    557 
    558   textual-parenthesis-balancer:
    559     - match: \)
    560       pop: true
    561     - include: variable-substitutions
    562 
    563   eat-whitespace-then-pop:
    564     - clear_scopes: 1
    565     - match: \s*
    566       pop: true
    567 
    568   value-maybe-shellscript:
    569     - match: ((?:bash|sh|zsh)\s+-c\s+)(['"`])
    570       captures:
    571         1: meta.string.makefile string.unquoted.makefile
    572         2: meta.string.makefile meta.interpolation.makefile punctuation.section.interpolation.begin.makefile
    573       embed: shell-content
    574       embed_scope: meta.string.makefile meta.interpolation.makefile source.shell.embedded.makefile
    575       escape: (?!<\\)\2
    576       escape_captures:
    577         0: meta.string.makefile meta.interpolation.makefile punctuation.section.interpolation.end.makefile
    578     - match: ''
    579       set: value-to-be-defined
    580 
    581   value-to-be-defined:
    582     - meta_content_scope: meta.string.makefile string.unquoted.makefile
    583     - include: escape-literals
    584     - match: (?=#)
    585       set:
    586         - match: \#
    587           scope: punctuation.definition.comment.makefile
    588           set:
    589             - meta_scope: comment.line.number-sign.makefile
    590             - include: comments-pop-on-line-end
    591     - include: variable-substitutions
    592     - include: continuation-or-pop-on-line-end
    593 
    594   inside-define-directive-context:
    595     - meta_content_scope: variable.other.makefile
    596     - match: (?=(!|\?|\+|::?)?=\s*\n)
    597       set:
    598         - match: ((!|\?|\+|::?)?=)\s*\n
    599           captures:
    600             1: keyword.operator.assignment.makefile
    601           set: inside-define-directive-value
    602 
    603     # Need to eat the actual newline character in order to start the
    604     # string.unquoted scope on the next line.
    605     - match: \n
    606       set: inside-define-directive-value
    607     - include: variable-substitutions
    608 
    609   inside-define-directive-value:
    610     - meta_content_scope: meta.string.makefile string.unquoted.makefile
    611     - match: ^\s*(endef)\b
    612       captures:
    613         1: keyword.control.makefile
    614       pop: true
    615     # keep in balance with nested define statements
    616     # see: https://github.com/sublimehq/Packages/issues/1998
    617     - match: ^\s*define\b
    618       push:
    619         - match: ^\s*endef\b
    620           pop: true
    621 
    622   variable-sub-common:
    623     - match: ':'
    624       scope: punctuation.definition.substitution.makefile
    625     - match: =
    626       scope: punctuation.definition.assignment.makefile
    627     - include: highlight-percentage-sign
    628     - include: variable-substitutions
    629 
    630   variable-substitutions:
    631     - include: function-invocations
    632     - match: \$\$?\(
    633       scope: keyword.other.block.begin.makefile
    634       push:
    635         - meta_scope: variable.parameter.makefile
    636         - match: \)
    637           scope: keyword.other.block.end.makefile
    638           pop: true
    639         - include: variable-sub-common
    640     - match: \$\$?{
    641       scope: keyword.other.block.begin.makefile
    642       push:
    643         - meta_scope: variable.parameter.makefile
    644         - match: \}
    645           scope: keyword.other.block.end.makefile
    646           pop: true
    647         - include: variable-sub-common
    648     - match: \$\$?[@%<?^+|*]
    649       scope: variable.language.automatic.makefile
    650     - match: \$\$
    651       scope: constant.character.escape.makefile
    652     - match: (\$)[[:alpha:]]
    653       captures:
    654         0: variable.parameter.makefile
    655         1: keyword.other.single-character-variable.makefile