mirror of
https://github.com/neovim/neovim.git
synced 2026-08-30 19:11:52 +00:00
Merge remote-tracking branch 'upstream/master'
This commit is contained in:
@@ -11,6 +11,18 @@ if [[ "${TRAVIS_OS_NAME}" == osx ]]; then
|
||||
brew update
|
||||
fi
|
||||
|
||||
echo 'python info:'
|
||||
(
|
||||
2>&1 python --version || true
|
||||
2>&1 python2 --version || true
|
||||
2>&1 python3 --version || true
|
||||
2>&1 pip --version || true
|
||||
2>&1 pip2 --version || true
|
||||
2>&1 pip3 --version || true
|
||||
echo 'pyenv versions:'
|
||||
2>&1 pyenv versions || true
|
||||
) | sed 's/^/ /'
|
||||
|
||||
echo "Upgrade Python 2 pip."
|
||||
pip2.7 -q install --user --upgrade pip
|
||||
|
||||
@@ -20,6 +32,10 @@ if [[ "${TRAVIS_OS_NAME}" == osx ]]; then
|
||||
echo "Upgrade Python 3 pip."
|
||||
pip3 -q install --user --upgrade pip
|
||||
else
|
||||
echo "Upgrade Python 3 pip."
|
||||
pip3 -q install --user --upgrade pip
|
||||
if command -v pip3 ; then
|
||||
echo "Upgrade Python 3 pip."
|
||||
pip3 -q install --user --upgrade pip
|
||||
else
|
||||
echo 'warning: missing pip3'
|
||||
fi
|
||||
fi
|
||||
|
||||
@@ -239,7 +239,7 @@ function! s:check_python(version) abort
|
||||
|
||||
let pyname = 'python'.(a:version == 2 ? '' : '3')
|
||||
let pyenv = resolve(exepath('pyenv'))
|
||||
let pyenv_root = exists('$PYENV_ROOT') ? resolve($PYENV_ROOT) : 'n'
|
||||
let pyenv_root = exists('$PYENV_ROOT') ? resolve($PYENV_ROOT) : ''
|
||||
let venv = exists('$VIRTUAL_ENV') ? resolve($VIRTUAL_ENV) : ''
|
||||
let host_prog_var = pyname.'_host_prog'
|
||||
let loaded_var = 'g:loaded_'.pyname.'_provider'
|
||||
@@ -251,6 +251,19 @@ function! s:check_python(version) abort
|
||||
return
|
||||
endif
|
||||
|
||||
if !empty(pyenv)
|
||||
if empty(pyenv_root)
|
||||
call health#report_warn(
|
||||
\ 'pyenv was found, but $PYENV_ROOT is not set.',
|
||||
\ ['Did you follow the final install instructions?',
|
||||
\ 'If you use a shell "framework" like Prezto or Oh My Zsh, try without.',
|
||||
\ 'Try a different shell (bash).']
|
||||
\ )
|
||||
else
|
||||
call health#report_ok(printf('pyenv found: "%s"', pyenv))
|
||||
endif
|
||||
endif
|
||||
|
||||
if exists('g:'.host_prog_var)
|
||||
call health#report_info(printf('Using: g:%s = "%s"', host_prog_var, get(g:, host_prog_var)))
|
||||
endif
|
||||
@@ -282,15 +295,6 @@ function! s:check_python(version) abort
|
||||
endif
|
||||
|
||||
if !empty(pyenv)
|
||||
if empty(pyenv_root)
|
||||
call health#report_warn(
|
||||
\ 'pyenv was found, but $PYENV_ROOT is not set.',
|
||||
\ ['Did you follow the final install instructions?']
|
||||
\ )
|
||||
else
|
||||
call health#report_ok(printf('pyenv found: "%s"', pyenv))
|
||||
endif
|
||||
|
||||
let python_bin = s:trim(s:system([pyenv, 'which', pyname], '', 1))
|
||||
|
||||
if empty(python_bin)
|
||||
@@ -320,9 +324,8 @@ function! s:check_python(version) abort
|
||||
|
||||
if python_bin =~# '\<shims\>'
|
||||
call health#report_warn(printf('`%s` appears to be a pyenv shim.', python_bin), [
|
||||
\ 'The `pyenv` executable is not in $PATH,',
|
||||
\ 'Your pyenv installation is broken. You should set '
|
||||
\ . '`g:'.host_prog_var.'` to avoid surprises.',
|
||||
\ '`pyenv` is not in $PATH, your pyenv installation is broken. '
|
||||
\ .'Set `g:'.host_prog_var.'` to avoid surprises.',
|
||||
\ ])
|
||||
endif
|
||||
endif
|
||||
@@ -335,7 +338,7 @@ function! s:check_python(version) abort
|
||||
call health#report_warn('pyenv is not set up optimally.', [
|
||||
\ printf('Create a virtualenv specifically '
|
||||
\ . 'for Neovim using pyenv, and set `g:%s`. This will avoid '
|
||||
\ . 'the need to install Neovim''s Python module in each '
|
||||
\ . 'the need to install the Neovim Python module in each '
|
||||
\ . 'version/virtualenv.', host_prog_var)
|
||||
\ ])
|
||||
elseif !empty(venv) && exists('g:'.host_prog_var)
|
||||
|
||||
@@ -215,6 +215,7 @@ static void ui_set_option(UI *ui, String name, Object value, Error *error)
|
||||
#undef UI_EXT_OPTION
|
||||
}
|
||||
|
||||
/// Pushes data into UI.UIData, to be consumed later by remote_ui_flush().
|
||||
static void push_call(UI *ui, char *name, Array args)
|
||||
{
|
||||
Array call = ARRAY_DICT_INIT;
|
||||
|
||||
@@ -255,12 +255,11 @@ free_vim_args:
|
||||
return rv;
|
||||
}
|
||||
|
||||
/// Execute lua code. Parameters might be passed, they are available inside
|
||||
/// the chunk as `...`. The chunk can return a value.
|
||||
/// Execute lua code. Parameters (if any) are available as `...` inside the
|
||||
/// chunk. The chunk can return a value.
|
||||
///
|
||||
/// To evaluate an expression, it must be prefixed with "return ". For
|
||||
/// instance, to call a lua function with arguments sent in and get its
|
||||
/// return value back, use the code "return my_function(...)".
|
||||
/// Only statements are executed. To evaluate an expression, prefix it
|
||||
/// with `return`: return my_function(...)
|
||||
///
|
||||
/// @param code lua code to execute
|
||||
/// @param args Arguments to the code
|
||||
@@ -423,29 +422,18 @@ void nvim_del_var(String name, Error *err)
|
||||
dict_set_var(&globvardict, name, NIL, true, false, err);
|
||||
}
|
||||
|
||||
/// Sets a global variable
|
||||
///
|
||||
/// @deprecated
|
||||
///
|
||||
/// @param name Variable name
|
||||
/// @param value Variable value
|
||||
/// @param[out] err Error details, if any
|
||||
/// @see nvim_set_var
|
||||
/// @return Old value or nil if there was no previous value.
|
||||
///
|
||||
/// @warning It may return nil if there was no previous value
|
||||
/// or if previous value was `v:null`.
|
||||
/// @warning May return nil if there was no previous value
|
||||
/// OR if previous value was `v:null`.
|
||||
Object vim_set_var(String name, Object value, Error *err)
|
||||
{
|
||||
return dict_set_var(&globvardict, name, value, false, true, err);
|
||||
}
|
||||
|
||||
/// Removes a global variable
|
||||
///
|
||||
/// @deprecated
|
||||
///
|
||||
/// @param name Variable name
|
||||
/// @param[out] err Error details, if any
|
||||
/// @return Old value
|
||||
/// @see nvim_del_var
|
||||
Object vim_del_var(String name, Error *err)
|
||||
{
|
||||
return dict_set_var(&globvardict, name, NIL, true, true, err);
|
||||
|
||||
41
src/nvim/aucmd.c
Normal file
41
src/nvim/aucmd.c
Normal file
@@ -0,0 +1,41 @@
|
||||
// This is an open source non-commercial project. Dear PVS-Studio, please check
|
||||
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
#include "nvim/os/os.h"
|
||||
#include "nvim/fileio.h"
|
||||
#include "nvim/vim.h"
|
||||
#include "nvim/main.h"
|
||||
#include "nvim/ui.h"
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "aucmd.c.generated.h"
|
||||
#endif
|
||||
|
||||
static void focusgained_event(void **argv)
|
||||
{
|
||||
bool *gainedp = argv[0];
|
||||
do_autocmd_focusgained(*gainedp);
|
||||
xfree(gainedp);
|
||||
}
|
||||
void aucmd_schedule_focusgained(bool gained)
|
||||
{
|
||||
bool *gainedp = xmalloc(sizeof(*gainedp));
|
||||
*gainedp = gained;
|
||||
loop_schedule_deferred(&main_loop,
|
||||
event_create(focusgained_event, 1, gainedp));
|
||||
}
|
||||
|
||||
static void do_autocmd_focusgained(bool gained)
|
||||
FUNC_ATTR_NONNULL_ALL
|
||||
{
|
||||
static bool recursive = false;
|
||||
|
||||
if (recursive) {
|
||||
return; // disallow recursion
|
||||
}
|
||||
recursive = true;
|
||||
apply_autocmds((gained ? EVENT_FOCUSGAINED : EVENT_FOCUSLOST),
|
||||
NULL, NULL, false, curbuf);
|
||||
recursive = false;
|
||||
}
|
||||
|
||||
9
src/nvim/aucmd.h
Normal file
9
src/nvim/aucmd.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#ifndef NVIM_AUCMD_H
|
||||
#define NVIM_AUCMD_H
|
||||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "aucmd.h.generated.h"
|
||||
#endif
|
||||
|
||||
#endif // NVIM_AUCMD_H
|
||||
|
||||
@@ -974,14 +974,6 @@ static int insert_handle_key(InsertState *s)
|
||||
multiqueue_process_events(main_loop.events);
|
||||
break;
|
||||
|
||||
case K_FOCUSGAINED: // Neovim has been given focus
|
||||
apply_autocmds(EVENT_FOCUSGAINED, NULL, NULL, false, curbuf);
|
||||
break;
|
||||
|
||||
case K_FOCUSLOST: // Neovim has lost focus
|
||||
apply_autocmds(EVENT_FOCUSLOST, NULL, NULL, false, curbuf);
|
||||
break;
|
||||
|
||||
case K_HOME: // <Home>
|
||||
case K_KHOME:
|
||||
case K_S_HOME:
|
||||
@@ -2406,6 +2398,7 @@ void set_completion(colnr_T startcol, list_T *list)
|
||||
ins_compl_prep(' ');
|
||||
}
|
||||
ins_compl_clear();
|
||||
ins_compl_free();
|
||||
|
||||
compl_direction = FORWARD;
|
||||
if (startcol > curwin->w_cursor.col)
|
||||
@@ -3166,8 +3159,7 @@ static bool ins_compl_prep(int c)
|
||||
|
||||
/* Ignore end of Select mode mapping and mouse scroll buttons. */
|
||||
if (c == K_SELECT || c == K_MOUSEDOWN || c == K_MOUSEUP
|
||||
|| c == K_MOUSELEFT || c == K_MOUSERIGHT || c == K_EVENT
|
||||
|| c == K_FOCUSGAINED || c == K_FOCUSLOST) {
|
||||
|| c == K_MOUSELEFT || c == K_MOUSERIGHT || c == K_EVENT) {
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
@@ -59,7 +59,14 @@ void loop_poll_events(Loop *loop, int ms)
|
||||
multiqueue_process_events(loop->fast_events);
|
||||
}
|
||||
|
||||
// Schedule an event from another thread
|
||||
/// Schedules an event from another thread.
|
||||
///
|
||||
/// @note Event is queued into `fast_events`, which is processed outside of the
|
||||
/// primary `events` queue by loop_poll_events(). For `main_loop`, that
|
||||
/// means `fast_events` is NOT processed in an "editor mode"
|
||||
/// (VimState.execute), so redraw and other side-effects are likely to be
|
||||
/// skipped.
|
||||
/// @see loop_schedule_deferred
|
||||
void loop_schedule(Loop *loop, Event event)
|
||||
{
|
||||
uv_mutex_lock(&loop->mutex);
|
||||
@@ -68,6 +75,24 @@ void loop_schedule(Loop *loop, Event event)
|
||||
uv_mutex_unlock(&loop->mutex);
|
||||
}
|
||||
|
||||
/// Schedules an event from another thread. Unlike loop_schedule(), the event
|
||||
/// is forwarded to `Loop.events`, instead of being processed immediately.
|
||||
///
|
||||
/// @see loop_schedule
|
||||
void loop_schedule_deferred(Loop *loop, Event event)
|
||||
{
|
||||
Event *eventp = xmalloc(sizeof(*eventp));
|
||||
*eventp = event;
|
||||
loop_schedule(loop, event_create(loop_deferred_event, 2, loop, eventp));
|
||||
}
|
||||
static void loop_deferred_event(void **argv)
|
||||
{
|
||||
Loop *loop = argv[0];
|
||||
Event *eventp = argv[1];
|
||||
multiqueue_put_event(loop->events, *eventp);
|
||||
xfree(eventp);
|
||||
}
|
||||
|
||||
void loop_on_put(MultiQueue *queue, void *data)
|
||||
{
|
||||
Loop *loop = data;
|
||||
|
||||
@@ -16,10 +16,28 @@ KLIST_INIT(WatcherPtr, WatcherPtr, _noop)
|
||||
|
||||
typedef struct loop {
|
||||
uv_loop_t uv;
|
||||
MultiQueue *events, *fast_events, *thread_events;
|
||||
MultiQueue *events;
|
||||
MultiQueue *thread_events;
|
||||
// Immediate events:
|
||||
// "Events that should be processed after exiting uv_run() (to avoid
|
||||
// recursion), but before returning from loop_poll_events()."
|
||||
// 502aee690c980fcb3cfcb3f211dcfad06103db46
|
||||
// Practical consequence: these events are processed by
|
||||
// state_enter()..os_inchar()
|
||||
// whereas "regular" (main_loop.events) events are processed by
|
||||
// state_enter()..VimState.execute()
|
||||
// But state_enter()..os_inchar() can be "too early" if you want the event
|
||||
// to trigger UI updates and other user-activity-related side-effects.
|
||||
MultiQueue *fast_events;
|
||||
|
||||
// used by process/job-control subsystem
|
||||
klist_t(WatcherPtr) *children;
|
||||
uv_signal_t children_watcher;
|
||||
uv_timer_t children_kill_timer, poll_timer;
|
||||
uv_timer_t children_kill_timer;
|
||||
|
||||
// generic timer, used by loop_poll_events()
|
||||
uv_timer_t poll_timer;
|
||||
|
||||
size_t children_stop_requests;
|
||||
uv_async_t async;
|
||||
uv_mutex_t mutex;
|
||||
|
||||
@@ -3332,10 +3332,12 @@ static buf_T *do_sub(exarg_T *eap, proftime_T timeout)
|
||||
sub = regtilde(sub, p_magic);
|
||||
|
||||
// Check for a match on each line.
|
||||
// If preview: limit to max('cmdwinheight', viewport).
|
||||
linenr_T line2 = eap->line2;
|
||||
for (linenr_T lnum = eap->line1;
|
||||
lnum <= line2 && !(got_quit || aborting())
|
||||
&& (!preview || matched_lines.size <= (size_t)p_cwh);
|
||||
lnum <= line2 && !got_quit && !aborting()
|
||||
&& (!preview || matched_lines.size < (size_t)p_cwh
|
||||
|| lnum <= curwin->w_botline);
|
||||
lnum++) {
|
||||
long nmatch = vim_regexec_multi(®match, curwin, curbuf, lnum,
|
||||
(colnr_T)0, NULL);
|
||||
|
||||
@@ -1620,14 +1620,6 @@ static int command_line_handle_key(CommandLineState *s)
|
||||
}
|
||||
return command_line_not_changed(s);
|
||||
|
||||
case K_FOCUSGAINED: // Neovim has been given focus
|
||||
apply_autocmds(EVENT_FOCUSGAINED, NULL, NULL, false, curbuf);
|
||||
return command_line_not_changed(s);
|
||||
|
||||
case K_FOCUSLOST: // Neovim has lost focus
|
||||
apply_autocmds(EVENT_FOCUSLOST, NULL, NULL, false, curbuf);
|
||||
return command_line_not_changed(s);
|
||||
|
||||
default:
|
||||
// Normal character with no special meaning. Just set mod_mask
|
||||
// to 0x0 so that typing Shift-Space in the GUI doesn't enter
|
||||
|
||||
@@ -140,155 +140,153 @@ static char_u modifier_keys_table[] =
|
||||
};
|
||||
|
||||
static struct key_name_entry {
|
||||
int key; /* Special key code or ascii value */
|
||||
char_u *name; /* Name of key */
|
||||
int key; // Special key code or ascii value
|
||||
char *name; // Name of key
|
||||
} key_names_table[] =
|
||||
{
|
||||
{' ', (char_u *)"Space"},
|
||||
{TAB, (char_u *)"Tab"},
|
||||
{K_TAB, (char_u *)"Tab"},
|
||||
{NL, (char_u *)"NL"},
|
||||
{NL, (char_u *)"NewLine"}, /* Alternative name */
|
||||
{NL, (char_u *)"LineFeed"}, /* Alternative name */
|
||||
{NL, (char_u *)"LF"}, /* Alternative name */
|
||||
{CAR, (char_u *)"CR"},
|
||||
{CAR, (char_u *)"Return"}, /* Alternative name */
|
||||
{CAR, (char_u *)"Enter"}, /* Alternative name */
|
||||
{K_BS, (char_u *)"BS"},
|
||||
{K_BS, (char_u *)"BackSpace"}, /* Alternative name */
|
||||
{ESC, (char_u *)"Esc"},
|
||||
{CSI, (char_u *)"CSI"},
|
||||
{K_CSI, (char_u *)"xCSI"},
|
||||
{'|', (char_u *)"Bar"},
|
||||
{'\\', (char_u *)"Bslash"},
|
||||
{K_DEL, (char_u *)"Del"},
|
||||
{K_DEL, (char_u *)"Delete"}, /* Alternative name */
|
||||
{K_KDEL, (char_u *)"kDel"},
|
||||
{K_UP, (char_u *)"Up"},
|
||||
{K_DOWN, (char_u *)"Down"},
|
||||
{K_LEFT, (char_u *)"Left"},
|
||||
{K_RIGHT, (char_u *)"Right"},
|
||||
{K_XUP, (char_u *)"xUp"},
|
||||
{K_XDOWN, (char_u *)"xDown"},
|
||||
{K_XLEFT, (char_u *)"xLeft"},
|
||||
{K_XRIGHT, (char_u *)"xRight"},
|
||||
{ ' ', "Space" },
|
||||
{ TAB, "Tab" },
|
||||
{ K_TAB, "Tab" },
|
||||
{ NL, "NL" },
|
||||
{ NL, "NewLine" }, // Alternative name
|
||||
{ NL, "LineFeed" }, // Alternative name
|
||||
{ NL, "LF" }, // Alternative name
|
||||
{ CAR, "CR" },
|
||||
{ CAR, "Return" }, // Alternative name
|
||||
{ CAR, "Enter" }, // Alternative name
|
||||
{ K_BS, "BS" },
|
||||
{ K_BS, "BackSpace" }, // Alternative name
|
||||
{ ESC, "Esc" },
|
||||
{ CSI, "CSI" },
|
||||
{ K_CSI, "xCSI" },
|
||||
{ '|', "Bar" },
|
||||
{ '\\', "Bslash" },
|
||||
{ K_DEL, "Del" },
|
||||
{ K_DEL, "Delete" }, // Alternative name
|
||||
{ K_KDEL, "kDel" },
|
||||
{ K_UP, "Up" },
|
||||
{ K_DOWN, "Down" },
|
||||
{ K_LEFT, "Left" },
|
||||
{ K_RIGHT, "Right" },
|
||||
{ K_XUP, "xUp" },
|
||||
{ K_XDOWN, "xDown" },
|
||||
{ K_XLEFT, "xLeft" },
|
||||
{ K_XRIGHT, "xRight" },
|
||||
|
||||
{K_F1, (char_u *)"F1"},
|
||||
{K_F2, (char_u *)"F2"},
|
||||
{K_F3, (char_u *)"F3"},
|
||||
{K_F4, (char_u *)"F4"},
|
||||
{K_F5, (char_u *)"F5"},
|
||||
{K_F6, (char_u *)"F6"},
|
||||
{K_F7, (char_u *)"F7"},
|
||||
{K_F8, (char_u *)"F8"},
|
||||
{K_F9, (char_u *)"F9"},
|
||||
{K_F10, (char_u *)"F10"},
|
||||
{ K_F1, "F1" },
|
||||
{ K_F2, "F2" },
|
||||
{ K_F3, "F3" },
|
||||
{ K_F4, "F4" },
|
||||
{ K_F5, "F5" },
|
||||
{ K_F6, "F6" },
|
||||
{ K_F7, "F7" },
|
||||
{ K_F8, "F8" },
|
||||
{ K_F9, "F9" },
|
||||
{ K_F10, "F10" },
|
||||
|
||||
{K_F11, (char_u *)"F11"},
|
||||
{K_F12, (char_u *)"F12"},
|
||||
{K_F13, (char_u *)"F13"},
|
||||
{K_F14, (char_u *)"F14"},
|
||||
{K_F15, (char_u *)"F15"},
|
||||
{K_F16, (char_u *)"F16"},
|
||||
{K_F17, (char_u *)"F17"},
|
||||
{K_F18, (char_u *)"F18"},
|
||||
{K_F19, (char_u *)"F19"},
|
||||
{K_F20, (char_u *)"F20"},
|
||||
{ K_F11, "F11" },
|
||||
{ K_F12, "F12" },
|
||||
{ K_F13, "F13" },
|
||||
{ K_F14, "F14" },
|
||||
{ K_F15, "F15" },
|
||||
{ K_F16, "F16" },
|
||||
{ K_F17, "F17" },
|
||||
{ K_F18, "F18" },
|
||||
{ K_F19, "F19" },
|
||||
{ K_F20, "F20" },
|
||||
|
||||
{K_F21, (char_u *)"F21"},
|
||||
{K_F22, (char_u *)"F22"},
|
||||
{K_F23, (char_u *)"F23"},
|
||||
{K_F24, (char_u *)"F24"},
|
||||
{K_F25, (char_u *)"F25"},
|
||||
{K_F26, (char_u *)"F26"},
|
||||
{K_F27, (char_u *)"F27"},
|
||||
{K_F28, (char_u *)"F28"},
|
||||
{K_F29, (char_u *)"F29"},
|
||||
{K_F30, (char_u *)"F30"},
|
||||
{ K_F21, "F21" },
|
||||
{ K_F22, "F22" },
|
||||
{ K_F23, "F23" },
|
||||
{ K_F24, "F24" },
|
||||
{ K_F25, "F25" },
|
||||
{ K_F26, "F26" },
|
||||
{ K_F27, "F27" },
|
||||
{ K_F28, "F28" },
|
||||
{ K_F29, "F29" },
|
||||
{ K_F30, "F30" },
|
||||
|
||||
{K_F31, (char_u *)"F31"},
|
||||
{K_F32, (char_u *)"F32"},
|
||||
{K_F33, (char_u *)"F33"},
|
||||
{K_F34, (char_u *)"F34"},
|
||||
{K_F35, (char_u *)"F35"},
|
||||
{K_F36, (char_u *)"F36"},
|
||||
{K_F37, (char_u *)"F37"},
|
||||
{ K_F31, "F31" },
|
||||
{ K_F32, "F32" },
|
||||
{ K_F33, "F33" },
|
||||
{ K_F34, "F34" },
|
||||
{ K_F35, "F35" },
|
||||
{ K_F36, "F36" },
|
||||
{ K_F37, "F37" },
|
||||
|
||||
{K_XF1, (char_u *)"xF1"},
|
||||
{K_XF2, (char_u *)"xF2"},
|
||||
{K_XF3, (char_u *)"xF3"},
|
||||
{K_XF4, (char_u *)"xF4"},
|
||||
{ K_XF1, "xF1" },
|
||||
{ K_XF2, "xF2" },
|
||||
{ K_XF3, "xF3" },
|
||||
{ K_XF4, "xF4" },
|
||||
|
||||
{K_HELP, (char_u *)"Help"},
|
||||
{K_UNDO, (char_u *)"Undo"},
|
||||
{K_INS, (char_u *)"Insert"},
|
||||
{K_INS, (char_u *)"Ins"}, /* Alternative name */
|
||||
{K_KINS, (char_u *)"kInsert"},
|
||||
{K_HOME, (char_u *)"Home"},
|
||||
{K_KHOME, (char_u *)"kHome"},
|
||||
{K_XHOME, (char_u *)"xHome"},
|
||||
{K_ZHOME, (char_u *)"zHome"},
|
||||
{K_END, (char_u *)"End"},
|
||||
{K_KEND, (char_u *)"kEnd"},
|
||||
{K_XEND, (char_u *)"xEnd"},
|
||||
{K_ZEND, (char_u *)"zEnd"},
|
||||
{K_PAGEUP, (char_u *)"PageUp"},
|
||||
{K_PAGEDOWN, (char_u *)"PageDown"},
|
||||
{K_KPAGEUP, (char_u *)"kPageUp"},
|
||||
{K_KPAGEDOWN, (char_u *)"kPageDown"},
|
||||
{ K_HELP, "Help" },
|
||||
{ K_UNDO, "Undo" },
|
||||
{ K_INS, "Insert" },
|
||||
{ K_INS, "Ins" }, // Alternative name
|
||||
{ K_KINS, "kInsert" },
|
||||
{ K_HOME, "Home" },
|
||||
{ K_KHOME, "kHome" },
|
||||
{ K_XHOME, "xHome" },
|
||||
{ K_ZHOME, "zHome" },
|
||||
{ K_END, "End" },
|
||||
{ K_KEND, "kEnd" },
|
||||
{ K_XEND, "xEnd" },
|
||||
{ K_ZEND, "zEnd" },
|
||||
{ K_PAGEUP, "PageUp" },
|
||||
{ K_PAGEDOWN, "PageDown" },
|
||||
{ K_KPAGEUP, "kPageUp" },
|
||||
{ K_KPAGEDOWN, "kPageDown" },
|
||||
|
||||
{K_KPLUS, (char_u *)"kPlus"},
|
||||
{K_KMINUS, (char_u *)"kMinus"},
|
||||
{K_KDIVIDE, (char_u *)"kDivide"},
|
||||
{K_KMULTIPLY, (char_u *)"kMultiply"},
|
||||
{K_KENTER, (char_u *)"kEnter"},
|
||||
{K_KPOINT, (char_u *)"kPoint"},
|
||||
{ K_KPLUS, "kPlus" },
|
||||
{ K_KMINUS, "kMinus" },
|
||||
{ K_KDIVIDE, "kDivide" },
|
||||
{ K_KMULTIPLY, "kMultiply" },
|
||||
{ K_KENTER, "kEnter" },
|
||||
{ K_KPOINT, "kPoint" },
|
||||
|
||||
{K_K0, (char_u *)"k0"},
|
||||
{K_K1, (char_u *)"k1"},
|
||||
{K_K2, (char_u *)"k2"},
|
||||
{K_K3, (char_u *)"k3"},
|
||||
{K_K4, (char_u *)"k4"},
|
||||
{K_K5, (char_u *)"k5"},
|
||||
{K_K6, (char_u *)"k6"},
|
||||
{K_K7, (char_u *)"k7"},
|
||||
{K_K8, (char_u *)"k8"},
|
||||
{K_K9, (char_u *)"k9"},
|
||||
{ K_K0, "k0" },
|
||||
{ K_K1, "k1" },
|
||||
{ K_K2, "k2" },
|
||||
{ K_K3, "k3" },
|
||||
{ K_K4, "k4" },
|
||||
{ K_K5, "k5" },
|
||||
{ K_K6, "k6" },
|
||||
{ K_K7, "k7" },
|
||||
{ K_K8, "k8" },
|
||||
{ K_K9, "k9" },
|
||||
|
||||
{'<', (char_u *)"lt"},
|
||||
{ '<', "lt" },
|
||||
|
||||
{K_MOUSE, (char_u *)"Mouse"},
|
||||
{K_LEFTMOUSE, (char_u *)"LeftMouse"},
|
||||
{K_LEFTMOUSE_NM, (char_u *)"LeftMouseNM"},
|
||||
{K_LEFTDRAG, (char_u *)"LeftDrag"},
|
||||
{K_LEFTRELEASE, (char_u *)"LeftRelease"},
|
||||
{K_LEFTRELEASE_NM, (char_u *)"LeftReleaseNM"},
|
||||
{K_MIDDLEMOUSE, (char_u *)"MiddleMouse"},
|
||||
{K_MIDDLEDRAG, (char_u *)"MiddleDrag"},
|
||||
{K_MIDDLERELEASE, (char_u *)"MiddleRelease"},
|
||||
{K_RIGHTMOUSE, (char_u *)"RightMouse"},
|
||||
{K_RIGHTDRAG, (char_u *)"RightDrag"},
|
||||
{K_RIGHTRELEASE, (char_u *)"RightRelease"},
|
||||
{K_MOUSEDOWN, (char_u *)"ScrollWheelUp"},
|
||||
{K_MOUSEUP, (char_u *)"ScrollWheelDown"},
|
||||
{K_MOUSELEFT, (char_u *)"ScrollWheelRight"},
|
||||
{K_MOUSERIGHT, (char_u *)"ScrollWheelLeft"},
|
||||
{K_MOUSEDOWN, (char_u *)"MouseDown"}, /* OBSOLETE: Use */
|
||||
{K_MOUSEUP, (char_u *)"MouseUp"}, /* ScrollWheelXXX instead */
|
||||
{K_X1MOUSE, (char_u *)"X1Mouse"},
|
||||
{K_X1DRAG, (char_u *)"X1Drag"},
|
||||
{K_X1RELEASE, (char_u *)"X1Release"},
|
||||
{K_X2MOUSE, (char_u *)"X2Mouse"},
|
||||
{K_X2DRAG, (char_u *)"X2Drag"},
|
||||
{K_X2RELEASE, (char_u *)"X2Release"},
|
||||
{K_DROP, (char_u *)"Drop"},
|
||||
{K_ZERO, (char_u *)"Nul"},
|
||||
{K_SNR, (char_u *)"SNR"},
|
||||
{K_PLUG, (char_u *)"Plug"},
|
||||
{K_PASTE, (char_u *)"Paste"},
|
||||
{K_FOCUSGAINED, (char_u *)"FocusGained"},
|
||||
{K_FOCUSLOST, (char_u *)"FocusLost"},
|
||||
{0, NULL}
|
||||
{ K_MOUSE, "Mouse" },
|
||||
{ K_LEFTMOUSE, "LeftMouse" },
|
||||
{ K_LEFTMOUSE_NM, "LeftMouseNM" },
|
||||
{ K_LEFTDRAG, "LeftDrag" },
|
||||
{ K_LEFTRELEASE, "LeftRelease" },
|
||||
{ K_LEFTRELEASE_NM, "LeftReleaseNM" },
|
||||
{ K_MIDDLEMOUSE, "MiddleMouse" },
|
||||
{ K_MIDDLEDRAG, "MiddleDrag" },
|
||||
{ K_MIDDLERELEASE, "MiddleRelease" },
|
||||
{ K_RIGHTMOUSE, "RightMouse" },
|
||||
{ K_RIGHTDRAG, "RightDrag" },
|
||||
{ K_RIGHTRELEASE, "RightRelease" },
|
||||
{ K_MOUSEDOWN, "ScrollWheelUp" },
|
||||
{ K_MOUSEUP, "ScrollWheelDown" },
|
||||
{ K_MOUSELEFT, "ScrollWheelRight" },
|
||||
{ K_MOUSERIGHT, "ScrollWheelLeft" },
|
||||
{ K_MOUSEDOWN, "MouseDown" }, // OBSOLETE: Use
|
||||
{ K_MOUSEUP, "MouseUp" }, // ScrollWheelXXX instead
|
||||
{ K_X1MOUSE, "X1Mouse" },
|
||||
{ K_X1DRAG, "X1Drag" },
|
||||
{ K_X1RELEASE, "X1Release" },
|
||||
{ K_X2MOUSE, "X2Mouse" },
|
||||
{ K_X2DRAG, "X2Drag" },
|
||||
{ K_X2RELEASE, "X2Release" },
|
||||
{ K_DROP, "Drop" },
|
||||
{ K_ZERO, "Nul" },
|
||||
{ K_SNR, "SNR" },
|
||||
{ K_PLUG, "Plug" },
|
||||
{ K_PASTE, "Paste" },
|
||||
{ 0, NULL }
|
||||
};
|
||||
|
||||
static struct mousetable {
|
||||
@@ -721,7 +719,7 @@ int find_special_key_in_table(int c)
|
||||
*/
|
||||
int get_special_key_code(const char_u *name)
|
||||
{
|
||||
char_u *table_name;
|
||||
char *table_name;
|
||||
int i, j;
|
||||
|
||||
for (i = 0; key_names_table[i].name != NULL; i++) {
|
||||
|
||||
@@ -428,8 +428,6 @@ enum key_extra {
|
||||
#define K_CMDWIN TERMCAP2KEY(KS_EXTRA, KE_CMDWIN)
|
||||
|
||||
#define K_DROP TERMCAP2KEY(KS_EXTRA, KE_DROP)
|
||||
#define K_FOCUSGAINED TERMCAP2KEY(KS_EXTRA, KE_FOCUSGAINED)
|
||||
#define K_FOCUSLOST TERMCAP2KEY(KS_EXTRA, KE_FOCUSLOST)
|
||||
|
||||
#define K_EVENT TERMCAP2KEY(KS_EXTRA, KE_EVENT)
|
||||
#define K_PASTE TERMCAP2KEY(KS_EXTRA, KE_PASTE)
|
||||
|
||||
@@ -95,8 +95,12 @@ void log_unlock(void)
|
||||
uv_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
bool do_log(int log_level, const char *func_name, int line_num, bool eol,
|
||||
const char* fmt, ...) FUNC_ATTR_UNUSED
|
||||
/// @param context description of a shared context or subsystem
|
||||
/// @param func_name function name, or NULL
|
||||
/// @param line_num source line number, or -1
|
||||
bool do_log(int log_level, const char *context, const char *func_name,
|
||||
int line_num, bool eol, const char *fmt, ...)
|
||||
FUNC_ATTR_UNUSED
|
||||
{
|
||||
if (log_level < MIN_LOG_LEVEL) {
|
||||
return false;
|
||||
@@ -112,8 +116,8 @@ bool do_log(int log_level, const char *func_name, int line_num, bool eol,
|
||||
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
ret = v_do_log_to_file(log_file, log_level, func_name, line_num, eol,
|
||||
fmt, args);
|
||||
ret = v_do_log_to_file(log_file, log_level, context, func_name, line_num,
|
||||
eol, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
if (log_file != stderr && log_file != stdout) {
|
||||
@@ -151,7 +155,7 @@ FILE *open_log_file(void)
|
||||
static bool opening_log_file = false;
|
||||
// check if it's a recursive call
|
||||
if (opening_log_file) {
|
||||
do_log_to_file(stderr, ERROR_LOG_LEVEL, __func__, __LINE__, true,
|
||||
do_log_to_file(stderr, ERROR_LOG_LEVEL, NULL, __func__, __LINE__, true,
|
||||
"Cannot LOG() recursively.");
|
||||
return stderr;
|
||||
}
|
||||
@@ -171,7 +175,7 @@ FILE *open_log_file(void)
|
||||
// - LOG() is called before early_init()
|
||||
// - Directory does not exist
|
||||
// - File is not writable
|
||||
do_log_to_file(stderr, ERROR_LOG_LEVEL, __func__, __LINE__, true,
|
||||
do_log_to_file(stderr, ERROR_LOG_LEVEL, NULL, __func__, __LINE__, true,
|
||||
"Logging to stderr, failed to open $" LOG_FILE_ENV ": %s",
|
||||
log_file_path);
|
||||
return stderr;
|
||||
@@ -201,7 +205,7 @@ void log_callstack_to_file(FILE *log_file, const char *const func_name,
|
||||
// Now we have a command string like:
|
||||
// addr2line -e /path/to/exe -f -p 0x123 0x456 ...
|
||||
|
||||
do_log_to_file(log_file, DEBUG_LOG_LEVEL, func_name, line_num, true,
|
||||
do_log_to_file(log_file, DEBUG_LOG_LEVEL, NULL, func_name, line_num, true,
|
||||
"trace:");
|
||||
FILE *fp = popen(cmdbuf, "r");
|
||||
char linebuf[IOSIZE];
|
||||
@@ -230,22 +234,23 @@ end:
|
||||
}
|
||||
#endif
|
||||
|
||||
static bool do_log_to_file(FILE *log_file, int log_level,
|
||||
static bool do_log_to_file(FILE *log_file, int log_level, const char *context,
|
||||
const char *func_name, int line_num, bool eol,
|
||||
const char* fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
bool ret = v_do_log_to_file(log_file, log_level, func_name, line_num, eol,
|
||||
fmt, args);
|
||||
bool ret = v_do_log_to_file(log_file, log_level, context, func_name,
|
||||
line_num, eol, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static bool v_do_log_to_file(FILE *log_file, int log_level,
|
||||
const char *func_name, int line_num, bool eol,
|
||||
const char* fmt, va_list args)
|
||||
const char *context, const char *func_name,
|
||||
int line_num, bool eol, const char *fmt,
|
||||
va_list args)
|
||||
{
|
||||
static const char *log_levels[] = {
|
||||
[DEBUG_LOG_LEVEL] = "DEBUG",
|
||||
@@ -268,8 +273,15 @@ static bool v_do_log_to_file(FILE *log_file, int log_level,
|
||||
|
||||
// print the log message prefixed by the current timestamp and pid
|
||||
int64_t pid = os_get_pid();
|
||||
if (fprintf(log_file, "%s %s %" PRId64 "/%s:%d: ", date_time,
|
||||
log_levels[log_level], pid, func_name, line_num) < 0) {
|
||||
int rv = (line_num == -1 || func_name == NULL)
|
||||
? fprintf(log_file, "%s %s %" PRId64 " %s", date_time,
|
||||
log_levels[log_level], pid,
|
||||
(context == NULL ? "?:" : context))
|
||||
: fprintf(log_file, "%s %s %" PRId64 " %s%s:%d: ", date_time,
|
||||
log_levels[log_level], pid,
|
||||
(context == NULL ? "" : context),
|
||||
func_name, line_num);
|
||||
if (rv < 0) {
|
||||
return false;
|
||||
}
|
||||
if (vfprintf(log_file, fmt, args) < 0) {
|
||||
|
||||
@@ -22,42 +22,42 @@
|
||||
# define MIN_LOG_LEVEL INFO_LOG_LEVEL
|
||||
#endif
|
||||
|
||||
#define LOG(level, ...) do_log((level), __func__, __LINE__, true, \
|
||||
#define LOG(level, ...) do_log((level), NULL, __func__, __LINE__, true, \
|
||||
__VA_ARGS__)
|
||||
|
||||
#if MIN_LOG_LEVEL <= DEBUG_LOG_LEVEL
|
||||
# undef DLOG
|
||||
# undef DLOGN
|
||||
# define DLOG(...) do_log(DEBUG_LOG_LEVEL, __func__, __LINE__, true, \
|
||||
# define DLOG(...) do_log(DEBUG_LOG_LEVEL, NULL, __func__, __LINE__, true, \
|
||||
__VA_ARGS__)
|
||||
# define DLOGN(...) do_log(DEBUG_LOG_LEVEL, __func__, __LINE__, false, \
|
||||
# define DLOGN(...) do_log(DEBUG_LOG_LEVEL, NULL, __func__, __LINE__, false, \
|
||||
__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#if MIN_LOG_LEVEL <= INFO_LOG_LEVEL
|
||||
# undef ILOG
|
||||
# undef ILOGN
|
||||
# define ILOG(...) do_log(INFO_LOG_LEVEL, __func__, __LINE__, true, \
|
||||
# define ILOG(...) do_log(INFO_LOG_LEVEL, NULL, __func__, __LINE__, true, \
|
||||
__VA_ARGS__)
|
||||
# define ILOGN(...) do_log(INFO_LOG_LEVEL, __func__, __LINE__, false, \
|
||||
# define ILOGN(...) do_log(INFO_LOG_LEVEL, NULL, __func__, __LINE__, false, \
|
||||
__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#if MIN_LOG_LEVEL <= WARN_LOG_LEVEL
|
||||
# undef WLOG
|
||||
# undef WLOGN
|
||||
# define WLOG(...) do_log(WARN_LOG_LEVEL, __func__, __LINE__, true, \
|
||||
# define WLOG(...) do_log(WARN_LOG_LEVEL, NULL, __func__, __LINE__, true, \
|
||||
__VA_ARGS__)
|
||||
# define WLOGN(...) do_log(WARN_LOG_LEVEL, __func__, __LINE__, false, \
|
||||
# define WLOGN(...) do_log(WARN_LOG_LEVEL, NULL, __func__, __LINE__, false, \
|
||||
__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
#if MIN_LOG_LEVEL <= ERROR_LOG_LEVEL
|
||||
# undef ELOG
|
||||
# undef ELOGN
|
||||
# define ELOG(...) do_log(ERROR_LOG_LEVEL, __func__, __LINE__, true, \
|
||||
# define ELOG(...) do_log(ERROR_LOG_LEVEL, NULL, __func__, __LINE__, true, \
|
||||
__VA_ARGS__)
|
||||
# define ELOGN(...) do_log(ERROR_LOG_LEVEL, __func__, __LINE__, false, \
|
||||
# define ELOGN(...) do_log(ERROR_LOG_LEVEL, NULL, __func__, __LINE__, false, \
|
||||
__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
|
||||
@@ -2164,16 +2164,21 @@ void do_check_cursorbind(void)
|
||||
int restart_edit_save = restart_edit;
|
||||
restart_edit = true;
|
||||
check_cursor();
|
||||
if (curwin->w_p_cul || curwin->w_p_cuc) {
|
||||
validate_cursor();
|
||||
}
|
||||
restart_edit = restart_edit_save;
|
||||
}
|
||||
/* Correct cursor for multi-byte character. */
|
||||
if (has_mbyte)
|
||||
// Correct cursor for multi-byte character.
|
||||
if (has_mbyte) {
|
||||
mb_adjust_cursor();
|
||||
}
|
||||
redraw_later(VALID);
|
||||
|
||||
/* Only scroll when 'scrollbind' hasn't done this. */
|
||||
if (!curwin->w_p_scb)
|
||||
// Only scroll when 'scrollbind' hasn't done this.
|
||||
if (!curwin->w_p_scb) {
|
||||
update_topline();
|
||||
}
|
||||
curwin->w_redr_status = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -188,12 +188,11 @@ uint64_t channel_connect(bool tcp, const char *address, int timeout,
|
||||
return channel->id;
|
||||
}
|
||||
|
||||
/// Sends event/arguments to channel
|
||||
/// Publishes an event to a channel.
|
||||
///
|
||||
/// @param id The channel id. If 0, the event will be sent to all
|
||||
/// channels that have subscribed to the event type
|
||||
/// @param name The event name, an arbitrary string
|
||||
/// @param args Array with event arguments
|
||||
/// @param id Channel id. 0 means "broadcast to all subscribed channels"
|
||||
/// @param name Event name (application-defined)
|
||||
/// @param args Array of event arguments
|
||||
/// @return True if the event was sent successfully, false otherwise.
|
||||
bool channel_send_event(uint64_t id, const char *name, Array args)
|
||||
{
|
||||
@@ -215,7 +214,6 @@ bool channel_send_event(uint64_t id, const char *name, Array args)
|
||||
send_event(channel, name, args);
|
||||
}
|
||||
} else {
|
||||
// TODO(tarruda): Implement event broadcasting in vimscript
|
||||
broadcast_event(name, args);
|
||||
}
|
||||
|
||||
|
||||
@@ -345,8 +345,6 @@ static const struct nv_cmd {
|
||||
{ K_F8, farsi_f8, 0, 0 },
|
||||
{ K_F9, farsi_f9, 0, 0 },
|
||||
{ K_EVENT, nv_event, NV_KEEPREG, 0 },
|
||||
{ K_FOCUSGAINED, nv_focusgained, NV_KEEPREG, 0 },
|
||||
{ K_FOCUSLOST, nv_focuslost, NV_KEEPREG, 0 },
|
||||
};
|
||||
|
||||
/* Number of commands in nv_cmds[]. */
|
||||
@@ -7958,18 +7956,7 @@ static void nv_event(cmdarg_T *cap)
|
||||
may_garbage_collect = false;
|
||||
multiqueue_process_events(main_loop.events);
|
||||
cap->retval |= CA_COMMAND_BUSY; // don't call edit() now
|
||||
}
|
||||
|
||||
/// Trigger FocusGained event.
|
||||
static void nv_focusgained(cmdarg_T *cap)
|
||||
{
|
||||
apply_autocmds(EVENT_FOCUSGAINED, NULL, NULL, false, curbuf);
|
||||
}
|
||||
|
||||
/// Trigger FocusLost event.
|
||||
static void nv_focuslost(cmdarg_T *cap)
|
||||
{
|
||||
apply_autocmds(EVENT_FOCUSLOST, NULL, NULL, false, curbuf);
|
||||
finish_op = false;
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
@@ -5847,7 +5847,7 @@ static void screen_start_highlight(int attr)
|
||||
ui_start_highlight(attr);
|
||||
}
|
||||
|
||||
void screen_stop_highlight(void)
|
||||
static void screen_stop_highlight(void)
|
||||
{
|
||||
ui_stop_highlight();
|
||||
screen_attr = 0;
|
||||
|
||||
@@ -26,10 +26,11 @@ void state_enter(VimState *s)
|
||||
int check_result = s->check ? s->check(s) : 1;
|
||||
|
||||
if (!check_result) {
|
||||
break;
|
||||
break; // Terminate this state.
|
||||
} else if (check_result == -1) {
|
||||
continue;
|
||||
continue; // check() again.
|
||||
}
|
||||
// Execute this state.
|
||||
|
||||
int key;
|
||||
|
||||
@@ -48,11 +49,13 @@ getkey:
|
||||
ui_flush();
|
||||
// Call `os_inchar` directly to block for events or user input without
|
||||
// consuming anything from `input_buffer`(os/input.c) or calling the
|
||||
// mapping engine. If an event was put into the queue, we send K_EVENT
|
||||
// directly.
|
||||
// mapping engine.
|
||||
(void)os_inchar(NULL, 0, -1, 0);
|
||||
input_disable_events();
|
||||
key = !multiqueue_empty(main_loop.events) ? K_EVENT : safe_vgetc();
|
||||
// If an event was put into the queue, we send K_EVENT directly.
|
||||
key = !multiqueue_empty(main_loop.events)
|
||||
? K_EVENT
|
||||
: safe_vgetc();
|
||||
}
|
||||
|
||||
if (key == K_EVENT) {
|
||||
|
||||
@@ -432,14 +432,6 @@ static int terminal_execute(VimState *state, int key)
|
||||
TerminalState *s = (TerminalState *)state;
|
||||
|
||||
switch (key) {
|
||||
case K_FOCUSGAINED: // nvim has been given focus
|
||||
apply_autocmds(EVENT_FOCUSGAINED, NULL, NULL, false, curbuf);
|
||||
break;
|
||||
|
||||
case K_FOCUSLOST: // nvim has lost focus
|
||||
apply_autocmds(EVENT_FOCUSLOST, NULL, NULL, false, curbuf);
|
||||
break;
|
||||
|
||||
// Temporary fix until paste events gets implemented
|
||||
case K_PASTE:
|
||||
break;
|
||||
@@ -530,6 +522,12 @@ void terminal_send(Terminal *term, char *data, size_t size)
|
||||
void terminal_send_key(Terminal *term, int c)
|
||||
{
|
||||
VTermModifier mod = VTERM_MOD_NONE;
|
||||
|
||||
// Convert K_ZERO back to ASCII
|
||||
if (c == K_ZERO) {
|
||||
c = Ctrl_AT;
|
||||
}
|
||||
|
||||
VTermKey key = convert_key(c, &mod);
|
||||
|
||||
if (key) {
|
||||
@@ -783,26 +781,60 @@ static int term_sb_pop(int cols, VTermScreenCell *cells, void *data)
|
||||
// }}}
|
||||
// input handling {{{
|
||||
|
||||
static void convert_modifiers(VTermModifier *statep)
|
||||
static void convert_modifiers(int key, VTermModifier *statep)
|
||||
{
|
||||
if (mod_mask & MOD_MASK_SHIFT) { *statep |= VTERM_MOD_SHIFT; }
|
||||
if (mod_mask & MOD_MASK_CTRL) { *statep |= VTERM_MOD_CTRL; }
|
||||
if (mod_mask & MOD_MASK_ALT) { *statep |= VTERM_MOD_ALT; }
|
||||
|
||||
switch (key) {
|
||||
case K_S_TAB:
|
||||
case K_S_UP:
|
||||
case K_S_DOWN:
|
||||
case K_S_LEFT:
|
||||
case K_S_RIGHT:
|
||||
case K_S_F1:
|
||||
case K_S_F2:
|
||||
case K_S_F3:
|
||||
case K_S_F4:
|
||||
case K_S_F5:
|
||||
case K_S_F6:
|
||||
case K_S_F7:
|
||||
case K_S_F8:
|
||||
case K_S_F9:
|
||||
case K_S_F10:
|
||||
case K_S_F11:
|
||||
case K_S_F12:
|
||||
*statep |= VTERM_MOD_SHIFT;
|
||||
break;
|
||||
|
||||
case K_C_LEFT:
|
||||
case K_C_RIGHT:
|
||||
*statep |= VTERM_MOD_CTRL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static VTermKey convert_key(int key, VTermModifier *statep)
|
||||
{
|
||||
convert_modifiers(statep);
|
||||
convert_modifiers(key, statep);
|
||||
|
||||
switch (key) {
|
||||
case K_BS: return VTERM_KEY_BACKSPACE;
|
||||
case K_S_TAB: // FALLTHROUGH
|
||||
case TAB: return VTERM_KEY_TAB;
|
||||
case Ctrl_M: return VTERM_KEY_ENTER;
|
||||
case ESC: return VTERM_KEY_ESCAPE;
|
||||
|
||||
case K_S_UP: // FALLTHROUGH
|
||||
case K_UP: return VTERM_KEY_UP;
|
||||
case K_S_DOWN: // FALLTHROUGH
|
||||
case K_DOWN: return VTERM_KEY_DOWN;
|
||||
case K_S_LEFT: // FALLTHROUGH
|
||||
case K_C_LEFT: // FALLTHROUGH
|
||||
case K_LEFT: return VTERM_KEY_LEFT;
|
||||
case K_S_RIGHT: // FALLTHROUGH
|
||||
case K_C_RIGHT: // FALLTHROUGH
|
||||
case K_RIGHT: return VTERM_KEY_RIGHT;
|
||||
|
||||
case K_INS: return VTERM_KEY_INS;
|
||||
@@ -812,22 +844,22 @@ static VTermKey convert_key(int key, VTermModifier *statep)
|
||||
case K_PAGEUP: return VTERM_KEY_PAGEUP;
|
||||
case K_PAGEDOWN: return VTERM_KEY_PAGEDOWN;
|
||||
|
||||
case K_K0:
|
||||
case K_K0: // FALLTHROUGH
|
||||
case K_KINS: return VTERM_KEY_KP_0;
|
||||
case K_K1:
|
||||
case K_K1: // FALLTHROUGH
|
||||
case K_KEND: return VTERM_KEY_KP_1;
|
||||
case K_K2: return VTERM_KEY_KP_2;
|
||||
case K_K3:
|
||||
case K_K3: // FALLTHROUGH
|
||||
case K_KPAGEDOWN: return VTERM_KEY_KP_3;
|
||||
case K_K4: return VTERM_KEY_KP_4;
|
||||
case K_K5: return VTERM_KEY_KP_5;
|
||||
case K_K6: return VTERM_KEY_KP_6;
|
||||
case K_K7:
|
||||
case K_K7: // FALLTHROUGH
|
||||
case K_KHOME: return VTERM_KEY_KP_7;
|
||||
case K_K8: return VTERM_KEY_KP_8;
|
||||
case K_K9:
|
||||
case K_K9: // FALLTHROUGH
|
||||
case K_KPAGEUP: return VTERM_KEY_KP_9;
|
||||
case K_KDEL:
|
||||
case K_KDEL: // FALLTHROUGH
|
||||
case K_KPOINT: return VTERM_KEY_KP_PERIOD;
|
||||
case K_KENTER: return VTERM_KEY_KP_ENTER;
|
||||
case K_KPLUS: return VTERM_KEY_KP_PLUS;
|
||||
@@ -835,6 +867,57 @@ static VTermKey convert_key(int key, VTermModifier *statep)
|
||||
case K_KMULTIPLY: return VTERM_KEY_KP_MULT;
|
||||
case K_KDIVIDE: return VTERM_KEY_KP_DIVIDE;
|
||||
|
||||
case K_S_F1: // FALLTHROUGH
|
||||
case K_F1: return VTERM_KEY_FUNCTION(1);
|
||||
case K_S_F2: // FALLTHROUGH
|
||||
case K_F2: return VTERM_KEY_FUNCTION(2);
|
||||
case K_S_F3: // FALLTHROUGH
|
||||
case K_F3: return VTERM_KEY_FUNCTION(3);
|
||||
case K_S_F4: // FALLTHROUGH
|
||||
case K_F4: return VTERM_KEY_FUNCTION(4);
|
||||
case K_S_F5: // FALLTHROUGH
|
||||
case K_F5: return VTERM_KEY_FUNCTION(5);
|
||||
case K_S_F6: // FALLTHROUGH
|
||||
case K_F6: return VTERM_KEY_FUNCTION(6);
|
||||
case K_S_F7: // FALLTHROUGH
|
||||
case K_F7: return VTERM_KEY_FUNCTION(7);
|
||||
case K_S_F8: // FALLTHROUGH
|
||||
case K_F8: return VTERM_KEY_FUNCTION(8);
|
||||
case K_S_F9: // FALLTHROUGH
|
||||
case K_F9: return VTERM_KEY_FUNCTION(9);
|
||||
case K_S_F10: // FALLTHROUGH
|
||||
case K_F10: return VTERM_KEY_FUNCTION(10);
|
||||
case K_S_F11: // FALLTHROUGH
|
||||
case K_F11: return VTERM_KEY_FUNCTION(11);
|
||||
case K_S_F12: // FALLTHROUGH
|
||||
case K_F12: return VTERM_KEY_FUNCTION(12);
|
||||
|
||||
case K_F13: return VTERM_KEY_FUNCTION(13);
|
||||
case K_F14: return VTERM_KEY_FUNCTION(14);
|
||||
case K_F15: return VTERM_KEY_FUNCTION(15);
|
||||
case K_F16: return VTERM_KEY_FUNCTION(16);
|
||||
case K_F17: return VTERM_KEY_FUNCTION(17);
|
||||
case K_F18: return VTERM_KEY_FUNCTION(18);
|
||||
case K_F19: return VTERM_KEY_FUNCTION(19);
|
||||
case K_F20: return VTERM_KEY_FUNCTION(20);
|
||||
case K_F21: return VTERM_KEY_FUNCTION(21);
|
||||
case K_F22: return VTERM_KEY_FUNCTION(22);
|
||||
case K_F23: return VTERM_KEY_FUNCTION(23);
|
||||
case K_F24: return VTERM_KEY_FUNCTION(24);
|
||||
case K_F25: return VTERM_KEY_FUNCTION(25);
|
||||
case K_F26: return VTERM_KEY_FUNCTION(26);
|
||||
case K_F27: return VTERM_KEY_FUNCTION(27);
|
||||
case K_F28: return VTERM_KEY_FUNCTION(28);
|
||||
case K_F29: return VTERM_KEY_FUNCTION(29);
|
||||
case K_F30: return VTERM_KEY_FUNCTION(30);
|
||||
case K_F31: return VTERM_KEY_FUNCTION(31);
|
||||
case K_F32: return VTERM_KEY_FUNCTION(32);
|
||||
case K_F33: return VTERM_KEY_FUNCTION(33);
|
||||
case K_F34: return VTERM_KEY_FUNCTION(34);
|
||||
case K_F35: return VTERM_KEY_FUNCTION(35);
|
||||
case K_F36: return VTERM_KEY_FUNCTION(36);
|
||||
case K_F37: return VTERM_KEY_FUNCTION(37);
|
||||
|
||||
default: return VTERM_KEY_NONE;
|
||||
}
|
||||
}
|
||||
@@ -1176,6 +1259,10 @@ static void redraw(bool restore_cursor)
|
||||
update_screen(0);
|
||||
}
|
||||
|
||||
if (need_maketitle) { // Update title in terminal-mode. #7248
|
||||
maketitle();
|
||||
}
|
||||
|
||||
if (restore_cursor) {
|
||||
ui_cursor_goto(save_row, save_col);
|
||||
} else if (term) {
|
||||
|
||||
@@ -230,9 +230,26 @@ func Test_paste_in_cmdline()
|
||||
|
||||
call feedkeys("f;:aaa \<C-R>\<C-A> bbb\<C-B>\"\<CR>", 'tx')
|
||||
call assert_equal('"aaa a;b-c*d bbb', @:)
|
||||
|
||||
call feedkeys(":\<C-\>etoupper(getline(1))\<CR>\<C-B>\"\<CR>", 'tx')
|
||||
call assert_equal('"ASDF.X /TMP/SOME VERYLONGWORD A;B-C*D ', @:)
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
func Test_remove_char_in_cmdline()
|
||||
call feedkeys(":abc def\<S-Left>\<Del>\<C-B>\"\<CR>", 'tx')
|
||||
call assert_equal('"abc ef', @:)
|
||||
|
||||
call feedkeys(":abc def\<S-Left>\<BS>\<C-B>\"\<CR>", 'tx')
|
||||
call assert_equal('"abcdef', @:)
|
||||
|
||||
call feedkeys(":abc def ghi\<S-Left>\<C-W>\<C-B>\"\<CR>", 'tx')
|
||||
call assert_equal('"abc ghi', @:)
|
||||
|
||||
call feedkeys(":abc def\<S-Left>\<C-U>\<C-B>\"\<CR>", 'tx')
|
||||
call assert_equal('"def', @:)
|
||||
endfunc
|
||||
|
||||
func Test_illegal_address()
|
||||
new
|
||||
2;'(
|
||||
|
||||
@@ -7,10 +7,10 @@ func! ListMonths()
|
||||
if g:setting != ''
|
||||
exe ":set" g:setting
|
||||
endif
|
||||
let mth=copy(g:months)
|
||||
let mth = copy(g:months)
|
||||
let entered = strcharpart(getline('.'),0,col('.'))
|
||||
if !empty(entered)
|
||||
let mth=filter(mth, 'v:val=~"^".entered')
|
||||
let mth = filter(mth, 'v:val=~"^".entered')
|
||||
endif
|
||||
call complete(1, mth)
|
||||
return ''
|
||||
@@ -468,7 +468,7 @@ endfunc
|
||||
" auto-wrap text.
|
||||
func Test_completion_ctrl_e_without_autowrap()
|
||||
new
|
||||
let tw_save=&tw
|
||||
let tw_save = &tw
|
||||
set tw=78
|
||||
let li = [
|
||||
\ '" zzz',
|
||||
@@ -478,7 +478,7 @@ func Test_completion_ctrl_e_without_autowrap()
|
||||
call feedkeys("A\<C-X>\<C-N>\<C-E>\<Esc>", "tx")
|
||||
call assert_equal(li, getline(1, '$'))
|
||||
|
||||
let &tw=tw_save
|
||||
let &tw = tw_save
|
||||
q!
|
||||
endfunc
|
||||
|
||||
@@ -541,4 +541,33 @@ func Test_completion_comment_formatting()
|
||||
bwipe!
|
||||
endfunc
|
||||
|
||||
function! DummyCompleteSix()
|
||||
call complete(1, ['Hello', 'World'])
|
||||
return ''
|
||||
endfunction
|
||||
|
||||
" complete() correctly clears the list of autocomplete candidates
|
||||
func Test_completion_clear_candidate_list()
|
||||
new
|
||||
%d
|
||||
" select first entry from the completion popup
|
||||
call feedkeys("a xxx\<C-N>\<C-R>=DummyCompleteSix()\<CR>", "tx")
|
||||
call assert_equal('Hello', getline(1))
|
||||
%d
|
||||
" select second entry from the completion popup
|
||||
call feedkeys("a xxx\<C-N>\<C-R>=DummyCompleteSix()\<CR>\<C-N>", "tx")
|
||||
call assert_equal('World', getline(1))
|
||||
%d
|
||||
" select original text
|
||||
call feedkeys("a xxx\<C-N>\<C-R>=DummyCompleteSix()\<CR>\<C-N>\<C-N>", "tx")
|
||||
call assert_equal(' xxx', getline(1))
|
||||
%d
|
||||
" back at first entry from completion list
|
||||
call feedkeys("a xxx\<C-N>\<C-R>=DummyCompleteSix()\<CR>\<C-N>\<C-N>\<C-N>", "tx")
|
||||
call assert_equal('Hello', getline(1))
|
||||
|
||||
bw!
|
||||
endfunc
|
||||
|
||||
|
||||
" vim: shiftwidth=2 sts=2 expandtab
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
#include "nvim/api/private/helpers.h"
|
||||
#include "nvim/ascii.h"
|
||||
#include "nvim/main.h"
|
||||
#include "nvim/aucmd.h"
|
||||
#include "nvim/os/os.h"
|
||||
#include "nvim/os/input.h"
|
||||
#include "nvim/event/rstream.h"
|
||||
@@ -280,9 +281,9 @@ static void timer_cb(TimeWatcher *watcher, void *data)
|
||||
|
||||
/// Handle focus events.
|
||||
///
|
||||
/// If the upcoming sequence of bytes in the input stream matches either the
|
||||
/// escape code for focus gained `<ESC>[I` or focus lost `<ESC>[O` then consume
|
||||
/// that sequence and push the appropriate event into the input queue
|
||||
/// If the upcoming sequence of bytes in the input stream matches the termcode
|
||||
/// for "focus gained" or "focus lost", consume that sequence and schedule an
|
||||
/// event on the main loop.
|
||||
///
|
||||
/// @param input the input stream
|
||||
/// @return true iff handle_focus_event consumed some input
|
||||
@@ -294,11 +295,7 @@ static bool handle_focus_event(TermInput *input)
|
||||
// Advance past the sequence
|
||||
bool focus_gained = *rbuffer_get(input->read_stream.buffer, 2) == 'I';
|
||||
rbuffer_consumed(input->read_stream.buffer, 3);
|
||||
if (focus_gained) {
|
||||
enqueue_input(input, FOCUSGAINED_KEY, sizeof(FOCUSGAINED_KEY) - 1);
|
||||
} else {
|
||||
enqueue_input(input, FOCUSLOST_KEY, sizeof(FOCUSLOST_KEY) - 1);
|
||||
}
|
||||
aucmd_schedule_focusgained(focus_gained);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
@@ -1448,7 +1448,7 @@ static void patch_terminfo_bugs(TUIData *data, const char *term,
|
||||
// teminfo entries. See
|
||||
// https://github.com/gnachman/iTerm2/pull/92 for more.
|
||||
// xterm even has an extended version that has a vertical bar.
|
||||
if (true_xterm // per xterm ctlseqs doco (since version 282)
|
||||
if (!konsole && (true_xterm // per xterm ctlseqs doco (since version 282)
|
||||
// per MinTTY 0.4.3-1 release notes from 2009
|
||||
|| putty
|
||||
// per https://bugzilla.gnome.org/show_bug.cgi?id=720821
|
||||
@@ -1463,7 +1463,7 @@ static void patch_terminfo_bugs(TUIData *data, const char *term,
|
||||
// Allows forcing the use of DECSCUSR on linux type terminals, such as
|
||||
// console-terminal-emulator from the nosh toolset, which does indeed
|
||||
// implement the xterm extension:
|
||||
|| (linuxvt && (xterm_version || (vte_version > 0) || colorterm))) {
|
||||
|| (linuxvt && (xterm_version || (vte_version > 0) || colorterm)))) {
|
||||
data->unibi_ext.set_cursor_style =
|
||||
(int)unibi_add_ext_str(ut, "Ss", "\x1b[%p1%d q");
|
||||
if (-1 == data->unibi_ext.reset_cursor_style) {
|
||||
|
||||
@@ -71,10 +71,10 @@ static char uilog_last_event[1024] = { 0 };
|
||||
uilog_seen++; \
|
||||
} else { \
|
||||
if (uilog_seen > 0) { \
|
||||
do_log(DEBUG_LOG_LEVEL, "ui", 0, true, \
|
||||
do_log(DEBUG_LOG_LEVEL, "UI: ", NULL, -1, true, \
|
||||
"%s (+%zu times...)", uilog_last_event, uilog_seen); \
|
||||
} \
|
||||
DLOG("ui: " STR(funname)); \
|
||||
do_log(DEBUG_LOG_LEVEL, "UI: ", NULL, -1, true, STR(funname)); \
|
||||
uilog_seen = 0; \
|
||||
xstrlcpy(uilog_last_event, STR(funname), sizeof(uilog_last_event)); \
|
||||
} \
|
||||
|
||||
@@ -705,7 +705,7 @@ static const int included_patches[] = {
|
||||
250,
|
||||
// 249 NA
|
||||
// 248,
|
||||
// 247,
|
||||
247,
|
||||
// 246 NA
|
||||
// 245,
|
||||
// 244,
|
||||
@@ -764,14 +764,14 @@ static const int included_patches[] = {
|
||||
// 191 NA
|
||||
190,
|
||||
// 189,
|
||||
// 188,
|
||||
188,
|
||||
// 187 NA
|
||||
// 186,
|
||||
// 185,
|
||||
// 184,
|
||||
// 183,
|
||||
// 182,
|
||||
// 181,
|
||||
182,
|
||||
181,
|
||||
// 180,
|
||||
179,
|
||||
178,
|
||||
@@ -827,7 +827,7 @@ static const int included_patches[] = {
|
||||
128,
|
||||
127,
|
||||
126,
|
||||
// 125,
|
||||
125,
|
||||
124,
|
||||
// 123 NA
|
||||
// 122 NA
|
||||
|
||||
@@ -329,24 +329,74 @@ describe('api', function()
|
||||
}
|
||||
eq({ { {mode='n', blocking=false},
|
||||
13,
|
||||
{mode='n', blocking=false}, -- TODO: should be blocked=true
|
||||
{mode='n', blocking=false}, -- TODO: should be blocked=true ?
|
||||
1 },
|
||||
NIL}, meths.call_atomic(req))
|
||||
eq({mode='r', blocking=true}, nvim("get_mode"))
|
||||
end)
|
||||
-- TODO: bug #6166
|
||||
it("during insert-mode map-pending, returns blocking=true #6166", function()
|
||||
command("inoremap xx foo")
|
||||
nvim("input", "ix")
|
||||
eq({mode='i', blocking=true}, nvim("get_mode"))
|
||||
end)
|
||||
-- TODO: bug #6166
|
||||
it("during normal-mode gU, returns blocking=false #6166", function()
|
||||
nvim("input", "gu")
|
||||
eq({mode='no', blocking=false}, nvim("get_mode"))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('RPC (K_EVENT) #6166', function()
|
||||
it('does not complete ("interrupt") normal-mode operator-pending', function()
|
||||
helpers.insert([[
|
||||
FIRST LINE
|
||||
SECOND LINE]])
|
||||
nvim('input', 'gg')
|
||||
nvim('input', 'gu')
|
||||
-- Make any RPC request (can be non-async: op-pending does not block).
|
||||
nvim('get_current_buf')
|
||||
-- Buffer should not change.
|
||||
helpers.expect([[
|
||||
FIRST LINE
|
||||
SECOND LINE]])
|
||||
-- Now send input to complete the operator.
|
||||
nvim('input', 'j')
|
||||
helpers.expect([[
|
||||
first line
|
||||
second line]])
|
||||
end)
|
||||
it('does not complete ("interrupt") normal-mode map-pending', function()
|
||||
command("nnoremap dd :let g:foo='it worked...'<CR>")
|
||||
helpers.insert([[
|
||||
FIRST LINE
|
||||
SECOND LINE]])
|
||||
nvim('input', 'gg')
|
||||
nvim('input', 'd')
|
||||
-- Make any RPC request (must be async, because map-pending blocks).
|
||||
nvim('get_api_info')
|
||||
-- Send input to complete the mapping.
|
||||
nvim('input', 'd')
|
||||
helpers.expect([[
|
||||
FIRST LINE
|
||||
SECOND LINE]])
|
||||
eq('it worked...', helpers.eval('g:foo'))
|
||||
end)
|
||||
it('does not complete ("interrupt") insert-mode map-pending', function()
|
||||
command('inoremap xx foo')
|
||||
command('set timeoutlen=9999')
|
||||
helpers.insert([[
|
||||
FIRST LINE
|
||||
SECOND LINE]])
|
||||
nvim('input', 'ix')
|
||||
-- Make any RPC request (must be async, because map-pending blocks).
|
||||
nvim('get_api_info')
|
||||
-- Send input to complete the mapping.
|
||||
nvim('input', 'x')
|
||||
helpers.expect([[
|
||||
FIRST LINE
|
||||
SECOND LINfooE]])
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('nvim_replace_termcodes', function()
|
||||
it('escapes K_SPECIAL as K_SPECIAL KS_SPECIAL KE_FILLER', function()
|
||||
eq('\128\254X', helpers.nvim('replace_termcodes', '\128', true, true, true))
|
||||
|
||||
@@ -3,6 +3,7 @@ local Screen = require('test.functional.ui.screen')
|
||||
local clear, wait, nvim = helpers.clear, helpers.wait, helpers.nvim
|
||||
local nvim_dir, source, eq = helpers.nvim_dir, helpers.source, helpers.eq
|
||||
local feed_command, eval = helpers.feed_command, helpers.eval
|
||||
local retry = helpers.retry
|
||||
local iswin = helpers.iswin
|
||||
|
||||
describe(':terminal', function()
|
||||
@@ -70,19 +71,19 @@ describe(':terminal (with fake shell)', function()
|
||||
|
||||
it('with no argument, acts like termopen()', function()
|
||||
terminal_with_fake_shell()
|
||||
wait()
|
||||
retry(3, 4 * screen.timeout, function()
|
||||
screen:expect([[
|
||||
^ready $ |
|
||||
[Process exited 0] |
|
||||
|
|
||||
:terminal |
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
|
||||
it("with no argument, and 'shell' is set to empty string", function()
|
||||
nvim('set_option', 'shell', '')
|
||||
terminal_with_fake_shell()
|
||||
wait()
|
||||
screen:expect([[
|
||||
^ |
|
||||
~ |
|
||||
@@ -94,7 +95,6 @@ describe(':terminal (with fake shell)', function()
|
||||
it("with no argument, but 'shell' has arguments, acts like termopen()", function()
|
||||
nvim('set_option', 'shell', nvim_dir..'/shell-test -t jeff')
|
||||
terminal_with_fake_shell()
|
||||
wait()
|
||||
screen:expect([[
|
||||
^jeff $ |
|
||||
[Process exited 0] |
|
||||
@@ -105,7 +105,6 @@ describe(':terminal (with fake shell)', function()
|
||||
|
||||
it('executes a given command through the shell', function()
|
||||
terminal_with_fake_shell('echo hi')
|
||||
wait()
|
||||
screen:expect([[
|
||||
^ready $ echo hi |
|
||||
|
|
||||
@@ -117,7 +116,6 @@ describe(':terminal (with fake shell)', function()
|
||||
it("executes a given command through the shell, when 'shell' has arguments", function()
|
||||
nvim('set_option', 'shell', nvim_dir..'/shell-test -t jeff')
|
||||
terminal_with_fake_shell('echo hi')
|
||||
wait()
|
||||
screen:expect([[
|
||||
^jeff $ echo hi |
|
||||
|
|
||||
@@ -128,7 +126,6 @@ describe(':terminal (with fake shell)', function()
|
||||
|
||||
it('allows quotes and slashes', function()
|
||||
terminal_with_fake_shell([[echo 'hello' \ "world"]])
|
||||
wait()
|
||||
screen:expect([[
|
||||
^ready $ echo 'hello' \ "world" |
|
||||
|
|
||||
@@ -164,7 +161,6 @@ describe(':terminal (with fake shell)', function()
|
||||
|
||||
it('works with :find', function()
|
||||
terminal_with_fake_shell()
|
||||
wait()
|
||||
screen:expect([[
|
||||
^ready $ |
|
||||
[Process exited 0] |
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
-- Some sanity checks for the TUI using the builtin terminal emulator
|
||||
-- as a simple way to send keys and assert screen state.
|
||||
-- TUI acceptance tests.
|
||||
-- Uses :terminal as a way to send keys and assert screen state.
|
||||
local global_helpers = require('test.helpers')
|
||||
local helpers = require('test.functional.helpers')(after_each)
|
||||
local thelpers = require('test.functional.terminal.helpers')
|
||||
local feed_data = thelpers.feed_data
|
||||
@@ -194,7 +195,7 @@ describe('tui with non-tty file descriptors', function()
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('tui focus event handling', function()
|
||||
describe('tui FocusGained/FocusLost', function()
|
||||
local screen
|
||||
|
||||
before_each(function()
|
||||
@@ -206,7 +207,8 @@ describe('tui focus event handling', function()
|
||||
feed_data("\034\016") -- CTRL-\ CTRL-N
|
||||
end)
|
||||
|
||||
it('can handle focus events in normal mode', function()
|
||||
it('in normal-mode', function()
|
||||
retry(2, 3 * screen.timeout, function()
|
||||
feed_data('\027[I')
|
||||
screen:expect([[
|
||||
{1: } |
|
||||
@@ -228,11 +230,13 @@ describe('tui focus event handling', function()
|
||||
lost |
|
||||
{3:-- TERMINAL --} |
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
|
||||
it('can handle focus events in insert mode', function()
|
||||
it('in insert-mode', function()
|
||||
feed_command('set noshowmode')
|
||||
feed_data('i')
|
||||
retry(2, 3 * screen.timeout, function()
|
||||
feed_data('\027[I')
|
||||
screen:expect([[
|
||||
{1: } |
|
||||
@@ -253,9 +257,12 @@ describe('tui focus event handling', function()
|
||||
lost |
|
||||
{3:-- TERMINAL --} |
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
|
||||
it('can handle focus events in cmdline mode', function()
|
||||
-- During cmdline-mode we ignore :echo invoked by timers/events.
|
||||
-- See commit: 5cc87d4dabd02167117be7a978b5c8faaa975419.
|
||||
it('in cmdline-mode does NOT :echo', function()
|
||||
feed_data(':')
|
||||
feed_data('\027[I')
|
||||
screen:expect([[
|
||||
@@ -264,7 +271,7 @@ describe('tui focus event handling', function()
|
||||
{4:~ }|
|
||||
{4:~ }|
|
||||
{5:[No Name] }|
|
||||
g{1:a}ined |
|
||||
:{1: } |
|
||||
{3:-- TERMINAL --} |
|
||||
]])
|
||||
feed_data('\027[O')
|
||||
@@ -274,17 +281,48 @@ describe('tui focus event handling', function()
|
||||
{4:~ }|
|
||||
{4:~ }|
|
||||
{5:[No Name] }|
|
||||
l{1:o}st |
|
||||
:{1: } |
|
||||
{3:-- TERMINAL --} |
|
||||
]])
|
||||
end)
|
||||
|
||||
it('can handle focus events in terminal mode', function()
|
||||
it('in cmdline-mode', function()
|
||||
-- Set up autocmds that modify the buffer, instead of just calling :echo.
|
||||
-- This is how we can test handling of focus gained/lost during cmdline-mode.
|
||||
-- See commit: 5cc87d4dabd02167117be7a978b5c8faaa975419.
|
||||
feed_data(":autocmd!\n")
|
||||
feed_data(":autocmd FocusLost * call append(line('$'), 'lost')\n")
|
||||
feed_data(":autocmd FocusGained * call append(line('$'), 'gained')\n")
|
||||
retry(2, 3 * screen.timeout, function()
|
||||
-- Enter cmdline-mode.
|
||||
feed_data(':')
|
||||
screen:sleep(1)
|
||||
-- Send focus lost/gained termcodes.
|
||||
feed_data('\027[O')
|
||||
feed_data('\027[I')
|
||||
screen:sleep(1)
|
||||
-- Exit cmdline-mode. Redraws from timers/events are blocked during
|
||||
-- cmdline-mode, so the buffer won't be updated until we exit cmdline-mode.
|
||||
feed_data('\n')
|
||||
screen:expect([[
|
||||
{1: } |
|
||||
lost |
|
||||
gained |
|
||||
{4:~ }|
|
||||
{5:[No Name] [+] }|
|
||||
: |
|
||||
{3:-- TERMINAL --} |
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
|
||||
it('in terminal-mode', function()
|
||||
feed_data(':set shell='..nvim_dir..'/shell-test\n')
|
||||
feed_data(':set noshowmode laststatus=0\n')
|
||||
|
||||
retry(2, 3 * screen.timeout, function()
|
||||
feed_data(':terminal\n')
|
||||
screen:sleep(1)
|
||||
feed_data('\027[I')
|
||||
screen:expect([[
|
||||
{1:r}eady $ |
|
||||
@@ -311,13 +349,30 @@ describe('tui focus event handling', function()
|
||||
feed_data(':bwipeout!\n')
|
||||
end)
|
||||
end)
|
||||
|
||||
it('in press-enter prompt', function()
|
||||
feed_data(":echom 'msg1'|echom 'msg2'|echom 'msg3'|echom 'msg4'|echom 'msg5'\n")
|
||||
-- Execute :messages to provoke the press-enter prompt.
|
||||
feed_data(":messages\n")
|
||||
feed_data('\027[I')
|
||||
feed_data('\027[I')
|
||||
screen:expect([[
|
||||
msg1 |
|
||||
msg2 |
|
||||
msg3 |
|
||||
msg4 |
|
||||
msg5 |
|
||||
{10:Press ENTER or type command to continue}{1: } |
|
||||
{3:-- TERMINAL --} |
|
||||
]])
|
||||
end)
|
||||
end)
|
||||
|
||||
-- These tests require `thelpers` because --headless/--embed
|
||||
-- does not initialize the TUI.
|
||||
describe("tui 't_Co' (terminal colors)", function()
|
||||
local screen
|
||||
local is_freebsd = (helpers.eval("system('uname') =~? 'FreeBSD'") == 1)
|
||||
local is_freebsd = (string.lower(global_helpers.uname()) == 'freebsd')
|
||||
|
||||
local function assert_term_colors(term, colorterm, maxcolors)
|
||||
helpers.clear({env={TERM=term}, args={}})
|
||||
|
||||
@@ -892,6 +892,31 @@ describe(":substitute, inccommand=split", function()
|
||||
]])
|
||||
end)
|
||||
|
||||
it('previews correctly when previewhight is small', function()
|
||||
feed_command('set cwh=3')
|
||||
feed_command('set hls')
|
||||
feed('ggdG')
|
||||
insert(string.rep('abc abc abc\n', 20))
|
||||
feed(':%s/abc/MMM/g')
|
||||
screen:expect([[
|
||||
MMM MMM MMM |
|
||||
MMM MMM MMM |
|
||||
MMM MMM MMM |
|
||||
MMM MMM MMM |
|
||||
MMM MMM MMM |
|
||||
MMM MMM MMM |
|
||||
MMM MMM MMM |
|
||||
MMM MMM MMM |
|
||||
MMM MMM MMM |
|
||||
{11:[No Name] [+] }|
|
||||
| 1| {12:MMM} {12:MMM} {12:MMM} |
|
||||
| 2| {12:MMM} {12:MMM} {12:MMM} |
|
||||
| 3| {12:MMM} {12:MMM} {12:MMM} |
|
||||
{10:[Preview] }|
|
||||
:%s/abc/MMM/g^ |
|
||||
]])
|
||||
end)
|
||||
|
||||
it('actually replaces text', function()
|
||||
feed(":%s/tw/XX/g<Enter>")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user