feat(api): implement nvim_buf_get_text (#15181)

nvim_buf_get_text is the mirror of nvim_buf_set_text. It differs from
nvim_buf_get_lines in that it allows retrieving only portions of lines.

While this can typically be done easily enough by API clients,
implementing this function provides symmetry between the get/set
text/lines APIs, and also provides a nice convenience that saves API
clients the work of having to slice the result of nvim_buf_get_lines
themselves.
This commit is contained in:
Gregory Anders
2022-02-22 13:19:21 -07:00
committed by GitHub
parent 30c9c8815b
commit 11f7aeed7a
4 changed files with 207 additions and 10 deletions

View File

@@ -411,7 +411,6 @@ void set_option_to(uint64_t channel_id, void *to, int type, String name, Object
current_sctx = save_current_sctx;
}
buf_T *find_buffer_by_handle(Buffer buffer, Error *err)
{
if (buffer == 0) {
@@ -758,6 +757,52 @@ bool buf_collect_lines(buf_T *buf, size_t n, int64_t start, bool replace_nl, Arr
return true;
}
/// Returns a substring of a buffer line
///
/// @param buf Buffer handle
/// @param lnum Line number (1-based)
/// @param start_col Starting byte offset into line (0-based)
/// @param end_col Ending byte offset into line (0-based, exclusive)
/// @param replace_nl Replace newlines ('\n') with null ('\0')
/// @param err Error object
/// @return The text between start_col and end_col on line lnum of buffer buf
String buf_get_text(buf_T *buf, int64_t lnum, int64_t start_col, int64_t end_col, bool replace_nl,
Error *err)
{
String rv = STRING_INIT;
if (lnum >= MAXLNUM) {
api_set_error(err, kErrorTypeValidation, "Line index is too high");
return rv;
}
const char *bufstr = (char *)ml_get_buf(buf, (linenr_T)lnum, false);
size_t line_length = strlen(bufstr);
start_col = start_col < 0 ? (int64_t)line_length + start_col + 1 : start_col;
end_col = end_col < 0 ? (int64_t)line_length + end_col + 1 : end_col;
if (start_col >= MAXCOL || end_col >= MAXCOL) {
api_set_error(err, kErrorTypeValidation, "Column index is too high");
return rv;
}
if (start_col > end_col) {
api_set_error(err, kErrorTypeValidation, "start_col must be less than end_col");
return rv;
}
if ((size_t)start_col >= line_length) {
return rv;
}
rv = cstrn_to_string(&bufstr[start_col], (size_t)(end_col - start_col));
if (replace_nl) {
strchrsub(rv.data, '\n', '\0');
}
return rv;
}
void api_free_string(String value)
{