diff options
-rw-r--r-- | runtime/doc/tips.txt | 2 | ||||
-rw-r--r-- | src/nvim/eval.c | 5 | ||||
-rw-r--r-- | src/nvim/event/libuv_process.c | 7 | ||||
-rw-r--r-- | src/nvim/event/process.c | 36 | ||||
-rw-r--r-- | src/nvim/ex_cmds.c | 2 | ||||
-rw-r--r-- | src/nvim/globals.h | 2 | ||||
-rw-r--r-- | src/nvim/if_cscope.c | 5 | ||||
-rw-r--r-- | src/nvim/os/pty_process_unix.c | 40 | ||||
-rw-r--r-- | src/nvim/os/shell.c | 33 | ||||
-rw-r--r-- | src/nvim/testdir/Makefile | 1 | ||||
-rw-r--r-- | src/nvim/testdir/runtest.vim | 1 | ||||
-rw-r--r-- | src/nvim/testdir/samples/memfile_test.c | 143 | ||||
-rw-r--r-- | src/nvim/testdir/test_cscope.vim | 266 | ||||
-rw-r--r-- | src/nvim/testdir/test_digraph.vim | 461 | ||||
-rw-r--r-- | src/nvim/version.c | 22 |
15 files changed, 954 insertions, 72 deletions
diff --git a/runtime/doc/tips.txt b/runtime/doc/tips.txt index 8032af7d0a..9d2eb3deba 100644 --- a/runtime/doc/tips.txt +++ b/runtime/doc/tips.txt @@ -400,7 +400,7 @@ when they are not in the same location as the compressed "doc" directory. See ============================================================================== Hex editing *hex-editing* *using-xxd* -See section |23.4| of the user manual. +See section |23.3| of the user manual. If one has a particular extension that one uses for binary files (such as exe, bin, etc), you may find it helpful to automate the process with the following diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 1cc84f8c16..823b621638 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -23046,8 +23046,9 @@ static inline bool common_job_start(TerminalJobData *data, typval_T *rettv) data->refcount++; char *cmd = xstrdup(proc->argv[0]); - if (!process_spawn(proc)) { - EMSG2(_(e_jobspawn), cmd); + int status = process_spawn(proc); + if (status) { + EMSG3(_(e_jobspawn), os_strerror(status), cmd); xfree(cmd); if (proc->type == kProcessTypePty) { xfree(data->proc.pty.term_name); diff --git a/src/nvim/event/libuv_process.c b/src/nvim/event/libuv_process.c index 907187aa17..3da0c386b4 100644 --- a/src/nvim/event/libuv_process.c +++ b/src/nvim/event/libuv_process.c @@ -13,7 +13,8 @@ # include "event/libuv_process.c.generated.h" #endif -bool libuv_process_spawn(LibuvProcess *uvproc) +/// @returns zero on success, or negative error code +int libuv_process_spawn(LibuvProcess *uvproc) FUNC_ATTR_NONNULL_ALL { Process *proc = (Process *)uvproc; @@ -51,11 +52,11 @@ bool libuv_process_spawn(LibuvProcess *uvproc) int status; if ((status = uv_spawn(&proc->loop->uv, &uvproc->uv, &uvproc->uvopts))) { ELOG("uv_spawn failed: %s", uv_strerror(status)); - return false; + return status; } proc->pid = uvproc->uv.pid; - return true; + return status; } void libuv_process_close(LibuvProcess *uvproc) diff --git a/src/nvim/event/process.c b/src/nvim/event/process.c index dc7886469b..4429a65f92 100644 --- a/src/nvim/event/process.c +++ b/src/nvim/event/process.c @@ -30,7 +30,8 @@ static bool process_is_tearing_down = false; -bool process_spawn(Process *proc) FUNC_ATTR_NONNULL_ALL +/// @returns zero on success, or negative error code +int process_spawn(Process *proc) FUNC_ATTR_NONNULL_ALL { if (proc->in) { uv_pipe_init(&proc->loop->uv, &proc->in->uv.pipe, 0); @@ -44,19 +45,19 @@ bool process_spawn(Process *proc) FUNC_ATTR_NONNULL_ALL uv_pipe_init(&proc->loop->uv, &proc->err->uv.pipe, 0); } - bool success; + int status; switch (proc->type) { case kProcessTypeUv: - success = libuv_process_spawn((LibuvProcess *)proc); + status = libuv_process_spawn((LibuvProcess *)proc); break; case kProcessTypePty: - success = pty_process_spawn((PtyProcess *)proc); + status = pty_process_spawn((PtyProcess *)proc); break; default: abort(); } - if (!success) { + if (status) { if (proc->in) { uv_close((uv_handle_t *)&proc->in->uv.pipe, NULL); } @@ -74,7 +75,7 @@ bool process_spawn(Process *proc) FUNC_ATTR_NONNULL_ALL } shell_free_argv(proc->argv); proc->status = -1; - return false; + return status; } if (proc->in) { @@ -105,7 +106,7 @@ bool process_spawn(Process *proc) FUNC_ATTR_NONNULL_ALL proc->internal_close_cb = decref; proc->refcount++; kl_push(WatcherPtr, proc->loop->children, proc); - return true; + return 0; } void process_teardown(Loop *loop) FUNC_ATTR_NONNULL_ALL @@ -155,19 +156,16 @@ void process_close_err(Process *proc) FUNC_ATTR_NONNULL_ALL /// Synchronously wait for a process to finish /// -/// @param process The Process instance -/// @param ms Number of milliseconds to wait, 0 for not waiting, -1 for -/// waiting until the process quits. -/// @return returns the status code of the exited process. -1 if the process is -/// still running and the `timeout` has expired. Note that this is -/// indistinguishable from the process returning -1 by itself. Which -/// is possible on some OS. Returns -2 if an user has interruped the -/// wait. +/// @param process Process instance +/// @param ms Time in milliseconds to wait for the process. +/// 0 for no wait. -1 to wait until the process quits. +/// @return Exit code of the process. +/// -1 if the timeout expired while the process is still running. +/// -2 if the user interruped the wait. int process_wait(Process *proc, int ms, MultiQueue *events) FUNC_ATTR_NONNULL_ARG(1) { - // The default status is -1, which represents a timeout - int status = -1; + int status = -1; // default bool interrupted = false; if (!proc->refcount) { status = proc->status; @@ -179,8 +177,8 @@ int process_wait(Process *proc, int ms, MultiQueue *events) events = proc->events; } - // Increase refcount to stop the exit callback from being called(and possibly - // being freed) before we have a chance to get the status. + // Increase refcount to stop the exit callback from being called (and possibly + // freed) before we have a chance to get the status. proc->refcount++; LOOP_PROCESS_EVENTS_UNTIL(proc->loop, events, ms, // Until... diff --git a/src/nvim/ex_cmds.c b/src/nvim/ex_cmds.c index 3b7f3b7b97..4b3798794c 100644 --- a/src/nvim/ex_cmds.c +++ b/src/nvim/ex_cmds.c @@ -2340,6 +2340,7 @@ int do_ecmd( } xfree(new_name); au_new_curbuf.br_buf = NULL; + au_new_curbuf.br_buf_free_count = 0; } curwin->w_pcmark.lnum = 1; @@ -2625,6 +2626,7 @@ static void delbuf_msg(char_u *name) name == NULL ? (char_u *)"" : name); xfree(name); au_new_curbuf.br_buf = NULL; + au_new_curbuf.br_buf_free_count = 0; } static int append_indent = 0; /* autoindent for first line */ diff --git a/src/nvim/globals.h b/src/nvim/globals.h index 9da6062ffb..696bdf586f 100644 --- a/src/nvim/globals.h +++ b/src/nvim/globals.h @@ -1127,7 +1127,7 @@ EXTERN char_u e_isadir2[] INIT(= N_("E17: \"%s\" is a directory")); EXTERN char_u e_invjob[] INIT(= N_("E900: Invalid job id")); EXTERN char_u e_jobtblfull[] INIT(= N_("E901: Job table is full")); EXTERN char_u e_jobspawn[] INIT(= N_( - "E903: Process for command \"%s\" could not be spawned")); + "E903: Process failed to start: %s: \"%s\"")); EXTERN char_u e_jobnotpty[] INIT(= N_("E904: Job is not connected to a pty")); EXTERN char_u e_libcall[] INIT(= N_("E364: Library call failed for \"%s()\"")); EXTERN char_u e_mkdir[] INIT(= N_("E739: Cannot create directory %s: %s")); diff --git a/src/nvim/if_cscope.c b/src/nvim/if_cscope.c index 0b20647771..9d50058257 100644 --- a/src/nvim/if_cscope.c +++ b/src/nvim/if_cscope.c @@ -1294,9 +1294,10 @@ static int cs_kill(exarg_T *eap) } } - if (i >= csinfo_size || csinfo[i].fname == NULL) { - if (p_csverbose) + if (!killall && (i >= csinfo_size || csinfo[i].fname == NULL)) { + if (p_csverbose) { (void)EMSG2(_("E261: cscope connection %s not found"), stok); + } return CSCOPE_FAILURE; } else { if (killall) { diff --git a/src/nvim/os/pty_process_unix.c b/src/nvim/os/pty_process_unix.c index b57a69b82b..f5ba0c2612 100644 --- a/src/nvim/os/pty_process_unix.c +++ b/src/nvim/os/pty_process_unix.c @@ -33,7 +33,8 @@ # include "os/pty_process_unix.c.generated.h" #endif -bool pty_process_spawn(PtyProcess *ptyproc) +/// @returns zero on success, or negative error code +int pty_process_spawn(PtyProcess *ptyproc) FUNC_ATTR_NONNULL_ALL { static struct termios termios; @@ -41,6 +42,7 @@ bool pty_process_spawn(PtyProcess *ptyproc) init_termios(&termios); } + int status = 0; // zero or negative error code (libuv convention) Process *proc = (Process *)ptyproc; assert(!proc->err); uv_signal_start(&proc->loop->children_watcher, chld_handler, SIGCHLD); @@ -50,8 +52,9 @@ bool pty_process_spawn(PtyProcess *ptyproc) int pid = forkpty(&master, NULL, &termios, &ptyproc->winsize); if (pid < 0) { + status = -errno; ELOG("forkpty failed: %s", strerror(errno)); - return false; + return status; } else if (pid == 0) { init_child(ptyproc); abort(); @@ -60,30 +63,34 @@ bool pty_process_spawn(PtyProcess *ptyproc) // make sure the master file descriptor is non blocking int master_status_flags = fcntl(master, F_GETFL); if (master_status_flags == -1) { + status = -errno; ELOG("Failed to get master descriptor status flags: %s", strerror(errno)); goto error; } if (fcntl(master, F_SETFL, master_status_flags | O_NONBLOCK) == -1) { + status = -errno; ELOG("Failed to make master descriptor non-blocking: %s", strerror(errno)); goto error; } - if (proc->in && !set_duplicating_descriptor(master, &proc->in->uv.pipe)) { + if (proc->in + && (status = set_duplicating_descriptor(master, &proc->in->uv.pipe))) { goto error; } - if (proc->out && !set_duplicating_descriptor(master, &proc->out->uv.pipe)) { + if (proc->out + && (status = set_duplicating_descriptor(master, &proc->out->uv.pipe))) { goto error; } ptyproc->tty_fd = master; proc->pid = pid; - return true; + return 0; error: close(master); kill(pid, SIGKILL); waitpid(pid, NULL, 0); - return false; + return status; } void pty_process_resize(PtyProcess *ptyproc, uint16_t width, uint16_t height) @@ -137,9 +144,10 @@ static void init_child(PtyProcess *ptyproc) FUNC_ATTR_NONNULL_ALL return; } + char *prog = ptyproc->process.argv[0]; setenv("TERM", ptyproc->term_name ? ptyproc->term_name : "ansi", 1); - execvp(ptyproc->process.argv[0], ptyproc->process.argv); - fprintf(stderr, "execvp failed: %s\n", strerror(errno)); + execvp(prog, ptyproc->process.argv); + fprintf(stderr, "execvp failed: %s: %s\n", strerror(errno), prog); } static void init_termios(struct termios *termios) FUNC_ATTR_NONNULL_ALL @@ -197,22 +205,24 @@ static void init_termios(struct termios *termios) FUNC_ATTR_NONNULL_ALL termios->c_cc[VTIME] = 0; } -static bool set_duplicating_descriptor(int fd, uv_pipe_t *pipe) +static int set_duplicating_descriptor(int fd, uv_pipe_t *pipe) FUNC_ATTR_NONNULL_ALL { + int status = 0; // zero or negative error code (libuv convention) int fd_dup = dup(fd); if (fd_dup < 0) { + status = -errno; ELOG("Failed to dup descriptor %d: %s", fd, strerror(errno)); - return false; + return status; } - int uv_result = uv_pipe_open(pipe, fd_dup); - if (uv_result) { + status = uv_pipe_open(pipe, fd_dup); + if (status) { ELOG("Failed to set pipe to descriptor %d: %s", - fd_dup, uv_strerror(uv_result)); + fd_dup, uv_strerror(status)); close(fd_dup); - return false; + return status; } - return true; + return status; } static void chld_handler(uv_signal_t *handle, int signum) diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c index 9514936ad0..a5fd37ed5c 100644 --- a/src/nvim/os/shell.c +++ b/src/nvim/os/shell.c @@ -124,13 +124,9 @@ int os_call_shell(char_u *cmd, ShellOpts opts, char_u *extra_args) size_t nread; - int status = do_os_system(shell_build_argv((char *)cmd, (char *)extra_args), - input.data, - input.len, - output_ptr, - &nread, - emsg_silent, - forward_output); + int exitcode = do_os_system(shell_build_argv((char *)cmd, (char *)extra_args), + input.data, input.len, output_ptr, &nread, + emsg_silent, forward_output); xfree(input.data); @@ -139,16 +135,16 @@ int os_call_shell(char_u *cmd, ShellOpts opts, char_u *extra_args) xfree(output); } - if (!emsg_silent && status != 0 && !(opts & kShellOptSilent)) { + if (!emsg_silent && exitcode != 0 && !(opts & kShellOptSilent)) { MSG_PUTS(_("\nshell returned ")); - msg_outnum(status); + msg_outnum(exitcode); msg_putchar('\n'); } State = current_state; signal_accept_deadly(); - return status; + return exitcode; } /// os_system - synchronously execute a command in the shell @@ -157,7 +153,7 @@ int os_call_shell(char_u *cmd, ShellOpts opts, char_u *extra_args) /// char *output = NULL; /// size_t nread = 0; /// char *argv[] = {"ls", "-la", NULL}; -/// int status = os_sytem(argv, NULL, 0, &output, &nread); +/// int exitcode = os_sytem(argv, NULL, 0, &output, &nread); /// /// @param argv The commandline arguments to be passed to the shell. `argv` /// will be consumed. @@ -218,11 +214,14 @@ static int do_os_system(char **argv, proc->in = input != NULL ? &in : NULL; proc->out = &out; proc->err = &err; - if (!process_spawn(proc)) { + int status = process_spawn(proc); + if (status) { loop_poll_events(&main_loop, 0); - // Failed, probably due to 'sh' not being executable + // Failed, probably 'shell' is not executable. if (!silent) { - MSG_PUTS(_("\nCannot execute ")); + MSG_PUTS(_("\nshell failed to start: ")); + msg_outtrans((char_u *)os_strerror(status)); + MSG_PUTS(": "); msg_outtrans((char_u *)prog); msg_putchar('\n'); } @@ -262,7 +261,7 @@ static int do_os_system(char **argv, // busy state. ui_busy_start(); ui_flush(); - int status = process_wait(proc, -1, NULL); + int exitcode = process_wait(proc, -1, NULL); if (!got_int && out_data_decide_throttle(0)) { // Last chunk of output was skipped; display it now. out_data_ring(NULL, SIZE_MAX); @@ -289,7 +288,7 @@ static int do_os_system(char **argv, assert(multiqueue_empty(events)); multiqueue_free(events); - return status; + return exitcode; } /// - ensures at least `desired` bytes in buffer @@ -321,7 +320,7 @@ static void system_data_cb(Stream *stream, RBuffer *buf, size_t count, /// Tracks output received for the current executing shell command, and displays /// a pulsing "..." when output should be skipped. Tracking depends on the /// synchronous/blocking nature of ":!". -// +/// /// Purpose: /// 1. CTRL-C is more responsive. #1234 #5396 /// 2. Improves performance of :! (UI, esp. TUI, is the bottleneck). diff --git a/src/nvim/testdir/Makefile b/src/nvim/testdir/Makefile index 7bcc78e58a..59c93f1673 100644 --- a/src/nvim/testdir/Makefile +++ b/src/nvim/testdir/Makefile @@ -31,6 +31,7 @@ NEW_TESTS = \ test_bufwintabinfo.res \ test_cmdline.res \ test_cscope.res \ + test_digraph.res \ test_diffmode.res \ test_gn.res \ test_hardcopy.res \ diff --git a/src/nvim/testdir/runtest.vim b/src/nvim/testdir/runtest.vim index eb5912086b..316aba968d 100644 --- a/src/nvim/testdir/runtest.vim +++ b/src/nvim/testdir/runtest.vim @@ -65,6 +65,7 @@ set shellslash " Align with vim defaults. set directory^=. set nohidden +set backspace= function RunTheTest(test) echo 'Executing ' . a:test diff --git a/src/nvim/testdir/samples/memfile_test.c b/src/nvim/testdir/samples/memfile_test.c new file mode 100644 index 0000000000..0fa1e14c40 --- /dev/null +++ b/src/nvim/testdir/samples/memfile_test.c @@ -0,0 +1,143 @@ +/* vi:set ts=8 sts=4 sw=4 noet: + * + * VIM - Vi IMproved by Bram Moolenaar + * + * Do ":help uganda" in Vim to read copying and usage conditions. + * Do ":help credits" in Vim to see a list of people who contributed. + * See README.txt for an overview of the Vim source code. + */ + +/* + * memfile_test.c: Unittests for memfile.c + * Mostly by Ivan Krasilnikov. + */ + +#undef NDEBUG +#include <assert.h> + +/* Must include main.c because it contains much more than just main() */ +#define NO_VIM_MAIN +#include "main.c" + +/* This file has to be included because the tested functions are static */ +#include "memfile.c" + +#define index_to_key(i) ((i) ^ 15167) +#define TEST_COUNT 50000 + +/* + * Test mf_hash_*() functions. + */ + static void +test_mf_hash(void) +{ + mf_hashtab_T ht; + mf_hashitem_T *item; + blocknr_T key; + long_u i; + long_u num_buckets; + + mf_hash_init(&ht); + + /* insert some items and check invariants */ + for (i = 0; i < TEST_COUNT; i++) + { + assert(ht.mht_count == i); + + /* check that number of buckets is a power of 2 */ + num_buckets = ht.mht_mask + 1; + assert(num_buckets > 0 && (num_buckets & (num_buckets - 1)) == 0); + + /* check load factor */ + assert(ht.mht_count <= (num_buckets << MHT_LOG_LOAD_FACTOR)); + + if (i < (MHT_INIT_SIZE << MHT_LOG_LOAD_FACTOR)) + { + /* first expansion shouldn't have occurred yet */ + assert(num_buckets == MHT_INIT_SIZE); + assert(ht.mht_buckets == ht.mht_small_buckets); + } + else + { + assert(num_buckets > MHT_INIT_SIZE); + assert(ht.mht_buckets != ht.mht_small_buckets); + } + + key = index_to_key(i); + assert(mf_hash_find(&ht, key) == NULL); + + /* allocate and add new item */ + item = (mf_hashitem_T *)lalloc_clear(sizeof(mf_hashtab_T), FALSE); + assert(item != NULL); + item->mhi_key = key; + mf_hash_add_item(&ht, item); + + assert(mf_hash_find(&ht, key) == item); + + if (ht.mht_mask + 1 != num_buckets) + { + /* hash table was expanded */ + assert(ht.mht_mask + 1 == num_buckets * MHT_GROWTH_FACTOR); + assert(i + 1 == (num_buckets << MHT_LOG_LOAD_FACTOR)); + } + } + + /* check presence of inserted items */ + for (i = 0; i < TEST_COUNT; i++) + { + key = index_to_key(i); + item = mf_hash_find(&ht, key); + assert(item != NULL); + assert(item->mhi_key == key); + } + + /* delete some items */ + for (i = 0; i < TEST_COUNT; i++) + { + if (i % 100 < 70) + { + key = index_to_key(i); + item = mf_hash_find(&ht, key); + assert(item != NULL); + assert(item->mhi_key == key); + + mf_hash_rem_item(&ht, item); + assert(mf_hash_find(&ht, key) == NULL); + + mf_hash_add_item(&ht, item); + assert(mf_hash_find(&ht, key) == item); + + mf_hash_rem_item(&ht, item); + assert(mf_hash_find(&ht, key) == NULL); + + vim_free(item); + } + } + + /* check again */ + for (i = 0; i < TEST_COUNT; i++) + { + key = index_to_key(i); + item = mf_hash_find(&ht, key); + + if (i % 100 < 70) + { + assert(item == NULL); + } + else + { + assert(item != NULL); + assert(item->mhi_key == key); + } + } + + /* free hash table and all remaining items */ + mf_hash_free_all(&ht); +} + + int +main(void) +{ + test_mf_hash(); + return 0; +} diff --git a/src/nvim/testdir/test_cscope.vim b/src/nvim/testdir/test_cscope.vim index b6d70f0765..c8d2ebd7da 100644 --- a/src/nvim/testdir/test_cscope.vim +++ b/src/nvim/testdir/test_cscope.vim @@ -1,9 +1,262 @@ " Test for cscope commands. -if !has('cscope') +if !has('cscope') || !executable('cscope') || !has('quickfix') finish endif +func CscopeSetupOrClean(setup) + if a:setup + noa sp samples/memfile_test.c + saveas! Xmemfile_test.c + call system('cscope -bk -fXcscope.out Xmemfile_test.c') + call system('cscope -bk -fXcscope2.out Xmemfile_test.c') + cscope add Xcscope.out + set cscopequickfix=s-,g-,d-,c-,t-,e-,f-,i-,a- + else + cscope kill -1 + for file in ['Xcscope.out', 'Xcscope2.out', 'Xmemfile_test.c'] + call delete(file) + endfo + endif +endfunc + +func Test_cscopeWithCscopeConnections() + call CscopeSetupOrClean(1) + " Test 0: E568: duplicate cscope database not added + try + set nocscopeverbose + cscope add Xcscope.out + set cscopeverbose + catch + call assert_true(0) + endtry + call assert_fails('cscope add', 'E560') + call assert_fails('cscope add Xcscope.out', 'E568') + call assert_fails('cscope add doesnotexist.out', 'E563') + + " Test 1: Find this C-Symbol + for cmd in ['cs find s main', 'cs find 0 main'] + let a=execute(cmd) + " Test 1.1 test where it moves the cursor + call assert_equal('main(void)', getline('.')) + " Test 1.2 test the output of the :cs command + call assert_match('\n(1 of 1): <<main>> main(void )', a) + endfor + + " Test 2: Find this definition + for cmd in ['cs find g test_mf_hash', 'cs find 1 test_mf_hash'] + exe cmd + call assert_equal(['', '/*', ' * Test mf_hash_*() functions.', ' */', ' static void', 'test_mf_hash(void)', '{'], getline(line('.')-5, line('.')+1)) + endfor + + " Test 3: Find functions called by this function + for cmd in ['cs find d test_mf_hash', 'cs find 2 test_mf_hash'] + let a=execute(cmd) + call assert_match('\n(1 of 42): <<mf_hash_init>> mf_hash_init(&ht);', a) + call assert_equal(' mf_hash_init(&ht);', getline('.')) + endfor + + " Test 4: Find functions calling this function + for cmd in ['cs find c test_mf_hash', 'cs find 3 test_mf_hash'] + let a=execute(cmd) + call assert_match('\n(1 of 1): <<main>> test_mf_hash();', a) + call assert_equal(' test_mf_hash();', getline('.')) + endfor + + " Test 5: Find this text string + for cmd in ['cs find t Bram', 'cs find 4 Bram'] + let a=execute(cmd) + call assert_match('(1 of 1): <<<unknown>>> \* VIM - Vi IMproved^Iby Bram Moolenaar', a) + call assert_equal(' * VIM - Vi IMproved by Bram Moolenaar', getline('.')) + endfor + + " Test 6: Find this egrep pattern + " test all matches returned by cscope + for cmd in ['cs find e ^\#includ.', 'cs find 6 ^\#includ.'] + let a=execute(cmd) + call assert_match('\n(1 of 3): <<<unknown>>> #include <assert.h>', a) + call assert_equal('#include <assert.h>', getline('.')) + cnext + call assert_equal('#include "main.c"', getline('.')) + cnext + call assert_equal('#include "memfile.c"', getline('.')) + call assert_fails('cnext', 'E553:') + endfor + + " Test 7: Find the same egrep pattern using lcscope this time. + let a=execute('lcs find e ^\#includ.') + call assert_match('\n(1 of 3): <<<unknown>>> #include <assert.h>', a) + call assert_equal('#include <assert.h>', getline('.')) + lnext + call assert_equal('#include "main.c"', getline('.')) + lnext + call assert_equal('#include "memfile.c"', getline('.')) + call assert_fails('lnext', 'E553:') + + " Test 8: Find this file + for cmd in ['cs find f Xmemfile_test.c', 'cs find 7 Xmemfile_test.c'] + enew + let a=execute(cmd) + call assert_true(a =~ '"Xmemfile_test.c" \d\+L, \d\+C') + call assert_equal('Xmemfile_test.c', @%) + endfor + + " Test 9: Find files #including this file + for cmd in ['cs find i assert.h', 'cs find 8 assert.h'] + enew + let a=execute(cmd) + let alines = split(a, '\n', 1) + call assert_equal('', alines[0]) + call assert_true(alines[1] =~ '"Xmemfile_test.c" \d\+L, \d\+C') + call assert_equal('(1 of 1): <<global>> #include <assert.h>', alines[2]) + call assert_equal('#include <assert.h>', getline('.')) + endfor + + " Test 10: Invalid find command + call assert_fails('cs find x', 'E560:') + + " Test 11: Find places where this symbol is assigned a value + " this needs a cscope >= 15.8 + " unfortunately, Travis has cscope version 15.7 + let cscope_version=systemlist('cscope --version')[0] + let cs_version=str2float(matchstr(cscope_version, '\d\+\(\.\d\+\)\?')) + if cs_version >= 15.8 + for cmd in ['cs find a item', 'cs find 9 item'] + let a=execute(cmd) + call assert_equal(['', '(1 of 4): <<test_mf_hash>> item = (mf_hashitem_T *)lalloc_clear(sizeof(mf_hashtab_T), FALSE);'], split(a, '\n', 1)) + call assert_equal(' item = (mf_hashitem_T *)lalloc_clear(sizeof(mf_hashtab_T), FALSE);', getline('.')) + cnext + call assert_equal(' item = mf_hash_find(&ht, key);', getline('.')) + cnext + call assert_equal(' item = mf_hash_find(&ht, key);', getline('.')) + cnext + call assert_equal(' item = mf_hash_find(&ht, key);', getline('.')) + endfor + endif + + " Test 12: leading whitespace is not removed for cscope find text + let a=execute('cscope find t test_mf_hash') + call assert_equal(['', '(1 of 1): <<<unknown>>> test_mf_hash();'], split(a, '\n', 1)) + call assert_equal(' test_mf_hash();', getline('.')) + + " Test 13: test with scscope + let a=execute('scs find t Bram') + call assert_match('(1 of 1): <<<unknown>>> \* VIM - Vi IMproved^Iby Bram Moolenaar', a) + call assert_equal(' * VIM - Vi IMproved by Bram Moolenaar', getline('.')) + + " Test 14: cscope help + for cmd in ['cs', 'cs help', 'cs xxx'] + let a=execute(cmd) + call assert_match('^cscope commands:\n', a) + call assert_match('\nadd :', a) + call assert_match('\nfind :', a) + call assert_match('\nhelp : Show this message', a) + call assert_match('\nkill : Kill a connection', a) + call assert_match('\nreset: Reinit all connections', a) + call assert_match('\nshow : Show connections', a) + endfor + let a=execute('scscope help') + call assert_match('This cscope command does not support splitting the window\.', a) + + " Test 15: reset connections + let a=execute('cscope reset') + call assert_match('\nAdded cscope database.*Xcscope.out (#0)', a) + call assert_match('\nAll cscope databases reset', a) + + " Test 16: cscope show + let a=execute('cscope show') + call assert_match('\n 0 \d\+.*Xcscope.out\s*<none>', a) + + " Test 17: cstag and 'csto' option + set csto=0 + let a=execute('cstag TEST_COUNT') + call assert_match('(1 of 1): <<TEST_COUNT>> #define TEST_COUNT 50000', a) + call assert_equal('#define TEST_COUNT 50000', getline('.')) + set csto=1 + let a=execute('cstag index_to_key') + call assert_match('(1 of 1): <<index_to_key>> #define index_to_key(i) ((i) ^ 15167)', a) + call assert_equal('#define index_to_key(i) ((i) ^ 15167)', getline('.')) + call assert_fails('cstag xxx', 'E257:') + call assert_fails('cstag', 'E562:') + + " Test 18: 'cst' option + set nocst + call assert_fails('tag TEST_COUNT', 'E426:') + set cst + let a=execute('tag TEST_COUNT') + call assert_match('(1 of 1): <<TEST_COUNT>> #define TEST_COUNT 50000', a) + call assert_equal('#define TEST_COUNT 50000', getline('.')) + let a=execute('tags') + call assert_match('1 1 TEST_COUNT\s\+\d\+\s\+#define index_to_key', a) + + " Test 19: this should trigger call to cs_print_tags() + " Unclear how to check result though, we just exercise the code. + set cst cscopequickfix=s0 + call feedkeys(":cs find s main\<CR>", 't') + + " Test 20: cscope kill + call assert_fails('cscope kill 2', 'E261:') + call assert_fails('cscope kill xxx', 'E261:') + + let a=execute('cscope kill 0') + call assert_match('cscope connection 0 closed', a) + + cscope add Xcscope.out + let a=execute('cscope kill Xcscope.out') + call assert_match('cscope connection Xcscope.out closed', a) + + cscope add Xcscope.out . + let a=execute('cscope kill -1') + call assert_match('cscope connection .*Xcscope.out closed', a) + let a=execute('cscope kill -1') + call assert_equal('', a) + + " Test 21: 'csprg' option + call assert_equal('cscope', &csprg) + set csprg=doesnotexist + call assert_fails('cscope add Xcscope2.out', 'E609:') + set csprg=cscope + + " Test 22: multiple cscope connections + cscope add Xcscope.out + cscope add Xcscope2.out . -C + let a=execute('cscope show') + call assert_match('\n 0 \d\+.*Xcscope.out\s*<none>', a) + call assert_match('\n 1 \d\+.*Xcscope2.out\s*\.', a) + + " Test 23: test Ex command line completion + call feedkeys(":cs \<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"cs add find help kill reset show', @:) + + call feedkeys(":scs \<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"scs find', @:) + + call feedkeys(":cs find \<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"cs find a c d e f g i s t', @:) + + call feedkeys(":cs kill \<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"cs kill -1 0 1', @:) + + call feedkeys(":cs add Xcscope\<C-A>\<C-B>\"\<CR>", 'tx') + call assert_equal('"cs add Xcscope.out Xcscope2.out', @:) + + " Test 24: cscope_connection() + call assert_equal(cscope_connection(), 1) + call assert_equal(cscope_connection(0, 'out'), 1) + call assert_equal(cscope_connection(0, 'xxx'), 1) + call assert_equal(cscope_connection(1, 'out'), 1) + call assert_equal(cscope_connection(1, 'xxx'), 0) + call assert_equal(cscope_connection(2, 'out'), 0) + call assert_equal(cscope_connection(3, 'xxx', '..'), 0) + call assert_equal(cscope_connection(3, 'out', 'xxx'), 0) + call assert_equal(cscope_connection(3, 'out', '.'), 1) + call assert_equal(cscope_connection(4, 'out', '.'), 0) + + " CleanUp + call CscopeSetupOrClean(0) + +endfunc + func Test_cscopequickfix() set cscopequickfix=s-,g-,d+,c-,t+,e-,f0,i-,a- call assert_equal('s-,g-,d+,c-,t+,e-,f0,i-,a-', &cscopequickfix) @@ -13,3 +266,14 @@ func Test_cscopequickfix() call assert_fails('set cscopequickfix=s7', 'E474:') call assert_fails('set cscopequickfix=s-a', 'E474:') endfunc + +func Test_withoutCscopeConnection() + call assert_equal(cscope_connection(), 0) + + call assert_fails('cscope find s main', 'E567:') + let a=execute('cscope show') + call assert_match('no cscope connections', a) +endfunc + + +" vim: shiftwidth=2 sts=2 expandtab diff --git a/src/nvim/testdir/test_digraph.vim b/src/nvim/testdir/test_digraph.vim new file mode 100644 index 0000000000..95500853f2 --- /dev/null +++ b/src/nvim/testdir/test_digraph.vim @@ -0,0 +1,461 @@ +" Tests for digraphs + +if !has("digraphs") || !has("multi_byte") + finish +endif + +func! Put_Dig(chars) + exe "norm! o\<c-k>".a:chars +endfu + +func! Put_Dig_BS(char1, char2) + exe "norm! o".a:char1."\<bs>".a:char2 +endfu + +func! Test_digraphs() + new + call Put_Dig("00") + call assert_equal("∞", getline('.')) + " not a digraph + call Put_Dig("el") + call assert_equal("l", getline('.')) + call Put_Dig("ht") + call assert_equal("þ", getline('.')) + " digraph "ab" is the same as "ba" + call Put_Dig("ab") + call Put_Dig("ba") + call assert_equal(["ば","ば"], getline(line('.')-1,line('.'))) + " Euro sign + call Put_Dig("e=") + call Put_Dig("=e") + call Put_Dig("Eu") + call Put_Dig("uE") + call assert_equal(['е']+repeat(["€"],3), getline(line('.')-3,line('.'))) + " Rouble sign + call Put_Dig("R=") + call Put_Dig("=R") + call Put_Dig("=P") + call Put_Dig("P=") + call assert_equal(['Р']+repeat(["₽"],2)+['П'], getline(line('.')-3,line('.'))) + " Not a digraph + call Put_Dig("a\<bs>") + call Put_Dig("\<bs>a") + call assert_equal(["<BS>", "<BS>a"], getline(line('.')-1,line('.'))) + " Grave + call Put_Dig("a!") + call Put_Dig("!e") + call Put_Dig("b!") " not defined + call assert_equal(["à", "è", "!"], getline(line('.')-2,line('.'))) + " Acute accent + call Put_Dig("a'") + call Put_Dig("'e") + call Put_Dig("b'") " not defined + call assert_equal(["á", "é", "'"], getline(line('.')-2,line('.'))) + " Cicumflex + call Put_Dig("a>") + call Put_Dig(">e") + call Put_Dig("b>") " not defined + call assert_equal(['â', 'ê', '>'], getline(line('.')-2,line('.'))) + " Tilde + call Put_Dig("o~") + call Put_Dig("~u") " not defined + call Put_Dig("z~") " not defined + call assert_equal(['õ', 'u', '~'], getline(line('.')-2,line('.'))) + " Tilde + call Put_Dig("o?") + call Put_Dig("?u") + call Put_Dig("z?") " not defined + call assert_equal(['õ', 'ũ', '?'], getline(line('.')-2,line('.'))) + " Macron + call Put_Dig("o-") + call Put_Dig("-u") + call Put_Dig("z-") " not defined + call assert_equal(['ō', 'ū', '-'], getline(line('.')-2,line('.'))) + " Breve + call Put_Dig("o(") + call Put_Dig("(u") + call Put_Dig("z(") " not defined + call assert_equal(['ŏ', 'ŭ', '('], getline(line('.')-2,line('.'))) + " Dot above + call Put_Dig("b.") + call Put_Dig(".e") + call Put_Dig("a.") " not defined + call assert_equal(['ḃ', 'ė', '.'], getline(line('.')-2,line('.'))) + " Diaresis + call Put_Dig("a:") + call Put_Dig(":u") + call Put_Dig("b:") " not defined + call assert_equal(['ä', 'ü', ':'], getline(line('.')-2,line('.'))) + " Cedilla + call Put_Dig("',") + call Put_Dig(",C") + call Put_Dig("b,") " not defined + call assert_equal(['¸', 'Ç', ','], getline(line('.')-2,line('.'))) + " Underline + call Put_Dig("B_") + call Put_Dig("_t") + call Put_Dig("a_") " not defined + call assert_equal(['Ḇ', 'ṯ', '_'], getline(line('.')-2,line('.'))) + " Stroke + call Put_Dig("j/") + call Put_Dig("/l") + call Put_Dig("b/") " not defined + call assert_equal(['/', 'ł', '/'], getline(line('.')-2,line('.'))) + " Double acute + call Put_Dig('O"') + call Put_Dig('"y') + call Put_Dig('b"') " not defined + call assert_equal(['Ő', 'ÿ', '"'], getline(line('.')-2,line('.'))) + " Ogonek + call Put_Dig('u;') + call Put_Dig(';E') + call Put_Dig('b;') " not defined + call assert_equal(['ų', 'Ę', ';'], getline(line('.')-2,line('.'))) + " Caron + call Put_Dig('u<') + call Put_Dig('<E') + call Put_Dig('b<') " not defined + call assert_equal(['ǔ', 'Ě', '<'], getline(line('.')-2,line('.'))) + " Ring above + call Put_Dig('u0') + call Put_Dig('0E') " not defined + call Put_Dig('b0') " not defined + call assert_equal(['ů', 'E', '0'], getline(line('.')-2,line('.'))) + " Hook + call Put_Dig('u2') + call Put_Dig('2E') + call Put_Dig('b2') " not defined + call assert_equal(['ủ', 'Ẻ', '2'], getline(line('.')-2,line('.'))) + " Horn + call Put_Dig('u9') + call Put_Dig('9E') " not defined + call Put_Dig('b9') " not defined + call assert_equal(['ư', 'E', '9'], getline(line('.')-2,line('.'))) + " Cyrillic + call Put_Dig('u=') + call Put_Dig('=b') + call Put_Dig('=_') + call assert_equal(['у', 'б', '〓'], getline(line('.')-2,line('.'))) + " Greek + call Put_Dig('u*') + call Put_Dig('*b') + call Put_Dig('*_') + call assert_equal(['υ', 'β', '々'], getline(line('.')-2,line('.'))) + " Greek/Cyrillic special + call Put_Dig('u%') + call Put_Dig('%b') " not defined + call Put_Dig('%_') " not defined + call assert_equal(['ύ', 'b', '_'], getline(line('.')-2,line('.'))) + " Arabic + call Put_Dig('u+') + call Put_Dig('+b') + call Put_Dig('+_') " japanese industrial symbol + call assert_equal(['+', 'ب', '〄'], getline(line('.')-2,line('.'))) + " Hebrew + call Put_Dig('Q+') + call Put_Dig('+B') + call Put_Dig('+X') + call assert_equal(['ק', 'ב', 'ח'], getline(line('.')-2,line('.'))) + " Latin + call Put_Dig('a3') + call Put_Dig('A3') + call Put_Dig('3X') + call assert_equal(['ǣ', 'Ǣ', 'X'], getline(line('.')-2,line('.'))) + " Bopomofo + call Put_Dig('a4') + call Put_Dig('A4') + call Put_Dig('4X') + call assert_equal(['ㄚ', '4', 'X'], getline(line('.')-2,line('.'))) + " Hiragana + call Put_Dig('a5') + call Put_Dig('A5') + call Put_Dig('5X') + call assert_equal(['あ', 'ぁ', 'X'], getline(line('.')-2,line('.'))) + " Katakana + call Put_Dig('a6') + call Put_Dig('A6') + call Put_Dig('6X') + call assert_equal(['ァ', 'ア', 'X'], getline(line('.')-2,line('.'))) + " Superscripts + call Put_Dig('1S') + call Put_Dig('2S') + call Put_Dig('3S') + call assert_equal(['¹', '²', '³'], getline(line('.')-2,line('.'))) + " Subscripts + call Put_Dig('1s') + call Put_Dig('2s') + call Put_Dig('3s') + call assert_equal(['₁', '₂', '₃'], getline(line('.')-2,line('.'))) + " Eszet (only lowercase) + call Put_Dig("ss") + call Put_Dig("SS") " start of string + call assert_equal(["ß", ""], getline(line('.')-1,line('.'))) + " High bit set + call Put_Dig("a ") + call Put_Dig(" A") + call assert_equal(['á', 'Á'], getline(line('.')-1,line('.'))) + " Escape is not part of a digraph + call Put_Dig("a\<esc>") + call Put_Dig("\<esc>A") + call assert_equal(['', 'A'], getline(line('.')-1,line('.'))) + " define some custom digraphs + " old: 00 ∞ + " old: el l + digraph 00 9216 + digraph el 0252 + call Put_Dig("00") + call Put_Dig("el") + " Reset digraphs + digraph 00 8734 + digraph el 108 + call Put_Dig("00") + call Put_Dig("el") + call assert_equal(['␀', 'ü', '∞', 'l'], getline(line('.')-3,line('.'))) + bw! +endfunc + +func! Test_digraphs_option() + " reset whichwrap option, so that testing <esc><bs>A works, + " without moving up a line + set digraph ww= + new + call Put_Dig_BS("0","0") + call assert_equal("∞", getline('.')) + " not a digraph + call Put_Dig_BS("e","l") + call assert_equal("l", getline('.')) + call Put_Dig_BS("h","t") + call assert_equal("þ", getline('.')) + " digraph "ab" is the same as "ba" + call Put_Dig_BS("a","b") + call Put_Dig_BS("b","a") + call assert_equal(["ば","ば"], getline(line('.')-1,line('.'))) + " Euro sign + call Put_Dig_BS("e","=") + call Put_Dig_BS("=","e") + call Put_Dig_BS("E","u") + call Put_Dig_BS("u","E") + call assert_equal(['е']+repeat(["€"],3), getline(line('.')-3,line('.'))) + " Rouble sign + call Put_Dig_BS("R","=") + call Put_Dig_BS("=","R") + call Put_Dig_BS("=","P") + call Put_Dig_BS("P","=") + call assert_equal(['Р']+repeat(["₽"],2)+['П'], getline(line('.')-3,line('.'))) + " Not a digraph: this is different from <c-k>! + call Put_Dig_BS("a","\<bs>") + call Put_Dig_BS("\<bs>","a") + call assert_equal(['','a'], getline(line('.')-1,line('.'))) + " Grave + call Put_Dig_BS("a","!") + call Put_Dig_BS("!","e") + call Put_Dig_BS("b","!") " not defined + call assert_equal(["à", "è", "!"], getline(line('.')-2,line('.'))) + " Acute accent + call Put_Dig_BS("a","'") + call Put_Dig_BS("'","e") + call Put_Dig_BS("b","'") " not defined + call assert_equal(["á", "é", "'"], getline(line('.')-2,line('.'))) + " Cicumflex + call Put_Dig_BS("a",">") + call Put_Dig_BS(">","e") + call Put_Dig_BS("b",">") " not defined + call assert_equal(['â', 'ê', '>'], getline(line('.')-2,line('.'))) + " Tilde + call Put_Dig_BS("o","~") + call Put_Dig_BS("~","u") " not defined + call Put_Dig_BS("z","~") " not defined + call assert_equal(['õ', 'u', '~'], getline(line('.')-2,line('.'))) + " Tilde + call Put_Dig_BS("o","?") + call Put_Dig_BS("?","u") + call Put_Dig_BS("z","?") " not defined + call assert_equal(['õ', 'ũ', '?'], getline(line('.')-2,line('.'))) + " Macron + call Put_Dig_BS("o","-") + call Put_Dig_BS("-","u") + call Put_Dig_BS("z","-") " not defined + call assert_equal(['ō', 'ū', '-'], getline(line('.')-2,line('.'))) + " Breve + call Put_Dig_BS("o","(") + call Put_Dig_BS("(","u") + call Put_Dig_BS("z","(") " not defined + call assert_equal(['ŏ', 'ŭ', '('], getline(line('.')-2,line('.'))) + " Dot above + call Put_Dig_BS("b",".") + call Put_Dig_BS(".","e") + call Put_Dig_BS("a",".") " not defined + call assert_equal(['ḃ', 'ė', '.'], getline(line('.')-2,line('.'))) + " Diaresis + call Put_Dig_BS("a",":") + call Put_Dig_BS(":","u") + call Put_Dig_BS("b",":") " not defined + call assert_equal(['ä', 'ü', ':'], getline(line('.')-2,line('.'))) + " Cedilla + call Put_Dig_BS("'",",") + call Put_Dig_BS(",","C") + call Put_Dig_BS("b",",") " not defined + call assert_equal(['¸', 'Ç', ','], getline(line('.')-2,line('.'))) + " Underline + call Put_Dig_BS("B","_") + call Put_Dig_BS("_","t") + call Put_Dig_BS("a","_") " not defined + call assert_equal(['Ḇ', 'ṯ', '_'], getline(line('.')-2,line('.'))) + " Stroke + call Put_Dig_BS("j","/") + call Put_Dig_BS("/","l") + call Put_Dig_BS("b","/") " not defined + call assert_equal(['/', 'ł', '/'], getline(line('.')-2,line('.'))) + " Double acute + call Put_Dig_BS('O','"') + call Put_Dig_BS('"','y') + call Put_Dig_BS('b','"') " not defined + call assert_equal(['Ő', 'ÿ', '"'], getline(line('.')-2,line('.'))) + " Ogonek + call Put_Dig_BS('u',';') + call Put_Dig_BS(';','E') + call Put_Dig_BS('b',';') " not defined + call assert_equal(['ų', 'Ę', ';'], getline(line('.')-2,line('.'))) + " Caron + call Put_Dig_BS('u','<') + call Put_Dig_BS('<','E') + call Put_Dig_BS('b','<') " not defined + call assert_equal(['ǔ', 'Ě', '<'], getline(line('.')-2,line('.'))) + " Ring above + call Put_Dig_BS('u','0') + call Put_Dig_BS('0','E') " not defined + call Put_Dig_BS('b','0') " not defined + call assert_equal(['ů', 'E', '0'], getline(line('.')-2,line('.'))) + " Hook + call Put_Dig_BS('u','2') + call Put_Dig_BS('2','E') + call Put_Dig_BS('b','2') " not defined + call assert_equal(['ủ', 'Ẻ', '2'], getline(line('.')-2,line('.'))) + " Horn + call Put_Dig_BS('u','9') + call Put_Dig_BS('9','E') " not defined + call Put_Dig_BS('b','9') " not defined + call assert_equal(['ư', 'E', '9'], getline(line('.')-2,line('.'))) + " Cyrillic + call Put_Dig_BS('u','=') + call Put_Dig_BS('=','b') + call Put_Dig_BS('=','_') + call assert_equal(['у', 'б', '〓'], getline(line('.')-2,line('.'))) + " Greek + call Put_Dig_BS('u','*') + call Put_Dig_BS('*','b') + call Put_Dig_BS('*','_') + call assert_equal(['υ', 'β', '々'], getline(line('.')-2,line('.'))) + " Greek/Cyrillic special + call Put_Dig_BS('u','%') + call Put_Dig_BS('%','b') " not defined + call Put_Dig_BS('%','_') " not defined + call assert_equal(['ύ', 'b', '_'], getline(line('.')-2,line('.'))) + " Arabic + call Put_Dig_BS('u','+') + call Put_Dig_BS('+','b') + call Put_Dig_BS('+','_') " japanese industrial symbol + call assert_equal(['+', 'ب', '〄'], getline(line('.')-2,line('.'))) + " Hebrew + call Put_Dig_BS('Q','+') + call Put_Dig_BS('+','B') + call Put_Dig_BS('+','X') + call assert_equal(['ק', 'ב', 'ח'], getline(line('.')-2,line('.'))) + " Latin + call Put_Dig_BS('a','3') + call Put_Dig_BS('A','3') + call Put_Dig_BS('3','X') + call assert_equal(['ǣ', 'Ǣ', 'X'], getline(line('.')-2,line('.'))) + " Bopomofo + call Put_Dig_BS('a','4') + call Put_Dig_BS('A','4') + call Put_Dig_BS('4','X') + call assert_equal(['ㄚ', '4', 'X'], getline(line('.')-2,line('.'))) + " Hiragana + call Put_Dig_BS('a','5') + call Put_Dig_BS('A','5') + call Put_Dig_BS('5','X') + call assert_equal(['あ', 'ぁ', 'X'], getline(line('.')-2,line('.'))) + " Katakana + call Put_Dig_BS('a','6') + call Put_Dig_BS('A','6') + call Put_Dig_BS('6','X') + call assert_equal(['ァ', 'ア', 'X'], getline(line('.')-2,line('.'))) + " Superscripts + call Put_Dig_BS('1','S') + call Put_Dig_BS('2','S') + call Put_Dig_BS('3','S') + call assert_equal(['¹', '²', '³'], getline(line('.')-2,line('.'))) + " Subscripts + call Put_Dig_BS('1','s') + call Put_Dig_BS('2','s') + call Put_Dig_BS('3','s') + call assert_equal(['₁', '₂', '₃'], getline(line('.')-2,line('.'))) + " Eszet (only lowercase) + call Put_Dig_BS("s","s") + call Put_Dig_BS("S","S") " start of string + call assert_equal(["ß", ""], getline(line('.')-1,line('.'))) + " High bit set (different from <c-k>) + call Put_Dig_BS("a"," ") + call Put_Dig_BS(" ","A") + call assert_equal([' ', 'A'], getline(line('.')-1,line('.'))) + " Escape is not part of a digraph (different from <c-k>) + call Put_Dig_BS("a","\<esc>") + call Put_Dig_BS("\<esc>","A") + call assert_equal(['', ''], getline(line('.')-1,line('.'))) + " define some custom digraphs + " old: 00 ∞ + " old: el l + digraph 00 9216 + digraph el 0252 + call Put_Dig_BS("0","0") + call Put_Dig_BS("e","l") + " Reset digraphs + digraph 00 8734 + digraph el 108 + call Put_Dig_BS("0","0") + call Put_Dig_BS("e","l") + call assert_equal(['␀', 'ü', '∞', 'l'], getline(line('.')-3,line('.'))) + set nodigraph ww&vim + bw! +endfunc + +func! Test_digraphs_output() + new + let out = execute(':digraph') + call assert_equal('Eu € 8364', matchstr(out, '\C\<Eu\D*8364\>')) + call assert_equal('=e € 8364', matchstr(out, '\C=e\D*8364\>')) + call assert_equal('=R ₽ 8381', matchstr(out, '\C=R\D*8381\>')) + call assert_equal('=P ₽ 8381', matchstr(out, '\C=P\D*8381\>')) + call assert_equal('o: ö 246', matchstr(out, '\C\<o:\D*246\>')) + call assert_equal('v4 ㄪ 12586', matchstr(out, '\C\<v4\D*12586\>')) + call assert_equal("'0 ˚ 730", matchstr(out, '\C''0\D*730\>')) + call assert_equal('Z% Ж 1046', matchstr(out, '\C\<Z%\D*1046\>')) + call assert_equal('u- ū 363', matchstr(out, '\C\<u-\D*363\>')) + call assert_equal('SH ^A 1', matchstr(out, '\C\<SH\D*1\>')) + bw! +endfunc + +func! Test_loadkeymap() + if !has('keymap') + return + endif + new + set keymap=czech + set iminsert=0 + call feedkeys("o|\<c-^>|01234567890|\<esc>", 'tx') + call assert_equal("|'é+ěščřžýáíé'", getline('.')) + " reset keymap and encoding option + set keymap= + bw! +endfunc + +func! Test_digraph_cmndline() + " Create digraph on commandline + " This is a hack, to let Vim create the digraph in commandline mode + let s = '' + exe "sil! norm! :let s.='\<c-k>Eu'\<cr>" + call assert_equal("€", s) +endfunc + +" vim: tabstop=2 shiftwidth=0 sts=-1 expandtab diff --git a/src/nvim/version.c b/src/nvim/version.c index ee2288e1b0..763447295b 100644 --- a/src/nvim/version.c +++ b/src/nvim/version.c @@ -145,7 +145,7 @@ static int included_patches[] = { // 2298 NA // 2297 NA // 2296, - // 2295, + 2295, 2294, // 2293, // 2292, @@ -265,7 +265,7 @@ static int included_patches[] = { // 2178, // 2177, // 2176 NA - // 2175, + 2175, 2174, // 2173, // 2172, @@ -281,7 +281,7 @@ static int included_patches[] = { 2162, // 2161, 2160, - // 2159, + 2159, 2158, // 2157 NA // 2156 NA @@ -292,7 +292,7 @@ static int included_patches[] = { // 2151, // 2150 NA 2149, - // 2148, + 2148, 2147, 2146, // 2145 NA @@ -333,8 +333,8 @@ static int included_patches[] = { 2110, 2109, // 2108 NA - // 2107, - // 2106, + 2107, + 2106, // 2105 NA // 2104, 2103, @@ -352,13 +352,13 @@ static int included_patches[] = { // 2091 NA // 2090, // 2089 NA - // 2088, - // 2087, + 2088, + 2087, 2086, - // 2085, - // 2084, + 2085, + 2084, // 2083, - // 2082, + 2082, 2081, // 2080, // 2079 NA |