1
0
mirror of https://github.com/akelge/zsh synced 2025-07-04 13:39:07 +00:00

Added GetLatestScript update plugin and updated all plugins

This commit is contained in:
2013-01-17 12:18:17 +00:00
parent d9013ec2da
commit 4873c64f28
54 changed files with 10380 additions and 4761 deletions

View File

@ -1,10 +1,10 @@
" Align: tool to align multiple fields based on one or more separators
" Author: Charles E. Campbell, Jr.
" Date: Mar 03, 2009
" Version: 35
" Date: Jun 18, 2012
" Version: 36
" GetLatestVimScripts: 294 1 :AutoInstall: Align.vim
" GetLatestVimScripts: 1066 1 :AutoInstall: cecutil.vim
" Copyright: Copyright (C) 1999-2007 Charles E. Campbell, Jr. {{{1
" Copyright: Copyright (C) 1999-2012 Charles E. Campbell, Jr. {{{1
" Permission is hereby granted to use and distribute this code,
" with or without modifications, provided that this copyright
" notice is copied with it. Like anything else that's free,
@ -18,13 +18,14 @@
" the power of God for salvation for everyone who believes; for the Jew first,
" and also for the Greek. For in it is revealed God's righteousness from
" faith to faith.
"redraw!|call DechoSep()|call inputsave()|call input("Press <cr> to continue")|call inputrestore()
" ---------------------------------------------------------------------
" Load Once: {{{1
if exists("g:loaded_Align") || &cp
finish
endif
let g:loaded_Align = "v35"
let g:loaded_Align = "v36"
if v:version < 700
echohl WarningMsg
echo "***warning*** this version of Align needs vim 7.0"
@ -84,14 +85,13 @@ endif
" | s:AlignSep
fun! Align#AlignCtrl(...)
" call Dfunc("AlignCtrl(...) a:0=".a:0)
" call Dfunc("Align#AlignCtrl(...) a:0=".a:0)
" save options that will be changed
let keep_search = @/
let keep_ic = &ic
" save options that may be changed later
call s:SaveUserOptions()
" turn ignorecase off
set noic
setlocal noic
" clear visual mode so that old visual-mode selections don't
" get applied to new invocations of Align().
@ -121,19 +121,20 @@ fun! Align#AlignCtrl(...)
let ipat= 2
while ipat <= A[0]
if "" =~ A[ipat]
echoerr "AlignCtrl: separator<".A[ipat]."> matches zero-length string"
let &ic= keep_ic
" call Dret("AlignCtrl")
echoerr "(AlignCtrl) separator<".A[ipat]."> matches zero-length string"
call s:RestoreUserOptions()
" call Dret("Align#AlignCtrl")
return
endif
let ipat= ipat + 1
endwhile
endif
endif
" call Decho("(AlignCtrl) passed bad-separator pattern check (no zero-length matches)")
" call Decho("AlignCtrl() A[0]=".A[0])
" call Decho("(AlignCtrl) A[0]=".A[0])
if !exists("s:AlignStyle")
let s:AlignStyle= "l"
let s:AlignStyle= 'l'
endif
if !exists("s:AlignPrePad")
let s:AlignPrePad= 0
@ -153,7 +154,7 @@ fun! Align#AlignCtrl(...)
let s:AlignPatQty= 0
endif
echo "AlignCtrl<".s:AlignCtrl."> qty=".s:AlignPatQty." AlignStyle<".s:AlignStyle."> Padding<".s:AlignPrePad."|".s:AlignPostPad."> LeadingWS=".s:AlignLeadKeep." AlignSep=".s:AlignSep
" call Decho("AlignCtrl<".s:AlignCtrl."> qty=".s:AlignPatQty." AlignStyle<".s:AlignStyle."> Padding<".s:AlignPrePad."|".s:AlignPostPad."> LeadingWS=".s:AlignLeadKeep." AlignSep=".s:AlignSep)
" call Decho("(AlignCtrl) AlignCtrl<".s:AlignCtrl."> qty=".s:AlignPatQty." AlignStyle<".s:AlignStyle."> Padding<".s:AlignPrePad."|".s:AlignPostPad."> LeadingWS=".s:AlignLeadKeep." AlignSep=".s:AlignSep)
if exists("s:AlignGPat") && !exists("s:AlignVPat")
echo "AlignGPat<".s:AlignGPat.">"
elseif !exists("s:AlignGPat") && exists("s:AlignVPat")
@ -164,7 +165,7 @@ fun! Align#AlignCtrl(...)
let ipat= 1
while ipat <= s:AlignPatQty
echo "Pat".ipat."<".s:AlignPat_{ipat}.">"
" call Decho("Pat".ipat."<".s:AlignPat_{ipat}.">")
" call Decho("(AlignCtrl) Pat".ipat."<".s:AlignPat_{ipat}.">")
let ipat= ipat + 1
endwhile
@ -190,9 +191,8 @@ fun! Align#AlignCtrl(...)
call Align#AlignCtrl("g")
call Align#AlignCtrl("v")
let s:dovisclear = 1
let &ic = keep_ic
let @/ = keep_search
" call Dret("AlignCtrl")
call s:RestoreUserOptions()
" call Dret("Align#AlignCtrl")
return
endif
@ -205,7 +205,7 @@ fun! Align#AlignCtrl(...)
endif
" = : record a list of alignment patterns that are equivalent
if style =~# "="
if style =~# "=" || (A[0] >= 2 && style !~# "C" && s:AlignCtrl =~# '=')
" call Decho("style case =: record list of equiv alignment patterns")
let s:AlignCtrl = '='
if A[0] >= 2
@ -221,7 +221,7 @@ fun! Align#AlignCtrl(...)
endif
"c : cycle through alignment pattern(s)
elseif style =~# 'C'
elseif style =~# 'C' || (A[0] >= 2 && s:AlignCtrl =~# '=')
" call Decho("style case C: cycle through alignment pattern(s)")
let s:AlignCtrl = 'C'
if A[0] >= 2
@ -239,10 +239,9 @@ fun! Align#AlignCtrl(...)
let s:AlignPrePad= substitute(style,'^.*p\(\d\+\).*$','\1','')
" call Decho("style case p".s:AlignPrePad.": pre-separator padding")
if s:AlignPrePad == ""
echoerr "AlignCtrl: 'p' needs to be followed by a numeric argument'
let @/ = keep_search
let &ic= keep_ic
" call Dret("AlignCtrl")
echoerr "(AlignCtrl) 'p' needs to be followed by a numeric argument'"
call s:RestoreUserOptions()
" call Dret("Align#AlignCtrl")
return
endif
endif
@ -251,10 +250,9 @@ fun! Align#AlignCtrl(...)
let s:AlignPostPad= substitute(style,'^.*P\(\d\+\).*$','\1','')
" call Decho("style case P".s:AlignPostPad.": post-separator padding")
if s:AlignPostPad == ""
echoerr "AlignCtrl: 'P' needs to be followed by a numeric argument'
let @/ = keep_search
let &ic= keep_ic
" call Dret("AlignCtrl")
echoerr "(AlignCtrl) 'P' needs to be followed by a numeric argument'"
call s:RestoreUserOptions()
" call Dret("Align#AlignCtrl")
return
endif
endif
@ -263,10 +261,10 @@ fun! Align#AlignCtrl(...)
" call Decho("style case w: ignore leading whitespace")
let s:AlignLeadKeep= 'w'
elseif style =~# 'W'
" call Decho("style case w: keep leading whitespace")
" call Decho("style case W: keep leading whitespace")
let s:AlignLeadKeep= 'W'
elseif style =~# 'I'
" call Decho("style case w: retain initial leading whitespace")
" call Decho("style case I: retain initial leading whitespace")
let s:AlignLeadKeep= 'I'
endif
@ -274,8 +272,8 @@ fun! Align#AlignCtrl(...)
" first list item is a "g" selector pattern
" call Decho("style case g: global selector pattern")
if A[0] < 2
if exists("s:AlignGPat")
unlet s:AlignGPat
if exists("s:AlignVPat")
unlet s:AlignVPat
" call Decho("unlet s:AlignGPat")
endif
else
@ -286,8 +284,8 @@ fun! Align#AlignCtrl(...)
" first list item is a "v" selector pattern
" call Decho("style case v: global selector anti-pattern")
if A[0] < 2
if exists("s:AlignVPat")
unlet s:AlignVPat
if exists("s:AlignGPat")
unlet s:AlignGPat
" call Decho("unlet s:AlignVPat")
endif
else
@ -297,9 +295,9 @@ fun! Align#AlignCtrl(...)
endif
"[-lrc+:] : set up s:AlignStyle
if style =~# '[-lrc+:]'
if style =~# '[-lrc+:*]'
" call Decho("style case [-lrc+:]: field justification")
let s:AlignStyle= substitute(style,'[^-lrc:+]','','g')
let s:AlignStyle= substitute(style,'[^-lrc:+*]','','g')
" call Decho("AlignStyle<".s:AlignStyle.">")
endif
@ -316,11 +314,9 @@ fun! Align#AlignCtrl(...)
let s:AlignCtrl= '='
endif
" restore search and options
let @/ = keep_search
let &ic= keep_ic
" call Dret("AlignCtrl ".s:AlignCtrl.'p'.s:AlignPrePad.'P'.s:AlignPostPad.s:AlignLeadKeep.s:AlignStyle)
" restore options and return
call s:RestoreUserOptions()
" call Dret("Align#AlignCtrl ".s:AlignCtrl.'p'.s:AlignPrePad.'P'.s:AlignPostPad.s:AlignLeadKeep.s:AlignStyle)
return s:AlignCtrl.'p'.s:AlignPrePad.'P'.s:AlignPostPad.s:AlignLeadKeep.s:AlignStyle
endfun
@ -355,6 +351,9 @@ fun! Align#Align(hasctrl,...) range
return
endif
" save user options
call s:SaveUserOptions()
" set up a list akin to an argument list
if a:0 > 0
let A= s:QArgSplitter(a:1)
@ -384,7 +383,8 @@ fun! Align#Align(hasctrl,...) range
let ipat= 1 + hasctrl
while ipat <= A[0]
if "" =~ A[ipat]
echoerr "Align: separator<".A[ipat]."> matches zero-length string"
echoerr "(Align) separator<".A[ipat]."> matches zero-length string"
call s:RestoreUserOptions()
" call Dret("Align#Align")
return
endif
@ -392,10 +392,8 @@ fun! Align#Align(hasctrl,...) range
endwhile
" record current search pattern for subsequent restoration
let keep_search= @/
let keep_ic = &ic
let keep_report= &report
set noic report=10000
" (these are all global-only options)
set noic report=10000 nohls
if A[0] > hasctrl
" Align will accept a list of separator regexps
@ -447,17 +445,32 @@ fun! Align#Align(hasctrl,...) range
let begline = a:lastline
let endline = a:firstline
endif
" Expand range to cover align-able lines when the given range is only the current line.
" Look for the first line above the current line that matches the first separator pattern, and
" look for the last line below the current line that matches the first separator pattern.
if begline == endline
" call Decho("case begline == endline")
if !exists("s:AlignPat_{1}")
echohl Error|echo "(Align) no separators specified!"|echohl None
call s:RestoreUserOptions()
" call Dret("Align#Align")
return
endif
let seppat = s:AlignPat_{1}
let begline= search('^\%(\%('.seppat.'\)\@!.\)*$',"bnW")
if begline == 0|let begline= 1|else|let begline= begline + 1|endif
let endline= search('^\%(\%('.seppat.'\)\@!.\)*$',"nW")
if endline == 0|let endline= line("$")|else|let endline= endline - 1|endif
" call Decho("begline=".begline." endline=".endline." curline#".line("."))
endif
" call Decho("begline=".begline." endline=".endline)
let fieldcnt = 0
if (begline == line("'>") && endline == line("'<")) || (begline == line("'<") && endline == line("'>"))
let vmode= visualmode()
" call Decho("vmode=".vmode)
if vmode == "\<c-v>"
if exists("g:Align_xstrlen") && g:Align_xstrlen
let ragged = ( col("'>") > s:Strlen(getline("'>")) || col("'<") > s:Strlen(getline("'<")) )
else
let ragged = ( col("'>") > strlen(getline("'>")) || col("'<") > strlen(getline("'<")) )
endif
let ragged = ( col("'>") > s:Strlen(getline("'>")) || col("'<") > s:Strlen(getline("'<")) )
else
let ragged= 1
endif
@ -469,10 +482,14 @@ fun! Align#Align(hasctrl,...) range
endif
" call Decho("lines[".begline.",".endline."] col[".begcol.",".endcol."] ragged=".ragged." AlignCtrl<".s:AlignCtrl.">")
" Keep user options
let etkeep = &l:et
let pastekeep= &l:paste
setlocal et paste
" record initial whitespace
if s:AlignLeadKeep == 'W'
let wskeep = map(getline(begline,endline),"substitute(v:val,'^\\(\\s*\\).\\{-}$','\\1','')")
endif
" Align needs these options
setl et
set paste
" convert selected range of lines to use spaces instead of tabs
" but if first line's initial white spaces are to be retained
@ -480,11 +497,30 @@ fun! Align#Align(hasctrl,...) range
if begcol <= 0 && s:AlignLeadKeep == 'I'
" retain first leading whitespace for all subsequent lines
let bgntxt= substitute(getline(begline),'^\(\s*\).\{-}$','\1','')
" exception: retain first leading whitespace predicated on g and v patterns
" if such a selected line exists
if exists("s:AlignGPat")
let firstgline= search(s:AlignGPat,"cnW",endline)
if firstgline > 0
let bgntxt= substitute(getline(firstgline),'^\(\s*\).\{-}$','\1','')
endif
elseif exists("s:AlignVPat")
let firstvline= search(s:AlignVPat,"cnW",endline)
if firstvline > 0
let bgntxt= substitute('^\%(\%('.getline(firstvline).')\@!\)*$','^\(\s*\).\{-}$','\1','')
endif
endif
" call Decho("retaining 1st leading whitespace: bgntxt<".bgntxt.">")
set noet
let &l:et= s:keep_et
endif
exe begline.",".endline."ret"
" record transformed to spaces leading whitespace
if s:AlignLeadKeep == 'W'
let wsblanks = map(getline(begline,endline),"substitute(v:val,'^\\(\\s*\\).\\{-}$','\\1','')")
endif
" Execute two passes
" First pass: collect alignment data (max field sizes)
" Second pass: perform alignment
@ -528,11 +564,7 @@ fun! Align#Align(hasctrl,...) range
endif
" Extract visual-block selected text (init bgntxt, endtxt)
if exists("g:Align_xstrlen") && g:Align_xstrlen
let txtlen= s:Strlen(txt)
else
let txtlen= strlen(txt)
endif
if begcol > 0
" Record text to left of selected area
let bgntxt= strpart(txt,0,begcol)
@ -557,7 +589,8 @@ fun! Align#Align(hasctrl,...) range
" call Decho("Pass".pass.": txt<". txt .">")
" call Decho("Pass".pass.": endtxt<".endtxt.">")
if !exists("s:AlignPat_{1}")
echohl Error|echo "no separators specified!"|echohl None
echohl Error|echo "(Align) no separators specified!"|echohl None
call s:RestoreUserOptions()
" call Dret("Align#Align")
return
endif
@ -575,7 +608,7 @@ fun! Align#Align(hasctrl,...) range
let alignpostpad= s:AlignPostPad
let alignsep = s:AlignSep
let alignophold = " "
let alignop = "l"
let alignop = 'l'
" call Decho("Pass".pass.": initial alignstyle<".alignstyle."> seppat<".seppat.">")
" Process each field on the line
@ -606,23 +639,41 @@ fun! Align#Align(hasctrl,...) range
endif
endif
" cylic separator alignment specification handling
" cyclic separator alignment specification handling
let alignsepop= strpart(alignsep,0,1)
let alignsep = strpart(alignsep,1).alignsepop
" ------------------------------------------------------
" mark end-of-field and the subsequent end-of-separator.
" Extend field if alignop is '-'
" ------------------------------------------------------
let endfield = match(txt,seppat,bgnfield)
let sepfield = matchend(txt,seppat,bgnfield)
let skipfield= sepfield
" call Decho("Pass".pass.": endfield=match(txt<".txt.">,seppat<".seppat.">,bgnfield=".bgnfield.")=".endfield)
" call Decho("Pass".pass.": endfield=match(txt<".txt.">,seppat<".seppat.">,bgnfield=".bgnfield.")=".endfield." alignop=".alignop)
" Mark eof: Extend field if alignop is '*' and AlignSkip() is true.
if alignop == '*' && exists("g:AlignSkip") && type(g:AlignSkip) == 2
" call Decho("Pass".pass.": endfield=match(txt<".txt.">,seppat<".seppat.">,bgnfield=".bgnfield.")=".endfield." alignop=".alignop)
" a '*' acts like a '-' while the g:AlignSkip function reference is true except that alignop doesn't advance
while g:AlignSkip(line,endfield) && endfield != -1
let endfield = match(txt,seppat,skipfield)
let sepfield = matchend(txt,seppat,skipfield)
let skipfield = sepfield
" call Decho("Pass".pass.": extend field: endfield<".strpart(txt,bgnfield,endfield-bgnfield)."> alignop<".alignop."> alignstyle<".alignstyle.">")
endwhile
let alignop = strpart(alignstyle,0,1)
let alignstyle= strpart(alignstyle,1).strpart(alignstyle,0,1)
" call Decho("Pass".pass.": endfield=match(txt<".txt.">,seppat<".seppat.">,bgnfield=".bgnfield.")=".endfield." alignop=".alignop." (after *)")
endif
" Mark eof: Extend field if alignop is '-'
while alignop == '-' && endfield != -1
let endfield = match(txt,seppat,skipfield)
let sepfield = matchend(txt,seppat,skipfield)
let skipfield = sepfield
let alignop = strpart(alignstyle,0,1)
let alignstyle= strpart(alignstyle,1).strpart(alignstyle,0,1)
" call Decho("Pass".pass.": extend field: endfield<".strpart(txt,bgnfield,endfield-bgnfield)."> alignop<".alignop."> alignstyle<".alignstyle.">")
" call Decho("Pass".pass.": extend field: endfield<".strpart(txt,bgnfield,endfield-bgnfield)."> alignop<".alignop."> alignstyle<".alignstyle.">")
endwhile
let seplen= sepfield - endfield
" call Decho("Pass".pass.": seplen=[sepfield=".sepfield."] - [endfield=".endfield."]=".seplen)
@ -637,11 +688,7 @@ fun! Align#Align(hasctrl,...) range
let field = bgntxt.field
let bgntxt= ""
endif
if exists("g:Align_xstrlen") && g:Align_xstrlen
let fieldlen = s:Strlen(field)
else
let fieldlen = strlen(field)
endif
let fieldlen = s:Strlen(field)
let sFieldSize = "FieldSize_".ifield
if !exists(sFieldSize)
let FieldSize_{ifield}= fieldlen
@ -675,11 +722,7 @@ fun! Align#Align(hasctrl,...) range
let prepad = 0
let postpad= 0
endif
if exists("g:Align_xstrlen") && g:Align_xstrlen
let fieldlen = s:Strlen(field)
else
let fieldlen = strlen(field)
endif
let fieldlen = s:Strlen(field)
let sep = s:MakeSpace(prepad).strpart(txt,endfield,sepfield-endfield).s:MakeSpace(postpad)
if seplen < SepSize_{ifield}
if alignsepop == "<"
@ -695,7 +738,7 @@ fun! Align#Align(hasctrl,...) range
let sep = s:MakeSpace(sepleft).sep.s:MakeSpace(sepright)
endif
endif
let spaces = FieldSize_{ifield} - fieldlen
let spaces = FieldSize_{ifield} - fieldlen
" call Decho("Pass".pass.": Field #".ifield."<".field."> spaces=".spaces." be[".bgnfield.",".endfield."] pad=".prepad.','.postpad." FS_".ifield."<".FieldSize_{ifield}."> sep<".sep."> ragged=".ragged." doend=".doend." alignop<".alignop.">")
" Perform alignment according to alignment style justification
@ -746,7 +789,7 @@ fun! Align#Align(hasctrl,...) range
" call Decho("Pass".pass.": bgntxt<".bgntxt."> line=".line)
" call Decho("Pass".pass.": newtxt<".newtxt.">")
" call Decho("Pass".pass.": endtxt<".endtxt.">")
call setline(line,bgntxt.newtxt.endtxt)
keepj call setline(line,bgntxt.newtxt.endtxt)
endif
let line = line + 1
@ -756,9 +799,18 @@ fun! Align#Align(hasctrl,...) range
endwhile " pass loop
" call Decho("end of two pass loop")
" Restore user options
let &l:et = etkeep
let &l:paste = pastekeep
" restore original leading whitespace
if s:AlignLeadKeep == 'W'
let iline= begline
let i = 0
" call Decho("restore original leading whitespace")
while iline <= endline
" call Decho("exe ".iline."s/^".wsblanks[i]."/".wskeep[i]."/")
exe "keepj ".iline."s/^".wsblanks[i]."/".wskeep[i]."/"
let iline= iline + 1
let i = i + 1
endwhile
endif
if exists("s:DoAlignPop")
" AlignCtrl Map support
@ -766,11 +818,8 @@ fun! Align#Align(hasctrl,...) range
unlet s:DoAlignPop
endif
" restore current search pattern
let @/ = keep_search
let &ic = keep_ic
let &report = keep_report
" restore user options and return
call s:RestoreUserOptions()
" call Dret("Align#Align")
return
endfun
@ -778,7 +827,7 @@ endfun
" ---------------------------------------------------------------------
" Align#AlignPush: this command/function pushes an alignment control string onto a stack {{{1
fun! Align#AlignPush()
" call Dfunc("AlignPush()")
" call Dfunc("Align#AlignPush()")
" initialize the stack
if !exists("s:AlignCtrlStackQty")
@ -806,7 +855,7 @@ fun! Align#AlignPush()
let s:AlignVPat_{s:AlignCtrlStackQty}= ""
endif
" call Dret("AlignPush")
" call Dret("Align#AlignPush")
endfun
" ---------------------------------------------------------------------
@ -817,13 +866,13 @@ fun! Align#AlignPop()
" sanity checks
if !exists("s:AlignCtrlStackQty")
echoerr "AlignPush needs to be used prior to AlignPop"
echoerr "(AlignPop) AlignPush needs to be used prior to AlignPop"
" call Dret("Align#AlignPop <> : AlignPush needs to have been called first")
return ""
endif
if s:AlignCtrlStackQty <= 0
unlet s:AlignCtrlStackQty
echoerr "AlignPush needs to be used prior to AlignPop"
echoerr "(AlignPop) AlignPush needs to be used prior to AlignPop"
" call Dret("Align#AlignPop <> : AlignPop needs to have been called first")
return ""
endif
@ -857,15 +906,11 @@ endfun
" ---------------------------------------------------------------------
" Align#AlignReplaceQuotedSpaces: {{{1
fun! Align#AlignReplaceQuotedSpaces()
" call Dfunc("AlignReplaceQuotedSpaces()")
fun! Align#AlignReplaceQuotedSpaces()
" call Dfunc("Align#AlignReplaceQuotedSpaces()")
let l:line = getline(line("."))
if exists("g:Align_xstrlen") && g:Align_xstrlen
let l:linelen = s:Strlen(l:line)
else
let l:linelen = strlen(l:line)
endif
let l:linelen = s:Strlen(l:line)
let l:startingPos = 0
let l:startQuotePos = 0
let l:endQuotePos = 0
@ -875,28 +920,28 @@ fun! Align#AlignReplaceQuotedSpaces()
" "call Decho("in replace spaces. line=" . line('.'))
while (1)
let l:startQuotePos = match(l:line, l:quoteRe, l:startingPos)
if (l:startQuotePos < 0)
" "call Decho("No more quotes to the end of line")
break
if (l:startQuotePos < 0)
" call Decho("No more quotes to the end of line")
break
endif
let l:endQuotePos = match(l:line, l:quoteRe, l:startQuotePos + 1)
if (l:endQuotePos < 0)
" "call Decho("Mismatched quotes")
break
" call Decho("Mismatched quotes")
break
endif
let l:spaceReplaceRe = '^.\{' . (l:startQuotePos + 1) . '}.\{-}\zs\s\ze.*.\{' . (linelen - l:endQuotePos) . '}$'
" "call Decho('spaceReplaceRe="' . l:spaceReplaceRe . '"')
" call Decho('spaceReplaceRe="' . l:spaceReplaceRe . '"')
let l:newStr = substitute(l:line, l:spaceReplaceRe, '%', '')
while (l:newStr != l:line)
" "call Decho('newstr="' . l:newStr . '"')
" call Decho('newstr="' . l:newStr . '"')
let l:line = l:newStr
let l:newStr = substitute(l:line, l:spaceReplaceRe, '%', '')
endwhile
let l:startingPos = l:endQuotePos + 1
endwhile
call setline(line('.'), l:line)
keepj call setline(line('.'), l:line)
" call Dret("AlignReplaceQuotedSpaces")
" call Dret("Align#AlignReplaceQuotedSpaces")
endfun
" ---------------------------------------------------------------------
@ -923,19 +968,20 @@ fun! s:QArgSplitter(qarg)
while args != ""
let iarg = 0
let arglen = strlen(args)
" call Decho("args[".iarg."]<".args[iarg]."> arglen=".arglen)
" call Decho(".args[".iarg."]<".args[iarg]."> arglen=".arglen)
" find index to first not-escaped '"'
" call Decho("find index to first not-escaped \"")
while args[iarg] != '"' && iarg < arglen
if args[iarg] == '\'
let args= strpart(args,1)
endif
let iarg= iarg + 1
endwhile
" call Decho("args<".args."> iarg=".iarg." arglen=".arglen)
" call Decho(".args<".args."> iarg=".iarg." arglen=".arglen)
if iarg > 0
" handle left of quote or remaining section
" call Decho("handle left of quote or remaining section")
" call Decho(".handle left of quote or remaining section")
if args[iarg] == '"'
let qarglist= qarglist + split(strpart(args,0,iarg-1))
else
@ -946,7 +992,7 @@ fun! s:QArgSplitter(qarg)
elseif iarg < arglen && args[0] == '"'
" handle "quoted" section
" call Decho("handle quoted section")
" call Decho(".handle quoted section")
let iarg= 1
while args[iarg] != '"' && iarg < arglen
if args[iarg] == '\'
@ -954,7 +1000,7 @@ fun! s:QArgSplitter(qarg)
endif
let iarg= iarg + 1
endwhile
" call Decho("args<".args."> iarg=".iarg." arglen=".arglen)
" call Decho(".args<".args."> iarg=".iarg." arglen=".arglen)
if args[iarg] == '"'
call add(qarglist,strpart(args,1,iarg-1))
let args= strpart(args,iarg+1)
@ -963,12 +1009,14 @@ fun! s:QArgSplitter(qarg)
let args = ""
endif
endif
" call Decho("qarglist".string(qarglist)." iarg=".iarg." args<".args.">")
" call Decho(".qarglist".string(qarglist)." iarg=".iarg." args<".args.">")
endwhile
" call Decho("end of loop (handling quoted arguments)")
else
" split at all whitespace
let qarglist= split(a:qarg)
" call Decho("split at all whitespace")
let qarglist= split(a:qarg,"[ \t]")
endif
let qarglistlen= len(qarglist)
@ -984,21 +1032,26 @@ endfun
" nonzero value. Solution from Nicolai Weibull, vim docs
" (:help strlen()), Tony Mechelynck, and my own invention.
fun! s:Strlen(x)
" call Dfunc("s:Strlen(x<".a:x.">")
if g:Align_xstrlen == 1
" call Dfunc("s:Strlen(x<".a:x."> g:Align_xstrlen=".g:Align_xstrlen)
if type(g:Align_xstrlen) == 1
" allow user to specify a function to compute the string length
exe "let ret= ".g:Align_xstrlen."('".substitute(a:x,"'","''","g")."')"
elseif g:Align_xstrlen == 1
" number of codepoints (Latin a + combining circumflex is two codepoints)
" (comment from TM, solution from NW)
let ret= strlen(substitute(a:x,'.','c','g'))
elseif g:Align_xstrlen == 2
" number of spacing codepoints (Latin a + combining circumflex is one spacing
" number of spacing codepoints (Latin a + combining circumflex is one spacing
" codepoint; a hard tab is one; wide and narrow CJK are one each; etc.)
" (comment from TM, solution from TM)
let ret=strlen(substitute(a:x, '.\Z', 'x', 'g'))
let ret=strlen(substitute(a:x, '.\Z', 'x', 'g'))
elseif g:Align_xstrlen == 3
" virtual length (counting, for instance, tabs as anything between 1 and
" 'tabstop', wide CJK as 2 rather than 1, Arabic alif as zero when immediately
" virtual length (counting, for instance, tabs as anything between 1 and
" 'tabstop', wide CJK as 2 rather than 1, Arabic alif as zero when immediately
" preceded by lam, one otherwise, etc.)
" (comment from TM, solution from me)
let modkeep= &l:mod
@ -1010,12 +1063,58 @@ fun! s:Strlen(x)
else
" at least give a decent default
ret= strlen(a:x)
if v:version >= 703
let ret= strdisplaywidth(a:x)
else
let ret= strlen(a:x)
endif
endif
" call Dret("s:Strlen ".ret)
return ret
endfun
" ---------------------------------------------------------------------
" s:SaveUserOptions: {{{1
fun! s:SaveUserOptions()
" call Dfunc("s:SaveUserOptions() s:saved_user_options=".(exists("s:saved_user_options")? s:saved_user_options : 'n/a'))
if !exists("s:saved_user_options")
let s:saved_user_options = 1
let s:keep_search = @/
let s:keep_et = &l:et
let s:keep_hls = &hls
let s:keep_ic = &ic
let s:keep_paste = &paste
let s:keep_report = &report
else
let s:saved_user_options = s:saved_user_options + 1
endif
" call Dret("s:SaveUserOptions : s:saved_user_options=".s:saved_user_options)
endfun
" ---------------------------------------------------------------------
" s:RestoreUserOptions: {{{1
fun! s:RestoreUserOptions()
" call Dfunc("s:RestoreUserOptions() s:saved_user_options=".(exists("s:saved_user_options")? s:saved_user_options : 'n/a'))
if exists("s:saved_user_options") && s:saved_user_options == 1
let @/ = s:keep_search
let &l:et = s:keep_et
let &hls = s:keep_hls
let &ic = s:keep_ic
let &paste = s:keep_paste
let &report = s:keep_report
unlet s:keep_search
unlet s:keep_et
unlet s:keep_hls
unlet s:keep_ic
unlet s:keep_paste
unlet s:keep_report
unlet s:saved_user_options
elseif exists("s:saved_user_options")
let s:saved_user_options= s:saved_user_options - 1
endif
" call Dret("s:RestoreUserOptions : s:saved_user_options=".(exists("s:saved_user_options")? s:saved_user_options : 'n/a'))
endfun
" ---------------------------------------------------------------------
" Set up default values: {{{1
"call Decho("-- Begin AlignCtrl Initialization --")

View File

@ -1,15 +1,25 @@
" AlignMaps.vim : support functions for AlignMaps
" Author: Charles E. Campbell, Jr.
" Date: Mar 03, 2009
" Version: 41
" Date: Jun 18, 2012
" Version: 42
" Copyright: Copyright (C) 1999-2012 Charles E. Campbell, Jr. {{{1
" Permission is hereby granted to use and distribute this code,
" with or without modifications, provided that this copyright
" notice is copied with it. Like anything else that's free,
" Align.vim is provided *as is* and comes with no warranty
" of any kind, either expressed or implied. By using this
" plugin, you agree that in no event will the copyright
" holder be liable for any damages resulting from the use
"redraw!|call DechoSep()|call inputsave()|call input("Press <cr> to continue")|call inputrestore()
" ---------------------------------------------------------------------
" Load Once: {{{1
if &cp || exists("g:loaded_AlignMaps")
finish
endif
let g:loaded_AlignMaps= "v41"
let g:loaded_AlignMaps= "v42"
let s:keepcpo = &cpo
set cpo&vim
"DechoTabOn
" =====================================================================
" Functions: {{{1
@ -20,7 +30,7 @@ fun! AlignMaps#WrapperStart(vis) range
" call Dfunc("AlignMaps#WrapperStart(vis=".a:vis.")")
if a:vis
norm! '<ma'>
keepj norm! '<ma'>
endif
if line("'y") == 0 || line("'z") == 0 || !exists("s:alignmaps_wrapcnt") || s:alignmaps_wrapcnt <= 0
@ -34,22 +44,22 @@ fun! AlignMaps#WrapperStart(vis) range
let s:alignmaps_posn = SaveWinPosn(0)
" set up fencepost blank lines
put =''
norm! mz'a
keepj norm! mz'a
put! =''
ky
let s:alignmaps_zline = line("'z")
exe "'y,'zs/@/\177/ge"
exe "keepj 'y,'zs/@/\177/ge"
else
" call Decho("embedded wrapper")
let s:alignmaps_wrapcnt = s:alignmaps_wrapcnt + 1
norm! 'yjma'zk
keepj norm! 'yjma'zk
endif
" change some settings to align-standard values
set nogd
set ch=2
AlignPush
norm! 'zk
keepj norm! 'zk
" call Dret("AlignMaps#WrapperStart : alignmaps_wrapcnt=".s:alignmaps_wrapcnt." my=".line("'y")." mz=".line("'z"))
endfun
@ -59,7 +69,7 @@ fun! AlignMaps#WrapperEnd() range
" call Dfunc("AlignMaps#WrapperEnd() alignmaps_wrapcnt=".s:alignmaps_wrapcnt." my=".line("'y")." mz=".line("'z"))
" remove trailing white space introduced by whatever in the modification zone
'y,'zs/ \+$//e
keepj 'y,'zs/ \+$//e
" restore AlignCtrl settings
AlignPop
@ -67,14 +77,14 @@ fun! AlignMaps#WrapperEnd() range
let s:alignmaps_wrapcnt= s:alignmaps_wrapcnt - 1
if s:alignmaps_wrapcnt <= 0
" initial wrapper ending
exe "'y,'zs/\177/@/ge"
exe "keepj 'y,'zs/\177/@/ge"
" if the 'z line hasn't moved, then go ahead and restore window position
let zstationary= s:alignmaps_zline == line("'z")
" remove fencepost blank lines.
" restore 'a
norm! 'yjmakdd'zdd
keepj norm! 'yjmakdd'zdd
" restore original 'y, 'z, and window positioning
call RestoreMark(s:alignmaps_keepmy)
@ -135,10 +145,10 @@ fun! AlignMaps#CharJoiner(chr)
let aline = line("'a")
let rep = line(".") - aline
while rep > 0
norm! 'a
keepj norm! 'a
while match(getline(aline),a:chr . "\s*$") != -1 && rep >= 0
" while = at end-of-line, delete it and join with next
norm! 'a$
keepj norm! 'a$
j!
let rep = rep - 1
endwhile
@ -149,7 +159,7 @@ fun! AlignMaps#CharJoiner(chr)
break
endif
" prepare for next line
norm! jma
keepj norm! jma
let aline = line("'a")
endwhile
" call Dret("AlignMaps#CharJoiner")
@ -159,31 +169,32 @@ endfun
" AlignMaps#Equals: supports \t= and \T= {{{2
fun! AlignMaps#Equals() range
" call Dfunc("AlignMaps#Equals()")
'a,'zs/\s\+\([*/+\-%|&\~^]\==\)/ \1/e
'a,'zs@ \+\([*/+\-%|&\~^]\)=@\1=@ge
'a,'zs/==/\="\<Char-0x0f>\<Char-0x0f>"/ge
'a,'zs/\([!<>:]\)=/\=submatch(1)."\<Char-0x0f>"/ge
norm g'zk
keepj 'a,'zs/\s\+\([*/+\-%|&\~^]\==\)/ \1/e
keepj 'a,'zs@ \+\([*/+\-%|&\~^]\)=@\1=@ge
keepj 'a,'zs/==/\="\<Char-0x0f>\<Char-0x0f>"/ge
keepj 'a,'zs/\([!<>:]\)=/\=submatch(1)."\<Char-0x0f>"/ge
keepj norm g'zk
AlignCtrl mIp1P1=l =
AlignCtrl g =
'a,'z-1Align
'a,'z-1s@\([*/+\-%|&\~^!=]\)\( \+\)=@\2\1=@ge
'a,'z-1s/\( \+\);/;\1/ge
keepj 'a,'z-1Align
keepj 'a,'z-1s@\([*/%|&\~^!=]\)\( \+\)=@\2\1=@ge
keepj 'a,'z-1s@[^+\-]\zs\([+\-]\)\( \+\)=@\2\1=@ge
keepj 'a,'z-1s/\( \+\);/;\1/ge
if &ft == "c" || &ft == "cpp"
" call Decho("exception for ".&ft)
'a,'z-1v/^\s*\/[*/]/s/\/[*/]/@&@/e
'a,'z-1v/^\s*\/[*/]/s/\*\//@&/e
keepj 'a,'z-1v/^\s*\/[*/]/s/\/[*/]/@&@/e
keepj 'a,'z-1v/^\s*\/[*/]/s/\*\//@&/e
if exists("g:mapleader")
exe "norm 'zk"
exe "keepj norm 'zk"
call AlignMaps#StdAlign(1)
else
exe "norm 'zk"
exe "keepj norm 'zk"
call AlignMaps#StdAlign(1)
endif
'y,'zs/^\(\s*\) @/\1/e
keepj 'y,'zs/^\(\s*\) @/\1/e
endif
'a,'z-1s/\%x0f/=/ge
'y,'zs/ @//eg
keepj 'a,'z-1s/\%x0f/=/ge
keepj 'y,'zs/ @//eg
" call Dret("AlignMaps#Equals")
endfun
@ -194,10 +205,11 @@ fun! AlignMaps#Afnc()
" call Dfunc("AlignMaps#Afnc()")
" keep display quiet
let chkeep = &ch
let gdkeep = &gd
let vekeep = &ve
set ch=2 nogd ve=
let chkeep = &l:ch
let gdkeep = &l:gd
let wwkeep = &l:ww
let vekeep = &l:ve
setlocal ch=2 nogd ve= ww=b,s,<,>,[,]
" will use marks y,z ; save current values
let mykeep = SaveMark("'y")
@ -206,7 +218,7 @@ fun! AlignMaps#Afnc()
" Find beginning of function -- be careful to skip over comments
let cmmntid = synIDtrans(hlID("Comment"))
let stringid = synIDtrans(hlID("String"))
exe "norm! ]]"
exe "keepj norm! ]]"
while search(")","bW") != 0
" call Decho("line=".line(".")." col=".col("."))
let parenid= synIDtrans(synID(line("."),col("."),1))
@ -214,23 +226,23 @@ fun! AlignMaps#Afnc()
break
endif
endwhile
norm! %my
s/(\s*\(\S\)/(\r \1/e
exe "norm! `y%"
s/)\s*\(\/[*/]\)/)\r\1/e
exe "norm! `y%mz"
'y,'zs/\s\+$//e
'y,'zs/^\s\+//e
'y+1,'zs/^/ /
keepj norm! %my
keepj s/(\s*\(\S\)/(\r \1/e
exe "keepj norm! `y%"
keepj s/)\s*\(\/[*/]\)/)\r\1/e
exe "keepj norm! `y%mz"
keepj 'y,'zs/\s\+$//e
keepj 'y,'zs/^\s\+//e
keepj 'y+1,'zs/^/ /
" insert newline after every comma only one parenthesis deep
sil! exe "norm! `y\<right>h"
exe "sil! keepj norm! `y\<right>h"
let parens = 1
let cmmnt = 0
let cmmntline= -1
while parens >= 1
" call Decho("parens=".parens." @a=".@a)
exe 'norm! ma "ay`a '
exe 'keepj norm! ma "ay`a '
" call Decho("parens=".parens." cmmnt=".cmmnt." cmmntline=".cmmntline." line(.)=".line(".")." @a<".@a."> line<".getline(".").">")
if @a == "("
let parens= parens + 1
elseif @a == ")"
@ -261,41 +273,42 @@ fun! AlignMaps#Afnc()
endif
elseif @a == "," && parens == 1 && cmmnt == 0
exe "norm! i\<CR>\<Esc>"
exe "keepj norm! i\<CR>\<Esc>"
endif
endwhile
norm! `y%mz%
sil! 'y,'zg/^\s*$/d
sil! keepj norm! `y%mz%
sil! keepj 'y,'zg/^\s*$/d
" perform substitutes to mark fields for Align
sil! 'y+1,'zv/^\//s/^\s\+\(\S\)/ \1/e
sil! 'y+1,'zv/^\//s/\(\S\)\s\+/\1 /eg
sil! 'y+1,'zv/^\//s/\* \+/*/ge
sil! 'y+1,'zv/^\//s/\w\zs\s*\*/ */ge
sil! keepj 'y+1,'zv/^\//s/^\s\+\(\S\)/ \1/e
sil! keepj 'y+1,'zv/^\//s/\(\S\)\s\+/\1 /eg
sil! keepj 'y+1,'zv/^\//s/\* \+/*/ge
sil! keepj 'y+1,'zv/^\//s/\w\zs\s*\*/ */ge
" func
" ws <- declaration -> <-ptr -> <-var-> <-[array][] -> <-glop-> <-end->
sil! 'y+1,'zv/^\//s/^\s*\(\(\K\k*\s*\)\+\)\s\+\([(*]*\)\s*\(\K\k*\)\s*\(\(\[.\{-}]\)*\)\s*\(.\{-}\)\=\s*\([,)]\)\s*$/ \1@#\3@\4\5@\7\8/e
sil! 'y+1,'z+1g/^\s*\/[*/]/norm! kJ
sil! 'y+1,'z+1s%/[*/]%@&@%ge
sil! 'y+1,'z+1s%*/%@&%ge
sil! keepj 'y+1,'zv/^\//s/^\s*\(\(\K\k*\s*\)\+\)\s\+\([(*]*\)\s*\(\K\k*\)\s*\(\(\[.\{-}]\)*\)\s*\(.\{-}\)\=\s*\([,)]\)\s*$/ \1@#\3@\4\5@\7\8/e
sil! keepj 'y+1,'z+1g/^\s*\/[*/]/norm! kJ
sil! keepj 'y+1,'z+1s%/[*/]%@&@%ge
sil! keepj 'y+1,'z+1s%*/%@&%ge
AlignCtrl mIp0P0=l @
sil! 'y+1,'zAlign
sil! 'y,'zs%@\(/[*/]\)@%\t\1 %e
sil! 'y,'zs%@\*/% */%e
sil! 'y,'zs/@\([,)]\)/\1/
sil! 'y,'zs/@/ /
sil! keepj 'y+1,'zAlign
sil! keepj 'y,'zs%@\(/[*/]\)@%\t\1 %e
sil! keepj 'y,'zs%@\*/% */%e
sil! keepj 'y,'zs/@\([,)]\)/\1/
sil! keepj 'y,'zs/@/ /
AlignCtrl mIlrp0P0= # @
sil! 'y+1,'zAlign
sil! 'y+1,'zs/#/ /
sil! 'y+1,'zs/@//
sil! 'y+1,'zs/\(\s\+\)\([,)]\)/\2\1/e
sil! keepj 'y+1,'zAlign
sil! keepj 'y+1,'zs/#/ /
sil! keepj 'y+1,'zs/@//
sil! keepj 'y+1,'zs/\(\s\+\)\([,)]\)/\2\1/e
" Restore
call RestoreMark(mykeep)
call RestoreMark(mzkeep)
let &ch= chkeep
let &gd= gdkeep
let &ve= vekeep
let &l:ch= chkeep
let &l:gd= gdkeep
let &l:ww= wwkeep
let &l:ve= vekeep
" call Dret("AlignMaps#Afnc")
endfun
@ -310,12 +323,42 @@ fun! AlignMaps#FixMultiDec()
let curline = getline(".")
" call Decho("curline<".curline.">")
" " Attempt to ignore function calls (ie. double x=pow(2.,3.),...
" let leader= substitute(curline,'^\s*\([a-zA-Z_ \t][a-zA-Z0-9<>_ \t]*\)\s\+.*$','\1','')
" let i = strlen(leader)
" let paren = 0
" let fmd = strpart(curline,i)
" let ifmd = i
" call Decho("fmd<".fmd."> ifmd=".ifmd)
" while i < strlen(curline)
" if strpart(curline,i,1) == '('
" let paren= paren+1
" elseif strpart(curline,i,1) == ')' && paren > 0
" let paren= paren-1
" elseif strpart(curline,i,1) == '='
" let eq= 1
" elseif strpart(curline,i,1) == ';'
" let paren = 0
" let eq = 0
" let fmd = fmd.strpart(fmd,ifmd,i-ifmd).";\<cr>"
" let ifmd = i + 2
" let i = i + 1
" let leader= substitute(curline,'^\s*\([a-zA-Z_ \t][a-zA-Z0-9<>_ \t]*\)\s\+.*$','\1','')
" elseif strpart(curline,i,1) == ','
" if paren == 0
" let fmd = fmd.strpart(fmd,ifmd,i-ifmd).";\<cr>"
" let ifmd = i + 2
" let i = i + 1
" endif
" endif
" let i= i + 1
" endwhile
" Get the type. I'm assuming one type per line (ie. int x; double y; on one line will not be handled properly)
let @x=substitute(curline,'^\(\s*[a-zA-Z_ \t][a-zA-Z0-9_ \t]*\)\s\+[(*]*\h.*$','\1','')
let @x=substitute(curline,'^\(\s*[a-zA-Z_ \t][a-zA-Z0-9<>_ \t]*\)\s\+[(*]*\h.*$','\1','')
" call Decho("@x<".@x.">")
" transform line
exe 's/,/;\r'.@x.' /ge'
exe 'keepj s/,/;\r'.@x.' /ge'
"restore register x
let @x= xkeep
@ -323,6 +366,26 @@ fun! AlignMaps#FixMultiDec()
" call Dret("AlignMaps#FixMultiDec : my=".line("'y")." mz=".line("'z"))
endfun
" ---------------------------------------------------------------------
" AlignMaps#AlignMapsClean: this function removes the AlignMaps plugin {{{2
fun! AlignMaps#AlignMapsClean()
" call Dfunc("AlignMaps#AlignMapsClean()")
for home in split(&rtp,',') + ['']
" call Decho("considering home<".home.">")
if isdirectory(home)
if filereadable(home."/autoload/AlignMaps.vim")
" call Decho("deleting ".home."/autoload/AlignMaps.vim")
call delete(home."/autoload/AlignMaps.vim")
endif
if filereadable(home."/plugin/AlignMapsPlugin.vim")
" call Decho("deleting ".home."/plugin/AlignMapsPlugin.vim")
call delete(home."/plugin/AlignMapsPlugin.vim")
endif
endif
endfor
" call Dret("AlignMaps#AlignMapsClean")
endfun
" ---------------------------------------------------------------------
" Restore: {{{1
let &cpo= s:keepcpo

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,11 @@
# FILE: autoload/conque_term/conque.py {{{
# FILE: autoload/conque_term/conque.py
# AUTHOR: Nico Raffo <nicoraffo@gmail.com>
# WEBSITE: http://conque.googlecode.com
# MODIFIED: 2010-11-15
# VERSION: 2.0, for Vim 7.0
# MODIFIED: 2011-08-12
# VERSION: 2.2, for Vim 7.0
# LICENSE:
# Conque - Vim terminal/console emulator
# Copyright (C) 2009-2010 Nico Raffo
# Copyright (C) 2009-__YEAR__ Nico Raffo
#
# MIT License
#
@ -25,29 +25,33 @@
# 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. }}}
# THE SOFTWARE.
"""
Vim terminal emulator.
The Conque does two things. First, it handles communication between Vim and
the terminal/console subprocess. For example, Vim uses the Conque.write()
method to send input, and Conque.read() to update the terminal buffer.
This class is the main interface between Vim and the terminal application. It
handles both updating the Vim buffer with new output and accepting new keyboard
input from the Vim user.
Second, the Conque class handles Unix terminal escape sequence parsing.
Although this class was originally designed for a Unix terminal environment, it
has been extended by the ConqueSole class for Windows.
Usage:
term = Conque()
term.open('/bin/bash', {'TERM': 'vt100'})
term.write("ls -lha\r")
term.read()
term.close()
"""
import vim
import re
import math
import time # DEBUG
class Conque:
# CLASS PROPERTIES {{{
# screen object
screen = None
@ -86,6 +90,12 @@ class Conque:
# color history
color_history = {}
# color highlight cache
highlight_groups = {}
# prune terminal colors
color_pruning = True
# don't wrap table output
unwrap_tables = True
@ -101,15 +111,23 @@ class Conque:
# used for auto_read actions
read_count = 0
# }}}
# input buffer, array of ordinals
input_buffer = []
# constructor
def __init__(self): # {{{
def open(self):
""" Start program and initialize this instance.
Arguments:
command -- Command string to execute, e.g. '/bin/bash --login'
options -- Dictionary of environment vars to set and other options.
"""
# get arguments
command = vim.eval('command')
options = vim.eval('options')
# create terminal screen instance
self.screen = ConqueScreen()
# }}}
# start program and initialize this instance
def open(self, command, options): # {{{
# int vars
self.columns = vim.current.window.width
@ -118,8 +136,12 @@ class Conque:
self.working_lines = vim.current.window.height
self.bottom = vim.current.window.height
# offset first line to make room for startup messages
if int(options['offset']) > 0:
self.l = int(options['offset'])
# init color
self.enable_colors = options['color']
self.enable_colors = options['color'] and not CONQUE_FAST_MODE
# init tabstops
self.init_tabstops()
@ -130,11 +152,15 @@ class Conque:
# send window size signal, in case LINES/COLUMNS is ignored
self.update_window_size(True)
# }}}
# write to pty
def write(self, input, set_cursor=True, read=True): # {{{
def write(self, input, set_cursor=True, read=True):
""" Write a unicode string to the subprocess.
set_cursor -- Position the cursor in the current buffer when finished
read -- Check program for new output when finished
"""
# check if window size has changed
if read:
self.update_window_size()
@ -146,11 +172,40 @@ class Conque:
if read:
self.read(1, set_cursor)
# }}}
# convert latin-1 input into utf-8
# XXX - this is a hack, to be removed soon
def write_latin1(self, input, set_cursor=True, read=True): # {{{
def write_ord(self, input, set_cursor=True, read=True):
""" Write a single character to the subprocess, using an unicode ordinal. """
if CONQUE_PYTHON_VERSION == 2:
self.write(unichr(input), set_cursor, read)
else:
self.write(chr(input), set_cursor, read)
def write_expr(self, expr, set_cursor=True, read=True):
""" Write the value of a Vim expression to the subprocess. """
if CONQUE_PYTHON_VERSION == 2:
try:
val = vim.eval(expr)
self.write(unicode(val, CONQUE_VIM_ENCODING, 'ignore'), set_cursor, read)
except:
pass
else:
try:
# XXX - Depending on Vim to deal with encoding, sadly
self.write(vim.eval(expr), set_cursor, read)
except:
pass
def write_latin1(self, input, set_cursor=True, read=True):
""" Write latin-1 string to conque. Very ugly, shood be removed. """
# XXX - this whole method is a hack, to be removed soon
if CONQUE_PYTHON_VERSION == 2:
try:
@ -161,19 +216,34 @@ class Conque:
else:
self.write(input, set_cursor, read)
# }}}
# read from pty, and update buffer
def read(self, timeout=1, set_cursor=True, return_output=False, update_buffer=True): # {{{
def write_buffered_ord(self, chr):
""" Add character ordinal to input buffer. In case we're not allowed to modify buffer a time of input. """
self.input_buffer.append(chr)
def read(self, timeout=1, set_cursor=True, return_output=False, update_buffer=True):
""" Read new output from the subprocess and update the Vim buffer.
Arguments:
timeout -- Milliseconds to wait before reading input
set_cursor -- Set the cursor position in the current buffer when finished
return_output -- Return new subprocess STDOUT + STDERR as a string
update_buffer -- Update the current Vim buffer with the new output
This method goes through the following rough steps:
1. Get new output from subprocess
2. Split output string into control codes, escape sequences, or plain text
3. Loop over and process each chunk, updating the Vim buffer as we go
"""
output = ''
# this may not actually work
try:
# read from subprocess
# read from subprocess and strip null characters
output = self.proc.read(timeout)
# and strip null chars
output = output.replace(chr(0), '')
if output == '':
return
@ -184,19 +254,19 @@ class Conque:
# strip null characters. I'm still not sure why they appear
output = output.replace(chr(0), '')
# split input into individual escape sequences, control codes, and text output
chunks = CONQUE_SEQ_REGEX.split(output)
# don't go through all the csi regex if length is one (no matches)
# if there were no escape sequences, skip processing and treat entire string as plain text
if len(chunks) == 1:
self.plain_text(chunks[0])
# loop through and process escape sequences
else:
for s in chunks:
if s == '':
@ -205,8 +275,7 @@ class Conque:
# Check for control character match {{{
# Check for control character match
if CONQUE_SEQ_REGEX_CTL.match(s[0]):
nr = ord(s[0])
@ -215,9 +284,8 @@ class Conque:
else:
pass
# }}}
# check for escape sequence match {{{
# check for escape sequence match
elif CONQUE_SEQ_REGEX_CSI.match(s):
if s[-1] in CONQUE_ESCAPE:
@ -227,15 +295,13 @@ class Conque:
else:
pass
# }}}
# check for title match {{{
# check for title match
elif CONQUE_SEQ_REGEX_TITLE.match(s):
self.change_title(s[2], s[4:-1])
# }}}
# check for hash match {{{
# check for hash match
elif CONQUE_SEQ_REGEX_HASH.match(s):
if s[-1] in CONQUE_ESCAPE_HASH:
@ -243,9 +309,8 @@ class Conque:
else:
pass
# }}}
# check for charset match {{{
# check for charset match
elif CONQUE_SEQ_REGEX_CHAR.match(s):
if s[-1] in CONQUE_ESCAPE_CHARSET:
@ -253,9 +318,8 @@ class Conque:
else:
pass
# }}}
# check for other escape match {{{
# check for other escape match
elif CONQUE_SEQ_REGEX_ESC.match(s):
if s[-1] in CONQUE_ESCAPE_PLAIN:
@ -263,23 +327,21 @@ class Conque:
else:
pass
# }}}
# else process plain text {{{
# else process plain text
else:
self.plain_text(s)
# }}}
# check window size
# set cusor position
if set_cursor:
self.screen.set_cursor(self.l, self.c)
# we need to set the cursor position
self.cursor_set = False
vim.command('redraw')
# redraw screen for immediate feedback
#if not CONQUE_FAST_MODE:
# vim.command('redraw')
except:
@ -290,19 +352,42 @@ class Conque:
if CONQUE_PYTHON_VERSION == 3:
return output
else:
return output.encode(vim.eval('&encoding'), 'replace')
# }}}
return output.encode(CONQUE_VIM_ENCODING, 'replace')
# for polling
def auto_read(self): # {{{
def auto_read(self):
""" Poll program for more output.
Since Vim doesn't have a reliable event system that can be triggered when new
output is available, we have to continually poll the subprocess instead. This
method is called many times a second when the terminal buffer is active, so it
needs to be very fast and efficient.
The feedkeys portion is required to reset Vim's timer system. The timer is used
to execute this command, typically set to go off after 50 ms of inactivity.
"""
# process buffered input if any
if len(self.input_buffer):
for chr in self.input_buffer:
self.write_ord(chr, set_cursor=False, read=False)
self.input_buffer = []
self.read(1)
# check subprocess status, but not every time since it's CPU expensive
if self.read_count == 10:
if self.read_count % 32 == 0:
if not self.proc.is_alive():
vim.command('call conque_term#get_instance().close()')
return
else:
if self.read_count > 512:
self.read_count = 0
# trim color history occasionally if desired
if self.enable_colors and self.color_pruning:
self.prune_colors()
# ++
self.read_count += 1
# read output
@ -327,17 +412,22 @@ class Conque:
pass
self.cursor_set = True
# }}}
###############################################################################################
# Plain text # {{{
def plain_text(self, input):
""" Write text output to Vim buffer.
# translate input into correct character set
This method writes a string of characters without any control characters or escape sequences
to the Vim buffer. In simple terms, it writes the input string to the buffer starting at the
current cursor position, wrapping the text to a new line if needed. It also triggers the
terminal coloring methods if needed.
"""
# translate input into graphics character set if needed
if self.character_set == 'graphics':
old_input = input
input = ''
input = u('')
for i in range(0, len(old_input)):
chrd = ord(old_input[i])
@ -347,19 +437,23 @@ class Conque:
input = input + old_input[i]
else:
input = input + unichr(CONQUE_GRAPHICS_SET[chrd])
input = input + uchr(CONQUE_GRAPHICS_SET[chrd])
except:
pass
# get current line from Vim buffer
current_line = self.screen[self.l]
if len(current_line) < self.working_columns:
# pad current line with spaces, if it's shorter than cursor position
if len(current_line) < self.c:
current_line = current_line + ' ' * (self.c - len(current_line))
# if line is wider than screen
if self.c + len(input) - 1 > self.working_columns:
# Table formatting hack
if self.unwrap_tables and CONQUE_TABLE_OUTPUT.match(input):
self.screen[self.l] = current_line[:self.c - 1] + input + current_line[self.c + len(input) - 1:]
@ -367,7 +461,9 @@ class Conque:
self.c += len(input)
return
diff = self.c + len(input) - self.working_columns - 1
# if autowrap is enabled
if self.autowrap:
self.screen[self.l] = current_line[:self.c - 1] + input[:-1 * diff]
@ -388,7 +484,21 @@ class Conque:
self.apply_color(self.c, self.c + len(input))
self.c += len(input)
def apply_color(self, start, end, line=0):
""" Apply terminal colors to buffer for a range of characters in a single line.
When a text attribute escape sequence is encountered during input processing, the
attributes are recorded in the dictionary self.color_changes. After those attributes
have been applied, the changes are recorded in a second dictionary self.color_history.
This method inspects both dictionaries to calculate any syntax highlighting
that needs to be executed to render the text attributes in the Vim buffer.
"""
# stop here if coloration is disabled
@ -397,16 +507,16 @@ class Conque:
# allow custom line nr to be passed
if line:
real_line = line
buffer_line = line
else:
real_line = self.screen.get_real_line(self.l)
buffer_line = self.get_buffer_line(self.l)
# check for previous overlapping coloration
to_del = []
if real_line in self.color_history:
for i in range(len(self.color_history[real_line])):
syn = self.color_history[real_line][i]
if buffer_line in self.color_history:
for i in range(len(self.color_history[buffer_line])):
syn = self.color_history[buffer_line][i]
if syn['start'] >= start and syn['start'] < end:
@ -415,7 +525,7 @@ class Conque:
# outside
if syn['end'] > end:
self.exec_highlight(real_line, end, syn['end'], syn['highlight'])
self.exec_highlight(buffer_line, end, syn['end'], syn['highlight'])
elif syn['end'] > start and syn['end'] <= end:
vim.command('syn clear ' + syn['name'])
@ -423,47 +533,83 @@ class Conque:
# outside
if syn['start'] < start:
self.exec_highlight(real_line, syn['start'], start, syn['highlight'])
self.exec_highlight(buffer_line, syn['start'], start, syn['highlight'])
# remove overlapped colors
if len(to_del) > 0:
to_del.reverse()
for di in to_del:
del self.color_history[real_line][di]
del self.color_history[buffer_line][di]
# if there are no new colors
if len(self.color_changes) == 0:
return
# build the color attribute string
highlight = ''
for attr in self.color_changes.keys():
highlight = highlight + ' ' + attr + '=' + self.color_changes[attr]
# execute the highlight
self.exec_highlight(real_line, start, end, highlight)
self.exec_highlight(buffer_line, start, end, highlight)
def exec_highlight(self, buffer_line, start, end, highlight):
""" Execute the Vim commands for a single syntax highlight """
syntax_name = 'ConqueHighLightAt_%d_%d_%d_%d' % (self.proc.pid, self.l, start, len(self.color_history) + 1)
syntax_options = 'contains=ALLBUT,ConqueString,MySQLString,MySQLKeyword oneline'
syntax_region = 'syntax match %s /\%%%dl\%%>%dc.\{%d}\%%<%dc/ %s' % (syntax_name, buffer_line, start - 1, end - start, end + 1, syntax_options)
# check for cached highlight group
hgroup = 'ConqueHL_%d' % (abs(hash(highlight)))
if hgroup not in self.highlight_groups:
syntax_group = 'highlight %s %s' % (hgroup, highlight)
self.highlight_groups[hgroup] = hgroup
vim.command(syntax_group)
# link this syntax match to existing highlight group
syntax_highlight = 'highlight link %s %s' % (syntax_name, self.highlight_groups[hgroup])
def exec_highlight(self, real_line, start, end, highlight):
unique_key = str(self.proc.pid)
syntax_name = 'EscapeSequenceAt_' + unique_key + '_' + str(self.l) + '_' + str(start) + '_' + str(len(self.color_history) + 1)
syntax_options = ' contains=ALLBUT,ConqueString,MySQLString,MySQLKeyword oneline'
syntax_region = 'syntax match ' + syntax_name + ' /\%' + str(real_line) + 'l\%>' + str(start - 1) + 'c.*\%<' + str(end + 1) + 'c/' + syntax_options
syntax_highlight = 'highlight ' + syntax_name + highlight
vim.command(syntax_region)
vim.command(syntax_highlight)
# add syntax name to history
if not real_line in self.color_history:
self.color_history[real_line] = []
if not buffer_line in self.color_history:
self.color_history[buffer_line] = []
self.color_history[buffer_line].append({'name': syntax_name, 'start': start, 'end': end, 'highlight': highlight})
def prune_colors(self):
""" Remove old syntax highlighting from the Vim buffer
The kind of syntax highlighting required for terminal colors can make
Conque run slowly. The prune_colors() method will remove old highlight definitions
to keep the maximum number of highlight rules within a reasonable range.
"""
buffer_line = self.get_buffer_line(self.l)
ks = list(self.color_history.keys())
for line in ks:
if line < buffer_line - CONQUE_MAX_SYNTAX_LINES:
for syn in self.color_history[line]:
vim.command('syn clear ' + syn['name'])
del self.color_history[line]
self.color_history[real_line].append({'name': syntax_name, 'start': start, 'end': end, 'highlight': highlight})
# }}}
###############################################################################################
# Control functions {{{
# Control functions
def ctl_nl(self):
""" Process the newline control character. """
# if we're in a scrolling region, scroll instead of moving cursor down
if self.lines != self.working_lines and self.l == self.bottom:
del self.screen[self.top]
@ -476,24 +622,29 @@ class Conque:
self.color_changes = {}
def ctl_cr(self):
""" Process the carriage return control character. """
self.c = 1
self.color_changes = {}
def ctl_bs(self):
""" Process the backspace control character. """
if self.c > 1:
self.c += -1
def ctl_soh(self):
""" Process the start of heading control character. """
pass
def ctl_stx(self):
pass
def ctl_bel(self):
""" Process the bell control character. """
vim.command('call conque_term#bell()')
def ctl_tab(self):
""" Process the tab control character. """
# default tabstop location
ts = self.working_columns
@ -508,17 +659,20 @@ class Conque:
self.c = ts
def ctl_so(self):
""" Process the shift out control character. """
self.character_set = 'graphics'
def ctl_si(self):
""" Process the shift in control character. """
self.character_set = 'ascii'
# }}}
###############################################################################################
# CSI functions {{{
# CSI functions
def csi_font(self, csi): # {{{
def csi_font(self, csi):
""" Process the text attribute escape sequence. """
if not self.enable_colors:
return
@ -557,9 +711,10 @@ class Conque:
self.color_changes[attr] += ',' + CONQUE_FONT[val]['attributes'][attr]
else:
self.color_changes[attr] = CONQUE_FONT[val]['attributes'][attr]
# }}}
def csi_clear_line(self, csi): # {{{
def csi_clear_line(self, csi):
""" Process the line clear escape sequence. """
# this escape defaults to 0
@ -583,16 +738,17 @@ class Conque:
# clear colors
if csi['val'] == 2 or (csi['val'] == 0 and self.c == 1):
real_line = self.screen.get_real_line(self.l)
if real_line in self.color_history:
for syn in self.color_history[real_line]:
buffer_line = self.get_buffer_line(self.l)
if buffer_line in self.color_history:
for syn in self.color_history[buffer_line]:
vim.command('syn clear ' + syn['name'])
# }}}
def csi_cursor_right(self, csi): # {{{
def csi_cursor_right(self, csi):
""" Process the move cursor right escape sequence. """
# we use 1 even if escape explicitly specifies 0
if csi['val'] == 0:
csi['val'] = 1
@ -606,9 +762,10 @@ class Conque:
return
self.c = self.bound(self.c + csi['val'], 1, self.working_columns)
# }}}
def csi_cursor_left(self, csi): # {{{
def csi_cursor_left(self, csi):
""" Process the move cursor left escape sequence. """
# we use 1 even if escape explicitly specifies 0
if csi['val'] == 0:
csi['val'] = 1
@ -619,25 +776,29 @@ class Conque:
return
self.c = self.bound(self.c - csi['val'], 1, self.working_columns)
# }}}
def csi_cursor_to_column(self, csi): # {{{
def csi_cursor_to_column(self, csi):
""" Process the move cursor to column escape sequence. """
self.c = self.bound(csi['val'], 1, self.working_columns)
# }}}
def csi_cursor_up(self, csi): # {{{
def csi_cursor_up(self, csi):
""" Process the move cursor up escape sequence. """
self.l = self.bound(self.l - csi['val'], self.top, self.bottom)
self.color_changes = {}
# }}}
def csi_cursor_down(self, csi): # {{{
def csi_cursor_down(self, csi):
""" Process the move cursor down escape sequence. """
self.l = self.bound(self.l + csi['val'], self.top, self.bottom)
self.color_changes = {}
# }}}
def csi_clear_screen(self, csi): # {{{
def csi_clear_screen(self, csi):
""" Process the clear screen escape sequence. """
# default to 0
if len(csi['vals']) == 0:
csi['val'] = 0
@ -666,24 +827,24 @@ class Conque:
# clear coloration
if csi['val'] == 2 or csi['val'] == 0:
real_line = self.screen.get_real_line(self.l)
buffer_line = self.get_buffer_line(self.l)
for line in self.color_history.keys():
if line >= real_line:
if line >= buffer_line:
for syn in self.color_history[line]:
vim.command('syn clear ' + syn['name'])
self.color_changes = {}
# }}}
def csi_delete_chars(self, csi): # {{{
def csi_delete_chars(self, csi):
self.screen[self.l] = self.screen[self.l][:self.c] + self.screen[self.l][self.c + csi['val']:]
# }}}
def csi_add_spaces(self, csi): # {{{
def csi_add_spaces(self, csi):
self.screen[self.l] = self.screen[self.l][: self.c - 1] + ' ' * csi['val'] + self.screen[self.l][self.c:]
# }}}
def csi_cursor(self, csi): # {{{
def csi_cursor(self, csi):
if len(csi['vals']) == 2:
new_line = csi['vals'][0]
new_col = csi['vals'][1]
@ -700,9 +861,9 @@ class Conque:
if self.c > len(self.screen[self.l]):
self.screen[self.l] = self.screen[self.l] + ' ' * (self.c - len(self.screen[self.l]))
# }}}
def csi_set_coords(self, csi): # {{{
def csi_set_coords(self, csi):
if len(csi['vals']) == 2:
new_start = csi['vals'][0]
new_end = csi['vals'][1]
@ -721,9 +882,9 @@ class Conque:
self.l = self.bottom
self.color_changes = {}
# }}}
def csi_tab_clear(self, csi): # {{{
def csi_tab_clear(self, csi):
# this escape defaults to 0
if len(csi['vals']) == 0:
csi['val'] = 0
@ -735,9 +896,9 @@ class Conque:
elif csi['val'] == 3:
for i in range(0, self.columns + 1):
self.tabstops[i] = False
# }}}
def csi_set(self, csi): # {{{
def csi_set(self, csi):
# 132 cols
if csi['val'] == 3:
self.csi_clear_screen(self.parse_csi('2J'))
@ -753,9 +914,9 @@ class Conque:
self.color_changes = {}
# }}}
def csi_reset(self, csi): # {{{
def csi_reset(self, csi):
# 80 cols
if csi['val'] == 3:
self.csi_clear_screen(self.parse_csi('2J'))
@ -771,31 +932,31 @@ class Conque:
self.color_changes = {}
# }}}
# }}}
###############################################################################################
# ESC functions {{{
# ESC functions
def esc_scroll_up(self): # {{{
def esc_scroll_up(self):
self.ctl_nl()
self.color_changes = {}
# }}}
def esc_next_line(self): # {{{
def esc_next_line(self):
self.ctl_nl()
self.c = 1
# }}}
def esc_set_tab(self): # {{{
def esc_set_tab(self):
if self.c <= len(self.tabstops):
self.tabstops[self.c - 1] = True
# }}}
def esc_scroll_down(self): # {{{
def esc_scroll_down(self):
if self.l == self.top:
del self.screen[self.bottom]
self.screen.insert(self.top, '')
@ -803,24 +964,23 @@ class Conque:
self.l += -1
self.color_changes = {}
# }}}
# }}}
###############################################################################################
# HASH functions {{{
# HASH functions
def hash_screen_alignment_test(self): # {{{
def hash_screen_alignment_test(self):
self.csi_clear_screen(self.parse_csi('2J'))
self.working_lines = self.lines
for l in range(1, self.lines + 1):
self.screen[l] = 'E' * self.working_columns
# }}}
# }}}
###############################################################################################
# CHARSET functions {{{
# CHARSET functions
def charset_us(self):
self.character_set = 'ascii'
@ -831,15 +991,22 @@ class Conque:
def charset_graphics(self):
self.character_set = 'graphics'
# }}}
###############################################################################################
# Random stuff {{{
# Random stuff
def set_cursor(self, line, col):
""" Set cursor position in the Vim buffer.
Note: the line and column numbers are relative to the top left corner of the
visible screen. Not the line number in the Vim buffer.
"""
self.screen.set_cursor(line, col)
def change_title(self, key, val):
""" Change the Vim window title. """
if key == '0' or key == '2':
@ -850,17 +1017,14 @@ class Conque:
except:
pass
def paste(self):
input = vim.eval('@@')
input = input.replace("\n", "\r")
self.read(50)
def paste_selection(self):
input = vim.eval('@@')
input = input.replace("\n", "\r")
self.write(input)
def update_window_size(self, force=False):
""" Check and save the current buffer dimensions.
If the buffer size has changed, the update_window_size() method both updates
the Conque buffer size attributes as well as sending the new dimensions to the
subprocess pty.
"""
# resize if needed
if force or vim.current.window.width != self.columns or vim.current.window.height != self.lines:
@ -883,6 +1047,7 @@ class Conque:
self.proc.window_resize(self.lines, self.columns)
def insert_enter(self):
""" Run commands when user enters insert mode. """
# check window size
self.update_window_size()
@ -891,6 +1056,7 @@ class Conque:
self.cursor_set = False
def init_tabstops(self):
""" Intitialize terminal tabstop positions. """
for i in range(0, self.columns + 1):
if i % 8 == 0:
self.tabstops.append(True)
@ -898,23 +1064,30 @@ class Conque:
self.tabstops.append(False)
def idle(self):
""" Called when this terminal becomes idle. """
pass
def resume(self):
""" Called when this terminal is no longer idle. """
pass
pass
def close(self):
""" End the process running in the terminal. """
self.proc.close()
def abort(self):
""" Forcefully end the process running in the terminal. """
self.proc.signal(1)
# }}}
###############################################################################################
# Utility {{{
# Utility
def parse_csi(self, s):
""" Parse an escape sequence into it's meaningful values. """
def parse_csi(self, s): # {{{
attr = {'key': s[-1], 'flag': '', 'val': 1, 'vals': []}
if len(s) == 1:
@ -939,9 +1112,10 @@ class Conque:
attr['val'] = int(attr['vals'][0])
return attr
# }}}
def bound(self, val, min, max): # {{{
def bound(self, val, min, max):
""" TODO: This probably exists as a builtin function. """
if val > max:
return max
@ -949,9 +1123,10 @@ class Conque:
return min
return val
# }}}
def xterm_to_rgb(self, color_code): # {{{
def xterm_to_rgb(self, color_code):
""" Translate a terminal color number into a RGB string. """
if color_code < 16:
ascii_colors = ['000000', 'CD0000', '00CD00', 'CDCD00', '0000EE', 'CD00CD', '00CDCD', 'E5E5E5',
'7F7F7F', 'FF0000', '00FF00', 'FFFF00', '5C5CFF', 'FF00FF', '00FFFF', 'FFFFFF']
@ -968,8 +1143,12 @@ class Conque:
else:
grey_tone = "%02x" % math.floor((255 / 24) * (color_code - 232))
return grey_tone + grey_tone + grey_tone
# }}}
# }}}
# vim:foldmethod=marker
def get_buffer_line(self, line):
""" Get the buffer line number corresponding to the supplied screen line number. """
return self.screen.get_buffer_line(line)

View File

@ -1,11 +1,11 @@
# FILE: autoload/conque_term/conque_globals.py {{{
# FILE: autoload/conque_term/conque_globals.py
# AUTHOR: Nico Raffo <nicoraffo@gmail.com>
# WEBSITE: http://conque.googlecode.com
# MODIFIED: 2010-11-15
# VERSION: 2.0, for Vim 7.0
# MODIFIED: 2011-08-12
# VERSION: 2.2, for Vim 7.0
# LICENSE:
# Conque - Vim terminal/console emulator
# Copyright (C) 2009-2010 Nico Raffo
# Copyright (C) 2009-__YEAR__ Nico Raffo
#
# MIT License
#
@ -25,56 +25,32 @@
# 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. }}}
# THE SOFTWARE.
"""Common global constants and functions for Conque."""
import sys
import os
import re
import os # DEBUG
# shared memory size
CONQUE_SOLE_BUFFER_LENGTH = 1000
CONQUE_SOLE_INPUT_SIZE = 1000
CONQUE_SOLE_STATS_SIZE = 1000
CONQUE_SOLE_COMMANDS_SIZE = 255
CONQUE_SOLE_RESCROLL_SIZE = 255
CONQUE_SOLE_RESIZE_SIZE = 255
# interval of screen redraw
# larger number means less frequent
CONQUE_SOLE_SCREEN_REDRAW = 100
# interval of full buffer redraw
# larger number means less frequent
CONQUE_SOLE_BUFFER_REDRAW = 500
# interval of full output bucket replacement
# larger number means less frequent, 1 = every time
CONQUE_SOLE_MEM_REDRAW = 1000
import traceback # DEBUG
# PYTHON VERSION
CONQUE_PYTHON_VERSION = sys.version_info[0]
# Encoding
def u(str_val, str_encoding='latin-1', errors='strict'):
"""foolhardy attempt to make unicode string syntax compatible with both python 2 and 3"""
try:
# Vim's character encoding
import vim
CONQUE_VIM_ENCODING = vim.eval('&encoding')
except:
CONQUE_VIM_ENCODING = 'utf-8'
def u(str_val, str_encoding='utf-8', errors='strict'):
""" Foolhardy attempt to make unicode string syntax compatible with both python 2 and 3. """
if not str_val:
str_val = ''
@ -85,7 +61,34 @@ def u(str_val, str_encoding='latin-1', errors='strict'):
else:
return unicode(str_val, str_encoding, errors)
# Escape sequence settings {{{
def uchr(str):
""" Foolhardy attempt to make unicode string syntax compatible with both python 2 and 3. """
if CONQUE_PYTHON_VERSION == 3:
return chr(str)
else:
return unichr(str)
# Unix escape sequence settings
CONQUE_CTL = {
1: 'soh', # start of heading
@ -209,7 +212,7 @@ CONQUE_GRAPHICS_SET = [
0x00F8, 0x00F9, 0x00FA, 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF
]
# Font codes {{{
# Font codes
CONQUE_FONT = {
0: {'description': 'Normal (default)', 'attributes': {'cterm': 'NONE', 'ctermfg': 'NONE', 'ctermbg': 'NONE', 'gui': 'NONE', 'guifg': 'NONE', 'guibg': 'NONE'}, 'normal': True},
1: {'description': 'Bold', 'attributes': {'cterm': 'BOLD', 'gui': 'BOLD'}, 'normal': False},
@ -257,31 +260,60 @@ CONQUE_FONT = {
106: {'description': 'Set background color to Cyan', 'attributes': {'ctermbg': '14', 'guibg': '#009999'}, 'normal': False},
107: {'description': 'Set background color to White', 'attributes': {'ctermbg': '15', 'guibg': '#ffffff'}, 'normal': False}
}
# }}}
# regular expression matching (almost) all control sequences
CONQUE_SEQ_REGEX = re.compile(u("(\x1b\[?\??#?[0-9;]*[a-zA-Z0-9@=>]|\x1b\][0-9];.*?\x07|[\x01-\x0f]|\x1b\([AB0])"), re.UNICODE)
CONQUE_SEQ_REGEX_CTL = re.compile(u("^[\x01-\x0f]$"), re.UNICODE)
CONQUE_SEQ_REGEX_CSI = re.compile(u("^\x1b\["), re.UNICODE)
CONQUE_SEQ_REGEX_TITLE = re.compile(u("^\x1b\]"), re.UNICODE)
CONQUE_SEQ_REGEX_HASH = re.compile(u("^\x1b#"), re.UNICODE)
CONQUE_SEQ_REGEX_ESC = re.compile(u("^\x1b.$"), re.UNICODE)
CONQUE_SEQ_REGEX_CHAR = re.compile(u("^\x1b\("), re.UNICODE)
CONQUE_SEQ_REGEX = re.compile("(\x1b\[?\??#?[0-9;]*[a-zA-Z0-9@=>]|\x1b\][0-9];.*?\x07|[\x01-\x0f]|\x1b\([AB0])")
CONQUE_SEQ_REGEX_CTL = re.compile("^[\x01-\x0f]$")
CONQUE_SEQ_REGEX_CSI = re.compile("^\x1b\[")
CONQUE_SEQ_REGEX_TITLE = re.compile("^\x1b\]")
CONQUE_SEQ_REGEX_HASH = re.compile("^\x1b#")
CONQUE_SEQ_REGEX_ESC = re.compile("^\x1b.$")
CONQUE_SEQ_REGEX_CHAR = re.compile("^\x1b[()]")
# match table output
CONQUE_TABLE_OUTPUT = re.compile("^\s*\|\s.*\s\|\s*$|^\s*\+[=+-]+\+\s*$")
# }}}
# Windows subprocess config {{{
CONQUE_SEQ_REGEX_VK = re.compile(u("(\x1b\[\d{1,3}VK)"), re.UNICODE)
# }}}
# basic terminal colors
CONQUE_COLOR_SEQUENCE = (
'000', '009', '090', '099', '900', '909', '990', '999',
'000', '00f', '0f0', '0ff', 'f00', 'f0f', 'ff0', 'fff'
)
# vim:foldmethod=marker
# Windows subprocess constants
# shared memory size
CONQUE_SOLE_BUFFER_LENGTH = 1000
CONQUE_SOLE_INPUT_SIZE = 1000
CONQUE_SOLE_STATS_SIZE = 1000
CONQUE_SOLE_COMMANDS_SIZE = 255
CONQUE_SOLE_RESCROLL_SIZE = 255
CONQUE_SOLE_RESIZE_SIZE = 255
# interval of screen redraw
# larger number means less frequent
CONQUE_SOLE_SCREEN_REDRAW = 50
# interval of full buffer redraw
# larger number means less frequent
CONQUE_SOLE_BUFFER_REDRAW = 500
# interval of full output bucket replacement
# larger number means less frequent, 1 = every time
CONQUE_SOLE_MEM_REDRAW = 1000
# maximum number of lines with terminal colors
# ignored if g:ConqueTerm_Color = 2
CONQUE_MAX_SYNTAX_LINES = 200
# windows input splitting on special keys
CONQUE_WIN32_REGEX_VK = re.compile("(\x1b\[[0-9;]+VK)")
# windows attribute string splitting
CONQUE_WIN32_REGEX_ATTR = re.compile("((.)\\2*)", re.DOTALL)
# special key attributes
CONQUE_VK_ATTR_CTRL_PRESSED = u('1024')

View File

@ -1,11 +1,11 @@
# FILE: autoload/conque_term/conque_screen.py {{{
# FILE: autoload/conque_term/conque_screen.py
# AUTHOR: Nico Raffo <nicoraffo@gmail.com>
# WEBSITE: http://conque.googlecode.com
# MODIFIED: 2010-11-15
# VERSION: 2.0, for Vim 7.0
# MODIFIED: 2011-08-12
# VERSION: 2.2, for Vim 7.0
# LICENSE:
# Conque - Vim terminal/console emulator
# Copyright (C) 2009-2010 Nico Raffo
# Copyright (C) 2009-__YEAR__ Nico Raffo
#
# MIT License
#
@ -25,14 +25,19 @@
# 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. }}}
# THE SOFTWARE.
"""
ConqueScreen is an extention of the vim.current.buffer object
It restricts the working indices of the buffer object to the scroll region
which pty is expecting. It also uses 1-based indexes, to match escape
sequence commands.
Unix terminal escape sequences usually reference line numbers relative to the
top of the visible screen. However the visible portion of the Vim buffer
representing the terminal probably doesn't start at the first line of the
buffer.
The ConqueScreen class allows access to the Vim buffer with screen-relative
line numbering. And handles a few other related tasks, such as setting the
correct cursor position.
E.g.:
s = ConqueScreen()
@ -40,6 +45,7 @@ sequence commands.
s[5] = 'Set 5th line in terminal to this line'
s.append('Add new line to terminal')
s[5] = 'Since previous append() command scrolled the terminal down, this is a different line than first cb[5] call'
"""
import vim
@ -47,8 +53,6 @@ import vim
class ConqueScreen(object):
# CLASS PROPERTIES {{{
# the buffer
buffer = None
@ -59,55 +63,66 @@ class ConqueScreen(object):
screen_width = 80
screen_height = 80
# }}}
# char encoding for vim buffer
screen_encoding = 'utf-8'
def __init__(self):
""" Initialize screen size and character encoding. """
def __init__(self): # {{{
self.buffer = vim.current.buffer
# initialize screen size
self.screen_top = 1
self.screen_width = vim.current.window.width
self.screen_height = vim.current.window.height
# }}}
###############################################################################################
# List overload {{{
# save screen character encoding type
self.screen_encoding = vim.eval('&fileencoding')
def __len__(self): # {{{
def __len__(self):
""" Define the len() function for ConqueScreen objects. """
return len(self.buffer)
# }}}
def __getitem__(self, key): # {{{
real_line = self.get_real_idx(key)
def __getitem__(self, key):
""" Define value access for ConqueScreen objects. """
buffer_line = self.get_real_idx(key)
# if line is past buffer end, add lines to buffer
if real_line >= len(self.buffer):
for i in range(len(self.buffer), real_line + 1):
self.append(' ' * self.screen_width)
if buffer_line >= len(self.buffer):
for i in range(len(self.buffer), buffer_line + 1):
self.append(' ')
return u(self.buffer[real_line], 'utf-8')
# }}}
return u(self.buffer[buffer_line], 'utf-8')
def __setitem__(self, key, value): # {{{
real_line = self.get_real_idx(key)
def __setitem__(self, key, value):
""" Define value assignments for ConqueScreen objects. """
buffer_line = self.get_real_idx(key)
if CONQUE_PYTHON_VERSION == 2:
val = value.encode('utf-8')
val = value.encode(self.screen_encoding)
else:
# XXX / Vim's python3 interface doesn't accept bytes object
val = str(value)
# if line is past end of screen, append
if real_line == len(self.buffer):
if buffer_line == len(self.buffer):
self.buffer.append(val)
else:
self.buffer[real_line] = val
# }}}
self.buffer[buffer_line] = val
def __delitem__(self, key): # {{{
def __delitem__(self, key):
""" Define value deletion for ConqueScreen objects. """
del self.buffer[self.screen_top + key - 2]
# }}}
def append(self, value): # {{{
def append(self, value):
""" Define value appending for ConqueScreen objects. """
if len(self.buffer) > self.screen_top + self.screen_height - 1:
self.buffer[len(self.buffer) - 1] = value
else:
@ -115,72 +130,83 @@ class ConqueScreen(object):
if len(self.buffer) > self.screen_top + self.screen_height - 1:
self.screen_top += 1
if vim.current.buffer.number == self.buffer.number:
vim.command('normal G')
# }}}
def insert(self, line, value): # {{{
if vim.current.buffer.number == self.buffer.number:
vim.command('normal! G')
def insert(self, line, value):
""" Define value insertion for ConqueScreen objects. """
l = self.screen_top + line - 2
self.buffer.append(value, l)
# }}}
# }}}
###############################################################################################
# Util {{{
def get_top(self): # {{{
def get_top(self):
""" Get the Vim line number representing the top of the visible terminal. """
return self.screen_top
# }}}
def get_real_idx(self, line): # {{{
def get_real_idx(self, line):
""" Get the zero index Vim line number corresponding to the provided screen line. """
return (self.screen_top + line - 2)
# }}}
def get_real_line(self, line): # {{{
def get_buffer_line(self, line):
""" Get the Vim line number corresponding to the provided screen line. """
return (self.screen_top + line - 1)
# }}}
def set_screen_width(self, width): # {{{
def set_screen_width(self, width):
""" Set the screen width. """
self.screen_width = width
# }}}
# }}}
###############################################################################################
def clear(self): # {{{
def clear(self):
""" Clear the screen. Does not clear the buffer, just scrolls down past all text. """
self.screen_width = width
self.buffer.append(' ')
vim.command('normal Gzt')
vim.command('normal! Gzt')
self.screen_top = len(self.buffer)
# }}}
def set_cursor(self, line, column): # {{{
def set_cursor(self, line, column):
""" Set cursor position. """
# figure out line
real_line = self.screen_top + line - 1
if real_line > len(self.buffer):
for l in range(len(self.buffer) - 1, real_line):
buffer_line = self.screen_top + line - 1
if buffer_line > len(self.buffer):
for l in range(len(self.buffer) - 1, buffer_line):
self.buffer.append('')
# figure out column
real_column = column
if len(self.buffer[real_line - 1]) < real_column:
self.buffer[real_line - 1] = self.buffer[real_line - 1] + ' ' * (real_column - len(self.buffer[real_line - 1]))
if len(self.buffer[buffer_line - 1]) < real_column:
self.buffer[buffer_line - 1] = self.buffer[buffer_line - 1] + ' ' * (real_column - len(self.buffer[buffer_line - 1]))
# python version is occasionally grumpy
try:
vim.current.window.cursor = (real_line, real_column - 1)
except:
vim.command('call cursor(' + str(real_line) + ', ' + str(real_column) + ')')
# }}}
if not CONQUE_FAST_MODE:
# set cursor at byte index of real_column'th character
vim.command('call cursor(' + str(buffer_line) + ', byteidx(getline(' + str(buffer_line) + '), ' + str(real_column) + '))')
else:
# old version
# python version is occasionally grumpy
try:
vim.current.window.cursor = (buffer_line, real_column - 1)
except:
vim.command('call cursor(' + str(buffer_line) + ', ' + str(real_column) + ')')
def reset_size(self, line):
""" Change screen size """
def reset_size(self, line): # {{{
# save cursor line number
real_line = self.screen_top + line
buffer_line = self.screen_top + line
# reset screen size
self.screen_width = vim.current.window.width
@ -191,19 +217,14 @@ class ConqueScreen(object):
# align bottom of buffer to bottom of screen
vim.command('normal ' + str(self.screen_height) + 'kG')
vim.command('normal! ' + str(self.screen_height) + 'kG')
# return new relative line number
return (real_line - self.screen_top)
# }}}
return (buffer_line - self.screen_top)
def scroll_to_bottom(self): # {{{
vim.current.window.cursor = (len(self.buffer) - 1, 1)
# }}}
def align(self): # {{{
# align bottom of buffer to bottom of screen
vim.command('normal ' + str(self.screen_height) + 'kG')
# }}}
def align(self):
""" align bottom of buffer to bottom of screen """
vim.command('normal! ' + str(self.screen_height) + 'kG')
# vim:foldmethod=marker

View File

@ -1,11 +1,11 @@
# FILE: autoload/conque_term/conque_sole.py {{{
# FILE: autoload/conque_term/conque_sole.py
# AUTHOR: Nico Raffo <nicoraffo@gmail.com>
# WEBSITE: http://conque.googlecode.com
# MODIFIED: 2010-11-15
# VERSION: 2.0, for Vim 7.0
# MODIFIED: 2011-08-12
# VERSION: 2.2, for Vim 7.0
# LICENSE:
# Conque - Vim terminal/console emulator
# Copyright (C) 2009-2010 Nico Raffo
# Copyright (C) 2009-__YEAR__ Nico Raffo
#
# MIT License
#
@ -25,7 +25,14 @@
# 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. }}}
# THE SOFTWARE.
"""
Windows Console Emulator
This is the main interface to the Windows emulator. It reads new output from the background console
and updates the Vim buffer.
"""
import vim
@ -36,19 +43,36 @@ class ConqueSole(Conque):
window_bottom = None
color_cache = {}
attribute_cache = {}
color_mode = None
color_conceals = {}
buffer = None
encoding = None
# counters for periodic rendering
buffer_redraw_ct = 0
screen_redraw_ct = 0
buffer_redraw_ct = 1
screen_redraw_ct = 1
# *********************************************************************************************
# start program and initialize this instance
# line offset, shifts output down
offset = 0
def open(self, command, options={}, python_exe='', communicator_py=''): # {{{
def open(self):
""" Start command and initialize this instance
Arguments:
command - Command string, e.g. "Powershell.exe"
options - Dictionary of config options
python_exe - Path to the python.exe executable. Usually C:\PythonXX\python.exe
communicator_py - Path to subprocess controller script in user's vimfiles directory
"""
# get arguments
command = vim.eval('command')
options = vim.eval('options')
python_exe = vim.eval('py_exe')
communicator_py = vim.eval('py_vim')
# init size
self.columns = vim.current.window.width
@ -56,22 +80,25 @@ class ConqueSole(Conque):
self.window_top = 0
self.window_bottom = vim.current.window.height - 1
# color mode
self.color_mode = vim.eval('g:ConqueTerm_ColorMode')
# line offset
self.offset = int(options['offset'])
# init color
self.enable_colors = options['color']
self.enable_colors = options['color'] and not CONQUE_FAST_MODE
# open command
self.proc = ConqueSoleWrapper()
self.proc.open(command, {'TERM': options['TERM'], 'CONQUE': '1', 'LINES': self.lines, 'COLUMNS': self.columns}, python_exe, communicator_py)
self.proc.open(command, self.lines, self.columns, python_exe, communicator_py, options)
self.buffer = vim.current.buffer
# }}}
self.screen_encoding = vim.eval('&fileencoding')
# *********************************************************************************************
# read and update screen
def read(self, timeout=1, set_cursor=True, return_output=False, update_buffer=True): # {{{
def read(self, timeout=1, set_cursor=True, return_output=False, update_buffer=True):
""" Read from console and update Vim buffer. """
try:
stats = self.proc.get_stats()
@ -79,48 +106,59 @@ class ConqueSole(Conque):
if not stats:
return
self.buffer_redraw_ct += 1
self.screen_redraw_ct += 1
# disable screen and buffer redraws in fast mode
if not CONQUE_FAST_MODE:
self.buffer_redraw_ct += 1
self.screen_redraw_ct += 1
update_top = 0
update_bottom = 0
lines = []
# full buffer redraw, our favorite!
if self.buffer_redraw_ct == CONQUE_SOLE_BUFFER_REDRAW:
self.buffer_redraw_ct = 0
update_top = 0
update_bottom = stats['top_offset'] + self.lines
(lines, attributes) = self.proc.read(update_top, update_bottom)
if return_output:
output = self.get_new_output(lines, update_top, stats)
if update_buffer:
for i in range(update_top, update_bottom + 1):
self.plain_text(i, lines[i], attributes[i], stats)
#if self.buffer_redraw_ct == CONQUE_SOLE_BUFFER_REDRAW:
# self.buffer_redraw_ct = 0
# update_top = 0
# update_bottom = stats['top_offset'] + self.lines
# (lines, attributes) = self.proc.read(update_top, update_bottom)
# if return_output:
# output = self.get_new_output(lines, update_top, stats)
# if update_buffer:
# for i in range(update_top, update_bottom + 1):
# if CONQUE_FAST_MODE:
# self.plain_text(i, lines[i], None, stats)
# else:
# self.plain_text(i, lines[i], attributes[i], stats)
# full screen redraw
elif stats['cursor_y'] + 1 != self.l or stats['top_offset'] != self.window_top or self.screen_redraw_ct == CONQUE_SOLE_SCREEN_REDRAW:
if stats['cursor_y'] + 1 != self.l or stats['top_offset'] != self.window_top or self.screen_redraw_ct >= CONQUE_SOLE_SCREEN_REDRAW:
self.screen_redraw_ct = 0
update_top = self.window_top
update_bottom = stats['top_offset'] + self.lines + 1
update_bottom = max([stats['top_offset'] + self.lines + 1, stats['cursor_y']])
(lines, attributes) = self.proc.read(update_top, update_bottom - update_top + 1)
if return_output:
output = self.get_new_output(lines, update_top, stats)
if update_buffer:
for i in range(update_top, update_bottom + 1):
self.plain_text(i, lines[i - update_top], attributes[i - update_top], stats)
if CONQUE_FAST_MODE:
self.plain_text(i, lines[i - update_top], None, stats)
else:
self.plain_text(i, lines[i - update_top], attributes[i - update_top], stats)
# single line redraw
else:
update_top = stats['cursor_y']
update_bottom = stats['cursor_y']
(lines, attributes) = self.proc.read(update_top, 1)
if return_output:
output = self.get_new_output(lines, update_top, stats)
if update_buffer:
if lines[0].rstrip() != self.buffer[update_top].rstrip():
self.plain_text(update_top, lines[0], attributes[0], stats)
if lines[0].rstrip() != u(self.buffer[update_top].rstrip()):
if CONQUE_FAST_MODE:
self.plain_text(update_top, lines[0], None, stats)
else:
self.plain_text(update_top, lines[0], attributes[0], stats)
# reset current position
@ -138,12 +176,10 @@ class ConqueSole(Conque):
except:
pass
# }}}
#########################################################################
# Calculate the "new" output from this read. Fake but useful
def get_new_output(self, lines, update_top, stats): # {{{
def get_new_output(self, lines, update_top, stats):
""" Calculate the "new" output from this read. Fake but useful """
if not (stats['cursor_y'] + 1 > self.l or (stats['cursor_y'] + 1 == self.l and stats['cursor_x'] + 1 > self.c)):
return ""
@ -175,18 +211,19 @@ class ConqueSole(Conque):
return "\n".join(new_output)
# }}}
#########################################################################
# update the buffer
def plain_text(self, line_nr, text, attributes, stats): # {{{
def plain_text(self, line_nr, text, attributes, stats):
""" Write plain text to Vim buffer. """
self.l = line_nr + 1
# handle line offset
line_nr += self.offset
self.l = line_nr + 1
# remove trailing whitespace
text = text.rstrip()
@ -197,21 +234,28 @@ class ConqueSole(Conque):
text = self.add_conceal_color(text, attributes, stats, line_nr)
# deal with character encoding
if CONQUE_PYTHON_VERSION == 2:
val = text.encode(self.screen_encoding)
else:
# XXX / Vim's python3 interface doesn't accept bytes object
val = str(text)
# update vim buffer
if len(self.buffer) <= line_nr:
self.buffer.append(text)
self.buffer.append(val)
else:
self.buffer[line_nr] = text
self.buffer[line_nr] = val
if not self.color_mode == 'conceal':
self.do_color(attributes=attributes, stats=stats)
if self.enable_colors and not self.color_mode == 'conceal' and line_nr > self.l - CONQUE_MAX_SYNTAX_LINES:
relevant = attributes[0:len(text)]
if line_nr not in self.attribute_cache or self.attribute_cache[line_nr] != relevant:
self.do_color(attributes=relevant, stats=stats)
self.attribute_cache[line_nr] = relevant
# }}}
#########################################################################
# add conceal color
def add_conceal_color(self, text, attributes, stats, line_nr): # {{{
def add_conceal_color(self, text, attributes, stats, line_nr):
""" Add 'conceal' color strings to output text """
# stop here if coloration is disabled
if not self.enable_colors:
@ -222,71 +266,42 @@ class ConqueSole(Conque):
return text
new_text = ''
# if text attribute is different, call add_color()
attr = None
start = 0
self.color_conceals[line_nr] = []
attribute_chunks = CONQUE_WIN32_REGEX_ATTR.findall(attributes)
offset = 0
ends = []
for i in range(0, len(attributes)):
c = ord(attributes[i])
for attr in attribute_chunks:
attr_num = ord(attr[1])
ends = []
if attr_num != stats['default_attribute']:
if c != attr:
if attr and attr != stats['default_attribute']:
color = self.translate_color(attr_num)
color = self.translate_color(attr)
new_text += chr(27) + 'sf' + color['fg_code'] + ';'
ends.append(chr(27) + 'ef' + color['fg_code'] + ';')
self.color_conceals[line_nr].append(offset)
new_text += chr(27) + 'sf' + color['fg_code'] + ';'
ends.append(chr(27) + 'ef' + color['fg_code'] + ';')
self.color_conceals[line_nr].append(start)
if attr_num > 15:
new_text += chr(27) + 'sb' + color['bg_code'] + ';'
ends.append(chr(27) + 'eb' + color['bg_code'] + ';')
self.color_conceals[line_nr].append(offset)
if c > 15:
new_text += chr(27) + 'sf' + color['bg_code'] + ';'
ends.append(chr(27) + 'ef' + color['bg_code'] + ';')
self.color_conceals[line_nr].append(start)
new_text += text[offset:offset + len(attr[0])]
new_text += text[start:i]
# close color regions
ends.reverse()
for i in range(0, len(ends)):
self.color_conceals[line_nr].append(len(new_text))
new_text += ends[i]
# close color regions
ends.reverse()
for j in range(0, len(ends)):
new_text += ends[j]
self.color_conceals[line_nr].append(i)
ends = []
start = i
attr = c
if attr and attr != stats['default_attribute']:
color = self.translate_color(attr)
new_text += chr(27) + 'sf' + color['fg_code'] + ';'
ends.append(chr(27) + 'ef' + color['fg_code'] + ';')
if c > 15:
new_text += chr(27) + 'sf' + color['bg_code'] + ';'
ends.append(chr(27) + 'ef' + color['bg_code'] + ';')
new_text += text[start:]
# close color regions
ends.reverse()
for i in range(0, len(ends)):
new_text += ends[i]
offset += len(attr[0])
return new_text
# }}}
#########################################################################
def do_color(self, start=0, end=0, attributes='', stats=None): # {{{
# stop here if coloration is disabled
if not self.enable_colors:
return
def do_color(self, start=0, end=0, attributes='', stats=None):
""" Convert Windows console attributes into Vim syntax highlighting """
# if no colors for this line, clear everything out
if len(attributes) == 0 or attributes == u(chr(stats['default_attribute'])) * len(attributes):
@ -294,29 +309,18 @@ class ConqueSole(Conque):
self.apply_color(1, len(attributes), self.l)
return
# if text attribute is different, call add_color()
attr = None
start = 0
for i in range(0, len(attributes)):
c = ord(attributes[i])
if c != attr:
if attr and attr != stats['default_attribute']:
self.color_changes = self.translate_color(attr)
self.apply_color(start + 1, i + 1, self.l)
start = i
attr = c
if attr and attr != stats['default_attribute']:
self.color_changes = self.translate_color(attr)
self.apply_color(start + 1, len(attributes), self.l)
attribute_chunks = CONQUE_WIN32_REGEX_ATTR.findall(attributes)
offset = 0
for attr in attribute_chunks:
attr_num = ord(attr[1])
if attr_num != stats['default_attribute']:
self.color_changes = self.translate_color(attr_num)
self.apply_color(offset + 1, offset + len(attr[0]) + 1, self.l)
offset += len(attr[0])
# }}}
#########################################################################
def translate_color(self, attr): # {{{
def translate_color(self, attr):
""" Convert Windows console attributes into RGB colors """
# check for cached color
if attr in self.color_cache:
@ -363,24 +367,20 @@ class ConqueSole(Conque):
return color
# }}}
#########################################################################
# write virtual key code to shared memory using proprietary escape seq
def write_vk(self, vk_code): # {{{
def write_vk(self, vk_code):
""" write virtual key code to shared memory using proprietary escape seq """
self.proc.write_vk(vk_code)
# }}}
# *********************************************************************************************
# resize if needed
def update_window_size(self): # {{{
def update_window_size(self):
""" Resize underlying console if Vim buffer size has changed """
if vim.current.window.width != self.columns or vim.current.window.height != self.lines:
# reset all window size attributes to default
self.columns = vim.current.window.width
self.lines = vim.current.window.height
@ -390,12 +390,14 @@ class ConqueSole(Conque):
self.proc.window_resize(vim.current.window.height, vim.current.window.width)
# }}}
# *********************************************************************************************
# resize if needed
def set_cursor(self, line, column):
""" Update cursor position in Vim buffer """
def set_cursor(self, line, column): # {{{
# handle offset
line += self.offset
# shift cursor position to handle concealed text
if self.enable_colors and self.color_mode == 'conceal':
@ -406,54 +408,51 @@ class ConqueSole(Conque):
else:
break
# figure out line
real_line = line
if real_line > len(self.buffer):
for l in range(len(self.buffer) - 1, real_line):
buffer_line = line
if buffer_line > len(self.buffer):
for l in range(len(self.buffer) - 1, buffer_line):
self.buffer.append('')
# figure out column
real_column = column
if len(self.buffer[real_line - 1]) < real_column:
self.buffer[real_line - 1] = self.buffer[real_line - 1] + ' ' * (real_column - len(self.buffer[real_line - 1]))
if len(self.buffer[buffer_line - 1]) < real_column:
self.buffer[buffer_line - 1] = self.buffer[buffer_line - 1] + ' ' * (real_column - len(self.buffer[buffer_line - 1]))
# python version is occasionally grumpy
try:
vim.current.window.cursor = (real_line, real_column - 1)
vim.current.window.cursor = (buffer_line, real_column - 1)
except:
vim.command('call cursor(' + str(real_line) + ', ' + str(real_column) + ')')
# }}}
vim.command('call cursor(' + str(buffer_line) + ', ' + str(real_column) + ')')
# *********************************************************************************************
# go into idle mode
def idle(self): # {{{
def idle(self):
""" go into idle mode """
self.proc.idle()
# }}}
# *********************************************************************************************
# resume from idle mode
def resume(self): # {{{
def resume(self):
""" resume from idle mode """
self.proc.resume()
# }}}
# *********************************************************************************************
# end subprocess
def close(self):
""" end console subprocess """
self.proc.close()
# *********************************************************************************************
# end subprocess forcefully
def abort(self):
""" end subprocess forcefully """
self.proc.close()
def get_buffer_line(self, line):
""" get buffer line """
return line
# vim:foldmethod=marker

View File

@ -1,11 +1,11 @@
# FILE: autoload/conque_term/conque_sole_communicator.py {{{
# FILE: autoload/conque_term/conque_sole_communicator.py
# AUTHOR: Nico Raffo <nicoraffo@gmail.com>
# WEBSITE: http://conque.googlecode.com
# MODIFIED: 2010-11-15
# VERSION: 2.0, for Vim 7.0
# MODIFIED: 2011-08-12
# VERSION: 2.2, for Vim 7.0
# LICENSE:
# Conque - Vim terminal/console emulator
# Copyright (C) 2009-2010 Nico Raffo
# Copyright (C) 2009-__YEAR__ Nico Raffo
#
# MIT License
#
@ -25,17 +25,20 @@
# 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. }}}
# THE SOFTWARE.
"""
ConqueSoleCommunicator
Script to transfer communications between python being run in Vim and a
subprocess run inside a Windows console. This is required since interactive
programs in Windows appear to require a console, and python run in Vim is
not attached to any console. So a console version of python must be initiated
for the subprocess. Communication is then done with the use of shared memory
objects. Good times!
This script will create a new Windows console and start the requested program
inside of it. This process is launched independently from the parent Vim
program, so it has no access to the vim module.
The main loop in this script reads data from the console and syncs it onto
blocks of memory shared with the Vim process. In this way the Vim process
and this script can communicate with each other.
"""
import time
@ -54,17 +57,12 @@ if __name__ == '__main__':
# attempt to catch ALL exceptions to fend of zombies
try:
# startup and config {{{
# simple arg validation
if len(sys.argv) < 5:
exit()
# shared memory size
CONQUE_SOLE_COMMANDS_SIZE = 255
# maximum time this thing reads. 0 means no limit. Only for testing.
max_loops = 0
@ -86,12 +84,18 @@ if __name__ == '__main__':
# console height
console_height = int(sys.argv[3])
# code page
code_page = int(sys.argv[4])
# code page
fast_mode = int(sys.argv[5])
# the actual subprocess to run
cmd_line = " ".join(sys.argv[4:])
cmd_line = " ".join(sys.argv[6:])
# width and height
options = {'LINES': console_height, 'COLUMNS': console_width}
options = {'LINES': console_height, 'COLUMNS': console_width, 'CODE_PAGE': code_page, 'FAST_MODE': fast_mode}
@ -106,12 +110,10 @@ if __name__ == '__main__':
is_idle = True
shm_command.clear()
# }}}
##############################################################
# Create the subprocess
# {{{
proc = ConqueSoleSubprocess()
res = proc.open(cmd_line, mem_key, options)
@ -119,8 +121,6 @@ if __name__ == '__main__':
exit()
# }}}
##############################################################
# main loop!
@ -135,7 +135,7 @@ if __name__ == '__main__':
if not proc.is_alive():
proc.close()
exit()
break
# check for change in buffer focus
cmd = shm_command.read()

View File

@ -1,11 +1,11 @@
# FILE: autoload/conque_term/conque_sole_shared_memory.py {{{
# FILE: autoload/conque_term/conque_sole_shared_memory.py
# AUTHOR: Nico Raffo <nicoraffo@gmail.com>
# WEBSITE: http://conque.googlecode.com
# MODIFIED: 2010-11-15
# VERSION: 2.0, for Vim 7.0
# MODIFIED: 2011-08-12
# VERSION: 2.2, for Vim 7.0
# LICENSE:
# Conque - Vim terminal/console emulator
# Copyright (C) 2009-2010 Nico Raffo
# Copyright (C) 2009-__YEAR__ Nico Raffo
#
# MIT License
#
@ -25,17 +25,20 @@
# 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. }}}
# THE SOFTWARE.
"""Wrapper class for shared memory between Windows python processes"""
"""
Wrapper class for shared memory between Windows python processes
Adds a small amount of functionality to the standard mmap module.
"""
import mmap
import sys
if sys.version_info[0] == 2:
CONQUE_PYTHON_VERSION = 2
else:
CONQUE_PYTHON_VERSION = 3
# PYTHON VERSION
CONQUE_PYTHON_VERSION = sys.version_info[0]
if CONQUE_PYTHON_VERSION == 2:
import cPickle as pickle
@ -45,16 +48,14 @@ else:
class ConqueSoleSharedMemory():
# ****************************************************************************
# class properties
# {{{
# is the data being stored not fixed length
fixed_length = False
# maximum number of bytes per character, for fixed width blocks
char_width = 1
# fill memory with this character when clearing and fixed_length is true
fill_char = ' '
FILL_CHAR = None
# serialize and unserialize data automatically
serialize = False
@ -72,18 +73,25 @@ class ConqueSoleSharedMemory():
shm = None
# character encoding, dammit
encoding = 'ascii'
encoding = 'utf-8'
# pickle terminator
TERMINATOR = None
# }}}
# ****************************************************************************
# constructor I guess
def __init__(self, mem_size, mem_type, mem_key, fixed_length=False, fill_char=' ', serialize=False, encoding='utf-8'):
""" Initialize new shared memory block instance
def __init__(self, mem_size, mem_type, mem_key, fixed_length=False, fill_char=' ', serialize=False, encoding='ascii'): # {{{
Arguments:
mem_size -- Memory size in characters, depends on encoding argument to calcuate byte size
mem_type -- Label to identify what will be stored
mem_key -- Unique, probably random key to identify this block
fixed_length -- If set to true, assume the data stored will always fill the memory size
fill_char -- Initialize memory block with this character, only really helpful with fixed_length blocks
serialize -- Automatically serialize data passed to write. Allows storing non-byte data
encoding -- Character encoding to use when storing character data
"""
self.mem_size = mem_size
self.mem_type = mem_type
self.mem_key = mem_key
@ -93,12 +101,17 @@ class ConqueSoleSharedMemory():
self.encoding = encoding
self.TERMINATOR = str(chr(0)).encode(self.encoding)
# }}}
if CONQUE_PYTHON_VERSION == 3:
self.FILL_CHAR = fill_char
else:
self.FILL_CHAR = unicode(fill_char)
# ****************************************************************************
# create memory block
if fixed_length and encoding == 'utf-8':
self.char_width = 4
def create(self, access='write'): # {{{
def create(self, access='write'):
""" Create a new block of shared memory using the mmap module. """
if access == 'write':
mmap_access = mmap.ACCESS_WRITE
@ -107,28 +120,28 @@ class ConqueSoleSharedMemory():
name = "conque_%s_%s" % (self.mem_type, self.mem_key)
self.shm = mmap.mmap(0, self.mem_size, name, mmap_access)
self.shm = mmap.mmap(0, self.mem_size * self.char_width, name, mmap_access)
if not self.shm:
return False
else:
return True
# }}}
# ****************************************************************************
# read data
def read(self, chars=1, start=0):
""" Read data from shared memory.
def read(self, chars=1, start=0): # {{{
# invalid reads
if self.fixed_length and (chars == 0 or start + chars > self.mem_size):
return ''
If this is a fixed length block, read 'chars' characters from memory.
Otherwise read up until the TERMINATOR character (null byte).
If this memory is serialized, unserialize it automatically.
"""
# go to start position
self.shm.seek(start)
self.shm.seek(start * self.char_width)
if not self.fixed_length:
if self.fixed_length:
chars = chars * self.char_width
else:
chars = self.shm.find(self.TERMINATOR)
if chars == 0:
@ -150,13 +163,15 @@ class ConqueSoleSharedMemory():
return shm_str
# }}}
# ****************************************************************************
# write data
def write(self, text, start=0):
""" Write data to memory.
def write(self, text, start=0): # {{{
If memory is fixed length, simply write the 'text' characters at 'start' position.
Otherwise write 'text' characters and append a null character.
If memory is serializable, do so first.
"""
# simple scenario, let pickle create bytes
if self.serialize:
if CONQUE_PYTHON_VERSION == 3:
@ -167,36 +182,29 @@ class ConqueSoleSharedMemory():
else:
tb = text.encode(self.encoding, 'replace')
self.shm.seek(start)
# write to memory
self.shm.seek(start * self.char_width)
if self.fixed_length:
self.shm.write(tb)
else:
self.shm.write(tb + self.TERMINATOR)
# }}}
# ****************************************************************************
# clear
def clear(self, start=0): # {{{
def clear(self, start=0):
""" Clear memory block using self.fill_char. """
self.shm.seek(start)
if self.fixed_length:
self.shm.write(str(self.fill_char * self.mem_size).encode(self.encoding))
self.shm.write(str(self.fill_char * self.mem_size * self.char_width).encode(self.encoding))
else:
self.shm.write(self.TERMINATOR)
# }}}
# ****************************************************************************
# close
def close(self):
""" Close/destroy memory block. """
self.shm.close()
# vim:foldmethod=marker

View File

@ -1,11 +1,11 @@
# FILE: autoload/conque_term/conque_sole_subprocess.py {{{
# FILE: autoload/conque_term/conque_sole_subprocess.py
# AUTHOR: Nico Raffo <nicoraffo@gmail.com>
# WEBSITE: http://conque.googlecode.com
# MODIFIED: 2010-11-15
# VERSION: 2.0, for Vim 7.0
# MODIFIED: 2011-08-12
# VERSION: 2.2, for Vim 7.0
# LICENSE:
# Conque - Vim terminal/console emulator
# Copyright (C) 2009-2010 Nico Raffo
# Copyright (C) 2009-__YEAR__ Nico Raffo
#
# MIT License
#
@ -25,9 +25,9 @@
# 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. }}}
# THE SOFTWARE.
""" ConqueSoleSubprocess {{{
""" ConqueSoleSubprocess
Creates a new subprocess with it's own (hidden) console window.
@ -47,12 +47,7 @@ Sample Usage:
shm_in.write("dir\r")
output = shm_out.read(...)
Requirements:
* Python for Windows extensions. Available at http://sourceforge.net/projects/pywin32/
* Must be run from process attached to an existing console.
}}} """
"""
import time
import re
@ -66,9 +61,7 @@ from conque_sole_shared_memory import *
class ConqueSoleSubprocess():
# Class properties {{{
#window = None
# subprocess handle and pid
handle = None
pid = None
@ -117,25 +110,16 @@ class ConqueSoleSubprocess():
# are we still a valid process?
is_alive = True
# running in fast mode
fast_mode = 0
# used for periodic execution of screen and memory redrawing
screen_redraw_ct = 0
mem_redraw_ct = 0
# }}}
# ****************************************************************************
# initialize class instance
def __init__(self): # {{{
pass
# }}}
# ****************************************************************************
# Create proccess cmd
def open(self, cmd, mem_key, options={}): # {{{
def open(self, cmd, mem_key, options={}):
""" Create subproccess running in hidden console window. """
@ -156,6 +140,9 @@ class ConqueSoleSubprocess():
self.window_height = options['LINES']
self.buffer_width = options['COLUMNS']
# fast mode
self.fast_mode = options['FAST_MODE']
# console window options
si = STARTUPINFO()
@ -178,15 +165,18 @@ class ConqueSoleSubprocess():
# process info
self.pid = pi.dwProcessId
self.handle = pi.hProcess
# attach ourselves to the new console
# console is not immediately available
for i in range(10):
time.sleep(1)
time.sleep(0.25)
try:
res = ctypes.windll.kernel32.AttachConsole(self.pid)
@ -221,6 +211,13 @@ class ConqueSoleSubprocess():
# set window size
self.set_window_size(self.window_width, self.window_height)
# set utf-8 code page
if 'CODE_PAGE' in options and options['CODE_PAGE'] > 0:
if ctypes.windll.kernel32.IsValidCodePage(ctypes.c_uint(options['CODE_PAGE'])):
ctypes.windll.kernel32.SetConsoleCP(ctypes.c_uint(options['CODE_PAGE']))
ctypes.windll.kernel32.SetConsoleOutputCP(ctypes.c_uint(options['CODE_PAGE']))
# init shared memory
self.init_shared_memory(mem_key)
@ -234,17 +231,9 @@ class ConqueSoleSubprocess():
return False
# }}}
# ****************************************************************************
# create shared memory objects
def init_shared_memory(self, mem_key): # {{{
buf_info = self.get_buffer_info()
def init_shared_memory(self, mem_key):
""" Create shared memory objects. """
self.shm_input = ConqueSoleSharedMemory(CONQUE_SOLE_INPUT_SIZE, 'input', mem_key)
self.shm_input.create('write')
@ -254,9 +243,11 @@ class ConqueSoleSubprocess():
self.shm_output.create('write')
self.shm_output.clear()
self.shm_attributes = ConqueSoleSharedMemory(self.buffer_height * self.buffer_width, 'attributes', mem_key, True, chr(buf_info.wAttributes), encoding='latin-1')
self.shm_attributes.create('write')
self.shm_attributes.clear()
if not self.fast_mode:
buf_info = self.get_buffer_info()
self.shm_attributes = ConqueSoleSharedMemory(self.buffer_height * self.buffer_width, 'attributes', mem_key, True, chr(buf_info.wAttributes), encoding='latin-1')
self.shm_attributes.create('write')
self.shm_attributes.clear()
self.shm_stats = ConqueSoleSharedMemory(CONQUE_SOLE_STATS_SIZE, 'stats', mem_key, serialize=True)
self.shm_stats.create('write')
@ -276,12 +267,9 @@ class ConqueSoleSubprocess():
return True
# }}}
# ****************************************************************************
# check for and process commands
def check_commands(self): # {{{
def check_commands(self):
""" Check for and process commands from Vim. """
cmd = self.shm_command.read()
@ -320,12 +308,9 @@ class ConqueSoleSubprocess():
buf_info = self.get_buffer_info()
self.reset_console(buf_info, add_block=False)
# }}}
# ****************************************************************************
# read from windows console and update output buffer
def read(self, timeout=0): # {{{
def read(self):
""" Read from windows console and update shared memory blocks. """
# no point really
if self.screen_redraw_ct == 0 and not self.is_alive():
@ -337,12 +322,6 @@ class ConqueSoleSubprocess():
# check for commands
self.check_commands()
# emulate timeout by sleeping timeout time
if timeout > 0:
read_timeout = float(timeout) / 1000
time.sleep(read_timeout)
# get cursor position
buf_info = self.get_buffer_info()
curs_line = buf_info.dwCursorPosition.Y
@ -353,12 +332,15 @@ class ConqueSoleSubprocess():
self.screen_redraw_ct = 0
read_start = self.top
read_end = buf_info.srWindow.Bottom + 1
read_end = max([buf_info.srWindow.Bottom + 1, curs_line + 1])
else:
read_start = curs_line
read_end = curs_line + 1
# vars used in for loop
coord = COORD(0, 0)
chars_read = ctypes.c_int(0)
@ -369,45 +351,68 @@ class ConqueSoleSubprocess():
coord.Y = i
res = ctypes.windll.kernel32.ReadConsoleOutputCharacterW(self.stdout, ctypes.byref(self.tc), self.buffer_width, coord, ctypes.byref(chars_read))
ctypes.windll.kernel32.ReadConsoleOutputAttribute(self.stdout, ctypes.byref(self.ac), self.buffer_width, coord, ctypes.byref(chars_read))
if not self.fast_mode:
ctypes.windll.kernel32.ReadConsoleOutputAttribute(self.stdout, ctypes.byref(self.ac), self.buffer_width, coord, ctypes.byref(chars_read))
t = self.tc.value
a = self.ac.value
if not self.fast_mode:
a = self.ac.value
# add data
if i >= len(self.data):
self.data.append(t)
self.attributes.append(a)
else:
self.data[i] = t
for j in range(len(self.data), i + 1):
self.data.append('')
if not self.fast_mode:
self.attributes.append('')
self.data[i] = t
if not self.fast_mode:
self.attributes[i] = a
#for i in range(0, len(t)):
# write new output to shared memory
if self.mem_redraw_ct == CONQUE_SOLE_MEM_REDRAW:
self.mem_redraw_ct = 0
try:
if self.mem_redraw_ct == CONQUE_SOLE_MEM_REDRAW:
self.mem_redraw_ct = 0
self.shm_output.write(''.join(self.data))
self.shm_attributes.write(''.join(self.attributes))
else:
for i in range(0, len(self.data)):
self.shm_output.write(text=self.data[i], start=self.buffer_width * i)
if not self.fast_mode:
self.shm_attributes.write(text=self.attributes[i], start=self.buffer_width * i)
else:
self.shm_output.write(text=''.join(self.data[read_start:read_end]), start=read_start * self.buffer_width)
self.shm_attributes.write(text=''.join(self.attributes[read_start:read_end]), start=read_start * self.buffer_width)
for i in range(read_start, read_end):
self.shm_output.write(text=self.data[i], start=self.buffer_width * i)
if not self.fast_mode:
self.shm_attributes.write(text=self.attributes[i], start=self.buffer_width * i)
#self.shm_output.write(text=''.join(self.data[read_start:read_end]), start=read_start * self.buffer_width)
#self.shm_attributes.write(text=''.join(self.attributes[read_start:read_end]), start=read_start * self.buffer_width)
# write cursor position to shared memory
stats = {'top_offset': buf_info.srWindow.Top, 'default_attribute': buf_info.wAttributes, 'cursor_x': curs_col, 'cursor_y': curs_line, 'is_alive': 1}
self.shm_stats.write(stats)
# write cursor position to shared memory
stats = {'top_offset': buf_info.srWindow.Top, 'default_attribute': buf_info.wAttributes, 'cursor_x': curs_col, 'cursor_y': curs_line, 'is_alive': 1}
self.shm_stats.write(stats)
# adjust screen position
self.top = buf_info.srWindow.Top
self.cursor_line = curs_line
# check for reset
if curs_line > buf_info.dwSize.Y - 200:
self.reset_console(buf_info)
except:
# adjust screen position
self.top = buf_info.srWindow.Top
self.cursor_line = curs_line
# check for reset
if curs_line > buf_info.dwSize.Y - 200:
self.reset_console(buf_info)
pass
# increment redraw counters
self.screen_redraw_ct += 1
@ -415,12 +420,9 @@ class ConqueSoleSubprocess():
return None
# }}}
# ****************************************************************************
# clear the console and set cursor at home position
def reset_console(self, buf_info, add_block=True): # {{{
def reset_console(self, buf_info, add_block=True):
""" Extend the height of the current console if the cursor postion gets within 200 lines of the current size. """
# sometimes we just want to change the buffer width,
# in which case no need to add another block
@ -431,8 +433,9 @@ class ConqueSoleSubprocess():
self.shm_output.close()
self.shm_output = None
self.shm_attributes.close()
self.shm_attributes = None
if not self.fast_mode:
self.shm_attributes.close()
self.shm_attributes = None
# new shared memory key
mem_key = 'mk' + str(time.time())
@ -448,15 +451,17 @@ class ConqueSoleSubprocess():
self.data[i] = self.data[i] + ' ' * (self.buffer_width - len(self.data[i]))
self.shm_output.write(''.join(self.data))
self.shm_attributes = ConqueSoleSharedMemory(self.buffer_height * self.buffer_width * self.output_blocks, 'attributes', mem_key, True, chr(buf_info.wAttributes), encoding='latin-1')
self.shm_attributes.create('write')
self.shm_attributes.clear()
if not self.fast_mode:
self.shm_attributes = ConqueSoleSharedMemory(self.buffer_height * self.buffer_width * self.output_blocks, 'attributes', mem_key, True, chr(buf_info.wAttributes), encoding='latin-1')
self.shm_attributes.create('write')
self.shm_attributes.clear()
# backfill attributes
if len(self.attributes[0]) < self.buffer_width:
for i in range(0, len(self.attributes)):
self.attributes[i] = self.attributes[i] + chr(buf_info.wAttributes) * (self.buffer_width - len(self.attributes[i]))
self.shm_attributes.write(''.join(self.attributes))
if not self.fast_mode:
self.shm_attributes.write(''.join(self.attributes))
# notify wrapper of new output block
self.shm_rescroll.write({'cmd': 'new_output', 'data': {'blocks': self.output_blocks, 'mem_key': mem_key}})
@ -481,19 +486,20 @@ class ConqueSoleSubprocess():
self.tc = ctypes.create_unicode_buffer(self.buffer_width)
self.ac = ctypes.create_unicode_buffer(self.buffer_width)
# }}}
# ****************************************************************************
# write text to console. this function just parses out special sequences for
# special key events and passes on the text to the plain or virtual key functions
def write(self): # {{{
def write(self):
""" Write text to console.
This function just parses out special sequences for special key events
and passes on the text to the plain or virtual key functions.
"""
# get input from shared mem
text = self.shm_input.read()
# nothing to do here
if text == '':
if text == u(''):
return
@ -502,7 +508,7 @@ class ConqueSoleSubprocess():
self.shm_input.clear()
# split on VK codes
chunks = CONQUE_SEQ_REGEX_VK.split(text)
chunks = CONQUE_WIN32_REGEX_VK.split(text)
# if len() is one then no vks
if len(chunks) == 1:
@ -517,45 +523,48 @@ class ConqueSoleSubprocess():
if t == '':
continue
if CONQUE_SEQ_REGEX_VK.match(t):
if CONQUE_WIN32_REGEX_VK.match(t):
self.write_vk(t[2:-2])
else:
self.write_plain(t)
# }}}
# ****************************************************************************
def write_plain(self, text): # {{{
def write_plain(self, text):
""" Write simple text to subprocess. """
li = INPUT_RECORD * len(text)
list_input = li()
for i in range(0, len(text)):
# create keyboard input
ke = KEY_EVENT_RECORD()
ke.bKeyDown = ctypes.c_byte(1)
ke.wRepeatCount = ctypes.c_short(1)
cnum = ord(text[i])
ke.wVirtualKeyCode = ctypes.windll.user32.VkKeyScanW(cnum)
ke.wVirtualScanCode = ctypes.c_short(ctypes.windll.user32.MapVirtualKeyW(int(cnum), 0))
if cnum > 31:
ke.uChar.UnicodeChar = u(chr(cnum))
ke.uChar.UnicodeChar = uchr(cnum)
elif cnum == 3:
ctypes.windll.kernel32.GenerateConsoleCtrlEvent(0, self.pid)
ke.uChar.UnicodeChar = u(chr(cnum))
ke.uChar.UnicodeChar = uchr(cnum)
ke.wVirtualKeyCode = ctypes.windll.user32.VkKeyScanW(cnum + 96)
ke.dwControlKeyState = LEFT_CTRL_PRESSED
ke.dwControlKeyState |= LEFT_CTRL_PRESSED
else:
ke.uChar.UnicodeChar = u(chr(cnum))
ke.uChar.UnicodeChar = uchr(cnum)
if cnum in CONQUE_WINDOWS_VK_INV:
ke.wVirtualKeyCode = cnum
else:
ke.wVirtualKeyCode = ctypes.windll.user32.VkKeyScanW(cnum + 96)
ke.dwControlKeyState = LEFT_CTRL_PRESSED
ke.dwControlKeyState |= LEFT_CTRL_PRESSED
kc = INPUT_RECORD(KEY_EVENT)
kc.Event.KeyEvent = ke
@ -574,27 +583,41 @@ class ConqueSoleSubprocess():
# }}}
def write_vk(self, vk_code):
""" Write special characters to console subprocess. """
# ****************************************************************************
def write_vk(self, vk_code): # {{{
code = None
ctrl_pressed = False
# this could be made more generic when more attributes
# other than ctrl_pressed are available
vk_attributes = vk_code.split(';')
for attr in vk_attributes:
if attr == CONQUE_VK_ATTR_CTRL_PRESSED:
ctrl_pressed = True
else:
code = attr
li = INPUT_RECORD * 1
# create keyboard input
ke = KEY_EVENT_RECORD()
ke.uChar.UnicodeChar = u(chr(0))
ke.wVirtualKeyCode = ctypes.c_short(int(vk_code))
ke.wVirtualScanCode = ctypes.c_short(ctypes.windll.user32.MapVirtualKeyW(int(vk_code), 0))
ke.uChar.UnicodeChar = uchr(0)
ke.wVirtualKeyCode = ctypes.c_short(int(code))
ke.wVirtualScanCode = ctypes.c_short(ctypes.windll.user32.MapVirtualKeyW(int(code), 0))
ke.bKeyDown = ctypes.c_byte(1)
ke.wRepeatCount = ctypes.c_short(1)
# set enhanced key mode for arrow keys
if vk_code in CONQUE_WINDOWS_VK_ENHANCED:
if code in CONQUE_WINDOWS_VK_ENHANCED:
ke.dwControlKeyState = ENHANCED_KEY
ke.dwControlKeyState |= ENHANCED_KEY
if ctrl_pressed:
ke.dwControlKeyState |= LEFT_CTRL_PRESSED
kc = INPUT_RECORD(KEY_EVENT)
kc.Event.KeyEvent = ke
@ -610,11 +633,8 @@ class ConqueSoleSubprocess():
# }}}
# ****************************************************************************
def close(self): # {{{
def close(self):
""" Close all running subproccesses """
# record status
self.is_alive = False
@ -656,18 +676,18 @@ class ConqueSoleSubprocess():
pass
def close_pid(self, pid):
""" Terminate a single process. """
handle = ctypes.windll.kernel32.OpenProcess(PROCESS_TERMINATE, 0, pid)
ctypes.windll.kernel32.TerminateProcess(handle, -1)
ctypes.windll.kernel32.CloseHandle(handle)
# }}}
# ****************************************************************************
# check process health
def is_alive(self): # {{{
def is_alive(self):
""" Check process health. """
status = ctypes.windll.kernel32.WaitForSingleObject(self.handle, 1)
@ -677,21 +697,15 @@ class ConqueSoleSubprocess():
return self.is_alive
# }}}
# ****************************************************************************
# return screen data as string
def get_screen_text(self): # {{{
def get_screen_text(self):
""" Return screen data as string. """
return "\n".join(self.data)
# }}}
# ****************************************************************************
def set_window_size(self, width, height): # {{{
def set_window_size(self, width, height):
""" Change Windows console size. """
@ -735,19 +749,14 @@ class ConqueSoleSubprocess():
self.window_width = buf_info.srWindow.Right + 1
self.window_height = buf_info.srWindow.Bottom + 1
# }}}
# ****************************************************************************
# get buffer info, used a lot
def get_buffer_info(self): # {{{
def get_buffer_info(self):
""" Retrieve commonly-used buffer information. """
buf_info = CONSOLE_SCREEN_BUFFER_INFO()
ctypes.windll.kernel32.GetConsoleScreenBufferInfo(self.stdout, ctypes.byref(buf_info))
return buf_info
# }}}
# vim:foldmethod=marker

View File

@ -1,11 +1,11 @@
# FILE: autoload/conque_term/conque_sole_wrapper.py {{{
# FILE: autoload/conque_term/conque_sole_wrapper.py
# AUTHOR: Nico Raffo <nicoraffo@gmail.com>
# WEBSITE: http://conque.googlecode.com
# MODIFIED: 2010-11-15
# VERSION: 2.0, for Vim 7.0
# MODIFIED: 2011-08-12
# VERSION: 2.2, for Vim 7.0
# LICENSE:
# Conque - Vim terminal/console emulator
# Copyright (C) 2009-2010 Nico Raffo
# Copyright (C) 2009-__YEAR__ Nico Raffo
#
# MIT License
#
@ -25,15 +25,17 @@
# 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. }}}
# THE SOFTWARE.
""" ConqueSoleSubprocessWrapper {{{
"""
ConqueSoleSubprocessWrapper
Subprocess wrapper to deal with Windows insanity. Launches console based python,
which in turn launches originally requested command. Communicates with cosole
python through shared memory objects.
}}} """
"""
import ctypes
import time
@ -41,8 +43,7 @@ import time
class ConqueSoleWrapper():
# class properties {{{
# unique key used for shared memory block names
shm_key = ''
# process info
@ -53,7 +54,6 @@ class ConqueSoleWrapper():
bucket = None
# console size
# NOTE: columns should never change after open() is called
lines = 24
columns = 80
@ -69,33 +69,31 @@ class ConqueSoleWrapper():
# console python process
proc = None
# }}}
#########################################################################
# unused
def open(self, cmd, lines, columns, python_exe='python.exe', communicator_py='conque_sole_communicator.py', options={}):
""" Launch python.exe subprocess which will in turn launch the user's program.
def __init__(self): # {{{
Arguments:
cmd -- The user's command to run. E.g. "Powershell.exe" or "C:\Python27\Scripts\ipython.bat"
lines, columns -- The size of the console, also the size of the Vim buffer
python.exe -- The path to the python executable, typically C:\PythonXX\python.exe
communicator_py -- The path to the subprocess controller script in the user's vimfiles directory
options -- optional configuration
"""
self.lines = lines
self.columns = columns
self.bucket = u('')
# }}}
#########################################################################
# run communicator process which will in turn run cmd
def open(self, cmd, options={}, python_exe='python.exe', communicator_py='conque_sole_communicator.py'): # {{{
self.lines = options['LINES']
self.columns = options['COLUMNS']
# create a shm key
self.shm_key = 'mk' + str(time.time())
# python command
cmd_line = '%s "%s" %s %d %d %s' % (python_exe, communicator_py, self.shm_key, int(self.columns), int(self.lines), cmd)
cmd_line = '%s "%s" %s %d %d %d %d %s' % (python_exe, communicator_py, self.shm_key, int(self.columns), int(self.lines), int(options['CODE_PAGE']), int(CONQUE_FAST_MODE), cmd)
# console window attributes
flags = NORMAL_PRIORITY_CLASS | DETACHED_PROCESS
flags = NORMAL_PRIORITY_CLASS | DETACHED_PROCESS | CREATE_UNICODE_ENVIRONMENT
si = STARTUPINFO()
pi = PROCESS_INFORMATION()
@ -114,13 +112,13 @@ class ConqueSoleWrapper():
# init shared memory objects
self.init_shared_memory(self.shm_key)
# }}}
#########################################################################
# read output from shared memory
def read(self, start_line, num_lines, timeout=0):
""" Read a range of console lines from shared memory.
def read(self, start_line, num_lines, timeout=0): # {{{
Returns a pair of lists containing the console text and console text attributes.
"""
# emulate timeout by sleeping timeout time
if timeout > 0:
read_timeout = float(timeout) / 1000
@ -133,16 +131,14 @@ class ConqueSoleWrapper():
# get output
for i in range(start_line, start_line + num_lines + 1):
output.append(self.shm_output.read(self.columns, i * self.columns))
attributes.append(self.shm_attributes.read(self.columns, i * self.columns))
if not CONQUE_FAST_MODE:
attributes.append(self.shm_attributes.read(self.columns, i * self.columns))
return (output, attributes)
# }}}
#########################################################################
# get current cursor/scroll position
def get_stats(self): # {{{
def get_stats(self):
""" Return a dictionary with current console cursor and scrolling information. """
try:
rescroll = self.shm_rescroll.read()
@ -156,16 +152,18 @@ class ConqueSoleWrapper():
self.shm_output.close()
self.shm_output = None
self.shm_attributes.close()
self.shm_attributes = None
if not CONQUE_FAST_MODE:
self.shm_attributes.close()
self.shm_attributes = None
# reallocate memory
self.shm_output = ConqueSoleSharedMemory(CONQUE_SOLE_BUFFER_LENGTH * self.columns * rescroll['data']['blocks'], 'output', rescroll['data']['mem_key'], True)
self.shm_output.create('read')
self.shm_attributes = ConqueSoleSharedMemory(CONQUE_SOLE_BUFFER_LENGTH * self.columns * rescroll['data']['blocks'], 'attributes', rescroll['data']['mem_key'], True, encoding='latin-1')
self.shm_attributes.create('read')
if not CONQUE_FAST_MODE:
self.shm_attributes = ConqueSoleSharedMemory(CONQUE_SOLE_BUFFER_LENGTH * self.columns * rescroll['data']['blocks'], 'attributes', rescroll['data']['mem_key'], True, encoding='latin-1')
self.shm_attributes.create('read')
stats_str = self.shm_stats.read()
if stats_str != '':
@ -178,12 +176,10 @@ class ConqueSoleWrapper():
return self.stats
# }}}
#########################################################################
# get process status
def is_alive(self):
""" Get process status. """
def is_alive(self): # {{{
if not self.shm_stats:
return True
@ -192,16 +188,12 @@ class ConqueSoleWrapper():
return (stats_str['is_alive'])
else:
return True
# }}}
#########################################################################
# write input to shared memory
def write(self, text): # {{{
self.bucket += u(text, 'ascii', 'replace')
def write(self, text):
""" Write input to shared memory. """
self.bucket += text
istr = self.shm_input.read()
@ -210,51 +202,36 @@ class ConqueSoleWrapper():
self.shm_input.write(self.bucket[:500])
self.bucket = self.bucket[500:]
# }}}
#########################################################################
# write virtual key code to shared memory using proprietary escape seq
def write_vk(self, vk_code):
""" Write virtual key code to shared memory using proprietary escape sequences. """
def write_vk(self, vk_code): # {{{
seq = "\x1b[" + str(vk_code) + "VK"
seq = u("\x1b[") + u(str(vk_code)) + u("VK")
self.write(seq)
# }}}
#########################################################################
# idle
def idle(self): # {{{
def idle(self):
""" Write idle command to shared memory block, so subprocess controller can hibernate. """
self.shm_command.write({'cmd': 'idle', 'data': {}})
# }}}
#########################################################################
# resume
def resume(self): # {{{
def resume(self):
""" Write resume command to shared memory block, so subprocess controller can wake up. """
self.shm_command.write({'cmd': 'resume', 'data': {}})
# }}}
#########################################################################
# shut it all down
def close(self): # {{{
def close(self):
""" Shut it all down. """
self.shm_command.write({'cmd': 'close', 'data': {}})
time.sleep(0.2)
# }}}
#########################################################################
# resize console window
def window_resize(self, lines, columns): # {{{
def window_resize(self, lines, columns):
""" Resize console window. """
self.lines = lines
@ -264,12 +241,9 @@ class ConqueSoleWrapper():
self.shm_resize.write({'cmd': 'resize', 'data': {'width': columns, 'height': lines}})
# }}}
# ****************************************************************************
# create shared memory objects
def init_shared_memory(self, mem_key): # {{{
def init_shared_memory(self, mem_key):
""" Create shared memory objects. """
self.shm_input = ConqueSoleSharedMemory(CONQUE_SOLE_INPUT_SIZE, 'input', mem_key)
self.shm_input.create('write')
@ -278,8 +252,9 @@ class ConqueSoleWrapper():
self.shm_output = ConqueSoleSharedMemory(CONQUE_SOLE_BUFFER_LENGTH * self.columns, 'output', mem_key, True)
self.shm_output.create('write')
self.shm_attributes = ConqueSoleSharedMemory(CONQUE_SOLE_BUFFER_LENGTH * self.columns, 'attributes', mem_key, True, encoding='latin-1')
self.shm_attributes.create('write')
if not CONQUE_FAST_MODE:
self.shm_attributes = ConqueSoleSharedMemory(CONQUE_SOLE_BUFFER_LENGTH * self.columns, 'attributes', mem_key, True, encoding='latin-1')
self.shm_attributes.create('write')
self.shm_stats = ConqueSoleSharedMemory(CONQUE_SOLE_STATS_SIZE, 'stats', mem_key, serialize=True)
self.shm_stats.create('write')
@ -299,6 +274,5 @@ class ConqueSoleWrapper():
return True
# }}}
# vim:foldmethod=marker

View File

@ -1,11 +1,11 @@
# FILE: autoload/conque_term/conque_subprocess.py {{{
# FILE: autoload/conque_term/conque_subprocess.py
# AUTHOR: Nico Raffo <nicoraffo@gmail.com>
# WEBSITE: http://conque.googlecode.com
# MODIFIED: 2010-11-15
# VERSION: 2.0, for Vim 7.0
# MODIFIED: 2011-08-12
# VERSION: 2.2, for Vim 7.0
# LICENSE:
# Conque - Vim terminal/console emulator
# Copyright (C) 2009-2010 Nico Raffo
# Copyright (C) 2009-__YEAR__ Nico Raffo
#
# MIT License
#
@ -25,7 +25,7 @@
# 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. }}}
# THE SOFTWARE.
"""
ConqueSubprocess
@ -43,15 +43,15 @@ Usage:
p.close()
"""
if CONQUE_PLATFORM == 'nix':
import os
import signal
import pty
import tty
import select
import fcntl
import termios
import struct
import os
import signal
import pty
import tty
import select
import fcntl
import termios
import struct
import shlex
class ConqueSubprocess:
@ -62,16 +62,12 @@ class ConqueSubprocess:
# stdout+stderr file descriptor
fd = None
# constructor
def __init__(self): # {{{
self.pid = 0
# }}}
# create pty + subprocess
def open(self, command, env={}): # {{{
def open(self, command, env={}):
""" Create subprocess using forkpty() """
# parse command
command_arr = command.split()
command_arr = shlex.split(command)
executable = command_arr[0]
args = command_arr
@ -90,7 +86,7 @@ class ConqueSubprocess:
for k in env.keys():
os.environ[k] = env[k]
# set some attributes
# set tty attributes
try:
attrs = tty.tcgetattr(1)
attrs[0] = attrs[0] ^ tty.IGNBRK
@ -111,14 +107,13 @@ class ConqueSubprocess:
else:
pass
# }}}
# read from pty
# XXX - select.poll() doesn't work in OS X!!!!!!!
def read(self, timeout=1): # {{{
def read(self, timeout=1):
""" Read from subprocess and return new output """
output = ''
read_timeout = float(timeout) / 1000
read_ct = 0
try:
# read from fd until no more output
@ -128,49 +123,59 @@ class ConqueSubprocess:
lines = ''
for s_fd in s_read:
try:
lines = os.read(self.fd, 32)
# increase read buffer so huge reads don't slow down
if read_ct < 10:
lines = os.read(self.fd, 32)
elif read_ct < 50:
lines = os.read(self.fd, 512)
else:
lines = os.read(self.fd, 2048)
read_ct += 1
except:
pass
output = output + lines.decode('utf-8')
if lines == '':
if lines == '' or read_ct > 100:
break
except:
pass
return output
# }}}
# I guess this one's not bad
def write(self, input): # {{{
def write(self, input):
""" Write new input to subprocess """
try:
if CONQUE_PYTHON_VERSION == 2:
os.write(self.fd, input)
os.write(self.fd, input.encode('utf-8', 'ignore'))
else:
os.write(self.fd, bytes(input, 'utf-8'))
except:
pass
# }}}
# signal process
def signal(self, signum): # {{{
def signal(self, signum):
""" signal process """
try:
os.kill(self.pid, signum)
except:
pass
# }}}
# close process
def close(self): # {{{
def close(self):
""" close process with sigterm signal """
self.signal(15)
# }}}
# get process status
def is_alive(self): #{{{
def is_alive(self):
""" get process status """
p_status = True
try:
if os.waitpid(self.pid, os.WNOHANG)[0]:
p_status = False
@ -179,17 +184,15 @@ class ConqueSubprocess:
return p_status
# }}}
# update window size in kernel, then send SIGWINCH to fg process
def window_resize(self, lines, columns): # {{{
def window_resize(self, lines, columns):
""" update window size in kernel, then send SIGWINCH to fg process """
try:
fcntl.ioctl(self.fd, termios.TIOCSWINSZ, struct.pack("HHHH", lines, columns, 0, 0))
os.kill(self.pid, signal.SIGWINCH)
except:
pass
# }}}
# vim:foldmethod=marker

View File

@ -1,11 +1,11 @@
# FILE: autoload/conque_term/conque_win32_util.py {{{
# FILE: autoload/conque_term/conque_win32_util.py
# AUTHOR: Nico Raffo <nicoraffo@gmail.com>
# WEBSITE: http://conque.googlecode.com
# MODIFIED: 2010-11-15
# VERSION: 2.0, for Vim 7.0
# MODIFIED: 2011-08-12
# VERSION: 2.2, for Vim 7.0
# LICENSE:
# Conque - Vim terminal/console emulator
# Copyright (C) 2009-2010 Nico Raffo
# Copyright (C) 2009-__YEAR__ Nico Raffo
#
# MIT License
#
@ -25,15 +25,15 @@
# 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. }}}
# THE SOFTWARE.
"""Python structures used for ctypes interaction"""
""" Python constants and structures used for ctypes interaction. """
from ctypes import *
# Constants
# create process flag constants {{{
# create process flag constants
CREATE_BREAKAWAY_FROM_JOB = 0x01000000
CREATE_DEFAULT_ERROR_MODE = 0x04000000
@ -46,15 +46,14 @@ CREATE_SEPARATE_WOW_VDM = 0x00000800
CREATE_SHARED_WOW_VDM = 0x00001000
CREATE_SUSPENDED = 0x00000004
CREATE_UNICODE_ENVIRONMENT = 0x00000400
DEBUG_ONLY_THIS_PROCESS = 0x00000002
DEBUG_PROCESS = 0x00000001
DETACHED_PROCESS = 0x00000008
EXTENDED_STARTUPINFO_PRESENT = 0x00080000
INHERIT_PARENT_AFFINITY = 0x00010000
# }}}
# process priority constants {{{
# process priority constants
ABOVE_NORMAL_PRIORITY_CLASS = 0x00008000
BELOW_NORMAL_PRIORITY_CLASS = 0x00004000
@ -63,9 +62,8 @@ IDLE_PRIORITY_CLASS = 0x00000040
NORMAL_PRIORITY_CLASS = 0x00000020
REALTIME_PRIORITY_CLASS = 0x00000100
# }}}
# startup info constants {{{
# startup info constants
STARTF_FORCEONFEEDBACK = 0x00000040
STARTF_FORCEOFFFEEDBACK = 0x00000080
@ -81,9 +79,8 @@ STARTF_USESHOWWINDOW = 0x00000001
STARTF_USESIZE = 0x00000002
STARTF_USESTDHANDLES = 0x00000100
# }}}
# show window constants {{{
# show window constants
SW_FORCEMINIMIZE = 11
SW_HIDE = 0
@ -99,9 +96,8 @@ SW_SHOWNA = 8
SW_SHOWNOACTIVATE = 4
SW_SHOWNORMAL = 1
# }}}
# input event types {{{
# input event types
FOCUS_EVENT = 0x0010
KEY_EVENT = 0x0001
@ -109,9 +105,8 @@ MENU_EVENT = 0x0008
MOUSE_EVENT = 0x0002
WINDOW_BUFFER_SIZE_EVENT = 0x0004
# }}}
# key event modifiers {{{
# key event modifiers
CAPSLOCK_ON = 0x0080
ENHANCED_KEY = 0x0100
@ -123,9 +118,8 @@ RIGHT_CTRL_PRESSED = 0x0004
SCROLLLOCK_ON = 0x0040
SHIFT_PRESSED = 0x0010
# }}}
# process access {{{
# process access
PROCESS_CREATE_PROCESS = 0x0080
PROCESS_CREATE_THREAD = 0x0002
@ -140,17 +134,15 @@ PROCESS_VM_OPERATION = 0x0008
PROCESS_VM_READ = 0x0010
PROCESS_VM_WRITE = 0x0020
# }}}
# input / output handles {{{
# input / output handles
STD_INPUT_HANDLE = c_ulong(-10)
STD_OUTPUT_HANDLE = c_ulong(-11)
STD_ERROR_HANDLE = c_ulong(-12)
# }}}
CONQUE_WINDOWS_VK = { # {{{
CONQUE_WINDOWS_VK = {
'VK_LBUTTON': 0x0001,
'VK_RBUTTON': 0x0002,
'VK_CANCEL': 0x0003,
@ -280,19 +272,16 @@ CONQUE_WINDOWS_VK_ENHANCED = {
str(int(CONQUE_WINDOWS_VK['VK_END'])): 1
}
# }}}
# structures used for CreateProcess
# Odd types {{{
# Odd types
LPBYTE = POINTER(c_ubyte)
LPTSTR = POINTER(c_char)
# }}}
class STARTUPINFO(Structure): # {{{
class STARTUPINFO(Structure):
_fields_ = [("cb", c_ulong),
("lpReserved", LPTSTR),
("lpDesktop", LPTSTR),
@ -315,9 +304,8 @@ class STARTUPINFO(Structure): # {{{
def to_str(self):
return ''
# }}}
class PROCESS_INFORMATION(Structure): # {{{
class PROCESS_INFORMATION(Structure):
_fields_ = [("hProcess", c_void_p),
("hThread", c_void_p),
("dwProcessId", c_ulong),
@ -326,9 +314,8 @@ class PROCESS_INFORMATION(Structure): # {{{
def to_str(self):
return ''
# }}}
class MEMORY_BASIC_INFORMATION(Structure): # {{{
class MEMORY_BASIC_INFORMATION(Structure):
_fields_ = [("BaseAddress", c_void_p),
("AllocationBase", c_void_p),
("AllocationProtect", c_ulong),
@ -340,9 +327,8 @@ class MEMORY_BASIC_INFORMATION(Structure): # {{{
def to_str(self):
return ''
# }}}
class SECURITY_ATTRIBUTES(Structure): # {{{
class SECURITY_ATTRIBUTES(Structure):
_fields_ = [("Length", c_ulong),
("SecDescriptor", c_void_p),
("InheritHandle", c_bool)]
@ -350,18 +336,16 @@ class SECURITY_ATTRIBUTES(Structure): # {{{
def to_str(self):
return ''
# }}}
class COORD(Structure): # {{{
class COORD(Structure):
_fields_ = [("X", c_short),
("Y", c_short)]
def to_str(self):
return ''
# }}}
class SMALL_RECT(Structure): # {{{
class SMALL_RECT(Structure):
_fields_ = [("Left", c_short),
("Top", c_short),
("Right", c_short),
@ -370,9 +354,8 @@ class SMALL_RECT(Structure): # {{{
def to_str(self):
return ''
# }}}
class CONSOLE_SCREEN_BUFFER_INFO(Structure): # {{{
class CONSOLE_SCREEN_BUFFER_INFO(Structure):
_fields_ = [("dwSize", COORD),
("dwCursorPosition", COORD),
("wAttributes", c_short),
@ -382,27 +365,24 @@ class CONSOLE_SCREEN_BUFFER_INFO(Structure): # {{{
def to_str(self):
return ''
# }}}
class CHAR_UNION(Union): # {{{
class CHAR_UNION(Union):
_fields_ = [("UnicodeChar", c_wchar),
("AsciiChar", c_char)]
def to_str(self):
return ''
# }}}
class CHAR_INFO(Structure): # {{{
class CHAR_INFO(Structure):
_fields_ = [("Char", CHAR_UNION),
("Attributes", c_short)]
def to_str(self):
return ''
# }}}
class KEY_EVENT_RECORD(Structure): # {{{
class KEY_EVENT_RECORD(Structure):
_fields_ = [("bKeyDown", c_byte),
("pad2", c_byte),
('pad1', c_short),
@ -415,9 +395,8 @@ class KEY_EVENT_RECORD(Structure): # {{{
def to_str(self):
return ''
# }}}
class MOUSE_EVENT_RECORD(Structure): # {{{
class MOUSE_EVENT_RECORD(Structure):
_fields_ = [("dwMousePosition", COORD),
("dwButtonState", c_int),
("dwControlKeyState", c_int),
@ -426,32 +405,29 @@ class MOUSE_EVENT_RECORD(Structure): # {{{
def to_str(self):
return ''
# }}}
class WINDOW_BUFFER_SIZE_RECORD(Structure): # {{{
class WINDOW_BUFFER_SIZE_RECORD(Structure):
_fields_ = [("dwSize", COORD)]
def to_str(self):
return ''
# }}}
class MENU_EVENT_RECORD(Structure): # {{{
class MENU_EVENT_RECORD(Structure):
_fields_ = [("dwCommandId", c_uint)]
def to_str(self):
return ''
# }}}
class FOCUS_EVENT_RECORD(Structure): # {{{
class FOCUS_EVENT_RECORD(Structure):
_fields_ = [("bSetFocus", c_byte)]
def to_str(self):
return ''
# }}}
class INPUT_UNION(Union): # {{{
class INPUT_UNION(Union):
_fields_ = [("KeyEvent", KEY_EVENT_RECORD),
("MouseEvent", MOUSE_EVENT_RECORD),
("WindowBufferSizeEvent", WINDOW_BUFFER_SIZE_RECORD),
@ -460,14 +436,13 @@ class INPUT_UNION(Union): # {{{
def to_str(self):
return ''
# }}}
class INPUT_RECORD(Structure): # {{{
class INPUT_RECORD(Structure):
_fields_ = [("EventType", c_short),
("Event", INPUT_UNION)]
def to_str(self):
return ''
# }}}
# vim:foldmethod=marker

650
vim/autoload/getscript.vim Normal file
View File

@ -0,0 +1,650 @@
" ---------------------------------------------------------------------
" getscript.vim
" Author: Charles E. Campbell, Jr.
" Date: May 31, 2011
" Version: 33
" Installing: :help glvs-install
" Usage: :help glvs
"
" GetLatestVimScripts: 642 1 :AutoInstall: getscript.vim
"redraw!|call inputsave()|call input("Press <cr> to continue")|call inputrestore()
" ---------------------------------------------------------------------
" Initialization: {{{1
" if you're sourcing this file, surely you can't be
" expecting vim to be in its vi-compatible mode!
if exists("g:loaded_getscript")
finish
endif
let g:loaded_getscript= "v33"
if &cp
echoerr "GetLatestVimScripts is not vi-compatible; not loaded (you need to set nocp)"
finish
endif
if v:version < 702
echohl WarningMsg
echo "***warning*** this version of getscript needs vim 7.2"
echohl Normal
finish
endif
let s:keepcpo = &cpo
set cpo&vim
"DechoTabOn
" ---------------------------
" Global Variables: {{{1
" ---------------------------
" Cygwin Detection ------- {{{2
if !exists("g:getscript_cygwin")
if has("win32") || has("win95") || has("win64") || has("win16")
if &shell =~ '\%(\<bash\>\|\<zsh\>\)\%(\.exe\)\=$'
let g:getscript_cygwin= 1
else
let g:getscript_cygwin= 0
endif
else
let g:getscript_cygwin= 0
endif
endif
" wget vs curl {{{2
if !exists("g:GetLatestVimScripts_wget")
if executable("wget")
let g:GetLatestVimScripts_wget= "wget"
elseif executable("curl")
let g:GetLatestVimScripts_wget= "curl"
else
let g:GetLatestVimScripts_wget = 'echo "GetLatestVimScripts needs wget or curl"'
let g:GetLatestVimScripts_options = ""
endif
endif
" options that wget and curl require:
if !exists("g:GetLatestVimScripts_options")
if g:GetLatestVimScripts_wget == "wget"
let g:GetLatestVimScripts_options= "-q -O"
elseif g:GetLatestVimScripts_wget == "curl"
let g:GetLatestVimScripts_options= "-s -O"
else
let g:GetLatestVimScripts_options= ""
endif
endif
" by default, allow autoinstall lines to work
if !exists("g:GetLatestVimScripts_allowautoinstall")
let g:GetLatestVimScripts_allowautoinstall= 1
endif
"" For debugging:
"let g:GetLatestVimScripts_wget = "echo"
"let g:GetLatestVimScripts_options = "options"
" ---------------------------------------------------------------------
" Check If AutoInstall Capable: {{{1
let s:autoinstall= ""
if g:GetLatestVimScripts_allowautoinstall
if (has("win32") || has("gui_win32") || has("gui_win32s") || has("win16") || has("win64") || has("win32unix") || has("win95")) && &shell != "bash"
" windows (but not cygwin/bash)
let s:dotvim= "vimfiles"
if !exists("g:GetLatestVimScripts_mv")
let g:GetLatestVimScripts_mv= "ren"
endif
else
" unix
let s:dotvim= ".vim"
if !exists("g:GetLatestVimScripts_mv")
let g:GetLatestVimScripts_mv= "mv"
endif
endif
if exists("g:GetLatestVimScripts_autoinstalldir") && isdirectory(g:GetLatestVimScripts_autoinstalldir)
let s:autoinstall= g:GetLatestVimScripts_autoinstalldir"
elseif exists('$HOME') && isdirectory(expand("$HOME")."/".s:dotvim)
let s:autoinstall= $HOME."/".s:dotvim
endif
" call Decho("s:autoinstall<".s:autoinstall.">")
"else "Decho
" call Decho("g:GetLatestVimScripts_allowautoinstall=".g:GetLatestVimScripts_allowautoinstall.": :AutoInstall: disabled")
endif
" ---------------------------------------------------------------------
" Public Interface: {{{1
com! -nargs=0 GetLatestVimScripts call getscript#GetLatestVimScripts()
com! -nargs=0 GetScript call getscript#GetLatestVimScripts()
silent! com -nargs=0 GLVS call getscript#GetLatestVimScripts()
" ---------------------------------------------------------------------
" GetLatestVimScripts: this function gets the latest versions of {{{1
" scripts based on the list in
" (first dir in runtimepath)/GetLatest/GetLatestVimScripts.dat
fun! getscript#GetLatestVimScripts()
" call Dfunc("GetLatestVimScripts() autoinstall<".s:autoinstall.">")
" insure that wget is executable
if executable(g:GetLatestVimScripts_wget) != 1
echoerr "GetLatestVimScripts needs ".g:GetLatestVimScripts_wget." which apparently is not available on your system"
" call Dret("GetLatestVimScripts : wget not executable/availble")
return
endif
" insure that fnameescape() is available
if !exists("*fnameescape")
echoerr "GetLatestVimScripts needs fnameescape() (provided by 7.1.299 or later)"
return
endif
" Find the .../GetLatest subdirectory under the runtimepath
for datadir in split(&rtp,',') + ['']
if isdirectory(datadir."/GetLatest")
" call Decho("found directory<".datadir.">")
let datadir= datadir . "/GetLatest"
break
endif
if filereadable(datadir."GetLatestVimScripts.dat")
" call Decho("found ".datadir."/GetLatestVimScripts.dat")
break
endif
endfor
" Sanity checks: readability and writability
if datadir == ""
echoerr 'Missing "GetLatest/" on your runtimepath - see :help glvs-dist-install'
" call Dret("GetLatestVimScripts : unable to find a GetLatest subdirectory")
return
endif
if filewritable(datadir) != 2
echoerr "(getLatestVimScripts) Your ".datadir." isn't writable"
" call Dret("GetLatestVimScripts : non-writable directory<".datadir.">")
return
endif
let datafile= datadir."/GetLatestVimScripts.dat"
if !filereadable(datafile)
echoerr "Your data file<".datafile."> isn't readable"
" call Dret("GetLatestVimScripts : non-readable datafile<".datafile.">")
return
endif
if !filewritable(datafile)
echoerr "Your data file<".datafile."> isn't writable"
" call Dret("GetLatestVimScripts : non-writable datafile<".datafile.">")
return
endif
" --------------------
" Passed sanity checks
" --------------------
" call Decho("datadir <".datadir.">")
" call Decho("datafile <".datafile.">")
" don't let any event handlers interfere (like winmanager's, taglist's, etc)
let eikeep = &ei
let hlskeep = &hls
let acdkeep = &acd
set ei=all hls&vim noacd
" Edit the datafile (ie. GetLatestVimScripts.dat):
" 1. record current directory (origdir),
" 2. change directory to datadir,
" 3. split window
" 4. edit datafile
let origdir= getcwd()
" call Decho("exe cd ".fnameescape(substitute(datadir,'\','/','ge')))
exe "cd ".fnameescape(substitute(datadir,'\','/','ge'))
split
" call Decho("exe e ".fnameescape(substitute(datafile,'\','/','ge')))
exe "e ".fnameescape(substitute(datafile,'\','/','ge'))
res 1000
let s:downloads = 0
let s:downerrors= 0
" Check on dependencies mentioned in plugins
" call Decho(" ")
" call Decho("searching plugins for GetLatestVimScripts dependencies")
let lastline = line("$")
" call Decho("lastline#".lastline)
let firstdir = substitute(&rtp,',.*$','','')
let plugins = split(globpath(firstdir,"plugin/*.vim"),'\n')
let plugins = plugins + split(globpath(firstdir,"AsNeeded/*.vim"),'\n')
let foundscript = 0
" this loop updates the GetLatestVimScripts.dat file
" with dependencies explicitly mentioned in the plugins
" via GetLatestVimScripts: ... lines
" It reads the plugin script at the end of the GetLatestVimScripts.dat
" file, examines it, and then removes it.
for plugin in plugins
" call Decho(" ")
" call Decho("plugin<".plugin.">")
" read plugin in
" evidently a :r creates a new buffer (the "#" buffer) that is subsequently unused -- bwiping it
$
" call Decho(".dependency checking<".plugin."> line$=".line("$"))
" call Decho("..exe silent r ".fnameescape(plugin))
exe "silent r ".fnameescape(plugin)
exe "silent bwipe ".bufnr("#")
while search('^"\s\+GetLatestVimScripts:\s\+\d\+\s\+\d\+','W') != 0
let depscript = substitute(getline("."),'^"\s\+GetLatestVimScripts:\s\+\d\+\s\+\d\+\s\+\(.*\)$','\1','e')
let depscriptid = substitute(getline("."),'^"\s\+GetLatestVimScripts:\s\+\(\d\+\)\s\+.*$','\1','')
let llp1 = lastline+1
" call Decho("..depscript<".depscript.">")
" found a "GetLatestVimScripts: # #" line in the script;
" check if its already in the datafile by searching backwards from llp1,
" the (prior to reading in the plugin script) last line plus one of the GetLatestVimScripts.dat file,
" for the script-id with no wrapping allowed.
let curline = line(".")
let noai_script = substitute(depscript,'\s*:AutoInstall:\s*','','e')
exe llp1
let srchline = search('^\s*'.depscriptid.'\s\+\d\+\s\+.*$','bW')
if srchline == 0
" this second search is taken when, for example, a 0 0 scriptname is to be skipped over
let srchline= search('\<'.noai_script.'\>','bW')
endif
" call Decho("..noai_script<".noai_script."> depscriptid#".depscriptid." srchline#".srchline." curline#".line(".")." lastline#".lastline)
if srchline == 0
" found a new script to permanently include in the datafile
let keep_rega = @a
let @a = substitute(getline(curline),'^"\s\+GetLatestVimScripts:\s\+','','')
echomsg "Appending <".@a."> to ".datafile." for ".depscript
" call Decho("..Appending <".@a."> to ".datafile." for ".depscript)
exe lastline."put a"
let @a = keep_rega
let lastline = llp1
let curline = curline + 1
let foundscript = foundscript + 1
" else " Decho
" call Decho("..found <".noai_script."> (already in datafile at line#".srchline.")")
endif
let curline = curline + 1
exe curline
endwhile
" llp1: last line plus one
let llp1= lastline + 1
" call Decho(".deleting lines: ".llp1.",$d")
exe "silent! ".llp1.",$d"
endfor
" call Decho("--- end dependency checking loop --- foundscript=".foundscript)
" call Decho(" ")
" call Dredir("BUFFER TEST (GetLatestVimScripts 1)","ls!")
if foundscript == 0
setlocal nomod
endif
" --------------------------------------------------------------------
" Check on out-of-date scripts using GetLatest/GetLatestVimScripts.dat
" --------------------------------------------------------------------
" call Decho("begin: checking out-of-date scripts using datafile<".datafile.">")
setlocal lz
1
" /^-----/,$g/^\s*\d/call Decho(getline("."))
1
/^-----/,$g/^\s*\d/call s:GetOneScript()
" call Decho("--- end out-of-date checking --- ")
" Final report (an echomsg)
try
silent! ?^-------?
catch /^Vim\%((\a\+)\)\=:E114/
" call Dret("GetLatestVimScripts : nothing done!")
return
endtry
exe "norm! kz\<CR>"
redraw!
let s:msg = ""
if s:downloads == 1
let s:msg = "Downloaded one updated script to <".datadir.">"
elseif s:downloads == 2
let s:msg= "Downloaded two updated scripts to <".datadir.">"
elseif s:downloads > 1
let s:msg= "Downloaded ".s:downloads." updated scripts to <".datadir.">"
else
let s:msg= "Everything was already current"
endif
if s:downerrors > 0
let s:msg= s:msg." (".s:downerrors." downloading errors)"
endif
echomsg s:msg
" save the file
if &mod
silent! w!
endif
q
" restore events and current directory
exe "cd ".fnameescape(substitute(origdir,'\','/','ge'))
let &ei = eikeep
let &hls = hlskeep
let &acd = acdkeep
setlocal nolz
" call Dredir("BUFFER TEST (GetLatestVimScripts 2)","ls!")
" call Dret("GetLatestVimScripts : did ".s:downloads." downloads")
endfun
" ---------------------------------------------------------------------
" GetOneScript: (Get Latest Vim Script) this function operates {{{1
" on the current line, interpreting two numbers and text as
" ScriptID, SourceID, and Filename.
" It downloads any scripts that have newer versions from vim.sourceforge.net.
fun! s:GetOneScript(...)
" call Dfunc("GetOneScript()")
" set options to allow progress to be shown on screen
let rega= @a
let t_ti= &t_ti
let t_te= &t_te
let rs = &rs
set t_ti= t_te= nors
" put current line on top-of-screen and interpret it into
" a script identifer : used to obtain webpage
" source identifier : used to identify current version
" and an associated comment: used to report on what's being considered
if a:0 >= 3
let scriptid = a:1
let srcid = a:2
let fname = a:3
let cmmnt = ""
" call Decho("scriptid<".scriptid.">")
" call Decho("srcid <".srcid.">")
" call Decho("fname <".fname.">")
else
let curline = getline(".")
if curline =~ '^\s*#'
let @a= rega
" call Dret("GetOneScript : skipping a pure comment line")
return
endif
let parsepat = '^\s*\(\d\+\)\s\+\(\d\+\)\s\+\(.\{-}\)\(\s*#.*\)\=$'
try
let scriptid = substitute(curline,parsepat,'\1','e')
catch /^Vim\%((\a\+)\)\=:E486/
let scriptid= 0
endtry
try
let srcid = substitute(curline,parsepat,'\2','e')
catch /^Vim\%((\a\+)\)\=:E486/
let srcid= 0
endtry
try
let fname= substitute(curline,parsepat,'\3','e')
catch /^Vim\%((\a\+)\)\=:E486/
let fname= ""
endtry
try
let cmmnt= substitute(curline,parsepat,'\4','e')
catch /^Vim\%((\a\+)\)\=:E486/
let cmmnt= ""
endtry
" call Decho("curline <".curline.">")
" call Decho("parsepat<".parsepat.">")
" call Decho("scriptid<".scriptid.">")
" call Decho("srcid <".srcid.">")
" call Decho("fname <".fname.">")
endif
" plugin author protection from downloading his/her own scripts atop their latest work
if scriptid == 0 || srcid == 0
" When looking for :AutoInstall: lines, skip scripts that have 0 0 scriptname
let @a= rega
" call Dret("GetOneScript : skipping a scriptid==srcid==0 line")
return
endif
let doautoinstall= 0
if fname =~ ":AutoInstall:"
" call Decho("case AutoInstall: fname<".fname.">")
let aicmmnt= substitute(fname,'\s\+:AutoInstall:\s\+',' ','')
" call Decho("aicmmnt<".aicmmnt."> s:autoinstall=".s:autoinstall)
if s:autoinstall != ""
let doautoinstall = g:GetLatestVimScripts_allowautoinstall
endif
else
let aicmmnt= fname
endif
" call Decho("aicmmnt<".aicmmnt.">: doautoinstall=".doautoinstall)
exe "norm z\<CR>"
redraw!
" call Decho('considering <'.aicmmnt.'> scriptid='.scriptid.' srcid='.srcid)
echo 'considering <'.aicmmnt.'> scriptid='.scriptid.' srcid='.srcid
" grab a copy of the plugin's vim.sourceforge.net webpage
let scriptaddr = 'http://vim.sourceforge.net/script.php?script_id='.scriptid
let tmpfile = tempname()
let v:errmsg = ""
" make up to three tries at downloading the description
let itry= 1
while itry <= 3
" call Decho(".try#".itry." to download description of <".aicmmnt."> with addr=".scriptaddr)
if has("win32") || has("win16") || has("win95")
" call Decho(".new|exe silent r!".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".shellescape(tmpfile).' '.shellescape(scriptaddr)."|bw!")
new|exe "silent r!".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".shellescape(tmpfile).' '.shellescape(scriptaddr)|bw!
else
" call Decho(".exe silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".shellescape(tmpfile)." ".shellescape(scriptaddr))
exe "silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".shellescape(tmpfile)." ".shellescape(scriptaddr)
endif
if itry == 1
exe "silent vsplit ".fnameescape(tmpfile)
else
silent! e %
endif
setlocal bh=wipe
" find the latest source-id in the plugin's webpage
silent! 1
let findpkg= search('Click on the package to download','W')
if findpkg > 0
break
endif
let itry= itry + 1
endwhile
" call Decho(" --- end downloading tries while loop --- itry=".itry)
" testing: did finding "Click on the package..." fail?
if findpkg == 0 || itry >= 4
silent q!
call delete(tmpfile)
" restore options
let &t_ti = t_ti
let &t_te = t_te
let &rs = rs
let s:downerrors = s:downerrors + 1
" call Decho("***warning*** couldn'".'t find "Click on the package..." in description page for <'.aicmmnt.">")
echomsg "***warning*** couldn'".'t find "Click on the package..." in description page for <'.aicmmnt.">"
" call Dret("GetOneScript : srch for /Click on the package/ failed")
let @a= rega
return
endif
" call Decho('found "Click on the package to download"')
let findsrcid= search('src_id=','W')
if findsrcid == 0
silent q!
call delete(tmpfile)
" restore options
let &t_ti = t_ti
let &t_te = t_te
let &rs = rs
let s:downerrors = s:downerrors + 1
" call Decho("***warning*** couldn'".'t find "src_id=" in description page for <'.aicmmnt.">")
echomsg "***warning*** couldn'".'t find "src_id=" in description page for <'.aicmmnt.">"
let @a= rega
" call Dret("GetOneScript : srch for /src_id/ failed")
return
endif
" call Decho('found "src_id=" in description page')
let srcidpat = '^\s*<td class.*src_id=\(\d\+\)">\([^<]\+\)<.*$'
let latestsrcid= substitute(getline("."),srcidpat,'\1','')
let sname = substitute(getline("."),srcidpat,'\2','') " script name actually downloaded
" call Decho("srcidpat<".srcidpat."> latestsrcid<".latestsrcid."> sname<".sname.">")
silent q!
call delete(tmpfile)
" convert the strings-of-numbers into numbers
let srcid = srcid + 0
let latestsrcid = latestsrcid + 0
" call Decho("srcid=".srcid." latestsrcid=".latestsrcid." sname<".sname.">")
" has the plugin's most-recent srcid increased, which indicates that it has been updated
if latestsrcid > srcid
" call Decho("[latestsrcid=".latestsrcid."] <= [srcid=".srcid."]: need to update <".sname.">")
let s:downloads= s:downloads + 1
if sname == bufname("%")
" GetLatestVimScript has to be careful about downloading itself
let sname= "NEW_".sname
endif
" -----------------------------------------------------------------------------
" the plugin has been updated since we last obtained it, so download a new copy
" -----------------------------------------------------------------------------
" call Decho(".downloading new <".sname.">")
echomsg ".downloading new <".sname.">"
if has("win32") || has("win16") || has("win95")
" call Decho(".new|exe silent r!".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".shellescape(sname)." ".shellescape('http://vim.sourceforge.net/scripts/download_script.php?src_id='.latestsrcid)."|q")
new|exe "silent r!".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".shellescape(sname)." ".shellescape('http://vim.sourceforge.net/scripts/download_script.php?src_id='.latestsrcid)|q
else
" call Decho(".exe silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".shellescape(sname)." ".shellescape('http://vim.sourceforge.net/scripts/download_script.php?src_id='))
exe "silent !".g:GetLatestVimScripts_wget." ".g:GetLatestVimScripts_options." ".shellescape(sname)." ".shellescape('http://vim.sourceforge.net/scripts/download_script.php?src_id=').latestsrcid
endif
" --------------------------------------------------------------------------
" AutoInstall: only if doautoinstall has been requested by the plugin itself
" --------------------------------------------------------------------------
" call Decho("checking if plugin requested autoinstall: doautoinstall=".doautoinstall)
if doautoinstall
" call Decho(" ")
" call Decho("Autoinstall: getcwd<".getcwd()."> filereadable(".sname.")=".filereadable(sname))
if filereadable(sname)
" call Decho("<".sname."> is readable")
" call Decho("exe silent !".g:GetLatestVimScripts_mv." ".shellescape(sname)." ".shellescape(s:autoinstall))
exe "silent !".g:GetLatestVimScripts_mv." ".shellescape(sname)." ".shellescape(s:autoinstall)
let curdir = fnameescape(substitute(getcwd(),'\','/','ge'))
let installdir= curdir."/Installed"
if !isdirectory(installdir)
call mkdir(installdir)
endif
" call Decho("curdir<".curdir."> installdir<".installdir.">")
" call Decho("exe cd ".fnameescape(s:autoinstall))
exe "cd ".fnameescape(s:autoinstall)
" determine target directory for moves
let firstdir= substitute(&rtp,',.*$','','')
let pname = substitute(sname,'\..*','.vim','')
" call Decho("determine tgtdir: is <".firstdir.'/AsNeeded/'.pname." readable?")
if filereadable(firstdir.'/AsNeeded/'.pname)
let tgtdir= "AsNeeded"
else
let tgtdir= "plugin"
endif
" call Decho("tgtdir<".tgtdir."> pname<".pname.">")
" decompress
if sname =~ '\.bz2$'
" call Decho("decompress: attempt to bunzip2 ".sname)
exe "silent !bunzip2 ".shellescape(sname)
let sname= substitute(sname,'\.bz2$','','')
" call Decho("decompress: new sname<".sname."> after bunzip2")
elseif sname =~ '\.gz$'
" call Decho("decompress: attempt to gunzip ".sname)
exe "silent !gunzip ".shellescape(sname)
let sname= substitute(sname,'\.gz$','','')
" call Decho("decompress: new sname<".sname."> after gunzip")
elseif sname =~ '\.xz$'
" call Decho("decompress: attempt to unxz ".sname)
exe "silent !unxz ".shellescape(sname)
let sname= substitute(sname,'\.xz$','','')
" call Decho("decompress: new sname<".sname."> after unxz")
else
" call Decho("no decompression needed")
endif
" distribute archive(.zip, .tar, .vba) contents
if sname =~ '\.zip$'
" call Decho("dearchive: attempt to unzip ".sname)
exe "silent !unzip -o ".shellescape(sname)
elseif sname =~ '\.tar$'
" call Decho("dearchive: attempt to untar ".sname)
exe "silent !tar -xvf ".shellescape(sname)
elseif sname =~ '\.vba$'
" call Decho("dearchive: attempt to handle a vimball: ".sname)
silent 1split
if exists("g:vimball_home")
let oldvimballhome= g:vimball_home
endif
let g:vimball_home= s:autoinstall
exe "silent e ".fnameescape(sname)
silent so %
silent q
if exists("oldvimballhome")
let g:vimball_home= oldvimballhome
else
unlet g:vimball_home
endif
else
" call Decho("no dearchiving needed")
endif
" ---------------------------------------------
" move plugin to plugin/ or AsNeeded/ directory
" ---------------------------------------------
if sname =~ '.vim$'
" call Decho("dearchive: attempt to simply move ".sname." to ".tgtdir)
exe "silent !".g:GetLatestVimScripts_mv." ".shellescape(sname)." ".tgtdir
else
" call Decho("dearchive: move <".sname."> to installdir<".installdir.">")
exe "silent !".g:GetLatestVimScripts_mv." ".shellescape(sname)." ".installdir
endif
if tgtdir != "plugin"
" call Decho("exe silent !".g:GetLatestVimScripts_mv." plugin/".shellescape(pname)." ".tgtdir)
exe "silent !".g:GetLatestVimScripts_mv." plugin/".shellescape(pname)." ".tgtdir
endif
" helptags step
let docdir= substitute(&rtp,',.*','','e')."/doc"
" call Decho("helptags: docdir<".docdir.">")
exe "helptags ".fnameescape(docdir)
exe "cd ".fnameescape(curdir)
endif
if fname !~ ':AutoInstall:'
let modline=scriptid." ".latestsrcid." :AutoInstall: ".fname.cmmnt
else
let modline=scriptid." ".latestsrcid." ".fname.cmmnt
endif
else
let modline=scriptid." ".latestsrcid." ".fname.cmmnt
endif
" update the data in the <GetLatestVimScripts.dat> file
call setline(line("."),modline)
" call Decho("update data in ".expand("%")."#".line(".").": modline<".modline.">")
" else " Decho
" call Decho("[latestsrcid=".latestsrcid."] <= [srcid=".srcid."], no need to update")
endif
" restore options
let &t_ti = t_ti
let &t_te = t_te
let &rs = rs
let @a = rega
" call Dredir("BUFFER TEST (GetOneScript)","ls!")
" call Dret("GetOneScript")
endfun
" ---------------------------------------------------------------------
" Restore Options: {{{1
let &cpo= s:keepcpo
unlet s:keepcpo
" ---------------------------------------------------------------------
" Modelines: {{{1
" vim: ts=8 sts=2 fdm=marker nowrap