diff options
-rwxr-xr-x | .ci/after_success.sh | 6 | ||||
-rw-r--r-- | .ci/common/test.sh | 10 | ||||
-rw-r--r-- | .travis.yml | 3 | ||||
-rw-r--r-- | CMakeLists.txt | 3 | ||||
-rw-r--r-- | cmake/RunTests.cmake | 2 | ||||
-rw-r--r-- | runtime/autoload/provider/clipboard.vim | 7 | ||||
-rw-r--r-- | runtime/doc/nvim_terminal_emulator.txt | 22 | ||||
-rw-r--r-- | scripts/genvimvim.lua | 2 | ||||
-rw-r--r-- | src/nvim/event/process.c | 25 | ||||
-rw-r--r-- | src/nvim/map.c | 5 | ||||
-rw-r--r-- | src/nvim/msgpack_rpc/server.c | 4 | ||||
-rw-r--r-- | src/nvim/ops.c | 2 | ||||
-rw-r--r-- | src/nvim/po/ja.po | 2 | ||||
-rw-r--r-- | src/nvim/terminal.c | 19 | ||||
-rw-r--r-- | src/nvim/version.c | 2 | ||||
-rw-r--r-- | src/nvim/window.c | 5 | ||||
-rw-r--r-- | test/functional/clipboard/clipboard_provider_spec.lua | 2 | ||||
-rw-r--r-- | test/functional/core/job_spec.lua (renamed from test/functional/job/job_spec.lua) | 49 | ||||
-rw-r--r-- | test/functional/fixtures/autoload/provider/clipboard.vim | 5 | ||||
-rw-r--r-- | test/functional/ui/output_spec.lua | 39 |
20 files changed, 169 insertions, 45 deletions
diff --git a/.ci/after_success.sh b/.ci/after_success.sh index 580b988061..0215eb139b 100755 --- a/.ci/after_success.sh +++ b/.ci/after_success.sh @@ -3,8 +3,6 @@ set -e set -o pipefail -if [[ -n "${CI_TARGET}" ]]; then - exit +if [[ -n "${GCOV}" ]]; then + coveralls --gcov "$(which "${GCOV}")" --encoding iso-8859-1 || echo 'coveralls upload failed.' fi - -[ "$USE_GCOV" = on ] && { coveralls --gcov "$(which "${GCOV}")" --encoding iso-8859-1 || echo 'coveralls upload failed.' ; } diff --git a/.ci/common/test.sh b/.ci/common/test.sh index 225d88e072..1e66ecb239 100644 --- a/.ci/common/test.sh +++ b/.ci/common/test.sh @@ -83,8 +83,9 @@ install_nvim() { exit 1 } + local genvimsynf=syntax/vim/generated.vim # Check that all runtime files were installed - for file in doc/tags syntax/vim/generated.vim $( + for file in doc/tags $genvimsynf $( cd runtime ; git ls-files | grep -e '.vim$' -e '.ps$' -e '.dict$' -e '.py$' -e '.tutor$' ) ; do if ! test -e "${INSTALL_PREFIX}/share/nvim/runtime/$file" ; then @@ -93,6 +94,13 @@ install_nvim() { fi done + # Check that generated syntax file has function names, #5060. + local gpat='syn keyword vimFuncName .*eval' + if ! grep -q "$gpat" "${INSTALL_PREFIX}/share/nvim/runtime/$genvimsynf"; then + echo "It appears that $genvimsynf does not contain $gpat." + exit 1 + fi + for file in $( cd runtime ; git ls-files | grep -e '.awk$' -e '.sh$' -e '.bat$' ) ; do diff --git a/.travis.yml b/.travis.yml index 8334b03cdf..9d529c2632 100644 --- a/.travis.yml +++ b/.travis.yml @@ -61,6 +61,7 @@ matrix: env: CI_TARGET=lint - os: linux compiler: gcc-5 + env: GCOV=gcov-5 CMAKE_FLAGS="$CMAKE_FLAGS -DUSE_GCOV=ON" - os: linux compiler: gcc-5 env: FUNCTIONALTEST=functionaltest-lua @@ -72,7 +73,7 @@ matrix: env: BUILD_32BIT=ON - os: linux compiler: clang - env: GCOV=llvm-cov CLANG_SANITIZER=ASAN_UBSAN CMAKE_FLAGS="$CMAKE_FLAGS -DUSE_GCOV=ON" + env: CLANG_SANITIZER=ASAN_UBSAN - os: linux compiler: clang env: CLANG_SANITIZER=TSAN diff --git a/CMakeLists.txt b/CMakeLists.txt index 0b3e6ec85e..1787f4e306 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -501,6 +501,7 @@ if(BUSTED_PRG) add_custom_target(functionaltest COMMAND ${CMAKE_COMMAND} -DBUSTED_PRG=${BUSTED_PRG} + -DLUA_PRG=${LUA_PRG} -DNVIM_PRG=$<TARGET_FILE:nvim> -DWORKING_DIR=${CMAKE_CURRENT_SOURCE_DIR} -DBUSTED_OUTPUT_TYPE=${BUSTED_OUTPUT_TYPE} @@ -514,6 +515,7 @@ if(BUSTED_PRG) add_custom_target(benchmark COMMAND ${CMAKE_COMMAND} -DBUSTED_PRG=${BUSTED_PRG} + -DLUA_PRG=${LUA_PRG} -DNVIM_PRG=$<TARGET_FILE:nvim> -DWORKING_DIR=${CMAKE_CURRENT_SOURCE_DIR} -DBUSTED_OUTPUT_TYPE=${BUSTED_OUTPUT_TYPE} @@ -529,6 +531,7 @@ if(BUSTED_LUA_PRG) add_custom_target(functionaltest-lua COMMAND ${CMAKE_COMMAND} -DBUSTED_PRG=${BUSTED_LUA_PRG} + -DLUA_PRG=${LUA_PRG} -DNVIM_PRG=$<TARGET_FILE:nvim> -DWORKING_DIR=${CMAKE_CURRENT_SOURCE_DIR} -DBUSTED_OUTPUT_TYPE=${BUSTED_OUTPUT_TYPE} diff --git a/cmake/RunTests.cmake b/cmake/RunTests.cmake index 0858ea24ac..9fa91ffb5d 100644 --- a/cmake/RunTests.cmake +++ b/cmake/RunTests.cmake @@ -27,7 +27,7 @@ endif() execute_process( COMMAND ${BUSTED_PRG} ${TEST_TAG} ${TEST_FILTER} -v -o ${BUSTED_OUTPUT_TYPE} - --lazy --helper=${TEST_DIR}/${TEST_TYPE}/preload.lua + --lua=${LUA_PRG} --lazy --helper=${TEST_DIR}/${TEST_TYPE}/preload.lua --lpath=${BUILD_DIR}/?.lua ${TEST_PATH} WORKING_DIRECTORY ${WORKING_DIR} ERROR_VARIABLE err diff --git a/runtime/autoload/provider/clipboard.vim b/runtime/autoload/provider/clipboard.vim index 77bc8c781d..0f4aa78ddd 100644 --- a/runtime/autoload/provider/clipboard.vim +++ b/runtime/autoload/provider/clipboard.vim @@ -65,11 +65,10 @@ endif let s:clipboard = {} function! s:clipboard.get(reg) - let reg = a:reg == '"' ? '+' : a:reg - if s:selections[reg].owner > 0 - return s:selections[reg].data + if s:selections[a:reg].owner > 0 + return s:selections[a:reg].data end - return s:try_cmd(s:paste[reg]) + return s:try_cmd(s:paste[a:reg]) endfunction function! s:clipboard.set(lines, regtype, reg) diff --git a/runtime/doc/nvim_terminal_emulator.txt b/runtime/doc/nvim_terminal_emulator.txt index 4296ef6490..8f7dc0dbf0 100644 --- a/runtime/doc/nvim_terminal_emulator.txt +++ b/runtime/doc/nvim_terminal_emulator.txt @@ -10,6 +10,7 @@ Embedded terminal emulator *terminal-emulator* 2. Spawning |terminal-emulator-spawning| 3. Input |terminal-emulator-input| 4. Configuration |terminal-emulator-configuration| +5. Status Variables |terminal-emulator-status| ============================================================================== 1. Introduction *terminal-emulator-intro* @@ -113,4 +114,25 @@ The terminal cursor can be highlighted via |hl-TermCursor| and |hl-TermCursorNC|. ============================================================================== +5. Status Variables *terminal-emulator-status* + +Terminal buffers maintain some information about the terminal in buffer-local +variables: + +- *b:term_title* The settable title of the terminal, typically displayed in + the window title or tab title of a graphical terminal emulator. Programs + running in the terminal can set this title via an escape sequence. +- *b:terminal_job_id* The nvim job ID of the job running in the terminal. See + |job-control| for more information. +- *b:terminal_job_pid* The PID of the top-level process running in the + terminal. + +These variables will have a value by the time the TermOpen autocmd runs, and +will continue to have a value for the lifetime of the terminal buffer, making +them suitable for use in 'statusline'. For example, to show the terminal title +as the status line: +> + :autocmd TermOpen * setlocal statusline=%{b:term_title} +< +============================================================================== vim:tw=78:ts=8:noet:ft=help:norl: diff --git a/scripts/genvimvim.lua b/scripts/genvimvim.lua index 9135c8e3ab..2a82181841 100644 --- a/scripts/genvimvim.lua +++ b/scripts/genvimvim.lua @@ -123,7 +123,7 @@ for line in eval_fd:lines() do if line == '};' then break end - local func_name = line:match('^ {"(%w+)",') + local func_name = line:match('^ { "([%w_]+)",') if func_name then if lld.line_length > 850 then w('\n' .. vimfun_start) diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c index 1c4c9737c3..317e40e43a 100644 --- a/src/nvim/event/process.c +++ b/src/nvim/event/process.c @@ -116,23 +116,20 @@ void process_teardown(Loop *loop) FUNC_ATTR_NONNULL_ALL process_is_tearing_down = true; kl_iter(WatcherPtr, loop->children, current) { Process *proc = (*current)->data; - if (proc->detach) { + if (proc->detach || proc->type == kProcessTypePty) { // Close handles to process without killing it. CREATE_EVENT(loop->events, process_close_handles, 1, proc); } else { - if (proc->type == kProcessTypeUv) { - uv_kill(proc->pid, SIGTERM); - proc->term_sent = true; - process_stop(proc); - } else { // kProcessTypePty - process_close_streams(proc); - pty_process_close_master((PtyProcess *)proc); - } + uv_kill(proc->pid, SIGTERM); + proc->term_sent = true; + process_stop(proc); } } - // Wait until all children exit - LOOP_PROCESS_EVENTS_UNTIL(loop, loop->events, -1, kl_empty(loop->children)); + // Wait until all children exit and all close events are processed. + LOOP_PROCESS_EVENTS_UNTIL( + loop, loop->events, -1, + kl_empty(loop->children) && queue_empty(loop->events)); pty_process_teardown(loop); } @@ -315,8 +312,10 @@ static void decref(Process *proc) static void process_close(Process *proc) FUNC_ATTR_NONNULL_ARG(1) { - if (process_is_tearing_down && proc->detach && proc->closed) { - // If a detached process dies while tearing down it might get closed twice. + if (process_is_tearing_down && (proc->detach || proc->type == kProcessTypePty) + && proc->closed) { + // If a detached/pty process dies while tearing down it might get closed + // twice. return; } assert(!proc->closed); diff --git a/src/nvim/map.c b/src/nvim/map.c index 03439e7a9c..398e74268f 100644 --- a/src/nvim/map.c +++ b/src/nvim/map.c @@ -129,7 +129,10 @@ static inline khint_t String_hash(String s) static inline bool String_eq(String a, String b) { - return strncmp(a.data, b.data, MIN(a.size, b.size)) == 0; + if (a.size != b.size) { + return false; + } + return memcmp(a.data, b.data, a.size) == 0; } diff --git a/src/nvim/msgpack_rpc/server.c b/src/nvim/msgpack_rpc/server.c index abbd3e8aff..d7c2926a0f 100644 --- a/src/nvim/msgpack_rpc/server.c +++ b/src/nvim/msgpack_rpc/server.c @@ -40,6 +40,10 @@ bool server_init(void) listen_address = server_address_new(); } + if (!listen_address) { + return false; + } + bool ok = (server_start(listen_address) == 0); if (must_free) { xfree((char *) listen_address); diff --git a/src/nvim/ops.c b/src/nvim/ops.c index a498fc481a..25b3b85497 100644 --- a/src/nvim/ops.c +++ b/src/nvim/ops.c @@ -5452,7 +5452,7 @@ static yankreg_T *adjust_clipboard_name(int *name, bool quiet, bool writing) yankreg_T *target; if (cb_flags & CB_UNNAMEDPLUS) { - *name = cb_flags & CB_UNNAMED ? '"': '+'; + *name = (cb_flags & CB_UNNAMED && writing) ? '"': '+'; target = &y_regs[PLUS_REGISTER]; } else { *name = '*'; diff --git a/src/nvim/po/ja.po b/src/nvim/po/ja.po index 8a3fcb8f78..0326f33bb5 100644 --- a/src/nvim/po/ja.po +++ b/src/nvim/po/ja.po @@ -5653,7 +5653,7 @@ msgstr "単語 '%.*s' が %s から削除されました" #: ../spell.c:8117 #, c-format msgid "Word '%.*s' added to %s" -msgstr "%s に単語が追加されました" +msgstr "単語 '%.*s' が %s へ追加されました" #: ../spell.c:8381 msgid "E763: Word characters differ between spell files" diff --git a/src/nvim/terminal.c b/src/nvim/terminal.c index fd416b3dcc..6f50c03be9 100644 --- a/src/nvim/terminal.c +++ b/src/nvim/terminal.c @@ -241,6 +241,7 @@ Terminal *terminal_open(TerminalOptions opts) set_option_value((uint8_t *)"wrap", false, NULL, OPT_LOCAL); set_option_value((uint8_t *)"number", false, NULL, OPT_LOCAL); set_option_value((uint8_t *)"relativenumber", false, NULL, OPT_LOCAL); + buf_set_term_title(curbuf, (char *)curbuf->b_ffname); RESET_BINDING(curwin); // Apply TermOpen autocmds so the user can configure the terminal apply_autocmds(EVENT_TERMOPEN, NULL, NULL, false, curbuf); @@ -618,6 +619,17 @@ static int term_movecursor(VTermPos new, VTermPos old, int visible, return 1; } +static void buf_set_term_title(buf_T *buf, char *title) + FUNC_ATTR_NONNULL_ALL +{ + Error err; + api_free_object(dict_set_value(buf->b_vars, + cstr_as_string("term_title"), + STRING_OBJ(cstr_as_string(title)), + false, + &err)); +} + static int term_settermprop(VTermProp prop, VTermValue *val, void *data) { Terminal *term = data; @@ -633,12 +645,7 @@ static int term_settermprop(VTermProp prop, VTermValue *val, void *data) case VTERM_PROP_TITLE: { buf_T *buf = handle_get_buffer(term->buf_handle); - Error err; - api_free_object(dict_set_value(buf->b_vars, - cstr_as_string("term_title"), - STRING_OBJ(cstr_as_string(val->string)), - false, - &err)); + buf_set_term_title(buf, val->string); break; } diff --git a/src/nvim/version.c b/src/nvim/version.c index 5fdbb7db57..70c6af2a12 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -513,7 +513,7 @@ static int included_patches[] = { // 1189 NA // 1188 NA // 1187 NA - // 1186, + // 1186 NA // 1185 NA // 1184 NA // 1183 NA diff --git a/src/nvim/window.c b/src/nvim/window.c index 1298248f1e..e267d493bf 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -3296,8 +3296,11 @@ void tabpage_move(int nr) tabpage_T *tp; tabpage_T *tp_dst; - if (first_tabpage->tp_next == NULL) + assert(curtab != NULL); + + if (first_tabpage->tp_next == NULL) { return; + } for (tp = first_tabpage; tp->tp_next != NULL && n < nr; tp = tp->tp_next) { ++n; diff --git a/test/functional/clipboard/clipboard_provider_spec.lua b/test/functional/clipboard/clipboard_provider_spec.lua index b4febe4bfb..15977b9777 100644 --- a/test/functional/clipboard/clipboard_provider_spec.lua +++ b/test/functional/clipboard/clipboard_provider_spec.lua @@ -308,6 +308,7 @@ describe('clipboard usage', function() end) it('links the "+ and unnamed registers', function() + eq('+', eval('v:register')) insert("one two") feed('^"+dwdw"+P') expect('two') @@ -335,6 +336,7 @@ describe('clipboard usage', function() eq({{'really unnamed', ''}, 'V'}, eval("g:test_clip['*']")) -- unnamedplus takes predecence when pasting + eq('+', eval('v:register')) execute("let g:test_clip['+'] = ['the plus','']") execute("let g:test_clip['*'] = ['the star','']") feed("p") diff --git a/test/functional/job/job_spec.lua b/test/functional/core/job_spec.lua index b54d5166ac..61ecdd1835 100644 --- a/test/functional/job/job_spec.lua +++ b/test/functional/core/job_spec.lua @@ -1,4 +1,3 @@ - local helpers = require('test.functional.helpers')(after_each) local clear, eq, eval, execute, feed, insert, neq, next_msg, nvim, nvim_dir, ok, source, write_file, mkdir, rmdir = helpers.clear, @@ -120,7 +119,7 @@ describe('jobs', function() {0, {'a', '', 'c', '', '', '', 'b', '', ''}}}, next_msg()) end) - it('can preserve nuls', function() + it('can preserve NULs', function() nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)") nvim('command', 'call jobsend(j, ["\n123\n", "abc\\nxyz\n", ""])') eq({'notification', 'stdout', {0, {'\n123\n', 'abc\nxyz\n', ''}}}, @@ -144,7 +143,7 @@ describe('jobs', function() eq({'notification', 'exit', {0, 0}}, next_msg()) end) - it("won't allow jobsend with a job that closed stdin", function() + it("disallows jobsend on a job that closed stdin", function() nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)") nvim('command', 'call jobclose(j, "stdin")') eq(false, pcall(function() @@ -152,12 +151,12 @@ describe('jobs', function() end)) end) - it('will not allow jobsend/stop on a non-existent job', function() + it('disallows jobsend/stop on a non-existent job', function() eq(false, pcall(eval, "jobsend(-1, 'lol')")) eq(false, pcall(eval, "jobstop(-1)")) end) - it('will not allow jobstop twice on the same job', function() + it('disallows jobstop twice on the same job', function() nvim('command', "let j = jobstart(['cat', '-'], g:job_opts)") neq(0, eval('j')) eq(true, pcall(eval, "jobstop(j)")) @@ -244,7 +243,7 @@ describe('jobs', function() eq({'notification', 'exit', {45, 10}}, next_msg()) end) - it('cant redefine callbacks being used by a job', function() + it('cannot redefine callbacks being used by a job', function() local screen = Screen.new() screen:attach() local script = [[ @@ -467,3 +466,41 @@ describe('jobs', function() end) end) end) + +describe("pty process teardown", function() + local screen + before_each(function() + clear() + screen = Screen.new(30, 6) + screen:attach() + screen:expect([[ + ^ | + ~ | + ~ | + ~ | + ~ | + | + ]]) + end) + after_each(function() + screen:detach() + end) + + it("does not prevent/delay exit. #4798 #4900", function() + -- Use a nested nvim (in :term) to test without --headless. + execute(":terminal '"..helpers.nvim_prog + -- Use :term again in the _nested_ nvim to get a PTY process. + -- Use `sleep` to simulate a long-running child of the PTY. + .."' +terminal +'!(sleep 300 &)' +qa") + + -- Exiting should terminate all descendants (PTY, its children, ...). + screen:expect([[ + | + [Process exited 0] | + | + | + | + -- TERMINAL -- | + ]]) + end) +end) diff --git a/test/functional/fixtures/autoload/provider/clipboard.vim b/test/functional/fixtures/autoload/provider/clipboard.vim index 0935ea45ff..411e095c71 100644 --- a/test/functional/fixtures/autoload/provider/clipboard.vim +++ b/test/functional/fixtures/autoload/provider/clipboard.vim @@ -9,13 +9,12 @@ function! s:methods.get(reg) if g:cliperror return 0 end - let reg = a:reg == '"' ? '+' : a:reg if g:cliplossy " behave like pure text clipboard - return g:test_clip[reg][0] + return g:test_clip[a:reg][0] else " behave like VIMENC clipboard - return g:test_clip[reg] + return g:test_clip[a:reg] end endfunction diff --git a/test/functional/ui/output_spec.lua b/test/functional/ui/output_spec.lua new file mode 100644 index 0000000000..c7c8986527 --- /dev/null +++ b/test/functional/ui/output_spec.lua @@ -0,0 +1,39 @@ +local session = require('test.functional.helpers')(after_each) +local child_session = require('test.functional.terminal.helpers') + +describe("shell command :!", function() + local screen + before_each(function() + session.clear() + screen = child_session.screen_setup(0, '["'..session.nvim_prog.. + '", "-u", "NONE", "-i", "NONE", "--cmd", "set noswapfile"]') + screen:expect([[ + {1: } | + ~ | + ~ | + ~ | + [No Name] | + | + -- TERMINAL -- | + ]]) + end) + + after_each(function() + screen:detach() + end) + + it("displays output even without LF/EOF. #4646 #4569 #3772", function() + -- NOTE: We use a child nvim (within a :term buffer) + -- to avoid triggering a UI flush. + child_session.feed_data(":!printf foo; sleep 200\n") + screen:expect([[ + ~ | + ~ | + [No Name] | + :!printf foo; sleep 200 | + | + foo | + -- TERMINAL -- | + ]]) + end) +end) |