API: Implement buffer_{get,set}_line

This commit is contained in:
Thiago de Arruda 2014-05-08 16:22:08 -03:00
parent 7b04674174
commit 9f25a4153c
3 changed files with 207 additions and 14 deletions

View File

@ -2,7 +2,40 @@
#include <stdlib.h>
#include "api/buffer.h"
#include "api/helpers.h"
#include "api/defs.h"
#include "../vim.h"
#include "../buffer.h"
#include "memline.h"
#include "memory.h"
#include "misc1.h"
#include "misc2.h"
#include "move.h"
#include "../window.h"
#include "undo.h"
static buf_T *find_buffer(Buffer buffer, Error *err);
// Find a window that contains "buf" and switch to it.
// If there is no such window, use the current window and change "curbuf".
// Caller must initialize save_curbuf to NULL.
// restore_win_for_buf() MUST be called later!
static void switch_to_win_for_buf(buf_T *buf,
win_T **save_curwinp,
tabpage_T **save_curtabp,
buf_T **save_curbufp);
static void restore_win_for_buf(win_T *save_curwin,
tabpage_T *save_curtab,
buf_T *save_curbuf);
// Check if deleting lines made the cursor position invalid.
// Changed the lines from "lo" to "hi" and added "extra" lines (negative if
// deleted).
static void fix_cursor(linenr_T lo, linenr_T hi, linenr_T extra);
// Normalizes 0-based indexes to buffer line numbers
static int64_t normalize_index(buf_T *buf, int64_t index);
int64_t buffer_get_length(Buffer buffer, Error *err)
{
@ -11,27 +44,116 @@ int64_t buffer_get_length(Buffer buffer, Error *err)
String buffer_get_line(Buffer buffer, int64_t index, Error *err)
{
abort();
String rv;
buf_T *buf = find_buffer(buffer, err);
if (!buf) {
return rv;
}
index = normalize_index(buf, index);
char *line = (char *)ml_get_buf(buf, index, false);
rv.size = strlen(line);
rv.data = xmalloc(rv.size);
memcpy(rv.data, line, rv.size);
return rv;
}
void buffer_set_line(Buffer buffer, int64_t index, String line, Error *err)
void buffer_set_line(Buffer buffer, int64_t index, Object line, Error *err)
{
abort();
buf_T *buf = find_buffer(buffer, err);
if (!buf) {
return;
}
if (line.type != kObjectTypeNil && line.type != kObjectTypeString) {
char msg[] = "Invalid line";
strncpy(err->msg, msg, sizeof(err->msg));
err->set = true;
return;
}
index = normalize_index(buf, index);
buf_T *save_curbuf = NULL;
win_T *save_curwin = NULL;
tabpage_T *save_curtab = NULL;
try_start();
switch_to_win_for_buf(buf, &save_curwin, &save_curtab, &save_curbuf);
if (line.type == kObjectTypeNil) {
// Delete the line
if (u_savedel(index, 1L) == FAIL) {
// Failed to save undo
char msg[] = "Cannot save undo information";
strncpy(err->msg, msg, sizeof(err->msg));
err->set = true;
} else if (ml_delete(index, FALSE) == FAIL) {
// Failed to delete
char msg[] = "Cannot delete the line";
strncpy(err->msg, msg, sizeof(err->msg));
err->set = true;
} else {
restore_win_for_buf(save_curwin, save_curtab, save_curbuf);
// Success
if (buf == curbuf) {
// fix the cursor if it's the current buffer
fix_cursor(index, index + 1, -1);
}
if (save_curbuf == NULL) {
// Only adjust marks if we managed to switch to a window that
// holds the buffer, otherwise line numbers will be invalid.
deleted_lines_mark(index, 1L);
}
}
} else if (line.type == kObjectTypeString) {
// Replace line
char *string = xmalloc(line.data.string.size + 1);
memcpy(string, line.data.string.data, line.data.string.size);
string[line.data.string.size] = NUL;
if (u_savesub(index) == FAIL) {
// Failed to save undo
char msg[] = "Cannot save undo information";
strncpy(err->msg, msg, sizeof(err->msg));
err->set = true;
} else if (ml_replace(index, (char_u *)string, FALSE) == FAIL) {
// Failed to replace
char msg[] = "Cannot replace line";
strncpy(err->msg, msg, sizeof(err->msg));
err->set = true;
free(string);
} else {
// Success
changed_bytes(index, 0);
restore_win_for_buf(save_curwin, save_curtab, save_curbuf);
// Check that the cursor is not beyond the end of the line now.
if (buf == curbuf) {
check_cursor_col();
}
}
}
try_end(err);
}
StringArray buffer_get_slice(Buffer buffer,
int64_t start,
int64_t end,
Error *err)
int64_t start,
int64_t end,
Error *err)
{
abort();
}
void buffer_set_slice(Buffer buffer,
int64_t start,
int64_t end,
StringArray lines,
Error *err)
int64_t start,
int64_t end,
StringArray lines,
Error *err)
{
abort();
}
@ -85,3 +207,71 @@ Position buffer_mark(Buffer buffer, String name, Error *err)
{
abort();
}
static buf_T *find_buffer(Buffer buffer, Error *err)
{
buf_T *buf = buflist_findnr(buffer);
if (buf == NULL) {
char msg[] = "Invalid buffer id";
strncpy(err->msg, msg, sizeof(err->msg));
err->set = true;
}
return buf;
}
static void switch_to_win_for_buf(buf_T *buf,
win_T **save_curwinp,
tabpage_T **save_curtabp,
buf_T **save_curbufp)
{
win_T *wp;
tabpage_T *tp;
if (find_win_for_buf(buf, &wp, &tp) == FAIL
|| switch_win(save_curwinp, save_curtabp, wp, tp, TRUE) == FAIL)
switch_buffer(save_curbufp, buf);
}
static void restore_win_for_buf(win_T *save_curwin,
tabpage_T *save_curtab,
buf_T *save_curbuf)
{
if (save_curbuf == NULL) {
restore_win(save_curwin, save_curtab, TRUE);
} else {
restore_buffer(save_curbuf);
}
}
static void fix_cursor(linenr_T lo, linenr_T hi, linenr_T extra)
{
if (curwin->w_cursor.lnum >= lo) {
// Adjust the cursor position if it's in/after the changed
// lines.
if (curwin->w_cursor.lnum >= hi) {
curwin->w_cursor.lnum += extra;
check_cursor_col();
}
else if (extra < 0) {
curwin->w_cursor.lnum = lo;
check_cursor();
} else {
check_cursor_col();
}
changed_cline_bef_curs();
}
invalidate_botline();
}
static int64_t normalize_index(buf_T *buf, int64_t index)
{
// Fix if < 0
index = index < 0 ? buf->b_ml.ml_line_count + index : index;
// Convert the index to a vim line number
index++;
// Fix if > line_count
index = index > buf->b_ml.ml_line_count ? buf->b_ml.ml_line_count : index;
return index;
}

View File

@ -25,9 +25,10 @@ String buffer_get_line(Buffer buffer, int64_t index, Error *err);
///
/// @param buffer The buffer handle
/// @param index The line index
/// @param line The new line
/// @param line The new line. This can can be a String(replacement) or
/// Nil(delete). Anything else is an error.
/// @param[out] err Details of an error that may have occurred
void buffer_set_line(Buffer buffer, int64_t index, String line, Error *err);
void buffer_set_line(Buffer buffer, int64_t index, Object line, Error *err);
/// Retrieves a line range from the buffer
///

View File

@ -4,8 +4,9 @@
#include <string.h>
#include "api/vim.h"
#include "api/defs.h"
#include "api/helpers.h"
#include "api/defs.h"
#include "api/buffer.h"
#include "../vim.h"
#include "types.h"
#include "ascii.h"
@ -139,7 +140,8 @@ void vim_change_directory(String dir, Error *err)
String vim_get_current_line(void)
{
abort();
Error stub;
return buffer_get_line(curbuf->b_fnum, curwin->w_cursor.lnum - 1, &stub);
}
void vim_set_current_line(String line)