summaryrefslogtreecommitdiffstats
path: root/.vim/autoload/screen.vim
diff options
context:
space:
mode:
Diffstat (limited to '.vim/autoload/screen.vim')
-rw-r--r--.vim/autoload/screen.vim1081
1 files changed, 1081 insertions, 0 deletions
diff --git a/.vim/autoload/screen.vim b/.vim/autoload/screen.vim
new file mode 100644
index 0000000..66de7f6
--- /dev/null
+++ b/.vim/autoload/screen.vim
@@ -0,0 +1,1081 @@
+" Author: Eric Van Dewoestine <ervandew@gmail.com>
+"
+" License: {{{
+" Copyright (c) 2009 - 2011
+" All rights reserved.
+"
+" Redistribution and use of this software in source and binary forms, with
+" or without modification, are permitted provided that the following
+" conditions are met:
+"
+" * Redistributions of source code must retain the above
+" copyright notice, this list of conditions and the
+" following disclaimer.
+"
+" * Redistributions in binary form must reproduce the above
+" copyright notice, this list of conditions and the
+" following disclaimer in the documentation and/or other
+" materials provided with the distribution.
+"
+" * Neither the name of Eric Van Dewoestine nor the names of its
+" contributors may be used to endorse or promote products derived from
+" this software without specific prior written permission of
+" Eric Van Dewoestine.
+"
+" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+" IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+" THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+" CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+" EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+" PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+" PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+" LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+" SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+" }}}
+
+let s:save_cpo=&cpo
+set cpo&vim
+
+" Script Variables {{{
+
+ if has('win32') || has('win64') || has('win32unix')
+ let s:terminals = ['bash']
+ elseif has('mac') && has('gui_running')
+ let s:terminals = ['Terminal.app']
+ else
+ let s:terminals = [
+ \ 'gnome-terminal', 'konsole',
+ \ 'urxvt', 'multi-aterm', 'aterm', 'mrxvt', 'rxvt',
+ \ 'xterm',
+ \ ]
+ endif
+
+" }}}
+
+" ScreenShellCommands() {{{
+function! screen#ScreenShellCommands()
+ command -nargs=? -complete=shellcmd ScreenShell
+ \ :call screen#ScreenShell('<args>', 'horizontal')
+ command -nargs=? -complete=customlist,screen#CommandCompleteScreenSessions
+ \ ScreenShellAttach :call screen#ScreenShellAttach('<args>')
+
+ if !has('gui_running') &&
+ \ !g:ScreenShellExternal &&
+ \ (g:ScreenImpl == 'Tmux' || g:ScreenShellGnuScreenVerticalSupport != '')
+ command -nargs=? -complete=shellcmd ScreenShellVertical
+ \ :call screen#ScreenShell('<args>', 'vertical')
+ endif
+endfunction " }}}
+
+" ScreenShell(cmd, orientation) {{{
+" Open a split shell.
+function! screen#ScreenShell(cmd, orientation)
+ if g:ScreenImpl !~ '^\(GnuScreen\|Tmux\)$'
+ echohl WarningMsg
+ echom 'Unsupported g:ScreenImpl value "' . g:ScreenImpl . '". ' .
+ \ 'Supported values included "GnuScreen" or "Tmux".'
+ echohl Normal
+ return
+ endif
+
+ if !s:screen{g:ScreenImpl}.isValid()
+ return
+ endif
+
+ let s:orientation = a:orientation
+
+ " Specifies a name to be supplied to vim's --servername arg when invoked in
+ " a new screen session.
+ if !exists('g:ScreenShellServerName')
+ " Perform this here so that g:ScreenShellExternal can be set after vim
+ " starts.
+ let s:servername = g:ScreenShellExternal ? '' : 'vim'
+ else
+ let s:servername = g:ScreenShellServerName
+ endif
+
+ try
+ let bootstrap =
+ \ g:ScreenImpl =~ 'GnuScreen\|Tmux' &&
+ \ !has('gui_running') &&
+ \ !exists('g:ScreenShellBootstrapped') &&
+ \ expand('$TERM') !~ '^screen'
+
+ " if using an external shell without the need to set the vim servername,
+ " then don't bootstrap
+ if bootstrap
+ if g:ScreenShellExternal &&
+ \ (s:servername == '' || g:ScreenImpl == 'Tmux' ||
+ \ !has('clientserver') || has('win32') || has('win64'))
+ let bootstrap = 0
+ endif
+ endif
+
+ if bootstrap
+ call s:ScreenBootstrap(a:cmd)
+ else
+ call s:ScreenInit(a:cmd)
+ endif
+ finally
+ " wrapping in a try without catching anything just cleans up the vim error
+ " produced by an exception thrown from one of the above functions.
+ endtry
+endfunction " }}}
+
+" ScreenShellAttach(session) {{{
+" Attach to an existing screen session.
+function! screen#ScreenShellAttach(session)
+ if !s:screen{g:ScreenImpl}.isValid()
+ return
+ endif
+
+ let g:ScreenShellSession = s:screen{g:ScreenImpl}.attachSession(a:session)
+
+ if g:ScreenShellSession != '0'
+ if !exists(':ScreenSend')
+ command -nargs=0 -range=% ScreenSend :call <SID>ScreenSend(<line1>, <line2>)
+ let g:ScreenShellSend = s:ScreenSendFuncRef()
+ let g:ScreenShellFocus = s:ScreenFocusFuncRef()
+ endif
+
+ if g:ScreenShellAttachTargetCurrent
+ let g:ScreenShellWindow = 'screenshell'
+ call s:screen{g:ScreenImpl}.setTitle()
+ endif
+ endif
+endfunction " }}}
+
+" s:ScreenBootstrap(cmd) {{{
+" Bootstrap a new screen session.
+function! s:ScreenBootstrap(cmd)
+ try
+ let g:ScreenShellBootstrapped = 1
+ let g:ScreenShellSession = s:screen{g:ScreenImpl}.newSessionName()
+
+ wa
+ let save_sessionoptions = &sessionoptions
+ set sessionoptions+=globals
+ set sessionoptions-=tabpages
+ let sessionfile = substitute(tempname(), '\', '/', 'g')
+ exec 'mksession ' . sessionfile
+
+ " when transitioning from windows vim to cygwin vim, the session file
+ " needs to be purged of windows line endings.
+ if has('win32') || has('win64')
+ let winrestcmd = winrestcmd()
+ try
+ exec '1split ' . sessionfile
+ set ff=unix
+ exec "%s/\<c-m>$//g"
+ wq
+ finally
+ exec winrestcmd
+ endtry
+ endif
+
+ " support for taglist
+ if exists(':TlistSessionSave') &&
+ \ exists('g:TagList_title') &&
+ \ bufwinnr(g:TagList_title)
+ let g:ScreenShellTaglistSession = sessionfile . '.taglist'
+ exec 'TlistSessionSave ' . g:ScreenShellTaglistSession
+ exec 'silent! !echo "Tlist | TlistSessionLoad ' .
+ \ g:ScreenShellTaglistSession . '" >> "' . sessionfile . '"'
+ endif
+
+ let bufend = bufnr('$')
+ let bufnum = 1
+ while bufnum <= bufend
+ if bufnr(bufnum) != -1
+ call setbufvar(bufnum, 'save_swapfile', getbufvar(bufnum, '&swapfile'))
+ call setbufvar(bufnum, '&swapfile', 0)
+
+ " suppress prompt and auto reload changed files for the user when
+ " returning to this vim session
+ augroup screenshell_filechanged
+ exec 'autocmd! FileChangedShell <buffer=' . bufnum . '>'
+ exec 'autocmd FileChangedShell <buffer=' . bufnum . '> ' .
+ \ 'let v:fcs_choice = (v:fcs_reason == "changed" ? "reload" : "ask") | ' .
+ \ 'autocmd! screenshell_filechanged FileChangedShell <buffer=' . bufnum . '>'
+ augroup END
+ endif
+ let bufnum = bufnum + 1
+ endwhile
+
+ " supply a servername when starting vim if supported
+ let server = ''
+ if has('clientserver') && s:servername != ''
+ let server = '--servername "' . s:servername . '" '
+ endif
+
+ " when transitioning from windows console vim to cygwin vim, we don't know
+ " if the cygwin version support clientserver, so error on the safe side
+ " (in my environment the cygwin vim doesn't support client server).
+ if has('win32') || has('win64')
+ let server = ''
+ endif
+
+ call s:screen{g:ScreenImpl}.bootstrap(server, sessionfile, a:cmd)
+ finally
+ redraw!
+
+ unlet g:ScreenShellBootstrapped
+
+ " if there was an error writing files, then we didn't get far enough to
+ " need this cleanup.
+ if exists('save_sessionoptions')
+ let &sessionoptions = save_sessionoptions
+ call delete(sessionfile)
+
+ " remove taglist session file
+ if exists('g:ScreenShellTaglistSession')
+ call delete(g:ScreenShellTaglistSession)
+ endif
+
+ redraw!
+
+ let possible_detach = 0
+ let bufnum = 1
+ let winrestcmd = winrestcmd()
+ new
+ try
+ while bufnum <= bufend
+ if bufnr(bufnum) != -1
+ try
+ call setbufvar(bufnum, '&swapfile', getbufvar(bufnum, 'save_swapfile'))
+ catch /E325/
+ let possible_detach = 1
+ exec 'buffer ' . bufnum
+ try
+ redraw
+ edit
+ catch
+ endtry
+ endtry
+ endif
+ let bufnum = bufnum + 1
+ endwhile
+ finally
+ quit!
+ exec winrestcmd
+ endtry
+
+ if possible_detach
+ echohl WarningMsg
+ echom 'Warning: detatching from a screen session started by ' .
+ \ ':ScreenShell may result in conflicting swap files like those ' .
+ \ 'just encountered. Due to this possibility, detaching from a ' .
+ \ 'screen session started by :ScreenShell is discouraged. ' .
+ \ 'Instead you should issue a :ScreenQuit or exit the vim ' .
+ \ 'instance in screen normally (:qa)'
+ echohl None
+ endif
+ endif
+ endtry
+endfunction " }}}
+
+" s:ScreenInit(cmd) {{{
+" Initialize the current screen session.
+function! s:ScreenInit(cmd)
+ let g:ScreenShellWindow = 'screenshell'
+ " use a portion of the command as the title, if supplied
+ "if a:cmd != '' && a:cmd !~ '^\s*vim\>'
+ " let g:ScreenShellWindow = s:ScreenCmdName(a:cmd)[:15]
+ "endif
+
+ let external = 0
+ let owner = ''
+ if g:ScreenImpl =~ 'GnuScreen\|Tmux'
+ " when already running in a screen session, never use an external shell
+ let external = !exists('g:ScreenShellBootstrapped') &&
+ \ expand('$TERM') =~ '^screen' ? 0 : g:ScreenShellExternal
+ " w/ gvim always use an external shell
+ let external = has('gui_running') ? 1 : external
+ endif
+
+ if exists('g:ScreenShellBootstrapped')
+ let owner = 'session'
+ endif
+
+ " use screen regions
+ if !external
+ let result = s:screen{g:ScreenImpl}.openRegion(a:cmd)
+ let owner = 'region'
+
+ " use an external terminal
+ else
+ let g:ScreenShellSession = exists('g:ScreenShellSession') ?
+ \ g:ScreenShellSession : s:screen{g:ScreenImpl}.newSessionName()
+
+ " This block should only be hit in console mode with external terminal +
+ " vim server name set.
+ " Not supported by tmux since it doesn't appear that you can have
+ " more than one terminal connected to a session without them all
+ " focusing the same window.
+ if !has('gui_running') &&
+ \ exists('g:ScreenShellBootstrapped') &&
+ \ g:ScreenImpl != 'Tmux'
+
+ let result = s:screen{g:ScreenImpl}.newWindow(0)
+ let owner = 'window'
+
+ if !v:shell_error
+ let result = s:screen{g:ScreenImpl}.newTerminalMulti()
+
+ if !v:shell_error && result != '0' && a:cmd != ''
+ let result = s:screen{g:ScreenImpl}.send(a:cmd)
+ endif
+ endif
+
+ else
+ let result = s:screen{g:ScreenImpl}.newTerminal()
+ let owner = 'terminal'
+
+ if has('win32') || has('win64') || has('win32unix') || has('mac')
+ " like, the sleep hack below, but longer for windows.
+ sleep 3000m
+ else
+ " looks like this is needed for ubuntu as well... ugg.
+ sleep 1000m
+ endif
+
+ if !v:shell_error && result != '0'
+ " Hack, but should be plenty of time to let screen get to a state
+ " where it will apply the title command.
+ sleep 500m
+ let result = s:screen{g:ScreenImpl}.setTitle()
+
+ if g:ScreenImpl == 'Tmux'
+ let g:ScreenShellTmuxPane = s:screen{g:ScreenImpl}.activePane()
+ endif
+
+ " execute the supplied command if any
+ if !v:shell_error && a:cmd != ''
+ let result = s:screen{g:ScreenImpl}.send(a:cmd)
+ endif
+ endif
+ endif
+ endif
+
+ if v:shell_error
+ if exists(':ScreenQuit')
+ delcommand ScreenQuit
+ endif
+ echoerr result
+ else
+ if !exists(':ScreenSend')
+ command -nargs=0 -range=% ScreenSend :call <SID>ScreenSend(<line1>, <line2>)
+ exec "command -nargs=0 ScreenQuit :call <SID>ScreenQuit('" . owner . "', 0)"
+ if g:ScreenShellQuitOnVimExit
+ augroup screen_shell
+ autocmd!
+ exec "autocmd VimLeave * call <SID>ScreenQuit('" . owner . "', 1)"
+ augroup END
+ endif
+
+ let g:ScreenShellSend = s:ScreenSendFuncRef()
+ let g:ScreenShellFocus = s:ScreenFocusFuncRef()
+ " remove :ScreenShell command to avoid accidentally calling it again.
+ delcommand ScreenShell
+ delcommand ScreenShellAttach
+ if exists(':ScreenShellVertical')
+ delcommand ScreenShellVertical
+ endif
+
+ " Hook for creating keybindings (or similar)
+ let g:ScreenShellActive = 1
+ let g:ScreenShellCmd = a:cmd
+ try
+ doautoall ScreenShellEnter User
+ catch /E216/
+ endtry
+ endif
+ endif
+endfunction " }}}
+
+" s:ScreenSend(string or list<string> or line1, line2) {{{
+" Send lines to the screen shell.
+function! s:ScreenSend(...)
+ if a:0 == 1
+ let argtype = type(a:1)
+ if argtype == 1
+ let lines = split(a:1, "\n")
+ elseif argtype == 3
+ let lines = a:1
+ else
+ echoe 'ScreenShell: Argument must be a string or list.'
+ return
+ endif
+ elseif a:0 == 2
+ if type(a:1) != 0 || type(a:2) != 0
+ echoe 'ScreenShell: Arguments must be positive integer line numbers.'
+ return
+ endif
+
+ let lines = getline(a:1, a:2)
+ let mode = visualmode(1)
+ if mode != '' && line("'<") == a:1
+ if mode == "v"
+ let start = col("'<") - 1
+ let end = col("'>") - 1
+ " slice in end before start in case the selection is only one line
+ let lines[-1] = lines[-1][: end]
+ let lines[0] = lines[0][start :]
+ elseif mode == "\<c-v>"
+ let start = col("'<")
+ if col("'>") < start
+ let start = col("'>")
+ endif
+ let start = start - 1
+ call map(lines, 'v:val[start :]')
+ endif
+ endif
+ else
+ echoe 'ScreenShell: Invalid number of arguments for ScreenSend.'
+ return
+ endif
+
+ if g:ScreenShellExpandTabs
+ let expanded = ''
+ let index = 0
+ while index < &shiftwidth
+ let expanded .= ' '
+ let index += 1
+ endwhile
+ call map(lines, 'substitute(v:val, "\\t", expanded, "g")')
+ endif
+
+ let result = s:screen{g:ScreenImpl}.send(lines)
+
+ if v:shell_error
+ echoerr result
+ endif
+endfunction " }}}
+
+" s:ScreenFocus() {{{
+function! s:ScreenFocus()
+ let result = s:screen{g:ScreenImpl}.focus()
+
+ if v:shell_error
+ echoerr result
+ endif
+endfun " }}}
+
+" s:ScreenSendFuncRef() {{{
+function! s:ScreenSendFuncRef()
+ let sid = matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze_ScreenSendFuncRef$')
+ return function(printf('<SNR>%s_ScreenSend', sid))
+endfun " }}}
+
+" s:ScreenFocusFuncRef() {{{
+function! s:ScreenFocusFuncRef()
+ let sid = matchstr(expand('<sfile>'), '<SNR>\zs\d\+\ze_ScreenFocusFuncRef$')
+ return function(printf('<SNR>%s_ScreenFocus', sid))
+endfun " }}}
+
+" s:ScreenQuit(owner, onleave) {{{
+" Quit the current screen session (short cut to manually quiting vim and
+" closing all screen windows.
+function! s:ScreenQuit(owner, onleave)
+ if exists('g:ScreenShellBootstrapped')
+ if !a:onleave
+ wa
+ endif
+
+ let bufend = bufnr('$')
+ let bufnum = 1
+ while bufnum <= bufend
+ if bufnr(bufnum) != -1
+ call setbufvar(bufnum, '&swapfile', 0)
+ endif
+ let bufnum = bufnum + 1
+ endwhile
+ else
+ call screen#ScreenShellCommands()
+ delcommand ScreenQuit
+ delcommand ScreenSend
+ unlet g:ScreenShellSend
+ unlet g:ScreenShellFocus
+ augroup screen_shell
+ autocmd!
+ augroup END
+
+ " Hook for creating keybindings (or similar)
+ let g:ScreenShellActive = 0
+ let g:ScreenShellCmd = ''
+ try
+ doautoall ScreenShellExit User
+ catch /E216/
+ endtry
+ endif
+
+ let result = ''
+ if exists('g:ScreenShellBootstrapped') ||
+ \ a:owner == 'session' ||
+ \ a:owner == 'terminal'
+ let result = s:screen{g:ScreenImpl}.quit()
+ elseif a:owner == 'region' || a:owner == 'window'
+ let result = s:screen{g:ScreenImpl}.close(a:owner)
+ endif
+
+ unlet g:ScreenShellTmuxPane
+
+ if v:shell_error
+ if result !~ 'No screen session found'
+ echoerr result
+ endif
+ endif
+endfunction " }}}
+
+" s:ScreenCmdName(cmd) {{{
+" Generate a name for the given command.
+function! s:ScreenCmdName(cmd)
+ let cmd = substitute(a:cmd, '^\s*\(\S\+\)\s.*', '\1', '')
+ " if the command is a path to one, use the tail of the path
+ if cmd =~ '/'
+ let cmd = fnamemodify(cmd, ':t')
+ endif
+ return cmd
+endfunction " }}}
+
+" s:StartTerminal(command) {{{
+function! s:StartTerminal(command)
+ let terminal = s:GetTerminal()
+ if !s:ValidTerminal(terminal)
+ echoerr 'Unable to find a terminal, please set g:ScreenShellTerminal'
+ return
+ endif
+
+ " handle using cygwin bash
+ if has('win32') || has('win64') || has('win32unix')
+ let result = ''
+ let command = 'start "' . terminal . '"'
+ if has('win32unix')
+ let command = substitute(command, '\', '/', 'g')
+ let command = 'cmd /c ' . command
+ endif
+ let command .= ' --login -c "' . a:command . '"'
+ exec 'silent !' . command
+ redraw!
+
+ elseif has('mac') && has('gui_running')
+ let result = ''
+ exec s:MacGuiCmd(a:command, terminal)
+
+ " gnome-terminal needs quotes around the screen call, but konsole and
+ " rxvt based terms (urxvt, aterm, mrxvt, etc.) don't work properly with
+ " quotes. xterm seems content either way, so we'll treat gnome-terminal
+ " as the odd ball here.
+ elseif terminal == 'gnome-terminal'
+ let result = system(terminal . ' -e "' . a:command . '" &')
+
+ else
+ let result = system(terminal . ' -e ' . a:command . ' &')
+ endif
+ return result
+endfunction " }}}
+
+" s:GetScreenSessions() {{{
+" Gets a list of screen [session, state] pairs.
+function! s:GetScreenSessions()
+ let results = split(system('screen -wipe'), "\n")
+ call filter(results, 'v:val =~ "(\\w\\+)"')
+ call map(results, '[' .
+ \ 'substitute(v:val, "^\\s*\\(\\S*\\).*", "\\1", ""), ' .
+ \ 'tolower(substitute(v:val, "(\\(\\w\\+\\))$", "\\1", ""))]')
+ return results
+endfunction " }}}
+
+" s:GetSize() {{{
+function! s:GetSize()
+ if s:orientation == 'vertical'
+ let size = g:ScreenShellWidth
+ let sizefunc = 'winwidth'
+ else
+ let size = g:ScreenShellHeight
+ let sizefunc = 'winheight'
+ endif
+
+ if size <= 0
+ exec 'let size = ' . sizefunc . '(winnr()) / 2'
+ endif
+ return size
+endfunction " }}}
+
+" s:GetTerminal() {{{
+" Generate a name for the given command.
+function! s:GetTerminal()
+ if g:ScreenShellTerminal == ''
+ for term in s:terminals
+ if s:ValidTerminal(term)
+ let g:ScreenShellTerminal = term
+ break
+ endif
+ endfor
+ endif
+ return g:ScreenShellTerminal
+endfunction " }}}
+
+" s:ValidTerminal(term) {{{
+function! s:ValidTerminal(term)
+ if a:term == ''
+ return 0
+ endif
+
+ " assumes that Terminal.app, or whatever the user may have set, is available
+ if has('mac') && has('gui_running')
+ return 1
+ endif
+
+ if has('win32unix')
+ if !executable(a:term)
+ let term = substitute(a:term, '\', '/', 'g')
+ let term = substitute(system('cygpath "' . term . '"'), '\n', '', 'g')
+ return executable(term)
+ endif
+ endif
+
+ return executable(a:term)
+endfunction " }}}
+
+" s:MacGuiCmd(cmd, term) {{{
+function! s:MacGuiCmd(cmd, term)
+ if a:term != '0'
+ return 'silent !osascript -e "tell application \"' . a:term .
+ \ '\"" -e "do script \"' . a:cmd . '\"" -e "end tell"'
+ endif
+
+ let cmd = substitute(a:cmd, '"', "'", 'g')
+ return 'silent !osascript -e "do shell script \"' . cmd . '\""'
+endfunction " }}}
+
+" CommandCompleteScreenSessions(argLead, cmdLine, cursorPos) {{{
+function! screen#CommandCompleteScreenSessions(argLead, cmdLine, cursorPos)
+ let cmdLine = strpart(a:cmdLine, 0, a:cursorPos)
+ let cmdTail = strpart(a:cmdLine, a:cursorPos)
+ let argLead = substitute(a:argLead, cmdTail . '$', '', '')
+
+ if g:ScreenImpl == 'GnuScreen'
+ let sessions = s:GetScreenSessions()
+ if has('win32') || has('win64') || has('win32unix')
+ call filter(sessions, 'v:val[1] != "detached"')
+ endif
+ call map(sessions, 'v:val[0]')
+ if cmdLine !~ '[^\\]\s$'
+ call filter(sessions, 'v:val =~ "^' . argLead . '"')
+ endif
+
+ return sessions
+ endif
+
+ return []
+endfunction " }}}
+
+let s:screenGnuScreen = {}
+
+function s:screenGnuScreen.isValid() dict " {{{
+ if !executable('screen')
+ echoerr 'gnu screen not found in your path'
+ return 0
+ endif
+ return 1
+endfunction " }}}
+
+function s:screenGnuScreen.attachSession(session) dict " {{{
+ let sessions = s:GetScreenSessions()
+ if a:session != ''
+ let session = []
+ for s in sessions
+ if s[0] == a:session
+ let session = s
+ break
+ endif
+ endfor
+
+ if len(session) == 0
+ echoerr 'unable to find the gnu screen session "' . a:session . '"'
+ return
+ endif
+ elseif len(sessions) > 0
+ if has('win32') || has('win64') || has('win32unix')
+ call filter(sessions, 'v:val[1] != "detached"')
+ endif
+ let session = sessions[0]
+ else
+ echoerr 'unable to find any gnu screen sessions'
+ return
+ endif
+
+ if session[1] == 'detached'
+ if has('win32') || has('win64') || has('win32unix')
+ echoerr 'attaching to a session in the "Detached" state is not ' .
+ \ 'supported on windows due to deficiencies in the cygwin version ' .
+ \ 'of gnu screen.'
+ return
+ endif
+ let result = self.newTerminalResume()
+ if result == '0'
+ return
+ endif
+ if v:shell_error
+ echoerr result
+ endif
+ endif
+
+ return session[0]
+endfunction " }}}
+
+function s:screenGnuScreen.bootstrap(server, sessionfile, cmd) dict " {{{
+ let vertical = s:orientation == 'vertical' ? 'Vertical' : ''
+ exec 'silent! !screen -S ' . g:ScreenShellSession .
+ \ ' vim ' . a:server .
+ \ '-c "silent source ' . escape(a:sessionfile, ' ') . '" ' .
+ \ '-c "ScreenShell' . vertical . ' ' . a:cmd . '"'
+endfunction " }}}
+
+function s:screenGnuScreen.newSessionName() dict " {{{
+ return substitute(tempname(), '\W', '', 'g')
+endfunction " }}}
+
+function s:screenGnuScreen.newTerminal() dict " {{{
+ return s:StartTerminal('screen -S ' . g:ScreenShellSession)
+endfunction " }}}
+
+function s:screenGnuScreen.newTerminalMulti() dict " {{{
+ return s:StartTerminal('screen -S ' . g:ScreenShellSession . ' -x')
+endfunction " }}}
+
+function s:screenGnuScreen.newTerminalResume() dict " {{{
+ return s:StartTerminal('screen -r ' . g:ScreenShellSession)
+endfunction " }}}
+
+function s:screenGnuScreen.newWindow(focus) dict " {{{
+ return self.exec(printf(
+ \ '-X eval "screen -t %s" %s',
+ \ g:ScreenShellWindow,
+ \ a:focus ? '""' : '"other"'))
+endfunction " }}}
+
+function s:screenGnuScreen.openRegion(cmd) dict " {{{
+ let splitcmd = 'split'
+ if s:orientation == 'vertical'
+ if g:ScreenShellGnuScreenVerticalSupport == 'patch'
+ let splitcmd = 'vert_split'
+ elseif g:ScreenShellGnuScreenVerticalSupport == 'native'
+ let splitcmd = 'split -v'
+ else
+ echohl WarningMsg
+ echom 'Unsupported g:ScreenShellGnuScreenVerticalSupport value "' .
+ \ g:ScreenShellGnuScreenVerticalSupport . '". ' .
+ \ 'Supported values included "patch" or "native".'
+ echohl Normal
+ let s:orientation = ''
+ endif
+ endif
+
+ let focus = g:ScreenShellInitialFocus == 'shell' ? '' : ' "focus up"'
+ let chdir = exists('g:ScreenShellBootstrapped') ? '' : '"chdir \"' . getcwd() . '\"" '
+ let result = self.exec('-X eval ' .
+ \ '"' . splitcmd . '" ' .
+ \ '"focus down" ' .
+ \ '"resize ' . s:GetSize() . '" ' .
+ \ chdir .
+ \ '"screen -t ' . g:ScreenShellWindow . '"' .
+ \ focus)
+
+ " if we ran a chdir, reset it
+ if chdir != ''
+ call self.exec('-X eval "chdir"')
+ endif
+
+ if !v:shell_error && a:cmd != ''
+ let result = self.send(a:cmd)
+ endif
+
+ return result
+endfunction " }}}
+
+function s:screenGnuScreen.setTitle() dict " {{{
+ return self.exec('-X title ' . g:ScreenShellWindow)
+endfunction " }}}
+
+function s:screenGnuScreen.send(value) dict " {{{
+ let lines = type(a:value) == 3 ? a:value : [a:value]
+ let tmp = tempname()
+ call writefile(lines, tmp)
+ try
+ if exists('g:ScreenShellWindow')
+ let result = self.exec(
+ \ '-p ' . g:ScreenShellWindow . ' -X eval ' .
+ \ '"msgminwait 0" ' .
+ \ '"msgwait 0" ' .
+ \ '"readbuf ' . tmp . '" ' .
+ \ '"at ' . g:ScreenShellWindow . ' paste ." ' .
+ \ '"msgwait 5" ' .
+ \ '"msgminwait 1"')
+ else
+ let result = self.exec(
+ \ '-X eval ' .
+ \ '"msgminwait 0" ' .
+ \ '"msgwait 0" ' .
+ \ '"readbuf ' . tmp . '" ' .
+ \ '"paste ." ' .
+ \ '"msgwait 5" ' .
+ \ '"msgminwait 1"')
+ endif
+ finally
+ call delete(tmp)
+ endtry
+ return result
+endfunction " }}}
+
+function s:screenGnuScreen.focus() dict " {{{
+ return self.exec('-X focus bottom')
+endfunction " }}}
+
+function s:screenGnuScreen.close(type) dict " {{{
+ call self.focus()
+ if a:type == 'region'
+ call self.exec('-X kill')
+ return self.exec('-X remove')
+ endif
+ return self.exec('-X kill')
+endfunction " }}}
+
+function s:screenGnuScreen.quit() dict " {{{
+ return self.exec('-X quit')
+endfunction " }}}
+
+function s:screenGnuScreen.exec(cmd) dict " {{{
+ let cmd = 'screen '
+ if exists('g:ScreenShellSession')
+ let cmd .= '-S ' . g:ScreenShellSession . ' '
+ endif
+ let cmd .= a:cmd
+
+ if has('win32unix')
+ let result = ''
+ exec 'silent! !' . cmd
+ redraw!
+ elseif has('mac') && has('gui_running')
+ let term = s:GetTerminal()
+ let result = ''
+ exec s:MacGuiCmd(cmd, '0')
+ else " system() works for windows gvim too
+ let result = system(cmd)
+ endif
+ return result
+endfunction " }}}
+
+let s:screenTmux = {}
+
+function s:screenTmux.isValid() dict " {{{
+ if !executable('tmux')
+ echoerr 'tmux not found in your path'
+ return 0
+ endif
+
+ if has('win32') || has('win64')
+ echoerr 'ScreenShell does not currently support tmux on windows.'
+ return 0
+ endif
+
+ return 1
+endfunction " }}}
+
+function s:screenTmux.activePane() dict "{{{
+ " tmux 1.4: (active) label for current pane
+ " tmux 1.5: Unique %paneid for every pane
+ let line = self.exec('list-panes | grep "(active)$"')
+ let paneid = matchstr(line, '\v\%\d+ \(active\)')
+ if !empty(paneid)
+ return matchstr(paneid, '\v^\%\d+')
+ else
+ return matchstr(line, '\v^\d+')
+ endif
+endfunction " }}}
+
+function s:screenTmux.attachSession(session) dict " {{{
+ " TODO: currently unable to implement this since we use -S which creates a
+ " new server, which a tmux list-sessions wouldn't be able to talk to. As
+ " for sessions created on the default server, we can get the list of
+ " sessions, but tmux doesn't appear to have a way to send commands targeting
+ " a specific session, which is why we use -S to target servers.
+ echom 'Attaching to an existing session is currently not supported with tmux.'
+ return
+endfunction " }}}
+
+function s:screenTmux.bootstrap(server, sessionfile, cmd) dict " {{{
+ let vertical = s:orientation == 'vertical' ? 'Vertical' : ''
+ exec printf('silent! !tmux %s -S %s new-session ' .
+ \ '"vim %s -c \"silent source %s\" -c \"ScreenShell' . vertical . ' %s\""',
+ \ g:ScreenShellTmuxInitArgs, g:ScreenShellSession,
+ \ a:server, escape(a:sessionfile, ' '), a:cmd)
+endfunction " }}}
+
+function s:screenTmux.newSessionName() dict " {{{
+ return tempname()
+endfunction " }}}
+
+function s:screenTmux.newTerminal() dict " {{{
+ return s:StartTerminal(printf(
+ \ 'tmux %s -S %s', g:ScreenShellTmuxInitArgs, g:ScreenShellSession))
+endfunction " }}}
+
+function s:screenTmux.newTerminalResume() dict " {{{
+ return s:StartTerminal(printf(
+ \ 'tmux %s -S %s attach-session',
+ \ g:ScreenShellTmuxInitArgs, g:ScreenShellSession))
+endfunction " }}}
+
+function s:screenTmux.newWindow(focus) dict " {{{
+ let result = self.exec('new-window -n ' . g:ScreenShellWindow . (a:focus ? '' : ' -d'))
+ let g:ScreenShellTmuxPane = self.activePane()
+ return result
+endfunction " }}}
+
+function s:screenTmux.openRegion(cmd) dict " {{{
+ let orient = s:orientation == 'vertical' ? '-h ' : ''
+ let focus = g:ScreenShellInitialFocus == 'shell' ? '' : (' ; select-pane -t ' . self.activePane())
+
+ let result = self.exec('split ' . orient . '-l ' . s:GetSize())
+ if v:shell_error | return result | endif
+
+ let g:ScreenShellTmuxPane = self.activePane()
+
+ let result = self.exec('rename-window ' . g:ScreenShellWindow . focus)
+ if v:shell_error | return result | endif
+
+ if !v:shell_error && a:cmd != ''
+ let result = self.send(a:cmd)
+ if v:shell_error | return result | endif
+ endif
+endfunction " }}}
+
+function s:screenTmux.setTitle() dict " {{{
+ return self.exec('rename-window ' . g:ScreenShellWindow)
+endfunction " }}}
+
+function s:screenTmux.send(value) dict " {{{
+ let vimpane = self.activePane()
+ let lines = type(a:value) == 3 ? a:value : [a:value]
+ let tmp = tempname()
+ call writefile(lines, tmp)
+ try
+ let result = self.focus()
+ if v:shell_error
+ return result
+ endif
+ let result = self.exec(printf(
+ \ 'load-buffer %s ; ' .
+ \ 'paste-buffer', tmp
+ \ ))
+ if exists('g:ScreenShellWindow') && !g:ScreenShellExternal
+ call self.exec('select-pane -t ' . vimpane)
+ endif
+ finally
+ call delete(tmp)
+ endtry
+ return result
+endfunction " }}}
+
+function s:screenTmux.focus() dict " {{{
+ if !exists('g:ScreenShellWindow')
+ return
+ endif
+
+ let result = self.exec('list-windows')
+ if v:shell_error
+ return result
+ endif
+
+ let windows = filter(
+ \ split(result, "\n"),
+ \ 'v:val =~ "^\\s*\\d\\+:\\s\\+' . g:ScreenShellWindow . '"')
+ if len(windows)
+ let window = substitute(windows[0], '^\s*\(\d\+\):.*', '\1', '')
+ let result = self.exec('select-window -t:' . window)
+ if v:shell_error
+ return result
+ endif
+ endif
+
+ if !g:ScreenShellExternal
+ let result = self.exec('select-pane -t ' . g:ScreenShellTmuxPane)
+ endif
+ return result
+endfunction " }}}
+
+function s:screenTmux.quit() dict " {{{
+ return self.exec('kill-session')
+endfunction " }}}
+
+function s:screenTmux.close(type) dict " {{{
+ let result = self.focus()
+ if v:shell_error
+ return result
+ endif
+ return self.exec('kill-pane')
+endfunction " }}}
+
+function s:screenTmux.exec(cmd) dict " {{{
+ let tmux = 'tmux '
+ let cmd = a:cmd
+
+ if exists('g:ScreenShellSession')
+ let tmux .= '-S ' . g:ScreenShellSession . ' '
+ endif
+
+ " hack to account for apparent bug in tmux when redirecting stdout to a file
+ " when attempting to list windows
+ if cmd =~ 'list-windows'
+ let cmd .= ' | cat'
+ endif
+
+ return system(tmux . escape(cmd, ';'))
+endfunction " }}}
+
+let s:screenConque = {}
+
+function s:screenConque.isValid() dict " {{{
+ if !exists(':ConqueTerm')
+ echoerr 'The conque plugin does not appear to be loaded'
+ return 0
+ endif
+
+ return 1
+endfunction " }}}
+
+function s:screenConque.openRegion(cmd) dict " {{{
+ " without this, the conque behavior isn't very useful
+ let g:ConqueTerm_ReadUnfocused = 1
+
+ let split = s:orientation == 'vertical' ? 'bot vsplit' : 'bot split'
+ let remain = g:ScreenShellInitialFocus == 'vim' ? 1 : 0
+ let cmd = a:cmd != '' ? a:cmd : 'bash'
+
+ call conque_term#open(cmd, [split], remain)
+
+ " maybe a bug with conque, bug the cmd output doesn't seem to start until
+ " insert mode is entered.
+ startinsert
+endfunction " }}}
+
+function s:screenConque.send(value) dict " {{{
+ let lines = type(a:value) == 3 ? a:value : [a:value]
+
+ let term = conque_term#get_instance()
+ for line in lines
+ call term.writeln(line)
+ endfor
+endfunction " }}}
+
+function s:screenConque.quit() dict " {{{
+ call conque_term#get_instance().close()
+endfunction " }}}
+
+let &cpo = s:save_cpo
+
+" vim:ft=vim:fdm=marker