diff options
author | Thiago de Arruda <tpadilha84@gmail.com> | 2014-05-23 18:10:52 -0300 |
---|---|---|
committer | Thiago de Arruda <tpadilha84@gmail.com> | 2014-05-23 18:10:52 -0300 |
commit | 9e95c8aa331e3872253e7a06be32103b440bc97f (patch) | |
tree | d25a81cd37939466e5b9c8b33b3566f9aefbdf49 | |
parent | f1e52c496ddb89f830cdbc4f23d756131106b97f (diff) | |
parent | 6c96e42e2c18bd6ae685b5a41c69b03954aa0375 (diff) | |
download | rneovim-9e95c8aa331e3872253e7a06be32103b440bc97f.tar.gz rneovim-9e95c8aa331e3872253e7a06be32103b440bc97f.tar.bz2 rneovim-9e95c8aa331e3872253e7a06be32103b440bc97f.zip |
Merge branch 'use-uids-for-api-remote-objects'
-rw-r--r-- | .travis.yml | 1 | ||||
-rwxr-xr-x | scripts/run-api-tests.exp | 86 | ||||
-rwxr-xr-x | scripts/travis.sh | 62 | ||||
-rw-r--r-- | src/nvim/CMakeLists.txt | 17 | ||||
-rw-r--r-- | src/nvim/api/buffer.c | 35 | ||||
-rw-r--r-- | src/nvim/api/buffer.h | 9 | ||||
-rw-r--r-- | src/nvim/api/private/defs.h (renamed from src/nvim/api/defs.h) | 23 | ||||
-rw-r--r-- | src/nvim/api/private/handle.c | 40 | ||||
-rw-r--r-- | src/nvim/api/private/handle.h | 20 | ||||
-rw-r--r-- | src/nvim/api/private/helpers.c (renamed from src/nvim/api/helpers.c) | 35 | ||||
-rw-r--r-- | src/nvim/api/private/helpers.h (renamed from src/nvim/api/helpers.h) | 2 | ||||
-rw-r--r-- | src/nvim/api/tabpage.c | 25 | ||||
-rw-r--r-- | src/nvim/api/tabpage.h | 4 | ||||
-rw-r--r-- | src/nvim/api/vim.c | 115 | ||||
-rw-r--r-- | src/nvim/api/vim.h | 14 | ||||
-rw-r--r-- | src/nvim/api/window.c | 16 | ||||
-rw-r--r-- | src/nvim/api/window.h | 2 | ||||
-rw-r--r-- | src/nvim/buffer.c | 3 | ||||
-rw-r--r-- | src/nvim/buffer_defs.h | 3 | ||||
-rw-r--r-- | src/nvim/map.c | 1 | ||||
-rw-r--r-- | src/nvim/map.h | 1 | ||||
-rw-r--r-- | src/nvim/os/msgpack_rpc.c | 122 | ||||
-rw-r--r-- | src/nvim/os/msgpack_rpc.h | 21 | ||||
-rw-r--r-- | src/nvim/os_unix.c | 2 | ||||
-rw-r--r-- | src/nvim/window.c | 6 |
25 files changed, 455 insertions, 210 deletions
diff --git a/.travis.yml b/.travis.yml index 25ab961ec4..d883410123 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,5 +4,6 @@ env: - TRAVIS_BUILD_TYPE=gcc/ia32 - TRAVIS_BUILD_TYPE=gcc/unittest - TRAVIS_BUILD_TYPE=clint + - TRAVIS_BUILD_TYPE=api/python script: - ./scripts/travis.sh diff --git a/scripts/run-api-tests.exp b/scripts/run-api-tests.exp new file mode 100755 index 0000000000..6a568e17cb --- /dev/null +++ b/scripts/run-api-tests.exp @@ -0,0 +1,86 @@ +#!/usr/bin/env expect + +if {$argc < 2} { + puts "Need commands for running the tests and for starting nvim" + exit 1 +} + +set timeout 10 +set run_tests [split [lindex $argv 0] " "] +set run_nvim [split [lindex $argv 1] " "] + +# don't echo to stdout +log_user 0 +# set NEOVIM_LISTEN_ADDRESS, so nvim will listen on a known socket +set env(NEOVIM_LISTEN_ADDRESS) "/tmp/nvim-[exec date +%s%N].sock" +# start nvim +spawn {*}$run_nvim +# save the job descriptor +set nvim_id $spawn_id +# Reset function that can be invoked by test runners to put nvim in a cleaner +# state +send { +:function BeforeEachTest() + set all& + redir => groups + silent augroup + redir END + for group in split(groups) + exe 'augroup '.group + autocmd! + augroup NONE + exe 'augroup! '.group + endfor + tabnew + let curbufnum = eval(bufnr('%')) + redir => buflist + silent ls! + redir END + let bufnums = [] + for buf in split(buflist, '\n') + let bufnum = eval(split(buf, '[ u]')[0]) + if bufnum != curbufnum + call add(bufnums, bufnum) + endif + endfor + if len(bufnums) > 0 + exe 'silent bwipeout! '.join(bufnums, ' ') + endif + silent tabonly + for k in keys(g:) + exe 'unlet g:'.k + endfor + filetype plugin indent off + mapclear + mapclear! + abclear + comclear +endfunction +:echo "read"."y" +} +# wait until nvim is ready +expect "ready" +# run tests +spawn {*}$run_tests +set tests_id $spawn_id +set status 1 +# listen for test output in the background +expect_background { + * { + # show test output to the user + send_user -- $expect_out(buffer) + } + eof { + # collect the exit status code + set spawn_id $tests_id + catch wait result + set status [lindex $result 3] + set spawn_id $nvim_id + # quit nvim + send ":qa!\r" + } +} +# switch back nvim and wait until it exits +set spawn_id $nvim_id +expect eof +exit $status diff --git a/scripts/travis.sh b/scripts/travis.sh index 62c4fbe98e..3daa2652e5 100755 --- a/scripts/travis.sh +++ b/scripts/travis.sh @@ -1,8 +1,44 @@ #!/bin/sh -e -check_and_report() { +tmpdir="$(pwd)/tmp" +rm -rf "$tmpdir" +mkdir -p "$tmpdir" + +valgrind_check() { ( - cd $tmpdir + cd $1 + set -- valgrind-[*] valgrind-* + case $1$2 in + 'valgrind-[*]valgrind-*') + ;; + *) + shift + local err='' + for valgrind_log in "$@"; do + # Remove useless warning + sed -i "$valgrind_log" \ + -e '/Warning: noted but unhandled ioctl/d' \ + -e '/could cause spurious value errors to appear/d' \ + -e '/See README_MISSING_SYSCALL_OR_IOCTL for guidance/d' + if [ "$(stat -c %s $valgrind_log)" != "0" ]; then + # if after removing the warning, the log still has errors, show its + # contents and set the flag so we exit with non-zero status + cat "$valgrind_log" + err=1 + fi + done + if [ -n "$err" ]; then + echo "Runtime errors detected" + exit 1 + fi + ;; + esac + ) +} + +asan_check() { + ( + cd $1 set -- [*]san.[*] *san.* case $1$2 in '[*]san.[*]*san.*') @@ -68,9 +104,6 @@ if [ "$TRAVIS_BUILD_TYPE" = "clang/asan" ]; then install_dir="$(pwd)/dist" # temporary directory for writing sanitizer logs - tmpdir="$(pwd)/tmp" - rm -rf "$tmpdir" - mkdir -p "$tmpdir" # need the symbolizer path for stack traces with source information if [ -n "$USE_CLANG_34" ]; then @@ -91,10 +124,10 @@ if [ "$TRAVIS_BUILD_TYPE" = "clang/asan" ]; then $MAKE_CMD if ! $MAKE_CMD test; then reset - check_and_report + asan_check "$tmpdir" exit 1 fi - check_and_report + asan_check "$tmpdir" coveralls --encoding iso-8859-1 || echo 'coveralls upload failed.' $MAKE_CMD install elif [ "$TRAVIS_BUILD_TYPE" = "gcc/unittest" ]; then @@ -129,4 +162,19 @@ elif [ "$TRAVIS_BUILD_TYPE" = "gcc/ia32" ]; then $MAKE_CMD test elif [ "$TRAVIS_BUILD_TYPE" = "clint" ]; then ./scripts/clint.sh +elif [ "$TRAVIS_BUILD_TYPE" = "api/python" ]; then + set_environment /opt/neovim-deps + $MAKE_CMD + sudo apt-get install expect valgrind + git clone --depth=1 -b master git://github.com/neovim/python-client + cd python-client + sudo pip install . + sudo pip install nose + test_cmd="nosetests --verbosity=2" + nvim_cmd="valgrind -q --track-origins=yes --log-file=$tmpdir/valgrind-%p.log ../build/bin/nvim -u NONE" + if ! ../scripts/run-api-tests.exp "$test_cmd" "$nvim_cmd"; then + valgrind_check "$tmpdir" + exit 1 + fi + valgrind_check "$tmpdir" fi diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt index d9ec65af86..ad45f3ad3b 100644 --- a/src/nvim/CMakeLists.txt +++ b/src/nvim/CMakeLists.txt @@ -6,17 +6,6 @@ file(GLOB API_HEADERS api/*.h) set(MSGPACK_RPC_HEADER ${PROJECT_SOURCE_DIR}/src/nvim/os/msgpack_rpc.h) set(MSGPACK_DISPATCH ${GENERATED_DIR}/msgpack_dispatch.c) -# Remove helpers.h from API_HEADERS since it doesn't contain public API -# functions -foreach(sfile ${API_HEADERS}) - get_filename_component(f ${sfile} NAME) - if(${f} MATCHES "^(helpers.h)$") - list(APPEND to_remove ${sfile}) - endif() -endforeach() -list(REMOVE_ITEM API_HEADERS ${to_remove}) -set(to_remove) - file(MAKE_DIRECTORY ${GENERATED_DIR}) add_custom_command(OUTPUT ${MSGPACK_DISPATCH} @@ -42,6 +31,7 @@ list(APPEND NEOVIM_SOURCES "${MSGPACK_DISPATCH}") file( GLOB OS_SOURCES os/*.c ) file( GLOB API_SOURCES api/*.c ) +file( GLOB API_PRIV_SOURCES api/private/*.c ) set(CONV_SRCS api.c @@ -110,13 +100,14 @@ list(APPEND NVIM_LINK_LIBRARIES ${CMAKE_THREAD_LIBS_INIT}) if(NOT DEFINED ENV{SKIP_EXEC}) - add_executable(nvim ${NEOVIM_SOURCES} ${OS_SOURCES} ${API_SOURCES}) + add_executable(nvim ${NEOVIM_SOURCES} ${OS_SOURCES} ${API_SOURCES} + ${API_PRIV_SOURCES}) target_link_libraries(nvim ${NVIM_LINK_LIBRARIES}) install(TARGETS nvim RUNTIME DESTINATION bin) endif() if(NOT DEFINED ENV{SKIP_UNITTEST}) add_library(nvim-test MODULE EXCLUDE_FROM_ALL ${NEOVIM_SOURCES} - ${OS_SOURCES} ${API_SOURCES}) + ${OS_SOURCES} ${API_SOURCES} ${API_PRIV_SOURCES}) target_link_libraries(nvim-test ${NVIM_LINK_LIBRARIES}) endif() diff --git a/src/nvim/api/buffer.c b/src/nvim/api/buffer.c index e73823e5c3..bf30ccf856 100644 --- a/src/nvim/api/buffer.c +++ b/src/nvim/api/buffer.c @@ -4,8 +4,8 @@ #include <stdlib.h> #include "nvim/api/buffer.h" -#include "nvim/api/helpers.h" -#include "nvim/api/defs.h" +#include "nvim/api/private/helpers.h" +#include "nvim/api/private/defs.h" #include "nvim/vim.h" #include "nvim/buffer.h" #include "nvim/memline.h" @@ -56,7 +56,7 @@ String buffer_get_line(Buffer buffer, Integer index, Error *err) String rv = {.size = 0}; StringArray slice = buffer_get_slice(buffer, index, index, true, true, err); - if (slice.size) { + if (!err->set && slice.size) { rv = slice.items[0]; } @@ -71,7 +71,7 @@ void buffer_set_line(Buffer buffer, Integer index, String line, Error *err) void buffer_del_line(Buffer buffer, Integer index, Error *err) { - StringArray array = {.size = 0}; + StringArray array = ARRAY_DICT_INIT; buffer_set_slice(buffer, index, index, true, true, array, err); } @@ -82,7 +82,7 @@ StringArray buffer_get_slice(Buffer buffer, Boolean include_end, Error *err) { - StringArray rv = {.size = 0}; + StringArray rv = ARRAY_DICT_INIT; buf_T *buf = find_buffer(buffer, err); if (!buf) { @@ -115,9 +115,7 @@ StringArray buffer_get_slice(Buffer buffer, end: if (err->set) { for (size_t i = 0; i < rv.size; i++) { - if (rv.items[i].data != NULL) { - free(rv.items[i].data); - } + free(rv.items[i].data); } free(rv.items); @@ -221,7 +219,6 @@ void buffer_set_slice(Buffer buffer, // Same as with replacing lines[i] = NULL; - i++; extra++; } @@ -240,10 +237,8 @@ void buffer_set_slice(Buffer buffer, } end: - for (uint32_t i = 0; i < new_len; i++) { - if (lines[i] != NULL) { - free(lines[i]); - } + for (size_t i = 0; i < new_len; i++) { + free(lines[i]); } free(lines); @@ -298,6 +293,18 @@ void buffer_set_option(Buffer buffer, String name, Object value, Error *err) set_option_to(buf, SREQ_BUF, name, value, err); } +Integer buffer_get_number(Buffer buffer, Error *err) +{ + Integer rv = 0; + buf_T *buf = find_buffer(buffer, err); + + if (!buf) { + return rv; + } + + return buf->b_fnum; +} + String buffer_get_name(Buffer buffer, Error *err) { String rv = {.size = 0, .data = ""}; @@ -357,7 +364,7 @@ Position buffer_get_mark(Buffer buffer, String name, Error *err) return rv; } - if (name.size != 0) { + if (name.size != 1) { set_api_error("mark name must be a single character", err); return rv; } diff --git a/src/nvim/api/buffer.h b/src/nvim/api/buffer.h index 5f39589679..52a3b7cdb3 100644 --- a/src/nvim/api/buffer.h +++ b/src/nvim/api/buffer.h @@ -4,7 +4,7 @@ #include <stdint.h> #include <stdbool.h> -#include "nvim/api/defs.h" +#include "nvim/api/private/defs.h" /// Gets the buffer line count /// @@ -104,6 +104,13 @@ Object buffer_get_option(Buffer buffer, String name, Error *err); /// @param[out] err Details of an error that may have occurred void buffer_set_option(Buffer buffer, String name, Object value, Error *err); +/// Gets the buffer number +/// +/// @param buffer The buffer handle +/// @param[out] err Details of an error that may have occurred +/// @return The buffer number +Integer buffer_get_number(Buffer buffer, Error *err); + /// Gets the full file name for the buffer /// /// @param buffer The buffer handle diff --git a/src/nvim/api/defs.h b/src/nvim/api/private/defs.h index 3ee50310fb..a91907f4f8 100644 --- a/src/nvim/api/defs.h +++ b/src/nvim/api/private/defs.h @@ -5,6 +5,15 @@ #include <stdbool.h> #include <string.h> +#define ARRAY_DICT_INIT {.size = 0, .items = NULL} +#define REMOTE_TYPE(type) typedef uint64_t type + +#define TYPED_ARRAY_OF(type) \ + typedef struct { \ + type *items; \ + size_t size; \ + } type##Array + // Basic types typedef struct { char msg[256]; @@ -20,16 +29,16 @@ typedef struct { size_t size; } String; -typedef Integer Buffer; -typedef Integer Window; -typedef Integer Tabpage; +REMOTE_TYPE(Buffer); +REMOTE_TYPE(Window); +REMOTE_TYPE(Tabpage); typedef struct object Object; -typedef struct { - String *items; - size_t size; -} StringArray; +TYPED_ARRAY_OF(Buffer); +TYPED_ARRAY_OF(Window); +TYPED_ARRAY_OF(Tabpage); +TYPED_ARRAY_OF(String); typedef struct { Integer row, col; diff --git a/src/nvim/api/private/handle.c b/src/nvim/api/private/handle.c new file mode 100644 index 0000000000..88d176fccb --- /dev/null +++ b/src/nvim/api/private/handle.c @@ -0,0 +1,40 @@ +#include <stdint.h> + +#include "nvim/vim.h" +#include "nvim/map.h" +#include "nvim/api/private/handle.h" + +#define HANDLE_INIT(name) name##_handles = map_new(uint64_t)() + +#define HANDLE_IMPL(type, name) \ + static Map(uint64_t) *name##_handles = NULL; \ + \ + type *handle_get_##name(uint64_t handle) \ + { \ + return map_get(uint64_t)(name##_handles, handle); \ + } \ + \ + void handle_register_##name(type *name) \ + { \ + assert(!name->handle); \ + name->handle = next_handle++; \ + map_put(uint64_t)(name##_handles, name->handle, name); \ + } \ + \ + void handle_unregister_##name(type *name) \ + { \ + map_del(uint64_t)(name##_handles, name->handle); \ + } + +static uint64_t next_handle = 1; + +HANDLE_IMPL(buf_T, buffer) +HANDLE_IMPL(win_T, window) +HANDLE_IMPL(tabpage_T, tabpage) + +void handle_init() +{ + HANDLE_INIT(buffer); + HANDLE_INIT(window); + HANDLE_INIT(tabpage); +} diff --git a/src/nvim/api/private/handle.h b/src/nvim/api/private/handle.h new file mode 100644 index 0000000000..27df453233 --- /dev/null +++ b/src/nvim/api/private/handle.h @@ -0,0 +1,20 @@ +#ifndef NVIM_API_HANDLE_H +#define NVIM_API_HANDLE_H + +#include "nvim/vim.h" +#include "nvim/buffer_defs.h" + +#define HANDLE_DECLS(type, name) \ + type *handle_get_##name(uint64_t handle); \ + void handle_register_##name(type *name); \ + void handle_unregister_##name(type *name); + +HANDLE_DECLS(buf_T, buffer) +HANDLE_DECLS(win_T, window) +HANDLE_DECLS(tabpage_T, tabpage) + +void handle_init(void); + + +#endif // NVIM_API_HANDLE_H + diff --git a/src/nvim/api/helpers.c b/src/nvim/api/private/helpers.c index a193c8721e..c4340ddd89 100644 --- a/src/nvim/api/helpers.c +++ b/src/nvim/api/private/helpers.c @@ -2,8 +2,9 @@ #include <stdlib.h> #include <string.h> -#include "nvim/api/helpers.h" -#include "nvim/api/defs.h" +#include "nvim/api/private/helpers.h" +#include "nvim/api/private/defs.h" +#include "nvim/api/private/handle.h" #include "nvim/vim.h" #include "nvim/buffer.h" #include "nvim/window.h" @@ -285,43 +286,29 @@ Object vim_to_object(typval_T *obj) buf_T *find_buffer(Buffer buffer, Error *err) { - if (buffer > INT_MAX || buffer < INT_MIN) { - set_api_error("Invalid buffer id", err); - return NULL; - } - - buf_T *buf = buflist_findnr((int)buffer); + buf_T *rv = handle_get_buffer(buffer); - if (buf == NULL) { + if (!rv) { set_api_error("Invalid buffer id", err); } - return buf; + return rv; } win_T * find_window(Window window, Error *err) { - tabpage_T *tp; - win_T *wp; + win_T *rv = handle_get_window(window); - FOR_ALL_TAB_WINDOWS(tp, wp) { - if (!--window) { - return wp; - } + if (!rv) { + set_api_error("Invalid window id", err); } - set_api_error("Invalid window id", err); - return NULL; + return rv; } tabpage_T * find_tab(Tabpage tabpage, Error *err) { - if (tabpage > INT_MAX || tabpage < INT_MIN) { - set_api_error("Invalid tabpage id", err); - return NULL; - } - - tabpage_T *rv = find_tabpage((int)tabpage); + tabpage_T *rv = handle_get_tabpage(tabpage); if (!rv) { set_api_error("Invalid tabpage id", err); diff --git a/src/nvim/api/helpers.h b/src/nvim/api/private/helpers.h index f93487d62f..da7e357d04 100644 --- a/src/nvim/api/helpers.h +++ b/src/nvim/api/private/helpers.h @@ -3,7 +3,7 @@ #include <stdbool.h> -#include "nvim/api/defs.h" +#include "nvim/api/private/defs.h" #include "nvim/vim.h" #define set_api_error(message, err) \ diff --git a/src/nvim/api/tabpage.c b/src/nvim/api/tabpage.c index fc50723ba5..b7243c68a8 100644 --- a/src/nvim/api/tabpage.c +++ b/src/nvim/api/tabpage.c @@ -4,12 +4,13 @@ #include "nvim/api/tabpage.h" #include "nvim/api/vim.h" -#include "nvim/api/defs.h" -#include "nvim/api/helpers.h" +#include "nvim/api/private/defs.h" +#include "nvim/api/private/helpers.h" +#include "nvim/memory.h" -Integer tabpage_get_window_count(Tabpage tabpage, Error *err) +WindowArray tabpage_get_windows(Tabpage tabpage, Error *err) { - Integer rv = 0; + WindowArray rv = ARRAY_DICT_INIT; tabpage_T *tab = find_tab(tabpage, err); if (!tab) { @@ -23,7 +24,17 @@ Integer tabpage_get_window_count(Tabpage tabpage, Error *err) if (tp != tab) { break; } - rv++; + rv.size++; + } + + rv.items = xmalloc(sizeof(Window) * rv.size); + size_t i = 0; + + FOR_ALL_TAB_WINDOWS(tp, wp) { + if (tp != tab) { + break; + } + rv.items[i++] = wp->handle; } return rv; @@ -67,13 +78,11 @@ Window tabpage_get_window(Tabpage tabpage, Error *err) } else { tabpage_T *tp; win_T *wp; - rv = 1; FOR_ALL_TAB_WINDOWS(tp, wp) { if (tp == tab && wp == tab->tp_curwin) { - return rv; + return wp->handle; } - rv++; } // There should always be a current window for a tabpage abort(); diff --git a/src/nvim/api/tabpage.h b/src/nvim/api/tabpage.h index ef049fb644..dddcecbdbd 100644 --- a/src/nvim/api/tabpage.h +++ b/src/nvim/api/tabpage.h @@ -4,14 +4,14 @@ #include <stdint.h> #include <stdbool.h> -#include "nvim/api/defs.h" +#include "nvim/api/private/defs.h" /// Gets the number of windows in a tabpage /// /// @param tabpage The tabpage /// @param[out] err Details of an error that may have occurred /// @return The number of windows in `tabpage` -Integer tabpage_get_window_count(Tabpage tabpage, Error *err); +WindowArray tabpage_get_windows(Tabpage tabpage, Error *err); /// Gets a tabpage variable /// diff --git a/src/nvim/api/vim.c b/src/nvim/api/vim.c index 505844e651..694781e0a3 100644 --- a/src/nvim/api/vim.c +++ b/src/nvim/api/vim.c @@ -4,8 +4,8 @@ #include <string.h> #include "nvim/api/vim.h" -#include "nvim/api/helpers.h" -#include "nvim/api/defs.h" +#include "nvim/api/private/helpers.h" +#include "nvim/api/private/defs.h" #include "nvim/api/buffer.h" #include "nvim/vim.h" #include "nvim/buffer.h" @@ -73,12 +73,15 @@ Integer vim_strwidth(String str, Error *err) return 0; } - return mb_string2cells((char_u *)str.data, (int)str.size); + char *buf = xstrndup(str.data, str.size); + Integer rv = mb_string2cells((char_u *)buf, -1); + free(buf); + return rv; } StringArray vim_list_runtime_paths(void) { - StringArray rv = {.size = 0}; + StringArray rv = ARRAY_DICT_INIT; uint8_t *rtp = p_rtp; if (*rtp == NUL) { @@ -94,14 +97,12 @@ StringArray vim_list_runtime_paths(void) rtp++; } - // index - uint32_t i = 0; // Allocate memory for the copies rv.items = xmalloc(sizeof(String) * rv.size); // reset the position rtp = p_rtp; // Start copying - while (*rtp != NUL) { + for (size_t i = 0; i < rv.size && *rtp != NUL; i++) { rv.items[i].data = xmalloc(MAXPATHL); // Copy the path from 'runtimepath' to rv.items[i] int length = copy_option_part(&rtp, @@ -110,7 +111,6 @@ StringArray vim_list_runtime_paths(void) ","); assert(length >= 0); rv.items[i].size = (size_t)length; - i++; } return rv; @@ -118,8 +118,14 @@ StringArray vim_list_runtime_paths(void) void vim_change_directory(String dir, Error *err) { + if (dir.size >= MAXPATHL) { + set_api_error("directory string is too long", err); + return; + } + char string[MAXPATHL]; strncpy(string, dir.data, dir.size); + string[dir.size] = NUL; try_start(); @@ -136,17 +142,17 @@ void vim_change_directory(String dir, Error *err) String vim_get_current_line(Error *err) { - return buffer_get_line(curbuf->b_fnum, curwin->w_cursor.lnum - 1, err); + return buffer_get_line(curbuf->handle, curwin->w_cursor.lnum - 1, err); } void vim_set_current_line(String line, Error *err) { - buffer_set_line(curbuf->b_fnum, curwin->w_cursor.lnum - 1, line, err); + buffer_set_line(curbuf->handle, curwin->w_cursor.lnum - 1, line, err); } void vim_del_current_line(Error *err) { - buffer_del_line(curbuf->b_fnum, curwin->w_cursor.lnum - 1, err); + buffer_del_line(curbuf->handle, curwin->w_cursor.lnum - 1, err); } Object vim_get_var(String name, Error *err) @@ -184,32 +190,43 @@ void vim_err_write(String str) write_msg(str, true); } -Integer vim_get_buffer_count(void) +BufferArray vim_get_buffers(void) { + BufferArray rv = ARRAY_DICT_INIT; buf_T *b = firstbuf; - Integer n = 0; while (b) { - n++; + rv.size++; b = b->b_next; } - return n; + rv.items = xmalloc(sizeof(Buffer) * rv.size); + size_t i = 0; + b = firstbuf; + + while (b) { + rv.items[i++] = b->handle; + b = b->b_next; + } + + return rv; } Buffer vim_get_current_buffer(void) { - return curbuf->b_fnum; + return curbuf->handle; } void vim_set_current_buffer(Buffer buffer, Error *err) { - if (!find_buffer(buffer, err)) { + buf_T *buf = find_buffer(buffer, err); + + if (!buf) { return; } try_start(); - if (do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, (int)buffer, 0) == FAIL) { + if (do_buffer(DOBUF_GOTO, DOBUF_FIRST, FORWARD, buf->b_fnum, 0) == FAIL) { if (try_end(err)) { return; } @@ -223,14 +240,21 @@ void vim_set_current_buffer(Buffer buffer, Error *err) try_end(err); } -Integer vim_get_window_count(void) +WindowArray vim_get_windows(void) { + WindowArray rv = ARRAY_DICT_INIT; tabpage_T *tp; win_T *wp; - Integer rv = 0; FOR_ALL_TAB_WINDOWS(tp, wp) { - rv++; + rv.size++; + } + + rv.items = xmalloc(sizeof(Window) * rv.size); + size_t i = 0; + + FOR_ALL_TAB_WINDOWS(tp, wp) { + rv.items[i++] = wp->handle; } return rv; @@ -238,20 +262,7 @@ Integer vim_get_window_count(void) Window vim_get_current_window(void) { - tabpage_T *tp; - win_T *wp; - Window rv = 1; - - FOR_ALL_TAB_WINDOWS(tp, wp) { - if (wp == curwin) { - return rv; - } - - rv++; - } - - // There should always be a current window - abort(); + return curwin->handle; } void vim_set_current_window(Window window, Error *err) @@ -263,7 +274,7 @@ void vim_set_current_window(Window window, Error *err) } try_start(); - win_goto(win); + goto_tabpage_win(win_find_tabpage(win), win); if (win != curwin) { if (try_end(err)) { @@ -276,14 +287,23 @@ void vim_set_current_window(Window window, Error *err) try_end(err); } -Integer vim_get_tabpage_count(void) +TabpageArray vim_get_tabpages(void) { + TabpageArray rv = ARRAY_DICT_INIT; tabpage_T *tp = first_tabpage; - Integer rv = 0; - while (tp != NULL) { + while (tp) { + rv.size++; + tp = tp->tp_next; + } + + rv.items = xmalloc(sizeof(Tabpage) * rv.size); + size_t i = 0; + tp = first_tabpage; + + while (tp) { + rv.items[i++] = tp->handle; tp = tp->tp_next; - rv++; } return rv; @@ -291,24 +311,19 @@ Integer vim_get_tabpage_count(void) Tabpage vim_get_current_tabpage(void) { - Tabpage rv = 1; - tabpage_T *t; - - for (t = first_tabpage; t != NULL && t != curtab; t = t->tp_next) { - rv++; - } - - return rv; + return curtab->handle; } void vim_set_current_tabpage(Tabpage tabpage, Error *err) { - if (!find_tab(tabpage, err)) { + tabpage_T *tp = find_tab(tabpage, err); + + if (!tp) { return; } try_start(); - goto_tabpage((int)tabpage); + goto_tabpage_tp(tp, true, true); try_end(err); } diff --git a/src/nvim/api/vim.h b/src/nvim/api/vim.h index 4ecc9fc2d0..acfab11cf7 100644 --- a/src/nvim/api/vim.h +++ b/src/nvim/api/vim.h @@ -4,7 +4,7 @@ #include <stdint.h> #include <stdbool.h> -#include "nvim/api/defs.h" +#include "nvim/api/private/defs.h" /// Send keys to vim input buffer, simulating user input. /// @@ -108,10 +108,10 @@ void vim_out_write(String str); /// @param str The message void vim_err_write(String str); -/// Gets the number of buffers +/// Gets the current list of buffer handles /// /// @return The number of buffers -Integer vim_get_buffer_count(void); +BufferArray vim_get_buffers(void); /// Return the current buffer /// @@ -124,10 +124,10 @@ Buffer vim_get_current_buffer(void); /// @param[out] err Details of an error that may have occurred void vim_set_current_buffer(Buffer buffer, Error *err); -/// Gets the number of windows +/// Gets the current list of window handles /// /// @return The number of windows -Integer vim_get_window_count(void); +WindowArray vim_get_windows(void); /// Return the current window /// @@ -139,10 +139,10 @@ Window vim_get_current_window(void); /// @param handle The window handle void vim_set_current_window(Window window, Error *err); -/// Gets the number of tab pages +/// Gets the current list of tabpage handles /// /// @return The number of tab pages -Integer vim_get_tabpage_count(void); +TabpageArray vim_get_tabpages(void); /// Return the current tab page /// diff --git a/src/nvim/api/window.c b/src/nvim/api/window.c index 8e21034c40..8bd8316477 100644 --- a/src/nvim/api/window.c +++ b/src/nvim/api/window.c @@ -3,8 +3,8 @@ #include <stdlib.h> #include "nvim/api/window.h" -#include "nvim/api/defs.h" -#include "nvim/api/helpers.h" +#include "nvim/api/private/defs.h" +#include "nvim/api/private/helpers.h" #include "nvim/vim.h" #include "nvim/window.h" #include "nvim/screen.h" @@ -19,7 +19,7 @@ Buffer window_get_buffer(Window window, Error *err) return 0; } - return win->w_buffer->b_fnum; + return win->w_buffer->handle; } Position window_get_cursor(Window window, Error *err) @@ -192,8 +192,14 @@ Position window_get_position(Window window, Error *err) Tabpage window_get_tabpage(Window window, Error *err) { - set_api_error("Not implemented", err); - return 0; + Tabpage rv = 0; + win_T *win = find_window(window, err); + + if (win) { + rv = win_find_tabpage(win)->handle; + } + + return rv; } Boolean window_is_valid(Window window) diff --git a/src/nvim/api/window.h b/src/nvim/api/window.h index 525b7f86c7..4c036ff5d7 100644 --- a/src/nvim/api/window.h +++ b/src/nvim/api/window.h @@ -4,7 +4,7 @@ #include <stdint.h> #include <stdbool.h> -#include "nvim/api/defs.h" +#include "nvim/api/private/defs.h" /// Gets the current buffer in a window /// diff --git a/src/nvim/buffer.c b/src/nvim/buffer.c index ffb62add3c..7c50b1721c 100644 --- a/src/nvim/buffer.c +++ b/src/nvim/buffer.c @@ -26,6 +26,7 @@ #include <string.h> +#include "nvim/api/private/handle.h" #include "nvim/vim.h" #include "nvim/buffer.h" #include "nvim/charset.h" @@ -538,6 +539,7 @@ void buf_freeall(buf_T *buf, int flags) */ static void free_buffer(buf_T *buf) { + handle_unregister_buffer(buf); free_buffer_stuff(buf, TRUE); unref_var_dict(buf->b_vars); aubuflocal_remove(buf); @@ -1362,6 +1364,7 @@ buflist_new ( } if (buf != curbuf || curbuf == NULL) { buf = xcalloc(1, sizeof(buf_T)); + handle_register_buffer(buf); /* init b: variables */ buf->b_vars = dict_alloc(); init_var_dict(buf->b_vars, &buf->b_bufvar, VAR_SCOPE); diff --git a/src/nvim/buffer_defs.h b/src/nvim/buffer_defs.h index d658da9502..0a24280b4a 100644 --- a/src/nvim/buffer_defs.h +++ b/src/nvim/buffer_defs.h @@ -401,6 +401,7 @@ typedef struct { */ struct file_buffer { + uint64_t handle; // unique identifier for the buffer memline_T b_ml; /* associated memline (also contains line count) */ @@ -737,6 +738,7 @@ struct diffblock_S { */ typedef struct tabpage_S tabpage_T; struct tabpage_S { + uint64_t handle; tabpage_T *tp_next; /* next tabpage or NULL */ frame_T *tp_topframe; /* topframe for the windows */ win_T *tp_curwin; /* current window in this Tab page */ @@ -839,6 +841,7 @@ struct matchitem { * All row numbers are relative to the start of the window, except w_winrow. */ struct window_S { + uint64_t handle; buf_T *w_buffer; /* buffer we are a window into (used often, keep it the first item!) */ diff --git a/src/nvim/map.c b/src/nvim/map.c index 28fd0af61c..559a5f261a 100644 --- a/src/nvim/map.c +++ b/src/nvim/map.c @@ -85,3 +85,4 @@ MAP_IMPL(cstr_t) MAP_IMPL(ptr_t) +MAP_IMPL(uint64_t) diff --git a/src/nvim/map.h b/src/nvim/map.h index ae47561deb..dba56dc5aa 100644 --- a/src/nvim/map.h +++ b/src/nvim/map.h @@ -21,6 +21,7 @@ MAP_DECLS(cstr_t) MAP_DECLS(ptr_t) +MAP_DECLS(uint64_t) #define map_new(T) map_##T##_new #define map_free(T) map_##T##_free diff --git a/src/nvim/os/msgpack_rpc.c b/src/nvim/os/msgpack_rpc.c index 45832070b1..d7ffa6f559 100644 --- a/src/nvim/os/msgpack_rpc.c +++ b/src/nvim/os/msgpack_rpc.c @@ -4,6 +4,54 @@ #include "nvim/vim.h" #include "nvim/memory.h" +#define REMOTE_FUNCS_IMPL(t, lt) \ + bool msgpack_rpc_to_##lt(msgpack_object *obj, t *arg) \ + { \ + *arg = obj->via.u64; \ + return obj->type == MSGPACK_OBJECT_POSITIVE_INTEGER; \ + } \ + \ + void msgpack_rpc_from_##lt(t result, msgpack_packer *res) \ + { \ + msgpack_pack_uint64(res, result); \ + } + +#define TYPED_ARRAY_IMPL(t, lt) \ + bool msgpack_rpc_to_##lt##array(msgpack_object *obj, t##Array *arg) \ + { \ + if (obj->type != MSGPACK_OBJECT_ARRAY) { \ + return false; \ + } \ + \ + arg->size = obj->via.array.size; \ + arg->items = xcalloc(obj->via.array.size, sizeof(t)); \ + \ + for (size_t i = 0; i < obj->via.array.size; i++) { \ + if (!msgpack_rpc_to_##lt(obj->via.array.ptr + i, &arg->items[i])) { \ + return false; \ + } \ + } \ + \ + return true; \ + } \ + \ + void msgpack_rpc_from_##lt##array(t##Array result, msgpack_packer *res) \ + { \ + msgpack_pack_array(res, result.size); \ + \ + for (size_t i = 0; i < result.size; i++) { \ + msgpack_rpc_from_##lt(result.items[i], res); \ + } \ + } \ + \ + void msgpack_rpc_free_##lt##array(t##Array value) { \ + for (size_t i = 0; i < value.size; i++) { \ + msgpack_rpc_free_##lt(value.items[i]); \ + } \ + \ + free(value.items); \ + } + void msgpack_rpc_call(msgpack_object *req, msgpack_packer *res) { // The initial response structure is the same no matter what happens, @@ -104,21 +152,6 @@ bool msgpack_rpc_to_string(msgpack_object *obj, String *arg) return obj->type == MSGPACK_OBJECT_RAW; } -bool msgpack_rpc_to_buffer(msgpack_object *obj, Buffer *arg) -{ - return msgpack_rpc_to_integer(obj, arg); -} - -bool msgpack_rpc_to_window(msgpack_object *obj, Window *arg) -{ - return msgpack_rpc_to_integer(obj, arg); -} - -bool msgpack_rpc_to_tabpage(msgpack_object *obj, Tabpage *arg) -{ - return msgpack_rpc_to_integer(obj, arg); -} - bool msgpack_rpc_to_object(msgpack_object *obj, Object *arg) { switch (obj->type) { @@ -156,24 +189,6 @@ bool msgpack_rpc_to_object(msgpack_object *obj, Object *arg) } } -bool msgpack_rpc_to_stringarray(msgpack_object *obj, StringArray *arg) -{ - if (obj->type != MSGPACK_OBJECT_ARRAY) { - return false; - } - - arg->size = obj->via.array.size; - arg->items = xcalloc(obj->via.array.size, sizeof(String)); - - for (uint32_t i = 0; i < obj->via.array.size; i++) { - if (!msgpack_rpc_to_string(obj->via.array.ptr + i, &arg->items[i])) { - return false; - } - } - - return true; -} - bool msgpack_rpc_to_position(msgpack_object *obj, Position *arg) { return obj->type == MSGPACK_OBJECT_ARRAY @@ -251,21 +266,6 @@ void msgpack_rpc_from_string(String result, msgpack_packer *res) msgpack_pack_raw_body(res, result.data, result.size); } -void msgpack_rpc_from_buffer(Buffer result, msgpack_packer *res) -{ - msgpack_rpc_from_integer(result, res); -} - -void msgpack_rpc_from_window(Window result, msgpack_packer *res) -{ - msgpack_rpc_from_integer(result, res); -} - -void msgpack_rpc_from_tabpage(Tabpage result, msgpack_packer *res) -{ - msgpack_rpc_from_integer(result, res); -} - void msgpack_rpc_from_object(Object result, msgpack_packer *res) { switch (result.type) { @@ -302,15 +302,6 @@ void msgpack_rpc_from_object(Object result, msgpack_packer *res) } } -void msgpack_rpc_from_stringarray(StringArray result, msgpack_packer *res) -{ - msgpack_pack_array(res, result.size); - - for (size_t i = 0; i < result.size; i++) { - msgpack_rpc_from_string(result.items[i], res); - } -} - void msgpack_rpc_from_position(Position result, msgpack_packer *res) { msgpack_pack_array(res, 2);; @@ -363,14 +354,6 @@ void msgpack_rpc_free_object(Object value) } } -void msgpack_rpc_free_stringarray(StringArray value) { - for (uint32_t i = 0; i < value.size; i++) { - msgpack_rpc_free_string(value.items[i]); - } - - free(value.items); -} - void msgpack_rpc_free_array(Array value) { for (uint32_t i = 0; i < value.size; i++) { @@ -390,3 +373,12 @@ void msgpack_rpc_free_dictionary(Dictionary value) free(value.items); } +REMOTE_FUNCS_IMPL(Buffer, buffer) +REMOTE_FUNCS_IMPL(Window, window) +REMOTE_FUNCS_IMPL(Tabpage, tabpage) + +TYPED_ARRAY_IMPL(Buffer, buffer) +TYPED_ARRAY_IMPL(Window, window) +TYPED_ARRAY_IMPL(Tabpage, tabpage) +TYPED_ARRAY_IMPL(String, string) + diff --git a/src/nvim/os/msgpack_rpc.h b/src/nvim/os/msgpack_rpc.h index 0e9d474d8d..a6a909ac1f 100644 --- a/src/nvim/os/msgpack_rpc.h +++ b/src/nvim/os/msgpack_rpc.h @@ -6,7 +6,7 @@ #include <msgpack.h> -#include "nvim/api/defs.h" +#include "nvim/api/private/defs.h" /// Validates the basic structure of the msgpack-rpc call and fills `res` /// with the basic response structure. @@ -48,6 +48,9 @@ bool msgpack_rpc_to_window(msgpack_object *obj, Window *arg); bool msgpack_rpc_to_tabpage(msgpack_object *obj, Tabpage *arg); bool msgpack_rpc_to_object(msgpack_object *obj, Object *arg); bool msgpack_rpc_to_stringarray(msgpack_object *obj, StringArray *arg); +bool msgpack_rpc_to_bufferarray(msgpack_object *obj, BufferArray *arg); +bool msgpack_rpc_to_windowarray(msgpack_object *obj, WindowArray *arg); +bool msgpack_rpc_to_tabpagearray(msgpack_object *obj, TabpageArray *arg); bool msgpack_rpc_to_array(msgpack_object *obj, Array *arg); bool msgpack_rpc_to_dictionary(msgpack_object *obj, Dictionary *arg); @@ -67,6 +70,9 @@ void msgpack_rpc_from_window(Window result, msgpack_packer *res); void msgpack_rpc_from_tabpage(Tabpage result, msgpack_packer *res); void msgpack_rpc_from_object(Object result, msgpack_packer *res); void msgpack_rpc_from_stringarray(StringArray result, msgpack_packer *res); +void msgpack_rpc_from_bufferarray(BufferArray result, msgpack_packer *res); +void msgpack_rpc_from_windowarray(WindowArray result, msgpack_packer *res); +void msgpack_rpc_from_tabpagearray(TabpageArray result, msgpack_packer *res); void msgpack_rpc_from_array(Array result, msgpack_packer *res); void msgpack_rpc_from_dictionary(Dictionary result, msgpack_packer *res); @@ -80,9 +86,12 @@ void msgpack_rpc_from_dictionary(Dictionary result, msgpack_packer *res); #define msgpack_rpc_init_window #define msgpack_rpc_init_tabpage #define msgpack_rpc_init_object = {.type = kObjectTypeNil} -#define msgpack_rpc_init_stringarray = {.items = NULL, .size = 0} -#define msgpack_rpc_init_array = {.items = NULL, .size = 0} -#define msgpack_rpc_init_dictionary = {.items = NULL, .size = 0} +#define msgpack_rpc_init_stringarray = ARRAY_DICT_INIT +#define msgpack_rpc_init_bufferarray = ARRAY_DICT_INIT +#define msgpack_rpc_init_windowarray = ARRAY_DICT_INIT +#define msgpack_rpc_init_tabpagearray = ARRAY_DICT_INIT +#define msgpack_rpc_init_array = ARRAY_DICT_INIT +#define msgpack_rpc_init_dictionary = ARRAY_DICT_INIT /// Helpers for freeing arguments/return value /// @@ -99,9 +108,11 @@ void msgpack_rpc_from_dictionary(Dictionary result, msgpack_packer *res); #define msgpack_rpc_free_tabpage(value) void msgpack_rpc_free_object(Object value); void msgpack_rpc_free_stringarray(StringArray value); +void msgpack_rpc_free_bufferarray(BufferArray value); +void msgpack_rpc_free_windowarray(WindowArray value); +void msgpack_rpc_free_tabpagearray(TabpageArray value); void msgpack_rpc_free_array(Array value); void msgpack_rpc_free_dictionary(Dictionary value); - #endif // NVIM_OS_MSGPACK_RPC_H diff --git a/src/nvim/os_unix.c b/src/nvim/os_unix.c index 52627b6a8b..e0b838ed26 100644 --- a/src/nvim/os_unix.c +++ b/src/nvim/os_unix.c @@ -27,6 +27,7 @@ #include <string.h> +#include "nvim/api/private/handle.h" #include "nvim/vim.h" #include "nvim/os_unix.h" #include "nvim/buffer.h" @@ -542,6 +543,7 @@ int mch_nodetype(char_u *name) void mch_early_init() { + handle_init(); time_init(); } diff --git a/src/nvim/window.c b/src/nvim/window.c index 851e9cead7..534805b766 100644 --- a/src/nvim/window.c +++ b/src/nvim/window.c @@ -6,6 +6,7 @@ * See README.txt for an overview of the Vim source code. */ +#include "nvim/api/private/handle.h" #include "nvim/vim.h" #include "nvim/window.h" #include "nvim/buffer.h" @@ -2844,6 +2845,7 @@ void win_init_size(void) static tabpage_T *alloc_tabpage(void) { tabpage_T *tp = xcalloc(1, sizeof(tabpage_T)); + handle_register_tabpage(tp); /* init t: variables */ tp->tp_vars = dict_alloc(); @@ -2858,6 +2860,7 @@ void free_tabpage(tabpage_T *tp) { int idx; + handle_unregister_tabpage(tp); diff_clear(tp); for (idx = 0; idx < SNAP_COUNT; ++idx) clear_snapshot(tp, idx); @@ -3568,6 +3571,7 @@ static win_T *win_alloc(win_T *after, int hidden) * allocate window structure and linesizes arrays */ win_T *new_wp = xcalloc(1, sizeof(win_T)); + handle_register_window(new_wp); win_alloc_lines(new_wp); /* init w: variables */ @@ -3583,6 +3587,7 @@ static win_T *win_alloc(win_T *after, int hidden) */ if (!hidden) win_append(after, new_wp); + new_wp->w_wincol = 0; new_wp->w_width = Columns; @@ -3618,6 +3623,7 @@ win_free ( buf_T *buf; wininfo_T *wip; + handle_unregister_window(wp); clearFolding(wp); /* reduce the reference count to the argument list. */ |