mirror of
https://github.com/kristoferssolo/tree-sitter-bruno.git
synced 2026-03-21 16:26:24 +00:00
feat(queries): add embedded language injections for Bruno blocks
This commit is contained in:
27
grammar.js
27
grammar.js
@@ -11,6 +11,7 @@ module.exports = grammar({
|
||||
name: "bruno",
|
||||
|
||||
extras: (_) => [/\s/],
|
||||
externals: ($) => [$.rawtext],
|
||||
|
||||
rules: {
|
||||
source_file: ($) => repeat($.section),
|
||||
@@ -77,14 +78,14 @@ module.exports = grammar({
|
||||
$.bodyformmultipart,
|
||||
$.bodyraw,
|
||||
),
|
||||
bodyraw: ($) => seq(alias("body", $.keyword), $.raw_block),
|
||||
bodyjson: ($) => seq(alias("body:json", $.keyword), $.raw_block),
|
||||
bodytext: ($) => seq(alias("body:text", $.keyword), $.raw_block),
|
||||
bodyxml: ($) => seq(alias("body:xml", $.keyword), $.raw_block),
|
||||
bodysparql: ($) => seq(alias("body:sparql", $.keyword), $.raw_block),
|
||||
bodygraphql: ($) => seq(alias("body:graphql", $.keyword), $.raw_block),
|
||||
bodyraw: ($) => seq(alias("body", $.keyword), $.textblock),
|
||||
bodyjson: ($) => seq(alias("body:json", $.keyword), $.textblock),
|
||||
bodytext: ($) => seq(alias("body:text", $.keyword), $.textblock),
|
||||
bodyxml: ($) => seq(alias("body:xml", $.keyword), $.textblock),
|
||||
bodysparql: ($) => seq(alias("body:sparql", $.keyword), $.textblock),
|
||||
bodygraphql: ($) => seq(alias("body:graphql", $.keyword), $.textblock),
|
||||
bodygraphqlvars: ($) =>
|
||||
seq(alias("body:graphql:vars", $.keyword), $.raw_block),
|
||||
seq(alias("body:graphql:vars", $.keyword), $.textblock),
|
||||
bodyformurlencoded: ($) =>
|
||||
seq(alias("body:form-urlencoded", $.keyword), $.object_block),
|
||||
bodyformmultipart: ($) =>
|
||||
@@ -100,17 +101,17 @@ module.exports = grammar({
|
||||
assert: ($) => seq(alias("assert", $.keyword), $.assert_block),
|
||||
|
||||
script: ($) => choice($.scriptreq, $.scriptres),
|
||||
scriptreq: ($) => seq(alias("script:pre-request", $.keyword), $.raw_block),
|
||||
scriptreq: ($) => seq(alias("script:pre-request", $.keyword), $.textblock),
|
||||
scriptres: ($) =>
|
||||
seq(alias("script:post-response", $.keyword), $.raw_block),
|
||||
seq(alias("script:post-response", $.keyword), $.textblock),
|
||||
|
||||
params: ($) => choice($.params_path, $.params_query),
|
||||
params_query: ($) => seq(alias("params:query", $.keyword), $.object_block),
|
||||
params_path: ($) => seq(alias("params:path", $.keyword), $.object_block),
|
||||
|
||||
tests: ($) => seq(alias("tests", $.keyword), $.raw_block),
|
||||
tests: ($) => seq(alias("tests", $.keyword), $.textblock),
|
||||
|
||||
docs: ($) => seq(alias("docs", $.keyword), $.raw_block),
|
||||
docs: ($) => seq(alias("docs", $.keyword), $.textblock),
|
||||
|
||||
object_block: ($) => seq("{", repeat($.dictionary_pair), "}"),
|
||||
dictionary_pair: ($) => seq($.key, ":", $.dictionary_value),
|
||||
@@ -124,9 +125,7 @@ module.exports = grammar({
|
||||
array_value: ($) =>
|
||||
choice($.template_value, $.quoted_value, $.bare_value),
|
||||
|
||||
raw_block: ($) => seq("{", repeat($.raw_fragment), "}"),
|
||||
raw_fragment: ($) => choice($.raw_text, $.raw_block),
|
||||
raw_text: (_) => token(prec(-1, /[^{}]+/)),
|
||||
textblock: ($) => seq("{", optional($.rawtext), "}"),
|
||||
|
||||
assert_key: (_) => /[^\r\n:]+/,
|
||||
|
||||
|
||||
59
queries/injections.scm
Normal file
59
queries/injections.scm
Normal file
@@ -0,0 +1,59 @@
|
||||
((bodyraw
|
||||
(keyword)
|
||||
(textblock
|
||||
(rawtext) @injection.content))
|
||||
(#set! injection.language "json"))
|
||||
|
||||
((bodyjson
|
||||
(keyword)
|
||||
(textblock
|
||||
(rawtext) @injection.content))
|
||||
(#set! injection.language "json"))
|
||||
|
||||
((bodygraphql
|
||||
(keyword)
|
||||
(textblock
|
||||
(rawtext) @injection.content))
|
||||
(#set! injection.language "graphql"))
|
||||
|
||||
((bodygraphqlvars
|
||||
(keyword)
|
||||
(textblock
|
||||
(rawtext) @injection.content))
|
||||
(#set! injection.language "json"))
|
||||
|
||||
((bodyxml
|
||||
(keyword)
|
||||
(textblock
|
||||
(rawtext) @injection.content))
|
||||
(#set! injection.language "xml"))
|
||||
|
||||
((bodysparql
|
||||
(keyword)
|
||||
(textblock
|
||||
(rawtext) @injection.content))
|
||||
(#set! injection.language "sparql"))
|
||||
|
||||
((scriptreq
|
||||
(keyword)
|
||||
(textblock
|
||||
(rawtext) @injection.content))
|
||||
(#set! injection.language "javascript"))
|
||||
|
||||
((scriptres
|
||||
(keyword)
|
||||
(textblock
|
||||
(rawtext) @injection.content))
|
||||
(#set! injection.language "javascript"))
|
||||
|
||||
((tests
|
||||
(keyword)
|
||||
(textblock
|
||||
(rawtext) @injection.content))
|
||||
(#set! injection.language "javascript"))
|
||||
|
||||
((docs
|
||||
(keyword)
|
||||
(textblock
|
||||
(rawtext) @injection.content))
|
||||
(#set! injection.language "markdown"))
|
||||
70
src/grammar.json
generated
70
src/grammar.json
generated
@@ -345,7 +345,7 @@
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "raw_block"
|
||||
"name": "textblock"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -363,7 +363,7 @@
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "raw_block"
|
||||
"name": "textblock"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -381,7 +381,7 @@
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "raw_block"
|
||||
"name": "textblock"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -399,7 +399,7 @@
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "raw_block"
|
||||
"name": "textblock"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -417,7 +417,7 @@
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "raw_block"
|
||||
"name": "textblock"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -435,7 +435,7 @@
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "raw_block"
|
||||
"name": "textblock"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -453,7 +453,7 @@
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "raw_block"
|
||||
"name": "textblock"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -631,7 +631,7 @@
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "raw_block"
|
||||
"name": "textblock"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -649,7 +649,7 @@
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "raw_block"
|
||||
"name": "textblock"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -716,7 +716,7 @@
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "raw_block"
|
||||
"name": "textblock"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -734,7 +734,7 @@
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "raw_block"
|
||||
"name": "textblock"
|
||||
}
|
||||
]
|
||||
},
|
||||
@@ -883,7 +883,7 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"raw_block": {
|
||||
"textblock": {
|
||||
"type": "SEQ",
|
||||
"members": [
|
||||
{
|
||||
@@ -891,11 +891,16 @@
|
||||
"value": "{"
|
||||
},
|
||||
{
|
||||
"type": "REPEAT",
|
||||
"content": {
|
||||
"type": "SYMBOL",
|
||||
"name": "raw_fragment"
|
||||
}
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "rawtext"
|
||||
},
|
||||
{
|
||||
"type": "BLANK"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "STRING",
|
||||
@@ -903,30 +908,6 @@
|
||||
}
|
||||
]
|
||||
},
|
||||
"raw_fragment": {
|
||||
"type": "CHOICE",
|
||||
"members": [
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "raw_text"
|
||||
},
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "raw_block"
|
||||
}
|
||||
]
|
||||
},
|
||||
"raw_text": {
|
||||
"type": "TOKEN",
|
||||
"content": {
|
||||
"type": "PREC",
|
||||
"value": -1,
|
||||
"content": {
|
||||
"type": "PATTERN",
|
||||
"value": "[^{}]+"
|
||||
}
|
||||
}
|
||||
},
|
||||
"assert_key": {
|
||||
"type": "PATTERN",
|
||||
"value": "[^\\r\\n:]+"
|
||||
@@ -1012,7 +993,12 @@
|
||||
],
|
||||
"conflicts": [],
|
||||
"precedences": [],
|
||||
"externals": [],
|
||||
"externals": [
|
||||
{
|
||||
"type": "SYMBOL",
|
||||
"name": "rawtext"
|
||||
}
|
||||
],
|
||||
"inline": [],
|
||||
"supertypes": [],
|
||||
"reserved": {}
|
||||
|
||||
73
src/node-types.json
generated
73
src/node-types.json
generated
@@ -314,7 +314,7 @@
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "raw_block",
|
||||
"type": "textblock",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
@@ -333,7 +333,7 @@
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "raw_block",
|
||||
"type": "textblock",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
@@ -352,7 +352,7 @@
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "raw_block",
|
||||
"type": "textblock",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
@@ -371,7 +371,7 @@
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "raw_block",
|
||||
"type": "textblock",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
@@ -390,7 +390,7 @@
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "raw_block",
|
||||
"type": "textblock",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
@@ -409,7 +409,7 @@
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "raw_block",
|
||||
"type": "textblock",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
@@ -428,7 +428,7 @@
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "raw_block",
|
||||
"type": "textblock",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
@@ -489,7 +489,7 @@
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "raw_block",
|
||||
"type": "textblock",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
@@ -648,40 +648,6 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "raw_block",
|
||||
"named": true,
|
||||
"fields": {},
|
||||
"children": {
|
||||
"multiple": true,
|
||||
"required": false,
|
||||
"types": [
|
||||
{
|
||||
"type": "raw_fragment",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "raw_fragment",
|
||||
"named": true,
|
||||
"fields": {},
|
||||
"children": {
|
||||
"multiple": false,
|
||||
"required": true,
|
||||
"types": [
|
||||
{
|
||||
"type": "raw_block",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "raw_text",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "script",
|
||||
"named": true,
|
||||
@@ -714,7 +680,7 @@
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "raw_block",
|
||||
"type": "textblock",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
@@ -733,7 +699,7 @@
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "raw_block",
|
||||
"type": "textblock",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
@@ -827,7 +793,22 @@
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "raw_block",
|
||||
"type": "textblock",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"type": "textblock",
|
||||
"named": true,
|
||||
"fields": {},
|
||||
"children": {
|
||||
"multiple": false,
|
||||
"required": false,
|
||||
"types": [
|
||||
{
|
||||
"type": "rawtext",
|
||||
"named": true
|
||||
}
|
||||
]
|
||||
@@ -1001,7 +982,7 @@
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
"type": "raw_text",
|
||||
"type": "rawtext",
|
||||
"named": true
|
||||
},
|
||||
{
|
||||
|
||||
1549
src/parser.c
generated
1549
src/parser.c
generated
File diff suppressed because it is too large
Load Diff
98
src/scanner.c
Normal file
98
src/scanner.c
Normal file
@@ -0,0 +1,98 @@
|
||||
#include "tree_sitter/parser.h"
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
enum TokenType {
|
||||
RAWTEXT,
|
||||
};
|
||||
|
||||
void *tree_sitter_bruno_external_scanner_create(void) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void tree_sitter_bruno_external_scanner_destroy(void *payload) {
|
||||
(void)payload;
|
||||
}
|
||||
|
||||
unsigned tree_sitter_bruno_external_scanner_serialize(void *payload, char *buffer) {
|
||||
(void)payload;
|
||||
(void)buffer;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void tree_sitter_bruno_external_scanner_deserialize(void *payload, const char *buffer, unsigned length) {
|
||||
(void)payload;
|
||||
(void)buffer;
|
||||
(void)length;
|
||||
}
|
||||
|
||||
static void advance(TSLexer *lexer) {
|
||||
lexer->advance(lexer, false);
|
||||
}
|
||||
|
||||
static void skip(TSLexer *lexer) {
|
||||
lexer->advance(lexer, true);
|
||||
}
|
||||
|
||||
static bool scan_quoted(TSLexer *lexer, int32_t quote) {
|
||||
advance(lexer);
|
||||
|
||||
while (lexer->lookahead) {
|
||||
if (lexer->lookahead == '\\') {
|
||||
advance(lexer);
|
||||
if (lexer->lookahead) advance(lexer);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lexer->lookahead == quote) {
|
||||
advance(lexer);
|
||||
return true;
|
||||
}
|
||||
|
||||
advance(lexer);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool tree_sitter_bruno_external_scanner_scan(void *payload, TSLexer *lexer, const bool *valid_symbols) {
|
||||
(void)payload;
|
||||
|
||||
if (!valid_symbols[RAWTEXT]) return false;
|
||||
if (lexer->lookahead == '}') return false;
|
||||
|
||||
unsigned depth = 0;
|
||||
bool has_content = false;
|
||||
|
||||
while (lexer->lookahead) {
|
||||
if (lexer->lookahead == '\'' || lexer->lookahead == '"' || lexer->lookahead == '`') {
|
||||
has_content = true;
|
||||
if (!scan_quoted(lexer, lexer->lookahead)) break;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lexer->lookahead == '{') {
|
||||
has_content = true;
|
||||
depth++;
|
||||
advance(lexer);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (lexer->lookahead == '}') {
|
||||
if (depth == 0) break;
|
||||
depth--;
|
||||
has_content = true;
|
||||
advance(lexer);
|
||||
continue;
|
||||
}
|
||||
|
||||
has_content = true;
|
||||
advance(lexer);
|
||||
}
|
||||
|
||||
if (!has_content) return false;
|
||||
|
||||
lexer->result_symbol = RAWTEXT;
|
||||
return true;
|
||||
}
|
||||
@@ -6,12 +6,13 @@
|
||||
"camelcase": "Bruno",
|
||||
"title": "Bruno",
|
||||
"scope": "source.bruno",
|
||||
"highlights": "queries/highlights.scm",
|
||||
"file-types": [
|
||||
"bru"
|
||||
],
|
||||
"injection-regex": "^bruno$",
|
||||
"class-name": "TreeSitterBruno"
|
||||
"class-name": "TreeSitterBruno",
|
||||
"highlights": "queries/highlights.scm",
|
||||
"injections": "queries/injections.scm"
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
|
||||
Reference in New Issue
Block a user