aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/nvim/api/extmark.c16
-rw-r--r--src/nvim/api/keysets.lua1
-rw-r--r--src/nvim/decoration.c15
-rw-r--r--src/nvim/decoration.h13
-rw-r--r--src/nvim/screen.c17
5 files changed, 58 insertions, 4 deletions
diff --git a/src/nvim/api/extmark.c b/src/nvim/api/extmark.c
index c02688a815..797b64e2af 100644
--- a/src/nvim/api/extmark.c
+++ b/src/nvim/api/extmark.c
@@ -467,6 +467,11 @@ Array nvim_buf_get_extmarks(Buffer buffer, Integer ns_id, Object start, Object e
/// as the mark and 'cursorline' is enabled.
/// Note: ranges are unsupported and decorations are only
/// applied to start_row
+/// - conceal: string which should be either empty or a single
+/// character. Enable concealing similar to |:syn-conceal|.
+/// When a character is supplied it is used as |:syn-cchar|.
+/// "hl_group" is used as highlight for the cchar if provided,
+/// otherwise it defaults to |hl-Conceal|.
///
/// @param[out] err Error details, if any
/// @return Id of the created/updated extmark
@@ -563,6 +568,17 @@ Integer nvim_buf_set_extmark(Buffer buffer, Integer ns_id, Integer line, Integer
}
}
+ if (opts->conceal.type == kObjectTypeString) {
+ String c = opts->conceal.data.string;
+ decor.conceal = true;
+ if (c.size) {
+ decor.conceal_char = utf_ptr2char((const char_u *)c.data);
+ }
+ } else if (HAS_KEY(opts->conceal)) {
+ api_set_error(err, kErrorTypeValidation, "conceal is not a String");
+ goto error;
+ }
+
if (opts->virt_text.type == kObjectTypeArray) {
decor.virt_text = parse_virt_text(opts->virt_text.data.array, err,
&decor.virt_text_width);
diff --git a/src/nvim/api/keysets.lua b/src/nvim/api/keysets.lua
index 435e8195dd..b6264cdfab 100644
--- a/src/nvim/api/keysets.lua
+++ b/src/nvim/api/keysets.lua
@@ -27,6 +27,7 @@ return {
"number_hl_group";
"line_hl_group";
"cursorline_hl_group";
+ "conceal";
};
keymap = {
"noremap";
diff --git a/src/nvim/decoration.c b/src/nvim/decoration.c
index fb709d12ff..a0f189ca38 100644
--- a/src/nvim/decoration.c
+++ b/src/nvim/decoration.c
@@ -312,6 +312,10 @@ next_mark:
int attr = 0;
size_t j = 0;
+ bool conceal = 0;
+ int conceal_char = 0;
+ int conceal_attr = 0;
+
for (size_t i = 0; i < kv_size(state->active); i++) {
DecorRange item = kv_A(state->active, i);
bool active = false, keep = true;
@@ -336,6 +340,14 @@ next_mark:
if (active && item.attr_id > 0) {
attr = hl_combine_attr(attr, item.attr_id);
}
+ if (active && item.decor.conceal) {
+ conceal = true;
+ if (item.start_row == state->row && item.start_col == col && item.decor.conceal_char) {
+ conceal_char = item.decor.conceal_char;
+ state->col_until = MIN(state->col_until, item.start_col);
+ conceal_attr = item.attr_id;
+ }
+ }
if ((item.start_row == state->row && item.start_col <= col)
&& kv_size(item.decor.virt_text)
&& item.decor.virt_text_pos == kVTOverlay && item.win_col == -1) {
@@ -349,6 +361,9 @@ next_mark:
}
kv_size(state->active) = j;
state->current = attr;
+ state->conceal = conceal;
+ state->conceal_char = conceal_char;
+ state->conceal_attr = conceal_attr;
return attr;
}
diff --git a/src/nvim/decoration.h b/src/nvim/decoration.h
index 8df53caa0a..97ab218f86 100644
--- a/src/nvim/decoration.h
+++ b/src/nvim/decoration.h
@@ -47,6 +47,7 @@ struct Decoration {
bool virt_text_hide;
bool hl_eol;
bool virt_lines_above;
+ bool conceal;
// TODO(bfredl): style, etc
DecorPriority priority;
int col; // fixed col value, like win_col
@@ -56,9 +57,13 @@ struct Decoration {
int number_hl_id;
int line_hl_id;
int cursorline_hl_id;
+ // TODO(bfredl): in principle this should be a schar_T, but we
+ // probably want some kind of glyph cache for that..
+ int conceal_char;
};
-#define DECORATION_INIT { KV_INITIAL_VALUE, KV_INITIAL_VALUE, 0, kVTEndOfLine, kHlModeUnknown, \
- false, false, false, DECOR_PRIORITY_BASE, 0, 0, NULL, 0, 0, 0, 0 }
+#define DECORATION_INIT { KV_INITIAL_VALUE, KV_INITIAL_VALUE, 0, kVTEndOfLine, \
+ kHlModeUnknown, false, false, false, false, DECOR_PRIORITY_BASE, \
+ 0, 0, NULL, 0, 0, 0, 0, 0 }
typedef struct {
int start_row;
@@ -80,6 +85,10 @@ typedef struct {
int col_until;
int current;
int eol_col;
+
+ bool conceal;
+ int conceal_char;
+ int conceal_attr;
} DecorState;
EXTERN DecorState decor_state INIT(= { 0 });
diff --git a/src/nvim/screen.c b/src/nvim/screen.c
index 60de4e479e..0e1f469a4b 100644
--- a/src/nvim/screen.c
+++ b/src/nvim/screen.c
@@ -2682,6 +2682,8 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
// Repeat for the whole displayed line.
for (;;) {
int has_match_conc = 0; ///< match wants to conceal
+ int decor_conceal = 0;
+
bool did_decrement_ptr = false;
// Skip this quickly when working on the text.
@@ -3506,6 +3508,11 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
char_attr = hl_combine_attr(extmark_attr, char_attr);
}
}
+
+ decor_conceal = decor_state.conceal;
+ if (decor_conceal && decor_state.conceal_char) {
+ decor_conceal = 2; // really??
+ }
}
// Found last space before word: check for line break.
@@ -3809,19 +3816,25 @@ static int win_line(win_T *wp, linenr_T lnum, int startrow, int endrow, bool noc
if (wp->w_p_cole > 0
&& (wp != curwin || lnum != wp->w_cursor.lnum
|| conceal_cursor_line(wp))
- && ((syntax_flags & HL_CONCEAL) != 0 || has_match_conc > 0)
+ && ((syntax_flags & HL_CONCEAL) != 0 || has_match_conc > 0 || decor_conceal > 0)
&& !(lnum_in_visual_area
&& vim_strchr(wp->w_p_cocu, 'v') == NULL)) {
char_attr = conceal_attr;
- if ((prev_syntax_id != syntax_seqnr || has_match_conc > 1)
+ if ((prev_syntax_id != syntax_seqnr || has_match_conc > 1 || decor_conceal > 1)
&& (syn_get_sub_char() != NUL
|| (has_match_conc && match_conc)
+ || (decor_conceal && decor_state.conceal_char)
|| wp->w_p_cole == 1)
&& wp->w_p_cole != 3) {
// First time at this concealed item: display one
// character.
if (has_match_conc && match_conc) {
c = match_conc;
+ } else if (decor_conceal && decor_state.conceal_char) {
+ c = decor_state.conceal_char;
+ if (decor_state.conceal_attr) {
+ char_attr = decor_state.conceal_attr;
+ }
} else if (syn_get_sub_char() != NUL) {
c = syn_get_sub_char();
} else if (wp->w_p_lcs_chars.conceal != NUL) {