aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt33
-rw-r--r--cmake/LuaHelpers.cmake4
-rw-r--r--runtime/autoload/remote/host.vim1
-rw-r--r--runtime/doc/eval.txt20
-rw-r--r--src/nvim/CMakeLists.txt1
-rw-r--r--src/nvim/eval.c33
-rw-r--r--src/nvim/misc2.c5
-rw-r--r--src/nvim/ops.c19
-rw-r--r--src/nvim/option.c19
-rw-r--r--src/nvim/os/fs.c4
-rw-r--r--src/nvim/syntax.c3
-rw-r--r--src/nvim/version.c14
-rw-r--r--test/functional/legacy/file_perm_spec.lua42
-rw-r--r--test/functional/legacy/set_spec.lua15
-rw-r--r--test/functional/ui/highlight_spec.lua41
-rw-r--r--test/unit/os/fs_spec.lua19
16 files changed, 222 insertions, 51 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 1abc05f0da..317d2a1a5b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -300,9 +300,6 @@ include_directories(SYSTEM ${LIBUV_INCLUDE_DIRS})
find_package(Msgpack 1.0.0 REQUIRED)
include_directories(SYSTEM ${MSGPACK_INCLUDE_DIRS})
-find_package(LuaJit REQUIRED)
-include_directories(SYSTEM ${LUAJIT_INCLUDE_DIRS})
-
find_package(Unibilium REQUIRED)
include_directories(SYSTEM ${UNIBILIUM_INCLUDE_DIRS})
@@ -477,18 +474,24 @@ if(BUSTED_PRG)
add_custom_target(benchmark-prereqs
DEPENDS ${BENCHMARK_PREREQS})
- add_custom_target(unittest
- COMMAND ${CMAKE_COMMAND}
- -DBUSTED_PRG=${BUSTED_PRG}
- -DLUA_PRG=${LUA_PRG}
- -DWORKING_DIR=${CMAKE_CURRENT_SOURCE_DIR}
- -DBUSTED_OUTPUT_TYPE=${BUSTED_OUTPUT_TYPE}
- -DTEST_DIR=${CMAKE_CURRENT_SOURCE_DIR}/test
- -DBUILD_DIR=${CMAKE_BINARY_DIR}
- -DTEST_TYPE=unit
- -P ${PROJECT_SOURCE_DIR}/cmake/RunTests.cmake
- DEPENDS ${UNITTEST_PREREQS}
- ${TEST_TARGET_ARGS})
+ check_lua_module(${LUA_PRG} "ffi" LUA_HAS_FFI)
+ if(LUA_HAS_FFI)
+ add_custom_target(unittest
+ COMMAND ${CMAKE_COMMAND}
+ -DBUSTED_PRG=${BUSTED_PRG}
+ -DLUA_PRG=${LUA_PRG}
+ -DWORKING_DIR=${CMAKE_CURRENT_SOURCE_DIR}
+ -DBUSTED_OUTPUT_TYPE=${BUSTED_OUTPUT_TYPE}
+ -DTEST_DIR=${CMAKE_CURRENT_SOURCE_DIR}/test
+ -DBUILD_DIR=${CMAKE_BINARY_DIR}
+ -DTEST_TYPE=unit
+ -P ${PROJECT_SOURCE_DIR}/cmake/RunTests.cmake
+ DEPENDS ${UNITTEST_PREREQS}
+ ${TEST_TARGET_ARGS})
+ else()
+ message(WARNING "The Luajit ffi is not available in ${LUA_PRG}"
+ ", disabling unit tests")
+ endif()
add_custom_target(functionaltest
COMMAND ${CMAKE_COMMAND}
diff --git a/cmake/LuaHelpers.cmake b/cmake/LuaHelpers.cmake
index b1e67e0ca7..32f7e46a57 100644
--- a/cmake/LuaHelpers.cmake
+++ b/cmake/LuaHelpers.cmake
@@ -8,8 +8,6 @@ function(check_lua_module LUA_PRG_PATH MODULE RESULT_VAR)
RESULT_VARIABLE module_missing
ERROR_QUIET)
if(module_missing)
- message(STATUS
- "[${LUA_PRG_PATH}] The '${MODULE}' lua package is required for building Neovim")
set(${RESULT_VAR} False PARENT_SCOPE)
else()
set(${RESULT_VAR} True PARENT_SCOPE)
@@ -29,6 +27,8 @@ function(check_lua_deps LUA_PRG_PATH MODULES RESULT_VAR)
foreach(module ${MODULES})
check_lua_module(${LUA_PRG_PATH} ${module} has_module)
if(NOT has_module)
+ message(STATUS
+ "[${LUA_PRG_PATH}] The '${module}' lua package is required for building Neovim")
set(${RESULT_VAR} False PARENT_SCOPE)
return()
endif()
diff --git a/runtime/autoload/remote/host.vim b/runtime/autoload/remote/host.vim
index 8faeaed2ea..a63c6a923b 100644
--- a/runtime/autoload/remote/host.vim
+++ b/runtime/autoload/remote/host.vim
@@ -140,6 +140,7 @@ function! s:RegistrationCommands(host) abort
call remote#host#RegisterClone(host_id, a:host)
let pattern = s:plugin_patterns[a:host]
let paths = globpath(&rtp, 'rplugin/'.a:host.'/'.pattern, 0, 1)
+ let paths = map(paths, 'tr(v:val,"\\","/")') " Normalize slashes #4795
if empty(paths)
return []
endif
diff --git a/runtime/doc/eval.txt b/runtime/doc/eval.txt
index 87b90900cb..eebdabd154 100644
--- a/runtime/doc/eval.txt
+++ b/runtime/doc/eval.txt
@@ -2051,6 +2051,7 @@ serverlist() String get a list of available servers
setbufvar({expr}, {varname}, {val}) set {varname} in buffer {expr} to {val}
setcharsearch({dict}) Dict set character search from {dict}
setcmdpos({pos}) Number set cursor position in command-line
+setfperm({fname}, {mode} Number set {fname} file permissions to {mode}
setline({lnum}, {line}) Number set line {lnum} to {line}
setloclist({nr}, {list}[, {action}[, {title}]])
Number modify location list using {list}
@@ -3628,6 +3629,8 @@ getfperm({fname}) *getfperm()*
< This will hopefully (from a security point of view) display
the string "rw-r--r--" or even "rw-------".
+ For setting permissions use |setfperm()|.
+
getftime({fname}) *getftime()*
The result is a Number, which is the last modification time of
the given file {fname}. The value is measured as seconds
@@ -5866,6 +5869,23 @@ setcmdpos({pos}) *setcmdpos()*
Returns 0 when successful, 1 when not editing the command
line.
+setfperm({fname}, {mode}) *setfperm()* *chmod*
+ Set the file permissions for {fname} to {mode}.
+ {mode} must be a string with 9 characters. It is of the form
+ "rwxrwxrwx", where each group of "rwx" flags represent, in
+ turn, the permissions of the owner of the file, the group the
+ file belongs to, and other users. A '-' character means the
+ permission is off, any other character means on. Multi-byte
+ characters are not supported.
+
+ For example "rw-r-----" means read-write for the user,
+ readable by the group, not accessible by others. "xx-x-----"
+ would do the same thing.
+
+ Returns non-zero for success, zero for failure.
+
+ To read permissions see |getfperm()|.
+
setline({lnum}, {text}) *setline()*
Set line {lnum} of the current buffer to {text}. To insert
lines use |append()|.
diff --git a/src/nvim/CMakeLists.txt b/src/nvim/CMakeLists.txt
index 6b2ce08d36..172643091a 100644
--- a/src/nvim/CMakeLists.txt
+++ b/src/nvim/CMakeLists.txt
@@ -231,7 +231,6 @@ endif()
list(APPEND NVIM_LINK_LIBRARIES
${LIBUV_LIBRARIES}
${MSGPACK_LIBRARIES}
- ${LUAJIT_LIBRARIES}
${LIBVTERM_LIBRARIES}
${LIBTERMKEY_LIBRARIES}
${UNIBILIUM_LIBRARIES}
diff --git a/src/nvim/eval.c b/src/nvim/eval.c
index 201a71facb..96c008b0e0 100644
--- a/src/nvim/eval.c
+++ b/src/nvim/eval.c
@@ -6877,6 +6877,7 @@ static struct fst {
{ "setbufvar", 3, 3, f_setbufvar },
{ "setcharsearch", 1, 1, f_setcharsearch },
{ "setcmdpos", 1, 1, f_setcmdpos },
+ { "setfperm", 2, 2, f_setfperm },
{ "setline", 2, 2, f_setline },
{ "setloclist", 2, 4, f_setloclist },
{ "setmatches", 1, 1, f_setmatches },
@@ -14446,6 +14447,38 @@ static void f_setcmdpos(typval_T *argvars, typval_T *rettv)
rettv->vval.v_number = set_cmdline_pos(pos);
}
+
+/// "setfperm({fname}, {mode})" function
+static void f_setfperm(typval_T *argvars, typval_T *rettv)
+{
+ rettv->vval.v_number = 0;
+
+ char_u *fname = get_tv_string_chk(&argvars[0]);
+ if (fname == NULL) {
+ return;
+ }
+
+ char_u modebuf[NUMBUFLEN];
+ char_u *mode_str = get_tv_string_buf_chk(&argvars[1], modebuf);
+ if (mode_str == NULL) {
+ return;
+ }
+ if (STRLEN(mode_str) != 9) {
+ EMSG2(_(e_invarg2), mode_str);
+ return;
+ }
+
+ int mask = 1;
+ int mode = 0;
+ for (int i = 8; i >= 0; i--) {
+ if (mode_str[i] != '-') {
+ mode |= mask;
+ }
+ mask = mask << 1;
+ }
+ rettv->vval.v_number = os_setperm(fname, mode) == OK;
+}
+
/*
* "setline()" function
*/
diff --git a/src/nvim/misc2.c b/src/nvim/misc2.c
index 4b64de1be0..368f83cfb5 100644
--- a/src/nvim/misc2.c
+++ b/src/nvim/misc2.c
@@ -467,11 +467,12 @@ bool put_bytes(FILE *fd, uintmax_t number, size_t len)
}
/// Writes time_t to file "fd" in 8 bytes.
-void put_time(FILE *fd, time_t time_)
+/// @returns FAIL when the write failed.
+int put_time(FILE *fd, time_t time_)
{
uint8_t buf[8];
time_to_bytes(time_, buf);
- (void)fwrite(buf, sizeof(uint8_t), ARRAY_SIZE(buf), fd);
+ return fwrite(buf, sizeof(uint8_t), ARRAY_SIZE(buf), fd) == 1 ? OK : FAIL;
}
/// Writes time_t to "buf[8]".
diff --git a/src/nvim/ops.c b/src/nvim/ops.c
index eda963ff77..adfd0424f0 100644
--- a/src/nvim/ops.c
+++ b/src/nvim/ops.c
@@ -5372,11 +5372,10 @@ void cursor_pos_info(dict_T *dict)
}
}
- // Don't shorten this message, the user asked for it.
bom_count = bomb_size();
if (bom_count > 0) {
vim_snprintf((char *)IObuff + STRLEN(IObuff), IOSIZE - STRLEN(IObuff),
- _("(+%" PRId64 " for BOM)"), (int64_t)byte_count);
+ _("(+%" PRId64 " for BOM)"), (int64_t)bom_count);
}
if (dict == NULL) {
p = p_shm;
@@ -5387,20 +5386,18 @@ void cursor_pos_info(dict_T *dict)
}
if (dict != NULL) {
+ // Don't shorten this message, the user asked for it.
dict_add_nr_str(dict, "words", word_count, NULL);
dict_add_nr_str(dict, "chars", char_count, NULL);
dict_add_nr_str(dict, "bytes", byte_count + bom_count, NULL);
- if (l_VIsual_active) {
- dict_add_nr_str(dict, "visual_bytes", byte_count_cursor, NULL);
- dict_add_nr_str(dict, "visual_chars", char_count_cursor, NULL);
- dict_add_nr_str(dict, "visual_words", word_count_cursor, NULL);
- } else {
- dict_add_nr_str(dict, "cursor_bytes", byte_count_cursor, NULL);
- dict_add_nr_str(dict, "cursor_chars", char_count_cursor, NULL);
- dict_add_nr_str(dict, "cursor_words", word_count_cursor, NULL);
+ dict_add_nr_str(dict, l_VIsual_active ? "visual_bytes" : "cursor_bytes",
+ byte_count_cursor, NULL);
+ dict_add_nr_str(dict, l_VIsual_active ? "visual_chars" : "cursor_chars",
+ char_count_cursor, NULL);
+ dict_add_nr_str(dict, l_VIsual_active ? "visual_words" : "cursor_words",
+ word_count_cursor, NULL);
}
- }
}
/// Check if the default register (used in an unnamed paste) should be a
diff --git a/src/nvim/option.c b/src/nvim/option.c
index 2f22c245dd..45ebb4fa4c 100644
--- a/src/nvim/option.c
+++ b/src/nvim/option.c
@@ -1639,18 +1639,21 @@ do_set (
&& STRNCMP(s, newval, i) == 0
&& (!(flags & P_COMMA)
|| s[i] == ','
- || s[i] == NUL))
+ || s[i] == NUL)) {
break;
- /* Count backslashes. Only a comma with an
- * even number of backslashes before it is
- * recognized as a separator */
- if (s > origval && s[-1] == '\\')
- ++bs;
- else
+ }
+ // Count backslashes. Only a comma with an even number of
+ // backslashes or a single backslash preceded by a comma
+ // before it is recognized as a separator
+ if ((s > origval + 1 && s[-1] == '\\' && s[-2] != ',')
+ || (s == origval + 1 && s[-1] == '\\')) {
+ bs++;
+ } else {
bs = 0;
+ }
}
- /* do not add if already there */
+ // do not add if already there
if ((adding || prepending) && *s) {
prepending = FALSE;
adding = FALSE;
diff --git a/src/nvim/os/fs.c b/src/nvim/os/fs.c
index 49a74cf0d1..143a7160b0 100644
--- a/src/nvim/os/fs.c
+++ b/src/nvim/os/fs.c
@@ -111,8 +111,8 @@ int os_nodetype(const char *name)
#endif
uv_stat_t statbuf;
- if (os_stat(name, &statbuf) == 0) {
- return NODE_NORMAL;
+ if (0 != os_stat(name, &statbuf)) {
+ return NODE_NORMAL; // File doesn't exist.
}
#ifndef WIN32
diff --git a/src/nvim/syntax.c b/src/nvim/syntax.c
index 9a5484704e..1f9dbd8228 100644
--- a/src/nvim/syntax.c
+++ b/src/nvim/syntax.c
@@ -6972,6 +6972,9 @@ set_hl_attr (
|| at_en.rgb_sp_color != -1 || at_en.cterm_ae_attr != 0
|| at_en.rgb_ae_attr != 0) {
sgp->sg_attr = get_attr_entry(&at_en);
+ } else {
+ // If all the fields are cleared, clear the attr field back to default value
+ sgp->sg_attr = 0;
}
}
diff --git a/src/nvim/version.c b/src/nvim/version.c
index 82a15f9833..23bfca6221 100644
--- a/src/nvim/version.c
+++ b/src/nvim/version.c
@@ -163,12 +163,12 @@ static int included_patches[] = {
// 1524 NA
// 1523 NA
// 1522 NA
- // 1521,
+ 1521,
// 1520 NA
// 1519 NA
// 1518 NA
// 1517 NA
- // 1516,
+ 1516,
// 1515 NA
// 1514 NA
1513,
@@ -623,7 +623,7 @@ static int included_patches[] = {
// 1064,
// 1063 NA
// 1062 NA
- // 1061,
+ 1061,
// 1060 NA
1059,
// 1058,
@@ -634,7 +634,7 @@ static int included_patches[] = {
// 1053,
1052,
// 1051,
- // 1050,
+ 1050,
1049,
1048,
1047,
@@ -650,7 +650,7 @@ static int included_patches[] = {
1037,
1036,
1035,
- // 1034,
+ 1034,
// 1033 NA
1032,
// 1031 NA,
@@ -666,8 +666,8 @@ static int included_patches[] = {
// 1021 NA
// 1020 NA
// 1019 NA
- // 1018,
- // 1017,
+ 1018,
+ 1017,
// 1016 NA
1015,
// 1014 NA
diff --git a/test/functional/legacy/file_perm_spec.lua b/test/functional/legacy/file_perm_spec.lua
new file mode 100644
index 0000000000..cabeecdc9c
--- /dev/null
+++ b/test/functional/legacy/file_perm_spec.lua
@@ -0,0 +1,42 @@
+-- Test getting and setting file permissions.
+require('os')
+
+local helpers = require('test.functional.helpers')
+local clear, call, eq = helpers.clear, helpers.call, helpers.eq
+local neq, exc_exec = helpers.neq, helpers.exc_exec
+
+describe('Test getting and setting file permissions', function()
+ local tempfile = os.tmpname()
+
+ before_each(function()
+ os.remove(tempfile)
+ clear()
+ end)
+
+ it('file permissions', function()
+ eq('', call('getfperm', tempfile))
+ eq(0, call('setfperm', tempfile, 'r------'))
+
+ call('writefile', {'one'}, tempfile)
+ eq(9, call('len', call('getfperm', tempfile)))
+
+ eq(1, call('setfperm', tempfile, 'rwx------'))
+ if helpers.os_name == 'windows' then
+ eq('rw-rw-rw-', call('getfperm', tempfile))
+ else
+ eq('rwx------', call('getfperm', tempfile))
+ end
+
+ eq(1, call('setfperm', tempfile, 'r--r--r--'))
+ eq('r--r--r--', call('getfperm', tempfile))
+
+ local err = exc_exec(('call setfperm("%s", "---")'):format(tempfile))
+ neq(err:find('E475:'), nil)
+
+ eq(1, call('setfperm', tempfile, 'rwx------'))
+ end)
+
+ after_each(function()
+ os.remove(tempfile)
+ end)
+end)
diff --git a/test/functional/legacy/set_spec.lua b/test/functional/legacy/set_spec.lua
index f81fcd3700..f2c907084e 100644
--- a/test/functional/legacy/set_spec.lua
+++ b/test/functional/legacy/set_spec.lua
@@ -7,6 +7,21 @@ local clear, execute, eval, eq =
describe(':set', function()
before_each(clear)
+ it('handles backslash properly', function()
+ execute('set iskeyword=a,b,c')
+ execute('set iskeyword+=d')
+ eq('a,b,c,d', eval('&iskeyword'))
+
+ execute([[set iskeyword+=\\,e]])
+ eq([[a,b,c,d,\,e]], eval('&iskeyword'))
+
+ execute('set iskeyword-=e')
+ eq([[a,b,c,d,\]], eval('&iskeyword'))
+
+ execute([[set iskeyword-=\]])
+ eq('a,b,c,d', eval('&iskeyword'))
+ end)
+
it('recognizes a trailing comma with +=', function()
execute('set wildignore=*.png,')
execute('set wildignore+=*.jpg')
diff --git a/test/functional/ui/highlight_spec.lua b/test/functional/ui/highlight_spec.lua
index 0229b8bbf7..85fca4d7ca 100644
--- a/test/functional/ui/highlight_spec.lua
+++ b/test/functional/ui/highlight_spec.lua
@@ -302,6 +302,47 @@ describe('Default highlight groups', function()
{1:-- INSERT --} |
]], {[1] = {foreground = Screen.colors.Red, background = Screen.colors.Green}})
end)
+ it('can be cleared by assigning NONE', function()
+ execute('syn keyword TmpKeyword neovim')
+ execute('hi link TmpKeyword ErrorMsg')
+ insert('neovim')
+ screen:expect([[
+ {1:neovi^m} |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]], {
+ [1] = {foreground = Screen.colors.White, background = Screen.colors.Red}
+ })
+ execute("hi ErrorMsg term=NONE cterm=NONE ctermfg=NONE ctermbg=NONE"
+ .. " gui=NONE guifg=NONE guibg=NONE guisp=NONE")
+ screen:expect([[
+ neovi^m |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ ~ |
+ |
+ ]], {})
+ end)
end)
describe('guisp (special/undercurl)', function()
diff --git a/test/unit/os/fs_spec.lua b/test/unit/os/fs_spec.lua
index 71b5e7f576..857a5001f1 100644
--- a/test/unit/os/fs_spec.lua
+++ b/test/unit/os/fs_spec.lua
@@ -14,6 +14,8 @@ local to_cstr = helpers.to_cstr
local OK = helpers.OK
local FAIL = helpers.FAIL
local NULL = helpers.NULL
+local NODE_NORMAL = 0
+local NODE_WRITABLE = 1
cimport('unistd.h')
cimport('./src/nvim/os/shell.h')
@@ -357,15 +359,12 @@ describe('fs function', function()
local function os_file_exists(filename)
return fs.os_file_exists((to_cstr(filename)))
end
-
local function os_rename(path, new_path)
return fs.os_rename((to_cstr(path)), (to_cstr(new_path)))
end
-
local function os_remove(path)
return fs.os_remove((to_cstr(path)))
end
-
local function os_open(path, flags, mode)
return fs.os_open((to_cstr(path)), flags, mode)
end
@@ -484,6 +483,20 @@ describe('fs function', function()
assert.is_true(0 <= (os_open(existing_file, ffi.C.kO_RDWR, 0)))
end)
end)
+
+ describe('os_nodetype', function()
+ before_each(function()
+ os.remove('non-existing-file')
+ end)
+
+ it('returns NODE_NORMAL for non-existing file', function()
+ eq(NODE_NORMAL, fs.os_nodetype(to_cstr('non-existing-file')))
+ end)
+
+ it('returns NODE_WRITABLE for /dev/stderr', function()
+ eq(NODE_WRITABLE, fs.os_nodetype(to_cstr('/dev/stderr')))
+ end)
+ end)
end)
describe('folder operations', function()