diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 22e3e09d..9f587a4f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -457,7 +457,7 @@ jobs: path: dist/plugins retention-days: "7" build-plugins-maple: - name: "Plugins (maple): caddy, cmake, dockerfile, dot, graphql, hcl, ini, jq, meson, nginx, ninja, nix, query, rego, ron, sql, ssh-config, styx, toml, yaml" + name: "Plugins (maple): caddy, cmake, dockerfile, dot, gitattributes, graphql, hcl, ini, jq, meson, nginx, ninja, nix, query, rego, ron, sql, ssh-config, styx, toml, yaml" runs-on: depot-ubuntu-24.04-32 container: "ghcr.io/bearcove/arborium-plugin-builder:latest" needs: @@ -475,10 +475,10 @@ jobs: set -e tar -xf generate-output.tar && rm generate-output.tar shell: bash - - name: Build caddy, cmake, dockerfile, dot, graphql, hcl, ini, jq, meson, nginx, ninja, nix, query, rego, ron, sql, ssh-config, styx, toml, yaml + - name: Build caddy, cmake, dockerfile, dot, gitattributes, graphql, hcl, ini, jq, meson, nginx, ninja, nix, query, rego, ron, sql, ssh-config, styx, toml, yaml run: |- set -e - ./xtask/target/release/xtask build caddy cmake dockerfile dot graphql hcl ini jq meson nginx ninja nix query rego ron sql ssh-config styx toml yaml -o dist/plugins + ./xtask/target/release/xtask build caddy cmake dockerfile dot gitattributes graphql hcl ini jq meson nginx ninja nix query rego ron sql ssh-config styx toml yaml -o dist/plugins shell: bash - name: Upload plugins artifact uses: actions/upload-artifact@v4 diff --git a/langs/group-maple/gitattributes/def/arborium.yaml b/langs/group-maple/gitattributes/def/arborium.yaml new file mode 100644 index 00000000..fcb5acb9 --- /dev/null +++ b/langs/group-maple/gitattributes/def/arborium.yaml @@ -0,0 +1,20 @@ +repo: https://github.com/tree-sitter-grammars/tree-sitter-gitattributes +commit: 1b7af09d45b579f9f288453b95ad555f1f431645 +license: MIT + +grammars: + - id: gitattributes + name: .gitattributes + tag: config + tier: 2 + has_scanner: false + + inventor: Linus Torvalds + year: 2005 + description: Defining attributes per path for Git. + link: https://git-scm.com/docs/gitattributes + + samples: + - path: samples/.gitattributes + link: https://github.com/gitattributes/gitattributes/blob/1dcb1ff5890b3997642b295fee6934204b4f79ac/.gitattributes + license: MIT diff --git a/langs/group-maple/gitattributes/def/grammar/grammar.js b/langs/group-maple/gitattributes/def/grammar/grammar.js new file mode 100644 index 00000000..90391664 --- /dev/null +++ b/langs/group-maple/gitattributes/def/grammar/grammar.js @@ -0,0 +1,220 @@ +/** + * @file gitattributes grammar for tree-sitter + * @author ObserverOfTime + * @license MIT + */ + +/// +// @ts-check + +/** Built-in attribute names */ +const BUILTIN_ATTRIBUTES = [ + 'text', + 'eol', + 'crlf', + 'working-tree-encoding', + 'ident', + 'filter', + 'diff', + 'merge', + 'whitespace', + 'export-ignore', + 'export-subst', + 'delta', + 'encoding', + 'binary' +]; + +/** POSIX character classes */ +const POSIX_CLASSES = [ + 'alnum', + 'alpha', + 'blank', + 'cntrl', + 'digit', + 'graph', + 'lower', + 'print', + 'punct', + 'space', + 'upper', + 'xdigit' +]; + +/** + * Returns a quoted or unquoted pattern sequence + * @param {GrammarSymbols} $ the symbols of the grammar + * @param {boolean} quoted `true` if the pattern is in quotes + */ +const __pattern = ($, quoted) => [ + optional(alias('!', $.pattern_negation)), // error + optional(field('absolute', $.dir_sep)), + quoted ? $._quoted_pattern : $._pattern, + repeat(seq(field('relative', $.dir_sep), $._pattern)), + optional(alias($.dir_sep, $.trailing_slash)) // error +] + +module.exports = grammar({ + name: 'gitattributes', + + extras: _ => [], + + word: $ => $.attr_name, + + rules: { + file: $ => repeat($._line), + + _line: $ => seq( + optional($._space), + optional(choice( + $.comment, + $._attr_list, + $.macro_def + )), + choice($._eol, $._eof) + ), + + _attr_list: $ => seq( + prec.left(choice($.pattern, $.quoted_pattern)), + repeat1(seq($._space, $.attribute)), + optional($._space) + ), + + pattern: $ => seq(...__pattern($, false)), + + _pattern: $ => repeat1(choice( + $._pattern_char, + $.wildcard, + $.escaped_char, + $.range_notation, + alias('\\', $.redundant_escape) // error + )), + + quoted_pattern: $ => seq( + '"', ...__pattern($, true), '"' + ), + + _quoted_pattern: $ => repeat1(choice( + /[^\n/]/, + choice($.ansi_c_escape, $.escaped_char), + alias('\\', $.redundant_escape), + )), + + _pattern_char: _ => /[^\s/?*]/, + + escaped_char: _ => /\\[\\\[\]!?*]/, + + ansi_c_escape: $ => prec.right( + 1, choice( + $._special_char, $._char_code + ) + ), + + _special_char: _ => /\\[abeEfnrtv\\'"?]/, + + _char_code: $ => choice( + $._octal_code, + $._hex_code, + $._unicode_code, + $._control_code + ), + + _octal_code: _ => /\\\d{1,3}/, + + _hex_code: _ => /\\x[0-9A-Fa-f]{2}/, + + _unicode_code: _ => choice( + /\\u[0-9A-Fa-f]{4}/, + /\\U[0-9A-Fa-f]{8}/ + ), + + _control_code: _ => token(choice( + /\\c[\x00-\x5B\x5D-\x7F]/, /\\c\\\\/ + )), + + range_notation: $ => prec.left(seq( + '[', + optional(alias( + token(choice('!', '^')), + $.range_negation + )), + repeat1(choice( + $.class_range, + $.character_class, + $._class_char, + $.ansi_c_escape, + '-' + )), + ']' + )), + + class_range: $ => prec.right( + 2, seq( + choice($._class_char, $._char_code), + '-', + choice($._class_char, $._char_code) + ) + ), + + _class_char: _ => token(choice( + /[^-\\\]\n]/, /\\[-\\\[\]!^]/ + )), + + character_class: _ => token(seq( + '[:', choice(...POSIX_CLASSES), ':]' + )), + + wildcard: _ => token(choice('?', '*', '**')), + + dir_sep: _ => '/', + + attribute: $ => choice( + seq( + choice($.attr_name, $.builtin_attr), + $._attr_value + ), + $._prefixed_attr + ), + + _prefixed_attr: $ => seq( + optional(choice( + alias('!', $.attr_reset), + alias('-', $.attr_unset), + )), + choice($.attr_name, $.builtin_attr), + prec(-1, optional( + alias($._attr_value, $.ignored_value) + )) + ), + + _attr_value: $ => seq( + alias('=', $.attr_set), + choice( + prec(2, alias( + token(choice('true', 'false')), + $.boolean_value + )), + prec(1, alias(/\S+/, $.string_value)) + ) + ), + + attr_name: _ => /[A-Za-z0-9_.][-A-Za-z0-9_.]*/, + + builtin_attr: _ => prec(1, choice(...BUILTIN_ATTRIBUTES)), + + macro_def: $ => seq( + alias('[attr]', $.macro_tag), + field('macro_name', $.attr_name), + repeat1(seq($._space, $.attribute)), + optional($._space) + ), + + comment: _ => seq('#', repeat(/[^\n]/)), + + _space: _ => prec(-1, /[ \t]+/), + + _eol: _ => /\r?\n/, + + _eof: _ => '\0' + } +}); diff --git a/langs/group-maple/gitattributes/def/queries/highlights.scm b/langs/group-maple/gitattributes/def/queries/highlights.scm new file mode 100644 index 00000000..f9d2a5a9 --- /dev/null +++ b/langs/group-maple/gitattributes/def/queries/highlights.scm @@ -0,0 +1,52 @@ +(dir_sep) @punctuation.delimiter + +(quoted_pattern + "\"" @punctuation.special) + +(range_notation) @string.special + +(range_notation + [ "[" "]" ] @punctuation.bracket) + +(wildcard) @string.regexp + +(range_negation) @operator + +(character_class) @constant + +(class_range "-" @operator) + +[ + (ansi_c_escape) + (escaped_char) +] @escape + +(attribute + (attr_name) @variable.parameter) + +(attribute + (builtin_attr) @variable.builtin) + +[ + (attr_reset) + (attr_unset) + (attr_set) +] @operator + +(boolean_value) @boolean + +(string_value) @string + +(macro_tag) @keyword + +(macro_def + macro_name: (_) @property) + +[ + (pattern_negation) + (redundant_escape) + (trailing_slash) + (ignored_value) +] @error + +(comment) @comment diff --git a/langs/group-maple/gitattributes/def/samples/.gitattributes b/langs/group-maple/gitattributes/def/samples/.gitattributes new file mode 100644 index 00000000..605e2505 --- /dev/null +++ b/langs/group-maple/gitattributes/def/samples/.gitattributes @@ -0,0 +1,25 @@ +# Handle line endings automatically for files detected as text +# and leave all files detected as binary untouched. +* text=auto + +# +# The above will handle all files NOT found below +# +# These files are text and should be normalized (Convert crlf => lf) +*.gitattributes text +.gitignore text +*.md text diff=markdown + +# +# Exclude files from exporting +# + +.gitattributes export-ignore +.gitignore export-ignore + +# +# Enable syntax highlighting for files with `.gitattributes` extensions. +# +*.gitattributes linguist-language=gitattributes +*.gitattributes linguist-detectable=true +*.gitattributes linguist-documentation=false