1
0
Fork 0
mirror of https://github.com/kastdeur/dotfiles.git synced 2025-05-14 20:09:26 +02:00

Added vim plugin + autoindent\n use vi if vim is typed and not available

This commit is contained in:
Eric-Teunis de Boone 2016-10-05 00:32:06 +02:00
parent ef8bf8ac54
commit 061f80b9b9
144 changed files with 30057 additions and 0 deletions

View file

@ -0,0 +1,323 @@
" ==============================================================================
" File: syntaxFolds.vim
" Author: Srinath Avadhanula
" ( srinath@fastmail.fm )
" Last Change: Sun Oct 27 01:00 AM 2002 PST
" Description: Emulation of the syntax folding capability of vim using manual
" folding
"
" This script provides an emulation of the syntax folding of vim using manual
" folding. Just as in syntax folding, the folds are defined by regions. Each
" region is specified by a call to FoldRegions() which accepts 4 parameters:
"
" call FoldRegions(startpat, endpat, startoff, endoff)
"
" startpat: a line matching this pattern defines the beginning of a fold.
" endpat : a line matching this pattern defines the end of a fold.
" startoff: this is the offset from the starting line at which folding will
" actually start
" endoff : like startoff, but gives the offset of the actual fold end from
" the line satisfying endpat.
" startoff and endoff are necessary when the folding region does
" not have a specific end pattern corresponding to a start
" pattern. for example in latex,
" \begin{section}
" defines the beginning of a section, but its not necessary to
" have a corresponding
" \end{section}
" the section is assumed to end 1 line _before_ another section
" starts.
" startskip: a pattern which defines the beginning of a "skipped" region.
"
" For example, suppose we define a \itemize fold as follows:
" startpat = '^\s*\\item',
" endpat = '^\s*\\item\|^\s*\\end{\(enumerate\|itemize\|description\)}',
" startoff = 0,
" endoff = -1
"
" This defines a fold which starts with a line beginning with an
" \item and ending one line before a line beginning with an
" \item or \end{enumerate} etc.
"
" Then, as long as \item's are not nested things are fine.
" However, once items begin to nest, the fold started by one
" \item can end because of an \item in an \itemize
" environment within this \item. i.e, the following can happen:
"
" \begin{itemize}
" \item Some text <------- fold will start here
" This item will contain a nested item
" \begin{itemize} <----- fold will end here because next line contains \item...
" \item Hello
" \end{itemize} <----- ... instead of here.
" \item Next item of the parent itemize
" \end{itemize}
"
" Therefore, in order to completely define a folding item which
" allows nesting, we need to also define a "skip" pattern.
" startskip and end skip do that.
" Leave '' when there is no nesting.
" endskip: the pattern which defines the end of the "skip" pattern for
" nested folds.
"
" Example:
" 1. A syntax fold region for a latex section is
" startpat = "\\section{"
" endpat = "\\section{"
" startoff = 0
" endoff = -1
" startskip = ''
" endskip = ''
" Note that the start and end patterns are thus the same and endoff has a
" negative value to capture the effect of a section ending one line before
" the next starts.
" 2. A syntax fold region for the \itemize environment is:
" startpat = '^\s*\\item',
" endpat = '^\s*\\item\|^\s*\\end{\(enumerate\|itemize\|description\)}',
" startoff = 0,
" endoff = -1,
" startskip = '^\s*\\begin{\(enumerate\|itemize\|description\)}',
" endskip = '^\s*\\end{\(enumerate\|itemize\|description\)}'
" Note the use of startskip and endskip to allow nesting.
"
"
" Each time a call is made to FoldRegions(), all the regions (which might be
" disjoint, but not nested) are folded up.
" Nested folds can be created by successive calls to FoldRegions(). The first
" call defines the region which is deepest in the folding. See MakeTexFolds()
" for an idea of how this works for latex files.
" Function: AddSyntaxFoldItem (start, end, startoff, endoff [, skipStart, skipEnd]) {{{
function! AddSyntaxFoldItem(start, end, startoff, endoff, ...)
if a:0 > 0
let skipStart = a:1
let skipEnd = a:2
else
let skipStart = ''
let skipEnd = ''
end
if !exists('b:numFoldItems')
let b:numFoldItems = 0
end
let b:numFoldItems = b:numFoldItems + 1
exe 'let b:startPat_'.b:numFoldItems.' = a:start'
exe 'let b:endPat_'.b:numFoldItems.' = a:end'
exe 'let b:startOff_'.b:numFoldItems.' = a:startoff'
exe 'let b:endOff_'.b:numFoldItems.' = a:endoff'
exe 'let b:skipStartPat_'.b:numFoldItems.' = skipStart'
exe 'let b:skipEndPat_'.b:numFoldItems.' = skipEnd'
endfunction
" }}}
" Function: MakeSyntaxFolds (force) {{{
" Description: This function calls FoldRegions() several times with the
" parameters specifying various regions resulting in a nested fold
" structure for the file.
function! MakeSyntaxFolds(force, ...)
if exists('b:doneFolding') && a:force == 0
return
end
let skipEndPattern = ''
if a:0 > 0
let line1 = a:1
let skipEndPattern = '\|'.a:2
else
let line1 = 1
let r = line('.')
let c = virtcol('.')
setlocal fdm=manual
normal! zE
end
if !exists('b:numFoldItems')
b:numFoldItems = 1000000
end
let i = 1
let maxline = line('.')
while exists('b:startPat_'.i) && i <= b:numFoldItems
exe 'let startPat = b:startPat_'.i
exe 'let endPat = b:endPat_'.i
exe 'let startOff = b:startOff_'.i
exe 'let endOff = b:endOff_'.i
let skipStart = ''
let skipEnd = ''
if exists('b:skipStartPat_'.i)
exe 'let skipStart = b:skipStartPat_'.i
exe 'let skipEnd = b:skipEndPat_'.i
end
exe line1
let lastLoc = line1
if skipStart != ''
call InitStack('BeginSkipArray')
call FoldRegionsWithSkip(startPat, endPat, startOff, endOff, skipStart, skipEnd, 1, line('$'))
" call PrintError('done folding ['.startPat.']')
else
call FoldRegionsWithNoSkip(startPat, endPat, startOff, endOff, 1, line('$'), '')
end
let i = i + 1
endwhile
exe maxline
if a:0 == 0
exe r
exe "normal! ".c."|"
if foldlevel(r) > 1
exe "normal! ".(foldlevel(r) - 1)."zo"
end
let b:doneFolding = 0
end
endfunction
" }}}
" FoldRegionsWithSkip: folding things such as \item's which can be nested. {{{
function! FoldRegionsWithSkip(startpat, endpat, startoff, endoff, startskip, endskip, line1, line2)
exe a:line1
" count the regions which have been skipped as we go along. do not want to
" create a fold which with a beginning or end line in one of the skipped
" regions.
let skippedRegions = ''
" start searching for either the starting pattern or the end pattern.
while search(a:startskip.'\|'.a:endskip, 'W')
if getline('.') =~ a:endskip
let lastBegin = Pop('BeginSkipArray')
" call PrintError('popping '.lastBegin.' from stack and folding till '.line('.'))
call FoldRegionsWithNoSkip(a:startpat, a:endpat, a:startoff, a:endoff, lastBegin, line('.'), skippedRegions)
let skippedRegions = skippedRegions.lastBegin.','.line('.').'|'
" if this is the beginning of a skip region, then, push this line as
" the beginning of a skipped region.
elseif getline('.') =~ a:startskip
" call PrintError('pushing '.line('.').' ['.getline('.').'] into stack')
call Push('BeginSkipArray', line('.'))
end
endwhile
" call PrintError('with skip starting at '.a:line1.' returning at line# '.line('.'))
endfunction
" }}}
" FoldRegionsWithNoSkip: folding things such as \sections which do not nest. {{{
function! FoldRegionsWithNoSkip(startpat, endpat, startoff, endoff, line1, line2, skippedRegions)
exe a:line1
" call PrintError('line1 = '.a:line1.', searching from '.line('.').'... for ['.a:startpat.'')
let lineBegin = s:MySearch(a:startpat, 'in')
" call PrintError('... and finding it at '.lineBegin)
while lineBegin <= a:line2
if IsInSkippedRegion(lineBegin, a:skippedRegions)
let lineBegin = s:MySearch(a:startpat, 'out')
" call PrintError(lineBegin.' is being skipped')
continue
end
let lineEnd = s:MySearch(a:endpat, 'out')
while IsInSkippedRegion(lineEnd, a:skippedRegions) && lineEnd <= a:line2
let lineEnd = s:MySearch(a:endpat, 'out')
endwhile
if lineEnd > a:line2
exe (lineBegin + a:startoff).','.a:line2.' fold'
break
else
" call PrintError ('for ['.a:startpat.'] '.(lineBegin + a:startoff).','.(lineEnd + a:endoff).' fold')
exe (lineBegin + a:startoff).','.(lineEnd + a:endoff).' fold'
end
" call PrintError('line1 = '.a:line1.', searching from '.line('.').'... for ['.a:startpat.'')
let lineBegin = s:MySearch(a:startpat, 'in')
" call PrintError('... and finding it at '.lineBegin)
endwhile
exe a:line2
return
endfunction
" }}}
" InitStack: initialize a stack {{{
function! InitStack(name)
exe 'let s:'.a:name.'_numElems = 0'
endfunction
" }}}
" Push: push element into stack {{{
function! Push(name, elem)
exe 'let numElems = s:'.a:name.'_numElems'
let numElems = numElems + 1
exe 'let s:'.a:name.'_Element_'.numElems.' = a:elem'
exe 'let s:'.a:name.'_numElems = numElems'
endfunction
" }}}
" Pop: pops element off stack {{{
function! Pop(name)
exe 'let numElems = s:'.a:name.'_numElems'
if numElems == 0
return ''
else
exe 'let ret = s:'.a:name.'_Element_'.numElems
let numElems = numElems - 1
exe 'let s:'.a:name.'_numElems = numElems'
return ret
end
endfunction
" }}}
" MySearch: just like search(), but returns large number on failure {{{
function! <SID>MySearch(pat, opt)
if a:opt == 'in'
if getline('.') =~ a:pat
let ret = line('.')
else
let ret = search(a:pat, 'W')
end
else
normal! $
let ret = search(a:pat, 'W')
end
if ret == 0
let ret = line('$') + 1
end
return ret
endfunction
" }}}
" Function: IsInSkippedRegion (lnum, regions) {{{
" Description: finds whether a given line number is within one of the regions
" skipped.
function! IsInSkippedRegion(lnum, regions)
let i = 1
let subset = s:Strntok(a:regions, '|', i)
while subset != ''
let n1 = s:Strntok(subset, ',', 1)
let n2 = s:Strntok(subset, ',', 2)
if a:lnum >= n1 && a:lnum <= n2
return 1
end
let subset = s:Strntok(a:regions, '|', i)
let i = i + 1
endwhile
return 0
endfunction " }}}
" Function: Strntok (string, tok, n) {{{
" extract the n^th token from s seperated by tok.
" example: Strntok('1,23,3', ',', 2) = 23
fun! <SID>Strntok(s, tok, n)
return matchstr( a:s.a:tok[0], '\v(\zs([^'.a:tok.']*)\ze['.a:tok.']){'.a:n.'}')
endfun " }}}
" vim600:fdm=marker

View file

@ -0,0 +1,250 @@
" filebrowser.vim: utility file for vim 6.2+
"
" Copyright: Srinath Avadhanula <srinath AT fastmail DOT fm>
" Parts of this file are taken from explorer.vim which is a plugin file
" distributed with vim under the Vim charityware license.
" License: distributed under the Vim charityware license.
"
" Settings:
" FB_CallBackFunction: the function name which gets called when the user
" presses <cr> on a file-name in the file browser.
" FB_AllowRegexp: A filename has to match this regexp to be displayed.
" FB_RejectRegexp: If a filename matches this regexp, then its not displayed.
" (Both these regexps are '' by default which means no filtering is
" done).
" line continuation used here.
let s:save_cpo = &cpo
set cpo&vim
"======================================================================
" Globally visible functions (API)
"======================================================================
" FB_OpenFileBrowser: opens a new buffer and displays the file list {{{
" Description:
function! FB_OpenFileBrowser(dir)
if !isdirectory(a:dir)
return
endif
if exists('s:FB_BufferNumber')
if bufwinnr(s:FB_BufferNumber) != -1
execute bufwinnr(s:FB_BufferNumber).' wincmd w'
return
endif
execute 'aboveleft split #'.s:FB_BufferNumber
else
aboveleft split __Choose_File__
let s:FB_BufferNumber = bufnr('%')
endif
call FB_DisplayFiles(a:dir)
endfunction " }}}
" FB_DisplayFiles: displays the files in a given directory {{{
" Description:
" Call this function only when the cursor is in a temporary buffer
function! FB_DisplayFiles(dir)
if !isdirectory(a:dir)
return
endif
call s:FB_SetSilentSettings()
" make this a "scratch" buffer
call s:FB_SetScratchSettings()
let allowRegexp = s:FB_GetVar('FB_AllowRegexp', '')
let rejectRegexp = s:FB_GetVar('FB_RejectRegexp', '')
" change to the directory to make processing simpler.
execute "lcd ".a:dir
" delete everything in the buffer.
" IMPORTANT: we need to be in a scratch buffer
0,$ d_
let allFilenames = glob('*')
let dispFiles = ""
let subDirs = "../\n"
let allFilenames = allFilenames."\n"
let start = 0
while 1
let next = stridx(allFilenames, "\n", start)
let filename = strpart(allFilenames, start, next-start)
if filename == ""
break
endif
if isdirectory(filename)
let subDirs = subDirs.filename."/\n"
else
if allowRegexp != '' && filename !~ allowRegexp
elseif rejectRegexp != '' && filename =~ rejectRegexp
else
let dispFiles = dispFiles.filename."\n"
endif
endif
let start = next + 1
endwhile
0put!=dispFiles
0put!=subDirs
" delte the last empty line resulting from the put
$ d_
call s:FB_SetHighlighting()
call s:FB_DisplayHelp()
call s:FB_SetMaps()
" goto the first file/directory
0
call search('^"=', 'w')
normal! j:<bs>
set nomodified nomodifiable
call s:FB_ResetSilentSettings()
endfunction " }}}
" FB_SetVar: sets script local variables from outside this script {{{
" Description:
function! FB_SetVar(varname, value)
let s:{a:varname} = a:value
endfunction " }}}
" ==============================================================================
" Script local functions below this
" ==============================================================================
" FB_SetHighlighting: sets syntax highlighting for the buffer {{{
" Description:
" Origin: from explorer.vim in vim
function! <SID>FB_SetHighlighting()
" Set up syntax highlighting
" Something wrong with the evaluation of the conditional though...
if has("syntax") && exists("g:syntax_on") && !has("syntax_items")
syn match browseSynopsis "^\"[ -].*"
syn match browseDirectory "[^\"].*/ "
syn match browseDirectory "[^\"].*/$"
syn match browseCurDir "^\"= .*$"
syn match browseSortBy "^\" Sorted by .*$" contains=browseSuffixInfo
syn match browseSuffixInfo "(.*)$" contained
syn match browseFilter "^\" Not Showing:.*$"
syn match browseFiletime "«\d\+$"
"hi def link browseSynopsis PreProc
hi def link browseSynopsis Special
hi def link browseDirectory Directory
hi def link browseCurDir Statement
hi def link browseSortBy String
hi def link browseSuffixInfo Type
hi def link browseFilter String
hi def link browseFiletime Ignore
hi def link browseSuffixes Type
endif
endfunction " }}}
" FB_SetMaps: sets buffer local maps {{{
" Description:
function! <SID>FB_SetMaps()
nnoremap <buffer> <silent> q :bdelete<cr>
nnoremap <buffer> <silent> C :call FB_DisplayFiles(getcwd())<CR>
nnoremap <buffer> <silent> <esc> :bdelete<cr>
nnoremap <buffer> <silent> <CR> :call <SID>FB_EditEntry()<CR>
nnoremap <buffer> <silent> ? :call <SID>FB_ToggleHelp()<CR>
" lock the user in this window
nnoremap <buffer> <C-w> <nop>
endfunction " }}}
" FB_SetSilentSettings: some settings which make things silent {{{
" Description:
" Origin: from explorer.vim distributed with vim.
function! <SID>FB_SetSilentSettings()
let s:save_report=&report
let s:save_showcmd = &sc
set report=10000 noshowcmd
endfunction
" FB_ResetSilentSettings: reset settings set by FB_SetSilentSettings
" Description:
function! <SID>FB_ResetSilentSettings()
let &report=s:save_report
let &showcmd = s:save_showcmd
endfunction " }}}
" FB_SetScratchSettings: makes the present buffer a scratch buffer {{{
" Description:
function! <SID>FB_SetScratchSettings()
" Turn off the swapfile, set the buffer type so that it won't get
" written, and so that it will get deleted when it gets hidden.
setlocal noreadonly modifiable
setlocal noswapfile
setlocal buftype=nowrite
setlocal bufhidden=delete
" Don't wrap around long lines
setlocal nowrap
endfunction
" }}}
" FB_ToggleHelp: toggles verbosity of help {{{
" Description:
function! <SID>FB_ToggleHelp()
let s:FB_VerboseHelp = 1 - s:FB_GetVar('FB_VerboseHelp', 0)
call FB_DisplayFiles('.')
endfunction " }}}
" FB_DisplayHelp: displays a helpful header {{{
" Description:
function! <SID>FB_DisplayHelp()
let verboseHelp = s:FB_GetVar('FB_VerboseHelp', 0)
if verboseHelp
let txt =
\ "\" <cr>: on file, choose the file and quit\n"
\ ."\" on dir, enter directory\n"
\ ."\" q/<esc>: quit without choosing\n"
\ ."\" C: change directory to getcwd()\n"
\ ."\" ?: toggle help verbosity\n"
\ ."\"= ".getcwd()
else
let txt = "\" ?: toggle help verbosity\n"
\ ."\"= ".getcwd()
endif
0put!=txt
endfunction " }}}
" FB_EditEntry: handles the user pressing <enter> on a line {{{
" Description:
function! <SID>FB_EditEntry()
let line = getline('.')
if isdirectory(line)
call FB_DisplayFiles(line)
endif
" If the user has a call back function defined on choosing a file, handle
" it.
let cbf = s:FB_GetVar('FB_CallBackFunction', '')
if cbf != '' && line !~ '^" ' && filereadable(line)
let fname = fnamemodify(line, ':p')
bdelete
let arguments = s:FB_GetVar('FB_CallBackFunctionArgs', '')
if arguments != ''
let arguments = ','.arguments
endif
call Tex_Debug('arguments = '.arguments, 'fb')
call Tex_Debug("call ".cbf."('".fname."'".arguments.')', 'fb')
exec "call ".cbf."('".fname."'".arguments.')'
endif
endfunction " }}}
" FB_GetVar: gets the most local value of a variable {{{
function! <SID>FB_GetVar(name, default)
if exists('s:'.a:name)
return s:{a:name}
elseif exists('w:'.a:name)
return w:{a:name}
elseif exists('b:'.a:name)
return b:{a:name}
elseif exists('g:'.a:name)
return g:{a:name}
else
return a:default
endif
endfunction
" }}}
let &cpo = s:save_cpo
" vim:fdm=marker:ff=unix:noet:ts=4:sw=4:nowrap

832
vim/vim-latex/plugin/imaps.vim Executable file
View file

@ -0,0 +1,832 @@
" File: imaps.vim
" Authors: Srinath Avadhanula <srinath AT fastmail.fm>
" Benji Fisher <benji AT member.AMS.org>
"
" WWW: http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/vim-latex/vimfiles/plugin/imaps.vim?only_with_tag=MAIN
"
" Description: insert mode template expander with cursor placement
" while preserving filetype indentation.
"
" $Id: imaps.vim 997 2006-03-20 09:45:45Z srinathava $
"
" Documentation: {{{
"
" Motivation:
" this script provides a way to generate insert mode mappings which do not
" suffer from some of the problem of mappings and abbreviations while allowing
" cursor placement after the expansion. It can alternatively be thought of as
" a template expander.
"
" Consider an example. If you do
"
" imap lhs something
"
" then a mapping is set up. However, there will be the following problems:
" 1. the 'ttimeout' option will generally limit how easily you can type the
" lhs. if you type the left hand side too slowly, then the mapping will not
" be activated.
" 2. if you mistype one of the letters of the lhs, then the mapping is
" deactivated as soon as you backspace to correct the mistake.
"
" If, in order to take care of the above problems, you do instead
"
" iab lhs something
"
" then the timeout problem is solved and so is the problem of mistyping.
" however, abbreviations are only expanded after typing a non-word character.
" which causes problems of cursor placement after the expansion and invariably
" spurious spaces are inserted.
"
" Usage Example:
" this script attempts to solve all these problems by providing an emulation
" of imaps wchich does not suffer from its attendant problems. Because maps
" are activated without having to press additional characters, therefore
" cursor placement is possible. furthermore, file-type specific indentation is
" preserved, because the rhs is expanded as if the rhs is typed in literally
" by the user.
"
" The script already provides some default mappings. each "mapping" is of the
" form:
"
" call IMAP (lhs, rhs, ft)
"
" Some characters in the RHS have special meaning which help in cursor
" placement.
"
" Example One:
"
" call IMAP ("bit`", "\\begin{itemize}\<cr>\\item <++>\<cr>\\end{itemize}<++>", "tex")
"
" This effectively sets up the map for "bit`" whenever you edit a latex file.
" When you type in this sequence of letters, the following text is inserted:
"
" \begin{itemize}
" \item *
" \end{itemize}<++>
"
" where * shows the cursor position. The cursor position after inserting the
" text is decided by the position of the first "place-holder". Place holders
" are special characters which decide cursor placement and movement. In the
" example above, the place holder characters are <+ and +>. After you have typed
" in the item, press <C-j> and you will be taken to the next set of <++>'s.
" Therefore by placing the <++> characters appropriately, you can minimize the
" use of movement keys.
"
" NOTE: Set g:Imap_UsePlaceHolders to 0 to disable placeholders altogether.
" Set
" g:Imap_PlaceHolderStart and g:Imap_PlaceHolderEnd
" to something else if you want different place holder characters.
" Also, b:Imap_PlaceHolderStart and b:Imap_PlaceHolderEnd override the values
" of g:Imap_PlaceHolderStart and g:Imap_PlaceHolderEnd respectively. This is
" useful for setting buffer specific place hoders.
"
" Example Two:
" You can use the <C-r> command to insert dynamic elements such as dates.
" call IMAP ('date`', "\<c-r>=strftime('%b %d %Y')\<cr>", '')
"
" sets up the map for date` to insert the current date.
"
"--------------------------------------%<--------------------------------------
" Bonus: This script also provides a command Snip which puts tearoff strings,
" '----%<----' above and below the visually selected range of lines. The
" length of the string is chosen to be equal to the longest line in the range.
" Recommended Usage:
" '<,'>Snip
"--------------------------------------%<--------------------------------------
" }}}
" line continuation used here.
let s:save_cpo = &cpo
set cpo&vim
" ==============================================================================
" Script Options / Variables
" ==============================================================================
" Options {{{
if !exists('g:Imap_StickyPlaceHolders')
let g:Imap_StickyPlaceHolders = 1
endif
if !exists('g:Imap_DeleteEmptyPlaceHolders')
let g:Imap_DeleteEmptyPlaceHolders = 1
endif
" }}}
" Variables {{{
" s:LHS_{ft}_{char} will be generated automatically. It will look like
" s:LHS_tex_o = 'fo\|foo\|boo' and contain all mapped sequences ending in "o".
" s:Map_{ft}_{lhs} will be generated automatically. It will look like
" s:Map_c_foo = 'for(<++>; <++>; <++>)', the mapping for "foo".
"
" }}}
" ==============================================================================
" functions for easy insert mode mappings.
" ==============================================================================
" IMAP: Adds a "fake" insert mode mapping. {{{
" For example, doing
" IMAP('abc', 'def' ft)
" will mean that if the letters abc are pressed in insert mode, then
" they will be replaced by def. If ft != '', then the "mapping" will be
" specific to the files of type ft.
"
" Using IMAP has a few advantages over simply doing:
" imap abc def
" 1. with imap, if you begin typing abc, the cursor will not advance and
" long as there is a possible completion, the letters a, b, c will be
" displayed on on top of the other. using this function avoids that.
" 2. with imap, if a backspace or arrow key is pressed before completing
" the word, then the mapping is lost. this function allows movement.
" (this ofcourse means that this function is only limited to
" left-hand-sides which do not have movement keys or unprintable
" characters)
" It works by only mapping the last character of the left-hand side.
" when this character is typed in, then a reverse lookup is done and if
" the previous characters consititute the left hand side of the mapping,
" the previously typed characters and erased and the right hand side is
" inserted
" IMAP: set up a filetype specific mapping.
" Description:
" "maps" the lhs to rhs in files of type 'ft'. If supplied with 2
" additional arguments, then those are assumed to be the placeholder
" characters in rhs. If unspecified, then the placeholder characters
" are assumed to be '<+' and '+>' These placeholder characters in
" a:rhs are replaced with the users setting of
" [bg]:Imap_PlaceHolderStart and [bg]:Imap_PlaceHolderEnd settings.
"
function! IMAP(lhs, rhs, ft, ...)
" Find the place holders to save for IMAP_PutTextWithMovement() .
if a:0 < 2
let phs = '<+'
let phe = '+>'
else
let phs = a:1
let phe = a:2
endif
let hash = s:Hash(a:lhs)
let s:Map_{a:ft}_{hash} = a:rhs
let s:phs_{a:ft}_{hash} = phs
let s:phe_{a:ft}_{hash} = phe
" Add a:lhs to the list of left-hand sides that end with lastLHSChar:
let lastLHSChar = a:lhs[strlen(a:lhs)-1]
let hash = s:Hash(lastLHSChar)
if !exists("s:LHS_" . a:ft . "_" . hash)
let s:LHS_{a:ft}_{hash} = escape(a:lhs, '\')
else
let s:LHS_{a:ft}_{hash} = escape(a:lhs, '\') .'\|'. s:LHS_{a:ft}_{hash}
endif
" map only the last character of the left-hand side.
if lastLHSChar == ' '
let lastLHSChar = '<space>'
end
exe 'inoremap <silent>'
\ escape(lastLHSChar, '|')
\ '<C-r>=<SID>LookupCharacter("' .
\ escape(lastLHSChar, '\|"') .
\ '")<CR>'
endfunction
" }}}
" IMAP_list: list the rhs and place holders corresponding to a:lhs {{{
"
" Added mainly for debugging purposes, but maybe worth keeping.
function! IMAP_list(lhs)
let char = a:lhs[strlen(a:lhs)-1]
let charHash = s:Hash(char)
if exists("s:LHS_" . &ft ."_". charHash) && a:lhs =~ s:LHS_{&ft}_{charHash}
let ft = &ft
elseif exists("s:LHS__" . charHash) && a:lhs =~ s:LHS__{charHash}
let ft = ""
else
return ""
endif
let hash = s:Hash(a:lhs)
return "rhs = " . s:Map_{ft}_{hash} . " place holders = " .
\ s:phs_{ft}_{hash} . " and " . s:phe_{ft}_{hash}
endfunction
" }}}
" LookupCharacter: inserts mapping corresponding to this character {{{
"
" This function extracts from s:LHS_{&ft}_{a:char} or s:LHS__{a:char}
" the longest lhs matching the current text. Then it replaces lhs with the
" corresponding rhs saved in s:Map_{ft}_{lhs} .
" The place-holder variables are passed to IMAP_PutTextWithMovement() .
function! s:LookupCharacter(char)
if IMAP_GetVal('Imap_FreezeImap', 0) == 1
return a:char
endif
let charHash = s:Hash(a:char)
" The line so far, including the character that triggered this function:
let text = strpart(getline("."), 0, col(".")-1) . a:char
" Prefer a local map to a global one, even if the local map is shorter.
" Is this what we want? Do we care?
" Use '\V' (very no-magic) so that only '\' is special, and it was already
" escaped when building up s:LHS_{&ft}_{charHash} .
if exists("s:LHS_" . &ft . "_" . charHash)
\ && text =~ "\\C\\V\\(" . s:LHS_{&ft}_{charHash} . "\\)\\$"
let ft = &ft
elseif exists("s:LHS__" . charHash)
\ && text =~ "\\C\\V\\(" . s:LHS__{charHash} . "\\)\\$"
let ft = ""
else
" If this is a character which could have been used to trigger an
" abbreviation, check if an abbreviation exists.
if a:char !~ '\k'
let lastword = matchstr(getline('.'), '\k\+$', '')
call IMAP_Debug('getting lastword = ['.lastword.']', 'imap')
if lastword != ''
" An extremeley wierd way to get around the fact that vim
" doesn't have the equivalent of the :mapcheck() function for
" abbreviations.
let _a = @a
exec "redir @a | silent! iab ".lastword." | redir END"
let abbreviationRHS = matchstr(@a."\n", "\n".'i\s\+'.lastword.'\s\+@\?\zs.*\ze'."\n")
call IMAP_Debug('getting abbreviationRHS = ['.abbreviationRHS.']', 'imap')
if @a =~ "No abbreviation found" || abbreviationRHS == ""
let @a = _a
return a:char
endif
let @a = _a
let abbreviationRHS = escape(abbreviationRHS, '\<"')
exec 'let abbreviationRHS = "'.abbreviationRHS.'"'
let lhs = lastword.a:char
let rhs = abbreviationRHS.a:char
let phs = IMAP_GetPlaceHolderStart()
let phe = IMAP_GetPlaceHolderEnd()
else
return a:char
endif
else
return a:char
endif
endif
" Find the longest left-hand side that matches the line so far.
" matchstr() returns the match that starts first. This automatically
" ensures that the longest LHS is used for the mapping.
if !exists('lhs') || !exists('rhs')
let lhs = matchstr(text, "\\C\\V\\(" . s:LHS_{ft}_{charHash} . "\\)\\$")
let hash = s:Hash(lhs)
let rhs = s:Map_{ft}_{hash}
let phs = s:phs_{ft}_{hash}
let phe = s:phe_{ft}_{hash}
endif
if strlen(lhs) == 0
return a:char
endif
" enough back-spaces to erase the left-hand side; -1 for the last
" character typed:
let bs = substitute(strpart(lhs, 1), ".", "\<bs>", "g")
" \<c-g>u inserts an undo point
return a:char . "\<c-g>u\<bs>" . bs . IMAP_PutTextWithMovement(rhs, phs, phe)
endfunction
" }}}
" IMAP_PutTextWithMovement: returns the string with movement appended {{{
" Description:
" If a:str contains "placeholders", then appends movement commands to
" str in a way that the user moves to the first placeholder and enters
" insert or select mode. If supplied with 2 additional arguments, then
" they are assumed to be the placeholder specs. Otherwise, they are
" assumed to be '<+' and '+>'. These placeholder chars are replaced
" with the users settings of [bg]:Imap_PlaceHolderStart and
" [bg]:Imap_PlaceHolderEnd.
function! IMAP_PutTextWithMovement(str, ...)
" The placeholders used in the particular input string. These can be
" different from what the user wants to use.
if a:0 < 2
let phs = '<+'
let phe = '+>'
else
let phs = escape(a:1, '\')
let phe = escape(a:2, '\')
endif
let text = a:str
" The user's placeholder settings.
let phsUser = IMAP_GetPlaceHolderStart()
let pheUser = IMAP_GetPlaceHolderEnd()
" Problem: depending on the setting of the 'encoding' option, a character
" such as "\xab" may not match itself. We try to get around this by
" changing the encoding of all our strings. At the end, we have to
" convert text back.
let phsEnc = s:Iconv(phs, "encode")
let pheEnc = s:Iconv(phe, "encode")
let phsUserEnc = s:Iconv(phsUser, "encode")
let pheUserEnc = s:Iconv(pheUser, "encode")
let textEnc = s:Iconv(text, "encode")
if textEnc != text
let textEncoded = 1
else
let textEncoded = 0
endif
let pattern = '\V\(\.\{-}\)' .phs. '\(\.\{-}\)' .phe. '\(\.\*\)'
" If there are no placeholders, just return the text.
if textEnc !~ pattern
call IMAP_Debug('Not getting '.phs.' and '.phe.' in '.textEnc, 'imap')
return text
endif
" Break text up into "initial <+template+> final"; any piece may be empty.
let initialEnc = substitute(textEnc, pattern, '\1', '')
let templateEnc = substitute(textEnc, pattern, '\2', '')
let finalEnc = substitute(textEnc, pattern, '\3', '')
" If the user does not want to use placeholders, then remove all but the
" first placeholder.
" Otherwise, replace all occurences of the placeholders here with the
" user's choice of placeholder settings.
if exists('g:Imap_UsePlaceHolders') && !g:Imap_UsePlaceHolders
let finalEnc = substitute(finalEnc, '\V'.phs.'\.\{-}'.phe, '', 'g')
else
let finalEnc = substitute(finalEnc, '\V'.phs.'\(\.\{-}\)'.phe,
\ phsUserEnc.'\1'.pheUserEnc, 'g')
endif
" The substitutions are done, so convert back, if necessary.
if textEncoded
let initial = s:Iconv(initialEnc, "decode")
let template = s:Iconv(templateEnc, "decode")
let final = s:Iconv(finalEnc, "decode")
else
let initial = initialEnc
let template = templateEnc
let final = finalEnc
endif
" Build up the text to insert:
" 1. the initial text plus an extra character;
" 2. go to Normal mode with <C-\><C-N>, so it works even if 'insertmode'
" is set, and mark the position;
" 3. replace the extra character with tamplate and final;
" 4. back to Normal mode and restore the cursor position;
" 5. call IMAP_Jumpfunc().
let template = phsUser . template . pheUser
" Old trick: insert and delete a character to get the same behavior at
" start, middle, or end of line and on empty lines.
let text = initial . "X\<C-\>\<C-N>:call IMAP_Mark('set')\<CR>\"_s"
let text = text . template . final
let text = text . "\<C-\>\<C-N>:call IMAP_Mark('go')\<CR>"
let text = text . "i\<C-r>=IMAP_Jumpfunc('', 1)\<CR>"
call IMAP_Debug('IMAP_PutTextWithMovement: text = ['.text.']', 'imap')
return text
endfunction
" }}}
" IMAP_Jumpfunc: takes user to next <+place-holder+> {{{
" Author: Luc Hermitte
" Arguments:
" direction: flag for the search() function. If set to '', search forwards,
" if 'b', then search backwards. See the {flags} argument of the
" |search()| function for valid values.
" inclusive: In vim, the search() function is 'exclusive', i.e we always goto
" next cursor match even if there is a match starting from the
" current cursor position. Setting this argument to 1 makes
" IMAP_Jumpfunc() also respect a match at the current cursor
" position. 'inclusive'ness is necessary for IMAP() because a
" placeholder string can occur at the very beginning of a map which
" we want to select.
" We use a non-zero value only in special conditions. Most mappings
" should use a zero value.
function! IMAP_Jumpfunc(direction, inclusive)
" The user's placeholder settings.
let phsUser = IMAP_GetPlaceHolderStart()
let pheUser = IMAP_GetPlaceHolderEnd()
let searchString = ''
" If this is not an inclusive search or if it is inclusive, but the
" current cursor position does not contain a placeholder character, then
" search for the placeholder characters.
if !a:inclusive || strpart(getline('.'), col('.')-1) !~ '\V\^'.phsUser
let searchString = '\V'.phsUser.'\_.\{-}'.pheUser
endif
" If we didn't find any placeholders return quietly.
if searchString != '' && !search(searchString, a:direction)
return ''
endif
" Open any closed folds and make this part of the text visible.
silent! foldopen!
" Calculate if we have an empty placeholder or if it contains some
" description.
let template =
\ matchstr(strpart(getline('.'), col('.')-1),
\ '\V\^'.phsUser.'\zs\.\{-}\ze\('.pheUser.'\|\$\)')
let placeHolderEmpty = !strlen(template)
" If we are selecting in exclusive mode, then we need to move one step to
" the right
let extramove = ''
if &selection == 'exclusive'
let extramove = 'l'
endif
" Select till the end placeholder character.
let movement = "\<C-o>v/\\V".pheUser."/e\<CR>".extramove
" First remember what the search pattern was. s:RemoveLastHistoryItem will
" reset @/ to this pattern so we do not create new highlighting.
let g:Tex_LastSearchPattern = @/
" Now either goto insert mode or select mode.
if placeHolderEmpty && g:Imap_DeleteEmptyPlaceHolders
" delete the empty placeholder into the blackhole.
return movement."\"_c\<C-o>:".s:RemoveLastHistoryItem."\<CR>"
else
return movement."\<C-\>\<C-N>:".s:RemoveLastHistoryItem."\<CR>gv\<C-g>"
endif
endfunction
" }}}
" Maps for IMAP_Jumpfunc {{{
"
" These mappings use <Plug> and thus provide for easy user customization. When
" the user wants to map some other key to jump forward, he can do for
" instance:
" nmap ,f <plug>IMAP_JumpForward
" etc.
" jumping forward and back in insert mode.
imap <silent> <Plug>IMAP_JumpForward <c-r>=IMAP_Jumpfunc('', 0)<CR>
imap <silent> <Plug>IMAP_JumpBack <c-r>=IMAP_Jumpfunc('b', 0)<CR>
" jumping in normal mode
nmap <silent> <Plug>IMAP_JumpForward i<c-r>=IMAP_Jumpfunc('', 0)<CR>
nmap <silent> <Plug>IMAP_JumpBack i<c-r>=IMAP_Jumpfunc('b', 0)<CR>
" deleting the present selection and then jumping forward.
vmap <silent> <Plug>IMAP_DeleteAndJumpForward "_<Del>i<c-r>=IMAP_Jumpfunc('', 0)<CR>
vmap <silent> <Plug>IMAP_DeleteAndJumpBack "_<Del>i<c-r>=IMAP_Jumpfunc('b', 0)<CR>
" jumping forward without deleting present selection.
vmap <silent> <Plug>IMAP_JumpForward <C-\><C-N>i<c-r>=IMAP_Jumpfunc('', 0)<CR>
vmap <silent> <Plug>IMAP_JumpBack <C-\><C-N>`<i<c-r>=IMAP_Jumpfunc('b', 0)<CR>
" }}}
" Default maps for IMAP_Jumpfunc {{{
" map only if there is no mapping already. allows for user customization.
" NOTE: Default mappings for jumping to the previous placeholder are not
" provided. It is assumed that if the user will create such mappings
" hself if e so desires.
if !hasmapto('<Plug>IMAP_JumpForward', 'i')
imap <C-J> <Plug>IMAP_JumpForward
endif
if !hasmapto('<Plug>IMAP_JumpForward', 'n')
nmap <C-J> <Plug>IMAP_JumpForward
endif
if exists('g:Imap_StickyPlaceHolders') && g:Imap_StickyPlaceHolders
if !hasmapto('<Plug>IMAP_JumpForward', 'v')
vmap <C-J> <Plug>IMAP_JumpForward
endif
else
if !hasmapto('<Plug>IMAP_DeleteAndJumpForward', 'v')
vmap <C-J> <Plug>IMAP_DeleteAndJumpForward
endif
endif
" }}}
nmap <silent> <script> <plug><+SelectRegion+> `<v`>
" ==============================================================================
" enclosing selected region.
" ==============================================================================
" VEnclose: encloses the visually selected region with given arguments {{{
" Description: allows for differing action based on visual line wise
" selection or visual characterwise selection. preserves the
" marks and search history.
function! VEnclose(vstart, vend, VStart, VEnd)
" its characterwise if
" 1. characterwise selection and valid values for vstart and vend.
" OR
" 2. linewise selection and invalid values for VStart and VEnd
if (visualmode() ==# 'v' && (a:vstart != '' || a:vend != '')) || (a:VStart == '' && a:VEnd == '')
let newline = ""
let _r = @r
let normcmd = "normal! \<C-\>\<C-n>`<v`>\"_s"
exe "normal! \<C-\>\<C-n>`<v`>\"ry"
if @r =~ "\n$"
let newline = "\n"
let @r = substitute(@r, "\n$", '', '')
endif
" In exclusive selection, we need to select an extra character.
if &selection == 'exclusive'
let movement = 8
else
let movement = 7
endif
let normcmd = normcmd.
\ a:vstart."!!mark!!".a:vend.newline.
\ "\<C-\>\<C-N>?!!mark!!\<CR>v".movement."l\"_s\<C-r>r\<C-\>\<C-n>"
" this little if statement is because till very recently, vim used to
" report col("'>") > length of selected line when `> is $. on some
" systems it reports a -ve number.
if col("'>") < 0 || col("'>") > strlen(getline("'>"))
let lastcol = strlen(getline("'>"))
else
let lastcol = col("'>")
endif
if lastcol - col("'<") != 0
let len = lastcol - col("'<")
else
let len = ''
endif
" the next normal! is for restoring the marks.
let normcmd = normcmd."`<v".len."l\<C-\>\<C-N>"
" First remember what the search pattern was. s:RemoveLastHistoryItem
" will reset @/ to this pattern so we do not create new highlighting.
let g:Tex_LastSearchPattern = @/
silent! exe normcmd
" this is to restore the r register.
let @r = _r
" and finally, this is to restore the search history.
execute s:RemoveLastHistoryItem
else
exec 'normal! `<O'.a:VStart."\<C-\>\<C-n>"
exec 'normal! `>o'.a:VEnd."\<C-\>\<C-n>"
if &indentexpr != ''
silent! normal! `<kV`>j=
endif
silent! normal! `>
endif
endfunction
" }}}
" ExecMap: adds the ability to correct an normal/visual mode mapping. {{{
" Author: Hari Krishna Dara <hari_vim@yahoo.com>
" Reads a normal mode mapping at the command line and executes it with the
" given prefix. Press <BS> to correct and <Esc> to cancel.
function! ExecMap(prefix, mode)
" Temporarily remove the mapping, otherwise it will interfere with the
" mapcheck call below:
let myMap = maparg(a:prefix, a:mode)
exec a:mode."unmap ".a:prefix
" Generate a line with spaces to clear the previous message.
let i = 1
let clearLine = "\r"
while i < &columns
let clearLine = clearLine . ' '
let i = i + 1
endwhile
let mapCmd = a:prefix
let foundMap = 0
let breakLoop = 0
echon "\rEnter Map: " . mapCmd
while !breakLoop
let char = getchar()
if char !~ '^\d\+$'
if char == "\<BS>"
let mapCmd = strpart(mapCmd, 0, strlen(mapCmd) - 1)
endif
else " It is the ascii code.
let char = nr2char(char)
if char == "\<Esc>"
let breakLoop = 1
else
let mapCmd = mapCmd . char
if maparg(mapCmd, a:mode) != ""
let foundMap = 1
let breakLoop = 1
elseif mapcheck(mapCmd, a:mode) == ""
let mapCmd = strpart(mapCmd, 0, strlen(mapCmd) - 1)
endif
endif
endif
echon clearLine
echon "\rEnter Map: " . mapCmd
endwhile
if foundMap
if a:mode == 'v'
" use a plug to select the region instead of using something like
" `<v`> to avoid problems caused by some of the characters in
" '`<v`>' being mapped.
let gotoc = "\<plug><+SelectRegion+>"
else
let gotoc = ''
endif
exec "normal ".gotoc.mapCmd
endif
exec a:mode.'noremap '.a:prefix.' '.myMap
endfunction
" }}}
" ==============================================================================
" helper functions
" ==============================================================================
" Strntok: extract the n^th token from a list {{{
" example: Strntok('1,23,3', ',', 2) = 23
fun! <SID>Strntok(s, tok, n)
return matchstr( a:s.a:tok[0], '\v(\zs([^'.a:tok.']*)\ze['.a:tok.']){'.a:n.'}')
endfun
" }}}
" s:RemoveLastHistoryItem: removes last search item from search history {{{
" Description: Execute this string to clean up the search history.
let s:RemoveLastHistoryItem = ':call histdel("/", -1)|let @/=g:Tex_LastSearchPattern'
" }}}
" s:Hash: Return a version of a string that can be used as part of a variable" {{{
" name.
" Converts every non alphanumeric character into _{ascii}_ where {ascii} is
" the ASCII code for that character...
fun! s:Hash(text)
return substitute(a:text, '\([^[:alnum:]]\)',
\ '\="_".char2nr(submatch(1))."_"', 'g')
endfun
"" }}}
" IMAP_GetPlaceHolderStart and IMAP_GetPlaceHolderEnd: "{{{
" return the buffer local placeholder variables, or the global one, or the default.
function! IMAP_GetPlaceHolderStart()
if exists("b:Imap_PlaceHolderStart") && strlen(b:Imap_PlaceHolderEnd)
return b:Imap_PlaceHolderStart
elseif exists("g:Imap_PlaceHolderStart") && strlen(g:Imap_PlaceHolderEnd)
return g:Imap_PlaceHolderStart
else
return "<+"
endfun
function! IMAP_GetPlaceHolderEnd()
if exists("b:Imap_PlaceHolderEnd") && strlen(b:Imap_PlaceHolderEnd)
return b:Imap_PlaceHolderEnd
elseif exists("g:Imap_PlaceHolderEnd") && strlen(g:Imap_PlaceHolderEnd)
return g:Imap_PlaceHolderEnd
else
return "+>"
endfun
" }}}
" s:Iconv: a wrapper for iconv()" {{{
" Problem: after
" let text = "\xab"
" (or using the raw 8-bit ASCII character in a file with 'fenc' set to
" "latin1") if 'encoding' is set to utf-8, then text does not match itself:
" echo text =~ text
" returns 0.
" Solution: When this happens, a re-encoded version of text does match text:
" echo iconv(text, "latin1", "utf8") =~ text
" returns 1. In this case, convert text to utf-8 with iconv().
" TODO: Is it better to use &encoding instead of "utf8"? Internally, vim
" uses utf-8, and can convert between latin1 and utf-8 even when compiled with
" -iconv, so let's try using utf-8.
" Arguments:
" a:text = text to be encoded or decoded
" a:mode = "encode" (latin1 to utf8) or "decode" (utf8 to latin1)
" Caution: do not encode and then decode without checking whether the text
" has changed, becuase of the :if clause in encoding!
function! s:Iconv(text, mode)
if a:mode == "decode"
return iconv(a:text, "utf8", "latin1")
endif
if a:text =~ '\V\^' . escape(a:text, '\') . '\$'
return a:text
endif
let textEnc = iconv(a:text, "latin1", "utf8")
if textEnc !~ '\V\^' . escape(a:text, '\') . '\$'
call IMAP_Debug('Encoding problems with text '.a:text.' ', 'imap')
endif
return textEnc
endfun
"" }}}
" IMAP_Debug: interface to Tex_Debug if available, otherwise emulate it {{{
" Description:
" Do not want a memory leak! Set this to zero so that imaps always
" starts out in a non-debugging mode.
if !exists('g:Imap_Debug')
let g:Imap_Debug = 0
endif
function! IMAP_Debug(string, pattern)
if !g:Imap_Debug
return
endif
if exists('*Tex_Debug')
call Tex_Debug(a:string, a:pattern)
else
if !exists('s:debug_'.a:pattern)
let s:debug_{a:pattern} = a:string
else
let s:debug_{a:pattern} = s:debug_{a:pattern}.a:string
endif
endif
endfunction " }}}
" IMAP_DebugClear: interface to Tex_DebugClear if avaialable, otherwise emulate it {{{
" Description:
function! IMAP_DebugClear(pattern)
if exists('*Tex_DebugClear')
call Tex_DebugClear(a:pattern)
else
let s:debug_{a:pattern} = ''
endif
endfunction " }}}
" IMAP_PrintDebug: interface to Tex_DebugPrint if avaialable, otherwise emulate it {{{
" Description:
function! IMAP_PrintDebug(pattern)
if exists('*Tex_PrintDebug')
call Tex_PrintDebug(a:pattern)
else
if exists('s:debug_'.a:pattern)
echo s:debug_{a:pattern}
endif
endif
endfunction " }}}
" IMAP_Mark: Save the cursor position (if a:action == 'set') in a" {{{
" script-local variable; restore this position if a:action == 'go'.
let s:Mark = "(0,0)"
let s:initBlanks = ''
function! IMAP_Mark(action)
if a:action == 'set'
let s:Mark = "(" . line(".") . "," . col(".") . ")"
let s:initBlanks = matchstr(getline('.'), '^\s*')
elseif a:action == 'go'
execute "call cursor" s:Mark
let blanksNow = matchstr(getline('.'), '^\s*')
if strlen(blanksNow) > strlen(s:initBlanks)
execute 'silent! normal! '.(strlen(blanksNow) - strlen(s:initBlanks)).'l'
elseif strlen(blanksNow) < strlen(s:initBlanks)
execute 'silent! normal! '.(strlen(s:initBlanks) - strlen(blanksNow)).'h'
endif
endif
endfunction "" }}}
" IMAP_GetVal: gets the value of a variable {{{
" Description: first checks window local, then buffer local etc.
function! IMAP_GetVal(name, ...)
if a:0 > 0
let default = a:1
else
let default = ''
endif
if exists('w:'.a:name)
return w:{a:name}
elseif exists('b:'.a:name)
return b:{a:name}
elseif exists('g:'.a:name)
return g:{a:name}
else
return default
endif
endfunction " }}}
" ==============================================================================
" A bonus function: Snip()
" ==============================================================================
" Snip: puts a scissor string above and below block of text {{{
" Desciption:
"-------------------------------------%<-------------------------------------
" this puts a the string "--------%<---------" above and below the visually
" selected block of lines. the length of the 'tearoff' string depends on the
" maximum string length in the selected range. this is an aesthetically more
" pleasing alternative instead of hardcoding a length.
"-------------------------------------%<-------------------------------------
function! <SID>Snip() range
let i = a:firstline
let maxlen = -2
" find out the maximum virtual length of each line.
while i <= a:lastline
exe i
let length = virtcol('$')
let maxlen = (length > maxlen ? length : maxlen)
let i = i + 1
endwhile
let maxlen = (maxlen > &tw && &tw != 0 ? &tw : maxlen)
let half = maxlen/2
exe a:lastline
" put a string below
exe "norm! o\<esc>".(half - 1)."a-\<esc>A%<\<esc>".(half - 1)."a-"
" and above. its necessary to put the string below the block of lines
" first because that way the first line number doesnt change...
exe a:firstline
exe "norm! O\<esc>".(half - 1)."a-\<esc>A%<\<esc>".(half - 1)."a-"
endfunction
com! -nargs=0 -range Snip :<line1>,<line2>call <SID>Snip()
" }}}
let &cpo = s:save_cpo
" vim:ft=vim:ts=4:sw=4:noet:fdm=marker:commentstring=\"\ %s:nowrap

249
vim/vim-latex/plugin/libList.vim Executable file
View file

@ -0,0 +1,249 @@
" File: libList.vim
" Last Change: 2001 Dec 10
" Maintainer: Gontran BAERTS <gbcreation@free.fr>
" Version: 0.1
"
" Please don't hesitate to correct my english :)
" Send corrections to <gbcreation@free.fr>
"
"-----------------------------------------------------------------------------
" Description: libList.vim is a set of functions to work with lists or one
" level arrays.
"
"-----------------------------------------------------------------------------
" To Enable: Normally, this file will reside in your plugins directory and be
" automatically sourced.
"
"-----------------------------------------------------------------------------
" Usage: Lists are strings variable with values separated by g:listSep
" character (comma" by default). You may redefine g:listSep variable as you
" wish.
"
" Here are available functions :
"
" - AddListItem( array, newItem, index ) :
" Add item "newItem" to array "array" at "index" position
" - GetListItem( array, index ) :
" Return item at "index" position in array "array"
" - GetListMatchItem( array, pattern ) :
" Return item matching "pattern" in array "array"
" - GetListCount( array ) :
" Return the number of items in array "array"
" - RemoveListItem( array, index ) :
" Remove item at "index" position from array "array"
" - ReplaceListItem( array, index, item ) :
" Remove item at "index" position by "item" in array "array"
" - ExchangeListItems( array, item1Index, item2Index ) :
" Exchange item "item1Index" with item "item2Index" in array "array"
" - QuickSortList( array, beg, end ) :
" Return array "array" with items between "beg" and "end" sorted
"
" Example:
" let mylist=""
" echo GetListCount( mylist ) " --> 0
" let mylist = AddListItem( mylist, "One", 0 ) " mylist == "One"
" let mylist = AddListItem( mylist, "Three", 1 ) " mylist == "One,Three"
" let mylist = AddListItem( mylist, "Two", 1 ) " mylist == "One,Two,Three"
" echo GetListCount( mylist ) " --> 3
" echo GetListItem( mylist, 2 ) " --> Three
" echo GetListMatchItem( mylist, "w" ) " --> two
" echo GetListMatchItem( mylist, "e" ) " --> One
" let mylist = RemoveListItem( mylist, 2 ) " mylist == "One,Two"
" echo GetListCount( mylist ) " --> 2
" let mylist = ReplaceListItem( mylist, 0, "Three" ) " mylist == "Three,Two"
" let mylist = ExchangeListItems( mylist, 0, 1 ) " mylist == "Two,Three"
" let mylist = AddListItem( mylist, "One", 0 ) " mylist == "One,Two,Three"
" let mylist = QuickSortList( mylist, 0, GetListCount(mylist)-1 )
" " mylist == "One,Three,Two"
"
"-----------------------------------------------------------------------------
" Updates:
" in version 0.1
" - First version
" Has this already been loaded ?
if exists("loaded_libList")
finish
endif
let loaded_libList=1
"**
" Separator:
" You may change the separator character et any time.
"**
let g:listSep = ","
"**
"AddListItem:
" Add new item at given position.
" First item index is 0 (zero).
"Parameters:
" - array : Array/List (string of values) which receives the new item.
" - newItem : String containing the item value to add.
" - index : Integer indicating the position at which the new item is added.
" It must be greater than or equals to 0 (zero).
"Return:
"String containing array values, including newItem.
"**
function AddListItem( array, newItem, index )
if a:index == 0
if a:array == ""
return a:newItem
endif
return a:newItem . g:listSep . a:array
endif
return substitute( a:array, '\(\%(^\|' . g:listSep . '\)[^' . g:listSep . ']\+\)\{' . a:index . '\}', '\0' . g:listSep . a:newItem , "" )
endfunction
"**
"GetListItem:
" Get item at given position.
"Parameters:
" - array : Array/List (string of values).
" - index : Integer indicating the position of item to return.
" It must be greater than or equals to 0 (zero).
"Return:
"String representing the item.
"**
function GetListItem( array, index )
if a:index == 0
return matchstr( a:array, '^[^' . g:listSep . ']\+' )
else
return matchstr( a:array, "[^" . g:listSep . "]\\+", matchend( a:array, '\(\%(^\|' . g:listSep . '\)[^' . g:listSep . ']\+\)\{' . a:index . '\}' . g:listSep ) )
endif
endfunction
"**
"GetListMatchItem:
" Get the first item matching given pattern.
"Parameters:
" - array : Array/List (string of values).
" - pattern : Regular expression to match with items.
" Avoid to use ^, $ and listSep characters in pattern, unless you
" know what you do.
"Return:
"String representing the first item that matches the pattern.
"**
function GetListMatchItem( array, pattern )
return matchstr( a:array, '[^' . g:listSep . ']*' . a:pattern . '[^' . g:listSep . ']*' )
endfunction
"**
"ReplaceListItem:
" Replace item at given position by a new one.
"Parameters:
" - array : Array/List (string of values).
" - index : Integer indicating the position of item to replace.
" It must be greater than or equals to 0 (zero).
" - item : String containing the new value of the replaced item.
"Return:
"String containing array values.
"**
function ReplaceListItem( array, index, item )
if a:index == 0
return substitute( a:array, '^[^' .g:listSep. ']\+', a:item, "" )
else
return substitute( a:array, '\(\%(\%(^\|' . g:listSep . '\)[^' . g:listSep . ']\+\)\{' . a:index . '\}\)' . g:listSep . '[^' . g:listSep . ']\+', '\1' . g:listSep . a:item , "" )
endif
endfunction
"**
"RemoveListItem:
" Remove item at given position.
"Parameters:
" - array : Array/List (string of values) from which remove an item.
" - index : Integer indicating the position of item to remove.
" It must be greater than or equals to 0 (zero).
"Return:
"String containing array values, except the removed one.
"**
function RemoveListItem( array, index )
if a:index == 0
return substitute( a:array, '^[^' .g:listSep. ']\+\(' . g:listSep . '\|$\)', "", "" )
else
return substitute( a:array, '\(\%(\%(^\|' . g:listSep . '\)[^' . g:listSep . ']\+\)\{' . a:index . '\}\)' . g:listSep . '[^' . g:listSep . ']\+', '\1', "" )
endif
endfunction
"**
"ExchangeListItems:
" Exchange item at position item1Index with item at position item2Index.
"Parameters:
" - array : Array/List (string of values).
" - item1index : Integer indicating the position of the first item to exchange.
" It must be greater than or equals to 0 (zero).
" - item2index : Integer indicating the position of the second item to
" exchange. It must be greater than or equals to 0 (zero).
"Return:
"String containing array values.
"**
function ExchangeListItems( array, item1Index, item2Index )
let item1 = GetListItem( a:array, a:item1Index )
let array = ReplaceListItem( a:array, a:item1Index, GetListItem( a:array, a:item2Index ) )
return ReplaceListItem( array, a:item2Index, item1 )
endfunction
"**
"GetListCount:
" Number of items in array.
"Parameters:
" - array : Array/List (string of values).
"Return:
"Integer representing the number of items in array.
"Index of last item is GetListCount(array)-1.
"**
function GetListCount( array )
if a:array == "" | return 0 | endif
let pos = 0
let cnt = 0
while pos != -1
let pos = matchend( a:array, g:listSep, pos )
let cnt = cnt + 1
endwhile
return cnt
endfunction
"**
"QuickSortList:
" Sort array.
"Parameters:
" - array : Array/List (string of values).
" - beg : Min index of the range of items to sort.
" - end : Max index of the range of items to sort.
"Return:
"String containing array values with indicated range of items sorted.
"**
function QuickSortList( array, beg, end )
let array = a:array
let pivot = GetListItem( array, a:beg )
let l = a:beg
let r = a:end
while l < r
while GetListItem( array, r ) > pivot
let r = r - 1
endwhile
if l != r
let array = ReplaceListItem( array, l, GetListItem( array, r ) )
let array = ReplaceListItem( array, r, pivot )
let l = l + 1
endif
while GetListItem( array, l ) < pivot
let l = l + 1
endwhile
if l != r
let array = ReplaceListItem( array, r, GetListItem( array, l ) )
let array = ReplaceListItem( array, l, pivot )
let r = r - 1
endif
endwhile
if a:beg < l-1
let array = QuickSortList( array, a:beg, l-1 )
endif
if a:end > l+1
let array = QuickSortList( array, l+1, a:end )
endif
return array
endfunction

View file

@ -0,0 +1,163 @@
" File: remoteOpen.vim
" Author: Srinath Avadhanula <srinath AT fastmail DOT fm>
" $Id: remoteOpen.vim 1080 2010-01-26 22:02:34Z tmaas $
"
" Description:
" Often times, an external program needs to open a file in gvim from the
" command line. However, it will not know if the file is already opened in a
" previous vim session. It is not sufficient to simply specify
"
" gvim --remote-silent <filename>
"
" because this simply opens up <filename> in the first remote gvim session it
" sees. This script provides a command RemoteOpen which is meant to be used
" from the command line as follows:
"
" gvim -c ":RemoteOpen +<lnum> <filename>"
"
" where <lnum> is the line-number you wish <filename> to open to. What will
" happen is that a new gvim will start up and enquire from all previous
" sessions if <filename> is already open in any of them. If it is, then it
" will edit the file in that session and bring it to the foreground and itself
" quit. Otherwise, it will not quit and instead open up the file for editing
" at <lnum>.
"
" This was mainly created to be used with Yap (the dvi previewer in miktex),
" so you can specify the program for "inverse search" as specified above.
" This ensures that the inverse search uses the correct gvim each time.
"
" Ofcourse, this requires vim with +clientserver. If not, then RemoteOpen just
" opens in the present session.
" Enclose <args> in single quotes so it can be passed as a function argument.
com! -nargs=1 RemoteOpen :call RemoteOpen('<args>')
com! -nargs=? RemoteInsert :call RemoteInsert('<args>')
" RemoteOpen: open a file remotely (if possible) {{{
" Description: checks all open vim windows to see if this file has been opened
" anywhere and if so, opens it there instead of in this session.
function! RemoteOpen(arglist)
" First construct line number and filename from argument. a:arglist is of
" the form:
" +10 c:\path\to\file
" or just
" c:\path\to\file
if a:arglist =~ '^\s*+\d\+'
let linenum = matchstr(a:arglist, '^\s*+\zs\d\+\ze')
let filename = matchstr(a:arglist, '^\s*+\d\+\s*\zs.*\ze')
else
let linenum = 1
let filename = matchstr(a:arglist, '^\s*\zs.*\ze')
endif
let filename = escape(filename, ' ')
call Tex_Debug("linenum = ".linenum.', filename = '.filename, "ropen")
" If there is no clientserver functionality, then just open in the present
" session and return
if !has('clientserver')
call Tex_Debug("-clientserver, opening locally and returning", "ropen")
exec "e ".filename
exec linenum
normal! zv
return
endif
" Otherwise, loop through all available servers
let servers = serverlist()
" If there are no servers, open file locally.
if servers == ''
call Tex_Debug("no open servers, opening locally", "ropen")
exec "e ".filename
exec linenum
let g:Remote_Server = 1
normal! zv
return
endif
let i = 1
let server = s:Strntok(servers, "\n", i)
let targetServer = v:servername
while server != ''
" Find out if there was any server which was used by remoteOpen before
" this. If a new gvim session was ever started via remoteOpen, then
" g:Remote_Server will be set.
if remote_expr(server, 'exists("g:Remote_Server")')
let targetServer = server
endif
" Ask each server if that file is being edited by them.
let bufnum = remote_expr(server, "bufnr('".filename."')")
" If it is...
if bufnum != -1
" ask the server to edit that file and come to the foreground.
" set a variable g:Remote_Server to indicate that this server
" session has at least one file opened via RemoteOpen
let targetServer = server
break
end
let i = i + 1
let server = s:Strntok(servers, "\n", i)
endwhile
" If none of the servers have the file open, then open this file in the
" first server. This has the advantage if yap tries to make vim open
" multiple vims, then at least they will all be opened by the same gvim
" server.
call remote_send(targetServer,
\ "\<C-\>\<C-n>".
\ ":let g:Remote_Server = 1\<CR>".
\ ":drop ".filename."\<CR>".
\ ":".linenum."\<CR>zv"
\ )
call remote_foreground(targetServer)
" quit this vim session
if v:servername != targetServer
q
endif
endfunction " }}}
" RemoteInsert: inserts a \cite'ation remotely (if possible) {{{
" Description:
function! RemoteInsert(...)
let citation = matchstr(argv(0), "\\[InsText('.cite{\\zs.\\{-}\\ze}');\\]")
if citation == ""
q
endif
" Otherwise, loop through all available servers
let servers = serverlist()
let i = 1
let server = s:Strntok(servers, "\n", i)
let targetServer = v:servername
while server != ''
if remote_expr(server, 'exists("g:Remote_WaitingForCite")')
call remote_send(server, citation . "\<CR>")
call remote_foreground(server)
if v:servername != server
q
else
return
endif
endif
let i = i + 1
let server = s:Strntok(servers, "\n", i)
endwhile
q
endfunction " }}}
" Strntok: extract the n^th token from a list {{{
" example: Strntok('1,23,3', ',', 2) = 23
fun! <SID>Strntok(s, tok, n)
return matchstr( a:s.a:tok[0], '\v(\zs([^'.a:tok.']*)\ze['.a:tok.']){'.a:n.'}')
endfun
" }}}
" vim:ft=vim:ts=4:sw=4:noet:fdm=marker:commentstring=\"\ %s:nowrap