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 <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
||||||
@ -10,6 +12,7 @@
|
|||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "misc1.h"
|
#include "misc1.h"
|
||||||
#include "misc2.h"
|
#include "misc2.h"
|
||||||
|
#include "mark.h"
|
||||||
#include "move.h"
|
#include "move.h"
|
||||||
#include "../window.h"
|
#include "../window.h"
|
||||||
#include "undo.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,
|
StringArray buffer_get_slice(Buffer buffer,
|
||||||
int64_t start,
|
int64_t start,
|
||||||
int64_t end,
|
int64_t end,
|
||||||
Error *err)
|
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,
|
void buffer_set_slice(Buffer buffer,
|
||||||
int64_t start,
|
int64_t start,
|
||||||
int64_t end,
|
int64_t end,
|
||||||
StringArray lines,
|
bool include_start,
|
||||||
Error *err)
|
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)
|
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 buffer The buffer handle
|
||||||
/// @param start The first line index
|
/// @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
|
/// @param[out] err Details of an error that may have occurred
|
||||||
/// @return An array of lines
|
/// @return An array of lines
|
||||||
StringArray buffer_get_slice(Buffer buffer,
|
StringArray buffer_get_slice(Buffer buffer,
|
||||||
int64_t start,
|
int64_t start,
|
||||||
int64_t end,
|
int64_t end,
|
||||||
|
bool include_start,
|
||||||
|
bool include_end,
|
||||||
Error *err);
|
Error *err);
|
||||||
|
|
||||||
/// Replaces a line range on the buffer
|
/// Replaces a line range on the buffer
|
||||||
///
|
///
|
||||||
/// @param buffer The buffer handle
|
/// @param buffer The buffer handle
|
||||||
/// @param start The first line index
|
/// @param start The first line index
|
||||||
/// @param end The last line index(exclusive)
|
/// @param end The last line index
|
||||||
/// @param lines An array of lines to use as replacement
|
/// @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
|
/// @param[out] err Details of an error that may have occurred
|
||||||
void buffer_set_slice(Buffer buffer,
|
void buffer_set_slice(Buffer buffer,
|
||||||
int64_t start,
|
int64_t start,
|
||||||
int64_t end,
|
int64_t end,
|
||||||
StringArray lines,
|
bool include_start,
|
||||||
|
bool include_end,
|
||||||
|
StringArray replacement,
|
||||||
Error *err);
|
Error *err);
|
||||||
|
|
||||||
/// Gets a buffer variable
|
/// Gets a buffer variable
|
||||||
|
Loading…
Reference in New Issue
Block a user