mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
Merge #7821 'api: nvim_command_output'
This commit is contained in:
commit
911b1e49ab
@ -1,10 +1,22 @@
|
|||||||
Nvim core source
|
Nvim core
|
||||||
================
|
=========
|
||||||
|
|
||||||
Module-specific details are documented at the top of each module (`terminal.c`,
|
Module-specific details are documented at the top of each module (`terminal.c`,
|
||||||
`screen.c`, ...).
|
`screen.c`, …).
|
||||||
|
|
||||||
See `:help development` for more guidelines.
|
See `:help dev` for guidelines.
|
||||||
|
|
||||||
|
Filename conventions
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
The source files use extensions to hint about their purpose.
|
||||||
|
|
||||||
|
- `*.c`, `*.generated.c` - full C files, with all includes, etc.
|
||||||
|
- `*.c.h` - parametrized C files, contain all necessary includes, but require
|
||||||
|
defining macros before actually using. Example: `typval_encode.c.h`
|
||||||
|
- `*.h` - full headers, with all includes. Does *not* apply to `*.generated.h`.
|
||||||
|
- `*.h.generated.h` - exported functions’ declarations.
|
||||||
|
- `*.c.generated.h` - static functions’ declarations.
|
||||||
|
|
||||||
Logs
|
Logs
|
||||||
----
|
----
|
||||||
@ -20,17 +32,36 @@ UI events are logged at level 0 (`DEBUG_LOG_LEVEL`).
|
|||||||
rm -rf build/
|
rm -rf build/
|
||||||
make CMAKE_EXTRA_FLAGS="-DMIN_LOG_LEVEL=0"
|
make CMAKE_EXTRA_FLAGS="-DMIN_LOG_LEVEL=0"
|
||||||
|
|
||||||
Filename conventions
|
Build with ASAN
|
||||||
--------------------
|
---------------
|
||||||
|
|
||||||
The source files use extensions to hint about their purpose.
|
Building Nvim with Clang sanitizers (Address Sanitizer: ASan, Undefined
|
||||||
|
Behavior Sanitizer: UBSan, Memory Sanitizer: MSan, Thread Sanitizer: TSan) is
|
||||||
|
a good way to catch undefined behavior, leaks and other errors as soon as they
|
||||||
|
happen. It's significantly faster than Valgrind.
|
||||||
|
|
||||||
- `*.c`, `*.generated.c` - full C files, with all includes, etc.
|
Requires clang 3.4 or later:
|
||||||
- `*.c.h` - parametrized C files, contain all necessary includes, but require
|
|
||||||
defining macros before actually using. Example: `typval_encode.c.h`
|
clang --version
|
||||||
- `*.h` - full headers, with all includes. Does *not* apply to `*.generated.h`.
|
|
||||||
- `*.h.generated.h` - exported functions’ declarations.
|
Build Nvim with sanitizer instrumentation:
|
||||||
- `*.c.generated.h` - static functions’ declarations.
|
|
||||||
|
CC=clang make CMAKE_EXTRA_FLAGS="-DCLANG_ASAN_UBSAN=ON"
|
||||||
|
|
||||||
|
Create a directory to store logs:
|
||||||
|
|
||||||
|
mkdir -p "$HOME/logs"
|
||||||
|
|
||||||
|
Enable the sanitizer(s) via these environment variables:
|
||||||
|
|
||||||
|
# Change to detect_leaks=1 to detect memory leaks (slower).
|
||||||
|
export ASAN_OPTIONS="detect_leaks=0:log_path=$HOME/logs/asan"
|
||||||
|
export ASAN_SYMBOLIZER_PATH=/usr/lib/llvm-5.0/bin/llvm-symbolizer
|
||||||
|
|
||||||
|
export MSAN_SYMBOLIZER_PATH=/usr/lib/llvm-5.0/bin/llvm-symbolizer
|
||||||
|
export TSAN_OPTIONS="external_symbolizer_path=/usr/lib/llvm-5.0/bin/llvm-symbolizer log_path=${HOME}/logs/tsan"
|
||||||
|
|
||||||
|
Logs will be written to `${HOME}/logs/*san.PID`.
|
||||||
|
|
||||||
TUI debugging
|
TUI debugging
|
||||||
-------------
|
-------------
|
||||||
|
@ -43,14 +43,15 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/// Executes an ex-command.
|
/// Executes an ex-command.
|
||||||
/// On VimL error: Returns the VimL error; v:errmsg is not updated.
|
///
|
||||||
|
/// On parse error: forwards the Vim error; does not update v:errmsg.
|
||||||
|
/// On runtime error: forwards the Vim error; does not update v:errmsg.
|
||||||
///
|
///
|
||||||
/// @param command Ex-command string
|
/// @param command Ex-command string
|
||||||
/// @param[out] err Error details (including actual VimL error), if any
|
/// @param[out] err Error details (Vim error), if any
|
||||||
void nvim_command(String command, Error *err)
|
void nvim_command(String command, Error *err)
|
||||||
FUNC_API_SINCE(1)
|
FUNC_API_SINCE(1)
|
||||||
{
|
{
|
||||||
// Run the command
|
|
||||||
try_start();
|
try_start();
|
||||||
do_cmdline_cmd(command.data);
|
do_cmdline_cmd(command.data);
|
||||||
update_screen(VALID);
|
update_screen(VALID);
|
||||||
@ -207,18 +208,49 @@ String nvim_replace_termcodes(String str, Boolean from_part, Boolean do_lt,
|
|||||||
return cstr_as_string(ptr);
|
return cstr_as_string(ptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
String nvim_command_output(String str, Error *err)
|
/// Executes an ex-command and returns its (non-error) output.
|
||||||
|
/// Shell |:!| output is not captured.
|
||||||
|
///
|
||||||
|
/// On parse error: forwards the Vim error; does not update v:errmsg.
|
||||||
|
/// On runtime error: forwards the Vim error; does not update v:errmsg.
|
||||||
|
///
|
||||||
|
/// @param command Ex-command string
|
||||||
|
/// @param[out] err Error details (Vim error), if any
|
||||||
|
String nvim_command_output(String command, Error *err)
|
||||||
FUNC_API_SINCE(1)
|
FUNC_API_SINCE(1)
|
||||||
{
|
{
|
||||||
do_cmdline_cmd("redir => v:command_output");
|
const int save_msg_silent = msg_silent;
|
||||||
nvim_command(str, err);
|
garray_T *const save_capture_ga = capture_ga;
|
||||||
do_cmdline_cmd("redir END");
|
garray_T capture_local;
|
||||||
|
ga_init(&capture_local, 1, 80);
|
||||||
|
|
||||||
|
try_start();
|
||||||
|
msg_silent++;
|
||||||
|
capture_ga = &capture_local;
|
||||||
|
do_cmdline_cmd(command.data);
|
||||||
|
capture_ga = save_capture_ga;
|
||||||
|
msg_silent = save_msg_silent;
|
||||||
|
try_end(err);
|
||||||
|
|
||||||
if (ERROR_SET(err)) {
|
if (ERROR_SET(err)) {
|
||||||
return (String)STRING_INIT;
|
goto theend;
|
||||||
}
|
}
|
||||||
|
|
||||||
return cstr_to_string((char *)get_vim_var_str(VV_COMMAND_OUTPUT));
|
if (capture_local.ga_len > 1) {
|
||||||
|
// redir always(?) prepends a newline; remove it.
|
||||||
|
char *s = capture_local.ga_data;
|
||||||
|
assert(s[0] == '\n');
|
||||||
|
memmove(s, s + 1, (size_t)capture_local.ga_len);
|
||||||
|
s[capture_local.ga_len - 1] = '\0';
|
||||||
|
return (String) { // Caller will free the memory.
|
||||||
|
.data = s,
|
||||||
|
.size = (size_t)(capture_local.ga_len - 1),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
theend:
|
||||||
|
ga_clear(&capture_local);
|
||||||
|
return (String)STRING_INIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Evaluates a VimL expression (:help expression).
|
/// Evaluates a VimL expression (:help expression).
|
||||||
|
@ -402,7 +402,6 @@ static struct vimvar {
|
|||||||
VV(VV_OLDFILES, "oldfiles", VAR_LIST, 0),
|
VV(VV_OLDFILES, "oldfiles", VAR_LIST, 0),
|
||||||
VV(VV_WINDOWID, "windowid", VAR_NUMBER, VV_RO_SBX),
|
VV(VV_WINDOWID, "windowid", VAR_NUMBER, VV_RO_SBX),
|
||||||
VV(VV_PROGPATH, "progpath", VAR_STRING, VV_RO),
|
VV(VV_PROGPATH, "progpath", VAR_STRING, VV_RO),
|
||||||
VV(VV_COMMAND_OUTPUT, "command_output", VAR_STRING, 0),
|
|
||||||
VV(VV_COMPLETED_ITEM, "completed_item", VAR_DICT, VV_RO),
|
VV(VV_COMPLETED_ITEM, "completed_item", VAR_DICT, VV_RO),
|
||||||
VV(VV_OPTION_NEW, "option_new", VAR_STRING, VV_RO),
|
VV(VV_OPTION_NEW, "option_new", VAR_STRING, VV_RO),
|
||||||
VV(VV_OPTION_OLD, "option_old", VAR_STRING, VV_RO),
|
VV(VV_OPTION_OLD, "option_old", VAR_STRING, VV_RO),
|
||||||
@ -8117,8 +8116,7 @@ static void f_execute(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
|
|
||||||
ga_append(capture_ga, NUL);
|
ga_append(capture_ga, NUL);
|
||||||
rettv->v_type = VAR_STRING;
|
rettv->v_type = VAR_STRING;
|
||||||
rettv->vval.v_string = vim_strsave(capture_ga->ga_data);
|
rettv->vval.v_string = capture_ga->ga_data;
|
||||||
ga_clear(capture_ga);
|
|
||||||
|
|
||||||
capture_ga = save_capture_ga;
|
capture_ga = save_capture_ga;
|
||||||
}
|
}
|
||||||
|
@ -86,7 +86,6 @@ typedef enum {
|
|||||||
VV_OLDFILES,
|
VV_OLDFILES,
|
||||||
VV_WINDOWID,
|
VV_WINDOWID,
|
||||||
VV_PROGPATH,
|
VV_PROGPATH,
|
||||||
VV_COMMAND_OUTPUT,
|
|
||||||
VV_COMPLETED_ITEM,
|
VV_COMPLETED_ITEM,
|
||||||
VV_OPTION_NEW,
|
VV_OPTION_NEW,
|
||||||
VV_OPTION_OLD,
|
VV_OPTION_OLD,
|
||||||
|
@ -37,7 +37,7 @@ describe('api', function()
|
|||||||
os.remove(fname)
|
os.remove(fname)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it("VimL error: fails (VimL error), does NOT update v:errmsg", function()
|
it("parse error: fails (specific error), does NOT update v:errmsg", function()
|
||||||
-- Most API methods return generic errors (or no error) if a VimL
|
-- Most API methods return generic errors (or no error) if a VimL
|
||||||
-- expression fails; nvim_command returns the VimL error details.
|
-- expression fails; nvim_command returns the VimL error details.
|
||||||
local status, rv = pcall(nvim, "command", "bogus_command")
|
local status, rv = pcall(nvim, "command", "bogus_command")
|
||||||
@ -45,6 +45,82 @@ describe('api', function()
|
|||||||
eq("E492:", string.match(rv, "E%d*:")) -- VimL error was returned.
|
eq("E492:", string.match(rv, "E%d*:")) -- VimL error was returned.
|
||||||
eq("", nvim("eval", "v:errmsg")) -- v:errmsg was not updated.
|
eq("", nvim("eval", "v:errmsg")) -- v:errmsg was not updated.
|
||||||
end)
|
end)
|
||||||
|
|
||||||
|
it("runtime error: fails (specific error)", function()
|
||||||
|
local status, rv = pcall(nvim, "command_output", "buffer 23487")
|
||||||
|
eq(false, status) -- nvim_command() failed.
|
||||||
|
eq("E86: Buffer 23487 does not exist", string.match(rv, "E%d*:.*"))
|
||||||
|
eq("", nvim("eval", "v:errmsg")) -- v:errmsg was not updated.
|
||||||
|
end)
|
||||||
|
end)
|
||||||
|
|
||||||
|
describe('nvim_command_output', function()
|
||||||
|
it('does not induce hit-enter prompt', function()
|
||||||
|
-- Induce a hit-enter prompt use nvim_input (non-blocking).
|
||||||
|
nvim('command', 'set cmdheight=1')
|
||||||
|
nvim('input', [[:echo "hi\nhi2"<CR>]])
|
||||||
|
|
||||||
|
-- Verify hit-enter prompt.
|
||||||
|
eq({mode='r', blocking=true}, nvim("get_mode"))
|
||||||
|
nvim('input', [[<C-c>]])
|
||||||
|
|
||||||
|
-- Verify NO hit-enter prompt.
|
||||||
|
nvim('command_output', [[echo "hi\nhi2"]])
|
||||||
|
eq({mode='n', blocking=false}, nvim("get_mode"))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('captures command output', function()
|
||||||
|
eq('this is\nspinal tap',
|
||||||
|
nvim('command_output', [[echo "this is\nspinal tap"]]))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('captures empty command output', function()
|
||||||
|
eq('', nvim('command_output', 'echo'))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('captures single-char command output', function()
|
||||||
|
eq('x', nvim('command_output', 'echo "x"'))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('captures multiple commands', function()
|
||||||
|
eq('foo\n 1 %a "[No Name]" line 1',
|
||||||
|
nvim('command_output', 'echo "foo" | ls'))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('captures nested execute()', function()
|
||||||
|
eq('\nnested1\nnested2\n 1 %a "[No Name]" line 1',
|
||||||
|
nvim('command_output',
|
||||||
|
[[echo execute('echo "nested1\nnested2"') | ls]]))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('captures nested nvim_command_output()', function()
|
||||||
|
eq('nested1\nnested2\n 1 %a "[No Name]" line 1',
|
||||||
|
nvim('command_output',
|
||||||
|
[[echo nvim_command_output('echo "nested1\nnested2"') | ls]]))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('does not return shell |:!| output', function()
|
||||||
|
eq(':!echo "foo"\r\n', nvim('command_output', [[!echo "foo"]]))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("parse error: fails (specific error), does NOT update v:errmsg", function()
|
||||||
|
local status, rv = pcall(nvim, "command_output", "bogus commannnd")
|
||||||
|
eq(false, status) -- nvim_command_output() failed.
|
||||||
|
eq("E492: Not an editor command: bogus commannnd",
|
||||||
|
string.match(rv, "E%d*:.*"))
|
||||||
|
eq("", nvim("eval", "v:errmsg")) -- v:errmsg was not updated.
|
||||||
|
-- Verify NO hit-enter prompt.
|
||||||
|
eq({mode='n', blocking=false}, nvim("get_mode"))
|
||||||
|
end)
|
||||||
|
|
||||||
|
it("runtime error: fails (specific error)", function()
|
||||||
|
local status, rv = pcall(nvim, "command_output", "buffer 42")
|
||||||
|
eq(false, status) -- nvim_command_output() failed.
|
||||||
|
eq("E86: Buffer 42 does not exist", string.match(rv, "E%d*:.*"))
|
||||||
|
eq("", nvim("eval", "v:errmsg")) -- v:errmsg was not updated.
|
||||||
|
-- Verify NO hit-enter prompt.
|
||||||
|
eq({mode='n', blocking=false}, nvim("get_mode"))
|
||||||
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
describe('nvim_eval', function()
|
describe('nvim_eval', function()
|
||||||
|
@ -11,10 +11,10 @@ describe('TabClosed', function()
|
|||||||
repeat
|
repeat
|
||||||
nvim('command', 'tabnew')
|
nvim('command', 'tabnew')
|
||||||
until nvim('eval', 'tabpagenr()') == 6 -- current tab is now 6
|
until nvim('eval', 'tabpagenr()') == 6 -- current tab is now 6
|
||||||
eq("\ntabclosed:6:6:5", nvim('command_output', 'tabclose')) -- close last 6, current tab is now 5
|
eq("tabclosed:6:6:5", nvim('command_output', 'tabclose')) -- close last 6, current tab is now 5
|
||||||
eq("\ntabclosed:5:5:4", nvim('command_output', 'close')) -- close last window on tab, closes tab
|
eq("tabclosed:5:5:4", nvim('command_output', 'close')) -- close last window on tab, closes tab
|
||||||
eq("\ntabclosed:2:2:3", nvim('command_output', '2tabclose')) -- close tab 2, current tab is now 3
|
eq("tabclosed:2:2:3", nvim('command_output', '2tabclose')) -- close tab 2, current tab is now 3
|
||||||
eq("\ntabclosed:1:1:2\ntabclosed:1:1:1", nvim('command_output', 'tabonly')) -- close tabs 1 and 2
|
eq("tabclosed:1:1:2\ntabclosed:1:1:1", nvim('command_output', 'tabonly')) -- close tabs 1 and 2
|
||||||
end)
|
end)
|
||||||
|
|
||||||
it('is triggered when closing a window via bdelete from another tab', function()
|
it('is triggered when closing a window via bdelete from another tab', function()
|
||||||
@ -23,7 +23,7 @@ describe('TabClosed', function()
|
|||||||
nvim('command', '1tabedit Xtestfile')
|
nvim('command', '1tabedit Xtestfile')
|
||||||
nvim('command', 'normal! 1gt')
|
nvim('command', 'normal! 1gt')
|
||||||
eq({1, 3}, nvim('eval', '[tabpagenr(), tabpagenr("$")]'))
|
eq({1, 3}, nvim('eval', '[tabpagenr(), tabpagenr("$")]'))
|
||||||
eq("\ntabclosed:2:2:1\ntabclosed:2:2:1", nvim('command_output', 'bdelete Xtestfile'))
|
eq("tabclosed:2:2:1\ntabclosed:2:2:1", nvim('command_output', 'bdelete Xtestfile'))
|
||||||
eq({1, 1}, nvim('eval', '[tabpagenr(), tabpagenr("$")]'))
|
eq({1, 1}, nvim('eval', '[tabpagenr(), tabpagenr("$")]'))
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@ -35,7 +35,7 @@ describe('TabClosed', function()
|
|||||||
|
|
||||||
-- Only one tab is closed, and the alternate file is used for the other.
|
-- Only one tab is closed, and the alternate file is used for the other.
|
||||||
eq({2, 3}, nvim('eval', '[tabpagenr(), tabpagenr("$")]'))
|
eq({2, 3}, nvim('eval', '[tabpagenr(), tabpagenr("$")]'))
|
||||||
eq("\ntabclosed:2:2:2", nvim('command_output', 'bdelete Xtestfile2'))
|
eq("tabclosed:2:2:2", nvim('command_output', 'bdelete Xtestfile2'))
|
||||||
eq('Xtestfile1', nvim('eval', 'bufname("")'))
|
eq('Xtestfile1', nvim('eval', 'bufname("")'))
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
@ -48,9 +48,9 @@ describe('TabClosed', function()
|
|||||||
nvim('command', 'tabnew')
|
nvim('command', 'tabnew')
|
||||||
until nvim('eval', 'tabpagenr()') == 7 -- current tab is now 7
|
until nvim('eval', 'tabpagenr()') == 7 -- current tab is now 7
|
||||||
-- sanity check, we shouldn't match on tabs with numbers other than 2
|
-- sanity check, we shouldn't match on tabs with numbers other than 2
|
||||||
eq("\ntabclosed:7:7:6", nvim('command_output', 'tabclose'))
|
eq("tabclosed:7:7:6", nvim('command_output', 'tabclose'))
|
||||||
-- close tab page 2, current tab is now 5
|
-- close tab page 2, current tab is now 5
|
||||||
eq("\ntabclosed:2:2:5\ntabclosed:match", nvim('command_output', '2tabclose'))
|
eq("tabclosed:2:2:5\ntabclosed:match", nvim('command_output', '2tabclose'))
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
|
||||||
@ -59,7 +59,7 @@ describe('TabClosed', function()
|
|||||||
nvim('command', 'au! TabClosed * echom "tabclosed:".expand("<afile>").":".expand("<amatch>").":".tabpagenr()')
|
nvim('command', 'au! TabClosed * echom "tabclosed:".expand("<afile>").":".expand("<amatch>").":".tabpagenr()')
|
||||||
nvim('command', 'tabedit Xtestfile')
|
nvim('command', 'tabedit Xtestfile')
|
||||||
eq({2, 2}, nvim('eval', '[tabpagenr(), tabpagenr("$")]'))
|
eq({2, 2}, nvim('eval', '[tabpagenr(), tabpagenr("$")]'))
|
||||||
eq("\ntabclosed:2:2:1", nvim('command_output', 'close'))
|
eq("tabclosed:2:2:1", nvim('command_output', 'close'))
|
||||||
eq({1, 1}, nvim('eval', '[tabpagenr(), tabpagenr("$")]'))
|
eq({1, 1}, nvim('eval', '[tabpagenr(), tabpagenr("$")]'))
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
@ -7,14 +7,14 @@ describe('TabNewEntered', function()
|
|||||||
it('matches when entering any new tab', function()
|
it('matches when entering any new tab', function()
|
||||||
clear()
|
clear()
|
||||||
nvim('command', 'au! TabNewEntered * echom "tabnewentered:".tabpagenr().":".bufnr("")')
|
nvim('command', 'au! TabNewEntered * echom "tabnewentered:".tabpagenr().":".bufnr("")')
|
||||||
eq("\ntabnewentered:2:2", nvim('command_output', 'tabnew'))
|
eq("tabnewentered:2:2", nvim('command_output', 'tabnew'))
|
||||||
eq("\n\"test.x2\" [New File]\ntabnewentered:3:3", nvim('command_output', 'tabnew test.x2'))
|
eq("tabnewentered:3:3", nvim('command_output', 'tabnew test.x2'))
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
describe('with FILE as <afile>', function()
|
describe('with FILE as <afile>', function()
|
||||||
it('matches when opening a new tab for FILE', function()
|
it('matches when opening a new tab for FILE', function()
|
||||||
nvim('command', 'au! TabNewEntered Xtest-tabnewentered echom "tabnewentered:match"')
|
nvim('command', 'au! TabNewEntered Xtest-tabnewentered echom "tabnewentered:match"')
|
||||||
eq('\n"Xtest-tabnewentered" [New File]\ntabnewentered:4:4\ntabnewentered:match',
|
eq('tabnewentered:4:4\ntabnewentered:match',
|
||||||
nvim('command_output', 'tabnew Xtest-tabnewentered'))
|
nvim('command_output', 'tabnew Xtest-tabnewentered'))
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
@ -24,7 +24,7 @@ describe('TabNewEntered', function()
|
|||||||
nvim('command', 'au! TabNewEntered * echom "entered"')
|
nvim('command', 'au! TabNewEntered * echom "entered"')
|
||||||
nvim('command', 'tabnew test.x2')
|
nvim('command', 'tabnew test.x2')
|
||||||
nvim('command', 'split')
|
nvim('command', 'split')
|
||||||
eq('\nentered', nvim('command_output', 'execute "normal \\<C-W>T"'))
|
eq('entered', nvim('command_output', 'execute "normal \\<C-W>T"'))
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
@ -16,8 +16,8 @@ describe('sign', function()
|
|||||||
nvim('command', 'sign place 34 line=3 name=Foo buffer='..buf2)
|
nvim('command', 'sign place 34 line=3 name=Foo buffer='..buf2)
|
||||||
-- now unplace without specifying a buffer
|
-- now unplace without specifying a buffer
|
||||||
nvim('command', 'sign unplace 34')
|
nvim('command', 'sign unplace 34')
|
||||||
eq("\n--- Signs ---\n", nvim('command_output', 'sign place buffer='..buf1))
|
eq("--- Signs ---\n", nvim('command_output', 'sign place buffer='..buf1))
|
||||||
eq("\n--- Signs ---\n", nvim('command_output', 'sign place buffer='..buf2))
|
eq("--- Signs ---\n", nvim('command_output', 'sign place buffer='..buf2))
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
end)
|
end)
|
||||||
|
@ -644,7 +644,7 @@ local function alter_slashes(obj)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function hexdump(str)
|
local function hexdump(str)
|
||||||
local len = string.len( str )
|
local len = string.len(str)
|
||||||
local dump = ""
|
local dump = ""
|
||||||
local hex = ""
|
local hex = ""
|
||||||
local asc = ""
|
local asc = ""
|
||||||
@ -652,22 +652,20 @@ local function hexdump(str)
|
|||||||
for i = 1, len do
|
for i = 1, len do
|
||||||
if 1 == i % 8 then
|
if 1 == i % 8 then
|
||||||
dump = dump .. hex .. asc .. "\n"
|
dump = dump .. hex .. asc .. "\n"
|
||||||
hex = string.format( "%04x: ", i - 1 )
|
hex = string.format("%04x: ", i - 1)
|
||||||
asc = ""
|
asc = ""
|
||||||
end
|
end
|
||||||
|
|
||||||
local ord = string.byte( str, i )
|
local ord = string.byte(str, i)
|
||||||
hex = hex .. string.format( "%02x ", ord )
|
hex = hex .. string.format("%02x ", ord)
|
||||||
if ord >= 32 and ord <= 126 then
|
if ord >= 32 and ord <= 126 then
|
||||||
asc = asc .. string.char( ord )
|
asc = asc .. string.char(ord)
|
||||||
else
|
else
|
||||||
asc = asc .. "."
|
asc = asc .. "."
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
return dump .. hex
|
return dump .. hex .. string.rep(" ", 8 - len % 8) .. asc
|
||||||
.. string.rep( " ", 8 - len % 8 ) .. asc
|
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
local module = {
|
local module = {
|
||||||
|
@ -849,7 +849,7 @@ describe('Ex commands coloring support', function()
|
|||||||
{EOB:~ }|
|
{EOB:~ }|
|
||||||
|
|
|
|
||||||
]])
|
]])
|
||||||
eq('\nError detected while processing :\nE605: Exception not caught: 42',
|
eq('Error detected while processing :\nE605: Exception not caught: 42',
|
||||||
meths.command_output('messages'))
|
meths.command_output('messages'))
|
||||||
end)
|
end)
|
||||||
it('errors out when failing to get callback', function()
|
it('errors out when failing to get callback', function()
|
||||||
|
Loading…
Reference in New Issue
Block a user