"============================================================================= " FILE: init.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. "{{{ let g:vimshell_enable_start_insert = \ get(g:, 'vimshell_enable_start_insert', 1) "}}} let s:manager = vimshell#util#get_vital().import('Vim.Buffer') function! vimshell#init#_start(path, ...) abort "{{{ " Check vimproc. "{{{ if !vimshell#util#has_vimproc() call vimshell#echo_error(v:errmsg) call vimshell#echo_error(v:exception) call vimshell#echo_error('Error occurred while loading vimproc.') call vimshell#echo_error('Please install vimproc Ver.6.0 or above.') return elseif vimproc#version() < 600 call vimshell#echo_error('Your vimproc is too old.') call vimshell#echo_error('Please install vimproc Ver.6.0 or above.') return endif"}}} if vimshell#util#is_cmdwin() call vimshell#echo_error( \ '[vimshell] Command line buffer is detected!') call vimshell#echo_error( \ '[vimshell] Please close command line buffer.') return endif " Detect autochdir option. "{{{ if exists('+autochdir') && &autochdir call vimshell#echo_error( \ '[vimshell] Detected autochdir!') call vimshell#echo_error( \ '[vimshell] vimshell does''t work if you set autochdir option.') return endif "}}} let path = a:path if path != '' let path = vimshell#util#substitute_path_separator( \ fnamemodify(vimshell#util#expand(a:path), ':p')) if !isdirectory(path) call vimshell#echo_error( \ printf('[vimshell] argument path: "%s" invalid!', path)) " Don't use argument path. let path = '' endif endif let context = vimshell#init#_context(get(a:000, 0, {})) if context.create " Create shell buffer. call s:create_shell(path, context) return elseif context.toggle \ && vimshell#view#_close(context.buffer_name) return elseif &filetype ==# 'vimshell' " Search vimshell buffer. call s:switch_vimshell(bufnr('%'), context, path) return endif if !exists('t:vimshell') call vimshell#init#tab_variable() endif for bufnr in filter(insert(range(1, bufnr('$')), \ t:vimshell.last_vimshell_bufnr), \ "buflisted(v:val) && \ getbufvar(v:val, '&filetype') ==# 'vimshell'") if (!exists('t:tabpagebuffer') \ || has_key(t:tabpagebuffer, bufnr)) call s:switch_vimshell(bufnr, context, path) return endif endfor " Create shell buffer. call s:create_shell(path, context) endfunction"}}} function! vimshell#init#_context(context) abort "{{{ let default_context = { \ 'buffer_name' : 'default', \ 'quit' : 0, \ 'toggle' : 0, \ 'create' : 0, \ 'simple' : 0, \ 'split' : 0, \ 'popup' : 0, \ 'winwidth' : 0, \ 'winminwidth' : 0, \ 'project' : 0, \ 'tab' : 0, \ 'direction' : '', \ 'prompt' : get(g:, \ 'vimshell_prompt', 'vimshell% '), \ 'prompt_expr' : get(g:, \ 'vimshell_prompt_expr', ''), \ 'prompt_pattern' : get(g:, \ 'vimshell_prompt_pattern', ''), \ 'secondary_prompt' : get(g:, \ 'vimshell_secondary_prompt', '%% '), \ 'user_prompt' : get(g:, \ 'vimshell_user_prompt', ''), \ 'right_prompt' : get(g:, \ 'vimshell_right_prompt', ''), \ } let context = extend(default_context, a:context) " Complex initializer. if !has_key(context, 'profile_name') let context.profile_name = context.buffer_name endif if !has_key(context, 'split_command') if context.popup && g:vimshell_popup_command == '' " Default popup command. let context.split_command = 'split | resize ' \ . winheight(0)*g:vimshell_popup_height/100 elseif context.popup let context.split_command = g:vimshell_popup_command elseif context.split let context.split_command = g:vimshell_split_command else let context.split_command = '' endif endif " Set prompt pattern. if context.prompt_pattern == '' if context.prompt_expr != '' " Error. call vimshell#echo_error( \ 'Your prompt_pattern is invalid. '. \ 'You must set prompt_pattern in vimshell.') endif let context.prompt_pattern = \ '^' . vimshell#util#escape_match(context.prompt) endif if &l:modified && !&l:hidden " Split automatically. let context.split = 1 endif " Initialize. let context.has_head_spaces = 0 let context.is_interactive = 1 let context.is_insert = 1 let context.fd = { 'stdin' : '', 'stdout': '', 'stderr': ''} return context endfunction"}}} function! vimshell#init#_internal_commands(command) abort "{{{ " Initialize internal commands table. let internal_commands = vimshell#variables#internal_commands() if has_key(internal_commands, a:command) || a:command =~ '\.' return get(internal_commands, a:command, {}) endif " Search autoload. for list in split(globpath(&runtimepath, \ 'autoload/vimshell/commands/' . a:command . '*.vim'), '\n') let command_name = fnamemodify(list, ':t:r') if command_name == '' || \ has_key(internal_commands, command_name) continue endif let result = {'vimshell#commands#'.command_name.'#define'}() for command in (type(result) == type([])) ? \ result : [result] if !has_key(command, 'description') let command.description = '' endif let internal_commands[command.name] = command endfor unlet result endfor return get(internal_commands, a:command, {}) endfunction"}}} function! vimshell#init#_default_settings() abort "{{{ " Common. setlocal bufhidden=hide setlocal buftype=nofile setlocal nolist setlocal noswapfile setlocal tabstop=8 setlocal foldcolumn=0 setlocal foldmethod=manual setlocal winfixheight setlocal noreadonly setlocal iskeyword+=-,+,\\,!,~ setlocal textwidth=0 if has('conceal') setlocal conceallevel=3 setlocal concealcursor=nvi endif if exists('&colorcolumn') setlocal colorcolumn= endif endfunction"}}} function! vimshell#init#tab_variable() abort "{{{ let t:vimshell = { \ 'last_vimshell_bufnr' : -1, \ 'last_interactive_bufnr' : -1, \ } endfunction"}}} function! s:create_shell(path, context) abort "{{{ let path = a:path if path == '' " Use current directory. let path = vimshell#util#substitute_path_separator(getcwd()) endif if a:context.project let path = vimshell#util#path2project_directory(path) endif " Create new buffer. let prefix = '[vimshell] - ' let prefix .= a:context.profile_name let postfix = s:get_postfix(prefix, 1) let bufname = prefix . postfix if a:context.split_command != '' call vimshell#helpers#split(a:context.split_command) endif " Save swapfile option. let swapfile_save = &swapfile set noswapfile try let loaded = s:manager.open(bufname, 'silent edit') finally let &swapfile = swapfile_save endtry if !loaded call vimshell#echo_error( \ '[vimshell] Failed to open Buffer.') return endif call s:initialize_vimshell(path, a:context) call vimshell#interactive#set_send_buffer(bufname('%')) call vimshell#print_prompt(a:context) if g:vimshell_enable_start_insert call vimshell#start_insert() endif " Check prompt value. "{{{ let prompt = vimshell#get_prompt() if vimshell#util#head_match(prompt, vimshell#get_secondary_prompt()) \ || vimshell#util#head_match(vimshell#get_secondary_prompt(), prompt) call vimshell#echo_error(printf('Head matched g:vimshell_prompt("%s")'. \ ' and your g:vimshell_secondary_prompt("%s").', \ prompt, vimshell#get_secondary_prompt())) finish elseif vimshell#util#head_match(prompt, '[%] ') \ || vimshell#util#head_match('[%] ', prompt) call vimshell#echo_error(printf('Head matched g:vimshell_prompt("%s")'. \ ' and your g:vimshell_user_prompt("[%] ").', prompt)) finish elseif vimshell#util#head_match('[%] ', vimshell#get_secondary_prompt()) \ || vimshell#util#head_match(vimshell#get_secondary_prompt(), '[%] ') call vimshell#echo_error(printf('Head matched g:vimshell_user_prompt("[%] ")'. \ ' and your g:vimshell_secondary_prompt("%s").', \ vimshell#get_secondary_prompt())) finish endif"}}} endfunction"}}} function! s:switch_vimshell(bufnr, context, path) abort "{{{ if bufwinnr(a:bufnr) > 0 execute bufwinnr(a:bufnr) 'wincmd w' else if a:context.split_command != '' call vimshell#helpers#split(a:context.split_command) endif execute 'buffer' a:bufnr endif if !empty(b:vimshell.continuation) return endif if a:path != '' && isdirectory(a:path) " Change current directory. let current = fnamemodify(a:path, ':p') let b:vimshell.current_dir = current call vimshell#cd(current) endif if getline('$') =~# a:context.prompt_pattern.'$' " Delete current prompt. let promptnr = vimshell#view#_check_user_prompt(line('$')) > 0 ? \ vimshell#view#_check_user_prompt(line('$')) . ',' : '' silent execute promptnr . '$delete _' endif normal! zb call vimshell#print_prompt() if g:vimshell_enable_start_insert call vimshell#start_insert() endif endfunction"}}} function! s:initialize_vimshell(path, context) abort "{{{ " Load history. let g:vimshell#hist_buffer = vimshell#history#read() " Initialize variables. let b:vimshell = {} let b:vimshell.current_dir = a:path let b:vimshell.alias_table = {} let b:vimshell.galias_table = {} let b:vimshell.altercmd_table = {} let b:vimshell.commandline_stack = [] let b:vimshell.variables = {} let b:vimshell.system_variables = { 'status' : 0 } let b:vimshell.directory_stack = [] let b:vimshell.prompt_current_dir = {} let b:vimshell.continuation = {} let b:vimshell.prompts_save = {} let b:vimshell.statusline = \ '*vimshell* : %{vimshell#get_status_string()}' . \ "\ %=%{exists('b:vimshell') ? printf('%s %4d/%d', \ b:vimshell.right_prompt, line('.'), line('$')) : ''}" let b:vimshell.right_prompt = '' " Default settings. call s:default_settings() " Change current directory. call vimshell#cd(a:path) call vimshell#set_context(a:context) " Set interactive variables. let b:interactive = { \ 'type' : 'vimshell', \ 'syntax' : 'vimshell', \ 'process' : {}, \ 'continuation' : {}, \ 'fd' : a:context.fd, \ 'encoding' : &encoding, \ 'is_pty' : 0, \ 'echoback_linenr' : -1, \ 'stdout_cache' : '', \ 'stderr_cache' : '', \ 'width' : vimshell#helpers#get_winwidth(), \ 'height' : g:vimshell_scrollback_limit, \ 'hook_functions_table' : {}, \} " Load rc file. if filereadable(g:vimshell_vimshrc_path) call vimshell#helpers#execute_internal_command('vimsh', \ [g:vimshell_vimshrc_path], \ { 'has_head_spaces' : 0, 'is_interactive' : 0 }) let b:vimshell.loaded_vimshrc = 1 endif setfiletype vimshell call vimshell#help#init() call vimshell#interactive#init() call vimshell#handlers#_restore_statusline() endfunction"}}} function! s:default_settings() abort "{{{ " Common. call vimshell#init#_default_settings() " Set autocommands. augroup vimshell autocmd BufDelete,VimLeavePre \ call vimshell#interactive#hang_up(expand('')) autocmd BufEnter,BufWinEnter,WinEnter,BufRead \ call vimshell#handlers#_on_bufwin_enter(expand('')) augroup end call vimshell#handlers#_on_bufwin_enter(bufnr('%')) " Define mappings. call vimshell#mappings#define_default_mappings() endfunction"}}} function! s:get_postfix(prefix, is_create) abort "{{{ let buffers = get(a:000, 0, range(1, bufnr('$'))) let buflist = vimshell#util#sort_by(filter(map(buffers, \ 'bufname(v:val)'), 'stridx(v:val, a:prefix) >= 0'), \ "str2nr(matchstr(v:val, '\\d\\+$'))") if empty(buflist) return '' endif let num = matchstr(buflist[-1], '@\zs\d\+$') return num == '' && !a:is_create ? '' : \ '@' . (a:is_create ? (num + 1) : num) endfunction"}}} let &cpo = s:save_cpo unlet s:save_cpo " vim: foldmethod=marker