mirror of
https://github.com/neovim/neovim.git
synced 2025-02-25 18:55:25 -06:00
bufhl: new mechanism for plugins to add highlights to a buffer
This commit is contained in:
parent
18605d6785
commit
44b2cef83a
@ -19,6 +19,7 @@
|
|||||||
#include "nvim/mark.h"
|
#include "nvim/mark.h"
|
||||||
#include "nvim/fileio.h"
|
#include "nvim/fileio.h"
|
||||||
#include "nvim/move.h"
|
#include "nvim/move.h"
|
||||||
|
#include "nvim/syntax.h"
|
||||||
#include "nvim/window.h"
|
#include "nvim/window.h"
|
||||||
#include "nvim/undo.h"
|
#include "nvim/undo.h"
|
||||||
|
|
||||||
@ -514,6 +515,99 @@ ArrayOf(Integer, 2) buffer_get_mark(Buffer buffer, String name, Error *err)
|
|||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Adds a highlight to buffer.
|
||||||
|
///
|
||||||
|
/// This can be used for plugins which dynamically generate highlights to a
|
||||||
|
/// buffer (like a semantic highlighter or linter). The function adds a single
|
||||||
|
/// highlight to a buffer. Unlike matchaddpos() highlights follow changes to
|
||||||
|
/// line numbering (as lines are inserted/removed above the highlighted line),
|
||||||
|
/// like signs and marks do.
|
||||||
|
///
|
||||||
|
/// "src_id" is useful for batch deletion/updating of a set of highlights. When
|
||||||
|
/// called with src_id = 0, an unique source id is generated and returned.
|
||||||
|
/// Succesive calls can pass in it as "src_id" to add new highlights to the same
|
||||||
|
/// source group. All highlights in the same group can then be cleared with
|
||||||
|
/// buffer_clear_highlight. If the highlight never will be manually deleted
|
||||||
|
/// pass in -1 for "src_id".
|
||||||
|
///
|
||||||
|
/// If "hl_group" is the empty string no highlight is added, but a new src_id
|
||||||
|
/// is still returned. This is useful for an external plugin to synchrounously
|
||||||
|
/// request an unique src_id at initialization, and later asynchronously add and
|
||||||
|
/// clear highlights in response to buffer changes.
|
||||||
|
///
|
||||||
|
/// @param buffer The buffer handle
|
||||||
|
/// @param src_id Source group to use or 0 to use a new group,
|
||||||
|
/// or -1 for ungrouped highlight
|
||||||
|
/// @param hl_group Name of the highlight group to use
|
||||||
|
/// @param line The line to highlight
|
||||||
|
/// @param col_start Start of range of columns to highlight
|
||||||
|
/// @param col_end End of range of columns to highlight,
|
||||||
|
/// or -1 to highlight to end of line
|
||||||
|
/// @param[out] err Details of an error that may have occurred
|
||||||
|
/// @return The src_id that was used
|
||||||
|
Integer buffer_add_highlight(Buffer buffer,
|
||||||
|
Integer src_id,
|
||||||
|
String hl_group,
|
||||||
|
Integer line,
|
||||||
|
Integer col_start,
|
||||||
|
Integer col_end,
|
||||||
|
Error *err)
|
||||||
|
{
|
||||||
|
buf_T *buf = find_buffer_by_handle(buffer, err);
|
||||||
|
if (!buf) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line < 0 || line >= MAXLNUM) {
|
||||||
|
api_set_error(err, Validation, _("Line number outside range"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (col_start < 0 || col_start > MAXCOL) {
|
||||||
|
api_set_error(err, Validation, _("Column value outside range"));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (col_end < 0 || col_end > MAXCOL) {
|
||||||
|
col_end = MAXCOL;
|
||||||
|
}
|
||||||
|
|
||||||
|
int hlg_id = syn_name2id((char_u*)hl_group.data);
|
||||||
|
src_id = bufhl_add_hl(buf, (int)src_id, hlg_id, (linenr_T)line+1,
|
||||||
|
(colnr_T)col_start+1, (colnr_T)col_end);
|
||||||
|
return src_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Clears highlights from a given source group and a range of lines
|
||||||
|
///
|
||||||
|
/// To clear a source group in the entire buffer, pass in 1 and -1 to
|
||||||
|
/// line_start and line_end respectively.
|
||||||
|
///
|
||||||
|
/// @param buffer The buffer handle
|
||||||
|
/// @param src_id Highlight source group to clear, or -1 to clear all groups.
|
||||||
|
/// @param line_start Start of range of lines to clear
|
||||||
|
/// @param line_end End of range of lines to clear (exclusive)
|
||||||
|
/// or -1 to clear to end of file.
|
||||||
|
/// @param[out] err Details of an error that may have occurred
|
||||||
|
void buffer_clear_highlight(Buffer buffer,
|
||||||
|
Integer src_id,
|
||||||
|
Integer line_start,
|
||||||
|
Integer line_end,
|
||||||
|
Error *err)
|
||||||
|
{
|
||||||
|
buf_T *buf = find_buffer_by_handle(buffer, err);
|
||||||
|
if (!buf) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line_start < 0 || line_start >= MAXLNUM) {
|
||||||
|
api_set_error(err, Validation, _("Line number outside range"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (line_end < 0 || line_end > MAXLNUM) {
|
||||||
|
line_end = MAXLNUM;
|
||||||
|
}
|
||||||
|
|
||||||
|
bufhl_clear_line_range(buf, (int)src_id, (int)line_start+1, (int)line_end);
|
||||||
|
}
|
||||||
|
|
||||||
// Check if deleting lines made the cursor position invalid.
|
// Check if deleting lines made the cursor position invalid.
|
||||||
// Changed the lines from "lo" to "hi" and added "extra" lines (negative if
|
// Changed the lines from "lo" to "hi" and added "extra" lines (negative if
|
||||||
|
@ -580,16 +580,17 @@ free_buffer_stuff (
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
if (free_options) {
|
if (free_options) {
|
||||||
clear_wininfo(buf); /* including window-local options */
|
clear_wininfo(buf); // including window-local options
|
||||||
free_buf_options(buf, TRUE);
|
free_buf_options(buf, true);
|
||||||
ga_clear(&buf->b_s.b_langp);
|
ga_clear(&buf->b_s.b_langp);
|
||||||
}
|
}
|
||||||
vars_clear(&buf->b_vars->dv_hashtab); /* free all internal variables */
|
vars_clear(&buf->b_vars->dv_hashtab); // free all internal variables
|
||||||
hash_init(&buf->b_vars->dv_hashtab);
|
hash_init(&buf->b_vars->dv_hashtab);
|
||||||
uc_clear(&buf->b_ucmds); /* clear local user commands */
|
uc_clear(&buf->b_ucmds); // clear local user commands
|
||||||
buf_delete_signs(buf); /* delete any signs */
|
buf_delete_signs(buf); // delete any signs
|
||||||
map_clear_int(buf, MAP_ALL_MODES, TRUE, FALSE); /* clear local mappings */
|
bufhl_clear_all(buf); // delete any highligts
|
||||||
map_clear_int(buf, MAP_ALL_MODES, TRUE, TRUE); /* clear local abbrevs */
|
map_clear_int(buf, MAP_ALL_MODES, true, false); // clear local mappings
|
||||||
|
map_clear_int(buf, MAP_ALL_MODES, true, true); // clear local abbrevs
|
||||||
xfree(buf->b_start_fenc);
|
xfree(buf->b_start_fenc);
|
||||||
buf->b_start_fenc = NULL;
|
buf->b_start_fenc = NULL;
|
||||||
}
|
}
|
||||||
@ -4870,6 +4871,224 @@ void sign_mark_adjust(linenr_T line1, linenr_T line2, long amount, long amount_a
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// bufhl: plugin highlights associated with a buffer
|
||||||
|
|
||||||
|
/// Adds a highlight to buffer.
|
||||||
|
///
|
||||||
|
/// Unlike matchaddpos() highlights follow changes to line numbering (as lines
|
||||||
|
/// are inserted/removed above the highlighted line), like signs and marks do.
|
||||||
|
///
|
||||||
|
/// When called with "src_id" set to 0, a unique source id is generated and
|
||||||
|
/// returned. Succesive calls can pass it in as "src_id" to add new highlights
|
||||||
|
/// to the same source group. All highlights in the same group can be cleared
|
||||||
|
/// at once. If the highlight never will be manually deleted pass in -1 for
|
||||||
|
/// "src_id"
|
||||||
|
///
|
||||||
|
/// if "hl_id" or "lnum" is invalid no highlight is added, but a new src_id
|
||||||
|
/// is still returned.
|
||||||
|
///
|
||||||
|
/// @param buf The buffer to add highlights to
|
||||||
|
/// @param src_id src_id to use or 0 to use a new src_id group,
|
||||||
|
/// or -1 for ungrouped highlight.
|
||||||
|
/// @param hl_id Id of the highlight group to use
|
||||||
|
/// @param lnum The line to highlight
|
||||||
|
/// @param col_start First column to highlight
|
||||||
|
/// @param col_end The last column to highlight,
|
||||||
|
/// or -1 to highlight to end of line
|
||||||
|
/// @return The src_id that was used
|
||||||
|
int bufhl_add_hl(buf_T *buf,
|
||||||
|
int src_id,
|
||||||
|
int hl_id,
|
||||||
|
linenr_T lnum,
|
||||||
|
colnr_T col_start,
|
||||||
|
colnr_T col_end) {
|
||||||
|
static int next_src_id = 1;
|
||||||
|
if (src_id == 0) {
|
||||||
|
src_id = next_src_id++;
|
||||||
|
}
|
||||||
|
if (hl_id <= 0) {
|
||||||
|
// no highlight group or invalid line, just return src_id
|
||||||
|
return src_id;
|
||||||
|
}
|
||||||
|
if (!buf->b_bufhl_info) {
|
||||||
|
buf->b_bufhl_info = map_new(linenr_T, bufhl_vec_T)();
|
||||||
|
}
|
||||||
|
bufhl_vec_T* lineinfo = map_ref(linenr_T, bufhl_vec_T)(buf->b_bufhl_info,
|
||||||
|
lnum, true);
|
||||||
|
|
||||||
|
bufhl_hl_item_T *hlentry = kv_pushp(bufhl_hl_item_T, *lineinfo);
|
||||||
|
hlentry->src_id = src_id;
|
||||||
|
hlentry->hl_id = hl_id;
|
||||||
|
hlentry->start = col_start;
|
||||||
|
hlentry->stop = col_end;
|
||||||
|
|
||||||
|
if (0 < lnum && lnum <= buf->b_ml.ml_line_count) {
|
||||||
|
changed_lines_buf(buf, lnum, lnum+1, 0);
|
||||||
|
redraw_buf_later(buf, VALID);
|
||||||
|
}
|
||||||
|
return src_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Clear bufhl highlights from a given source group and range of lines.
|
||||||
|
///
|
||||||
|
/// @param buf The buffer to remove highlights from
|
||||||
|
/// @param src_id highlight source group to clear, or -1 to clear all groups.
|
||||||
|
/// @param line_start first line to clear
|
||||||
|
/// @param line_end last line to clear or MAXLNUM to clear to end of file.
|
||||||
|
void bufhl_clear_line_range(buf_T *buf,
|
||||||
|
int src_id,
|
||||||
|
linenr_T line_start,
|
||||||
|
linenr_T line_end) {
|
||||||
|
if (!buf->b_bufhl_info) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
linenr_T line;
|
||||||
|
linenr_T first_changed = MAXLNUM, last_changed = -1;
|
||||||
|
// In the case line_start - line_end << bufhl_info->size
|
||||||
|
// it might be better to reverse this, i e loop over the lines
|
||||||
|
// to clear on.
|
||||||
|
bufhl_vec_T unused;
|
||||||
|
map_foreach(buf->b_bufhl_info, line, unused, {
|
||||||
|
(void)unused;
|
||||||
|
if (line_start <= line && line <= line_end) {
|
||||||
|
if (bufhl_clear_line(buf->b_bufhl_info, src_id, line)) {
|
||||||
|
if (line > last_changed) {
|
||||||
|
last_changed = line;
|
||||||
|
}
|
||||||
|
if (line < first_changed) {
|
||||||
|
first_changed = line;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if (last_changed != -1) {
|
||||||
|
changed_lines_buf(buf, first_changed, last_changed+1, 0);
|
||||||
|
redraw_buf_later(buf, VALID);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Clear bufhl highlights from a given source group and given line
|
||||||
|
///
|
||||||
|
/// @param bufhl_info The highlight info for the buffer
|
||||||
|
/// @param src_id Highlight source group to clear, or -1 to clear all groups.
|
||||||
|
/// @param lnum Linenr where the highlight should be cleared
|
||||||
|
static bool bufhl_clear_line(bufhl_info_T *bufhl_info, int src_id, int lnum) {
|
||||||
|
bufhl_vec_T* lineinfo = map_ref(linenr_T, bufhl_vec_T)(bufhl_info,
|
||||||
|
lnum, false);
|
||||||
|
size_t oldsize = kv_size(*lineinfo);
|
||||||
|
if (src_id < 0) {
|
||||||
|
kv_size(*lineinfo) = 0;
|
||||||
|
} else {
|
||||||
|
size_t newind = 0;
|
||||||
|
for (size_t i = 0; i < kv_size(*lineinfo); i++) {
|
||||||
|
if (kv_A(*lineinfo, i).src_id != src_id) {
|
||||||
|
if (i != newind) {
|
||||||
|
kv_A(*lineinfo, newind) = kv_A(*lineinfo, i);
|
||||||
|
}
|
||||||
|
newind++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
kv_size(*lineinfo) = newind;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (kv_size(*lineinfo) == 0) {
|
||||||
|
kv_destroy(*lineinfo);
|
||||||
|
map_del(linenr_T, bufhl_vec_T)(bufhl_info, lnum);
|
||||||
|
}
|
||||||
|
return kv_size(*lineinfo) != oldsize;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove all highlights and free the highlight data
|
||||||
|
void bufhl_clear_all(buf_T* buf) {
|
||||||
|
if (!buf->b_bufhl_info) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
bufhl_clear_line_range(buf, -1, 1, MAXLNUM);
|
||||||
|
map_free(linenr_T, bufhl_vec_T)(buf->b_bufhl_info);
|
||||||
|
buf->b_bufhl_info = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adjust a placed highlight for inserted/deleted lines.
|
||||||
|
void bufhl_mark_adjust(buf_T* buf,
|
||||||
|
linenr_T line1,
|
||||||
|
linenr_T line2,
|
||||||
|
long amount,
|
||||||
|
long amount_after) {
|
||||||
|
if (!buf->b_bufhl_info) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
bufhl_info_T *newmap = map_new(linenr_T, bufhl_vec_T)();
|
||||||
|
linenr_T line;
|
||||||
|
bufhl_vec_T lineinfo;
|
||||||
|
map_foreach(buf->b_bufhl_info, line, lineinfo, {
|
||||||
|
if (line >= line1 && line <= line2) {
|
||||||
|
if (amount == MAXLNUM) {
|
||||||
|
bufhl_clear_line(buf->b_bufhl_info, -1, line);
|
||||||
|
continue;
|
||||||
|
} else {
|
||||||
|
line += amount;
|
||||||
|
}
|
||||||
|
} else if (line > line2) {
|
||||||
|
line += amount_after;
|
||||||
|
}
|
||||||
|
map_put(linenr_T, bufhl_vec_T)(newmap, line, lineinfo);
|
||||||
|
});
|
||||||
|
map_free(linenr_T, bufhl_vec_T)(buf->b_bufhl_info);
|
||||||
|
buf->b_bufhl_info = newmap;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Get highlights to display at a specific line
|
||||||
|
///
|
||||||
|
/// @param buf The buffer handle
|
||||||
|
/// @param lnum The line number
|
||||||
|
/// @param[out] info The highligts for the line
|
||||||
|
/// @return true if there was highlights to display
|
||||||
|
bool bufhl_start_line(buf_T *buf, linenr_T lnum, bufhl_lineinfo_T *info) {
|
||||||
|
if (!buf->b_bufhl_info) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
info->valid_to = -1;
|
||||||
|
info->entries = map_get(linenr_T, bufhl_vec_T)(buf->b_bufhl_info, lnum);
|
||||||
|
return kv_size(info->entries) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// get highlighting at column col
|
||||||
|
///
|
||||||
|
/// It is is assumed this will be called with
|
||||||
|
/// non-decreasing column nrs, so that it is
|
||||||
|
/// possible to only recalculate highlights
|
||||||
|
/// at endpoints.
|
||||||
|
///
|
||||||
|
/// @param info The info returned by bufhl_start_line
|
||||||
|
/// @param col The column to get the attr for
|
||||||
|
/// @return The highilight attr to display at the column
|
||||||
|
int bufhl_get_attr(bufhl_lineinfo_T *info, colnr_T col) {
|
||||||
|
if (col <= info->valid_to) {
|
||||||
|
return info->current;
|
||||||
|
}
|
||||||
|
int attr = 0;
|
||||||
|
info->valid_to = MAXCOL;
|
||||||
|
for (size_t i = 0; i < kv_size(info->entries); i++) {
|
||||||
|
bufhl_hl_item_T entry = kv_A(info->entries, i);
|
||||||
|
if (entry.start <= col && col <= entry.stop) {
|
||||||
|
int entry_attr = syn_id2attr(entry.hl_id);
|
||||||
|
attr = hl_combine_attr(attr, entry_attr);
|
||||||
|
if (entry.stop < info->valid_to) {
|
||||||
|
info->valid_to = entry.stop;
|
||||||
|
}
|
||||||
|
} else if (col < entry.start && entry.start-1 < info->valid_to) {
|
||||||
|
info->valid_to = entry.start-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
info->current = attr;
|
||||||
|
return attr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Set 'buflisted' for curbuf to "on" and trigger autocommands if it changed.
|
* Set 'buflisted' for curbuf to "on" and trigger autocommands if it changed.
|
||||||
*/
|
*/
|
||||||
|
@ -28,6 +28,8 @@ typedef struct file_buffer buf_T; // Forward declaration
|
|||||||
#include "nvim/profile.h"
|
#include "nvim/profile.h"
|
||||||
// for String
|
// for String
|
||||||
#include "nvim/api/private/defs.h"
|
#include "nvim/api/private/defs.h"
|
||||||
|
// for Map(K, V)
|
||||||
|
#include "nvim/map.h"
|
||||||
|
|
||||||
#define MODIFIABLE(buf) (!buf->terminal && buf->b_p_ma)
|
#define MODIFIABLE(buf) (!buf->terminal && buf->b_p_ma)
|
||||||
|
|
||||||
@ -101,6 +103,11 @@ typedef int scid_T; /* script ID */
|
|||||||
// for signlist_T
|
// for signlist_T
|
||||||
#include "nvim/sign_defs.h"
|
#include "nvim/sign_defs.h"
|
||||||
|
|
||||||
|
// for bufhl_*_T
|
||||||
|
#include "nvim/bufhl_defs.h"
|
||||||
|
|
||||||
|
typedef Map(linenr_T, bufhl_vec_T) bufhl_info_T;
|
||||||
|
|
||||||
// for FileID
|
// for FileID
|
||||||
#include "nvim/os/fs_defs.h"
|
#include "nvim/os/fs_defs.h"
|
||||||
|
|
||||||
@ -754,6 +761,8 @@ struct file_buffer {
|
|||||||
dict_T *additional_data; // Additional data from shada file if any.
|
dict_T *additional_data; // Additional data from shada file if any.
|
||||||
|
|
||||||
int b_mapped_ctrl_c; // modes where CTRL-C is mapped
|
int b_mapped_ctrl_c; // modes where CTRL-C is mapped
|
||||||
|
|
||||||
|
bufhl_info_T *b_bufhl_info; // buffer stored highlights
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
25
src/nvim/bufhl_defs.h
Normal file
25
src/nvim/bufhl_defs.h
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
#ifndef NVIM_BUFHL_DEFS_H
|
||||||
|
#define NVIM_BUFHL_DEFS_H
|
||||||
|
|
||||||
|
#include "nvim/pos.h"
|
||||||
|
#include "nvim/lib/kvec.h"
|
||||||
|
// bufhl: buffer specific highlighting
|
||||||
|
|
||||||
|
struct bufhl_hl_item
|
||||||
|
{
|
||||||
|
int src_id;
|
||||||
|
int hl_id; // highlight group
|
||||||
|
colnr_T start; // first column to highlight
|
||||||
|
colnr_T stop; // last column to highlight
|
||||||
|
};
|
||||||
|
typedef struct bufhl_hl_item bufhl_hl_item_T;
|
||||||
|
|
||||||
|
typedef kvec_t(struct bufhl_hl_item) bufhl_vec_T;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bufhl_vec_T entries;
|
||||||
|
int current;
|
||||||
|
colnr_T valid_to;
|
||||||
|
} bufhl_lineinfo_T;
|
||||||
|
|
||||||
|
#endif // NVIM_BUFHL_DEFS_H
|
@ -4320,7 +4320,7 @@ static void ex_unmap(exarg_T *eap)
|
|||||||
*/
|
*/
|
||||||
static void ex_mapclear(exarg_T *eap)
|
static void ex_mapclear(exarg_T *eap)
|
||||||
{
|
{
|
||||||
map_clear(eap->cmd, eap->arg, eap->forceit, FALSE);
|
map_clear_mode(eap->cmd, eap->arg, eap->forceit, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -4328,7 +4328,7 @@ static void ex_mapclear(exarg_T *eap)
|
|||||||
*/
|
*/
|
||||||
static void ex_abclear(exarg_T *eap)
|
static void ex_abclear(exarg_T *eap)
|
||||||
{
|
{
|
||||||
map_clear(eap->cmd, eap->arg, TRUE, TRUE);
|
map_clear_mode(eap->cmd, eap->arg, true, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ex_autocmd(exarg_T *eap)
|
static void ex_autocmd(exarg_T *eap)
|
||||||
|
@ -2915,9 +2915,9 @@ do_map (
|
|||||||
did_it = TRUE;
|
did_it = TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (mp->m_mode == 0) { /* entry can be deleted */
|
if (mp->m_mode == 0) { // entry can be deleted
|
||||||
map_free(mpp);
|
mapblock_free(mpp);
|
||||||
continue; /* continue with *mpp */
|
continue; // continue with *mpp
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -3012,7 +3012,7 @@ theend:
|
|||||||
* Delete one entry from the abbrlist or maphash[].
|
* Delete one entry from the abbrlist or maphash[].
|
||||||
* "mpp" is a pointer to the m_next field of the PREVIOUS entry!
|
* "mpp" is a pointer to the m_next field of the PREVIOUS entry!
|
||||||
*/
|
*/
|
||||||
static void map_free(mapblock_T **mpp)
|
static void mapblock_free(mapblock_T **mpp)
|
||||||
{
|
{
|
||||||
mapblock_T *mp;
|
mapblock_T *mp;
|
||||||
|
|
||||||
@ -3080,7 +3080,7 @@ int get_map_mode(char_u **cmdp, int forceit)
|
|||||||
* Clear all mappings or abbreviations.
|
* Clear all mappings or abbreviations.
|
||||||
* 'abbr' should be FALSE for mappings, TRUE for abbreviations.
|
* 'abbr' should be FALSE for mappings, TRUE for abbreviations.
|
||||||
*/
|
*/
|
||||||
void map_clear(char_u *cmdp, char_u *arg, int forceit, int abbr)
|
void map_clear_mode(char_u *cmdp, char_u *arg, int forceit, int abbr)
|
||||||
{
|
{
|
||||||
int mode;
|
int mode;
|
||||||
int local;
|
int local;
|
||||||
@ -3132,8 +3132,8 @@ map_clear_int (
|
|||||||
mp = *mpp;
|
mp = *mpp;
|
||||||
if (mp->m_mode & mode) {
|
if (mp->m_mode & mode) {
|
||||||
mp->m_mode &= ~mode;
|
mp->m_mode &= ~mode;
|
||||||
if (mp->m_mode == 0) { /* entry can be deleted */
|
if (mp->m_mode == 0) { // entry can be deleted
|
||||||
map_free(mpp);
|
mapblock_free(mpp);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -77,10 +77,10 @@ int main() {
|
|||||||
(v).items[(v).size++] = (x); \
|
(v).items[(v).size++] = (x); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define kv_pushp(type, v) (((v).size == (v).capacity)? \
|
#define kv_pushp(type, v) ((((v).size == (v).capacity)? \
|
||||||
((v).capacity = ((v).capacity? (v).capacity<<1 : 8), \
|
((v).capacity = ((v).capacity? (v).capacity<<1 : 8), \
|
||||||
(v).items = (type*)xrealloc((v).items, sizeof(type) * (v).capacity), 0) \
|
(v).items = (type*)xrealloc((v).items, sizeof(type) * (v).capacity), 0) \
|
||||||
: 0), ((v).items + ((v).size++))
|
: 0), ((v).items + ((v).size++)))
|
||||||
|
|
||||||
#define kv_a(type, v, i) (((v).capacity <= (size_t)(i)? \
|
#define kv_a(type, v, i) (((v).capacity <= (size_t)(i)? \
|
||||||
((v).capacity = (v).size = (i) + 1, kv_roundup32((v).capacity), \
|
((v).capacity = (v).size = (i) + 1, kv_roundup32((v).capacity), \
|
||||||
|
@ -18,6 +18,9 @@
|
|||||||
#define uint32_t_eq kh_int_hash_equal
|
#define uint32_t_eq kh_int_hash_equal
|
||||||
#define int_hash kh_int_hash_func
|
#define int_hash kh_int_hash_func
|
||||||
#define int_eq kh_int_hash_equal
|
#define int_eq kh_int_hash_equal
|
||||||
|
#define linenr_T_hash kh_int_hash_func
|
||||||
|
#define linenr_T_eq kh_int_hash_equal
|
||||||
|
|
||||||
|
|
||||||
#if defined(ARCH_64)
|
#if defined(ARCH_64)
|
||||||
#define ptr_t_hash(key) uint64_t_hash((uint64_t)key)
|
#define ptr_t_hash(key) uint64_t_hash((uint64_t)key)
|
||||||
@ -78,6 +81,25 @@
|
|||||||
return rv; \
|
return rv; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
|
U *map_##T##_##U##_ref(Map(T, U) *map, T key, bool put) \
|
||||||
|
{ \
|
||||||
|
int ret; \
|
||||||
|
khiter_t k; \
|
||||||
|
if (put) { \
|
||||||
|
k = kh_put(T##_##U##_map, map->table, key, &ret); \
|
||||||
|
if (ret) { \
|
||||||
|
kh_val(map->table, k) = INITIALIZER(T, U); \
|
||||||
|
} \
|
||||||
|
} else { \
|
||||||
|
k = kh_get(T##_##U##_map, map->table, key); \
|
||||||
|
if (k == kh_end(map->table)) { \
|
||||||
|
return NULL; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
return &kh_val(map->table, k); \
|
||||||
|
} \
|
||||||
|
\
|
||||||
U map_##T##_##U##_del(Map(T, U) *map, T key) \
|
U map_##T##_##U##_del(Map(T, U) *map, T key) \
|
||||||
{ \
|
{ \
|
||||||
U rv = INITIALIZER(T, U); \
|
U rv = INITIALIZER(T, U); \
|
||||||
@ -118,3 +140,5 @@ MAP_IMPL(ptr_t, ptr_t, DEFAULT_INITIALIZER)
|
|||||||
MAP_IMPL(uint64_t, ptr_t, DEFAULT_INITIALIZER)
|
MAP_IMPL(uint64_t, ptr_t, DEFAULT_INITIALIZER)
|
||||||
#define MSGPACK_HANDLER_INITIALIZER {.fn = NULL, .async = false}
|
#define MSGPACK_HANDLER_INITIALIZER {.fn = NULL, .async = false}
|
||||||
MAP_IMPL(String, MsgpackRpcRequestHandler, MSGPACK_HANDLER_INITIALIZER)
|
MAP_IMPL(String, MsgpackRpcRequestHandler, MSGPACK_HANDLER_INITIALIZER)
|
||||||
|
#define KVEC_INITIALIZER { .size = 0, .capacity = 0, .items = NULL }
|
||||||
|
MAP_IMPL(linenr_T, bufhl_vec_T, KVEC_INITIALIZER)
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include "nvim/map_defs.h"
|
#include "nvim/map_defs.h"
|
||||||
#include "nvim/api/private/defs.h"
|
#include "nvim/api/private/defs.h"
|
||||||
#include "nvim/msgpack_rpc/defs.h"
|
#include "nvim/msgpack_rpc/defs.h"
|
||||||
|
#include "nvim/bufhl_defs.h"
|
||||||
|
|
||||||
#define MAP_DECLS(T, U) \
|
#define MAP_DECLS(T, U) \
|
||||||
KHASH_DECLARE(T##_##U##_map, T, U) \
|
KHASH_DECLARE(T##_##U##_map, T, U) \
|
||||||
@ -19,6 +20,7 @@
|
|||||||
U map_##T##_##U##_get(Map(T, U) *map, T key); \
|
U map_##T##_##U##_get(Map(T, U) *map, T key); \
|
||||||
bool map_##T##_##U##_has(Map(T, U) *map, T key); \
|
bool map_##T##_##U##_has(Map(T, U) *map, T key); \
|
||||||
U map_##T##_##U##_put(Map(T, U) *map, T key, U value); \
|
U map_##T##_##U##_put(Map(T, U) *map, T key, U value); \
|
||||||
|
U *map_##T##_##U##_ref(Map(T, U) *map, T key, bool put); \
|
||||||
U map_##T##_##U##_del(Map(T, U) *map, T key); \
|
U map_##T##_##U##_del(Map(T, U) *map, T key); \
|
||||||
void map_##T##_##U##_clear(Map(T, U) *map);
|
void map_##T##_##U##_clear(Map(T, U) *map);
|
||||||
|
|
||||||
@ -28,12 +30,14 @@ MAP_DECLS(cstr_t, ptr_t)
|
|||||||
MAP_DECLS(ptr_t, ptr_t)
|
MAP_DECLS(ptr_t, ptr_t)
|
||||||
MAP_DECLS(uint64_t, ptr_t)
|
MAP_DECLS(uint64_t, ptr_t)
|
||||||
MAP_DECLS(String, MsgpackRpcRequestHandler)
|
MAP_DECLS(String, MsgpackRpcRequestHandler)
|
||||||
|
MAP_DECLS(linenr_T, bufhl_vec_T)
|
||||||
|
|
||||||
#define map_new(T, U) map_##T##_##U##_new
|
#define map_new(T, U) map_##T##_##U##_new
|
||||||
#define map_free(T, U) map_##T##_##U##_free
|
#define map_free(T, U) map_##T##_##U##_free
|
||||||
#define map_get(T, U) map_##T##_##U##_get
|
#define map_get(T, U) map_##T##_##U##_get
|
||||||
#define map_has(T, U) map_##T##_##U##_has
|
#define map_has(T, U) map_##T##_##U##_has
|
||||||
#define map_put(T, U) map_##T##_##U##_put
|
#define map_put(T, U) map_##T##_##U##_put
|
||||||
|
#define map_ref(T, U) map_##T##_##U##_ref
|
||||||
#define map_del(T, U) map_##T##_##U##_del
|
#define map_del(T, U) map_##T##_##U##_del
|
||||||
#define map_clear(T, U) map_##T##_##U##_clear
|
#define map_clear(T, U) map_##T##_##U##_clear
|
||||||
|
|
||||||
|
@ -922,6 +922,7 @@ void mark_adjust(linenr_T line1, linenr_T line2, long amount, long amount_after)
|
|||||||
}
|
}
|
||||||
|
|
||||||
sign_mark_adjust(line1, line2, amount, amount_after);
|
sign_mark_adjust(line1, line2, amount, amount_after);
|
||||||
|
bufhl_mark_adjust(curbuf, line1, line2, amount, amount_after);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* previous context mark */
|
/* previous context mark */
|
||||||
|
@ -1985,13 +1985,13 @@ changed_lines (
|
|||||||
changed_common(lnum, col, lnume, xtra);
|
changed_common(lnum, col, lnume, xtra);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
/// Mark line range in buffer as changed.
|
||||||
changed_lines_buf (
|
///
|
||||||
buf_T *buf,
|
/// @param buf the buffer where lines were changed
|
||||||
linenr_T lnum, /* first line with change */
|
/// @param lnum first line with change
|
||||||
linenr_T lnume, /* line below last changed line */
|
/// @param lnume line below last changed line
|
||||||
long xtra /* number of extra lines (negative when deleting) */
|
/// @param xtra number of extra lines (negative when deleting)
|
||||||
)
|
void changed_lines_buf(buf_T *buf, linenr_T lnum, linenr_T lnume, long xtra)
|
||||||
{
|
{
|
||||||
if (buf->b_mod_set) {
|
if (buf->b_mod_set) {
|
||||||
/* find the maximum area that must be redisplayed */
|
/* find the maximum area that must be redisplayed */
|
||||||
|
@ -2184,6 +2184,10 @@ win_line (
|
|||||||
int prev_c1 = 0; /* first composing char for prev_c */
|
int prev_c1 = 0; /* first composing char for prev_c */
|
||||||
int did_line_attr = 0;
|
int did_line_attr = 0;
|
||||||
|
|
||||||
|
bool has_bufhl = false; // this buffer has highlight matches
|
||||||
|
int bufhl_attr = 0; // attributes desired by bufhl
|
||||||
|
bufhl_lineinfo_T bufhl_info; // bufhl data for this line
|
||||||
|
|
||||||
/* draw_state: items that are drawn in sequence: */
|
/* draw_state: items that are drawn in sequence: */
|
||||||
#define WL_START 0 /* nothing done yet */
|
#define WL_START 0 /* nothing done yet */
|
||||||
# define WL_CMDLINE WL_START + 1 /* cmdline window column */
|
# define WL_CMDLINE WL_START + 1 /* cmdline window column */
|
||||||
@ -2244,6 +2248,11 @@ win_line (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (bufhl_start_line(wp->w_buffer, lnum, &bufhl_info)) {
|
||||||
|
has_bufhl = true;
|
||||||
|
extra_check = true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Check for columns to display for 'colorcolumn'. */
|
/* Check for columns to display for 'colorcolumn'. */
|
||||||
color_cols = wp->w_buffer->terminal ? NULL : wp->w_p_cc_cols;
|
color_cols = wp->w_buffer->terminal ? NULL : wp->w_p_cc_cols;
|
||||||
if (color_cols != NULL)
|
if (color_cols != NULL)
|
||||||
@ -3335,6 +3344,17 @@ win_line (
|
|||||||
char_attr = hl_combine_attr(spell_attr, char_attr);
|
char_attr = hl_combine_attr(spell_attr, char_attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (has_bufhl && v > 0) {
|
||||||
|
bufhl_attr = bufhl_get_attr(&bufhl_info, (colnr_T)v);
|
||||||
|
if (bufhl_attr != 0) {
|
||||||
|
if (!attr_pri) {
|
||||||
|
char_attr = hl_combine_attr(char_attr, bufhl_attr);
|
||||||
|
} else {
|
||||||
|
char_attr = hl_combine_attr(bufhl_attr, char_attr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (wp->w_buffer->terminal) {
|
if (wp->w_buffer->terminal) {
|
||||||
char_attr = hl_combine_attr(char_attr, term_attrs[vcol]);
|
char_attr = hl_combine_attr(char_attr, term_attrs[vcol]);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user