mirror of
https://github.com/neovim/neovim.git
synced 2025-09-06 03:18:16 +00:00
vim-patch:8.1.2047: cannot check the current state
Problem: Cannot check the current state.
Solution: Add the state() function.
0e57dd859e
Co-authored-by: Bram Moolenaar <Bram@vim.org>
This commit is contained in:
26
runtime/doc/builtin.txt
generated
26
runtime/doc/builtin.txt
generated
@@ -4753,6 +4753,7 @@ mode([expr]) *mode()*
|
|||||||
If [expr] is supplied and it evaluates to a non-zero Number or
|
If [expr] is supplied and it evaluates to a non-zero Number or
|
||||||
a non-empty String (|non-zero-arg|), then the full mode is
|
a non-empty String (|non-zero-arg|), then the full mode is
|
||||||
returned, otherwise only the first letter is returned.
|
returned, otherwise only the first letter is returned.
|
||||||
|
Also see |state()|.
|
||||||
|
|
||||||
n Normal
|
n Normal
|
||||||
no Operator-pending
|
no Operator-pending
|
||||||
@@ -7368,6 +7369,31 @@ srand([{expr}]) *srand()*
|
|||||||
echo rand(seed)
|
echo rand(seed)
|
||||||
<
|
<
|
||||||
|
|
||||||
|
state([{what}]) *state()*
|
||||||
|
Return a string which contains characters indicating the
|
||||||
|
current state. Mostly useful in callbacks that want to do
|
||||||
|
work that may not always be safe. Roughly this works like:
|
||||||
|
- callback uses state() to check if work is safe to do.
|
||||||
|
If yes, then do it right away.
|
||||||
|
Otherwise add to work queue and add SafeState autocommand.
|
||||||
|
- When SafeState is triggered, check with state() if the work
|
||||||
|
can be done now, and if yes remove it from the queue and
|
||||||
|
execute.
|
||||||
|
Also see |mode()|.
|
||||||
|
|
||||||
|
When {what} is given only characters in this string will be
|
||||||
|
added. E.g, this checks if the screen has scrolled: >vim
|
||||||
|
if state('s') != ''
|
||||||
|
|
||||||
|
These characters indicate the state:
|
||||||
|
m halfway a mapping, :normal command, feedkeys() or
|
||||||
|
stuffed command
|
||||||
|
o operator pending or waiting for a command argument
|
||||||
|
a Insert mode autocomplete active
|
||||||
|
x executing an autocommand
|
||||||
|
c callback invoked (repeats for recursiveness up to "ccc")
|
||||||
|
s screen has scrolled for messages
|
||||||
|
|
||||||
stdioopen({opts}) *stdioopen()*
|
stdioopen({opts}) *stdioopen()*
|
||||||
With |--headless| this opens stdin and stdout as a |channel|.
|
With |--headless| this opens stdin and stdout as a |channel|.
|
||||||
May be called only once. See |channel-stdio|. stderr is not
|
May be called only once. See |channel-stdio|. stderr is not
|
||||||
|
29
runtime/lua/vim/_meta/vimfn.lua
generated
29
runtime/lua/vim/_meta/vimfn.lua
generated
@@ -5713,6 +5713,7 @@ function vim.fn.mkdir(name, flags, prot) end
|
|||||||
--- If [expr] is supplied and it evaluates to a non-zero Number or
|
--- If [expr] is supplied and it evaluates to a non-zero Number or
|
||||||
--- a non-empty String (|non-zero-arg|), then the full mode is
|
--- a non-empty String (|non-zero-arg|), then the full mode is
|
||||||
--- returned, otherwise only the first letter is returned.
|
--- returned, otherwise only the first letter is returned.
|
||||||
|
--- Also see |state()|.
|
||||||
---
|
---
|
||||||
--- n Normal
|
--- n Normal
|
||||||
--- no Operator-pending
|
--- no Operator-pending
|
||||||
@@ -8744,6 +8745,34 @@ function vim.fn.sqrt(expr) end
|
|||||||
--- @return any
|
--- @return any
|
||||||
function vim.fn.srand(expr) end
|
function vim.fn.srand(expr) end
|
||||||
|
|
||||||
|
--- Return a string which contains characters indicating the
|
||||||
|
--- current state. Mostly useful in callbacks that want to do
|
||||||
|
--- work that may not always be safe. Roughly this works like:
|
||||||
|
--- - callback uses state() to check if work is safe to do.
|
||||||
|
--- If yes, then do it right away.
|
||||||
|
--- Otherwise add to work queue and add SafeState autocommand.
|
||||||
|
--- - When SafeState is triggered, check with state() if the work
|
||||||
|
--- can be done now, and if yes remove it from the queue and
|
||||||
|
--- execute.
|
||||||
|
--- Also see |mode()|.
|
||||||
|
---
|
||||||
|
--- When {what} is given only characters in this string will be
|
||||||
|
--- added. E.g, this checks if the screen has scrolled: >vim
|
||||||
|
--- if state('s') != ''
|
||||||
|
---
|
||||||
|
--- These characters indicate the state:
|
||||||
|
--- m halfway a mapping, :normal command, feedkeys() or
|
||||||
|
--- stuffed command
|
||||||
|
--- o operator pending or waiting for a command argument
|
||||||
|
--- a Insert mode autocomplete active
|
||||||
|
--- x executing an autocommand
|
||||||
|
--- c callback invoked (repeats for recursiveness up to "ccc")
|
||||||
|
--- s screen has scrolled for messages
|
||||||
|
---
|
||||||
|
--- @param what? string
|
||||||
|
--- @return any
|
||||||
|
function vim.fn.state(what) end
|
||||||
|
|
||||||
--- With |--headless| this opens stdin and stdout as a |channel|.
|
--- With |--headless| this opens stdin and stdout as a |channel|.
|
||||||
--- May be called only once. See |channel-stdio|. stderr is not
|
--- May be called only once. See |channel-stdio|. stderr is not
|
||||||
--- handled by this function, see |v:stderr|.
|
--- handled by this function, see |v:stderr|.
|
||||||
|
@@ -5994,6 +5994,13 @@ bool callback_from_typval(Callback *const callback, const typval_T *const arg)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int callback_depth = 0;
|
||||||
|
|
||||||
|
int get_callback_depth(void)
|
||||||
|
{
|
||||||
|
return callback_depth;
|
||||||
|
}
|
||||||
|
|
||||||
/// @return whether the callback could be called.
|
/// @return whether the callback could be called.
|
||||||
bool callback_call(Callback *const callback, const int argcount_in, typval_T *const argvars_in,
|
bool callback_call(Callback *const callback, const int argcount_in, typval_T *const argvars_in,
|
||||||
typval_T *const rettv)
|
typval_T *const rettv)
|
||||||
@@ -6041,7 +6048,11 @@ bool callback_call(Callback *const callback, const int argcount_in, typval_T *co
|
|||||||
funcexe.fe_lastline = curwin->w_cursor.lnum;
|
funcexe.fe_lastline = curwin->w_cursor.lnum;
|
||||||
funcexe.fe_evaluate = true;
|
funcexe.fe_evaluate = true;
|
||||||
funcexe.fe_partial = partial;
|
funcexe.fe_partial = partial;
|
||||||
return call_func(name, -1, rettv, argcount_in, argvars_in, &funcexe);
|
|
||||||
|
callback_depth++;
|
||||||
|
int ret = call_func(name, -1, rettv, argcount_in, argvars_in, &funcexe);
|
||||||
|
callback_depth--;
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool set_ref_in_callback(Callback *callback, int copyID, ht_stack_T **ht_stack,
|
bool set_ref_in_callback(Callback *callback, int copyID, ht_stack_T **ht_stack,
|
||||||
|
@@ -6917,6 +6917,7 @@ M.funcs = {
|
|||||||
If [expr] is supplied and it evaluates to a non-zero Number or
|
If [expr] is supplied and it evaluates to a non-zero Number or
|
||||||
a non-empty String (|non-zero-arg|), then the full mode is
|
a non-empty String (|non-zero-arg|), then the full mode is
|
||||||
returned, otherwise only the first letter is returned.
|
returned, otherwise only the first letter is returned.
|
||||||
|
Also see |state()|.
|
||||||
|
|
||||||
n Normal
|
n Normal
|
||||||
no Operator-pending
|
no Operator-pending
|
||||||
@@ -10451,6 +10452,38 @@ M.funcs = {
|
|||||||
params = { { 'what', 'any' } },
|
params = { { 'what', 'any' } },
|
||||||
signature = 'stdpath({what})',
|
signature = 'stdpath({what})',
|
||||||
},
|
},
|
||||||
|
state = {
|
||||||
|
args = {0, 1},
|
||||||
|
base = 1,
|
||||||
|
desc = [=[
|
||||||
|
Return a string which contains characters indicating the
|
||||||
|
current state. Mostly useful in callbacks that want to do
|
||||||
|
work that may not always be safe. Roughly this works like:
|
||||||
|
- callback uses state() to check if work is safe to do.
|
||||||
|
If yes, then do it right away.
|
||||||
|
Otherwise add to work queue and add SafeState autocommand.
|
||||||
|
- When SafeState is triggered, check with state() if the work
|
||||||
|
can be done now, and if yes remove it from the queue and
|
||||||
|
execute.
|
||||||
|
Also see |mode()|.
|
||||||
|
|
||||||
|
When {what} is given only characters in this string will be
|
||||||
|
added. E.g, this checks if the screen has scrolled: >vim
|
||||||
|
if state('s') != ''
|
||||||
|
|
||||||
|
These characters indicate the state:
|
||||||
|
m halfway a mapping, :normal command, feedkeys() or
|
||||||
|
stuffed command
|
||||||
|
o operator pending or waiting for a command argument
|
||||||
|
a Insert mode autocomplete active
|
||||||
|
x executing an autocommand
|
||||||
|
c callback invoked (repeats for recursiveness up to "ccc")
|
||||||
|
s screen has scrolled for messages
|
||||||
|
]=],
|
||||||
|
name = 'state',
|
||||||
|
params = { { 'what', 'string' } },
|
||||||
|
signature = 'state([{what}])',
|
||||||
|
},
|
||||||
str2float = {
|
str2float = {
|
||||||
args = 1,
|
args = 1,
|
||||||
base = 1,
|
base = 1,
|
||||||
|
@@ -4925,6 +4925,47 @@ static void f_mode(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
|||||||
rettv->v_type = VAR_STRING;
|
rettv->v_type = VAR_STRING;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void may_add_state_char(garray_T *gap, const char *include, uint8_t c)
|
||||||
|
{
|
||||||
|
if (include == NULL || vim_strchr(include, c) != NULL) {
|
||||||
|
ga_append(gap, c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// "state()" function
|
||||||
|
static void f_state(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||||
|
{
|
||||||
|
garray_T ga;
|
||||||
|
ga_init(&ga, 1, 20);
|
||||||
|
const char *include = NULL;
|
||||||
|
|
||||||
|
if (argvars[0].v_type != VAR_UNKNOWN) {
|
||||||
|
include = tv_get_string(&argvars[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!(stuff_empty() && typebuf.tb_len == 0 && !using_script())) {
|
||||||
|
may_add_state_char(&ga, include, 'm');
|
||||||
|
}
|
||||||
|
if (op_pending()) {
|
||||||
|
may_add_state_char(&ga, include, 'o');
|
||||||
|
}
|
||||||
|
if (autocmd_busy) {
|
||||||
|
may_add_state_char(&ga, include, 'x');
|
||||||
|
}
|
||||||
|
if (!ctrl_x_mode_none()) {
|
||||||
|
may_add_state_char(&ga, include, 'a');
|
||||||
|
}
|
||||||
|
for (int i = 0; i < get_callback_depth() && i < 3; i++) {
|
||||||
|
may_add_state_char(&ga, include, 'c');
|
||||||
|
}
|
||||||
|
if (msg_scrolled > 0) {
|
||||||
|
may_add_state_char(&ga, include, 's');
|
||||||
|
}
|
||||||
|
|
||||||
|
rettv->v_type = VAR_STRING;
|
||||||
|
rettv->vval.v_string = ga.ga_data;
|
||||||
|
}
|
||||||
|
|
||||||
/// "msgpackdump()" function
|
/// "msgpackdump()" function
|
||||||
static void f_msgpackdump(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
static void f_msgpackdump(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
|
||||||
FUNC_ATTR_NONNULL_ALL
|
FUNC_ATTR_NONNULL_ALL
|
||||||
|
@@ -36,6 +36,7 @@ hashpipe:write([[
|
|||||||
#include "nvim/quickfix.h"
|
#include "nvim/quickfix.h"
|
||||||
#include "nvim/runtime.h"
|
#include "nvim/runtime.h"
|
||||||
#include "nvim/search.h"
|
#include "nvim/search.h"
|
||||||
|
#include "nvim/state.h"
|
||||||
#include "nvim/strings.h"
|
#include "nvim/strings.h"
|
||||||
#include "nvim/sign.h"
|
#include "nvim/sign.h"
|
||||||
#include "nvim/testing.h"
|
#include "nvim/testing.h"
|
||||||
|
@@ -482,6 +482,20 @@ bool check_text_or_curbuf_locked(oparg_T *oap)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static oparg_T *current_oap = NULL;
|
||||||
|
|
||||||
|
/// Check if an operator was started but not finished yet.
|
||||||
|
/// Includes typing a count or a register name.
|
||||||
|
bool op_pending(void)
|
||||||
|
{
|
||||||
|
return !(current_oap != NULL
|
||||||
|
&& !finish_op
|
||||||
|
&& current_oap->prev_opcount == 0
|
||||||
|
&& current_oap->prev_count0 == 0
|
||||||
|
&& current_oap->op_type == OP_NOP
|
||||||
|
&& current_oap->regname == NUL);
|
||||||
|
}
|
||||||
|
|
||||||
/// Normal state entry point. This is called on:
|
/// Normal state entry point. This is called on:
|
||||||
///
|
///
|
||||||
/// - Startup, In this case the function never returns.
|
/// - Startup, In this case the function never returns.
|
||||||
@@ -490,15 +504,18 @@ bool check_text_or_curbuf_locked(oparg_T *oap)
|
|||||||
/// for example. Returns when re-entering ex mode(because ex mode recursion is
|
/// for example. Returns when re-entering ex mode(because ex mode recursion is
|
||||||
/// not allowed)
|
/// not allowed)
|
||||||
///
|
///
|
||||||
/// This used to be called main_loop on main.c
|
/// This used to be called main_loop() on main.c
|
||||||
void normal_enter(bool cmdwin, bool noexmode)
|
void normal_enter(bool cmdwin, bool noexmode)
|
||||||
{
|
{
|
||||||
NormalState state;
|
NormalState state;
|
||||||
normal_state_init(&state);
|
normal_state_init(&state);
|
||||||
|
oparg_T *prev_oap = current_oap;
|
||||||
|
current_oap = &state.oa;
|
||||||
state.cmdwin = cmdwin;
|
state.cmdwin = cmdwin;
|
||||||
state.noexmode = noexmode;
|
state.noexmode = noexmode;
|
||||||
state.toplevel = (!cmdwin || cmdwin_result == 0) && !noexmode;
|
state.toplevel = (!cmdwin || cmdwin_result == 0) && !noexmode;
|
||||||
state_enter(&state.state);
|
state_enter(&state.state);
|
||||||
|
current_oap = prev_oap;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void normal_prepare(NormalState *s)
|
static void normal_prepare(NormalState *s)
|
||||||
@@ -1299,12 +1316,7 @@ static void normal_check_buffer_modified(NormalState *s)
|
|||||||
/// type a character, trigger SafeState.
|
/// type a character, trigger SafeState.
|
||||||
static void normal_check_safe_state(NormalState *s)
|
static void normal_check_safe_state(NormalState *s)
|
||||||
{
|
{
|
||||||
may_trigger_safestate(!finish_op
|
may_trigger_safestate(!op_pending() && restart_edit == 0);
|
||||||
&& s->oa.prev_opcount > 0
|
|
||||||
&& s->oa.prev_count0 == 0
|
|
||||||
&& s->oa.op_type == OP_NOP
|
|
||||||
&& s->oa.regname == NUL
|
|
||||||
&& restart_edit == 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void normal_check_folds(NormalState *s)
|
static void normal_check_folds(NormalState *s)
|
||||||
|
Reference in New Issue
Block a user