mirror of
https://github.com/neovim/neovim.git
synced 2024-12-19 18:55:14 -07:00
Merge pull request #8660 from phodge/7688-nvim-buf-lines-should-return-empty-list-for-unloaded-buffer
handle unloaded buffers in nvim_buf_*() functions
This commit is contained in:
commit
2b9fc9a13f
@ -113,9 +113,9 @@ set(NVIM_VERSION_PATCH 2)
|
||||
set(NVIM_VERSION_PRERELEASE "-dev") # for package maintainers
|
||||
|
||||
# API level
|
||||
set(NVIM_API_LEVEL 4) # Bump this after any API change.
|
||||
set(NVIM_API_LEVEL 5) # Bump this after any API change.
|
||||
set(NVIM_API_LEVEL_COMPAT 0) # Adjust this after a _breaking_ API change.
|
||||
set(NVIM_API_PRERELEASE false)
|
||||
set(NVIM_API_PRERELEASE true)
|
||||
|
||||
file(TO_CMAKE_PATH ${CMAKE_CURRENT_LIST_DIR}/.git FORCED_GIT_DIR)
|
||||
include(GetGitRevisionDescription)
|
||||
|
@ -836,10 +836,26 @@ nvim_get_proc({pid}) *nvim_get_proc()*
|
||||
Return: ~
|
||||
Map of process properties, or NIL if process not found.
|
||||
|
||||
nvim__inspect_cell({row}, {col}) *nvim__inspect_cell()*
|
||||
TODO: Documentation
|
||||
|
||||
|
||||
==============================================================================
|
||||
Buffer Functions *api-buffer*
|
||||
|
||||
Unloaded Buffers:~
|
||||
|
||||
Buffers may be unloaded by the |:bunload| command or the
|
||||
buffer's |'bufhidden'| option. When a buffer is unloaded its
|
||||
file contents are freed from memory and vim cannot operate on
|
||||
the buffer lines until it is reloaded (usually by opening the
|
||||
buffer again in a new window). API methods such as
|
||||
|nvim_buf_get_lines()| and |nvim_buf_line_count()| will be
|
||||
affected.
|
||||
|
||||
You can use |nvim_buf_is_loaded()| or |nvim_buf_line_count()|
|
||||
to check whether a buffer is loaded.
|
||||
|
||||
nvim_buf_line_count({buffer}) *nvim_buf_line_count()*
|
||||
Gets the buffer line count
|
||||
|
||||
@ -847,7 +863,8 @@ nvim_buf_line_count({buffer}) *nvim_buf_line_count()*
|
||||
{buffer} Buffer handle
|
||||
|
||||
Return: ~
|
||||
Line count
|
||||
Line count, or `0` if the buffer has been unloaded (see
|
||||
|api-buffer|).
|
||||
|
||||
nvim_buf_attach({buffer}, {send_buffer}, {opts}) *nvim_buf_attach()*
|
||||
Activate updates from this buffer to the current channel.
|
||||
@ -896,7 +913,8 @@ nvim_buf_get_lines({buffer}, {start}, {end}, {strict_indexing})
|
||||
error.
|
||||
|
||||
Return: ~
|
||||
Array of lines
|
||||
Array of lines. If the buffer has been unloaded then an
|
||||
empty array will be returned instead. (See |api-buffer|.)
|
||||
|
||||
*nvim_buf_set_lines()*
|
||||
nvim_buf_set_lines({buffer}, {start}, {end}, {strict_indexing},
|
||||
@ -1013,14 +1031,28 @@ nvim_buf_set_name({buffer}, {name}) *nvim_buf_set_name()*
|
||||
{buffer} Buffer handle
|
||||
{name} Buffer name
|
||||
|
||||
nvim_buf_is_valid({buffer}) *nvim_buf_is_valid()*
|
||||
Checks if a buffer is valid
|
||||
nvim_buf_is_loaded({buffer}) *nvim_buf_is_loaded()*
|
||||
Checks if a buffer is valid and loaded. See |api-buffer| for
|
||||
more info about unloaded buffers.
|
||||
|
||||
Parameters: ~
|
||||
{buffer} Buffer handle
|
||||
|
||||
Return: ~
|
||||
true if the buffer is valid, false otherwise
|
||||
true if the buffer is valid and loaded, false otherwise.
|
||||
|
||||
nvim_buf_is_valid({buffer}) *nvim_buf_is_valid()*
|
||||
Checks if a buffer is valid.
|
||||
|
||||
Note:
|
||||
Even if a buffer is valid it may have been unloaded. See
|
||||
|api-buffer| for more info about unloaded buffers.
|
||||
|
||||
Parameters: ~
|
||||
{buffer} Buffer handle
|
||||
|
||||
Return: ~
|
||||
true if the buffer is valid, false otherwise.
|
||||
|
||||
nvim_buf_get_mark({buffer}, {name}) *nvim_buf_get_mark()*
|
||||
Return a tuple (row,col) representing the position of the
|
||||
|
@ -413,10 +413,26 @@ def gen_docs(config):
|
||||
sys.exit(p.returncode)
|
||||
|
||||
sections = {}
|
||||
intros = {}
|
||||
sep = '=' * text_width
|
||||
|
||||
base = os.path.join(out_dir, 'xml')
|
||||
dom = minidom.parse(os.path.join(base, 'index.xml'))
|
||||
|
||||
# generate docs for section intros
|
||||
for compound in dom.getElementsByTagName('compound'):
|
||||
if compound.getAttribute('kind') != 'group':
|
||||
continue
|
||||
|
||||
groupname = get_text(find_first(compound, 'name'))
|
||||
groupxml = os.path.join(base, '%s.xml' % compound.getAttribute('refid'))
|
||||
|
||||
desc = find_first(minidom.parse(groupxml), 'detaileddescription')
|
||||
if desc:
|
||||
doc = parse_parblock(desc)
|
||||
if doc:
|
||||
intros[groupname] = doc
|
||||
|
||||
for compound in dom.getElementsByTagName('compound'):
|
||||
if compound.getAttribute('kind') != 'file':
|
||||
continue
|
||||
@ -437,6 +453,11 @@ def gen_docs(config):
|
||||
name = name.title()
|
||||
|
||||
doc = ''
|
||||
|
||||
intro = intros.get('api-%s' % name.lower())
|
||||
if intro:
|
||||
doc += '\n\n' + intro
|
||||
|
||||
if functions:
|
||||
doc += '\n\n' + functions
|
||||
|
||||
|
@ -31,11 +31,27 @@
|
||||
# include "api/buffer.c.generated.h"
|
||||
#endif
|
||||
|
||||
|
||||
/// \defgroup api-buffer
|
||||
///
|
||||
/// Unloaded Buffers:~
|
||||
///
|
||||
/// Buffers may be unloaded by the |:bunload| command or the buffer's
|
||||
/// |'bufhidden'| option. When a buffer is unloaded its file contents are freed
|
||||
/// from memory and vim cannot operate on the buffer lines until it is reloaded
|
||||
/// (usually by opening the buffer again in a new window). API methods such as
|
||||
/// |nvim_buf_get_lines()| and |nvim_buf_line_count()| will be affected.
|
||||
///
|
||||
/// You can use |nvim_buf_is_loaded()| or |nvim_buf_line_count()| to check
|
||||
/// whether a buffer is loaded.
|
||||
|
||||
|
||||
/// Gets the buffer line count
|
||||
///
|
||||
/// @param buffer Buffer handle
|
||||
/// @param[out] err Error details, if any
|
||||
/// @return Line count
|
||||
/// @return Line count, or \`0` if the buffer has been unloaded (see
|
||||
/// |api-buffer|).
|
||||
Integer nvim_buf_line_count(Buffer buffer, Error *err)
|
||||
FUNC_API_SINCE(1)
|
||||
{
|
||||
@ -45,6 +61,11 @@ Integer nvim_buf_line_count(Buffer buffer, Error *err)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// return sentinel value if the buffer isn't loaded
|
||||
if (buf->b_ml.ml_mfp == NULL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return buf->b_ml.ml_line_count;
|
||||
}
|
||||
|
||||
@ -205,7 +226,8 @@ ArrayOf(String) buffer_get_line_slice(Buffer buffer,
|
||||
/// @param end Last line index (exclusive)
|
||||
/// @param strict_indexing Whether out-of-bounds should be an error.
|
||||
/// @param[out] err Error details, if any
|
||||
/// @return Array of lines
|
||||
/// @return Array of lines. If the buffer has been unloaded then an empty array
|
||||
/// will be returned instead. (See |api-buffer|.)
|
||||
ArrayOf(String) nvim_buf_get_lines(uint64_t channel_id,
|
||||
Buffer buffer,
|
||||
Integer start,
|
||||
@ -221,6 +243,11 @@ ArrayOf(String) nvim_buf_get_lines(uint64_t channel_id,
|
||||
return rv;
|
||||
}
|
||||
|
||||
// return sentinel value if the buffer isn't loaded
|
||||
if (buf->b_ml.ml_mfp == NULL) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
bool oob = false;
|
||||
start = normalize_index(buf, start, &oob);
|
||||
end = normalize_index(buf, end, &oob);
|
||||
@ -745,10 +772,27 @@ void nvim_buf_set_name(Buffer buffer, String name, Error *err)
|
||||
}
|
||||
}
|
||||
|
||||
/// Checks if a buffer is valid
|
||||
/// Checks if a buffer is valid and loaded. See |api-buffer| for more info
|
||||
/// about unloaded buffers.
|
||||
///
|
||||
/// @param buffer Buffer handle
|
||||
/// @return true if the buffer is valid, false otherwise
|
||||
/// @return true if the buffer is valid and loaded, false otherwise.
|
||||
Boolean nvim_buf_is_loaded(Buffer buffer)
|
||||
FUNC_API_SINCE(5)
|
||||
{
|
||||
Error stub = ERROR_INIT;
|
||||
buf_T *buf = find_buffer_by_handle(buffer, &stub);
|
||||
api_clear_error(&stub);
|
||||
return buf && buf->b_ml.ml_mfp != NULL;
|
||||
}
|
||||
|
||||
/// Checks if a buffer is valid.
|
||||
///
|
||||
/// @note Even if a buffer is valid it may have been unloaded. See |api-buffer|
|
||||
/// for more info about unloaded buffers.
|
||||
///
|
||||
/// @param buffer Buffer handle
|
||||
/// @return true if the buffer is valid, false otherwise.
|
||||
Boolean nvim_buf_is_valid(Buffer buffer)
|
||||
FUNC_API_SINCE(1)
|
||||
{
|
||||
|
@ -35,8 +35,37 @@ describe('api/buf', function()
|
||||
-- There's always at least one line
|
||||
eq(1, curbuf_depr('line_count'))
|
||||
end)
|
||||
end)
|
||||
|
||||
it('line_count has defined behaviour for unloaded buffers', function()
|
||||
-- we'll need to know our bufnr for when it gets unloaded
|
||||
local bufnr = curbuf('get_number')
|
||||
-- replace the buffer contents with these three lines
|
||||
request('nvim_buf_set_lines', bufnr, 0, -1, 1, {"line1", "line2", "line3", "line4"})
|
||||
-- check the line count is correct
|
||||
eq(4, request('nvim_buf_line_count', bufnr))
|
||||
-- force unload the buffer (this will discard changes)
|
||||
command('new')
|
||||
command('bunload! '..bufnr)
|
||||
-- line count for an unloaded buffer should always be 0
|
||||
eq(0, request('nvim_buf_line_count', bufnr))
|
||||
end)
|
||||
|
||||
it('get_lines has defined behaviour for unloaded buffers', function()
|
||||
-- we'll need to know our bufnr for when it gets unloaded
|
||||
local bufnr = curbuf('get_number')
|
||||
-- replace the buffer contents with these three lines
|
||||
buffer('set_lines', bufnr, 0, -1, 1, {"line1", "line2", "line3", "line4"})
|
||||
-- confirm that getting lines works
|
||||
eq({"line2", "line3"}, buffer('get_lines', bufnr, 1, 3, 1))
|
||||
-- force unload the buffer (this will discard changes)
|
||||
command('new')
|
||||
command('bunload! '..bufnr)
|
||||
-- attempting to get lines now always gives empty list
|
||||
eq({}, buffer('get_lines', bufnr, 1, 3, 1))
|
||||
-- it's impossible to get out-of-bounds errors for an unloaded buffer
|
||||
eq({}, buffer('get_lines', bufnr, 8888, 9999, 1))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('{get,set,del}_line', function()
|
||||
it('works', function()
|
||||
@ -70,7 +99,6 @@ describe('api/buf', function()
|
||||
end)
|
||||
end)
|
||||
|
||||
|
||||
describe('{get,set}_line_slice', function()
|
||||
it('get_line_slice: out-of-bounds returns empty array', function()
|
||||
curbuf_depr('set_line_slice', 0, 0, true, true, {'a', 'b', 'c'})
|
||||
@ -345,6 +373,31 @@ describe('api/buf', function()
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('is_loaded', function()
|
||||
it('works', function()
|
||||
-- record our buffer number for when we unload it
|
||||
local bufnr = curbuf('get_number')
|
||||
-- api should report that the buffer is loaded
|
||||
ok(buffer('is_loaded', bufnr))
|
||||
-- hide the current buffer by switching to a new empty buffer
|
||||
-- Careful! we need to modify the buffer first or vim will just reuse it
|
||||
buffer('set_lines', bufnr, 0, -1, 1, {'line1'})
|
||||
command('hide enew')
|
||||
-- confirm the buffer is hidden, but still loaded
|
||||
local infolist = nvim('eval', 'getbufinfo('..bufnr..')')
|
||||
eq(1, #infolist)
|
||||
eq(1, infolist[1].hidden)
|
||||
eq(1, infolist[1].loaded)
|
||||
-- now force unload the buffer
|
||||
command('bunload! '..bufnr)
|
||||
-- confirm the buffer is unloaded
|
||||
infolist = nvim('eval', 'getbufinfo('..bufnr..')')
|
||||
eq(0, infolist[1].loaded)
|
||||
-- nvim_buf_is_loaded() should also report the buffer as unloaded
|
||||
eq(false, buffer('is_loaded', bufnr))
|
||||
end)
|
||||
end)
|
||||
|
||||
describe('is_valid', function()
|
||||
it('works', function()
|
||||
nvim('command', 'new')
|
||||
|
Loading…
Reference in New Issue
Block a user