Merge remote-tracking branch 'upstream/release-0.4' into libcallnr-0.4

This commit is contained in:
James McCoy 2020-08-11 07:33:42 -04:00
commit 47b84599df
No known key found for this signature in database
GPG Key ID: DFE691AE331BA3DB
65 changed files with 991 additions and 193 deletions

View File

@ -76,7 +76,7 @@ addons:
- valgrind
- xclip
homebrew:
update: false
update: true
packages:
- ccache
- ninja

View File

@ -114,8 +114,8 @@ set_property(CACHE CMAKE_BUILD_TYPE PROPERTY
# version string, else they are combined with the result of `git describe`.
set(NVIM_VERSION_MAJOR 0)
set(NVIM_VERSION_MINOR 4)
set(NVIM_VERSION_PATCH 0)
set(NVIM_VERSION_PRERELEASE "") # for package maintainers
set(NVIM_VERSION_PATCH 5)
set(NVIM_VERSION_PRERELEASE "-dev") # for package maintainers
# API level
set(NVIM_API_LEVEL 6) # Bump this after any API change.
@ -314,6 +314,11 @@ if(UNIX)
endif()
endif()
check_c_compiler_flag(-fno-common HAVE_FNO_COMMON)
if (HAVE_FNO_COMMON)
add_compile_options(-fno-common)
endif()
check_c_compiler_flag(-fdiagnostics-color=auto HAS_DIAG_COLOR_FLAG)
if(HAS_DIAG_COLOR_FLAG)
if(CMAKE_GENERATOR MATCHES "Ninja")
@ -454,17 +459,17 @@ if((CLANG_ASAN_UBSAN OR CLANG_MSAN OR CLANG_TSAN) AND NOT CMAKE_C_COMPILER_ID MA
message(FATAL_ERROR "Sanitizers are only supported for Clang")
endif()
if(ENABLE_LIBICONV)
find_package(Iconv REQUIRED)
include_directories(SYSTEM ${Iconv_INCLUDE_DIRS})
endif()
if(ENABLE_LIBINTL)
# LibIntl (not Intl) selects our FindLibIntl.cmake script. #8464
find_package(LibIntl REQUIRED)
include_directories(SYSTEM ${LibIntl_INCLUDE_DIRS})
endif()
if(ENABLE_LIBICONV)
find_package(Iconv REQUIRED)
include_directories(SYSTEM ${Iconv_INCLUDE_DIRS})
endif()
# Determine platform's threading library. Set CMAKE_THREAD_PREFER_PTHREAD
# explicitly to indicate a strong preference for pthread.
set(CMAKE_THREAD_PREFER_PTHREAD ON)

View File

@ -40,6 +40,3 @@ cache:
artifacts:
- path: build/Neovim.zip
- path: build/bin/nvim.exe
branches:
only:
- master

View File

@ -26,7 +26,7 @@ if [[ "${TRAVIS_OS_NAME}" != osx ]] && command -v pyenv; then
echo 'Setting Python versions via pyenv'
# Prefer Python 2 over 3 (more conservative).
pyenv global 2.7.15:3.7
pyenv global 2.7.15:3.7.1
echo 'Updated Python info:'
(

View File

@ -38,6 +38,9 @@ endif()
if (LibIntl_LIBRARY)
list(APPEND CMAKE_REQUIRED_LIBRARIES "${LibIntl_LIBRARY}")
endif()
if (MSVC)
list(APPEND CMAKE_REQUIRED_LIBRARIES ${ICONV_LIBRARY})
endif()
check_c_source_compiles("
#include <libintl.h>
@ -48,6 +51,9 @@ int main(int argc, char** argv) {
bind_textdomain_codeset(\"foo\", \"bar\");
textdomain(\"foo\");
}" HAVE_WORKING_LIBINTL)
if (MSVC)
list(REMOVE_ITEM CMAKE_REQUIRED_LIBRARIES ${ICONV_LIBRARY})
endif()
if (LibIntl_INCLUDE_DIR)
list(REMOVE_ITEM CMAKE_REQUIRED_INCLUDES "${LibIntl_INCLUDE_DIR}")
endif()

View File

@ -688,10 +688,6 @@ fun! netrw#Explore(indx,dosplit,style,...)
endif
" save registers
if has("clipboard")
sil! let keepregstar = @*
sil! let keepregplus = @+
endif
sil! let keepregslash= @/
" if dosplit
@ -915,10 +911,6 @@ fun! netrw#Explore(indx,dosplit,style,...)
" call Decho("..case Nexplore with starpat=".starpat.": (indx=".indx.")",'~'.expand("<slnum>"))
if !exists("w:netrw_explore_list") " sanity check
NetrwKeepj call netrw#ErrorMsg(s:WARNING,"using Nexplore or <s-down> improperly; see help for netrw-starstar",40)
if has("clipboard")
sil! let @* = keepregstar
sil! let @+ = keepregplus
endif
sil! let @/ = keepregslash
" call Dret("netrw#Explore")
return
@ -940,10 +932,6 @@ fun! netrw#Explore(indx,dosplit,style,...)
" call Decho("case Pexplore with starpat=".starpat.": (indx=".indx.")",'~'.expand("<slnum>"))
if !exists("w:netrw_explore_list") " sanity check
NetrwKeepj call netrw#ErrorMsg(s:WARNING,"using Pexplore or <s-up> improperly; see help for netrw-starstar",41)
if has("clipboard")
sil! let @* = keepregstar
sil! let @+ = keepregplus
endif
sil! let @/ = keepregslash
" call Dret("netrw#Explore")
return
@ -995,10 +983,6 @@ fun! netrw#Explore(indx,dosplit,style,...)
catch /^Vim\%((\a\+)\)\=:E480/
keepalt call netrw#ErrorMsg(s:WARNING,'no files matched pattern<'.pattern.'>',45)
if &hls | let keepregslash= s:ExplorePatHls(pattern) | endif
if has("clipboard")
sil! let @* = keepregstar
sil! let @+ = keepregplus
endif
sil! let @/ = keepregslash
" call Dret("netrw#Explore : no files matched pattern")
return
@ -1031,10 +1015,6 @@ fun! netrw#Explore(indx,dosplit,style,...)
if w:netrw_explore_listlen == 0 || (w:netrw_explore_listlen == 1 && w:netrw_explore_list[0] =~ '\*\*\/')
keepalt NetrwKeepj call netrw#ErrorMsg(s:WARNING,"no files matched",42)
if has("clipboard")
sil! let @* = keepregstar
sil! let @+ = keepregplus
endif
sil! let @/ = keepregslash
" call Dret("netrw#Explore : no files matched")
return
@ -1079,10 +1059,6 @@ fun! netrw#Explore(indx,dosplit,style,...)
if !exists("g:netrw_quiet")
keepalt NetrwKeepj call netrw#ErrorMsg(s:WARNING,"your vim needs the +path_extra feature for Exploring with **!",44)
endif
if has("clipboard")
sil! let @* = keepregstar
sil! let @+ = keepregplus
endif
sil! let @/ = keepregslash
" call Dret("netrw#Explore : missing +path_extra")
return
@ -1152,10 +1128,6 @@ fun! netrw#Explore(indx,dosplit,style,...)
" there's no danger of a late FocusGained event on initialization.
" Consequently, set s:netrw_events to 2.
let s:netrw_events= 2
if has("clipboard")
sil! let @* = keepregstar
sil! let @+ = keepregplus
endif
sil! let @/ = keepregslash
" call Dret("netrw#Explore : @/<".@/.">")
endfun
@ -9559,10 +9531,6 @@ fun! s:NetrwWideListing()
let newcolstart = w:netrw_bannercnt + fpc
let newcolend = newcolstart + fpc - 1
" call Decho("bannercnt=".w:netrw_bannercnt." fpl=".w:netrw_fpl." fpc=".fpc." newcol[".newcolstart.",".newcolend."]",'~'.expand("<slnum>"))
if has("clipboard")
sil! let keepregstar = @*
sil! let keepregplus = @+
endif
while line("$") >= newcolstart
if newcolend > line("$") | let newcolend= line("$") | endif
let newcolqty= newcolend - newcolstart
@ -9575,10 +9543,6 @@ fun! s:NetrwWideListing()
exe "sil! NetrwKeepj ".newcolstart.','.newcolend.'d _'
exe 'sil! NetrwKeepj '.w:netrw_bannercnt
endwhile
if has("clipboard")
sil! let @*= keepregstar
sil! let @+= keepregplus
endif
exe "sil! NetrwKeepj ".w:netrw_bannercnt.',$s/\s\+$//e'
NetrwKeepj call histdel("/",-1)
exe 'nno <buffer> <silent> w :call search(''^.\\|\s\s\zs\S'',''W'')'."\<cr>"

View File

@ -51,6 +51,9 @@ function! provider#node#Detect() abort
if exists('g:node_host_prog')
return expand(g:node_host_prog)
endif
if !executable('node')
return ''
endif
if !s:is_minimum_version(v:null, 6, 0)
return ''
endif

View File

@ -2348,7 +2348,7 @@ A jump table for the options with a short description can be found at |Q_op|.
*'fillchars'* *'fcs'*
'fillchars' 'fcs' string (default "")
local to window
global or local to window |global-local|
Characters to fill the statuslines and vertical separators.
It is a comma separated list of items:
@ -3657,7 +3657,7 @@ A jump table for the options with a short description can be found at |Q_op|.
*'listchars'* *'lcs'*
'listchars' 'lcs' string (default: "tab:> ,trail:-,nbsp:+"
Vi default: "eol:$")
local to window
global or local to window |global-local|
Strings to use in 'list' mode and for the |:list| command. It is a
comma separated list of string settings.
@ -3698,9 +3698,9 @@ A jump table for the options with a short description can be found at |Q_op|.
off and the line continues beyond the right of the
screen.
*lcs-precedes*
precedes:c Character to show in the first column, when 'wrap'
is off and there is text preceding the character
visible in the first column.
precedes:c Character to show in the first visible column of the
physical line, when there is text preceding the
character visible in the first column.
*lcs-conceal*
conceal:c Character to show in place of concealed text, when
'conceallevel' is set to 1. A space when omitted.
@ -4583,6 +4583,16 @@ A jump table for the options with a short description can be found at |Q_op|.
RedrawDebugRecompose guibg=Red redraw generated by the
compositor itself, due to a
grid being moved or deleted.
nothrottle Turn off throttling of the message grid. This is an
optimization that joins many small scrolls to one
larger scroll when drawing the message area (with
'display' msgsep flag active).
invalid Enable stricter checking (abort) of inconsistencies
of the internal screen state. This is mostly
useful when running nvim inside a debugger (and
the test suite).
nodelta Send all internally redrawn cells to the UI, even if
they are unchanged from the already displayed state.
*'redrawtime'* *'rdt'*
'redrawtime' 'rdt' number (default 2000)
@ -6908,7 +6918,6 @@ A jump table for the options with a short description can be found at |Q_op|.
global
The number of milliseconds to wait for each character sent to the
screen. When positive, characters are sent to the UI one by one.
When negative, all redrawn characters cause a delay, even if the
character already was displayed by the UI. For debugging purposes.
See 'redrawdebug' for more options. For debugging purposes.
vim:tw=78:ts=8:noet:ft=help:norl:

View File

@ -26,6 +26,11 @@
</screenshots>
<releases>
<release date="2020-08-04" version="0.4.4"/>
<release date="2019-11-06" version="0.4.3"/>
<release date="2019-09-15" version="0.4.2"/>
<release date="2019-09-15" version="0.4.1"/>
<release date="2019-09-15" version="0.4.0"/>
<release date="2019-07-03" version="0.3.8"/>
<release date="2019-04-29" version="0.3.5"/>
<release date="2019-01-13" version="0.3.4"/>

View File

@ -1363,6 +1363,9 @@ Dictionary copy_dictionary(Dictionary dict)
Object copy_object(Object obj)
{
switch (obj.type) {
case kObjectTypeBuffer:
case kObjectTypeTabpage:
case kObjectTypeWindow:
case kObjectTypeNil:
case kObjectTypeBoolean:
case kObjectTypeInteger:

View File

@ -1266,7 +1266,7 @@ Boolean nvim_paste(String data, Boolean crlf, Integer phase, Error *err)
draining = true;
goto theend;
}
if (!(State & CMDLINE) && !(State & INSERT) && (phase == -1 || phase == 1)) {
if (!(State & (CMDLINE | INSERT)) && (phase == -1 || phase == 1)) {
ResetRedobuff();
AppendCharToRedobuff('a'); // Dot-repeat.
}
@ -1284,7 +1284,7 @@ Boolean nvim_paste(String data, Boolean crlf, Integer phase, Error *err)
}
}
}
if (!(State & CMDLINE) && !(State & INSERT) && (phase == -1 || phase == 3)) {
if (!(State & (CMDLINE | INSERT)) && (phase == -1 || phase == 3)) {
AppendCharToRedobuff(ESC); // Dot-repeat.
}
theend:

View File

@ -21,9 +21,9 @@ return {
'BufWritePre', -- before writing a buffer
'ChanInfo', -- info was received about channel
'ChanOpen', -- channel was opened
'CmdLineChanged', -- command line was modified
'CmdLineEnter', -- after entering cmdline mode
'CmdLineLeave', -- before leaving cmdline mode
'CmdlineChanged', -- command line was modified
'CmdlineEnter', -- after entering cmdline mode
'CmdlineLeave', -- before leaving cmdline mode
'CmdUndefined', -- command undefined
'CmdWinEnter', -- after entering the cmdline window
'CmdWinLeave', -- before leaving the cmdline window

View File

@ -3530,8 +3530,20 @@ int build_stl_str_hl(
}
}
if (n == curitem && group_start_userhl == group_end_userhl) {
// empty group
out_p = t;
group_len = 0;
for (n = groupitems[groupdepth] + 1; n < curitem; n++) {
// do not use the highlighting from the removed group
if (items[n].type == Highlight) {
items[n].type = Empty;
}
// adjust the start position of TabPage to the next
// item position
if (items[n].type == TabPage) {
items[n].start = out_p;
}
}
}
}

View File

@ -15,7 +15,6 @@
#include "nvim/ascii.h"
static bool did_stdio = false;
PMap(uint64_t) *channels = NULL;
/// next free id for a job or rpc channel
/// 1 is reserved for stdio channel

View File

@ -85,7 +85,7 @@ struct Channel {
bool callback_scheduled;
};
EXTERN PMap(uint64_t) *channels;
EXTERN PMap(uint64_t) *channels INIT(= NULL);
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "channel.h.generated.h"

View File

@ -8492,7 +8492,7 @@ static void f_getenv(typval_T *argvars, typval_T *rettv, FunPtr fptr)
if (p == NULL) {
rettv->v_type = VAR_SPECIAL;
rettv->vval.v_number = kSpecialVarNull;
rettv->vval.v_special = kSpecialVarNull;
return;
}
rettv->vval.v_string = p;
@ -15441,7 +15441,7 @@ static void f_setenv(typval_T *argvars, typval_T *rettv, FunPtr fptr)
const char *name = tv_get_string_buf(&argvars[0], namebuf);
if (argvars[1].v_type == VAR_SPECIAL
&& argvars[1].vval.v_number == kSpecialVarNull) {
&& argvars[1].vval.v_special == kSpecialVarNull) {
os_unsetenv(name);
} else {
os_setenv(name, tv_get_string_buf(&argvars[1], valbuf), 1);
@ -18747,8 +18747,9 @@ static void f_visualmode(typval_T *argvars, typval_T *rettv, FunPtr fptr)
*/
static void f_wildmenumode(typval_T *argvars, typval_T *rettv, FunPtr fptr)
{
if (wild_menu_showing)
if (wild_menu_showing || ((State & CMDLINE) && pum_visible())) {
rettv->vval.v_number = 1;
}
}
/// "win_findbuf()" function
@ -20871,6 +20872,7 @@ void ex_echo(exarg_T *eap)
char_u *arg = eap->arg;
typval_T rettv;
bool atstart = true;
bool need_clear = true;
const int did_emsg_before = did_emsg;
if (eap->skip)
@ -20913,7 +20915,7 @@ void ex_echo(exarg_T *eap)
char *tofree = encode_tv2echo(&rettv, NULL);
if (*tofree != NUL) {
msg_ext_set_kind("echo");
msg_multiline_attr(tofree, echo_attr, true);
msg_multiline_attr(tofree, echo_attr, true, &need_clear);
}
xfree(tofree);
}
@ -20926,7 +20928,9 @@ void ex_echo(exarg_T *eap)
emsg_skip--;
} else {
// remove text that may still be there from the command
msg_clr_eos();
if (need_clear) {
msg_clr_eos();
}
if (eap->cmdidx == CMD_echo) {
msg_end();
}

View File

@ -33,7 +33,7 @@ typedef double float_T;
enum { DO_NOT_FREE_CNT = (INT_MAX / 2) };
/// Additional values for tv_list_alloc() len argument
enum {
enum ListLenSpecials {
/// List length is not known in advance
///
/// To be used when there is neither a way to know how many elements will be
@ -49,7 +49,7 @@ enum {
///
/// To be used when it looks impractical to determine list length.
kListLenMayKnow = -3,
} ListLenSpecials;
};
/// Maximal possible value of varnumber_T variable
#define VARNUMBER_MAX INT64_MAX

View File

@ -116,6 +116,20 @@ void loop_on_put(MultiQueue *queue, void *data)
uv_stop(&loop->uv);
}
#if !defined(EXITFREE)
static void loop_walk_cb(uv_handle_t *handle, void *arg)
{
if (!uv_is_closing(handle)) {
uv_close(handle, NULL);
}
}
#endif
/// Closes `loop` and its handles, and frees its structures.
///
/// @param loop Loop to destroy
/// @param wait Wait briefly for handles to deref
///
/// @returns false if the loop could not be closed gracefully
bool loop_close(Loop *loop, bool wait)
{
@ -126,18 +140,34 @@ bool loop_close(Loop *loop, bool wait)
uv_close((uv_handle_t *)&loop->poll_timer, timer_close_cb);
uv_close((uv_handle_t *)&loop->async, NULL);
uint64_t start = wait ? os_hrtime() : 0;
bool didstop = false;
while (true) {
uv_run(&loop->uv, wait ? UV_RUN_DEFAULT : UV_RUN_NOWAIT);
if (!uv_loop_close(&loop->uv) || !wait) {
// Run the loop to tickle close-callbacks (which should then free memory).
// Use UV_RUN_NOWAIT to avoid a hang. #11820
uv_run(&loop->uv, didstop ? UV_RUN_DEFAULT : UV_RUN_NOWAIT);
if ((uv_loop_close(&loop->uv) != UV_EBUSY) || !wait) {
break;
}
if (os_hrtime() - start >= 2 * 1000000000) {
uint64_t elapsed_s = (os_hrtime() - start) / 1000000000; // seconds
if (elapsed_s >= 2) {
// Some libuv resource was not correctly deref'd. Log and bail.
rv = false;
ELOG("uv_loop_close() hang?");
log_uv_handles(&loop->uv);
break;
}
#if defined(EXITFREE)
(void)didstop;
#else
if (!didstop) {
// Loop wont block for I/O after this.
uv_stop(&loop->uv);
// XXX: Close all (lua/luv!) handles. But loop_walk_cb() does not call
// resource-specific close-callbacks, so this leaks memory...
uv_walk(&loop->uv, loop_walk_cb, NULL);
didstop = true;
}
#endif
}
multiqueue_free(loop->fast_events);
multiqueue_free(loop->thread_events);

View File

@ -10,12 +10,12 @@
/// Values for "noremap" argument of ins_typebuf()
///
/// Also used for map->m_noremap and menu->noremap[].
enum {
enum RemapValues {
REMAP_YES = 0, ///< Allow remapping.
REMAP_NONE = -1, ///< No remapping.
REMAP_SCRIPT = -2, ///< Remap script-local mappings only.
REMAP_SKIP = -3, ///< No remapping for first char.
} RemapValues;
};
// Argument for flush_buffers().
typedef enum {

View File

@ -11,7 +11,7 @@
// The characters and attributes drawn on grids.
typedef char_u schar_T[(MAX_MCO+1) * 4 + 1];
typedef int16_t sattr_T;
typedef int sattr_T;
/// ScreenGrid represents a resizable rectuangular grid displayed by UI clients.
///

View File

@ -90,7 +90,12 @@ static int get_attr_entry(HlEntry entry)
}
}
id = (int)kv_size(attr_entries);
size_t next_id = kv_size(attr_entries);
if (next_id > INT_MAX) {
ELOG("The index on attr_entries has overflowed");
return 0;
}
id = (int)next_id;
kv_push(attr_entries, entry);
map_put(HlEntry, int)(attr_entry_ids, entry, id);

View File

@ -189,11 +189,14 @@ paste = (function()
if mode == 'c' and not got_line1 then -- cmdline-mode: paste only 1 line.
got_line1 = (#lines > 1)
vim.api.nvim_set_option('paste', true) -- For nvim_input().
local line1, _ = string.gsub(lines[1], '[\r\n\012\027]', ' ') -- Scrub.
local line1 = lines[1]:gsub('<', '<lt>'):gsub('[\r\n\012\027]', ' ') -- Scrub.
vim.api.nvim_input(line1)
vim.api.nvim_set_option('paste', false)
elseif mode ~= 'c' then -- Else: discard remaining cmdline-mode chunks.
if phase < 2 and mode ~= 'i' and mode ~= 'R' and mode ~= 't' then
elseif mode ~= 'c' then
if phase < 2 and mode:find('^[vV\22sS\19]') then
vim.api.nvim_command([[exe "normal! \<Del>"]])
vim.api.nvim_put(lines, 'c', false, true)
elseif phase < 2 and not mode:find('^[iRt]') then
vim.api.nvim_put(lines, 'c', true, true)
-- XXX: Normal-mode: workaround bad cursor-placement after first chunk.
vim.api.nvim_command('normal! a')

View File

@ -10,6 +10,7 @@
#include <msgpack.h>
#include "nvim/ascii.h"
#include "nvim/channel.h"
#include "nvim/vim.h"
#include "nvim/main.h"
#include "nvim/aucmd.h"
@ -284,6 +285,12 @@ int main(int argc, char **argv)
fname = get_fname(&params, cwd);
}
// Recovery mode without a file name: List swap files.
// In this case, no UI is needed.
if (recoverymode && fname == NULL) {
headless_mode = true;
}
TIME_MSG("expanding arguments");
if (params.diff_mode && params.window_count == -1)

View File

@ -228,20 +228,25 @@ int msg_attr(const char *s, const int attr)
}
/// similar to msg_outtrans_attr, but support newlines and tabs.
void msg_multiline_attr(const char *s, int attr, bool check_int)
void msg_multiline_attr(const char *s, int attr,
bool check_int, bool *need_clear)
FUNC_ATTR_NONNULL_ALL
{
const char *next_spec = s;
while (next_spec != NULL && (!check_int || !got_int)) {
while (next_spec != NULL) {
if (check_int && got_int) {
return;
}
next_spec = strpbrk(s, "\t\n\r");
if (next_spec != NULL) {
// Printing all char that are before the char found by strpbrk
msg_outtrans_len_attr((char_u *)s, next_spec - s, attr);
if (*next_spec != TAB) {
if (*next_spec != TAB && *need_clear) {
msg_clr_eos();
*need_clear = false;
}
msg_putchar_attr((uint8_t)(*next_spec), attr);
s = next_spec + 1;
@ -253,6 +258,7 @@ void msg_multiline_attr(const char *s, int attr, bool check_int)
if (*s != NUL) {
msg_outtrans_attr((char_u *)s, attr);
}
return;
}
@ -311,12 +317,15 @@ bool msg_attr_keep(char_u *s, int attr, bool keep, bool multiline)
if (buf != NULL)
s = buf;
bool need_clear = true;
if (multiline) {
msg_multiline_attr((char *)s, attr, false);
msg_multiline_attr((char *)s, attr, false, &need_clear);
} else {
msg_outtrans_attr(s, attr);
}
msg_clr_eos();
if (need_clear) {
msg_clr_eos();
}
retval = msg_end();
if (keep && retval && vim_strsize(s) < (int)(Rows - cmdline_row - 1)
@ -2561,10 +2570,15 @@ static int do_more_prompt(int typed_char)
msgchunk_T *mp;
int i;
// If headless mode is enabled and no input is required, this variable
// will be true. However If server mode is enabled, the message "--more--"
// should be displayed.
bool no_need_more = headless_mode && !embedded_mode;
// We get called recursively when a timer callback outputs a message. In
// that case don't show another prompt. Also when at the hit-Enter prompt
// and nothing was typed.
if (entered || (State == HITRETURN && typed_char == 0)) {
if (no_need_more || entered || (State == HITRETURN && typed_char == 0)) {
return false;
}
entered = true;

View File

@ -15,7 +15,7 @@
/// HACK: os/input.c drains this queue immediately before blocking for input.
/// Events on this queue are async-safe, but they need the resolved state
/// of os_inchar(), so they are processed "just-in-time".
MultiQueue *ch_before_blocking_events;
EXTERN MultiQueue *ch_before_blocking_events INIT(= NULL);
#ifdef INCLUDE_GENERATED_DECLARATIONS

View File

@ -2204,10 +2204,10 @@ static void didset_options2(void)
(void)opt_strings_flags(p_cb, p_cb_values, &cb_flags, true);
// Parse default for 'fillchars'.
(void)set_chars_option(curwin, &curwin->w_p_fcs);
(void)set_chars_option(curwin, &curwin->w_p_fcs, true);
// Parse default for 'listchars'.
(void)set_chars_option(curwin, &curwin->w_p_lcs);
(void)set_chars_option(curwin, &curwin->w_p_lcs, true);
// Parse default for 'wildmode'.
check_opt_wim();
@ -2661,11 +2661,11 @@ did_set_string_option(
errmsg = e_invarg;
} else {
FOR_ALL_TAB_WINDOWS(tp, wp) {
if (set_chars_option(wp, &wp->w_p_lcs) != NULL) {
if (set_chars_option(wp, &wp->w_p_lcs, true) != NULL) {
errmsg = (char_u *)_("E834: Conflicts with value of 'listchars'");
goto ambw_end;
}
if (set_chars_option(wp, &wp->w_p_fcs) != NULL) {
if (set_chars_option(wp, &wp->w_p_fcs, true) != NULL) {
errmsg = (char_u *)_("E835: Conflicts with value of 'fillchars'");
goto ambw_end;
}
@ -2866,10 +2866,26 @@ ambw_end:
}
s = skip_to_option_part(s);
}
} else if (varp == &curwin->w_p_lcs) { // 'listchars'
errmsg = set_chars_option(curwin, varp);
} else if (varp == &curwin->w_p_fcs) { // 'fillchars'
errmsg = set_chars_option(curwin, varp);
} else if (varp == &p_lcs) { // 'listchars'
errmsg = set_chars_option(curwin, varp, false);
if (!errmsg) {
FOR_ALL_TAB_WINDOWS(tp, wp) {
set_chars_option(wp, &wp->w_p_lcs, true);
}
}
redraw_all_later(NOT_VALID);
} else if (varp == &curwin->w_p_lcs) { // local 'listchars'
errmsg = set_chars_option(curwin, varp, true);
} else if (varp == &p_fcs) { // 'fillchars'
errmsg = set_chars_option(curwin, varp, false);
if (!errmsg) {
FOR_ALL_TAB_WINDOWS(tp, wp) {
set_chars_option(wp, &wp->w_p_fcs, true);
}
}
redraw_all_later(NOT_VALID);
} else if (varp == &curwin->w_p_fcs) { // local 'fillchars'
errmsg = set_chars_option(curwin, varp, true);
} else if (varp == &p_cedit) { // 'cedit'
errmsg = check_cedit();
} else if (varp == &p_vfile) { // 'verbosefile'
@ -3499,7 +3515,7 @@ skip:
///
/// @param varp either &curwin->w_p_lcs or &curwin->w_p_fcs
/// @return error message, NULL if it's OK.
static char_u *set_chars_option(win_T *wp, char_u **varp)
static char_u *set_chars_option(win_T *wp, char_u **varp, bool set)
{
int round, i, len, entries;
char_u *p, *s;
@ -3534,12 +3550,18 @@ static char_u *set_chars_option(win_T *wp, char_u **varp)
{ &wp->w_p_lcs_chars.conceal, "conceal", NUL },
};
if (varp == &wp->w_p_lcs) {
if (varp == &p_lcs || varp == &wp->w_p_lcs) {
tab = lcs_tab;
entries = ARRAY_SIZE(lcs_tab);
if (varp == &wp->w_p_lcs && wp->w_p_lcs[0] == NUL) {
varp = &p_lcs;
}
} else {
tab = fcs_tab;
entries = ARRAY_SIZE(fcs_tab);
if (varp == &wp->w_p_fcs && wp->w_p_fcs[0] == NUL) {
varp = &p_fcs;
}
if (*p_ambw == 'd') {
// XXX: If ambiwidth=double then "|" and "·" take 2 columns, which is
// forbidden (TUI limitation?). Set old defaults.
@ -3552,7 +3574,7 @@ static char_u *set_chars_option(win_T *wp, char_u **varp)
}
// first round: check for valid value, second round: assign values
for (round = 0; round <= 1; round++) {
for (round = 0; round <= set ? 1 : 0; round++) {
if (round > 0) {
// After checking that the value is valid: set defaults
for (i = 0; i < entries; i++) {
@ -3560,7 +3582,7 @@ static char_u *set_chars_option(win_T *wp, char_u **varp)
*(tab[i].cp) = tab[i].def;
}
}
if (varp == &wp->w_p_lcs) {
if (varp == &p_lcs || varp == &wp->w_p_lcs) {
wp->w_p_lcs_chars.tab1 = NUL;
wp->w_p_lcs_chars.tab3 = NUL;
}
@ -4306,6 +4328,10 @@ static char *set_num_option(int opt_idx, char_u *varp, long value,
if (value < 0) {
errmsg = e_positive;
}
} else if (pp == &p_wd) {
if (value < 0) {
errmsg = e_positive;
}
}
// Don't change the value and return early if validation failed.
@ -5556,6 +5582,16 @@ void unset_global_local_option(char *name, void *from)
case PV_MENC:
clear_string_option(&buf->b_p_menc);
break;
case PV_LCS:
clear_string_option(&((win_T *)from)->w_p_lcs);
set_chars_option((win_T *)from, &((win_T *)from)->w_p_lcs, true);
redraw_win_later((win_T *)from, NOT_VALID);
break;
case PV_FCS:
clear_string_option(&((win_T *)from)->w_p_fcs);
set_chars_option((win_T *)from, &((win_T *)from)->w_p_fcs, true);
redraw_win_later((win_T *)from, NOT_VALID);
break;
}
}
@ -5591,6 +5627,8 @@ static char_u *get_varp_scope(vimoption_T *p, int opt_flags)
case PV_LW: return (char_u *)&(curbuf->b_p_lw);
case PV_BKC: return (char_u *)&(curbuf->b_p_bkc);
case PV_MENC: return (char_u *)&(curbuf->b_p_menc);
case PV_FCS: return (char_u *)&(curwin->w_p_fcs);
case PV_LCS: return (char_u *)&(curwin->w_p_lcs);
}
return NULL; // "cannot happen"
}
@ -5649,6 +5687,10 @@ static char_u *get_varp(vimoption_T *p)
? (char_u *)&(curbuf->b_p_lw) : p->var;
case PV_MENC: return *curbuf->b_p_menc != NUL
? (char_u *)&(curbuf->b_p_menc) : p->var;
case PV_FCS: return *curwin->w_p_fcs != NUL
? (char_u *)&(curwin->w_p_fcs) : p->var;
case PV_LCS: return *curwin->w_p_lcs != NUL
? (char_u *)&(curwin->w_p_lcs) : p->var;
case PV_ARAB: return (char_u *)&(curwin->w_p_arab);
case PV_LIST: return (char_u *)&(curwin->w_p_list);
@ -5745,8 +5787,6 @@ static char_u *get_varp(vimoption_T *p)
case PV_KMAP: return (char_u *)&(curbuf->b_p_keymap);
case PV_SCL: return (char_u *)&(curwin->w_p_scl);
case PV_WINHL: return (char_u *)&(curwin->w_p_winhl);
case PV_FCS: return (char_u *)&(curwin->w_p_fcs);
case PV_LCS: return (char_u *)&(curwin->w_p_lcs);
case PV_WINBL: return (char_u *)&(curwin->w_p_winbl);
default: IEMSG(_("E356: get_varp ERROR"));
}
@ -5888,8 +5928,8 @@ void didset_window_options(win_T *wp)
{
check_colorcolumn(wp);
briopt_check(wp);
set_chars_option(wp, &wp->w_p_fcs);
set_chars_option(wp, &wp->w_p_lcs);
set_chars_option(wp, &wp->w_p_fcs, true);
set_chars_option(wp, &wp->w_p_lcs, true);
parse_winhl_opt(wp); // sets w_hl_needs_update also for w_p_winbl
wp->w_grid.blending = wp->w_p_winbl > 0;
}

View File

@ -484,6 +484,7 @@ EXTERN long p_linespace; // 'linespace'
EXTERN char_u *p_lispwords; // 'lispwords'
EXTERN long p_ls; // 'laststatus'
EXTERN long p_stal; // 'showtabline'
EXTERN char_u *p_lcs; // 'listchars'
EXTERN int p_lz; // 'lazyredraw'
EXTERN int p_lpl; // 'loadplugins'
@ -518,10 +519,18 @@ EXTERN long p_pyx; // 'pyxversion'
EXTERN char_u *p_rdb; // 'redrawdebug'
EXTERN unsigned rdb_flags;
# ifdef IN_OPTION_C
static char *(p_rdb_values[]) = { "compositor", "nothrottle", NULL };
static char *(p_rdb_values[]) = {
"compositor",
"nothrottle",
"invalid",
"nodelta",
NULL
};
# endif
# define RDB_COMPOSITOR 0x001
# define RDB_NOTHROTTLE 0x002
# define RDB_INVALID 0x004
# define RDB_NODELTA 0x008
EXTERN long p_rdt; // 'redrawtime'
EXTERN int p_remap; // 'remap'
@ -644,6 +653,7 @@ EXTERN long p_ul; ///< 'undolevels'
EXTERN long p_ur; ///< 'undoreload'
EXTERN long p_uc; ///< 'updatecount'
EXTERN long p_ut; ///< 'updatetime'
EXTERN char_u *p_fcs; ///< 'fillchar'
EXTERN char_u *p_shada; ///< 'shada'
EXTERN char *p_shadafile; ///< 'shadafile'
EXTERN char_u *p_vdir; ///< 'viewdir'

View File

@ -804,11 +804,12 @@ return {
},
{
full_name='fillchars', abbreviation='fcs',
type='string', list='onecomma', scope={'window'},
type='string', list='onecomma', scope={'global', 'window'},
deny_duplicates=true,
vi_def=true,
alloced=true,
redraw={'current_window'},
varname='p_fcs',
defaults={if_true={vi=''}}
},
{
@ -1420,11 +1421,12 @@ return {
},
{
full_name='listchars', abbreviation='lcs',
type='string', list='onecomma', scope={'window'},
type='string', list='onecomma', scope={'global', 'window'},
deny_duplicates=true,
vim=true,
alloced=true,
redraw={'current_window'},
varname='p_lcs',
defaults={if_true={vi="eol:$", vim="tab:> ,trail:-,nbsp:+"}}
},
{

View File

@ -135,7 +135,16 @@ int os_setenv(const char *name, const char *value, int overwrite)
}
#endif
uv_mutex_lock(&mutex);
int r = uv_os_setenv(name, value);
int r;
#ifdef WIN32
// libintl uses getenv() for LC_ALL/LANG/etc., so we must use _putenv_s().
if (striequal(name, "LC_ALL") || striequal(name, "LANGUAGE")
|| striequal(name, "LANG") || striequal(name, "LC_MESSAGES")) {
r = _putenv_s(name, value); // NOLINT
assert(r == 0);
}
#endif
r = uv_os_setenv(name, value);
assert(r != UV_EINVAL);
// Destroy the old map item. Do this AFTER uv_os_setenv(), because `value`
// could be a previous os_getenv() result.

View File

@ -50,22 +50,13 @@ void signal_init(void)
signal_watcher_init(&main_loop, &shup, NULL);
signal_watcher_init(&main_loop, &squit, NULL);
signal_watcher_init(&main_loop, &sterm, NULL);
#ifdef SIGPIPE
signal_watcher_start(&spipe, on_signal, SIGPIPE);
#endif
signal_watcher_start(&shup, on_signal, SIGHUP);
#ifdef SIGQUIT
signal_watcher_start(&squit, on_signal, SIGQUIT);
#endif
signal_watcher_start(&sterm, on_signal, SIGTERM);
#ifdef SIGPWR
signal_watcher_init(&main_loop, &spwr, NULL);
signal_watcher_start(&spwr, on_signal, SIGPWR);
#endif
#ifdef SIGUSR1
signal_watcher_init(&main_loop, &susr1, NULL);
signal_watcher_start(&susr1, on_signal, SIGUSR1);
#endif
signal_start();
}
void signal_teardown(void)
@ -83,11 +74,33 @@ void signal_teardown(void)
#endif
}
void signal_start(void)
{
#ifdef SIGPIPE
signal_watcher_start(&spipe, on_signal, SIGPIPE);
#endif
signal_watcher_start(&shup, on_signal, SIGHUP);
#ifdef SIGQUIT
signal_watcher_start(&squit, on_signal, SIGQUIT);
#endif
signal_watcher_start(&sterm, on_signal, SIGTERM);
#ifdef SIGPWR
signal_watcher_start(&spwr, on_signal, SIGPWR);
#endif
#ifdef SIGUSR1
signal_watcher_start(&susr1, on_signal, SIGUSR1);
#endif
}
void signal_stop(void)
{
#ifdef SIGPIPE
signal_watcher_stop(&spipe);
#endif
signal_watcher_stop(&shup);
#ifdef SIGQUIT
signal_watcher_stop(&squit);
#endif
signal_watcher_stop(&sterm);
#ifdef SIGPWR
signal_watcher_stop(&spwr);

View File

@ -4022,10 +4022,10 @@ static void vgr_display_fname(char_u *fname)
static buf_T *vgr_load_dummy_buf(char_u *fname, char_u *dirname_start,
char_u *dirname_now)
{
char_u *save_ei = NULL;
// Don't do Filetype autocommands to avoid loading syntax and
// indent scripts, a great speed improvement.
char_u *save_ei = au_event_disable(",Filetype");
long save_mls = p_mls;
p_mls = 0;

View File

@ -347,6 +347,17 @@ int update_screen(int type)
grid_clear_line(&default_grid, default_grid.line_offset[i],
Columns, false);
}
FOR_ALL_WINDOWS_IN_TAB(wp, curtab) {
if (wp->w_floating) {
continue;
}
if (W_ENDROW(wp) > valid) {
wp->w_redr_type = MAX(wp->w_redr_type, NOT_VALID);
}
if (W_ENDROW(wp) + wp->w_status_height > valid) {
wp->w_redr_status = true;
}
}
}
msg_grid_set_pos(Rows-p_ch, false);
msg_grid_invalid = false;
@ -577,11 +588,14 @@ void conceal_check_cursor_line(void)
/// Whether cursorline is drawn in a special way
///
/// If true, both old and new cursorline will need
/// need to be redrawn when moving cursor within windows.
/// to be redrawn when moving cursor within windows.
/// TODO(bfredl): VIsual_active shouldn't be needed, but is used to fix a glitch
/// caused by scrolling.
bool win_cursorline_standout(const win_T *wp)
FUNC_ATTR_NONNULL_ALL
{
return wp->w_p_cul || (wp->w_p_cole > 0 && !conceal_cursor_line(wp));
return wp->w_p_cul
|| (wp->w_p_cole > 0 && (VIsual_active || !conceal_cursor_line(wp)));
}
/*
@ -871,7 +885,7 @@ static void win_update(win_T *wp)
if (wp->w_lines[0].wl_lnum != wp->w_topline)
i += diff_check_fill(wp, wp->w_lines[0].wl_lnum)
- wp->w_old_topfill;
if (i < wp->w_grid.Rows - 2) { // less than a screen off
if (i != 0 && i < wp->w_grid.Rows - 2) { // less than a screen off
// Try to insert the correct number of lines.
// If not the last window, delete the lines at the bottom.
// win_ins_lines may fail when the terminal can't do it.
@ -2403,10 +2417,10 @@ win_line (
filler_todo = filler_lines;
// Cursor line highlighting for 'cursorline' in the current window.
if (wp->w_p_cul && lnum == wp->w_cursor.lnum) {
if (lnum == wp->w_cursor.lnum) {
// Do not show the cursor line when Visual mode is active, because it's
// not clear what is selected then.
if (!(wp == curwin && VIsual_active)) {
if (wp->w_p_cul && !(wp == curwin && VIsual_active)) {
int cul_attr = win_hl_attr(wp, HLF_CUL);
HlAttrs ae = syn_attr2entry(cul_attr);
@ -3756,14 +3770,12 @@ win_line (
char_attr = hl_combine_attr(char_attr, extra_attr);
}
/*
* Handle the case where we are in column 0 but not on the first
* character of the line and the user wants us to show us a
* special character (via 'listchars' option "precedes:<char>".
*/
// Handle the case where we are in column 0 but not on the first
// character of the line and the user wants us to show us a
// special character (via 'listchars' option "precedes:<char>".
if (lcs_prec_todo != NUL
&& wp->w_p_list
&& (wp->w_p_wrap ? wp->w_skipcol > 0 : wp->w_leftcol > 0)
&& (wp->w_p_wrap ? (wp->w_skipcol > 0 && row == 0) : wp->w_leftcol > 0)
&& filler_todo <= 0
&& draw_state > WL_NR
&& c != NUL) {
@ -4007,7 +4019,7 @@ win_line (
break;
}
++vcol;
vcol += cells;
}
}
@ -4015,10 +4027,13 @@ win_line (
if (wp->w_buffer->terminal) {
// terminal buffers may need to highlight beyond the end of the
// logical line
while (col < grid->Columns) {
int n = wp->w_p_rl ? -1 : 1;
while (col >= 0 && col < grid->Columns) {
schar_from_ascii(linebuf_char[off], ' ');
linebuf_attr[off++] = term_attrs[vcol++];
col++;
linebuf_attr[off] = term_attrs[vcol];
off += n;
vcol += n;
col += n;
}
}
grid_put_linebuf(grid, row, 0, col, grid->Columns, wp->w_p_rl, wp,
@ -4353,7 +4368,7 @@ static int grid_char_needs_redraw(ScreenGrid *grid, int off_from, int off_to,
|| (line_off2cells(linebuf_char, off_from, off_from + cols) > 1
&& schar_cmp(linebuf_char[off_from + 1],
grid->chars[off_to + 1])))
|| p_wd < 0));
|| rdb_flags & RDB_NODELTA));
}
/// Move one buffered line to the window grid, but only the characters that
@ -5103,6 +5118,8 @@ win_redr_custom (
win_T *ewp;
int p_crb_save;
ScreenGrid *grid = &default_grid;
/* There is a tiny chance that this gets called recursively: When
* redrawing a status line triggers redrawing the ruler or tabline.
* Avoid trouble by not allowing recursion. */
@ -5142,10 +5159,11 @@ win_redr_custom (
}
maxwidth = wp->w_width - col;
if (!wp->w_status_height) {
grid = &msg_grid_adj;
row = Rows - 1;
maxwidth--; // writing in last column may cause scrolling
fillchar = ' ';
attr = 0;
attr = HL_ATTR(HLF_MSG);
}
use_sandbox = was_set_insecurely((char_u *)"rulerformat", 0);
@ -5195,13 +5213,13 @@ win_redr_custom (
/*
* Draw each snippet with the specified highlighting.
*/
grid_puts_line_start(&default_grid, row);
grid_puts_line_start(grid, row);
curattr = attr;
p = buf;
for (n = 0; hltab[n].start != NULL; n++) {
int textlen = (int)(hltab[n].start - p);
grid_puts_len(&default_grid, p, textlen, row, col, curattr);
grid_puts_len(grid, p, textlen, row, col, curattr);
col += vim_strnsize(p, textlen);
p = hltab[n].start;
@ -5215,7 +5233,7 @@ win_redr_custom (
curattr = highlight_user[hltab[n].userhl - 1];
}
// Make sure to use an empty string instead of p, if p is beyond buf + len.
grid_puts(&default_grid, p >= buf + len ? (char_u *)"" : p, row, col,
grid_puts(grid, p >= buf + len ? (char_u *)"" : p, row, col,
curattr);
grid_puts_line_flush(false);
@ -7060,7 +7078,7 @@ static void win_redr_ruler(win_T *wp, int always)
} else {
row = Rows - 1;
fillchar = ' ';
attr = 0;
attr = HL_ATTR(HLF_MSG);
width = Columns;
off = 0;
}

View File

@ -1508,11 +1508,11 @@ line_read_in:
* compute the first offset.
*/
if (state == TS_BINARY) {
// Get the tag file size.
if ((filesize = vim_lseek(fileno(fp), (off_T)0L, SEEK_END)) <= 0) {
if (vim_fseek(fp, 0, SEEK_END) != 0) {
state = TS_LINEAR;
} else {
vim_lseek(fileno(fp), (off_T)0L, SEEK_SET);
filesize = vim_ftell(fp);
vim_fseek(fp, 0, SEEK_SET);
/* Calculate the first read offset in the file. Start
* the search in the middle of the file. */

View File

@ -220,8 +220,6 @@ Terminal *terminal_open(TerminalOptions opts)
rv->sb_size = (size_t)curbuf->b_p_scbk;
rv->sb_buffer = xmalloc(sizeof(ScrollbackLine *) * rv->sb_size);
vterm_state_set_bold_highbright(state, true);
// Configure the color palette. Try to get the color from:
//
// - b:terminal_color_{NUM}

View File

@ -69,3 +69,59 @@ func! Test_display_foldtext_mbyte()
set foldtext& fillchars& foldmethod& fdc&
bw!
endfunc
func Test_display_listchars_precedes()
set fillchars+=vert:\|
call NewWindow(10, 10)
" Need a physical line that wraps over the complete
" window size
call append(0, repeat('aaa aaa aa ', 10))
call append(1, repeat(['bbb bbb bbb bbb'], 2))
" remove blank trailing line
$d
set list nowrap
call cursor(1, 1)
" move to end of line and scroll 2 characters back
norm! $2zh
let lines=ScreenLines([1,4], winwidth(0)+1)
let expect = [
\ " aaa aa $ |",
\ "$ |",
\ "$ |",
\ "~ |",
\ ]
call assert_equal(expect, lines)
set list listchars+=precedes:< nowrap
call cursor(1, 1)
" move to end of line and scroll 2 characters back
norm! $2zh
let lines = ScreenLines([1,4], winwidth(0)+1)
let expect = [
\ "<aaa aa $ |",
\ "< |",
\ "< |",
\ "~ |",
\ ]
call assert_equal(expect, lines)
set wrap
call cursor(1, 1)
" the complete line should be displayed in the window
norm! $
let lines = ScreenLines([1,10], winwidth(0)+1)
let expect = [
\ "<aaa aaa a|",
\ "a aaa aaa |",
\ "aa aaa aaa|",
\ " aa aaa aa|",
\ "a aa aaa a|",
\ "aa aa aaa |",
\ "aaa aa aaa|",
\ " aaa aa aa|",
\ "a aaa aa a|",
\ "aa aaa aa |",
\ ]
call assert_equal(expect, lines)
set list& listchars& wrap&
bw!
endfunc

View File

@ -347,3 +347,24 @@ func Test_statusline()
set laststatus&
set splitbelow&
endfunc
func Test_statusline_removed_group()
if !CanRunVimInTerminal()
throw 'Skipped: cannot make screendumps'
endif
let lines =<< trim END
scriptencoding utf-8
set laststatus=2
let &statusline = '%#StatColorHi2#%(✓%#StatColorHi2#%) Q≡'
END
call writefile(lines, 'XTest_statusline')
let buf = RunVimInTerminal('-S XTest_statusline', {'rows': 10, 'cols': 50})
call term_wait(buf, 100)
call VerifyScreenDump(buf, 'Test_statusline_1', {})
" clean up
call StopVimInTerminal(buf)
call delete('XTest_statusline')
endfunc

View File

@ -64,3 +64,28 @@ func Test_redrawtabline()
let &showtabline = showtabline_save
au! Bufadd
endfunc
function EmptyTabname()
return ""
endfunction
function MakeTabLine() abort
let titles = map(range(1, tabpagenr('$')), '"%( %" . v:val . "T%{EmptyTabname()}%T %)"')
let sep = 'あ'
let tabpages = join(titles, sep)
return tabpages .. sep .. '%=%999X X'
endfunction
func Test_tabline_empty_group()
" this was reading invalid memory
set tabline=%!MakeTabLine()
tabnew
redraw!
tabclose
set tabline=
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@ -42,6 +42,7 @@ endfunction
function! NewWindow(height, width) abort
exe a:height . 'new'
exe a:width . 'vsp'
set winfixwidth winfixheight
redraw!
endfunction

View File

@ -31,6 +31,7 @@
#include "nvim/event/signal.h"
#include "nvim/os/input.h"
#include "nvim/os/os.h"
#include "nvim/os/signal.h"
#include "nvim/os/tty.h"
#include "nvim/strings.h"
#include "nvim/syntax.h"
@ -93,7 +94,7 @@ typedef struct {
int out_fd;
bool scroll_region_is_full_screen;
bool can_change_scroll_region;
bool can_set_lr_margin;
bool can_set_lr_margin; // smglr
bool can_set_left_right_margin;
bool can_scroll;
bool can_erase_chars;
@ -312,6 +313,7 @@ static void terminfo_start(UI *ui)
uv_pipe_init(&data->write_loop, &data->output_handle.pipe, 0);
uv_pipe_open(&data->output_handle.pipe, data->out_fd);
}
flush_buf(ui);
}
static void terminfo_stop(UI *ui)
@ -1231,7 +1233,9 @@ static void suspend_event(void **argv)
tui_terminal_stop(ui);
data->cont_received = false;
stream_set_blocking(input_global_fd(), true); // normalize stream (#2598)
signal_stop();
kill(0, SIGTSTP);
signal_start();
while (!data->cont_received) {
// poll the event loop until SIGCONT is received
loop_poll_events(data->loop, -1);
@ -1598,6 +1602,12 @@ static void patch_terminfo_bugs(TUIData *data, const char *term,
unibi_set_if_empty(ut, unibi_set_lr_margin, "\x1b[%i%p1%d;%p2%ds");
unibi_set_if_empty(ut, unibi_set_left_margin_parm, "\x1b[%i%p1%ds");
unibi_set_if_empty(ut, unibi_set_right_margin_parm, "\x1b[%i;%p2%ds");
} else {
// Fix things advertised via TERM=xterm, for non-xterm.
if (unibi_get_str(ut, unibi_set_lr_margin)) {
ILOG("Disabling smglr with TERM=xterm for non-xterm.");
unibi_set_str(ut, unibi_set_lr_margin, NULL);
}
}
#ifdef WIN32

View File

@ -425,6 +425,15 @@ static void compose_line(Integer row, Integer startcol, Integer endcol,
flags = flags & ~kLineFlagWrap;
}
for (int i = skipstart; i < (endcol-skipend)-startcol; i++) {
if (attrbuf[i] < 0) {
if (rdb_flags & RDB_INVALID) {
abort();
} else {
attrbuf[i] = 0;
}
}
}
ui_composed_call_raw_line(1, row, startcol+skipstart,
endcol-skipend, endcol-skipend, 0, flags,
(const schar_T *)linebuf+skipstart,
@ -535,6 +544,11 @@ static void ui_comp_raw_line(UI *ui, Integer grid, Integer row,
} else {
compose_debug(row, row+1, startcol, endcol, dbghl_normal, false);
compose_debug(row, row+1, endcol, clearcol, dbghl_clear, true);
#ifndef NDEBUG
for (int i = 0; i < endcol-startcol; i++) {
assert(attrs[i] >= 0);
}
#endif
ui_composed_call_raw_line(1, row, startcol, endcol, clearcol, clearattr,
flags, chunk, attrs);
}

View File

@ -326,7 +326,7 @@ struct expr_ast_node {
} data;
};
enum {
enum ExprParserFlags {
/// Allow multiple expressions in a row: e.g. for :echo
///
/// Parser will still parse only one of them though.
@ -345,7 +345,7 @@ enum {
// viml_expressions_parser.c, nvim_parse_expression() flags parsing
// alongside with its documentation and flag sets in check_parsing()
// function in expressions parser functional and unit tests.
} ExprParserFlags;
};
/// AST error definition
typedef struct {

View File

@ -277,6 +277,24 @@ describe('startup', function()
[4] = {bold = true, foreground = Screen.colors.Blue1},
}})
end)
it('fixed hang issue with --headless (#11386)', function()
local expected = ''
local period = 100
for i = 1, period - 1 do
expected = expected .. i .. '\r\n'
end
expected = expected .. period
eq(
expected,
-- FIXME(codehex): We should really set a timeout for the system function.
-- If this test fails, there will be a waiting input state.
funcs.system({nvim_prog, '-u', 'NONE', '-c',
'for i in range(1, 100) | echo i | endfor | quit',
'--headless'
})
)
end)
end)
describe('sysinit', function()

View File

@ -38,7 +38,7 @@ module.nvim_prog = (
module.nvim_set = (
'set shortmess+=IS background=light noswapfile noautoindent'
..' laststatus=1 undodir=. directory=. viewdir=. backupdir=.'
..' belloff= wildoptions-=pum noshowcmd noruler nomore')
..' belloff= wildoptions-=pum noshowcmd noruler nomore redrawdebug=invalid')
module.nvim_argv = {
module.nvim_prog, '-u', 'NONE', '-i', 'NONE',
'--cmd', module.nvim_set, '--embed'}

View File

@ -71,15 +71,28 @@ describe("'fillchars'", function()
shouldfail('eob:xy') -- two ascii chars
shouldfail('eob:\255', 'eob:<ff>') -- invalid UTF-8
end)
it('is local to window', function()
clear()
screen = Screen.new(50, 5)
screen:attach()
it('has global value', function()
screen:try_resize(50, 5)
insert("foo\nbar")
command('set laststatus=0')
command('1,2fold')
command('vsplit')
command('set fillchars=fold:x')
screen:expect([[
^+-- 2 lines: fooxxxxxxxx+-- 2 lines: fooxxxxxxx|
~ ~ |
~ ~ |
~ ~ |
|
]])
end)
it('has local window value', function()
screen:try_resize(50, 5)
insert("foo\nbar")
command('set laststatus=0')
command('1,2fold')
command('vsplit')
command('setl fillchars=fold:x')
screen:expect([[
^+-- 2 lines: fooxxxxxxxx+-- 2 lines: foo·······|
~ ~ |
@ -100,16 +113,25 @@ describe("'listchars'", function()
screen:attach()
end)
after_each(function()
screen:detach()
end)
it('is local to window', function()
it('has global value', function()
feed('i<tab><tab><tab><esc>')
command('set laststatus=0')
command('set list listchars=tab:<->')
command('set list laststatus=0')
command('vsplit')
command('set listchars&')
command('set listchars=tab:<->')
screen:expect([[
<------><------>^<------> <------><------><------>|
~ ~ |
~ ~ |
~ ~ |
|
]])
end)
it('has value local to window', function()
feed('i<tab><tab><tab><esc>')
command('set list laststatus=0')
command('setl listchars=tab:<->')
command('vsplit')
command('setl listchars<')
screen:expect([[
> > ^> <------><------><------>|
~ ~ |

View File

@ -7,11 +7,8 @@ local eval = helpers.eval
local retry = helpers.retry
do
clear()
if missing_provider('node') then
pending("Missing nodejs host, or nodejs version is too old.", function()end)
return
end
pending("nodejs test times out on 0.4.x branch", function() end)
return
end
before_each(function()

View File

@ -10,13 +10,14 @@ local pcall_err = helpers.pcall_err
do
clear()
if missing_provider('python3') then
local reason = missing_provider('python3')
if reason then
it(':python3 reports E319 if provider is missing', function()
local expected = [[Vim%(py3.*%):E319: No "python3" provider found.*]]
matches(expected, pcall_err(command, 'py3 print("foo")'))
matches(expected, pcall_err(command, 'py3file foo'))
end)
pending('Python 3 (or the pynvim module) is broken/missing', function() end)
pending(string.format('Python 3 (or the pynvim module) is broken/missing (%s)', reason), function() end)
return
end
end

View File

@ -18,13 +18,14 @@ local pcall_err = helpers.pcall_err
do
clear()
if missing_provider('python') then
local reason = missing_provider('python')
if reason then
it(':python reports E319 if provider is missing', function()
local expected = [[Vim%(py.*%):E319: No "python" provider found.*]]
matches(expected, pcall_err(command, 'py print("foo")'))
matches(expected, pcall_err(command, 'pyfile foo'))
end)
pending('Python 2 (or the pynvim module) is broken/missing', function() end)
pending(string.format('Python 2 (or the pynvim module) is broken/missing (%s)', reason), function() end)
return
end
end

View File

@ -18,13 +18,14 @@ local pcall_err = helpers.pcall_err
do
clear()
if missing_provider('ruby') then
local reason = missing_provider('ruby')
if reason then
it(':ruby reports E319 if provider is missing', function()
local expected = [[Vim%(ruby.*%):E319: No "ruby" provider found.*]]
matches(expected, pcall_err(command, 'ruby puts "foo"'))
matches(expected, pcall_err(command, 'rubyfile foo'))
end)
pending("Missing neovim RubyGem.", function() end)
pending(string.format('Missing neovim RubyGem (%s)', reason), function() end)
return
end
end

View File

@ -5,6 +5,7 @@ local wait = helpers.wait
local eval, feed_command, source = helpers.eval, helpers.feed_command, helpers.source
local eq, neq = helpers.eq, helpers.neq
local write_file = helpers.write_file
local command= helpers.command
describe(':terminal buffer', function()
local screen
@ -224,6 +225,22 @@ describe(':terminal buffer', function()
neq('terminal', eval('&buftype'))
end)
end)
it('it works with set rightleft #11438', function()
local columns = eval('&columns')
feed(string.rep('a', columns))
command('set rightleft')
screen:expect([[
ydaer ytt|
{1:a}aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa|
|
|
|
|
{3:-- TERMINAL --} |
]])
command('bdelete!')
end)
end)
describe('No heap-buffer-overflow when using', function()

View File

@ -52,7 +52,7 @@ local function screen_setup(extra_rows, command, cols, opts)
[3] = {bold = true},
[4] = {foreground = 12},
[5] = {bold = true, reverse = true},
[6] = {background = 11},
-- 6 was a duplicate item
[7] = {foreground = 130},
[8] = {foreground = 15, background = 1}, -- error message
[9] = {foreground = 4},

View File

@ -306,6 +306,49 @@ describe('TUI', function()
expect_child_buf_lines({''})
end)
it('paste: select-mode', function()
feed_data('ithis is line 1\nthis is line 2\nline 3 is here\n\027')
wait_for_mode('n')
screen:expect{grid=[[
this is line 1 |
this is line 2 |
line 3 is here |
{1: } |
{5:[No Name] [+] }|
|
{3:-- TERMINAL --} |
]]}
-- Select-mode. Use <C-n> to move down.
feed_data('gg04lgh\14\14')
wait_for_mode('s')
feed_data('\027[200~')
feed_data('just paste it™')
feed_data('\027[201~')
screen:expect{grid=[[
thisjust paste it{1:3} is here |
|
{4:~ }|
{4:~ }|
{5:[No Name] [+] }|
|
{3:-- TERMINAL --} |
]]}
-- Undo.
feed_data('u')
expect_child_buf_lines{
'this is line 1',
'this is line 2',
'line 3 is here',
'',
}
-- Redo.
feed_data('\18') -- <C-r>
expect_child_buf_lines{
'thisjust paste it™3 is here',
'',
}
end)
it('paste: terminal mode', function()
feed_data(':set statusline=^^^^^^^\n')
feed_data(':terminal '..nvim_dir..'/tty-test\n')
@ -539,7 +582,7 @@ describe('TUI', function()
|
{4:~ }|
{5: }|
{8:paste: Error executing lua: vim.lua:197: Vim:E21: }|
{8:paste: Error executing lua: vim.lua:200: Vim:E21: }|
{8:Cannot make changes, 'modifiable' is off} |
{10:Press ENTER or type command to continue}{1: } |
{3:-- TERMINAL --} |
@ -578,6 +621,23 @@ describe('TUI', function()
]])
end)
it('paste: less-than sign in cmdline #11088', function()
local expected = '<'
feed_data(':')
wait_for_mode('c')
-- "bracketed paste"
feed_data('\027[200~'..expected..'\027[201~')
screen:expect{grid=[[
|
{4:~ }|
{4:~ }|
{4:~ }|
{5:[No Name] }|
:<{1: } |
{3:-- TERMINAL --} |
]]}
end)
it('paste: big burst of input', function()
feed_data(':set ruler\n')
local t = {}

View File

@ -31,6 +31,9 @@ describe('Buffer highlighting', function()
[14] = {background = Screen.colors.Gray90},
[15] = {background = Screen.colors.Gray90, bold = true, foreground = Screen.colors.Brown},
[16] = {foreground = Screen.colors.Magenta, background = Screen.colors.Gray90},
[17] = {foreground = Screen.colors.Magenta, background = Screen.colors.LightRed},
[18] = {background = Screen.colors.LightRed},
[19] = {foreground = Screen.colors.Blue1, background = Screen.colors.LightRed},
})
end)
@ -516,6 +519,32 @@ describe('Buffer highlighting', function()
|
]])
end)
it('works with color column', function()
eq(-1, set_virtual_text(-1, 3, {{"暗x事", "Comment"}}, {}))
screen:expect{grid=[[
^1 + 2 {3:=}{2: 3} |
3 + {11:ERROR:} invalid syntax |
5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
x = 4 {12:x事} |
{1:~ }|
{1:~ }|
|
]]}
command("set colorcolumn=9")
screen:expect{grid=[[
^1 + 2 {3:=}{2: }{17:3} |
3 + {11:ERROR:} invalid syntax |
5, 5, 5,{18: }5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5|
, 5, 5, 5, 5, 5, 5, Lorem ipsum dolor s|
x = 4 {12:}{19:x}{12:} |
{1:~ }|
{1:~ }|
|
]]}
end)
end)
it('and virtual text use the same namespace counter', function()

View File

@ -3,6 +3,8 @@ local Screen = require('test.functional.ui.screen')
local feed = helpers.feed
local clear = helpers.clear
local command = helpers.command
local insert = helpers.insert
local write_file = helpers.write_file
describe('Diff mode screen', function()
@ -957,3 +959,75 @@ int main(int argc, char **argv)
end)
end)
end)
it('win_update redraws lines properly', function()
local screen
clear()
screen = Screen.new(30, 10)
screen:attach()
screen:set_default_attr_ids({
[1] = {bold = true, foreground = Screen.colors.Blue1},
[2] = {foreground = Screen.colors.Grey100, background = Screen.colors.Red},
[3] = {background = Screen.colors.Red, foreground = Screen.colors.Grey100, special = Screen.colors.Yellow},
[4] = {bold = true, foreground = Screen.colors.SeaGreen4},
[5] = {special = Screen.colors.Yellow},
[6] = {special = Screen.colors.Yellow, bold = true, foreground = Screen.colors.SeaGreen4},
[7] = {foreground = Screen.colors.Grey0, background = Screen.colors.Grey100},
[8] = {foreground = Screen.colors.Gray90, background = Screen.colors.Grey100},
[9] = {foreground = tonumber('0x00000c'), background = Screen.colors.Grey100},
[10] = {background = Screen.colors.Grey100, bold = true, foreground = tonumber('0xe5e5ff')},
[11] = {background = Screen.colors.Grey100, bold = true, foreground = tonumber('0x2b8452')},
[12] = {bold = true, reverse = true},
[13] = {foreground = Screen.colors.DarkBlue, background = Screen.colors.WebGray},
[14] = {reverse = true},
[15] = {background = Screen.colors.LightBlue},
[16] = {background = Screen.colors.LightCyan1, bold = true, foreground = Screen.colors.Blue1},
[17] = {bold = true, background = Screen.colors.Red},
[18] = {background = Screen.colors.LightMagenta},
})
insert([[
1
2
1a
]])
command("vnew")
insert([[
2
2a
2b
]])
command("windo diffthis")
command("windo 1")
screen:expect{grid=[[
{13: }{16:-------}{14:│}{13: }{15:^1 }|
{13: }{16:-------}{14:│}{13: }{15: }|
{13: }{16:-------}{14:│}{13: }{15: }|
{13: }2 {14:}{13: }2 |
{13: }{17:2}{18:a }{14:}{13: }{17:1}{18:a }|
{13: }{15:2b }{14:}{13: }{16:------------------}|
{13: } {14:}{13: } |
{1:~ }{14:}{1:~ }|
{14:<me] [+] }{12:[No Name] [+] }|
|
]]}
feed('<C-e>')
feed('<C-e>')
feed('<C-y>')
feed('<C-y>')
feed('<C-y>')
screen:expect{grid=[[
{13: }{16:-------}{14:│}{13: }{15:1 }|
{13: }{16:-------}{14:│}{13: }{15: }|
{13: }{16:-------}{14:│}{13: }{15:^ }|
{13: }2 {14:}{13: }2 |
{13: }{17:2}{18:a }{14:}{13: }{17:1}{18:a }|
{13: }{15:2b }{14:}{13: }{16:------------------}|
{13: } {14:}{13: } |
{1:~ }{14:}{1:~ }|
{14:<me] [+] }{12:[No Name] [+] }|
|
]]}
end)

View File

@ -657,6 +657,30 @@ describe("'listchars' highlight", function()
]])
end)
it("'listchar' with wrap", function()
screen:set_default_attr_ids({
[0] = {bold=true, foreground=Screen.colors.Blue},
})
feed_command('set wrap')
feed_command('set listchars=eol:¬,precedes:< list')
feed('90ia<esc>')
screen:expect([[
{0:<}aaaaaaaaaaaaaaaaaaa|
aaaaaaaaaaaaaaaaaaaa|
aaaaaaaaaaaaaaaaaaaa|
aaaaaaaaa^a{0:¬} |
|
]])
feed('0')
screen:expect([[
^aaaaaaaaaaaaaaaaaaaa|
aaaaaaaaaaaaaaaaaaaa|
aaaaaaaaaaaaaaaaaaaa|
aaaaaaaaaaaaaaaaaaaa|
|
]])
end)
it("'listchar' in visual mode", function()
screen:set_default_attr_ids({
[1] = {background=Screen.colors.Grey90},

View File

@ -810,6 +810,9 @@ describe('ui/builtin messages', function()
[4] = {bold = true, foreground = Screen.colors.SeaGreen4},
[5] = {foreground = Screen.colors.Blue1},
[6] = {bold = true, foreground = Screen.colors.Magenta},
[7] = {background = Screen.colors.Grey20},
[8] = {reverse = true},
[9] = {background = Screen.colors.LightRed}
})
end)
@ -902,6 +905,151 @@ vimComment xxx match /\s"[^\-:.%#=*].*$/ms=s+1,lc=1 excludenl contains=@vim
meths.command_output('syntax list vimComment'))
-- luacheck: pop
end)
it('supports ruler with laststatus=0', function()
command("set ruler laststatus=0")
screen:expect{grid=[[
^ |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
0,0-1 All |
]]}
command("hi MsgArea guibg=#333333")
screen:expect{grid=[[
^ |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{7: 0,0-1 All }|
]]}
command("set rulerformat=%15(%c%V\\ %p%%%)")
screen:expect{grid=[[
^ |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{7: 0,0-1 100% }|
]]}
end)
it('supports echo with CRLF line separators', function()
feed(':echo "line 1\\r\\nline 2"<cr>')
screen:expect{grid=[[
|
{1:~ }|
{1:~ }|
{3: }|
line 1 |
line 2 |
{4:Press ENTER or type command to continue}^ |
]]}
feed('<cr>:echo "abc\\rz"<cr>')
screen:expect{grid=[[
^ |
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
{1:~ }|
zbc |
]]}
end)
it('redraws NOT_VALID correctly after message', function()
-- edge case: only one window was set NOT_VALID. Orginal report
-- used :make, but fake it using one command to set the current
-- window NOT_VALID and another to show a long message.
screen:try_resize(80, 7)
command("set more")
feed(':new<cr><c-w><c-w>')
screen:expect{grid=[[
|
{1:~ }|
{8:[No Name] }|
^ |
{1:~ }|
{3:[No Name] }|
:new |
]]}
feed(':set colorcolumn=10 | digraphs<cr>')
screen:expect{grid=[[
:set colorcolumn=10 | digraphs |
NU {5:^@} 10 SH {5:^A} 1 SX {5:^B} 2 EX {5:^C} 3 ET {5:^D} 4 EQ {5:^E} 5 |
AK {5:^F} 6 BL {5:^G} 7 BS {5:^H} 8 HT {5:^I} 9 LF {5:^@} 10 VT {5:^K} 11 |
FF {5:^L} 12 CR {5:^M} 13 SO {5:^N} 14 SI {5:^O} 15 DL {5:^P} 16 D1 {5:^Q} 17 |
D2 {5:^R} 18 D3 {5:^S} 19 D4 {5:^T} 20 NK {5:^U} 21 SY {5:^V} 22 EB {5:^W} 23 |
CN {5:^X} 24 EM {5:^Y} 25 SB {5:^Z} 26 EC {5:^[} 27 FS {5:^\} 28 GS {5:^]} 29 |
{4:-- More --}^ |
]]}
feed('q')
screen:expect{grid=[[
|
{1:~ }|
{8:[No Name] }|
^ {9: } |
{1:~ }|
{3:[No Name] }|
|
]]}
-- edge case: just covers statusline
feed(':set colorcolumn=5 | lua error("x\\n\\nx")<cr>')
screen:expect{grid=[[
|
{1:~ }|
{3: }|
{2:E5105: Error while calling lua chunk: [string "<VimL compiled string>"]:1: x} |
|
{2:x} |
{4:Press ENTER or type command to continue}^ |
]]}
feed('<cr>')
screen:expect{grid=[[
|
{1:~ }|
{8:[No Name] }|
^ {9: } |
{1:~ }|
{3:[No Name] }|
|
]]}
-- edge case: just covers lowest window line
feed(':set colorcolumn=5 | lua error("x\\n\\n\\nx")<cr>')
screen:expect{grid=[[
|
{3: }|
{2:E5105: Error while calling lua chunk: [string "<VimL compiled string>"]:1: x} |
|
|
{2:x} |
{4:Press ENTER or type command to continue}^ |
]]}
feed('<cr>')
screen:expect{grid=[[
|
{1:~ }|
{8:[No Name] }|
^ {9: } |
{1:~ }|
{3:[No Name] }|
|
]]}
end)
end)
describe('ui/ext_messages', function()
@ -1089,7 +1237,7 @@ aliquip ex ea commodo consequat.]])
it('can be quit', function()
screen:try_resize(25,5)
feed(':echon join(map(range(0, &lines*2), "v:val"), "\\n")<cr>')
feed(':echon join(map(range(0, &lines*10), "v:val"), "\\n")<cr>')
screen:expect{grid=[[
0 |
1 |

View File

@ -12,7 +12,10 @@ describe('ui/mouse/input', function()
clear()
meths.set_option('mouse', 'a')
meths.set_option('list', true)
meths.set_option('listchars', 'eol:$')
-- NB: this is weird, but mostly irrelevant to the test
-- So I didn't bother to change it
command('set listchars=eol:$')
command('setl listchars=nbsp:x')
screen = Screen.new(25, 5)
screen:attach()
screen:set_default_attr_ids({
@ -814,7 +817,8 @@ describe('ui/mouse/input', function()
feed_command('set concealcursor=ni')
feed_command('set nowrap')
feed_command('set shiftwidth=2 tabstop=4 list listchars=tab:>-')
feed_command('set shiftwidth=2 tabstop=4 list')
feed_command('setl listchars=tab:>-')
feed_command('syntax match NonText "\\*" conceal')
feed_command('syntax match NonText "cats" conceal cchar=X')
feed_command('syntax match NonText "x" conceal cchar=>')

View File

@ -127,6 +127,10 @@ describe('multibyte rendering: statusline', function()
before_each(function()
clear()
screen = Screen.new(40, 4)
screen:set_default_attr_ids({
[1] = {bold = true, foreground = Screen.colors.Blue1},
[2] = {bold = true, reverse = true},
})
screen:attach()
command('set laststatus=2')
end)
@ -139,8 +143,8 @@ describe('multibyte rendering: statusline', function()
command('set statusline=你好')
screen:expect([[
^ |
~ |
|
{1:~ }|
{2: }|
|
]])
end)
@ -148,8 +152,8 @@ describe('multibyte rendering: statusline', function()
command('set statusline=abc')
screen:expect([[
^ |
~ |
abc |
{1:~ }|
{2:abc }|
|
]])
end)
@ -157,8 +161,8 @@ describe('multibyte rendering: statusline', function()
command('set statusline=Ÿ')
screen:expect([[
^ |
~ |
<9f> |
{1:~ }|
{2:<9f> }|
|
]])
end)
@ -167,8 +171,8 @@ describe('multibyte rendering: statusline', function()
-- o + U+1DF0 + U+20EF + U+0338 + U+20D0 + U+20E7 + U+20DD
screen:expect([[
^ |
~ |
o̸⃯ᷰ⃐⃧ |
{1:~ }|
{2:o̸⃯ᷰ⃐⃧ }|
|
]])
end)
@ -177,9 +181,19 @@ describe('multibyte rendering: statusline', function()
-- U+9F + U+1DF0 + U+20EF + U+0338 + U+20D0 + U+20E7 + U+20DD
screen:expect([[
^ |
~ |
<9f><1df0><20ef><0338><20d0><20e7><20dd>|
{1:~ }|
{2:<9f><1df0><20ef><0338><20d0><20e7><20dd>}|
|
]])
end)
it('hidden group %( %) does not cause invalid unicode', function()
command("let &statusline = '%#StatColorHi2#%(✓%#StatColorHi2#%) Q≡'")
screen:expect{grid=[[
^ |
{1:~ }|
{2: Q }|
|
]]}
end)
end)

View File

@ -516,6 +516,7 @@ describe('ui/ext_popupmenu', function()
{1:~ }|
:sign ^ |
]])
eq(0, funcs.wildmenumode())
feed('<tab>')
screen:expect{grid=[[
@ -530,6 +531,7 @@ describe('ui/ext_popupmenu', function()
{1:~ }|
:sign define^ |
]], popupmenu={items=wild_expected, pos=0, anchor={1, 9, 6}}}
eq(1, funcs.wildmenumode())
feed('<left>')
screen:expect{grid=[[
@ -589,6 +591,7 @@ describe('ui/ext_popupmenu', function()
:sign unplace^ |
]], popupmenu={items=wild_expected, pos=5, anchor={1, 9, 6}}}
feed('<esc>')
eq(0, funcs.wildmenumode())
-- check positioning with multibyte char in pattern
command("e långfile1")

View File

@ -1,6 +1,7 @@
local helpers = require('test.functional.helpers')(after_each)
local Screen = require('test.functional.ui.screen')
local clear, feed, command = helpers.clear, helpers.feed, helpers.command
local eq = helpers.eq
local insert = helpers.insert
describe('Screen', function()
@ -17,6 +18,7 @@ describe('Screen', function()
[3] = {reverse = true},
[4] = {bold = true},
[5] = {background = Screen.colors.Yellow},
[6] = {background = Screen.colors.LightGrey},
} )
end)
@ -823,5 +825,96 @@ describe('Screen', function()
]])
end)
end)
it('redraws properly with concealcursor in visual mode', function()
command('set concealcursor=v conceallevel=2')
feed('10Ofoo barf bar barf eggs<esc>')
feed(':3<cr>o a<Esc>ggV')
screen:expect{grid=[[
^f{6:oo }{1:b}{6: bar }{1:b}{6: eggs} |
foo {1:b} bar {1:b} eggs |
foo {1:b} bar {1:b} eggs |
a |
foo {1:b} bar {1:b} eggs |
foo {1:b} bar {1:b} eggs |
foo {1:b} bar {1:b} eggs |
foo {1:b} bar {1:b} eggs |
foo {1:b} bar {1:b} eggs |
{4:-- VISUAL LINE --} |
]]}
feed(string.rep('j', 15))
screen:expect{grid=[[
{6:foo }{1:b}{6: bar }{1:b}{6: eggs} |
{6:foo }{1:b}{6: bar }{1:b}{6: eggs} |
{6:foo }{1:b}{6: bar }{1:b}{6: eggs} |
{6:foo }{1:b}{6: bar }{1:b}{6: eggs} |
{6:foo }{1:b}{6: bar }{1:b}{6: eggs} |
{6:foo }{1:b}{6: bar }{1:b}{6: eggs} |
{6:foo }{1:b}{6: bar }{1:b}{6: eggs} |
{6:foo }{1:b}{6: bar }{1:b}{6: eggs} |
^f{6:oo }{1:b}{6: bar }{1:b}{6: eggs} |
{4:-- VISUAL LINE --} |
]]}
feed(string.rep('k', 15))
screen:expect{grid=[[
^f{6:oo }{1:b}{6: bar }{1:b}{6: eggs} |
foo {1:b} bar {1:b} eggs |
foo {1:b} bar {1:b} eggs |
a |
foo {1:b} bar {1:b} eggs |
foo {1:b} bar {1:b} eggs |
foo {1:b} bar {1:b} eggs |
foo {1:b} bar {1:b} eggs |
foo {1:b} bar {1:b} eggs |
{4:-- VISUAL LINE --} |
]]}
end)
end)
it('redraws not too much with conceallevel=1', function()
command('set conceallevel=1')
command('set redrawdebug+=nodelta')
insert([[
aaa
bbb
ccc
]])
screen:expect{grid=[[
aaa |
bbb |
ccc |
^ |
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
|
]]}
-- XXX: hack to get notifications, and check only a single line is
-- updated. Could use next_msg() also.
local orig_handle_grid_line = screen._handle_grid_line
local grid_lines = {}
function screen._handle_grid_line(self, grid, row, col, items)
table.insert(grid_lines, {row, col, items})
orig_handle_grid_line(self, grid, row, col, items)
end
feed('k')
screen:expect{grid=[[
aaa |
bbb |
^ccc |
|
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
{0:~ }|
|
]]}
eq(grid_lines, {{2, 0, {{'c', 0, 3}}}})
end)
end)

View File

@ -160,8 +160,8 @@ set(UNIBILIUM_SHA256 29815283c654277ef77a3adcc8840db79ddbb20a0f0b0c8f648bd8cd49a
set(LIBTERMKEY_URL http://www.leonerd.org.uk/code/libtermkey/libtermkey-0.21.1.tar.gz)
set(LIBTERMKEY_SHA256 cecbf737f35d18f433c8d7864f63c0f878af41f8bd0255a3ebb16010dc044d5f)
set(LIBVTERM_URL https://github.com/neovim/libvterm/archive/4a5fa43e0dbc0db4fe67d40d788d60852864df9e.tar.gz)
set(LIBVTERM_SHA256 49b3cf2dcb988b887671b1011cfeac98ff81bb5c23fb4ac34b91a59524992935)
set(LIBVTERM_URL https://github.com/neovim/libvterm/archive/7c72294d84ce20da4c27362dbd7fa4b08cfc91da.tar.gz)
set(LIBVTERM_SHA256 f30c4d43e0c6db3e0912daf7188d98fbf6ee88f97589d72f6f304e5db48826a8)
set(LUV_VERSION 1.30.0-0)
set(LUV_URL https://github.com/luvit/luv/archive/${LUV_VERSION}.tar.gz)
@ -177,8 +177,8 @@ set(GPERF_SHA256 588546b945bba4b70b6a3a616e80b4ab466e3f33024a352fc2198112cdbb3ae
set(WINTOOLS_URL https://github.com/neovim/deps/raw/2f9acbecf06365c10baa3c0087f34a54c9c6f949/opt/win32tools.zip)
set(WINTOOLS_SHA256 8bfce7e3a365721a027ce842f2ec1cf878f1726233c215c05964aac07300798c)
set(WINGUI_URL https://github.com/equalsraf/neovim-qt/releases/download/v0.2.14/neovim-qt.zip)
set(WINGUI_SHA256 dfcb1f7d25d4907dc1d4f20edd71ff9eb4762196225106bec01274dd668fb04c)
set(WINGUI_URL https://github.com/equalsraf/neovim-qt/releases/download/v0.2.15/neovim-qt.zip)
set(WINGUI_SHA256 b519ecb80b60522d25043f2d076a55656f5fbe5adf7f7e2943e5d8b161043987)
set(WIN32YANK_X86_URL https://github.com/equalsraf/win32yank/releases/download/v0.0.4/win32yank-x86.zip)
set(WIN32YANK_X86_SHA256 62f34e5a46c5d4a7b3f3b512e1ff7b77fedd432f42581cbe825233a996eed62c)

View File

@ -48,6 +48,7 @@ ExternalProject_Add(libtermkey
PREFIX=${DEPS_INSTALL_DIR}
PKG_CONFIG_PATH=${DEPS_LIB_DIR}/pkgconfig
CFLAGS=-fPIC
LDFLAGS+=-static
${DEFAULT_MAKE_CFLAGS}
install)
endif()

View File

@ -58,6 +58,7 @@ else()
set(LIBVTERM_INSTALL_COMMAND ${MAKE_PRG} CC=${DEPS_C_COMPILER}
PREFIX=${DEPS_INSTALL_DIR}
CFLAGS=-fPIC
LDFLAGS+=-static
${DEFAULT_MAKE_CFLAGS}
install)
endif()

View File

@ -40,6 +40,7 @@ else()
BUILD_COMMAND ${MAKE_PRG} CC=${DEPS_C_COMPILER}
PREFIX=${DEPS_INSTALL_DIR}
CFLAGS=-fPIC
LDFLAGS+=-static
INSTALL_COMMAND ${MAKE_PRG} PREFIX=${DEPS_INSTALL_DIR} install)
endif()

View File

@ -8,6 +8,9 @@ endmacro()
file(READ gettext-runtime/config.h.in CONFIG_CONTENT)
string(REPLACE "#undef HAVE_GETCWD" "#define HAVE_GETCWD 1" CONFIG_CONTENT ${CONFIG_CONTENT})
string(REPLACE "#undef HAVE_ICONV_H" "#define HAVE_ICONV_H 1" CONFIG_CONTENT ${CONFIG_CONTENT})
string(REPLACE "#undef HAVE_ICONV" "#define HAVE_ICONV 1" CONFIG_CONTENT ${CONFIG_CONTENT})
string(REPLACE "#undef ICONV_CONST" "#define ICONV_CONST const" CONFIG_CONTENT ${CONFIG_CONTENT})
string(REPLACE "#undef uintmax_t" "
#if _WIN64
# define intmax_t long long
@ -54,7 +57,8 @@ PREFIX_LIST_ITEMS(libintl_SOURCES "gettext-runtime/intl/")
add_library(libintl ${libintl_SOURCES})
set_property(TARGET libintl APPEND PROPERTY INCLUDE_DIRECTORIES
${CMAKE_CURRENT_BINARY_DIR}/gettext-runtime
${CMAKE_CURRENT_BINARY_DIR}/gettext-runtime/intl)
${CMAKE_CURRENT_BINARY_DIR}/gettext-runtime/intl
${LIBICONV_INCLUDE_DIRS})
set_property(TARGET libintl APPEND PROPERTY COMPILE_DEFINITIONS
BUILDING_LIBINTL
IN_LIBINTL
@ -72,6 +76,8 @@ string(REPLACE "#undef ENDIANNESS" "#define ENDIANNESS 0" CONFIG_CONTENT ${CONFI
string(REPLACE "#undef GNULIB_FWRITEERROR" "#define GNULIB_FWRITEERROR 1" CONFIG_CONTENT ${CONFIG_CONTENT})
string(REPLACE "#undef HAVE_DECL_STRERROR_R" "#define HAVE_DECL_STRERROR_R 0" CONFIG_CONTENT ${CONFIG_CONTENT})
string(REPLACE "#undef HAVE_DUP2" "#define HAVE_DUP2 1" CONFIG_CONTENT ${CONFIG_CONTENT})
string(REPLACE "#undef HAVE_ICONV_H" "#define HAVE_ICONV_H 1" CONFIG_CONTENT ${CONFIG_CONTENT})
string(REPLACE "#undef HAVE_ICONV" "#define HAVE_ICONV 1" CONFIG_CONTENT ${CONFIG_CONTENT})
string(REPLACE "#undef HAVE_LIBUNISTRING" "#define HAVE_LIBUNISTRING 1" CONFIG_CONTENT ${CONFIG_CONTENT})
string(REPLACE "#undef HAVE_STDINT_H_WITH_UINTMAX" "#define HAVE_STDINT_H_WITH_UINTMAX 1" CONFIG_CONTENT ${CONFIG_CONTENT})
string(REPLACE "#undef HAVE_STDINT_H" "#define HAVE_STDINT_H 1" CONFIG_CONTENT ${CONFIG_CONTENT})
@ -126,7 +132,7 @@ set(GLIBC_SOURCE
mbchar.c mbslen.c mbsstr.c mbswidth.c obstack.c ostream.c html-ostream.c
fd-ostream.c styled-ostream.c progname.c html-styled-ostream.c printf-args.c
printf-parse.c propername.c quotearg.c rawmemchr.c safe-read.c safe-write.c
stpcpy.c stpncpy.c strchrnul.c striconveh.c striconveha.c strnlen1.c
stpcpy.c stpncpy.c strchrnul.c striconv.c striconveh.c striconveha.c strnlen1.c
term-ostream.c term-styled-ostream.c tparm.c trim.c gcd.c gl_linkedhash_list.c
uniconv/u8-conv-from-enc.c unictype/ctype_space.c unilbrk/lbrktables.c
unilbrk/u8-possible-linebreaks.c unilbrk/u8-width-linebreaks.c
@ -135,7 +141,7 @@ set(GLIBC_SOURCE
unistr/u8-mbtouc-unsafe-aux.c unistr/u8-mbtouc-unsafe.c unistr/u8-mbtouc.c
unistr/u8-mbtoucr.c unistr/u8-prev.c unistr/u8-uctomb-aux.c unistr/u8-uctomb.c
uniwidth/width.c vasnprintf.c vasprintf.c wcwidth.c xasprintf.c
xconcat-filename.c xerror.c xmalloc.c xstrdup.c xvasprintf.c glib/ghash.c
xconcat-filename.c xerror.c xmalloc.c xstrdup.c xstriconv.c xstriconveh.c xvasprintf.c glib/ghash.c
glib/glist.c glib/gmessages.c glib/gprimes.c glib/gstrfuncs.c glib/gstring.c
libcroco/cr-additional-sel.c libcroco/cr-attr-sel.c libcroco/cr-cascade.c
libcroco/cr-declaration.c libcroco/cr-doc-handler.c libcroco/cr-enc-handler.c