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:
@ -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 --")
|
||||
|
@ -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
@ -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)
|
||||
|
||||
|
||||
|
@ -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')
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
650
vim/autoload/getscript.vim
Normal 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
|
Reference in New Issue
Block a user