1" Vim functions for file type detection 2" 3" Maintainer: Bram Moolenaar <[email protected]> 4" Last Change: 2020 Aug 17 5 6" These functions are moved here from runtime/filetype.vim to make startup 7" faster. 8 9" Line continuation is used here, remove 'C' from 'cpoptions' 10let s:cpo_save = &cpo 11set cpo&vim 12 13func dist#ft#Check_inp() 14 if getline(1) =~ '^\*' 15 setf abaqus 16 else 17 let n = 1 18 if line("$") > 500 19 let nmax = 500 20 else 21 let nmax = line("$") 22 endif 23 while n <= nmax 24 if getline(n) =~? "^header surface data" 25 setf trasys 26 break 27 endif 28 let n = n + 1 29 endwhile 30 endif 31endfunc 32 33" This function checks for the kind of assembly that is wanted by the user, or 34" can be detected from the first five lines of the file. 35func dist#ft#FTasm() 36 " make sure b:asmsyntax exists 37 if !exists("b:asmsyntax") 38 let b:asmsyntax = "" 39 endif 40 41 if b:asmsyntax == "" 42 call dist#ft#FTasmsyntax() 43 endif 44 45 " if b:asmsyntax still isn't set, default to asmsyntax or GNU 46 if b:asmsyntax == "" 47 if exists("g:asmsyntax") 48 let b:asmsyntax = g:asmsyntax 49 else 50 let b:asmsyntax = "asm" 51 endif 52 endif 53 54 exe "setf " . fnameescape(b:asmsyntax) 55endfunc 56 57func dist#ft#FTasmsyntax() 58 " see if file contains any asmsyntax=foo overrides. If so, change 59 " b:asmsyntax appropriately 60 let head = " ".getline(1)." ".getline(2)." ".getline(3)." ".getline(4). 61 \" ".getline(5)." " 62 let match = matchstr(head, '\sasmsyntax=\zs[a-zA-Z0-9]\+\ze\s') 63 if match != '' 64 let b:asmsyntax = match 65 elseif ((head =~? '\.title') || (head =~? '\.ident') || (head =~? '\.macro') || (head =~? '\.subtitle') || (head =~? '\.library')) 66 let b:asmsyntax = "vmasm" 67 endif 68endfunc 69 70" Check if one of the first five lines contains "VB_Name". In that case it is 71" probably a Visual Basic file. Otherwise it's assumed to be "alt" filetype. 72func dist#ft#FTVB(alt) 73 if getline(1).getline(2).getline(3).getline(4).getline(5) =~? 'VB_Name\|Begin VB\.\(Form\|MDIForm\|UserControl\)' 74 setf vb 75 else 76 exe "setf " . a:alt 77 endif 78endfunc 79 80func dist#ft#FTbtm() 81 if exists("g:dosbatch_syntax_for_btm") && g:dosbatch_syntax_for_btm 82 setf dosbatch 83 else 84 setf btm 85 endif 86endfunc 87 88func dist#ft#BindzoneCheck(default) 89 if getline(1).getline(2).getline(3).getline(4) =~ '^; <<>> DiG [0-9.]\+.* <<>>\|$ORIGIN\|$TTL\|IN\s\+SOA' 90 setf bindzone 91 elseif a:default != '' 92 exe 'setf ' . a:default 93 endif 94endfunc 95 96func dist#ft#FTlpc() 97 if exists("g:lpc_syntax_for_c") 98 let lnum = 1 99 while lnum <= 12 100 if getline(lnum) =~# '^\(//\|inherit\|private\|protected\|nosave\|string\|object\|mapping\|mixed\)' 101 setf lpc 102 return 103 endif 104 let lnum = lnum + 1 105 endwhile 106 endif 107 setf c 108endfunc 109 110func dist#ft#FTheader() 111 if match(getline(1, min([line("$"), 200])), '^@\(interface\|end\|class\)') > -1 112 if exists("g:c_syntax_for_h") 113 setf objc 114 else 115 setf objcpp 116 endif 117 elseif exists("g:c_syntax_for_h") 118 setf c 119 elseif exists("g:ch_syntax_for_h") 120 setf ch 121 else 122 setf cpp 123 endif 124endfunc 125 126" This function checks if one of the first ten lines start with a '@'. In 127" that case it is probably a change file. 128" If the first line starts with # or ! it's probably a ch file. 129" If a line has "main", "include", "//" or "/*" it's probably ch. 130" Otherwise CHILL is assumed. 131func dist#ft#FTchange() 132 let lnum = 1 133 while lnum <= 10 134 if getline(lnum)[0] == '@' 135 setf change 136 return 137 endif 138 if lnum == 1 && (getline(1)[0] == '#' || getline(1)[0] == '!') 139 setf ch 140 return 141 endif 142 if getline(lnum) =~ "MODULE" 143 setf chill 144 return 145 endif 146 if getline(lnum) =~ 'main\s*(\|#\s*include\|//' 147 setf ch 148 return 149 endif 150 let lnum = lnum + 1 151 endwhile 152 setf chill 153endfunc 154 155func dist#ft#FTent() 156 " This function checks for valid cl syntax in the first five lines. 157 " Look for either an opening comment, '#', or a block start, '{". 158 " If not found, assume SGML. 159 let lnum = 1 160 while lnum < 6 161 let line = getline(lnum) 162 if line =~ '^\s*[#{]' 163 setf cl 164 return 165 elseif line !~ '^\s*$' 166 " Not a blank line, not a comment, and not a block start, 167 " so doesn't look like valid cl code. 168 break 169 endif 170 let lnum = lnum + 1 171 endw 172 setf dtd 173endfunc 174 175func dist#ft#ExCheck() 176 let lines = getline(1, min([line("$"), 100])) 177 if exists('g:filetype_euphoria') 178 exe 'setf ' . g:filetype_euphoria 179 elseif match(lines, '^--\|^ifdef\>\|^include\>') > -1 180 setf euphoria3 181 else 182 setf elixir 183 endif 184endfunc 185 186func dist#ft#EuphoriaCheck() 187 if exists('g:filetype_euphoria') 188 exe 'setf ' . g:filetype_euphoria 189 else 190 setf euphoria3 191 endif 192endfunc 193 194func dist#ft#DtraceCheck() 195 let lines = getline(1, min([line("$"), 100])) 196 if match(lines, '^module\>\|^import\>') > -1 197 " D files often start with a module and/or import statement. 198 setf d 199 elseif match(lines, '^#!\S\+dtrace\|#pragma\s\+D\s\+option\|:\S\{-}:\S\{-}:') > -1 200 setf dtrace 201 else 202 setf d 203 endif 204endfunc 205 206func dist#ft#FTe() 207 if exists('g:filetype_euphoria') 208 exe 'setf ' . g:filetype_euphoria 209 else 210 let n = 1 211 while n < 100 && n <= line("$") 212 if getline(n) =~ "^\\s*\\(<'\\|'>\\)\\s*$" 213 setf specman 214 return 215 endif 216 let n = n + 1 217 endwhile 218 setf eiffel 219 endif 220endfunc 221 222" Distinguish between HTML, XHTML and Django 223func dist#ft#FThtml() 224 let n = 1 225 while n < 10 && n <= line("$") 226 if getline(n) =~ '\<DTD\s\+XHTML\s' 227 setf xhtml 228 return 229 endif 230 if getline(n) =~ '{%\s*\(extends\|block\|load\)\>\|{#\s\+' 231 setf htmldjango 232 return 233 endif 234 let n = n + 1 235 endwhile 236 setf FALLBACK html 237endfunc 238 239" Distinguish between standard IDL and MS-IDL 240func dist#ft#FTidl() 241 let n = 1 242 while n < 50 && n <= line("$") 243 if getline(n) =~ '^\s*import\s\+"\(unknwn\|objidl\)\.idl"' 244 setf msidl 245 return 246 endif 247 let n = n + 1 248 endwhile 249 setf idl 250endfunc 251 252" Distinguish between "default" and Cproto prototype file. */ 253func dist#ft#ProtoCheck(default) 254 " Cproto files have a comment in the first line and a function prototype in 255 " the second line, it always ends in ";". Indent files may also have 256 " comments, thus we can't match comments to see the difference. 257 " IDL files can have a single ';' in the second line, require at least one 258 " chacter before the ';'. 259 if getline(2) =~ '.;$' 260 setf cpp 261 else 262 exe 'setf ' . a:default 263 endif 264endfunc 265 266func dist#ft#FTm() 267 if exists("g:filetype_m") 268 exe "setf " . g:filetype_m 269 return 270 endif 271 272 " excluding end(for|function|if|switch|while) common to Murphi 273 let octave_block_terminators = '\<end\%(_try_catch\|classdef\|enumeration\|events\|methods\|parfor\|properties\)\>' 274 275 let n = 1 276 let saw_comment = 0 " Whether we've seen a multiline comment leader. 277 while n < 100 278 let line = getline(n) 279 if line =~ '^\s*/\*' 280 " /* ... */ is a comment in Objective C and Murphi, so we can't conclude 281 " it's either of them yet, but track this as a hint in case we don't see 282 " anything more definitive. 283 let saw_comment = 1 284 endif 285 if line =~ '^\s*\(#\s*\(include\|import\)\>\|@import\>\|//\)' 286 setf objc 287 return 288 endif 289 if line =~ '^\s*\%(#\|%!\)' || line =~ '^\s*unwind_protect\>' || 290 \ line =~ '\%(^\|;\)\s*' .. octave_block_terminators 291 setf octave 292 return 293 endif 294 " TODO: could be Matlab or Octave 295 if line =~ '^\s*%' 296 setf matlab 297 return 298 endif 299 if line =~ '^\s*(\*' 300 setf mma 301 return 302 endif 303 if line =~ '^\c\s*\(\(type\|var\)\>\|--\)' 304 setf murphi 305 return 306 endif 307 let n = n + 1 308 endwhile 309 310 if saw_comment 311 " We didn't see anything definitive, but this looks like either Objective C 312 " or Murphi based on the comment leader. Assume the former as it is more 313 " common. 314 setf objc 315 else 316 " Default is Matlab 317 setf matlab 318 endif 319endfunc 320 321func dist#ft#FTmms() 322 let n = 1 323 while n < 20 324 let line = getline(n) 325 if line =~ '^\s*\(%\|//\)' || line =~ '^\*' 326 setf mmix 327 return 328 endif 329 if line =~ '^\s*#' 330 setf make 331 return 332 endif 333 let n = n + 1 334 endwhile 335 setf mmix 336endfunc 337 338" This function checks if one of the first five lines start with a dot. In 339" that case it is probably an nroff file: 'filetype' is set and 1 is returned. 340func dist#ft#FTnroff() 341 if getline(1)[0] . getline(2)[0] . getline(3)[0] . getline(4)[0] . getline(5)[0] =~ '\.' 342 setf nroff 343 return 1 344 endif 345 return 0 346endfunc 347 348func dist#ft#FTmm() 349 let n = 1 350 while n < 20 351 let line = getline(n) 352 if line =~ '^\s*\(#\s*\(include\|import\)\>\|@import\>\|/\*\)' 353 setf objcpp 354 return 355 endif 356 let n = n + 1 357 endwhile 358 setf nroff 359endfunc 360 361func dist#ft#FTpl() 362 if exists("g:filetype_pl") 363 exe "setf " . g:filetype_pl 364 else 365 " recognize Prolog by specific text in the first non-empty line 366 " require a blank after the '%' because Perl uses "%list" and "%translate" 367 let l = getline(nextnonblank(1)) 368 if l =~ '\<prolog\>' || l =~ '^\s*\(%\+\(\s\|$\)\|/\*\)' || l =~ ':-' 369 setf prolog 370 else 371 setf perl 372 endif 373 endif 374endfunc 375 376func dist#ft#FTinc() 377 if exists("g:filetype_inc") 378 exe "setf " . g:filetype_inc 379 else 380 let lines = getline(1).getline(2).getline(3) 381 if lines =~? "perlscript" 382 setf aspperl 383 elseif lines =~ "<%" 384 setf aspvbs 385 elseif lines =~ "<?" 386 setf php 387 " Pascal supports // comments but they're vary rarely used for file 388 " headers so assume POV-Ray 389 elseif lines =~ '^\s*\%({\|(\*\)' || lines =~? s:ft_pascal_keywords 390 setf pascal 391 else 392 call dist#ft#FTasmsyntax() 393 if exists("b:asmsyntax") 394 exe "setf " . fnameescape(b:asmsyntax) 395 else 396 setf pov 397 endif 398 endif 399 endif 400endfunc 401 402func dist#ft#FTprogress_cweb() 403 if exists("g:filetype_w") 404 exe "setf " . g:filetype_w 405 return 406 endif 407 if getline(1) =~ '&ANALYZE' || getline(3) =~ '&GLOBAL-DEFINE' 408 setf progress 409 else 410 setf cweb 411 endif 412endfunc 413 414func dist#ft#FTprogress_asm() 415 if exists("g:filetype_i") 416 exe "setf " . g:filetype_i 417 return 418 endif 419 " This function checks for an assembly comment the first ten lines. 420 " If not found, assume Progress. 421 let lnum = 1 422 while lnum <= 10 && lnum < line('$') 423 let line = getline(lnum) 424 if line =~ '^\s*;' || line =~ '^\*' 425 call dist#ft#FTasm() 426 return 427 elseif line !~ '^\s*$' || line =~ '^/\*' 428 " Not an empty line: Doesn't look like valid assembly code. 429 " Or it looks like a Progress /* comment 430 break 431 endif 432 let lnum = lnum + 1 433 endw 434 setf progress 435endfunc 436 437let s:ft_pascal_comments = '^\s*\%({\|(\*\|//\)' 438let s:ft_pascal_keywords = '^\s*\%(program\|unit\|library\|uses\|begin\|procedure\|function\|const\|type\|var\)\>' 439 440func dist#ft#FTprogress_pascal() 441 if exists("g:filetype_p") 442 exe "setf " . g:filetype_p 443 return 444 endif 445 " This function checks for valid Pascal syntax in the first ten lines. 446 " Look for either an opening comment or a program start. 447 " If not found, assume Progress. 448 let lnum = 1 449 while lnum <= 10 && lnum < line('$') 450 let line = getline(lnum) 451 if line =~ s:ft_pascal_comments || line =~? s:ft_pascal_keywords 452 setf pascal 453 return 454 elseif line !~ '^\s*$' || line =~ '^/\*' 455 " Not an empty line: Doesn't look like valid Pascal code. 456 " Or it looks like a Progress /* comment 457 break 458 endif 459 let lnum = lnum + 1 460 endw 461 setf progress 462endfunc 463 464func dist#ft#FTpp() 465 if exists("g:filetype_pp") 466 exe "setf " . g:filetype_pp 467 else 468 let line = getline(nextnonblank(1)) 469 if line =~ s:ft_pascal_comments || line =~? s:ft_pascal_keywords 470 setf pascal 471 else 472 setf puppet 473 endif 474 endif 475endfunc 476 477func dist#ft#FTr() 478 let max = line("$") > 50 ? 50 : line("$") 479 480 for n in range(1, max) 481 " Rebol is easy to recognize, check for that first 482 if getline(n) =~? '\<REBOL\>' 483 setf rebol 484 return 485 endif 486 endfor 487 488 for n in range(1, max) 489 " R has # comments 490 if getline(n) =~ '^\s*#' 491 setf r 492 return 493 endif 494 " Rexx has /* comments */ 495 if getline(n) =~ '^\s*/\*' 496 setf rexx 497 return 498 endif 499 endfor 500 501 " Nothing recognized, use user default or assume Rexx 502 if exists("g:filetype_r") 503 exe "setf " . g:filetype_r 504 else 505 " Rexx used to be the default, but R appears to be much more popular. 506 setf r 507 endif 508endfunc 509 510func dist#ft#McSetf() 511 " Rely on the file to start with a comment. 512 " MS message text files use ';', Sendmail files use '#' or 'dnl' 513 for lnum in range(1, min([line("$"), 20])) 514 let line = getline(lnum) 515 if line =~ '^\s*\(#\|dnl\)' 516 setf m4 " Sendmail .mc file 517 return 518 elseif line =~ '^\s*;' 519 setf msmessages " MS Message text file 520 return 521 endif 522 endfor 523 setf m4 " Default: Sendmail .mc file 524endfunc 525 526" Called from filetype.vim and scripts.vim. 527func dist#ft#SetFileTypeSH(name) 528 if did_filetype() 529 " Filetype was already detected 530 return 531 endif 532 if expand("<amatch>") =~ g:ft_ignore_pat 533 return 534 endif 535 if a:name =~ '\<csh\>' 536 " Some .sh scripts contain #!/bin/csh. 537 call dist#ft#SetFileTypeShell("csh") 538 return 539 elseif a:name =~ '\<tcsh\>' 540 " Some .sh scripts contain #!/bin/tcsh. 541 call dist#ft#SetFileTypeShell("tcsh") 542 return 543 elseif a:name =~ '\<zsh\>' 544 " Some .sh scripts contain #!/bin/zsh. 545 call dist#ft#SetFileTypeShell("zsh") 546 return 547 elseif a:name =~ '\<ksh\>' 548 let b:is_kornshell = 1 549 if exists("b:is_bash") 550 unlet b:is_bash 551 endif 552 if exists("b:is_sh") 553 unlet b:is_sh 554 endif 555 elseif exists("g:bash_is_sh") || a:name =~ '\<bash\>' || a:name =~ '\<bash2\>' 556 let b:is_bash = 1 557 if exists("b:is_kornshell") 558 unlet b:is_kornshell 559 endif 560 if exists("b:is_sh") 561 unlet b:is_sh 562 endif 563 elseif a:name =~ '\<sh\>' 564 let b:is_sh = 1 565 if exists("b:is_kornshell") 566 unlet b:is_kornshell 567 endif 568 if exists("b:is_bash") 569 unlet b:is_bash 570 endif 571 endif 572 call dist#ft#SetFileTypeShell("sh") 573endfunc 574 575" For shell-like file types, check for an "exec" command hidden in a comment, 576" as used for Tcl. 577" Also called from scripts.vim, thus can't be local to this script. 578func dist#ft#SetFileTypeShell(name) 579 if did_filetype() 580 " Filetype was already detected 581 return 582 endif 583 if expand("<amatch>") =~ g:ft_ignore_pat 584 return 585 endif 586 let l = 2 587 while l < 20 && l < line("$") && getline(l) =~ '^\s*\(#\|$\)' 588 " Skip empty and comment lines. 589 let l = l + 1 590 endwhile 591 if l < line("$") && getline(l) =~ '\s*exec\s' && getline(l - 1) =~ '^\s*#.*\\$' 592 " Found an "exec" line after a comment with continuation 593 let n = substitute(getline(l),'\s*exec\s\+\([^ ]*/\)\=', '', '') 594 if n =~ '\<tclsh\|\<wish' 595 setf tcl 596 return 597 endif 598 endif 599 exe "setf " . a:name 600endfunc 601 602func dist#ft#CSH() 603 if did_filetype() 604 " Filetype was already detected 605 return 606 endif 607 if exists("g:filetype_csh") 608 call dist#ft#SetFileTypeShell(g:filetype_csh) 609 elseif &shell =~ "tcsh" 610 call dist#ft#SetFileTypeShell("tcsh") 611 else 612 call dist#ft#SetFileTypeShell("csh") 613 endif 614endfunc 615 616let s:ft_rules_udev_rules_pattern = '^\s*\cudev_rules\s*=\s*"\([^"]\{-1,}\)/*".*' 617func dist#ft#FTRules() 618 let path = expand('<amatch>:p') 619 if path =~ '/\(etc/udev/\%(rules\.d/\)\=.*\.rules\|\%(usr/\)\=lib/udev/\%(rules\.d/\)\=.*\.rules\)$' 620 setf udevrules 621 return 622 endif 623 if path =~ '^/etc/ufw/' 624 setf conf " Better than hog 625 return 626 endif 627 if path =~ '^/\(etc\|usr/share\)/polkit-1/rules\.d' 628 setf javascript 629 return 630 endif 631 try 632 let config_lines = readfile('/etc/udev/udev.conf') 633 catch /^Vim\%((\a\+)\)\=:E484/ 634 setf hog 635 return 636 endtry 637 let dir = expand('<amatch>:p:h') 638 for line in config_lines 639 if line =~ s:ft_rules_udev_rules_pattern 640 let udev_rules = substitute(line, s:ft_rules_udev_rules_pattern, '\1', "") 641 if dir == udev_rules 642 setf udevrules 643 endif 644 break 645 endif 646 endfor 647 setf hog 648endfunc 649 650func dist#ft#SQL() 651 if exists("g:filetype_sql") 652 exe "setf " . g:filetype_sql 653 else 654 setf sql 655 endif 656endfunc 657 658" If the file has an extension of 't' and is in a directory 't' or 'xt' then 659" it is almost certainly a Perl test file. 660" If the first line starts with '#' and contains 'perl' it's probably a Perl 661" file. 662" (Slow test) If a file contains a 'use' statement then it is almost certainly 663" a Perl file. 664func dist#ft#FTperl() 665 let dirname = expand("%:p:h:t") 666 if expand("%:e") == 't' && (dirname == 't' || dirname == 'xt') 667 setf perl 668 return 1 669 endif 670 if getline(1)[0] == '#' && getline(1) =~ 'perl' 671 setf perl 672 return 1 673 endif 674 let save_cursor = getpos('.') 675 call cursor(1,1) 676 let has_use = search('^use\s\s*\k', 'c', 30) 677 call setpos('.', save_cursor) 678 if has_use 679 setf perl 680 return 1 681 endif 682 return 0 683endfunc 684 685" Choose context, plaintex, or tex (LaTeX) based on these rules: 686" 1. Check the first line of the file for "%&<format>". 687" 2. Check the first 1000 non-comment lines for LaTeX or ConTeXt keywords. 688" 3. Default to "plain" or to g:tex_flavor, can be set in user's vimrc. 689func dist#ft#FTtex() 690 let firstline = getline(1) 691 if firstline =~ '^%&\s*\a\+' 692 let format = tolower(matchstr(firstline, '\a\+')) 693 let format = substitute(format, 'pdf', '', '') 694 if format == 'tex' 695 let format = 'latex' 696 elseif format == 'plaintex' 697 let format = 'plain' 698 endif 699 elseif expand('%') =~ 'tex/context/.*/.*.tex' 700 let format = 'context' 701 else 702 " Default value, may be changed later: 703 let format = exists("g:tex_flavor") ? g:tex_flavor : 'plain' 704 " Save position, go to the top of the file, find first non-comment line. 705 let save_cursor = getpos('.') 706 call cursor(1,1) 707 let firstNC = search('^\s*[^[:space:]%]', 'c', 1000) 708 if firstNC " Check the next thousand lines for a LaTeX or ConTeXt keyword. 709 let lpat = 'documentclass\>\|usepackage\>\|begin{\|newcommand\>\|renewcommand\>' 710 let cpat = 'start\a\+\|setup\a\+\|usemodule\|enablemode\|enableregime\|setvariables\|useencoding\|usesymbols\|stelle\a\+\|verwende\a\+\|stel\a\+\|gebruik\a\+\|usa\a\+\|imposta\a\+\|regle\a\+\|utilisemodule\>' 711 let kwline = search('^\s*\\\%(' . lpat . '\)\|^\s*\\\(' . cpat . '\)', 712 \ 'cnp', firstNC + 1000) 713 if kwline == 1 " lpat matched 714 let format = 'latex' 715 elseif kwline == 2 " cpat matched 716 let format = 'context' 717 endif " If neither matched, keep default set above. 718 " let lline = search('^\s*\\\%(' . lpat . '\)', 'cn', firstNC + 1000) 719 " let cline = search('^\s*\\\%(' . cpat . '\)', 'cn', firstNC + 1000) 720 " if cline > 0 721 " let format = 'context' 722 " endif 723 " if lline > 0 && (cline == 0 || cline > lline) 724 " let format = 'tex' 725 " endif 726 endif " firstNC 727 call setpos('.', save_cursor) 728 endif " firstline =~ '^%&\s*\a\+' 729 730 " Translation from formats to file types. TODO: add AMSTeX, RevTex, others? 731 if format == 'plain' 732 setf plaintex 733 elseif format == 'context' 734 setf context 735 else " probably LaTeX 736 setf tex 737 endif 738 return 739endfunc 740 741func dist#ft#FTxml() 742 let n = 1 743 while n < 100 && n <= line("$") 744 let line = getline(n) 745 " DocBook 4 or DocBook 5. 746 let is_docbook4 = line =~ '<!DOCTYPE.*DocBook' 747 let is_docbook5 = line =~ ' xmlns="http://docbook.org/ns/docbook"' 748 if is_docbook4 || is_docbook5 749 let b:docbk_type = "xml" 750 if is_docbook5 751 let b:docbk_ver = 5 752 else 753 let b:docbk_ver = 4 754 endif 755 setf docbk 756 return 757 endif 758 if line =~ 'xmlns:xbl="http://www.mozilla.org/xbl"' 759 setf xbl 760 return 761 endif 762 let n += 1 763 endwhile 764 setf xml 765endfunc 766 767func dist#ft#FTy() 768 let n = 1 769 while n < 100 && n <= line("$") 770 let line = getline(n) 771 if line =~ '^\s*%' 772 setf yacc 773 return 774 endif 775 if getline(n) =~ '^\s*\(#\|class\>\)' && getline(n) !~ '^\s*#\s*include' 776 setf racc 777 return 778 endif 779 let n = n + 1 780 endwhile 781 setf yacc 782endfunc 783 784func dist#ft#Redif() 785 let lnum = 1 786 while lnum <= 5 && lnum < line('$') 787 if getline(lnum) =~ "^\ctemplate-type:" 788 setf redif 789 return 790 endif 791 let lnum = lnum + 1 792 endwhile 793endfunc 794 795 796" Restore 'cpoptions' 797let &cpo = s:cpo_save 798unlet s:cpo_save 799