mirror of
https://github.com/neovim/neovim.git
synced 2026-07-14 13:20:35 +00:00
refactor(vimscript)!: drop ctxget(), ctxpush(), etc #40724
Problem: This functions are most likely never used in the wild. - They are redundant with `nvim_get_context` + `nvim_load_context`. - The "context" concept was never fully developed and hasn't gained traction. Solution: Drop these vimscript aliases, they are just extra cruft.
This commit is contained in:
@@ -44,6 +44,10 @@ LSP
|
||||
|
||||
• vim.lsp.util.character_offset() Use to |vim.str_utfindex()| instead
|
||||
|
||||
VIMSCRIPT
|
||||
• ctxget(), ctxpop(), ctxpush(), ctxset(), ctxsize(). Use
|
||||
|nvim_get_context()| and |nvim_load_context()| instead.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
DEPRECATED IN 0.12 *deprecated-0.12*
|
||||
|
||||
|
||||
@@ -132,6 +132,11 @@ TREESITTER
|
||||
|
||||
• todo
|
||||
|
||||
VIMSCRIPT
|
||||
|
||||
• Removed: ctxget(), ctxpop(), ctxpush(), ctxset(), ctxsize(). Use
|
||||
|nvim_get_context()| and |nvim_load_context()| instead.
|
||||
|
||||
==============================================================================
|
||||
NEW FEATURES *news-features*
|
||||
|
||||
@@ -392,6 +397,9 @@ REMOVED FEATURES *news-removed*
|
||||
|
||||
These deprecated features were removed.
|
||||
|
||||
• Vimscript functions ctxget(), ctxpop(), ctxpush(), ctxset(), ctxsize()
|
||||
and the "context stack". Use |nvim_get_context()| and |nvim_load_context()|
|
||||
with a script-owned list instead.
|
||||
• |vim.lsp.buf.declaration()|, |vim.lsp.buf.definition()|,
|
||||
|vim.lsp.buf.type_definition()|, and |vim.lsp.buf.implementation()|
|
||||
no longer accept the `reuse_win` option.
|
||||
|
||||
@@ -917,9 +917,5 @@ Context objects are dictionaries with the following key-value pairs:
|
||||
- "funcs" (includes |script-local| functions as well):
|
||||
|List| of |:function| definitions.
|
||||
|
||||
*context-stack*
|
||||
An initially-empty internal Context stack is maintained by the ctx-family
|
||||
functions (see |ctx-functions|).
|
||||
|
||||
|
||||
vim:tw=78:ts=8:noet:ft=help:norl:
|
||||
|
||||
@@ -1101,13 +1101,6 @@ Registers: *register-functions*
|
||||
reg_executing() return the name of the register being executed
|
||||
reg_recording() return the name of the register being recorded
|
||||
|
||||
Context Stack: *ctx-functions*
|
||||
ctxget() return context at given index from top
|
||||
ctxpop() pop and restore top context
|
||||
ctxpush() push given context
|
||||
ctxset() set context at given index from top
|
||||
ctxsize() return context stack size
|
||||
|
||||
Various: *various-functions*
|
||||
mode() get current editing mode
|
||||
visualmode() last visual mode used
|
||||
|
||||
@@ -1517,56 +1517,6 @@ count({comp}, {expr} [, {ic} [, {start}]]) *count()* *E70
|
||||
Return: ~
|
||||
(`integer`)
|
||||
|
||||
ctxget([{index}]) *ctxget()*
|
||||
Returns a |Dictionary| representing the |context| at {index}
|
||||
from the top of the |context-stack| (see |context-dict|).
|
||||
If {index} is not given, it is assumed to be 0 (i.e.: top).
|
||||
|
||||
Parameters: ~
|
||||
• {index} (`integer?`)
|
||||
|
||||
Return: ~
|
||||
(`table`)
|
||||
|
||||
ctxpop() *ctxpop()*
|
||||
Pops and restores the |context| at the top of the
|
||||
|context-stack|.
|
||||
|
||||
Return: ~
|
||||
(`any`)
|
||||
|
||||
ctxpush([{types}]) *ctxpush()*
|
||||
Pushes the current editor state (|context|) on the
|
||||
|context-stack|.
|
||||
If {types} is given and is a |List| of |String|s, it specifies
|
||||
which |context-types| to include in the pushed context.
|
||||
Otherwise, all context types are included.
|
||||
|
||||
Parameters: ~
|
||||
• {types} (`string[]?`)
|
||||
|
||||
Return: ~
|
||||
(`any`)
|
||||
|
||||
ctxset({context} [, {index}]) *ctxset()*
|
||||
Sets the |context| at {index} from the top of the
|
||||
|context-stack| to that represented by {context}.
|
||||
{context} is a Dictionary with context data (|context-dict|).
|
||||
If {index} is not given, it is assumed to be 0 (i.e.: top).
|
||||
|
||||
Parameters: ~
|
||||
• {context} (`table`)
|
||||
• {index} (`integer?`)
|
||||
|
||||
Return: ~
|
||||
(`integer`)
|
||||
|
||||
ctxsize() *ctxsize()*
|
||||
Returns the size of the |context-stack|.
|
||||
|
||||
Return: ~
|
||||
(`any`)
|
||||
|
||||
cursor({lnum}, {col} [, {off}]) *cursor()*
|
||||
cursor({list})
|
||||
Lua: Prefer |nvim_win_set_cursor()| with `{lnum, col - 1}`;
|
||||
|
||||
39
runtime/lua/vim/_meta/vimfn.gen.lua
generated
39
runtime/lua/vim/_meta/vimfn.gen.lua
generated
@@ -1333,45 +1333,6 @@ function vim.fn.cosh(expr) end
|
||||
--- @return integer
|
||||
function vim.fn.count(comp, expr, ic, start) end
|
||||
|
||||
--- Returns a |Dictionary| representing the |context| at {index}
|
||||
--- from the top of the |context-stack| (see |context-dict|).
|
||||
--- If {index} is not given, it is assumed to be 0 (i.e.: top).
|
||||
---
|
||||
--- @param index? integer
|
||||
--- @return table
|
||||
function vim.fn.ctxget(index) end
|
||||
|
||||
--- Pops and restores the |context| at the top of the
|
||||
--- |context-stack|.
|
||||
---
|
||||
--- @return any
|
||||
function vim.fn.ctxpop() end
|
||||
|
||||
--- Pushes the current editor state (|context|) on the
|
||||
--- |context-stack|.
|
||||
--- If {types} is given and is a |List| of |String|s, it specifies
|
||||
--- which |context-types| to include in the pushed context.
|
||||
--- Otherwise, all context types are included.
|
||||
---
|
||||
--- @param types? string[]
|
||||
--- @return any
|
||||
function vim.fn.ctxpush(types) end
|
||||
|
||||
--- Sets the |context| at {index} from the top of the
|
||||
--- |context-stack| to that represented by {context}.
|
||||
--- {context} is a Dictionary with context data (|context-dict|).
|
||||
--- If {index} is not given, it is assumed to be 0 (i.e.: top).
|
||||
---
|
||||
--- @param context table
|
||||
--- @param index? integer
|
||||
--- @return integer
|
||||
function vim.fn.ctxset(context, index) end
|
||||
|
||||
--- Returns the size of the |context-stack|.
|
||||
---
|
||||
--- @return any
|
||||
function vim.fn.ctxsize() end
|
||||
|
||||
--- @param lnum integer|string
|
||||
--- @param col? integer
|
||||
--- @param off? integer
|
||||
|
||||
@@ -52,41 +52,12 @@
|
||||
|
||||
int kCtxAll = (kCtxRegs | kCtxJumps | kCtxBufs | kCtxGVars | kCtxSFuncs | kCtxFuncs);
|
||||
|
||||
static ContextVec ctx_stack = KV_INITIAL_VALUE;
|
||||
|
||||
/// Nesting depth of ctx_switch() calls that changed curwin.
|
||||
static int _ctx_switch_depth = 0;
|
||||
|
||||
/// curwin saved by the outermost curwin-changing ctx_switch() (0: none).
|
||||
static handle_T _ctx_saved_curwin = 0;
|
||||
|
||||
/// Clears and frees the context stack
|
||||
void ctx_free_all(void)
|
||||
{
|
||||
for (size_t i = 0; i < kv_size(ctx_stack); i++) {
|
||||
ctx_free(&kv_A(ctx_stack, i));
|
||||
}
|
||||
kv_destroy(ctx_stack);
|
||||
}
|
||||
|
||||
/// Returns the size of the context stack.
|
||||
size_t ctx_size(void)
|
||||
FUNC_ATTR_PURE
|
||||
{
|
||||
return kv_size(ctx_stack);
|
||||
}
|
||||
|
||||
/// Returns pointer to Context object with given zero-based index from the top
|
||||
/// of context stack or NULL if index is out of bounds.
|
||||
Context *ctx_get(size_t index)
|
||||
FUNC_ATTR_PURE
|
||||
{
|
||||
if (index < kv_size(ctx_stack)) {
|
||||
return &kv_Z(ctx_stack, index);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/// Free resources used by Context object.
|
||||
///
|
||||
/// param[in] ctx pointer to Context object to free.
|
||||
@@ -102,18 +73,13 @@ void ctx_free(Context *ctx)
|
||||
|
||||
/// Saves the editor state to a context.
|
||||
///
|
||||
/// If "context" is NULL, pushes context on context stack.
|
||||
/// Use "flags" to select particular types of context.
|
||||
///
|
||||
/// @param ctx Save to this context, or push on context stack if NULL.
|
||||
/// @param ctx Save to this context.
|
||||
/// @param flags Flags, see ContextTypeFlags enum.
|
||||
void ctx_save(Context *ctx, const int flags)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
if (ctx == NULL) {
|
||||
kv_push(ctx_stack, CONTEXT_INIT);
|
||||
ctx = &kv_last(ctx_stack);
|
||||
}
|
||||
|
||||
if (flags & kCtxRegs) {
|
||||
ctx->regs = shada_encode_regs();
|
||||
}
|
||||
@@ -158,24 +124,13 @@ void ctx_save(Context *ctx, const int flags)
|
||||
|
||||
/// Loads (restores) the editor state from a Context snapshot.
|
||||
///
|
||||
/// If "context" is NULL, pops context from context stack.
|
||||
/// Use "flags" to select particular types of context.
|
||||
///
|
||||
/// @param ctx Load from this context. Pop from context stack if NULL.
|
||||
/// @param ctx Load from this context.
|
||||
/// @param flags Flags, see ContextTypeFlags enum.
|
||||
///
|
||||
/// @return true on success, false otherwise (i.e.: empty context stack).
|
||||
bool ctx_load(Context *ctx, const int flags)
|
||||
void ctx_load(Context *ctx, const int flags)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
bool free_ctx = false;
|
||||
if (ctx == NULL) {
|
||||
if (ctx_stack.size == 0) {
|
||||
return false;
|
||||
}
|
||||
ctx = &kv_pop(ctx_stack);
|
||||
free_ctx = true;
|
||||
}
|
||||
|
||||
OptVal op_shada = get_option_value(kOptShada, OPT_GLOBAL);
|
||||
set_option_value(kOptShada, STATIC_CSTR_AS_OPTVAL("!,'100,%"), OPT_GLOBAL);
|
||||
|
||||
@@ -201,14 +156,8 @@ bool ctx_load(Context *ctx, const int flags)
|
||||
}
|
||||
}
|
||||
|
||||
if (free_ctx) {
|
||||
ctx_free(ctx);
|
||||
}
|
||||
|
||||
set_option_value(kOptShada, op_shada, OPT_GLOBAL);
|
||||
optval_free(op_shada);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Convert readfile()-style array to String
|
||||
|
||||
@@ -1722,61 +1722,6 @@ M.funcs = {
|
||||
returns = 'integer',
|
||||
signature = 'count({comp}, {expr} [, {ic} [, {start}]])',
|
||||
},
|
||||
ctxget = {
|
||||
args = { 0, 1 },
|
||||
desc = [=[
|
||||
Returns a |Dictionary| representing the |context| at {index}
|
||||
from the top of the |context-stack| (see |context-dict|).
|
||||
If {index} is not given, it is assumed to be 0 (i.e.: top).
|
||||
]=],
|
||||
name = 'ctxget',
|
||||
params = { { 'index', 'integer' } },
|
||||
returns = 'table',
|
||||
signature = 'ctxget([{index}])',
|
||||
},
|
||||
ctxpop = {
|
||||
desc = [=[
|
||||
Pops and restores the |context| at the top of the
|
||||
|context-stack|.
|
||||
]=],
|
||||
name = 'ctxpop',
|
||||
params = {},
|
||||
signature = 'ctxpop()',
|
||||
},
|
||||
ctxpush = {
|
||||
args = { 0, 1 },
|
||||
desc = [=[
|
||||
Pushes the current editor state (|context|) on the
|
||||
|context-stack|.
|
||||
If {types} is given and is a |List| of |String|s, it specifies
|
||||
which |context-types| to include in the pushed context.
|
||||
Otherwise, all context types are included.
|
||||
]=],
|
||||
name = 'ctxpush',
|
||||
params = { { 'types', 'string[]' } },
|
||||
signature = 'ctxpush([{types}])',
|
||||
},
|
||||
ctxset = {
|
||||
args = { 1, 2 },
|
||||
desc = [=[
|
||||
Sets the |context| at {index} from the top of the
|
||||
|context-stack| to that represented by {context}.
|
||||
{context} is a Dictionary with context data (|context-dict|).
|
||||
If {index} is not given, it is assumed to be 0 (i.e.: top).
|
||||
]=],
|
||||
name = 'ctxset',
|
||||
params = { { 'context', 'table' }, { 'index', 'integer' } },
|
||||
returns = 'integer',
|
||||
signature = 'ctxset({context} [, {index}])',
|
||||
},
|
||||
ctxsize = {
|
||||
desc = [=[
|
||||
Returns the size of the |context-stack|.
|
||||
]=],
|
||||
name = 'ctxsize',
|
||||
params = {},
|
||||
signature = 'ctxsize()',
|
||||
},
|
||||
cursor = {
|
||||
args = { 1, 3 },
|
||||
base = 1,
|
||||
|
||||
@@ -844,121 +844,6 @@ static void f_copy(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||
var_item_copy(NULL, &argvars[0], rettv, false, 0);
|
||||
}
|
||||
|
||||
/// "ctxget([{index}])" function
|
||||
static void f_ctxget(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||
{
|
||||
size_t index = 0;
|
||||
if (argvars[0].v_type == VAR_NUMBER) {
|
||||
index = (size_t)argvars[0].vval.v_number;
|
||||
} else if (argvars[0].v_type != VAR_UNKNOWN) {
|
||||
semsg(_(e_invarg2), "expected nothing or a Number as an argument");
|
||||
return;
|
||||
}
|
||||
|
||||
Context *ctx = ctx_get(index);
|
||||
if (ctx == NULL) {
|
||||
semsg(_(e_invargNval), "index", "out of bounds");
|
||||
return;
|
||||
}
|
||||
|
||||
Arena arena = ARENA_EMPTY;
|
||||
Dict ctx_dict = ctx_to_dict(ctx, &arena);
|
||||
Error err = ERROR_INIT;
|
||||
object_to_vim(DICT_OBJ(ctx_dict), rettv, &err);
|
||||
arena_mem_free(arena_finish(&arena));
|
||||
api_clear_error(&err);
|
||||
}
|
||||
|
||||
/// "ctxpop()" function
|
||||
static void f_ctxpop(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||
{
|
||||
if (!ctx_load(NULL, kCtxAll)) {
|
||||
emsg(_("Context stack is empty"));
|
||||
}
|
||||
}
|
||||
|
||||
/// "ctxpush([{types}])" function
|
||||
static void f_ctxpush(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||
{
|
||||
int types = kCtxAll;
|
||||
if (argvars[0].v_type == VAR_LIST) {
|
||||
types = 0;
|
||||
TV_LIST_ITER(argvars[0].vval.v_list, li, {
|
||||
typval_T *tv_li = TV_LIST_ITEM_TV(li);
|
||||
if (tv_li->v_type == VAR_STRING) {
|
||||
if (strequal(tv_li->vval.v_string, "regs")) {
|
||||
types |= kCtxRegs;
|
||||
} else if (strequal(tv_li->vval.v_string, "jumps")) {
|
||||
types |= kCtxJumps;
|
||||
} else if (strequal(tv_li->vval.v_string, "bufs")) {
|
||||
types |= kCtxBufs;
|
||||
} else if (strequal(tv_li->vval.v_string, "gvars")) {
|
||||
types |= kCtxGVars;
|
||||
} else if (strequal(tv_li->vval.v_string, "sfuncs")) {
|
||||
types |= kCtxSFuncs;
|
||||
} else if (strequal(tv_li->vval.v_string, "funcs")) {
|
||||
types |= kCtxFuncs;
|
||||
}
|
||||
}
|
||||
});
|
||||
} else if (argvars[0].v_type != VAR_UNKNOWN) {
|
||||
semsg(_(e_invarg2), "expected nothing or a List as an argument");
|
||||
return;
|
||||
}
|
||||
ctx_save(NULL, types);
|
||||
}
|
||||
|
||||
/// "ctxset({context}[, {index}])" function
|
||||
static void f_ctxset(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||
{
|
||||
if (argvars[0].v_type != VAR_DICT) {
|
||||
semsg(_(e_invarg2), "expected dictionary as first argument");
|
||||
return;
|
||||
}
|
||||
|
||||
size_t index = 0;
|
||||
if (argvars[1].v_type == VAR_NUMBER) {
|
||||
index = (size_t)argvars[1].vval.v_number;
|
||||
} else if (argvars[1].v_type != VAR_UNKNOWN) {
|
||||
semsg(_(e_invarg2), "expected nothing or a Number as second argument");
|
||||
return;
|
||||
}
|
||||
|
||||
Context *ctx = ctx_get(index);
|
||||
if (ctx == NULL) {
|
||||
semsg(_(e_invargNval), "index", "out of bounds");
|
||||
return;
|
||||
}
|
||||
|
||||
const int save_did_emsg = did_emsg;
|
||||
did_emsg = false;
|
||||
|
||||
Arena arena = ARENA_EMPTY;
|
||||
Dict dict = vim_to_object(&argvars[0], &arena, true).data.dict;
|
||||
Context tmp = CONTEXT_INIT;
|
||||
Error err = ERROR_INIT;
|
||||
ctx_from_dict(dict, &tmp, &err);
|
||||
|
||||
if (ERROR_SET(&err)) {
|
||||
semsg("%s", err.msg);
|
||||
ctx_free(&tmp);
|
||||
} else {
|
||||
ctx_free(ctx);
|
||||
*ctx = tmp;
|
||||
}
|
||||
|
||||
arena_mem_free(arena_finish(&arena));
|
||||
api_clear_error(&err);
|
||||
did_emsg = save_did_emsg;
|
||||
}
|
||||
|
||||
/// "ctxsize()" function
|
||||
static void f_ctxsize(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||
{
|
||||
rettv->v_type = VAR_NUMBER;
|
||||
rettv->vval.v_number = (varnumber_T)ctx_size();
|
||||
}
|
||||
|
||||
/// Set the cursor position.
|
||||
/// If "charcol" is true, then use the column number as a character offset.
|
||||
/// Otherwise use the column number as a byte offset.
|
||||
|
||||
@@ -983,7 +983,6 @@ void free_all_mem(void)
|
||||
channel_free_all_mem();
|
||||
eval_clear();
|
||||
api_extmark_free_all_mem();
|
||||
ctx_free_all();
|
||||
|
||||
map_destroy(int, &buffer_handles);
|
||||
map_destroy(int, &window_handles);
|
||||
|
||||
@@ -1,444 +0,0 @@
|
||||
local t = require('test.testutil')
|
||||
local n = require('test.functional.testnvim')()
|
||||
|
||||
local call = n.call
|
||||
local clear = n.clear
|
||||
local command = n.command
|
||||
local eq = t.eq
|
||||
local eval = n.eval
|
||||
local feed = n.feed
|
||||
local map = vim.tbl_map
|
||||
local api = n.api
|
||||
local parse_context = n.parse_context
|
||||
local exec_capture = n.exec_capture
|
||||
local source = n.source
|
||||
local trim = vim.trim
|
||||
local write_file = t.write_file
|
||||
local pcall_err = t.pcall_err
|
||||
|
||||
describe('context functions', function()
|
||||
local fname1 = 'Xtest-functional-eval-ctx1'
|
||||
local fname2 = 'Xtest-functional-eval-ctx2'
|
||||
local outofbounds = 'Vim:E475: Invalid value for argument index: out of bounds'
|
||||
|
||||
before_each(function()
|
||||
clear()
|
||||
write_file(fname1, '1\n2\n3')
|
||||
write_file(fname2, 'a\nb\nc')
|
||||
end)
|
||||
|
||||
after_each(function()
|
||||
os.remove(fname1)
|
||||
os.remove(fname2)
|
||||
end)
|
||||
|
||||
describe('ctxpush/ctxpop', function()
|
||||
it('saves and restores registers properly', function()
|
||||
local regs = { '1', '2', '3', 'a' }
|
||||
local vals = { '1', '2', '3', 'hjkl' }
|
||||
feed('i1<cr>2<cr>3<c-[>ddddddqahjklq')
|
||||
eq(
|
||||
vals,
|
||||
map(function(r)
|
||||
return trim(call('getreg', r))
|
||||
end, regs)
|
||||
)
|
||||
call('ctxpush')
|
||||
call('ctxpush', { 'regs' })
|
||||
|
||||
map(function(r)
|
||||
call('setreg', r, {})
|
||||
end, regs)
|
||||
eq(
|
||||
{ '', '', '', '' },
|
||||
map(function(r)
|
||||
return trim(call('getreg', r))
|
||||
end, regs)
|
||||
)
|
||||
|
||||
call('ctxpop')
|
||||
eq(
|
||||
vals,
|
||||
map(function(r)
|
||||
return trim(call('getreg', r))
|
||||
end, regs)
|
||||
)
|
||||
|
||||
map(function(r)
|
||||
call('setreg', r, {})
|
||||
end, regs)
|
||||
eq(
|
||||
{ '', '', '', '' },
|
||||
map(function(r)
|
||||
return trim(call('getreg', r))
|
||||
end, regs)
|
||||
)
|
||||
|
||||
call('ctxpop')
|
||||
eq(
|
||||
vals,
|
||||
map(function(r)
|
||||
return trim(call('getreg', r))
|
||||
end, regs)
|
||||
)
|
||||
end)
|
||||
|
||||
it('saves and restores jumplist properly', function()
|
||||
command('edit ' .. fname1)
|
||||
feed('G')
|
||||
feed('gg')
|
||||
command('edit ' .. fname2)
|
||||
local jumplist = call('getjumplist')
|
||||
call('ctxpush')
|
||||
call('ctxpush', { 'jumps' })
|
||||
|
||||
command('clearjumps')
|
||||
eq({ {}, 0 }, call('getjumplist'))
|
||||
|
||||
call('ctxpop')
|
||||
eq(jumplist, call('getjumplist'))
|
||||
|
||||
command('clearjumps')
|
||||
eq({ {}, 0 }, call('getjumplist'))
|
||||
|
||||
call('ctxpop')
|
||||
eq(jumplist, call('getjumplist'))
|
||||
end)
|
||||
|
||||
it('saves and restores buffer list properly', function()
|
||||
command('edit ' .. fname1)
|
||||
command('edit ' .. fname2)
|
||||
command('edit TEST')
|
||||
local bufs = call('map', call('getbufinfo'), 'v:val.name')
|
||||
call('ctxpush')
|
||||
call('ctxpush', { 'bufs' })
|
||||
|
||||
command('%bwipeout')
|
||||
eq({ '' }, call('map', call('getbufinfo'), 'v:val.name'))
|
||||
|
||||
call('ctxpop')
|
||||
eq({ '', unpack(bufs) }, call('map', call('getbufinfo'), 'v:val.name'))
|
||||
|
||||
command('%bwipeout')
|
||||
eq({ '' }, call('map', call('getbufinfo'), 'v:val.name'))
|
||||
|
||||
call('ctxpop')
|
||||
eq({ '', unpack(bufs) }, call('map', call('getbufinfo'), 'v:val.name'))
|
||||
end)
|
||||
|
||||
it('saves and restores global variables properly', function()
|
||||
api.nvim_set_var('one', 1)
|
||||
api.nvim_set_var('Two', 2)
|
||||
api.nvim_set_var('THREE', 3)
|
||||
eq({ 1, 2, 3 }, eval('[g:one, g:Two, g:THREE]'))
|
||||
call('ctxpush')
|
||||
call('ctxpush', { 'gvars' })
|
||||
|
||||
api.nvim_del_var('one')
|
||||
api.nvim_del_var('Two')
|
||||
api.nvim_del_var('THREE')
|
||||
eq('Vim:E121: Undefined variable: g:one', pcall_err(eval, 'g:one'))
|
||||
eq('Vim:E121: Undefined variable: g:Two', pcall_err(eval, 'g:Two'))
|
||||
eq('Vim:E121: Undefined variable: g:THREE', pcall_err(eval, 'g:THREE'))
|
||||
|
||||
call('ctxpop')
|
||||
eq({ 1, 2, 3 }, eval('[g:one, g:Two, g:THREE]'))
|
||||
|
||||
api.nvim_del_var('one')
|
||||
api.nvim_del_var('Two')
|
||||
api.nvim_del_var('THREE')
|
||||
eq('Vim:E121: Undefined variable: g:one', pcall_err(eval, 'g:one'))
|
||||
eq('Vim:E121: Undefined variable: g:Two', pcall_err(eval, 'g:Two'))
|
||||
eq('Vim:E121: Undefined variable: g:THREE', pcall_err(eval, 'g:THREE'))
|
||||
|
||||
call('ctxpop')
|
||||
eq({ 1, 2, 3 }, eval('[g:one, g:Two, g:THREE]'))
|
||||
end)
|
||||
|
||||
it('saves and restores script functions properly', function()
|
||||
source([[
|
||||
function s:greet(name)
|
||||
echom 'Hello, '.a:name.'!'
|
||||
endfunction
|
||||
|
||||
function s:greet_all(name, ...)
|
||||
echom 'Hello, '.a:name.'!'
|
||||
for more in a:000
|
||||
echom 'Hello, '.more.'!'
|
||||
endfor
|
||||
endfunction
|
||||
|
||||
function Greet(name)
|
||||
call call('s:greet', [a:name])
|
||||
endfunction
|
||||
|
||||
function GreetAll(name, ...)
|
||||
call call('s:greet_all', extend([a:name], a:000))
|
||||
endfunction
|
||||
|
||||
function SaveSFuncs()
|
||||
call ctxpush(['sfuncs'])
|
||||
endfunction
|
||||
|
||||
function DeleteSFuncs()
|
||||
delfunction s:greet
|
||||
delfunction s:greet_all
|
||||
endfunction
|
||||
|
||||
function RestoreFuncs()
|
||||
call ctxpop()
|
||||
endfunction
|
||||
|
||||
let g:sid = expand('<SID>')
|
||||
]])
|
||||
local sid = api.nvim_get_var('sid')
|
||||
|
||||
eq('Hello, World!', exec_capture([[call Greet('World')]]))
|
||||
eq(
|
||||
'Hello, World!' .. '\nHello, One!' .. '\nHello, Two!' .. '\nHello, Three!',
|
||||
exec_capture([[call GreetAll('World', 'One', 'Two', 'Three')]])
|
||||
)
|
||||
|
||||
call('SaveSFuncs')
|
||||
call('DeleteSFuncs')
|
||||
|
||||
eq(
|
||||
('function Greet, line 1: Vim(call):E117: Unknown function: %sgreet'):format(sid),
|
||||
pcall_err(command, [[call Greet('World')]])
|
||||
)
|
||||
eq(
|
||||
('function GreetAll, line 1: Vim(call):E117: Unknown function: %sgreet_all'):format(sid),
|
||||
pcall_err(command, [[call GreetAll('World', 'One', 'Two', 'Three')]])
|
||||
)
|
||||
|
||||
call('RestoreFuncs')
|
||||
|
||||
eq('Hello, World!', exec_capture([[call Greet('World')]]))
|
||||
eq(
|
||||
'Hello, World!' .. '\nHello, One!' .. '\nHello, Two!' .. '\nHello, Three!',
|
||||
exec_capture([[call GreetAll('World', 'One', 'Two', 'Three')]])
|
||||
)
|
||||
end)
|
||||
|
||||
it('saves and restores functions properly', function()
|
||||
source([[
|
||||
function Greet(name)
|
||||
echom 'Hello, '.a:name.'!'
|
||||
endfunction
|
||||
|
||||
function GreetAll(name, ...)
|
||||
echom 'Hello, '.a:name.'!'
|
||||
for more in a:000
|
||||
echom 'Hello, '.more.'!'
|
||||
endfor
|
||||
endfunction
|
||||
]])
|
||||
|
||||
eq('Hello, World!', exec_capture([[call Greet('World')]]))
|
||||
eq(
|
||||
'Hello, World!' .. '\nHello, One!' .. '\nHello, Two!' .. '\nHello, Three!',
|
||||
exec_capture([[call GreetAll('World', 'One', 'Two', 'Three')]])
|
||||
)
|
||||
|
||||
call('ctxpush', { 'funcs' })
|
||||
command('delfunction Greet')
|
||||
command('delfunction GreetAll')
|
||||
|
||||
eq('Vim:E117: Unknown function: Greet', pcall_err(call, 'Greet', 'World'))
|
||||
eq(
|
||||
'Vim:E117: Unknown function: GreetAll',
|
||||
pcall_err(call, 'GreetAll', 'World', 'One', 'Two', 'Three')
|
||||
)
|
||||
|
||||
call('ctxpop')
|
||||
|
||||
eq('Hello, World!', exec_capture([[call Greet('World')]]))
|
||||
eq(
|
||||
'Hello, World!' .. '\nHello, One!' .. '\nHello, Two!' .. '\nHello, Three!',
|
||||
exec_capture([[call GreetAll('World', 'One', 'Two', 'Three')]])
|
||||
)
|
||||
end)
|
||||
|
||||
it('errors out when context stack is empty', function()
|
||||
local err = 'Vim:Context stack is empty'
|
||||
eq(err, pcall_err(call, 'ctxpop'))
|
||||
eq(err, pcall_err(call, 'ctxpop'))
|
||||
call('ctxpush')
|
||||
call('ctxpush')
|
||||
call('ctxpop')
|
||||
call('ctxpop')
|
||||
eq(err, pcall_err(call, 'ctxpop'))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('ctxsize()', function()
|
||||
it('returns context stack size', function()
|
||||
eq(0, call('ctxsize'))
|
||||
call('ctxpush')
|
||||
eq(1, call('ctxsize'))
|
||||
call('ctxpush')
|
||||
eq(2, call('ctxsize'))
|
||||
call('ctxpush')
|
||||
eq(3, call('ctxsize'))
|
||||
call('ctxpop')
|
||||
eq(2, call('ctxsize'))
|
||||
call('ctxpop')
|
||||
eq(1, call('ctxsize'))
|
||||
call('ctxpop')
|
||||
eq(0, call('ctxsize'))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('ctxget()', function()
|
||||
it('errors out when index is out of bounds', function()
|
||||
eq(outofbounds, pcall_err(call, 'ctxget'))
|
||||
call('ctxpush')
|
||||
eq(outofbounds, pcall_err(call, 'ctxget', 1))
|
||||
call('ctxpop')
|
||||
eq(outofbounds, pcall_err(call, 'ctxget', 0))
|
||||
end)
|
||||
|
||||
it('returns context dict at index in context stack', function()
|
||||
feed('i1<cr>2<cr>3<c-[>ddddddqahjklq')
|
||||
command('edit! ' .. fname1)
|
||||
feed('G')
|
||||
feed('gg')
|
||||
command('edit ' .. fname2)
|
||||
api.nvim_set_var('one', 1)
|
||||
api.nvim_set_var('Two', 2)
|
||||
api.nvim_set_var('THREE', 3)
|
||||
|
||||
local with_regs = {
|
||||
['regs'] = {
|
||||
{ ['rt'] = 1, ['rc'] = { '1' }, ['n'] = 49, ['ru'] = true },
|
||||
{ ['rt'] = 1, ['rc'] = { '2' }, ['n'] = 50 },
|
||||
{ ['rt'] = 1, ['rc'] = { '3' }, ['n'] = 51 },
|
||||
{ ['rc'] = { 'hjkl' }, ['n'] = 97 },
|
||||
},
|
||||
}
|
||||
|
||||
local with_jumps = {
|
||||
['jumps'] = eval((([[
|
||||
filter(map(add(
|
||||
getjumplist()[0], { 'bufnr': bufnr('%'), 'lnum': getcurpos()[1] }),
|
||||
'filter(
|
||||
{ "f": expand("#".v:val.bufnr.":p:gs?\\?/?"), "l": v:val.lnum },
|
||||
{ k, v -> k != "l" || v != 1 })'), '!empty(v:val.f)')
|
||||
]]):gsub('\n', ''))),
|
||||
}
|
||||
|
||||
local with_bufs = {
|
||||
['bufs'] = eval([[
|
||||
filter(map(getbufinfo(), '{ "f": v:val.name }'), '!empty(v:val.f)')
|
||||
]]),
|
||||
}
|
||||
|
||||
local with_gvars = {
|
||||
['gvars'] = { { 'one', 1 }, { 'Two', 2 }, { 'THREE', 3 } },
|
||||
}
|
||||
|
||||
local with_all = {
|
||||
['regs'] = with_regs['regs'],
|
||||
['jumps'] = with_jumps['jumps'],
|
||||
['bufs'] = with_bufs['bufs'],
|
||||
['gvars'] = with_gvars['gvars'],
|
||||
}
|
||||
|
||||
call('ctxpush')
|
||||
eq(with_all, parse_context(call('ctxget')))
|
||||
eq(with_all, parse_context(call('ctxget', 0)))
|
||||
|
||||
call('ctxpush', { 'gvars' })
|
||||
eq(with_gvars, parse_context(call('ctxget')))
|
||||
eq(with_gvars, parse_context(call('ctxget', 0)))
|
||||
eq(with_all, parse_context(call('ctxget', 1)))
|
||||
|
||||
call('ctxpush', { 'bufs' })
|
||||
eq(with_bufs, parse_context(call('ctxget')))
|
||||
eq(with_bufs, parse_context(call('ctxget', 0)))
|
||||
eq(with_gvars, parse_context(call('ctxget', 1)))
|
||||
eq(with_all, parse_context(call('ctxget', 2)))
|
||||
|
||||
call('ctxpush', { 'jumps' })
|
||||
eq(with_jumps, parse_context(call('ctxget')))
|
||||
eq(with_jumps, parse_context(call('ctxget', 0)))
|
||||
eq(with_bufs, parse_context(call('ctxget', 1)))
|
||||
eq(with_gvars, parse_context(call('ctxget', 2)))
|
||||
eq(with_all, parse_context(call('ctxget', 3)))
|
||||
|
||||
call('ctxpush', { 'regs' })
|
||||
eq(with_regs, parse_context(call('ctxget')))
|
||||
eq(with_regs, parse_context(call('ctxget', 0)))
|
||||
eq(with_jumps, parse_context(call('ctxget', 1)))
|
||||
eq(with_bufs, parse_context(call('ctxget', 2)))
|
||||
eq(with_gvars, parse_context(call('ctxget', 3)))
|
||||
eq(with_all, parse_context(call('ctxget', 4)))
|
||||
|
||||
call('ctxpop')
|
||||
eq(with_jumps, parse_context(call('ctxget')))
|
||||
eq(with_jumps, parse_context(call('ctxget', 0)))
|
||||
eq(with_bufs, parse_context(call('ctxget', 1)))
|
||||
eq(with_gvars, parse_context(call('ctxget', 2)))
|
||||
eq(with_all, parse_context(call('ctxget', 3)))
|
||||
|
||||
call('ctxpop')
|
||||
eq(with_bufs, parse_context(call('ctxget')))
|
||||
eq(with_bufs, parse_context(call('ctxget', 0)))
|
||||
eq(with_gvars, parse_context(call('ctxget', 1)))
|
||||
eq(with_all, parse_context(call('ctxget', 2)))
|
||||
|
||||
call('ctxpop')
|
||||
eq(with_gvars, parse_context(call('ctxget')))
|
||||
eq(with_gvars, parse_context(call('ctxget', 0)))
|
||||
eq(with_all, parse_context(call('ctxget', 1)))
|
||||
|
||||
call('ctxpop')
|
||||
eq(with_all, parse_context(call('ctxget')))
|
||||
eq(with_all, parse_context(call('ctxget', 0)))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('ctxset()', function()
|
||||
it('errors out when index is out of bounds', function()
|
||||
eq(outofbounds, pcall_err(call, 'ctxset', { dummy = 1 }))
|
||||
call('ctxpush')
|
||||
eq(outofbounds, pcall_err(call, 'ctxset', { dummy = 1 }, 1))
|
||||
call('ctxpop')
|
||||
eq(outofbounds, pcall_err(call, 'ctxset', { dummy = 1 }, 0))
|
||||
end)
|
||||
|
||||
it('errors when context dict is invalid', function()
|
||||
call('ctxpush')
|
||||
eq(
|
||||
'Vim:E474: Failed to convert list to msgpack string buffer',
|
||||
pcall_err(call, 'ctxset', { regs = { {} }, jumps = { {} } })
|
||||
)
|
||||
end)
|
||||
|
||||
it('sets context dict at index in context stack', function()
|
||||
api.nvim_set_var('one', 1)
|
||||
api.nvim_set_var('Two', 2)
|
||||
api.nvim_set_var('THREE', 3)
|
||||
call('ctxpush')
|
||||
local ctx1 = call('ctxget')
|
||||
api.nvim_set_var('one', 'a')
|
||||
api.nvim_set_var('Two', 'b')
|
||||
api.nvim_set_var('THREE', 'c')
|
||||
call('ctxpush')
|
||||
call('ctxpush')
|
||||
local ctx2 = call('ctxget')
|
||||
|
||||
eq({ 'a', 'b', 'c' }, eval('[g:one, g:Two, g:THREE]'))
|
||||
call('ctxset', ctx1)
|
||||
call('ctxset', ctx2, 2)
|
||||
call('ctxpop')
|
||||
eq({ 1, 2, 3 }, eval('[g:one, g:Two, g:THREE]'))
|
||||
call('ctxpop')
|
||||
eq({ 'a', 'b', 'c' }, eval('[g:one, g:Two, g:THREE]'))
|
||||
api.nvim_set_var('one', 1.5)
|
||||
eq({ 1.5, 'b', 'c' }, eval('[g:one, g:Two, g:THREE]'))
|
||||
call('ctxpop')
|
||||
eq({ 'a', 'b', 'c' }, eval('[g:one, g:Two, g:THREE]'))
|
||||
end)
|
||||
end)
|
||||
end)
|
||||
Reference in New Issue
Block a user