api/vim: Add “len” dictionary key

This allows determining where parsing ended which may be needed for e.g. parsing
`:echo` with that API function.
This commit is contained in:
ZyX
2017-11-06 01:15:18 +03:00
parent 7849070f99
commit ebb5977837
2 changed files with 38 additions and 2 deletions

View File

@@ -922,6 +922,12 @@ typedef kvec_withinit_t(ExprASTConvStackItem, 16) ExprASTConvStack;
/// Must contain exactly one "%.*s". /// Must contain exactly one "%.*s".
/// "arg": String, error message argument. /// "arg": String, error message argument.
/// ///
/// "len": Amount of bytes successfully parsed. With flags equal to ""
/// that should be equal to the length of expr string.
///
/// @note: “Sucessfully parsed” here means “participated in AST
/// creation”, not “till the first error”.
///
/// "ast": actual AST, either nil or a dictionary with the following /// "ast": actual AST, either nil or a dictionary with the following
/// keys: /// keys:
/// ///
@@ -1000,9 +1006,8 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight,
&pstate, parser_simple_get_line, &plines_p, colors_p); &pstate, parser_simple_get_line, &plines_p, colors_p);
ExprAST east = viml_pexpr_parse(&pstate, pflags); ExprAST east = viml_pexpr_parse(&pstate, pflags);
// FIXME add parse_length key
const size_t ret_size = ( const size_t ret_size = (
1 // "ast" 2 // "ast", "len"
+ (size_t)(east.err.msg != NULL) // "error" + (size_t)(east.err.msg != NULL) // "error"
+ (size_t)highlight // "highlight" + (size_t)highlight // "highlight"
); );
@@ -1015,6 +1020,12 @@ Dictionary nvim_parse_expression(String expr, String flags, Boolean highlight,
.key = STATIC_CSTR_TO_STRING("ast"), .key = STATIC_CSTR_TO_STRING("ast"),
.value = NIL, .value = NIL,
}; };
ret.items[ret.size++] = (KeyValuePair) {
.key = STATIC_CSTR_TO_STRING("len"),
.value = INTEGER_OBJ((Integer)(pstate.pos.line == 1
? plines[0].size
: pstate.pos.col)),
};
if (east.err.msg != NULL) { if (east.err.msg != NULL) {
Dictionary err_dict = { Dictionary err_dict = {
.items = xmalloc(2 * sizeof(err_dict.items[0])), .items = xmalloc(2 * sizeof(err_dict.items[0])),

View File

@@ -799,6 +799,9 @@ describe('api', function()
if east_api.ast then if east_api.ast then
east_api.ast = {simplify_east_api_node(line, east_api.ast)} east_api.ast = {simplify_east_api_node(line, east_api.ast)}
end end
if east_api.len == #line then
east_api.len = nil
end
return east_api return east_api
end end
local function simplify_east_hl(line, east_hl) local function simplify_east_hl(line, east_hl)
@@ -997,6 +1000,7 @@ describe('api', function()
}, { }, {
[1] = { [1] = {
ast = { ast = {
len = 2,
err = REMOVE_THIS, err = REMOVE_THIS,
ast = { ast = {
'Register(name=a):0:0:@a' 'Register(name=a):0:0:@a'
@@ -1028,6 +1032,7 @@ describe('api', function()
}, { }, {
[1] = { [1] = {
ast = { ast = {
len = 6,
err = REMOVE_THIS, err = REMOVE_THIS,
ast = { ast = {
'Register(name=a):0:0: @a' 'Register(name=a):0:0: @a'
@@ -1236,6 +1241,7 @@ describe('api', function()
}, { }, {
[1] = { [1] = {
ast = { ast = {
len = 3,
err = REMOVE_THIS, err = REMOVE_THIS,
ast = { ast = {
'Register(name=a):0:0:@a', 'Register(name=a):0:0:@a',
@@ -5456,6 +5462,7 @@ describe('api', function()
}, { }, {
[1] = { [1] = {
ast = { ast = {
len = 3,
err = REMOVE_THIS, err = REMOVE_THIS,
ast = { ast = {
'ListLiteral:0:0:[', 'ListLiteral:0:0:[',
@@ -7135,6 +7142,7 @@ describe('api', function()
}, { }, {
[1] = { [1] = {
ast = { ast = {
len = 4,
err = REMOVE_THIS, err = REMOVE_THIS,
ast = { ast = {
'Option(scope=0,ident=xxx):0:0:&xxx', 'Option(scope=0,ident=xxx):0:0:&xxx',
@@ -7520,6 +7528,7 @@ describe('api', function()
}, { }, {
[1] = { [1] = {
ast = { ast = {
len = 1,
err = REMOVE_THIS, err = REMOVE_THIS,
ast = { ast = {
'Integer(val=1):0:0:1', 'Integer(val=1):0:0:1',
@@ -7652,6 +7661,7 @@ describe('api', function()
end) end)
it('respects highlight argument', function() it('respects highlight argument', function()
eq({ eq({
len = 1,
ast = { ast = {
ivalue = 1, ivalue = 1,
len = 1, len = 1,
@@ -7660,6 +7670,7 @@ describe('api', function()
}, },
}, meths.parse_expression('1', '', false)) }, meths.parse_expression('1', '', false))
eq({ eq({
len = 1,
ast = { ast = {
ivalue = 1, ivalue = 1,
len = 1, len = 1,
@@ -7674,6 +7685,7 @@ describe('api', function()
it('works (KLEE tests)', function() it('works (KLEE tests)', function()
check_parsing('\0002&A:\000', { check_parsing('\0002&A:\000', {
ast = {}, ast = {},
len = 0,
err = { err = {
arg = '\0002&A:\0', arg = '\0002&A:\0',
msg = 'E15: Expected value, got EOC: %.*s', msg = 'E15: Expected value, got EOC: %.*s',
@@ -7682,6 +7694,7 @@ describe('api', function()
}, { }, {
[2] = { [2] = {
ast = { ast = {
len = REMOVE_THIS,
ast = { ast = {
{ {
'Colon:0:4::', 'Colon:0:4::',
@@ -7711,6 +7724,7 @@ describe('api', function()
}, },
[3] = { [3] = {
ast = { ast = {
len = 2,
ast = { ast = {
'Integer(val=2):0:1:2', 'Integer(val=2):0:1:2',
}, },
@@ -7754,6 +7768,7 @@ describe('api', function()
check_parsing('|"\\U\\', { check_parsing('|"\\U\\', {
-- 01234 -- 01234
ast = {}, ast = {},
len = 0,
err = { err = {
arg = '|"\\U\\', arg = '|"\\U\\',
msg = 'E15: Expected value, got EOC: %.*s', msg = 'E15: Expected value, got EOC: %.*s',
@@ -7762,6 +7777,7 @@ describe('api', function()
}, { }, {
[2] = { [2] = {
ast = { ast = {
len = REMOVE_THIS,
ast = { ast = {
{ {
'Or:0:0:|', 'Or:0:0:|',
@@ -7786,6 +7802,7 @@ describe('api', function()
check_parsing('|"\\e"', { check_parsing('|"\\e"', {
-- 01234 -- 01234
ast = {}, ast = {},
len = 0,
err = { err = {
arg = '|"\\e"', arg = '|"\\e"',
msg = 'E15: Expected value, got EOC: %.*s', msg = 'E15: Expected value, got EOC: %.*s',
@@ -7794,6 +7811,7 @@ describe('api', function()
}, { }, {
[2] = { [2] = {
ast = { ast = {
len = REMOVE_THIS,
ast = { ast = {
{ {
'Or:0:0:|', 'Or:0:0:|',
@@ -7818,6 +7836,7 @@ describe('api', function()
check_parsing('|\029', { check_parsing('|\029', {
-- 01 -- 01
ast = {}, ast = {},
len = 0,
err = { err = {
arg = '|\029', arg = '|\029',
msg = 'E15: Expected value, got EOC: %.*s', msg = 'E15: Expected value, got EOC: %.*s',
@@ -7826,6 +7845,7 @@ describe('api', function()
}, { }, {
[2] = { [2] = {
ast = { ast = {
len = REMOVE_THIS,
ast = { ast = {
{ {
'Or:0:0:|', 'Or:0:0:|',
@@ -7892,6 +7912,7 @@ describe('api', function()
}, { }, {
[1] = { [1] = {
ast = { ast = {
len = 1,
ast = { ast = {
'UnknownFigure:0:0:', 'UnknownFigure:0:0:',
}, },
@@ -7917,6 +7938,7 @@ describe('api', function()
}, },
}, },
}, },
len = 2,
err = { err = {
arg = ':?\000\000\000\000\000\000\000', arg = ':?\000\000\000\000\000\000\000',
msg = 'E15: Colon outside of dictionary or ternary operator: %.*s', msg = 'E15: Colon outside of dictionary or ternary operator: %.*s',
@@ -7926,6 +7948,9 @@ describe('api', function()
hl('InvalidTernary', '?'), hl('InvalidTernary', '?'),
}, { }, {
[2] = { [2] = {
ast = {
len = REMOVE_THIS,
},
hl_fs = { hl_fs = {
[3] = hl('InvalidSpacing', '\0'), [3] = hl('InvalidSpacing', '\0'),
[4] = hl('InvalidSpacing', '\0'), [4] = hl('InvalidSpacing', '\0'),