Show
Ignore:
Timestamp:
10/02/07 16:13:00 (16 months ago)
Author:
kana
Message:

lang/vim/surround:
* Support n-stroke key for user-defined objects.
* Change the way to register user-defined objects.

Location:
lang/vim/surround/trunk
Files:
2 modified

Legend:

Unmodified
Added
Removed
  • lang/vim/surround/trunk/doc/surround.txt

    r336 r339  
    155155CUSTOMIZING                                     *surround-customizing* 
    156156 
     157NOTE: There are some incompatible changes from the original version. 
     158See |surrounding-customizing-difference| for the detail. 
     159 
    157160The following adds a potential replacement on "-" (ASCII 45) in PHP files. 
    158161(To determine the ASCII code to use, :echo char2nr("-")).  The carriage 
     
    207210  let g:surround_insert_tail = "<++>" 
    208211< 
     212                                        *surrounding-customizing-difference* 
     213DIFFERENCE FROM THE ORIGINAL VERSION ~ 
     214 
     215The original way - g:surround_{char2nr(key)} - is no longer supported.  Please 
     216use |SurroundRegister| and |SurroundUnregister| to register/unregister 
     217user-defined surrounding objects. 
     218 
     219Tips: 
     220        g:surround_{char2nr(key)} = template    ~ 
     221        b:surround_{char2nr(key)} = template    ~ 
     222and 
     223        call SurroundRegister('g', key, template)       ~ 
     224        call SurroundRegister('b', key, template)       ~ 
     225have same meaning. 
     226 
     227SurroundRegister({type}, {key}, {template})             *SurroundRegister* 
     228        Register new user-defined surrounding object. 
     229 
     230        {type}  ('b' or 'g') 
     231                The scope of this object. 
     232                'b' means buffer-local and 
     233                'g' means global. 
     234 
     235        {key}   (string with 1 or more characters) 
     236                Key stroke for this object. 
     237 
     238        {template} 
     239                Template for this object. 
     240                See |surrounding-customizing| for the detail. 
     241 
     242SurroundUnregister({type}, {key})                       *SurroundUnregister* 
     243        Unregister user-defined surrounding object corresponding to 
     244        the givin {key}. 
     245 
    209246ISSUES                                          *surround-issues* 
    210247 
     
    229266 
    230267CHANGELOG                                       *surround-changelog* 
     268 
     2692007-10-01T22:46:14+09:00       kana    <http://nicht.s8.xrea.com/> 
     270 
     271        - INCOMPATIBLE CHANGE: the way of |surround-customizing| is changed. 
     272          See |surrounding-customizing-difference| for the detail. 
     273 
     274        - Support n-stroke key for user-defined surrounding objects. 
    231275 
    2322762007-10-01T03:43:51+09:00       kana    <http://nicht.s8.xrea.com/> 
  • lang/vim/surround/trunk/plugin/surround.vim

    r338 r339  
    4646 
    4747function! s:inputtarget() 
     48    let key = '' 
    4849    let c = s:getchar() 
    49     while c =~ '^\d\+$' 
    50         let c = c . s:getchar() 
     50    while c =~ '\d' 
     51        let key = key . c 
     52        let c = s:getchar() 
    5153    endwhile 
    52     if c == " " 
    53         let c = c . s:getchar() 
    54     endif 
    55     if c =~ "\<Esc>\|\<C-C>\|\0" 
     54 
     55    call feedkeys(c, 't') 
     56    let t = s:user_obj_input() 
     57    if t != '' 
     58        return key . t 
     59    endif 
     60    let key = key . s:getchar() 
     61 
     62    if key == " " 
     63        let key = key . s:getchar() 
     64    endif 
     65    if key =~ "\<Esc>\|\<C-C>\|\0" 
    5666        return "" 
    5767    else 
    58         return c 
     68        return key 
    5969    endif 
    6070endfunction 
     
    6272function! s:inputreplacement() 
    6373    "echo '-- SURROUND --' 
     74    let key = '' 
    6475    let c = s:getchar() 
    6576    if c == " " 
    66         let c = c . s:getchar() 
    67     endif 
    68     if c =~ "\<Esc>" || c =~ "\<C-C>" 
     77        let key = key . c 
     78        let c = s:getchar() 
     79    endif 
     80 
     81    call feedkeys(c, 't') 
     82    let t = s:user_obj_input() 
     83    if t != '' 
     84        return key . t 
     85    endif 
     86    let key = key . s:getchar() 
     87 
     88    if key =~ "\<Esc>" || key =~ "\<C-C>" 
    6989        return "" 
    7090    else 
    71         return c 
     91        return key 
    7292    endif 
    7393endfunction 
     
    183203    endif 
    184204    let idx = stridx(pairs,newchar) 
    185     let user_defined_object = s:get_user_defined_object(newchar) 
     205    let user_defined_object = s:user_obj_value(newchar) 
    186206    if newchar == ' ' 
    187207        let before = '' 
     
    436456    " move the target text range into @@, then delete surroudings  "{{{3 
    437457    let strcount = (scount == 1 ? "" : scount) 
    438     let user_defined_object = s:get_user_defined_object(char) 
     458    let user_defined_object = s:user_obj_value(char) 
    439459    if len(user_defined_object)  " FIXME: [count] is not supported yet 
    440460        let all = s:process(user_defined_object) 
     
    622642  
    623643 
     644" Trie  "{{{2 
     645" 
     646" trie ::= {'root': node, 
     647"           'default_value': <any value>} 
     648" default-value ::= <any value> 
     649" node ::= {'value': <any value>, 
     650"           'children': {<a part of key (1 char)>: node, 
     651"                        ...}} 
     652 
     653let s:trie = {} 
     654let s:FALSE = 0 
     655let s:TRUE = !s:FALSE 
     656 
     657 
     658function! s:trie.new(default_value)  "{{{3 
     659    let new_instance = copy(s:trie) 
     660    let new_instance.root = s:trie.node.new(a:default_value) 
     661    let new_instance.default_value = a:default_value 
     662    return new_instance 
     663endfunction 
     664 
     665 
     666function! s:trie.dump()  "{{{3 
     667    echomsg 'Trie:' 
     668    echomsg '  default_value:' string(self.default_value) 
     669    call self.root.dump('root', 1) 
     670endfunction 
     671 
     672 
     673function! s:trie.put(sequence, value)  "{{{3 
     674    let node = self.root 
     675    let i = 0 
     676    while i < len(a:sequence) 
     677        let item = a:sequence[i] 
     678        if !has_key(node.children, item) 
     679            let node.children[item] = s:trie.node.new(self.default_value) 
     680        endif 
     681        let node = node.children[item] 
     682        let i = i + 1 
     683    endwhile 
     684    let old_value = node.value 
     685    let node.value = a:value 
     686    return old_value 
     687endfunction 
     688 
     689 
     690function! s:trie.get(sequence, accept_halfway_matchp, ...)  "{{{3 
     691    let default_value = a:0 ? a:1 : self.default_value 
     692    let node = self.root 
     693    let i = 0 
     694    while i < len(a:sequence) 
     695        let item = a:sequence[i] 
     696        if !has_key(node.children, item) 
     697            return default_value 
     698        endif 
     699        let node = node.children[item] 
     700        let i = i + 1 
     701    endwhile 
     702 
     703    if node.leafp() || a:accept_halfway_matchp 
     704        return node.value 
     705    else 
     706        return default_value 
     707    endif 
     708endfunction 
     709 
     710 
     711function! s:trie.take(sequence)  "{{{3 
     712    if len(a:sequence) == 0 
     713        throw 'empty sequence is not allowed' 
     714    endif 
     715    let parent = self.root 
     716    let node = self.root 
     717    let i = 0 
     718    while i < len(a:sequence) 
     719        let item = a:sequence[i] 
     720        if !has_key(node.children, item) 
     721            throw 'value corresponding to the given sequence is not found' 
     722        endif 
     723        let parent = node 
     724        let node = node.children[item] 
     725        let i = i + 1 
     726    endwhile 
     727    return remove(parent.children, item).value 
     728endfunction 
     729 
     730 
     731function! s:trie.get_incremental(accept_halfway_matchp, ...)  "{{{3 
     732    let state = {} 
     733    let state.accept_halfway_matchp = a:accept_halfway_matchp 
     734    let state.default_value = a:0 ? a:1 : self.default_value 
     735    let state.node = self.root 
     736    let state.i = 0 
     737 
     738    function state.feed(item) 
     739        if !has_key(self.node.children, a:item) 
     740            return [s:trie.FAILED, self.default_value] 
     741        endif 
     742        let self.node = self.node.children[a:item] 
     743        let self.i = self.i + 1 
     744 
     745        if self.node.leafp() || self.accept_halfway_matchp 
     746            return [s:trie.MATCHED, self.node.value] 
     747        else 
     748            return [s:trie.CONTINUED, self.default_value] 
     749        endif 
     750    endfunction 
     751 
     752    return state 
     753endfunction 
     754 
     755let s:trie.CONTINUED = ['CONTINUED'] 
     756let s:trie.FAILED = ['FAILED'] 
     757let s:trie.MATCHED = ['MATCHED'] 
     758 
     759 
     760let s:trie.node = {}  "{{{3 
     761 
     762function! s:trie.node.new(value) 
     763    let new_instance = copy(s:trie.node) 
     764    let new_instance.value = a:value 
     765    let new_instance.children = {} 
     766    return new_instance 
     767endfunction 
     768 
     769function! s:trie.node.leafp() 
     770    return len(self.children) == 0 
     771endfunction 
     772 
     773function! s:trie.node.dump(label, lv) 
     774    echomsg s:indent(a:lv) string(a:label) ':' string(self.value) 
     775    for key in sort(keys(self.children)) 
     776        call self.children[key].dump(key, a:lv+1) 
     777    endfor 
     778endfunction 
     779 
     780 
     781 
     782 
     783" User-defined surrounding objects  "{{{2 
     784 
     785function! s:user_obj_trie(type) 
     786    if a:type ==# 'b' 
     787        if !exists('b:surround_objects') 
     788            let b:surround_objects = s:trie.new('') 
     789        endif 
     790        return b:surround_objects 
     791    else  " a:type ==# 'g' 
     792        if !exists('g:surround_objects') 
     793            let g:surround_objects = s:trie.new('') 
     794        endif 
     795        return g:surround_objects 
     796    endif 
     797endfunction 
     798 
     799 
     800function! SurroundRegister(type, key, template) 
     801    return s:user_obj_trie(a:type).put(a:key, a:template) 
     802endfunction 
     803 
     804function! SurroundUnregister(type, key) 
     805    return s:user_obj_trie(a:type).take(a:key) 
     806endfunction 
     807 
     808 
     809function! s:user_obj_input() 
     810    let [result, key] = s:user_obj_input_sub('b') 
     811    if result is s:trie.FAILED 
     812        call feedkeys(key, 't') 
     813        let [result, key] = s:user_obj_input_sub('g') 
     814        if result is s:trie.FAILED 
     815            call feedkeys(key, 't') 
     816            return '' 
     817        endif 
     818    endif 
     819 
     820    return key 
     821endfunction 
     822 
     823function! s:user_obj_input_sub(type) 
     824    let state = s:user_obj_trie(a:type).get_incremental(s:FALSE, 'not-used') 
     825    let key = '' 
     826    while 1 
     827        let c = s:getchar() 
     828        let [result, _] = state.feed(c) 
     829        let key = key . c 
     830        if result is s:trie.MATCHED 
     831            break 
     832        elseif result is s:trie.FAILED 
     833            break 
     834        else  " result is s:trie.CONTINUED 
     835            " NOP 
     836        endif 
     837    endwhile 
     838    return [result, key] 
     839endfunction 
     840 
     841 
     842function! s:user_obj_value(key) 
     843    let Template = s:user_obj_trie('b').get(a:key, s:FALSE, '') 
     844    if Template == '' 
     845        let Template = s:user_obj_trie('g').get(a:key, s:FALSE, '') 
     846    endif 
     847 
     848    if type(Template) == type('string') 
     849        return Template 
     850    else  " function? 
     851        return Template() 
     852    endif 
     853endfunction 
     854 
     855 
     856 
     857 
    624858" Misc. functions  "{{{2 
    625859 
     
    628862endfunction 
    629863 
     864 
    630865function! s:literalize_pattern(pattern) 
    631866    return '\V'.substitute(a:pattern, '\', '\\', 'g') 
    632867endfunction 
    633868 
    634 function! s:get_user_defined_object(char) 
    635     if exists("b:surround_".char2nr(a:char)) 
    636         let Value = b:surround_{char2nr(a:char)} 
    637     elseif exists("*b:surround_".char2nr(a:char)) 
    638         let Value = function('b:surround_'.char2nr(a:char)) 
    639     elseif exists("g:surround_".char2nr(a:char)) 
    640         let Value = g:surround_{char2nr(a:char)} 
    641     elseif exists("*g:surround_".char2nr(a:char)) 
    642         let Value = function('g:surround_'.char2nr(a:char)) 
    643     else 
    644         let Value = '' 
    645     endif 
    646  
    647     if type(Value) == type('string') 
    648         return Value 
    649     else  " function? 
    650         return Value() 
    651     endif 
     869 
     870function! s:indent(level) 
     871    return repeat('  ', a:level)[1:] 
    652872endfunction 
    653873