mirror of
https://github.com/neovim/neovim.git
synced 2025-10-26 12:27:24 +00:00
Merge #10433 from erw7/vim-8.1.0027
vim-patch:8.1.{27,32,36,69,70,71,91,92}
This commit is contained in:
@@ -2084,6 +2084,7 @@ ctxsize() Number return |context-stack| size
|
|||||||
cursor({lnum}, {col} [, {off}])
|
cursor({lnum}, {col} [, {off}])
|
||||||
Number move cursor to {lnum}, {col}, {off}
|
Number move cursor to {lnum}, {col}, {off}
|
||||||
cursor({list}) Number move cursor to position in {list}
|
cursor({list}) Number move cursor to position in {list}
|
||||||
|
debugbreak({pid}) Number interrupt process being debugged
|
||||||
deepcopy({expr} [, {noref}]) any make a full copy of {expr}
|
deepcopy({expr} [, {noref}]) any make a full copy of {expr}
|
||||||
delete({fname} [, {flags}]) Number delete the file or directory {fname}
|
delete({fname} [, {flags}]) Number delete the file or directory {fname}
|
||||||
deletebufline({expr}, {first}[, {last}])
|
deletebufline({expr}, {first}[, {last}])
|
||||||
@@ -2280,6 +2281,10 @@ pathshorten({expr}) String shorten directory names in a path
|
|||||||
pow({x}, {y}) Float {x} to the power of {y}
|
pow({x}, {y}) Float {x} to the power of {y}
|
||||||
prevnonblank({lnum}) Number line nr of non-blank line <= {lnum}
|
prevnonblank({lnum}) Number line nr of non-blank line <= {lnum}
|
||||||
printf({fmt}, {expr1}...) String format text
|
printf({fmt}, {expr1}...) String format text
|
||||||
|
prompt_addtext({buf}, {expr}) none add text to a prompt buffer
|
||||||
|
prompt_setcallback({buf}, {expr}) none set prompt callback function
|
||||||
|
prompt_setinterrupt({buf}, {text}) none set prompt interrupt function
|
||||||
|
prompt_setprompt({buf}, {text}) none set prompt text
|
||||||
pum_getpos() Dict position and size of pum if visible
|
pum_getpos() Dict position and size of pum if visible
|
||||||
pumvisible() Number whether popup menu is visible
|
pumvisible() Number whether popup menu is visible
|
||||||
pyeval({expr}) any evaluate |Python| expression
|
pyeval({expr}) any evaluate |Python| expression
|
||||||
@@ -2290,7 +2295,7 @@ range({expr} [, {max} [, {stride}]])
|
|||||||
readdir({dir} [, {expr}]) List file names in {dir} selected by {expr}
|
readdir({dir} [, {expr}]) List file names in {dir} selected by {expr}
|
||||||
readfile({fname} [, {binary} [, {max}]])
|
readfile({fname} [, {binary} [, {max}]])
|
||||||
List get list of lines from file {fname}
|
List get list of lines from file {fname}
|
||||||
reg_executing() Number get the executing register name
|
reg_executing() String get the executing register name
|
||||||
reg_recording() String get the recording register name
|
reg_recording() String get the recording register name
|
||||||
reltime([{start} [, {end}]]) List get time value
|
reltime([{start} [, {end}]]) List get time value
|
||||||
reltimefloat({time}) Float turn the time value into a Float
|
reltimefloat({time}) Float turn the time value into a Float
|
||||||
@@ -3637,6 +3642,11 @@ exp({expr}) *exp()*
|
|||||||
:echo exp(-1)
|
:echo exp(-1)
|
||||||
< 0.367879
|
< 0.367879
|
||||||
|
|
||||||
|
debugbreak({pid}) *debugbreak()*
|
||||||
|
Specifically used to interrupt a program being debugged. It
|
||||||
|
will cause process {pid} to get a SIGTRAP. Behavior for other
|
||||||
|
processes is undefined. See |terminal-debugger|.
|
||||||
|
{Sends a SIGINT to a process {pid} other than MS-Windows}
|
||||||
|
|
||||||
expand({expr} [, {nosuf} [, {list}]]) *expand()*
|
expand({expr} [, {nosuf} [, {list}]]) *expand()*
|
||||||
Expand wildcards and the following special keywords in {expr}.
|
Expand wildcards and the following special keywords in {expr}.
|
||||||
@@ -4541,7 +4551,7 @@ getline({lnum} [, {end}])
|
|||||||
from the current buffer. Example: >
|
from the current buffer. Example: >
|
||||||
getline(1)
|
getline(1)
|
||||||
< When {lnum} is a String that doesn't start with a
|
< When {lnum} is a String that doesn't start with a
|
||||||
digit, line() is called to translate the String into a Number.
|
digit, |line()| is called to translate the String into a Number.
|
||||||
To get the line under the cursor: >
|
To get the line under the cursor: >
|
||||||
getline(".")
|
getline(".")
|
||||||
< When {lnum} is smaller than 1 or bigger than the number of
|
< When {lnum} is smaller than 1 or bigger than the number of
|
||||||
@@ -6541,6 +6551,50 @@ printf({fmt}, {expr1} ...) *printf()*
|
|||||||
of "%" items. If there are not sufficient or too many
|
of "%" items. If there are not sufficient or too many
|
||||||
arguments an error is given. Up to 18 arguments can be used.
|
arguments an error is given. Up to 18 arguments can be used.
|
||||||
|
|
||||||
|
prompt_setcallback({buf}, {expr}) *prompt_setcallback()*
|
||||||
|
Set prompt callback for buffer {buf} to {expr}. When {expr}
|
||||||
|
is an empty string the callback is removed. This has only
|
||||||
|
effect if {buf} has 'buftype' set to "prompt".
|
||||||
|
|
||||||
|
The callback is invoked when pressing Enter. The current
|
||||||
|
buffer will always be the prompt buffer. A new line for a
|
||||||
|
prompt is added before invoking the callback, thus the prompt
|
||||||
|
for which the callback was invoked will be in the last but one
|
||||||
|
line.
|
||||||
|
If the callback wants to add text to the buffer, it must
|
||||||
|
insert it above the last line, since that is where the current
|
||||||
|
prompt is. This can also be done asynchronously.
|
||||||
|
The callback is invoked with one argument, which is the text
|
||||||
|
that was entered at the prompt. This can be an empty string
|
||||||
|
if the user only typed Enter.
|
||||||
|
Example: >
|
||||||
|
call prompt_setcallback(bufnr(''), function('s:TextEntered'))
|
||||||
|
func s:TextEntered(text)
|
||||||
|
if a:text == 'exit' || a:text == 'quit'
|
||||||
|
stopinsert
|
||||||
|
close
|
||||||
|
else
|
||||||
|
call append(line('$') - 1, 'Entered: "' . a:text . '"')
|
||||||
|
" Reset 'modified' to allow the buffer to be closed.
|
||||||
|
set nomodified
|
||||||
|
endif
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
prompt_setinterrupt({buf}, {expr}) *prompt_setinterrupt()*
|
||||||
|
Set a callback for buffer {buf} to {expr}. When {expr} is an
|
||||||
|
empty string the callback is removed. This has only effect if
|
||||||
|
{buf} has 'buftype' set to "prompt".
|
||||||
|
|
||||||
|
This callback will be invoked when pressing CTRL-C in Insert
|
||||||
|
mode. Without setting a callback Vim will exit Insert mode,
|
||||||
|
as in any buffer.
|
||||||
|
|
||||||
|
prompt_setprompt({buf}, {text}) *prompt_setprompt()*
|
||||||
|
Set prompt for buffer {buf} to {text}. You most likely want
|
||||||
|
{text} to end in a space.
|
||||||
|
The result is only visible if {buf} has 'buftype' set to
|
||||||
|
"prompt". Example: >
|
||||||
|
call prompt_setprompt(bufnr(''), 'command: ')
|
||||||
|
|
||||||
pum_getpos() *pum_getpos()*
|
pum_getpos() *pum_getpos()*
|
||||||
If the popup menu (see |ins-completion-menu|) is not visible,
|
If the popup menu (see |ins-completion-menu|) is not visible,
|
||||||
|
|||||||
@@ -307,6 +307,23 @@ Other commands ~
|
|||||||
isn't one
|
isn't one
|
||||||
|
|
||||||
|
|
||||||
|
Prompt mode ~
|
||||||
|
*termdebug-prompt*
|
||||||
|
When on MS-Windows, gdb will run in a buffer with 'buftype' set to "prompt".
|
||||||
|
This works slightly differently:
|
||||||
|
- The gdb window will be in Insert mode while typing commands. Go to Normal
|
||||||
|
mode with <Esc>, then you can move around in the buffer, copy/paste, etc.
|
||||||
|
Go back to editing the gdb command with any command that starts Insert mode,
|
||||||
|
such as `a` or `i`.
|
||||||
|
- The program being debugged will run in a separate window. On MS-Windows
|
||||||
|
this is a new console window. On Unix, if the |+terminal| feature is
|
||||||
|
available a Terminal window will be opened to run the debugged program in.
|
||||||
|
|
||||||
|
*termdebug_use_prompt*
|
||||||
|
Prompt mode can be used even when the |+terminal| feature is present with: >
|
||||||
|
let g:termdebug_use_prompt = 1
|
||||||
|
|
||||||
|
|
||||||
Communication ~
|
Communication ~
|
||||||
*termdebug-communication*
|
*termdebug-communication*
|
||||||
There is another, hidden, buffer, which is used for Vim to communicate with
|
There is another, hidden, buffer, which is used for Vim to communicate with
|
||||||
|
|||||||
@@ -1093,6 +1093,8 @@ A jump table for the options with a short description can be found at |Q_op|.
|
|||||||
nowrite buffer will not be written
|
nowrite buffer will not be written
|
||||||
quickfix list of errors |:cwindow| or locations |:lwindow|
|
quickfix list of errors |:cwindow| or locations |:lwindow|
|
||||||
terminal |terminal-emulator| buffer
|
terminal |terminal-emulator| buffer
|
||||||
|
prompt buffer where only the last line can be edited, meant
|
||||||
|
to be used by a plugin, see |prompt-buffer|
|
||||||
|
|
||||||
This option is used together with 'bufhidden' and 'swapfile' to
|
This option is used together with 'bufhidden' and 'swapfile' to
|
||||||
specify special kinds of buffers. See |special-buffers|.
|
specify special kinds of buffers. See |special-buffers|.
|
||||||
|
|||||||
223
runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
vendored
223
runtime/pack/dist/opt/termdebug/plugin/termdebug.vim
vendored
@@ -37,7 +37,7 @@
|
|||||||
" For neovim compatibility, the vim specific calls were replaced with neovim
|
" For neovim compatibility, the vim specific calls were replaced with neovim
|
||||||
" specific calls:
|
" specific calls:
|
||||||
" term_start -> term_open
|
" term_start -> term_open
|
||||||
" term_sendkeys -> jobsend
|
" term_sendkeys -> chansend
|
||||||
" term_getline -> getbufline
|
" term_getline -> getbufline
|
||||||
" job_info && term_getjob -> using linux command ps to get the tty
|
" job_info && term_getjob -> using linux command ps to get the tty
|
||||||
" balloon -> nvim floating window
|
" balloon -> nvim floating window
|
||||||
@@ -47,8 +47,6 @@
|
|||||||
" https://github.com/autozimu/LanguageClient-neovim/blob/0ed9b69dca49c415390a8317b19149f97ae093fa/autoload/LanguageClient.vim#L304
|
" https://github.com/autozimu/LanguageClient-neovim/blob/0ed9b69dca49c415390a8317b19149f97ae093fa/autoload/LanguageClient.vim#L304
|
||||||
"
|
"
|
||||||
" Neovim terminal also works seamlessly on windows, which is why the ability
|
" Neovim terminal also works seamlessly on windows, which is why the ability
|
||||||
" to use the prompt buffer was removed.
|
|
||||||
"
|
|
||||||
" Author: Bram Moolenaar
|
" Author: Bram Moolenaar
|
||||||
" Copyright: Vim license applies, see ":help license"
|
" Copyright: Vim license applies, see ":help license"
|
||||||
|
|
||||||
@@ -57,6 +55,12 @@ if exists(':Termdebug')
|
|||||||
finish
|
finish
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
" The terminal feature does not work with gdb on win32.
|
||||||
|
if !has('win32')
|
||||||
|
let s:way = 'terminal'
|
||||||
|
else
|
||||||
|
let s:way = 'prompt'
|
||||||
|
endif
|
||||||
|
|
||||||
let s:keepcpo = &cpo
|
let s:keepcpo = &cpo
|
||||||
set cpo&vim
|
set cpo&vim
|
||||||
@@ -138,7 +142,19 @@ func s:StartDebug_internal(dict)
|
|||||||
let s:vertical = 0
|
let s:vertical = 0
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
" Override using a terminal window by setting g:termdebug_use_prompt to 1.
|
||||||
|
let use_prompt = exists('g:termdebug_use_prompt') && g:termdebug_use_prompt
|
||||||
|
if !has('win32') && !use_prompt
|
||||||
|
let s:way = 'terminal'
|
||||||
|
else
|
||||||
|
let s:way = 'prompt'
|
||||||
|
endif
|
||||||
|
|
||||||
|
if s:way == 'prompt'
|
||||||
|
call s:StartDebug_prompt(a:dict)
|
||||||
|
else
|
||||||
call s:StartDebug_term(a:dict)
|
call s:StartDebug_term(a:dict)
|
||||||
|
endif
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
" Use when debugger didn't start or ended.
|
" Use when debugger didn't start or ended.
|
||||||
@@ -214,11 +230,11 @@ func s:StartDebug_term(dict)
|
|||||||
|
|
||||||
" Set arguments to be run
|
" Set arguments to be run
|
||||||
if len(proc_args)
|
if len(proc_args)
|
||||||
call jobsend(s:gdb_job_id, 'set args ' . join(proc_args) . "\r")
|
call chansend(s:gdb_job_id, 'set args ' . join(proc_args) . "\r")
|
||||||
endif
|
endif
|
||||||
|
|
||||||
" Connect gdb to the communication pty, using the GDB/MI interface
|
" Connect gdb to the communication pty, using the GDB/MI interface
|
||||||
call jobsend(s:gdb_job_id, 'new-ui mi ' . commpty . "\r")
|
call chansend(s:gdb_job_id, 'new-ui mi ' . commpty . "\r")
|
||||||
|
|
||||||
" Wait for the response to show up, users may not notice the error and wonder
|
" Wait for the response to show up, users may not notice the error and wonder
|
||||||
" why the debugger doesn't work.
|
" why the debugger doesn't work.
|
||||||
@@ -275,6 +291,100 @@ func s:StartDebug_term(dict)
|
|||||||
call s:StartDebugCommon(a:dict)
|
call s:StartDebugCommon(a:dict)
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func s:StartDebug_prompt(dict)
|
||||||
|
" Open a window with a prompt buffer to run gdb in.
|
||||||
|
if s:vertical
|
||||||
|
vertical new
|
||||||
|
else
|
||||||
|
new
|
||||||
|
endif
|
||||||
|
let s:gdbwin = win_getid(winnr())
|
||||||
|
let s:promptbuf = bufnr('')
|
||||||
|
call prompt_setprompt(s:promptbuf, 'gdb> ')
|
||||||
|
set buftype=prompt
|
||||||
|
file gdb
|
||||||
|
call prompt_setcallback(s:promptbuf, function('s:PromptCallback'))
|
||||||
|
call prompt_setinterrupt(s:promptbuf, function('s:PromptInterrupt'))
|
||||||
|
|
||||||
|
if s:vertical
|
||||||
|
" Assuming the source code window will get a signcolumn, use two more
|
||||||
|
" columns for that, thus one less for the terminal window.
|
||||||
|
exe (&columns / 2 - 1) . "wincmd |"
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Add -quiet to avoid the intro message causing a hit-enter prompt.
|
||||||
|
let gdb_args = get(a:dict, 'gdb_args', [])
|
||||||
|
let proc_args = get(a:dict, 'proc_args', [])
|
||||||
|
|
||||||
|
let cmd = [g:termdebugger, '-quiet', '--interpreter=mi2'] + gdb_args
|
||||||
|
"call ch_log('executing "' . join(cmd) . '"')
|
||||||
|
|
||||||
|
let s:gdbjob = jobstart(cmd, {
|
||||||
|
\ 'on_exit': function('s:EndPromptDebug'),
|
||||||
|
\ 'on_stdout': function('s:GdbOutCallback'),
|
||||||
|
\ })
|
||||||
|
if s:gdbjob == 0
|
||||||
|
echoerr 'invalid argument (or job table is full) while starting gdb job'
|
||||||
|
exe 'bwipe! ' . s:ptybuf
|
||||||
|
return
|
||||||
|
elseif s:gdbjob == -1
|
||||||
|
echoerr 'Failed to start the gdb job'
|
||||||
|
call s:CloseBuffers()
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
|
||||||
|
" Interpret commands while the target is running. This should usualy only
|
||||||
|
" be exec-interrupt, since many commands don't work properly while the
|
||||||
|
" target is running.
|
||||||
|
call s:SendCommand('-gdb-set mi-async on')
|
||||||
|
" Older gdb uses a different command.
|
||||||
|
call s:SendCommand('-gdb-set target-async on')
|
||||||
|
|
||||||
|
let s:ptybuf = 0
|
||||||
|
if has('win32')
|
||||||
|
" MS-Windows: run in a new console window for maximum compatibility
|
||||||
|
call s:SendCommand('set new-console on')
|
||||||
|
else
|
||||||
|
" Unix: Run the debugged program in a terminal window. Open it below the
|
||||||
|
" gdb window.
|
||||||
|
execute 'new'
|
||||||
|
wincmd x | wincmd j
|
||||||
|
belowright let s:pty_job_id = termopen('tail -f /dev/null;#gdb program')
|
||||||
|
if s:pty_job_id == 0
|
||||||
|
echoerr 'invalid argument (or job table is full) while opening terminal window'
|
||||||
|
return
|
||||||
|
elseif s:pty_job_id == -1
|
||||||
|
echoerr 'Failed to open the program terminal window'
|
||||||
|
return
|
||||||
|
endif
|
||||||
|
let pty_job_info = nvim_get_chan_info(s:pty_job_id)
|
||||||
|
let s:ptybuf = pty_job_info['buffer']
|
||||||
|
let pty = pty_job_info['pty']
|
||||||
|
let s:ptywin = win_getid(winnr())
|
||||||
|
call s:SendCommand('tty ' . pty)
|
||||||
|
|
||||||
|
" Since GDB runs in a prompt window, the environment has not been set to
|
||||||
|
" match a terminal window, need to do that now.
|
||||||
|
call s:SendCommand('set env TERM = xterm-color')
|
||||||
|
call s:SendCommand('set env ROWS = ' . winheight(s:ptywin))
|
||||||
|
call s:SendCommand('set env LINES = ' . winheight(s:ptywin))
|
||||||
|
call s:SendCommand('set env COLUMNS = ' . winwidth(s:ptywin))
|
||||||
|
call s:SendCommand('set env COLORS = ' . &t_Co)
|
||||||
|
call s:SendCommand('set env VIM_TERMINAL = ' . v:version)
|
||||||
|
endif
|
||||||
|
call s:SendCommand('set print pretty on')
|
||||||
|
call s:SendCommand('set breakpoint pending on')
|
||||||
|
" Disable pagination, it causes everything to stop at the gdb
|
||||||
|
call s:SendCommand('set pagination off')
|
||||||
|
|
||||||
|
" Set arguments to be run
|
||||||
|
if len(proc_args)
|
||||||
|
call s:SendCommand('set args ' . join(proc_args))
|
||||||
|
endif
|
||||||
|
|
||||||
|
call s:StartDebugCommon(a:dict)
|
||||||
|
startinsert
|
||||||
|
endfunc
|
||||||
|
|
||||||
func s:StartDebugCommon(dict)
|
func s:StartDebugCommon(dict)
|
||||||
" Sign used to highlight the line where the program has stopped.
|
" Sign used to highlight the line where the program has stopped.
|
||||||
@@ -316,21 +426,97 @@ endfunc
|
|||||||
" Send a command to gdb. "cmd" is the string without line terminator.
|
" Send a command to gdb. "cmd" is the string without line terminator.
|
||||||
func s:SendCommand(cmd)
|
func s:SendCommand(cmd)
|
||||||
"call ch_log('sending to gdb: ' . a:cmd)
|
"call ch_log('sending to gdb: ' . a:cmd)
|
||||||
call jobsend(s:comm_job_id, a:cmd . "\r")
|
if s:way == 'prompt'
|
||||||
|
call chansend(s:gdbjob, a:cmd . "\n")
|
||||||
|
else
|
||||||
|
call chansend(s:comm_job_id, a:cmd . "\r")
|
||||||
|
endif
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
" This is global so that a user can create their mappings with this.
|
" This is global so that a user can create their mappings with this.
|
||||||
func TermDebugSendCommand(cmd)
|
func TermDebugSendCommand(cmd)
|
||||||
|
if s:way == 'prompt'
|
||||||
|
call chansend(s:gdbjob, a:cmd . "\n")
|
||||||
|
else
|
||||||
let do_continue = 0
|
let do_continue = 0
|
||||||
if !s:stopped
|
if !s:stopped
|
||||||
let do_continue = 1
|
let do_continue = 1
|
||||||
|
if s:way == 'prompt'
|
||||||
|
" Need to send a signal to get the UI to listen. Strangely this is only
|
||||||
|
" needed once.
|
||||||
|
call jobstop(s:gdbjob)
|
||||||
|
else
|
||||||
call s:SendCommand('-exec-interrupt')
|
call s:SendCommand('-exec-interrupt')
|
||||||
|
endif
|
||||||
sleep 10m
|
sleep 10m
|
||||||
endif
|
endif
|
||||||
call jobsend(s:gdb_job_id, a:cmd . "\r")
|
call chansend(s:gdb_job_id, a:cmd . "\r")
|
||||||
if do_continue
|
if do_continue
|
||||||
Continue
|
Continue
|
||||||
endif
|
endif
|
||||||
|
endif
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Function called when entering a line in the prompt buffer.
|
||||||
|
func s:PromptCallback(text)
|
||||||
|
call s:SendCommand(a:text)
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Function called when pressing CTRL-C in the prompt buffer and when placing a
|
||||||
|
" breakpoint.
|
||||||
|
func s:PromptInterrupt()
|
||||||
|
if s:pid == 0
|
||||||
|
echoerr 'Cannot interrupt gdb, did not find a process ID'
|
||||||
|
else
|
||||||
|
"call ch_log('Interrupting gdb')
|
||||||
|
" Using job_stop(s:gdbjob, 'int') does not work.
|
||||||
|
call debugbreak(s:pid)
|
||||||
|
endif
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
" Function called when gdb outputs text.
|
||||||
|
func s:GdbOutCallback(job_id, msgs, event)
|
||||||
|
"call ch_log('received from gdb: ' . a:text)
|
||||||
|
|
||||||
|
" Drop the gdb prompt, we have our own.
|
||||||
|
" Drop status and echo'd commands.
|
||||||
|
call filter(a:msgs, { index, val ->
|
||||||
|
\ val !=# '(gdb)' && val !=# '^done' && val[0] !=# '&'})
|
||||||
|
|
||||||
|
let lines = []
|
||||||
|
let index = 0
|
||||||
|
|
||||||
|
for msg in a:msgs
|
||||||
|
if msg =~ '^^error,msg='
|
||||||
|
if exists('s:evalexpr')
|
||||||
|
\ && s:DecodeMessage(msg[11:])
|
||||||
|
\ =~ 'A syntax error in expression, near\|No symbol .* in current context'
|
||||||
|
" Silently drop evaluation errors.
|
||||||
|
call remove(a:msgs, index)
|
||||||
|
unlet s:evalexpr
|
||||||
|
continue
|
||||||
|
endif
|
||||||
|
elseif msg[0] == '~'
|
||||||
|
call add(lines, s:DecodeMessage(msg[1:]))
|
||||||
|
call remove(a:msgs, index)
|
||||||
|
continue
|
||||||
|
endif
|
||||||
|
let index += 1
|
||||||
|
endfor
|
||||||
|
|
||||||
|
let curwinid = win_getid(winnr())
|
||||||
|
call win_gotoid(s:gdbwin)
|
||||||
|
|
||||||
|
" Add the output above the current prompt.
|
||||||
|
for line in lines
|
||||||
|
call append(line('$') - 1, line)
|
||||||
|
endfor
|
||||||
|
if !empty(lines)
|
||||||
|
set modified
|
||||||
|
endif
|
||||||
|
|
||||||
|
call win_gotoid(curwinid)
|
||||||
|
call s:CommOutput(a:job_id, a:msgs, a:event)
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
" Decode a message from gdb. quotedText starts with a ", return the text up
|
" Decode a message from gdb. quotedText starts with a ", return the text up
|
||||||
@@ -396,6 +582,19 @@ func s:EndDebugCommon()
|
|||||||
au! TermDebug
|
au! TermDebug
|
||||||
endfunc
|
endfunc
|
||||||
|
|
||||||
|
func s:EndPromptDebug(job_id, exit_code, event)
|
||||||
|
let curwinid = win_getid(winnr())
|
||||||
|
call win_gotoid(s:gdbwin)
|
||||||
|
close
|
||||||
|
if curwinid != s:gdbwin
|
||||||
|
call win_gotoid(curwinid)
|
||||||
|
endif
|
||||||
|
|
||||||
|
call s:EndDebugCommon()
|
||||||
|
unlet s:gdbwin
|
||||||
|
"call ch_log("Returning from EndPromptDebug()")
|
||||||
|
endfunc
|
||||||
|
|
||||||
func s:CommOutput(job_id, msgs, event)
|
func s:CommOutput(job_id, msgs, event)
|
||||||
|
|
||||||
for msg in a:msgs
|
for msg in a:msgs
|
||||||
@@ -436,7 +635,11 @@ func s:InstallCommands()
|
|||||||
command Stop call s:SendCommand('-exec-interrupt')
|
command Stop call s:SendCommand('-exec-interrupt')
|
||||||
|
|
||||||
" using -exec-continue results in CTRL-C in gdb window not working
|
" using -exec-continue results in CTRL-C in gdb window not working
|
||||||
command Continue call jobsend(s:gdb_job_id, "continue\r")
|
if s:way == 'prompt'
|
||||||
|
command Continue call s:SendCommand('continue')
|
||||||
|
else
|
||||||
|
command Continue call chansend(s:gdb_job_id, "continue\r")
|
||||||
|
endif
|
||||||
|
|
||||||
command -range -nargs=* Evaluate call s:Evaluate(<range>, <q-args>)
|
command -range -nargs=* Evaluate call s:Evaluate(<range>, <q-args>)
|
||||||
command Gdb call win_gotoid(s:gdbwin)
|
command Gdb call win_gotoid(s:gdbwin)
|
||||||
@@ -494,7 +697,11 @@ func s:SetBreakpoint()
|
|||||||
let do_continue = 0
|
let do_continue = 0
|
||||||
if !s:stopped
|
if !s:stopped
|
||||||
let do_continue = 1
|
let do_continue = 1
|
||||||
|
if s:way == 'prompt'
|
||||||
|
call s:PromptInterrupt()
|
||||||
|
else
|
||||||
call s:SendCommand('-exec-interrupt')
|
call s:SendCommand('-exec-interrupt')
|
||||||
|
endif
|
||||||
sleep 10m
|
sleep 10m
|
||||||
endif
|
endif
|
||||||
" Use the fname:lnum format, older gdb can't handle --source.
|
" Use the fname:lnum format, older gdb can't handle --source.
|
||||||
|
|||||||
@@ -763,6 +763,9 @@ static void free_buffer(buf_T *buf)
|
|||||||
unref_var_dict(buf->b_vars);
|
unref_var_dict(buf->b_vars);
|
||||||
aubuflocal_remove(buf);
|
aubuflocal_remove(buf);
|
||||||
tv_dict_unref(buf->additional_data);
|
tv_dict_unref(buf->additional_data);
|
||||||
|
xfree(buf->b_prompt_text);
|
||||||
|
callback_free(&buf->b_prompt_callback);
|
||||||
|
callback_free(&buf->b_prompt_interrupt);
|
||||||
clear_fmark(&buf->b_last_cursor);
|
clear_fmark(&buf->b_last_cursor);
|
||||||
clear_fmark(&buf->b_last_insert);
|
clear_fmark(&buf->b_last_insert);
|
||||||
clear_fmark(&buf->b_last_change);
|
clear_fmark(&buf->b_last_change);
|
||||||
@@ -1876,6 +1879,10 @@ buf_T * buflist_new(char_u *ffname, char_u *sfname, linenr_T lnum, int flags)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
buf->b_prompt_callback.type = kCallbackNone;
|
||||||
|
buf->b_prompt_interrupt.type = kCallbackNone;
|
||||||
|
buf->b_prompt_text = NULL;
|
||||||
|
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4824,6 +4831,12 @@ do_arg_all(
|
|||||||
xfree(opened);
|
xfree(opened);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return TRUE if "buf" is a prompt buffer.
|
||||||
|
int bt_prompt(buf_T *buf)
|
||||||
|
{
|
||||||
|
return buf != NULL && buf->b_p_bt[0] == 'p';
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Open a window for a number of buffers.
|
* Open a window for a number of buffers.
|
||||||
*/
|
*/
|
||||||
@@ -5218,14 +5231,18 @@ bool bt_nofile(const buf_T *const buf)
|
|||||||
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
|
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
|
||||||
{
|
{
|
||||||
return buf != NULL && ((buf->b_p_bt[0] == 'n' && buf->b_p_bt[2] == 'f')
|
return buf != NULL && ((buf->b_p_bt[0] == 'n' && buf->b_p_bt[2] == 'f')
|
||||||
|| buf->b_p_bt[0] == 'a' || buf->terminal);
|
|| buf->b_p_bt[0] == 'a'
|
||||||
|
|| buf->terminal
|
||||||
|
|| buf->b_p_bt[0] == 'p');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return true if "buf" is a "nowrite", "nofile" or "terminal" buffer.
|
// Return true if "buf" is a "nowrite", "nofile" or "terminal" buffer.
|
||||||
bool bt_dontwrite(const buf_T *const buf)
|
bool bt_dontwrite(const buf_T *const buf)
|
||||||
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
|
FUNC_ATTR_PURE FUNC_ATTR_WARN_UNUSED_RESULT
|
||||||
{
|
{
|
||||||
return buf != NULL && (buf->b_p_bt[0] == 'n' || buf->terminal);
|
return buf != NULL && (buf->b_p_bt[0] == 'n'
|
||||||
|
|| buf->terminal
|
||||||
|
|| buf->b_p_bt[0] == 'p');
|
||||||
}
|
}
|
||||||
|
|
||||||
bool bt_dontwrite_msg(const buf_T *const buf)
|
bool bt_dontwrite_msg(const buf_T *const buf)
|
||||||
@@ -5278,6 +5295,9 @@ char_u *buf_spname(buf_T *buf)
|
|||||||
if (buf->b_fname != NULL) {
|
if (buf->b_fname != NULL) {
|
||||||
return buf->b_fname;
|
return buf->b_fname;
|
||||||
}
|
}
|
||||||
|
if (bt_prompt(buf)) {
|
||||||
|
return (char_u *)_("[Prompt]");
|
||||||
|
}
|
||||||
return (char_u *)_("[Scratch]");
|
return (char_u *)_("[Scratch]");
|
||||||
}
|
}
|
||||||
if (buf->b_fname == NULL) {
|
if (buf->b_fname == NULL) {
|
||||||
|
|||||||
@@ -791,6 +791,12 @@ struct file_buffer {
|
|||||||
// are not used! Use the B_SPELL macro to
|
// are not used! Use the B_SPELL macro to
|
||||||
// access b_spell without #ifdef.
|
// access b_spell without #ifdef.
|
||||||
|
|
||||||
|
char_u *b_prompt_text; // set by prompt_setprompt()
|
||||||
|
Callback b_prompt_callback; // set by prompt_setcallback()
|
||||||
|
Callback b_prompt_interrupt; // set by prompt_setinterrupt()
|
||||||
|
int b_prompt_insert; // value for restart_edit when entering
|
||||||
|
// a prompt buffer window.
|
||||||
|
|
||||||
synblock_T b_s; // Info related to syntax highlighting. w_s
|
synblock_T b_s; // Info related to syntax highlighting. w_s
|
||||||
// normally points to this, but some windows
|
// normally points to this, but some windows
|
||||||
// may use a different synblock_T.
|
// may use a different synblock_T.
|
||||||
|
|||||||
@@ -2432,6 +2432,10 @@ void nv_diffgetput(bool put, size_t count)
|
|||||||
exarg_T ea;
|
exarg_T ea;
|
||||||
char buf[30];
|
char buf[30];
|
||||||
|
|
||||||
|
if (bt_prompt(curbuf)) {
|
||||||
|
vim_beep(BO_OPER);
|
||||||
|
return;
|
||||||
|
}
|
||||||
if (count == 0) {
|
if (count == 0) {
|
||||||
ea.arg = (char_u *)"";
|
ea.arg = (char_u *)"";
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -574,6 +574,12 @@ static int insert_check(VimState *state)
|
|||||||
foldCheckClose();
|
foldCheckClose();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int cmdchar_todo = s->cmdchar;
|
||||||
|
if (bt_prompt(curbuf)) {
|
||||||
|
init_prompt(cmdchar_todo);
|
||||||
|
cmdchar_todo = NUL;
|
||||||
|
}
|
||||||
|
|
||||||
// If we inserted a character at the last position of the last line in the
|
// If we inserted a character at the last position of the last line in the
|
||||||
// window, scroll the window one line up. This avoids an extra redraw. This
|
// window, scroll the window one line up. This avoids an extra redraw. This
|
||||||
// is detected when the cursor column is smaller after inserting something.
|
// is detected when the cursor column is smaller after inserting something.
|
||||||
@@ -817,6 +823,16 @@ static int insert_handle_key(InsertState *s)
|
|||||||
s->nomove = true;
|
s->nomove = true;
|
||||||
return 0; // exit insert mode
|
return 0; // exit insert mode
|
||||||
}
|
}
|
||||||
|
if (s->c == Ctrl_C && bt_prompt(curbuf)) {
|
||||||
|
if (invoke_prompt_interrupt()) {
|
||||||
|
if (!bt_prompt(curbuf)) {
|
||||||
|
// buffer changed to a non-prompt buffer, get out of
|
||||||
|
// Insert mode
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// when 'insertmode' set, and not halfway through a mapping, don't leave
|
// when 'insertmode' set, and not halfway through a mapping, don't leave
|
||||||
// Insert mode
|
// Insert mode
|
||||||
@@ -1143,6 +1159,15 @@ check_pum:
|
|||||||
cmdwin_result = CAR;
|
cmdwin_result = CAR;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
if (bt_prompt(curbuf)) {
|
||||||
|
invoke_prompt_callback();
|
||||||
|
if (!bt_prompt(curbuf)) {
|
||||||
|
// buffer changed to a non-prompt buffer, get out of
|
||||||
|
// Insert mode
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
if (!ins_eol(s->c) && !p_im) {
|
if (!ins_eol(s->c) && !p_im) {
|
||||||
return 0; // out of memory
|
return 0; // out of memory
|
||||||
}
|
}
|
||||||
@@ -1569,6 +1594,52 @@ void edit_putchar(int c, int highlight)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Return the effective prompt for the current buffer.
|
||||||
|
char_u *prompt_text(void)
|
||||||
|
{
|
||||||
|
if (curbuf->b_prompt_text == NULL) {
|
||||||
|
return (char_u *)"% ";
|
||||||
|
}
|
||||||
|
return curbuf->b_prompt_text;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Prepare for prompt mode: Make sure the last line has the prompt text.
|
||||||
|
// Move the cursor to this line.
|
||||||
|
static void init_prompt(int cmdchar_todo)
|
||||||
|
{
|
||||||
|
char_u *prompt = prompt_text();
|
||||||
|
char_u *text;
|
||||||
|
|
||||||
|
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
|
||||||
|
text = get_cursor_line_ptr();
|
||||||
|
if (STRNCMP(text, prompt, STRLEN(prompt)) != 0) {
|
||||||
|
// prompt is missing, insert it or append a line with it
|
||||||
|
if (*text == NUL) {
|
||||||
|
ml_replace(curbuf->b_ml.ml_line_count, prompt, true);
|
||||||
|
} else {
|
||||||
|
ml_append(curbuf->b_ml.ml_line_count, prompt, 0, false);
|
||||||
|
}
|
||||||
|
curwin->w_cursor.lnum = curbuf->b_ml.ml_line_count;
|
||||||
|
coladvance((colnr_T)MAXCOL);
|
||||||
|
changed_bytes(curbuf->b_ml.ml_line_count, 0);
|
||||||
|
}
|
||||||
|
if (cmdchar_todo == 'A') {
|
||||||
|
coladvance((colnr_T)MAXCOL);
|
||||||
|
}
|
||||||
|
if (cmdchar_todo == 'I' || curwin->w_cursor.col <= (int)STRLEN(prompt)) {
|
||||||
|
curwin->w_cursor.col = STRLEN(prompt);
|
||||||
|
}
|
||||||
|
// Make sure the cursor is in a valid position.
|
||||||
|
check_cursor();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return TRUE if the cursor is in the editable position of the prompt line.
|
||||||
|
int prompt_curpos_editable(void)
|
||||||
|
{
|
||||||
|
return curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count
|
||||||
|
&& curwin->w_cursor.col >= (int)STRLEN(prompt_text());
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Undo the previous edit_putchar().
|
* Undo the previous edit_putchar().
|
||||||
*/
|
*/
|
||||||
@@ -8161,10 +8232,14 @@ static void ins_mouse(int c)
|
|||||||
win_T *new_curwin = curwin;
|
win_T *new_curwin = curwin;
|
||||||
|
|
||||||
if (curwin != old_curwin && win_valid(old_curwin)) {
|
if (curwin != old_curwin && win_valid(old_curwin)) {
|
||||||
/* Mouse took us to another window. We need to go back to the
|
// Mouse took us to another window. We need to go back to the
|
||||||
* previous one to stop insert there properly. */
|
// previous one to stop insert there properly.
|
||||||
curwin = old_curwin;
|
curwin = old_curwin;
|
||||||
curbuf = curwin->w_buffer;
|
curbuf = curwin->w_buffer;
|
||||||
|
if (bt_prompt(curbuf)) {
|
||||||
|
// Restart Insert mode when re-entering the prompt buffer.
|
||||||
|
curbuf->b_prompt_insert = 'A';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
start_arrow(curwin == old_curwin ? &tpos : NULL);
|
start_arrow(curwin == old_curwin ? &tpos : NULL);
|
||||||
if (curwin != new_curwin && win_valid(new_curwin)) {
|
if (curwin != new_curwin && win_valid(new_curwin)) {
|
||||||
|
|||||||
@@ -5152,6 +5152,10 @@ bool garbage_collect(bool testing)
|
|||||||
}
|
}
|
||||||
// buffer ShaDa additional data
|
// buffer ShaDa additional data
|
||||||
ABORTING(set_ref_dict)(buf->additional_data, copyID);
|
ABORTING(set_ref_dict)(buf->additional_data, copyID);
|
||||||
|
|
||||||
|
// buffer callback functions
|
||||||
|
set_ref_in_callback(&buf->b_prompt_callback, copyID, NULL, NULL);
|
||||||
|
set_ref_in_callback(&buf->b_prompt_interrupt, copyID, NULL, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
FOR_ALL_TAB_WINDOWS(tp, wp) {
|
FOR_ALL_TAB_WINDOWS(tp, wp) {
|
||||||
@@ -7315,9 +7319,7 @@ dict_T *get_win_info(win_T *wp, int16_t tpnr, int16_t winnr)
|
|||||||
return dict;
|
return dict;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// Find window specified by "vp" in tabpage "tp".
|
||||||
* Find window specified by "vp" in tabpage "tp".
|
|
||||||
*/
|
|
||||||
win_T *
|
win_T *
|
||||||
find_win_by_nr(
|
find_win_by_nr(
|
||||||
typval_T *vp,
|
typval_T *vp,
|
||||||
@@ -13687,3 +13689,51 @@ void ex_checkhealth(exarg_T *eap)
|
|||||||
|
|
||||||
xfree(buf);
|
xfree(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void invoke_prompt_callback(void)
|
||||||
|
{
|
||||||
|
typval_T rettv;
|
||||||
|
typval_T argv[2];
|
||||||
|
char_u *text;
|
||||||
|
char_u *prompt;
|
||||||
|
linenr_T lnum = curbuf->b_ml.ml_line_count;
|
||||||
|
|
||||||
|
// Add a new line for the prompt before invoking the callback, so that
|
||||||
|
// text can always be inserted above the last line.
|
||||||
|
ml_append(lnum, (char_u *)"", 0, false);
|
||||||
|
curwin->w_cursor.lnum = lnum + 1;
|
||||||
|
curwin->w_cursor.col = 0;
|
||||||
|
|
||||||
|
if (curbuf->b_prompt_callback.type == kCallbackNone) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
text = ml_get(lnum);
|
||||||
|
prompt = prompt_text();
|
||||||
|
if (STRLEN(text) >= STRLEN(prompt)) {
|
||||||
|
text += STRLEN(prompt);
|
||||||
|
}
|
||||||
|
argv[0].v_type = VAR_STRING;
|
||||||
|
argv[0].vval.v_string = vim_strsave(text);
|
||||||
|
argv[1].v_type = VAR_UNKNOWN;
|
||||||
|
|
||||||
|
callback_call(&curbuf->b_prompt_callback, 1, argv, &rettv);
|
||||||
|
tv_clear(&argv[0]);
|
||||||
|
tv_clear(&rettv);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return true When the interrupt callback was invoked.
|
||||||
|
bool invoke_prompt_interrupt(void)
|
||||||
|
{
|
||||||
|
typval_T rettv;
|
||||||
|
typval_T argv[1];
|
||||||
|
|
||||||
|
if (curbuf->b_prompt_interrupt.type == kCallbackNone) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
argv[0].v_type = VAR_UNKNOWN;
|
||||||
|
|
||||||
|
got_int = false; // don't skip executing commands
|
||||||
|
callback_call(&curbuf->b_prompt_interrupt, 0, argv, &rettv);
|
||||||
|
tv_clear(&rettv);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|||||||
@@ -82,6 +82,7 @@ return {
|
|||||||
ctxset={args={1, 2}},
|
ctxset={args={1, 2}},
|
||||||
ctxsize={},
|
ctxsize={},
|
||||||
cursor={args={1, 3}},
|
cursor={args={1, 3}},
|
||||||
|
debugbreak={args={1, 1}},
|
||||||
deepcopy={args={1, 2}},
|
deepcopy={args={1, 2}},
|
||||||
delete={args={1,2}},
|
delete={args={1,2}},
|
||||||
deletebufline={args={2,3}},
|
deletebufline={args={2,3}},
|
||||||
@@ -243,6 +244,9 @@ return {
|
|||||||
pow={args=2},
|
pow={args=2},
|
||||||
prevnonblank={args=1},
|
prevnonblank={args=1},
|
||||||
printf={args=varargs(1)},
|
printf={args=varargs(1)},
|
||||||
|
prompt_setcallback={args={2, 2}},
|
||||||
|
prompt_setinterrupt={args={2, 2}},
|
||||||
|
prompt_setprompt={args={2, 2}},
|
||||||
pum_getpos={},
|
pum_getpos={},
|
||||||
pumvisible={},
|
pumvisible={},
|
||||||
py3eval={args=1},
|
py3eval={args=1},
|
||||||
|
|||||||
@@ -1408,9 +1408,31 @@ static void f_cursor(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
rettv->vval.v_number = 0;
|
rettv->vval.v_number = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
// "debugbreak()" function
|
||||||
* "deepcopy()" function
|
static void f_debugbreak(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||||
*/
|
{
|
||||||
|
int pid;
|
||||||
|
|
||||||
|
rettv->vval.v_number = FAIL;
|
||||||
|
pid = (int)tv_get_number(&argvars[0]);
|
||||||
|
if (pid == 0) {
|
||||||
|
EMSG(_(e_invarg));
|
||||||
|
} else {
|
||||||
|
#ifdef WIN32
|
||||||
|
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, 0, pid);
|
||||||
|
|
||||||
|
if (hProcess != NULL) {
|
||||||
|
DebugBreakProcess(hProcess);
|
||||||
|
CloseHandle(hProcess);
|
||||||
|
rettv->vval.v_number = OK;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
uv_kill(pid, SIGINT);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// "deepcopy()" function
|
||||||
static void f_deepcopy(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
static void f_deepcopy(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||||
{
|
{
|
||||||
int noref = 0;
|
int noref = 0;
|
||||||
@@ -6076,6 +6098,76 @@ static void f_printf(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// "prompt_setcallback({buffer}, {callback})" function
|
||||||
|
static void f_prompt_setcallback(typval_T *argvars,
|
||||||
|
typval_T *rettv, FunPtr fptr)
|
||||||
|
{
|
||||||
|
buf_T *buf;
|
||||||
|
Callback prompt_callback = { .type = kCallbackNone };
|
||||||
|
|
||||||
|
if (check_secure()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
buf = tv_get_buf(&argvars[0], false);
|
||||||
|
if (buf == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argvars[1].v_type != VAR_STRING || *argvars[1].vval.v_string != NUL) {
|
||||||
|
if (!callback_from_typval(&prompt_callback, &argvars[1])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
callback_free(&buf->b_prompt_callback);
|
||||||
|
buf->b_prompt_callback = prompt_callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "prompt_setinterrupt({buffer}, {callback})" function
|
||||||
|
static void f_prompt_setinterrupt(typval_T *argvars,
|
||||||
|
typval_T *rettv, FunPtr fptr)
|
||||||
|
{
|
||||||
|
buf_T *buf;
|
||||||
|
Callback interrupt_callback = { .type = kCallbackNone };
|
||||||
|
|
||||||
|
if (check_secure()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
buf = tv_get_buf(&argvars[0], false);
|
||||||
|
if (buf == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argvars[1].v_type != VAR_STRING || *argvars[1].vval.v_string != NUL) {
|
||||||
|
if (!callback_from_typval(&interrupt_callback, &argvars[1])) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
callback_free(&buf->b_prompt_interrupt);
|
||||||
|
buf->b_prompt_interrupt= interrupt_callback;
|
||||||
|
}
|
||||||
|
|
||||||
|
// "prompt_setprompt({buffer}, {text})" function
|
||||||
|
static void f_prompt_setprompt(typval_T *argvars,
|
||||||
|
typval_T *rettv, FunPtr fptr)
|
||||||
|
{
|
||||||
|
buf_T *buf;
|
||||||
|
const char_u *text;
|
||||||
|
|
||||||
|
if (check_secure()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
buf = tv_get_buf(&argvars[0], false);
|
||||||
|
if (buf == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
text = (const char_u *)tv_get_string(&argvars[1]);
|
||||||
|
xfree(buf->b_prompt_text);
|
||||||
|
buf->b_prompt_text = vim_strsave(text);
|
||||||
|
}
|
||||||
|
|
||||||
// "pum_getpos()" function
|
// "pum_getpos()" function
|
||||||
static void f_pum_getpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
static void f_pum_getpos(typval_T *argvars, typval_T *rettv, FunPtr fptr)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3642,7 +3642,9 @@ static void nv_help(cmdarg_T *cap)
|
|||||||
*/
|
*/
|
||||||
static void nv_addsub(cmdarg_T *cap)
|
static void nv_addsub(cmdarg_T *cap)
|
||||||
{
|
{
|
||||||
if (!VIsual_active && cap->oap->op_type == OP_NOP) {
|
if (bt_prompt(curbuf) && !prompt_curpos_editable()) {
|
||||||
|
clearopbeep(cap->oap);
|
||||||
|
} else if (!VIsual_active && cap->oap->op_type == OP_NOP) {
|
||||||
prep_redo_cmd(cap);
|
prep_redo_cmd(cap);
|
||||||
cap->oap->op_type = cap->cmdchar == Ctrl_A ? OP_NR_ADD : OP_NR_SUB;
|
cap->oap->op_type = cap->cmdchar == Ctrl_A ? OP_NR_ADD : OP_NR_SUB;
|
||||||
op_addsub(cap->oap, cap->count1, cap->arg);
|
op_addsub(cap->oap, cap->count1, cap->arg);
|
||||||
@@ -5239,6 +5241,13 @@ static void nv_down(cmdarg_T *cap)
|
|||||||
// In the cmdline window a <CR> executes the command.
|
// In the cmdline window a <CR> executes the command.
|
||||||
if (cmdwin_type != 0 && cap->cmdchar == CAR) {
|
if (cmdwin_type != 0 && cap->cmdchar == CAR) {
|
||||||
cmdwin_result = CAR;
|
cmdwin_result = CAR;
|
||||||
|
} else if (bt_prompt(curbuf) && cap->cmdchar == CAR
|
||||||
|
&& curwin->w_cursor.lnum == curbuf->b_ml.ml_line_count) {
|
||||||
|
// In a prompt buffer a <CR> in the last line invokes the callback.
|
||||||
|
invoke_prompt_callback();
|
||||||
|
if (restart_edit == 0) {
|
||||||
|
restart_edit = 'a';
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
cap->oap->motion_type = kMTLineWise;
|
cap->oap->motion_type = kMTLineWise;
|
||||||
if (cursor_down(cap->count1, cap->oap->op_type == OP_NOP) == false) {
|
if (cursor_down(cap->count1, cap->oap->op_type == OP_NOP) == false) {
|
||||||
@@ -5831,6 +5840,10 @@ static void nv_undo(cmdarg_T *cap)
|
|||||||
static void nv_kundo(cmdarg_T *cap)
|
static void nv_kundo(cmdarg_T *cap)
|
||||||
{
|
{
|
||||||
if (!checkclearopq(cap->oap)) {
|
if (!checkclearopq(cap->oap)) {
|
||||||
|
if (bt_prompt(curbuf)) {
|
||||||
|
clearopbeep(cap->oap);
|
||||||
|
return;
|
||||||
|
}
|
||||||
u_undo((int)cap->count1);
|
u_undo((int)cap->count1);
|
||||||
curwin->w_set_curswant = true;
|
curwin->w_set_curswant = true;
|
||||||
}
|
}
|
||||||
@@ -5844,8 +5857,13 @@ static void nv_replace(cmdarg_T *cap)
|
|||||||
char_u *ptr;
|
char_u *ptr;
|
||||||
int had_ctrl_v;
|
int had_ctrl_v;
|
||||||
|
|
||||||
if (checkclearop(cap->oap))
|
if (checkclearop(cap->oap)) {
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
if (bt_prompt(curbuf) && !prompt_curpos_editable()) {
|
||||||
|
clearopbeep(cap->oap);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* get another character */
|
/* get another character */
|
||||||
if (cap->nchar == Ctrl_V) {
|
if (cap->nchar == Ctrl_V) {
|
||||||
@@ -6182,7 +6200,11 @@ static void v_visop(cmdarg_T *cap)
|
|||||||
*/
|
*/
|
||||||
static void nv_subst(cmdarg_T *cap)
|
static void nv_subst(cmdarg_T *cap)
|
||||||
{
|
{
|
||||||
if (VIsual_active) { /* "vs" and "vS" are the same as "vc" */
|
if (bt_prompt(curbuf) && !prompt_curpos_editable()) {
|
||||||
|
clearopbeep(cap->oap);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (VIsual_active) { // "vs" and "vS" are the same as "vc"
|
||||||
if (cap->cmdchar == 'S') {
|
if (cap->cmdchar == 'S') {
|
||||||
VIsual_mode_orig = VIsual_mode;
|
VIsual_mode_orig = VIsual_mode;
|
||||||
VIsual_mode = 'V';
|
VIsual_mode = 'V';
|
||||||
@@ -7120,11 +7142,16 @@ static void nv_tilde(cmdarg_T *cap)
|
|||||||
{
|
{
|
||||||
if (!p_to
|
if (!p_to
|
||||||
&& !VIsual_active
|
&& !VIsual_active
|
||||||
&& cap->oap->op_type != OP_TILDE)
|
&& cap->oap->op_type != OP_TILDE) {
|
||||||
|
if (bt_prompt(curbuf) && !prompt_curpos_editable()) {
|
||||||
|
clearopbeep(cap->oap);
|
||||||
|
return;
|
||||||
|
}
|
||||||
n_swapchar(cap);
|
n_swapchar(cap);
|
||||||
else
|
} else {
|
||||||
nv_operator(cap);
|
nv_operator(cap);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle an operator command.
|
* Handle an operator command.
|
||||||
@@ -7136,6 +7163,12 @@ static void nv_operator(cmdarg_T *cap)
|
|||||||
|
|
||||||
op_type = get_op_type(cap->cmdchar, cap->nchar);
|
op_type = get_op_type(cap->cmdchar, cap->nchar);
|
||||||
|
|
||||||
|
if (bt_prompt(curbuf) && op_is_change(op_type)
|
||||||
|
&& !prompt_curpos_editable()) {
|
||||||
|
clearopbeep(cap->oap);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (op_type == cap->oap->op_type) /* double operator works on lines */
|
if (op_type == cap->oap->op_type) /* double operator works on lines */
|
||||||
nv_lineop(cap);
|
nv_lineop(cap);
|
||||||
else if (!checkclearop(cap->oap)) {
|
else if (!checkclearop(cap->oap)) {
|
||||||
@@ -7796,7 +7829,10 @@ static void nv_put_opt(cmdarg_T *cap, bool fix_indent)
|
|||||||
clearop(cap->oap);
|
clearop(cap->oap);
|
||||||
assert(cap->opcount >= 0);
|
assert(cap->opcount >= 0);
|
||||||
nv_diffgetput(true, (size_t)cap->opcount);
|
nv_diffgetput(true, (size_t)cap->opcount);
|
||||||
} else
|
} else {
|
||||||
|
clearopbeep(cap->oap);
|
||||||
|
}
|
||||||
|
} else if (bt_prompt(curbuf) && !prompt_curpos_editable()) {
|
||||||
clearopbeep(cap->oap);
|
clearopbeep(cap->oap);
|
||||||
} else {
|
} else {
|
||||||
if (fix_indent) {
|
if (fix_indent) {
|
||||||
@@ -7809,8 +7845,9 @@ static void nv_put_opt(cmdarg_T *cap, bool fix_indent)
|
|||||||
? BACKWARD : FORWARD;
|
? BACKWARD : FORWARD;
|
||||||
}
|
}
|
||||||
prep_redo_cmd(cap);
|
prep_redo_cmd(cap);
|
||||||
if (cap->cmdchar == 'g')
|
if (cap->cmdchar == 'g') {
|
||||||
flags |= PUT_CURSEND;
|
flags |= PUT_CURSEND;
|
||||||
|
}
|
||||||
|
|
||||||
if (VIsual_active) {
|
if (VIsual_active) {
|
||||||
/* Putting in Visual mode: The put text replaces the selected
|
/* Putting in Visual mode: The put text replaces the selected
|
||||||
@@ -7916,11 +7953,15 @@ static void nv_open(cmdarg_T *cap)
|
|||||||
clearop(cap->oap);
|
clearop(cap->oap);
|
||||||
assert(cap->opcount >= 0);
|
assert(cap->opcount >= 0);
|
||||||
nv_diffgetput(false, (size_t)cap->opcount);
|
nv_diffgetput(false, (size_t)cap->opcount);
|
||||||
} else if (VIsual_active) /* switch start and end of visual */
|
} else if (VIsual_active) {
|
||||||
|
// switch start and end of visual/
|
||||||
v_swap_corners(cap->cmdchar);
|
v_swap_corners(cap->cmdchar);
|
||||||
else
|
} else if (bt_prompt(curbuf)) {
|
||||||
|
clearopbeep(cap->oap);
|
||||||
|
} else {
|
||||||
n_opencmd(cap);
|
n_opencmd(cap);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Calculate start/end virtual columns for operating in block mode.
|
// Calculate start/end virtual columns for operating in block mode.
|
||||||
static void get_op_vcol(
|
static void get_op_vcol(
|
||||||
|
|||||||
@@ -89,6 +89,10 @@ struct block_def {
|
|||||||
# include "ops.c.generated.h"
|
# include "ops.c.generated.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// Flags for third item in "opchars".
|
||||||
|
#define OPF_LINES 1 // operator always works on lines
|
||||||
|
#define OPF_CHANGE 2 // operator changes text
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The names of operators.
|
* The names of operators.
|
||||||
* IMPORTANT: Index must correspond with defines in vim.h!!!
|
* IMPORTANT: Index must correspond with defines in vim.h!!!
|
||||||
@@ -96,36 +100,36 @@ struct block_def {
|
|||||||
*/
|
*/
|
||||||
static char opchars[][3] =
|
static char opchars[][3] =
|
||||||
{
|
{
|
||||||
{ NUL, NUL, false }, // OP_NOP
|
{ NUL, NUL, 0 }, // OP_NOP
|
||||||
{ 'd', NUL, false }, // OP_DELETE
|
{ 'd', NUL, OPF_CHANGE }, // OP_DELETE
|
||||||
{ 'y', NUL, false }, // OP_YANK
|
{ 'y', NUL, 0 }, // OP_YANK
|
||||||
{ 'c', NUL, false }, // OP_CHANGE
|
{ 'c', NUL, OPF_CHANGE }, // OP_CHANGE
|
||||||
{ '<', NUL, true }, // OP_LSHIFT
|
{ '<', NUL, OPF_LINES | OPF_CHANGE }, // OP_LSHIFT
|
||||||
{ '>', NUL, true }, // OP_RSHIFT
|
{ '>', NUL, OPF_LINES | OPF_CHANGE }, // OP_RSHIFT
|
||||||
{ '!', NUL, true }, // OP_FILTER
|
{ '!', NUL, OPF_LINES | OPF_CHANGE }, // OP_FILTER
|
||||||
{ 'g', '~', false }, // OP_TILDE
|
{ 'g', '~', OPF_CHANGE }, // OP_TILDE
|
||||||
{ '=', NUL, true }, // OP_INDENT
|
{ '=', NUL, OPF_LINES | OPF_CHANGE }, // OP_INDENT
|
||||||
{ 'g', 'q', true }, // OP_FORMAT
|
{ 'g', 'q', OPF_LINES | OPF_CHANGE }, // OP_FORMAT
|
||||||
{ ':', NUL, true }, // OP_COLON
|
{ ':', NUL, OPF_LINES }, // OP_COLON
|
||||||
{ 'g', 'U', false }, // OP_UPPER
|
{ 'g', 'U', OPF_CHANGE }, // OP_UPPER
|
||||||
{ 'g', 'u', false }, // OP_LOWER
|
{ 'g', 'u', OPF_CHANGE }, // OP_LOWER
|
||||||
{ 'J', NUL, true }, // DO_JOIN
|
{ 'J', NUL, OPF_LINES | OPF_CHANGE }, // DO_JOIN
|
||||||
{ 'g', 'J', true }, // DO_JOIN_NS
|
{ 'g', 'J', OPF_LINES | OPF_CHANGE }, // DO_JOIN_NS
|
||||||
{ 'g', '?', false }, // OP_ROT13
|
{ 'g', '?', OPF_CHANGE }, // OP_ROT13
|
||||||
{ 'r', NUL, false }, // OP_REPLACE
|
{ 'r', NUL, OPF_CHANGE }, // OP_REPLACE
|
||||||
{ 'I', NUL, false }, // OP_INSERT
|
{ 'I', NUL, OPF_CHANGE }, // OP_INSERT
|
||||||
{ 'A', NUL, false }, // OP_APPEND
|
{ 'A', NUL, OPF_CHANGE }, // OP_APPEND
|
||||||
{ 'z', 'f', true }, // OP_FOLD
|
{ 'z', 'f', OPF_LINES }, // OP_FOLD
|
||||||
{ 'z', 'o', true }, // OP_FOLDOPEN
|
{ 'z', 'o', OPF_LINES }, // OP_FOLDOPEN
|
||||||
{ 'z', 'O', true }, // OP_FOLDOPENREC
|
{ 'z', 'O', OPF_LINES }, // OP_FOLDOPENREC
|
||||||
{ 'z', 'c', true }, // OP_FOLDCLOSE
|
{ 'z', 'c', OPF_LINES }, // OP_FOLDCLOSE
|
||||||
{ 'z', 'C', true }, // OP_FOLDCLOSEREC
|
{ 'z', 'C', OPF_LINES }, // OP_FOLDCLOSEREC
|
||||||
{ 'z', 'd', true }, // OP_FOLDDEL
|
{ 'z', 'd', OPF_LINES }, // OP_FOLDDEL
|
||||||
{ 'z', 'D', true }, // OP_FOLDDELREC
|
{ 'z', 'D', OPF_LINES }, // OP_FOLDDELREC
|
||||||
{ 'g', 'w', true }, // OP_FORMAT2
|
{ 'g', 'w', OPF_LINES | OPF_CHANGE }, // OP_FORMAT2
|
||||||
{ 'g', '@', false }, // OP_FUNCTION
|
{ 'g', '@', OPF_CHANGE }, // OP_FUNCTION
|
||||||
{ Ctrl_A, NUL, false }, // OP_NR_ADD
|
{ Ctrl_A, NUL, OPF_CHANGE }, // OP_NR_ADD
|
||||||
{ Ctrl_X, NUL, false }, // OP_NR_SUB
|
{ Ctrl_X, NUL, OPF_CHANGE }, // OP_NR_SUB
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -169,7 +173,13 @@ int get_op_type(int char1, int char2)
|
|||||||
*/
|
*/
|
||||||
int op_on_lines(int op)
|
int op_on_lines(int op)
|
||||||
{
|
{
|
||||||
return opchars[op][2];
|
return opchars[op][2] & OPF_LINES;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return TRUE if operator "op" changes text.
|
||||||
|
int op_is_change(int op)
|
||||||
|
{
|
||||||
|
return opchars[op][2] & OPF_CHANGE;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|||||||
@@ -299,7 +299,8 @@ static char *(p_scbopt_values[]) = { "ver", "hor", "jump", NULL };
|
|||||||
static char *(p_debug_values[]) = { "msg", "throw", "beep", NULL };
|
static char *(p_debug_values[]) = { "msg", "throw", "beep", NULL };
|
||||||
static char *(p_ead_values[]) = { "both", "ver", "hor", NULL };
|
static char *(p_ead_values[]) = { "both", "ver", "hor", NULL };
|
||||||
static char *(p_buftype_values[]) = { "nofile", "nowrite", "quickfix",
|
static char *(p_buftype_values[]) = { "nofile", "nowrite", "quickfix",
|
||||||
"help", "acwrite", "terminal", NULL };
|
"help", "acwrite", "terminal",
|
||||||
|
"prompt", NULL };
|
||||||
|
|
||||||
static char *(p_bufhidden_values[]) = { "hide", "unload", "delete",
|
static char *(p_bufhidden_values[]) = { "hide", "unload", "delete",
|
||||||
"wipe", NULL };
|
"wipe", NULL };
|
||||||
@@ -7091,6 +7092,9 @@ static int check_opt_wim(void)
|
|||||||
*/
|
*/
|
||||||
bool can_bs(int what)
|
bool can_bs(int what)
|
||||||
{
|
{
|
||||||
|
if (what == BS_START && bt_prompt(curbuf)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
switch (*p_bs) {
|
switch (*p_bs) {
|
||||||
case '2': return true;
|
case '2': return true;
|
||||||
case '1': return what != BS_START;
|
case '1': return what != BS_START;
|
||||||
|
|||||||
@@ -2971,7 +2971,10 @@ static char_u *u_save_line(linenr_T lnum)
|
|||||||
bool bufIsChanged(buf_T *buf)
|
bool bufIsChanged(buf_T *buf)
|
||||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
|
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
|
||||||
{
|
{
|
||||||
return !bt_dontwrite(buf) && (buf->b_changed || file_ff_differs(buf, true));
|
// In a "prompt" buffer we do respect 'modified', so that we can control
|
||||||
|
// closing the window by setting or resetting that option.
|
||||||
|
return (!bt_dontwrite(buf) || bt_prompt(buf))
|
||||||
|
&& (buf->b_changed || file_ff_differs(buf, true));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return true if any buffer has changes. Also buffers that are not written.
|
// Return true if any buffer has changes. Also buffers that are not written.
|
||||||
|
|||||||
153
test/functional/legacy/prompt_buffer_spec.lua
Normal file
153
test/functional/legacy/prompt_buffer_spec.lua
Normal file
@@ -0,0 +1,153 @@
|
|||||||
|
local helpers = require('test.functional.helpers')(after_each)
|
||||||
|
local Screen = require('test.functional.ui.screen')
|
||||||
|
local feed= helpers.feed
|
||||||
|
local source = helpers.source
|
||||||
|
local clear = helpers.clear
|
||||||
|
local feed_command = helpers.feed_command
|
||||||
|
|
||||||
|
describe('prompt buffer', function()
|
||||||
|
local screen
|
||||||
|
|
||||||
|
before_each(function()
|
||||||
|
clear()
|
||||||
|
screen = Screen.new(25, 10)
|
||||||
|
screen:attach()
|
||||||
|
source([[
|
||||||
|
func TextEntered(text)
|
||||||
|
if a:text == "exit"
|
||||||
|
set nomodified
|
||||||
|
stopinsert
|
||||||
|
close
|
||||||
|
else
|
||||||
|
call append(line("$") - 1, 'Command: "' . a:text . '"')
|
||||||
|
set nomodfied
|
||||||
|
call timer_start(20, {id -> TimerFunc(a:text)})
|
||||||
|
endif
|
||||||
|
endfunc
|
||||||
|
|
||||||
|
func TimerFunc(text)
|
||||||
|
call append(line("$") - 1, 'Result: "' . a:text .'"')
|
||||||
|
endfunc
|
||||||
|
]])
|
||||||
|
feed_command("set noshowmode | set laststatus=0")
|
||||||
|
feed_command("call setline(1, 'other buffer')")
|
||||||
|
feed_command("new")
|
||||||
|
feed_command("set buftype=prompt")
|
||||||
|
feed_command("call prompt_setcallback(bufnr(''), function('TextEntered'))")
|
||||||
|
end)
|
||||||
|
|
||||||
|
after_each(function()
|
||||||
|
screen:detach()
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('works', function()
|
||||||
|
screen:expect([[
|
||||||
|
^ |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
[Prompt] |
|
||||||
|
other buffer |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
feed("i")
|
||||||
|
feed("hello\n")
|
||||||
|
screen:expect([[
|
||||||
|
% hello |
|
||||||
|
Command: "hello" |
|
||||||
|
Result: "hello" |
|
||||||
|
% ^ |
|
||||||
|
[Prompt] [+] |
|
||||||
|
other buffer |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
feed("exit\n")
|
||||||
|
screen:expect([[
|
||||||
|
^other buffer |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
end)
|
||||||
|
|
||||||
|
it('editing', function()
|
||||||
|
screen:expect([[
|
||||||
|
^ |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
[Prompt] |
|
||||||
|
other buffer |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
feed("i")
|
||||||
|
feed("hello<BS><BS>")
|
||||||
|
screen:expect([[
|
||||||
|
% hel^ |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
[Prompt] [+] |
|
||||||
|
other buffer |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
feed("<Left><Left><Left><BS>-")
|
||||||
|
screen:expect([[
|
||||||
|
% -^hel |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
[Prompt] [+] |
|
||||||
|
other buffer |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
feed("<End>x")
|
||||||
|
screen:expect([[
|
||||||
|
% -helx^ |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
[Prompt] [+] |
|
||||||
|
other buffer |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
feed("<C-U>exit\n")
|
||||||
|
screen:expect([[
|
||||||
|
^other buffer |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
~ |
|
||||||
|
|
|
||||||
|
]])
|
||||||
|
end)
|
||||||
|
|
||||||
|
end)
|
||||||
Reference in New Issue
Block a user