Skip to content

Commit 1cf4533

Browse files
authored
Merge pull request #126 from lambdalisue/mark-on-sign
Use sign instead to display marks and add "badge" support for 3rd parties
2 parents e6f1e05 + 3d5da30 commit 1cf4533

File tree

17 files changed

+278
-115
lines changed

17 files changed

+278
-115
lines changed

autoload/fern.vim

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,5 @@ call s:Config.config(expand('<sfile>:p'), {
3030
\ 'comparators': get(g:, 'fern#internal#core#comparators', {}),
3131
\ 'drawer_width': 30,
3232
\ 'drawer_keep': v:false,
33+
\ 'mark_symbol': '*',
3334
\})

autoload/fern/helper/async.vim

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
let s:Promise = vital#fern#import('Async.Promise')
2+
let s:AsyncLambda = vital#fern#import('Async.Lambda')
23

34
function! fern#helper#async#new(helper) abort
45
let async = extend({ 'helper': a:helper }, s:async)
@@ -17,17 +18,28 @@ function! s:async_redraw() abort dict
1718
let helper = self.helper
1819
let fern = helper.fern
1920
return s:Promise.resolve()
20-
\.then({ -> fern.renderer.render(
21-
\ fern.visible_nodes,
22-
\ fern.marks,
23-
\ )
24-
\})
21+
\.then({ -> fern.renderer.render(fern.visible_nodes) })
2522
\.then({ v -> fern#internal#buffer#replace(helper.bufnr, v) })
23+
\.then({ -> helper.async.remark() })
2624
\.then({ -> fern#hook#emit('viewer:redraw', helper) })
2725
\.finally({ -> Profile() })
2826
endfunction
2927
let s:async.redraw = funcref('s:async_redraw')
3028

29+
function! s:async_remark() abort dict
30+
let Profile = fern#profile#start('fern#helper:helper.async.remark')
31+
let helper = self.helper
32+
let fern = helper.fern
33+
let marks = fern.marks
34+
return s:Promise.resolve(fern.visible_nodes)
35+
\.then(s:AsyncLambda.map_f({ n, i -> index(marks, n.__key) isnot# -1 ? i + 1 : 0 }))
36+
\.then(s:AsyncLambda.filter_f({ v -> v isnot# 0 }))
37+
\.then({ v -> fern#internal#mark#replace(helper.bufnr, v) })
38+
\.then({ -> fern#hook#emit('viewer:remark', helper) })
39+
\.finally({ -> Profile() })
40+
endfunction
41+
let s:async.remark = funcref('s:async_remark')
42+
3143
function! s:async_set_mark(key, value) abort dict
3244
let helper = self.helper
3345
let fern = helper.fern

autoload/fern/internal/mark.vim

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
function! fern#internal#mark#replace(bufnr, lnums) abort
2+
call execute(printf('sign unplace * group=fern-mark buffer=%d', a:bufnr))
3+
call map(a:lnums, { _, v -> execute(printf(
4+
\ 'sign place %d group=fern-mark line=%d name=FernSignMarked buffer=%d',
5+
\ v,
6+
\ v,
7+
\ a:bufnr,
8+
\))})
9+
endfunction
10+
11+
function! s:define_signs() abort
12+
execute printf(
13+
\ 'sign define FernSignMarked text=%s linehl=FernMarkedLine texthl=FernMarkedText',
14+
\ g:fern#mark_symbol,
15+
\)
16+
endfunction
17+
18+
function! s:define_highlight() abort
19+
highlight default link FernMarkedLine Title
20+
highlight default link FernMarkedText Title
21+
endfunction
22+
23+
augroup fern_mark_internal
24+
autocmd!
25+
autocmd ColorScheme * call s:define_highlight()
26+
augroup END
27+
28+
call s:define_signs()
29+
call s:define_highlight()

autoload/fern/internal/node.vim

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ endfunction
207207
function! s:new(node, ...) abort
208208
let node = extend(a:node, {
209209
\ 'label': get(a:node, 'label', a:node.name),
210+
\ 'badge': get(a:node, 'badge', ''),
210211
\ 'hidden': get(a:node, 'hidden', 0),
211212
\ 'bufname': get(a:node, 'bufname', v:null),
212213
\ 'concealed': get(a:node, 'concealed', {}),

autoload/fern/internal/spinner.vim

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ function! s:update(timer, spinner, bufnr) abort
2525
return
2626
endif
2727
let frame = a:spinner.next()
28-
call execute(printf('sign unplace * group=fern buffer=%d', a:bufnr))
28+
call execute(printf('sign unplace * group=fern-spinner buffer=%d', a:bufnr))
2929
let info = getwininfo(winid)[0]
3030
let rng = sort([info.topline, info.botline], 'n')
3131
for lnum in range(rng[0], rng[1])
@@ -36,7 +36,7 @@ function! s:update(timer, spinner, bufnr) abort
3636
continue
3737
endif
3838
call execute(printf(
39-
\ 'sign place %d group=fern line=%d name=%s buffer=%d',
39+
\ 'sign place %d group=fern-spinner line=%d name=%s buffer=%d',
4040
\ lnum,
4141
\ lnum,
4242
\ frame,

autoload/fern/internal/viewer.vim

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,10 +67,18 @@ function! s:init() abort
6767
call fern#internal#drawer#init()
6868
call fern#internal#spinner#start()
6969
call helper.fern.renderer.highlight()
70+
" Notify plugins
71+
call fern#hook#emit('renderer:highlight', helper)
72+
" Notify users
73+
doautocmd <nomodeline> User FernHighlight
7074

7175
" now the buffer is ready so set filetype to emit FileType
7276
setlocal filetype=fern
7377
call helper.fern.renderer.syntax()
78+
" Notify plugins
79+
call fern#hook#emit('renderer:syntax', helper)
80+
" Notify users
81+
doautocmd <nomodeline> User FernSyntax
7482
call fern#internal#action#init()
7583

7684
let reveal = split(fri.fragment, '/')
@@ -106,7 +114,10 @@ function! s:BufReadCmd() abort
106114
let helper = fern#helper#new()
107115
setlocal filetype=fern
108116
call helper.fern.renderer.syntax()
117+
" Notify plugins
109118
call fern#hook#emit('renderer:syntax', helper)
119+
" Notify users
120+
doautocmd <nomodeline> User FernSyntax
110121
let root = helper.sync.get_root_node()
111122
let cursor = get(b:, 'fern_cursor', getcurpos())
112123
call s:Promise.resolve()
@@ -121,5 +132,14 @@ endfunction
121132
function! s:ColorScheme() abort
122133
let helper = fern#helper#new()
123134
call helper.fern.renderer.highlight()
135+
" Notify plugins
124136
call fern#hook#emit('renderer:highlight', helper)
137+
" Notify users
138+
doautocmd <nomodeline> User FernHighlight
125139
endfunction
140+
141+
augroup fern-internal-viewer-internal
142+
autocmd!
143+
autocmd User FernSyntax :
144+
autocmd User FernHighlight :
145+
augroup END

autoload/fern/mapping/mark.vim

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ function! s:map_mark_set(helper) abort
3030
return s:Promise.reject('no node found on a cursor line')
3131
endif
3232
return a:helper.async.set_mark(node.__key, 1)
33-
\.then({ -> a:helper.async.redraw() })
33+
\.then({ -> a:helper.async.remark() })
3434
endfunction
3535

3636
function! s:map_mark_unset(helper) abort
@@ -39,7 +39,7 @@ function! s:map_mark_unset(helper) abort
3939
return s:Promise.reject('no node found on a cursor line')
4040
endif
4141
return a:helper.async.set_mark(node.__key, 0)
42-
\.then({ -> a:helper.async.redraw() })
42+
\.then({ -> a:helper.async.remark() })
4343
endfunction
4444

4545
function! s:map_mark_toggle(helper) abort
@@ -55,5 +55,6 @@ function! s:map_mark_toggle(helper) abort
5555
endfunction
5656

5757
function! s:map_mark_clear(helper) abort
58-
return a:helper.update_marks([])
58+
return a:helper.async.update_marks([])
59+
\.then({ -> a:helper.async.remark() })
5960
endfunction

autoload/fern/mapping/open.vim

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,7 +82,7 @@ function! s:map_open(helper, opener) abort
8282
noautocmd call win_gotoid(winid)
8383
noautocmd call win_gotoid(winid_fern)
8484
return a:helper.async.update_marks([])
85-
\.then({ -> a:helper.async.redraw() })
85+
\.then({ -> a:helper.async.remark() })
8686
catch
8787
return s:Promise.reject(v:exception)
8888
endtry

autoload/fern/renderer/default.vim

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
let s:Config = vital#fern#import('Config')
22
let s:AsyncLambda = vital#fern#import('Async.Lambda')
33

4-
let s:PATTERN = '^$~.*[]\'
4+
let s:ESCAPE_PATTERN = '^$~.*[]\'
55
let s:STATUS_NONE = g:fern#STATUS_NONE
66
let s:STATUS_COLLAPSED = g:fern#STATUS_COLLAPSED
77

@@ -15,19 +15,17 @@ function! fern#renderer#default#new() abort
1515
\}
1616
endfunction
1717

18-
function! s:render(nodes, marks) abort
18+
function! s:render(nodes) abort
1919
let options = {
2020
\ 'leading': g:fern#renderer#default#leading,
2121
\ 'root_symbol': g:fern#renderer#default#root_symbol,
2222
\ 'leaf_symbol': g:fern#renderer#default#leaf_symbol,
2323
\ 'expanded_symbol': g:fern#renderer#default#expanded_symbol,
2424
\ 'collapsed_symbol': g:fern#renderer#default#collapsed_symbol,
25-
\ 'marked_symbol': g:fern#renderer#default#marked_symbol,
26-
\ 'unmarked_symbol': g:fern#renderer#default#unmarked_symbol,
2725
\}
2826
let base = len(a:nodes[0].__key)
2927
let Profile = fern#profile#start('fern#renderer#default#s:render')
30-
return s:AsyncLambda.map(copy(a:nodes), { v, -> s:render_node(v, a:marks, base, options) })
28+
return s:AsyncLambda.map(copy(a:nodes), { v, -> s:render_node(v, base, options) })
3129
\.finally({ -> Profile() })
3230
endfunction
3331

@@ -40,45 +38,46 @@ function! s:lnum(index) abort
4038
endfunction
4139

4240
function! s:syntax() abort
43-
syntax clear
4441
execute printf(
45-
\ 'syntax match FernLeaf /^\s*%s/',
46-
\ escape(g:fern#renderer#default#leaf_symbol, s:PATTERN),
42+
\ 'syntax match FernRootSymbol /\%%1l%s/ nextgroup=FernRootText',
43+
\ escape(g:fern#renderer#default#root_symbol, s:ESCAPE_PATTERN),
4744
\)
4845
execute printf(
49-
\ 'syntax match FernBranch /^\s*\%%(%s\|%s\).*/',
50-
\ escape(g:fern#renderer#default#collapsed_symbol, s:PATTERN),
51-
\ escape(g:fern#renderer#default#expanded_symbol, s:PATTERN),
46+
\ 'syntax match FernLeafSymbol /^\s*%s/ nextgroup=FernLeafText',
47+
\ escape(g:fern#renderer#default#leaf_symbol, s:ESCAPE_PATTERN),
5248
\)
53-
syntax match FernRoot /\%1l.*/
5449
execute printf(
55-
\ 'syntax match FernMarked /^%s.*/',
56-
\ escape(g:fern#renderer#default#marked_symbol, s:PATTERN),
50+
\ 'syntax match FernBranchSymbol /^\s*\%%(%s\|%s\)/ nextgroup=FernBranchText',
51+
\ escape(g:fern#renderer#default#collapsed_symbol, s:ESCAPE_PATTERN),
52+
\ escape(g:fern#renderer#default#expanded_symbol, s:ESCAPE_PATTERN),
5753
\)
54+
syntax match FernRootText /.*\ze .*$/ contained nextgroup=FernBadge
55+
syntax match FernLeafText /.*\ze .*$/ contained nextgroup=FernBadge
56+
syntax match FernBranchText /.*\ze .*$/ contained nextgroup=FernBadge
57+
syntax match FernBadge /.*/ contained
5858
endfunction
5959

6060
function! s:highlight() abort
61-
highlight default link FernRoot Directory
62-
highlight default link FernLeaf Directory
63-
highlight default link FernBranch Directory
64-
highlight default link FernMarked Title
61+
highlight default link FernRootSymbol Directory
62+
highlight default link FernRootText Directory
63+
highlight default link FernLeafSymbol Directory
64+
highlight default link FernLeafText None
65+
highlight default link FernBranchSymbol Directory
66+
highlight default link FernBranchText Directory
6567
endfunction
6668

67-
function! s:render_node(node, marks, base, options) abort
68-
let prefix = index(a:marks, a:node.__key) is# -1
69-
\ ? a:options.unmarked_symbol
70-
\ : a:options.marked_symbol
69+
function! s:render_node(node, base, options) abort
7170
let level = len(a:node.__key) - a:base
7271
if level is# 0
73-
return prefix . a:options.root_symbol . a:node.label
72+
return a:options.root_symbol . a:node.label . ' ' . a:node.badge
7473
endif
7574
let leading = repeat(a:options.leading, level - 1)
7675
let symbol = a:node.status is# s:STATUS_NONE
7776
\ ? a:options.leaf_symbol
7877
\ : a:node.status is# s:STATUS_COLLAPSED
7978
\ ? a:options.collapsed_symbol
8079
\ : a:options.expanded_symbol
81-
return prefix . leading . symbol . a:node.label
80+
return leading . symbol . a:node.label . ' ' . a:node.badge
8281
endfunction
8382

8483
call s:Config.config(expand('<sfile>:p'), {
@@ -87,6 +86,15 @@ call s:Config.config(expand('<sfile>:p'), {
8786
\ 'leaf_symbol': '| ',
8887
\ 'collapsed_symbol': '|+ ',
8988
\ 'expanded_symbol': '|- ',
90-
\ 'marked_symbol': '* ',
91-
\ 'unmarked_symbol': ' ',
9289
\})
90+
91+
" Obsolete warnings
92+
if exists('g:fern#renderer#default#marked_symbol')
93+
call fern#util#obsolete(
94+
\ 'g:fern#renderer#default#marked_symbol',
95+
\ 'g:fern#mark_symbol',
96+
\)
97+
endif
98+
if exists('g:fern#renderer#default#unmarked_symbol')
99+
call fern#util#obsolete('g:fern#renderer#default#unmarked_symbol')
100+
endif

autoload/fern/scheme/dict/mapping/clipboard.vim

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ function! s:map_clipboard_move(helper) abort
3434
\}
3535
return s:Promise.resolve()
3636
\.then({ -> a:helper.async.update_marks([]) })
37-
\.then({ -> a:helper.async.redraw() })
37+
\.then({ -> a:helper.async.remark() })
3838
\.then({ -> a:helper.sync.echo(printf('%d items are saved in clipboard to move', len(nodes))) })
3939
endfunction
4040

@@ -46,7 +46,7 @@ function! s:map_clipboard_copy(helper) abort
4646
\}
4747
return s:Promise.resolve()
4848
\.then({ -> a:helper.async.update_marks([]) })
49-
\.then({ -> a:helper.async.redraw() })
49+
\.then({ -> a:helper.async.remark() })
5050
\.then({ -> a:helper.sync.echo(printf('%d items are saved in clipboard to copy', len(nodes))) })
5151
endfunction
5252

0 commit comments

Comments
 (0)