Merge branch 'master' into expression-parser

This commit is contained in:
ZyX
2017-11-30 02:02:55 +03:00
21 changed files with 427 additions and 107 deletions

View File

@@ -0,0 +1,20 @@
" Common functionality for providers
let s:stderr = {}
function! provider#stderr_collector(chan_id, data, event)
let stderr = get(s:stderr, a:chan_id, [''])
let stderr[-1] .= a:data[0]
call extend(stderr, a:data[1:])
let s:stderr[a:chan_id] = stderr
endfunction
function! provider#clear_stderr(chan_id)
if has_key(s:stderr, a:chan_id)
call remove(s:stderr, a:chan_id)
endif
endfunction
function! provider#get_stderr(chan_id)
return get(s:stderr, a:chan_id, [])
endfunction

View File

@@ -7,7 +7,7 @@ let s:clipboard = {}
" When caching is enabled, store the jobid of the xclip/xsel process keeping " When caching is enabled, store the jobid of the xclip/xsel process keeping
" ownership of the selection, so we know how long the cache is valid. " ownership of the selection, so we know how long the cache is valid.
let s:selection = { 'owner': 0, 'data': [], 'stderr_buffered': v:true } let s:selection = { 'owner': 0, 'data': [], 'on_stderr': function('provider#stderr_collector') }
function! s:selection.on_exit(jobid, data, event) abort function! s:selection.on_exit(jobid, data, event) abort
" At this point this nvim instance might already have launched " At this point this nvim instance might already have launched
@@ -16,10 +16,12 @@ function! s:selection.on_exit(jobid, data, event) abort
let self.owner = 0 let self.owner = 0
endif endif
if a:data != 0 if a:data != 0
let stderr = provider#get_stderr(a:jobid)
echohl WarningMsg echohl WarningMsg
echomsg 'clipboard: error invoking '.get(self.argv, 0, '?').': '.join(self.stderr) echomsg 'clipboard: error invoking '.get(self.argv, 0, '?').': '.join(stderr)
echohl None echohl None
endif endif
call provider#clear_stderr(a:jobid)
endfunction endfunction
let s:selections = { '*': s:selection, '+': copy(s:selection) } let s:selections = { '*': s:selection, '+': copy(s:selection) }

View File

@@ -3,7 +3,7 @@ if exists('g:loaded_node_provider')
endif endif
let g:loaded_node_provider = 1 let g:loaded_node_provider = 1
let s:job_opts = {'rpc': v:true, 'stderr_buffered': v:true} let s:job_opts = {'rpc': v:true, 'on_stderr': function('provider#stderr_collector')}
function! provider#node#Detect() abort function! provider#node#Detect() abort
return has('win32') ? exepath('neovim-node-host.cmd') : exepath('neovim-node-host') return has('win32') ? exepath('neovim-node-host.cmd') : exepath('neovim-node-host')
@@ -32,18 +32,19 @@ function! provider#node#Require(host) abort
endif endif
try try
let job = copy(s:job_opts) let channel_id = jobstart(args, s:job_opts)
let channel_id = jobstart(args, job)
if rpcrequest(channel_id, 'poll') ==# 'ok' if rpcrequest(channel_id, 'poll') ==# 'ok'
return channel_id return channel_id
endif endif
catch catch
echomsg v:throwpoint echomsg v:throwpoint
echomsg v:exception echomsg v:exception
for row in job.stderr for row in provider#get_stderr(channel_id)
echomsg row echomsg row
endfor endfor
endtry endtry
finally
call provider#clear_stderr(channel_id)
endtry endtry
throw remote#host#LoadErrorForHost(a:host.orig_name, '$NVIM_NODE_LOG_FILE') throw remote#host#LoadErrorForHost(a:host.orig_name, '$NVIM_NODE_LOG_FILE')
endfunction endfunction

View File

@@ -5,7 +5,7 @@ endif
let s:loaded_pythonx_provider = 1 let s:loaded_pythonx_provider = 1
let s:job_opts = {'rpc': v:true, 'stderr_buffered': v:true} let s:job_opts = {'rpc': v:true, 'on_stderr': function('provider#stderr_collector')}
function! provider#pythonx#Require(host) abort function! provider#pythonx#Require(host) abort
let ver = (a:host.orig_name ==# 'python') ? 2 : 3 let ver = (a:host.orig_name ==# 'python') ? 2 : 3
@@ -21,17 +21,18 @@ function! provider#pythonx#Require(host) abort
endfor endfor
try try
let job = copy(s:job_opts) let channel_id = jobstart(args, s:job_opts)
let channel_id = jobstart(args, job)
if rpcrequest(channel_id, 'poll') ==# 'ok' if rpcrequest(channel_id, 'poll') ==# 'ok'
return channel_id return channel_id
endif endif
catch catch
echomsg v:throwpoint echomsg v:throwpoint
echomsg v:exception echomsg v:exception
for row in job.stderr for row in provider#get_stderr(channel_id)
echomsg row echomsg row
endfor endfor
finally
call provider#clear_stderr(channel_id)
endtry endtry
throw remote#host#LoadErrorForHost(a:host.orig_name, throw remote#host#LoadErrorForHost(a:host.orig_name,
\ '$NVIM_PYTHON_LOG_FILE') \ '$NVIM_PYTHON_LOG_FILE')

View File

@@ -19,7 +19,7 @@ function! provider#ruby#Detect() abort
if exists("g:ruby_host_prog") if exists("g:ruby_host_prog")
return g:ruby_host_prog return g:ruby_host_prog
else else
return has('win32') ? exepath('neovim-ruby-host.cmd') : exepath('neovim-ruby-host') return has('win32') ? exepath('neovim-ruby-host.bat') : exepath('neovim-ruby-host')
end end
endfunction endfunction

View File

@@ -334,9 +334,11 @@ terminal capabilities. Instead Nvim treats the terminal as any other UI. For
example, 'guicursor' sets the terminal cursor style if possible. example, 'guicursor' sets the terminal cursor style if possible.
*'term'* *E529* *E530* *E531* *'term'* *E529* *E530* *E531*
The 'term' option has a fixed value, present only for script compatibility and 'term' reflects the terminal type derived from |$TERM| and other environment
intentionally not the same as any known terminal type name. It should be a checks. For debugging only; not reliable during startup. >
rare case in Nvim where one needs |term-dependent-settings|. :echo &term
"builtin_x" means one of the |builtin-terms| was chosen, because the expected
terminfo file was not found on the system.
*termcap* *termcap*
Nvim never uses the termcap database, only |terminfo| and |builtin-terms|. Nvim never uses the termcap database, only |terminfo| and |builtin-terms|.

View File

@@ -3199,8 +3199,14 @@ static char_u *get_one_sourceline(struct source_cookie *sp)
ga_grow(&ga, 120); ga_grow(&ga, 120);
buf = (char_u *)ga.ga_data; buf = (char_u *)ga.ga_data;
retry:
errno = 0;
if (fgets((char *)buf + ga.ga_len, ga.ga_maxlen - ga.ga_len, if (fgets((char *)buf + ga.ga_len, ga.ga_maxlen - ga.ga_len,
sp->fp) == NULL) { sp->fp) == NULL) {
if (errno == EINTR) {
goto retry;
}
break; break;
} }
len = ga.ga_len + (int)STRLEN(buf + ga.ga_len); len = ga.ga_len + (int)STRLEN(buf + ga.ga_len);

View File

@@ -4443,22 +4443,32 @@ char *modname(const char *fname, const char *ext, bool prepend_dot)
/// @return true for end-of-file. /// @return true for end-of-file.
bool vim_fgets(char_u *buf, int size, FILE *fp) FUNC_ATTR_NONNULL_ALL bool vim_fgets(char_u *buf, int size, FILE *fp) FUNC_ATTR_NONNULL_ALL
{ {
char *eof; char *retval;
#define FGETS_SIZE 200
char tbuf[FGETS_SIZE];
assert(size > 0);
buf[size - 2] = NUL; buf[size - 2] = NUL;
eof = fgets((char *)buf, size, fp);
if (buf[size - 2] != NUL && buf[size - 2] != '\n') {
buf[size - 1] = NUL; /* Truncate the line */
/* Now throw away the rest of the line: */ do {
errno = 0;
retval = fgets((char *)buf, size, fp);
} while (retval == NULL && errno == EINTR);
if (buf[size - 2] != NUL && buf[size - 2] != '\n') {
char tbuf[200];
buf[size - 1] = NUL; // Truncate the line.
// Now throw away the rest of the line:
do { do {
tbuf[FGETS_SIZE - 2] = NUL; tbuf[sizeof(tbuf) - 2] = NUL;
ignoredp = fgets((char *)tbuf, FGETS_SIZE, fp); errno = 0;
} while (tbuf[FGETS_SIZE - 2] != NUL && tbuf[FGETS_SIZE - 2] != '\n'); retval = fgets((char *)tbuf, sizeof(tbuf), fp);
if (retval == NULL && errno != EINTR) {
break;
}
} while (tbuf[sizeof(tbuf) - 2] != NUL && tbuf[sizeof(tbuf) - 2] != '\n');
} }
return eof == NULL; return retval ? false : feof(fp);
} }
/// Read 2 bytes from "fd" and turn them into an int, MSB first. /// Read 2 bytes from "fd" and turn them into an int, MSB first.

View File

@@ -553,9 +553,15 @@ static int cs_cnt_matches(size_t idx)
char *buf = xmalloc(CSREAD_BUFSIZE); char *buf = xmalloc(CSREAD_BUFSIZE);
for (;; ) { for (;; ) {
errno = 0;
if (!fgets(buf, CSREAD_BUFSIZE, csinfo[idx].fr_fp)) { if (!fgets(buf, CSREAD_BUFSIZE, csinfo[idx].fr_fp)) {
if (feof(csinfo[idx].fr_fp)) if (errno == EINTR) {
continue;
}
if (feof(csinfo[idx].fr_fp)) {
errno = EIO; errno = EIO;
}
cs_reading_emsg(idx); cs_reading_emsg(idx);
@@ -1380,9 +1386,16 @@ static char *cs_parse_results(size_t cnumber, char *buf, int bufsize,
char *p; char *p;
char *name; char *name;
retry:
errno = 0;
if (fgets(buf, bufsize, csinfo[cnumber].fr_fp) == NULL) { if (fgets(buf, bufsize, csinfo[cnumber].fr_fp) == NULL) {
if (feof(csinfo[cnumber].fr_fp)) if (errno == EINTR) {
goto retry;
}
if (feof(csinfo[cnumber].fr_fp)) {
errno = EIO; errno = EIO;
}
cs_reading_emsg(cnumber); cs_reading_emsg(cnumber);

View File

@@ -105,6 +105,9 @@ typedef enum {
*/ */
#define VAR_WIN ((char_u *)-1) #define VAR_WIN ((char_u *)-1)
static char *p_term = NULL;
static char *p_ttytype = NULL;
/* /*
* These are the global values for options which are also local to a buffer. * These are the global values for options which are also local to a buffer.
* Only to be used in option.c! * Only to be used in option.c!
@@ -4530,13 +4533,17 @@ int findoption_len(const char *const arg, const size_t len)
bool is_tty_option(const char *name) bool is_tty_option(const char *name)
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_NONNULL_ALL FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
{ {
return (name[0] == 't' && name[1] == '_') || strcmp(name, "term") == 0; return (name[0] == 't' && name[1] == '_')
|| strequal(name, "term")
|| strequal(name, "ttytype");
} }
#define TCO_BUFFER_SIZE 8 #define TCO_BUFFER_SIZE 8
/// @param name TUI-related option
/// @param[out,allocated] value option string value
bool get_tty_option(char *name, char **value) bool get_tty_option(char *name, char **value)
{ {
if (!strcmp(name, "t_Co")) { if (strequal(name, "t_Co")) {
if (value) { if (value) {
if (t_colors <= 1) { if (t_colors <= 1) {
*value = xstrdup(""); *value = xstrdup("");
@@ -4548,9 +4555,16 @@ bool get_tty_option(char *name, char **value)
return true; return true;
} }
if (!strcmp(name, "term") || !strcmp(name, "ttytype")) { if (strequal(name, "term")) {
if (value) { if (value) {
*value = xstrdup("nvim"); *value = p_term ? xstrdup(p_term) : xstrdup("nvim");
}
return true;
}
if (strequal(name, "ttytype")) {
if (value) {
*value = p_ttytype ? xstrdup(p_ttytype) : xstrdup("nvim");
} }
return true; return true;
} }
@@ -4566,25 +4580,25 @@ bool get_tty_option(char *name, char **value)
return false; return false;
} }
bool set_tty_option(const char *name, const char *value) bool set_tty_option(const char *name, char *value)
{ {
if (!strcmp(name, "t_Co")) { if (strequal(name, "term")) {
int colors = atoi(value); if (p_term) {
xfree(p_term);
// Only reinitialize colors if t_Co value has really changed to
// avoid expensive reload of colorscheme if t_Co is set to the
// same value multiple times
if (colors != t_colors) {
t_colors = colors;
// We now have a different color setup, initialize it again.
init_highlight(true, false);
} }
p_term = value;
return true; return true;
} }
return (is_tty_option(name) || !strcmp(name, "term") if (strequal(name, "ttytype")) {
|| !strcmp(name, "ttytype")); if (p_ttytype) {
xfree(p_ttytype);
}
p_ttytype = value;
return true;
}
return false;
} }
/// Find index for an option /// Find index for an option
@@ -4597,21 +4611,18 @@ static int findoption(const char *const arg)
return findoption_len(arg, strlen(arg)); return findoption_len(arg, strlen(arg));
} }
/* /// Gets the value for an option.
* Get the value for an option. ///
* /// @returns:
* Returns: /// Number or Toggle option: 1, *numval gets value.
* Number or Toggle option: 1, *numval gets value. /// String option: 0, *stringval gets allocated string.
* String option: 0, *stringval gets allocated string. /// Hidden Number or Toggle option: -1.
* Hidden Number or Toggle option: -1. /// hidden String option: -2.
* hidden String option: -2. /// unknown option: -3.
* unknown option: -3. int get_option_value(
*/
int
get_option_value (
char_u *name, char_u *name,
long *numval, long *numval,
char_u **stringval, /* NULL when only checking existence */ char_u **stringval, ///< NULL when only checking existence
int opt_flags int opt_flags
) )
{ {
@@ -4619,32 +4630,31 @@ get_option_value (
return 0; return 0;
} }
int opt_idx; int opt_idx = findoption((const char *)name);
char_u *varp;
opt_idx = findoption((const char *)name);
if (opt_idx < 0) { // Unknown option. if (opt_idx < 0) { // Unknown option.
return -3; return -3;
} }
varp = get_varp_scope(&(options[opt_idx]), opt_flags); char_u *varp = get_varp_scope(&(options[opt_idx]), opt_flags);
if (options[opt_idx].flags & P_STRING) { if (options[opt_idx].flags & P_STRING) {
if (varp == NULL) /* hidden option */ if (varp == NULL) { // hidden option
return -2; return -2;
}
if (stringval != NULL) { if (stringval != NULL) {
*stringval = vim_strsave(*(char_u **)(varp)); *stringval = vim_strsave(*(char_u **)(varp));
} }
return 0; return 0;
} }
if (varp == NULL) /* hidden option */ if (varp == NULL) { // hidden option
return -1; return -1;
if (options[opt_idx].flags & P_NUM) }
if (options[opt_idx].flags & P_NUM) {
*numval = *(long *)varp; *numval = *(long *)varp;
else { } else {
/* Special case: 'modified' is b_changed, but we also want to consider // Special case: 'modified' is b_changed, but we also want to consider
* it set when 'ff' or 'fenc' changed. */ // it set when 'ff' or 'fenc' changed.
if ((int *)varp == &curbuf->b_changed) { if ((int *)varp == &curbuf->b_changed) {
*numval = curbufIsChanged(); *numval = curbufIsChanged();
} else { } else {
@@ -4791,8 +4801,8 @@ char *set_option_value(const char *const name, const long number,
const char *const string, const int opt_flags) const char *const string, const int opt_flags)
FUNC_ATTR_NONNULL_ARG(1) FUNC_ATTR_NONNULL_ARG(1)
{ {
if (set_tty_option(name, string)) { if (is_tty_option(name)) {
return NULL; return NULL; // Fail silently; many old vimrcs set t_xx options.
} }
int opt_idx; int opt_idx;

View File

@@ -4,6 +4,7 @@
#include <ctype.h> #include <ctype.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <sys/param.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>

View File

@@ -570,7 +570,12 @@ static int qf_get_next_file_line(qfstate_T *state)
{ {
size_t growbuflen; size_t growbuflen;
retry:
errno = 0;
if (fgets((char *)IObuff, IOSIZE, state->fd) == NULL) { if (fgets((char *)IObuff, IOSIZE, state->fd) == NULL) {
if (errno == EINTR) {
goto retry;
}
return QF_END_OF_INPUT; return QF_END_OF_INPUT;
} }
@@ -590,8 +595,12 @@ static int qf_get_next_file_line(qfstate_T *state)
growbuflen = state->linelen; growbuflen = state->linelen;
for (;;) { for (;;) {
errno = 0;
if (fgets((char *)state->growbuf + growbuflen, if (fgets((char *)state->growbuf + growbuflen,
(int)(state->growbufsiz - growbuflen), state->fd) == NULL) { (int)(state->growbufsiz - growbuflen), state->fd) == NULL) {
if (errno == EINTR) {
continue;
}
break; break;
} }
state->linelen = STRLEN(state->growbuf + growbuflen); state->linelen = STRLEN(state->growbuf + growbuflen);
@@ -612,9 +621,14 @@ static int qf_get_next_file_line(qfstate_T *state)
while (discard) { while (discard) {
// The current line is longer than LINE_MAXLEN, continue reading but // The current line is longer than LINE_MAXLEN, continue reading but
// discard everything until EOL or EOF is reached. // discard everything until EOL or EOF is reached.
if (fgets((char *)IObuff, IOSIZE, state->fd) == NULL errno = 0;
|| STRLEN(IObuff) < IOSIZE - 1 if (fgets((char *)IObuff, IOSIZE, state->fd) == NULL) {
|| IObuff[IOSIZE - 1] == '\n') { if (errno == EINTR) {
continue;
}
break;
}
if (STRLEN(IObuff) < IOSIZE - 1 || IObuff[IOSIZE - 1] == '\n') {
break; break;
} }
} }

View File

@@ -9,6 +9,7 @@
#include <unibilium.h> #include <unibilium.h>
#include "nvim/log.h" #include "nvim/log.h"
#include "nvim/memory.h"
#include "nvim/tui/terminfo.h" #include "nvim/tui/terminfo.h"
#ifdef INCLUDE_GENERATED_DECLARATIONS #ifdef INCLUDE_GENERATED_DECLARATIONS
@@ -94,51 +95,72 @@ bool terminfo_is_term_family(const char *term, const char *family)
/// Loads a built-in terminfo db when we (unibilium) failed to load a terminfo /// Loads a built-in terminfo db when we (unibilium) failed to load a terminfo
/// record from the environment (termcap systems, unrecognized $TERM, …). /// record from the environment (termcap systems, unrecognized $TERM, …).
/// We do not attempt to detect xterm pretenders here. /// We do not attempt to detect xterm pretenders here.
static unibi_term *terminfo_builtin(const char *term) ///
/// @param term $TERM value
/// @param[out,allocated] termname decided builtin 'term' name
/// @return [allocated] terminfo structure
static unibi_term *terminfo_builtin(const char *term, char **termname)
{ {
if (terminfo_is_term_family(term, "xterm")) { if (terminfo_is_term_family(term, "xterm")) {
*termname = xstrdup("builtin_xterm");
return unibi_from_mem((const char *)xterm_256colour_terminfo, return unibi_from_mem((const char *)xterm_256colour_terminfo,
sizeof xterm_256colour_terminfo); sizeof xterm_256colour_terminfo);
} else if (terminfo_is_term_family(term, "screen")) { } else if (terminfo_is_term_family(term, "screen")) {
*termname = xstrdup("builtin_screen");
return unibi_from_mem((const char *)screen_256colour_terminfo, return unibi_from_mem((const char *)screen_256colour_terminfo,
sizeof screen_256colour_terminfo); sizeof screen_256colour_terminfo);
} else if (terminfo_is_term_family(term, "tmux")) { } else if (terminfo_is_term_family(term, "tmux")) {
*termname = xstrdup("builtin_tmux");
return unibi_from_mem((const char *)tmux_256colour_terminfo, return unibi_from_mem((const char *)tmux_256colour_terminfo,
sizeof tmux_256colour_terminfo); sizeof tmux_256colour_terminfo);
} else if (terminfo_is_term_family(term, "rxvt")) { } else if (terminfo_is_term_family(term, "rxvt")) {
*termname = xstrdup("builtin_rxvt");
return unibi_from_mem((const char *)rxvt_256colour_terminfo, return unibi_from_mem((const char *)rxvt_256colour_terminfo,
sizeof rxvt_256colour_terminfo); sizeof rxvt_256colour_terminfo);
} else if (terminfo_is_term_family(term, "putty")) { } else if (terminfo_is_term_family(term, "putty")) {
*termname = xstrdup("builtin_putty");
return unibi_from_mem((const char *)putty_256colour_terminfo, return unibi_from_mem((const char *)putty_256colour_terminfo,
sizeof putty_256colour_terminfo); sizeof putty_256colour_terminfo);
} else if (terminfo_is_term_family(term, "linux")) { } else if (terminfo_is_term_family(term, "linux")) {
*termname = xstrdup("builtin_linux");
return unibi_from_mem((const char *)linux_16colour_terminfo, return unibi_from_mem((const char *)linux_16colour_terminfo,
sizeof linux_16colour_terminfo); sizeof linux_16colour_terminfo);
} else if (terminfo_is_term_family(term, "interix")) { } else if (terminfo_is_term_family(term, "interix")) {
*termname = xstrdup("builtin_interix");
return unibi_from_mem((const char *)interix_8colour_terminfo, return unibi_from_mem((const char *)interix_8colour_terminfo,
sizeof interix_8colour_terminfo); sizeof interix_8colour_terminfo);
} else if (terminfo_is_term_family(term, "iterm") } else if (terminfo_is_term_family(term, "iterm")
|| terminfo_is_term_family(term, "iterm2") || terminfo_is_term_family(term, "iterm2")
|| terminfo_is_term_family(term, "iTerm.app") || terminfo_is_term_family(term, "iTerm.app")
|| terminfo_is_term_family(term, "iTerm2.app")) { || terminfo_is_term_family(term, "iTerm2.app")) {
*termname = xstrdup("builtin_iterm");
return unibi_from_mem((const char *)iterm_256colour_terminfo, return unibi_from_mem((const char *)iterm_256colour_terminfo,
sizeof iterm_256colour_terminfo); sizeof iterm_256colour_terminfo);
} else if (terminfo_is_term_family(term, "st")) { } else if (terminfo_is_term_family(term, "st")) {
*termname = xstrdup("builtin_st");
return unibi_from_mem((const char *)st_256colour_terminfo, return unibi_from_mem((const char *)st_256colour_terminfo,
sizeof st_256colour_terminfo); sizeof st_256colour_terminfo);
} else if (terminfo_is_term_family(term, "gnome") } else if (terminfo_is_term_family(term, "gnome")
|| terminfo_is_term_family(term, "vte")) { || terminfo_is_term_family(term, "vte")) {
*termname = xstrdup("builtin_vte");
return unibi_from_mem((const char *)vte_256colour_terminfo, return unibi_from_mem((const char *)vte_256colour_terminfo,
sizeof vte_256colour_terminfo); sizeof vte_256colour_terminfo);
} else { } else {
*termname = xstrdup("builtin_ansi");
return unibi_from_mem((const char *)ansi_terminfo, return unibi_from_mem((const char *)ansi_terminfo,
sizeof ansi_terminfo); sizeof ansi_terminfo);
} }
} }
unibi_term *terminfo_from_builtin(const char *term) /// @param term $TERM value
/// @param[out,allocated] termname decided builtin 'term' name
/// @return [allocated] terminfo structure
unibi_term *terminfo_from_builtin(const char *term, char **termname)
{ {
unibi_term *ut = terminfo_builtin(term); unibi_term *ut = terminfo_builtin(term, termname);
if (*termname == NULL) {
*termname = xstrdup("builtin_?");
}
// Disable BCE by default (for built-in terminfos). #7624 // Disable BCE by default (for built-in terminfos). #7624
// https://github.com/kovidgoyal/kitty/issues/160#issuecomment-346470545 // https://github.com/kovidgoyal/kitty/issues/160#issuecomment-346470545
unibi_set_bool(ut, unibi_back_color_erase, false); unibi_set_bool(ut, unibi_back_color_erase, false);

View File

@@ -23,6 +23,7 @@
#include "nvim/map.h" #include "nvim/map.h"
#include "nvim/main.h" #include "nvim/main.h"
#include "nvim/memory.h" #include "nvim/memory.h"
#include "nvim/option.h"
#include "nvim/api/vim.h" #include "nvim/api/vim.h"
#include "nvim/api/private/helpers.h" #include "nvim/api/private/helpers.h"
#include "nvim/event/loop.h" #include "nvim/event/loop.h"
@@ -166,6 +167,13 @@ static size_t unibi_pre_fmt_str(TUIData *data, unsigned int unibi_index,
return unibi_run(str, data->params, buf, len); return unibi_run(str, data->params, buf, len);
} }
static void termname_set_event(void **argv)
{
char *termname = argv[0];
set_tty_option("term", termname);
// Do not free termname, it is freed by set_tty_option.
}
static void terminfo_start(UI *ui) static void terminfo_start(UI *ui)
{ {
TUIData *data = ui->data; TUIData *data = ui->data;
@@ -190,12 +198,20 @@ static void terminfo_start(UI *ui)
data->unibi_ext.reset_cursor_style = -1; data->unibi_ext.reset_cursor_style = -1;
data->out_fd = 1; data->out_fd = 1;
data->out_isatty = os_isatty(data->out_fd); data->out_isatty = os_isatty(data->out_fd);
// setup unibilium
// Set up unibilium/terminfo.
const char *term = os_getenv("TERM"); const char *term = os_getenv("TERM");
data->ut = unibi_from_env(); data->ut = unibi_from_env();
char *termname = NULL;
if (!data->ut) { if (!data->ut) {
data->ut = terminfo_from_builtin(term); data->ut = terminfo_from_builtin(term, &termname);
} else {
termname = xstrdup(term);
} }
// Update 'term' option.
loop_schedule_deferred(&main_loop,
event_create(termname_set_event, 1, termname));
// None of the following work over SSH; see :help TERM . // None of the following work over SSH; see :help TERM .
const char *colorterm = os_getenv("COLORTERM"); const char *colorterm = os_getenv("COLORTERM");
const char *termprg = os_getenv("TERM_PROGRAM"); const char *termprg = os_getenv("TERM_PROGRAM");
@@ -344,7 +360,7 @@ static void tui_scheduler(Event event, void *d)
{ {
UI *ui = d; UI *ui = d;
TUIData *data = ui->data; TUIData *data = ui->data;
loop_schedule(data->loop, event); loop_schedule(data->loop, event); // `tui_loop` local to tui_main().
} }
#ifdef UNIX #ifdef UNIX
@@ -940,10 +956,9 @@ static void tui_scroll(UI *ui, Integer count)
} }
cursor_goto(ui, saved_row, saved_col); cursor_goto(ui, saved_row, saved_col);
if (!scroll_clears_to_current_colour && grid->bg != -1) { if (!scroll_clears_to_current_colour) {
// Scrolling may leave wrong background in the cleared area on non-bge // Scrolling will leave wrong background in the cleared area on non-BCE
// terminals. Update the cleared area of the terminal if its builtin // terminals. Update the cleared area.
// scrolling facility was used and bg color is not the default.
clear_region(ui, clear_top, clear_bot, grid->left, grid->right); clear_region(ui, clear_top, clear_bot, grid->left, grid->right);
} }
} else { } else {

View File

@@ -78,8 +78,157 @@ NULL
// clang-format off // clang-format off
static const int included_patches[] = { static const int included_patches[] = {
1357,
// 1356,
// 1355,
// 1354,
// 1353,
// 1352,
// 1351,
// 1350,
// 1349,
// 1348,
// 1347,
// 1346,
// 1345,
// 1344,
// 1343,
// 1342,
// 1341,
// 1340,
// 1339,
// 1338,
// 1337,
// 1336,
// 1335,
// 1334,
// 1333,
// 1332,
// 1331,
// 1330,
// 1329,
// 1328,
// 1327,
// 1326,
// 1325,
// 1324,
// 1323,
// 1322,
// 1321,
// 1320,
// 1319,
// 1318,
// 1317,
// 1316,
// 1315,
// 1314,
// 1313,
// 1312,
// 1311,
// 1310,
// 1309,
// 1308,
// 1307,
// 1306,
// 1305,
// 1304,
// 1303,
// 1302,
// 1301,
// 1300,
// 1299,
// 1298,
// 1297,
// 1296,
// 1295,
// 1294,
// 1293,
// 1292,
// 1291,
// 1290,
// 1289,
// 1288,
// 1287,
// 1286,
// 1285,
// 1284,
// 1283,
// 1282,
// 1281,
// 1280,
// 1279,
// 1278,
// 1277,
// 1276,
// 1275,
// 1274,
// 1273,
// 1272,
// 1271,
// 1270,
// 1269,
// 1268,
// 1267,
// 1266,
// 1265,
// 1264,
// 1263,
// 1262,
// 1261,
// 1260,
// 1259,
// 1258,
// 1257,
// 1256,
// 1255,
// 1254,
// 1253,
// 1252,
// 1251,
// 1250,
// 1249,
// 1248,
// 1247,
// 1246,
// 1245,
// 1244,
// 1243,
// 1242,
// 1241,
// 1240,
// 1239,
// 1238,
// 1237,
// 1236,
// 1235,
// 1234,
// 1233,
// 1232,
// 1231,
1230, 1230,
1229, 1229,
// 1228,
// 1227,
// 1226,
// 1225,
// 1224,
// 1223,
// 1222,
// 1221,
// 1220,
// 1219,
// 1218,
// 1217,
// 1216,
// 1215,
// 1214,
// 1213,
// 1212,
// 1211,
// 1210,
// 1209,
// 1208,
// 1207,
1206, 1206,
// 1026, // 1026,
1025, 1025,
@@ -805,7 +954,7 @@ static const int included_patches[] = {
305, 305,
// 304, // 304,
// 303, // 303,
// 302, NA // 302 NA
// 301, // 301,
300, 300,
// 299, // 299,
@@ -927,7 +1076,7 @@ static const int included_patches[] = {
// 183 NA // 183 NA
182, 182,
181, 181,
// 180, // 180 NA
179, 179,
178, 178,
177, 177,
@@ -937,11 +1086,11 @@ static const int included_patches[] = {
// 173 NA // 173 NA
172, 172,
// 171, // 171,
// 170, // 170 NA
// 169, // 169 NA
168, 168,
167, 167,
// 166, // 166 NA
165, 165,
164, 164,
// 163 NA // 163 NA
@@ -966,7 +1115,7 @@ static const int included_patches[] = {
// 144 NA // 144 NA
143, 143,
142, 142,
// 141, // 141 NA
140, 140,
// 139 NA // 139 NA
// 138 NA // 138 NA
@@ -1011,7 +1160,7 @@ static const int included_patches[] = {
99, 99,
// 98 NA // 98 NA
// 97 NA // 97 NA
// 96, 96,
// 95 NA // 95 NA
// 94 NA // 94 NA
// 93 NA // 93 NA
@@ -1086,10 +1235,10 @@ static const int included_patches[] = {
// 24 NA // 24 NA
23, 23,
// 22 NA // 22 NA
// 21, // 21 NA
20, 20,
19, 19,
// 18, // 18 NA
17, 17,
// 16 NA // 16 NA
// 15 NA // 15 NA

View File

@@ -307,7 +307,8 @@ enum { FOLD_TEXT_LEN = 51 }; //!< buffer size for get_foldtext()
// Lowest number used for window ID. Cannot have this many windows per tab. // Lowest number used for window ID. Cannot have this many windows per tab.
#define LOWEST_WIN_ID 1000 #define LOWEST_WIN_ID 1000
#if (defined(__FreeBSD__) || defined(__FreeBSD_kernel__)) && defined(S_ISCHR) // BSD is supposed to cover FreeBSD and similar systems.
#if (defined(BSD) || defined(__FreeBSD_kernel__)) && defined(S_ISCHR)
# define OPEN_CHR_FILES # define OPEN_CHR_FILES
#endif #endif

View File

@@ -27,7 +27,7 @@ describe('channels', function()
source(init) source(init)
end) end)
it('can connect to socket', function() pending('can connect to socket', function()
local server = spawn(nvim_argv) local server = spawn(nvim_argv)
set_session(server) set_session(server)
local address = funcs.serverlist()[1] local address = funcs.serverlist()[1]

View File

@@ -603,6 +603,15 @@ local function get_pathsep()
return funcs.fnamemodify('.', ':p'):sub(-1) return funcs.fnamemodify('.', ':p'):sub(-1)
end end
-- Returns a valid, platform-independent $NVIM_LISTEN_ADDRESS.
-- Useful for communicating with child instances.
local function new_pipename()
-- HACK: Start a server temporarily, get the name, then stop it.
local pipename = nvim_eval('serverstart()')
funcs.serverstop(pipename)
return pipename
end
local function missing_provider(provider) local function missing_provider(provider)
if provider == 'ruby' then if provider == 'ruby' then
local prog = funcs['provider#' .. provider .. '#Detect']() local prog = funcs['provider#' .. provider .. '#Detect']()
@@ -732,6 +741,7 @@ local module = {
missing_provider = missing_provider, missing_provider = missing_provider,
alter_slashes = alter_slashes, alter_slashes = alter_slashes,
hexdump = hexdump, hexdump = hexdump,
new_pipename = new_pipename,
} }
return function(after_each) return function(after_each)

View File

@@ -1,12 +1,16 @@
-- TUI acceptance tests. -- TUI acceptance tests.
-- Uses :terminal as a way to send keys and assert screen state. -- Uses :terminal as a way to send keys and assert screen state.
local global_helpers = require('test.helpers') local global_helpers = require('test.helpers')
local uname = global_helpers.uname
local helpers = require('test.functional.helpers')(after_each) local helpers = require('test.functional.helpers')(after_each)
local thelpers = require('test.functional.terminal.helpers') local thelpers = require('test.functional.terminal.helpers')
local feed_data = thelpers.feed_data local feed_data = thelpers.feed_data
local feed_command = helpers.feed_command local feed_command = helpers.feed_command
local clear = helpers.clear
local nvim_dir = helpers.nvim_dir local nvim_dir = helpers.nvim_dir
local retry = helpers.retry local retry = helpers.retry
local nvim_prog = helpers.nvim_prog
local nvim_set = helpers.nvim_set
if helpers.pending_win32(pending) then return end if helpers.pending_win32(pending) then return end
@@ -14,9 +18,9 @@ describe('tui', function()
local screen local screen
before_each(function() before_each(function()
helpers.clear() clear()
screen = thelpers.screen_setup(0, '["'..helpers.nvim_prog screen = thelpers.screen_setup(0, '["'..nvim_prog
..'", "-u", "NONE", "-i", "NONE", "--cmd", "set noswapfile noshowcmd noruler"]') ..'", "-u", "NONE", "-i", "NONE", "--cmd", "set noswapfile noshowcmd noruler undodir=. directory=. viewdir=. backupdir=."]')
-- right now pasting can be really slow in the TUI, especially in ASAN. -- right now pasting can be really slow in the TUI, especially in ASAN.
-- this will be fixed later but for now we require a high timeout. -- this will be fixed later but for now we require a high timeout.
screen.timeout = 60000 screen.timeout = 60000
@@ -372,19 +376,20 @@ end)
-- does not initialize the TUI. -- does not initialize the TUI.
describe("tui 't_Co' (terminal colors)", function() describe("tui 't_Co' (terminal colors)", function()
local screen local screen
local is_freebsd = (string.lower(global_helpers.uname()) == 'freebsd') local is_freebsd = (string.lower(uname()) == 'freebsd')
local function assert_term_colors(term, colorterm, maxcolors) local function assert_term_colors(term, colorterm, maxcolors)
helpers.clear({env={TERM=term}, args={}}) helpers.clear({env={TERM=term}, args={}})
-- This is ugly because :term/termopen() forces TERM=xterm-256color. -- This is ugly because :term/termopen() forces TERM=xterm-256color.
-- TODO: Revisit this after jobstart/termopen accept `env` dict. -- TODO: Revisit this after jobstart/termopen accept `env` dict.
screen = thelpers.screen_setup(0, string.format( screen = thelpers.screen_setup(0, string.format(
[=[['sh', '-c', 'LANG=C TERM=%s %s %s -u NONE -i NONE --cmd "silent set noswapfile noshowcmd noruler"']]=], [=[['sh', '-c', 'LANG=C TERM=%s %s %s -u NONE -i NONE --cmd "%s"']]=],
term or "", term or "",
(colorterm ~= nil and "COLORTERM="..colorterm or ""), (colorterm ~= nil and "COLORTERM="..colorterm or ""),
helpers.nvim_prog)) nvim_prog,
nvim_set))
thelpers.feed_data(":echo &t_Co\n") feed_data(":echo &t_Co\n")
helpers.wait() helpers.wait()
local tline local tline
if maxcolors == 8 or maxcolors == 16 then if maxcolors == 8 or maxcolors == 16 then
@@ -397,10 +402,10 @@ describe("tui 't_Co' (terminal colors)", function()
%s| %s|
%s| %s|
%s| %s|
{5:[No Name] }| %s|
%-3s | %-3s |
{3:-- TERMINAL --} | {3:-- TERMINAL --} |
]], tline, tline, tline, tostring(maxcolors and maxcolors or ""))) ]], tline, tline, tline, tline, tostring(maxcolors and maxcolors or "")))
end end
-- ansi and no terminal type at all: -- ansi and no terminal type at all:
@@ -628,3 +633,42 @@ describe("tui 't_Co' (terminal colors)", function()
end) end)
end) end)
-- These tests require `thelpers` because --headless/--embed
-- does not initialize the TUI.
describe("tui 'term' option", function()
local screen
local is_bsd = not not string.find(string.lower(uname()), 'bsd')
local function assert_term(term_envvar, term_expected)
clear()
-- This is ugly because :term/termopen() forces TERM=xterm-256color.
-- TODO: Revisit this after jobstart/termopen accept `env` dict.
local cmd = string.format(
[=[['sh', '-c', 'LANG=C TERM=%s %s -u NONE -i NONE --cmd "%s"']]=],
term_envvar or "",
nvim_prog,
nvim_set)
screen = thelpers.screen_setup(0, cmd)
local full_timeout = screen.timeout
screen.timeout = 250 -- We want screen:expect() to fail quickly.
retry(nil, 2 * full_timeout, function() -- Wait for TUI thread to set 'term'.
feed_data(":echo 'term='.(&term)\n")
screen:expect('term='..term_expected, nil, nil, nil, true)
end)
end
it('gets builtin term if $TERM is invalid', function()
assert_term("foo", "builtin_ansi")
end)
it('gets system-provided term if $TERM is valid', function()
if is_bsd then -- BSD lacks terminfo, we always use builtin there.
assert_term("xterm", "builtin_xterm")
else
assert_term("xterm", "xterm")
end
end)
end)

View File

@@ -4,7 +4,7 @@ local os = require('os')
local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert local clear, feed, insert = helpers.clear, helpers.feed, helpers.insert
local command = helpers.command local command = helpers.command
local eval, exc_exec = helpers.eval, helpers.exc_exec local eval, exc_exec = helpers.eval, helpers.exc_exec
local feed_command, request, eq = helpers.feed_command, helpers.request, helpers.eq local feed_command, eq = helpers.feed_command, helpers.eq
local curbufmeths = helpers.curbufmeths local curbufmeths = helpers.curbufmeths
describe('colorscheme compatibility', function() describe('colorscheme compatibility', function()
@@ -14,8 +14,6 @@ describe('colorscheme compatibility', function()
it('t_Co is set to 256 by default', function() it('t_Co is set to 256 by default', function()
eq('256', eval('&t_Co')) eq('256', eval('&t_Co'))
request('nvim_set_option', 't_Co', '88')
eq('88', eval('&t_Co'))
end) end)
end) end)

View File

@@ -138,6 +138,7 @@ local function filter_complex_blocks(body)
for line in body:gmatch("[^\r\n]+") do for line in body:gmatch("[^\r\n]+") do
if not (string.find(line, "(^)", 1, true) ~= nil if not (string.find(line, "(^)", 1, true) ~= nil
or string.find(line, "_ISwupper", 1, true) or string.find(line, "_ISwupper", 1, true)
or string.find(line, "_Float128")
or string.find(line, "msgpack_zone_push_finalizer") or string.find(line, "msgpack_zone_push_finalizer")
or string.find(line, "msgpack_unpacker_reserve_buffer") or string.find(line, "msgpack_unpacker_reserve_buffer")
or string.find(line, "UUID_NULL") -- static const uuid_t UUID_NULL = {...} or string.find(line, "UUID_NULL") -- static const uuid_t UUID_NULL = {...}