[Vim-latex-cvs] vimfiles/plugin imaps.vim,1.9.2.3,1.9.2.4
Brought to you by:
srinathava,
tmaas
From: <ma...@us...> - 2002-12-18 16:36:22
|
Update of /cvsroot/vim-latex/vimfiles/plugin In directory sc8-pr-cvs1:/tmp/cvs-serv24432/plugin Modified Files: Tag: b-newimaps imaps.vim Log Message: I implemented yet another new syntax for IMAP() and IMAP_PutTextWithMovement(): IMAP(lhs, rhs, ft, ...) IMAP_PutTextWithMovement(str, ...) In both cases, the optinal arguments are place holders, such as "<<" and ">>". If not supplied, the default values "<+" and "+>" are used. IMAP() saves these in script variables, which are then read by s:LookupCharacter() and passed to IMAP_PutTextWithMovement(). Index: imaps.vim =================================================================== RCS file: /cvsroot/vim-latex/vimfiles/plugin/imaps.vim,v retrieving revision 1.9.2.3 retrieving revision 1.9.2.4 diff -C2 -d -r1.9.2.3 -r1.9.2.4 *** imaps.vim 14 Dec 2002 14:22:23 -0000 1.9.2.3 --- imaps.vim 18 Dec 2002 16:36:19 -0000 1.9.2.4 *************** *** 8,12 **** " while preserving filetype indentation. " ! " Last Change: Sat Dec 14 09:00 AM 2002 EST " " Documentation: {{{ --- 8,12 ---- " while preserving filetype indentation. " ! " Last Change: Wed Dec 18 11:00 AM 2002 EST " " Documentation: {{{ *************** *** 130,234 **** " the previously typed characters and erased and the right hand side is " inserted - function! IMAP(ft, lhs, ...) - let lastLHSChar = a:lhs[strlen(a:lhs)-1] - " Add a:lhs to the list of left-hand sides that end with lastLHSChar: - if !exists("s:LHS_" . a:ft . "_" . s:Hash(lastLHSChar)) - let s:LHS_{a:ft}_{s:Hash(lastLHSChar)} = escape(a:lhs, '\') - else - let s:LHS_{a:ft}_{s:Hash(lastLHSChar)} = escape(a:lhs, "\\") . '\|' . - \ s:LHS_{a:ft}_{s:Hash(lastLHSChar)} - endif - - " Build up the right-hand side: - let rhs = "" - let phs = s:PlaceHolderStart() " default <+ - let phe = s:PlaceHolderEnd() " default +> - let i = 1 " counter for arguments - let template = 0 " flag: is the current argument a <+template+> ? - while i <= a:0 - if template - let rhs = rhs . phs . a:{i} . phe - else - let rhs = rhs . a:{i} - endif - let i = i+1 - let template = !template - endwhile - let s:Map_{a:ft}_{s:Hash(a:lhs)} = rhs - - " map only the last character of the left-hand side. - if lastLHSChar == ' ' - let lastLHSChar = '<space>' - end - exe 'inoremap <silent>' escape(lastLHSChar, '|') - \ '<C-r>=<SID>NewLookupCharacter("' . escape(lastLHSChar, '\|') . - \ '")<CR>' - endfunction ! " }}} ! " Tex_IMAP: This is the old version of IMAP which used to take 3 arguments. {{{ ! " It has been changed in order to retain backwards compatibility (of ! " sorts) while still using the new IMAP ! " It could also be used for convenience in places where specifying multiple ! " arguments might be tedious. ! " ! " Ex: ! " ! " call Tex_IMAP('foo', 'ba<++>bar', '', '<+', '+>') " ! " The last 2 optional arguments specify the placeholder characters in the rhs. ! " See s:PlaceHolderStart() and s:PlaceHolderEnd() for how they are chosen if ! " the the optional arguments are unspecified. ! function! Tex_IMAP(lhs, rhs, ft, ...) ! if a:0 > 0 ! let phs = a:1 ! let phe = a:2 ! else ! " Tex_IMAP is only concerned with mappings which latex-suite itself ! " generates. This means that we do not use the g:Imap_PlaceHolder* ! " settings. let phs = '<+' let phe = '+>' endif - let startpat = escape(phs, '\') - let endpat = escape(phe, '\') ! " This might not work in all cases, but it is a good idea. ! " Problem: \ or " or ' in a:rhs ... ! " " Change 'ba<++>bar' into '"ba", "", "bar"' ! " let args = '"' . escape(a:rhs, '\"') . '"' ! " let args = substitute(args, '\V' . startpat . '\|' . endpat, '","', "g") ! " let callString = 'call IMAP(a:ft, a:lhs,' . args . ')' ! ! " break up the rhs into multiple chunks ! let remainingString = a:rhs ! let callString = 'call IMAP(a:ft, a:lhs' ! " Use \V so that we do not have to worry about magic characters. ! let pat = '\V' . '\(\.\{-}\)' .startpat. '\(\.\{-}\)' .endpat. '\(\.\*\)' ! let i = 1 ! while remainingString =~ pat ! let arg_{i} = substitute(remainingString, pat, '\1', '') ! let callString = callString.', arg_'.i ! let arg_{i+1} = substitute(remainingString, pat, '\2', '') ! let callString = callString.', arg_'.(i+1) ! let remainingString = substitute(remainingString, pat, '\3', '') ! let i = i+2 ! if i >= 20 ! echomsg 'getting more than 20 placeholders!' ! echomsg 'input rhs = '.a:rhs ! endif ! endwhile ! if strlen(remainingString) ! let arg_{i} = remainingString ! let callString = callString.', arg_'.i endif ! " Finally, we end up with a string like: ! " 'call IMAP(a:ft, a:lhs, arg_1, arg_2, arg_3)' ! let callString = callString.')' ! ! exec callString endfunction --- 130,177 ---- " 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>' (a:ft== '' ? '' : '<buffer>') ! \ escape(lastLHSChar, '|') ! \ '<C-r>=<SID>LookupCharacter("' . ! \ escape(lastLHSChar, '\|') . ! \ '")<CR>' endfunction *************** *** 236,244 **** " LookupCharacter: inserts mapping corresponding to this character {{{ " ! " This function performs a reverse lookup when this character is typed in. It ! " loops over all the possible left-hand side variables ending in this ! " character and then if a possible match exists, erases the left-hand side ! " and inserts the right-hand side instead. ! function! s:NewLookupCharacter(char) let charHash = s:Hash(a:char) --- 179,187 ---- " 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) let charHash = s:Hash(a:char) *************** *** 254,259 **** " escaped when building up s:LHS_{ft}_{charHash} . let text = strpart(getline("."), 0, col(".")-1) . a:char ! " matchstr() returns the longest match. This automatically ensures that ! " the longest LHS is used for the mapping. let lhs = matchstr(text, '\V\(' . s:LHS_{ft}_{charHash} . '\)\$') if strlen(lhs) == 0 --- 197,202 ---- " escaped when building up s:LHS_{ft}_{charHash} . let text = strpart(getline("."), 0, col(".")-1) . a:char ! " matchstr() returns the match that starts first. This automatically ! " ensures that the longest LHS is used for the mapping. let lhs = matchstr(text, '\V\(' . s:LHS_{ft}_{charHash} . '\)\$') if strlen(lhs) == 0 *************** *** 263,357 **** " character typed: let bs = substitute(strpart(lhs, 1), ".", "\<bs>", "g") ! " Execute this string to get to the start of the replacement text: ! let mark = line(".") . "norm!" . (virtcol(".") - strlen(lhs) + 1) . "|" ! return bs . IMAP_PutTextWithMovement(s:Map_{ft}_{s:Hash(lhs)}, mark) ! endfunction ! ! " Old version: ! function! <SID>LookupCharacter(char) ! let charHash = char2nr(a:char) ! ! if !exists('s:charLens_'.&ft.'_'.charHash) ! \ && !exists('s:charLens__'.charHash) ! return a:char ! end ! ! let k = 1 ! while k <= 2 ! " first check the filetype specific mappings and then the general ! " purpose mappings. ! if k == 1 ! let ft = &ft ! else ! let ft = '' ! end ! ! " get the lengths of the left-hand side mappings which end in this ! " character. if no mappings ended in this character, then continue... ! if !exists('s:charLens_'.ft.'_'.charHash) ! let k = k + 1 ! continue ! end ! ! exe 'let lens = s:charLens_'.ft.'_'.charHash ! ! let i = 1 ! while 1 ! " get the i^th length. ! let numchars = s:Strntok(lens, ',', i) ! " if there are no more lengths, then skip to the next outer while ! " loop. ! if numchars == '' ! break ! end ! ! if col('.') < numchars ! let i = i + 1 ! continue ! end ! ! " get the corresponding text from before the text. append the present ! " char to complete the (possible) LHS ! let text = strpart(getline('.'), col('.') - numchars, numchars - 1).a:char ! let lhsHash = 's:Map_'.ft.'_'.substitute(text, '\(\W\)', '\="_".char2nr(submatch(1))."_"', 'g') ! ! " if there is no mapping of this length which satisfies the previously ! " typed in characters, then proceed to the next length group... ! if !exists(lhsHash) ! let i = i + 1 ! continue ! end ! ! " ... otherwise insert the corresponding RHS ! " first generate the required number of back-spaces to erase the ! " previously typed in characters. ! exe "let tokLHS = s:LenStr_".numchars ! let bkspc = substitute(tokLHS, '.$', '', '') ! let bkspc = substitute(bkspc, '.', "\<bs>", "g") ! ! " get the corresponding RHS ! exe "let ret = ".lhsHash ! ! return bkspc.Tex_PutTextWithMovement(ret) ! ! endwhile ! ! let k = k + 1 ! endwhile ! ! return a:char endfunction " }}} ! " IMAP_PutTextWithMovement: appends movement commands to a text {{{ ! " This enables which cursor placement. ! function! IMAP_PutTextWithMovement(text, mark) ! let text = a:text ! let phs = s:PlaceHolderStart() ! let phe = s:PlaceHolderEnd() let startpat = escape(phs, '\') let endpat = escape(phe, '\') " If the user does not want to use place-holders, then remove them. if exists('g:Imap_UsePlaceHolders') && !g:Imap_UsePlaceHolders --- 206,242 ---- " character typed: let bs = substitute(strpart(lhs, 1), ".", "\<bs>", "g") ! let hash = s:Hash(lhs) ! return bs . IMAP_PutTextWithMovement(s:Map_{ft}_{hash}, ! \ s:phs_{ft}_{hash}, s:phe_{ft}_{hash}) 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, ...) ! " Find the place holders for the input. ! if a:0 < 2 ! let phs = '<+' ! let phe = '+>' ! else ! let phs = a:1 ! let phe = a:2 ! endif let startpat = escape(phs, '\') let endpat = escape(phe, '\') + " A very rare string: + let marker = phs . phs . phe . phe + " TODO: Maybe I need to play some games with iconv() to define marker and + " markerpat in case marker !~ marker ... + let text = a:str " If the user does not want to use place-holders, then remove them. if exists('g:Imap_UsePlaceHolders') && !g:Imap_UsePlaceHolders *************** *** 365,394 **** endif ! " template = first <+{...}+> in text, where {...} may be empty. ! let template = matchstr(text, '\V' . startpat . '\.\{-}' . endpat) " If there are no place holders, just return the text. ! if strlen(template) == 0 ! echomsg 'searching for \V' . startpat . '\.\{-}' . endpat . ' in ' . text return text endif " Now, start building the return value. " Return to Normal mode: this works even if 'insertmode' is set: let text = text . "\<C-\>\<C-N>" ! " Start at the position given by mark: ! let text = text . ":" . a:mark . "\<CR>" ! " Look for the first place holder: ! let text = text . ":call search('\\V" . startpat . "', 'W')\<CR>" " Finally, append commands to Select <+template+> or replace <++> . ! " Enter Visual mode and move to the end. Use a search strategy instead of ! " computing the length of the template because strlen() returns different ! " things depending on the encoding. ! let text = text . "v/\\V" . endpat . "/e\<CR>\<ESC>" ! \ . s:RemoveLastHistoryItem . "\<CR>gv" ! if template == phs . phe ! " template looks like <++> so Change it: let text = text . "c" ! else ! " Enter Select mode. let text = text . "\<C-G>" endif --- 250,290 ---- endif ! let pattern = '\V\(\.\{-}\)' .startpat. '\(\.\{-}\)' .endpat. '\(\.\*\)' " If there are no place holders, just return the text. ! if text !~ pattern return text endif + " Break text up into "initial <+template+> final"; any piece may be empty. + let initial = substitute(text, pattern, '\1', '') + let template = substitute(text, pattern, '\2', '') + let final = substitute(text, pattern, '\3', '') + + " Now, get the place holders for the output. + let phs = s:PlaceHolderStart() " default <+ + let phe = s:PlaceHolderEnd() " default +> + let template = phs . template . phe + let final = substitute(final, startpat, escape(phs, '\'), 'g') + let final = substitute(final, endpat, escape(phe, '\'), 'g') " Now, start building the return value. + let text = initial . marker . template . marker . final " Return to Normal mode: this works even if 'insertmode' is set: let text = text . "\<C-\>\<C-N>" ! " Move to the first marker and delete it. Cursor ends on beginning of ! " template. ! let text = text . "2?" . marker . "\<CR>" . "v/" . marker . "/e\<CR>x" ! " Enter Visual mode and move to just before the next marker. ! let text = text . "v/" . marker . "/s-1\<CR>\<C-\>\<C-N>" ! " Move to the second marker and delete it. ! let text = text . "/" . marker . "\<CR>" . "d/" . marker . "/e\<CR>" ! " Note: We use a search strategy instead of computing the length of the ! " template because strlen() returns different things depending on the ! " encoding. ! " Clean up the search history. Restore Visual selection. ! let text = text . ":" . s:RemoveLastHistoryItem . "\<CR>gv" " Finally, append commands to Select <+template+> or replace <++> . ! if template == phs . phe " template looks like <++> so Change it: let text = text . "c" ! else " Enter Select mode. let text = text . "\<C-G>" endif |