mirror of
https://github.com/neovim/neovim.git
synced 2024-12-20 19:25:11 -07:00
Merge pull request #13489 from janlazo/issue-13485
eval: executable(), exepath() accept strings only
This commit is contained in:
commit
cacdef5ff1
@ -95,7 +95,6 @@ PRAGMA_DIAG_POP
|
|||||||
|
|
||||||
|
|
||||||
static char *e_listarg = N_("E686: Argument of %s must be a List");
|
static char *e_listarg = N_("E686: Argument of %s must be a List");
|
||||||
static char *e_stringreq = N_("E928: String required");
|
|
||||||
static char *e_invalwindow = N_("E957: Invalid window number");
|
static char *e_invalwindow = N_("E957: Invalid window number");
|
||||||
|
|
||||||
/// Dummy va_list for passing to vim_snprintf
|
/// Dummy va_list for passing to vim_snprintf
|
||||||
@ -1877,10 +1876,12 @@ static void f_eventhandler(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
*/
|
*/
|
||||||
static void f_executable(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
static void f_executable(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||||
{
|
{
|
||||||
const char *name = tv_get_string(&argvars[0]);
|
if (tv_check_for_string(&argvars[0]) == FAIL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Check in $PATH and also check directly if there is a directory name
|
// Check in $PATH and also check directly if there is a directory name
|
||||||
rettv->vval.v_number = os_can_exe(name, NULL, true);
|
rettv->vval.v_number = os_can_exe(tv_get_string(&argvars[0]), NULL, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
@ -1984,10 +1985,13 @@ static void f_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
/// "exepath()" function
|
/// "exepath()" function
|
||||||
static void f_exepath(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
static void f_exepath(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||||
{
|
{
|
||||||
const char *arg = tv_get_string(&argvars[0]);
|
if (tv_check_for_string(&argvars[0]) == FAIL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
char *path = NULL;
|
char *path = NULL;
|
||||||
|
|
||||||
(void)os_can_exe(arg, &path, true);
|
(void)os_can_exe(tv_get_string(&argvars[0]), &path, true);
|
||||||
|
|
||||||
rettv->v_type = VAR_STRING;
|
rettv->v_type = VAR_STRING;
|
||||||
rettv->vval.v_string = (char_u *)path;
|
rettv->vval.v_string = (char_u *)path;
|
||||||
|
@ -2953,6 +2953,19 @@ float_T tv_get_float(const typval_T *const tv)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Give an error and return FAIL unless "tv" is a non-empty string.
|
||||||
|
int tv_check_for_string(const typval_T *const tv)
|
||||||
|
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT FUNC_ATTR_PURE
|
||||||
|
{
|
||||||
|
if (tv->v_type != VAR_STRING
|
||||||
|
|| tv->vval.v_string == NULL
|
||||||
|
|| *tv->vval.v_string == NUL) {
|
||||||
|
EMSG(_(e_stringreq));
|
||||||
|
return FAIL;
|
||||||
|
}
|
||||||
|
return OK;
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the string value of a "stringish" VimL object.
|
/// Get the string value of a "stringish" VimL object.
|
||||||
///
|
///
|
||||||
/// @param[in] tv Object to get value of.
|
/// @param[in] tv Object to get value of.
|
||||||
|
@ -935,6 +935,7 @@ EXTERN char_u e_readonly[] INIT(= N_(
|
|||||||
"E45: 'readonly' option is set (add ! to override)"));
|
"E45: 'readonly' option is set (add ! to override)"));
|
||||||
EXTERN char_u e_readonlyvar[] INIT(= N_(
|
EXTERN char_u e_readonlyvar[] INIT(= N_(
|
||||||
"E46: Cannot change read-only variable \"%.*s\""));
|
"E46: Cannot change read-only variable \"%.*s\""));
|
||||||
|
EXTERN char_u e_stringreq[] INIT(= N_("E928: String required"));
|
||||||
EXTERN char_u e_dictreq[] INIT(= N_("E715: Dictionary required"));
|
EXTERN char_u e_dictreq[] INIT(= N_("E715: Dictionary required"));
|
||||||
EXTERN char_u e_toomanyarg[] INIT(= N_(
|
EXTERN char_u e_toomanyarg[] INIT(= N_(
|
||||||
"E118: Too many arguments for function: %s"));
|
"E118: Too many arguments for function: %s"));
|
||||||
|
@ -2,6 +2,7 @@ local helpers = require('test.functional.helpers')(after_each)
|
|||||||
local eq, clear, call, iswin, write_file, command =
|
local eq, clear, call, iswin, write_file, command =
|
||||||
helpers.eq, helpers.clear, helpers.call, helpers.iswin, helpers.write_file,
|
helpers.eq, helpers.clear, helpers.call, helpers.iswin, helpers.write_file,
|
||||||
helpers.command
|
helpers.command
|
||||||
|
local exc_exec = helpers.exc_exec
|
||||||
local eval = helpers.eval
|
local eval = helpers.eval
|
||||||
|
|
||||||
describe('executable()', function()
|
describe('executable()', function()
|
||||||
@ -10,6 +11,20 @@ describe('executable()', function()
|
|||||||
it('returns 1 for commands in $PATH', function()
|
it('returns 1 for commands in $PATH', function()
|
||||||
local exe = iswin() and 'ping' or 'ls'
|
local exe = iswin() and 'ping' or 'ls'
|
||||||
eq(1, call('executable', exe))
|
eq(1, call('executable', exe))
|
||||||
|
command('let $PATH = fnamemodify("./test/functional/fixtures/bin", ":p")')
|
||||||
|
eq(1, call('executable', 'null'))
|
||||||
|
eq(1, call('executable', 'true'))
|
||||||
|
eq(1, call('executable', 'false'))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('fails for invalid values', function()
|
||||||
|
for _, input in ipairs({'""', 'v:null', 'v:true', 'v:false', '{}', '[]'}) do
|
||||||
|
eq('Vim(call):E928: String required', exc_exec('call executable('..input..')'))
|
||||||
|
end
|
||||||
|
command('let $PATH = fnamemodify("./test/functional/fixtures/bin", ":p")')
|
||||||
|
for _, input in ipairs({'v:null', 'v:true', 'v:false'}) do
|
||||||
|
eq('Vim(call):E928: String required', exc_exec('call executable('..input..')'))
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('returns 0 for non-existent files', function()
|
it('returns 0 for non-existent files', function()
|
||||||
|
@ -1,14 +1,40 @@
|
|||||||
local helpers = require('test.functional.helpers')(after_each)
|
local helpers = require('test.functional.helpers')(after_each)
|
||||||
local eq, clear, call, iswin =
|
local eq, clear, call, iswin =
|
||||||
helpers.eq, helpers.clear, helpers.call, helpers.iswin
|
helpers.eq, helpers.clear, helpers.call, helpers.iswin
|
||||||
|
local command = helpers.command
|
||||||
|
local exc_exec = helpers.exc_exec
|
||||||
|
local matches = helpers.matches
|
||||||
|
|
||||||
describe('exepath() (Windows)', function()
|
describe('exepath()', function()
|
||||||
if not iswin() then return end -- N/A for Unix.
|
before_each(clear)
|
||||||
|
|
||||||
it('append extension if omitted', function()
|
it('returns 1 for commands in $PATH', function()
|
||||||
local filename = 'cmd'
|
local exe = iswin() and 'ping' or 'ls'
|
||||||
local pathext = '.exe'
|
local ext_pat = iswin() and '%.EXE$' or '$'
|
||||||
clear({env={PATHEXT=pathext}})
|
matches(exe .. ext_pat, call('exepath', exe))
|
||||||
eq(call('exepath', filename..pathext), call('exepath', filename))
|
command('let $PATH = fnamemodify("./test/functional/fixtures/bin", ":p")')
|
||||||
|
ext_pat = iswin() and '%.CMD$' or '$'
|
||||||
|
matches('null' .. ext_pat, call('exepath', 'null'))
|
||||||
|
matches('true' .. ext_pat, call('exepath', 'true'))
|
||||||
|
matches('false' .. ext_pat, call('exepath', 'false'))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it('fails for invalid values', function()
|
||||||
|
for _, input in ipairs({'""', 'v:null', 'v:true', 'v:false', '{}', '[]'}) do
|
||||||
|
eq('Vim(call):E928: String required', exc_exec('call exepath('..input..')'))
|
||||||
|
end
|
||||||
|
command('let $PATH = fnamemodify("./test/functional/fixtures/bin", ":p")')
|
||||||
|
for _, input in ipairs({'v:null', 'v:true', 'v:false'}) do
|
||||||
|
eq('Vim(call):E928: String required', exc_exec('call exepath('..input..')'))
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
if iswin() then
|
||||||
|
it('append extension if omitted', function()
|
||||||
|
local filename = 'cmd'
|
||||||
|
local pathext = '.exe'
|
||||||
|
clear({env={PATHEXT=pathext}})
|
||||||
|
eq(call('exepath', filename..pathext), call('exepath', filename))
|
||||||
|
end)
|
||||||
|
end
|
||||||
end)
|
end)
|
||||||
|
0
test/functional/fixtures/bin/false
Executable file
0
test/functional/fixtures/bin/false
Executable file
0
test/functional/fixtures/bin/false.cmd
Executable file
0
test/functional/fixtures/bin/false.cmd
Executable file
0
test/functional/fixtures/bin/null
Executable file
0
test/functional/fixtures/bin/null
Executable file
0
test/functional/fixtures/bin/null.cmd
Executable file
0
test/functional/fixtures/bin/null.cmd
Executable file
0
test/functional/fixtures/bin/true
Executable file
0
test/functional/fixtures/bin/true
Executable file
0
test/functional/fixtures/bin/true.cmd
Executable file
0
test/functional/fixtures/bin/true.cmd
Executable file
Loading…
Reference in New Issue
Block a user