"============================================================================= " FILE: file_vimfiler_base.vim " AUTHOR: Shougo Matsushita " License: MIT license {{{ " Permission is hereby granted, free of charge, to any person obtaining " a copy of this software and associated documentation files (the " "Software"), to deal in the Software without restriction, including " without limitation the rights to use, copy, modify, merge, publish, " distribute, sublicense, and/or sell copies of the Software, and to " permit persons to whom the Software is furnished to do so, subject to " the following conditions: " " The above copyright notice and this permission notice shall be included " in all copies or substantial portions of the Software. " " THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS " OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF " MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. " IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY " CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, " TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE " SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. " }}} "============================================================================= let s:save_cpo = &cpo set cpo&vim " Global options definition. "{{{ call unite#util#set_default( \ 'g:unite_kind_file_delete_file_command', \ unite#util#is_windows() && !executable('rm') ? '' : \ executable('trash-put') ? 'trash-put $srcs' : \ executable('rmtrash') ? 'rmtrash $srcs' : \ 'rm $srcs') call unite#util#set_default( \ 'g:unite_kind_file_delete_directory_command', \ unite#util#is_windows() && !executable('rm') ? '' : \ executable('trash-put') ? 'trash-put $srcs' : \ executable('rmtrash') ? 'rmtrash $srcs' : \ 'rm -r $srcs') call unite#util#set_default( \ 'g:unite_kind_file_copy_file_command', \ unite#util#is_windows() && !executable('cp') ? '' : \ 'cp -p $srcs $dest') call unite#util#set_default( \ 'g:unite_kind_file_copy_directory_command', \ unite#util#is_windows() && !executable('cp') ? '' : \ 'cp -p -r $srcs $dest') call unite#util#set_default( \ 'g:unite_kind_file_move_command', \ unite#util#is_windows() && !executable('mv') ? \ 'move /Y $srcs $dest' : 'mv $srcs $dest') call unite#util#set_default('g:unite_kind_file_use_trashbox', \ unite#util#is_windows() && unite#util#has_vimproc()) "}}} function! unite#kinds#file_vimfiler_base#define() abort "{{{ return s:kind endfunction"}}} let s:System = unite#util#get_vital().import('System.File') let s:kind = { \ 'name' : 'file_vimfiler_base', \ 'default_action' : 'open', \ 'action_table' : {}, \ 'parents' : [], \} " Actions "{{{ " For vimfiler. let s:kind.action_table.vimfiler__move = { \ 'description' : 'move files', \ 'is_quit' : 0, \ 'is_invalidate_cache' : 1, \ 'is_selectable' : 1, \ 'is_listed' : 0, \ } function! s:kind.action_table.vimfiler__move.func(candidates) abort "{{{ if !unite#util#input_yesno('Really move files?') echo 'Canceled.' return endif let vimfiler_current_dir = \ get(unite#get_context(), 'vimfiler__current_directory', '') if vimfiler_current_dir == '' let vimfiler_current_dir = getcwd() endif let current_dir = getcwd() try call unite#util#lcd(vimfiler_current_dir) if g:unite_kind_file_move_command == '' call unite#print_error('Please install mv.exe.') return 1 endif let context = unite#get_context() let dest_dir = get(context, 'action__directory', '') if dest_dir == '' let dest_dir = unite#util#input_directory( \ 'Input destination directory: ') endif if dest_dir == '' return elseif isdirectory(dest_dir) && dest_dir !~ '/$' let dest_dir .= '/' endif let context.action__directory = dest_dir let dest_drive = matchstr(dest_dir, '^\a\+\ze:') let candidates = [] for candidate in a:candidates let filename = candidate.action__path if isdirectory(filename) && unite#util#is_windows() \ && matchstr(filename, '^\a\+\ze:') !=? dest_drive call s:move_to_other_drive(candidate, filename) else call add(candidates, candidate) endif endfor if dest_dir =~ '^\h\w\+:' " Use protocol move method. let protocol = matchstr(dest_dir, '^\h\w\+') call unite#sources#{protocol}#move_files( \ dest_dir, candidates) else let filename = unite#kinds#file#do_action( \ candidates, dest_dir, 'move') call s:search_cursor(filename, dest_dir, a:candidates[-1]) endif finally call unite#util#lcd(current_dir) endtry endfunction"}}} let s:kind.action_table.move = \ deepcopy(s:kind.action_table.vimfiler__move) let s:kind.action_table.move.is_listed = 1 function! s:kind.action_table.move.func(candidates) abort "{{{ return s:kind.action_table.vimfiler__move.func(a:candidates) endfunction"}}} let s:kind.action_table.vimfiler__copy = { \ 'description' : 'copy files', \ 'is_quit' : 0, \ 'is_invalidate_cache' : 1, \ 'is_selectable' : 1, \ 'is_listed' : 0, \ } function! s:kind.action_table.vimfiler__copy.func(candidates) abort "{{{ let vimfiler_current_dir = \ get(unite#get_context(), 'vimfiler__current_directory', '') if vimfiler_current_dir == '' let vimfiler_current_dir = getcwd() endif let current_dir = getcwd() try call unite#util#lcd(vimfiler_current_dir) if g:unite_kind_file_copy_file_command == '' \ || g:unite_kind_file_copy_directory_command == '' call unite#print_error('Please install cp.exe.') return 1 endif let context = unite#get_context() let dest_dir = get(context, 'action__directory', '') if dest_dir == '' let dest_dir = unite#util#input_directory( \ 'Input destination directory: ') endif if dest_dir == '' return elseif isdirectory(dest_dir) && dest_dir !~ '/$' let dest_dir .= '/' endif if dest_dir =~ '^\h\w\+:' " Use protocol move method. let protocol = matchstr(dest_dir, '^\h\w\+') call unite#sources#{protocol}#copy_files(dest_dir, a:candidates) else let filename = unite#kinds#file#do_action( \ a:candidates, dest_dir, 'copy') call s:search_cursor(filename, dest_dir, a:candidates[-1]) endif finally call unite#util#lcd(current_dir) endtry endfunction"}}} let s:kind.action_table.copy = deepcopy(s:kind.action_table.vimfiler__copy) let s:kind.action_table.copy.is_listed = 1 function! s:kind.action_table.copy.func(candidates) abort "{{{ return s:kind.action_table.vimfiler__copy.func(a:candidates) endfunction"}}} let s:kind.action_table.vimfiler__delete = { \ 'description' : 'delete files', \ 'is_quit' : 0, \ 'is_invalidate_cache' : 1, \ 'is_selectable' : 1, \ 'is_listed' : 0, \ } function! s:kind.action_table.vimfiler__delete.func(candidates) abort "{{{ if g:unite_kind_file_delete_file_command == '' \ || g:unite_kind_file_delete_directory_command == '' call unite#print_error('Please install rm.exe.') return 1 endif if !unite#util#input_yesno('Really force delete files?') echo 'Canceled.' return endif call unite#kinds#file#do_action(a:candidates, '', 'delete') endfunction"}}} let s:kind.action_table.vimfiler__rename = { \ 'description' : 'rename files', \ 'is_quit' : 0, \ 'is_invalidate_cache' : 1, \ 'is_listed' : 0, \ } function! s:kind.action_table.vimfiler__rename.func(candidate) abort "{{{ let vimfiler_current_dir = \ get(unite#get_context(), 'vimfiler__current_directory', '') if vimfiler_current_dir == '' let vimfiler_current_dir = getcwd() endif let current_dir = getcwd() try call unite#util#lcd(vimfiler_current_dir) let context = unite#get_context() let filename = has_key(context, 'action__filename') ? \ context.action__filename : \ input(printf('New file name: %s -> ', \ a:candidate.action__path), a:candidate.action__path) if !has_key(context, 'action__filename') redraw endif if filename != '' && filename !=# a:candidate.action__path call unite#kinds#file#do_rename(a:candidate.action__path, filename) call s:search_cursor(filename, '', {}) endif finally call unite#util#lcd(current_dir) endtry endfunction"}}} let s:kind.action_table.vimfiler__newfile = { \ 'description' : 'make this file', \ 'is_quit' : 0, \ 'is_invalidate_cache' : 1, \ 'is_listed' : 0, \ } function! s:kind.action_table.vimfiler__newfile.func(candidate) abort "{{{ let vimfiler_current_dir = \ get(unite#get_context(), \ 'vimfiler__current_directory', '') if vimfiler_current_dir == '' let vimfiler_current_dir = getcwd() endif let current_dir = getcwd() try call unite#util#lcd(vimfiler_current_dir) let filenames = input('New files name(comma separated): ', \ '', 'file') if filenames == '' redraw echo 'Canceled.' return endif for filename in split(filenames, ',') call unite#util#lcd(vimfiler_current_dir) if filereadable(filename) redraw call unite#print_error(filename . ' is already exists.') continue endif let dir = fnamemodify(filename, ':h') if dir != '' && !isdirectory(dir) && !unite#util#is_sudo() " Auto create directory. call mkdir(dir, 'p') endif if filename !~ '/$' let file = unite#sources#file#create_file_dict(filename, '') let file.source = 'file' call writefile([], filename) endif call s:search_cursor(filename, '', {}) endfor finally call unite#util#lcd(current_dir) endtry endfunction"}}} let s:kind.action_table.unite__new_candidate = \ deepcopy(s:kind.action_table.vimfiler__newfile) let s:kind.action_table.vimfiler__shell = { \ 'description' : 'popup shell', \ 'is_listed' : 0, \ } function! s:kind.action_table.vimfiler__shell.func(candidate) abort "{{{ if !exists(':VimShellPop') shell return endif call vimshell#init#_start( \ unite#helper#get_candidate_directory(a:candidate), \ { 'popup' : 1, 'toggle' : 0 }) let files = unite#get_context().vimfiler__files if !empty(files) call setline(line('.'), getline('.') . ' ' . join(files)) call cursor(0, col('.')+1) endif endfunction"}}} let s:kind.action_table.vimfiler__shellcmd = { \ 'description' : 'execute shell command', \ 'is_listed' : 0, \ 'is_start' : 1, \ } function! s:kind.action_table.vimfiler__shellcmd.func(candidate) abort "{{{ let vimfiler_current_dir = \ get(unite#get_context(), 'vimfiler__current_directory', '') if vimfiler_current_dir == '' let vimfiler_current_dir = getcwd() endif let current_dir = getcwd() try call unite#util#lcd(vimfiler_current_dir) let command = unite#get_context().vimfiler__command let output = split(unite#util#system(command), '\n\|\r\n') if !empty(output) call unite#start_script([['output', output]]) endif finally call unite#util#lcd(current_dir) endtry endfunction"}}} let s:kind.action_table.vimfiler__mkdir = { \ 'description' : 'make this directory and parents directory', \ 'is_quit' : 0, \ 'is_invalidate_cache' : 1, \ 'is_listed' : 0, \ 'is_selectable' : 1, \ } function! s:kind.action_table.vimfiler__mkdir.func(candidates) abort "{{{ let context = unite#get_context() let vimfiler_current_dir = get(context, 'vimfiler__current_directory', '') if vimfiler_current_dir == '' let vimfiler_current_dir = getcwd() endif let current_dir = getcwd() try call unite#util#lcd(vimfiler_current_dir) let dirnames = split(input( \ 'New directory names(comma separated): ', '', 'dir'), ',') redraw if empty(dirnames) echo 'Canceled.' return endif for dirname in dirnames let dirname = unite#util#substitute_path_separator( \ fnamemodify(dirname, ':p')) if filereadable(dirname) || isdirectory(dirname) redraw call unite#print_error(dirname . ' is already exists.') continue endif call mkdir(dirname, 'p') endfor " Move marked files. if !get(context, 'vimfiler__is_dummy', 1) && len(dirnames) == 1 call unite#sources#file#move_files(dirname, a:candidates) endif call s:search_cursor(dirname, '', {}) finally call unite#util#lcd(current_dir) endtry endfunction"}}} let s:kind.action_table.vimfiler__execute = { \ 'description' : 'open files with associated program', \ 'is_selectable' : 1, \ 'is_listed' : 0, \ } function! s:kind.action_table.vimfiler__execute.func(candidates) abort "{{{ let vimfiler_current_dir = \ get(unite#get_context(), 'vimfiler__current_directory', '') if vimfiler_current_dir == '' let vimfiler_current_dir = getcwd() endif let current_dir = getcwd() try call unite#util#lcd(vimfiler_current_dir) for candidate in a:candidates let path = candidate.action__path if unite#util#is_windows() && path =~ '^//' " substitute separator for UNC. let path = substitute(path, '/', '\\', 'g') endif call s:System.open(path) endfor finally call unite#util#lcd(current_dir) endtry endfunction"}}} let s:kind.action_table.vimfiler__external_filer = { \ 'description' : 'open file with external file explorer', \ 'is_listed' : 0, \ } function! s:kind.action_table.vimfiler__external_filer.func(candidate) abort "{{{ let vimfiler_current_dir = \ get(unite#get_context(), 'vimfiler__current_directory', '') if vimfiler_current_dir == '' let vimfiler_current_dir = getcwd() endif let current_dir = getcwd() try call unite#util#lcd(vimfiler_current_dir) let path = a:candidate.action__path if unite#util#is_windows() let path = substitute(path, '/', '\\', 'g') endif let filer = '' if unite#util#is_mac() let filer = 'open -a Finder -R ' elseif unite#util#is_windows() let filer = 'explorer /SELECT,' elseif executable('nautilus') " Note: Older nautilus does not support "-s" option... let filer = 'nautilus ' if isdirectory(path) " Use parent path let path = fnamemodify(path, ':h') endif else " Not supported call s:System.open(fnamemodify(path, ':h')) return endif if unite#util#is_windows() let output = system(filer . '"' . path . '"') else let output = unite#util#system(filer . "'" . path . "' &") endif if output != '' call unite#util#print_error(output) endif finally call unite#util#lcd(current_dir) endtry endfunction"}}} let s:kind.action_table.vimfiler__write = { \ 'description' : 'save file', \ 'is_listed' : 0, \ } function! s:kind.action_table.vimfiler__write.func(candidate) abort "{{{ let context = unite#get_context() let lines = getline(context.vimfiler__line1, context.vimfiler__line2) if context.vimfiler__eventname ==# 'FileAppendCmd' " Append. let lines = readfile(a:candidate.action__path) + lines endif call writefile(lines, a:candidate.action__path) endfunction"}}} "}}} function! s:move_to_other_drive(candidate, filename) abort "{{{ " move command doesn't supported directory over drive move in Windows. if g:unite_kind_file_copy_file_command == '' \ || g:unite_kind_file_copy_directory_command == '' call unite#print_error('Please install cp.exe.') return 1 elseif g:unite_kind_file_delete_file_command == '' \ || g:unite_kind_file_delete_directory_command == '' call unite#print_error('Please install rm.exe.') return 1 endif if s:kind.action_table.vimfiler__copy.func([a:candidate]) call unite#print_error('Failed file move: ' . a:filename) return 1 endif if s:kind.action_table.vimfiler__delete.func([a:candidate]) call unite#print_error('Failed file delete: ' . a:filename) return 1 endif endfunction"}}} function! s:search_cursor(filename, dest_dir, candidate) abort "{{{ if &filetype !=# 'vimfiler' return endif if a:filename ==# a:dest_dir \ && vimfiler#exists_another_vimfiler() " Search from another vimfiler call vimfiler#mappings#switch_another_vimfiler() call vimfiler#view#_force_redraw_screen() call vimfiler#mappings#search_cursor( \ unite#util#substitute_path_separator( \ a:dest_dir . a:candidate.vimfiler__filename)) call vimfiler#mappings#switch_another_vimfiler() else " Search current vimfiler call vimfiler#view#_force_redraw_screen() call vimfiler#mappings#search_cursor( \ unite#util#substitute_path_separator( \ fnamemodify(a:filename, ':p'))) endif endfunction"}}} let &cpo = s:save_cpo unlet s:save_cpo " vim: foldmethod=marker