"=============================================================================
" FILE: iexe.vim
" AUTHOR: Shougo Matsushita <Shougo.Matsu@gmail.com>
" 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:manager = vimshell#util#get_vital().import('Vim.Buffer')
let s:command = {
\ 'name' : 'iexe',
\ 'kind' : 'execute',
\ 'description' : 'iexe [{options}...] {command}',
\}
function! s:command.execute(commands, context) abort "{{{
" Interactive execute command.
if empty(a:commands)
return
endif
let commands = a:commands
let [commands[0].args, options] = vimshell#parser#getopt(commands[0].args, {
\ 'arg=' : ['--encoding', '--split'],
\ }, {
\ '--encoding' : vimshell#interactive#get_default_encoding(a:commands),
\ '--split' : g:vimshell_split_command,
\ })
let args = commands[0].args
if empty(args)
return
endif
if has_key(g:vimshell_interactive_cygwin_commands, fnamemodify(args[0], ':r'))
" Use Cygwin pty.
call insert(args, 'fakecygpty')
endif
let use_cygpty = vimshell#util#is_windows() &&
\ args[0] =~ '^fakecygpty\%(\.exe\)\?$'
if use_cygpty
if !executable('fakecygpty')
call vimshell#error_line(a:context.fd,
\ 'iexe: "fakecygpty.exe" is required. Please install it.')
return
endif
" Get program path from g:vimshell_interactive_cygwin_path.
if len(args) < 2
call vimshell#error_line(a:context.fd, 'iexe: command is required.')
return
endif
let args[1] = vimproc#get_command_name(
\ args[1], g:vimshell_interactive_cygwin_path)
endif
let cmdname = fnamemodify(args[0], ':r')
if !use_cygpty && has_key(g:vimshell_interactive_command_options, cmdname)
for arg in vimproc#parser#split_args(
\ g:vimshell_interactive_command_options[cmdname])
call add(args, arg)
endfor
endif
if vimshell#util#is_windows() && cmdname == 'cmd'
" Run cmdproxy.exe instead of cmd.exe.
if !executable('cmdproxy.exe')
call vimshell#error_line(a:context.fd,
\ 'iexe: "cmdproxy.exe" is not found. Please install it.')
return
endif
let args[0] = 'cmdproxy.exe'
endif
" Encoding conversion.
if options['--encoding'] != '' && options['--encoding'] != &encoding
for command in commands
call map(command.args,
\ 'vimproc#util#iconv(v:val, &encoding, options["--encoding"])')
endfor
endif
if exists('b:interactive') && !empty(b:interactive.process)
\ && b:interactive.process.is_valid
" Delete zombie process.
call vimshell#interactive#force_exit()
endif
" Initialize.
let home_save = {}
if use_cygpty && g:vimshell_interactive_cygwin_home != ''
" Set $HOME.
let home_save = vimshell#util#set_variables({
\ '$HOME' : g:vimshell_interactive_cygwin_home,
\})
endif
try
let [new_pos, old_pos] = vimshell#helpers#split(options['--split'])
" Set environment variables.
let environments_save = vimshell#util#set_variables({
\ '$TERM' : g:vimshell_environment_term,
\ '$TERMCAP' : 'COLUMNS=' . vimshell#helpers#get_winwidth(),
\ '$VIMSHELL' : 1,
\ '$COLUMNS' : vimshell#helpers#get_winwidth(),
\ '$LINES' : g:vimshell_scrollback_limit,
\ '$VIMSHELL_TERM' : 'interactive',
\ '$EDITOR' : vimshell#helpers#get_editor_name(),
\ '$GIT_EDITOR' : vimshell#helpers#get_editor_name(),
\ '$PAGER' : g:vimshell_cat_command,
\ '$GIT_PAGER' : g:vimshell_cat_command,
\})
" Initialize.
let sub = vimproc#ptyopen(commands)
finally
" Restore environment variables.
call vimshell#util#restore_variables(environments_save)
if !empty(home_save)
" Restore $HOME.
call vimshell#util#restore_variables(home_save)
endif
endtry
" Set variables.
let interactive = {
\ 'type' : 'interactive',
\ 'process' : sub,
\ 'fd' : a:context.fd,
\ 'encoding' : options['--encoding'],
\ 'is_secret': 0,
\ 'prompt_history' : {},
\ 'is_pty' : (!vimshell#util#is_windows() || use_cygpty),
\ 'args' : args,
\ 'echoback_linenr' : 0,
\ 'prompt_nr' : line('.'),
\ 'width' : vimshell#helpers#get_winwidth(),
\ 'height' : g:vimshell_scrollback_limit,
\ 'stdout_cache' : '',
\ 'stderr_cache' : '',
\ 'command' : fnamemodify(use_cygpty ? args[1] : args[0], ':t:r'),
\ 'cmdline' : join(args),
\ 'is_close_immediately' :
\ get(a:context, 'is_close_immediately', 0),
\ 'hook_functions_table' : {},
\}
call vimshell#commands#iexe#init(a:context, interactive,
\ new_pos, old_pos, 1)
call vimshell#interactive#execute_process_out(1)
if b:interactive.process.is_valid
call vimshell#view#_simple_insert()
endif
endfunction"}}}
function! s:command.complete(args) abort "{{{
if len(a:args) == 1
return vimshell#complete#helper#executables(a:args[-1])
elseif vimshell#util#is_windows() &&
\ len(a:args) > 1 && a:args[1] == 'fakecygpty'
return vimshell#complete#helper#executables(
\ a:args[-1], g:vimshell_interactive_cygwin_path)
endif
return vimshell#complete#helper#args(a:args[1], a:args[2:])
endfunction"}}}
function! vimshell#commands#iexe#define() abort
return s:command
endfunction
" Set interactive options. "{{{
if vimshell#util#is_windows()
" Windows only options.
call vimshell#util#set_default_dictionary_helper(
\ g:vimshell_interactive_command_options, 'bash,bc,gosh,python,zsh', '-i')
call vimshell#util#set_default_dictionary_helper(
\ g:vimshell_interactive_command_options, 'irb', '--inf-ruby-mode')
call vimshell#util#set_default_dictionary_helper(
\ g:vimshell_interactive_command_options, 'powershell', '-Command -')
call vimshell#util#set_default_dictionary_helper(
\ g:vimshell_interactive_command_options, 'scala', '-Xnojline')
call vimshell#util#set_default_dictionary_helper(
\ g:vimshell_interactive_command_options, 'nyaos', '-t')
call vimshell#util#set_default_dictionary_helper(
\ g:vimshell_interactive_command_options, 'fsi', '--gui- --readline-')
call vimshell#util#set_default_dictionary_helper(
\ g:vimshell_interactive_command_options, 'sbt',
\ '-Djline.WindowsTerminal.directConsole=false')
call vimshell#util#set_default_dictionary_helper(
\ g:vimshell_interactive_command_options, 'ipython,ipython3',
\ '--TerminalInteractiveShell.readline_use=False')
call vimshell#util#set_default_dictionary_helper(
\ g:vimshell_interactive_cygwin_commands, 'tail,zsh,ssh', 1)
endif
call vimshell#util#set_default_dictionary_helper(
\ g:vimshell_interactive_command_options, 'termtter', '--monochrome')
call vimshell#util#set_default_dictionary_helper(
\ g:vimshell_interactive_command_options, 'php', '-a')
" Set interpreter commands.
call vimshell#util#set_default_dictionary_helper(
\ g:vimshell_interactive_interpreter_commands, 'ruby', 'irb')
call vimshell#util#set_default_dictionary_helper(
\ g:vimshell_interactive_interpreter_commands, 'python', 'python')
call vimshell#util#set_default_dictionary_helper(
\ g:vimshell_interactive_interpreter_commands, 'perl', 'perlsh')
call vimshell#util#set_default_dictionary_helper(
\ g:vimshell_interactive_interpreter_commands, 'perl6', 'perl6')
call vimshell#util#set_default_dictionary_helper(
\ g:vimshell_interactive_interpreter_commands, 'sh', 'sh')
call vimshell#util#set_default_dictionary_helper(
\ g:vimshell_interactive_interpreter_commands, 'zsh', 'zsh')
call vimshell#util#set_default_dictionary_helper(
\ g:vimshell_interactive_interpreter_commands, 'bash', 'bash')
call vimshell#util#set_default_dictionary_helper(
\ g:vimshell_interactive_interpreter_commands, 'erlang', 'erl')
call vimshell#util#set_default_dictionary_helper(
\ g:vimshell_interactive_interpreter_commands, 'scheme', 'gosh')
call vimshell#util#set_default_dictionary_helper(
\ g:vimshell_interactive_interpreter_commands, 'clojure', 'clj')
call vimshell#util#set_default_dictionary_helper(
\ g:vimshell_interactive_interpreter_commands, 'lisp', 'clisp')
call vimshell#util#set_default_dictionary_helper(
\ g:vimshell_interactive_interpreter_commands, 'ps1', 'powershell')
call vimshell#util#set_default_dictionary_helper(
\ g:vimshell_interactive_interpreter_commands, 'haskell', 'ghci')
call vimshell#util#set_default_dictionary_helper(
\ g:vimshell_interactive_interpreter_commands, 'dosbatch', 'cmdproxy')
call vimshell#util#set_default_dictionary_helper(
\ g:vimshell_interactive_interpreter_commands, 'scala',
\ vimshell#util#is_windows() ? 'scala.bat' : 'scala')
call vimshell#util#set_default_dictionary_helper(
\ g:vimshell_interactive_interpreter_commands, 'ocaml', 'ocaml')
call vimshell#util#set_default_dictionary_helper(
\ g:vimshell_interactive_interpreter_commands, 'sml', 'sml')
call vimshell#util#set_default_dictionary_helper(
\ g:vimshell_interactive_interpreter_commands, 'javascript', 'js')
call vimshell#util#set_default_dictionary_helper(
\ g:vimshell_interactive_interpreter_commands, 'php', 'php')
call vimshell#util#set_default_dictionary_helper(
\ g:vimshell_interactive_prompts, 'termtter', '> ')
call vimshell#util#set_default_dictionary_helper(
\ g:vimshell_interactive_monochrome_commands, 'earthquake', '1')
"}}}
function! s:default_settings() abort "{{{
" Common.
call vimshell#init#_default_settings()
" Define mappings.
call vimshell#int_mappings#define_default_mappings()
endfunction"}}}
function! s:default_syntax() abort "{{{
" Set syntax.
syntax match InteractiveError
\ '!!![^!].*!!!' contains=InteractiveErrorHidden
highlight def link InteractiveError Error
if has('conceal')
" Supported conceal features.
syntax match InteractiveErrorHidden
\ '!!!' contained conceal
else
syntax match InteractiveErrorHidden
\ '!!!' contained
highlight def link InteractiveErrorHidden Ignore
endif
endfunction"}}}
function! vimshell#commands#iexe#init(context, interactive, new_pos, old_pos, is_insert) abort "{{{
" Save current directiory.
let cwd = getcwd()
let loaded = s:manager.open('iexe-'.substitute(join(a:interactive.args),
\ '[<>|]', '_', 'g') .'@'.(bufnr('$')+1), 'silent edit')
if !loaded
call vimshell#echo_error(
\ '[vimshell] Failed to open Buffer.')
return
endif
let [a:new_pos[2], a:new_pos[3]] = [bufnr('%'), getpos('.')]
let b:interactive = a:interactive
call s:default_settings()
call vimshell#cd(cwd)
let syntax = 'int-' . a:interactive.command
let &filetype = syntax
let b:interactive.syntax = syntax
call s:default_syntax()
" Set autocommands.
augroup vimshell
autocmd BufDelete,VimLeavePre <buffer>
\ call vimshell#interactive#hang_up(expand('<afile>'))
autocmd BufWinEnter,WinEnter <buffer>
\ call s:event_bufwin_enter()
augroup END
" Set send buffer.
call vimshell#interactive#set_send_buffer(bufnr('%'))
noautocmd call vimshell#helpers#restore_pos(a:old_pos)
if get(a:context, 'is_single_command', 0)
call vimshell#next_prompt(a:context, a:is_insert)
noautocmd call vimshell#helpers#restore_pos(a:new_pos)
endif
endfunction"}}}
function! s:event_bufwin_enter() abort "{{{
if has('conceal')
setlocal conceallevel=3
setlocal concealcursor=nvi
endif
endfunction"}}}
" vim: foldmethod=marker