From 3a375c239955744d70041d30d40e9307dc05b3d0 Mon Sep 17 00:00:00 2001 From: Johannes Altmanninger Date: Sun, 1 Aug 2021 17:41:56 +0200 Subject: [PATCH] reader: fix regressions when moving between lines Fixes some regressions from 35ca42413 ("Simplify some parse_util functions"). The tmux tests are not beautiful but I find them easy to write. Probably a pexpect test would also be enough here? --- src/parse_util.cpp | 19 ++++++++++--------- tests/checks/tmux-bind.fish | 36 ++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 9 deletions(-) create mode 100644 tests/checks/tmux-bind.fish diff --git a/src/parse_util.cpp b/src/parse_util.cpp index be5a8e5eb..9671bfeec 100644 --- a/src/parse_util.cpp +++ b/src/parse_util.cpp @@ -54,8 +54,8 @@ int parse_util_lineno(const wcstring &str, size_t offset) { int parse_util_get_line_from_offset(const wcstring &str, size_t pos) { // Return the line pos is on, or -1 if it's after the end. - if (str.length() > pos) return -1; - return std::count(str.begin() + pos, str.end(), L'\n'); + if (pos > str.length()) return -1; + return std::count(str.begin(), str.begin() + pos, L'\n'); } size_t parse_util_get_offset_from_line(const wcstring &str, int line) { @@ -63,10 +63,11 @@ size_t parse_util_get_offset_from_line(const wcstring &str, int line) { if (line < 0) return static_cast(-1); if (line == 0) return 0; - ssize_t i = 0; - while (auto pos = str.find(L'\n')) { - i++; - if (i == line) return pos + 1; + size_t pos = -1; + int count = 0; + while ((pos = str.find(L'\n', pos + 1)) != wcstring::npos) { + count++; + if (count == line) return pos + 1; } return static_cast(-1); } @@ -222,7 +223,6 @@ long parse_util_slice_length(const wchar_t *in) { return -1; } - int parse_util_locate_cmdsubst_range(const wcstring &str, size_t *inout_cursor_offset, wcstring *out_contents, size_t *out_start, size_t *out_end, bool accept_incomplete, bool *out_is_quoted) { @@ -1112,8 +1112,9 @@ static bool detect_errors_in_decorated_statement(const wcstring &buff_src, const wcstring &com = dst.command.source(buff_src, storage); if (com == L"$status") { parse_error_offset_source_start(parse_errors, source_start); - errored = append_syntax_error(parse_errors, source_start, - _(L"$status is not valid as a command. See `help conditions`")); + errored = + append_syntax_error(parse_errors, source_start, + _(L"$status is not valid as a command. See `help conditions`")); } const wcstring &unexp_command = dst.command.source(buff_src, storage); diff --git a/tests/checks/tmux-bind.fish b/tests/checks/tmux-bind.fish new file mode 100644 index 000000000..d15cb85d7 --- /dev/null +++ b/tests/checks/tmux-bind.fish @@ -0,0 +1,36 @@ +#RUN: %fish -C 'set -g fish %fish' %s +#REQUIRES: command -v tmux + +set fish (builtin realpath $fish) + +# Isolated tmux. +set -g tmpdir (mktemp -d) + +# Don't CD elsewhere, because tmux socket file is relative to CWD. Using +# absolute path to socket file is prone to 'socket file name too long' error. +cd $tmpdir + +set -g tmux tmux -S .tmux-socket -f /dev/null + +set -g sleep sleep .1 +set -q CI && set sleep sleep 1 + + +$tmux new-session -x 80 -y 10 -d $fish -C ' + # This is similar to "tests/interactive.config". + function fish_greeting; end + function fish_prompt; printf "prompt $status_generation> "; end + # No autosuggestion from older history. + set fish_history "" +' +$sleep # Let fish draw a prompt. + +# Test moving around with up-or-search on a multi-line commandline. +$tmux send-keys 'echo 12' M-Enter 'echo ab' C-p 345 C-n cde +$sleep +$tmux capture-pane -p +# CHECK: prompt 0> echo 12345 +# CHECK: echo abcde + +$tmux kill-server +rm -r $tmpdir