diff options
45 files changed, 495 insertions, 486 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 41a22af538..ea3185d2a1 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -80,11 +80,11 @@ jobs: run: ./ci/before_script.sh - name: Build nvim - run: ./ci/run_tests.sh build + run: ./ci/run_tests.sh build_nvim - if: "!cancelled()" - name: clint - run: ./ci/run_lint.sh clint + name: clint-full + run: ./ci/run_lint.sh clint-full - if: "!cancelled()" name: lualint @@ -99,8 +99,8 @@ jobs: run: ./ci/run_lint.sh shlint - if: "!cancelled()" - name: single-includes - run: ./ci/run_lint.sh single-includes + name: check-single-includes + run: ./ci/run_lint.sh check-single-includes - name: Cache dependencies run: ./ci/before_cache.sh @@ -201,7 +201,7 @@ jobs: run: ./ci/before_script.sh - name: Build - run: ./ci/run_tests.sh build + run: ./ci/run_tests.sh build_nvim - if: matrix.flavor != 'tsan' && matrix.flavor != 'functionaltest-lua' && !cancelled() name: Unittests diff --git a/ci/common/suite.sh b/ci/common/suite.sh index 5110e22ec2..c0c470dce1 100644 --- a/ci/common/suite.sh +++ b/ci/common/suite.sh @@ -1,9 +1,3 @@ -# HACK: get newline for use in strings given that "\n" and $'' do not work. -NL="$(printf '\nE')" -NL="${NL%E}" - -FAIL_SUMMARY="" - # Test success marker. If END_MARKER file exists, we know that all tests # finished. If FAIL_SUMMARY_FILE exists we know that some tests failed, this # file will contain information about failed tests. Build is considered @@ -11,35 +5,15 @@ FAIL_SUMMARY="" END_MARKER="$BUILD_DIR/.tests_finished" FAIL_SUMMARY_FILE="$BUILD_DIR/.test_errors" -enter_suite() { - FAILED=0 - rm -f "${END_MARKER}" - local suite_name="$1" - export NVIM_TEST_CURRENT_SUITE="${NVIM_TEST_CURRENT_SUITE}/$suite_name" -} - -exit_suite() { - if test $FAILED -ne 0 ; then - echo "Suite ${NVIM_TEST_CURRENT_SUITE} failed, summary:" - echo "${FAIL_SUMMARY}" - fi - export NVIM_TEST_CURRENT_SUITE="${NVIM_TEST_CURRENT_SUITE%/*}" - FAILED=0 -} - fail() { local test_name="$1" - local fail_char="$2" - local message="$3" + local message="$2" - : ${fail_char:=F} : ${message:=Test $test_name failed} - local full_msg="$fail_char $NVIM_TEST_CURRENT_SUITE|$test_name :: $message" - FAIL_SUMMARY="${FAIL_SUMMARY}${NL}${full_msg}" + local full_msg="$test_name :: $message" echo "${full_msg}" >> "${FAIL_SUMMARY_FILE}" echo "Failed: $full_msg" - FAILED=1 } ended_successfully() { @@ -64,13 +38,3 @@ end_tests() { touch "${END_MARKER}" ended_successfully } - -run_suite() { - local command="$1" - local suite_name="$2" - - enter_suite "$suite_name" - eval "$command" || fail "$suite_name" - exit_suite -} - diff --git a/ci/common/test.sh b/ci/common/test.sh index f211a2e7aa..7db39a0e5f 100644 --- a/ci/common/test.sh +++ b/ci/common/test.sh @@ -51,7 +51,7 @@ check_core_dumps() { fi done if test "$app" != quiet ; then - fail 'cores' E 'Core dumps found' + fail 'cores' 'Core dumps found' fi } @@ -72,7 +72,7 @@ check_logs() { rm "${log}" done if test -n "${err}" ; then - fail 'logs' E 'Runtime errors detected.' + fail 'logs' 'Runtime errors detected.' fi } @@ -86,19 +86,19 @@ check_sanitizer() { fi } -run_unittests() {( +unittests() {( ulimit -c unlimited || true if ! build_make unittest ; then - fail 'unittests' F 'Unit tests failed' + fail 'unittests' 'Unit tests failed' fi submit_coverage unittest check_core_dumps "$(command -v luajit)" )} -run_functionaltests() {( +functionaltests() {( ulimit -c unlimited || true if ! build_make ${FUNCTIONALTEST}; then - fail 'functionaltests' F 'Functional tests failed' + fail 'functionaltests' 'Functional tests failed' fi submit_coverage functionaltest check_sanitizer "${LOG_DIR}" @@ -106,11 +106,11 @@ run_functionaltests() {( check_core_dumps )} -run_oldtests() {( +oldtests() {( ulimit -c unlimited || true if ! make oldtest; then reset - fail 'oldtests' F 'Legacy tests failed' + fail 'oldtests' 'Legacy tests failed' fi submit_coverage oldtest check_sanitizer "${LOG_DIR}" @@ -129,26 +129,25 @@ check_runtime_files() {( # Prefer failing the build over using more robust construct because files # with IFS are not welcome. if ! test -e "$file" ; then - fail "$test_name" E \ - "It appears that $file is only a part of the file name" + fail "$test_name" "It appears that $file is only a part of the file name" fi if ! test "$tst" "$INSTALL_PREFIX/share/nvim/runtime/$file" ; then - fail "$test_name" F "$(printf "$message" "$file")" + fail "$test_name" "$(printf "$message" "$file")" fi done )} install_nvim() {( if ! build_make install ; then - fail 'install' E 'make install failed' - exit_suite + fail 'install' 'make install failed' + exit 1 fi "${INSTALL_PREFIX}/bin/nvim" --version if ! "${INSTALL_PREFIX}/bin/nvim" -u NONE -e -c ':help' -c ':qall' ; then echo "Running ':help' in the installed nvim failed." echo "Maybe the helptags have not been generated properly." - fail 'help' F 'Failed running :help' + fail 'help' 'Failed running :help' fi # Check that all runtime files were installed @@ -169,6 +168,6 @@ install_nvim() {( local genvimsynf=syntax/vim/generated.vim local gpat='syn keyword vimFuncName .*eval' if ! grep -q "$gpat" "${INSTALL_PREFIX}/share/nvim/runtime/$genvimsynf" ; then - fail 'funcnames' F "It appears that $genvimsynf does not contain $gpat." + fail 'funcnames' "It appears that $genvimsynf does not contain $gpat." fi )} diff --git a/ci/run_lint.sh b/ci/run_lint.sh index 2fea7a40c0..3a524b4ed6 100755 --- a/ci/run_lint.sh +++ b/ci/run_lint.sh @@ -8,34 +8,17 @@ CI_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" source "${CI_DIR}/common/build.sh" source "${CI_DIR}/common/suite.sh" -if [[ "$GITHUB_ACTIONS" != "true" ]]; then - run_suite 'make clint-full' 'clint' - run_suite 'make lualint' 'lualint' - run_suite 'make pylint' 'pylint' - run_suite 'make shlint' 'shlint' - run_suite 'make check-single-includes' 'single-includes' +rm -f "$END_MARKER" - end_tests +# Run all tests if no input argument is given +if (($# == 0)); then + tests=('clint-full' 'lualint' 'pylint' 'shlint' 'check-single-includes') else - case "$1" in - clint) - run_suite 'make clint-full' 'clint' - ;; - lualint) - run_suite 'make lualint' 'lualint' - ;; - pylint) - run_suite 'make pylint' 'pylint' - ;; - shlint) - run_suite 'make shlint' 'shlint' - ;; - single-includes) - run_suite 'make check-single-includes' 'single-includes' - ;; - *) - :;; - esac - - end_tests + tests=("$@") fi + +for i in "${tests[@]}"; do + make "$i" || fail "$i" +done + +end_tests diff --git a/ci/run_tests.sh b/ci/run_tests.sh index ae85246ab6..23460b682e 100755 --- a/ci/run_tests.sh +++ b/ci/run_tests.sh @@ -8,42 +8,28 @@ source "${CI_DIR}/common/build.sh" source "${CI_DIR}/common/test.sh" source "${CI_DIR}/common/suite.sh" +rm -f "$END_MARKER" -if [[ "$GITHUB_ACTIONS" != "true" ]]; then - run_suite 'build_nvim' 'build' +# Run all tests (with some caveats) if no input argument is given +if (($# == 0)); then + tests=('build_nvim') if test "$CLANG_SANITIZER" != "TSAN"; then # Additional threads are only created when the builtin UI starts, which # doesn't happen in the unit/functional tests if test "${FUNCTIONALTEST}" != "functionaltest-lua"; then - run_suite run_unittests unittests + tests+=('unittests') fi - run_suite run_functionaltests functionaltests + tests+=('functionaltests') fi - run_suite run_oldtests oldtests - run_suite install_nvim install_nvim - end_tests + tests+=('oldtests' 'install_nvim') else - case "$1" in - build) - run_suite 'build_nvim' 'build' - ;; - unittests) - run_suite 'run_unittests' 'unittests' - ;; - functionaltests) - run_suite 'run_functionaltests' 'functionaltests' - ;; - oldtests) - run_suite 'run_oldtests' 'oldtests' - ;; - install_nvim) - run_suite 'install_nvim' 'install_nvim' - ;; - *) - :;; - esac - - end_tests + tests=("$@") fi + +for i in "${tests[@]}"; do + eval "$i" || fail "$i" +done + +end_tests diff --git a/src/nvim/api/autocmd.c b/src/nvim/api/autocmd.c index 5ede0e5265..8a7dd00b2a 100644 --- a/src/nvim/api/autocmd.c +++ b/src/nvim/api/autocmd.c @@ -63,26 +63,26 @@ Array nvim_get_autocmds(Dict(get_autocmds) *opts, Error *err) int group = 0; switch (opts->group.type) { - case kObjectTypeNil: - break; - case kObjectTypeString: - group = augroup_find(opts->group.data.string.data); - if (group < 0) { - api_set_error(err, kErrorTypeValidation, "invalid augroup passed."); - goto cleanup; - } - break; - case kObjectTypeInteger: - group = (int)opts->group.data.integer; - char *name = augroup_name(group); - if (!augroup_exists(name)) { - api_set_error(err, kErrorTypeValidation, "invalid augroup passed."); - goto cleanup; - } - break; - default: - api_set_error(err, kErrorTypeValidation, "group must be a string or an integer."); + case kObjectTypeNil: + break; + case kObjectTypeString: + group = augroup_find(opts->group.data.string.data); + if (group < 0) { + api_set_error(err, kErrorTypeValidation, "invalid augroup passed."); goto cleanup; + } + break; + case kObjectTypeInteger: + group = (int)opts->group.data.integer; + char *name = augroup_name(group); + if (!augroup_exists(name)) { + api_set_error(err, kErrorTypeValidation, "invalid augroup passed."); + goto cleanup; + } + break; + default: + api_set_error(err, kErrorTypeValidation, "group must be a string or an integer."); + goto cleanup; } if (opts->event.type != kObjectTypeNil) { @@ -415,28 +415,28 @@ Integer nvim_create_autocmd(uint64_t channel_id, Object event, Dict(create_autoc bool is_nested = api_object_to_bool(opts->nested, "nested", false, err); switch (opts->group.type) { - case kObjectTypeNil: - break; - case kObjectTypeString: - au_group = augroup_find(opts->group.data.string.data); - if (au_group == AUGROUP_ERROR) { - api_set_error(err, - kErrorTypeValidation, - "invalid augroup: %s", opts->group.data.string.data); - goto cleanup; - } - break; - case kObjectTypeInteger: - au_group = (int)opts->group.data.integer; - char *name = augroup_name(au_group); - if (!augroup_exists(name)) { - api_set_error(err, kErrorTypeValidation, "invalid augroup: %d", au_group); - goto cleanup; - } - break; - default: - api_set_error(err, kErrorTypeValidation, "'group' must be a string or an integer."); + case kObjectTypeNil: + break; + case kObjectTypeString: + au_group = augroup_find(opts->group.data.string.data); + if (au_group == AUGROUP_ERROR) { + api_set_error(err, + kErrorTypeValidation, + "invalid augroup: %s", opts->group.data.string.data); goto cleanup; + } + break; + case kObjectTypeInteger: + au_group = (int)opts->group.data.integer; + char *name = augroup_name(au_group); + if (!augroup_exists(name)) { + api_set_error(err, kErrorTypeValidation, "invalid augroup: %d", au_group); + goto cleanup; + } + break; + default: + api_set_error(err, kErrorTypeValidation, "'group' must be a string or an integer."); + goto cleanup; } if (opts->pattern.type != kObjectTypeNil && opts->buffer.type != kObjectTypeNil) { @@ -659,28 +659,28 @@ void nvim_do_autocmd(Object event, Dict(do_autocmd) *opts, Error *err) } switch (opts->group.type) { - case kObjectTypeNil: - break; - case kObjectTypeString: - au_group = augroup_find(opts->group.data.string.data); - if (au_group == AUGROUP_ERROR) { - api_set_error(err, - kErrorTypeValidation, - "invalid augroup: %s", opts->group.data.string.data); - goto cleanup; - } - break; - case kObjectTypeInteger: - au_group = (int)opts->group.data.integer; - char *name = augroup_name(au_group); - if (!augroup_exists(name)) { - api_set_error(err, kErrorTypeValidation, "invalid augroup: %d", au_group); - goto cleanup; - } - break; - default: - api_set_error(err, kErrorTypeValidation, "'group' must be a string or an integer."); + case kObjectTypeNil: + break; + case kObjectTypeString: + au_group = augroup_find(opts->group.data.string.data); + if (au_group == AUGROUP_ERROR) { + api_set_error(err, + kErrorTypeValidation, + "invalid augroup: %s", opts->group.data.string.data); goto cleanup; + } + break; + case kObjectTypeInteger: + au_group = (int)opts->group.data.integer; + char *name = augroup_name(au_group); + if (!augroup_exists(name)) { + api_set_error(err, kErrorTypeValidation, "invalid augroup: %d", au_group); + goto cleanup; + } + break; + default: + api_set_error(err, kErrorTypeValidation, "'group' must be a string or an integer."); + goto cleanup; } if (opts->buffer.type != kObjectTypeNil) { diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index 3bddbe8fe6..a3af51008f 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -965,8 +965,7 @@ void nvim_buf_set_keymap(uint64_t channel_id, Buffer buffer, String mode, String /// @see |nvim_del_keymap()| /// /// @param buffer Buffer handle, or 0 for current buffer -void nvim_buf_del_keymap(uint64_t channel_id, Buffer buffer, String mode, - String lhs, Error *err) +void nvim_buf_del_keymap(uint64_t channel_id, Buffer buffer, String mode, String lhs, Error *err) FUNC_API_SINCE(6) { String rhs = { .data = "", .size = 0 }; @@ -1380,8 +1379,8 @@ Object nvim_buf_call(Buffer buffer, LuaRef fun, Error *err) /// @param buffer Buffer handle, or 0 for current buffer. /// @param[out] err Error details, if any. /// @see nvim_add_user_command -void nvim_buf_add_user_command(Buffer buffer, String name, Object command, - Dict(user_command) *opts, Error *err) +void nvim_buf_add_user_command(Buffer buffer, String name, Object command, Dict(user_command) *opts, + Error *err) FUNC_API_SINCE(9) { buf_T *target_buf = find_buffer_by_handle(buffer, err); diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c index 0ee8134ec4..e355f82f4d 100644 --- a/src/nvim/api/extmark.c +++ b/src/nvim/api/extmark.c @@ -8,6 +8,7 @@ #include "nvim/api/extmark.h" #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" +#include "nvim/decoration_provider.h" #include "nvim/extmark.h" #include "nvim/lua/executor.h" #include "nvim/memline.h" diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 1a324bfaa5..ebf4f65c91 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -22,6 +22,7 @@ #include "nvim/charset.h" #include "nvim/context.h" #include "nvim/decoration.h" +#include "nvim/decoration_provider.h" #include "nvim/edit.h" #include "nvim/eval.h" #include "nvim/eval/typval.h" @@ -722,15 +723,15 @@ Object nvim_get_option_value(String name, Dict(option) *opts, Error *err) break; case 2: switch (numval) { - case 0: - case 1: - rv = BOOLEAN_OBJ(numval); - break; - default: - // Boolean options that return something other than 0 or 1 should return nil. Currently this - // only applies to 'autoread' which uses -1 as a local value to indicate "unset" - rv = NIL; - break; + case 0: + case 1: + rv = BOOLEAN_OBJ(numval); + break; + default: + // Boolean options that return something other than 0 or 1 should return nil. Currently this + // only applies to 'autoread' which uses -1 as a local value to indicate "unset" + rv = NIL; + break; } break; default: diff --git a/src/nvim/autocmd.c b/src/nvim/autocmd.c index a850e5c1a0..dfcdfd8203 100644 --- a/src/nvim/autocmd.c +++ b/src/nvim/autocmd.c @@ -2428,9 +2428,8 @@ char *aucmd_exec_default_desc(AucmdExecutable acc) default: return NULL; } - - abort(); } + char *aucmd_exec_to_string(AutoCmd *ac, AucmdExecutable acc) { switch (acc.type) { diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c index b533f4c46f..94bf1feeee 100644 --- a/src/nvim/decoration.c +++ b/src/nvim/decoration.c @@ -523,59 +523,6 @@ void decor_add_ephemeral(int start_row, int start_col, int end_row, int end_col, } -DecorProvider *get_decor_provider(NS ns_id, bool force) -{ - size_t i; - size_t len = kv_size(decor_providers); - for (i = 0; i < len; i++) { - DecorProvider *item = &kv_A(decor_providers, i); - if (item->ns_id == ns_id) { - return item; - } else if (item->ns_id > ns_id) { - break; - } - } - - if (!force) { - return NULL; - } - - // Adding a new provider, so allocate room in the vector - (void)kv_a(decor_providers, len); - if (i < len) { - // New ns_id needs to be inserted between existing providers to maintain - // ordering, so shift other providers with larger ns_id - memmove(&kv_A(decor_providers, i + 1), - &kv_A(decor_providers, i), - (len - i) * sizeof(kv_a(decor_providers, i))); - } - DecorProvider *item = &kv_a(decor_providers, i); - *item = DECORATION_PROVIDER_INIT(ns_id); - - return item; -} - -void decor_provider_clear(DecorProvider *p) -{ - if (p == NULL) { - return; - } - NLUA_CLEAR_REF(p->redraw_start); - NLUA_CLEAR_REF(p->redraw_buf); - NLUA_CLEAR_REF(p->redraw_win); - NLUA_CLEAR_REF(p->redraw_line); - NLUA_CLEAR_REF(p->redraw_end); - p->active = false; -} - -void decor_free_all_mem(void) -{ - for (size_t i = 0; i < kv_size(decor_providers); i++) { - decor_provider_clear(&kv_A(decor_providers, i)); - } - kv_destroy(decor_providers); -} - int decor_virt_lines(win_T *wp, linenr_T lnum, VirtLines *lines) { diff --git a/src/nvim/decoration.h b/src/nvim/decoration.h index 2277a0ef1c..8df53caa0a 100644 --- a/src/nvim/decoration.h +++ b/src/nvim/decoration.h @@ -82,34 +82,15 @@ typedef struct { int eol_col; } DecorState; -typedef struct { - NS ns_id; - bool active; - LuaRef redraw_start; - LuaRef redraw_buf; - LuaRef redraw_win; - LuaRef redraw_line; - LuaRef redraw_end; - LuaRef hl_def; - int hl_valid; -} DecorProvider; - -EXTERN kvec_t(DecorProvider) decor_providers INIT(= KV_INITIAL_VALUE); EXTERN DecorState decor_state INIT(= { 0 }); -EXTERN bool provider_active INIT(= false); - -#define DECORATION_PROVIDER_INIT(ns_id) (DecorProvider) \ - { ns_id, false, LUA_NOREF, LUA_NOREF, \ - LUA_NOREF, LUA_NOREF, LUA_NOREF, \ - LUA_NOREF, -1 } static inline bool decor_has_sign(Decoration *decor) { return decor->sign_text - || decor->sign_hl_id - || decor->number_hl_id - || decor->line_hl_id - || decor->cursorline_hl_id; + || decor->sign_hl_id + || decor->number_hl_id + || decor->line_hl_id + || decor->cursorline_hl_id; } #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/src/nvim/decoration_provider.c b/src/nvim/decoration_provider.c new file mode 100644 index 0000000000..6efcb08b9d --- /dev/null +++ b/src/nvim/decoration_provider.c @@ -0,0 +1,231 @@ +// This is an open source non-commercial project. Dear PVS-Studio, please check +// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + +#include "nvim/api/extmark.h" +#include "nvim/api/private/helpers.h" +#include "nvim/buffer.h" +#include "nvim/decoration.h" +#include "nvim/decoration_provider.h" +#include "nvim/highlight.h" +#include "nvim/lua/executor.h" + +static kvec_t(DecorProvider) decor_providers = KV_INITIAL_VALUE; + +#define DECORATION_PROVIDER_INIT(ns_id) (DecorProvider) \ + { ns_id, false, LUA_NOREF, LUA_NOREF, \ + LUA_NOREF, LUA_NOREF, LUA_NOREF, \ + LUA_NOREF, -1 } + +static bool decor_provider_invoke(NS ns_id, const char *name, LuaRef ref, + Array args, bool default_true, char **perr) +{ + Error err = ERROR_INIT; + + textlock++; + provider_active = true; + Object ret = nlua_call_ref(ref, name, args, true, &err); + provider_active = false; + textlock--; + + if (!ERROR_SET(&err) + && api_object_to_bool(ret, "provider %s retval", default_true, &err)) { + return true; + } + + if (ERROR_SET(&err)) { + const char *ns_name = describe_ns(ns_id); + ELOG("error in provider %s:%s: %s", ns_name, name, err.msg); + bool verbose_errs = true; // TODO(bfredl): + if (verbose_errs && perr && *perr == NULL) { + static char errbuf[IOSIZE]; + snprintf(errbuf, sizeof errbuf, "%s: %s", ns_name, err.msg); + *perr = xstrdup(errbuf); + } + } + + api_free_object(ret); + return false; +} + +/// For each provider invoke the 'start' callback +/// +/// @param[out] providers Decoration providers +/// @param[out] err Provider err +void decor_providers_start(DecorProviders *providers, int type, char **err) +{ + kvi_init(*providers); + + for (size_t i = 0; i < kv_size(decor_providers); i++) { + DecorProvider *p = &kv_A(decor_providers, i); + if (!p->active) { + continue; + } + + bool active; + if (p->redraw_start != LUA_NOREF) { + FIXED_TEMP_ARRAY(args, 2); + args.items[0] = INTEGER_OBJ((int)display_tick); + args.items[1] = INTEGER_OBJ(type); + active = decor_provider_invoke(p->ns_id, "start", p->redraw_start, args, true, err); + } else { + active = true; + } + + if (active) { + kvi_push(*providers, p); + } + } +} + +/// For each provider run 'win'. If result is not false, then collect the +/// 'on_line' callback to call inside win_line +/// +/// @param wp Window +/// @param providers Decoration providers +/// @param[out] line_providers Enabled line providers to invoke in win_line +/// @param[out] err Provider error +void decor_providers_invoke_win(win_T *wp, DecorProviders *providers, + DecorProviders *line_providers, char **err) +{ + kvi_init(*line_providers); + + linenr_T knownmax = ((wp->w_valid & VALID_BOTLINE) + ? wp->w_botline + : (wp->w_topline + wp->w_height_inner)); + + for (size_t k = 0; k < kv_size(*providers); k++) { + DecorProvider *p = kv_A(*providers, k); + if (p && p->redraw_win != LUA_NOREF) { + FIXED_TEMP_ARRAY(args, 4); + args.items[0] = WINDOW_OBJ(wp->handle); + args.items[1] = BUFFER_OBJ(wp->w_buffer->handle); + // TODO(bfredl): we are not using this, but should be first drawn line? + args.items[2] = INTEGER_OBJ(wp->w_topline-1); + args.items[3] = INTEGER_OBJ(knownmax); + if (decor_provider_invoke(p->ns_id, "win", p->redraw_win, args, true, err)) { + kvi_push(*line_providers, p); + } + } + } + + win_check_ns_hl(wp); +} + +/// For each provider invoke the 'line' callback for a given window row. +/// +/// @param wp Window +/// @param providers Decoration providers +/// @param row Row to invoke line callback for +/// @param[out] has_decor Set when at least one provider invokes a line callback +/// @param[out] err Provider error +void providers_invoke_line(win_T *wp, DecorProviders *providers, int row, bool *has_decor, + char **err) +{ + for (size_t k = 0; k < kv_size(*providers); k++) { + DecorProvider *p = kv_A(*providers, k); + if (p && p->redraw_line != LUA_NOREF) { + FIXED_TEMP_ARRAY(args, 3); + args.items[0] = WINDOW_OBJ(wp->handle); + args.items[1] = BUFFER_OBJ(wp->w_buffer->handle); + args.items[2] = INTEGER_OBJ(row); + if (decor_provider_invoke(p->ns_id, "line", p->redraw_line, args, true, err)) { + *has_decor = true; + } else { + // return 'false' or error: skip rest of this window + kv_A(*providers, k) = NULL; + } + + win_check_ns_hl(wp); + } + } +} + + +/// For each provider invoke the 'buf' callback for a given buffer. +/// +/// @param buf Buffer +/// @param providers Decoration providers +/// @param[out] err Provider error +void decor_providers_invoke_buf(buf_T *buf, DecorProviders *providers, char **err) +{ + for (size_t i = 0; i < kv_size(*providers); i++) { + DecorProvider *p = kv_A(*providers, i); + if (p && p->redraw_buf != LUA_NOREF) { + FIXED_TEMP_ARRAY(args, 1); + args.items[0] = BUFFER_OBJ(buf->handle); + decor_provider_invoke(p->ns_id, "buf", p->redraw_buf, args, true, err); + } + } +} + + +/// For each provider invoke the 'end' callback +/// +/// @param providers Decoration providers +/// @param displaytick Display tick +/// @param[out] err Provider error +void decor_providers_invoke_end(DecorProviders *providers, char **err) +{ + for (size_t i = 0; i < kv_size(*providers); i++) { + DecorProvider *p = kv_A(*providers, i); + if (p && p->active && p->redraw_end != LUA_NOREF) { + FIXED_TEMP_ARRAY(args, 1); + args.items[0] = INTEGER_OBJ((int)display_tick); + decor_provider_invoke(p->ns_id, "end", p->redraw_end, args, true, err); + } + } +} + +DecorProvider *get_decor_provider(NS ns_id, bool force) +{ + size_t i; + size_t len = kv_size(decor_providers); + for (i = 0; i < len; i++) { + DecorProvider *item = &kv_A(decor_providers, i); + if (item->ns_id == ns_id) { + return item; + } else if (item->ns_id > ns_id) { + break; + } + } + + if (!force) { + return NULL; + } + + // Adding a new provider, so allocate room in the vector + (void)kv_a(decor_providers, len); + if (i < len) { + // New ns_id needs to be inserted between existing providers to maintain + // ordering, so shift other providers with larger ns_id + memmove(&kv_A(decor_providers, i + 1), + &kv_A(decor_providers, i), + (len - i) * sizeof(kv_a(decor_providers, i))); + } + DecorProvider *item = &kv_a(decor_providers, i); + *item = DECORATION_PROVIDER_INIT(ns_id); + + return item; +} + +void decor_provider_clear(DecorProvider *p) +{ + if (p == NULL) { + return; + } + NLUA_CLEAR_REF(p->redraw_start); + NLUA_CLEAR_REF(p->redraw_buf); + NLUA_CLEAR_REF(p->redraw_win); + NLUA_CLEAR_REF(p->redraw_line); + NLUA_CLEAR_REF(p->redraw_end); + p->active = false; +} + +void decor_free_all_mem(void) +{ + for (size_t i = 0; i < kv_size(decor_providers); i++) { + decor_provider_clear(&kv_A(decor_providers, i)); + } + kv_destroy(decor_providers); +} + diff --git a/src/nvim/decoration_provider.h b/src/nvim/decoration_provider.h new file mode 100644 index 0000000000..3ec7c80357 --- /dev/null +++ b/src/nvim/decoration_provider.h @@ -0,0 +1,26 @@ +#ifndef NVIM_DECORATION_PROVIDER_H +#define NVIM_DECORATION_PROVIDER_H + +#include "nvim/buffer_defs.h" + +typedef struct { + NS ns_id; + bool active; + LuaRef redraw_start; + LuaRef redraw_buf; + LuaRef redraw_win; + LuaRef redraw_line; + LuaRef redraw_end; + LuaRef hl_def; + int hl_valid; +} DecorProvider; + +typedef kvec_withinit_t(DecorProvider *, 4) DecorProviders; + +EXTERN bool provider_active INIT(= false); + +#ifdef INCLUDE_GENERATED_DECLARATIONS +# include "decoration_provider.h.generated.h" +#endif + +#endif // NVIM_DECORATION_PROVIDER_H diff --git a/src/nvim/eval.c b/src/nvim/eval.c index 8cdb03c341..83223cdd5c 100644 --- a/src/nvim/eval.c +++ b/src/nvim/eval.c @@ -2710,7 +2710,7 @@ bool next_for_item(void *fi_void, char_u *arg) tv.vval.v_string = vim_strnsave(fi->fi_string + fi->fi_byte_idx, len); fi->fi_byte_idx += len; const int result - = ex_let_vars(arg, &tv, true, fi->fi_semicolon, fi->fi_varcount, false, NULL) == OK; + = ex_let_vars(arg, &tv, true, fi->fi_semicolon, fi->fi_varcount, false, NULL) == OK; xfree(tv.vval.v_string); return result; } diff --git a/src/nvim/eval/funcs.c b/src/nvim/eval/funcs.c index d81a408663..85c49c20e7 100644 --- a/src/nvim/eval/funcs.c +++ b/src/nvim/eval/funcs.c @@ -7066,10 +7066,12 @@ static void init_srand(uint32_t *const x) if (dev_urandom_state != OK) { // Reading /dev/urandom doesn't work, fall back to time(). #endif + // uncrustify:off *x = time(NULL); #ifndef MSWIN } #endif + // uncrustify:on } static inline uint32_t splitmix32(uint32_t *const x) diff --git a/src/nvim/eval/typval.c b/src/nvim/eval/typval.c index d492c67877..2a432ecb47 100644 --- a/src/nvim/eval/typval.c +++ b/src/nvim/eval/typval.c @@ -1171,10 +1171,10 @@ void callback_put(Callback *cb, typval_T *tv) func_ref(cb->data.funcref); break; case kCallbackLua: - // TODO(tjdevries): Unified Callback. - // At this point this isn't possible, but it'd be nice to put - // these handled more neatly in one place. - // So instead, we just do the default and put nil + // TODO(tjdevries): Unified Callback. + // At this point this isn't possible, but it'd be nice to put + // these handled more neatly in one place. + // So instead, we just do the default and put nil default: tv->v_type = VAR_SPECIAL; tv->vval.v_special = kSpecialVarNull; diff --git a/src/nvim/event/rstream.c b/src/nvim/event/rstream.c index 3c43d1f98d..e51689543f 100644 --- a/src/nvim/event/rstream.c +++ b/src/nvim/event/rstream.c @@ -11,8 +11,8 @@ #include "nvim/event/loop.h" #include "nvim/event/rstream.h" #include "nvim/log.h" -#include "nvim/memory.h" #include "nvim/main.h" +#include "nvim/memory.h" #include "nvim/vim.h" #ifdef INCLUDE_GENERATED_DECLARATIONS diff --git a/src/nvim/ex_docmd.h b/src/nvim/ex_docmd.h index abf6ec347b..be9f97e27d 100644 --- a/src/nvim/ex_docmd.h +++ b/src/nvim/ex_docmd.h @@ -1,8 +1,8 @@ #ifndef NVIM_EX_DOCMD_H #define NVIM_EX_DOCMD_H -#include "nvim/ex_cmds_defs.h" #include "nvim/eval/funcs.h" +#include "nvim/ex_cmds_defs.h" #include "nvim/globals.h" // flags for do_cmdline() diff --git a/src/nvim/extmark.c b/src/nvim/extmark.c index 2916e3e978..6b879f5139 100644 --- a/src/nvim/extmark.c +++ b/src/nvim/extmark.c @@ -118,7 +118,7 @@ void extmark_set(buf_T *buf, uint32_t ns_id, uint32_t *idp, int row, colnr_T col } mtkey_t mark = { { row, col }, ns_id, id, 0, - mt_flags(right_gravity, decor_level), 0, NULL }; + mt_flags(right_gravity, decor_level), 0, NULL }; if (decor_full) { mark.decor_full = decor; } else if (decor) { diff --git a/src/nvim/extmark.h b/src/nvim/extmark.h index af9526cd43..b856a1148f 100644 --- a/src/nvim/extmark.h +++ b/src/nvim/extmark.h @@ -2,8 +2,8 @@ #define NVIM_EXTMARK_H #include "nvim/buffer_defs.h" -#include "nvim/extmark_defs.h" #include "nvim/decoration.h" +#include "nvim/extmark_defs.h" #include "nvim/marktree.h" #include "nvim/pos.h" diff --git a/src/nvim/fileio.c b/src/nvim/fileio.c index 971ae9abae..41e67e5b3b 100644 --- a/src/nvim/fileio.c +++ b/src/nvim/fileio.c @@ -3,6 +3,8 @@ // fileio.c: read from and write to a file +// uncrustify:off + #include <assert.h> #include <errno.h> #include <fcntl.h> diff --git a/src/nvim/highlight.c b/src/nvim/highlight.c index a1fd0d0d66..abbda1e9fa 100644 --- a/src/nvim/highlight.c +++ b/src/nvim/highlight.c @@ -5,6 +5,7 @@ #include "nvim/api/private/defs.h" #include "nvim/api/private/helpers.h" +#include "nvim/decoration_provider.h" #include "nvim/highlight.h" #include "nvim/highlight_defs.h" #include "nvim/lua/executor.h" @@ -819,9 +820,9 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e bool cterm_mask_provided = false; #define CHECK_FLAG(d, m, name, extra, flag) \ - if (api_object_to_bool(d->name ## extra, #name, false, err)) { \ - m = m | flag; \ - } + if (api_object_to_bool(d->name##extra, #name, false, err)) { \ + m = m | flag; \ + } CHECK_FLAG(dict, mask, bold, , HL_BOLD); CHECK_FLAG(dict, mask, standout, , HL_STANDOUT); @@ -906,7 +907,6 @@ HlAttrs dict2hlattrs(Dict(highlight) *dict, bool use_rgb, int *link_id, Error *e CHECK_FLAG(cterm, cterm_mask, reverse, , HL_INVERSE); CHECK_FLAG(cterm, cterm_mask, strikethrough, , HL_STRIKETHROUGH); CHECK_FLAG(cterm, cterm_mask, nocombine, , HL_NOCOMBINE); - } else if (dict->cterm.type == kObjectTypeArray && dict->cterm.data.array.size == 0) { // empty list from Lua API should clear all cterm attributes // TODO(clason): handle via gen_api_dispatch diff --git a/src/nvim/input.c b/src/nvim/input.c index 5fa9b8b343..ff6b559710 100644 --- a/src/nvim/input.c +++ b/src/nvim/input.c @@ -9,9 +9,9 @@ #include "nvim/func_attr.h" #include "nvim/getchar.h" +#include "nvim/input.h" #include "nvim/mbyte.h" #include "nvim/memory.h" -#include "nvim/input.h" #include "nvim/mouse.h" #include "nvim/os/input.h" #include "nvim/ui.h" diff --git a/src/nvim/lua/executor.c b/src/nvim/lua/executor.c index 6aaff100ca..054f6c9483 100644 --- a/src/nvim/lua/executor.c +++ b/src/nvim/lua/executor.c @@ -15,8 +15,8 @@ #include "nvim/buffer_defs.h" #include "nvim/change.h" #include "nvim/cursor.h" -#include "nvim/eval/userfunc.h" #include "nvim/eval/typval.h" +#include "nvim/eval/userfunc.h" #include "nvim/event/loop.h" #include "nvim/event/time.h" #include "nvim/ex_cmds2.h" @@ -139,17 +139,17 @@ static void nlua_luv_error_event(void **argv) luv_err_t type = (luv_err_t)(intptr_t)argv[1]; msg_ext_set_kind("lua_error"); switch (type) { - case kCallback: - semsg_multiline("Error executing luv callback:\n%s", error); - break; - case kThread: - semsg_multiline("Error in luv thread:\n%s", error); - break; - case kThreadCallback: - semsg_multiline("Error in luv callback, thread:\n%s", error); - break; - default: - break; + case kCallback: + semsg_multiline("Error executing luv callback:\n%s", error); + break; + case kThread: + semsg_multiline("Error in luv thread:\n%s", error); + break; + case kThreadCallback: + semsg_multiline("Error in luv callback, thread:\n%s", error); + break; + default: + break; } xfree(error); } @@ -189,21 +189,18 @@ static int nlua_luv_cfpcall(lua_State *lstate, int nargs, int nresult, int flags return retval; } -static int nlua_luv_thread_cb_cfpcall(lua_State *lstate, int nargs, int nresult, - int flags) +static int nlua_luv_thread_cb_cfpcall(lua_State *lstate, int nargs, int nresult, int flags) { return nlua_luv_thread_common_cfpcall(lstate, nargs, nresult, flags, true); } -static int nlua_luv_thread_cfpcall(lua_State *lstate, int nargs, int nresult, - int flags) +static int nlua_luv_thread_cfpcall(lua_State *lstate, int nargs, int nresult, int flags) FUNC_ATTR_NONNULL_ALL { return nlua_luv_thread_common_cfpcall(lstate, nargs, nresult, flags, false); } -static int nlua_luv_thread_cfcpcall(lua_State *lstate, lua_CFunction func, - void *ud, int flags) +static int nlua_luv_thread_cfcpcall(lua_State *lstate, lua_CFunction func, void *ud, int flags) FUNC_ATTR_NONNULL_ARG(1, 2) { lua_pushcfunction(lstate, func); @@ -212,8 +209,8 @@ static int nlua_luv_thread_cfcpcall(lua_State *lstate, lua_CFunction func, return retval; } -static int nlua_luv_thread_common_cfpcall(lua_State *lstate, int nargs, int nresult, - int flags, bool is_callback) +static int nlua_luv_thread_common_cfpcall(lua_State *lstate, int nargs, int nresult, int flags, + bool is_callback) FUNC_ATTR_NONNULL_ALL { int retval; @@ -228,9 +225,9 @@ static int nlua_luv_thread_common_cfpcall(lua_State *lstate, int nargs, int nres mch_errmsg("\n"); lua_close(lstate); #ifdef WIN32 - ExitThread(0); + ExitThread(0); #else - pthread_exit(0); + pthread_exit(0); #endif } const char *error = lua_tostring(lstate, -1); @@ -565,9 +562,9 @@ static bool nlua_init_packages(lua_State *lstate) lua_getglobal(lstate, "require"); lua_pushstring(lstate, "vim._init_packages"); if (nlua_pcall(lstate, 1, 0)) { - mch_errmsg(lua_tostring(lstate, -1)); - mch_errmsg("\n"); - return false; + mch_errmsg(lua_tostring(lstate, -1)); + mch_errmsg("\n"); + return false; } return true; diff --git a/src/nvim/lua/executor.h b/src/nvim/lua/executor.h index d978dc55d3..e96494ec5a 100644 --- a/src/nvim/lua/executor.h +++ b/src/nvim/lua/executor.h @@ -4,8 +4,8 @@ #include <lauxlib.h> #include <lua.h> -#include "nvim/assert.h" #include "nvim/api/private/defs.h" +#include "nvim/assert.h" #include "nvim/eval/typval.h" #include "nvim/ex_cmds_defs.h" #include "nvim/ex_docmd.h" @@ -16,9 +16,9 @@ void nlua_add_api_functions(lua_State *lstate) REAL_FATTR_NONNULL_ALL; typedef struct { - LuaRef nil_ref; - LuaRef empty_dict_ref; - int ref_count; + LuaRef nil_ref; + LuaRef empty_dict_ref; + int ref_count; #if __has_feature(address_sanitizer) PMap(handle_T) ref_markers; #endif diff --git a/src/nvim/lua/spell.c b/src/nvim/lua/spell.c index 3a63f61200..31a2b2d19f 100644 --- a/src/nvim/lua/spell.c +++ b/src/nvim/lua/spell.c @@ -1,12 +1,12 @@ // This is an open source non-commercial project. Dear PVS-Studio, please check // it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com -#include <lua.h> #include <lauxlib.h> +#include <lua.h> +#include "nvim/lua/spell.h" #include "nvim/spell.h" #include "nvim/vim.h" -#include "nvim/lua/spell.h" #ifdef INCLUDE_GENERATED_DECLARATIONS # include "lua/spell.c.generated.h" @@ -45,7 +45,7 @@ int nlua_spell_check(lua_State *lstate) size_t pos = 0; int capcol = -1; int no_res = 0; - const char * result; + const char *result; lua_createtable(lstate, 0, 0); @@ -90,7 +90,7 @@ int nlua_spell_check(lua_State *lstate) static const luaL_Reg spell_functions[] = { { "check", nlua_spell_check }, - { NULL , NULL } + { NULL, NULL } }; int luaopen_spell(lua_State *L) diff --git a/src/nvim/lua/stdlib.c b/src/nvim/lua/stdlib.c index c2ce899a74..e94c61b37c 100644 --- a/src/nvim/lua/stdlib.c +++ b/src/nvim/lua/stdlib.c @@ -28,10 +28,10 @@ #include "nvim/globals.h" #include "nvim/lua/converter.h" #include "nvim/lua/executor.h" +#include "nvim/lua/spell.h" #include "nvim/lua/stdlib.h" #include "nvim/lua/treesitter.h" #include "nvim/lua/xdiff.h" -#include "nvim/lua/spell.h" #include "nvim/macros.h" #include "nvim/map.h" #include "nvim/memline.h" @@ -411,7 +411,7 @@ int nlua_getvar(lua_State *lstate) dictitem_T *di = tv_dict_find(dict, name, (ptrdiff_t)len); if (di == NULL && dict == &globvardict) { // try to autoload script if (!script_autoload(name, len, false) || aborting()) { - return 0; // nil + return 0; // nil } di = tv_dict_find(dict, name, (ptrdiff_t)len); } diff --git a/src/nvim/main.c b/src/nvim/main.c index 7281809c06..a575aba50a 100644 --- a/src/nvim/main.c +++ b/src/nvim/main.c @@ -14,6 +14,7 @@ #include "nvim/channel.h" #include "nvim/charset.h" #include "nvim/decoration.h" +#include "nvim/decoration_provider.h" #include "nvim/diff.h" #include "nvim/eval.h" #include "nvim/ex_cmds.h" diff --git a/src/nvim/mark.c b/src/nvim/mark.c index 8b29aa3676..b770fef05c 100644 --- a/src/nvim/mark.c +++ b/src/nvim/mark.c @@ -630,7 +630,7 @@ static char_u *mark_line(pos_T *mp, int lead_len) if (mp->lnum == 0 || mp->lnum > curbuf->b_ml.ml_line_count) { return vim_strsave((char_u *)"-invalid-"); } - assert(Columns >= 0 && (size_t)Columns <= SIZE_MAX); + assert(Columns >= 0); // Allow for up to 5 bytes per character. s = vim_strnsave(skipwhite(ml_get(mp->lnum)), (size_t)Columns * 5); diff --git a/src/nvim/marktree.c b/src/nvim/marktree.c index 4456b28293..937582572b 100644 --- a/src/nvim/marktree.c +++ b/src/nvim/marktree.c @@ -558,7 +558,7 @@ void marktree_revise(MarkTree *b, MarkTreeIter *itr, uint8_t decor_level, mtkey_ { // TODO(bfredl): clean up this mess and re-instantiate &= and |= forms // once we upgrade to a non-broken version of gcc in functionaltest-lua CI - rawkey(itr).flags = (uint16_t)(rawkey(itr).flags & (uint16_t)~MT_FLAG_DECOR_MASK); + rawkey(itr).flags = (uint16_t)(rawkey(itr).flags & (uint16_t) ~MT_FLAG_DECOR_MASK); rawkey(itr).flags = (uint16_t)(rawkey(itr).flags | (uint16_t)(decor_level << MT_FLAG_DECOR_OFFSET) | (uint16_t)(key.flags & MT_FLAG_DECOR_MASK)); @@ -1111,7 +1111,7 @@ static void marktree_itr_fix_pos(MarkTree *b, MarkTreeIter *itr) void marktree_put_test(MarkTree *b, uint32_t id, int row, int col, bool right_gravity) { mtkey_t key = { { row, col }, UINT32_MAX, id, 0, - mt_flags(right_gravity, 0), 0, NULL }; + mt_flags(right_gravity, 0), 0, NULL }; marktree_put(b, key, -1, -1, false); } diff --git a/src/nvim/marktree.h b/src/nvim/marktree.h index 440816930b..ae6da92106 100644 --- a/src/nvim/marktree.h +++ b/src/nvim/marktree.h @@ -1,14 +1,14 @@ #ifndef NVIM_MARKTREE_H #define NVIM_MARKTREE_H -#include <stdint.h> #include <assert.h> +#include <stdint.h> #include "nvim/assert.h" #include "nvim/garray.h" #include "nvim/map.h" -#include "nvim/types.h" #include "nvim/pos.h" +#include "nvim/types.h" #define MT_MAX_DEPTH 20 #define MT_BRANCH_FACTOR 10 diff --git a/src/nvim/memory.c b/src/nvim/memory.c index 677ff8f522..d68ca6b62e 100644 --- a/src/nvim/memory.c +++ b/src/nvim/memory.c @@ -10,7 +10,7 @@ #include "nvim/api/extmark.h" #include "nvim/context.h" -#include "nvim/decoration.h" +#include "nvim/decoration_provider.h" #include "nvim/eval.h" #include "nvim/highlight.h" #include "nvim/lua/executor.h" diff --git a/src/nvim/normal.c b/src/nvim/normal.c index 5c39e9c8bf..0e5e0ab403 100644 --- a/src/nvim/normal.c +++ b/src/nvim/normal.c @@ -3568,7 +3568,6 @@ static void nv_zet(cmdarg_T *cap) bool undo = false; int l_p_siso = (int)get_sidescrolloff_value(curwin); - assert(l_p_siso <= INT_MAX); if (ascii_isdigit(nchar)) { /* diff --git a/src/nvim/option.c b/src/nvim/option.c index a0706dfa14..191b635dc0 100644 --- a/src/nvim/option.c +++ b/src/nvim/option.c @@ -5664,12 +5664,10 @@ void comp_col(void) } } assert(sc_col >= 0 - && INT_MIN + sc_col <= Columns - && Columns - sc_col <= INT_MAX); + && INT_MIN + sc_col <= Columns); sc_col = Columns - sc_col; assert(ru_col >= 0 - && INT_MIN + ru_col <= Columns - && Columns - ru_col <= INT_MAX); + && INT_MIN + ru_col <= Columns); ru_col = Columns - ru_col; if (sc_col <= 0) { // screen too narrow, will become a mess sc_col = 1; diff --git a/src/nvim/os/os_defs.h b/src/nvim/os/os_defs.h index dce4b0c187..a4361859ec 100644 --- a/src/nvim/os/os_defs.h +++ b/src/nvim/os/os_defs.h @@ -14,7 +14,7 @@ #endif #if !defined(NAME_MAX) && defined(_XOPEN_NAME_MAX) -#define NAME_MAX _XOPEN_NAME_MAX +# define NAME_MAX _XOPEN_NAME_MAX #endif #define BASENAMELEN (NAME_MAX - 5) diff --git a/src/nvim/os/pty_process_unix.c b/src/nvim/os/pty_process_unix.c index 3459646bad..58cb1b8f84 100644 --- a/src/nvim/os/pty_process_unix.c +++ b/src/nvim/os/pty_process_unix.c @@ -16,11 +16,11 @@ #elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__APPLE__) # include <util.h> #elif defined(__sun) -# include <sys/stream.h> -# include <sys/syscall.h> -# include <fcntl.h> -# include <unistd.h> -# include <signal.h> +# include <fcntl.h> +# include <signal.h> +# include <sys/stream.h> +# include <sys/syscall.h> +# include <unistd.h> #else # include <pty.h> #endif @@ -49,10 +49,10 @@ // this header defines STR, just as nvim.h, but it is defined as ('S'<<8), // to avoid #undef STR, #undef STR, #define STR ('S'<<8) just delay the // inclusion of the header even though it gets include out of order. -#include <sys/stropts.h> +# include <sys/stropts.h> -static int openpty(int *amaster, int *aslave, char *name, - struct termios *termp, struct winsize *winp) +static int openpty(int *amaster, int *aslave, char *name, struct termios *termp, + struct winsize *winp) { int slave = -1; int master = open("/dev/ptmx", O_RDWR); @@ -63,7 +63,7 @@ static int openpty(int *amaster, int *aslave, char *name, // grantpt will invoke a setuid program to change permissions // and might fail if SIGCHLD handler is set, temporarily reset // while running - void(*sig_saved)(int) = signal(SIGCHLD, SIG_DFL); + void (*sig_saved)(int) = signal(SIGCHLD, SIG_DFL); int res = grantpt(master); signal(SIGCHLD, sig_saved); @@ -129,8 +129,7 @@ static int login_tty(int fd) return 0; } -static pid_t forkpty(int *amaster, char *name, - struct termios *termp, struct winsize *winp) +static pid_t forkpty(int *amaster, char *name, struct termios *termp, struct winsize *winp) { int master, slave; if (openpty(&master, &slave, name, termp, winp) == -1) { diff --git a/src/nvim/os/shell.c b/src/nvim/os/shell.c index e618b2788b..656e059303 100644 --- a/src/nvim/os/shell.c +++ b/src/nvim/os/shell.c @@ -9,10 +9,10 @@ #include "nvim/ascii.h" #include "nvim/charset.h" +#include "nvim/eval.h" #include "nvim/event/libuv_process.h" #include "nvim/event/loop.h" #include "nvim/event/rstream.h" -#include "nvim/eval.h" #include "nvim/ex_cmds.h" #include "nvim/fileio.h" #include "nvim/lib/kvec.h" @@ -27,8 +27,8 @@ #include "nvim/path.h" #include "nvim/screen.h" #include "nvim/strings.h" -#include "nvim/types.h" #include "nvim/tag.h" +#include "nvim/types.h" #include "nvim/ui.h" #include "nvim/vim.h" diff --git a/src/nvim/popupmnu.c b/src/nvim/popupmnu.c index d7726409b5..e354a589a5 100644 --- a/src/nvim/popupmnu.c +++ b/src/nvim/popupmnu.c @@ -289,8 +289,7 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed, i if (pum_rl) { pum_width = pum_col - pum_scrollbar + 1; } else { - assert(Columns - pum_col - pum_scrollbar >= INT_MIN - && Columns - pum_col - pum_scrollbar <= INT_MAX); + assert(Columns - pum_col - pum_scrollbar >= 0); pum_width = Columns - pum_col - pum_scrollbar; } @@ -356,7 +355,6 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed, i } else { pum_col = 0; } - assert(Columns - 1 >= INT_MIN); pum_width = Columns - 1; } else { if (max_width > p_pw) { @@ -367,8 +365,7 @@ void pum_display(pumitem_T *array, int size, int selected, bool array_changed, i if (pum_rl) { pum_col = max_width - 1; } else { - assert(Columns - max_width >= INT_MIN - && Columns - max_width <= INT_MAX); + assert(Columns - max_width >= 0); pum_col = Columns - max_width; } pum_width = max_width - pum_scrollbar; diff --git a/src/nvim/quickfix.c b/src/nvim/quickfix.c index 7e29aed51b..bddbd04af9 100644 --- a/src/nvim/quickfix.c +++ b/src/nvim/quickfix.c @@ -5421,9 +5421,8 @@ static int vgr_process_args(exarg_T *eap, vgr_args_T *args) /// Search for a pattern in a list of files and populate the quickfix list with /// the matches. -static int vgr_process_files(win_T *wp, qf_info_T *qi, vgr_args_T *cmd_args, - bool *redraw_for_dummy, buf_T **first_match_buf, - char_u **target_dir) +static int vgr_process_files(win_T *wp, qf_info_T *qi, vgr_args_T *cmd_args, bool *redraw_for_dummy, + buf_T **first_match_buf, char_u **target_dir) { int status = FAIL; unsigned save_qfid = qf_get_curlist(qi)->qf_id; diff --git a/src/nvim/screen.c b/src/nvim/screen.c index 3a87cba7f9..0a1f388456 100644 --- a/src/nvim/screen.c +++ b/src/nvim/screen.c @@ -75,6 +75,7 @@ #include "nvim/cursor.h" #include "nvim/cursor_shape.h" #include "nvim/decoration.h" +#include "nvim/decoration_provider.h" #include "nvim/diff.h" #include "nvim/edit.h" #include "nvim/eval.h" @@ -126,8 +127,6 @@ #define MB_FILLER_CHAR '<' /* character used when a double-width character * doesn't fit. */ -typedef kvec_withinit_t(DecorProvider *, 4) Providers; - // temporary buffer for rendering a single screenline, so it can be // compared with previous contents to calculate smallest delta. // Per-cell attributes @@ -168,36 +167,6 @@ static bool resizing = false; static char *provider_err = NULL; -static bool provider_invoke(NS ns_id, const char *name, LuaRef ref, Array args, bool default_true) -{ - Error err = ERROR_INIT; - - textlock++; - provider_active = true; - Object ret = nlua_call_ref(ref, name, args, true, &err); - provider_active = false; - textlock--; - - if (!ERROR_SET(&err) - && api_object_to_bool(ret, "provider %s retval", default_true, &err)) { - return true; - } - - if (ERROR_SET(&err)) { - const char *ns_name = describe_ns(ns_id); - ELOG("error in provider %s:%s: %s", ns_name, name, err.msg); - bool verbose_errs = true; // TODO(bfredl): - if (verbose_errs && provider_err == NULL) { - static char errbuf[IOSIZE]; - snprintf(errbuf, sizeof errbuf, "%s: %s", ns_name, err.msg); - provider_err = xstrdup(errbuf); - } - } - - api_free_object(ret); - return false; -} - /// Redraw a window later, with update_screen(type). /// /// Set must_redraw only if not already set to a higher value. @@ -501,28 +470,8 @@ int update_screen(int type) ui_comp_set_screen_valid(true); - Providers providers; - kvi_init(providers); - for (size_t i = 0; i < kv_size(decor_providers); i++) { - DecorProvider *p = &kv_A(decor_providers, i); - if (!p->active) { - continue; - } - - bool active; - if (p->redraw_start != LUA_NOREF) { - FIXED_TEMP_ARRAY(args, 2); - args.items[0] = INTEGER_OBJ(display_tick); - args.items[1] = INTEGER_OBJ(type); - active = provider_invoke(p->ns_id, "start", p->redraw_start, args, true); - } else { - active = true; - } - - if (active) { - kvi_push(providers, p); - } - } + DecorProviders providers; + decor_providers_start(&providers, type, &provider_err); // "start" callback could have changed highlights for global elements if (win_check_ns_hl(NULL)) { @@ -591,14 +540,7 @@ int update_screen(int type) } if (buf->b_mod_tick_decor < display_tick) { - for (size_t i = 0; i < kv_size(providers); i++) { - DecorProvider *p = kv_A(providers, i); - if (p && p->redraw_buf != LUA_NOREF) { - FIXED_TEMP_ARRAY(args, 1); - args.items[0] = BUFFER_OBJ(buf->handle); - provider_invoke(p->ns_id, "buf", p->redraw_buf, args, true); - } - } + decor_providers_invoke_buf(buf, &providers, &provider_err); buf->b_mod_tick_decor = display_tick; } } @@ -668,18 +610,7 @@ int update_screen(int type) } did_intro = true; - for (size_t i = 0; i < kv_size(providers); i++) { - DecorProvider *p = kv_A(providers, i); - if (!p->active) { - continue; - } - - if (p->redraw_end != LUA_NOREF) { - FIXED_TEMP_ARRAY(args, 1); - args.items[0] = INTEGER_OBJ(display_tick); - provider_invoke(p->ns_id, "end", p->redraw_end, args, true); - } - } + decor_providers_invoke_end(&providers, &provider_err); kvi_destroy(providers); @@ -766,7 +697,7 @@ bool win_cursorline_standout(const win_T *wp) * mid: from mid_start to mid_end (update inversion or changed text) * bot: from bot_start to last row (when scrolled up) */ -static void win_update(win_T *wp, Providers *providers) +static void win_update(win_T *wp, DecorProviders *providers) { buf_T *buf = wp->w_buffer; int type; @@ -1377,30 +1308,8 @@ static void win_update(win_T *wp, Providers *providers) decor_redraw_reset(buf, &decor_state); - Providers line_providers; - kvi_init(line_providers); - - linenr_T knownmax = ((wp->w_valid & VALID_BOTLINE) - ? wp->w_botline - : (wp->w_topline + wp->w_height_inner)); - - for (size_t k = 0; k < kv_size(*providers); k++) { - DecorProvider *p = kv_A(*providers, k); - if (p && p->redraw_win != LUA_NOREF) { - FIXED_TEMP_ARRAY(args, 4); - args.items[0] = WINDOW_OBJ(wp->handle); - args.items[1] = BUFFER_OBJ(buf->handle); - // TODO(bfredl): we are not using this, but should be first drawn line? - args.items[2] = INTEGER_OBJ(wp->w_topline-1); - args.items[3] = INTEGER_OBJ(knownmax); - if (provider_invoke(p->ns_id, "win", p->redraw_win, args, true)) { - kvi_push(line_providers, p); - } - } - } - - win_check_ns_hl(wp); - + DecorProviders line_providers; + decor_providers_invoke_win(wp, providers, &line_providers, &provider_err); for (;;) { /* stop updating when reached the end of the window (check for _past_ @@ -2028,6 +1937,17 @@ static size_t fill_foldcolumn(char_u *p, win_T *wp, foldinfo_T foldinfo, linenr_ return MAX(char_counter + (fdc-i), (size_t)fdc); } +static inline void provider_err_virt_text(linenr_T lnum, char *err) +{ + Decoration err_decor = DECORATION_INIT; + int hl_err = syn_check_group(S_LEN("ErrorMsg")); + kv_push(err_decor.virt_text, + ((VirtTextChunk){ .text = provider_err, + .hl_id = hl_err })); + err_decor.virt_text_width = mb_string2cells((char_u *)err); + decor_add_ephemeral(lnum-1, 0, lnum-1, 0, &err_decor); +} + /// Display line "lnum" of window 'wp' on the screen. /// wp->w_virtcol needs to be valid. /// @@ -2043,7 +1963,7 @@ static size_t fill_foldcolumn(char_u *p, win_T *wp, foldinfo_T foldinfo, linenr_ /// /// @return the number of last row the line occupies. static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool nochange, - bool number_only, foldinfo_T foldinfo, Providers *providers) + bool number_only, foldinfo_T foldinfo, DecorProviders *providers) { int c = 0; // init for GCC long vcol = 0; // virtual column (for tabs) @@ -2231,34 +2151,12 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc has_decor = decor_redraw_line(buf, lnum-1, &decor_state); - for (size_t k = 0; k < kv_size(*providers); k++) { - DecorProvider *p = kv_A(*providers, k); - if (p && p->redraw_line != LUA_NOREF) { - FIXED_TEMP_ARRAY(args, 3); - args.items[0] = WINDOW_OBJ(wp->handle); - args.items[1] = BUFFER_OBJ(buf->handle); - args.items[2] = INTEGER_OBJ(lnum-1); - if (provider_invoke(p->ns_id, "line", p->redraw_line, args, true)) { - has_decor = true; - } else { - // return 'false' or error: skip rest of this window - kv_A(*providers, k) = NULL; - } - - win_check_ns_hl(wp); - } - } + providers_invoke_line(wp, providers, lnum-1, &has_decor, &provider_err); if (provider_err) { - Decoration err_decor = DECORATION_INIT; - int hl_err = syn_check_group(S_LEN("ErrorMsg")); - kv_push(err_decor.virt_text, - ((VirtTextChunk){ .text = provider_err, - .hl_id = hl_err })); - err_decor.virt_text_width = mb_string2cells((char_u *)provider_err); - decor_add_ephemeral(lnum-1, 0, lnum-1, 0, &err_decor); - provider_err = NULL; + provider_err_virt_text(lnum, provider_err); has_decor = true; + provider_err = NULL; } if (has_decor) { @@ -4680,9 +4578,9 @@ static bool use_cursor_line_sign(win_T *wp, linenr_T lnum) // @param[in, out] sign_idxp Index of the displayed sign static void get_sign_display_info(bool nrcol, win_T *wp, linenr_T lnum, sign_attrs_T sattrs[], int row, int startrow, int filler_lines, int filler_todo, - int *c_extrap, int *c_finalp, char_u *extra, - size_t extra_size, char_u **pp_extra, int *n_extrap, - int *char_attrp, int *draw_statep, int *sign_idxp) + int *c_extrap, int *c_finalp, char_u *extra, size_t extra_size, + char_u **pp_extra, int *n_extrap, int *char_attrp, + int *draw_statep, int *sign_idxp) { int count = wp->w_scwidth; // Draw cells with the sign value or blank. diff --git a/src/nvim/search.c b/src/nvim/search.c index e6b47e75b2..cc7c2ecf06 100644 --- a/src/nvim/search.c +++ b/src/nvim/search.c @@ -13,8 +13,8 @@ #include "nvim/ascii.h" #include "nvim/buffer.h" -#include "nvim/charset.h" #include "nvim/change.h" +#include "nvim/charset.h" #include "nvim/cursor.h" #include "nvim/edit.h" #include "nvim/eval.h" @@ -5048,8 +5048,8 @@ bool fuzzy_match(char_u *const str, const char_u *const pat_arg, const bool matc int score = 0; int recursionCount = 0; const int matchCount - = fuzzy_match_recursive(pat, str, 0, &score, str, len, NULL, matches + numMatches, - maxMatches - numMatches, 0, &recursionCount); + = fuzzy_match_recursive(pat, str, 0, &score, str, len, NULL, matches + numMatches, + maxMatches - numMatches, 0, &recursionCount); if (matchCount == 0) { numMatches = 0; break; diff --git a/src/nvim/tui/tui.c b/src/nvim/tui/tui.c index 1ad82b7290..79a6b9ed0e 100644 --- a/src/nvim/tui/tui.c +++ b/src/nvim/tui/tui.c @@ -1475,8 +1475,8 @@ static void tui_guess_size(UI *ui) // 1 - look for non-default 'columns' and 'lines' options during startup if (data->is_starting && (Columns != DFLT_COLS || Rows != DFLT_ROWS)) { did_user_set_dimensions = true; - assert(Columns >= INT_MIN && Columns <= INT_MAX); - assert(Rows >= INT_MIN && Rows <= INT_MAX); + assert(Columns >= 0); + assert(Rows >= 0); width = Columns; height = Rows; goto end; diff --git a/src/nvim/vim.h b/src/nvim/vim.h index 6e0e9922a6..5d632b1b25 100644 --- a/src/nvim/vim.h +++ b/src/nvim/vim.h @@ -217,9 +217,9 @@ enum { FOLD_TEXT_LEN = 51, }; //!< buffer size for get_foldtext() #define STRLEN(s) strlen((char *)(s)) #ifdef HAVE_STRNLEN -# define STRNLEN(s, n) strnlen((char *)(s), (size_t)(n)) +# define STRNLEN(s, n) strnlen((char *)(s), (size_t)(n)) #else -# define STRNLEN(s, n) xstrnlen((char *)(s), (size_t)(n)) +# define STRNLEN(s, n) xstrnlen((char *)(s), (size_t)(n)) #endif #define STRCPY(d, s) strcpy((char *)(d), (char *)(s)) #define STRNCPY(d, s, n) strncpy((char *)(d), (char *)(s), (size_t)(n)) diff --git a/third-party/CMakeLists.txt b/third-party/CMakeLists.txt index 30c4752b87..8a8720fca3 100644 --- a/third-party/CMakeLists.txt +++ b/third-party/CMakeLists.txt @@ -144,8 +144,8 @@ endif() include(ExternalProject) -set(LIBUV_URL https://github.com/libuv/libuv/archive/v1.44.0.tar.gz) -set(LIBUV_SHA256 f2482d547009d26d4d590ed6588043c540e707c833df52536744cb9a809e6617) +set(LIBUV_URL https://github.com/libuv/libuv/archive/v1.44.1.tar.gz) +set(LIBUV_SHA256 e91614e6dc2dd0bfdd140ceace49438882206b7a6fb00b8750914e67a9ed6d6b) set(MSGPACK_URL https://github.com/msgpack/msgpack-c/releases/download/cpp-3.0.0/msgpack-3.0.0.tar.gz) set(MSGPACK_SHA256 bfbb71b7c02f806393bc3cbc491b40523b89e64f83860c58e3e54af47de176e4) |