mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
API: Implement buffer_{get,set}_slice
This commit is contained in:
parent
417a61f54f
commit
4dc34bc0e0
151
src/api/buffer.c
151
src/api/buffer.c
@ -1,3 +1,5 @@
|
||||
// Much of this code was adapted from 'if_py_both.h' from the original
|
||||
// vim source
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
@ -10,6 +12,7 @@
|
||||
#include "memory.h"
|
||||
#include "misc1.h"
|
||||
#include "misc2.h"
|
||||
#include "mark.h"
|
||||
#include "move.h"
|
||||
#include "../window.h"
|
||||
#include "undo.h"
|
||||
@ -136,20 +139,150 @@ void buffer_set_line(Buffer buffer, int64_t index, Object line, Error *err)
|
||||
}
|
||||
|
||||
StringArray buffer_get_slice(Buffer buffer,
|
||||
int64_t start,
|
||||
int64_t end,
|
||||
Error *err)
|
||||
int64_t start,
|
||||
int64_t end,
|
||||
bool include_start,
|
||||
bool include_end,
|
||||
Error *err)
|
||||
{
|
||||
abort();
|
||||
StringArray rv = {.size = 0};
|
||||
buf_T *buf = find_buffer(buffer, err);
|
||||
|
||||
if (!buf) {
|
||||
return rv;
|
||||
}
|
||||
|
||||
start = normalize_index(buf, start) + (include_start ? 0 : 1);
|
||||
end = normalize_index(buf, end) + (include_end ? 1 : 0);
|
||||
|
||||
if (start >= end) {
|
||||
// Return 0-length array
|
||||
return rv;
|
||||
}
|
||||
|
||||
rv.size = end - start;
|
||||
rv.items = xmalloc(sizeof(String) * rv.size);
|
||||
|
||||
for (uint32_t i = 0; i < rv.size; i++) {
|
||||
rv.items[i].data = xstrdup((char *)ml_get_buf(buf, start + i, FALSE));
|
||||
rv.items[i].size = strlen(rv.items[i].data);
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
void buffer_set_slice(Buffer buffer,
|
||||
int64_t start,
|
||||
int64_t end,
|
||||
StringArray lines,
|
||||
Error *err)
|
||||
int64_t start,
|
||||
int64_t end,
|
||||
bool include_start,
|
||||
bool include_end,
|
||||
StringArray replacement,
|
||||
Error *err)
|
||||
{
|
||||
abort();
|
||||
buf_T *buf = find_buffer(buffer, err);
|
||||
|
||||
if (!buf) {
|
||||
return;
|
||||
}
|
||||
|
||||
start = normalize_index(buf, start) + (include_start ? 0 : 1);
|
||||
end = normalize_index(buf, end) + (include_end ? 1 : 0);
|
||||
|
||||
if (start > end) {
|
||||
set_api_error("start > end", err);
|
||||
return;
|
||||
}
|
||||
|
||||
buf_T *save_curbuf = NULL;
|
||||
win_T *save_curwin = NULL;
|
||||
tabpage_T *save_curtab = NULL;
|
||||
uint32_t new_len = replacement.size;
|
||||
uint32_t old_len = end - start;
|
||||
uint32_t i;
|
||||
int32_t extra = 0; // lines added to text, can be negative
|
||||
char **lines;
|
||||
|
||||
if (new_len == 0) {
|
||||
// avoid allocating zero bytes
|
||||
lines = NULL;
|
||||
} else {
|
||||
lines = xcalloc(sizeof(char *), new_len);
|
||||
}
|
||||
|
||||
for (i = 0; i < new_len; i++) {
|
||||
String l = replacement.items[i];
|
||||
lines[i] = xstrndup(l.data, l.size);
|
||||
}
|
||||
|
||||
try_start();
|
||||
switch_to_win_for_buf(buf, &save_curwin, &save_curtab, &save_curbuf);
|
||||
|
||||
if (u_save(start - 1, end) == FAIL) {
|
||||
set_api_error("Cannot save undo information", err);
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
// If the size of the range is reducing (ie, new_len < old_len) we
|
||||
// need to delete some old_len. We do this at the start, by
|
||||
// repeatedly deleting line "start".
|
||||
for (i = 0; new_len < old_len && i < old_len - new_len; i++) {
|
||||
if (ml_delete(start, false) == FAIL) {
|
||||
set_api_error("Cannot delete line", err);
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
extra -= i;
|
||||
|
||||
// For as long as possible, replace the existing old_len with the
|
||||
// new old_len. This is a more efficient operation, as it requires
|
||||
// less memory allocation and freeing.
|
||||
for (i = 0; i < old_len && i < new_len; i++) {
|
||||
if (ml_replace(start + i, (char_u *)lines[i], false) == FAIL) {
|
||||
set_api_error("Cannot replace line", err);
|
||||
goto cleanup;
|
||||
}
|
||||
// Mark lines that haven't been passed to the buffer as they need
|
||||
// to be freed later
|
||||
lines[i] = NULL;
|
||||
}
|
||||
|
||||
// Now we may need to insert the remaining new old_len
|
||||
while (i < new_len) {
|
||||
if (ml_append(start + i - 1, (char_u *)lines[i], 0, false) == FAIL) {
|
||||
set_api_error("Cannot insert line", err);
|
||||
goto cleanup;
|
||||
}
|
||||
// Same as with replacing
|
||||
lines[i] = NULL;
|
||||
i++;
|
||||
extra++;
|
||||
}
|
||||
|
||||
// Adjust marks. Invalidate any which lie in the
|
||||
// changed range, and move any in the remainder of the buffer.
|
||||
// Only adjust marks if we managed to switch to a window that holds
|
||||
// the buffer, otherwise line numbers will be invalid.
|
||||
if (save_curbuf == NULL) {
|
||||
mark_adjust(start, end - 1, MAXLNUM, extra);
|
||||
}
|
||||
|
||||
changed_lines(start, 0, end, extra);
|
||||
|
||||
if (buf == curbuf) {
|
||||
fix_cursor(start, end, extra);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
for (uint32_t i = 0; i < new_len; i++) {
|
||||
if (lines[i] != NULL) {
|
||||
free(lines[i]);
|
||||
}
|
||||
}
|
||||
|
||||
free(lines);
|
||||
restore_win_for_buf(save_curwin, save_curtab, save_curbuf);
|
||||
try_end(err);
|
||||
}
|
||||
|
||||
Object buffer_get_var(Buffer buffer, String name, Error *err)
|
||||
|
@ -34,25 +34,34 @@ void buffer_set_line(Buffer buffer, int64_t index, Object line, Error *err);
|
||||
///
|
||||
/// @param buffer The buffer handle
|
||||
/// @param start The first line index
|
||||
/// @param end The last line index(exclusive)
|
||||
/// @param end The last line index
|
||||
/// @param include_start True if the slice includes the `start` parameter
|
||||
/// @param include_end True if the slice includes the `end` parameter
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return An array of lines
|
||||
StringArray buffer_get_slice(Buffer buffer,
|
||||
int64_t start,
|
||||
int64_t end,
|
||||
bool include_start,
|
||||
bool include_end,
|
||||
Error *err);
|
||||
|
||||
/// Replaces a line range on the buffer
|
||||
///
|
||||
/// @param buffer The buffer handle
|
||||
/// @param start The first line index
|
||||
/// @param end The last line index(exclusive)
|
||||
/// @param lines An array of lines to use as replacement
|
||||
/// @param end The last line index
|
||||
/// @param include_start True if the slice includes the `start` parameter
|
||||
/// @param include_end True if the slice includes the `end` parameter
|
||||
/// @param lines An array of lines to use as replacement(A 0-length array
|
||||
/// will simply delete the line range)
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
void buffer_set_slice(Buffer buffer,
|
||||
int64_t start,
|
||||
int64_t end,
|
||||
StringArray lines,
|
||||
bool include_start,
|
||||
bool include_end,
|
||||
StringArray replacement,
|
||||
Error *err);
|
||||
|
||||
/// Gets a buffer variable
|
||||
|
Loading…
Reference in New Issue
Block a user