From 4873c64f28d6d82e224c4cb8e732ce62386f45d9 Mon Sep 17 00:00:00 2001 From: Akelge Date: Thu, 17 Jan 2013 12:18:17 +0000 Subject: [PATCH] Added GetLatestScript update plugin and updated all plugins --- vim/.VimballRecord | 5 +- vim/GetLatest/GetLatestVimScripts.dat | 12 + vim/GetLatest/GetLatestVimScripts.dist | 18 + vim/autoload/Align.vim | 341 +- vim/autoload/AlignMaps.vim | 203 +- vim/autoload/conque_term.vim | 684 ++-- vim/autoload/conque_term/conque.py | 515 ++- vim/autoload/conque_term/conque_globals.py | 156 +- vim/autoload/conque_term/conque_screen.py | 181 +- vim/autoload/conque_term/conque_sole.py | 329 +- .../conque_term/conque_sole_communicator.py | 46 +- .../conque_term/conque_sole_shared_memory.py | 114 +- .../conque_term/conque_sole_subprocess.py | 305 +- .../conque_term/conque_sole_wrapper.py | 146 +- vim/autoload/conque_term/conque_subprocess.py | 97 +- vim/autoload/conque_term/conque_win32_util.py | 99 +- vim/autoload/getscript.vim | 650 +++ vim/colors/faded-black.vim | 89 + vim/doc/Align.txt | 289 +- vim/doc/NERD_commenter.txt | 265 +- vim/doc/NERD_tree.txt | 400 +- vim/doc/cecutil.txt | 204 + vim/doc/conque_term.txt | 384 +- vim/doc/pi_getscript.txt | 461 +++ vim/doc/tags | 103 +- vim/doc/vcscommand.txt | 31 +- vim/nerdtree_plugin/exec_menuitem.vim | 41 + vim/nerdtree_plugin/fs_menu.vim | 224 ++ vim/plugin/AlignMapsPlugin.vim | 69 +- vim/plugin/AlignPlugin.vim | 4 +- vim/plugin/NERD_commenter.vim | 1332 +++--- vim/plugin/NERD_tree.vim | 1729 ++++---- vim/plugin/cecutil.vim | 482 +++ vim/plugin/conque_term.vim | 86 +- vim/plugin/getscriptPlugin.vim | 38 + vim/plugin/pydoc.vim | 78 - vim/plugin/python_pydoc.vim | 196 + vim/plugin/taglist.vim | 3577 ++++++++++++----- vim/plugin/vcsbzr.vim | 38 +- vim/plugin/vcscommand.vim | 521 ++- vim/plugin/vcscvs.vim | 91 +- vim/plugin/vcsgit.vim | 46 +- vim/plugin/vcshg.vim | 51 +- vim/plugin/vcssvk.vim | 30 +- vim/plugin/vcssvn.vim | 68 +- vim/syntax/conque_term.vim | 6 +- vim/syntax/cvsannotate.vim | 45 + vim/syntax/gitannotate.vim | 44 + vim/syntax/hgannotate.vim | 40 + vim/syntax/nerdtree.vim | 88 + vim/syntax/svkannotate.vim | 42 + vim/syntax/svnannotate.vim | 40 + vim/syntax/vcscommit.vim | 2 +- vim/vimrc | 6 +- 54 files changed, 10380 insertions(+), 4761 deletions(-) create mode 100644 vim/GetLatest/GetLatestVimScripts.dat create mode 100644 vim/GetLatest/GetLatestVimScripts.dist create mode 100644 vim/autoload/getscript.vim create mode 100644 vim/colors/faded-black.vim create mode 100644 vim/doc/cecutil.txt create mode 100644 vim/doc/pi_getscript.txt create mode 100644 vim/nerdtree_plugin/exec_menuitem.vim create mode 100644 vim/nerdtree_plugin/fs_menu.vim create mode 100644 vim/plugin/cecutil.vim create mode 100644 vim/plugin/getscriptPlugin.vim delete mode 100644 vim/plugin/pydoc.vim create mode 100644 vim/plugin/python_pydoc.vim create mode 100644 vim/syntax/cvsannotate.vim create mode 100644 vim/syntax/gitannotate.vim create mode 100644 vim/syntax/hgannotate.vim create mode 100644 vim/syntax/nerdtree.vim create mode 100644 vim/syntax/svkannotate.vim create mode 100644 vim/syntax/svnannotate.vim diff --git a/vim/.VimballRecord b/vim/.VimballRecord index f7f97b5..078df91 100644 --- a/vim/.VimballRecord +++ b/vim/.VimballRecord @@ -1,4 +1,7 @@ -textformat.vba: call delete('/Users/andre/.vim/autoload/textformat.vim')|call delete('/Users/andre/.vim/doc/textformat.txt')|call delete('/Users/andre/.vim/plugin/textformat.vim') conque_2.0.vba: call delete('/Users/andre/.vim/doc/conque_term.txt')|call delete('/Users/andre/.vim/syntax/conque_term.vim')|call delete('/Users/andre/.vim/autoload/conque_term/conque_screen.py')|call delete('/Users/andre/.vim/autoload/conque_term/conque_win32_util.py')|call delete('/Users/andre/.vim/autoload/conque_term/conque_sole_shared_memory.py')|call delete('/Users/andre/.vim/autoload/conque_term/conque.py')|call delete('/Users/andre/.vim/autoload/conque_term/conque_sole_wrapper.py')|call delete('/Users/andre/.vim/autoload/conque_term/conque_sole_communicator.py')|call delete('/Users/andre/.vim/autoload/conque_term/conque_sole.py')|call delete('/Users/andre/.vim/autoload/conque_term/conque_globals.py')|call delete('/Users/andre/.vim/autoload/conque_term/conque_subprocess.py')|call delete('/Users/andre/.vim/autoload/conque_term/conque_sole_subprocess.py')|call delete('/Users/andre/.vim/autoload/conque_term.vim')|call delete('/Users/andre/.vim/plugin/conque_term.vim') +conqueterm_2.2.vmb: call delete('/Users/andre/.vim/autoload/conque_term.vim')|call delete('/Users/andre/.vim/autoload/conque_term/conque_globals.py')|call delete('/Users/andre/.vim/autoload/conque_term/conque.py')|call delete('/Users/andre/.vim/autoload/conque_term/conque_screen.py')|call delete('/Users/andre/.vim/autoload/conque_term/conque_sole_communicator.py')|call delete('/Users/andre/.vim/autoload/conque_term/conque_sole.py')|call delete('/Users/andre/.vim/autoload/conque_term/conque_sole_shared_memory.py')|call delete('/Users/andre/.vim/autoload/conque_term/conque_sole_subprocess.py')|call delete('/Users/andre/.vim/autoload/conque_term/conque_sole_wrapper.py')|call delete('/Users/andre/.vim/autoload/conque_term/conque_subprocess.py')|call delete('/Users/andre/.vim/autoload/conque_term/conque_win32_util.py')|call delete('/Users/andre/.vim/doc/conque_term.txt')|call delete('/Users/andre/.vim/plugin/conque_term.vim')|call delete('/Users/andre/.vim/syntax/conque_term.vim') Align.vba: call delete('/Users/andre/.vim/plugin/AlignPlugin.vim')|call delete('/Users/andre/.vim/plugin/AlignMapsPlugin.vim')|call delete('/Users/andre/.vim/plugin/cecutil.vim')|call delete('/Users/andre/.vim/doc/Align.txt')|call delete('/Users/andre/.vim/autoload/Align.vim')|call delete('/Users/andre/.vim/autoload/AlignMaps.vim') +cecutil.vba: call delete('/Users/andre/.vim/plugin/cecutil.vim')|call delete('/Users/andre/.vim/doc/cecutil.txt') +getscript.vba: call delete('/Users/andre/.vim/plugin/getscriptPlugin.vim')|call delete('/Users/andre/.vim/autoload/getscript.vim')|call delete('/Users/andre/.vim/GetLatest/GetLatestVimScripts.dist')|call delete('/Users/andre/.vim/doc/pi_getscript.txt') +textformat.vba: call delete('/Users/andre/.vim/autoload/textformat.vim')|call delete('/Users/andre/.vim/doc/textformat.txt')|call delete('/Users/andre/.vim/plugin/textformat.vim') open_terminal.vba: call delete('/Users/andre/.vim/plugin/open_terminal.vim')|call delete('/Users/andre/.vim/doc/open_terminal.txt') diff --git a/vim/GetLatest/GetLatestVimScripts.dat b/vim/GetLatest/GetLatestVimScripts.dat new file mode 100644 index 0000000..2972490 --- /dev/null +++ b/vim/GetLatest/GetLatestVimScripts.dat @@ -0,0 +1,12 @@ +ScriptID SourceID Filename +-------------------------- +910 18164 :AutoInstall: pydoc.vim +2771 16279 :AutoInstall: conque_term.vim +294 18148 :AutoInstall: Align.vim +1066 7618 :AutoInstall: cecutil.vim +642 15781 :AutoInstall: getscript.vim +2324 9247 :AutoInstall: TextFormat +1658 17123 :AutoInstall: NERD_tree.vim +1218 14455 :AutoInstall: NERD_commenter.vim +90 17031 :AutoInstall: vcscommand.vim +2896 11941 :AutoInstall: open_terminal.vim diff --git a/vim/GetLatest/GetLatestVimScripts.dist b/vim/GetLatest/GetLatestVimScripts.dist new file mode 100644 index 0000000..4745fc8 --- /dev/null +++ b/vim/GetLatest/GetLatestVimScripts.dist @@ -0,0 +1,18 @@ +ScriptID SourceID Filename +-------------------------- +294 1 Align.vim +302 2 AnsiEsc.vim +122 3 astronaut.vim +104 4 blockhl.vim +120 5 decho.vim + 40 6 DrawIt.tar.gz +451 7 EasyAccents.vim +195 8 engspchk.vim +642 9 GetLatestVimScripts.vim +489 10 Manpageview.vim +551 11 Mines.vim +514 12 mrswin.vim +670 13 visincr.vim +628 14 SeeTab.vim +508 15 ZoomWin.vim +877 16 gvcolor.vim diff --git a/vim/autoload/Align.vim b/vim/autoload/Align.vim index bce3542..e393584 100644 --- a/vim/autoload/Align.vim +++ b/vim/autoload/Align.vim @@ -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 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 == "\" - 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 --") diff --git a/vim/autoload/AlignMaps.vim b/vim/autoload/AlignMaps.vim index ace2de8..9b0f3bc 100644 --- a/vim/autoload/AlignMaps.vim +++ b/vim/autoload/AlignMaps.vim @@ -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 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! ' + keepj norm! ' 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/==/\="\\"/ge - 'a,'zs/\([!<>:]\)=/\=submatch(1)."\"/ge - norm g'zk + keepj 'a,'zs/\s\+\([*/+\-%|&\~^]\==\)/ \1/e + keepj 'a,'zs@ \+\([*/+\-%|&\~^]\)=@\1=@ge + keepj 'a,'zs/==/\="\\"/ge + keepj 'a,'zs/\([!<>:]\)=/\=submatch(1)."\"/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\h" + exe "sil! keepj norm! `y\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\\" + exe "keepj norm! i\\" 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).";\" +" 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).";\" +" 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 diff --git a/vim/autoload/conque_term.vim b/vim/autoload/conque_term.vim index a0b6790..856b97b 100644 --- a/vim/autoload/conque_term.vim +++ b/vim/autoload/conque_term.vim @@ -1,11 +1,11 @@ " FILE: autoload/conque_term.vim {{{ " AUTHOR: Nico Raffo " 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 " @@ -29,26 +29,50 @@ " }}} " ********************************************************************************************************** -" **** CROSS-TERMINAL SETTINGS ***************************************************************************** +" **** GLOBAL INITIALIZATION ******************************************************************************* " ********************************************************************************************************** " {{{ -" path to this file -let s:scriptfile = expand("") +" load plugin file if it hasn't already been loaded (e.g. conque_term#foo() is used in .vimrc) +if !exists('g:ConqueTerm_Loaded') + runtime! plugin/conque_term.vim +endif + +" path to conque install directories let s:scriptdir = expand(":h") . '/' let s:scriptdirpy = expand(":h") . '/conque_term/' -" Extra key codes -let s:input_extra = [] +" global list of terminal instances +let s:term_obj = {'idx': 1, 'var': '', 'is_buffer': 1, 'active': 1, 'buffer_name': '', 'command': ''} +let g:ConqueTerm_Terminals = {} -let s:term_obj = { 'idx' : 1, 'var' : '', 'is_buffer' : 1, 'active' : 1, 'buffer_name' : '' } -let s:terminals = {} +" global lists of registered functions +let s:hooks = { 'after_startup': [], 'buffer_enter': [], 'buffer_leave': [], 'after_keymap': [] } +" required for session support +if g:ConqueTerm_SessionSupport == 1 + set sessionoptions+=globals + try + sil! let s:saved_terminals = eval(g:ConqueTerm_TerminalsString) + catch + let s:saved_terminals = {} + endtry +endif + +" more session support +let g:ConqueTerm_TerminalsString = '' + +" init terminal counter +let g:ConqueTerm_Idx = 0 + +" we clobber this value later let s:save_updatetime = &updatetime +" have we called the init() function yet? let s:initialized = 0 + " }}} " ********************************************************************************************************** @@ -57,6 +81,7 @@ let s:initialized = 0 " {{{ +" Display various error messages function! conque_term#fail(feature) " {{{ " create a new buffer @@ -103,7 +128,7 @@ function! conque_term#fail(feature) " {{{ call append('$', "") call append('$', "Conque needs to know the full path to python.exe on Windows systems. By default, ") call append('$', "Conque will check your system path as well as the most common installation path ") - call append('$', "C:\\PythonXX\\. To fix this error either:") + call append('$', "C:\\PythonXX\\python.exe. To fix this error either:") call append('$', "") call append('$', "Set the g:ConqueTerm_PyExe option in your .vimrc. E.g.") call append('$', " let g:ConqueTerm_PyExe = 'C:\Program Files\Python27\python.exe'") @@ -126,6 +151,7 @@ function! conque_term#fail(feature) " {{{ endfunction " }}} +" Go through various system checks before attempting to launch conque function! conque_term#dependency_check() " {{{ " don't recheck the second time 'round @@ -133,18 +159,18 @@ function! conque_term#dependency_check() " {{{ return 1 endif - " choose a python version and define a string unicoding function + " choose a python version let s:py = '' if g:ConqueTerm_PyVersion == 3 - let s:pytest = 'python3' + let pytest = 'python3' else - let s:pytest = 'python' + let pytest = 'python' let g:ConqueTerm_PyVersion = 2 endif - " first the requested version - if has(s:pytest) - if s:pytest == 'python3' + " first test the requested version + if has(pytest) + if pytest == 'python3' let s:py = 'py3' else let s:py = 'py' @@ -152,16 +178,16 @@ function! conque_term#dependency_check() " {{{ " otherwise use the other version else - let s:py_alternate = 5 - g:ConqueTerm_PyVersion - if s:py_alternate == 3 - let s:pytest = 'python3' + let py_alternate = 5 - g:ConqueTerm_PyVersion + if py_alternate == 3 + let pytest = 'python3' else - let s:pytest = 'python' + let pytest = 'python' endif - if has(s:pytest) - echohl WarningMsg | echomsg "Python " . g:ConqueTerm_PyVersion . " interface is not installed, using Python " . s:py_alternate . " instead" | echohl None - let g:ConqueTerm_PyVersion = s:py_alternate - if s:pytest == 'python3' + if has(pytest) + echohl WarningMsg | echomsg "Python " . g:ConqueTerm_PyVersion . " interface is not installed, using Python " . py_alternate . " instead" | echohl None + let g:ConqueTerm_PyVersion = py_alternate + if pytest == 'python3' let s:py = 'py3' else let s:py = 'py' @@ -177,15 +203,15 @@ function! conque_term#dependency_check() " {{{ " quick and dirty platform declaration if has('unix') == 1 - let s:platform = 'nix' - sil exe s:py . " CONQUE_PLATFORM = 'nix'" + let s:platform = 'unix' + sil exe s:py . " CONQUE_PLATFORM = 'unix'" else - let s:platform = 'dos' - sil exe s:py . " CONQUE_PLATFORM = 'dos'" + let s:platform = 'windows' + sil exe s:py . " CONQUE_PLATFORM = 'windows'" endif " if we're using Windows, make sure ctypes is available - if s:platform == 'dos' + if s:platform == 'windows' try sil exe s:py . " import ctypes" catch @@ -195,7 +221,7 @@ function! conque_term#dependency_check() " {{{ endif " if we're using Windows, make sure we can finde python executable - if s:platform == 'dos' && conque_term#find_python_exe() == '' + if s:platform == 'windows' && conque_term#find_python_exe() == '' call conque_term#fail('python_exe') return 0 endif @@ -209,9 +235,23 @@ function! conque_term#dependency_check() " {{{ if line =~ '^ ' || line =~ '^--' || line =~ 'matchparen' continue endif - echohl WarningMsg | echomsg "Warning: Global CursorHoldI and CursorMovedI autocommands may cause ConqueTerm to run slowly." | echohl None + if g:ConqueTerm_StartMessages + echohl WarningMsg | echomsg "Warning: Global CursorHoldI and CursorMovedI autocommands may cause ConqueTerm to run slowly." | echohl None + endif endfor + " check for compatible mode + if &compatible == 1 + echohl WarningMsg | echomsg "Warning: Conque may not function normally in 'compatible' mode." | echohl None + endif + + " check for fast mode + if g:ConqueTerm_FastMode + sil exe s:py . " CONQUE_FAST_MODE = True" + else + sil exe s:py . " CONQUE_FAST_MODE = False" + endif + " if we're all good, load python files call conque_term#load_python() @@ -221,6 +261,47 @@ endfunction " }}} " }}} +" ********************************************************************************************************** +" **** STARTUP MESSAGES ************************************************************************************ +" ********************************************************************************************************** + +" {{{ +"if g:ConqueTerm_StartMessages +" let msg_file = s:scriptdirpy . 'version.vim' +" let msg_show = 1 +" let msg_ct = 1 +" +" " we can write to conque_term directory +" if filewritable(s:scriptdirpy) == 2 +" +" if filewritable(msg_file) +" +" " read current message file +" try +" silent execute "source " . msg_file +" if exists('g:ConqueTerm_MsgCt') && exists('g:ConqueTerm_MsgVer') +" if g:ConqueTerm_MsgVer == g:ConqueTerm_Version && g:ConqueTerm_MsgCt > 2 +" let msg_show = 0 +" else +" let msg_ct = g:ConqueTerm_MsgCt + 1 +" endif +" endif +" catch +" endtry +" endif +" +" " update message file +" if msg_show +" let file_contents = ['let g:ConqueTerm_MsgCt = ' . msg_ct, 'let g:ConqueTerm_MsgVer = ' . g:ConqueTerm_Version] +" call writefile(file_contents, msg_file) +" endif +" endif +" +" " save our final decision +" let g:ConqueTerm_StartMessages = msg_show +"endif +" }}} + " ********************************************************************************************************** " **** WINDOWS VK CODES ************************************************************************************ " ********************************************************************************************************** @@ -243,6 +324,7 @@ let s:windows_vk = { \ 'VK_DELETE' : 46, \ 'VK_DIVIDE' : 111, \ 'VK_DOWN' : 40, +\ 'VK_DOWN_CTL' : '40;1024', \ 'VK_END' : 35, \ 'VK_EREOF' : 249, \ 'VK_ESCAPE' : 27, @@ -285,6 +367,7 @@ let s:windows_vk = { \ 'VK_LBUTTON' : 1, \ 'VK_LCONTROL' : 162, \ 'VK_LEFT' : 37, +\ 'VK_LEFT_CTL' : '37;1024', \ 'VK_LMENU' : 164, \ 'VK_LSHIFT' : 160, \ 'VK_LWIN' : 91, @@ -320,6 +403,7 @@ let s:windows_vk = { \ 'VK_RCONTROL' : 163, \ 'VK_RETURN' : 13, \ 'VK_RIGHT' : 39, +\ 'VK_RIGHT_CTL' : '39;1024', \ 'VK_RMENU' : 165, \ 'VK_RSHIFT' : 161, \ 'VK_RWIN' : 92, @@ -332,6 +416,7 @@ let s:windows_vk = { \ 'VK_SUBTRACT' : 109, \ 'VK_TAB' : 9, \ 'VK_UP' : 38, +\ 'VK_UP_CTL' : '38;1024', \ 'VK_VOLUME_DOWN' : 174, \ 'VK_VOLUME_MUTE' : 173, \ 'VK_VOLUME_UP' : 175, @@ -350,43 +435,40 @@ let s:windows_vk = { " launch conque function! conque_term#open(...) "{{{ let command = get(a:000, 0, '') - let hooks = get(a:000, 1, []) + let vim_startup_commands = get(a:000, 1, []) let return_to_current = get(a:000, 2, 0) let is_buffer = get(a:000, 3, 1) " dependency check - if conque_term#dependency_check() == 0 + if !conque_term#dependency_check() return 0 endif " switch to buffer if needed if is_buffer && return_to_current let save_sb = &switchbuf - - "use an agressive sb option sil set switchbuf=usetab - - " current buffer name let current_buffer = bufname("%") endif " bare minimum validation if s:py == '' - echohl WarningMsg | echomsg "Conque requires the Python interface to be installed" | echohl None + echohl WarningMsg | echomsg "Conque requires the Python interface to be installed. See :help ConqueTerm for more information." | echohl None return 0 endif if empty(command) - echohl WarningMsg | echomsg "No command found" | echohl None + echohl WarningMsg | echomsg "Invalid usage: no program path given. Use :ConqueTerm YOUR PROGRAM, e.g. :ConqueTerm ipython" | echohl None return 0 else - let l:cargs = split(command, '[^\\]\@<=\s') - let l:cargs[0] = substitute(l:cargs[0], '\\ ', ' ', 'g') - if !executable(l:cargs[0]) - echohl WarningMsg | echomsg "Not an executable: " . l:cargs[0] | echohl None + let cmd_args = split(command, '[^\\]\@<=\s') + let cmd_args[0] = substitute(cmd_args[0], '\\ ', ' ', 'g') + if !executable(cmd_args[0]) + echohl WarningMsg | echomsg "Not an executable: " . cmd_args[0] | echohl None return 0 endif endif + " initialize global identifiers let g:ConqueTerm_Idx += 1 let g:ConqueTerm_Var = 'ConqueTerm_' . g:ConqueTerm_Idx let g:ConqueTerm_BufName = substitute(command, ' ', '\\ ', 'g') . "\\ -\\ " . g:ConqueTerm_Idx @@ -394,49 +476,58 @@ function! conque_term#open(...) "{{{ " initialize global mappings if needed call conque_term#init() - " set buffer window options + " set Vim buffer window options if is_buffer - call conque_term#set_buffer_settings(command, hooks) + call conque_term#set_buffer_settings(command, vim_startup_commands) let b:ConqueTerm_Idx = g:ConqueTerm_Idx let b:ConqueTerm_Var = g:ConqueTerm_Var endif - " save handle - let t_obj = conque_term#create_terminal_object(g:ConqueTerm_Idx, is_buffer, g:ConqueTerm_BufName) - let s:terminals[g:ConqueTerm_Idx] = t_obj + " save terminal instance + let t_obj = conque_term#create_terminal_object(g:ConqueTerm_Idx, is_buffer, g:ConqueTerm_BufName, command) + let g:ConqueTerm_Terminals[g:ConqueTerm_Idx] = t_obj + + " required for session support + let g:ConqueTerm_TerminalsString = string(g:ConqueTerm_Terminals) " open command try - let l:config = '{"color":' . string(g:ConqueTerm_Color) . ',"TERM":"' . g:ConqueTerm_TERM . '"}' - if s:platform == 'nix' + let options = {} + let options["TERM"] = g:ConqueTerm_TERM + let options["CODE_PAGE"] = g:ConqueTerm_CodePage + let options["color"] = g:ConqueTerm_Color + let options["offset"] = 0 " g:ConqueTerm_StartMessages * 10 + + if s:platform == 'unix' execute s:py . ' ' . g:ConqueTerm_Var . ' = Conque()' - execute s:py . ' ' . g:ConqueTerm_Var . ".open('" . conque_term#python_escape(command) . "', " . l:config . ")" + execute s:py . ' ' . g:ConqueTerm_Var . ".open()" else " find python.exe and communicator - let py_exe = conque_term#python_escape(conque_term#find_python_exe()) - let py_vim = conque_term#python_escape(s:scriptdirpy . 'conque_sole_communicator.py') - if py_exe == '' - return 0 - endif + let py_exe = conque_term#find_python_exe() + let py_vim = s:scriptdirpy . 'conque_sole_communicator.py' execute s:py . ' ' . g:ConqueTerm_Var . ' = ConqueSole()' - execute s:py . ' ' . g:ConqueTerm_Var . ".open('" . conque_term#python_escape(command) . "', " . l:config . ", '" . py_exe . "', '" . py_vim . "')" + execute s:py . ' ' . g:ConqueTerm_Var . ".open()" - "call conque_term#init_conceal_color() + if g:ConqueTerm_ColorMode == 'conceal' + call conque_term#init_conceal_color() + endif endif catch echohl WarningMsg | echomsg "An error occurred: " . command | echohl None - return + return 0 endtry - " set buffer mappings and auto commands + " set key mappings and auto commands if is_buffer call conque_term#set_mappings('start') endif + " call user defined functions + call conque_term#call_hooks('after_startup', t_obj) + " switch to buffer if needed if is_buffer && return_to_current - " jump back to code buffer sil exe ":sb " . current_buffer sil exe ":set switchbuf=" . save_sb elseif is_buffer @@ -444,6 +535,7 @@ function! conque_term#open(...) "{{{ endif return t_obj + endfunction "}}} " open(), but no buffer @@ -459,20 +551,16 @@ function! conque_term#subprocess(command) " {{{ endfunction " }}} " set buffer options -function! conque_term#set_buffer_settings(command, pre_hooks) "{{{ +function! conque_term#set_buffer_settings(command, vim_startup_commands) "{{{ " optional hooks to execute, e.g. 'split' - for h in a:pre_hooks + for h in a:vim_startup_commands sil exe h endfor sil exe 'edit ++enc=utf-8 ' . g:ConqueTerm_BufName - " showcmd gets altered by nocompatible - let sc_save = &showcmd - " buffer settings setlocal fileencoding=utf-8 " file encoding, even tho there's no file - setlocal nocompatible " conque won't work in compatible mode setlocal nopaste " conque won't work in paste mode setlocal buftype=nofile " this buffer is not a file, you can't save it setlocal nonumber " hide line numbers @@ -492,21 +580,23 @@ function! conque_term#set_buffer_settings(command, pre_hooks) "{{{ setlocal conceallevel=3 setlocal concealcursor=nic endif + if g:ConqueTerm_ReadUnfocused + set cpoptions+=I " Don't remove autoindent when moving cursor up and down + endif setfiletype conque_term " useful sil exe "setlocal syntax=" . g:ConqueTerm_Syntax - " reset showcmd - if sc_save - set showcmd - else - set noshowcmd - endif - " temporary global settings go in here call conque_term#on_focus(1) endfunction " }}} +" send normal character key press to terminal +function! conque_term#key_press() "{{{ + sil exe s:py . ' ' . b:ConqueTerm_Var . ".write_buffered_ord(" . char2nr(v:char) . ")" + sil let v:char = '' +endfunction " }}} + " set key mappings and auto commands function! conque_term#set_mappings(action) "{{{ @@ -532,27 +622,27 @@ function! conque_term#set_mappings(action) "{{{ " auto commands {{{ if l:action == 'stop' - execute 'autocmd! ' . b:ConqueTerm_Var + sil exe 'autocmd! ' . b:ConqueTerm_Var else - execute 'augroup ' . b:ConqueTerm_Var + sil exe 'augroup ' . b:ConqueTerm_Var " handle unexpected closing of shell, passes HUP to parent and all child processes - execute 'autocmd ' . b:ConqueTerm_Var . ' BufUnload ' . s:py . ' ' . b:ConqueTerm_Var . '.close()' + sil exe 'autocmd ' . b:ConqueTerm_Var . ' BufUnload ' . s:py . ' ' . b:ConqueTerm_Var . '.close()' " check for resized/scrolled buffer when entering buffer - execute 'autocmd ' . b:ConqueTerm_Var . ' BufEnter ' . s:py . ' ' . b:ConqueTerm_Var . '.update_window_size()' - execute 'autocmd ' . b:ConqueTerm_Var . ' VimResized ' . s:py . ' ' . b:ConqueTerm_Var . '.update_window_size()' + sil exe 'autocmd ' . b:ConqueTerm_Var . ' BufEnter ' . s:py . ' ' . b:ConqueTerm_Var . '.update_window_size()' + sil exe 'autocmd ' . b:ConqueTerm_Var . ' VimResized ' . s:py . ' ' . b:ConqueTerm_Var . '.update_window_size()' " set/reset updatetime on entering/exiting buffer - execute 'autocmd ' . b:ConqueTerm_Var . ' BufEnter call conque_term#on_focus()' - execute 'autocmd ' . b:ConqueTerm_Var . ' BufLeave call conque_term#on_blur()' + sil exe 'autocmd ' . b:ConqueTerm_Var . ' BufEnter call conque_term#on_focus()' + sil exe 'autocmd ' . b:ConqueTerm_Var . ' BufLeave call conque_term#on_blur()' " reposition cursor when going into insert mode - execute 'autocmd ' . b:ConqueTerm_Var . ' InsertEnter ' . s:py . ' ' . b:ConqueTerm_Var . '.insert_enter()' + sil exe 'autocmd ' . b:ConqueTerm_Var . ' InsertEnter ' . s:py . ' ' . b:ConqueTerm_Var . '.insert_enter()' " poll for more output - sil execute 'autocmd ' . b:ConqueTerm_Var . ' CursorHoldI ' . s:py . ' ' . b:ConqueTerm_Var . '.auto_read()' + sil exe 'autocmd ' . b:ConqueTerm_Var . ' CursorHoldI ' . s:py . ' ' . b:ConqueTerm_Var . '.auto_read()' endif " }}} @@ -563,15 +653,15 @@ function! conque_term#set_mappings(action) "{{{ continue endif if l:action == 'start' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(chr(' . c . '))' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_ord(' . c . ')' else sil exe 'i' . map_modifier . 'map ' endif endfor " bonus mapping: send in normal mode to terminal as well for panic interrupts if l:action == 'start' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(chr(3))' - sil exe 'n' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(chr(3))' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_ord(3)' + sil exe 'n' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_ord(3)' else sil exe 'i' . map_modifier . 'map ' sil exe 'n' . map_modifier . 'map ' @@ -581,7 +671,7 @@ function! conque_term#set_mappings(action) "{{{ if !exists('g:ConqueTerm_EscKey') || g:ConqueTerm_EscKey == '' " use to send to terminal if l:action == 'start' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(chr(27))' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_ord(27)' else sil exe 'i' . map_modifier . 'map ' endif @@ -589,7 +679,7 @@ function! conque_term#set_mappings(action) "{{{ " use to send to terminal if l:action == 'start' sil exe 'i' . map_modifier . 'map ' . g:ConqueTerm_EscKey . ' ' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(chr(27))' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_ord(27)' else sil exe 'i' . map_modifier . 'map ' . g:ConqueTerm_EscKey sil exe 'i' . map_modifier . 'map ' @@ -598,61 +688,67 @@ function! conque_term#set_mappings(action) "{{{ " Map in insert mode if exists('g:ConqueTerm_CWInsert') && g:ConqueTerm_CWInsert == 1 - inoremap j j - inoremap k k - inoremap h h - inoremap l l - inoremap w w + inoremap endif " }}} - " map ASCII 33-127 {{{ - for i in range(33, 127) - " - if i == 124 - if l:action == 'start' - sil exe "i" . map_modifier . "map :" . s:py . ' ' . b:ConqueTerm_Var . ".write(chr(124))" - else - sil exe "i" . map_modifier . "map " + " map 33 and beyond {{{ + if exists('##InsertCharPre') && g:ConqueTerm_InsertCharPre == 1 + if l:action == 'start' + autocmd InsertCharPre call conque_term#key_press() + else + autocmd! InsertCharPre + endif + else + for i in range(33, 127) + " + if i == 124 + if l:action == 'start' + sil exe "i" . map_modifier . "map :" . s:py . ' ' . b:ConqueTerm_Var . ".write_ord(124)" + else + sil exe "i" . map_modifier . "map " + endif + continue endif - continue - endif - if l:action == 'start' - sil exe "i" . map_modifier . "map " . nr2char(i) . " :" . s:py . ' ' . b:ConqueTerm_Var . ".write(chr(" . i . "))" - else - sil exe "i" . map_modifier . "map " . nr2char(i) - endif - endfor - " }}} - - " map Latin-1 128-255 {{{ - for i in range(128, 255) - if l:action == 'start' - sil exe "i" . map_modifier . "map " . nr2char(i) . " :" . s:py . ' ' . b:ConqueTerm_Var . ".write_latin1(chr(" . i . "))" - else - sil exe "i" . map_modifier . "map " . nr2char(i) - endif - endfor + if l:action == 'start' + sil exe "i" . map_modifier . "map " . nr2char(i) . " :" . s:py . ' ' . b:ConqueTerm_Var . ".write_ord(" . i . ")" + else + sil exe "i" . map_modifier . "map " . nr2char(i) + endif + endfor + endif " }}} " Special keys {{{ if l:action == 'start' - if s:platform == 'nix' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write("\x08")' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(" ")' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write("\x1b[A")' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write("\x1b[B")' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write("\x1b[C")' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write("\x1b[D")' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write("\x1bOH")' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write("\x1bOF")' + if s:platform == 'unix' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x08"))' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u(" "))' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x08"))' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u(" "))' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1b[A"))' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1b[B"))' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1b[C"))' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1b[D"))' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1bOH"))' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1bOF"))' else - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write("\x08")' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(" ")' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x08"))' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u(" "))' + + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x08"))' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u(" "))' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk(' . s:windows_vk.VK_UP . ')' sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk(' . s:windows_vk.VK_DOWN . ')' sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk(' . s:windows_vk.VK_RIGHT . ')' sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk(' . s:windows_vk.VK_LEFT . ')' + + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk("' . s:windows_vk.VK_UP_CTL . '")' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk("' . s:windows_vk.VK_DOWN_CTL . '")' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk("' . s:windows_vk.VK_RIGHT_CTL . '")' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk("' . s:windows_vk.VK_LEFT_CTL . '")' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk(' . s:windows_vk.VK_DELETE . ')' sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk(' . s:windows_vk.VK_HOME . ')' sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk(' . s:windows_vk.VK_END . ')' @@ -660,6 +756,8 @@ function! conque_term#set_mappings(action) "{{{ else sil exe 'i' . map_modifier . 'map ' sil exe 'i' . map_modifier . 'map ' + sil exe 'i' . map_modifier . 'map ' + sil exe 'i' . map_modifier . 'map ' sil exe 'i' . map_modifier . 'map ' sil exe 'i' . map_modifier . 'map ' sil exe 'i' . map_modifier . 'map ' @@ -672,19 +770,19 @@ function! conque_term#set_mappings(action) "{{{ " keys {{{ if g:ConqueTerm_SendFunctionKeys if l:action == 'start' - if s:platform == 'nix' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write("\x1b[11~")' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write("\x1b[12~")' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write("1b[13~")' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write("\x1b[14~")' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write("\x1b[15~")' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write("\x1b[17~")' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write("\x1b[18~")' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write("\x1b[19~")' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write("\x1b[20~")' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write("\x1b[21~")' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write("\x1b[23~")' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write("\x1b[24~")' + if s:platform == 'unix' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1b[11~"))' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1b[12~"))' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("1b[13~"))' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1b[14~"))' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1b[15~"))' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1b[17~"))' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1b[18~"))' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1b[19~"))' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1b[20~"))' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1b[21~"))' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1b[23~"))' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write(u("\x1b[24~"))' else sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk(' . s:windows_vk.VK_F1 . ')' sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_vk(' . s:windows_vk.VK_F2 . ')' @@ -716,18 +814,24 @@ function! conque_term#set_mappings(action) "{{{ endif " }}} - " send selected text into conque {{{ + " various global mappings {{{ + " don't overwrite existing mappings if l:action == 'start' - sil exe 'v' . map_modifier . 'map ' . g:ConqueTerm_SendVisKey . ' :call conque_term#send_selected(visualmode())' + if maparg(g:ConqueTerm_SendVisKey, 'v') == '' + sil exe 'v' . map_modifier . 'map ' . g:ConqueTerm_SendVisKey . ' :call conque_term#send_selected(visualmode())' + endif + if maparg(g:ConqueTerm_SendFileKey, 'n') == '' + sil exe 'n' . map_modifier . 'map ' . g:ConqueTerm_SendFileKey . ' :call conque_term#send_file()' + endif endif " }}} " remap paste keys {{{ if l:action == 'start' - sil exe 'n' . map_modifier . 'map p :' . s:py . ' ' . b:ConqueTerm_Var . '.write(vim.eval("@@"))a' - sil exe 'n' . map_modifier . 'map P :' . s:py . ' ' . b:ConqueTerm_Var . '.write(vim.eval("@@"))a' - sil exe 'n' . map_modifier . 'map ]p :' . s:py . ' ' . b:ConqueTerm_Var . '.write(vim.eval("@@"))a' - sil exe 'n' . map_modifier . 'map [p :' . s:py . ' ' . b:ConqueTerm_Var . '.write(vim.eval("@@"))a' + sil exe 'n' . map_modifier . 'map p :' . s:py . ' ' . b:ConqueTerm_Var . '.write_expr("@@")a' + sil exe 'n' . map_modifier . 'map P :' . s:py . ' ' . b:ConqueTerm_Var . '.write_expr("@@")a' + sil exe 'n' . map_modifier . 'map ]p :' . s:py . ' ' . b:ConqueTerm_Var . '.write_expr("@@")a' + sil exe 'n' . map_modifier . 'map [p :' . s:py . ' ' . b:ConqueTerm_Var . '.write_expr("@@")a' else sil exe 'n' . map_modifier . 'map p' sil exe 'n' . map_modifier . 'map P' @@ -736,8 +840,8 @@ function! conque_term#set_mappings(action) "{{{ endif if has('gui_running') == 1 if l:action == 'start' - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . ".write(vim.eval('@+'))a" - sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . ".write(vim.eval('@+'))a" + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_expr("@+")a' + sil exe 'i' . map_modifier . 'map :' . s:py . ' ' . b:ConqueTerm_Var . '.write_expr("@+")a' else sil exe 'i' . map_modifier . 'map ' sil exe 'i' . map_modifier . 'map ' @@ -763,16 +867,6 @@ function! conque_term#set_mappings(action) "{{{ endif " }}} - " user defined mappings {{{ - for [map_from, map_to] in s:input_extra - if l:action == 'start' - sil exe 'i' . map_modifier . 'map ' . map_from . ' :' . s:py . ' ' . b:ConqueTerm_Var . ".write('" . conque_term#python_escape(map_to) . "')" - else - sil exe 'i' . map_modifier . 'map ' . map_from - endif - endfor - " }}} - " set conque as on or off {{{ if l:action == 'start' let b:conque_on = 1 @@ -787,6 +881,11 @@ function! conque_term#set_mappings(action) "{{{ endif " }}} + " call user defined functions + if l:action == 'start' + call conque_term#call_hooks('after_keymap', conque_term#get_instance()) + endif + endfunction " }}} " Initialize global mappings. Should only be called once per Vim session @@ -797,6 +896,8 @@ function! conque_term#init() " {{{ endif augroup ConqueTerm + + " abort any remaining running terminals when Vim exits autocmd ConqueTerm VimLeave * call conque_term#close_all() " read more output when this isn't the current buffer @@ -813,14 +914,14 @@ function! conque_term#read_all(insert_mode) "{{{ for i in range(1, g:ConqueTerm_Idx) try - if !s:terminals[i].active + if !g:ConqueTerm_Terminals[i].active continue endif - let output = s:terminals[i].read(1) + let output = g:ConqueTerm_Terminals[i].read(1) - if !s:terminals[i].is_buffer && exists('*s:terminals[i].callback') - call s:terminals[i].callback(output) + if !g:ConqueTerm_Terminals[i].is_buffer && exists('*g:ConqueTerm_Terminals[i].callback') + call g:ConqueTerm_Terminals[i].callback(output) endif catch " probably a deleted buffer @@ -829,7 +930,14 @@ function! conque_term#read_all(insert_mode) "{{{ " restart updatetime if a:insert_mode - call feedkeys("\f\e", "n") + "call feedkeys("\f\e", "n") + let p = getpos('.') + if p[1] == 1 + sil exe 'call feedkeys("\\", "n")' + else + sil exe 'call feedkeys("\\", "n")' + endif + call setpos('.', p) else call feedkeys("f\e", "n") endif @@ -841,7 +949,7 @@ function! conque_term#close_all() "{{{ for i in range(1, g:ConqueTerm_Idx) try - call s:terminals[i].close() + call g:ConqueTerm_Terminals[i].close() catch " probably a deleted buffer endtry @@ -849,16 +957,6 @@ function! conque_term#close_all() "{{{ endfunction "}}} -" util function to add enough \s to pass a string to python -function! conque_term#python_escape(input) "{{{ - let l:cleaned = a:input - let l:cleaned = substitute(l:cleaned, '\\', '\\\\', 'g') - let l:cleaned = substitute(l:cleaned, '\n', '\\n', 'g') - let l:cleaned = substitute(l:cleaned, '\r', '\\r', 'g') - let l:cleaned = substitute(l:cleaned, "'", "\\\\'", 'g') - return l:cleaned -endfunction "}}} - " gets called when user enters conque buffer. " Useful for making temp changes to global config function! conque_term#on_focus(...) " {{{ @@ -879,10 +977,16 @@ function! conque_term#on_focus(...) " {{{ " set poll interval to 50ms set updatetime=50 + " resume subprocess fast polling if startup == 0 && exists('b:ConqueTerm_Var') sil exe s:py . ' ' . g:ConqueTerm_Var . '.resume()' endif + " call user defined functions + if startup == 0 + call conque_term#call_hooks('buffer_enter', conque_term#get_instance()) + endif + " if configured, go into insert mode if g:ConqueTerm_InsertOnEnter == 1 startinsert! @@ -898,6 +1002,7 @@ function! conque_term#on_blur() " {{{ NeoComplCacheUnlock endif + " turn off subprocess fast polling if exists('b:ConqueTerm_Var') sil exe s:py . ' ' . b:ConqueTerm_Var . '.idle()' endif @@ -912,6 +1017,10 @@ function! conque_term#on_blur() " {{{ else set updatetime=2000 endif + + " call user defined functions + call conque_term#call_hooks('buffer_leave', conque_term#get_instance()) + endfunction " }}} " bell event (^G) @@ -919,6 +1028,33 @@ function! conque_term#bell() " {{{ echohl WarningMsg | echomsg "BELL!" | echohl None endfunction " }}} +" register function to be called at conque events +function! conque_term#register_function(event, function_name) " {{{ + + if !has_key(s:hooks, a:event) + echomsg 'No such event: ' . a:event + return + endif + + if !exists('*' . a:function_name) + echomsg 'No such function: ' . a:function_name) + return + endif + + " register the function + call add(s:hooks[a:event], function(a:function_name)) + +endfunction " }}} + +" call hooks for an event +function! conque_term#call_hooks(event, t_obj) " {{{ + + for Fu in s:hooks[a:event] + call Fu(a:t_obj) + endfor + +endfunction " }}} + " }}} " ********************************************************************************************************** @@ -985,24 +1121,24 @@ function! conque_term#init_conceal_color() " {{{ syn region ConqueCCFfff matchgroup=ConqueConceal start="\esffff;" end="\eeffff;" concealends contains=ConqueCCBG " background colors, low intensity - syn region ConqueCCB000 matchgroup=ConqueConceal start="\esb000;" end="\eeb000;" concealends - syn region ConqueCCB00c matchgroup=ConqueConceal start="\esb00c;" end="\eeb00c;" concealends - syn region ConqueCCB0c0 matchgroup=ConqueConceal start="\esb0c0;" end="\eeb0c0;" concealends - syn region ConqueCCB0cc matchgroup=ConqueConceal start="\esb0cc;" end="\eeb0cc;" concealends - syn region ConqueCCBc00 matchgroup=ConqueConceal start="\esbc00;" end="\eebc00;" concealends - syn region ConqueCCBc0c matchgroup=ConqueConceal start="\esbc0c;" end="\eebc0c;" concealends - syn region ConqueCCBcc0 matchgroup=ConqueConceal start="\esbcc0;" end="\eebcc0;" concealends - syn region ConqueCCBccc matchgroup=ConqueConceal start="\esbccc;" end="\eebccc;" concealends + syn region ConqueCCB000 matchgroup=ConqueCCBG start="\esb000;" end="\eeb000;" concealends + syn region ConqueCCB00c matchgroup=ConqueCCBG start="\esb00c;" end="\eeb00c;" concealends + syn region ConqueCCB0c0 matchgroup=ConqueCCBG start="\esb0c0;" end="\eeb0c0;" concealends + syn region ConqueCCB0cc matchgroup=ConqueCCBG start="\esb0cc;" end="\eeb0cc;" concealends + syn region ConqueCCBc00 matchgroup=ConqueCCBG start="\esbc00;" end="\eebc00;" concealends + syn region ConqueCCBc0c matchgroup=ConqueCCBG start="\esbc0c;" end="\eebc0c;" concealends + syn region ConqueCCBcc0 matchgroup=ConqueCCBG start="\esbcc0;" end="\eebcc0;" concealends + syn region ConqueCCBccc matchgroup=ConqueCCBG start="\esbccc;" end="\eebccc;" concealends " background colors, high intensity - syn region ConqueCCB000 matchgroup=ConqueConceal start="\esb000;" end="\eeb000;" concealends - syn region ConqueCCB00f matchgroup=ConqueConceal start="\esb00f;" end="\eeb00f;" concealends - syn region ConqueCCB0f0 matchgroup=ConqueConceal start="\esb0f0;" end="\eeb0f0;" concealends - syn region ConqueCCB0ff matchgroup=ConqueConceal start="\esb0ff;" end="\eeb0ff;" concealends - syn region ConqueCCBf00 matchgroup=ConqueConceal start="\esbf00;" end="\eebf00;" concealends - syn region ConqueCCBf0f matchgroup=ConqueConceal start="\esbf0f;" end="\eebf0f;" concealends - syn region ConqueCCBff0 matchgroup=ConqueConceal start="\esbff0;" end="\eebff0;" concealends - syn region ConqueCCBfff matchgroup=ConqueConceal start="\esbfff;" end="\eebfff;" concealends + syn region ConqueCCB000 matchgroup=ConqueCCBG start="\esb000;" end="\eeb000;" concealends + syn region ConqueCCB00f matchgroup=ConqueCCBG start="\esb00f;" end="\eeb00f;" concealends + syn region ConqueCCB0f0 matchgroup=ConqueCCBG start="\esb0f0;" end="\eeb0f0;" concealends + syn region ConqueCCB0ff matchgroup=ConqueCCBG start="\esb0ff;" end="\eeb0ff;" concealends + syn region ConqueCCBf00 matchgroup=ConqueCCBG start="\esbf00;" end="\eebf00;" concealends + syn region ConqueCCBf0f matchgroup=ConqueCCBG start="\esbf0f;" end="\eebf0f;" concealends + syn region ConqueCCBff0 matchgroup=ConqueCCBG start="\esbff0;" end="\eebff0;" concealends + syn region ConqueCCBfff matchgroup=ConqueCCBG start="\esbfff;" end="\eebfff;" concealends """""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""""" @@ -1078,34 +1214,98 @@ endfunction " }}} " **** Add-on features ************************************************************************************* " ********************************************************************************************************** +" {{{ + " send selected text from another buffer function! conque_term#send_selected(type) "{{{ + + " get most recent/relevant terminal + let term = conque_term#get_instance() + + " shove visual text into @@ register let reg_save = @@ - - " save user's sb settings - let sb_save = &switchbuf - set switchbuf=usetab - - " yank current selection sil exe "normal! `<" . a:type . "`>y" - - " format yanked text let @@ = substitute(@@, '^[\r\n]*', '', '') let @@ = substitute(@@, '[\r\n]*$', '', '') + " go to terminal buffer + call term.focus() + " execute yanked text - sil exe ":sb " . g:ConqueTerm_BufName - sil exe s:py . ' ' . g:ConqueTerm_Var . '.paste_selection()' + call term.write(@@) " reset original values let @@ = reg_save - sil exe 'set switchbuf=' . sb_save " scroll buffer left startinsert! - normal 0zH + normal! 0zH + endfunction "}}} +function! conque_term#send_file() "{{{ + + let file_lines = readfile(expand('%:p')) + if type(file_lines) == 3 && len(file_lines) > 0 + let term = conque_term#get_instance() + call term.focus() + + for line in file_lines + call term.writeln(line) + endfor + else + echomsg 'Could not read file: ' . expand('%:p') + endif + +endfunction "}}} + + +function! conque_term#exec_file() "{{{ + + let current_file = expand('%:p') + if !executable(current_file) + echomsg "Could not run " . current_file . ". Not an executable." + return + endif + exe ':ConqueTermSplit ' . current_file + +endfunction "}}} + + +" called on SessionLoadPost event +function! conque_term#resume_session() " {{{ + if g:ConqueTerm_SessionSupport == 1 + + " make sure terminals exist + if !exists('s:saved_terminals') || type(s:saved_terminals) != 4 + return + endif + + " rebuild terminals + for idx in keys(s:saved_terminals) + + " don't recreate inactive terminals + if s:saved_terminals[idx].active == 0 + continue + endif + + " check we're in the right buffer + let bufname = substitute(s:saved_terminals[idx].buffer_name, '\', '', 'g') + if bufname != bufname("%") + continue + endif + + " reopen command + call conque_term#open(s:saved_terminals[idx].command) + + return + endfor + + endif +endfunction " }}} + +" }}} + " ********************************************************************************************************** " **** "API" functions ************************************************************************************* " ********************************************************************************************************** @@ -1113,17 +1313,39 @@ endfunction "}}} " See doc/conque_term.txt for full documentation {{{ " Write to a conque terminal buffer -function! s:term_obj.write(text) dict " {{{ +function! s:term_obj.write(...) dict " {{{ + + let text = get(a:000, 0, '') + let jump_to_buffer = get(a:000, 1, 0) " if we're not in terminal buffer, pass flag to not position the cursor - sil exe s:py . ' ' . self.var . '.write(vim.eval("a:text"), False, False)' + sil exe s:py . ' ' . self.var . '.write_expr("text", False, False)' + + " move cursor to conque buffer + if jump_to_buffer + call self.focus() + endif endfunction " }}} " same as write() but adds a newline -function! s:term_obj.writeln(text) dict " {{{ +function! s:term_obj.writeln(...) dict " {{{ - call self.write(a:text . "\r") + let text = get(a:000, 0, '') + let jump_to_buffer = get(a:000, 1, 0) + + call self.write(text . "\r", jump_to_buffer) + +endfunction " }}} + +" move cursor to terminal buffer +function! s:term_obj.focus() dict " {{{ + + let save_sb = &switchbuf + sil set switchbuf=usetab + exe 'sb ' . self.buffer_name + sil exe ":set switchbuf=" . save_sb + startinsert! endfunction " }}} @@ -1166,19 +1388,21 @@ endfunction " }}} " set output callback function! s:term_obj.set_callback(callback_func) dict " {{{ - let s:terminals[self.idx].callback = function(a:callback_func) + let g:ConqueTerm_Terminals[self.idx].callback = function(a:callback_func) endfunction " }}} " close subprocess with ABORT signal function! s:term_obj.close() dict " {{{ + " kill process try sil exe s:py . ' ' . self.var . '.abort()' catch " probably already dead endtry + " delete buffer if option is set if self.is_buffer call conque_term#set_mappings('stop') if exists('g:ConqueTerm_CloseOnEnd') && g:ConqueTerm_CloseOnEnd @@ -1187,6 +1411,12 @@ function! s:term_obj.close() dict " {{{ endif endif + " mark ourselves as inactive + let self.active = 0 + + " rebuild session options + let g:ConqueTerm_TerminalsString = string(g:ConqueTerm_Terminals) + endfunction " }}} " create a new terminal object @@ -1210,11 +1440,22 @@ function! conque_term#create_terminal_object(...) " {{{ " the buffer name let bname = get(a:000, 2, '') + " the command + let command = get(a:000, 3, '') + + " parse out the program name (not perfect) + let arg_split = split(command, '[^\\]\@<=\s') + let arg_split[0] = substitute(arg_split[0], '\\ ', ' ', 'g') + let slash_split = split(arg_split[0], '[/\\]') + let prg_name = substitute(slash_split[-1], '\(.*\)\..*', '\1', '') + let l:t_obj = copy(s:term_obj) let l:t_obj.is_buffer = is_buffer let l:t_obj.idx = buf_num let l:t_obj.buffer_name = bname let l:t_obj.var = pvar + let l:t_obj.command = command + let l:t_obj.program_name = prg_name return l:t_obj @@ -1226,7 +1467,7 @@ function! conque_term#get_instance(...) " {{{ " find conque buffer to update let buf_num = get(a:000, 0, 0) - if exists('s:terminals[buf_num]') + if exists('g:ConqueTerm_Terminals[buf_num]') elseif exists('b:ConqueTerm_Var') let buf_num = b:ConqueTerm_Idx @@ -1234,20 +1475,10 @@ function! conque_term#get_instance(...) " {{{ let buf_num = g:ConqueTerm_Idx endif - return s:terminals[buf_num] + return g:ConqueTerm_Terminals[buf_num] endfunction " }}} -" add a new default mapping -function! conque_term#imap(map_from, map_to) " {{{ - call add(s:input_extra, [a:map_from, a:map_to]) -endfunction " }}} - -" add a list of new default mappings -function! conque_term#imap_list(map_list) " {{{ - call extend(s:input_extra, a:map_list) -endfunction " }}} - " }}} " ********************************************************************************************************** @@ -1258,13 +1489,14 @@ function! conque_term#load_python() " {{{ exec s:py . "file " . s:scriptdirpy . "conque_globals.py" exec s:py . "file " . s:scriptdirpy . "conque.py" - exec s:py . "file " . s:scriptdirpy . "conque_screen.py" - exec s:py . "file " . s:scriptdirpy . "conque_subprocess.py" - if s:platform == 'dos' + if s:platform == 'windows' exec s:py . "file " . s:scriptdirpy . "conque_win32_util.py" exec s:py . "file " . s:scriptdirpy . "conque_sole_shared_memory.py" exec s:py . "file " . s:scriptdirpy . "conque_sole.py" exec s:py . "file " . s:scriptdirpy . "conque_sole_wrapper.py" + else + exec s:py . "file " . s:scriptdirpy . "conque_screen.py" + exec s:py . "file " . s:scriptdirpy . "conque_subprocess.py" endif endfunction " }}} diff --git a/vim/autoload/conque_term/conque.py b/vim/autoload/conque_term/conque.py index 6c7b2fc..08c92e4 100644 --- a/vim/autoload/conque_term/conque.py +++ b/vim/autoload/conque_term/conque.py @@ -1,11 +1,11 @@ -# FILE: autoload/conque_term/conque.py {{{ +# FILE: autoload/conque_term/conque.py # AUTHOR: Nico Raffo # 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) + + diff --git a/vim/autoload/conque_term/conque_globals.py b/vim/autoload/conque_term/conque_globals.py index dfc3707..d7a8c8f 100644 --- a/vim/autoload/conque_term/conque_globals.py +++ b/vim/autoload/conque_term/conque_globals.py @@ -1,11 +1,11 @@ -# FILE: autoload/conque_term/conque_globals.py {{{ +# FILE: autoload/conque_term/conque_globals.py # AUTHOR: Nico Raffo # 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') + + diff --git a/vim/autoload/conque_term/conque_screen.py b/vim/autoload/conque_term/conque_screen.py index a1eb4ee..40db616 100644 --- a/vim/autoload/conque_term/conque_screen.py +++ b/vim/autoload/conque_term/conque_screen.py @@ -1,11 +1,11 @@ -# FILE: autoload/conque_term/conque_screen.py {{{ +# FILE: autoload/conque_term/conque_screen.py # AUTHOR: Nico Raffo # 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 diff --git a/vim/autoload/conque_term/conque_sole.py b/vim/autoload/conque_term/conque_sole.py index d66078e..556aee9 100644 --- a/vim/autoload/conque_term/conque_sole.py +++ b/vim/autoload/conque_term/conque_sole.py @@ -1,11 +1,11 @@ -# FILE: autoload/conque_term/conque_sole.py {{{ +# FILE: autoload/conque_term/conque_sole.py # AUTHOR: Nico Raffo # 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 diff --git a/vim/autoload/conque_term/conque_sole_communicator.py b/vim/autoload/conque_term/conque_sole_communicator.py index 5c19ff3..e3f7db3 100644 --- a/vim/autoload/conque_term/conque_sole_communicator.py +++ b/vim/autoload/conque_term/conque_sole_communicator.py @@ -1,11 +1,11 @@ -# FILE: autoload/conque_term/conque_sole_communicator.py {{{ +# FILE: autoload/conque_term/conque_sole_communicator.py # AUTHOR: Nico Raffo # 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() diff --git a/vim/autoload/conque_term/conque_sole_shared_memory.py b/vim/autoload/conque_term/conque_sole_shared_memory.py index 32817ac..1d4ed3a 100644 --- a/vim/autoload/conque_term/conque_sole_shared_memory.py +++ b/vim/autoload/conque_term/conque_sole_shared_memory.py @@ -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 # 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 diff --git a/vim/autoload/conque_term/conque_sole_subprocess.py b/vim/autoload/conque_term/conque_sole_subprocess.py index 350a7df..0f205b6 100644 --- a/vim/autoload/conque_term/conque_sole_subprocess.py +++ b/vim/autoload/conque_term/conque_sole_subprocess.py @@ -1,11 +1,11 @@ -# FILE: autoload/conque_term/conque_sole_subprocess.py {{{ +# FILE: autoload/conque_term/conque_sole_subprocess.py # AUTHOR: Nico Raffo # 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 diff --git a/vim/autoload/conque_term/conque_sole_wrapper.py b/vim/autoload/conque_term/conque_sole_wrapper.py index 3d480c9..4e4816f 100644 --- a/vim/autoload/conque_term/conque_sole_wrapper.py +++ b/vim/autoload/conque_term/conque_sole_wrapper.py @@ -1,11 +1,11 @@ -# FILE: autoload/conque_term/conque_sole_wrapper.py {{{ +# FILE: autoload/conque_term/conque_sole_wrapper.py # AUTHOR: Nico Raffo # 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 diff --git a/vim/autoload/conque_term/conque_subprocess.py b/vim/autoload/conque_term/conque_subprocess.py index db2b93c..87d93c3 100644 --- a/vim/autoload/conque_term/conque_subprocess.py +++ b/vim/autoload/conque_term/conque_subprocess.py @@ -1,11 +1,11 @@ -# FILE: autoload/conque_term/conque_subprocess.py {{{ +# FILE: autoload/conque_term/conque_subprocess.py # AUTHOR: Nico Raffo # 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 diff --git a/vim/autoload/conque_term/conque_win32_util.py b/vim/autoload/conque_term/conque_win32_util.py index c11bdde..6ae7652 100644 --- a/vim/autoload/conque_term/conque_win32_util.py +++ b/vim/autoload/conque_term/conque_win32_util.py @@ -1,11 +1,11 @@ -# FILE: autoload/conque_term/conque_win32_util.py {{{ +# FILE: autoload/conque_term/conque_win32_util.py # AUTHOR: Nico Raffo # 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 + diff --git a/vim/autoload/getscript.vim b/vim/autoload/getscript.vim new file mode 100644 index 0000000..9e2a196 --- /dev/null +++ b/vim/autoload/getscript.vim @@ -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 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 =~ '\%(\\|\\)\%(\.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\" + 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\" + 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*\([^<]\+\)<.*$' + 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 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 diff --git a/vim/colors/faded-black.vim b/vim/colors/faded-black.vim new file mode 100644 index 0000000..37c945b --- /dev/null +++ b/vim/colors/faded-black.vim @@ -0,0 +1,89 @@ +" Vim color file +" Maintainer: John Kaul +" Created On: 2003 Mar 19 +" Last Change: 2013 Jan 16 + +" Notes: +" This started as a fadded version of of the 'Chocolate Liquor', but +" soon took on a life of its own. Easy on the eyes, but still has good +" contrast. I dont think there is any 'Chocolate Liquor' left in this +" file, but there is prolly an entry or two left in there somewhere. +" +" Only values that differ from defaults are specified. +" +" 01.07.05 update: Tweeked a few colors and added terminal colors. +" Please note that I didnt go thru the terminal colors very well. (I +" just added a few ''dif. then normal'' colors) If you use the terminal +" alot I would make an attempt to fix anything you dont like about this +" color scheme if I were you. :)~ Other than that, I just called it it +" good 'nuff. +" +" 01.16.13 update: Changed a few more colors (still havent looked at the +" terminal colors). +" +" I hope you enjoy... + +set background=dark +hi clear +if exists("syntax_on") + syntax reset +endif +let g:colors_name = "faded-black" + + +" Vim >= 7.0 specific colors +if version >= 700 + +hi CursorLine ctermbg=236 ctermfg=NONE guibg=#2d2d2d guifg=NONE term=NONE gui=NONE +hi CursorColumn ctermbg=236 ctermfg=NONE guibg=#2d2d2d guifg=NONE term=NONE gui=NONE +hi MatchParen ctermbg=237 ctermfg=157 guibg=#2f2f2f guifg=#d0ffc0 term=bold gui=bold +hi Pmenu ctermbg=238 ctermfg=255 guibg=#444444 guifg=#ffffff term=NONE gui=NONE +hi PmenuSel ctermbg=148 ctermfg=0 guibg=#b1d631 guifg=#000000 term=NONE gui=NONE + +endif + +" //-- Stuff --// +hi Cursor ctermbg=Red ctermfg=NONE guibg=#8b3a3a guifg=#e3e3e3 gui=NONE +hi Normal ctermbg=NONE ctermfg=LightGrey guibg=#03080F guifg=#958a73 gui=NONE +" hi Normal ctermbg=NONE ctermfg=LightGrey guibg=#03080F guifg=#a69d89 gui=NONE +" The text color between the above two are tough to decide; I leave it up to you. +hi NonText ctermbg=NONE ctermfg=Black guibg=#03080F guifg=#000030 gui=NONE +hi DiffDelete ctermbg=DarkRed ctermfg=White guibg=DarkRed guifg=White gui=NONE +hi DiffAdd ctermbg=DarkGreen ctermfg=White guibg=DarkGreen guifg=White gui=NONE +hi DiffText ctermbg=LightCyan ctermfg=Yellow guibg=Lightblue guifg=Yellow gui=NONE +hi DiffChange ctermbg=LightBlue ctermfg=White guibg=LightBlue3 guifg=White gui=NONE +hi Constant ctermbg=NONE ctermfg=Red guibg=NONE guifg=#872e30 gui=NONE +hi StatusLine ctermbg=DarkGrey ctermfg=Red guibg=DarkGrey guifg=LightRed gui=italic +hi StatusLineNC ctermbg=Darkgrey ctermfg=black guibg=DarkGrey guifg=Black gui=NONE +hi VertSplit ctermbg=NONE ctermfg=NONE guibg=NONE guifg=Grey gui=NONE +hi Visual ctermbg=DarkRed ctermfg=Red guibg=#6b6b6b guifg=#431818 term=reverse +hi Search ctermbg=NONE ctermfg=LightGrey guibg=#80363a guifg=#a69c89 gui=NONE +hi Label ctermbg=NONE ctermfg=NONE guibg=NONE guifg=#ffc0c0 gui=NONE +hi LineNr ctermbg=NONE ctermfg=Red guibg=NONE guifg=#A39274 gui=NONE + +" //-- Messages --// +hi MoreMsg ctermbg=NONE ctermfg=DarkGreen guibg=NONE guifg=SeaGreen term=bold,italic gui=bold +hi question ctermbg=NONE ctermfg=DarkGreen guibg=NONE guifg=SeaGreen term=standout gui=bold + +" //-- Syntax group --// +hi Comment ctermbg=NONE ctermfg=DarkGreen guibg=NONE guifg=#545f3a gui=italic +hi PreProc ctermbg=NONE ctermfg=NONE guibg=NONE guifg=#bbaccc gui=NONE +hi Statement ctermbg=NONE ctermfg=Yellow guibg=NONE guifg=#ab952b gui=NONE +hi Type ctermbg=NONE ctermfg=darkmagenta guibg=NONE guifg=#ba5bdb gui=NONE +hi Identifier ctermbg=NONE ctermfg=Yellow guibg=NONE guifg=#737d95 gui=NONE +hi Special ctermbg=NONE ctermfg=Green guibg=NONE guifg=#5b5646 gui=NONE +hi Todo ctermbg=NONE ctermfg=NONE guibg=NONE guifg=LightBlue gui=bold,italic +hi Number ctermbg=NONE ctermfg=NONE guibg=NONE guifg=lightblue gui=NONE +" +" Lisp stuff +hi lispAtomMark ctermbg=NONE ctermfg=cyan guifg=darkcyan guibg=NONE gui=NONE +hi lispNumber ctermbg=NONE ctermfg=DarkGreen guifg=lightblue guibg=NONE gui=NONE +" +" hi Constant +" hi Error +" hi Ignore +" hi Underlined + +" //-- Fold --// +hi Folded ctermbg=NONE ctermfg=NONE guibg=#001a33 guifg=#a69c89 gui=italic +hi FoldColumn ctermbg=NONE ctermfg=Yellow guibg=#6699CC guifg=#0000EE gui=NONE diff --git a/vim/doc/Align.txt b/vim/doc/Align.txt index c447372..b08eca3 100644 --- a/vim/doc/Align.txt +++ b/vim/doc/Align.txt @@ -1,8 +1,8 @@ -*align.txt* The Alignment Tool Mar 04, 2009 +*align.txt* The Alignment Tool Jun 18, 2012 -Author: Charles E. Campbell, Jr. +Author: Charles E. Campbell (remove NOSPAM from Campbell's email first) -Copyright: (c) 2004-2008 by Charles E. Campbell, Jr. *Align-copyright* +Copyright: (c) 2004-2012 by Charles E. Campbell *Align-copyright* The VIM LICENSE applies to Align.vim, AlignMaps.vim, and Align.txt (see |copyright|) except use "Align and AlignMaps" instead of "Vim" NO WARRANTY, EXPRESS OR IMPLIED. USE AT-YOUR-OWN-RISK. @@ -26,6 +26,7 @@ Copyright: (c) 2004-2008 by Charles E. Campbell, Jr. *Align-copyright* Temporary Settings.....: |alignctrl-m| Padding................: |alignctrl-p| |alignctrl-P| Current Options........: |alignctrl-settings| |alignctrl-| + Alignment Control Init...: |alignctrl-init| Alignment................: |align-align| 4. Alignment Maps...........: |align-maps| \a,....................: |alignmap-a,| @@ -91,6 +92,7 @@ Copyright: (c) 2004-2008 by Charles E. Campbell, Jr. *Align-copyright* || | | - skip this separator || || | | + re-use last justification method || || | | : treat rest of text as a field || +|| | | * use AlignSkip() function (to skip or not) || || | | || || | p1 | p### pad separator on left by # blanks || || | P1 | P### pad separator on right by # blanks || @@ -176,12 +178,14 @@ ALIGNMENT CONCEPTS *align-concept* *align-concepts* {{{2 < Note how each "=" sign is surrounded by a single space; the default padding is p1P1 (p1 means one space before the separator, and P1 means one space after it). If you wish to change the - padding, say to no padding, use (see |alignctrl-p|) > + padding, say, to no padding, use (see |alignctrl-p|) > + :AlignCtrl lp0P0 < Next, note how each field is left justified; that's what the "l" - (a small letter "ell") does. If right-justification of the fields - had been desired, an "r" could've been used: > + in the AlignCtrl parameters (a small letter "ell") does. If + right-justification of the fields had been desired, an "r" + could've been used: > :AlignCtrl r < yielding > x = y = z = 3; @@ -196,10 +200,10 @@ ALIGNMENT CONCEPTS *align-concept* *align-concepts* {{{2 justify, right justify, or center them, too (see |alignctrl-<|). Assume that for some reason a left-right-left-right-... justification - sequence was wished. This wish is simply achieved with > + sequence was desired. This wish is simply achieved with > :AlignCtrl lr :1,4Align = -< because the justification commands are considered to be "cylic"; ie. +< because the justification commands are considered to be "cyclic"; ie. lr is the same as lrlrlrlrlrlrlr... There's a lot more discussed under |alignctrl|; hopefully the examples @@ -261,7 +265,7 @@ ALIGNMENT COMMANDS *align-command* *align-commands* {{{2 < Also see |alignctrl-m| for a way to automatically do an AlignPop after an Align (primarily this is for maps). -ALIGNMENT OPTIONS *align-option* *align-options* {{{2 +ALIGNMENT OPTIONS *align-option* *align-options* *align-xstrlen* {{{2 *align-utf8* *align-utf* *align-codepoint* *align-strlen* *align-multibyte* For those of you who are using 2-byte (or more) characters such as are @@ -279,7 +283,7 @@ ALIGNMENT OPTIONS *align-option* *align-options* {{{2 vim compiled without multi-byte support $LANG is en_US.UTF-8 (assuming USA english) - Number of codepoints (Latin a + combining circumflex is two codepoints)~ + Number of codepoints (Latin a + combining circumflex are two codepoints)~ > let g:Align_xstrlen= 1 (default) < @@ -295,13 +299,20 @@ ALIGNMENT OPTIONS *align-option* *align-options* {{{2 > let g:Align_xstrlen= 3 < + User may specify a function to compute the string length~ +> + let g:Align_xstrlen= "strlen" +< This method will cause Align to call upon the named function returning + string length. it should resemble the |strlen()| function, taking one + argument (the string) for input and returning the string length. + By putting one of these settings into your <.vimrc>, Align will use an internal (interpreted) function to determine a string's length instead - of the Vim's built-in |strlen()| function. Since the function is + of Vim's built-in |strlen()| function. Since the function is interpreted, Align will run a bit slower but will handle such strings - correctly. The last setting (g:Align_xstrlen= 3) probably will run - the slowest but be the most accurate. (thanks to Tony Mechelynck for - these) + correctly. The last settings (g:Align_xstrlen= 3 and + g:Align_xstrlen="userfuncname") probably will run the slowest but be + the most accurate. (thanks to Tony Mechelynck for these) ALIGNMENT CONTROL *alignctrl* *align-control* {{{2 @@ -322,7 +333,7 @@ ALIGNMENT CONTROL *alignctrl* *align-control* {{{2 < where "ws" stands for "white space" such as blanks and/or tabs. - + SEPARATORS *alignctrl-separators* {{{3 As a result, separators may not have white space (tabs or blanks) on @@ -337,10 +348,11 @@ ALIGNMENT CONTROL *alignctrl* *align-control* {{{2 (ie. @), and then perform a substitute to revert the separators back to their desired condition (ie. s/@/ :: /g). - The Align#Align() function will first convert tabs over the region into - spaces and then apply alignment control. Except for initial white - space, white space surrounding the fields is ignored. One has three - options just for handling initial white space: + The Align#Align() function (which is invoked by the :Align command) + will first convert tabs over the region into spaces and then apply + alignment control. Except for initial white space, white space + surrounding the fields is ignored. One has three options just for + handling initial white space: --- *alignctrl-w* @@ -357,9 +369,9 @@ ALIGNMENT CONTROL *alignctrl* *align-control* {{{2 +------------------+---------------+-------------------+-----------------+ | Original | w option | W option | I option | +------------------+---------------+-------------------+-----------------+ - | a := baaa |a := baaa | a : = baaa | a := baaa | - | caaaa := deeee |caaaa := deeee | caaaa : = deeee| caaaa := deeee| - | ee := f |ee := f | ee : = f | ee := f | + | a := baaa |a := baaa | a := baaa | a := baaa | + | caaaa := deeee |caaaa := deeee | caaaa := deeee | caaaa := deeee| + | ee := f |ee := f | ee := f | ee := f | +------------------+---------------+-------------------+-----------------+ < The original has at least one leading white space on every line. @@ -397,17 +409,19 @@ ALIGNMENT CONTROL *alignctrl* *align-control* {{{2 cycle only consists of one character (the "l"). Every time left-justification is used for fields. AlignCtrl r : The = separator is repeatedly re-used, as the - cycle only consists of one character (the "l"). + cycle only consists of one character (the "r"). Every time right-justification is used for fields AlignCtrl lr: Again, the "=" separator is repeatedly re-used, but the fields are justified alternately between left and right. - Even more separator control is available. With "-+:": + Even more separator control is available! With "-+:": - - : skip treating the separator as a separator. *alignctrl--* - + : repeat use of the last "lrc" justification *alignctrl-+* - : : treat the rest of the line as a single field *alignctrl-:* + - : skip treating the separator as a separator. *alignctrl--* + + : repeat use of the last "lrc" justification *alignctrl-+* + : : treat the rest of the line as a single field *alignctrl-:* + * : like -, but only if g:AlignSkip() returns true *alignctrl-star* + (see |alignctrl-alignskip|) Example: More justification options: Align = > +------------+---------------+--------------------+---------------+ @@ -452,6 +466,35 @@ ALIGNMENT CONTROL *alignctrl* *align-control* {{{2 3rd separator only: AlignCtrl --l: etc. + *g:AlignSkip* + Align Skip Control *alignctrl-alignskip* + + The separator control '*' permits a function to decide whether or + not a character which matches the current separator pattern should + instead be skipped. + + 1. Define a function; example: > + + fun! AlignSkipString(lineno,indx) + let synid = synID(a:lineno,a:indx+1,1) + let synname = synIDattr(synIDtrans(synid),"name") + let ret= (synname == "String")? 1 : 0 + return ret + endfun +< + Input: lineno: current line number + indx : index to character; leftmost character + in the line has an indx of 0 (like |strpart()|) + Output: 0 : if separator is ok + 1 : skip separator like it was a '-' + + 2. Set up |g:AlignSkip| as a function reference (see |Funcref|): > + + let g:AlignSkip= function("AlignSkipString") +< + 3. Use * as a separator control where a separator potentially should + be skipped over. + --- *alignctrl-=* =C CYCLIC VS ALL-ACTIVE SEPARATORS *alignctrl-C* {{{3 @@ -465,8 +508,10 @@ ALIGNMENT CONTROL *alignctrl* *align-control* {{{2 constructed: > AlignCtrl ... pat1 pat2 pat3 +< becomes > \(pat1\|pat2\|pat3\) -< +< (ie. pat1 -or- pat2 -or- pat3; see |/bar|) + Each separator pattern is thus equivalent and simultaneously active. The cyclic separator AlignCtrl option stores a list of patterns, only one of which is active for each field at a time. @@ -606,12 +651,12 @@ ALIGNMENT CONTROL *alignctrl* *align-control* {{{2 |five= 6; |five = 6; |five = 6; | +----------------+------------------+----------------+ < - The first "Align =" aligned with all "="s, including that one in the - "skip=this" comment. + The first "Align =" aligned with all "="s, including the one in the + "/* skip=this */" comment. The second "Align =" had a AlignCtrl v-pattern which caused it to skip - (ignore) the "skip=this" line when aligning. - + (ignore) the "/* skip=this */" line when aligning. + To remove AlignCtrl's g and v patterns, use (as appropriate) > AlignCtrl g @@ -683,7 +728,7 @@ ALIGNMENT CONTROL *alignctrl* *align-control* {{{2 AlignCtrl......|alignctrl| qty............|align-concept| - AlignStyle.....|alignctrl--| |alignctrl-+| |alignctrl-:||alignctrl-c| + AlignStyle.....|alignctrl--| |alignctrl-+| |alignctrl-:| |alignctrl-c| Padding........|alignctrl-p| |alignctrl-P| One may get a string which can be fed back into AlignCtrl: > @@ -697,7 +742,19 @@ ALIGNMENT CONTROL *alignctrl* *align-control* {{{2 however: > :let alignctrl= Align#AlignCtrl("d") -< + + +ALIGNMENT CONTROL INITIALIZATION *alignctrl-init* *alignctrl-initialization* {{{2 + + If you'd like to have your own default AlignCtrl, you'll be wanting to + put it in a file such as: > + + $HOME/.vim/after/plugin/AlignPlugin.vim + +< Anything in that file would be sourced at startup, but after your + .vimrc and after $HOME/.vim/plugin/AlignPlugin.vim; hence, :Align + and :AlignCtrl will then be defined. + ALIGNMENT *align-align* {{{2 @@ -758,23 +815,31 @@ ALIGNMENT *align-align* {{{2 ============================================================================== 4. Alignment Maps *alignmaps* *align-maps* {{{1 - There are a number of maps using Align#AlignCtrl() and Align#Align() - in the file. This file may also be put into the - plugins subdirectory. Since AlignCtrl and Align supercede textab and - its file, the maps either have a leading "t" (for - "textab") or the more complicated ones an "a" (for "alignment") for - backwards compatibility. + There are a number of maps provided in the AlignMaps plugin which + depend upon the Align plugin. The maps provided by AlignMaps + typically start with a leading "t" (for the older "textab" program + which Align supercedes) or with an "a" for the more complicated + alignment maps. - The maps are shown below with a leading backslash (\). Actually, the - construct is used (see |mapleader|), so the maps' leading - kick-off character is easily customized. + The AlignMaps plugin, although provided in the vimball containing + Align.vim, is really a separate plugin (Align doesn't depend on + AlignMaps). Consequently, if you'd rather not have AlignMaps's + mappings, just use the *:AlignMapsClean* command to remove its + components. The :AlignMapsClean command does not remove any maps + generated by AlignMaps in the current instance of vim. - Furthermore, all AlignMapsPlugin.vim maps use the construct (see - ||and |usr_41.txt|). Hence, if one wishes to override the - mapping entirely, one may do that, too. As an example: > + The maps are shown below with a leading backslash (\). However, the + actual maps use the construct (see |mapleader|), so the maps' + leading kick-off character is easily customized. + + Furthermore, all the maps specified by the AlignMaps plugin use the + construct (see ||and |usr_41.txt|). Hence, if one wishes + to override the mapping(s) entirely, one may do that, too. As an + example: > map ACOM AM_acom -< would have \ACOM do what \acom previously did (assuming that the - mapleader has been left at its default value of a backslash). +< would have \ACOM do + what \acom previously did (assuming that the mapleader has been left + at its default value of a backslash). \a, : useful for breaking up comma-separated declarations prior to \adec |alignmap-a,| @@ -831,9 +896,9 @@ ALIGNMENT *align-align* {{{2 character "x" where "x" is: ,:<=@# |alignmap-T=| \m= : like \t= but aligns with %... style comments - The leading backslash is actually (see |mapleader| for how to - customize the leader to be whatever you like). These maps use the - package and are defined in the file. + The leading backslash is actually (see |mapleader| to learn + how to customize the leader to be whatever you like). These maps use + the package and are defined in the file. Although the maps use AlignCtrl options, they typically use the "m" option which pushes the options (AlignPush). The associated Align call which follows will then AlignPop the user's original options @@ -847,6 +912,18 @@ ALIGNMENT *align-align* {{{2 Alternatively, one may select the text with the "V" visual mode command. + If you want to use visual-block mode (ctrl-v), I suggest using + an AlignMap with the vis.vim plugin, available at either + + stable: http://vim.sourceforge.net/scripts/script.php?script_id=1195 + devel : http://mysite.verizon.net/astronaut/vim/index.html#VIS + + Use it with commands such as > + + ctrl-v (move) + :B norm \alignmap_sequence +< + ALIGNMENT MAP USE WITH MENUS~ One may use the mark-and-move style (ma, move, use the menu) or the visual mode style (use the V visual mode, move, then select @@ -862,7 +939,6 @@ ALIGNMENT *align-align* {{{2 must be included). COMPLEX ALIGNMENT MAP METHOD~ - For those complex alignment maps which do alignment on constructs (e.g. \acom, \adec, etc), a series of substitutes is used to insert "@" symbols in appropriate locations. Align#Align() is then used to @@ -934,7 +1010,7 @@ ALIGNMENT *align-align* {{{2 aa:=bb:=cc:=1; a:=b:=c:=1; aaa:=bbb:=ccc:=1; -< +< Bcomes: select the three assignment lines, then \a:= > aa := bb := cc := 1; a := b := c := 1; @@ -981,6 +1057,17 @@ ALIGNMENT *align-align* {{{2 Alignment Map Examples: \anum *alignmap-anum* {{{3 --------------------------- + First, note that the behavior of the \anum map depends on the existence + of either the vim variable > + g:alignmaps_usanumber +< or > + g:alignmaps_euronumber +< when AlignMaps is loaded. + + Essentially, "usa" numbers use "."s and "euro" numbers use ","s to + separate the integer from the fractional portion of a number. + "Usa" numbers are default. + Original: illustrates how to get numbers lined up > -1.234 .5678 -.901e-4 1.234 5.678 9.01e-4 @@ -1012,7 +1099,8 @@ ALIGNMENT *align-align* {{{2 12,34 56,78 90,1e-4 123,4 567,8 901,e-4 < - Becomes: Go to first line, ma. Go to last line, press \anum > + Becomes: (assuming g:alignmaps_euronumber exists) + Go to first line, ma. Go to last line, press \anum > -1,234 ,5678 -,901e-4 1,234 5,678 9,01e-4 12,34 56,78 90,1e-4 @@ -1022,9 +1110,10 @@ ALIGNMENT *align-align* {{{2 \aenum is provided to support European-style numbers \aunum is provided to support USA-style numbers - One may get \aenum behavior for \anum > + *g:alignmaps_usanumber* *g:alignmaps_euronumber* + One may get \aenum behavior for \anum by putting > let g:alignmaps_euronumber= 1 -< or \aunum behavior for \anum if one puts > +< or \aunum behavior for \anum by putting > let g:alignmaps_usanumber= 1 < in one's <.vimrc>. @@ -1311,21 +1400,48 @@ ALIGNMENT *align-align* {{{2 4. Alignment Tools' History *align-history* {{{1 ALIGN HISTORY {{{2 + 36 : May 20, 2009 * Previously, the "W" AlignCtrl setting, intended + to retain initial white space, did so by convert- + ing any leading tabs into an equivalent quantity + of blanks (using the current tabstop setting). + Align will now retain leading tabs. + Nov 24, 2009 * QArgSplitter() used split(), intending to split + on white space only. However, the \tab map + uses ctrl-o as a separator instead of tabs; the + split() function treated the ctrl-o as a whitespace + character, too. Solution: give split() an explicit + pattern matching blanks and tabs, only. \tab now + works again! + Jun 29, 2010 * included |g:AlignSkip| and |alignctrl-star| support + May 10, 2011 * if the range is only one line, then Align will + automatically grow the range to accommodate all + lines containing the first separator pattern + surrounding the current line. + Aug 05, 2011 * g:Align_xstrlen usage extended to permit users to + specify a function by name which computes string + length. + Oct 27, 2011 * (reported by Fco Javier) reported a problem with + the default s:Strlen() result; there was a missing + "let". Fixed. + Nov 10, 2011 * (Lewis Thompson) Align was doing "set noet" when + it should've been doing "setlocal noet". + Dec 22, 2011 * modifed s:Strlen() to use |strdisplaywidth()| when + g:Align_xstrlen is zero. 35 : Nov 02, 2008 * g:loaded_AlignPlugin testing to prevent re-loading - installed + installed Nov 19, 2008 * new sanity check for an AlignStyle of just ":" Jan 08, 2009 * save&restore of |'mod'| now done with local - variant + variant 34 : Jul 08, 2008 * using :AlignCtrl before entering any alignment - control commands was causing an error. + control commands was causing an error. 33 : Sep 20, 2007 * s:Strlen() introduced to support various ways - used to represent characters and their effects - on string lengths. See |align-strlen|. - * Align now accepts "..." -- so it can accept - whitespace as separators. + used to represent characters and their effects + on string lengths. See |align-strlen|. + * Align now accepts "..." -- so it can accept + whitespace as separators. 32 : Aug 18, 2007 * uses || instead of || plus a custom argument splitter to allow patterns with - backslashes to slide in unaltered. + backslashes to slide in unaltered. 31 : Aug 06, 2007 * :[range]Align! [AlignCtrl settings] pattern(s) implemented. 30 : Feb 12, 2007 * now uses |setline()| @@ -1341,8 +1457,8 @@ ALIGN HISTORY {{{2 25 : Jul 27, 2004 : For debugging, uses Dfunc(), Dret(), and Decho() 24 : Mar 03, 2004 : (should've done this earlier!) visualmode(1) not supported until v6.2, now Align will avoid - calling it for earlier versions. Visualmode - clearing won't take place then, of course. + calling it for earlier versions. Visualmode + clearing won't take place then, of course. 23 : Oct 07, 2003 : Included Leif Wickland's ReplaceQuotedSpaces() function which supports \tsq 22 : Jan 29, 2003 : Now requires 6.1.308 or later to clear visualmode() @@ -1365,7 +1481,7 @@ ALIGN HISTORY {{{2 14 : Aug 20, 2002 : bug fix: AlignCtrl default now keeps &ic unchanged bug fix: Align, on end-field, wasn't using correct alignop bug fix: Align, on end-field, was appending - padding + padding 13 : Aug 19, 2002 : bug fix: zero-length g/v patterns are accepted bug fix: always skip blank lines bug fix: AlignCtrl default now also clears g and v @@ -1382,28 +1498,37 @@ ALIGN HISTORY {{{2 9 : Jun 25, 2002 : implemented cyclic padding ALIGNMENT MAP HISTORY *alignmap-history* {{{2 + v42 Jan 06, 2010 * new maps for \anum, \aenum, \aunum + Feb 16, 2010 * map for \t=, \T= now handles x++ = something; + for c, c++ correctly. + Oct 29, 2010 * added a note on having one's own default + AlignCtrl (see |alignctrl-init|) + Feb 22, 2011 * for menus, &go =~# used to insure correct case + Jun 10, 2011 * |:AlignMapsClean| command provided to make it + easy for those who would prefer not to have + AlignMaps' maps not to have them. v41 Nov 02, 2008 * g:loaded_AlignMapsPlugin testing to prevent - re-loading installed - * AlignMaps now use 0x0f (ctrl-p) for special - character substitutions (instead of 0xff). - Seems to avoid some problems with having to - use Strlen(). - * bug fixed with \ts, - * new maps: \ts; \ts, \ts: \ts< \ts= \a( + re-loading installed + * AlignMaps now use 0x0f (ctrl-p) for special + character substitutions (instead of 0xff). + Seems to avoid some problems with having to + use Strlen(). + * bug fixed with \ts, + * new maps: \ts; \ts, \ts: \ts< \ts= \a( v40 Oct 21, 2008 * Modified AlignMaps so that its maps use s - and