Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Endless loop seems to be occuring when using autocmd to switch to Project directory #430

Closed
li-zyang opened this issue Jan 18, 2020 · 3 comments

Comments

@li-zyang
Copy link

I'm using Gvim 8.2 on Windows 10, and I use Vimfiler included in SpaceVim. I want Vimfiler to automatically switch to the project directory when I open a file (like pressing <F3> twice with SpaceVim)
I added

au VimEnter * call s:vimfile_chdir()
function! s:vimfile_chdir()
  call vimfiler#custom#profile('default', 'context', {
      \ 'winwidth' : 30,
      \ 'winminwidth' : 30,
      \ 'fnamewidth' : 29,
      \ 'toggle' : 0,
      \ 'auto_expand': 0,
      \ 'hidden': 1,
      \ 'no_quit' : 1,
      \ 'no_focus' : 1
      \ })
  exe 'VimFiler ' . get(b:, 'rootDir', '')
endfunction

to my _gvimrc (just copied from the config/vimfiler.vim in Spacevim and changed some of the values), and I just cannot get my cursor into Vimfiler window (if no_focus : 0, then stuck in Vimfiler window)

Then I reduced some of the options:

function! g:VimFile_Rootdir()
  call vimfiler#custom#profile('default', 'context', {'toggle' : 0, 'no_focus' : 1})
  exe 'VimFiler ' . get(b:, 'rootDir', '')
endfunction
au BufEnter * call g:VimFile_Rootdir()

Still stucking the cursor
Try deleting the 'toggle' option do not solve the problem

I also tried adding a delay before calling the function, by changing the last autocmd line to

au BufEnter * call timer_start(200, "g:VimFile_Rootdir", {'repeat': 1})

which seems changed something, Vimfiler no longer stucks the cursor, but it makes Vim very slow, When I opened my taskmanager, it shows that Vim is occupying a lot of CPU time.
Do not solved the problem as well.

In consideration of that calling #profile() when starting and changing directory when entering the Vimfiler buffer itself may cause problems, I added an if condition before executing the commands, and it finally looks like

function! g:VimFile_Rootdir(...)
  if !has('vim_starting') && buflisted(bufname())
    call vimfiler#custom#profile('default', 'context', {'toggle':0, 'no_focus' : 1})
    exe 'VimFiler ' . get(b:, 'rootDir', '')
  endif
endfunction
au BufEnter * call timer_start(200, "g:VimFile_Rootdir", {'repeat': 1})

This solves the problem when I opened Vim (also when going into Vimfiler window), but the same problem still occurs when I open a file

Noticing a doautocmd command in Spacevim's config file, I added doautocmd WinEnter to the end of the function (before endif), do not solve the problem.

Scripts in Spacevim relating to Vimfiler:
config/plugins_before/vimfiler.vim

function! s:open_vimfiler() abort
  " check if VimFiler exist, if the windows has been opened, just close the
  " vimfiler windows, if the vimfiler widnows is not exist, open vimfiler for
  " current project.
  silent exe 'VimFiler ' . get(b:, 'rootDir', '')
  doautocmd WinEnter
endfunction

nnoremap <silent> <F3> :call <SID>open_vimfiler()<CR>

config/plugins/vimfiler.vim

scriptencoding utf-8

let s:VCOP = SpaceVim#api#import('vim#compatible')

let g:vimfiler_as_default_explorer = get(g:, 'vimfiler_as_default_explorer', 1)
let g:vimfiler_restore_alternate_file = get(g:, 'vimfiler_restore_alternate_file', 1)
let g:vimfiler_tree_indentation = get(g:, 'vimfiler_tree_indentation', 1)
let g:vimfiler_tree_leaf_icon = get(g:, 'vimfiler_tree_leaf_icon', '')
let g:vimfiler_tree_opened_icon = get(g:, 'vimfiler_tree_opened_icon', '')
let g:vimfiler_tree_closed_icon = get(g:, 'vimfiler_tree_closed_icon', '')
let g:vimfiler_file_icon = get(g:, 'vimfiler_file_icon', '')
let g:vimfiler_readonly_file_icon = get(g:, 'vimfiler_readonly_file_icon', '*')
let g:vimfiler_marked_file_icon = get(g:, 'vimfiler_marked_file_icon', '√')
if g:spacevim_filetree_direction ==# 'right'
  let g:vimfiler_direction = get(g:, 'vimfiler_direction', 'rightbelow')
else
  let g:vimfiler_direction = 'leftabove'
endif
"let g:vimfiler_preview_action = 'auto_preview'
let g:vimfiler_ignore_pattern = get(g:, 'vimfiler_ignore_pattern', [
      \ '^\.git$',
      \ '^\.DS_Store$',
      \ '^\.init\.vim-rplugin\~$',
      \ '^\.netrwhist$',
      \ '\.class$',
      \ '^\.'
      \])

if has('mac') 
  let g:vimfiler_quick_look_command = 
        \ get(g:, 'vimfiler_quick_look_command', 'qlmanage -p') 
else 
  let g:vimfiler_quick_look_command = 
        \ get(g:, 'vimfiler_quick_look_command', 'gloobus-preview') 
endif

function! s:setcolum() abort
  if g:spacevim_enable_vimfiler_filetypeicon && !g:spacevim_enable_vimfiler_gitstatus
    return 'filetypeicon'
  elseif !g:spacevim_enable_vimfiler_filetypeicon && g:spacevim_enable_vimfiler_gitstatus
    return 'gitstatus'
  elseif g:spacevim_enable_vimfiler_filetypeicon && g:spacevim_enable_vimfiler_gitstatus
    return 'filetypeicon:gitstatus'
  else
    return ''
  endif
endfunction
"try
call vimfiler#custom#profile('default', 'context', {
      \ 'explorer' : 1,
      \ 'winwidth' : g:spacevim_sidebar_width,
      \ 'winminwidth' : 30,
      \ 'toggle' : 1,
      \ 'auto_expand': 1,
      \ 'direction' : g:vimfiler_direction,
      \ 'explorer_columns' : s:setcolum(),
      \ 'parent': 0,
      \ 'status' : 1,
      \ 'safe' : 0,
      \ 'split' : 1,
      \ 'hidden': g:_spacevim_filetree_show_hidden_files,
      \ 'no_quit' : 1,
      \ 'force_hide' : 0,
      \ })

"catch
"endtry
augroup vfinit
  au!
  autocmd FileType vimfiler call s:vimfilerinit()
  autocmd BufEnter * nested if (!has('vim_starting') && winnr('$') == 1 && &filetype ==# 'vimfiler'   && g:_spacevim_autoclose_filetree) |
        \ call s:close_last_vimfiler_windows() | endif
augroup END

" in this function, we should check if shell terminal still exists,
" then close the terminal job before close vimfiler
function! s:close_last_vimfiler_windows() abort
  call SpaceVim#layers#shell#close_terminal()
  q
endfunction

function! s:vimfilerinit()
  setl nonumber
  setl norelativenumber

  silent! nunmap <buffer> <Space>
  silent! nunmap <buffer> <C-l>
  silent! nunmap <buffer> <C-j>
  silent! nunmap <buffer> E
  silent! nunmap <buffer> gr
  silent! nunmap <buffer> gf
  silent! nunmap <buffer> -
  silent! nunmap <buffer> s

  nnoremap <silent><buffer> sg  :<C-u>call <SID>vimfiler_vsplit()<CR>
  nnoremap <silent><buffer> sv  :<C-u>call <SID>vimfiler_split()<CR>
  nnoremap <silent><buffer><expr> st  vimfiler#do_action('tabswitch')
  nnoremap <silent><buffer> yY  :<C-u>call <SID>copy_to_system_clipboard()<CR>
  nnoremap <silent><buffer> P  :<C-u>call <SID>paste_to_file_manager()<CR>
  nmap <buffer> gx      <Plug>(vimfiler_execute_vimfiler_associated)
  nmap <buffer> '       <Plug>(vimfiler_toggle_mark_current_line)
  nmap <buffer> v       <Plug>(vimfiler_quick_look)
  nmap <buffer> p       <Plug>(vimfiler_preview_file)
  nmap <buffer> V       <Plug>(vimfiler_clear_mark_all_lines)
  nmap <buffer> i       <Plug>(vimfiler_switch_to_history_directory)
  nmap <buffer> <Tab>   <Plug>(vimfiler_switch_to_other_window)
  nmap <buffer> <C-r>   <Plug>(vimfiler_redraw_screen)
  nmap <buffer> <Left>  <Plug>(vimfiler_smart_h)
  nmap <buffer> <Right> <Plug>(vimfiler_smart_l)
  nmap <buffer> <2-LeftMouse> <Plug>(vimfiler_expand_or_edit)
endf

function! s:vimfiler_vsplit() abort
  let path = vimfiler#get_filename()
  if !isdirectory(path)
    wincmd w
    exe 'vsplit' path
  else
    echohl ModeMsg
    echo path . ' is a directory!'
    echohl NONE
  endif
endfunction
function! s:vimfiler_split() abort
  let path = vimfiler#get_filename()
  if !isdirectory(path)
    wincmd w
    exe 'split' path
  else
    echohl ModeMsg
    echo path . ' is a directory!'
    echohl NONE
  endif
endfunction

function! s:paste_to_file_manager() abort
  let path = vimfiler#get_filename()
  if !isdirectory(path)
    let path = fnamemodify(path, ':p:h')
  endif
  let old_wd = getcwd()
  if old_wd == path
    call s:VCOP.systemlist(['xclip-pastefile'])
  else
    noautocmd exe 'cd' fnameescape(path)
    call s:VCOP.systemlist(['xclip-pastefile'])
    noautocmd exe 'cd' fnameescape(old_wd)
  endif
endfunction

function! s:copy_to_system_clipboard() abort
  let filename = vimfiler#get_marked_filenames(b:vimfiler)

  if empty(filename)
    " Use cursor filename.
    let filename = vimfiler#get_filename()
    if filename ==# '..' || empty(vimfiler#get_file(b:vimfiler))
      let filename = b:vimfiler.current_dir
    else
      let filename = vimfiler#get_file(b:vimfiler).action__path
    endif
    call s:VCOP.systemlist(['xclip-copyfile', filename])
  else
    call s:VCOP.systemlist(['xclip-copyfile'] + filename)
  endif
  echo 'Yanked:' . (type(filename) == 3 ? len(filename) : 1 ) . ' files'
endfunction

" vim:set et sw=2:
@li-zyang
Copy link
Author

Solved.
BufEnter event handler causes BufEnter event again by using VimFiler command, which moves the cursor back to the file window and causes BufEnter (no_focus), and finally causes the endless loop.
A dir-changed flag should be set in the file buffer scope

function! g:VimFile_Rootdir(...)
  if !has('vim_starting') && buflisted(bufname()) && !get(b:, 'vimfiler_dirchanged', 0)
    call vimfiler#custom#profile('default', 'context', {'toggle':0, 'no_focus' : 1})
    exe 'VimFiler ' . get(b:, 'rootDir', '')
    let b:vimfiler_dirchanged = 1  " THE FLAG
  endif
endfunction
au BufEnter * call timer_start(200, "g:VimFile_Rootdir", {'repeat': 1})

Found when I am just going to bed = =

@Shougo
Copy link
Owner

Shougo commented Jan 19, 2020

Yes. g:vimfiler_as_default_explorer conflicts with your BufEnter event.
So I don't like the option...

@li-zyang
Copy link
Author

li-zyang commented Jan 19, 2020

Here's a more useful one

function! g:VimFiler_Projdir(...) abort
  if !has('vim_starting') && buflisted(bufname())
    let l:cur_rootDir = get(b:, 'rootDir', '~')
    if get(l:, 'cur_rootDir', expand('~')) ==# get(g:, 'prev_rootDir', expand('~'))
      let g:vimfiler_dirchanged = 1
    endif
    if !get(g:, 'vimfiler_dirchanged', 0)
      exe 'VimFiler ' . get(b:, 'rootDir', '')
      let g:vimfiler_dirchanged = 1
      let g:prev_rootDir = get(b:, 'rootDir', expand('~'))
    elseif &filetype ==# 'vimfiler'
      " Make only one explorer window synchronize with the project directory...
    endif
  endif
endfunction
au BufEnter * call timer_start(0, "g:VimFiler_Projdir", {'repeat': 1})
au BufLeave * if buflisted(bufname()) || !strlen(bufname()) | let g:vimfiler_dirchanged = 0 | endif

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants