mirror of
https://github.com/neovim/neovim.git
synced 2026-03-28 03:12:00 +00:00
fix(prompt): don't implicitly set 'modified' #38118
Problem:
In aec3d7915c Vim changed prompt-buffers
to respect 'modified' so the termdebug plugin can "control closing the
window". But for most use-cases (REPL, shell, AI "chat", …),
prompt-buffers are in practice always "modified", and no way to "save"
them, so *implicitly* setting 'modified' is noisy and annoying.
Solution:
Don't implicitly set 'modified' when a prompt-buffer is updated.
Plugins/users can still explicitly set 'modified', which will then
trigger the "E37: No write since last change" warning.
This commit is contained in:
@@ -186,6 +186,11 @@ normally only do that in a newly created buffer: >vim
|
||||
|
||||
:set buftype=prompt
|
||||
|
||||
Prompt buffers ignore modified checks for changes made to the buffer, so
|
||||
interactive input does not make them hard to close. But if a plugin or user
|
||||
explicitly sets 'modified', a modified prompt buffer can't be closed without
|
||||
saving.
|
||||
|
||||
The user can edit and input text at the end of the buffer. Pressing Enter in
|
||||
the input section invokes the |prompt_setcallback()| callback, which is
|
||||
typically expected to process the prompt and show results by appending to the
|
||||
|
||||
@@ -4468,8 +4468,11 @@ A jump table for the options with a short description can be found at |Q_op|.
|
||||
result of a BufNewFile, BufRead/BufReadPost, BufWritePost,
|
||||
FileAppendPost or VimLeave autocommand event. See |gzip-example| for
|
||||
an explanation.
|
||||
When 'buftype' is "nowrite" or "nofile" this option may be set, but
|
||||
will be ignored.
|
||||
When 'buftype' is "nowrite" or "nofile", this option may be set, but
|
||||
it is ignored and will not block closing the window. For "prompt"
|
||||
buffers, changes made to the buffer do not make it count as modified,
|
||||
but an explicit ":set modified" is respected and will block closing the
|
||||
window.
|
||||
Note that the text may actually be the same, e.g. 'modified' is set
|
||||
when using "rA" on an "A".
|
||||
|
||||
|
||||
7
runtime/lua/vim/_meta/options.lua
generated
7
runtime/lua/vim/_meta/options.lua
generated
@@ -4565,8 +4565,11 @@ vim.bo.ma = vim.bo.modifiable
|
||||
--- result of a BufNewFile, BufRead/BufReadPost, BufWritePost,
|
||||
--- FileAppendPost or VimLeave autocommand event. See `gzip-example` for
|
||||
--- an explanation.
|
||||
--- When 'buftype' is "nowrite" or "nofile" this option may be set, but
|
||||
--- will be ignored.
|
||||
--- When 'buftype' is "nowrite" or "nofile", this option may be set, but
|
||||
--- it is ignored and will not block closing the window. For "prompt"
|
||||
--- buffers, changes made to the buffer do not make it count as modified,
|
||||
--- but an explicit ":set modified" is respected and will block closing the
|
||||
--- window.
|
||||
--- Note that the text may actually be the same, e.g. 'modified' is set
|
||||
--- when using "rA" on an "A".
|
||||
---
|
||||
|
||||
@@ -5935,8 +5935,11 @@ local options = {
|
||||
result of a BufNewFile, BufRead/BufReadPost, BufWritePost,
|
||||
FileAppendPost or VimLeave autocommand event. See |gzip-example| for
|
||||
an explanation.
|
||||
When 'buftype' is "nowrite" or "nofile" this option may be set, but
|
||||
will be ignored.
|
||||
When 'buftype' is "nowrite" or "nofile", this option may be set, but
|
||||
it is ignored and will not block closing the window. For "prompt"
|
||||
buffers, changes made to the buffer do not make it count as modified,
|
||||
but an explicit ":set modified" is respected and will block closing the
|
||||
window.
|
||||
Note that the text may actually be the same, e.g. 'modified' is set
|
||||
when using "rA" on an "A".
|
||||
]=],
|
||||
|
||||
@@ -3090,6 +3090,8 @@ static char *u_save_line_buf(buf_T *buf, linenr_T lnum)
|
||||
/// Check if the 'modified' flag is set, or 'ff' has changed (only need to
|
||||
/// check the first character, because it can only be "dos", "unix" or "mac").
|
||||
/// "nofile" and "scratch" type buffers are considered to always be unchanged.
|
||||
/// Prompt buffers ignore implicit modifications by default, but an explicit
|
||||
/// ":set modified" still makes them count as changed.
|
||||
///
|
||||
/// @param buf The buffer to check
|
||||
///
|
||||
@@ -3097,10 +3099,10 @@ static char *u_save_line_buf(buf_T *buf, linenr_T lnum)
|
||||
bool bufIsChanged(buf_T *buf)
|
||||
FUNC_ATTR_NONNULL_ALL FUNC_ATTR_WARN_UNUSED_RESULT
|
||||
{
|
||||
// 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));
|
||||
// In a "prompt" buffer we respect 'modified' if the user or a plugin explicitly set it.
|
||||
return bt_prompt(buf)
|
||||
? buf->b_modified_was_set
|
||||
: (!bt_dontwrite(buf) && (buf->b_changed || file_ff_differs(buf, true)));
|
||||
}
|
||||
|
||||
// Return true if any buffer has changes. Also buffers that are not written.
|
||||
|
||||
@@ -27,15 +27,11 @@ describe('prompt buffer', function()
|
||||
source([[
|
||||
func TextEntered(text)
|
||||
if a:text == "exit"
|
||||
" Reset &modified to allow the buffer to be closed.
|
||||
set nomodified
|
||||
stopinsert
|
||||
close
|
||||
else
|
||||
" Add the output above the current prompt.
|
||||
call append(line("$") - 1, split('Command: "' . a:text . '"', '\n'))
|
||||
" Reset &modified to allow the buffer to be closed.
|
||||
set nomodified
|
||||
call timer_start(20, {id -> TimerFunc(a:text)})
|
||||
endif
|
||||
endfunc
|
||||
@@ -43,8 +39,6 @@ describe('prompt buffer', function()
|
||||
func TimerFunc(text)
|
||||
" Add the output above the current prompt.
|
||||
call append(line("$") - 1, split('Result: "' . a:text .'"', '\n'))
|
||||
" Reset &modified to allow the buffer to be closed.
|
||||
set nomodified
|
||||
endfunc
|
||||
|
||||
func SwitchWindows()
|
||||
@@ -62,7 +56,7 @@ describe('prompt buffer', function()
|
||||
screen:expect([[
|
||||
cmd: ^ |
|
||||
{1:~ }|*3
|
||||
{3:[Prompt] [+] }|
|
||||
{3:[Prompt] }|
|
||||
other buffer |
|
||||
{1:~ }|*3
|
||||
{5:-- INSERT --} |
|
||||
@@ -89,6 +83,21 @@ describe('prompt buffer', function()
|
||||
{1:~ }|*8
|
||||
|
|
||||
]])
|
||||
|
||||
command('new')
|
||||
command('set buftype=prompt')
|
||||
feed('iabc<BS><BS>')
|
||||
eq('a', fn('prompt_getinput', fn('bufnr')))
|
||||
command('quit')
|
||||
eq(1, #api.nvim_list_wins())
|
||||
|
||||
command('new')
|
||||
command('set buftype=prompt modified')
|
||||
eq(
|
||||
'Vim(quit):E37: No write since last change (add ! to override)',
|
||||
t.pcall_err(command, 'quit')
|
||||
)
|
||||
eq(2, #api.nvim_list_wins())
|
||||
end)
|
||||
|
||||
-- oldtest: Test_prompt_editing()
|
||||
@@ -98,7 +107,7 @@ describe('prompt buffer', function()
|
||||
screen:expect([[
|
||||
cmd: hel^ |
|
||||
{1:~ }|*3
|
||||
{3:[Prompt] [+] }|
|
||||
{3:[Prompt] }|
|
||||
other buffer |
|
||||
{1:~ }|*3
|
||||
{5:-- INSERT --} |
|
||||
@@ -107,7 +116,7 @@ describe('prompt buffer', function()
|
||||
screen:expect([[
|
||||
cmd: -^hel |
|
||||
{1:~ }|*3
|
||||
{3:[Prompt] [+] }|
|
||||
{3:[Prompt] }|
|
||||
other buffer |
|
||||
{1:~ }|*3
|
||||
{5:-- INSERT --} |
|
||||
@@ -116,7 +125,7 @@ describe('prompt buffer', function()
|
||||
screen:expect([[
|
||||
cmd: -hz^el |
|
||||
{1:~ }|*3
|
||||
{3:[Prompt] [+] }|
|
||||
{3:[Prompt] }|
|
||||
other buffer |
|
||||
{1:~ }|*3
|
||||
{5:-- INSERT --} |
|
||||
@@ -125,7 +134,7 @@ describe('prompt buffer', function()
|
||||
screen:expect([[
|
||||
cmd: -hzelx^ |
|
||||
{1:~ }|*3
|
||||
{3:[Prompt] [+] }|
|
||||
{3:[Prompt] }|
|
||||
other buffer |
|
||||
{1:~ }|*3
|
||||
{5:-- INSERT --} |
|
||||
@@ -149,7 +158,7 @@ describe('prompt buffer', function()
|
||||
screen:expect([[
|
||||
cmd: |
|
||||
{1:~ }|*3
|
||||
{2:[Prompt] [+] }|
|
||||
{2:[Prompt] }|
|
||||
^other buffer |
|
||||
{1:~ }|*3
|
||||
|
|
||||
@@ -158,7 +167,7 @@ describe('prompt buffer', function()
|
||||
screen:expect([[
|
||||
cmd: ^ |
|
||||
{1:~ }|*3
|
||||
{3:[Prompt] [+] }|
|
||||
{3:[Prompt] }|
|
||||
other buffer |
|
||||
{1:~ }|*3
|
||||
{5:-- INSERT --} |
|
||||
@@ -167,7 +176,7 @@ describe('prompt buffer', function()
|
||||
screen:expect([[
|
||||
cmd:^ |
|
||||
{1:~ }|*3
|
||||
{3:[Prompt] [+] }|
|
||||
{3:[Prompt] }|
|
||||
other buffer |
|
||||
{1:~ }|*3
|
||||
|
|
||||
@@ -281,7 +290,7 @@ describe('prompt buffer', function()
|
||||
line 2 |
|
||||
line 3^ |
|
||||
{1:~ }|
|
||||
{3:[Prompt] [+] }|
|
||||
{3:[Prompt] }|
|
||||
other buffer |
|
||||
{1:~ }|*3
|
||||
{5:-- INSERT --} |
|
||||
@@ -403,7 +412,7 @@ describe('prompt buffer', function()
|
||||
line 2 |
|
||||
line 3 |
|
||||
{1:~ }|
|
||||
{3:[Prompt] [+] }|
|
||||
{3:[Prompt] }|
|
||||
other buffer |
|
||||
{1:~ }|*3
|
||||
|
|
||||
@@ -433,7 +442,7 @@ describe('prompt buffer', function()
|
||||
line 2 |
|
||||
line 3^ |
|
||||
{1:~ }|
|
||||
{3:[Prompt] [+] }|
|
||||
{3:[Prompt] }|
|
||||
other buffer |
|
||||
{1:~ }|*3
|
||||
{5:-- INSERT --} |
|
||||
@@ -450,7 +459,7 @@ describe('prompt buffer', function()
|
||||
screen:expect([[
|
||||
cmd: tests-middle^-initial|
|
||||
{1:~ }|*3
|
||||
{3:[Prompt] [+] }|
|
||||
{3:[Prompt] }|
|
||||
other buffer |
|
||||
{1:~ }|*3
|
||||
|
|
||||
@@ -460,7 +469,7 @@ describe('prompt buffer', function()
|
||||
screen:expect([[
|
||||
cmd: tests-mid^le-initial |
|
||||
{1:~ }|*3
|
||||
{3:[Prompt] [+] }|
|
||||
{3:[Prompt] }|
|
||||
other buffer |
|
||||
{1:~ }|*3
|
||||
|
|
||||
@@ -471,7 +480,7 @@ describe('prompt buffer', function()
|
||||
screen:expect([[
|
||||
cmd: tests-mid^dle-initial|
|
||||
{1:~ }|*3
|
||||
{3:[Prompt] [+] }|
|
||||
{3:[Prompt] }|
|
||||
other buffer |
|
||||
{1:~ }|*3
|
||||
1 change; {MATCH:.*} |
|
||||
@@ -484,7 +493,7 @@ describe('prompt buffer', function()
|
||||
screen:expect([[
|
||||
cmd: tests-^initial |
|
||||
{1:~ }|*3
|
||||
{3:[Prompt] [+] }|
|
||||
{3:[Prompt] }|
|
||||
other buffer |
|
||||
{1:~ }|*3
|
||||
1 change; {MATCH:.*} |
|
||||
@@ -509,7 +518,7 @@ describe('prompt buffer', function()
|
||||
Command: "tests-initial" |
|
||||
cmd:^ |
|
||||
{1:~ }|
|
||||
{3:[Prompt] [+] }|
|
||||
{3:[Prompt] }|
|
||||
other buffer |
|
||||
{1:~ }|*3
|
||||
1 line {MATCH:.*} |
|
||||
@@ -522,7 +531,7 @@ describe('prompt buffer', function()
|
||||
Command: "tests-initial" |
|
||||
cmd: ^ |
|
||||
{1:~ }|
|
||||
{3:[Prompt] [+] }|
|
||||
{3:[Prompt] }|
|
||||
other buffer |
|
||||
{1:~ }|*3
|
||||
{5:-- INSERT --} |
|
||||
@@ -533,7 +542,7 @@ describe('prompt buffer', function()
|
||||
Command: "tests-initial" |
|
||||
^cmd: hello |
|
||||
{1:~ }|
|
||||
{3:[Prompt] [+] }|
|
||||
{3:[Prompt] }|
|
||||
other buffer |
|
||||
{1:~ }|*3
|
||||
1 change; {MATCH:.*} |
|
||||
@@ -548,7 +557,7 @@ describe('prompt buffer', function()
|
||||
Command: "tests-initial" |
|
||||
c^md > hello |
|
||||
{1:~ }|
|
||||
{3:[Prompt] [+] }|
|
||||
{3:[Prompt] }|
|
||||
other buffer |
|
||||
{1:~ }|*3
|
||||
Already at oldest change |
|
||||
@@ -563,7 +572,7 @@ describe('prompt buffer', function()
|
||||
Command: "tests-initial" |
|
||||
cmd > hello there |
|
||||
cmd >^ |
|
||||
{3:[Prompt] [+] }|
|
||||
{3:[Prompt] }|
|
||||
other buffer |
|
||||
{1:~ }|*3
|
||||
Already at oldest change |
|
||||
@@ -580,7 +589,7 @@ describe('prompt buffer', function()
|
||||
line 2 |
|
||||
line 3^ |
|
||||
{1:~ }|
|
||||
{3:[Prompt] [+] }|
|
||||
{3:[Prompt] }|
|
||||
other buffer |
|
||||
{1:~ }|*3
|
||||
{5:-- INSERT --} |
|
||||
@@ -592,7 +601,7 @@ describe('prompt buffer', function()
|
||||
line 2 |
|
||||
after^ |
|
||||
line 3 |
|
||||
{3:[Prompt] [+] }|
|
||||
{3:[Prompt] }|
|
||||
other buffer |
|
||||
{1:~ }|*3
|
||||
{5:-- INSERT --} |
|
||||
@@ -608,7 +617,7 @@ describe('prompt buffer', function()
|
||||
before^ |
|
||||
line 2 |
|
||||
after |
|
||||
{3:[Prompt] [+] }|
|
||||
{3:[Prompt] }|
|
||||
other buffer |
|
||||
{1:~ }|*3
|
||||
{5:-- INSERT --} |
|
||||
@@ -618,6 +627,8 @@ describe('prompt buffer', function()
|
||||
eq('line 1\nbefore\nline 2\nafter\nline 3', fn('prompt_getinput', buf))
|
||||
|
||||
feed('<cr>')
|
||||
vim.uv.sleep(20)
|
||||
eq('', fn('prompt_getinput', buf))
|
||||
screen:expect([[
|
||||
line 2 |
|
||||
after |
|
||||
@@ -630,6 +641,16 @@ describe('prompt buffer', function()
|
||||
]])
|
||||
|
||||
feed('line 4<s-cr>line 5')
|
||||
screen:expect([[
|
||||
after |
|
||||
line 3" |
|
||||
cmd: line 4 |
|
||||
line 5^ |
|
||||
{3:[Prompt] }|
|
||||
other buffer |
|
||||
{1:~ }|*3
|
||||
{5:-- INSERT --} |
|
||||
]])
|
||||
|
||||
feed('<esc>k0oafter prompt')
|
||||
screen:expect([[
|
||||
@@ -637,7 +658,7 @@ describe('prompt buffer', function()
|
||||
line 3" |
|
||||
cmd: line 4 |
|
||||
after prompt^ |
|
||||
{3:[Prompt] [+] }|
|
||||
{3:[Prompt] }|
|
||||
other buffer |
|
||||
{1:~ }|*3
|
||||
{5:-- INSERT --} |
|
||||
@@ -649,13 +670,15 @@ describe('prompt buffer', function()
|
||||
line 3" |
|
||||
cmd: at prompt^ |
|
||||
line 4 |
|
||||
{3:[Prompt] [+] }|
|
||||
{3:[Prompt] }|
|
||||
other buffer |
|
||||
{1:~ }|*3
|
||||
{5:-- INSERT --} |
|
||||
]])
|
||||
|
||||
feed('<cr>')
|
||||
vim.uv.sleep(20)
|
||||
eq('', fn('prompt_getinput', buf))
|
||||
screen:expect([[
|
||||
line 4 |
|
||||
after prompt |
|
||||
@@ -674,7 +697,7 @@ describe('prompt buffer', function()
|
||||
screen:expect([[
|
||||
cmd: asdf^ |
|
||||
{1:~ }|*3
|
||||
{3:[Prompt] [+] }|
|
||||
{3:[Prompt] }|
|
||||
other buffer |
|
||||
{1:~ }|*3
|
||||
{5:-- INSERT --} |
|
||||
@@ -684,7 +707,7 @@ describe('prompt buffer', function()
|
||||
screen:expect([[
|
||||
cmd: ^ |
|
||||
{1:~ }|*3
|
||||
{3:[Prompt] [+] }|
|
||||
{3:[Prompt] }|
|
||||
other buffer |
|
||||
{1:~ }|*3
|
||||
{5:-- INSERT --} |
|
||||
@@ -694,7 +717,7 @@ describe('prompt buffer', function()
|
||||
screen:expect([[
|
||||
cmd: asdf^ |
|
||||
{1:~ }|*3
|
||||
{3:[Prompt] [+] }|
|
||||
{3:[Prompt] }|
|
||||
other buffer |
|
||||
{1:~ }|*3
|
||||
{5:-- INSERT --} |
|
||||
@@ -704,7 +727,7 @@ describe('prompt buffer', function()
|
||||
screen:expect([[
|
||||
cmd: ^ |
|
||||
{1:~ }|*3
|
||||
{3:[Prompt] [+] }|
|
||||
{3:[Prompt] }|
|
||||
other buffer |
|
||||
{1:~ }|*3
|
||||
{5:-- INSERT --} |
|
||||
@@ -1021,7 +1044,7 @@ describe('prompt buffer', function()
|
||||
ooooooooooooooooooooong >|
|
||||
^ |
|
||||
{1:~ }|
|
||||
{3:[Prompt] [+] }|
|
||||
{3:[Prompt] }|
|
||||
foo > hello |
|
||||
{1:~ }|*3
|
||||
{5:-- INSERT --} |
|
||||
|
||||
Reference in New Issue
Block a user