~spacexplorer/+junk/myenv

« back to all changes in this revision

Viewing changes to vim/vim/plugin/SyntaxFolds.vim

  • Committer: Kim Allamandola
  • Date: 2011-05-02 05:39:17 UTC
  • Revision ID: spacexplorer@gmail.com-20110502053917-x0yl2lr9ri4yskr2
InitĀ import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
" ==============================================================================
 
2
"        File: syntaxFolds.vim
 
3
"      Author: Srinath Avadhanula
 
4
"              ( srinath@fastmail.fm )
 
5
" Last Change: Sun Oct 27 01:00 AM 2002 PST
 
6
" Description: Emulation of the syntax folding capability of vim using manual
 
7
"              folding
 
8
"
 
9
" This script provides an emulation of the syntax folding of vim using manual
 
10
" folding. Just as in syntax folding, the folds are defined by regions. Each
 
11
" region is specified by a call to FoldRegions() which accepts 4 parameters:
 
12
"
 
13
"    call FoldRegions(startpat, endpat, startoff, endoff)
 
14
"
 
15
"    startpat: a line matching this pattern defines the beginning of a fold.
 
16
"    endpat  : a line matching this pattern defines the end of a fold.
 
17
"    startoff: this is the offset from the starting line at which folding will
 
18
"              actually start
 
19
"    endoff  : like startoff, but gives the offset of the actual fold end from
 
20
"              the line satisfying endpat.
 
21
"              startoff and endoff are necessary when the folding region does
 
22
"              not have a specific end pattern corresponding to a start
 
23
"              pattern. for example in latex,
 
24
"              \begin{section}
 
25
"              defines the beginning of a section, but its not necessary to
 
26
"              have a corresponding
 
27
"              \end{section}
 
28
"              the section is assumed to end 1 line _before_ another section
 
29
"              starts.
 
30
"    startskip: a pattern which defines the beginning of a "skipped" region.
 
31
"
 
32
"               For example, suppose we define a \itemize fold as follows:
 
33
"               startpat =  '^\s*\\item',
 
34
"               endpat = '^\s*\\item\|^\s*\\end{\(enumerate\|itemize\|description\)}',
 
35
"               startoff = 0,
 
36
"               endoff = -1
 
37
"
 
38
"               This defines a fold which starts with a line beginning with an
 
39
"               \item and ending one line before a line beginning with an
 
40
"               \item or \end{enumerate} etc.
 
41
"
 
42
"               Then, as long as \item's are not nested things are fine.
 
43
"               However, once items begin to nest, the fold started by one
 
44
"               \item can end because of an \item in an \itemize
 
45
"               environment within this \item. i.e, the following can happen:
 
46
"
 
47
"               \begin{itemize}
 
48
"               \item Some text <------- fold will start here
 
49
"                     This item will contain a nested item
 
50
"                     \begin{itemize} <----- fold will end here because next line contains \item...
 
51
"                     \item Hello
 
52
"                     \end{itemize} <----- ... instead of here.
 
53
"               \item Next item of the parent itemize
 
54
"               \end{itemize}
 
55
"
 
56
"               Therefore, in order to completely define a folding item which
 
57
"               allows nesting, we need to also define a "skip" pattern.
 
58
"               startskip and end skip do that.
 
59
"               Leave '' when there is no nesting.
 
60
"    endskip: the pattern which defines the end of the "skip" pattern for
 
61
"             nested folds.
 
62
"
 
63
"    Example: 
 
64
"    1. A syntax fold region for a latex section is
 
65
"           startpat = "\\section{"
 
66
"           endpat   = "\\section{"
 
67
"           startoff = 0
 
68
"           endoff   = -1
 
69
"           startskip = ''
 
70
"           endskip = ''
 
71
"    Note that the start and end patterns are thus the same and endoff has a
 
72
"    negative value to capture the effect of a section ending one line before
 
73
"    the next starts.
 
74
"    2. A syntax fold region for the \itemize environment is:
 
75
"           startpat = '^\s*\\item',
 
76
"           endpat = '^\s*\\item\|^\s*\\end{\(enumerate\|itemize\|description\)}',
 
77
"           startoff = 0,
 
78
"           endoff = -1,
 
79
"           startskip = '^\s*\\begin{\(enumerate\|itemize\|description\)}',
 
80
"           endskip = '^\s*\\end{\(enumerate\|itemize\|description\)}'
 
81
"     Note the use of startskip and endskip to allow nesting.
 
82
"
 
83
"
 
84
" Each time a call is made to FoldRegions(), all the regions (which might be
 
85
" disjoint, but not nested) are folded up.
 
86
" Nested folds can be created by successive calls to FoldRegions(). The first
 
87
" call defines the region which is deepest in the folding. See MakeTexFolds()
 
88
" for an idea of how this works for latex files.
 
89
 
 
90
" Function: AddSyntaxFoldItem (start, end, startoff, endoff [, skipStart, skipEnd]) {{{
 
91
function! AddSyntaxFoldItem(start, end, startoff, endoff, ...)
 
92
        if a:0 > 0
 
93
                let skipStart = a:1
 
94
                let skipEnd = a:2
 
95
        else
 
96
                let skipStart = ''
 
97
                let skipEnd = ''
 
98
        end
 
99
        if !exists('b:numFoldItems')
 
100
                let b:numFoldItems = 0
 
101
        end
 
102
        let b:numFoldItems = b:numFoldItems + 1
 
103
 
 
104
        exe 'let b:startPat_'.b:numFoldItems.' = a:start'
 
105
        exe 'let b:endPat_'.b:numFoldItems.' = a:end'
 
106
        exe 'let b:startOff_'.b:numFoldItems.' = a:startoff'
 
107
        exe 'let b:endOff_'.b:numFoldItems.' = a:endoff'
 
108
        exe 'let b:skipStartPat_'.b:numFoldItems.' = skipStart'
 
109
        exe 'let b:skipEndPat_'.b:numFoldItems.' = skipEnd'
 
110
endfunction 
 
111
 
 
112
 
 
113
" }}}
 
114
" Function: MakeSyntaxFolds (force) {{{
 
115
" Description: This function calls FoldRegions() several times with the
 
116
"     parameters specifying various regions resulting in a nested fold
 
117
"     structure for the file.
 
118
function! MakeSyntaxFolds(force, ...)
 
119
        if exists('b:doneFolding') && a:force == 0
 
120
                return
 
121
        end
 
122
 
 
123
        let skipEndPattern = ''
 
124
        if a:0 > 0
 
125
                let line1 = a:1
 
126
                let skipEndPattern = '\|'.a:2
 
127
        else
 
128
                let line1 = 1
 
129
                let r = line('.')
 
130
                let c = virtcol('.')
 
131
                
 
132
                setlocal fdm=manual
 
133
                normal! zE
 
134
        end
 
135
        if !exists('b:numFoldItems')
 
136
                b:numFoldItems = 1000000
 
137
        end
 
138
        
 
139
        let i = 1
 
140
 
 
141
        let maxline = line('.')
 
142
 
 
143
        while exists('b:startPat_'.i) && i <= b:numFoldItems
 
144
                exe 'let startPat = b:startPat_'.i
 
145
                exe 'let endPat = b:endPat_'.i
 
146
                exe 'let startOff = b:startOff_'.i
 
147
                exe 'let endOff = b:endOff_'.i
 
148
                
 
149
                let skipStart = ''
 
150
                let skipEnd = ''
 
151
                if exists('b:skipStartPat_'.i)
 
152
                        exe 'let skipStart = b:skipStartPat_'.i
 
153
                        exe 'let skipEnd = b:skipEndPat_'.i
 
154
                end
 
155
                exe line1
 
156
                let lastLoc = line1
 
157
 
 
158
                if skipStart != ''
 
159
                        call InitStack('BeginSkipArray')
 
160
                        call FoldRegionsWithSkip(startPat, endPat, startOff, endOff, skipStart, skipEnd, 1, line('$'))
 
161
                        " call PrintError('done folding ['.startPat.']')
 
162
                else
 
163
                        call FoldRegionsWithNoSkip(startPat, endPat, startOff, endOff, 1, line('$'), '')
 
164
                end
 
165
 
 
166
                let i = i + 1
 
167
        endwhile
 
168
 
 
169
        exe maxline
 
170
        
 
171
        if a:0 == 0
 
172
                exe r
 
173
                exe "normal! ".c."|"
 
174
                if foldlevel(r) > 1
 
175
                        exe "normal! ".(foldlevel(r) - 1)."zo"
 
176
                end
 
177
                let b:doneFolding = 0
 
178
        end
 
179
endfunction
 
180
 
 
181
 
 
182
" }}}
 
183
" FoldRegionsWithSkip: folding things such as \item's which can be nested. {{{
 
184
function! FoldRegionsWithSkip(startpat, endpat, startoff, endoff, startskip, endskip, line1, line2)
 
185
        exe a:line1
 
186
        " count the regions which have been skipped as we go along. do not want to
 
187
        " create a fold which with a beginning or end line in one of the skipped
 
188
        " regions.
 
189
        let skippedRegions = ''
 
190
 
 
191
        " start searching for either the starting pattern or the end pattern.
 
192
        while search(a:startskip.'\|'.a:endskip, 'W')
 
193
        
 
194
                if getline('.') =~ a:endskip
 
195
 
 
196
                        let lastBegin = Pop('BeginSkipArray')
 
197
                        " call PrintError('popping '.lastBegin.' from stack and folding till '.line('.'))
 
198
                        call FoldRegionsWithNoSkip(a:startpat, a:endpat, a:startoff, a:endoff, lastBegin, line('.'), skippedRegions)
 
199
                        let skippedRegions = skippedRegions.lastBegin.','.line('.').'|'
 
200
 
 
201
 
 
202
                " if this is the beginning of a skip region, then, push this line as
 
203
                " the beginning of a skipped region.
 
204
                elseif getline('.') =~ a:startskip
 
205
 
 
206
                        " call PrintError('pushing '.line('.').' ['.getline('.').'] into stack')
 
207
                        call Push('BeginSkipArray', line('.'))
 
208
 
 
209
                end
 
210
        endwhile
 
211
 
 
212
        " call PrintError('with skip starting at '.a:line1.' returning at line# '.line('.'))
 
213
endfunction
 
214
 
 
215
" }}}
 
216
" FoldRegionsWithNoSkip: folding things such as \sections which do not nest. {{{
 
217
function! FoldRegionsWithNoSkip(startpat, endpat, startoff, endoff, line1, line2, skippedRegions)
 
218
        exe a:line1
 
219
 
 
220
        " call PrintError('line1 = '.a:line1.', searching from '.line('.').'... for ['.a:startpat.'')
 
221
        let lineBegin = s:MySearch(a:startpat, 'in')
 
222
        " call PrintError('... and finding it at '.lineBegin)
 
223
 
 
224
        while lineBegin <= a:line2
 
225
                if IsInSkippedRegion(lineBegin, a:skippedRegions)
 
226
                        let lineBegin = s:MySearch(a:startpat, 'out')
 
227
                        " call PrintError(lineBegin.' is being skipped')
 
228
                        continue
 
229
                end
 
230
                let lineEnd = s:MySearch(a:endpat, 'out')
 
231
                while IsInSkippedRegion(lineEnd, a:skippedRegions) && lineEnd <= a:line2
 
232
                        let lineEnd = s:MySearch(a:endpat, 'out')
 
233
                endwhile
 
234
                if lineEnd > a:line2
 
235
                        exe (lineBegin + a:startoff).','.a:line2.' fold'
 
236
                        break
 
237
                else
 
238
                        " call PrintError ('for ['.a:startpat.'] '.(lineBegin + a:startoff).','.(lineEnd + a:endoff).' fold')
 
239
                        exe (lineBegin + a:startoff).','.(lineEnd + a:endoff).' fold'
 
240
                end
 
241
 
 
242
                " call PrintError('line1 = '.a:line1.', searching from '.line('.').'... for ['.a:startpat.'')
 
243
                let lineBegin = s:MySearch(a:startpat, 'in')
 
244
                " call PrintError('... and finding it at '.lineBegin)
 
245
        endwhile
 
246
 
 
247
        exe a:line2
 
248
        return
 
249
endfunction
 
250
 
 
251
" }}}
 
252
" InitStack: initialize a stack {{{
 
253
function! InitStack(name)
 
254
        exe 'let s:'.a:name.'_numElems = 0'
 
255
endfunction
 
256
" }}}
 
257
" Push: push element into stack {{{
 
258
function! Push(name, elem)
 
259
        exe 'let numElems = s:'.a:name.'_numElems'
 
260
        let numElems = numElems + 1
 
261
        exe 'let s:'.a:name.'_Element_'.numElems.' = a:elem'
 
262
        exe 'let s:'.a:name.'_numElems = numElems'
 
263
endfunction
 
264
" }}}
 
265
" Pop: pops element off stack {{{
 
266
function! Pop(name)
 
267
        exe 'let numElems = s:'.a:name.'_numElems'
 
268
        if numElems == 0
 
269
                return ''
 
270
        else
 
271
                exe 'let ret = s:'.a:name.'_Element_'.numElems
 
272
                let numElems = numElems - 1
 
273
                exe 'let s:'.a:name.'_numElems = numElems'
 
274
                return ret
 
275
        end
 
276
endfunction
 
277
" }}}
 
278
" MySearch: just like search(), but returns large number on failure {{{
 
279
function! <SID>MySearch(pat, opt)
 
280
        if a:opt == 'in'
 
281
                if getline('.') =~ a:pat
 
282
                        let ret = line('.')
 
283
                else
 
284
                        let ret = search(a:pat, 'W')
 
285
                end
 
286
        else
 
287
                normal! $
 
288
                let ret = search(a:pat, 'W')
 
289
        end
 
290
 
 
291
        if ret == 0
 
292
                let ret = line('$') + 1
 
293
        end
 
294
        return ret
 
295
endfunction
 
296
" }}}
 
297
" Function: IsInSkippedRegion (lnum, regions) {{{
 
298
" Description: finds whether a given line number is within one of the regions
 
299
"              skipped.
 
300
function! IsInSkippedRegion(lnum, regions)
 
301
        let i = 1
 
302
        let subset = s:Strntok(a:regions, '|', i)
 
303
        while subset != ''
 
304
                let n1 = s:Strntok(subset, ',', 1)
 
305
                let n2 = s:Strntok(subset, ',', 2)
 
306
                if a:lnum >= n1 && a:lnum <= n2
 
307
                        return 1
 
308
                end
 
309
 
 
310
                let subset = s:Strntok(a:regions, '|', i)
 
311
                let i = i + 1
 
312
        endwhile
 
313
 
 
314
        return 0
 
315
endfunction " }}}
 
316
" Function: Strntok (string, tok, n) {{{
 
317
" extract the n^th token from s seperated by tok.
 
318
" example: Strntok('1,23,3', ',', 2) = 23
 
319
fun! <SID>Strntok(s, tok, n)
 
320
        return matchstr( a:s.a:tok[0], '\v(\zs([^'.a:tok.']*)\ze['.a:tok.']){'.a:n.'}')
 
321
endfun " }}}
 
322
 
 
323
" vim600:fdm=marker