extmark: review changes
This commit is contained in:
parent
a9065a5051
commit
18a8b702c0
11
README.md
11
README.md
|
@ -148,14 +148,3 @@ See `LICENSE` for details.
|
|||
[Gentoo]: https://packages.gentoo.org/packages/app-editors/neovim
|
||||
|
||||
<!-- vim: set tw=80: -->
|
||||
|
||||
|
||||
CC=clang make functionaltest CMAKE_EXTRA_FLAGS="-DCLANG_ASAN_UBSAN=ON" TEST_FILE=test/functional/api TEST_TAG=extmarks
|
||||
|
||||
CC=clang make functionaltest CMAKE_EXTRA_FLAGS="-DCLANG_ASAN_UBSAN=ON" TEST_FILE=test/functional/ui/mouse_spec.lua TEST_TAG=blah
|
||||
CC=clang make functionaltest CMAKE_EXTRA_FLAGS="-DCLANG_ASAN_UBSAN=ON"
|
||||
|
||||
CC=clang make functionaltest CMAKE_EXTRA_FLAGS="-DCLANG_ASAN_UBSAN=OFF" TEST_FILE=test/functional/api/mark_extended_spec.lua TEST_TAG=broken
|
||||
|
||||
# TODO debug in container with clion...
|
||||
https://github.com/shuhaoliu/docker-clion-dev
|
||||
|
|
|
@ -439,34 +439,40 @@ Example: create a float with scratch buffer: >
|
|||
>
|
||||
|
||||
==============================================================================
|
||||
Buffer extended marks *api-extended-marks*
|
||||
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,
|
||||
An extended mark (extmark) represents a buffer annotation that follows
|
||||
movements 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.
|
||||
We will set an extmark at the first row and third column. As the API is zero-
|
||||
indexed, use row and column counts 0 and 2:
|
||||
|
||||
`let g:mark_ns = nvim_create_namespace('myplugin')`
|
||||
`let g:mark_id = nvim_buf_set_mark(0, :g:mark_ns, 0, 1, 3)`
|
||||
`let g:mark_id = nvim_buf_set_extmark(0, g:mark_ns, 0, 0, 2)`
|
||||
|
||||
Note: the mark id was randomly generated because we used an inital value of 0
|
||||
Passing in id=0 creates a new mark and returns the id. we can look-up a mark
|
||||
by its id:
|
||||
|
||||
`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]]
|
||||
`echo nvim_buf_get_extmark_by_id(0, g:mark_ns, g:mark_id)`
|
||||
=> [0, 2]
|
||||
|
||||
Or we can look-up all marks in a buffer for our namespace (or by a range):
|
||||
`echo nvim_buf_get_extmarks(0, g:mark_ns, 0, -1, -1)`
|
||||
=> [[1, 0, 2]]
|
||||
|
||||
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.
|
||||
to remove an extended mark, use the |nvim_buf_del_extmark()| 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.
|
||||
The namespace ensures your plugin doesn't have to deal with extmarks created
|
||||
by another plugin.
|
||||
|
||||
Mark positions changed by an edit will be restored on undo/redo. Creating and
|
||||
deleting marks doesn't count as a buffer change on itself, i e new undo
|
||||
states will not be created only for marks.
|
||||
|
||||
==============================================================================
|
||||
Global Functions *api-global*
|
||||
|
@ -1479,22 +1485,6 @@ 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()
|
||||
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*
|
||||
|
@ -1793,6 +1783,86 @@ nvim_buf_get_mark({buffer}, {name}) *nvim_buf_get_mark()*
|
|||
Return: ~
|
||||
(row, col) tuple
|
||||
|
||||
*nvim_buf_get_extmark_by_id()*
|
||||
nvim_buf_get_extmark_by_id({buffer}, {ns_id}, {id})
|
||||
Returns position for a given extmark id
|
||||
|
||||
Parameters: ~
|
||||
{buffer} The buffer handle
|
||||
{namespace} a identifier returned previously with
|
||||
nvim_create_namespace
|
||||
{id} the extmark id
|
||||
|
||||
Return: ~
|
||||
(row, col) tuple or empty list () if extmark id was absent
|
||||
|
||||
*nvim_buf_get_extmarks()*
|
||||
nvim_buf_get_extmarks({buffer}, {ns_id}, {start}, {end}, {opts})
|
||||
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.
|
||||
|
||||
Parameters: ~
|
||||
{buffer} The buffer handle
|
||||
{ns_id} An id returned previously from
|
||||
nvim_create_namespace
|
||||
{lower} One of: extmark id, (row, col) or 0, -1 for
|
||||
buffer ends
|
||||
{upper} One of: extmark id, (row, col) or 0, -1 for
|
||||
buffer ends
|
||||
{opts} additional options. Supports the keys:
|
||||
• amount: Maximum number of marks to return •
|
||||
|
||||
Return: ~
|
||||
[[nsmark_id, row, col], ...]
|
||||
|
||||
*nvim_buf_set_extmark()*
|
||||
nvim_buf_set_extmark({buffer}, {ns_id}, {id}, {line}, {col}, {opts})
|
||||
Create or update an extmark at a position
|
||||
|
||||
If an invalid namespace is given, an error will be raised.
|
||||
|
||||
To create a new extmark, pass in id=0. The new extmark id will
|
||||
be returned. To move an existing mark, pass in its id.
|
||||
|
||||
It is also allowed to create a new mark by passing in a
|
||||
previously unused id, but the caller must then keep track of
|
||||
existing and unused ids itself. This is mainly useful over
|
||||
RPC, to avoid needing to wait for the return value.
|
||||
|
||||
Parameters: ~
|
||||
{buffer} The buffer handle
|
||||
{ns_id} a identifier returned previously with
|
||||
nvim_create_namespace
|
||||
{id} The extmark's id or 0 to create a new mark.
|
||||
{row} The row to set the extmark to.
|
||||
{col} The column to set the extmark to.
|
||||
{opts} Optional parameters. Currently not used.
|
||||
|
||||
Return: ~
|
||||
the id of the extmark.
|
||||
|
||||
nvim_buf_del_extmark({buffer}, {ns_id}, {id}) *nvim_buf_del_extmark()*
|
||||
Remove an extmark
|
||||
|
||||
Parameters: ~
|
||||
{buffer} The buffer handle
|
||||
{ns_id} a identifier returned previously with
|
||||
nvim_create_namespace
|
||||
{id} The extmarks's id
|
||||
|
||||
Return: ~
|
||||
true on success, false if the extmark was not found.
|
||||
|
||||
*nvim_buf_add_highlight()*
|
||||
nvim_buf_add_highlight({buffer}, {ns_id}, {hl_group}, {line},
|
||||
{col_start}, {col_end})
|
||||
|
|
|
@ -1003,16 +1003,16 @@ ArrayOf(Integer, 2) nvim_buf_get_mark(Buffer buffer, String name, Error *err)
|
|||
return rv;
|
||||
}
|
||||
|
||||
/// Returns position info for a given extmark id
|
||||
/// Returns position 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,
|
||||
ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer ns_id,
|
||||
Integer id, Error *err)
|
||||
FUNC_API_SINCE(6)
|
||||
FUNC_API_SINCE(7)
|
||||
{
|
||||
Array rv = ARRAY_DICT_INIT;
|
||||
|
||||
|
@ -1022,13 +1022,13 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer namespace,
|
|||
return rv;
|
||||
}
|
||||
|
||||
if (!ns_initialized((uint64_t)namespace)) {
|
||||
api_set_error(err, kErrorTypeValidation, _("Invalid mark namespace"));
|
||||
if (!ns_initialized((uint64_t)ns_id)) {
|
||||
api_set_error(err, kErrorTypeValidation, _("Invalid ns_id"));
|
||||
return rv;
|
||||
}
|
||||
|
||||
ExtendedMark *extmark = extmark_from_id(buf,
|
||||
(uint64_t)namespace,
|
||||
(uint64_t)ns_id,
|
||||
(uint64_t)id);
|
||||
if (!extmark) {
|
||||
return rv;
|
||||
|
@ -1052,16 +1052,17 @@ ArrayOf(Integer) nvim_buf_get_extmark_by_id(Buffer buffer, Integer namespace,
|
|||
/// first marks prior to a given position.
|
||||
///
|
||||
/// @param buffer The buffer handle
|
||||
/// @param namespace An id returned previously from nvim_create_namespace
|
||||
/// @param ns_id 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
|
||||
/// @param opts additional options. Supports the keys:
|
||||
/// - amount: Maximum number of marks to return
|
||||
/// @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,
|
||||
Object start, Object end, Dictionary opts,
|
||||
Error *err)
|
||||
FUNC_API_SINCE(6)
|
||||
FUNC_API_SINCE(7)
|
||||
{
|
||||
Array rv = ARRAY_DICT_INIT;
|
||||
|
||||
|
@ -1071,9 +1072,26 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id,
|
|||
}
|
||||
|
||||
if (!ns_initialized((uint64_t)ns_id)) {
|
||||
api_set_error(err, kErrorTypeValidation, _("Invalid mark namespace"));
|
||||
api_set_error(err, kErrorTypeValidation, _("Invalid ns_id"));
|
||||
return rv;
|
||||
}
|
||||
Integer amount = -1;
|
||||
|
||||
for (size_t i = 0; i < opts.size; i++) {
|
||||
String k = opts.items[i].key;
|
||||
Object *v = &opts.items[i].value;
|
||||
if (strequal("amount", k.data)) {
|
||||
if (v->type != kObjectTypeInteger) {
|
||||
api_set_error(err, kErrorTypeValidation, "amount is not an integer");
|
||||
return rv;
|
||||
}
|
||||
amount = v->data.integer;
|
||||
v->data.integer = LUA_NOREF;
|
||||
} else {
|
||||
api_set_error(err, kErrorTypeValidation, "unexpected key: %s", k.data);
|
||||
return rv;
|
||||
}
|
||||
}
|
||||
|
||||
if (amount == 0) {
|
||||
return rv;
|
||||
|
@ -1122,20 +1140,30 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id,
|
|||
return rv;
|
||||
}
|
||||
|
||||
/// Create or update a namespaced mark at a position
|
||||
/// Create or update an extmark at a position
|
||||
///
|
||||
/// If an invalid namespace is given, an error will be raised.
|
||||
///
|
||||
/// To create a new extmark, pass in id=0. The new extmark id will be
|
||||
/// returned. To move an existing mark, pass in its id.
|
||||
///
|
||||
/// It is also allowed to create a new mark by passing in a previously unused
|
||||
/// id, but the caller must then keep track of existing and unused ids itself.
|
||||
/// This is mainly useful over RPC, to avoid needing to wait for the return
|
||||
/// value.
|
||||
///
|
||||
/// @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 id The extmark's id or 0 to create a new mark.
|
||||
/// @param row The row to set the extmark to.
|
||||
/// @param col The column to set the extmark to.
|
||||
/// @param opts Optional parameters. Currently not used.
|
||||
/// @param[out] err Details of an error that may have occurred
|
||||
/// @return the nsmark_id for a new mark, or 0 for an update
|
||||
/// @return the id of the extmark.
|
||||
Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer id,
|
||||
Integer line, Integer col, Error *err)
|
||||
FUNC_API_SINCE(6)
|
||||
Integer line, Integer col,
|
||||
Dictionary opts, Error *err)
|
||||
FUNC_API_SINCE(7)
|
||||
{
|
||||
buf_T *buf = find_buffer_by_handle(buffer, err);
|
||||
if (!buf) {
|
||||
|
@ -1143,7 +1171,12 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer id,
|
|||
}
|
||||
|
||||
if (!ns_initialized((uint64_t)ns_id)) {
|
||||
api_set_error(err, kErrorTypeValidation, _("Invalid mark namespace"));
|
||||
api_set_error(err, kErrorTypeValidation, _("Invalid ns_id"));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (opts.size > 0) {
|
||||
api_set_error(err, kErrorTypeValidation, "opts dict isn't empty");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1172,16 +1205,10 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer id,
|
|||
return 0;
|
||||
}
|
||||
|
||||
bool new = extmark_set(buf, (uint64_t)ns_id, id_num,
|
||||
(linenr_T)line+1,
|
||||
(colnr_T)col+1,
|
||||
kExtmarkUndo);
|
||||
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;
|
||||
}
|
||||
return (Integer)id_num;
|
||||
}
|
||||
|
||||
/// Remove an extmark
|
||||
|
@ -1190,12 +1217,12 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer id,
|
|||
/// @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
|
||||
/// @return true on success, false if the extmark was not found.
|
||||
Boolean nvim_buf_del_extmark(Buffer buffer,
|
||||
Integer ns_id,
|
||||
Integer id,
|
||||
Error *err)
|
||||
FUNC_API_SINCE(6)
|
||||
FUNC_API_SINCE(7)
|
||||
{
|
||||
buf_T *buf = find_buffer_by_handle(buffer, err);
|
||||
|
||||
|
@ -1203,7 +1230,7 @@ Boolean nvim_buf_del_extmark(Buffer buffer,
|
|||
return false;
|
||||
}
|
||||
if (!ns_initialized((uint64_t)ns_id)) {
|
||||
api_set_error(err, kErrorTypeValidation, _("Invalid mark namespace"));
|
||||
api_set_error(err, kErrorTypeValidation, _("Invalid ns_id"));
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -1575,12 +1575,14 @@ bool ns_initialized(uint64_t ns)
|
|||
return ns < (uint64_t)next_namespace_id;
|
||||
}
|
||||
|
||||
// Extmarks may be queried from position or name or even special names
|
||||
// in the future such as "cursor". This macro sets the line and col
|
||||
// to make the extmark functions recognize what's required
|
||||
//
|
||||
// *lnum: linenr_T, lnum to be set
|
||||
// *col: colnr_T, col to be set
|
||||
/// Get line and column from extmark object
|
||||
///
|
||||
/// Extmarks may be queried from position or name or even special names
|
||||
/// in the future such as "cursor". This function sets the line and col
|
||||
/// to make the extmark functions recognize what's required
|
||||
///
|
||||
/// @param[out] lnum lnum to be set
|
||||
/// @param[out] colnr col to be set
|
||||
bool set_extmark_index_from_obj(buf_T *buf, Integer namespace,
|
||||
Object obj, linenr_T *lnum, colnr_T *colnr,
|
||||
Error *err)
|
||||
|
|
|
@ -809,7 +809,7 @@ struct file_buffer {
|
|||
kvec_t(BufhlLine *) b_bufhl_move_space; // temporary space for highlights
|
||||
|
||||
PMap(uint64_t) *b_extmark_ns; // extmark namespaces
|
||||
kbtree_t(extlines) b_extlines; // extmarks
|
||||
kbtree_t(extmarklines) b_extlines; // extmarks
|
||||
kvec_t(ExtMarkLine *) b_extmark_move_space; // temp space for extmarks
|
||||
|
||||
// array of channel_id:s which have asked to receive updates for this
|
||||
|
|
|
@ -106,8 +106,6 @@ typedef struct {
|
|||
|
||||
#ifdef INCLUDE_GENERATED_DECLARATIONS
|
||||
# include "ex_cmds.c.generated.h"
|
||||
#include "mark_extended.h"
|
||||
|
||||
#endif
|
||||
|
||||
/// ":ascii" and "ga" implementation
|
||||
|
|
|
@ -184,7 +184,6 @@ MAP_IMPL(String, MsgpackRpcRequestHandler, MSGPACK_HANDLER_INITIALIZER)
|
|||
#define KVEC_INITIALIZER { .size = 0, .capacity = 0, .items = NULL }
|
||||
MAP_IMPL(HlEntry, int, DEFAULT_INITIALIZER)
|
||||
MAP_IMPL(String, handle_T, 0)
|
||||
MAP_IMPL(uint64_t, cstr_t, DEFAULT_INITIALIZER)
|
||||
|
||||
|
||||
/// Deletes a key:value pair from a string:pointer map, and frees the
|
||||
|
|
|
@ -42,7 +42,6 @@ MAP_DECLS(handle_T, ptr_t)
|
|||
MAP_DECLS(String, MsgpackRpcRequestHandler)
|
||||
MAP_DECLS(HlEntry, int)
|
||||
MAP_DECLS(String, handle_T)
|
||||
MAP_DECLS(uint64_t, cstr_t)
|
||||
|
||||
#define map_new(T, U) map_##T##_##U##_new
|
||||
#define map_free(T, U) map_##T##_##U##_free
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
// This is an open source non-commercial project. Dear PVS-Studio, please check
|
||||
// it. PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com
|
||||
|
||||
// Implements extended marks for plugins
|
||||
// Each Mark exists in a btree of lines containing btrees of columns.
|
||||
// Implements extended marks for plugins. Each mark exists in a btree of
|
||||
// lines containing btrees of columns.
|
||||
//
|
||||
// The btree provides efficent range lookups.
|
||||
// A map of pointers to the marks is used for fast lookup by mark id.
|
||||
|
@ -17,17 +17,17 @@
|
|||
// copy extmarks is for the area being effected by a delete.
|
||||
//
|
||||
// Marks live in namespaces that allow plugins/users to segregate marks
|
||||
// from other users, namespaces have to be initialized before usage
|
||||
// from other users.
|
||||
//
|
||||
// For possible ideas for efficency improvements see:
|
||||
// http://blog.atom.io/2015/06/16/optimizing-an-important-atom-primitive.html
|
||||
// TODO(bfredl): These ideas could be used for an enhanced btree, which
|
||||
// wouldn't need separate line and column layers.
|
||||
// Other implementations exist in gtk and tk toolkits.
|
||||
//
|
||||
// Deleting marks only happens explicitly extmark_del, deleteing over a
|
||||
// range of marks will only move the marks.
|
||||
//
|
||||
// deleting on a mark will leave it in that same position unless it is on
|
||||
// the eol of the line.
|
||||
// Deleting marks only happens when explicitly calling extmark_del, deleteing
|
||||
// over a range of marks will only move the marks. Deleting on a mark will
|
||||
// leave it in same position unless it is on the EOL of a line.
|
||||
|
||||
#include <assert.h>
|
||||
#include "nvim/vim.h"
|
||||
|
@ -50,23 +50,19 @@
|
|||
///
|
||||
/// must not be used during iteration!
|
||||
/// @returns whether a new mark was created
|
||||
int extmark_set(buf_T *buf,
|
||||
uint64_t ns,
|
||||
uint64_t id,
|
||||
linenr_T lnum,
|
||||
colnr_T col,
|
||||
ExtmarkOp op)
|
||||
int extmark_set(buf_T *buf, uint64_t ns, uint64_t id,
|
||||
linenr_T lnum, colnr_T col, ExtmarkOp op)
|
||||
{
|
||||
ExtendedMark *extmark = extmark_from_id(buf, ns, id);
|
||||
if (!extmark) {
|
||||
extmark_create(buf, ns, id, lnum, col, op);
|
||||
return true;
|
||||
} else {
|
||||
ExtMarkLine *extline = extmark->line;
|
||||
ExtMarkLine *extmarkline = extmark->line;
|
||||
extmark_update(extmark, buf, ns, id, lnum, col, op, NULL);
|
||||
if (kb_size(&extline->items) == 0) {
|
||||
kb_del(extlines, &buf->b_extlines, extline);
|
||||
extline_free(extline);
|
||||
if (kb_size(&extmarkline->items) == 0) {
|
||||
kb_del(extmarklines, &buf->b_extlines, extmarkline);
|
||||
extmarkline_free(extmarkline);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -74,10 +70,7 @@ int extmark_set(buf_T *buf,
|
|||
|
||||
// Remove an extmark
|
||||
// Returns 0 on missing id
|
||||
int extmark_del(buf_T *buf,
|
||||
uint64_t ns,
|
||||
uint64_t id,
|
||||
ExtmarkOp op)
|
||||
int extmark_del(buf_T *buf, uint64_t ns, uint64_t id, ExtmarkOp op)
|
||||
{
|
||||
ExtendedMark *extmark = extmark_from_id(buf, ns, id);
|
||||
if (!extmark) {
|
||||
|
@ -88,11 +81,8 @@ int extmark_del(buf_T *buf,
|
|||
|
||||
// Free extmarks in a ns between lines
|
||||
// if ns = 0, it means clear all namespaces
|
||||
void extmark_clear(buf_T *buf,
|
||||
uint64_t ns,
|
||||
linenr_T l_lnum,
|
||||
linenr_T u_lnum,
|
||||
ExtmarkOp undo)
|
||||
void extmark_clear(buf_T *buf, uint64_t ns,
|
||||
linenr_T l_lnum, linenr_T u_lnum, ExtmarkOp undo)
|
||||
{
|
||||
if (!buf->b_extmark_ns) {
|
||||
return;
|
||||
|
@ -115,7 +105,7 @@ void extmark_clear(buf_T *buf,
|
|||
}
|
||||
|
||||
FOR_ALL_EXTMARKLINES(buf, l_lnum, u_lnum, {
|
||||
FOR_ALL_EXTMARKS_IN_LINE(extline->items, 0, MAXCOL, {
|
||||
FOR_ALL_EXTMARKS_IN_LINE(extmarkline->items, 0, MAXCOL, {
|
||||
if (extmark->ns_id == ns || all_ns) {
|
||||
marks_cleared = true;
|
||||
if (all_ns) {
|
||||
|
@ -124,12 +114,12 @@ void extmark_clear(buf_T *buf,
|
|||
ns_obj = pmap_get(uint64_t)(buf->b_extmark_ns, ns);
|
||||
}
|
||||
pmap_del(uint64_t)(ns_obj->map, extmark->mark_id);
|
||||
kb_del_itr(markitems, &extline->items, &mitr);
|
||||
kb_del_itr(markitems, &extmarkline->items, &mitr);
|
||||
}
|
||||
});
|
||||
if (kb_size(&extline->items) == 0) {
|
||||
kb_del_itr(extlines, &buf->b_extlines, &itr);
|
||||
extline_free(extline);
|
||||
if (kb_size(&extmarkline->items) == 0) {
|
||||
kb_del_itr(extmarklines, &buf->b_extlines, &itr);
|
||||
extmarkline_free(extmarkline);
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -145,14 +135,10 @@ void extmark_clear(buf_T *buf,
|
|||
// will be searched to the start, or end
|
||||
// dir can be set to control the order of the array
|
||||
// amount = amount of marks to find or -1 for all
|
||||
ExtmarkArray extmark_get(buf_T *buf,
|
||||
uint64_t ns,
|
||||
linenr_T l_lnum,
|
||||
colnr_T l_col,
|
||||
linenr_T u_lnum,
|
||||
colnr_T u_col,
|
||||
int64_t amount,
|
||||
bool reverse)
|
||||
ExtmarkArray extmark_get(buf_T *buf, uint64_t ns,
|
||||
linenr_T l_lnum, colnr_T l_col,
|
||||
linenr_T u_lnum, colnr_T u_col,
|
||||
int64_t amount, bool reverse)
|
||||
{
|
||||
ExtmarkArray array = KV_INITIAL_VALUE;
|
||||
// Find all the marks
|
||||
|
@ -178,12 +164,8 @@ ExtmarkArray extmark_get(buf_T *buf,
|
|||
return array;
|
||||
}
|
||||
|
||||
static void extmark_create(buf_T *buf,
|
||||
uint64_t ns,
|
||||
uint64_t id,
|
||||
linenr_T lnum,
|
||||
colnr_T col,
|
||||
ExtmarkOp op)
|
||||
static void extmark_create(buf_T *buf, uint64_t ns, uint64_t id,
|
||||
linenr_T lnum, colnr_T col, ExtmarkOp op)
|
||||
{
|
||||
if (!buf->b_extmark_ns) {
|
||||
buf->b_extmark_ns = pmap_new(uint64_t)();
|
||||
|
@ -198,13 +180,13 @@ static void extmark_create(buf_T *buf,
|
|||
}
|
||||
|
||||
// Create or get a line
|
||||
ExtMarkLine *extline = extline_ref(buf, lnum, true);
|
||||
ExtMarkLine *extmarkline = extmarkline_ref(buf, lnum, true);
|
||||
// Create and put mark on the line
|
||||
extmark_put(col, id, extline, ns);
|
||||
extmark_put(col, id, extmarkline, ns);
|
||||
|
||||
// Marks do not have stable address so we have to look them up
|
||||
// by using the line instead of the mark
|
||||
pmap_put(uint64_t)(ns_obj->map, id, extline);
|
||||
pmap_put(uint64_t)(ns_obj->map, id, extmarkline);
|
||||
if (op != kExtmarkNoUndo) {
|
||||
u_extmark_set(buf, ns, id, lnum, col, kExtmarkSet);
|
||||
}
|
||||
|
@ -215,14 +197,10 @@ static void extmark_create(buf_T *buf,
|
|||
|
||||
// update the position of an extmark
|
||||
// to update while iterating pass the markitems itr
|
||||
static void extmark_update(ExtendedMark *extmark,
|
||||
buf_T *buf,
|
||||
uint64_t ns,
|
||||
uint64_t id,
|
||||
linenr_T lnum,
|
||||
colnr_T col,
|
||||
ExtmarkOp op,
|
||||
kbitr_t(markitems) *mitr)
|
||||
static void extmark_update(ExtendedMark *extmark, buf_T *buf,
|
||||
uint64_t ns, uint64_t id,
|
||||
linenr_T lnum, colnr_T col,
|
||||
ExtmarkOp op, kbitr_t(markitems) *mitr)
|
||||
{
|
||||
assert(op != kExtmarkNOOP);
|
||||
if (op != kExtmarkNoUndo) {
|
||||
|
@ -232,7 +210,7 @@ static void extmark_update(ExtendedMark *extmark,
|
|||
ExtMarkLine *old_line = extmark->line;
|
||||
// Move the mark to a new line and update column
|
||||
if (old_line->lnum != lnum) {
|
||||
ExtMarkLine *ref_line = extline_ref(buf, lnum, true);
|
||||
ExtMarkLine *ref_line = extmarkline_ref(buf, lnum, true);
|
||||
extmark_put(col, id, ref_line, ns);
|
||||
// Update the hashmap
|
||||
ExtmarkNs *ns_obj = pmap_get(uint64_t)(buf->b_extmark_ns, ns);
|
||||
|
@ -272,12 +250,12 @@ static int extmark_delete(ExtendedMark *extmark,
|
|||
pmap_del(uint64_t)(ns_obj->map, id);
|
||||
|
||||
// Remove the mark mark from the line
|
||||
ExtMarkLine *extline = extmark->line;
|
||||
kb_del(markitems, &extline->items, *extmark);
|
||||
ExtMarkLine *extmarkline = extmark->line;
|
||||
kb_del(markitems, &extmarkline->items, *extmark);
|
||||
// Remove the line if there are no more marks in the line
|
||||
if (kb_size(&extline->items) == 0) {
|
||||
kb_del(extlines, &buf->b_extlines, extline);
|
||||
extline_free(extline);
|
||||
if (kb_size(&extmarkline->items) == 0) {
|
||||
kb_del(extmarklines, &buf->b_extlines, extmarkline);
|
||||
extmarkline_free(extmarkline);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@ -292,12 +270,12 @@ ExtendedMark *extmark_from_id(buf_T *buf, uint64_t ns, uint64_t id)
|
|||
if (!ns_obj || !kh_size(ns_obj->map->table)) {
|
||||
return NULL;
|
||||
}
|
||||
ExtMarkLine *extline = pmap_get(uint64_t)(ns_obj->map, id);
|
||||
if (!extline) {
|
||||
ExtMarkLine *extmarkline = pmap_get(uint64_t)(ns_obj->map, id);
|
||||
if (!extmarkline) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
FOR_ALL_EXTMARKS_IN_LINE(extline->items, 0, MAXCOL, {
|
||||
FOR_ALL_EXTMARKS_IN_LINE(extmarkline->items, 0, MAXCOL, {
|
||||
if (extmark->ns_id == ns
|
||||
&& extmark->mark_id == id) {
|
||||
return extmark;
|
||||
|
@ -354,8 +332,8 @@ void extmark_free_all(buf_T *buf)
|
|||
ExtmarkNs *ns_obj;
|
||||
|
||||
FOR_ALL_EXTMARKLINES(buf, 1, MAXLNUM, {
|
||||
kb_del_itr(extlines, &buf->b_extlines, &itr);
|
||||
extline_free(extline);
|
||||
kb_del_itr(extmarklines, &buf->b_extlines, &itr);
|
||||
extmarkline_free(extmarkline);
|
||||
})
|
||||
|
||||
map_foreach(buf->b_extmark_ns, ns, ns_obj, {
|
||||
|
@ -365,9 +343,10 @@ void extmark_free_all(buf_T *buf)
|
|||
});
|
||||
|
||||
pmap_free(uint64_t)(buf->b_extmark_ns);
|
||||
buf->b_extmark_ns = NULL;
|
||||
|
||||
// k?_init called to set pointers to NULL
|
||||
kb_destroy(extlines, (&buf->b_extlines));
|
||||
kb_destroy(extmarklines, (&buf->b_extlines));
|
||||
kb_init(&buf->b_extlines);
|
||||
|
||||
kv_destroy(buf->b_extmark_move_space);
|
||||
|
@ -376,14 +355,10 @@ void extmark_free_all(buf_T *buf)
|
|||
|
||||
|
||||
// Save info for undo/redo of set marks
|
||||
static void u_extmark_set(buf_T *buf,
|
||||
uint64_t ns,
|
||||
uint64_t id,
|
||||
linenr_T lnum,
|
||||
colnr_T col,
|
||||
UndoObjectType undo_type)
|
||||
static void u_extmark_set(buf_T *buf, uint64_t ns, uint64_t id,
|
||||
linenr_T lnum, colnr_T col, UndoObjectType undo_type)
|
||||
{
|
||||
u_header_T *uhp = force_get_undo_header(buf);
|
||||
u_header_T *uhp = u_force_get_undo_header(buf);
|
||||
if (!uhp) {
|
||||
return;
|
||||
}
|
||||
|
@ -401,15 +376,11 @@ static void u_extmark_set(buf_T *buf,
|
|||
}
|
||||
|
||||
// Save info for undo/redo of deleted marks
|
||||
static void u_extmark_update(buf_T *buf,
|
||||
uint64_t ns,
|
||||
uint64_t id,
|
||||
linenr_T old_lnum,
|
||||
colnr_T old_col,
|
||||
linenr_T lnum,
|
||||
colnr_T col)
|
||||
static void u_extmark_update(buf_T *buf, uint64_t ns, uint64_t id,
|
||||
linenr_T old_lnum, colnr_T old_col,
|
||||
linenr_T lnum, colnr_T col)
|
||||
{
|
||||
u_header_T *uhp = force_get_undo_header(buf);
|
||||
u_header_T *uhp = u_force_get_undo_header(buf);
|
||||
if (!uhp) {
|
||||
return;
|
||||
}
|
||||
|
@ -431,13 +402,10 @@ static void u_extmark_update(buf_T *buf,
|
|||
// - Instead of 1 undo object for each char inserted,
|
||||
// we create 1 undo objet for all text inserted before the user hits esc
|
||||
// Return True if we compacted else False
|
||||
static bool u_compact_col_adjust(buf_T *buf,
|
||||
linenr_T lnum,
|
||||
colnr_T mincol,
|
||||
long lnum_amount,
|
||||
long col_amount)
|
||||
static bool u_compact_col_adjust(buf_T *buf, linenr_T lnum, colnr_T mincol,
|
||||
long lnum_amount, long col_amount)
|
||||
{
|
||||
u_header_T *uhp = force_get_undo_header(buf);
|
||||
u_header_T *uhp = u_force_get_undo_header(buf);
|
||||
if (!uhp) {
|
||||
return false;
|
||||
}
|
||||
|
@ -472,13 +440,10 @@ static bool u_compact_col_adjust(buf_T *buf,
|
|||
}
|
||||
|
||||
// Save col_adjust info so we can undo/redo
|
||||
void u_extmark_col_adjust(buf_T *buf,
|
||||
linenr_T lnum,
|
||||
colnr_T mincol,
|
||||
long lnum_amount,
|
||||
long col_amount)
|
||||
void u_extmark_col_adjust(buf_T *buf, linenr_T lnum, colnr_T mincol,
|
||||
long lnum_amount, long col_amount)
|
||||
{
|
||||
u_header_T *uhp = force_get_undo_header(buf);
|
||||
u_header_T *uhp = u_force_get_undo_header(buf);
|
||||
if (!uhp) {
|
||||
return;
|
||||
}
|
||||
|
@ -498,13 +463,10 @@ void u_extmark_col_adjust(buf_T *buf,
|
|||
}
|
||||
|
||||
// Save col_adjust_delete info so we can undo/redo
|
||||
void u_extmark_col_adjust_delete(buf_T *buf,
|
||||
linenr_T lnum,
|
||||
colnr_T mincol,
|
||||
colnr_T endcol,
|
||||
int eol)
|
||||
void u_extmark_col_adjust_delete(buf_T *buf, linenr_T lnum,
|
||||
colnr_T mincol, colnr_T endcol, int eol)
|
||||
{
|
||||
u_header_T *uhp = force_get_undo_header(buf);
|
||||
u_header_T *uhp = u_force_get_undo_header(buf);
|
||||
if (!uhp) {
|
||||
return;
|
||||
}
|
||||
|
@ -522,13 +484,10 @@ void u_extmark_col_adjust_delete(buf_T *buf,
|
|||
}
|
||||
|
||||
// Save adjust info so we can undo/redo
|
||||
static void u_extmark_adjust(buf_T * buf,
|
||||
linenr_T line1,
|
||||
linenr_T line2,
|
||||
long amount,
|
||||
long amount_after)
|
||||
static void u_extmark_adjust(buf_T * buf, linenr_T line1, linenr_T line2,
|
||||
long amount, long amount_after)
|
||||
{
|
||||
u_header_T *uhp = force_get_undo_header(buf);
|
||||
u_header_T *uhp = u_force_get_undo_header(buf);
|
||||
if (!uhp) {
|
||||
return;
|
||||
}
|
||||
|
@ -546,15 +505,11 @@ static void u_extmark_adjust(buf_T * buf,
|
|||
}
|
||||
|
||||
// save info to undo/redo a :move
|
||||
void u_extmark_move(buf_T *buf,
|
||||
linenr_T line1,
|
||||
linenr_T line2,
|
||||
linenr_T last_line,
|
||||
linenr_T dest,
|
||||
linenr_T num_lines,
|
||||
void u_extmark_move(buf_T *buf, linenr_T line1, linenr_T line2,
|
||||
linenr_T last_line, linenr_T dest, linenr_T num_lines,
|
||||
linenr_T extra)
|
||||
{
|
||||
u_header_T *uhp = force_get_undo_header(buf);
|
||||
u_header_T *uhp = u_force_get_undo_header(buf);
|
||||
if (!uhp) {
|
||||
return;
|
||||
}
|
||||
|
@ -577,14 +532,11 @@ void u_extmark_move(buf_T *buf,
|
|||
// the operation. This will do nothing on redo, enforces correct position when
|
||||
// undo.
|
||||
// if ns = 0, it means copy all namespaces
|
||||
void u_extmark_copy(buf_T *buf,
|
||||
uint64_t ns,
|
||||
linenr_T l_lnum,
|
||||
colnr_T l_col,
|
||||
linenr_T u_lnum,
|
||||
colnr_T u_col)
|
||||
void u_extmark_copy(buf_T *buf, uint64_t ns,
|
||||
linenr_T l_lnum, colnr_T l_col,
|
||||
linenr_T u_lnum, colnr_T u_col)
|
||||
{
|
||||
u_header_T *uhp = force_get_undo_header(buf);
|
||||
u_header_T *uhp = u_force_get_undo_header(buf);
|
||||
if (!uhp) {
|
||||
return;
|
||||
}
|
||||
|
@ -608,14 +560,11 @@ void u_extmark_copy(buf_T *buf,
|
|||
}
|
||||
|
||||
void u_extmark_copy_place(buf_T *buf,
|
||||
linenr_T l_lnum,
|
||||
colnr_T l_col,
|
||||
linenr_T u_lnum,
|
||||
colnr_T u_col,
|
||||
linenr_T p_lnum,
|
||||
colnr_T p_col)
|
||||
linenr_T l_lnum, colnr_T l_col,
|
||||
linenr_T u_lnum, colnr_T u_col,
|
||||
linenr_T p_lnum, colnr_T p_col)
|
||||
{
|
||||
u_header_T *uhp = force_get_undo_header(buf);
|
||||
u_header_T *uhp = u_force_get_undo_header(buf);
|
||||
if (!uhp) {
|
||||
return;
|
||||
}
|
||||
|
@ -635,12 +584,10 @@ void u_extmark_copy_place(buf_T *buf,
|
|||
}
|
||||
|
||||
// Save info for undo/redo of extmark_clear
|
||||
static void u_extmark_clear(buf_T *buf,
|
||||
uint64_t ns,
|
||||
linenr_T l_lnum,
|
||||
linenr_T u_lnum)
|
||||
static void u_extmark_clear(buf_T *buf, uint64_t ns,
|
||||
linenr_T l_lnum, linenr_T u_lnum)
|
||||
{
|
||||
u_header_T *uhp = force_get_undo_header(buf);
|
||||
u_header_T *uhp = u_force_get_undo_header(buf);
|
||||
if (!uhp) {
|
||||
return;
|
||||
}
|
||||
|
@ -843,105 +790,35 @@ static void apply_undo_move(ExtmarkUndoObject undo_info, bool undo)
|
|||
|
||||
if (undo) {
|
||||
if (dest >= line2) {
|
||||
extmark_adjust(curbuf,
|
||||
dest - num_lines + 1,
|
||||
dest,
|
||||
last_line - dest + num_lines - 1,
|
||||
0L,
|
||||
kExtmarkNoUndo,
|
||||
extmark_adjust(curbuf, dest - num_lines + 1, dest,
|
||||
last_line - dest + num_lines - 1, 0L, kExtmarkNoUndo,
|
||||
true);
|
||||
extmark_adjust(curbuf,
|
||||
dest - line2,
|
||||
dest - line1,
|
||||
dest - line2,
|
||||
0L,
|
||||
kExtmarkNoUndo,
|
||||
false);
|
||||
extmark_adjust(curbuf, dest - line2, dest - line1,
|
||||
dest - line2, 0L, kExtmarkNoUndo, false);
|
||||
} else {
|
||||
extmark_adjust(curbuf,
|
||||
line1-num_lines,
|
||||
line2-num_lines,
|
||||
last_line - (line1-num_lines),
|
||||
0L,
|
||||
kExtmarkNoUndo,
|
||||
true);
|
||||
extmark_adjust(curbuf,
|
||||
(line1-num_lines) + 1,
|
||||
(line2-num_lines) + 1,
|
||||
-num_lines,
|
||||
0L,
|
||||
kExtmarkNoUndo,
|
||||
false);
|
||||
extmark_adjust(curbuf, line1-num_lines, line2-num_lines,
|
||||
last_line - (line1-num_lines), 0L, kExtmarkNoUndo, true);
|
||||
extmark_adjust(curbuf, (line1-num_lines) + 1, (line2-num_lines) + 1,
|
||||
-num_lines, 0L, kExtmarkNoUndo, false);
|
||||
}
|
||||
extmark_adjust(curbuf,
|
||||
last_line,
|
||||
last_line + num_lines - 1,
|
||||
line1 - last_line,
|
||||
0L,
|
||||
kExtmarkNoUndo,
|
||||
true);
|
||||
extmark_adjust(curbuf, last_line, last_line + num_lines - 1,
|
||||
line1 - last_line, 0L, kExtmarkNoUndo, true);
|
||||
// redo
|
||||
} else {
|
||||
extmark_adjust(curbuf,
|
||||
line1,
|
||||
line2,
|
||||
last_line - line2,
|
||||
0L,
|
||||
kExtmarkNoUndo,
|
||||
true);
|
||||
extmark_adjust(curbuf, line1, line2,
|
||||
last_line - line2, 0L, kExtmarkNoUndo, true);
|
||||
if (dest >= line2) {
|
||||
extmark_adjust(curbuf,
|
||||
line2 + 1,
|
||||
dest,
|
||||
-num_lines,
|
||||
0L,
|
||||
kExtmarkNoUndo,
|
||||
false);
|
||||
extmark_adjust(curbuf, line2 + 1, dest,
|
||||
-num_lines, 0L, kExtmarkNoUndo, false);
|
||||
} else {
|
||||
extmark_adjust(curbuf,
|
||||
dest + 1,
|
||||
line1 - 1,
|
||||
num_lines,
|
||||
0L,
|
||||
kExtmarkNoUndo,
|
||||
false);
|
||||
extmark_adjust(curbuf, dest + 1, line1 - 1,
|
||||
num_lines, 0L, kExtmarkNoUndo, false);
|
||||
}
|
||||
extmark_adjust(curbuf,
|
||||
last_line - num_lines + 1,
|
||||
last_line,
|
||||
-(last_line - dest - extra),
|
||||
0L,
|
||||
kExtmarkNoUndo,
|
||||
true);
|
||||
extmark_adjust(curbuf, last_line - num_lines + 1, last_line,
|
||||
-(last_line - dest - extra), 0L, kExtmarkNoUndo, true);
|
||||
}
|
||||
}
|
||||
|
||||
// for anything other than deletes
|
||||
// Return, desired col amount where the adjustment should take place
|
||||
// (not taking) eol into account
|
||||
static long update_constantly(colnr_T _, colnr_T __, long col_amount)
|
||||
{
|
||||
return col_amount;
|
||||
}
|
||||
|
||||
// for deletes,
|
||||
// Return, desired col amount where the adjustment should take place
|
||||
// (not taking) eol into account
|
||||
static long update_variably(colnr_T mincol, colnr_T current, long endcol)
|
||||
{
|
||||
colnr_T start_effected_range = mincol - 1;
|
||||
long col_amount;
|
||||
// When mark inside range
|
||||
if (current < endcol) {
|
||||
col_amount = -(current - start_effected_range);
|
||||
// Mark outside of range
|
||||
} else {
|
||||
// -1 because a delete of width 0 should still move marks
|
||||
col_amount = -(endcol - mincol) - 1;
|
||||
}
|
||||
return col_amount;
|
||||
}
|
||||
|
||||
|
||||
/// Get the column position for EOL on a line
|
||||
///
|
||||
|
@ -960,23 +837,37 @@ colnr_T extmark_eol_col(buf_T *buf, linenr_T lnum)
|
|||
// returns true if something was moved otherwise false
|
||||
static bool extmark_col_adjust_impl(buf_T *buf, linenr_T lnum,
|
||||
colnr_T mincol, long lnum_amount,
|
||||
long (*calc_amount)(colnr_T, colnr_T, long),
|
||||
long func_arg)
|
||||
bool for_delete,
|
||||
long update_col)
|
||||
{
|
||||
bool marks_exist = false;
|
||||
colnr_T *cp;
|
||||
long col_amount;
|
||||
|
||||
ExtMarkLine *extline = extline_ref(buf, lnum, false);
|
||||
if (!extline) {
|
||||
ExtMarkLine *extmarkline = extmarkline_ref(buf, lnum, false);
|
||||
if (!extmarkline) {
|
||||
return false;
|
||||
}
|
||||
|
||||
FOR_ALL_EXTMARKS_IN_LINE(extline->items, mincol, MAXCOL, {
|
||||
FOR_ALL_EXTMARKS_IN_LINE(extmarkline->items, mincol, MAXCOL, {
|
||||
marks_exist = true;
|
||||
cp = &(extmark->col);
|
||||
|
||||
col_amount = (*calc_amount)(mincol, *cp, func_arg);
|
||||
// Calculate desired col amount where the adjustment should take place
|
||||
// (not taking) eol into account
|
||||
long col_amount;
|
||||
if (for_delete) {
|
||||
if (extmark->col < update_col) {
|
||||
// When mark inside range
|
||||
colnr_T start_effected_range = mincol - 1;
|
||||
col_amount = -(extmark->col - start_effected_range);
|
||||
} else {
|
||||
// Mark outside of range
|
||||
// -1 because a delete of width 0 should still move marks
|
||||
col_amount = -(update_col - mincol) - 1;
|
||||
}
|
||||
} else {
|
||||
// for anything other than deletes
|
||||
col_amount = update_col;
|
||||
}
|
||||
|
||||
// No update required for this guy
|
||||
if (col_amount == 0 && lnum_amount == 0) {
|
||||
continue;
|
||||
|
@ -984,23 +875,22 @@ static bool extmark_col_adjust_impl(buf_T *buf, linenr_T lnum,
|
|||
|
||||
// Set mark to start of line
|
||||
if (col_amount < 0
|
||||
&& *cp <= (colnr_T)-col_amount) { // TODO(timeyyy): does mark.c
|
||||
// need this line?
|
||||
&& extmark->col <= (colnr_T)-col_amount) {
|
||||
extmark_update(extmark, buf, extmark->ns_id, extmark->mark_id,
|
||||
extline->lnum + lnum_amount,
|
||||
extmarkline->lnum + lnum_amount,
|
||||
1, kExtmarkNoUndo, &mitr);
|
||||
// Update the mark
|
||||
} else {
|
||||
// Note: The undo is handled by u_extmark_col_adjust, NoUndo here
|
||||
extmark_update(extmark, buf, extmark->ns_id, extmark->mark_id,
|
||||
extline->lnum + lnum_amount,
|
||||
*cp + (colnr_T)col_amount, kExtmarkNoUndo, &mitr);
|
||||
extmarkline->lnum + lnum_amount,
|
||||
extmark->col + (colnr_T)col_amount, kExtmarkNoUndo, &mitr);
|
||||
}
|
||||
})
|
||||
|
||||
if (kb_size(&extline->items) == 0) {
|
||||
kb_del(extlines, &buf->b_extlines, extline);
|
||||
extline_free(extline);
|
||||
if (kb_size(&extmarkline->items) == 0) {
|
||||
kb_del(extmarklines, &buf->b_extlines, extmarkline);
|
||||
extmarkline_free(extmarkline);
|
||||
}
|
||||
|
||||
return marks_exist;
|
||||
|
@ -1019,7 +909,7 @@ void extmark_col_adjust(buf_T *buf, linenr_T lnum,
|
|||
assert(col_amount > INT_MIN && col_amount <= INT_MAX);
|
||||
|
||||
bool marks_moved = extmark_col_adjust_impl(buf, lnum, mincol, lnum_amount,
|
||||
&update_constantly, col_amount);
|
||||
false, col_amount);
|
||||
|
||||
if (undo == kExtmarkUndo && marks_moved) {
|
||||
u_extmark_col_adjust(buf, lnum, mincol, lnum_amount, col_amount);
|
||||
|
@ -1038,17 +928,6 @@ void extmark_col_adjust_delete(buf_T *buf, linenr_T lnum,
|
|||
ExtmarkOp undo, int _eol)
|
||||
{
|
||||
colnr_T start_effected_range = mincol;
|
||||
// TODO(timeyyy): understand why this has to be uncommented out for the
|
||||
// tests to pass.. shouldn't this be required?
|
||||
// why is this even being called if it's not neeed?
|
||||
|
||||
// Some tests in the vim suite were hitting the assertion that was here.
|
||||
// functional/ui/mouse_spec/
|
||||
// We don't know what to do in this case so just bail!
|
||||
|
||||
// if (start_effected_range <= endcol) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
bool marks_moved;
|
||||
if (undo == kExtmarkUndo) {
|
||||
|
@ -1058,7 +937,7 @@ void extmark_col_adjust_delete(buf_T *buf, linenr_T lnum,
|
|||
}
|
||||
|
||||
marks_moved = extmark_col_adjust_impl(buf, lnum, mincol, 0,
|
||||
&update_variably, (long)endcol);
|
||||
true, (long)endcol);
|
||||
|
||||
// Deletes at the end of the line have different behaviour than the normal
|
||||
// case when deleted.
|
||||
|
@ -1071,7 +950,7 @@ void extmark_col_adjust_delete(buf_T *buf, linenr_T lnum,
|
|||
}
|
||||
FOR_ALL_EXTMARKS(buf, 1, lnum, eol, lnum, -1, {
|
||||
extmark_update(extmark, buf, extmark->ns_id, extmark->mark_id,
|
||||
extline->lnum, (colnr_T)eol, kExtmarkNoUndo, &mitr);
|
||||
extmarkline->lnum, (colnr_T)eol, kExtmarkNoUndo, &mitr);
|
||||
})
|
||||
|
||||
// Record the undo for the actual move
|
||||
|
@ -1092,12 +971,12 @@ void extmark_adjust(buf_T *buf,
|
|||
ExtMarkLine *_extline;
|
||||
|
||||
// btree needs to be kept ordered to work, so far only :move requires this
|
||||
// 2nd call with end_temp = unpack the lines from the temp position
|
||||
// 2nd call with end_temp = true unpack the lines from the temp position
|
||||
if (end_temp && amount < 0) {
|
||||
for (size_t i = 0; i < kv_size(buf->b_extmark_move_space); i++) {
|
||||
_extline = kv_A(buf->b_extmark_move_space, i);
|
||||
_extline->lnum += amount;
|
||||
kb_put(extlines, &buf->b_extlines, _extline);
|
||||
kb_put(extmarklines, &buf->b_extlines, _extline);
|
||||
}
|
||||
kv_size(buf->b_extmark_move_space) = 0;
|
||||
return;
|
||||
|
@ -1108,11 +987,12 @@ void extmark_adjust(buf_T *buf,
|
|||
|
||||
linenr_T adj_start = line1;
|
||||
if (amount == MAXLNUM) {
|
||||
// Careful! marks from deleted region can end up on en extisting extline
|
||||
// Careful! marks from deleted region can end up on en extisting extmarkline
|
||||
// that is goinig to be adjusted to the target position.
|
||||
linenr_T join_num = line1 - amount_after;
|
||||
ExtMarkLine *joinline = join_num > line2 \
|
||||
? extline_ref(buf, join_num, false) : NULL;
|
||||
ExtMarkLine *joinline = (join_num > line2
|
||||
? extmarkline_ref(buf, join_num, false) : NULL);
|
||||
|
||||
// extmark_adjust is already redoable, the copy should only be for undo
|
||||
marks_exist = extmark_copy_and_place(curbuf,
|
||||
line1, 1,
|
||||
|
@ -1123,12 +1003,12 @@ void extmark_adjust(buf_T *buf,
|
|||
}
|
||||
FOR_ALL_EXTMARKLINES(buf, adj_start, MAXLNUM, {
|
||||
marks_exist = true;
|
||||
lp = &(extline->lnum);
|
||||
lp = &(extmarkline->lnum);
|
||||
if (*lp <= line2) {
|
||||
// 1st call with end_temp = true, store the lines in a temp position
|
||||
if (end_temp && amount > 0) {
|
||||
kb_del_itr_extlines(&buf->b_extlines, &itr);
|
||||
kv_push(buf->b_extmark_move_space, extline);
|
||||
kb_del_itr_extmarklines(&buf->b_extlines, &itr);
|
||||
kv_push(buf->b_extmark_move_space, extmarkline);
|
||||
}
|
||||
|
||||
*lp += amount;
|
||||
|
@ -1147,14 +1027,10 @@ void extmark_adjust(buf_T *buf,
|
|||
/// if part of a larger iteration we can't delete, then the caller
|
||||
/// must check for empty lines.
|
||||
bool extmark_copy_and_place(buf_T *buf,
|
||||
linenr_T l_lnum,
|
||||
colnr_T l_col,
|
||||
linenr_T u_lnum,
|
||||
colnr_T u_col,
|
||||
linenr_T p_lnum,
|
||||
colnr_T p_col,
|
||||
ExtmarkOp undo,
|
||||
bool delete,
|
||||
linenr_T l_lnum, colnr_T l_col,
|
||||
linenr_T u_lnum, colnr_T u_col,
|
||||
linenr_T p_lnum, colnr_T p_col,
|
||||
ExtmarkOp undo, bool delete,
|
||||
ExtMarkLine *destline)
|
||||
|
||||
{
|
||||
|
@ -1166,17 +1042,17 @@ bool extmark_copy_and_place(buf_T *buf,
|
|||
|
||||
// Move extmarks to their final position
|
||||
// Careful: if we move items within the same line, we might change order of
|
||||
// marks within the same extline. Too keep it simple, first delete all items
|
||||
// from the extline and put them back in the right order.
|
||||
// marks within the same extmarkline. Too keep it simple, first delete all
|
||||
// items from the extmarkline and put them back in the right order.
|
||||
FOR_ALL_EXTMARKLINES(buf, l_lnum, u_lnum, {
|
||||
kvec_t(ExtendedMark) temp_space = KV_INITIAL_VALUE;
|
||||
bool same_line = extline == destline;
|
||||
FOR_ALL_EXTMARKS_IN_LINE(extline->items,
|
||||
(extline->lnum > l_lnum) ? 0 : l_col,
|
||||
(extline->lnum < u_lnum) ? MAXCOL : u_col, {
|
||||
bool same_line = extmarkline == destline;
|
||||
FOR_ALL_EXTMARKS_IN_LINE(extmarkline->items,
|
||||
(extmarkline->lnum > l_lnum) ? 0 : l_col,
|
||||
(extmarkline->lnum < u_lnum) ? MAXCOL : u_col, {
|
||||
if (!destline) {
|
||||
destline = extline_ref(buf, p_lnum, true);
|
||||
same_line = extline == destline;
|
||||
destline = extmarkline_ref(buf, p_lnum, true);
|
||||
same_line = extmarkline == destline;
|
||||
}
|
||||
marks_moved = true;
|
||||
if (!same_line) {
|
||||
|
@ -1188,17 +1064,17 @@ bool extmark_copy_and_place(buf_T *buf,
|
|||
kv_push(temp_space, *extmark);
|
||||
}
|
||||
// Delete old mark
|
||||
kb_del_itr(markitems, &extline->items, &mitr);
|
||||
kb_del_itr(markitems, &extmarkline->items, &mitr);
|
||||
})
|
||||
if (same_line) {
|
||||
for (size_t i = 0; i < kv_size(temp_space); i++) {
|
||||
ExtendedMark mark = kv_A(temp_space, i);
|
||||
extmark_put(p_col, mark.mark_id, extline, mark.ns_id);
|
||||
extmark_put(p_col, mark.mark_id, extmarkline, mark.ns_id);
|
||||
}
|
||||
kv_destroy(temp_space);
|
||||
} else if (delete && kb_size(&extline->items) == 0) {
|
||||
kb_del_itr(extlines, &buf->b_extlines, &itr);
|
||||
extline_free(extline);
|
||||
} else if (delete && kb_size(&extmarkline->items) == 0) {
|
||||
kb_del_itr(extmarklines, &buf->b_extlines, &itr);
|
||||
extmarkline_free(extmarkline);
|
||||
}
|
||||
})
|
||||
|
||||
|
@ -1211,13 +1087,13 @@ bool extmark_copy_and_place(buf_T *buf,
|
|||
}
|
||||
|
||||
// Get reference to line in kbtree_t, allocating it if neccessary.
|
||||
ExtMarkLine *extline_ref(buf_T *buf, linenr_T lnum, bool put)
|
||||
ExtMarkLine *extmarkline_ref(buf_T *buf, linenr_T lnum, bool put)
|
||||
{
|
||||
kbtree_t(extlines) *b = &buf->b_extlines;
|
||||
kbtree_t(extmarklines) *b = &buf->b_extlines;
|
||||
ExtMarkLine t, **pp;
|
||||
t.lnum = lnum;
|
||||
|
||||
pp = kb_get(extlines, b, &t);
|
||||
pp = kb_get(extmarklines, b, &t);
|
||||
if (!pp) {
|
||||
if (!put) {
|
||||
return NULL;
|
||||
|
@ -1225,34 +1101,32 @@ ExtMarkLine *extline_ref(buf_T *buf, linenr_T lnum, bool put)
|
|||
ExtMarkLine *p = xcalloc(sizeof(ExtMarkLine), 1);
|
||||
p->lnum = lnum;
|
||||
// p->items zero initialized
|
||||
kb_put(extlines, b, p);
|
||||
kb_put(extmarklines, b, p);
|
||||
return p;
|
||||
}
|
||||
// Return existing
|
||||
return *pp;
|
||||
}
|
||||
|
||||
void extline_free(ExtMarkLine *extline)
|
||||
void extmarkline_free(ExtMarkLine *extmarkline)
|
||||
{
|
||||
kb_destroy(markitems, (&extline->items));
|
||||
xfree(extline);
|
||||
kb_destroy(markitems, (&extmarkline->items));
|
||||
xfree(extmarkline);
|
||||
}
|
||||
|
||||
/// Put an extmark into a line,
|
||||
///
|
||||
/// caller must ensure combination of id and ns_id isn't in use.
|
||||
void extmark_put(colnr_T col,
|
||||
uint64_t id,
|
||||
ExtMarkLine *extline,
|
||||
uint64_t ns)
|
||||
void extmark_put(colnr_T col, uint64_t id,
|
||||
ExtMarkLine *extmarkline, uint64_t ns)
|
||||
{
|
||||
ExtendedMark t;
|
||||
t.col = col;
|
||||
t.mark_id = id;
|
||||
t.line = extline;
|
||||
t.line = extmarkline;
|
||||
t.ns_id = ns;
|
||||
|
||||
kbtree_t(markitems) *b = &(extline->items);
|
||||
kbtree_t(markitems) *b = &(extmarkline->items);
|
||||
// kb_put requries the key to not be there
|
||||
assert(!kb_getp(markitems, b, &t));
|
||||
|
||||
|
|
|
@ -14,16 +14,17 @@
|
|||
|
||||
// see FOR_ALL_? for documentation
|
||||
#define FOR_ALL_EXTMARKLINES(buf, l_lnum, u_lnum, code)\
|
||||
kbitr_t(extlines) itr;\
|
||||
kbitr_t(extmarklines) itr;\
|
||||
ExtMarkLine t;\
|
||||
t.lnum = l_lnum;\
|
||||
if (!kb_itr_get(extlines, &buf->b_extlines, &t, &itr)) { \
|
||||
kb_itr_next(extlines, &buf->b_extlines, &itr);\
|
||||
if (!kb_itr_get(extmarklines, &buf->b_extlines, &t, &itr)) { \
|
||||
kb_itr_next(extmarklines, &buf->b_extlines, &itr);\
|
||||
}\
|
||||
ExtMarkLine *extline;\
|
||||
for (; kb_itr_valid(&itr); kb_itr_next(extlines, &buf->b_extlines, &itr)) { \
|
||||
extline = kb_itr_key(&itr);\
|
||||
if (extline->lnum > u_lnum) { \
|
||||
ExtMarkLine *extmarkline;\
|
||||
for (; kb_itr_valid(&itr); kb_itr_next(extmarklines, \
|
||||
&buf->b_extlines, &itr)) { \
|
||||
extmarkline = kb_itr_key(&itr);\
|
||||
if (extmarkline->lnum > u_lnum) { \
|
||||
break;\
|
||||
}\
|
||||
code;\
|
||||
|
@ -31,16 +32,17 @@
|
|||
|
||||
// see FOR_ALL_? for documentation
|
||||
#define FOR_ALL_EXTMARKLINES_PREV(buf, l_lnum, u_lnum, code)\
|
||||
kbitr_t(extlines) itr;\
|
||||
kbitr_t(extmarklines) itr;\
|
||||
ExtMarkLine t;\
|
||||
t.lnum = u_lnum;\
|
||||
if (!kb_itr_get(extlines, &buf->b_extlines, &t, &itr)) { \
|
||||
kb_itr_prev(extlines, &buf->b_extlines, &itr);\
|
||||
if (!kb_itr_get(extmarklines, &buf->b_extlines, &t, &itr)) { \
|
||||
kb_itr_prev(extmarklines, &buf->b_extlines, &itr);\
|
||||
}\
|
||||
ExtMarkLine *extline;\
|
||||
for (; kb_itr_valid(&itr); kb_itr_prev(extlines, &buf->b_extlines, &itr)) { \
|
||||
extline = kb_itr_key(&itr);\
|
||||
if (extline->lnum < l_lnum) { \
|
||||
ExtMarkLine *extmarkline;\
|
||||
for (; kb_itr_valid(&itr); kb_itr_prev(extmarklines, \
|
||||
&buf->b_extlines, &itr)) { \
|
||||
extmarkline = kb_itr_key(&itr);\
|
||||
if (extmarkline->lnum < l_lnum) { \
|
||||
break;\
|
||||
}\
|
||||
code;\
|
||||
|
@ -54,14 +56,14 @@
|
|||
mt.mark_id = 0;\
|
||||
mt.line = NULL;\
|
||||
FOR_ALL_EXTMARKLINES(buf, l_lnum, u_lnum, { \
|
||||
mt.col = (extline->lnum != l_lnum) ? MINCOL : l_col;\
|
||||
if (!kb_itr_get(markitems, &extline->items, mt, &mitr)) { \
|
||||
kb_itr_next(markitems, &extline->items, &mitr);\
|
||||
mt.col = (extmarkline->lnum != l_lnum) ? MINCOL : l_col;\
|
||||
if (!kb_itr_get(markitems, &extmarkline->items, mt, &mitr)) { \
|
||||
kb_itr_next(markitems, &extmarkline->items, &mitr);\
|
||||
} \
|
||||
ExtendedMark *extmark;\
|
||||
for (; \
|
||||
kb_itr_valid(&mitr); \
|
||||
kb_itr_next(markitems, &extline->items, &mitr)) { \
|
||||
kb_itr_next(markitems, &extmarkline->items, &mitr)) { \
|
||||
extmark = &kb_itr_key(&mitr);\
|
||||
if (extmark->line->lnum == u_lnum \
|
||||
&& extmark->col > u_col) { \
|
||||
|
@ -79,14 +81,14 @@
|
|||
mt.mark_id = sizeof(uint64_t);\
|
||||
mt.ns_id = ns;\
|
||||
FOR_ALL_EXTMARKLINES_PREV(buf, l_lnum, u_lnum, { \
|
||||
mt.col = (extline->lnum != u_lnum) ? MAXCOL : u_col;\
|
||||
if (!kb_itr_get(markitems, &extline->items, mt, &mitr)) { \
|
||||
kb_itr_prev(markitems, &extline->items, &mitr);\
|
||||
mt.col = (extmarkline->lnum != u_lnum) ? MAXCOL : u_col;\
|
||||
if (!kb_itr_get(markitems, &extmarkline->items, mt, &mitr)) { \
|
||||
kb_itr_prev(markitems, &extmarkline->items, &mitr);\
|
||||
} \
|
||||
ExtendedMark *extmark;\
|
||||
for (; \
|
||||
kb_itr_valid(&mitr); \
|
||||
kb_itr_prev(markitems, &extline->items, &mitr)) { \
|
||||
kb_itr_prev(markitems, &extmarkline->items, &mitr)) { \
|
||||
extmark = &kb_itr_key(&mitr);\
|
||||
if (extmark->line->lnum == l_lnum \
|
||||
&& extmark->col < l_col) { \
|
||||
|
@ -104,14 +106,14 @@
|
|||
mt.mark_id = 0;\
|
||||
mt.line = NULL;\
|
||||
mt.col = l_col;\
|
||||
colnr_T extline_u_col = u_col;\
|
||||
colnr_T extmarkline_u_col = u_col;\
|
||||
if (!kb_itr_get(markitems, &items, mt, &mitr)) { \
|
||||
kb_itr_next(markitems, &items, &mitr);\
|
||||
} \
|
||||
ExtendedMark *extmark;\
|
||||
for (; kb_itr_valid(&mitr); kb_itr_next(markitems, &items, &mitr)) { \
|
||||
extmark = &kb_itr_key(&mitr);\
|
||||
if (extmark->col > extline_u_col) { \
|
||||
if (extmark->col > extmarkline_u_col) { \
|
||||
break;\
|
||||
}\
|
||||
code;\
|
||||
|
@ -125,7 +127,6 @@ typedef struct ExtmarkNs { // For namespacing extmarks
|
|||
|
||||
|
||||
typedef kvec_t(ExtendedMark *) ExtmarkArray;
|
||||
typedef kvec_t(ExtMarkLine *) ExtlineArray;
|
||||
|
||||
|
||||
// Undo/redo extmarks
|
||||
|
@ -138,6 +139,7 @@ typedef enum {
|
|||
} ExtmarkOp;
|
||||
|
||||
|
||||
// adjust line numbers only, corresponding to mark_adjust call
|
||||
typedef struct {
|
||||
linenr_T line1;
|
||||
linenr_T line2;
|
||||
|
@ -145,6 +147,7 @@ typedef struct {
|
|||
long amount_after;
|
||||
} Adjust;
|
||||
|
||||
// adjust columns after split/join line, like mark_col_adjust
|
||||
typedef struct {
|
||||
linenr_T lnum;
|
||||
colnr_T mincol;
|
||||
|
@ -152,6 +155,7 @@ typedef struct {
|
|||
long lnum_amount;
|
||||
} ColAdjust;
|
||||
|
||||
// delete the columns between mincol and endcol
|
||||
typedef struct {
|
||||
linenr_T lnum;
|
||||
colnr_T mincol;
|
||||
|
@ -159,6 +163,7 @@ typedef struct {
|
|||
int eol;
|
||||
} ColAdjustDelete;
|
||||
|
||||
// adjust linenumbers after :move operation
|
||||
typedef struct {
|
||||
linenr_T line1;
|
||||
linenr_T line2;
|
||||
|
@ -168,6 +173,9 @@ typedef struct {
|
|||
linenr_T extra;
|
||||
} AdjustMove;
|
||||
|
||||
// TODO(bfredl): reconsider if we really should track mark creation/updating
|
||||
// itself, these are not really "edit" operation.
|
||||
// extmark was created
|
||||
typedef struct {
|
||||
uint64_t ns_id;
|
||||
uint64_t mark_id;
|
||||
|
@ -175,6 +183,7 @@ typedef struct {
|
|||
colnr_T col;
|
||||
} ExtmarkSet;
|
||||
|
||||
// extmark was updated
|
||||
typedef struct {
|
||||
uint64_t ns_id;
|
||||
uint64_t mark_id;
|
||||
|
@ -184,6 +193,7 @@ typedef struct {
|
|||
colnr_T col;
|
||||
} ExtmarkUpdate;
|
||||
|
||||
// copied mark before deletion (as operation is destructive)
|
||||
typedef struct {
|
||||
uint64_t ns_id;
|
||||
uint64_t mark_id;
|
||||
|
@ -191,6 +201,8 @@ typedef struct {
|
|||
colnr_T col;
|
||||
} ExtmarkCopy;
|
||||
|
||||
// also used as part of :move operation? probably can be simplified to one
|
||||
// event.
|
||||
typedef struct {
|
||||
linenr_T l_lnum;
|
||||
colnr_T l_col;
|
||||
|
@ -200,6 +212,8 @@ typedef struct {
|
|||
colnr_T p_col;
|
||||
} ExtmarkCopyPlace;
|
||||
|
||||
// extmark was cleared.
|
||||
// TODO(bfredl): same reconsideration as for ExtmarkSet/ExtmarkUpdate
|
||||
typedef struct {
|
||||
uint64_t ns_id;
|
||||
linenr_T l_lnum;
|
||||
|
@ -220,6 +234,7 @@ typedef enum {
|
|||
kExtmarkClear,
|
||||
} UndoObjectType;
|
||||
|
||||
// TODO(bfredl): reduce the number of undo action types
|
||||
struct undo_object {
|
||||
UndoObjectType type;
|
||||
union {
|
||||
|
|
|
@ -43,8 +43,8 @@ typedef struct ExtMarkLine
|
|||
kbtree_t(markitems) items;
|
||||
} ExtMarkLine;
|
||||
|
||||
#define extline_cmp(a, b) (kb_generic_cmp((a)->lnum, (b)->lnum))
|
||||
KBTREE_INIT(extlines, ExtMarkLine *, extline_cmp, 10)
|
||||
#define EXTMARKLINE_CMP(a, b) (kb_generic_cmp((a)->lnum, (b)->lnum))
|
||||
KBTREE_INIT(extmarklines, ExtMarkLine *, EXTMARKLINE_CMP, 10)
|
||||
|
||||
|
||||
typedef struct undo_object ExtmarkUndoObject;
|
||||
|
|
|
@ -127,30 +127,6 @@ static char opchars[][3] =
|
|||
{ Ctrl_X, NUL, false }, // OP_NR_SUB
|
||||
};
|
||||
|
||||
char *nvim_lltoa(int64_t val, int base)
|
||||
{
|
||||
static char buf[64] = { 0 };
|
||||
|
||||
int i = 62;
|
||||
int sign = (val < 0);
|
||||
if (sign) {
|
||||
val = -val;
|
||||
}
|
||||
|
||||
if (val == 0) {
|
||||
return "0";
|
||||
}
|
||||
|
||||
for (; val && i ; i--, val /= base) {
|
||||
buf[i] = "0123456789abcdef"[val % base];
|
||||
}
|
||||
|
||||
if (sign) {
|
||||
buf[i--] = '-';
|
||||
}
|
||||
return &buf[i+1];
|
||||
}
|
||||
|
||||
/*
|
||||
* Translate a command name into an operator type.
|
||||
* Must only be called with a valid operator name!
|
||||
|
@ -332,13 +308,8 @@ void shift_line(
|
|||
} else {
|
||||
(void)set_indent(count, call_changed_bytes ? SIN_CHANGED : 0);
|
||||
|
||||
colnr_T col_amount;
|
||||
colnr_T mincol = (curwin->w_cursor.col + 1) -p_sw;
|
||||
if (left) {
|
||||
col_amount = -p_sw;
|
||||
} else {
|
||||
col_amount = p_sw;
|
||||
}
|
||||
colnr_T col_amount = left ? -p_sw : p_sw;
|
||||
extmark_col_adjust(curbuf,
|
||||
curwin->w_cursor.lnum,
|
||||
mincol,
|
||||
|
@ -519,10 +490,7 @@ static void shift_block(oparg_T *oap, int amount)
|
|||
curwin->w_cursor.col = oldcol;
|
||||
p_ri = old_p_ri;
|
||||
|
||||
colnr_T col_amount = p_sw;
|
||||
if (left) {
|
||||
col_amount = -col_amount;
|
||||
}
|
||||
colnr_T col_amount = left ? -p_sw : p_sw;
|
||||
extmark_col_adjust(curbuf, curwin->w_cursor.lnum,
|
||||
curwin->w_cursor.col, 0, col_amount, kExtmarkUndo);
|
||||
}
|
||||
|
@ -1669,7 +1637,7 @@ int op_delete(oparg_T *oap)
|
|||
|
||||
curpos = curwin->w_cursor; // remember curwin->w_cursor
|
||||
curwin->w_cursor.lnum++;
|
||||
del_lines(oap->line_count - 2, true);
|
||||
del_lines(oap->line_count - 2, false);
|
||||
|
||||
// delete from start of line until op_end
|
||||
n = (oap->end.col + 1 - !oap->inclusive);
|
||||
|
@ -1715,12 +1683,7 @@ setmarks:
|
|||
|
||||
lnum = curwin->w_cursor.lnum;
|
||||
if (oap->is_VIsual == false) {
|
||||
// for some reason we required this :/
|
||||
endcol = endcol - 1;
|
||||
// for some reason we required this :/
|
||||
if (endcol < mincol) {
|
||||
endcol = mincol;
|
||||
}
|
||||
endcol = MAX(endcol - 1, mincol);
|
||||
}
|
||||
extmark_col_adjust_delete(curbuf, lnum, mincol, endcol, kExtmarkUndo, 0);
|
||||
}
|
||||
|
@ -2787,8 +2750,6 @@ static void do_autocmd_textyankpost(oparg_T *oap, yankreg_T *reg)
|
|||
}
|
||||
|
||||
|
||||
|
||||
// Function length couldn't be over 500 lines..
|
||||
static void extmarks_do_put(int dir,
|
||||
size_t totlen,
|
||||
MotionType y_type,
|
||||
|
@ -2796,12 +2757,7 @@ static void extmarks_do_put(int dir,
|
|||
colnr_T col)
|
||||
{
|
||||
// adjust extmarks
|
||||
colnr_T col_amount;
|
||||
if (dir == FORWARD) {
|
||||
col_amount = (colnr_T)(totlen-1);
|
||||
} else {
|
||||
col_amount = (colnr_T)totlen;
|
||||
}
|
||||
colnr_T col_amount = (colnr_T)(dir == FORWARD ? totlen-1 : totlen);
|
||||
// Move extmark with char put
|
||||
if (y_type == kMTCharWise) {
|
||||
extmark_col_adjust(curbuf, lnum, col, 0, col_amount, kExtmarkUndo);
|
||||
|
@ -3869,11 +3825,6 @@ int do_join(size_t count,
|
|||
* should not really be a problem.
|
||||
*/
|
||||
|
||||
linenr_T lnum;
|
||||
colnr_T mincol;
|
||||
long lnum_amount;
|
||||
long col_amount;
|
||||
|
||||
for (t = (linenr_T)count - 1;; t--) {
|
||||
cend -= currsize;
|
||||
memmove(cend, curr, (size_t)currsize);
|
||||
|
@ -3885,10 +3836,10 @@ int do_join(size_t count,
|
|||
// If deleting more spaces than adding, the cursor moves no more than
|
||||
// what is added if it is inside these spaces.
|
||||
const int spaces_removed = (int)((curr - curr_start) - spaces[t]);
|
||||
lnum = curwin->w_cursor.lnum + t;
|
||||
mincol = (colnr_T)0;
|
||||
lnum_amount = (linenr_T)-t;
|
||||
col_amount = (long)(cend - newp - spaces_removed);
|
||||
linenr_T lnum = curwin->w_cursor.lnum + t;
|
||||
colnr_T mincol = (colnr_T)0;
|
||||
long lnum_amount = (linenr_T)-t;
|
||||
long col_amount = (long)(cend - newp - spaces_removed);
|
||||
|
||||
mark_col_adjust(lnum, mincol, lnum_amount, col_amount, spaces_removed,
|
||||
kExtmarkUndo);
|
||||
|
@ -4675,7 +4626,7 @@ void op_addsub(oparg_T *oap, linenr_T Prenum1, bool g_cmd)
|
|||
int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
|
||||
{
|
||||
int col;
|
||||
char_u *buf1;
|
||||
char_u *buf1 = NULL;
|
||||
char_u buf2[NUMBUFLEN];
|
||||
int pre; // 'X' or 'x': hex; '0': octal; 'B' or 'b': bin
|
||||
static bool hexupper = false; // 0xABC
|
||||
|
@ -4984,7 +4935,6 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
|
|||
*ptr = NUL;
|
||||
STRCAT(buf1, buf2);
|
||||
ins_str(buf1); // insert the new number
|
||||
xfree(buf1);
|
||||
endpos = curwin->w_cursor;
|
||||
if (curwin->w_cursor.col) {
|
||||
curwin->w_cursor.col--;
|
||||
|
@ -4998,15 +4948,15 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
|
|||
curbuf->b_op_end.col--;
|
||||
}
|
||||
|
||||
if (did_change) {
|
||||
// if buf1 wasn't allocated, only a singe ASCII char was changed in-place.
|
||||
if (did_change && buf1 != NULL) {
|
||||
extmark_col_adjust_delete(curbuf,
|
||||
pos->lnum,
|
||||
startpos.col + 2,
|
||||
endpos.col + 1 + length,
|
||||
kExtmarkUndo,
|
||||
0);
|
||||
long col_amount = (long)strlen(nvim_lltoa((int64_t)n, 10));
|
||||
col_amount = negative ? col_amount + 1 : col_amount;
|
||||
long col_amount = (long)STRLEN(buf1);
|
||||
extmark_col_adjust(curbuf,
|
||||
pos->lnum,
|
||||
startpos.col + 1,
|
||||
|
@ -5016,6 +4966,7 @@ int do_addsub(int op_type, pos_T *pos, int length, linenr_T Prenum1)
|
|||
}
|
||||
|
||||
theend:
|
||||
xfree(buf1);
|
||||
if (visual) {
|
||||
curwin->w_cursor = save_cursor;
|
||||
} else if (did_change) {
|
||||
|
|
|
@ -2849,7 +2849,6 @@ u_freeentries(
|
|||
u_freeentry(uep, uep->ue_size);
|
||||
}
|
||||
|
||||
// TODO(timeyyy): is this the correct place? ...
|
||||
kv_destroy(uhp->uh_extmark);
|
||||
|
||||
#ifdef U_DEBUG
|
||||
|
@ -3049,7 +3048,7 @@ list_T *u_eval_tree(const u_header_T *const first_uhp)
|
|||
|
||||
// Given the buffer, Return the undo header. If none is set, set one first.
|
||||
// NULL will be returned if e.g undolevels = -1 (undo disabled)
|
||||
u_header_T *force_get_undo_header(buf_T *buf)
|
||||
u_header_T *u_force_get_undo_header(buf_T *buf)
|
||||
{
|
||||
u_header_T *uhp = NULL;
|
||||
if (buf->b_u_curhead != NULL) {
|
||||
|
@ -3064,8 +3063,8 @@ u_header_T *force_get_undo_header(buf_T *buf)
|
|||
uhp = buf->b_u_curhead;
|
||||
if (!uhp) {
|
||||
uhp = buf->b_u_newhead;
|
||||
if (get_undolevel() > 0) {
|
||||
assert(uhp);
|
||||
if (get_undolevel() > 0 && !uhp) {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -8,22 +8,22 @@ local expect = helpers.expect
|
|||
describe('multi-line regexp', function()
|
||||
setup(clear)
|
||||
|
||||
it('is working #fail', function()
|
||||
it('is working', function()
|
||||
insert([[
|
||||
1 aa
|
||||
bb
|
||||
cc
|
||||
2 dd
|
||||
ee
|
||||
3 ef
|
||||
gh
|
||||
4 ij
|
||||
5 a8
|
||||
8b c9
|
||||
9d
|
||||
6 e7
|
||||
77f
|
||||
xxxxx]])
|
||||
1 aa
|
||||
bb
|
||||
cc
|
||||
2 dd
|
||||
ee
|
||||
3 ef
|
||||
gh
|
||||
4 ij
|
||||
5 a8
|
||||
8b c9
|
||||
9d
|
||||
6 e7
|
||||
77f
|
||||
xxxxx]])
|
||||
|
||||
-- Test if replacing a line break works with a back reference
|
||||
feed([[:/^1/,/^2/s/\n\(.\)/ \1/<cr>]])
|
||||
|
|
|
@ -131,7 +131,7 @@ describe(":substitute, inccommand=split interactivity", function()
|
|||
end)
|
||||
end)
|
||||
|
||||
describe(":substitute, 'inccommand' preserves #inc", function()
|
||||
describe(":substitute, 'inccommand' preserves", function()
|
||||
before_each(clear)
|
||||
|
||||
it('listed buffers (:ls)', function()
|
||||
|
@ -293,7 +293,7 @@ describe(":substitute, 'inccommand' preserves #inc", function()
|
|||
|
||||
end)
|
||||
|
||||
describe(":substitute, 'inccommand' preserves undo #inc", function()
|
||||
describe(":substitute, 'inccommand' preserves undo", function()
|
||||
local cases = { "", "split", "nosplit" }
|
||||
|
||||
local substrings = {
|
||||
|
@ -1962,7 +1962,7 @@ describe(":substitute", function()
|
|||
clear()
|
||||
end)
|
||||
|
||||
it("inccommand=split, highlights multiline substitutions #inc2", function()
|
||||
it("inccommand=split, highlights multiline substitutions", function()
|
||||
common_setup(screen, "split", multiline_text)
|
||||
feed("gg")
|
||||
|
||||
|
@ -2024,7 +2024,7 @@ describe(":substitute", function()
|
|||
]])
|
||||
end)
|
||||
|
||||
it("inccommand=nosplit, highlights multiline substitutions #inc2", function()
|
||||
it("inccommand=nosplit, highlights multiline substitutions", function()
|
||||
common_setup(screen, "nosplit", multiline_text)
|
||||
feed("gg")
|
||||
|
||||
|
@ -2117,7 +2117,7 @@ describe(":substitute", function()
|
|||
]])
|
||||
end)
|
||||
|
||||
it("inccommand=split, with \\zs #inc", function()
|
||||
it("inccommand=split, with \\zs", function()
|
||||
common_setup(screen, "split", multiline_text)
|
||||
feed("gg")
|
||||
|
||||
|
@ -2141,7 +2141,7 @@ describe(":substitute", function()
|
|||
]])
|
||||
end)
|
||||
|
||||
it("inccommand=nosplit, with \\zs #inc", function()
|
||||
it("inccommand=nosplit, with \\zs", function()
|
||||
common_setup(screen, "nosplit", multiline_text)
|
||||
feed("gg")
|
||||
|
||||
|
@ -2212,7 +2212,7 @@ describe(":substitute", function()
|
|||
]])
|
||||
end)
|
||||
|
||||
it("inccommand=split, contraction of lines #inc2", function()
|
||||
it("inccommand=split, contraction of lines", function()
|
||||
local text = [[
|
||||
T T123 T T123 T2T TT T23423424
|
||||
x
|
||||
|
@ -2261,7 +2261,7 @@ describe(":substitute", function()
|
|||
]])
|
||||
end)
|
||||
|
||||
it("inccommand=nosplit, contraction of lines #inc2", function()
|
||||
it("inccommand=nosplit, contraction of lines", function()
|
||||
local text = [[
|
||||
T T123 T T123 T2T TT T23423424
|
||||
x
|
||||
|
|
|
@ -817,6 +817,7 @@ describe('ui/mouse/input', function()
|
|||
feed_command('syntax match NonText "cats" conceal cchar=X')
|
||||
feed_command('syntax match NonText "x" conceal cchar=>')
|
||||
|
||||
-- First column is there to retain the tabs.
|
||||
insert([[
|
||||
|Section *t1*
|
||||
| *t2* *t3* *t4*
|
||||
|
|
Loading…
Reference in New Issue