Skip to content

Commit

Permalink
added arbark (arbitrary marks), these are marks designed for
Browse files Browse the repository at this point in the history
developers who want to build plugins or embed neovim.
  • Loading branch information
timeyyy committed Jul 10, 2016
1 parent dcbd1c7 commit 50e4778
Show file tree
Hide file tree
Showing 5 changed files with 244 additions and 2 deletions.
10 changes: 8 additions & 2 deletions src/nvim/buffer_defs.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ typedef struct file_buffer buf_T; // Forward declaration
#include "nvim/api/private/defs.h"
// for Map(K, V)
#include "nvim/map.h"

// for arbmark_T
/* #include "nvim/lib/kbtree.h" */
#define MODIFIABLE(buf) (!buf->terminal && buf->b_p_ma)

/*
Expand Down Expand Up @@ -114,6 +115,7 @@ typedef Map(linenr_T, bufhl_vec_T) bufhl_info_T;
// for Terminal
#include "nvim/terminal.h"

#include "nvim/editor/arbmark.h"
/*
* The taggy struct is used to store the information about a :tag command.
*/
Expand Down Expand Up @@ -488,7 +490,11 @@ struct file_buffer {
FileID file_id;

int b_fnum; /* buffer number for this file. */

/* PMap(cstr_t) *b_arbmarks = pmap_new(cstr_t)(); /1* Hashtable of mark names *1/ */
/* kbtree_t(arbmark_T) *b_arbmarks_tree; /1* Btree of arbitrary marks *1/ */
// TODO make a macro for this stuff..
/* kKBTREE_INIT(str, arbmark_T, pos_cmp); */
/* to pointers of mark position */
bool b_changed; /* 'modified': Set to true if something in the
file has been changed and not written out. */
int b_changedtick; /* incremented for each change, also for undo */
Expand Down
156 changes: 156 additions & 0 deletions src/nvim/editor/arbmark.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
/*
* Same function but names are not limited to one char
* There is also no ex_command, just viml functions
*/

#include "nvim/vim.h"
#include "nvim/globals.h"
#include "nvim/mark.h"
#include "nvim/memory.h"
#include "nvim/map.h"
#include "nvim/lib/kvec.h"
#include "nvim/editor/arbmark.h"

# define FOR_ALL_ARBMARKS(buf) \
kbitr_t = itr; \
arbmark_T = *arbmark; \
for (;kb_itr_valid(&itr) \
;kb_itr_next(arbmark_T, buf->b_arbmarks_tree; &itr)){

static arbmark_T *_find_pos(pos_t pos, bool FORWARD);
static int _arbmark_create(buf_T *buf, cstr_t *name, pos_T *pos);
static int _arbmark_update(buf_T *buf, arbmark_T *arbmark, pos_T *pos);
static int _arbmark_delete(buf_T *buf, cstr_t *name);
static arbmark_T *get_arbmark(buf_T *buf, cstr_t *name);
static int pos_lt(pos_T *pos, pos_T *pos2);
static int pos_eq(pos_T *pos, pos_T *pos2);

/* Create or update an arbmark, */
int arbmark_set(buf_T *buf, char_u *name, pos_T *pos)
{
arbmark_T *arbmark = get_arbmark(buf, name);
if (!arbmark){
return _arbmark_create(buf, name, pos);
}
else {
return _arbmark_update(buf, arbmark, name, pos);
}
}

/* Will fail silently on missing name */
int arbmark_unset(buf_T *buf, cstr_t *name){
arbmark_T *arbmark = get_arbmark(buf, name);
if (!arbmark){
return FAIL;
}
return _arbmark_delete(buf, name);
}

/* Given a text position, finds the next mark */
arbmark_T *arbmark_next(pos_T pos){
arbmark_T *arbmark = _find_pos(pos, 1);
return arbmark;
}

arbmark_T *arbmark_prev(pos_T pos){
arbmark_T *arbmark = _find_pos(pos, 0);
return arbmark;
}

/* Get all mark names */
kvec_t(cstr_t) arbmark_names(char_u *name){
kvec_t(cstr_t) array;
FOR_ALL_ARBMARKS{
arbmark = &kb_itr_key(arbmark_T, &itr);
kv_push(array, arbmark->name);
}
return array;

static arbmark_T *_find_pos(pos_t pos, bool FORWARD){
int found = -1;
if (FORWARD == 1){
found = 1;
}

FOR_ALL_ARBMARKS{
arbmark = &kb_itr_key(arbmark_T, &itr);
int cmp = kb_generic_cmp(pos, arbmark->fmark.mark);
switch (cmp){
case !found:
continue;
case found:
return arbmark.prev;
case 0:
return arbmark;
}
}
return NULL;
}

static int _arbmark_create(buf_T *buf, cstr_t *name, pos_T *pos){
arbmark_T arbmark;
/* fmark_T fmark; */
/* arbmark.fmark = fmark; */
kb_putp(arbmark_T, buf->b_arbmarks_tree, &arbmark);
pmap_put(cstr_t)(buf->b_arbmarks, name, &arbmark);
SET_FMARK(&buf->b_arbmarks, *pos, buf->b_fnum, *name);
return OK;
}

static int _arbmark_update(buf_T *buf, arbmark_T *arbmark, pos_T *pos){
arbmark->mark.lnum = pos->lnum;
arbmark->mark.col = pos->col;
return OK;
}

static int _arbmark_delete(buf_T *buf, cstr_t *name){
pmap_del(ptr_t)(buf->b_arbmarks, name);
return OK;
}

// TODO start with current buffer
// TODO use a lru cache,
buf_T *arbmark_buf_from_fnum(int fnum){
buf_T *buf;
FOR_ALL_BUFFERS(buf){
if (fnum == buf->fnum){
return buf;
}
}
return buf;
}

/* returns an arbmark from it's buffer*/
static arbmark_T *get_arbmark(buf_T *buf, cstr_t *name){
return pmap_get(arbmark_T)(buf->b_arbmarks, name);
}

int _pos_cmp(pos_T a, pos_T b){
if (pos_lt(a, b) == OK){
return -1;
}
else if (pos_eq(a, b) == OK){
return 0;
}
else {
return 1;
}
}

static int pos_lt(pos_T *pos, pos_T *pos2){
if (pos->lnum < pos2->lnum){
if (pos->col < pos2->col){
return OK;
}
}
return FAIL;
}

static int pos_eq(pos_T *pos, pos_T *pos2){
if (pos->lnum == pos2->lnum){
if (pos->col == pos2->col){
return OK;
}
}
return FAIL;
}
27 changes: 27 additions & 0 deletions src/nvim/editor/arbmark.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#ifndef NVIM_ARBMARK_H
#define NVIM_ARBMARK_H

/* #include "nvim/vim.h" */
/* #include "nvim/lib/kvec.h" */

#define ARBMARK_MAXLEN 24
#define pos_cmp(a, b) (_pos_cmp((a).fmark.mark, (b).fmark.mark))

typedef struct {
fmark_T fmark;
fmark_T *next;
fmark_T *prev;
} arbmark_T;

int arbmark_set(buf_T *buf, char_u *name, pos_T *pos);
int arbmark_unset(buf_T, cstr_t *name);
arbmark_T *arbmark_next(pos_T pos);
arbmark_T *arbmark_prev(pos_T pos);
kvec_t(cstr_t) arbmark_names(cstr_t *name);
int _pos_cmp(pos_T a, pos_T b);
buf_T *arbmark_buf_from_fnum(int fnum);

/* #ifdef INCLUDE_GENERATED_DECLARATIONS */
/* # include "arbmark.h.generated.h" */
/* #endif */
#endif // NVIM_ARBMARK_H
35 changes: 35 additions & 0 deletions src/nvim/eval.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@
#include "nvim/event/loop.h"
#include "nvim/lib/queue.h"
#include "nvim/eval/typval_encode.h"
#include "nvim/editor/arbmark.h"

#define DICT_MAXNEST 100 /* maximum nesting of lists and dicts */

Expand Down Expand Up @@ -6688,6 +6689,7 @@ static struct fst {
{ "and", 2, 2, f_and },
{ "api_info", 0, 0, f_api_info },
{ "append", 2, 2, f_append },
{ "arbmark_set", 0, 4, f_arbmark_set },
{ "argc", 0, 0, f_argc },
{ "argidx", 0, 0, f_argidx },
{ "arglistid", 0, 2, f_arglistid },
Expand Down Expand Up @@ -12334,6 +12336,39 @@ static void f_mapcheck(typval_T *argvars, typval_T *rettv)
get_maparg(argvars, rettv, FALSE);
}

static void f_arbmark_set(typval_T *argvars, typval_T *rettv)
{
int fnum = 0;
buf_T *buf;
if (argvars[0].v_type != VAR_STRING){
EMSG(_("mark name must be a string")); return;
}
if (STRLEN(argvars[0].vval.v_string) > ARBMARK_MAXLEN){
EMSG(_("mark name is to large")); return;
}
if (argvars[1].v_type != VAR_NUMBER){
EMSG(_("Row must be a number")); return;
}
if (argvars[2].v_type != VAR_NUMBER){
EMSG(_("Col must be a number")); return;
}
if (argvars[3].v_type == VAR_NUMBER) {
fnum = argvars[3].vval.v_number;
buf = arbmark_buf_from_fnum(fnum);
if (!buf){
EMSG(_("Buffer could not be found...")); return;
}
} else if (argvars[3].v_type != VAR_UNKNOWN){
EMSG(_("buffer number must be of type number")); return;
}
// TODO DEL
buf = curbuf;
pos_T pos;
pos.lnum = argvars[1].vval.v_number;
pos.col = argvars[2].vval.v_number;
arbmark_set(buf, argvars[0].vval.v_string, &pos);
}


static void find_some_match(typval_T *argvars, typval_T *rettv, int type)
{
Expand Down
18 changes: 18 additions & 0 deletions test/functional/api/arbmark_spec.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
-- Sanity checks for buffer_* API calls via msgpack-rpc
local helpers = require('test.functional.helpers')(after_each)
local clear, nvim, buffer = helpers.clear, helpers.nvim, helpers.buffer
local curbuf, curwin, eq = helpers.curbuf, helpers.curwin, helpers.eq
local curbufmeths, ok = helpers.curbufmeths, helpers.ok
local funcs = helpers.funcs

describe('arbitrary marks set', function()
it('works', function()
curbuf('insert', -1, {'a', 'bit of', 'text'})
nvim('command', 'arb_mark haha 0 0')
curwin('set_cursor', {0, 0})
curbuf('insert', -1, {'12345'})
pos = nvim('eval', 'arbmark_index(haha)')
eq(pos, {0, 6})
end)
end)

0 comments on commit 50e4778

Please sign in to comment.