"============================================================================= " FILE: exrename.vim " AUTHOR: Shougo Matsushita " EDITOR: Alisue " " 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:PREFIX = unite#util#is_windows() ? '[exrename]' : '*exrename*' function! s:void(exrename) abort endfunction let s:VOID = function('s:void') function! unite#exrename#create_buffer(candidates, ...) abort "{{{ let options = extend({ \ 'cwd': getcwd(), \ 'bufnr': bufnr('%'), \ 'buffer_name': '', \ 'post_rename_callback': s:VOID, \}, get(a:000, 0, {})) if options.cwd !~# '/$' " current working directory MUST end with a trailing slash let options.cwd .= '/' endif if options.buffer_name ==# '' let options.buffer_name = s:PREFIX else let options.buffer_name = s:PREFIX . ' - ' . options.buffer_name endif vsplit redraw execute 'edit' fnameescape(options.buffer_name) setlocal buftype=acwrite setlocal noswapfile setfiletype unite_exrename let b:exrename = options call unite#util#lcd(b:exrename.cwd) nnoremap q :call exit(bufnr('%')) augroup unite-exrename autocmd! * autocmd BufHidden call s:exit(expand('')) autocmd BufWriteCmd call s:do_rename() autocmd CursorMoved,CursorMovedI call s:check_lines() augroup END " Clean up the screen. silent % delete _ silent! syntax clear uniteExrenameOriginal " validate candidates and register let unique_filenames = [] let b:exrename.candidates = [] let b:exrename.filenames = [] let cnt = 1 for candidate in a:candidates " make sure that the 'action__path' is absolute path if !s:is_absolute(candidate.action__path) let candidate.action__path = b:exrename.cwd . candidate.action__path endif " make sure that the 'action__path' exists if !filewritable(candidate.action__path) \ && !isdirectory(candidate.action__path) redraw echo candidate.action__path "does not exist. Skip." continue endif " make sure that the 'action__path' is unique if index(unique_filenames, candidate.action__path) != -1 redraw echo candidate.action__path "is duplicated. Skip." continue endif " create filename let filename = candidate.action__path if stridx(filename, b:exrename.cwd) == 0 let filename = filename[len(b:exrename.cwd) :] endif " directory should end with a trailing slash (to distinguish easily) if get(candidate, 'vimfiler__is_directory', \ get(candidate, 'kind', '') == 'directory') let filename .= '/' endif execute 'syntax match uniteExrenameOriginal' \ '/'.printf('^\%%%dl%s$', cnt, \ escape(unite#util#escape_pattern(filename), '/')).'/' " register call add(unique_filenames, candidate.action__path) call add(b:exrename.candidates, candidate) call add(b:exrename.filenames, filename) let cnt += 1 endfor " write filenames call setline(1, b:exrename.filenames) setlocal nomodified endfunction"}}} function! s:is_absolute(path) abort "{{{ return a:path =~# '^\%(\a\a\+:\)\|^\%(\a:\|/\)' endfunction "}}} function! s:do_rename() abort "{{{ if line('$') != len(b:exrename.filenames) echohl Error | echo 'Invalid rename buffer!' | echohl None return endif " Rename files. let linenr = 1 let max = line('$') while linenr <= max let filename = b:exrename.filenames[linenr - 1] redraw echo printf('(%'.len(max).'d/%d): %s -> %s', \ linenr, max, filename, getline(linenr)) if filename !=# getline(linenr) let old_file = b:exrename.candidates[linenr - 1].action__path let new_file = unite#util#expand(getline(linenr)) if new_file !~ '^\%(\a\a\+:\)\|^\%(\a:\|/\)' let new_file = b:exrename.cwd . new_file endif if unite#kinds#file#do_rename(old_file, new_file) " Rename error continue endif " update b:exrename let b:exrename.filenames[linenr - 1] = getline(linenr) let b:exrename.candidates[linenr - 1].action__path = new_file endif let linenr += 1 endwhile redraw echo 'Rename done!' setlocal nomodified if b:exrename.post_rename_callback != s:VOID call b:exrename.post_rename_callback(b:exrename) endif endfunction"}}} function! s:exit(bufnr) abort "{{{ if !bufexists(a:bufnr) return endif " Switch buffer. if winnr('$') != 1 close else call s:custom_alternate_buffer() endif silent execute 'bdelete!' a:bufnr endfunction "}}} function! s:check_lines() abort "{{{ if !exists('b:exrename') return endif if line('$') != len(b:exrename.filenames) echohl Error | echo 'Invalid rename buffer!' | echohl None return endif endfunction "}}} function! s:custom_alternate_buffer() abort "{{{ if bufnr('%') != bufnr('#') && buflisted(bufnr('#')) buffer # endif let cnt = 0 let pos = 1 let current = 0 while pos <= bufnr('$') if buflisted(pos) if pos == bufnr('%') let current = cnt endif let cnt += 1 endif let pos += 1 endwhile if current > cnt / 2 bprevious else bnext endif endfunction "}}} " vim: foldmethod=marker