Skip to content

Commit 21c0472

Browse files
committed
feat: add support for rendering text with props
Introduce the ability to render text with attached text properties. Renderers may now also return list of dictionaries where each line of text can include text properties for additional text styling capabilities. This change is backwards compatible with existing renderers; they will continue to work as before. These features, however, are not supported in Neovim. The semantics of this feature was inspired by popup_create(), which can accept a list of dictionaries with a 'text' and 'props' key.
1 parent 1856f03 commit 21c0472

File tree

6 files changed

+93
-4
lines changed

6 files changed

+93
-4
lines changed

autoload/fern.vim

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ call s:Config.config(expand('<sfile>:p'), {
3636
\ 'default_exclude': '',
3737
\ 'renderer': 'default',
3838
\ 'renderers': {},
39+
\ 'enable_textprop_support': 0,
3940
\ 'comparator': 'default',
4041
\ 'comparators': {},
4142
\ 'drawer_width': 30,

autoload/fern/internal/buffer.vim

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,40 @@ function! fern#internal#buffer#replace(bufnr, content) abort
55
let modifiable_saved = getbufvar(a:bufnr, '&modifiable')
66
try
77
call setbufvar(a:bufnr, '&modifiable', 1)
8-
call setbufline(a:bufnr, 1, a:content)
9-
call deletebufline(a:bufnr, len(a:content) + 1, '$')
8+
9+
if g:fern#enable_textprop_support
10+
call s:replace_buffer_content(a:bufnr, a:content)
11+
else
12+
call setbufline(a:bufnr, 1, a:content)
13+
call deletebufline(a:bufnr, len(a:content) + 1, '$')
14+
endif
1015
finally
1116
call setbufvar(a:bufnr, '&modifiable', modifiable_saved)
1217
call setbufvar(a:bufnr, '&modified', modified_saved)
1318
endtry
1419
endfunction
1520

21+
" Replace buffer content with lines of text with (optional) text properties.
22+
function! s:replace_buffer_content(bufnr, content) abort
23+
for lnum in range(len(a:content))
24+
let line = a:content[lnum]
25+
let [text, props] = type(line) is# v:t_dict
26+
\ ? [line.text, get(line, 'props', [])]
27+
\ : [line, []]
28+
29+
call setbufline(a:bufnr, lnum + 1, text)
30+
31+
if exists('*prop_add')
32+
for prop in props
33+
let prop.bufnr = a:bufnr
34+
call prop_add(lnum + 1, prop.col, prop)
35+
endfor
36+
endif
37+
endfor
38+
39+
call deletebufline(a:bufnr, len(a:content) + 1, '$')
40+
endfunction
41+
1642
function! fern#internal#buffer#open(bufname, ...) abort
1743
let options = extend({
1844
\ 'opener': 'edit',

autoload/fern/internal/drawer/hover_popup.vim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ function! s:show() abort
7474
call setbufline('%', 1, line)
7575
call helper.fern.renderer.syntax()
7676
call helper.fern.renderer.highlight()
77-
syntax clear FernRoot
77+
syntax clear FernRootSymbol
7878
syntax clear FernRootText
7979

8080
setlocal nowrap cursorline noswapfile nobuflisted buftype=nofile bufhidden=hide

doc/fern-develop.txt

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,15 @@ nodes as a tree.
558558

559559
*fern-develop-renderer.render()*
560560
.render({nodes})
561-
Return a promise which is resolved to a list of |String|.
561+
Return a promise which is resolved to:
562+
563+
a list of |String|, or
564+
if |g:fern#enable_textprop_support| is 1, a list of |Dictionary|
565+
with the following entries:
566+
text |String| with the text to display.
567+
props A list of text properties (|Dictionary|). Optional. Not supported
568+
for Neovim. Each entry is a dictionary, like the third argument
569+
of |prop_add()|, but specifying a column with a "col" entry.
562570

563571
Change (v1.6.0):~
564572
Second argument ({marks}) has removed.

doc/fern.txt

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -523,6 +523,11 @@ VARIABLE *fern-variable*
523523
is a key of |g:fern#renderers|.
524524
Default: "default"
525525

526+
*g:fern#enable_textprop_support*
527+
If set to 1, renderers may return lines of text with text properties.
528+
May incur slight performance penalty. See |fern-develop-renderer|.
529+
Default: 0
530+
526531
*g:fern#comparator*
527532
A |String| name of comparator used to sort tree items. Allowed value
528533
is a key of |g:fern#comparators|.

test/fern/internal/buffer.vimspec

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,16 @@ Describe fern#internal#buffer
55

66
Before
77
%bwipeout!
8+
if !has('nvim')
9+
call prop_type_add('test_prop', { 'highlight': 'Question' })
10+
endif
11+
End
12+
13+
After
14+
let g:fern#enable_textprop_support = 0
15+
if !has('nvim')
16+
call prop_type_delete('test_prop')
17+
endif
818
End
919

1020
Describe #replace()
@@ -115,6 +125,45 @@ Describe fern#internal#buffer
115125
\])
116126
Assert Equals(getbufvar(bufnr, '&modified'), 1)
117127
End
128+
129+
It should replace buffer content with text and properties
130+
if has('nvim')
131+
Assert Skip('text properties are only supported in vim')
132+
endif
133+
134+
let g:fern#enable_textprop_support = 1
135+
136+
let bufnr = bufnr('%')
137+
call setline(1, [
138+
\ "Hello",
139+
\ "Darkness",
140+
\ "My",
141+
\ "Old",
142+
\ "Friend",
143+
\])
144+
new
145+
call fern#internal#buffer#replace(bufnr, [
146+
\ { 'text': 'Empty Props', 'props': [] },
147+
\ { 'text': 'Undefined Props' },
148+
\ { 'text': 'With Properties!', 'props':
149+
\ [{ 'col': 1, 'length': 4, 'type': 'test_prop' }]
150+
\ },
151+
\])
152+
Assert Equals(getbufline(bufnr, 1, '$'), [
153+
\ "Empty Props",
154+
\ "Undefined Props",
155+
\ "With Properties!",
156+
\])
157+
158+
Assert True(empty(prop_list(1, { 'bufnr': bufnr })))
159+
Assert True(empty(prop_list(2, { 'bufnr': bufnr })))
160+
161+
let result_props = prop_list(3, { 'bufnr': bufnr })
162+
Assert Equal(len(result_props), 1)
163+
Assert Equal(result_props[0].col, 1)
164+
Assert Equal(result_props[0].length, 4)
165+
Assert Equal(result_props[0].type, 'test_prop')
166+
End
118167
End
119168

120169
Describe #open()

0 commit comments

Comments
 (0)