aboutsummaryrefslogtreecommitdiff
path: root/src/nvim/getchar.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/nvim/getchar.c')
-rw-r--r--src/nvim/getchar.c106
1 files changed, 77 insertions, 29 deletions
diff --git a/src/nvim/getchar.c b/src/nvim/getchar.c
index 82abd2888a..0817d40bb8 100644
--- a/src/nvim/getchar.c
+++ b/src/nvim/getchar.c
@@ -2,7 +2,6 @@
// file, manipulations with redo buffer and stuff buffer.
#include <assert.h>
-#include <lauxlib.h>
#include <limits.h>
#include <stdbool.h>
#include <stddef.h>
@@ -11,6 +10,7 @@
#include <stdlib.h>
#include <string.h>
+#include "klib/kvec.h"
#include "nvim/api/private/defs.h"
#include "nvim/api/private/helpers.h"
#include "nvim/api/vim.h"
@@ -29,6 +29,7 @@
#include "nvim/ex_cmds.h"
#include "nvim/ex_docmd.h"
#include "nvim/ex_getln.h"
+#include "nvim/ex_getln_defs.h"
#include "nvim/garray.h"
#include "nvim/garray_defs.h"
#include "nvim/getchar.h"
@@ -38,6 +39,7 @@
#include "nvim/insexpand.h"
#include "nvim/keycodes.h"
#include "nvim/lua/executor.h"
+#include "nvim/macros_defs.h"
#include "nvim/main.h"
#include "nvim/mapping.h"
#include "nvim/mapping_defs.h"
@@ -45,6 +47,7 @@
#include "nvim/mbyte_defs.h"
#include "nvim/memline.h"
#include "nvim/memory.h"
+#include "nvim/memory_defs.h"
#include "nvim/message.h"
#include "nvim/mouse.h"
#include "nvim/move.h"
@@ -53,6 +56,7 @@
#include "nvim/ops.h"
#include "nvim/option_vars.h"
#include "nvim/os/fileio.h"
+#include "nvim/os/fileio_defs.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
#include "nvim/os/os_defs.h"
@@ -471,7 +475,7 @@ void beep_flush(void)
{
if (emsg_silent == 0) {
flush_buffers(FLUSH_MINIMAL);
- vim_beep(BO_ERROR);
+ vim_beep(kOptBoFlagError);
}
}
@@ -1513,7 +1517,7 @@ int merge_modifiers(int c_arg, int *modifiers)
int c = c_arg;
if (*modifiers & MOD_MASK_CTRL) {
- if ((c >= '`' && c <= 0x7f) || (c >= '@' && c <= '_')) {
+ if (c >= '@' && c <= 0x7f) {
c &= 0x1f;
if (c == NUL) {
c = K_ZERO;
@@ -1862,29 +1866,73 @@ bool char_avail(void)
return retval != NUL;
}
+static int no_reduce_keys = 0; ///< Do not apply modifiers to the key.
+
/// "getchar()" and "getcharstr()" functions
-static void getchar_common(typval_T *argvars, typval_T *rettv)
+static void getchar_common(typval_T *argvars, typval_T *rettv, bool allow_number)
FUNC_ATTR_NONNULL_ALL
{
- varnumber_T n;
+ varnumber_T n = 0;
+ const int called_emsg_start = called_emsg;
bool error = false;
+ bool simplify = true;
+ char cursor_flag = NUL;
+
+ if (argvars[0].v_type != VAR_UNKNOWN
+ && tv_check_for_opt_dict_arg(argvars, 1) == FAIL) {
+ return;
+ }
+
+ if (argvars[0].v_type != VAR_UNKNOWN && argvars[1].v_type == VAR_DICT) {
+ dict_T *d = argvars[1].vval.v_dict;
+
+ if (allow_number) {
+ allow_number = tv_dict_get_bool(d, "number", true);
+ } else if (tv_dict_has_key(d, "number")) {
+ semsg(_(e_invarg2), "number");
+ }
+
+ simplify = tv_dict_get_bool(d, "simplify", true);
+
+ const char *cursor_str = tv_dict_get_string(d, "cursor", false);
+ if (cursor_str != NULL) {
+ if (strcmp(cursor_str, "hide") != 0
+ && strcmp(cursor_str, "keep") != 0
+ && strcmp(cursor_str, "msg") != 0) {
+ semsg(_(e_invargNval), "cursor", cursor_str);
+ } else {
+ cursor_flag = cursor_str[0];
+ }
+ }
+ }
+
+ if (called_emsg != called_emsg_start) {
+ return;
+ }
+
+ if (cursor_flag == 'h') {
+ ui_busy_start();
+ }
no_mapping++;
allow_keys++;
+ if (!simplify) {
+ no_reduce_keys++;
+ }
while (true) {
- if (msg_col > 0) {
- // Position the cursor. Needed after a message that ends in a space.
+ if (cursor_flag == 'm' || (cursor_flag == NUL && msg_col > 0)) {
ui_cursor_goto(msg_row, msg_col);
}
- if (argvars[0].v_type == VAR_UNKNOWN) {
+ if (argvars[0].v_type == VAR_UNKNOWN
+ || (argvars[0].v_type == VAR_NUMBER && argvars[0].vval.v_number == -1)) {
// getchar(): blocking wait.
// TODO(bfredl): deduplicate shared logic with state_enter ?
if (!char_avail()) {
// Flush screen updates before blocking.
ui_flush();
input_get(NULL, 0, -1, typebuf.tb_change_cnt, main_loop.events);
- if (!multiqueue_empty(main_loop.events)) {
+ if (!input_available() && !multiqueue_empty(main_loop.events)) {
state_handle_k_event();
continue;
}
@@ -1912,14 +1960,20 @@ static void getchar_common(typval_T *argvars, typval_T *rettv)
}
no_mapping--;
allow_keys--;
+ if (!simplify) {
+ no_reduce_keys--;
+ }
+
+ if (cursor_flag == 'h') {
+ ui_busy_stop();
+ }
set_vim_var_nr(VV_MOUSE_WIN, 0);
set_vim_var_nr(VV_MOUSE_WINID, 0);
set_vim_var_nr(VV_MOUSE_LNUM, 0);
set_vim_var_nr(VV_MOUSE_COL, 0);
- rettv->vval.v_number = n;
- if (n != 0 && (IS_SPECIAL(n) || mod_mask != 0)) {
+ if (n != 0 && (!allow_number || IS_SPECIAL(n) || mod_mask != 0)) {
char temp[10]; // modifier: 3, mbyte-char: 6, NUL: 1
int i = 0;
@@ -1966,35 +2020,23 @@ static void getchar_common(typval_T *argvars, typval_T *rettv)
set_vim_var_nr(VV_MOUSE_COL, col + 1);
}
}
+ } else if (!allow_number) {
+ rettv->v_type = VAR_STRING;
+ } else {
+ rettv->vval.v_number = n;
}
}
/// "getchar()" function
void f_getchar(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
- getchar_common(argvars, rettv);
+ getchar_common(argvars, rettv, true);
}
/// "getcharstr()" function
void f_getcharstr(typval_T *argvars, typval_T *rettv, EvalFuncData fptr)
{
- getchar_common(argvars, rettv);
-
- if (rettv->v_type != VAR_NUMBER) {
- return;
- }
-
- char temp[7]; // mbyte-char: 6, NUL: 1
- const varnumber_T n = rettv->vval.v_number;
- int i = 0;
-
- if (n != 0) {
- i += utf_char2bytes((int)n, temp);
- }
- assert(i < 7);
- temp[i] = NUL;
- rettv->v_type = VAR_STRING;
- rettv->vval.v_string = xmemdupz(temp, (size_t)i);
+ getchar_common(argvars, rettv, false);
}
/// "getcharmod()" function
@@ -2052,6 +2094,12 @@ static bool at_ins_compl_key(void)
/// @return the length of the replaced bytes, 0 if nothing changed, -1 for error.
static int check_simplify_modifier(int max_offset)
{
+ // We want full modifiers in Terminal mode so that the key can be correctly
+ // encoded
+ if ((State & MODE_TERMINAL) || no_reduce_keys > 0) {
+ return 0;
+ }
+
for (int offset = 0; offset < max_offset; offset++) {
if (offset + 3 >= typebuf.tb_len) {
break;