diff --git a/autoload/fern/helper/sync.vim b/autoload/fern/helper/sync.vim index d18eb4fa..e77a0717 100644 --- a/autoload/fern/helper/sync.vim +++ b/autoload/fern/helper/sync.vim @@ -117,6 +117,20 @@ function! s:sync_is_drawer() abort dict endfunction let s:sync.is_drawer = funcref('s:sync_is_drawer') +function! s:sync_is_left_drawer() abort dict + let helper = self.helper + let fern = helper.fern + return fern#internal#drawer#is_left_drawer(bufname(helper.bufnr)) +endfunction +let s:sync.is_left_drawer = funcref('s:sync_is_left_drawer') + +function! s:sync_is_right_drawer() abort dict + let helper = self.helper + let fern = helper.fern + return fern#internal#drawer#is_right_drawer(bufname(helper.bufnr)) +endfunction +let s:sync.is_right_drawer = funcref('s:sync_is_right_drawer') + function! s:sync_get_scheme() abort dict let helper = self.helper let fern = helper.fern diff --git a/autoload/fern/internal/command/do.vim b/autoload/fern/internal/command/do.vim index 262627b2..b2d20db0 100644 --- a/autoload/fern/internal/command/do.vim +++ b/autoload/fern/internal/command/do.vim @@ -3,18 +3,20 @@ function! fern#internal#command#do#command(mods, fargs) abort try let stay = fern#internal#args#pop(a:fargs, 'stay', v:false) let drawer = fern#internal#args#pop(a:fargs, 'drawer', v:false) + let right = fern#internal#args#pop(a:fargs, 'right', v:false) if len(a:fargs) is# 0 \ || type(stay) isnot# v:t_bool \ || type(drawer) isnot# v:t_bool - throw 'Usage: FernDo {expr...} [-drawer] [-stay]' + \ || type(right) isnot# v:t_bool + throw 'Usage: FernDo {expr...} [-drawer] [-right] [-stay]' endif " Does all options are handled? call fern#internal#args#throw_if_dirty(a:fargs) let found = fern#internal#window#find( - \ funcref('s:predicator', [drawer]), + \ funcref('s:predicator', [drawer, right]), \ winnr() + 1, \) if !found @@ -39,9 +41,11 @@ function! fern#internal#command#do#complete(arglead, cmdline, cursorpos) abort return fern#internal#complete#options(a:arglead, a:cmdline, a:cursorpos) endfunction -function! s:predicator(drawer, winnr) abort +function! s:predicator(drawer, right, winnr) abort let bufname = bufname(winbufnr(a:winnr)) let fri = fern#fri#parse(bufname) - return fri.scheme ==# 'fern' - \ && (!a:drawer || fri.authority =~# '^drawer:') + return fri.scheme ==# 'fern' && (!a:drawer + \ || (!a:right && fri.authority =~# '^drawer:') + \ || (a:right && fri.authority =~# '^drawer-right:') + \) endfunction diff --git a/autoload/fern/internal/command/fern.vim b/autoload/fern/internal/command/fern.vim index 79e7c518..12f3eef9 100644 --- a/autoload/fern/internal/command/fern.vim +++ b/autoload/fern/internal/command/fern.vim @@ -1,5 +1,6 @@ let s:Promise = vital#fern#import('Async.Promise') -let s:drawer_opener = 'topleft vsplit' +let s:drawer_left_opener = 'topleft vsplit' +let s:drawer_right_opener = 'botright vsplit' function! fern#internal#command#fern#command(mods, fargs) abort try @@ -8,15 +9,17 @@ function! fern#internal#command#fern#command(mods, fargs) abort let reveal = fern#internal#args#pop(a:fargs, 'reveal', '') let drawer = fern#internal#args#pop(a:fargs, 'drawer', v:false) if drawer - let opener = s:drawer_opener let width = fern#internal#args#pop(a:fargs, 'width', '') let keep = fern#internal#args#pop(a:fargs, 'keep', v:false) let toggle = fern#internal#args#pop(a:fargs, 'toggle', v:false) + let right = fern#internal#args#pop(a:fargs, 'right', v:false) + let opener = right ? s:drawer_right_opener : s:drawer_left_opener else let opener = fern#internal#args#pop(a:fargs, 'opener', g:fern#opener) let width = '' let keep = v:false let toggle = v:false + let right = v:false endif if len(a:fargs) isnot# 1 @@ -28,10 +31,11 @@ function! fern#internal#command#fern#command(mods, fargs) abort \ || type(width) isnot# v:t_string \ || type(keep) isnot# v:t_bool \ || type(toggle) isnot# v:t_bool + \ || type(right) isnot# v:t_bool if empty(drawer) throw 'Usage: Fern {url} [-opener={opener}] [-stay] [-wait] [-reveal={reveal}]' else - throw 'Usage: Fern {url} -drawer [-toggle] [-keep] [-width={width}] [-stay] [-wait] [-reveal={reveal}]' + throw 'Usage: Fern {url} -drawer [-right] [-toggle] [-keep] [-width={width}] [-stay] [-wait] [-reveal={reveal}]' endif endif @@ -41,9 +45,14 @@ function! fern#internal#command#fern#command(mods, fargs) abort " Force project drawer style when " - The current buffer is project drawer style fern " - The 'opener' is 'edit' - if opener ==# 'edit' && fern#internal#drawer#is_drawer() - let drawer = v:true - let opener = s:drawer_opener + if opener ==# 'edit' + if fern#internal#drawer#is_left_drawer() + let drawer = v:true + let opener = s:drawer_left_opener + elseif right && fern#internal#drawer#is_right_drawer() + let drawer = v:true + let opener = s:drawer_right_opener + endif endif let expr = fern#util#expand(a:fargs[0]) @@ -58,7 +67,9 @@ function! fern#internal#command#fern#command(mods, fargs) abort \ 'path': path, \}) let fri.authority = drawer - \ ? printf('drawer:%d', tabpagenr()) + \ ? right + \ ? printf('drawer-right:%d', tabpagenr()) + \ : printf('drawer:%d', tabpagenr()) \ : '' let fri.query = extend(fri.query, { \ 'width': width, @@ -77,12 +88,13 @@ function! fern#internal#command#fern#command(mods, fargs) abort endif let winid_saved = win_getid() - if fri.authority =~# '^drawer:' + if fri.authority =~# '^drawer\(-right\)\?:' call fern#internal#drawer#open(fri, { \ 'mods': a:mods, \ 'toggle': toggle, \ 'opener': opener, \ 'stay': stay ? win_getid() : 0, + \ 'right': right, \}) else call fern#internal#viewer#open(fri, { diff --git a/autoload/fern/internal/drawer.vim b/autoload/fern/internal/drawer.vim index 2762656d..cf379467 100644 --- a/autoload/fern/internal/drawer.vim +++ b/autoload/fern/internal/drawer.vim @@ -1,9 +1,21 @@ function! fern#internal#drawer#is_drawer(...) abort + let bufname = a:0 ? a:1 : bufname('%') + let fri = fern#fri#parse(bufname) + return fri.scheme ==# 'fern' && fri.authority =~# '^drawer\(-right\)\?:' +endfunction + +function! fern#internal#drawer#is_left_drawer(...) abort let bufname = a:0 ? a:1 : bufname('%') let fri = fern#fri#parse(bufname) return fri.scheme ==# 'fern' && fri.authority =~# '^drawer:' endfunction +function! fern#internal#drawer#is_right_drawer(...) abort + let bufname = a:0 ? a:1 : bufname('%') + let fri = fern#fri#parse(bufname) + return fri.scheme ==# 'fern' && fri.authority =~# '^drawer-right:' +endfunction + function! fern#internal#drawer#resize() abort let fri = fern#fri#parse(bufname('%')) let width = str2nr(get(fri.query, 'width', string(g:fern#drawer_width))) @@ -13,9 +25,10 @@ endfunction function! fern#internal#drawer#open(fri, ...) abort let options = extend({ \ 'toggle': 0, + \ 'right': 0, \}, a:0 ? a:1 : {}, \) - if s:focus_next() + if s:focus_next(options.right) if winnr('$') > 1 if options.toggle close @@ -42,9 +55,12 @@ function! fern#internal#drawer#init() abort setlocal winfixwidth endfunction -function! s:focus_next() abort +function! s:focus_next(right) abort + let l:Predicator = a:right + \ ? function('fern#internal#drawer#is_right_drawer') + \ : function('fern#internal#drawer#is_left_drawer') let winnr = fern#internal#window#find( - \ { w -> fern#internal#drawer#is_drawer(bufname(winbufnr(w))) }, + \ { w -> l:Predicator(bufname(winbufnr(w))) }, \) if winnr is# 0 return diff --git a/autoload/fern/internal/drawer/auto_resize.vim b/autoload/fern/internal/drawer/auto_resize.vim index f54e7e3f..54538bda 100644 --- a/autoload/fern/internal/drawer/auto_resize.vim +++ b/autoload/fern/internal/drawer/auto_resize.vim @@ -3,11 +3,19 @@ function! fern#internal#drawer#auto_resize#init() abort return endif - augroup fern_internal_drawer_init - autocmd! * - autocmd BufEnter call s:load_width() - autocmd BufLeave call s:save_width() - augroup END + if fern#internal#drawer#is_right_drawer() + augroup fern_internal_drawer_init_right + autocmd! * + autocmd WinEnter call s:load_width_right() + autocmd WinLeave call s:save_width_right() + augroup END + else + augroup fern_internal_drawer_init + autocmd! * + autocmd WinEnter call s:load_width() + autocmd WinLeave call s:save_width() + augroup END + endif endfunction if has('nvim') @@ -37,3 +45,21 @@ function! s:load_width() abort execute 'vertical resize' t:fern_drawer_auto_resize_width endif endfunction + +function! s:save_width_right() abort + if s:should_ignore() + return + endif + let t:fern_drawer_auto_resize_width_right = winwidth(0) +endfunction + +function! s:load_width_right() abort + if s:should_ignore() + return + endif + if !exists('t:fern_drawer_auto_resize_width_right') + call fern#internal#drawer#resize() + else + execute 'vertical resize' t:fern_drawer_auto_resize_width_right + endif +endfunction diff --git a/autoload/fern/mapping/open.vim b/autoload/fern/mapping/open.vim index 25212ccd..58a973b0 100644 --- a/autoload/fern/mapping/open.vim +++ b/autoload/fern/mapping/open.vim @@ -24,6 +24,7 @@ function! fern#mapping#open#init(disable_default_mappings) abort \ fern#smart#drawer( \ "\(fern-action-open:left)", \ "\(fern-action-open:right)", + \ "\(fern-action-open:right)", \ ) nmap \ (fern-action-open-or-enter) diff --git a/autoload/fern/smart.vim b/autoload/fern/smart.vim index d146b25a..1867d06e 100644 --- a/autoload/fern/smart.vim +++ b/autoload/fern/smart.vim @@ -13,11 +13,19 @@ function! fern#smart#leaf(leaf, branch, ...) abort endif endfunction -function! fern#smart#drawer(drawer, viewer) abort +function! fern#smart#drawer(drawer, viewer, ...) abort let helper = fern#helper#new() - return helper.sync.is_drawer() - \ ? a:drawer - \ : a:viewer + if a:0 is# 0 + return helper.sync.is_drawer() + \ ? a:drawer + \ : a:viewer + else + return helper.sync.is_drawer() + \ ? helper.sync.is_right_drawer() + \ ? a:viewer + \ : a:drawer + \ : a:1 + endif endfunction function! fern#smart#scheme(default, schemes) abort diff --git a/doc/fern-develop.txt b/doc/fern-develop.txt index 537a24ce..33d39385 100644 --- a/doc/fern-develop.txt +++ b/doc/fern-develop.txt @@ -400,9 +400,19 @@ Following methods are executed synchronously. *fern-develop-helper.sync.is_drawer()* .sync.is_drawer() - Returns 1 if the fern buffer is shwon in a project drawer. Otherwise + Returns 1 if the fern buffer is shown in a project drawer. Otherwise it returns 0. + *fern-develop-helper.sync.is_left_drawer()* +.sync.is_left_drawer() + Returns 1 if the fern buffer is shown in a project drawer (left). + Otherwise it returns 0. + + *fern-develop-helper.sync.is_right_drawer()* +.sync.is_right_drawer() + Returns 1 if the fern buffer is shown in a project drawer (right). + Otherwise it returns 0. + *fern-develop-helper.sync.get_scheme()* .sync.get_scheme() Return |String| which represent the scheme name of the fern buffer. diff --git a/doc/fern.txt b/doc/fern.txt index c549b240..226f738f 100644 --- a/doc/fern.txt +++ b/doc/fern.txt @@ -591,7 +591,7 @@ COMMAND *fern-command* Note that the command can be followed by a '|' and another command. *:Fern-drawer* -:Fern {url} -drawer [-width={width}] [-keep] [-toggle] ... +:Fern {url} -drawer [-width={width}] [-keep] [-toggle] [-right]... Open a fern buffer in project drawer style with the {width}. If the {width} is specified, the width of the window is regulated to @@ -600,16 +600,19 @@ COMMAND *fern-command* only this window exist. (See |g:fern#drawer_keep|) If "-toggle" option is specified, existing fern buffer will be closed rather than opening a new fern buffer when exist. + If "-right" option is specified, the drawer is placed on the right + side. See |:Fern| for other arguments and options. Note that -opener options is ignored for project drawer style. *:FernDo* -:FernDo {expr...} [-drawer] [-stay] +:FernDo {expr...} [-drawer] [-right] [-stay] Focus a next fern viewer and execute {expr...}. It does nothing if no next fern viewer is found. If "-drawer" option is specified, it focus and execute only a project drawer style fern. + If "-right" option is specified, the drawer on the right side is used. If "-stay" option is specified, it stay focus after execution. Note that the command can be followed by a '|' and another command. @@ -663,9 +666,10 @@ fern#smart#leaf({leaf}, {collapsed}[, {expanded}]) < *fern#smart#drawer()* fern#smart#drawer({drawer}, {explorer}) +fern#smart#drawer({drawer}, {drawer-right}, {explorer}) Return one of a given mapping expression determined by the style of a current buffer. If the current buffer is drawer, the {drawer} is - returned. Otherwise the {explorer} is retunred. + returned. Otherwise the {explorer} is returned. > " Perform 'expand' on drawer and 'enter' on explorer nmap