aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/os/input.c4
-rw-r--r--src/nvim/tag.c7
-rw-r--r--src/nvim/testdir/Makefile2
-rw-r--r--src/nvim/testdir/test47.in102
-rw-r--r--src/nvim/testdir/test47.ok44
-rw-r--r--src/nvim/testdir/test_diffmode.vim165
-rw-r--r--src/nvim/tui/input.c7
-rw-r--r--src/nvim/tui/input.h3
-rw-r--r--src/nvim/tui/tui.c58
-rw-r--r--src/nvim/version.c4
10 files changed, 242 insertions, 154 deletions
diff --git a/src/nvim/os/input.c b/src/nvim/os/input.c
index 1307ab5e5a..b60a7eed36 100644
--- a/src/nvim/os/input.c
+++ b/src/nvim/os/input.c
@@ -39,8 +39,6 @@ static int events_enabled = 0;
#ifdef INCLUDE_GENERATED_DECLARATIONS
# include "os/input.c.generated.h"
#endif
-// Helper function used to push bytes from the 'event' key sequence partially
-// between calls to os_inchar when maxlen < 3
void input_init(void)
{
@@ -389,6 +387,8 @@ static void process_interrupts(void)
}
}
+// Helper function used to push bytes from the 'event' key sequence partially
+// between calls to os_inchar when maxlen < 3
static int push_event_key(uint8_t *buf, int maxlen)
{
static const uint8_t key[3] = { K_SPECIAL, KS_EXTRA, KE_EVENT };
diff --git a/src/nvim/tag.c b/src/nvim/tag.c
index f83154afbf..0b76e36a6b 100644
--- a/src/nvim/tag.c
+++ b/src/nvim/tag.c
@@ -1297,7 +1297,12 @@ find_tags (
* Read and parse the lines in the file one by one
*/
for (;; ) {
- line_breakcheck(); /* check for CTRL-C typed */
+ // check for CTRL-C typed, more often when jumping around
+ if (state == TS_BINARY || state == TS_SKIP_BACK) {
+ line_breakcheck();
+ } else {
+ fast_breakcheck();
+ }
if ((flags & TAG_INS_COMP)) /* Double brackets for gcc */
ins_compl_check_keys(30, false);
if (got_int || compl_interrupted) {
diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile
index dba8a8a877..0118597eb8 100644
--- a/src/nvim/testdir/Makefile
+++ b/src/nvim/testdir/Makefile
@@ -17,7 +17,6 @@ SCRIPTS := \
test37.out \
test40.out \
test42.out \
- test47.out \
test48.out \
test49.out \
test52.out \
@@ -33,6 +32,7 @@ SCRIPTS := \
NEW_TESTS = \
test_cscope.res \
test_cmdline.res \
+ test_diffmode.res \
test_hardcopy.res \
test_help_tagjump.res \
test_history.res \
diff --git a/src/nvim/testdir/test47.in b/src/nvim/testdir/test47.in
deleted file mode 100644
index c95c6a6850..0000000000
--- a/src/nvim/testdir/test47.in
+++ /dev/null
@@ -1,102 +0,0 @@
-Tests for vertical splits and filler lines in diff mode
-
-Also tests restoration of saved options by :diffoff.
-
-STARTTEST
-:" Disable the title to avoid xterm keeping the wrong one.
-:set notitle noicon
-/^1
-yG:new
-pkdd:w! Xtest
-ddGpkkrXoxxx:w! Xtest2
-:file Nop
-ggoyyyjjjozzzz
-:set foldmethod=marker foldcolumn=4
-:redir => nodiffsettings
-:silent! :set diff? fdm? fdc? scb? crb? wrap?
-:redir END
-:vert diffsplit Xtest
-:vert diffsplit Xtest2
-:redir => diffsettings
-:silent! :set diff? fdm? fdc? scb? crb? wrap?
-:redir END
-:let diff_fdm = &fdm
-:let diff_fdc = &fdc
-:" repeat entering diff mode here to see if this saves the wrong settings
-:diffthis
-:" jump to second window for a moment to have filler line appear at start of
-:" first window
-ggpgg:let one = winline()
-j:let one = one . "-" . winline()
-j:let one = one . "-" . winline()
-j:let one = one . "-" . winline()
-j:let one = one . "-" . winline()
-j:let one = one . "-" . winline()
-gg:let two = winline()
-j:let two = two . "-" . winline()
-j:let two = two . "-" . winline()
-j:let two = two . "-" . winline()
-j:let two = two . "-" . winline()
-gg:let three = winline()
-j:let three = three . "-" . winline()
-j:let three = three . "-" . winline()
-j:let three = three . "-" . winline()
-j:let three = three . "-" . winline()
-j:let three = three . "-" . winline()
-j:let three = three . "-" . winline()
-:call append("$", one)
-:call append("$", two)
-:call append("$", three)
-:$-2,$w! test.out
-:"
-:" Test diffoff
-:diffoff!
-1
-:let &diff = 1
-:let &fdm = diff_fdm
-:let &fdc = diff_fdc
-4
-:diffoff!
-:$put =nodiffsettings
-:$put =diffsettings
-1
-:redir => nd1
-:silent! :set diff? fdm? fdc? scb? crb? wrap?
-:redir END
-
-:redir => nd2
-:silent! :set diff? fdm? fdc? scb? crb? wrap?
-:redir END
-
-:redir => nd3
-:silent! :set diff? fdm? fdc? scb? crb? wrap?
-:redir END
-
-:$put =nd1
-:$put =nd2
-:$put =nd3
-:$-39,$w >> test.out
-:"
-:" Test that diffing shows correct filler lines
-:windo :bw!
-:enew
-:put =range(4,10)
-:1d _
-:vnew
-:put =range(1,10)
-:1d _
-:windo :diffthis
-:wincmd h
-:let w0=line('w0')
-:enew
-:put =w0
-:.w >> test.out
-:unlet! one two three nodiffsettings diffsettings diff_fdm diff_fdc nd1 nd2 nd3 w0
-:qa!
-ENDTEST
-
-1 aa
-2 bb
-3 cc
-4 dd
-5 ee
diff --git a/src/nvim/testdir/test47.ok b/src/nvim/testdir/test47.ok
deleted file mode 100644
index 83e96571ad..0000000000
--- a/src/nvim/testdir/test47.ok
+++ /dev/null
@@ -1,44 +0,0 @@
-2-4-5-6-8-9
-1-2-4-5-8
-2-3-4-5-6-7-8
-
-
-nodiff
- foldmethod=marker
- foldcolumn=4
-noscrollbind
-nocursorbind
- wrap
-
-
- diff
- foldmethod=diff
- foldcolumn=2
- scrollbind
- cursorbind
-nowrap
-
-
-nodiff
- foldmethod=marker
- foldcolumn=4
-noscrollbind
-nocursorbind
- wrap
-
-
-nodiff
- foldmethod=marker
- foldcolumn=4
-noscrollbind
-nocursorbind
- wrap
-
-
-nodiff
- foldmethod=marker
- foldcolumn=4
-noscrollbind
-nocursorbind
- wrap
-1
diff --git a/src/nvim/testdir/test_diffmode.vim b/src/nvim/testdir/test_diffmode.vim
new file mode 100644
index 0000000000..e5d9ff94d9
--- /dev/null
+++ b/src/nvim/testdir/test_diffmode.vim
@@ -0,0 +1,165 @@
+" Tests for diff mode
+
+func Test_diff_fold_sync()
+ enew!
+ let l = range(50)
+ call setline(1, l)
+ diffthis
+ let winone = win_getid()
+ new
+ let l[25] = 'diff'
+ call setline(1, l)
+ diffthis
+ let wintwo = win_getid()
+ " line 15 is inside the closed fold
+ call assert_equal(19, foldclosedend(10))
+ call win_gotoid(winone)
+ call assert_equal(19, foldclosedend(10))
+ " open the fold
+ normal zv
+ call assert_equal(-1, foldclosedend(10))
+ " fold in other window must have opened too
+ call win_gotoid(wintwo)
+ call assert_equal(-1, foldclosedend(10))
+
+ " cursor position is in sync
+ normal 23G
+ call win_gotoid(winone)
+ call assert_equal(23, getcurpos()[1])
+
+ windo diffoff
+ close!
+ set nomodified
+endfunc
+
+func Test_vert_split()
+ " Disable the title to avoid xterm keeping the wrong one.
+ set notitle noicon
+ new
+ let l = ['1 aa', '2 bb', '3 cc', '4 dd', '5 ee']
+ call setline(1, l)
+ w! Xtest
+ normal dd
+ $
+ put
+ normal kkrXoxxx
+ w! Xtest2
+ file Nop
+ normal ggoyyyjjjozzzz
+ set foldmethod=marker foldcolumn=4
+ call assert_equal(0, &diff)
+ call assert_equal('marker', &foldmethod)
+ call assert_equal(4, &foldcolumn)
+ call assert_equal(0, &scrollbind)
+ call assert_equal(0, &cursorbind)
+ call assert_equal(1, &wrap)
+
+ vert diffsplit Xtest
+ vert diffsplit Xtest2
+ call assert_equal(1, &diff)
+ call assert_equal('diff', &foldmethod)
+ call assert_equal(2, &foldcolumn)
+ call assert_equal(1, &scrollbind)
+ call assert_equal(1, &cursorbind)
+ call assert_equal(0, &wrap)
+
+ let diff_fdm = &fdm
+ let diff_fdc = &fdc
+ " repeat entering diff mode here to see if this saves the wrong settings
+ diffthis
+ " jump to second window for a moment to have filler line appear at start of
+ " first window
+ wincmd w
+ normal gg
+ wincmd p
+ normal gg
+ call assert_equal(2, winline())
+ normal j
+ call assert_equal(4, winline())
+ normal j
+ call assert_equal(5, winline())
+ normal j
+ call assert_equal(6, winline())
+ normal j
+ call assert_equal(8, winline())
+ normal j
+ call assert_equal(9, winline())
+
+ wincmd w
+ normal gg
+ call assert_equal(1, winline())
+ normal j
+ call assert_equal(2, winline())
+ normal j
+ call assert_equal(4, winline())
+ normal j
+ call assert_equal(5, winline())
+ normal j
+ call assert_equal(8, winline())
+
+ wincmd w
+ normal gg
+ call assert_equal(2, winline())
+ normal j
+ call assert_equal(3, winline())
+ normal j
+ call assert_equal(4, winline())
+ normal j
+ call assert_equal(5, winline())
+ normal j
+ call assert_equal(6, winline())
+ normal j
+ call assert_equal(7, winline())
+ normal j
+ call assert_equal(8, winline())
+
+ " Test diffoff
+ diffoff!
+ 1wincmd 2
+ let &diff = 1
+ let &fdm = diff_fdm
+ let &fdc = diff_fdc
+ 4wincmd w
+ diffoff!
+ 1wincmd w
+ call assert_equal(0, &diff)
+ call assert_equal('marker', &foldmethod)
+ call assert_equal(4, &foldcolumn)
+ call assert_equal(0, &scrollbind)
+ call assert_equal(0, &cursorbind)
+ call assert_equal(1, &wrap)
+
+ wincmd w
+ call assert_equal(0, &diff)
+ call assert_equal('marker', &foldmethod)
+ call assert_equal(4, &foldcolumn)
+ call assert_equal(0, &scrollbind)
+ call assert_equal(0, &cursorbind)
+ call assert_equal(1, &wrap)
+
+ wincmd w
+ call assert_equal(0, &diff)
+ call assert_equal('marker', &foldmethod)
+ call assert_equal(4, &foldcolumn)
+ call assert_equal(0, &scrollbind)
+ call assert_equal(0, &cursorbind)
+ call assert_equal(1, &wrap)
+
+ windo bw!
+endfunc
+
+func Test_filler_lines()
+ " Test that diffing shows correct filler lines
+ enew!
+ put =range(4,10)
+ 1d _
+ vnew
+ put =range(1,10)
+ 1d _
+ windo diffthis
+ wincmd h
+ call assert_equal(1, line('w0'))
+ unlet! diff_fdm diff_fdc
+
+ windo bw!
+endfunc
diff --git a/src/nvim/tui/input.c b/src/nvim/tui/input.c
index 70d87a7ab2..8e5adb14f9 100644
--- a/src/nvim/tui/input.c
+++ b/src/nvim/tui/input.c
@@ -32,7 +32,14 @@ void term_input_init(TermInput *input, Loop *loop)
term = ""; // termkey_new_abstract assumes non-null (#2745)
}
+#if TERMKEY_VERSION_MAJOR > 0 || TERMKEY_VERSION_MINOR > 18
+ input->tk = termkey_new_abstract(term,
+ TERMKEY_FLAG_UTF8 | TERMKEY_FLAG_NOSTART);
+ termkey_hook_terminfo_getstr(input->tk, input->tk_ti_hook_fn, NULL);
+ termkey_start(input->tk);
+#else
input->tk = termkey_new_abstract(term, TERMKEY_FLAG_UTF8);
+#endif
int curflags = termkey_get_canonflags(input->tk);
termkey_set_canonflags(input->tk, curflags | TERMKEY_CANON_DELBS);
diff --git a/src/nvim/tui/input.h b/src/nvim/tui/input.h
index d7ee2b9e52..7d59cf5c6a 100644
--- a/src/nvim/tui/input.h
+++ b/src/nvim/tui/input.h
@@ -12,6 +12,9 @@ typedef struct term_input {
bool paste_enabled;
bool waiting;
TermKey *tk;
+#if TERMKEY_VERSION_MAJOR > 0 || TERMKEY_VERSION_MINOR > 18
+ TermKey_Terminfo_Getstr_Hook *tk_ti_hook_fn; ///< libtermkey terminfo hook
+#endif
TimeWatcher timer_handle;
Loop *loop;
Stream read_stream;
diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c
index bceb4ca4ff..74187e07c0 100644
--- a/src/nvim/tui/tui.c
+++ b/src/nvim/tui/tui.c
@@ -7,9 +7,13 @@
#include <uv.h>
#include <unibilium.h>
+#if defined(HAVE_TERMIOS_H)
+# include <termios.h>
+#endif
#include "nvim/lib/kvec.h"
+#include "nvim/ascii.h"
#include "nvim/vim.h"
#include "nvim/log.h"
#include "nvim/ui.h"
@@ -195,6 +199,11 @@ static void tui_terminal_start(UI *ui)
terminfo_start(ui);
update_size(ui);
signal_watcher_start(&data->winch_handle, sigwinch_cb, SIGWINCH);
+
+#if TERMKEY_VERSION_MAJOR > 0 || TERMKEY_VERSION_MINOR > 18
+ data->input.tk_ti_hook_fn = tui_tk_ti_getstr;
+#endif
+ term_input_init(&data->input, data->loop);
term_input_start(&data->input);
}
@@ -227,8 +236,6 @@ static void tui_main(UIBridgeData *bridge, UI *ui)
signal_watcher_init(data->loop, &data->winch_handle, ui);
signal_watcher_init(data->loop, &data->cont_handle, data);
signal_watcher_start(&data->cont_handle, sigcont_cb, SIGCONT);
- // initialize input reading structures
- term_input_init(&data->input, &tui_loop);
tui_terminal_start(ui);
data->stop = false;
// allow the main thread to continue, we are ready to start handling UI
@@ -957,3 +964,50 @@ static void flush_buf(UI *ui, bool toggle_cursor)
unibi_out(ui, unibi_cursor_invisible);
}
}
+
+#if TERMKEY_VERSION_MAJOR > 0 || TERMKEY_VERSION_MINOR > 18
+/// Try to get "kbs" code from stty because "the terminfo kbs entry is extremely
+/// unreliable." (Vim, Bash, and tmux also do this.)
+///
+/// @see tmux/tty-keys.c fe4e9470bb504357d073320f5d305b22663ee3fd
+/// @see https://bugzilla.redhat.com/show_bug.cgi?id=142659
+static const char *tui_get_stty_erase(void)
+{
+ static char stty_erase[2] = { 0 };
+#if defined(ECHOE) && defined(ICANON) && defined(HAVE_TERMIOS_H)
+ struct termios t;
+ if (tcgetattr(input_global_fd(), &t) != -1) {
+ stty_erase[0] = (char)t.c_cc[VERASE];
+ stty_erase[1] = '\0';
+ ILOG("stty/termios:erase=%s", stty_erase);
+ }
+#endif
+ return stty_erase;
+}
+
+/// libtermkey hook to override terminfo entries.
+/// @see TermInput.tk_ti_hook_fn
+static const char *tui_tk_ti_getstr(const char *name, const char *value,
+ void *data)
+{
+ static const char *stty_erase = NULL;
+ if (stty_erase == NULL) {
+ stty_erase = tui_get_stty_erase();
+ }
+
+ if (strcmp(name, "key_backspace") == 0) {
+ ILOG("libtermkey:kbs=%s", value);
+ if (stty_erase != NULL && stty_erase[0] != 0) {
+ return stty_erase;
+ }
+ } else if (strcmp(name, "key_dc") == 0) {
+ ILOG("libtermkey:kdch1=%s", value);
+ // Vim: "If <BS> and <DEL> are now the same, redefine <DEL>."
+ if (stty_erase != NULL && strcmp(stty_erase, value) == 0) {
+ return stty_erase[0] == DEL ? (char *)CTRL_H_STR : (char *)DEL_STR;
+ }
+ }
+
+ return value;
+}
+#endif
diff --git a/src/nvim/version.c b/src/nvim/version.c
index 8e7ad2199f..ce103ec7dd 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -105,7 +105,7 @@ static int included_patches[] = {
// 2338 NA
2337,
// 2336,
- // 2335,
+ 2335,
// 2334,
// 2333,
// 2332 NA
@@ -317,7 +317,7 @@ static int included_patches[] = {
// 2126,
// 2125,
// 2124,
- // 2123,
+ 2123,
// 2122 NA
// 2121,
// 2120,