From 796869a3655820ffda5adf4ebb5676e8234e373b Mon Sep 17 00:00:00 2001 From: lambdalisue Date: Thu, 30 Jul 2020 01:43:48 +0900 Subject: [PATCH 1/6] Update vital modules --- .../_fern/Async/CancellationTokenSource.vim | 2 +- .../vital/_fern/Async/Promise/Process.vim | 2 +- autoload/vital/fern.vim | 55 +++++++++++++------ autoload/vital/fern.vital | 2 +- 4 files changed, 41 insertions(+), 20 deletions(-) diff --git a/autoload/vital/_fern/Async/CancellationTokenSource.vim b/autoload/vital/_fern/Async/CancellationTokenSource.vim index 73bd3198..ae9117c5 100644 --- a/autoload/vital/_fern/Async/CancellationTokenSource.vim +++ b/autoload/vital/_fern/Async/CancellationTokenSource.vim @@ -82,5 +82,5 @@ function! s:_unlink(source) abort endfunction function! s:_throw(exception) abort - throw a:exception + throw substitute(a:exception, '^Vim(.*):', '', '') endfunction diff --git a/autoload/vital/_fern/Async/Promise/Process.vim b/autoload/vital/_fern/Async/Promise/Process.vim index 43b0729f..92409614 100644 --- a/autoload/vital/_fern/Async/Promise/Process.vim +++ b/autoload/vital/_fern/Async/Promise/Process.vim @@ -92,5 +92,5 @@ endfunction function! s:_on_cancel(ns, ...) abort call a:ns.job.stop() - call a:ns.reject(s:CancellationToken.CancellationError) + call a:ns.reject(s:CancellationToken.CancelledError) endfunction diff --git a/autoload/vital/fern.vim b/autoload/vital/fern.vim index 996ee7a6..6730f4e0 100644 --- a/autoload/vital/fern.vim +++ b/autoload/vital/fern.vim @@ -149,7 +149,7 @@ function! s:_import(name) abort dict call module._vital_created(module) endif let export_module = filter(copy(module), 'v:key =~# "^\\a"') - " Cache module before calling module.vital_loaded() to avoid cyclic + " Cache module before calling module._vital_loaded() to avoid cyclic " dependences but remove the cache if module._vital_loaded() fails. " let s:loaded[a:name] = export_module let s:loaded[a:name] = export_module @@ -167,30 +167,51 @@ let s:Vital._import = function('s:_import') function! s:_format_throwpoint(throwpoint) abort let funcs = [] - let stack = matchstr(a:throwpoint, '^function \zs.*\ze, line \d\+$') + let stack = matchstr(a:throwpoint, '^function \zs.*, .\{-} \d\+$') for line in split(stack, '\.\.') - let m = matchlist(line, '^\%(\(\d\+\)_\)\?\(.\+\)\[\(\d\+\)\]$') - if empty(m) - call add(funcs, line) - continue - endif - let [sid, name, lnum] = m[1:3] - let attr = '' - if !empty(sid) - let name = printf('%d_%s', sid, name) + let m = matchlist(line, '^\(.\+\)\%(\[\(\d\+\)\]\|, .\{-} \(\d\+\)\)$') + if !empty(m) + let [name, lnum, lnum2] = m[1:3] + if empty(lnum) + let lnum = lnum2 + endif + let info = s:_get_func_info(name) + if !empty(info) + let attrs = empty(info.attrs) ? '' : join([''] + info.attrs) + let flnum = info.lnum == 0 ? '' : printf(' Line:%d', info.lnum + lnum) + call add(funcs, printf('function %s(...)%s Line:%d (%s%s)', + \ info.funcname, attrs, lnum, info.filename, flnum)) + continue + endif endif - let file = s:_get_file_by_func_name(name) - call add(funcs, printf('function %s(...)%s Line:%d (%s)', name, attr, lnum, file)) + " fallback when function information cannot be detected + call add(funcs, line) endfor return join(funcs, "\n") endfunction -function! s:_get_file_by_func_name(name) abort - let body = execute(printf('verbose function %s', a:name)) +function! s:_get_func_info(name) abort + let name = a:name + if a:name =~# '^\d\+$' " is anonymous-function + let name = printf('{%s}', a:name) + elseif a:name =~# '^\d\+$' " is lambda-function + let name = printf("{'%s'}", a:name) + endif + if !exists('*' . name) + return {} + endif + let body = execute(printf('verbose function %s', name)) let lines = split(body, "\n") let signature = matchstr(lines[0], '^\s*\zs.*') - let file = matchstr(lines[1], '^\t\%(Last set from\|.\{-}:\)\s*\zs.*$') - return substitute(file, '[/\\]\+', '/', 'g') + let [_, file, lnum; __] = matchlist(lines[1], + \ '^\t\%(Last set from\|.\{-}:\)\s*\zs\(.\{-}\)\%( \S\+ \(\d\+\)\)\?$') + return { + \ 'filename': substitute(file, '[/\\]\+', '/', 'g'), + \ 'lnum': 0 + lnum, + \ 'funcname': a:name, + \ 'arguments': split(matchstr(signature, '(\zs.*\ze)'), '\s*,\s*'), + \ 'attrs': filter(['dict', 'abort', 'range', 'closure'], 'signature =~# (").*" . v:val)'), + \ } endfunction " s:_get_module() returns module object wihch has all script local functions. diff --git a/autoload/vital/fern.vital b/autoload/vital/fern.vital index 3b946056..03cf2b83 100644 --- a/autoload/vital/fern.vital +++ b/autoload/vital/fern.vital @@ -1,5 +1,5 @@ fern -8043f4d0f577ffb654cab9cfe629312b36c5342d +80887bd366c925887a40829eae73e86d7bb63ecc App.Spinner Async.CancellationTokenSource From ad432d2c3247fd4ffc0481a7b45eb5d8483e1710 Mon Sep 17 00:00:00 2001 From: lambdalisue Date: Wed, 29 Jul 2020 11:23:39 +0900 Subject: [PATCH 2/6] Rename to g:loaded_fern from g:fern_loaded --- plugin/fern.vim | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/plugin/fern.vim b/plugin/fern.vim index abbe9a1f..d5f06bfc 100644 --- a/plugin/fern.vim +++ b/plugin/fern.vim @@ -1,7 +1,8 @@ -if exists('g:fern_loaded') +if exists('g:loaded_fern') finish endif -let g:fern_loaded = 1 +let g:loaded_fern = 1 +let g:fern_loaded = 1 " Obsolete: For backward compatibility command! -bar -nargs=* \ -complete=customlist,fern#internal#command#fern#complete From a625c60ea9ed04048312aa4c4f0aeb04677f2f8d Mon Sep 17 00:00:00 2001 From: lambdalisue Date: Wed, 29 Jul 2020 11:25:51 +0900 Subject: [PATCH 3/6] Add 'User FernInit' autocmd to tell 3rd parties 3rd party plugins can use that autocmd to initialize like function! s:init() abort " Any autocmd function of fern is available here call fern#hook#add(...) endfunction augroup fern-xxxxx-internal autocmd! * autocmd User FernInit ++once s:init() augroup END --- plugin/fern.vim | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/plugin/fern.vim b/plugin/fern.vim index d5f06bfc..9520c649 100644 --- a/plugin/fern.vim +++ b/plugin/fern.vim @@ -31,4 +31,8 @@ augroup fern_internal autocmd! * autocmd BufReadCmd fern://* ++nested call s:BufReadCmd() autocmd SessionLoadPost fern://* ++nested call s:BufReadCmd() + autocmd User FernInit ++once : augroup END + +" Tell 3rd parties that fern has initialized +doautocmd User FernInit From c3cc5634253ac03f3733d6ff82f6f87f13ca69e2 Mon Sep 17 00:00:00 2001 From: lambdalisue Date: Wed, 29 Jul 2020 11:45:05 +0900 Subject: [PATCH 4/6] Add HOOKs --- autoload/fern/helper/async.vim | 1 + autoload/fern/internal/viewer.vim | 2 ++ doc/fern-develop.txt | 24 ++++++++++++++++++++++++ 3 files changed, 27 insertions(+) diff --git a/autoload/fern/helper/async.vim b/autoload/fern/helper/async.vim index 535bf4fa..d961601f 100644 --- a/autoload/fern/helper/async.vim +++ b/autoload/fern/helper/async.vim @@ -23,6 +23,7 @@ function! s:async_redraw() abort dict \ ) \}) \.then({ v -> fern#internal#buffer#replace(helper.bufnr, v) }) + \.then({ -> fern#hook#emit('viewer:redraw', helper) }) \.finally({ -> Profile() }) endfunction let s:async.redraw = funcref('s:async_redraw') diff --git a/autoload/fern/internal/viewer.vim b/autoload/fern/internal/viewer.vim index acd13fc8..b7c36bb9 100644 --- a/autoload/fern/internal/viewer.vim +++ b/autoload/fern/internal/viewer.vim @@ -105,6 +105,7 @@ endfunction function! s:BufReadCmd() abort let helper = fern#helper#new() call helper.fern.renderer.syntax() + call fern#hook#emit('renderer:syntax', helper) let root = helper.sync.get_root_node() let cursor = get(b:, 'fern_cursor', getcurpos()) call s:Promise.resolve() @@ -119,4 +120,5 @@ endfunction function! s:ColorScheme() abort let helper = fern#helper#new() call helper.fern.renderer.highlight() + call fern#hook#emit('renderer:highlight', helper) endfunction diff --git a/doc/fern-develop.txt b/doc/fern-develop.txt index 0461ffe1..21e30369 100644 --- a/doc/fern-develop.txt +++ b/doc/fern-develop.txt @@ -15,6 +15,7 @@ RENDERER |fern-develop-renderer| SCHEME |fern-develop-scheme| PROVIDER |fern-develop-scheme-provider| MAPPING |fern-develop-scheme-provider| +HOOK |fern-develop-hook| HELPER |fern-develop-helper| LOGGER |fern-develop-logger| UTILITY |fern-develop-utility| @@ -500,6 +501,29 @@ Following methods are executed asynchronously and return a promise. It is used to collapse modified nodes to solve issue #103. +============================================================================= +HOOK *fern-develop-hook* + +Following hook will be emitted by |fern#hook#emit()| from fern itself. + +"renderer:syntax" ({helper}) + Called when fern renderer has register its syntax. + The {helper} is a helper instance described in |fern-develop-helper|. + +"renderer:highlight" ({helper}) + Called when fern renderer has register its highlight. + The {helper} is a helper instance described in |fern-develop-helper|. + +"viewer:redraw" ({helper}) + Called when fern viewer has redrawed. + The {helper} is a helper instance described in |fern-develop-helper|. + +"viewer:ready" ({helper}) + Called when fern viewer has ready, mean that the buffer has opened and + all content has rendererd. + The {helper} is a helper instance described in |fern-develop-helper|. + + ============================================================================= LOGGER *fern-develop-logger* From 0030f7790b49aca85937f0b3443f9c0491389be9 Mon Sep 17 00:00:00 2001 From: lambdalisue Date: Wed, 29 Jul 2020 11:49:50 +0900 Subject: [PATCH 5/6] Add "scheme" to fern core instance --- autoload/fern/internal/core.vim | 2 ++ doc/fern-develop.txt | 1 + test/fern/internal/core.vimspec | 1 + 3 files changed, 4 insertions(+) diff --git a/autoload/fern/internal/core.vim b/autoload/fern/internal/core.vim index 33e0c943..a87588b3 100644 --- a/autoload/fern/internal/core.vim +++ b/autoload/fern/internal/core.vim @@ -14,8 +14,10 @@ function! fern#internal#core#new(url, provider, ...) abort \ 'comparator': g:fern#comparator, \}, a:0 ? a:1 : {}, \) + let scheme = fern#fri#parse(a:url).scheme let root = fern#internal#node#root(a:url, a:provider) let fern = { + \ 'scheme': scheme, \ 'source': s:CancellationTokenSource.new(), \ 'provider': a:provider, \ 'renderer': s:get_renderer(options.renderer), diff --git a/doc/fern-develop.txt b/doc/fern-develop.txt index 21e30369..82aa6a61 100644 --- a/doc/fern-develop.txt +++ b/doc/fern-develop.txt @@ -304,6 +304,7 @@ VARIABLE *fern-develop-helper-variable* .fern A fern instance which has the following attributes: + "scheme" A scheme name used to determine "provider" "source" A cancellation token source to cancel requests "provider" A provider instance for the fren tree "renderer" A renderer instance to sort nodes diff --git a/test/fern/internal/core.vimspec b/test/fern/internal/core.vimspec index 36b38ad7..c9fe3425 100644 --- a/test/fern/internal/core.vimspec +++ b/test/fern/internal/core.vimspec @@ -9,6 +9,7 @@ Describe fern#internal#core Describe #new() It returns a fern instance of given url and provider let fern = fern#internal#core#new('debug:///', provider) + Assert KeyExists(fern, 'scheme') Assert KeyExists(fern, 'source') Assert KeyExists(fern, 'provider') Assert KeyExists(fern, 'comparator') From 2be9ff513840d396179cb7f4934898e9640cb777 Mon Sep 17 00:00:00 2001 From: lambdalisue Date: Thu, 30 Jul 2020 06:21:31 +0900 Subject: [PATCH 6/6] Make sure FileType has called prior to touch syntax --- autoload/fern/internal/viewer.vim | 1 + 1 file changed, 1 insertion(+) diff --git a/autoload/fern/internal/viewer.vim b/autoload/fern/internal/viewer.vim index b7c36bb9..113f138d 100644 --- a/autoload/fern/internal/viewer.vim +++ b/autoload/fern/internal/viewer.vim @@ -104,6 +104,7 @@ endfunction function! s:BufReadCmd() abort let helper = fern#helper#new() + setlocal filetype=fern call helper.fern.renderer.syntax() call fern#hook#emit('renderer:syntax', helper) let root = helper.sync.get_root_node()