├── .gitignore ├── README.txt ├── autoload ├── voom.vim └── voom │ └── voom_vimplugin2657 │ ├── __init__.py │ ├── voom_mode_asciidoc.py │ ├── voom_mode_cwiki.py │ ├── voom_mode_dokuwiki.py │ ├── voom_mode_fmr.py │ ├── voom_mode_fmr1.py │ ├── voom_mode_fmr2.py │ ├── voom_mode_fmr3.py │ ├── voom_mode_hashes.py │ ├── voom_mode_html.py │ ├── voom_mode_inverseAtx.py │ ├── voom_mode_latex.py │ ├── voom_mode_latexDtx.py │ ├── voom_mode_markdown.py │ ├── voom_mode_org.py │ ├── voom_mode_pandoc.py │ ├── voom_mode_paragraphBlank.py │ ├── voom_mode_paragraphIndent.py │ ├── voom_mode_paragraphNoIndent.py │ ├── voom_mode_python.py │ ├── voom_mode_rest.py │ ├── voom_mode_taskpaper.py │ ├── voom_mode_thevimoutliner.py │ ├── voom_mode_txt2tags.py │ ├── voom_mode_viki.py │ ├── voom_mode_vimoutliner.py │ ├── voom_mode_vimwiki.py │ ├── voom_mode_wiki.py │ └── voom_vim.py ├── doc └── voom.txt └── plugin └── voom.vim /.gitignore: -------------------------------------------------------------------------------- 1 | __pycache__ 2 | *.pyc 3 | *.bat 4 | *.vbs 5 | *.lnk 6 | *.sh 7 | 8 | -------------------------------------------------------------------------------- /README.txt: -------------------------------------------------------------------------------- 1 | This is a mirror of http://www.vim.org/scripts/script.php?script_id=2657 2 | -------------------------------------------------------------------------------- /autoload/voom/voom_vimplugin2657/__init__.py: -------------------------------------------------------------------------------- 1 | # Dummy file to make this directory a Python package. 2 | -------------------------------------------------------------------------------- /autoload/voom/voom_vimplugin2657/voom_mode_asciidoc.py: -------------------------------------------------------------------------------- 1 | # File: voom_mode_asciidoc.py 2 | # Last Modified: 2017-01-07 3 | # Description: VOoM -- two-pane outliner plugin for Python-enabled Vim 4 | # Website: http://www.vim.org/scripts/script.php?script_id=2657 5 | # Author: Vlad Irnov (vlad DOT irnov AT gmail DOT com) 6 | # License: CC0, see http://creativecommons.org/publicdomain/zero/1.0/ 7 | 8 | """ 9 | VOoM markup mode for AsciiDoc document and section titles. 10 | See |voom-mode-asciidoc|, ../../../doc/voom.txt#*voom-mode-asciidoc* 11 | """ 12 | 13 | ### NOTES 14 | # 15 | # When outline operation changes level, it has to deal with two ambiguities: 16 | # a) Level 1-5 headline can use 2-style (underline) or 1-style (=). 17 | # b) 1-style can have or not have closing ='s. 18 | # To determine current preferences: check first headline at level <6 and check 19 | # first headline with =. This must be done in hook_makeOutline(). 20 | # (Save in VO, similar to reST mode.) Cannot be done during outline operation, 21 | # that is in hook_doBodyAfterOop(). 22 | # Defaults: use underline, use closing ='s. 23 | 24 | try: 25 | import vim 26 | if vim.eval('exists("g:voom_asciidoc_do_blanks")')=='1' and vim.eval("g:voom_asciidoc_do_blanks")=='0': 27 | DO_BLANKS = False 28 | else: 29 | DO_BLANKS = True 30 | except ImportError: 31 | DO_BLANKS = True 32 | 33 | import sys 34 | if sys.version_info[0] > 2: 35 | xrange = range 36 | def len_u(s, enc): 37 | return len(s) 38 | else: 39 | def len_u(s, enc): 40 | return len(unicode(s, enc, 'replace')) 41 | 42 | import re 43 | 44 | 45 | # regex for 1-style headline, assumes there is no trailing whitespace 46 | HEAD_MATCH = re.compile(r'^(=+)(\s+\S.*?)(\s+\1)?$').match 47 | 48 | #--------------------------------------------------------------------- 49 | # Characters used as underlines in two-line headlines. 50 | ADS_LEVELS = {'=' : 1, '-' : 2, '~' : 3, '^' : 4, '+' : 5} 51 | # Characters for Delimited Blocks. Headines are ignored inside such blocks. 52 | BLOCK_CHARS = {'/' : 0, '+' : 0, '-' : 0, '.' : 0, '*' : 0, '_' : 0, '=' : 0} 53 | 54 | #LEVELS_ADS = {1:'=', 2:'-', 3:'~', 4:'^', 5:'+'} 55 | LEVELS_ADS = {} 56 | for k in ADS_LEVELS: 57 | LEVELS_ADS[ADS_LEVELS[k]] = k 58 | # Combine all signficant chars. Need one of these at start of line for a headline or DelimitedBlock to occur. 59 | CHARS = {} 60 | for k in ADS_LEVELS: 61 | CHARS[k] = 0 62 | for k in BLOCK_CHARS: 63 | CHARS[k] = 0 64 | #--------------------------------------------------------------------- 65 | 66 | def hook_makeOutline(VO, blines): 67 | """Return (tlines, bnodes, levels) for Body lines blines. 68 | blines is either Vim buffer object (Body) or list of buffer lines. 69 | """ 70 | ENC = VO.enc 71 | Z = len(blines) 72 | tlines, bnodes, levels = [], [], [] 73 | tlines_add, bnodes_add, levels_add = tlines.append, bnodes.append, levels.append 74 | 75 | # trailing whitespace is always removed with rstrip() 76 | # if headline is precedeed by [AAA] and/or [[AAA]], bnode is set to their lnum 77 | # 78 | # 1-style, overrides 2-style 79 | # [[AAA]] L3, blines[i-2] 80 | # [yyy] L2, blines[i-1] 81 | # == head == L1, blines[i] -- current line, closing = are optional 82 | # 83 | # 2-style (underline) 84 | # [[AAA]] L4, blines[i-3] 85 | # [yyy] L3, blines[i-2] 86 | # head L2, blines[i-1] -- title line, many restrictions on the format 87 | # ---- L1, blines[i] -- current line 88 | 89 | 90 | # Set this the first time a headline with level 1-5 is encountered. 91 | # 0 or 1 -- False, use 2-style (default); 2 -- True, use 1-style 92 | useOne = 0 93 | # Set this the first time headline in 1-style is encountered. 94 | # 0 or 1 -- True, use closing ='s (default); 2 -- False, do not use closing ='s 95 | useOneClose = 0 96 | 97 | isHead = False 98 | isFenced = False # True if inside DelimitedBlock, the value is the char 99 | headI = -2 # idx of the last line that is part of a headline 100 | blockI = -2 # idx of the last line where a DelimitedBlock ended 101 | m = None # match object for 1-style regex 102 | 103 | for i in xrange(Z): 104 | L1 = blines[i].rstrip() 105 | if not L1 or not L1[0] in CHARS: 106 | continue 107 | ch = L1[0] 108 | 109 | if isFenced: 110 | if isFenced==ch and len(L1)>3 and L1.lstrip(ch)=='': 111 | isFenced = False 112 | blockI = i 113 | continue 114 | 115 | # 1-style headline 116 | if ch == '=' and L1.strip('='): 117 | m = HEAD_MATCH(L1) 118 | if m: 119 | isHead = True 120 | headI_ = headI 121 | headI = i 122 | lev = len(m.group(1)) 123 | head = m.group(2).strip() 124 | bnode = i+1 125 | 126 | # current line is an underline 127 | # the previous, underlined line (L2) is not a headline if it: 128 | # is not exactly the length of underline +/- 2 129 | # is already part of in the previous headline 130 | # looks like an underline or a delimited block line 131 | # is [[AAA]] or [AAA] (BlockID or Attribute List) 132 | # starts with . (Block Title, they have no level) 133 | # starts with // (comment line) 134 | # starts with tab (don't know why, spaces are ok) 135 | # is only 1 chars (avoids confusion with --, as in Vim syntax, not as in AsciiDoc) 136 | if not isHead and ch in ADS_LEVELS and L1.lstrip(ch)=='' and i > 0: 137 | L2 = blines[i-1].rstrip() 138 | z2 = len_u(L2, ENC) 139 | z1 = len(L1) 140 | if (L2 and 141 | (-3 < z2 - z1 < 3) and z1 > 1 and z2 > 1 and 142 | headI != i-1 and 143 | not ((L2[0] in CHARS) and L2.lstrip(L2[0])=='') and 144 | not (L2.startswith('[') and L2.endswith(']')) and 145 | not L2.startswith('.') and 146 | not L2.startswith('\t') and 147 | not (L2.startswith('//') and not L2.startswith('///')) 148 | ): 149 | isHead = True 150 | headI_ = headI 151 | headI = i 152 | lev = ADS_LEVELS[ch] 153 | head = L2.strip() 154 | bnode = i # lnum of previous line (L2) 155 | 156 | if isHead and bnode > 1: 157 | # decrement bnode if preceding lines are [[AAA]] or [AAA] lines 158 | # that is set bnode to the topmost [[AAA]] or [AAA] line number 159 | j_ = bnode-2 # idx of line before the title line 160 | L3 = blines[bnode-2].rstrip() 161 | while L3.startswith('[') and L3.endswith(']'): 162 | bnode -= 1 163 | if bnode > 1: 164 | L3 = blines[bnode-2].rstrip() 165 | else: 166 | break 167 | 168 | # headline must be preceded by a blank line unless: 169 | # it's line 1 (j == -1) 170 | # headline is preceded by [AAA] or [[AAA]] lines (j != j_) 171 | # previous line is a headline (headI_ == j) 172 | # previous line is the end of a DelimitedBlock (blockI == j) 173 | j = bnode-2 174 | if DO_BLANKS and j==j_ and j > -1: 175 | L3 = blines[j].rstrip() 176 | if L3 and headI_ != j and blockI != j: 177 | # skip over any adjacent comment lines 178 | while L3.startswith('//') and not L3.startswith('///'): 179 | j -= 1 180 | if j > -1: 181 | L3 = blines[j].rstrip() 182 | else: 183 | L3 = '' 184 | if L3 and headI_ != j and blockI != j: 185 | isHead = False 186 | headI = headI_ 187 | 188 | # start of DelimitedBlock 189 | if not isHead and ch in BLOCK_CHARS and len(L1)>3 and L1.lstrip(ch)=='': 190 | isFenced = ch 191 | continue 192 | 193 | if isHead: 194 | isHead = False 195 | # save style info for first headline and first 1-style headline 196 | if not useOne and lev < 6: 197 | if m: 198 | useOne = 2 199 | else: 200 | useOne = 1 201 | if not useOneClose and m: 202 | if m.group(3): 203 | useOneClose = 1 204 | else: 205 | useOneClose = 2 206 | # make outline 207 | tline = ' %s|%s' %('. '*(lev-1), head) 208 | tlines_add(tline) 209 | bnodes_add(bnode) 210 | levels_add(lev) 211 | 212 | # don't clobber these when parsing clipboard during Paste 213 | # which is the only time blines is not Body 214 | if blines is VO.Body: 215 | VO.useOne = useOne == 2 216 | VO.useOneClose = useOneClose < 2 217 | 218 | return (tlines, bnodes, levels) 219 | 220 | 221 | def hook_newHeadline(VO, level, blnum, tlnum): 222 | """Return (tree_head, bodyLines). 223 | tree_head is new headline string in Tree buffer (text after |). 224 | bodyLines is list of lines to insert in Body buffer. 225 | """ 226 | tree_head = 'NewHeadline' 227 | if level < 6 and not VO.useOne: 228 | bodyLines = [tree_head, LEVELS_ADS[level]*11, ''] 229 | else: 230 | lev = '='*level 231 | if VO.useOneClose: 232 | bodyLines = ['%s %s %s' %(lev, tree_head, lev), ''] 233 | else: 234 | bodyLines = ['%s %s' %(lev, tree_head), ''] 235 | 236 | # Add blank line when inserting after non-blank Body line. 237 | if VO.Body[blnum-1].strip(): 238 | bodyLines[0:0] = [''] 239 | 240 | return (tree_head, bodyLines) 241 | 242 | 243 | #def hook_changeLevBodyHead(VO, h, levDelta): 244 | # DO NOT CREATE THIS HOOK 245 | 246 | 247 | def hook_doBodyAfterOop(VO, oop, levDelta, blnum1, tlnum1, blnum2, tlnum2, blnumCut, tlnumCut): 248 | # this is instead of hook_changeLevBodyHead() 249 | 250 | # Based on Markdown mode function. 251 | # Inserts blank separator lines if missing. 252 | 253 | #print('oop=%s levDelta=%s blnum1=%s tlnum1=%s blnum2=%s tlnum2=%s tlnumCut=%s blnumCut=%s' % (oop, levDelta, blnum1, tlnum1, blnum2, tlnum2, tlnumCut, blnumCut)) 254 | Body = VO.Body 255 | Z = len(Body) 256 | bnodes, levels = VO.bnodes, VO.levels 257 | ENC = VO.enc 258 | 259 | # blnum1 blnum2 is first and last lnums of Body region pasted, inserted 260 | # during up/down, or promoted/demoted. 261 | if blnum1: 262 | assert blnum1 == bnodes[tlnum1-1] 263 | if tlnum2 < len(bnodes): 264 | assert blnum2 == bnodes[tlnum2]-1 265 | else: 266 | assert blnum2 == Z 267 | 268 | # blnumCut is Body lnum after which a region was removed during 'cut', 269 | # 'up', 'down'. Need this to check if there is blank line between nodes 270 | # used to be separated by the cut/moved region. 271 | if blnumCut: 272 | if tlnumCut < len(bnodes): 273 | assert blnumCut == bnodes[tlnumCut]-1 274 | else: 275 | assert blnumCut == Z 276 | 277 | # Total number of added lines minus number of deleted lines. 278 | b_delta = 0 279 | 280 | ### After 'cut' or 'up': insert blank line if there is none 281 | # between the nodes used to be separated by the cut/moved region. 282 | if DO_BLANKS and (oop=='cut' or oop=='up') and (0 < blnumCut < Z) and Body[blnumCut-1].strip(): 283 | Body[blnumCut:blnumCut] = [''] 284 | update_bnodes(VO, tlnumCut+1 ,1) 285 | b_delta+=1 286 | 287 | if oop=='cut': 288 | return 289 | 290 | ### Make sure there is blank line after the last node in the region: 291 | # insert blank line after blnum2 if blnum2 is not blank, that is insert 292 | # blank line before bnode at tlnum2+1. 293 | if DO_BLANKS and blnum2 < Z and Body[blnum2-1].strip(): 294 | Body[blnum2:blnum2] = [''] 295 | update_bnodes(VO, tlnum2+1 ,1) 296 | b_delta+=1 297 | 298 | ### Change levels and/or formats of headlines in the affected region. 299 | # Always do this after Paste, even if level is unchanged -- format can 300 | # be different when pasting from other outlines. 301 | # Examine each headline, from bottom to top, and change level and/or format. 302 | # To change from 1-style to 2-style: 303 | # strip ='s, strip whitespace; 304 | # insert underline. 305 | # To change from 2-style to 1-style: 306 | # delete underline; 307 | # insert ='s. 308 | # Update bnodes after inserting or deleting a line. 309 | # 310 | # NOTE: bnode can be [[AAA]] or [AAA] line, we check for that and adjust it 311 | # to point to the headline text line 312 | # 313 | # 1-style 2-style 314 | # 315 | # L0 L0 Body[bln-2] 316 | # == head L1 head L1 <--bnode Body[bln-1] (not always the actual bnode) 317 | # L2 ---- L2 Body[bln] 318 | # L3 L3 Body[bln+1] 319 | 320 | if levDelta or oop=='paste': 321 | for i in xrange(tlnum2, tlnum1-1, -1): 322 | # required level (VO.levels has been updated) 323 | lev = levels[i-1] 324 | # current level from which to change to lev 325 | lev_ = lev - levDelta 326 | 327 | # Body headline (bnode) and the next line 328 | bln = bnodes[i-1] 329 | L1 = Body[bln-1].rstrip() 330 | # bnode can point to the tompost [AAA] or [[AAA]] line 331 | # increment bln until the actual headline (title line) is found 332 | while L1.startswith('[') and L1.endswith(']'): 333 | bln += 1 334 | L1 = Body[bln-1].rstrip() 335 | # the underline line 336 | if bln < len(Body): 337 | L2 = Body[bln].rstrip() 338 | else: 339 | L2 = '' 340 | 341 | # get current headline format 342 | hasOne, hasOneClose = False, VO.useOneClose 343 | theHead = L1 344 | if L1.startswith('='): 345 | m = HEAD_MATCH(L1) 346 | if m: 347 | hasOne = True 348 | # headline without ='s but with whitespace around it preserved 349 | theHead = m.group(2) 350 | theclose = m.group(3) 351 | if theclose: 352 | hasOneClose = True 353 | theHead += theclose.rstrip('=') 354 | else: 355 | hasOneClose = False 356 | 357 | # get desired headline format 358 | if oop=='paste': 359 | if lev > 5: 360 | useOne = True 361 | else: 362 | useOne = VO.useOne 363 | useOneClose = VO.useOneClose 364 | elif lev < 6 and lev_ < 6: 365 | useOne = hasOne 366 | useOneClose = hasOneClose 367 | elif lev > 5 and lev_ > 5: 368 | useOne = True 369 | useOneClose = hasOneClose 370 | elif lev < 6 and lev_ > 5: 371 | useOne = VO.useOne 372 | useOneClose = VO.useOneClose 373 | elif lev > 5 and lev_ < 6: 374 | useOne = True 375 | useOneClose = hasOneClose 376 | else: 377 | assert False 378 | #print('useOne=%s hasOne=%s useOneClose=%s hasOneClose=%s' %(useOne, hasOne, useOneClose, hasOneClose)) 379 | 380 | ### change headline level and/or format 381 | # 2-style unchanged, only adjust level of underline 382 | if not useOne and not hasOne: 383 | if not levDelta: continue 384 | Body[bln] = LEVELS_ADS[lev]*len(L2) 385 | # 1-style unchanged, adjust level of ='s and add/remove closing ='s 386 | elif useOne and hasOne: 387 | # no format change, there are closing ='s 388 | if useOneClose and hasOneClose: 389 | if not levDelta: continue 390 | Body[bln-1] = '%s%s%s' %('='*lev, theHead, '='*lev) 391 | # no format change, there are no closing ='s 392 | elif not useOneClose and not hasOneClose: 393 | if not levDelta: continue 394 | Body[bln-1] = '%s%s' %('='*lev, theHead) 395 | # add closing ='s 396 | elif useOneClose and not hasOneClose: 397 | Body[bln-1] = '%s%s %s' %('='*lev, theHead.rstrip(), '='*lev) 398 | # remove closing ='s 399 | elif not useOneClose and hasOneClose: 400 | Body[bln-1] = '%s%s' %('='*lev, theHead.rstrip()) 401 | # insert underline, remove ='s 402 | elif not useOne and hasOne: 403 | L1 = theHead.strip() 404 | Body[bln-1] = L1 405 | # insert underline 406 | Body[bln:bln] = [LEVELS_ADS[lev] * len_u(L1, ENC)] 407 | update_bnodes(VO, i+1, 1) 408 | b_delta+=1 409 | # remove underline, insert ='s 410 | elif useOne and not hasOne: 411 | if useOneClose: 412 | Body[bln-1] = '%s %s %s' %('='*lev, theHead.strip(), '='*lev) 413 | else: 414 | Body[bln-1] = '%s %s' %('='*lev, theHead.strip()) 415 | # delete underline 416 | Body[bln:bln+1] = [] 417 | update_bnodes(VO, i+1, -1) 418 | b_delta-=1 419 | 420 | ### Make sure first headline is preceded by a blank line. 421 | blnum1 = bnodes[tlnum1-1] 422 | if DO_BLANKS and blnum1 > 1 and Body[blnum1-2].strip(): 423 | Body[blnum1-1:blnum1-1] = [''] 424 | update_bnodes(VO, tlnum1 ,1) 425 | b_delta+=1 426 | 427 | ### After 'down' : insert blank line if there is none 428 | # between the nodes used to be separated by the moved region. 429 | if DO_BLANKS and oop=='down' and (0 < blnumCut < Z) and Body[blnumCut-1].strip(): 430 | Body[blnumCut:blnumCut] = [''] 431 | update_bnodes(VO, tlnumCut+1 ,1) 432 | b_delta+=1 433 | 434 | assert len(Body) == Z + b_delta 435 | 436 | 437 | def update_bnodes(VO, tlnum, delta): 438 | """Update VO.bnodes by adding/substracting delta to each bnode 439 | starting with bnode at tlnum and to the end. 440 | """ 441 | bnodes = VO.bnodes 442 | for i in xrange(tlnum, len(bnodes)+1): 443 | bnodes[i-1] += delta 444 | 445 | 446 | -------------------------------------------------------------------------------- /autoload/voom/voom_vimplugin2657/voom_mode_cwiki.py: -------------------------------------------------------------------------------- 1 | # File: voom_mode_cwiki.py 2 | # Last Modified: 2017-01-07 3 | # Description: VOoM -- two-pane outliner plugin for Python-enabled Vim 4 | # Website: http://www.vim.org/scripts/script.php?script_id=2657 5 | # Author: Vlad Irnov (vlad DOT irnov AT gmail DOT com) 6 | # License: CC0, see http://creativecommons.org/publicdomain/zero/1.0/ 7 | 8 | """ 9 | VOoM markup mode for cwiki Vim plugin. Contributed by Craig B. Allen. 10 | http://www.vim.org/scripts/script.php?script_id=2176 11 | See |voom-mode-various|, ../../../doc/voom.txt#*voom-mode-various* 12 | 13 | +++ headline level 1 14 | some text 15 | ++++ headline level 2 16 | more text 17 | +++++ headline level 3 18 | ++++++ headline level 4 19 | etc. 20 | 21 | First + must be at start of line. Whitespace after the last + is optional. 22 | """ 23 | 24 | import sys 25 | if sys.version_info[0] > 2: 26 | xrange = range 27 | 28 | import re 29 | headline_match = re.compile(r'^\+\+(\++)').match 30 | 31 | 32 | def hook_makeOutline(VO, blines): 33 | """Return (tlines, bnodes, levels) for Body lines blines. 34 | blines is either Vim buffer object (Body) or list of buffer lines. 35 | """ 36 | Z = len(blines) 37 | tlines, bnodes, levels = [], [], [] 38 | tlines_add, bnodes_add, levels_add = tlines.append, bnodes.append, levels.append 39 | for i in xrange(Z): 40 | if not blines[i].startswith('+'): 41 | continue 42 | bline = blines[i] 43 | m = headline_match(bline) 44 | if not m: 45 | continue 46 | lev = len(m.group(1)) 47 | head = bline[2+lev:].strip() 48 | tline = ' %s|%s' %('. '*(lev-1), head) 49 | tlines_add(tline) 50 | bnodes_add(i+1) 51 | levels_add(lev) 52 | return (tlines, bnodes, levels) 53 | 54 | 55 | def hook_newHeadline(VO, level, blnum, tlnum): 56 | """Return (tree_head, bodyLines). 57 | tree_head is new headline string in Tree buffer (text after |). 58 | bodyLines is list of lines to insert in Body buffer. 59 | """ 60 | tree_head = 'NewHeadline' 61 | bodyLines = ['++%s %s' %('+'*level, tree_head), ''] 62 | return (tree_head, bodyLines) 63 | 64 | 65 | def hook_changeLevBodyHead(VO, h, levDelta): 66 | """Increase of decrease level number of Body headline by levDelta.""" 67 | if levDelta==0: return h 68 | m = headline_match(h) 69 | level = len(m.group(1)) 70 | return '++%s%s' %('+'*(level+levDelta), h[m.end(1):]) 71 | 72 | 73 | -------------------------------------------------------------------------------- /autoload/voom/voom_vimplugin2657/voom_mode_dokuwiki.py: -------------------------------------------------------------------------------- 1 | # File: voom_mode_dokuwiki.py 2 | # Last Modified: 2017-01-07 3 | # Description: VOoM -- two-pane outliner plugin for Python-enabled Vim 4 | # Website: http://www.vim.org/scripts/script.php?script_id=2657 5 | # Author: Vlad Irnov (vlad DOT irnov AT gmail DOT com) 6 | # License: CC0, see http://creativecommons.org/publicdomain/zero/1.0/ 7 | 8 | """ 9 | VOoM markup mode for DokuWiki sections. 10 | See |voom-mode-dokuwiki|, ../../../doc/voom.txt#*voom-mode-dokuwiki* 11 | """ 12 | # based on voom_mode_inverseAtx.py 13 | 14 | try: 15 | import vim 16 | except ImportError: 17 | pass 18 | 19 | import sys 20 | if sys.version_info[0] > 2: 21 | xrange = range 22 | 23 | import re 24 | 25 | headline_match = re.compile(r'^( ?| \t[ \t]*)(={2,})(.+?)(={2,})[ \t]*$').match 26 | # Marker character that denotes a headline in the regexp above. 27 | CHAR = '=' 28 | # The maximum possible level. 29 | # The number of leading marker characters for level 1 headline is MAX+1 or more. 30 | MAX = 5 31 | 32 | def hook_makeOutline(VO, blines): 33 | """Return (tlines, bnodes, levels) for Body lines blines. 34 | blines is either Vim buffer object (Body) or list of buffer lines. 35 | """ 36 | Z = len(blines) 37 | tlines, bnodes, levels = [], [], [] 38 | tlines_add, bnodes_add, levels_add = tlines.append, bnodes.append, levels.append 39 | for i in xrange(Z): 40 | if not blines[i].lstrip().startswith(CHAR): 41 | continue 42 | bline = blines[i] 43 | m = headline_match(bline) 44 | if not m: 45 | continue 46 | n = len(m.group(2)) 47 | if n > MAX: 48 | lev = 1 49 | else: 50 | lev = MAX - n + 2 51 | head = m.group(3).strip() 52 | tline = ' %s|%s' %('. '*(lev-1), head) 53 | tlines_add(tline) 54 | bnodes_add(i+1) 55 | levels_add(lev) 56 | return (tlines, bnodes, levels) 57 | 58 | 59 | def hook_newHeadline(VO, level, blnum, tlnum): 60 | """Return (tree_head, bodyLines). 61 | tree_head is new headline string in Tree buffer (text after |). 62 | bodyLines is list of lines to insert in Body buffer. 63 | """ 64 | tree_head = 'NewHeadline' 65 | if level >= MAX: 66 | C = CHAR 67 | else: 68 | C = CHAR * (MAX - level + 1) 69 | bodyLines = ['=%s %s =%s' %(C, tree_head, C), ''] 70 | return (tree_head, bodyLines) 71 | 72 | 73 | #def hook_changeLevBodyHead(VO, h, levDelta): 74 | 75 | def hook_doBodyAfterOop(VO, oop, levDelta, blnum1, tlnum1, blnum2, tlnum2, blnumCut, tlnumCut): 76 | # this is instead of hook_changeLevBodyHead() 77 | #print('oop=%s levDelta=%s blnum1=%s tlnum1=%s blnum2=%s tlnum2=%s tlnumCut=%s blnumCut=%s' % (oop, levDelta, blnum1, tlnum1, blnum2, tlnum2, tlnumCut, blnumCut)) 78 | Body = VO.Body 79 | Z = len(Body) 80 | bnodes, levels = VO.bnodes, VO.levels 81 | 82 | # blnum1 blnum2 is first and last lnums of Body region pasted, inserted 83 | # during up/down, or promoted/demoted. 84 | if blnum1: 85 | assert blnum1 == bnodes[tlnum1-1] 86 | if tlnum2 < len(bnodes): 87 | assert blnum2 == bnodes[tlnum2]-1 88 | else: 89 | assert blnum2 == Z 90 | 91 | # blnumCut is Body lnum after which a region was removed during 'cut' 92 | if blnumCut: 93 | if tlnumCut < len(bnodes): 94 | assert blnumCut == bnodes[tlnumCut]-1 95 | else: 96 | assert blnumCut == Z 97 | 98 | ### Change levels and/or sections of headlines in the affected region. 99 | if not levDelta: 100 | return 101 | 102 | # Examine each headline in the affected region from top to bottom. 103 | # Change levels. 104 | # Correct levels that exceed the MAX: set them to MAX. 105 | invalid_levs = [] # tree lnums of nodes with level > MAX 106 | for i in xrange(tlnum1, tlnum2+1): 107 | # required level based on new VO.levels, can be disallowed 108 | lev_ = levels[i-1] 109 | # Body line 110 | bln = bnodes[i-1] 111 | L = Body[bln-1] # original Body headline line 112 | 113 | if lev_ <= MAX: 114 | n = MAX - lev_ + 1 115 | # MAX level exceeded 116 | else: 117 | n = 1 118 | invalid_levs.append(i) 119 | levels[i-1] = MAX # correct VO.levels 120 | # don't change Body line if level is already at MAX 121 | if lev_ - levDelta == MAX: 122 | continue 123 | m = headline_match(L) 124 | # set Body line 125 | # don't bother changing closing CHARs if there are too many of them 126 | if len(m.group(4)) <= MAX+1: 127 | Body[bln-1] = '%s=%s%s=%s' %(m.group(1), CHAR * n, m.group(3), CHAR * n) 128 | else: 129 | Body[bln-1] = '%s=%s%s' %(m.group(1), CHAR * n, L[m.end(2):]) 130 | 131 | ### --- the end --- 132 | if invalid_levs: 133 | vim.command("call voom#ErrorMsg('VOoM (dokuwiki): Disallowed levels have been corrected after ''%s''')" %oop) 134 | invalid_levs = ', '.join(['%s' %i for i in invalid_levs]) 135 | vim.command("call voom#ErrorMsg(' level set to maximum (%s) for nodes: %s')" %(MAX, invalid_levs)) 136 | 137 | 138 | -------------------------------------------------------------------------------- /autoload/voom/voom_vimplugin2657/voom_mode_fmr.py: -------------------------------------------------------------------------------- 1 | # File: voom_mode_fmr.py 2 | # Last Modified: 2017-01-07 3 | # Description: VOoM -- two-pane outliner plugin for Python-enabled Vim 4 | # Website: http://www.vim.org/scripts/script.php?script_id=2657 5 | # Author: Vlad Irnov (vlad DOT irnov AT gmail DOT com) 6 | # License: CC0, see http://creativecommons.org/publicdomain/zero/1.0/ 7 | 8 | """ 9 | VOoM markup mode for start fold markers with levels. 10 | See |voom-mode-fmr|, ../../../doc/voom.txt#*voom-mode-fmr* 11 | This is the default or "fmr" mode. This module changes absolutely nothing. 12 | """ 13 | 14 | # Define this mode as an 'fmr' mode. 15 | MTYPE = 0 16 | 17 | 18 | -------------------------------------------------------------------------------- /autoload/voom/voom_vimplugin2657/voom_mode_fmr1.py: -------------------------------------------------------------------------------- 1 | # File: voom_mode_fmr1.py 2 | # Last Modified: 2017-01-07 3 | # Description: VOoM -- two-pane outliner plugin for Python-enabled Vim 4 | # Website: http://www.vim.org/scripts/script.php?script_id=2657 5 | # Author: Vlad Irnov (vlad DOT irnov AT gmail DOT com) 6 | # License: CC0, see http://creativecommons.org/publicdomain/zero/1.0/ 7 | 8 | """ 9 | VOoM markup mode for start fold markers with levels. 10 | See |voom-mode-fmr1|, ../../../doc/voom.txt#*voom-mode-fmr1* 11 | 12 | Headline text is before the start fold marker with level. 13 | Very similar to "fmr" mode. 14 | 15 | headline level 1 {{{1 16 | some text 17 | headline level 2 {{{2 18 | more text 19 | """ 20 | 21 | import sys 22 | if sys.version_info[0] > 2: 23 | xrange = range 24 | 25 | # Define this mode as an 'fmr' mode. 26 | MTYPE = 0 27 | 28 | 29 | # voom_vim.makeoutline() without char stripping 30 | def hook_makeOutline(VO, blines): 31 | """Return (tlines, bnodes, levels) for Body lines blines. 32 | blines is either Vim buffer object (Body) or list of buffer lines. 33 | """ 34 | marker = VO.marker 35 | marker_re_search = VO.marker_re.search 36 | Z = len(blines) 37 | tlines, bnodes, levels = [], [], [] 38 | tlines_add, bnodes_add, levels_add = tlines.append, bnodes.append, levels.append 39 | #c = VO.rstrip_chars 40 | for i in xrange(Z): 41 | if not marker in blines[i]: continue 42 | bline = blines[i] 43 | m = marker_re_search(bline) 44 | if not m: continue 45 | lev = int(m.group(1)) 46 | #head = bline[:m.start()].lstrip().rstrip(c).strip('-=~').strip() 47 | head = bline[:m.start()].strip() 48 | tline = ' %s%s|%s' %(m.group(2) or ' ', '. '*(lev-1), head) 49 | tlines_add(tline) 50 | bnodes_add(i+1) 51 | levels_add(lev) 52 | return (tlines, bnodes, levels) 53 | 54 | 55 | # same as voom_vim.newHeadline() but without --- 56 | def hook_newHeadline(VO, level, blnum, ln): 57 | """Return (tree_head, bodyLines). 58 | tree_head is new headline string in Tree buffer (text after |). 59 | bodyLines is list of lines to insert in Body buffer. 60 | """ 61 | tree_head = 'NewHeadline' 62 | #bodyLines = ['---%s--- %s%s' %(tree_head, VO.marker, level), ''] 63 | bodyLines = ['%s %s%s' %(tree_head, VO.marker, level), ''] 64 | return (tree_head, bodyLines) 65 | 66 | 67 | -------------------------------------------------------------------------------- /autoload/voom/voom_vimplugin2657/voom_mode_fmr2.py: -------------------------------------------------------------------------------- 1 | # File: voom_mode_fmr2.py 2 | # Last Modified: 2017-01-07 3 | # Description: VOoM -- two-pane outliner plugin for Python-enabled Vim 4 | # Website: http://www.vim.org/scripts/script.php?script_id=2657 5 | # Author: Vlad Irnov (vlad DOT irnov AT gmail DOT com) 6 | # License: CC0, see http://creativecommons.org/publicdomain/zero/1.0/ 7 | 8 | """ 9 | VOoM markup mode for start fold markers with levels. 10 | See |voom-mode-fmr2|, ../../../doc/voom.txt#*voom-mode-fmr2* 11 | 12 | Headline text is after the start fold marker with level. 13 | 14 | {{{1 headline level 1 15 | some text 16 | {{{2 headline level 2 17 | more text 18 | """ 19 | 20 | import sys 21 | if sys.version_info[0] > 2: 22 | xrange = range 23 | 24 | # Define this mode as an 'fmr' mode. 25 | MTYPE = 0 26 | 27 | 28 | def hook_makeOutline(VO, blines): 29 | """Return (tlines, bnodes, levels) for Body lines blines. 30 | blines is either Vim buffer object (Body) or list of buffer lines. 31 | """ 32 | marker = VO.marker 33 | marker_re_search = VO.marker_re.search 34 | Z = len(blines) 35 | tlines, bnodes, levels = [], [], [] 36 | tlines_add, bnodes_add, levels_add = tlines.append, bnodes.append, levels.append 37 | #c = VO.rstrip_chars 38 | for i in xrange(Z): 39 | if not marker in blines[i]: continue 40 | bline = blines[i] 41 | m = marker_re_search(bline) 42 | if not m: continue 43 | lev = int(m.group(1)) 44 | 45 | head = bline[m.end():] # part after the fold marker 46 | # strip optional special marks from left side: "o", "=", "o=" 47 | #if head and head[0]=='o': head = head[1:] 48 | #if head and head[0]=='=': head = head[1:] 49 | # lstrip all xo= to avoid conflicts with commands that add or remove them 50 | head = head.lstrip('xo=') 51 | 52 | tline = ' %s%s|%s' %(m.group(2) or ' ', '. '*(lev-1), head.strip()) 53 | tlines_add(tline) 54 | bnodes_add(i+1) 55 | levels_add(lev) 56 | return (tlines, bnodes, levels) 57 | 58 | 59 | def hook_newHeadline(VO, level, blnum, ln): 60 | """Return (tree_head, bodyLines). 61 | tree_head is new headline string in Tree buffer (text after |). 62 | bodyLines is list of lines to insert in Body buffer. 63 | """ 64 | tree_head = 'NewHeadline' 65 | bodyLines = ['%s%s %s' %(VO.marker, level, tree_head), ''] 66 | return (tree_head, bodyLines) 67 | 68 | 69 | -------------------------------------------------------------------------------- /autoload/voom/voom_vimplugin2657/voom_mode_fmr3.py: -------------------------------------------------------------------------------- 1 | # File: voom_mode_fmr3.py 2 | # Last Modified: 2017-01-07 3 | # Description: VOoM -- two-pane outliner plugin for Python-enabled Vim 4 | # Website: http://www.vim.org/scripts/script.php?script_id=2657 5 | # Author: Vlad Irnov (vlad DOT irnov AT gmail DOT com) 6 | # License: CC0, see http://creativecommons.org/publicdomain/zero/1.0/ 7 | 8 | """ 9 | VOoM markup mode for start fold markers with levels. 10 | See |voom-mode-fmr3|, ../../../doc/voom.txt#*voom-mode-fmr3* 11 | 12 | Headline text can be before or after the start fold marker with level. 13 | 14 | {{{1 headline level 1 15 | headline level 2 {{{2 16 | """ 17 | 18 | import sys 19 | if sys.version_info[0] > 2: 20 | xrange = range 21 | 22 | # Define this mode as an 'fmr' mode. 23 | MTYPE = 0 24 | 25 | 26 | def hook_makeOutline(VO, blines): 27 | """Return (tlines, bnodes, levels) for Body lines blines. 28 | blines is either Vim buffer object (Body) or list of buffer lines. 29 | """ 30 | marker = VO.marker 31 | marker_re_search = VO.marker_re.search 32 | Z = len(blines) 33 | tlines, bnodes, levels = [], [], [] 34 | tlines_add, bnodes_add, levels_add = tlines.append, bnodes.append, levels.append 35 | #c = VO.rstrip_chars 36 | for i in xrange(Z): 37 | if not marker in blines[i]: continue 38 | bline = blines[i] 39 | m = marker_re_search(bline) 40 | if not m: continue 41 | lev = int(m.group(1)) 42 | 43 | head = bline[m.end():] # part after the fold marker 44 | # strip optional special marks from left side: "o", "=", "o=" 45 | #if head and head[0]=='o': head = head[1:] 46 | #if head and head[0]=='=': head = head[1:] 47 | # lstrip all xo= to avoid conflicts with commands that add or remove them 48 | head = head.lstrip('xo=') 49 | 50 | # add part before the fold marker 51 | if head: 52 | head = '%s %s' % (bline[:m.start()].rstrip(), head.lstrip()) 53 | else: 54 | head = bline[:m.start()] 55 | 56 | tline = ' %s%s|%s' %(m.group(2) or ' ', '. '*(lev-1), head.strip()) 57 | tlines_add(tline) 58 | bnodes_add(i+1) 59 | levels_add(lev) 60 | return (tlines, bnodes, levels) 61 | 62 | 63 | def hook_newHeadline(VO, level, blnum, ln): 64 | """Return (tree_head, bodyLines). 65 | tree_head is new headline string in Tree buffer (text after |). 66 | bodyLines is list of lines to insert in Body buffer. 67 | """ 68 | tree_head = 'NewHeadline' 69 | bodyLines = ['%s %s%s' %(tree_head, VO.marker, level), ''] 70 | return (tree_head, bodyLines) 71 | 72 | 73 | -------------------------------------------------------------------------------- /autoload/voom/voom_vimplugin2657/voom_mode_hashes.py: -------------------------------------------------------------------------------- 1 | # File: voom_mode_hashes.py 2 | # Last Modified: 2017-01-07 3 | # Description: VOoM -- two-pane outliner plugin for Python-enabled Vim 4 | # Website: http://www.vim.org/scripts/script.php?script_id=2657 5 | # Author: Vlad Irnov (vlad DOT irnov AT gmail DOT com) 6 | # License: CC0, see http://creativecommons.org/publicdomain/zero/1.0/ 7 | 8 | """ 9 | VOoM markup mode for headlines marked with #'s (atx-headers, a subset of Markdown format). 10 | See |voom-mode-hashes|, ../../../doc/voom.txt#*voom-mode-hashes* 11 | 12 | # heading level 1 13 | ##heading level 2 14 | ### heading level 3 15 | """ 16 | 17 | import sys 18 | if sys.version_info[0] > 2: 19 | xrange = range 20 | 21 | import re 22 | 23 | # Marker character can be changed to any ASCII character. 24 | CHAR = '#' 25 | 26 | # Use this if whitespace after marker chars is optional. 27 | headline_match = re.compile(r'^(%s+)' %re.escape(CHAR)).match 28 | 29 | # Use this if a whitespace is required after marker chars (as in org-mode). 30 | #headline_match = re.compile(r'^(%s+)\s' %re.escape(CHAR)).match 31 | 32 | def hook_makeOutline(VO, blines): 33 | """Return (tlines, bnodes, levels) for Body lines blines. 34 | blines is either Vim buffer object (Body) or list of buffer lines. 35 | """ 36 | Z = len(blines) 37 | tlines, bnodes, levels = [], [], [] 38 | tlines_add, bnodes_add, levels_add = tlines.append, bnodes.append, levels.append 39 | for i in xrange(Z): 40 | if not blines[i].startswith(CHAR): 41 | continue 42 | bline = blines[i] 43 | m = headline_match(bline) 44 | # Uncomment the next line if whitespace is required after marker chars. 45 | #if not m: continue 46 | lev = len(m.group(1)) 47 | head = bline[lev:].strip() 48 | # Do this instead if optional closing markers need to be stripped. 49 | #head = bline[lev:].strip().rstrip(CHAR).rstrip() 50 | tline = ' %s|%s' %('. '*(lev-1), head) 51 | tlines_add(tline) 52 | bnodes_add(i+1) 53 | levels_add(lev) 54 | return (tlines, bnodes, levels) 55 | 56 | 57 | def hook_newHeadline(VO, level, blnum, tlnum): 58 | """Return (tree_head, bodyLines). 59 | tree_head is new headline string in Tree buffer (text after |). 60 | bodyLines is list of lines to insert in Body buffer. 61 | """ 62 | tree_head = 'NewHeadline' 63 | bodyLines = ['%s %s' %(CHAR * level, tree_head), ''] 64 | return (tree_head, bodyLines) 65 | 66 | 67 | def hook_changeLevBodyHead(VO, h, levDelta): 68 | """Increase of decrease level number of Body headline by levDelta.""" 69 | if levDelta==0: return h 70 | m = headline_match(h) 71 | level = len(m.group(1)) 72 | return '%s%s' %(CHAR * (level+levDelta), h[m.end(1):]) 73 | 74 | 75 | -------------------------------------------------------------------------------- /autoload/voom/voom_vimplugin2657/voom_mode_html.py: -------------------------------------------------------------------------------- 1 | # File: voom_mode_html.py 2 | # Last Modified: 2017-01-07 3 | # Description: VOoM -- two-pane outliner plugin for Python-enabled Vim 4 | # Website: http://www.vim.org/scripts/script.php?script_id=2657 5 | # Author: Vlad Irnov (vlad DOT irnov AT gmail DOT com) 6 | # License: CC0, see http://creativecommons.org/publicdomain/zero/1.0/ 7 | 8 | """ 9 | VOoM markup mode for HTML headings. 10 | See |voom-mode-html|, ../../../doc/voom.txt#*voom-mode-html* 11 | 12 |

headline level 1

13 | some text 14 |

headline level 2

15 | more text 16 |

headline level 3

17 | < h4 > headline level 4 18 | some text

headline 5

19 | etc. 20 | """ 21 | 22 | import sys 23 | if sys.version_info[0] > 2: 24 | xrange = range 25 | 26 | import re 27 | headline_search = re.compile(r'<\s*h(\d+).*?>(.*?)', re.IGNORECASE).search 28 | html_tag_sub = re.compile('<.*?>').sub 29 | 30 | 31 | def hook_makeOutline(VO, blines): 32 | """Return (tlines, bnodes, levels) for Body lines blines. 33 | blines is either Vim buffer object (Body) or list of buffer lines. 34 | """ 35 | Z = len(blines) 36 | tlines, bnodes, levels = [], [], [] 37 | tlines_add, bnodes_add, levels_add = tlines.append, bnodes.append, levels.append 38 | for i in xrange(Z): 39 | bline = blines[i] 40 | if not ('%s' %(level, tree_head, level), ''] 63 | return (tree_head, bodyLines) 64 | 65 | 66 | def hook_changeLevBodyHead(VO, h, levDelta): 67 | """Increase of decrease level number of Body headline by levDelta.""" 68 | if levDelta==0: return h 69 | m = headline_search(h) 70 | level = int(m.group(1)) 71 | lev = level+levDelta 72 | return '%s%s%s%s%s' %(h[:m.start(1)], lev, h[m.end(1):m.start(3)], lev, h[m.end(3):]) 73 | 74 | -------------------------------------------------------------------------------- /autoload/voom/voom_vimplugin2657/voom_mode_inverseAtx.py: -------------------------------------------------------------------------------- 1 | # File: voom_mode_inverseAtx.py 2 | # Last Modified: 2017-01-07 3 | # Description: VOoM -- two-pane outliner plugin for Python-enabled Vim 4 | # Website: http://www.vim.org/scripts/script.php?script_id=2657 5 | # Author: Vlad Irnov (vlad DOT irnov AT gmail DOT com) 6 | # License: CC0, see http://creativecommons.org/publicdomain/zero/1.0/ 7 | 8 | """ 9 | VOoM markup mode for inverse Atx-style headers. 10 | See |voom-mode-various|, ../../../doc/voom.txt#*voom-mode-various* 11 | 12 | Headlines start with '@'. There is a maximum of 3 levels: 13 | 14 | @@@ Headline level 1 15 | @@ Headline level 2 16 | @ Headline level 3 17 | 18 | To change the character that denotes headlines and the maximum level, change 19 | module-level constants CHAR and MAX below. 20 | You can also change them by adding options to .vimrc: 21 | let g:voom_inverseAtx_char = '^' 22 | let g:voom_inverseAtx_max = 5 23 | 24 | """ 25 | 26 | # Marker character that denotes a headline. It can be any ASCII character. 27 | CHAR = '@' 28 | # The number of marker characters for level 1 headline. This is also the maximum possible level. 29 | MAX = 3 30 | 31 | try: 32 | import vim 33 | if vim.eval('exists("g:voom_inverseAtx_char")')=='1': 34 | CHAR = vim.eval("g:voom_inverseAtx_char") 35 | if vim.eval('exists("g:voom_inverseAtx_max")')=='1': 36 | MAX = int(vim.eval("g:voom_inverseAtx_max")) 37 | except ImportError: 38 | pass 39 | 40 | import sys 41 | if sys.version_info[0] > 2: 42 | xrange = range 43 | 44 | import re 45 | 46 | # Use this if whitespace after marker chars is optional. 47 | headline_match = re.compile(r'^(%s+)' %re.escape(CHAR)).match 48 | 49 | # Use this if a whitespace is required after marker chars. 50 | #headline_match = re.compile(r'^(%s+)\s' %re.escape(CHAR)).match 51 | 52 | 53 | # based on voom_mode_hashes.py 54 | def hook_makeOutline(VO, blines): 55 | """Return (tlines, bnodes, levels) for Body lines blines. 56 | blines is either Vim buffer object (Body) or list of buffer lines. 57 | """ 58 | Z = len(blines) 59 | tlines, bnodes, levels = [], [], [] 60 | tlines_add, bnodes_add, levels_add = tlines.append, bnodes.append, levels.append 61 | for i in xrange(Z): 62 | if not blines[i].startswith(CHAR): 63 | continue 64 | bline = blines[i] 65 | m = headline_match(bline) 66 | # Uncomment the next line if whitespace is required after marker chars. 67 | #if not m: continue 68 | n = len(m.group(1)) 69 | if n >= MAX: 70 | lev = 1 71 | else: 72 | lev = MAX - n + 1 73 | head = bline.lstrip(CHAR).strip() 74 | # Do this instead if optional closing markers need to be stripped. 75 | #head = bline.rstrip().strip(CHAR).strip() 76 | tline = ' %s|%s' %('. '*(lev-1), head) 77 | tlines_add(tline) 78 | bnodes_add(i+1) 79 | levels_add(lev) 80 | return (tlines, bnodes, levels) 81 | 82 | 83 | def hook_newHeadline(VO, level, blnum, tlnum): 84 | """Return (tree_head, bodyLines). 85 | tree_head is new headline string in Tree buffer (text after |). 86 | bodyLines is list of lines to insert in Body buffer. 87 | """ 88 | tree_head = 'NewHeadline' 89 | if level >= MAX: 90 | n = 1 91 | else: 92 | n = MAX - level + 1 93 | bodyLines = ['%s %s' %(CHAR * n, tree_head), ''] 94 | return (tree_head, bodyLines) 95 | 96 | 97 | ## This is not good enough: Body is always modified when move right fails 98 | ## because MAX level was exceeded, even if no changes to headlines were made. 99 | #def hook_changeLevBodyHead(VO, h, levDelta): 100 | # """Increase of decrease level number of Body headline by levDelta.""" 101 | # if levDelta==0: return h 102 | # m = headline_match(h) 103 | # n = len(m.group(1)) 104 | # if n >= MAX: 105 | # lev = 1 106 | # else: 107 | # lev = MAX - n + 1 108 | # level = lev + levDelta 109 | # if level >= MAX: 110 | # n = 1 111 | # else: 112 | # n = MAX - level + 1 113 | # return '%s%s' %(CHAR * n, h[m.end(1):]) 114 | 115 | 116 | # based on voom_mode_latex.py 117 | def hook_doBodyAfterOop(VO, oop, levDelta, blnum1, tlnum1, blnum2, tlnum2, blnumCut, tlnumCut): 118 | # this is instead of hook_changeLevBodyHead() 119 | #print('oop=%s levDelta=%s blnum1=%s tlnum1=%s blnum2=%s tlnum2=%s tlnumCut=%s blnumCut=%s' % (oop, levDelta, blnum1, tlnum1, blnum2, tlnum2, tlnumCut, blnumCut)) 120 | Body = VO.Body 121 | Z = len(Body) 122 | bnodes, levels = VO.bnodes, VO.levels 123 | 124 | # blnum1 blnum2 is first and last lnums of Body region pasted, inserted 125 | # during up/down, or promoted/demoted. 126 | if blnum1: 127 | assert blnum1 == bnodes[tlnum1-1] 128 | if tlnum2 < len(bnodes): 129 | assert blnum2 == bnodes[tlnum2]-1 130 | else: 131 | assert blnum2 == Z 132 | 133 | # blnumCut is Body lnum after which a region was removed during 'cut' 134 | if blnumCut: 135 | if tlnumCut < len(bnodes): 136 | assert blnumCut == bnodes[tlnumCut]-1 137 | else: 138 | assert blnumCut == Z 139 | 140 | ### Change levels and/or sections of headlines in the affected region. 141 | if not levDelta: 142 | return 143 | 144 | # Examine each headline in the affected region from top to bottom. 145 | # Change levels. 146 | # Correct levels that exceed the MAX: set them to MAX. 147 | invalid_levs = [] # tree lnums of nodes with level > MAX 148 | for i in xrange(tlnum1, tlnum2+1): 149 | # required level based on new VO.levels, can be disallowed 150 | lev_ = levels[i-1] 151 | # Body line 152 | bln = bnodes[i-1] 153 | L = Body[bln-1] # original Body headline line 154 | 155 | if lev_ <= MAX: 156 | n = MAX - lev_ + 1 157 | # MAX level exceeded 158 | else: 159 | n = 1 160 | invalid_levs.append(i) 161 | levels[i-1] = MAX # correct VO.levels 162 | # don't change Body line if level is already at MAX 163 | if lev_ - levDelta == MAX: 164 | continue 165 | m = headline_match(L) 166 | Body[bln-1] ='%s%s' %(CHAR * n, L[m.end(1):]) 167 | 168 | ### --- the end --- 169 | if invalid_levs: 170 | vim.command("call voom#ErrorMsg('VOoM (inverseAtx): Disallowed levels have been corrected after ''%s''')" %oop) 171 | invalid_levs = ', '.join(['%s' %i for i in invalid_levs]) 172 | vim.command("call voom#ErrorMsg(' level set to maximum (%s) for nodes: %s')" %(MAX, invalid_levs)) 173 | 174 | 175 | -------------------------------------------------------------------------------- /autoload/voom/voom_vimplugin2657/voom_mode_latex.py: -------------------------------------------------------------------------------- 1 | # File: voom_mode_latex.py 2 | # Last Modified: 2017-01-15 3 | # Description: VOoM -- two-pane outliner plugin for Python-enabled Vim 4 | # Website: http://www.vim.org/scripts/script.php?script_id=2657 5 | # Author: Vlad Irnov (vlad DOT irnov AT gmail DOT com) 6 | # License: CC0, see http://creativecommons.org/publicdomain/zero/1.0/ 7 | 8 | """ 9 | VOoM markup mode for LaTeX. 10 | See |voom-mode-latex|, ../../../doc/voom.txt#*voom-mode-latex* 11 | """ 12 | 13 | # SECTIONS, ELEMENTS, VERBATIMS can be defined here or in Vim variables: 14 | # g:voom_latex_sections 15 | # g:voom_latex_elements 16 | # g:voom_latex_verbatims 17 | # 18 | # SECTIONS defines sectioning commands, in order of increasing level: 19 | # \part{A Heading} 20 | # \chapter{A Heading} 21 | # \section{A Heading} 22 | # \subsection{A Heading} 23 | # \subsubsection{A Heading} 24 | # \paragraph{A Heading} 25 | # \subparagraph{A Heading} 26 | # 27 | # ELEMENTS defines fixed elements -- always at level 1: 28 | # \begin{document} 29 | # \begin{abstract} 30 | # \begin{thebibliography} 31 | # \end{document} 32 | # \bibliography{... 33 | # 34 | # VERBATIMS defines regions where headlines are ignored: 35 | # \begin{verbatim} ... \end{verbatim} 36 | # \begin{comment} ... \end{comment} 37 | # 38 | # The actual levels are determined by sections that are present in the buffer. 39 | # Levels are always incremented by 1. That is, if there are only 40 | # \section and \paragraph then \section is level 1 and \paragraph is level 2. 41 | 42 | # sectioning commands, in order of increasing level 43 | SECTIONS = ['part', 'chapter', 44 | 'section', 'subsection', 'subsubsection', 45 | 'paragraph', 'subparagraph'] 46 | 47 | # fixed elements -- always at level 1 48 | ELEMENTS = r'^\s*\\(begin\s*\{(document|abstract|thebibliography)\}|end\s*\{document\}|bibliography\s*\{)' 49 | 50 | # verbatim regions, headlines are ignored inside \begin{verbatim} ... \end{verbatim} 51 | VERBATIMS = ['verbatim', 'comment'] 52 | #--------------------------------------------------------------------- 53 | 54 | try: 55 | import vim 56 | if vim.eval('exists("g:voom_latex_sections")')=='1': 57 | SECTIONS = vim.eval("g:voom_latex_sections") 58 | if vim.eval('exists("g:voom_latex_elements")')=='1': 59 | ELEMENTS = vim.eval("g:voom_latex_elements") 60 | if vim.eval('exists("g:voom_latex_verbatims")')=='1': 61 | VERBATIMS = vim.eval("g:voom_latex_verbatims") 62 | except ImportError: 63 | pass 64 | 65 | import sys 66 | if sys.version_info[0] > 2: 67 | xrange = range 68 | 69 | import re 70 | 71 | # \section{head} or \section*{head} or \section[optionaltitle]{head} 72 | # NOTE: match leading whitespace to preserve it during outline operations 73 | # m.group() 1 2 3 74 | SECTS_RE = re.compile(r'^\s*\\(%s)\s*(\*|\[[^]{]*\])?\s*\{(.*)' %('|'.join(SECTIONS))).match 75 | 76 | if ELEMENTS: 77 | ELEMS_RE = re.compile(ELEMENTS).match 78 | else: 79 | ELEMS_RE = 0 80 | 81 | if VERBATIMS: 82 | # NOTE: leading whitespace must be lstripped before matching 83 | VERBS_RE = re.compile(r'^\\begin\s*\{(%s)\}' %('|'.join(VERBATIMS))).match 84 | else: 85 | VERBS_RE = 0 86 | 87 | SECTIONS = ['\\'+s for s in SECTIONS] 88 | SECTS_LEVS = {} # {section: its default level, ...} 89 | LEVS_SECTS = {} # {level: its default section, ...} 90 | i = 1 91 | for s in SECTIONS: 92 | SECTS_LEVS[s] = i 93 | LEVS_SECTS[i] = s 94 | i+=1 95 | 96 | 97 | def hook_makeOutline(VO, blines): 98 | """Return (tlines, bnodes, levels) for Body lines blines. 99 | blines is either Vim buffer object (Body) or list of buffer lines. 100 | """ 101 | Z = len(blines) 102 | tlines, bnodes, levels = [], [], [] 103 | tlines_add, bnodes_add, levels_add = tlines.append, bnodes.append, levels.append 104 | marks, heads = [], [] 105 | marks_add, heads_add = marks.append, heads.append 106 | 107 | sects_levs = {} # {section: its default level} for all section found in the buffer 108 | inVerbatim = False 109 | isHead = False 110 | mark = ' ' # * or - 111 | for i in xrange(Z): 112 | L = blines[i].lstrip() 113 | if not L.startswith('\\'): continue 114 | # regions to ignore: \begin{verbatim} ... \end{verbatim} 115 | if VERBS_RE: 116 | if inVerbatim: 117 | if re.match(inVerbatim, L): 118 | inVerbatim = False 119 | continue 120 | else: 121 | m = VERBS_RE(L) 122 | if m: 123 | inVerbatim = r'\\end\s*\{%s\}' %m.group(1) 124 | continue 125 | # check for sections 126 | m = SECTS_RE(L) 127 | if m: 128 | isHead = True 129 | s = '\\' + m.group(1) 130 | lev = SECTS_LEVS[s] 131 | sects_levs[s] = lev 132 | if m.group(2) and m.group(2)=='*': 133 | mark = '*' 134 | head = m.group(3) 135 | # truncate head before the matching '}' 136 | j = 0; k = 1 137 | for ch in head: 138 | if ch=='{': k+=1 139 | elif ch=='}': k-=1 140 | if not k: break 141 | j+=1 142 | head = head[:j].strip() 143 | # check for fixed level 1 elements 144 | elif ELEMS_RE: 145 | m = ELEMS_RE(L) 146 | if m: 147 | isHead = True 148 | lev = 1 149 | head = L.rstrip() 150 | mark = '-' 151 | # add node to outline 152 | if isHead: 153 | isHead = False 154 | bnodes_add(i+1) 155 | levels_add(lev) 156 | # tlines must be constructed from marks and heads and after levels are adjusted 157 | marks_add(mark) 158 | mark = ' ' 159 | heads_add(head) 160 | 161 | # adjust default level numbers to reflect only sections present in the buffer 162 | # that is make all level numbers continuous, top level is 1 163 | d = {} # {default level: actual level, ...} 164 | levs_sects = {} # {actual level: section, ...} 165 | sects = [(sects_levs[s], s) for s in sects_levs.keys()] 166 | sects.sort() 167 | sects = [i[1] for i in sects] 168 | i = 1 169 | for s in sects: 170 | d[sects_levs[s]] = i 171 | levs_sects[i] = s 172 | i+=1 173 | levels = [d.get(i,i) for i in levels] 174 | 175 | # construct tlines 176 | for i in xrange(len(levels)): 177 | tlines_add(' %s%s|%s' %(marks[i], '. '*(levels[i]-1), heads[i])) 178 | 179 | # save levs_sects for outline operations 180 | # don't clobber VO.levs_sects when parsing clipboard during Paste 181 | # which is the only time blines is not Body 182 | if blines is VO.Body: 183 | VO._levs_sects = levs_sects 184 | 185 | return (tlines, bnodes, levels) 186 | 187 | 188 | def hook_newHeadline(VO, level, blnum, tlnum): 189 | """Return (tree_head, bodyLines). 190 | tree_head is new headline string in Tree buffer (text after |). 191 | bodyLines is list of lines to insert in Body buffer. 192 | """ 193 | tree_head = 'NewHeadline' 194 | (sect, lev) = get_sect_for_lev(VO._levs_sects, level) 195 | assert lev <= level 196 | if not lev==level: 197 | vim.command("call voom#ErrorMsg('VOoM (latex): MAXIMUM LEVEL EXCEEDED')") 198 | 199 | bodyLines = ['%s{%s}' %(sect, tree_head), ''] 200 | return (tree_head, bodyLines) 201 | 202 | 203 | #def hook_changeLevBodyHead(VO, h, levDelta): 204 | # DO NOT CREATE THIS HOOK 205 | 206 | 207 | def hook_doBodyAfterOop(VO, oop, levDelta, blnum1, tlnum1, blnum2, tlnum2, blnumCut, tlnumCut): 208 | # this is instead of hook_changeLevBodyHead() 209 | #print('oop=%s levDelta=%s blnum1=%s tlnum1=%s blnum2=%s tlnum2=%s tlnumCut=%s blnumCut=%s' % (oop, levDelta, blnum1, tlnum1, blnum2, tlnum2, tlnumCut, blnumCut)) 210 | Body = VO.Body 211 | Z = len(Body) 212 | bnodes, levels = VO.bnodes, VO.levels 213 | 214 | # blnum1 blnum2 is first and last lnums of Body region pasted, inserted 215 | # during up/down, or promoted/demoted. 216 | if blnum1: 217 | assert blnum1 == bnodes[tlnum1-1] 218 | if tlnum2 < len(bnodes): 219 | assert blnum2 == bnodes[tlnum2]-1 220 | else: 221 | assert blnum2 == Z 222 | 223 | # blnumCut is Body lnum after which a region was removed during 'cut' 224 | if blnumCut: 225 | if tlnumCut < len(bnodes): 226 | assert blnumCut == bnodes[tlnumCut]-1 227 | else: 228 | assert blnumCut == Z 229 | 230 | ### Change levels and/or sections of headlines in the affected region. 231 | # Sections must always be adjusted after Paste, even if level is unchanged, 232 | # in case pasting was done from another outline with different style. 233 | if not (levDelta or oop=='paste'): 234 | return 235 | 236 | # Examine each headline in the affected region from top to bottom. 237 | # For sections: change them to the current level and style. 238 | # Correct invalid levels: VOoM**voom_notes.txt#ID_20120520092604 239 | # use max level if max possible level is exeeded 240 | # use 1 for fixed elements at level >1 241 | invalid_sects, invalid_elems = [], [] # tree lnums of nodes with disallowed levels 242 | levs_sects = VO._levs_sects 243 | #for i in xrange(tlnum2, tlnum1-1, -1): 244 | for i in xrange(tlnum1, tlnum2+1): 245 | # required level based on new VO.levels, can be disallowed 246 | lev_ = levels[i-1] 247 | # Body line 248 | bln = bnodes[i-1] 249 | L = Body[bln-1] # NOTE: original line, not lstripped 250 | 251 | m = SECTS_RE(L) 252 | if not m: 253 | assert ELEMS_RE(L) 254 | # fixed level 1 element at level >1 255 | if lev_ > 1: 256 | invalid_elems.append(i) 257 | levels[i-1] = 1 # correct VO.levels 258 | continue 259 | 260 | # current section 261 | sect_ = '\\' + m.group(1) 262 | # required section and its actual level 263 | (sect, lev) = get_sect_for_lev(levs_sects, lev_) 264 | # change section (NOTE: SECTS_RE matches after \, thus -1) 265 | if not sect == sect_: 266 | Body[bln-1] = '%s%s%s' %(L[:m.start(1)-1], sect, L[m.end(1):]) 267 | # check if max level was exceeded 268 | if not lev == lev_: 269 | invalid_sects.append(i) 270 | levels[i-1] = lev # correct VO.levels 271 | # changes VO._levs_sects 272 | if not lev in levs_sects: 273 | levs_sects[lev] = sect 274 | 275 | ### --- the end --- 276 | if invalid_elems or invalid_sects: 277 | vim.command("call voom#ErrorMsg('VOoM (latex): Disallowed levels have been corrected after ''%s''')" %oop) 278 | if invalid_elems: 279 | invalid_elems = ', '.join(['%s' %i for i in invalid_elems]) 280 | vim.command("call voom#ErrorMsg(' level set to 1 for nodes: %s')" %invalid_elems) 281 | if invalid_sects: 282 | invalid_sects = ', '.join(['%s' %i for i in invalid_sects]) 283 | vim.command("call voom#ErrorMsg(' level set to maximum for nodes: %s')" %invalid_sects) 284 | 285 | 286 | def get_sect_for_lev(levs_sects, level): 287 | """Return (section, actual level) corresponding to the desired level. 288 | levs_sects contains all sections currently in use. 289 | If level exceeds the maximum, return section for maximum possible level and max level. 290 | """ 291 | 292 | if level in levs_sects: 293 | return (levs_sects[level], level) 294 | 295 | z = len(SECTIONS) 296 | # outline is empty 297 | if not levs_sects: 298 | if level <= z: 299 | return (SECTIONS[level-1], level) 300 | else: 301 | return (SECTIONS[-1], z) 302 | 303 | # pick new sect from SECTIONS 304 | levmax = max(levs_sects.keys()) # currently used max level 305 | sectmax = levs_sects[levmax] 306 | idx = SECTS_LEVS[sectmax] + (level - levmax) 307 | if idx <= z: 308 | return (SECTIONS[idx-1], level) 309 | else: 310 | return (SECTIONS[-1], level-(idx-z)) 311 | 312 | 313 | -------------------------------------------------------------------------------- /autoload/voom/voom_vimplugin2657/voom_mode_latexDtx.py: -------------------------------------------------------------------------------- 1 | # File: voom_mode_latexDtx.py 2 | # Last Modified: 2017-01-15 3 | # Description: VOoM -- two-pane outliner plugin for Python-enabled Vim 4 | # Website: http://www.vim.org/scripts/script.php?script_id=2657 5 | # Author: Vlad Irnov (vlad DOT irnov AT gmail DOT com) 6 | # License: CC0, see http://creativecommons.org/publicdomain/zero/1.0/ 7 | 8 | """ 9 | VOoM markup mode for .dtx files (Documented LaTeX sources). It is almost 10 | identical to the LaTeX mode. The main difference is that only lines that begin 11 | with the comment character "%" can be headlines. 12 | See |voom-mode-latexDtx|, ../../../doc/voom.txt#*voom-mode-latexDtx* 13 | """ 14 | # THIS MODULE IS ALMOST IDENTICAL TO voom_mode_latex.py -- KEEP IN SYNC. 15 | # 16 | # Only commented lines are considered. Commented lines start with: optional 17 | # leading whitespace, at least one % character, optionally followed by any 18 | # combination of % and whitespace. 19 | # The following are all valid sectioning commands: 20 | # %\section{Introduction} 21 | # % \section{Introduction} 22 | # %% \section{Introduction} 23 | # %%% % % \section{Introduction} 24 | # The leading string of % and whitespace is preserved during outline operations. 25 | 26 | 27 | # SECTIONS, ELEMENTS, VERBATIMS can be defined here or in Vim variables: 28 | # g:voom_latexdtx_sections 29 | # g:voom_latexdtx_elements 30 | # g:voom_latexdtx_verbatims 31 | # 32 | # SECTIONS defines sectioning commands, in order of increasing level: 33 | # \part{A Heading} 34 | # \chapter{A Heading} 35 | # \section{A Heading} 36 | # \subsection{A Heading} 37 | # \subsubsection{A Heading} 38 | # \paragraph{A Heading} 39 | # \subparagraph{A Heading} 40 | # 41 | # ELEMENTS defines fixed elements -- always at level 1: 42 | # \begin{document} 43 | # \begin{abstract} 44 | # \begin{thebibliography} 45 | # \end{document} 46 | # \bibliography{... 47 | # 48 | # VERBATIMS defines regions where headlines are ignored: 49 | # \begin{verbatim} ... \end{verbatim} 50 | # \begin{comment} ... \end{comment} 51 | # 52 | # The actual levels are determined by sections that are present in the buffer. 53 | # Levels are always incremented by 1. That is, if there are only 54 | # \section and \paragraph then \section is level 1 and \paragraph is level 2. 55 | 56 | # sectioning commands, in order of increasing level 57 | SECTIONS = ['part', 'chapter', 58 | 'section', 'subsection', 'subsubsection', 59 | 'paragraph', 'subparagraph'] 60 | 61 | # fixed elements -- always at level 1 62 | ELEMENTS = r'^[\s%]*\\(begin\s*\{(document|abstract|thebibliography)\}|end\s*\{document\}|bibliography\s*\{)' 63 | 64 | # verbatim regions, headlines are ignored inside \begin{verbatim} ... \end{verbatim} 65 | VERBATIMS = ['verbatim', 'comment', 'macrocode'] 66 | #--------------------------------------------------------------------- 67 | 68 | try: 69 | import vim 70 | if vim.eval('exists("g:voom_latexdtx_sections")')=='1': 71 | SECTIONS = vim.eval("g:voom_latexdtx_sections") 72 | if vim.eval('exists("g:voom_latexdtx_elements")')=='1': 73 | ELEMENTS = vim.eval("g:voom_latexdtx_elements") 74 | if vim.eval('exists("g:voom_latexdtx_verbatims")')=='1': 75 | VERBATIMS = vim.eval("g:voom_latexdtx_verbatims") 76 | except ImportError: 77 | pass 78 | 79 | import sys 80 | if sys.version_info[0] > 2: 81 | xrange = range 82 | 83 | import re 84 | 85 | # \section{head} or \section*{head} or \section[optionaltitle]{head} 86 | # NOTE: match leading whitespace to preserve it during outline operations 87 | # m.group() 1 2 3 88 | SECTS_RE = re.compile(r'^[\s%%]*\\(%s)\s*(\*|\[[^]{]*\])?\s*\{(.*)' %('|'.join(SECTIONS))).match 89 | 90 | if ELEMENTS: 91 | ELEMS_RE = re.compile(ELEMENTS).match 92 | else: 93 | ELEMS_RE = 0 94 | 95 | if VERBATIMS: 96 | # NOTE: leading whitespace and % must be lstripped before matching 97 | VERBS_RE = re.compile(r'^\\begin\s*\{(%s)\}' %('|'.join(VERBATIMS))).match 98 | else: 99 | VERBS_RE = 0 100 | 101 | SECTIONS = ['\\'+s for s in SECTIONS] 102 | SECTS_LEVS = {} # {section: its default level, ...} 103 | LEVS_SECTS = {} # {level: its default section, ...} 104 | i = 1 105 | for s in SECTIONS: 106 | SECTS_LEVS[s] = i 107 | LEVS_SECTS[i] = s 108 | i+=1 109 | 110 | 111 | def hook_makeOutline(VO, blines): 112 | """Return (tlines, bnodes, levels) for Body lines blines. 113 | blines is either Vim buffer object (Body) or list of buffer lines. 114 | """ 115 | Z = len(blines) 116 | tlines, bnodes, levels = [], [], [] 117 | tlines_add, bnodes_add, levels_add = tlines.append, bnodes.append, levels.append 118 | marks, heads = [], [] 119 | marks_add, heads_add = marks.append, heads.append 120 | 121 | sects_levs = {} # {section: its default level} for all section found in the buffer 122 | inVerbatim = False 123 | isHead = False 124 | mark = ' ' # * or - 125 | for i in xrange(Z): 126 | L = blines[i].lstrip() 127 | if not L.startswith('%'): continue # dtx-specific 128 | L = L.lstrip('% \t') # dtx-specifc 129 | if not L.startswith('\\'): continue 130 | # regions to ignore: \begin{verbatim} ... \end{verbatim} 131 | if VERBS_RE: 132 | if inVerbatim: 133 | if re.match(inVerbatim, L): 134 | inVerbatim = False 135 | continue 136 | else: 137 | m = VERBS_RE(L) 138 | if m: 139 | inVerbatim = r'\\end\s*\{%s\}' %m.group(1) 140 | continue 141 | # check for sections 142 | m = SECTS_RE(L) 143 | if m: 144 | isHead = True 145 | s = '\\' + m.group(1) 146 | lev = SECTS_LEVS[s] 147 | sects_levs[s] = lev 148 | if m.group(2) and m.group(2)=='*': 149 | mark = '*' 150 | head = m.group(3) 151 | # truncate head before the matching '}' 152 | j = 0; k = 1 153 | for ch in head: 154 | if ch=='{': k+=1 155 | elif ch=='}': k-=1 156 | if not k: break 157 | j+=1 158 | head = head[:j].strip() 159 | # check for fixed level 1 elements 160 | elif ELEMS_RE: 161 | m = ELEMS_RE(L) 162 | if m: 163 | isHead = True 164 | lev = 1 165 | head = L.rstrip() 166 | mark = '-' 167 | # add node to outline 168 | if isHead: 169 | isHead = False 170 | bnodes_add(i+1) 171 | levels_add(lev) 172 | # tlines must be constructed from marks and heads and after levels are adjusted 173 | marks_add(mark) 174 | mark = ' ' 175 | heads_add(head) 176 | 177 | # adjust default level numbers to reflect only sections present in the buffer 178 | # that is make all level numbers continuous, top level is 1 179 | d = {} # {default level: actual level, ...} 180 | levs_sects = {} # {actual level: section, ...} 181 | sects = [(sects_levs[s], s) for s in sects_levs.keys()] 182 | sects.sort() 183 | sects = [i[1] for i in sects] 184 | i = 1 185 | for s in sects: 186 | d[sects_levs[s]] = i 187 | levs_sects[i] = s 188 | i+=1 189 | levels = [d.get(i,i) for i in levels] 190 | 191 | # construct tlines 192 | for i in xrange(len(levels)): 193 | tlines_add(' %s%s|%s' %(marks[i], '. '*(levels[i]-1), heads[i])) 194 | 195 | # save levs_sects for outline operations 196 | # don't clobber VO.levs_sects when parsing clipboard during Paste 197 | # which is the only time blines is not Body 198 | if blines is VO.Body: 199 | VO._levs_sects = levs_sects 200 | 201 | return (tlines, bnodes, levels) 202 | 203 | 204 | def hook_newHeadline(VO, level, blnum, tlnum): 205 | """Return (tree_head, bodyLines). 206 | tree_head is new headline string in Tree buffer (text after |). 207 | bodyLines is list of lines to insert in Body buffer. 208 | """ 209 | tree_head = 'NewHeadline' 210 | (sect, lev) = get_sect_for_lev(VO._levs_sects, level) 211 | assert lev <= level 212 | if not lev==level: 213 | vim.command("call voom#ErrorMsg('VOoM (latexDtx): MAXIMUM LEVEL EXCEEDED')") 214 | 215 | bodyLines = ['%% %s{%s}' %(sect, tree_head), '%'] # dtx-specific (insert %) 216 | return (tree_head, bodyLines) 217 | 218 | 219 | #def hook_changeLevBodyHead(VO, h, levDelta): 220 | # DO NOT CREATE THIS HOOK 221 | 222 | 223 | def hook_doBodyAfterOop(VO, oop, levDelta, blnum1, tlnum1, blnum2, tlnum2, blnumCut, tlnumCut): 224 | # this is instead of hook_changeLevBodyHead() 225 | #print('oop=%s levDelta=%s blnum1=%s tlnum1=%s blnum2=%s tlnum2=%s tlnumCut=%s blnumCut=%s' % (oop, levDelta, blnum1, tlnum1, blnum2, tlnum2, tlnumCut, blnumCut)) 226 | Body = VO.Body 227 | Z = len(Body) 228 | bnodes, levels = VO.bnodes, VO.levels 229 | 230 | # blnum1 blnum2 is first and last lnums of Body region pasted, inserted 231 | # during up/down, or promoted/demoted. 232 | if blnum1: 233 | assert blnum1 == bnodes[tlnum1-1] 234 | if tlnum2 < len(bnodes): 235 | assert blnum2 == bnodes[tlnum2]-1 236 | else: 237 | assert blnum2 == Z 238 | 239 | # blnumCut is Body lnum after which a region was removed during 'cut' 240 | if blnumCut: 241 | if tlnumCut < len(bnodes): 242 | assert blnumCut == bnodes[tlnumCut]-1 243 | else: 244 | assert blnumCut == Z 245 | 246 | ### Change levels and/or sections of headlines in the affected region. 247 | # Sections must always be adjusted after Paste, even if level is unchanged, 248 | # in case pasting was done from another outline with different style. 249 | if not (levDelta or oop=='paste'): 250 | return 251 | 252 | # Examine each headline in the affected region from top to bottom. 253 | # For sections: change them to the current level and style. 254 | # Correct invalid levels: VOoM**voom_notes.txt#ID_20120520092604 255 | # use max level if max possible level is exeeded 256 | # use 1 for fixed elements at level >1 257 | invalid_sects, invalid_elems = [], [] # tree lnums of nodes with disallowed levels 258 | levs_sects = VO._levs_sects 259 | #for i in xrange(tlnum2, tlnum1-1, -1): 260 | for i in xrange(tlnum1, tlnum2+1): 261 | # required level based on new VO.levels, can be disallowed 262 | lev_ = levels[i-1] 263 | # Body line 264 | bln = bnodes[i-1] 265 | L = Body[bln-1] # NOTE: original line, not lstripped 266 | 267 | m = SECTS_RE(L) 268 | if not m: 269 | assert ELEMS_RE(L) 270 | # fixed level 1 element at level >1 271 | if lev_ > 1: 272 | invalid_elems.append(i) 273 | levels[i-1] = 1 # correct VO.levels 274 | continue 275 | 276 | # current section 277 | sect_ = '\\' + m.group(1) 278 | # required section and its actual level 279 | (sect, lev) = get_sect_for_lev(levs_sects, lev_) 280 | # change section (NOTE: SECTS_RE matches after \, thus -1) 281 | if not sect == sect_: 282 | Body[bln-1] = '%s%s%s' %(L[:m.start(1)-1], sect, L[m.end(1):]) 283 | # check if max level was exceeded 284 | if not lev == lev_: 285 | invalid_sects.append(i) 286 | levels[i-1] = lev # correct VO.levels 287 | # changes VO._levs_sects 288 | if not lev in levs_sects: 289 | levs_sects[lev] = sect 290 | 291 | ### --- the end --- 292 | if invalid_elems or invalid_sects: 293 | vim.command("call voom#ErrorMsg('VOoM (latexDtx): Disallowed levels have been corrected after ''%s''')" %oop) 294 | if invalid_elems: 295 | invalid_elems = ', '.join(['%s' %i for i in invalid_elems]) 296 | vim.command("call voom#ErrorMsg(' level set to 1 for nodes: %s')" %invalid_elems) 297 | if invalid_sects: 298 | invalid_sects = ', '.join(['%s' %i for i in invalid_sects]) 299 | vim.command("call voom#ErrorMsg(' level set to maximum for nodes: %s')" %invalid_sects) 300 | 301 | 302 | def get_sect_for_lev(levs_sects, level): 303 | """Return (section, actual level) corresponding to the desired level. 304 | levs_sects contains all sections currently in use. 305 | If level exceeds the maximum, return section for maximum possible level and max level. 306 | """ 307 | 308 | if level in levs_sects: 309 | return (levs_sects[level], level) 310 | 311 | z = len(SECTIONS) 312 | # outline is empty 313 | if not levs_sects: 314 | if level <= z: 315 | return (SECTIONS[level-1], level) 316 | else: 317 | return (SECTIONS[-1], z) 318 | 319 | # pick new sect from SECTIONS 320 | levmax = max(levs_sects.keys()) # currently used max level 321 | sectmax = levs_sects[levmax] 322 | idx = SECTS_LEVS[sectmax] + (level - levmax) 323 | if idx <= z: 324 | return (SECTIONS[idx-1], level) 325 | else: 326 | return (SECTIONS[-1], level-(idx-z)) 327 | 328 | 329 | -------------------------------------------------------------------------------- /autoload/voom/voom_vimplugin2657/voom_mode_markdown.py: -------------------------------------------------------------------------------- 1 | # File: voom_mode_markdown.py 2 | # Last Modified: 2017-01-07 3 | # Description: VOoM -- two-pane outliner plugin for Python-enabled Vim 4 | # Website: http://www.vim.org/scripts/script.php?script_id=2657 5 | # Author: Vlad Irnov (vlad DOT irnov AT gmail DOT com) 6 | # License: CC0, see http://creativecommons.org/publicdomain/zero/1.0/ 7 | 8 | """ 9 | VOoM markup mode for Markdown headers. 10 | See |voom-mode-markdown|, ../../../doc/voom.txt#*voom-mode-markdown* 11 | """ 12 | 13 | import sys 14 | if sys.version_info[0] > 2: 15 | xrange = range 16 | def len_u(s, enc): 17 | return len(s) 18 | else: 19 | def len_u(s, enc): 20 | return len(unicode(s, enc, 'replace')) 21 | 22 | ### NOTES 23 | # When an outline operation changes level, it has to deal with two ambiguities: 24 | # a) Level 1 and 2 headline can use underline-style or hashes-style. 25 | # b) Hashes-style can have or not have closing hashes. 26 | # To determine current preferences: check first headline at level <3 and check 27 | # first headline with hashes. This must be done in hook_makeOutline(). 28 | # (Save in VO, similar to reST mode.) Cannot be done during outline operation, 29 | # that is in hook_doBodyAfterOop(). 30 | # Defaults: use underline, use closing hashes. 31 | 32 | LEVELS_ADS = {1:'=', 2:'-'} 33 | ADS_LEVELS = {'=':1, '-':2} 34 | 35 | def hook_makeOutline(VO, blines): 36 | """Return (tlines, bnodes, levels) for Body lines blines. 37 | blines is either Vim buffer object (Body) or list of buffer lines. 38 | """ 39 | Z = len(blines) 40 | tlines, bnodes, levels = [], [], [] 41 | tlines_add, bnodes_add, levels_add = tlines.append, bnodes.append, levels.append 42 | 43 | # trailing whitespace is always removed with rstrip() 44 | # 45 | # underline-style, overrides hashes-style: 46 | # head L1, blines[i] -- current line, title line, not blank 47 | # ------ L2, blines[i+1] -- any number of = or - only 48 | # 49 | # hashes-style: 50 | # ## head L1, blines[i] -- current line 51 | # abcde L2, blines[i+1] 52 | # 53 | 54 | # Set this once when headline with level 1 or 2 is encountered. 55 | # 0 or 1 -- False, use underline-style (default); 2 -- True, use hashes-style 56 | useHash = 0 57 | # Set this once when headline with hashes is encountered. 58 | # 0 or 1 -- True, use closing hashes (default); 2 -- False, do not use closing hashes 59 | useCloseHash = 0 60 | 61 | L2 = blines[0].rstrip() # first Body line 62 | isHead = False 63 | for i in xrange(Z): 64 | L1 = L2 65 | j = i+1 66 | if j < Z: 67 | L2 = blines[j].rstrip() 68 | else: 69 | L2 = '' 70 | 71 | if not L1: 72 | continue 73 | 74 | if L2 and (L2[0] in ADS_LEVELS) and not L2.lstrip(L2[0]): 75 | isHead = True 76 | lev = ADS_LEVELS[L2[0]] 77 | head = L1.strip() 78 | L2 = '' 79 | if not useHash: 80 | useHash = 1 81 | elif L1.startswith('#'): 82 | isHead = True 83 | lev = len(L1) - len(L1.lstrip('#')) 84 | head = L1.strip('#').strip() 85 | if not useHash and lev < 3: 86 | useHash = 2 87 | if not useCloseHash: 88 | if L1.endswith('#'): useCloseHash = 1 89 | else: useCloseHash = 2 90 | else: 91 | continue 92 | 93 | if isHead: 94 | isHead = False 95 | tline = ' %s|%s' %('. '*(lev-1), head) 96 | tlines_add(tline) 97 | bnodes_add(j) 98 | levels_add(lev) 99 | 100 | # don't clobber these when parsing clipboard during Paste 101 | # which is the only time blines is not Body 102 | if blines is VO.Body: 103 | VO.useHash = useHash == 2 104 | VO.useCloseHash = useCloseHash < 2 105 | 106 | return (tlines, bnodes, levels) 107 | 108 | #------ the rest is identical to voom_mode_pandoc.py ------ 109 | 110 | 111 | def hook_newHeadline(VO, level, blnum, tlnum): 112 | """Return (tree_head, bodyLines). 113 | tree_head is new headline string in Tree buffer (text after |). 114 | bodyLines is list of lines to insert in Body buffer. 115 | """ 116 | tree_head = 'NewHeadline' 117 | if level < 3 and not VO.useHash: 118 | bodyLines = [tree_head, LEVELS_ADS[level]*11, ''] 119 | else: 120 | lev = '#'*level 121 | if VO.useCloseHash: 122 | bodyLines = ['%s %s %s' %(lev, tree_head, lev), ''] 123 | else: 124 | bodyLines = ['%s %s' %(lev, tree_head), ''] 125 | 126 | # Add blank line when inserting after non-blank Body line. 127 | if VO.Body[blnum-1].strip(): 128 | bodyLines[0:0] = [''] 129 | 130 | return (tree_head, bodyLines) 131 | 132 | 133 | #def hook_changeLevBodyHead(VO, h, levDelta): 134 | # DO NOT CREATE THIS HOOK 135 | 136 | 137 | def hook_doBodyAfterOop(VO, oop, levDelta, blnum1, tlnum1, blnum2, tlnum2, blnumCut, tlnumCut): 138 | # this is instead of hook_changeLevBodyHead() 139 | 140 | # Based on reST mode function. Insert blank separator lines if missing, 141 | # even though they are not important for Markdown headlines. 142 | 143 | #print('oop=%s levDelta=%s blnum1=%s tlnum1=%s blnum2=%s tlnum2=%s tlnumCut=%s blnumCut=%s' % (oop, levDelta, blnum1, tlnum1, blnum2, tlnum2, tlnumCut, blnumCut)) 144 | Body = VO.Body 145 | Z = len(Body) 146 | bnodes, levels = VO.bnodes, VO.levels 147 | ENC = VO.enc 148 | 149 | # blnum1 blnum2 is first and last lnums of Body region pasted, inserted 150 | # during up/down, or promoted/demoted. 151 | if blnum1: 152 | assert blnum1 == bnodes[tlnum1-1] 153 | if tlnum2 < len(bnodes): 154 | assert blnum2 == bnodes[tlnum2]-1 155 | else: 156 | assert blnum2 == Z 157 | 158 | # blnumCut is Body lnum after which a region was removed during 'cut', 159 | # 'up', 'down'. Need this to check if there is blank line between nodes 160 | # used to be separated by the cut/moved region. 161 | if blnumCut: 162 | if tlnumCut < len(bnodes): 163 | assert blnumCut == bnodes[tlnumCut]-1 164 | else: 165 | assert blnumCut == Z 166 | 167 | # Total number of added lines minus number of deleted lines. 168 | b_delta = 0 169 | 170 | ### After 'cut' or 'up': insert blank line if there is none 171 | # between the nodes used to be separated by the cut/moved region. 172 | if (oop=='cut' or oop=='up') and (0 < blnumCut < Z) and Body[blnumCut-1].strip(): 173 | Body[blnumCut:blnumCut] = [''] 174 | update_bnodes(VO, tlnumCut+1 ,1) 175 | b_delta+=1 176 | 177 | if oop=='cut': 178 | return 179 | 180 | ### Make sure there is blank line after the last node in the region: 181 | # insert blank line after blnum2 if blnum2 is not blank, that is insert 182 | # blank line before bnode at tlnum2+1. 183 | if blnum2 < Z and Body[blnum2-1].strip(): 184 | Body[blnum2:blnum2] = [''] 185 | update_bnodes(VO, tlnum2+1 ,1) 186 | b_delta+=1 187 | 188 | ### Change levels and/or formats of headlines in the affected region. 189 | # Always do this after Paste, even if level is unchanged -- format can 190 | # be different when pasting from other outlines. 191 | # Examine each headline, from bottom to top, and change level and/or format. 192 | # To change from hashes to underline-style: 193 | # strip hashes, strip whitespace; 194 | # insert underline. 195 | # To change from underline to hashes-style: 196 | # delete underline or change it to blank if it is followed by another underline 197 | # insert hashes. 198 | # Update bnodes after inserting or deleting a line. 199 | 200 | # hash-style underline-style (overrides hash-style) 201 | # 202 | # ## head L1 head L1 <--bnode Body[bln-1] 203 | # L2 ---- L2 Body[bln] 204 | # L3 L3 Body[bln+1] 205 | 206 | if levDelta or oop=='paste': 207 | for i in xrange(tlnum2, tlnum1-1, -1): 208 | # required level (VO.levels has been updated) 209 | lev = levels[i-1] 210 | # current level from which to change to lev 211 | lev_ = lev - levDelta 212 | 213 | # Body headline (bnode) and next line 214 | bln = bnodes[i-1] 215 | L1 = Body[bln-1].rstrip() 216 | if bln < len(Body): 217 | L2 = Body[bln].rstrip() 218 | else: 219 | L2 = '' 220 | 221 | # get the current headline format 222 | hasHash, hasCloseHash = True, VO.useCloseHash 223 | if L2 and (L2.lstrip('=')=='' or L2.lstrip('-')==''): 224 | hasHash = False 225 | else: 226 | if L1.endswith('#'): 227 | hasCloseHash = True 228 | else: 229 | hasCloseHash = False 230 | 231 | # get the desired headline format 232 | if oop=='paste': 233 | if lev > 2: 234 | useHash = True 235 | else: 236 | useHash = VO.useHash 237 | useCloseHash = VO.useCloseHash 238 | elif lev < 3 and lev_ < 3: 239 | useHash = hasHash 240 | useCloseHash = hasCloseHash 241 | elif lev > 2 and lev_ > 2: 242 | useHash = True 243 | useCloseHash = hasCloseHash 244 | elif lev < 3 and lev_ > 2: 245 | useHash = VO.useHash 246 | useCloseHash = VO.useCloseHash 247 | elif lev > 2 and lev_ < 3: 248 | useHash = True 249 | useCloseHash = hasCloseHash 250 | else: 251 | assert False 252 | #print('useHash=%s hasHash=%s useCloseHash=%s hasCloseHash=%s' %(useHash, hasHash, useCloseHash, hasCloseHash)) 253 | #print('%s %s' %(L1, L2)) 254 | 255 | # change headline level and/or format 256 | 257 | # underline-style unchanged, only adjust level of underline 258 | if not useHash and not hasHash: 259 | if not levDelta: continue 260 | Body[bln] = LEVELS_ADS[lev]*len(L2) 261 | # hashes-style unchanged, adjust level of hashes and add/remove closing hashes 262 | elif useHash and hasHash: 263 | # no format change, there are closing hashes 264 | if useCloseHash and hasCloseHash: 265 | if not levDelta: continue 266 | Body[bln-1] = '%s%s%s' %('#'*lev, L1.strip('#'), '#'*lev) 267 | # no format change, there are no closing hashes 268 | elif not useCloseHash and not hasCloseHash: 269 | if not levDelta: continue 270 | Body[bln-1] = '%s%s' %('#'*lev, L1.lstrip('#')) 271 | # add closing hashes 272 | elif useCloseHash and not hasCloseHash: 273 | Body[bln-1] = '%s%s %s' %('#'*lev, L1.strip('#').rstrip(), '#'*lev) 274 | # remove closing hashes 275 | elif not useCloseHash and hasCloseHash: 276 | Body[bln-1] = '%s%s' %('#'*lev, L1.strip('#').rstrip()) 277 | # insert underline, remove hashes 278 | elif not useHash and hasHash: 279 | L = L1.strip('#').strip() 280 | Body[bln-1] = L 281 | # insert underline 282 | Body[bln:bln] = [LEVELS_ADS[lev] * len_u(L, ENC)] 283 | update_bnodes(VO, i+1, 1) 284 | b_delta+=1 285 | # remove underline, insert hashes 286 | elif useHash and not hasHash: 287 | if L1[0].isspace(): 288 | sp = '' 289 | else: 290 | sp = ' ' 291 | if useCloseHash: 292 | Body[bln-1] = '%s%s%s %s' %('#'*lev, sp, L1, '#'*lev) 293 | else: 294 | Body[bln-1] = '%s%s%s' %('#'*lev, sp, L1) 295 | # check if the next line after underline is another underline 296 | if bln+1 < len(Body): 297 | L3 = Body[bln+1].rstrip() 298 | else: 299 | L3 = '' 300 | #print('%s %s %s' %(L1, L2, L3)) 301 | # yes: do not delete underline, change it to a blank line 302 | if L3 and (L3.lstrip('=')=='' or L3.lstrip('-')==''): 303 | Body[bln] = '' 304 | # no: delete underline 305 | else: 306 | Body[bln:bln+1] = [] 307 | update_bnodes(VO, i+1, -1) 308 | b_delta-=1 309 | 310 | ### Make sure first headline is preceded by a blank line. 311 | blnum1 = bnodes[tlnum1-1] 312 | if blnum1 > 1 and Body[blnum1-2].strip(): 313 | Body[blnum1-1:blnum1-1] = [''] 314 | update_bnodes(VO, tlnum1 ,1) 315 | b_delta+=1 316 | 317 | ### After 'down' : insert blank line if there is none 318 | # between the nodes used to be separated by the moved region. 319 | if oop=='down' and (0 < blnumCut < Z) and Body[blnumCut-1].strip(): 320 | Body[blnumCut:blnumCut] = [''] 321 | update_bnodes(VO, tlnumCut+1 ,1) 322 | b_delta+=1 323 | 324 | assert len(Body) == Z + b_delta 325 | 326 | 327 | def update_bnodes(VO, tlnum, delta): 328 | """Update VO.bnodes by adding/substracting delta to each bnode 329 | starting with bnode at tlnum and to the end. 330 | """ 331 | bnodes = VO.bnodes 332 | for i in xrange(tlnum, len(bnodes)+1): 333 | bnodes[i-1] += delta 334 | 335 | 336 | -------------------------------------------------------------------------------- /autoload/voom/voom_vimplugin2657/voom_mode_org.py: -------------------------------------------------------------------------------- 1 | # File: voom_mode_org.py 2 | # Last Modified: 2017-01-07 3 | # Description: VOoM -- two-pane outliner plugin for Python-enabled Vim 4 | # Website: http://www.vim.org/scripts/script.php?script_id=2657 5 | # Author: Vlad Irnov (vlad DOT irnov AT gmail DOT com) 6 | # License: CC0, see http://creativecommons.org/publicdomain/zero/1.0/ 7 | 8 | """ 9 | VOoM markup mode for Emacs Org-mode headline format. 10 | See |voom-mode-org|, ../../../doc/voom.txt#*voom-mode-org* 11 | """ 12 | 13 | import sys 14 | if sys.version_info[0] > 2: 15 | xrange = range 16 | 17 | import re 18 | headline_match = re.compile(r'^(\*+)\s').match 19 | 20 | 21 | def hook_makeOutline(VO, blines): 22 | """Return (tlines, bnodes, levels) for Body lines blines. 23 | blines is either Vim buffer object (Body) or list of buffer lines. 24 | """ 25 | Z = len(blines) 26 | tlines, bnodes, levels = [], [], [] 27 | tlines_add, bnodes_add, levels_add = tlines.append, bnodes.append, levels.append 28 | for i in xrange(Z): 29 | if not blines[i].startswith('*'): 30 | continue 31 | bline = blines[i] 32 | m = headline_match(bline) 33 | if not m: 34 | continue 35 | lev = len(m.group(1)) 36 | head = bline[lev:].strip() 37 | tline = ' %s|%s' %('. '*(lev-1), head) 38 | tlines_add(tline) 39 | bnodes_add(i+1) 40 | levels_add(lev) 41 | return (tlines, bnodes, levels) 42 | 43 | 44 | def hook_newHeadline(VO, level, blnum, tlnum): 45 | """Return (tree_head, bodyLines). 46 | tree_head is new headline string in Tree buffer (text after |). 47 | bodyLines is list of lines to insert in Body buffer. 48 | """ 49 | tree_head = 'NewHeadline' 50 | bodyLines = ['%s %s' %('*'*level, tree_head), ''] 51 | return (tree_head, bodyLines) 52 | 53 | 54 | def hook_changeLevBodyHead(VO, h, levDelta): 55 | """Increase of decrease level number of Body headline by levDelta.""" 56 | if levDelta==0: return h 57 | m = headline_match(h) 58 | level = len(m.group(1)) 59 | return '%s%s' %('*'*(level+levDelta), h[m.end(1):]) 60 | 61 | 62 | -------------------------------------------------------------------------------- /autoload/voom/voom_vimplugin2657/voom_mode_pandoc.py: -------------------------------------------------------------------------------- 1 | # File: voom_mode_pandoc.py 2 | # Last Modified: 2017-01-07 3 | # Description: VOoM -- two-pane outliner plugin for Python-enabled Vim 4 | # Website: http://www.vim.org/scripts/script.php?script_id=2657 5 | # Author: Vlad Irnov (vlad DOT irnov AT gmail DOT com) 6 | # License: CC0, see http://creativecommons.org/publicdomain/zero/1.0/ 7 | 8 | """ 9 | VOoM markup mode for Pandoc Markdown headers. 10 | See |voom-mode-pandoc|, ../../../doc/voom.txt#*voom-mode-pandoc* 11 | """ 12 | 13 | import sys 14 | if sys.version_info[0] > 2: 15 | xrange = range 16 | def len_u(s, enc): 17 | return len(s) 18 | else: 19 | def len_u(s, enc): 20 | return len(unicode(s, enc, 'replace')) 21 | 22 | ### NOTES 23 | # The code is identical to voom_mode_markdown.py except that the parser ignores 24 | # headlines that: 25 | # - are not preceded by a blank line, or another headline, or an end of fenced block 26 | # - are inside fenced code blocks. 27 | 28 | LEVELS_ADS = {1:'=', 2:'-'} 29 | ADS_LEVELS = {'=':1, '-':2} 30 | 31 | def hook_makeOutline(VO, blines): 32 | """Return (tlines, bnodes, levels) for Body lines blines. 33 | blines is either Vim buffer object (Body) or list of buffer lines. 34 | """ 35 | Z = len(blines) 36 | tlines, bnodes, levels = [], [], [] 37 | tlines_add, bnodes_add, levels_add = tlines.append, bnodes.append, levels.append 38 | 39 | # trailing whitespace is always removed with rstrip() 40 | # 41 | # underline-style, overrides hashes-style: 42 | # head L1, blines[i] -- current line, title line, not blank 43 | # ------ L2, blines[i+1] -- any number of = or - only 44 | # 45 | # hashes-style: 46 | # ## head L1, blines[i] -- current line 47 | # abcde L2, blines[i+1] 48 | # 49 | 50 | # Set this once when headline with level 1 or 2 is encountered. 51 | # 0 or 1 -- False, use underline-style (default); 2 -- True, use hashes-style 52 | useHash = 0 53 | # Set this once when headline with hashes is encountered. 54 | # 0 or 1 -- True, use closing hashes (default); 2 -- False, do not use closing hashes 55 | useCloseHash = 0 56 | 57 | # Keep track of fenced code blocks where headlines are ignored. 58 | isFenced = '' 59 | # Set True on lines after which a new headline is allowed: blank line, 60 | # headline, end-of-fenced-block. Also applies to start-of-fenced-block. 61 | ok = 1 62 | L2 = blines[0].rstrip() # first Body line 63 | isHead = False 64 | for i in xrange(Z): 65 | L1 = L2 66 | j = i+1 67 | if j < Z: 68 | L2 = blines[j].rstrip() 69 | else: 70 | L2 = '' 71 | 72 | if not L1: 73 | ok = 1 74 | continue 75 | 76 | # ignore headlines inside fenced code block 77 | if isFenced: 78 | if L1.startswith(isFenced) and L1.lstrip(isFenced[0])=='': 79 | isFenced = '' 80 | ok = 1 81 | continue 82 | 83 | # Headline is allowed only after a blank line, another headline, 84 | # end-of-fenced block. Same for start-of-fenced-block. 85 | if not ok: 86 | continue 87 | 88 | # new fenced code block 89 | if L1.startswith('~~~') or L1.startswith('```'): 90 | ch = L1[0] 91 | isFenced = ch*(len(L1)-len(L1.lstrip(ch))) 92 | continue 93 | 94 | if L2 and (L2[0] in ADS_LEVELS) and not L2.lstrip(L2[0]): 95 | isHead = True 96 | lev = ADS_LEVELS[L2[0]] 97 | head = L1.strip() 98 | L2 = '' # this will set ok=1 on the next line (underline) 99 | if not useHash: 100 | useHash = 1 101 | elif L1.startswith('#') and not L1.startswith('#. '): 102 | ok = 1 103 | isHead = True 104 | lev = len(L1) - len(L1.lstrip('#')) 105 | head = L1.strip('#').strip() 106 | if not useHash and lev < 3: 107 | useHash = 2 108 | if not useCloseHash: 109 | if L1.endswith('#'): useCloseHash = 1 110 | else: useCloseHash = 2 111 | else: 112 | ok = 0 113 | continue 114 | 115 | if isHead: 116 | isHead = False 117 | tline = ' %s|%s' %('. '*(lev-1), head) 118 | tlines_add(tline) 119 | bnodes_add(j) 120 | levels_add(lev) 121 | 122 | # don't clobber these when parsing clipboard during Paste 123 | # which is the only time blines is not Body 124 | if blines is VO.Body: 125 | VO.useHash = useHash == 2 126 | VO.useCloseHash = useCloseHash < 2 127 | 128 | return (tlines, bnodes, levels) 129 | 130 | #------ the rest is identical to voom_mode_markdown.py ------ 131 | 132 | 133 | def hook_newHeadline(VO, level, blnum, tlnum): 134 | """Return (tree_head, bodyLines). 135 | tree_head is new headline string in Tree buffer (text after |). 136 | bodyLines is list of lines to insert in Body buffer. 137 | """ 138 | tree_head = 'NewHeadline' 139 | if level < 3 and not VO.useHash: 140 | bodyLines = [tree_head, LEVELS_ADS[level]*11, ''] 141 | else: 142 | lev = '#'*level 143 | if VO.useCloseHash: 144 | bodyLines = ['%s %s %s' %(lev, tree_head, lev), ''] 145 | else: 146 | bodyLines = ['%s %s' %(lev, tree_head), ''] 147 | 148 | # Add blank line when inserting after non-blank Body line. 149 | if VO.Body[blnum-1].strip(): 150 | bodyLines[0:0] = [''] 151 | 152 | return (tree_head, bodyLines) 153 | 154 | 155 | #def hook_changeLevBodyHead(VO, h, levDelta): 156 | # DO NOT CREATE THIS HOOK 157 | 158 | 159 | def hook_doBodyAfterOop(VO, oop, levDelta, blnum1, tlnum1, blnum2, tlnum2, blnumCut, tlnumCut): 160 | # this is instead of hook_changeLevBodyHead() 161 | 162 | # Based on reST mode function. Insert blank separator lines if missing, 163 | # even though they are not important for Markdown headlines. 164 | 165 | #print('oop=%s levDelta=%s blnum1=%s tlnum1=%s blnum2=%s tlnum2=%s tlnumCut=%s blnumCut=%s' % (oop, levDelta, blnum1, tlnum1, blnum2, tlnum2, tlnumCut, blnumCut)) 166 | Body = VO.Body 167 | Z = len(Body) 168 | bnodes, levels = VO.bnodes, VO.levels 169 | ENC = VO.enc 170 | 171 | # blnum1 blnum2 is first and last lnums of Body region pasted, inserted 172 | # during up/down, or promoted/demoted. 173 | if blnum1: 174 | assert blnum1 == bnodes[tlnum1-1] 175 | if tlnum2 < len(bnodes): 176 | assert blnum2 == bnodes[tlnum2]-1 177 | else: 178 | assert blnum2 == Z 179 | 180 | # blnumCut is Body lnum after which a region was removed during 'cut', 181 | # 'up', 'down'. Need this to check if there is blank line between nodes 182 | # used to be separated by the cut/moved region. 183 | if blnumCut: 184 | if tlnumCut < len(bnodes): 185 | assert blnumCut == bnodes[tlnumCut]-1 186 | else: 187 | assert blnumCut == Z 188 | 189 | # Total number of added lines minus number of deleted lines. 190 | b_delta = 0 191 | 192 | ### After 'cut' or 'up': insert blank line if there is none 193 | # between the nodes used to be separated by the cut/moved region. 194 | if (oop=='cut' or oop=='up') and (0 < blnumCut < Z) and Body[blnumCut-1].strip(): 195 | Body[blnumCut:blnumCut] = [''] 196 | update_bnodes(VO, tlnumCut+1 ,1) 197 | b_delta+=1 198 | 199 | if oop=='cut': 200 | return 201 | 202 | ### Make sure there is blank line after the last node in the region: 203 | # insert blank line after blnum2 if blnum2 is not blank, that is insert 204 | # blank line before bnode at tlnum2+1. 205 | if blnum2 < Z and Body[blnum2-1].strip(): 206 | Body[blnum2:blnum2] = [''] 207 | update_bnodes(VO, tlnum2+1 ,1) 208 | b_delta+=1 209 | 210 | ### Change levels and/or formats of headlines in the affected region. 211 | # Always do this after Paste, even if level is unchanged -- format can 212 | # be different when pasting from other outlines. 213 | # Examine each headline, from bottom to top, and change level and/or format. 214 | # To change from hashes to underline-style: 215 | # strip hashes, strip whitespace; 216 | # insert underline. 217 | # To change from underline to hashes-style: 218 | # delete underline or change it to blank if it is followed by another underline 219 | # insert hashes. 220 | # Update bnodes after inserting or deleting a line. 221 | 222 | # hash-style underline-style (overrides hash-style) 223 | # 224 | # ## head L1 head L1 <--bnode Body[bln-1] 225 | # L2 ---- L2 Body[bln] 226 | # L3 L3 Body[bln+1] 227 | 228 | if levDelta or oop=='paste': 229 | for i in xrange(tlnum2, tlnum1-1, -1): 230 | # required level (VO.levels has been updated) 231 | lev = levels[i-1] 232 | # current level from which to change to lev 233 | lev_ = lev - levDelta 234 | 235 | # Body headline (bnode) and next line 236 | bln = bnodes[i-1] 237 | L1 = Body[bln-1].rstrip() 238 | if bln < len(Body): 239 | L2 = Body[bln].rstrip() 240 | else: 241 | L2 = '' 242 | 243 | # get the current headline format 244 | hasHash, hasCloseHash = True, VO.useCloseHash 245 | if L2 and (L2.lstrip('=')=='' or L2.lstrip('-')==''): 246 | hasHash = False 247 | else: 248 | if L1.endswith('#'): 249 | hasCloseHash = True 250 | else: 251 | hasCloseHash = False 252 | 253 | # get the desired headline format 254 | if oop=='paste': 255 | if lev > 2: 256 | useHash = True 257 | else: 258 | useHash = VO.useHash 259 | useCloseHash = VO.useCloseHash 260 | elif lev < 3 and lev_ < 3: 261 | useHash = hasHash 262 | useCloseHash = hasCloseHash 263 | elif lev > 2 and lev_ > 2: 264 | useHash = True 265 | useCloseHash = hasCloseHash 266 | elif lev < 3 and lev_ > 2: 267 | useHash = VO.useHash 268 | useCloseHash = VO.useCloseHash 269 | elif lev > 2 and lev_ < 3: 270 | useHash = True 271 | useCloseHash = hasCloseHash 272 | else: 273 | assert False 274 | #print('useHash=%s hasHash=%s useCloseHash=%s hasCloseHash=%s' %(useHash, hasHash, useCloseHash, hasCloseHash)) 275 | #print('%s %s' %(L1, L2)) 276 | 277 | # change headline level and/or format 278 | 279 | # underline-style unchanged, only adjust level of underline 280 | if not useHash and not hasHash: 281 | if not levDelta: continue 282 | Body[bln] = LEVELS_ADS[lev]*len(L2) 283 | # hashes-style unchanged, adjust level of hashes and add/remove closing hashes 284 | elif useHash and hasHash: 285 | # no format change, there are closing hashes 286 | if useCloseHash and hasCloseHash: 287 | if not levDelta: continue 288 | Body[bln-1] = '%s%s%s' %('#'*lev, L1.strip('#'), '#'*lev) 289 | # no format change, there are no closing hashes 290 | elif not useCloseHash and not hasCloseHash: 291 | if not levDelta: continue 292 | Body[bln-1] = '%s%s' %('#'*lev, L1.lstrip('#')) 293 | # add closing hashes 294 | elif useCloseHash and not hasCloseHash: 295 | Body[bln-1] = '%s%s %s' %('#'*lev, L1.strip('#').rstrip(), '#'*lev) 296 | # remove closing hashes 297 | elif not useCloseHash and hasCloseHash: 298 | Body[bln-1] = '%s%s' %('#'*lev, L1.strip('#').rstrip()) 299 | # insert underline, remove hashes 300 | elif not useHash and hasHash: 301 | L = L1.strip('#').strip() 302 | Body[bln-1] = L 303 | # insert underline 304 | Body[bln:bln] = [LEVELS_ADS[lev] * len_u(L, ENC)] 305 | update_bnodes(VO, i+1, 1) 306 | b_delta+=1 307 | # remove underline, insert hashes 308 | elif useHash and not hasHash: 309 | if L1[0].isspace(): 310 | sp = '' 311 | else: 312 | sp = ' ' 313 | if useCloseHash: 314 | Body[bln-1] = '%s%s%s %s' %('#'*lev, sp, L1, '#'*lev) 315 | else: 316 | Body[bln-1] = '%s%s%s' %('#'*lev, sp, L1) 317 | # check if the next line after underline is another underline 318 | if bln+1 < len(Body): 319 | L3 = Body[bln+1].rstrip() 320 | else: 321 | L3 = '' 322 | #print('%s %s %s' %(L1, L2, L3)) 323 | # yes: do not delete underline, change it to a blank line 324 | if L3 and (L3.lstrip('=')=='' or L3.lstrip('-')==''): 325 | Body[bln] = '' 326 | # no: delete underline 327 | else: 328 | Body[bln:bln+1] = [] 329 | update_bnodes(VO, i+1, -1) 330 | b_delta-=1 331 | 332 | ### Make sure first headline is preceded by a blank line. 333 | blnum1 = bnodes[tlnum1-1] 334 | if blnum1 > 1 and Body[blnum1-2].strip(): 335 | Body[blnum1-1:blnum1-1] = [''] 336 | update_bnodes(VO, tlnum1 ,1) 337 | b_delta+=1 338 | 339 | ### After 'down' : insert blank line if there is none 340 | # between the nodes used to be separated by the moved region. 341 | if oop=='down' and (0 < blnumCut < Z) and Body[blnumCut-1].strip(): 342 | Body[blnumCut:blnumCut] = [''] 343 | update_bnodes(VO, tlnumCut+1 ,1) 344 | b_delta+=1 345 | 346 | assert len(Body) == Z + b_delta 347 | 348 | 349 | def update_bnodes(VO, tlnum, delta): 350 | """Update VO.bnodes by adding/substracting delta to each bnode 351 | starting with bnode at tlnum and to the end. 352 | """ 353 | bnodes = VO.bnodes 354 | for i in xrange(tlnum, len(bnodes)+1): 355 | bnodes[i-1] += delta 356 | 357 | 358 | -------------------------------------------------------------------------------- /autoload/voom/voom_vimplugin2657/voom_mode_paragraphBlank.py: -------------------------------------------------------------------------------- 1 | # File: voom_mode_paragraphBlank.py 2 | # Last Modified: 2017-01-07 3 | # Description: VOoM -- two-pane outliner plugin for Python-enabled Vim 4 | # Website: http://www.vim.org/scripts/script.php?script_id=2657 5 | # Author: Vlad Irnov (vlad DOT irnov AT gmail DOT com) 6 | # License: CC0, see http://creativecommons.org/publicdomain/zero/1.0/ 7 | 8 | """ 9 | VOoM markup mode for paragraphs separated by blank lines. The first line of 10 | each paragraph is level 1 headline. That is the first non-blank line and any 11 | non-blank line preceded by a blank line is a headline. 12 | 13 | See |voom-mode-paragraphBlank|, ../../../doc/voom.txt#*voom-mode-paragraphBlank* 14 | 15 | Everything is at level 1. Levels >1 are not possible. 16 | 17 | There are must be a blank line after the last paragraph, that is end-of-file. 18 | Otherwise there are will be errors when the last paragraph is moved. 19 | """ 20 | 21 | import sys 22 | if sys.version_info[0] > 2: 23 | xrange = range 24 | 25 | # Disable unsupported outline operations: special node marks, insert new headline as child, move right. 26 | MTYPE = 2 27 | 28 | 29 | def hook_makeOutline(VO, blines): 30 | """Return (tlines, bnodes, levels) for Body lines blines. 31 | blines is either Vim buffer object (Body) or list of buffer lines. 32 | """ 33 | # A line is headline level 1 if it is: preceded by a blank line (or is 34 | # first buffer line) and is non-blank. 35 | Z = len(blines) 36 | tlines, bnodes, levels = [], [], [] 37 | tlines_add, bnodes_add, levels_add = tlines.append, bnodes.append, levels.append 38 | bline_ = '' 39 | for i in xrange(Z): 40 | bline = blines[i].strip() 41 | if bline_ or not bline: 42 | bline_ = bline 43 | continue 44 | bline_ = bline 45 | tlines_add(' |%s' %bline) 46 | bnodes_add(i+1) 47 | levels_add(1) 48 | return (tlines, bnodes, levels) 49 | 50 | 51 | def hook_newHeadline(VO, level, blnum, tlnum): 52 | """Return (tree_head, bodyLines). 53 | tree_head is new headline string in Tree buffer (text after |). 54 | bodyLines is list of lines to insert in Body buffer. 55 | """ 56 | # Add blank line when inserting after non-blank Body line. 57 | if VO.Body[blnum-1].strip(): 58 | return ('NewHeadline', ['', 'NewHeadline', '']) 59 | else: 60 | return ('NewHeadline', ['NewHeadline', '']) 61 | 62 | 63 | ### DO NOT DEFINE THIS HOOK -- level never changes, it is always 1 64 | #def hook_changeLevBodyHead(VO, h, levDelta): 65 | # """Increase of decrease level number of Body headline by levDelta.""" 66 | # return h 67 | 68 | 69 | # This is needed to insert blank line missing from end-of-file. Code is from rest mode. 70 | def hook_doBodyAfterOop(VO, oop, levDelta, blnum1, tlnum1, blnum2, tlnum2, blnumCut, tlnumCut): 71 | # this is instead of hook_changeLevBodyHead() 72 | #print('oop=%s levDelta=%s blnum1=%s tlnum1=%s blnum2=%s tlnum2=%s tlnumCut=%s blnumCut=%s' % (oop, levDelta, blnum1, tlnum1, blnum2, tlnum2, tlnumCut, blnumCut)) 73 | Body = VO.Body 74 | Z = len(Body) 75 | bnodes = VO.bnodes 76 | 77 | # blnum1 blnum2 is first and last lnums of Body region pasted, inserted 78 | # during up/down, or promoted/demoted. 79 | if blnum1: 80 | assert blnum1 == bnodes[tlnum1-1] 81 | if tlnum2 < len(bnodes): 82 | assert blnum2 == bnodes[tlnum2]-1 83 | else: 84 | assert blnum2 == Z 85 | 86 | # blnumCut is Body lnum after which a region was removed during 'cut', 87 | # 'up', 'down'. We need to check if there is blank line between nodes 88 | # used to be separated by the cut/moved region to prevent headline loss. 89 | if blnumCut: 90 | if tlnumCut < len(bnodes): 91 | assert blnumCut == bnodes[tlnumCut]-1 92 | else: 93 | assert blnumCut == Z 94 | 95 | # Total number of added lines minus number of deleted lines. 96 | b_delta = 0 97 | 98 | # ### After 'cut' or 'up': insert blank line if there is none 99 | # # between the nodes used to be separated by the cut/moved region. 100 | # if (oop=='cut' or oop=='up') and (0 < blnumCut < Z) and Body[blnumCut-1].strip(): 101 | # Body[blnumCut:blnumCut] = [''] 102 | # update_bnodes(VO, tlnumCut+1 ,1) 103 | # b_delta+=1 104 | 105 | if oop=='cut': 106 | return 107 | 108 | ### Prevent loss of headline after last node in the region: 109 | # insert blank line after blnum2 if blnum2 is not blank, that is insert 110 | # blank line before bnode at tlnum2+1. 111 | if blnum2 < Z and Body[blnum2-1].strip(): 112 | Body[blnum2:blnum2] = [''] 113 | update_bnodes(VO, tlnum2+1 ,1) 114 | b_delta+=1 115 | 116 | ### Prevent loss of first headline: make sure it is preceded by a blank line 117 | blnum1 = bnodes[tlnum1-1] 118 | if blnum1 > 1 and Body[blnum1-2].strip(): 119 | Body[blnum1-1:blnum1-1] = [''] 120 | update_bnodes(VO, tlnum1 ,1) 121 | b_delta+=1 122 | 123 | # ### After 'down' : insert blank line if there is none 124 | # # between the nodes used to be separated by the moved region. 125 | # if oop=='down' and (0 < blnumCut < Z) and Body[blnumCut-1].strip(): 126 | # Body[blnumCut:blnumCut] = [''] 127 | # update_bnodes(VO, tlnumCut+1 ,1) 128 | # b_delta+=1 129 | 130 | assert len(Body) == Z + b_delta 131 | 132 | 133 | def update_bnodes(VO, tlnum, delta): 134 | """Update VO.bnodes by adding/substracting delta to each bnode 135 | starting with bnode at tlnum and to the end. 136 | """ 137 | bnodes = VO.bnodes 138 | for i in xrange(tlnum, len(bnodes)+1): 139 | bnodes[i-1] += delta 140 | 141 | 142 | 143 | -------------------------------------------------------------------------------- /autoload/voom/voom_vimplugin2657/voom_mode_paragraphIndent.py: -------------------------------------------------------------------------------- 1 | # File: voom_mode_paragraphIndent.py 2 | # Last Modified: 2017-01-07 3 | # Description: VOoM -- two-pane outliner plugin for Python-enabled Vim 4 | # Website: http://www.vim.org/scripts/script.php?script_id=2657 5 | # Author: Vlad Irnov (vlad DOT irnov AT gmail DOT com) 6 | # License: CC0, see http://creativecommons.org/publicdomain/zero/1.0/ 7 | 8 | """ 9 | VOoM markup mode for paragraphs identified by indented lines. 10 | Any non-blank line that starts with a space or tab is a headline. 11 | Everything is at level 1. Levels >1 are not possible. 12 | 13 | See |voom-mode-paragraphIndent|, ../../../doc/voom.txt#*voom-mode-paragraphIndent* 14 | """ 15 | 16 | import sys 17 | if sys.version_info[0] > 2: 18 | xrange = range 19 | 20 | # Disable unsupported outline operations: special node marks, insert new headline as child, move right. 21 | MTYPE = 2 22 | 23 | whitespace = ('\t', ' ') 24 | 25 | def hook_makeOutline(VO, blines): 26 | """Return (tlines, bnodes, levels) for Body lines blines. 27 | blines is either Vim buffer object (Body) or list of buffer lines. 28 | """ 29 | # every line that doesn't start with a space or tab is level 1 headline 30 | Z = len(blines) 31 | tlines, bnodes, levels = [], [], [] 32 | tlines_add, bnodes_add, levels_add = tlines.append, bnodes.append, levels.append 33 | for i in xrange(Z): 34 | bline = blines[i] 35 | if not bline or not (bline[0] in whitespace): # THE ONLY DIFFERENCE FROM voom_mode_paragraphNoIndent.py 36 | continue 37 | bline = bline.strip() 38 | if not bline: 39 | continue 40 | tlines_add(' |%s' %bline) 41 | bnodes_add(i+1) 42 | levels_add(1) 43 | return (tlines, bnodes, levels) 44 | 45 | 46 | def hook_newHeadline(VO, level, blnum, tlnum): 47 | """Return (tree_head, bodyLines). 48 | tree_head is new headline string in Tree buffer (text after |). 49 | bodyLines is list of lines to insert in Body buffer. 50 | """ 51 | # inserting after another headline: use indent of previous body headline 52 | if tlnum > 1: 53 | bheadline = VO.Body[VO.bnodes[tlnum-1]-1] # previous Body headline 54 | idx = len(bheadline) - len(bheadline.lstrip()) 55 | indent = bheadline[: idx] 56 | # inserting as first headline and there are other headlines: use indent of next headline 57 | elif len(VO.bnodes) > 1: 58 | bheadline = VO.Body[VO.bnodes[tlnum]-1] # next Body headline 59 | idx = len(bheadline) - len(bheadline.lstrip()) 60 | indent = bheadline[: idx] 61 | else: 62 | indent = ' ' 63 | return ('NewHeadline', ['%sNewHeadline' %indent]) 64 | 65 | 66 | ### DO NOT DEFINE THIS HOOK -- level never changes, it is always 1 67 | #def hook_changeLevBodyHead(VO, h, levDelta): 68 | # """Increase of decrease level number of Body headline by levDelta.""" 69 | # return h 70 | 71 | 72 | -------------------------------------------------------------------------------- /autoload/voom/voom_vimplugin2657/voom_mode_paragraphNoIndent.py: -------------------------------------------------------------------------------- 1 | # File: voom_mode_paragraphNoIndent.py 2 | # Last Modified: 2017-01-07 3 | # Description: VOoM -- two-pane outliner plugin for Python-enabled Vim 4 | # Website: http://www.vim.org/scripts/script.php?script_id=2657 5 | # Author: Vlad Irnov (vlad DOT irnov AT gmail DOT com) 6 | # License: CC0, see http://creativecommons.org/publicdomain/zero/1.0/ 7 | 8 | """ 9 | VOoM markup mode for paragraphs identified by non-indented lines. 10 | Any line that starts with a character other than space or tab is a headline. 11 | Everything is at level 1. Levels >1 are not possible. 12 | 13 | See |voom-mode-paragraphNoIndent|, ../../../doc/voom.txt#*voom-mode-paragraphNoIndent* 14 | """ 15 | 16 | import sys 17 | if sys.version_info[0] > 2: 18 | xrange = range 19 | 20 | # Disable unsupported outline operations: special node marks, insert new headline as child, move right. 21 | MTYPE = 2 22 | 23 | whitespace = ('\t', ' ') 24 | 25 | def hook_makeOutline(VO, blines): 26 | """Return (tlines, bnodes, levels) for Body lines blines. 27 | blines is either Vim buffer object (Body) or list of buffer lines. 28 | """ 29 | # every line that doesn't start with a space or tab is level 1 headline 30 | Z = len(blines) 31 | tlines, bnodes, levels = [], [], [] 32 | tlines_add, bnodes_add, levels_add = tlines.append, bnodes.append, levels.append 33 | for i in xrange(Z): 34 | bline = blines[i] 35 | if not bline or bline[0] in whitespace: # THE ONLY DIFFERENCE FROM voom_mode_paragraphIndent.py 36 | continue 37 | bline = bline.strip() 38 | if not bline: 39 | continue 40 | tlines_add(' |%s' %bline) 41 | bnodes_add(i+1) 42 | levels_add(1) 43 | return (tlines, bnodes, levels) 44 | 45 | 46 | def hook_newHeadline(VO, level, blnum, tlnum): 47 | """Return (tree_head, bodyLines). 48 | tree_head is new headline string in Tree buffer (text after |). 49 | bodyLines is list of lines to insert in Body buffer. 50 | """ 51 | return ('NewHeadline', ['NewHeadline']) 52 | 53 | 54 | ### DO NOT DEFINE THIS HOOK -- level never changes, it is always 1 55 | #def hook_changeLevBodyHead(VO, h, levDelta): 56 | # """Increase of decrease level number of Body headline by levDelta.""" 57 | # return h 58 | 59 | 60 | -------------------------------------------------------------------------------- /autoload/voom/voom_vimplugin2657/voom_mode_python.py: -------------------------------------------------------------------------------- 1 | # File: voom_mode_python.py 2 | # Last Modified: 2017-01-07 3 | # Description: VOoM -- two-pane outliner plugin for Python-enabled Vim 4 | # Website: http://www.vim.org/scripts/script.php?script_id=2657 5 | # Author: Vlad Irnov (vlad DOT irnov AT gmail DOT com) 6 | # License: CC0, see http://creativecommons.org/publicdomain/zero/1.0/ 7 | 8 | """ 9 | VOoM markup mode for Python code. 10 | See |voom-mode-python|, ../../../doc/voom.txt#*voom-mode-python* 11 | """ 12 | 13 | import sys 14 | if sys.version_info[0] > 2: 15 | xrange = range 16 | 17 | import token, tokenize 18 | import traceback 19 | import vim 20 | 21 | 22 | def hook_makeOutline(VO, blines): 23 | """Return (tlines, bnodes, levels) for Body lines blines. 24 | blines is either Vim buffer object (Body) or list of buffer lines. 25 | """ 26 | Z = len(blines) 27 | tlines, bnodes, levels = [], [], [] 28 | tlines_add, bnodes_add, levels_add = tlines.append, bnodes.append, levels.append 29 | 30 | #ignore_lnums, func_lnums = get_lnums_from_tokenize(blines) 31 | try: 32 | ignore_lnums, func_lnums = get_lnums_from_tokenize(blines) 33 | except (IndentationError, tokenize.TokenError): 34 | vim.command("call voom#ErrorMsg('VOoM: EXCEPTION WHILE PARSING PYTHON OUTLINE')") 35 | # DO NOT print to sys.stderr -- triggers Vim error when default stderr (no PyLog) 36 | #traceback.print_exc() --this goes to sys.stderr 37 | #print traceback.format_exc() --ok but no highlighting 38 | lines = traceback.format_exc().replace("'","''").split('\n') 39 | for ln in lines: 40 | vim.command("call voom#ErrorMsg('%s')" %ln) 41 | return (['= |!!!ERROR: OUTLINE IS INVALID'], [1], [1]) 42 | 43 | isHead = False # True if current line is a headline 44 | indents = [0,] # indents of previous levels 45 | funcLevels = [] # levels of previous def or class 46 | indentError = '' # inconsistent indent 47 | isDecor = 0 # keeps track of decorators, set to lnum of the first decorator 48 | X = ' ' # char in Tree's column 2 (marks) 49 | for i in xrange(Z): 50 | bnode = i + 1 51 | if bnode in ignore_lnums: continue 52 | bline = blines[i] 53 | bline_s = bline.strip() 54 | if not bline_s: continue 55 | if bline_s.startswith('#'): 56 | # ignore comment lines consisting only of #, -, =, spaces, tabs (separators, pretty headers) 57 | if not bline_s.lstrip('# \t-='): continue 58 | isComment = True 59 | else: 60 | isComment = False 61 | bline_ls = bline.lstrip() 62 | 63 | # compute indent and level 64 | indent = len(bline) - len(bline_ls) 65 | if indent > indents[-1]: 66 | indents.append(indent) 67 | elif indent < indents[-1]: 68 | while indents and (indents[-1] > indent): 69 | indents.pop() 70 | if indents[-1]==indent: 71 | indentError = '' 72 | else: 73 | indentError = '!!! ' 74 | lev = len(indents) 75 | 76 | # First line after the end of a class or def block. 77 | if funcLevels and lev <= funcLevels[-1]: 78 | isHead = True 79 | while funcLevels and funcLevels[-1] >= lev: 80 | funcLevels.pop() 81 | # First line of a class or def block. 82 | if bnode in func_lnums: 83 | isHead = True 84 | if isDecor: 85 | bnode = isDecor 86 | isDecor = 0 87 | X = 'd' 88 | if not funcLevels or (lev > funcLevels[-1]): 89 | funcLevels.append(lev) 90 | # Line after a decorator. Not a def or class. 91 | elif isDecor: 92 | # ingore valid lines between the first decorator and function/class 93 | if bline_s.startswith('@') or isComment or not bline_s: 94 | isHead = False 95 | continue 96 | # Invalid line after a decorator (should be syntax error): anything 97 | # other than another decorator, comment, blank line, def/class. 98 | # If it looks like a headline, let it be a headline. 99 | else: 100 | isDecor = 0 101 | # Decorator line (the first one if a group of several). 102 | elif bline_s.startswith('@'): 103 | isDecor = bnode 104 | isHead = False 105 | continue 106 | # Special comment line (unconditional headline). Not a separator or pretty header line. 107 | elif isComment: 108 | if bline_s.startswith('###') or bline_s.startswith('#--') or bline_s.startswith('#=='): 109 | isHead = True 110 | 111 | if isHead: 112 | ########################################## 113 | # Take care of pretty headers like this. # 114 | ########################################## 115 | if isComment: 116 | # add preceding lines to the current node if they consist only of #, =, -, whitespace 117 | while bnode > 1: 118 | bline_p = blines[bnode-2].lstrip() 119 | if not bline_p.startswith('#') or bline_p.lstrip('# \t-='): 120 | break 121 | else: 122 | bnode -= 1 123 | # the end 124 | isHead = False 125 | tline = ' %s%s|%s%s' %(X, '. '*(lev-1), indentError, bline_s) 126 | X = ' ' 127 | tlines_add(tline) 128 | bnodes_add(bnode) 129 | levels_add(lev) 130 | 131 | return (tlines, bnodes, levels) 132 | 133 | 134 | class BLines: 135 | """Wrapper around Vim buffer object or list of Body lines to provide 136 | readline() method for use with tokenize.generate_tokens(). 137 | """ 138 | def __init__(self, blines): 139 | self.blines = blines 140 | self.size = len(blines) 141 | self.idx = -1 142 | 143 | def readline(self): 144 | self.idx += 1 145 | if self.idx == self.size: 146 | return '' 147 | return "%s\n" %self.blines[self.idx] 148 | 149 | 150 | ### toktypes of tokens 151 | STRING = token.STRING 152 | NAME = token.NAME 153 | NEWLINE = token.NEWLINE 154 | 155 | def get_lnums_from_tokenize(blines): 156 | """Return dicts. Keys are Body lnums. 157 | The main purpose is to get list of lnums to ignore: multi-line strings and 158 | expressions. 159 | """ 160 | # lnums to ignore: multi-line strings and expressions other than the first line 161 | ignore_lnums = {} 162 | # lnums of 'class' and 'def' tokens 163 | func_lnums = {} 164 | 165 | inName = False 166 | 167 | for tok in tokenize.generate_tokens(BLines(blines).readline): 168 | toktype, toktext, (srow, scol), (erow, ecol), line = tok 169 | #print('token.tok_name[toktype]=%s tok=%s' %(token.tok_name[toktype], tok)) 170 | if toktype == NAME: 171 | if not inName: 172 | inName = True 173 | srow_name = srow 174 | if toktext in ('def','class'): 175 | func_lnums[srow] = toktext 176 | elif toktype == NEWLINE and inName: 177 | inName = False 178 | if srow_name != erow: 179 | for i in xrange(srow_name+1, erow+1): 180 | ignore_lnums[i] = 0 181 | elif toktype == STRING: 182 | if srow != erow: 183 | for i in xrange(srow+1, erow+1): 184 | ignore_lnums[i] = 0 185 | 186 | return (ignore_lnums, func_lnums) 187 | 188 | 189 | def get_body_indent(body): 190 | """Return string used for indenting Body lines.""" 191 | et = int(vim.eval("getbufvar(%s,'&et')" %body)) 192 | if et: 193 | ts = int(vim.eval("getbufvar(%s,'&ts')" %body)) 194 | return ' '*ts 195 | else: 196 | return '\t' 197 | 198 | 199 | def hook_newHeadline(VO, level, blnum, tlnum): 200 | """Return (tree_head, bodyLines). 201 | tree_head is new headline string in Tree buffer (text after |). 202 | bodyLines is list of lines to insert in Body buffer. 203 | """ 204 | tree_head = '### NewHeadline' 205 | indent = get_body_indent(VO.body) 206 | body_head = '%s%s' %(indent*(level-1), tree_head) 207 | return (tree_head, [body_head]) 208 | 209 | 210 | #def hook_changeLevBodyHead(VO, h, levDelta): 211 | #"""Increase of decrease level number of Body headline by levDelta.""" 212 | #if levDelta==0: return h 213 | 214 | 215 | def hook_doBodyAfterOop(VO, oop, levDelta, blnum1, tlnum1, blnum2, tlnum2, blnumCut, tlnumCut): 216 | # this is instead of hook_changeLevBodyHead() 217 | #print('oop=%s levDelta=%s blnum1=%s tlnum1=%s blnum2=%s tlnum2=%s tlnumCut=%s blnumCut=%s' % (oop, levDelta, blnum1, tlnum1, blnum2, tlnum2, tlnumCut, blnumCut)) 218 | Body = VO.Body 219 | Z = len(Body) 220 | 221 | ind = get_body_indent(VO.body) 222 | # levDelta is wrong when pasting because hook_makeOutline() looks at relative indent 223 | # determine level of pasted region from indent of its first line 224 | if oop=='paste': 225 | bline1 = Body[blnum1-1] 226 | lev = int((len(bline1) - len(bline1.lstrip())) / len(ind)) + 1 227 | levDelta = VO.levels[tlnum1-1] - lev 228 | 229 | if not levDelta: return 230 | 231 | indent = abs(levDelta) * ind 232 | #--- copied from voom_mode_thevimoutliner.py ----------------------------- 233 | if blnum1: 234 | assert blnum1 == VO.bnodes[tlnum1-1] 235 | if tlnum2 < len(VO.bnodes): 236 | assert blnum2 == VO.bnodes[tlnum2]-1 237 | else: 238 | assert blnum2 == Z 239 | 240 | # dedent (if possible) or indent every non-blank line in Body region blnum1,blnum2 241 | blines = [] 242 | for i in xrange(blnum1-1,blnum2): 243 | line = Body[i] 244 | if not line.strip(): 245 | blines.append(line) 246 | continue 247 | if levDelta > 0: 248 | line = '%s%s' %(indent,line) 249 | elif levDelta < 0 and line.startswith(indent): 250 | line = line[len(indent):] 251 | blines.append(line) 252 | 253 | # replace Body region 254 | Body[blnum1-1:blnum2] = blines 255 | assert len(Body)==Z 256 | 257 | 258 | -------------------------------------------------------------------------------- /autoload/voom/voom_vimplugin2657/voom_mode_rest.py: -------------------------------------------------------------------------------- 1 | # File: voom_mode_rest.py 2 | # Last Modified: 2016-08-20 3 | # Description: VOoM -- two-pane outliner plugin for Python-enabled Vim 4 | # Website: http://www.vim.org/scripts/script.php?script_id=2657 5 | # Author: Vlad Irnov (vlad DOT irnov AT gmail DOT com) 6 | # License: CC0, see http://creativecommons.org/publicdomain/zero/1.0/ 7 | 8 | """ 9 | VOoM markup mode for reStructuredText. 10 | See |voom-mode-rest|, ../../../doc/voom.txt#*voom-mode-rest* 11 | 12 | http://docutils.sourceforge.net/docs/ref/rst/restructuredtext.html#sections 13 | The following are all valid section title adornment characters: 14 | ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~ 15 | 16 | Some characters are more suitable than others. The following are recommended: 17 | = - ` : . ' " ~ ^ _ * + # 18 | 19 | http://docs.python.org/documenting/rest.html#sections 20 | Python recommended styles: ## ** = - ^ " 21 | """ 22 | 23 | import sys 24 | if sys.version_info[0] > 2: 25 | xrange = range 26 | def len_u(s, enc): 27 | return len(s) 28 | else: 29 | def len_u(s, enc): 30 | return len(unicode(s, enc, 'replace')) 31 | 32 | 33 | # All valid section title adornment characters. 34 | AD_CHARS = """ ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~ """ 35 | AD_CHARS = AD_CHARS.split() 36 | 37 | # List of adornment styles, in order of preference. 38 | # Adornment style (ad) is a char or double char: '=', '==', '-', '--', '*', etc. 39 | # Char is adornment char, double if there is overline. 40 | AD_STYLES = """ == -- = - * " ' ` ~ : ^ + # . _ """ 41 | AD_STYLES = AD_STYLES.split() 42 | 43 | # add all other possible styles to AD_STYLES 44 | d = {}.fromkeys(AD_STYLES) 45 | for c in AD_CHARS: 46 | if not c*2 in d: 47 | AD_STYLES.append(c*2) 48 | if not c in d: 49 | AD_STYLES.append(c) 50 | assert len(AD_STYLES)==64 51 | 52 | # convert AD_CHARS to dict for faster lookups 53 | AD_CHARS = {}.fromkeys(AD_CHARS) 54 | 55 | 56 | def hook_makeOutline(VO, blines): 57 | """Return (tlines, bnodes, levels) for Body lines blines. 58 | blines is either Vim buffer object (Body) or list of buffer lines. 59 | """ 60 | Z = len(blines) 61 | tlines, bnodes, levels = [], [], [] 62 | tlines_add, bnodes_add, levels_add = tlines.append, bnodes.append, levels.append 63 | ENC = VO.enc 64 | 65 | # {adornment style: level, ...} 66 | # Level indicates when the first instance of this style was found. 67 | ads_levels = {} 68 | 69 | # diagram of Body lines when a headline is detected 70 | # trailing whitespace always removed with rstrip() 71 | # a b c 72 | # ------ L3, blines[i-2] -- an overline or a blank line 73 | # head L2, blines[i-1] -- title line, not blank, <= than underline, can be inset only if overline 74 | # ------ L1, blines[i] -- current line, always an underline 75 | # x y z 76 | L1, L2, L3 = '','','' 77 | 78 | # An underline can be only the 2nd or 3rd line of a block after a blank 79 | # line or previous underline. Thus, index of the next underline must be ok or ok+1. 80 | ok = 1 81 | isHead = False 82 | for i in xrange(Z): 83 | L2, L3 = L1, L2 84 | L1 = blines[i].rstrip() 85 | if not L1: 86 | ok = i+2 87 | continue 88 | if i < ok or not L2: 89 | continue 90 | # At this point both the current line (underline) and previous line (title) are not blank. 91 | 92 | # current line must be an underline 93 | if not ((L1[0] in AD_CHARS) and L1.lstrip(L1[0])==''): 94 | if i > ok: ok = Z 95 | continue 96 | # underline must be as long as headline text 97 | if len(L1) < len_u(L2, ENC): 98 | if i > ok: ok = Z 99 | continue 100 | head = L2.lstrip() 101 | # headline text cannot look like an underline unless it's shorter than underline 102 | if (head[0] in AD_CHARS) and head.lstrip(head[0])=='' and len(head)==len(L1): 103 | if i > ok: ok = Z 104 | continue 105 | # there is no overline; L3 must be blank line; L2 must be not inset 106 | if not L3 and len(L2)==len(head): 107 | #if len(L1) < len_u(L2, ENC): continue 108 | isHead = True 109 | ad = L1[0] 110 | bnode = i 111 | # there is overline -- bnode is lnum of overline! 112 | elif L3==L1: 113 | #if len(L1) < len_u(L2, ENC): continue 114 | isHead = True 115 | ad = L1[0]*2 116 | bnode = i-1 117 | else: 118 | if i > ok: ok = Z 119 | continue 120 | 121 | if isHead: 122 | if not ad in ads_levels: 123 | ads_levels[ad] = len(ads_levels)+1 124 | lev = ads_levels[ad] 125 | isHead = False 126 | L1, L2, L3 = '','','' 127 | ok = i+2 128 | 129 | tline = ' %s|%s' %('. '*(lev-1), head) 130 | tlines_add(tline) 131 | bnodes_add(bnode) 132 | levels_add(lev) 133 | 134 | # save ads_levels for outline operations 135 | # don't clobber VO.ads_levels when parsing clipboard during Paste 136 | # which is the only time blines is not Body 137 | if blines is VO.Body: 138 | VO.ads_levels = ads_levels 139 | 140 | return (tlines, bnodes, levels) 141 | 142 | 143 | def hook_newHeadline(VO, level, blnum, tlnum): 144 | """Return (tree_head, bodyLines). 145 | tree_head is new headline string in Tree buffer (text after |). 146 | bodyLines is list of lines to insert in Body buffer. 147 | """ 148 | tree_head = 'NewHeadline' 149 | ads_levels = VO.ads_levels 150 | levels_ads = dict([[v,k] for k,v in ads_levels.items()]) 151 | 152 | if level in levels_ads: 153 | ad = levels_ads[level] 154 | else: 155 | ad = get_new_ad(levels_ads, ads_levels, level) 156 | 157 | if len(ad)==1: 158 | bodyLines = [tree_head, ad*11, ''] 159 | elif len(ad)==2: 160 | ad = ad[0] 161 | bodyLines = [ad*11, tree_head, ad*11, ''] 162 | 163 | # Add blank line when inserting after non-blank Body line. 164 | if VO.Body[blnum-1].strip(): 165 | bodyLines[0:0] = [''] 166 | 167 | return (tree_head, bodyLines) 168 | 169 | 170 | #def hook_changeLevBodyHead(VO, h, levDelta): 171 | # DO NOT CREATE THIS HOOK 172 | 173 | 174 | def hook_doBodyAfterOop(VO, oop, levDelta, blnum1, tlnum1, blnum2, tlnum2, blnumCut, tlnumCut): 175 | # this is instead of hook_changeLevBodyHead() 176 | #print('oop=%s levDelta=%s blnum1=%s tlnum1=%s blnum2=%s tlnum2=%s tlnumCut=%s blnumCut=%s' % (oop, levDelta, blnum1, tlnum1, blnum2, tlnum2, tlnumCut, blnumCut)) 177 | Body = VO.Body 178 | Z = len(Body) 179 | bnodes, levels = VO.bnodes, VO.levels 180 | ENC = VO.enc 181 | 182 | # blnum1 blnum2 is first and last lnums of Body region pasted, inserted 183 | # during up/down, or promoted/demoted. 184 | if blnum1: 185 | assert blnum1 == bnodes[tlnum1-1] 186 | if tlnum2 < len(bnodes): 187 | assert blnum2 == bnodes[tlnum2]-1 188 | else: 189 | assert blnum2 == Z 190 | 191 | # blnumCut is Body lnum after which a region was removed during 'cut', 192 | # 'up', 'down'. We need to check if there is blank line between nodes 193 | # used to be separated by the cut/moved region to prevent headline loss. 194 | if blnumCut: 195 | if tlnumCut < len(bnodes): 196 | assert blnumCut == bnodes[tlnumCut]-1 197 | else: 198 | assert blnumCut == Z 199 | 200 | # Total number of added lines minus number of deleted lines. 201 | b_delta = 0 202 | 203 | ### After 'cut' or 'up': insert blank line if there is none 204 | # between the nodes used to be separated by the cut/moved region. 205 | if (oop=='cut' or oop=='up') and (0 < blnumCut < Z) and Body[blnumCut-1].strip(): 206 | Body[blnumCut:blnumCut] = [''] 207 | update_bnodes(VO, tlnumCut+1 ,1) 208 | b_delta+=1 209 | 210 | if oop=='cut': 211 | return 212 | 213 | ### Prevent loss of headline after last node in the region: 214 | # insert blank line after blnum2 if blnum2 is not blank, that is insert 215 | # blank line before bnode at tlnum2+1. 216 | if blnum2 < Z and Body[blnum2-1].strip(): 217 | Body[blnum2:blnum2] = [''] 218 | update_bnodes(VO, tlnum2+1 ,1) 219 | b_delta+=1 220 | 221 | ### Change levels and/or styles of headlines in the affected region. 222 | # Always do this after Paste, even if level is unchanged -- adornments can 223 | # be different when pasting from other outlines. 224 | # Examine each headline, from bottom to top, and change adornment style. 225 | # To change from underline to overline style: 226 | # insert overline. 227 | # To change from overline to underline style: 228 | # delete overline if there is blank before it; 229 | # otherwise change overline to blank line; 230 | # remove inset from headline text. 231 | # Update bnodes after inserting or deleting a line. 232 | if levDelta or oop=='paste': 233 | ads_levels = VO.ads_levels 234 | levels_ads = dict([[v,k] for k,v in ads_levels.items()]) 235 | # Add adornment styles for new levels. Can't do this in the main loop 236 | # because it goes backwards and thus will add styles in reverse order. 237 | for i in xrange(tlnum1, tlnum2+1): 238 | lev = levels[i-1] 239 | if not lev in levels_ads: 240 | ad = get_new_ad(levels_ads, ads_levels, lev) 241 | levels_ads[lev] = ad 242 | ads_levels[ad] = lev 243 | for i in xrange(tlnum2, tlnum1-1, -1): 244 | # required level (VO.levels has been updated) 245 | lev = levels[i-1] 246 | # required adornment style 247 | ad = levels_ads[lev] 248 | 249 | # deduce current adornment style 250 | bln = bnodes[i-1] 251 | L1 = Body[bln-1].rstrip() 252 | L2 = Body[bln].rstrip() 253 | if bln+1 < len(Body): 254 | L3 = Body[bln+1].rstrip() 255 | else: 256 | L3 = '' 257 | ad_ = deduce_ad_style(L1,L2,L3,ENC) 258 | 259 | # change adornment style 260 | # see deduce_ad_style() for diagram 261 | if ad_==ad: 262 | continue 263 | elif len(ad_)==1 and len(ad)==1: 264 | Body[bln] = ad*len(L2) 265 | elif len(ad_)==2 and len(ad)==2: 266 | Body[bln-1] = ad[0]*len(L1) 267 | Body[bln+1] = ad[0]*len(L3) 268 | elif len(ad_)==1 and len(ad)==2: 269 | # change underline if different 270 | if not ad_ == ad[0]: 271 | Body[bln] = ad[0]*len(L2) 272 | # insert overline; current bnode doesn't change 273 | Body[bln-1:bln-1] = [ad[0]*len(L2)] 274 | update_bnodes(VO, i+1, 1) 275 | b_delta+=1 276 | elif len(ad_)==2 and len(ad)==1: 277 | # change underline if different 278 | if not ad_[0] == ad: 279 | Body[bln+1] = ad*len(L3) 280 | # remove headline inset if any 281 | if not len(L2) == len(L2.lstrip()): 282 | Body[bln] = L2.lstrip() 283 | # check if line before overline is blank 284 | if bln >1: 285 | L0 = Body[bln-2].rstrip() 286 | else: 287 | L0 = '' 288 | # there is blank before overline 289 | # delete overline; current bnode doesn't change 290 | if not L0: 291 | Body[bln-1:bln] = [] 292 | update_bnodes(VO, i+1, -1) 293 | b_delta-=1 294 | # there is no blank before overline 295 | # change overline to blank; only current bnode needs updating 296 | else: 297 | Body[bln-1] = '' 298 | bnodes[i-1]+=1 299 | 300 | ### Prevent loss of first headline: make sure it is preceded by a blank line 301 | blnum1 = bnodes[tlnum1-1] 302 | if blnum1 > 1 and Body[blnum1-2].strip(): 303 | Body[blnum1-1:blnum1-1] = [''] 304 | update_bnodes(VO, tlnum1 ,1) 305 | b_delta+=1 306 | 307 | ### After 'down' : insert blank line if there is none 308 | # between the nodes used to be separated by the moved region. 309 | if oop=='down' and (0 < blnumCut < Z) and Body[blnumCut-1].strip(): 310 | Body[blnumCut:blnumCut] = [''] 311 | update_bnodes(VO, tlnumCut+1 ,1) 312 | b_delta+=1 313 | 314 | assert len(Body) == Z + b_delta 315 | 316 | 317 | def update_bnodes(VO, tlnum, delta): 318 | """Update VO.bnodes by adding/substracting delta to each bnode 319 | starting with bnode at tlnum and to the end. 320 | """ 321 | bnodes = VO.bnodes 322 | for i in xrange(tlnum, len(bnodes)+1): 323 | bnodes[i-1] += delta 324 | 325 | 326 | def get_new_ad(levels_ads, ads_levels, level): 327 | """Return adornment style for new level, that is level missing from 328 | levels_ads and ads_levels. 329 | """ 330 | for ad in AD_STYLES: 331 | if not ad in ads_levels: 332 | return ad 333 | # all 64 adornment styles are in use, return style for level 64 334 | assert len(levels_ads)==64 335 | return levels_ads[64] 336 | 337 | 338 | def deduce_ad_style(L1,L2,L3,ENC): 339 | """Deduce adornment style given first 3 lines of Body node. 340 | 1st line is bnode line. Lines must be rstripped. L1 and L2 are not blank. 341 | """ 342 | # '--' style '-' style 343 | # 344 | # L0 L0 Body[bln-2] 345 | # ---- L1 head L1 <--bnode Body[bln-1] 346 | # head L2 ---- L2 Body[bln] 347 | # ---- L3 text L3 Body[bln+1] 348 | 349 | # bnode is headline text, L2 is underline 350 | if (L2[0] in AD_CHARS) and L2.lstrip(L2[0])=='' and (len(L2) >= len_u(L1, ENC)): 351 | ad = L2[0] 352 | # bnode is overline 353 | elif L1==L3 and (L1[0] in AD_CHARS) and L1.lstrip(L1[0])=='' and (len(L1) >= len_u(L2, ENC)): 354 | ad = 2*L1[0] 355 | else: 356 | print(L1) 357 | print(L2) 358 | print(L3) 359 | print(ENC) 360 | assert None 361 | 362 | return ad 363 | 364 | 365 | def test_deduce_ad_style(VO): 366 | """ A test to verify deduce_ad_style(). Execute from Vim 367 | :py _VOoM2657.VOOMS[1].mModule.test_deduce_ad_style(_VOoM2657.VOOMS[1]) 368 | """ 369 | bnodes, levels, Body = VO.bnodes, VO.levels, VO.Body 370 | ads_levels = VO.ads_levels 371 | levels_ads = dict([[v,k] for k,v in ads_levels.items()]) 372 | ENC = VO.enc 373 | 374 | for i in xrange(2, len(bnodes)+1): 375 | bln = bnodes[i-1] 376 | L1 = Body[bln-1].rstrip() 377 | L2 = Body[bln].rstrip() 378 | if bln+1 < len(Body): 379 | L3 = Body[bln+1].rstrip() 380 | else: 381 | L3 = '' 382 | ad = deduce_ad_style(L1,L2,L3,ENC) 383 | lev = levels[i-1] 384 | print('%s %s %s' %(i, ad, levels_ads[lev])) 385 | assert ad == levels_ads[lev] 386 | 387 | 388 | -------------------------------------------------------------------------------- /autoload/voom/voom_vimplugin2657/voom_mode_taskpaper.py: -------------------------------------------------------------------------------- 1 | # File: voom_mode_taskpaper.py 2 | # Last Modified: 2017-01-07 3 | # Description: VOoM -- two-pane outliner plugin for Python-enabled Vim 4 | # Website: http://www.vim.org/scripts/script.php?script_id=2657 5 | # Author: Vlad Irnov (vlad DOT irnov AT gmail DOT com) 6 | # License: CC0, see http://creativecommons.org/publicdomain/zero/1.0/ 7 | 8 | """ 9 | VOoM markup mode for TaskPaper format. 10 | See |voom-mode-taskpaper|, ../../../doc/voom.txt#*voom-mode-taskpaper* 11 | """ 12 | 13 | import sys 14 | if sys.version_info[0] > 2: 15 | xrange = range 16 | 17 | import re 18 | # match for Project line, as in syntax/taskpaper.vim 19 | project_match = re.compile(r'^.+:(\s+@[^ \t(]+(\([^)]*\))?)*$').match 20 | 21 | def hook_makeOutline(VO, blines): 22 | """Return (tlines, bnodes, levels) for Body lines blines. 23 | blines is either Vim buffer object (Body) or list of buffer lines. 24 | """ 25 | Z = len(blines) 26 | tlines, bnodes, levels = [], [], [] 27 | tlines_add, bnodes_add, levels_add = tlines.append, bnodes.append, levels.append 28 | for i in xrange(Z): 29 | bline = blines[i] 30 | h = bline.lstrip('\t') 31 | # line is a Task 32 | if h.startswith('- '): 33 | head = h[2:] 34 | mark = ' ' 35 | # line is a Project 36 | # the "in" test is for efficiency sake in case there is lots of Notes 37 | elif h.endswith(':') or (':' in h and project_match(h)): 38 | head = h 39 | mark = 'x' 40 | else: 41 | continue 42 | lev = len(bline) - len(h) + 1 43 | 44 | tline = ' %s%s|%s' %(mark, '. '*(lev-1), head) 45 | tlines_add(tline) 46 | bnodes_add(i+1) 47 | levels_add(lev) 48 | return (tlines, bnodes, levels) 49 | 50 | 51 | def hook_newHeadline(VO, level, blnum, tlnum): 52 | """Return (tree_head, bodyLines). 53 | tree_head is new headline string in Tree buffer (text after |). 54 | bodyLines is list of lines to insert in Body buffer. 55 | """ 56 | tree_head = 'NewHeadline' 57 | bodyLines = ['%s- %s' %('\t'*(level-1), tree_head),] 58 | return (tree_head, bodyLines) 59 | 60 | 61 | # ---- The rest is identical to vimoutliner/thevimoutliner modes. ----------- 62 | 63 | def hook_doBodyAfterOop(VO, oop, levDelta, blnum1, tlnum1, blnum2, tlnum2, blnumCut, tlnumCut): 64 | # this is instead of hook_changeLevBodyHead() 65 | if not levDelta: return 66 | 67 | indent = abs(levDelta) * '\t' 68 | 69 | Body = VO.Body 70 | Z = len(Body) 71 | 72 | # ---- identical to voom_mode_python.py code ---------------------------- 73 | if blnum1: 74 | assert blnum1 == VO.bnodes[tlnum1-1] 75 | if tlnum2 < len(VO.bnodes): 76 | assert blnum2 == VO.bnodes[tlnum2]-1 77 | else: 78 | assert blnum2 == Z 79 | 80 | # dedent (if possible) or indent every non-blank line in Body region blnum1,blnum2 81 | blines = [] 82 | for i in xrange(blnum1-1,blnum2): 83 | line = Body[i] 84 | if not line.strip(): 85 | blines.append(line) 86 | continue 87 | if levDelta > 0: 88 | line = '%s%s' %(indent,line) 89 | elif levDelta < 0 and line.startswith(indent): 90 | line = line[len(indent):] 91 | blines.append(line) 92 | 93 | # replace Body region 94 | Body[blnum1-1:blnum2] = blines 95 | assert len(Body)==Z 96 | -------------------------------------------------------------------------------- /autoload/voom/voom_vimplugin2657/voom_mode_thevimoutliner.py: -------------------------------------------------------------------------------- 1 | # File: voom_mode_thevimoutliner.py 2 | # Last Modified: 2017-01-07 3 | # Description: VOoM -- two-pane outliner plugin for Python-enabled Vim 4 | # Website: http://www.vim.org/scripts/script.php?script_id=2657 5 | # Author: Vlad Irnov (vlad DOT irnov AT gmail DOT com) 6 | # License: CC0, see http://creativecommons.org/publicdomain/zero/1.0/ 7 | 8 | """ 9 | VOoM markup mode for The Vim Outliner format. 10 | See |voom-mode-thevimoutliner|, ../../../doc/voom.txt#*voom-mode-thevimoutliner* 11 | 12 | Headlines and body lines are indented with Tabs. Number of tabs indicates 13 | level. 0 Tabs means level 1. 14 | 15 | Headlines are lines with >=0 Tabs followed by any character except '|'. 16 | 17 | Blank lines are not headlines. 18 | """ 19 | 20 | import sys 21 | if sys.version_info[0] > 2: 22 | xrange = range 23 | 24 | # Body lines start with these chars 25 | BODY_CHARS = {'|':0,} 26 | 27 | # ------ the rest is identical to voom_mode_vimoutliner.py ------------------- 28 | def hook_makeOutline(VO, blines): 29 | """Return (tlines, bnodes, levels) for Body lines blines. 30 | blines is either Vim buffer object (Body) or list of buffer lines. 31 | """ 32 | Z = len(blines) 33 | tlines, bnodes, levels = [], [], [] 34 | tlines_add, bnodes_add, levels_add = tlines.append, bnodes.append, levels.append 35 | for i in xrange(Z): 36 | bline = blines[i].rstrip() 37 | if not bline: 38 | continue 39 | head = bline.lstrip('\t') 40 | if head[0] in BODY_CHARS: 41 | continue 42 | lev = len(bline) - len(head) + 1 43 | 44 | tline = ' %s|%s' %('. '*(lev-1), head) 45 | tlines_add(tline) 46 | bnodes_add(i+1) 47 | levels_add(lev) 48 | return (tlines, bnodes, levels) 49 | 50 | 51 | def hook_newHeadline(VO, level, blnum, tlnum): 52 | """Return (tree_head, bodyLines). 53 | tree_head is new headline string in Tree buffer (text after |). 54 | bodyLines is list of lines to insert in Body buffer. 55 | """ 56 | tree_head = 'NewHeadline' 57 | bodyLines = ['%s%s' %('\t'*(level-1), tree_head),] 58 | return (tree_head, bodyLines) 59 | 60 | 61 | #def hook_changeLevBodyHead(VO, h, levDelta): 62 | #"""Increase of decrease level number of Body headline by levDelta.""" 63 | #if levDelta==0: return h 64 | 65 | def hook_doBodyAfterOop(VO, oop, levDelta, blnum1, tlnum1, blnum2, tlnum2, blnumCut, tlnumCut): 66 | # this is instead of hook_changeLevBodyHead() 67 | if not levDelta: return 68 | 69 | indent = abs(levDelta) * '\t' 70 | 71 | Body = VO.Body 72 | Z = len(Body) 73 | 74 | # ---- identical to voom_mode_python.py code ---------------------------- 75 | if blnum1: 76 | assert blnum1 == VO.bnodes[tlnum1-1] 77 | if tlnum2 < len(VO.bnodes): 78 | assert blnum2 == VO.bnodes[tlnum2]-1 79 | else: 80 | assert blnum2 == Z 81 | 82 | # dedent (if possible) or indent every non-blank line in Body region blnum1,blnum2 83 | blines = [] 84 | for i in xrange(blnum1-1,blnum2): 85 | line = Body[i] 86 | if not line.strip(): 87 | blines.append(line) 88 | continue 89 | if levDelta > 0: 90 | line = '%s%s' %(indent,line) 91 | elif levDelta < 0 and line.startswith(indent): 92 | line = line[len(indent):] 93 | blines.append(line) 94 | 95 | # replace Body region 96 | Body[blnum1-1:blnum2] = blines 97 | assert len(Body)==Z 98 | -------------------------------------------------------------------------------- /autoload/voom/voom_vimplugin2657/voom_mode_txt2tags.py: -------------------------------------------------------------------------------- 1 | # File: voom_mode_txt2tags.py 2 | # Last Modified: 2017-01-07 3 | # Description: VOoM -- two-pane outliner plugin for Python-enabled Vim 4 | # Website: http://www.vim.org/scripts/script.php?script_id=2657 5 | # Author: Vlad Irnov (vlad DOT irnov AT gmail DOT com) 6 | # License: CC0, see http://creativecommons.org/publicdomain/zero/1.0/ 7 | 8 | """ 9 | VOoM markup mode for txt2tags titles. 10 | See |voom-mode-txt2tags|, ../../../doc/voom.txt#*voom-mode-txt2tags* 11 | """ 12 | 13 | import sys 14 | if sys.version_info[0] > 2: 15 | xrange = range 16 | 17 | import re 18 | # headline regexps from txt2tags.py: 19 | # titskel = r'^ *(?P%s)(?P%s)\1(\[(?P