-
-
Notifications
You must be signed in to change notification settings - Fork 5.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[RFC] - Extended Marks #5031
Closed
Closed
[RFC] - Extended Marks #5031
Changes from all commits
Commits
Show all changes
3 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -438,6 +438,36 @@ Example: create a float with scratch buffer: > | |
call nvim_win_set_option(win, 'winhl', 'Normal:MyHighlight') | ||
> | ||
|
||
============================================================================== | ||
Buffer extended marks *api-extended-marks* | ||
|
||
An extended mark represents a buffer annotation that remains logically | ||
stationary even as the buffer changes. They could be used to represent cursors, | ||
folds, misspelled words, and anything else that needs to track a logical | ||
location in the buffer over time. | ||
|
||
Example: | ||
|
||
We will set an extmark at row 1, column three. | ||
|
||
`let g:mark_ns = nvim_create_namespace('myplugin')` | ||
`let g:mark_id = nvim_buf_set_mark(0, :g:mark_ns, 0, 1, 3)` | ||
|
||
Note: the mark id was randomly generated because we used an inital value of 0 | ||
|
||
`echo nvim_buf_lookup_mark(0, g:mark_ns, g:mark_id)` | ||
=> [1, 1, 3] | ||
`echo nvim_buf_get_marks(0, g:mark_ns, [1, 1], [1, 3], -1, 0)` | ||
=> [[1, 1, 3]] | ||
|
||
Deleting the text all around an extended mark does not remove it. If you want | ||
to remove an extended mark, use the |nvim_buf_unset_mark()| function. | ||
|
||
The namepsace ensures you only ever work with the extended marks you mean to. | ||
|
||
Calling set and unset of marks will not automatically prop a new undo. | ||
|
||
|
||
============================================================================== | ||
Global Functions *api-global* | ||
|
||
|
@@ -1449,6 +1479,22 @@ nvim_select_popupmenu_item({item}, {insert}, {finish}, {opts}) | |
nvim__inspect_cell({grid}, {row}, {col}) *nvim__inspect_cell()* | ||
TODO: Documentation | ||
|
||
*nvim_init_mark_ns()* | ||
nvim_init_mark_ns({namespace}) | ||
Create a new namepsace for holding extended marks. The id | ||
of the namespace is returned, this namespace id is required | ||
for using the rest of the extended marks api. | ||
|
||
Parameters:~ | ||
{namespace} String name to be assigned to the namespace | ||
|
||
|
||
*nvim_mark_get_ns_ids()* | ||
nvim_mark_get_ns_ids() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
Returns a list of extended mark namespaces. | ||
Pairs of ids and string names are returned. | ||
An empty list will be returned if no namespaces are set. | ||
|
||
|
||
============================================================================== | ||
Buffer Functions *api-buffer* | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,7 +23,10 @@ | |
#include "nvim/memory.h" | ||
#include "nvim/misc1.h" | ||
#include "nvim/ex_cmds.h" | ||
#include "nvim/map_defs.h" | ||
#include "nvim/map.h" | ||
#include "nvim/mark.h" | ||
#include "nvim/mark_extended.h" | ||
#include "nvim/fileio.h" | ||
#include "nvim/move.h" | ||
#include "nvim/syntax.h" | ||
|
@@ -529,7 +532,8 @@ void nvim_buf_set_lines(uint64_t channel_id, | |
(linenr_T)(end - 1), | ||
MAXLNUM, | ||
(long)extra, | ||
false); | ||
false, | ||
kExtmarkUndo); | ||
|
||
changed_lines((linenr_T)start, 0, (linenr_T)end, (long)extra, true); | ||
fix_cursor((linenr_T)start, (linenr_T)end, (linenr_T)extra); | ||
|
@@ -984,6 +988,213 @@ ArrayOf(Integer, 2) nvim_buf_get_mark(Buffer buffer, String name, Error *err) | |
return rv; | ||
} | ||
|
||
/// Returns position info for a given extmark id | ||
/// | ||
/// @param buffer The buffer handle | ||
/// @param namespace a identifier returned previously with nvim_create_namespace | ||
/// @param id the extmark id | ||
/// @param[out] err Details of an error that may have occurred | ||
/// @return (row, col) tuple or empty list () if extmark id was absent | ||
ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer namespace, | ||
Integer id, Error *err) | ||
FUNC_API_SINCE(6) | ||
{ | ||
Array rv = ARRAY_DICT_INIT; | ||
|
||
buf_T *buf = find_buffer_by_handle(buffer, err); | ||
|
||
if (!buf) { | ||
return rv; | ||
} | ||
|
||
if (!ns_initialized((uint64_t)namespace)) { | ||
api_set_error(err, kErrorTypeValidation, _("Invalid mark namespace")); | ||
return rv; | ||
} | ||
|
||
ExtendedMark *extmark = extmark_from_id(buf, | ||
(uint64_t)namespace, | ||
(uint64_t)id); | ||
if (!extmark) { | ||
return rv; | ||
} | ||
ADD(rv, INTEGER_OBJ((Integer)extmark->line->lnum-1)); | ||
ADD(rv, INTEGER_OBJ((Integer)extmark->col-1)); | ||
return rv; | ||
} | ||
|
||
/// List extmarks in a range (inclusive) | ||
/// | ||
/// range ends can be specified as (row, col) tuples, as well as extmark | ||
/// ids in the same namespace. In addition, 0 and -1 works as shorthands | ||
/// for (0,0) and (-1,-1) respectively, so that all marks in the buffer can be | ||
/// quieried as: | ||
/// | ||
/// all_marks = nvim_buf_get_extmarks(0, my_ns, 0, -1, -1) | ||
/// | ||
/// If end is a lower position than start, then the range will be traversed | ||
/// backwards. This is mostly used with limited amount, to be able to get the | ||
/// first marks prior to a given position. | ||
/// | ||
/// @param buffer The buffer handle | ||
/// @param namespace An id returned previously from nvim_create_namespace | ||
/// @param lower One of: extmark id, (row, col) or 0, -1 for buffer ends | ||
/// @param upper One of: extmark id, (row, col) or 0, -1 for buffer ends | ||
/// @param amount Maximum number of marks to return or -1 for all marks found | ||
/// /// @param[out] err Details of an error that may have occurred | ||
/// @return [[nsmark_id, row, col], ...] | ||
Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, | ||
Object start, Object end, Integer amount, | ||
Error *err) | ||
FUNC_API_SINCE(6) | ||
{ | ||
Array rv = ARRAY_DICT_INIT; | ||
|
||
buf_T *buf = find_buffer_by_handle(buffer, err); | ||
if (!buf) { | ||
return rv; | ||
} | ||
|
||
if (!ns_initialized((uint64_t)ns_id)) { | ||
api_set_error(err, kErrorTypeValidation, _("Invalid mark namespace")); | ||
return rv; | ||
} | ||
|
||
if (amount == 0) { | ||
return rv; | ||
} | ||
|
||
|
||
bool reverse = false; | ||
|
||
linenr_T l_lnum; | ||
colnr_T l_col; | ||
if (!set_extmark_index_from_obj(buf, ns_id, start, &l_lnum, &l_col, err)) { | ||
return rv; | ||
} | ||
|
||
linenr_T u_lnum; | ||
colnr_T u_col; | ||
if (!set_extmark_index_from_obj(buf, ns_id, end, &u_lnum, &u_col, err)) { | ||
return rv; | ||
} | ||
|
||
if (l_lnum > u_lnum || (l_lnum == u_lnum && l_col > u_col)) { | ||
reverse = true; | ||
linenr_T tmp_lnum = l_lnum; | ||
l_lnum = u_lnum; | ||
u_lnum = tmp_lnum; | ||
colnr_T tmp_col = l_col; | ||
l_col = u_col; | ||
u_col = tmp_col; | ||
} | ||
|
||
|
||
ExtmarkArray marks = extmark_get(buf, (uint64_t)ns_id, l_lnum, l_col, | ||
u_lnum, u_col, (int64_t)amount, | ||
reverse); | ||
|
||
for (size_t i = 0; i < kv_size(marks); i++) { | ||
Array mark = ARRAY_DICT_INIT; | ||
ExtendedMark *extmark = kv_A(marks, i); | ||
ADD(mark, INTEGER_OBJ((Integer)extmark->mark_id)); | ||
ADD(mark, INTEGER_OBJ(extmark->line->lnum-1)); | ||
ADD(mark, INTEGER_OBJ(extmark->col-1)); | ||
ADD(rv, ARRAY_OBJ(mark)); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
|
||
kv_destroy(marks); | ||
return rv; | ||
} | ||
|
||
/// Create or update a namespaced mark at a position | ||
/// | ||
/// If an invalid namespace is given, an error will be raised. | ||
/// | ||
/// @param buffer The buffer handle | ||
/// @param ns_id a identifier returned previously with nvim_create_namespace | ||
/// @param id The extmark's id or 0 for next free id | ||
/// @param row The row to set the extmark to. | ||
/// @param col The column to set the extmark to. | ||
/// @param[out] err Details of an error that may have occurred | ||
/// @return the nsmark_id for a new mark, or 0 for an update | ||
Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer id, | ||
Integer line, Integer col, Error *err) | ||
FUNC_API_SINCE(6) | ||
{ | ||
buf_T *buf = find_buffer_by_handle(buffer, err); | ||
if (!buf) { | ||
return 0; | ||
} | ||
|
||
if (!ns_initialized((uint64_t)ns_id)) { | ||
api_set_error(err, kErrorTypeValidation, _("Invalid mark namespace")); | ||
return 0; | ||
} | ||
|
||
size_t len = 0; | ||
if (line < 0 || line > buf->b_ml.ml_line_count) { | ||
api_set_error(err, kErrorTypeValidation, "line value outside range"); | ||
return 0; | ||
} else if (line < buf->b_ml.ml_line_count) { | ||
len = STRLEN(ml_get_buf(curbuf, (linenr_T)line+1, false)); | ||
} | ||
|
||
if (col == -1) { | ||
col = (Integer)len; | ||
} else if (col < -1 || col > (Integer)len) { | ||
api_set_error(err, kErrorTypeValidation, "col value outside range"); | ||
return 0; | ||
} | ||
|
||
uint64_t id_num; | ||
if (id == 0) { | ||
id_num = extmark_free_id_get(buf, (uint64_t)ns_id); | ||
} else if (id > 0) { | ||
id_num = (uint64_t)id; | ||
} else { | ||
api_set_error(err, kErrorTypeValidation, _("Invalid mark id")); | ||
return 0; | ||
} | ||
|
||
bool new = extmark_set(buf, (uint64_t)ns_id, id_num, | ||
(linenr_T)line+1, | ||
(colnr_T)col+1, | ||
kExtmarkUndo); | ||
|
||
if (new) { | ||
return (Integer)id_num; | ||
} else { | ||
return 0; | ||
} | ||
} | ||
|
||
/// Remove an extmark | ||
/// | ||
/// @param buffer The buffer handle | ||
/// @param ns_id a identifier returned previously with nvim_create_namespace | ||
/// @param id The extmarks's id | ||
/// @param[out] err Details of an error that may have occurred | ||
/// @return true on success, false if no extmarks found | ||
Boolean nvim_buf_del_extmark(Buffer buffer, | ||
Integer ns_id, | ||
Integer id, | ||
Error *err) | ||
FUNC_API_SINCE(6) | ||
{ | ||
buf_T *buf = find_buffer_by_handle(buffer, err); | ||
|
||
if (!buf) { | ||
return false; | ||
} | ||
if (!ns_initialized((uint64_t)ns_id)) { | ||
api_set_error(err, kErrorTypeValidation, _("Invalid mark namespace")); | ||
return false; | ||
} | ||
|
||
return extmark_del(buf, (uint64_t)ns_id, (uint64_t)id, kExtmarkUndo); | ||
} | ||
|
||
/// Adds a highlight to buffer. | ||
/// | ||
/// Useful for plugins that dynamically generate highlights to a buffer | ||
|
@@ -1082,6 +1293,10 @@ void nvim_buf_clear_namespace(Buffer buffer, | |
} | ||
|
||
bufhl_clear_line_range(buf, (int)ns_id, (int)line_start+1, (int)line_end); | ||
extmark_clear(buf, ns_id == -1 ? 0 : (uint64_t)ns_id, | ||
(linenr_T)line_start+1, | ||
(linenr_T)line_end, | ||
kExtmarkUndo); | ||
} | ||
|
||
/// Clears highlights and virtual text from namespace and range of lines | ||
|
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The function does not exists.
And
nvim_create_namespace()
API is already added in neovim.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
api.txt
is autogenerated. we can just delete this file from the PR.