Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 1 | vim9script |
| 2 | |
| 3 | # Vim function for detecting a filetype from the file contents. |
| 4 | # Invoked from "scripts.vim" in 'runtimepath' |
| 5 | # |
Christian Brabandt | e978b45 | 2023-08-13 10:33:05 +0200 | [diff] [blame] | 6 | # Maintainer: The Vim Project <https://github.com/vim/vim> |
Eisuke Kawashima | f102f4c | 2025-04-24 22:03:21 +0200 | [diff] [blame] | 7 | # Last Change: 2025 Apr 24 |
Christian Brabandt | e978b45 | 2023-08-13 10:33:05 +0200 | [diff] [blame] | 8 | # Former Maintainer: Bram Moolenaar <Bram@vim.org> |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 9 | |
| 10 | export def DetectFiletype() |
| 11 | var line1 = getline(1) |
| 12 | if line1[0] == '#' && line1[1] == '!' |
| 13 | # File that starts with "#!". |
| 14 | DetectFromHashBang(line1) |
| 15 | else |
| 16 | # File does not start with "#!". |
| 17 | DetectFromText(line1) |
| 18 | endif |
| 19 | enddef |
| 20 | |
| 21 | # Called for a script that has "#!" in the first line. |
| 22 | def DetectFromHashBang(firstline: string) |
| 23 | var line1 = firstline |
| 24 | |
| 25 | # Check for a line like "#!/usr/bin/env {options} bash". Turn it into |
| 26 | # "#!/usr/bin/bash" to make matching easier. |
| 27 | # Recognize only a few {options} that are commonly used. |
| 28 | if line1 =~ '^#!\s*\S*\<env\s' |
Eisuke Kawashima | f102f4c | 2025-04-24 22:03:21 +0200 | [diff] [blame] | 29 | line1 = substitute(line1, '\s\zs--split-string[ \t=]', '', '') |
| 30 | line1 = substitute(line1, '\s\zs[A-Za-z0-9_]\+=\S*\ze\s', '', 'g') |
| 31 | line1 = substitute(line1, '\s\zs\%(-[iS]\+\|--ignore-environment\)\ze\s', '', 'g') |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 32 | line1 = substitute(line1, '\<env\s\+', '', '') |
| 33 | endif |
| 34 | |
| 35 | # Get the program name. |
| 36 | # Only accept spaces in PC style paths: "#!c:/program files/perl [args]". |
| 37 | # If the word env is used, use the first word after the space: |
| 38 | # "#!/usr/bin/env perl [path/args]" |
| 39 | # If there is no path use the first word: "#!perl [path/args]". |
| 40 | # Otherwise get the last word after a slash: "#!/usr/bin/perl [path/args]". |
| 41 | var name: string |
| 42 | if line1 =~ '^#!\s*\a:[/\\]' |
| 43 | name = substitute(line1, '^#!.*[/\\]\(\i\+\).*', '\1', '') |
| 44 | elseif line1 =~ '^#!.*\<env\>' |
| 45 | name = substitute(line1, '^#!.*\<env\>\s\+\(\i\+\).*', '\1', '') |
| 46 | elseif line1 =~ '^#!\s*[^/\\ ]*\>\([^/\\]\|$\)' |
| 47 | name = substitute(line1, '^#!\s*\([^/\\ ]*\>\).*', '\1', '') |
| 48 | else |
Bram Moolenaar | 19548c6 | 2023-06-08 21:27:13 +0100 | [diff] [blame] | 49 | name = substitute(line1, '^#!\s*\S*[/\\]\(\f\+\).*', '\1', '') |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 50 | endif |
| 51 | |
| 52 | # tcl scripts may have #!/bin/sh in the first line and "exec wish" in the |
| 53 | # third line. Suggested by Steven Atkinson. |
| 54 | if getline(3) =~ '^exec wish' |
| 55 | name = 'wish' |
| 56 | endif |
| 57 | |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 58 | var ft = Exe2filetype(name, line1) |
| 59 | if ft != '' |
| 60 | exe 'setl ft=' .. ft |
| 61 | endif |
| 62 | enddef |
| 63 | |
| 64 | # Returns the filetype name associated with program "name". |
| 65 | # "line1" is the #! line at the top of the file. Use the same as "name" if |
| 66 | # not available. |
| 67 | # Returns an empty string when not recognized. |
| 68 | export def Exe2filetype(name: string, line1: string): string |
Eisuke Kawashima | 24482fb | 2022-11-24 10:58:10 +0000 | [diff] [blame] | 69 | # Bourne-like shell scripts: bash bash2 dash ksh ksh93 sh |
| 70 | if name =~ '^\(bash\d*\|dash\|ksh\d*\|sh\)\>' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 71 | return dist#ft#SetFileTypeSH(line1, false) |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 72 | |
| 73 | # csh scripts |
| 74 | elseif name =~ '^csh\>' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 75 | return dist#ft#SetFileTypeShell(exists("g:filetype_csh") ? g:filetype_csh : 'csh', false) |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 76 | |
| 77 | # tcsh scripts |
| 78 | elseif name =~ '^tcsh\>' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 79 | return dist#ft#SetFileTypeShell("tcsh", false) |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 80 | |
| 81 | # Z shell scripts |
| 82 | elseif name =~ '^zsh\>' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 83 | return 'zsh' |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 84 | |
| 85 | # TCL scripts |
| 86 | elseif name =~ '^\(tclsh\|wish\|expectk\|itclsh\|itkwish\)\>' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 87 | return 'tcl' |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 88 | |
| 89 | # Expect scripts |
| 90 | elseif name =~ '^expect\>' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 91 | return 'expect' |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 92 | |
| 93 | # Gnuplot scripts |
| 94 | elseif name =~ '^gnuplot\>' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 95 | return 'gnuplot' |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 96 | |
| 97 | # Makefiles |
| 98 | elseif name =~ 'make\>' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 99 | return 'make' |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 100 | |
| 101 | # Pike |
| 102 | elseif name =~ '^pike\%(\>\|[0-9]\)' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 103 | return 'pike' |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 104 | |
| 105 | # Lua |
| 106 | elseif name =~ 'lua' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 107 | return 'lua' |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 108 | |
| 109 | # Perl |
| 110 | elseif name =~ 'perl' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 111 | return 'perl' |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 112 | |
| 113 | # PHP |
| 114 | elseif name =~ 'php' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 115 | return 'php' |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 116 | |
| 117 | # Python |
| 118 | elseif name =~ 'python' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 119 | return 'python' |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 120 | |
| 121 | # Groovy |
| 122 | elseif name =~ '^groovy\>' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 123 | return 'groovy' |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 124 | |
| 125 | # Raku |
| 126 | elseif name =~ 'raku' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 127 | return 'raku' |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 128 | |
| 129 | # Ruby |
| 130 | elseif name =~ 'ruby' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 131 | return 'ruby' |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 132 | |
| 133 | # JavaScript |
| 134 | elseif name =~ 'node\(js\)\=\>\|js\>' || name =~ 'rhino\>' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 135 | return 'javascript' |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 136 | |
Peter Benjamin | 72755b3 | 2025-01-20 21:56:41 +0100 | [diff] [blame] | 137 | elseif name =~# 'just' |
| 138 | return 'just' |
| 139 | |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 140 | # BC calculator |
| 141 | elseif name =~ '^bc\>' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 142 | return 'bc' |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 143 | |
| 144 | # sed |
| 145 | elseif name =~ 'sed\>' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 146 | return 'sed' |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 147 | |
| 148 | # OCaml-scripts |
| 149 | elseif name =~ 'ocaml' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 150 | return 'ocaml' |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 151 | |
| 152 | # Awk scripts; also finds "gawk" |
| 153 | elseif name =~ 'awk\>' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 154 | return 'awk' |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 155 | |
| 156 | # Website MetaLanguage |
| 157 | elseif name =~ 'wml' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 158 | return 'wml' |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 159 | |
| 160 | # Scheme scripts |
| 161 | elseif name =~ 'scheme' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 162 | return 'scheme' |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 163 | |
| 164 | # CFEngine scripts |
| 165 | elseif name =~ 'cfengine' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 166 | return 'cfengine' |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 167 | |
| 168 | # Erlang scripts |
| 169 | elseif name =~ 'escript' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 170 | return 'erlang' |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 171 | |
| 172 | # Haskell |
| 173 | elseif name =~ 'haskell' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 174 | return 'haskell' |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 175 | |
| 176 | # Scala |
| 177 | elseif name =~ 'scala\>' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 178 | return 'scala' |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 179 | |
| 180 | # Clojure |
| 181 | elseif name =~ 'clojure' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 182 | return 'clojure' |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 183 | |
| 184 | # Free Pascal |
| 185 | elseif name =~ 'instantfpc\>' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 186 | return 'pascal' |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 187 | |
| 188 | # Fennel |
| 189 | elseif name =~ 'fennel\>' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 190 | return 'fennel' |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 191 | |
| 192 | # MikroTik RouterOS script |
| 193 | elseif name =~ 'rsc\>' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 194 | return 'routeros' |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 195 | |
| 196 | # Fish shell |
| 197 | elseif name =~ 'fish\>' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 198 | return 'fish' |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 199 | |
| 200 | # Gforth |
| 201 | elseif name =~ 'gforth\>' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 202 | return 'forth' |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 203 | |
Bram Moolenaar | bf66146 | 2022-06-16 13:27:18 +0100 | [diff] [blame] | 204 | # Icon |
| 205 | elseif name =~ 'icon\>' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 206 | return 'icon' |
Bram Moolenaar | bf66146 | 2022-06-16 13:27:18 +0100 | [diff] [blame] | 207 | |
Bram Moolenaar | 3244780 | 2022-07-05 21:56:39 +0100 | [diff] [blame] | 208 | # Guile |
| 209 | elseif name =~ 'guile' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 210 | return 'scheme' |
Bram Moolenaar | 3244780 | 2022-07-05 21:56:39 +0100 | [diff] [blame] | 211 | |
Bram Moolenaar | 19548c6 | 2023-06-08 21:27:13 +0100 | [diff] [blame] | 212 | # Nix |
| 213 | elseif name =~ 'nix-shell' |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 214 | return 'nix' |
Bram Moolenaar | 19548c6 | 2023-06-08 21:27:13 +0100 | [diff] [blame] | 215 | |
Doug Kearns | 9b73902 | 2023-08-27 19:51:37 +0200 | [diff] [blame] | 216 | # Crystal |
| 217 | elseif name =~ '^crystal\>' |
| 218 | return 'crystal' |
| 219 | |
Doug Kearns | e06afb7 | 2023-08-29 22:21:35 +0200 | [diff] [blame] | 220 | # Rexx |
| 221 | elseif name =~ '^\%(rexx\|regina\)\>' |
| 222 | return 'rexx' |
| 223 | |
Doug Kearns | c038427 | 2023-10-23 19:24:05 +0200 | [diff] [blame] | 224 | # Janet |
| 225 | elseif name =~ '^janet\>' |
| 226 | return 'janet' |
| 227 | |
Doug Kearns | c1c177a | 2023-10-28 21:19:54 +0200 | [diff] [blame] | 228 | # Dart |
| 229 | elseif name =~ '^dart\>' |
| 230 | return 'dart' |
| 231 | |
Mazunki Hoksaas | 63210c2 | 2023-12-19 20:44:41 +0100 | [diff] [blame] | 232 | # Execline (s6) |
| 233 | elseif name =~ '^execlineb\>' |
| 234 | return 'execline' |
| 235 | |
Doug Kearns | 0d4d23d | 2024-06-16 08:32:15 +0200 | [diff] [blame] | 236 | # Vim |
| 237 | elseif name =~ '^vim\>' |
| 238 | return 'vim' |
| 239 | |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 240 | endif |
Bram Moolenaar | f07d1a7 | 2023-06-09 21:01:47 +0100 | [diff] [blame] | 241 | |
| 242 | return '' |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 243 | enddef |
| 244 | |
| 245 | |
| 246 | # Called for a script that does not have "#!" in the first line. |
| 247 | def DetectFromText(line1: string) |
| 248 | var line2 = getline(2) |
| 249 | var line3 = getline(3) |
| 250 | var line4 = getline(4) |
| 251 | var line5 = getline(5) |
| 252 | |
| 253 | # Bourne-like shell scripts: sh ksh bash bash2 |
| 254 | if line1 =~ '^:$' |
| 255 | call dist#ft#SetFileTypeSH(line1) |
| 256 | |
| 257 | # Z shell scripts |
| 258 | elseif line1 =~ '^#compdef\>' |
| 259 | || line1 =~ '^#autoload\>' |
| 260 | || "\n" .. line1 .. "\n" .. line2 .. "\n" .. line3 .. |
| 261 | "\n" .. line4 .. "\n" .. line5 |
| 262 | =~ '\n\s*emulate\s\+\%(-[LR]\s\+\)\=[ckz]\=sh\>' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 263 | setl ft=zsh |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 264 | |
| 265 | # ELM Mail files |
| 266 | elseif line1 =~ '^From \([a-zA-Z][a-zA-Z_0-9\.=-]*\(@[^ ]*\)\=\|-\) .* \(19\|20\)\d\d$' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 267 | setl ft=mail |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 268 | |
| 269 | # Mason |
| 270 | elseif line1 =~ '^<[%&].*>' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 271 | setl ft=mason |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 272 | |
| 273 | # Vim scripts (must have '" vim' as the first line to trigger this) |
| 274 | elseif line1 =~ '^" *[vV]im$' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 275 | setl ft=vim |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 276 | |
| 277 | # libcxx and libstdc++ standard library headers like "iostream" do not have |
| 278 | # an extension, recognize the Emacs file mode. |
| 279 | elseif line1 =~? '-\*-.*C++.*-\*-' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 280 | setl ft=cpp |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 281 | |
| 282 | # MOO |
| 283 | elseif line1 =~ '^\*\* LambdaMOO Database, Format Version \%([1-3]\>\)\@!\d\+ \*\*$' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 284 | setl ft=moo |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 285 | |
| 286 | # Diff file: |
| 287 | # - "diff" in first line (context diff) |
| 288 | # - "Only in " in first line |
| 289 | # - "--- " in first line and "+++ " in second line (unified diff). |
| 290 | # - "*** " in first line and "--- " in second line (context diff). |
| 291 | # - "# It was generated by makepatch " in the second line (makepatch diff). |
| 292 | # - "Index: <filename>" in the first line (CVS file) |
| 293 | # - "=== ", line of "=", "---", "+++ " (SVK diff) |
| 294 | # - "=== ", "--- ", "+++ " (bzr diff, common case) |
| 295 | # - "=== (removed|added|renamed|modified)" (bzr diff, alternative) |
| 296 | # - "# HG changeset patch" in first line (Mercurial export format) |
| 297 | elseif line1 =~ '^\(diff\>\|Only in \|\d\+\(,\d\+\)\=[cda]\d\+\>\|# It was generated by makepatch \|Index:\s\+\f\+\r\=$\|===== \f\+ \d\+\.\d\+ vs edited\|==== //\f\+#\d\+\|# HG changeset patch\)' |
| 298 | || (line1 =~ '^--- ' && line2 =~ '^+++ ') |
| 299 | || (line1 =~ '^\* looking for ' && line2 =~ '^\* comparing to ') |
| 300 | || (line1 =~ '^\*\*\* ' && line2 =~ '^--- ') |
| 301 | || (line1 =~ '^=== ' && ((line2 =~ '^=\{66\}' && line3 =~ '^--- ' && line4 =~ '^+++') || (line2 =~ '^--- ' && line3 =~ '^+++ '))) |
| 302 | || (line1 =~ '^=== \(removed\|added\|renamed\|modified\)') |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 303 | setl ft=diff |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 304 | |
| 305 | # PostScript Files (must have %!PS as the first line, like a2ps output) |
| 306 | elseif line1 =~ '^%![ \t]*PS' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 307 | setl ft=postscr |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 308 | |
| 309 | # M4 scripts: Guess there is a line that starts with "dnl". |
| 310 | elseif line1 =~ '^\s*dnl\>' |
| 311 | || line2 =~ '^\s*dnl\>' |
| 312 | || line3 =~ '^\s*dnl\>' |
| 313 | || line4 =~ '^\s*dnl\>' |
| 314 | || line5 =~ '^\s*dnl\>' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 315 | setl ft=m4 |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 316 | |
| 317 | # AmigaDos scripts |
| 318 | elseif $TERM == "amiga" && (line1 =~ "^;" || line1 =~? '^\.bra') |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 319 | setl ft=amiga |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 320 | |
| 321 | # SiCAD scripts (must have procn or procd as the first line to trigger this) |
| 322 | elseif line1 =~? '^ *proc[nd] *$' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 323 | setl ft=sicad |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 324 | |
| 325 | # Purify log files start with "**** Purify" |
| 326 | elseif line1 =~ '^\*\*\*\* Purify' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 327 | setl ft=purifylog |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 328 | |
| 329 | # XML |
| 330 | elseif line1 =~ '<?\s*xml.*?>' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 331 | setl ft=xml |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 332 | |
| 333 | # XHTML (e.g.: PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN") |
| 334 | elseif line1 =~ '\<DTD\s\+XHTML\s' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 335 | setl ft=xhtml |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 336 | |
| 337 | # HTML (e.g.: <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN") |
| 338 | # Avoid "doctype html", used by slim. |
| 339 | elseif line1 =~? '<!DOCTYPE\s\+html\>' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 340 | setl ft=html |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 341 | |
| 342 | # PDF |
| 343 | elseif line1 =~ '^%PDF-' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 344 | setl ft=pdf |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 345 | |
| 346 | # XXD output |
| 347 | elseif line1 =~ '^\x\{7}: \x\{2} \=\x\{2} \=\x\{2} \=\x\{2} ' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 348 | setl ft=xxd |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 349 | |
| 350 | # RCS/CVS log output |
| 351 | elseif line1 =~ '^RCS file:' || line2 =~ '^RCS file:' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 352 | setl ft=rcslog |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 353 | |
| 354 | # CVS commit |
| 355 | elseif line2 =~ '^CVS:' || getline("$") =~ '^CVS: ' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 356 | setl ft=cvs |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 357 | |
| 358 | # Prescribe |
| 359 | elseif line1 =~ '^!R!' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 360 | setl ft=prescribe |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 361 | |
| 362 | # Send-pr |
| 363 | elseif line1 =~ '^SEND-PR:' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 364 | setl ft=sendpr |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 365 | |
| 366 | # SNNS files |
| 367 | elseif line1 =~ '^SNNS network definition file' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 368 | setl ft=snnsnet |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 369 | elseif line1 =~ '^SNNS pattern definition file' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 370 | setl ft=snnspat |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 371 | elseif line1 =~ '^SNNS result file' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 372 | setl ft=snnsres |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 373 | |
| 374 | # Virata |
| 375 | elseif line1 =~ '^%.\{-}[Vv]irata' |
| 376 | || line2 =~ '^%.\{-}[Vv]irata' |
| 377 | || line3 =~ '^%.\{-}[Vv]irata' |
| 378 | || line4 =~ '^%.\{-}[Vv]irata' |
| 379 | || line5 =~ '^%.\{-}[Vv]irata' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 380 | setl ft=virata |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 381 | |
| 382 | # Strace |
Federico Mengozzi | 6e5a9f9 | 2023-04-17 22:31:38 +0100 | [diff] [blame] | 383 | # inaccurate fast match first, then use accurate slow match |
Jiri Slaby | 2f54c13 | 2023-11-04 09:39:54 +0100 | [diff] [blame] | 384 | elseif (line1 =~ 'execve(' && line1 =~ '^[0-9:. ]*execve(') |
Federico Mengozzi | 6e5a9f9 | 2023-04-17 22:31:38 +0100 | [diff] [blame] | 385 | || line1 =~ '^__libc_start_main' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 386 | setl ft=strace |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 387 | |
| 388 | # VSE JCL |
| 389 | elseif line1 =~ '^\* $$ JOB\>' || line1 =~ '^// *JOB\>' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 390 | setl ft=vsejcl |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 391 | |
| 392 | # TAK and SINDA |
| 393 | elseif line4 =~ 'K & K Associates' || line2 =~ 'TAK 2000' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 394 | setl ft=takout |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 395 | elseif line3 =~ 'S Y S T E M S I M P R O V E D ' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 396 | setl ft=sindaout |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 397 | elseif getline(6) =~ 'Run Date: ' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 398 | setl ft=takcmp |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 399 | elseif getline(9) =~ 'Node File 1' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 400 | setl ft=sindacmp |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 401 | |
| 402 | # DNS zone files |
| 403 | elseif line1 .. line2 .. line3 .. line4 =~ '^; <<>> DiG [0-9.]\+.* <<>>\|$ORIGIN\|$TTL\|IN\s\+SOA' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 404 | setl ft=bindzone |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 405 | |
| 406 | # BAAN |
| 407 | elseif line1 =~ '|\*\{1,80}' && line2 =~ 'VRC ' |
| 408 | || line2 =~ '|\*\{1,80}' && line3 =~ 'VRC ' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 409 | setl ft=baan |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 410 | |
| 411 | # Valgrind |
| 412 | elseif line1 =~ '^==\d\+== valgrind' || line3 =~ '^==\d\+== Using valgrind' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 413 | setl ft=valgrind |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 414 | |
| 415 | # Go docs |
| 416 | elseif line1 =~ '^PACKAGE DOCUMENTATION$' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 417 | setl ft=godoc |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 418 | |
| 419 | # Renderman Interface Bytestream |
| 420 | elseif line1 =~ '^##RenderMan' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 421 | setl ft=rib |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 422 | |
| 423 | # Scheme scripts |
| 424 | elseif line1 =~ 'exec\s\+\S*scheme' || line2 =~ 'exec\s\+\S*scheme' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 425 | setl ft=scheme |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 426 | |
| 427 | # Git output |
| 428 | elseif line1 =~ '^\(commit\|tree\|object\) \x\{40,\}\>\|^tag \S\+$' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 429 | setl ft=git |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 430 | |
| 431 | # Gprof (gnu profiler) |
| 432 | elseif line1 == 'Flat profile:' |
| 433 | && line2 == '' |
| 434 | && line3 =~ '^Each sample counts as .* seconds.$' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 435 | setl ft=gprof |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 436 | |
| 437 | # Erlang terms |
| 438 | # (See also: http://www.gnu.org/software/emacs/manual/html_node/emacs/Choosing-Modes.html#Choosing-Modes) |
| 439 | elseif line1 =~? '-\*-.*erlang.*-\*-' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 440 | setl ft=erlang |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 441 | |
| 442 | # YAML |
| 443 | elseif line1 =~ '^%YAML' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 444 | setl ft=yaml |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 445 | |
| 446 | # MikroTik RouterOS script |
| 447 | elseif line1 =~ '^#.*by RouterOS.*$' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 448 | setl ft=routeros |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 449 | |
| 450 | # Sed scripts |
| 451 | # #ncomment is allowed but most likely a false positive so require a space |
| 452 | # before any trailing comment text |
| 453 | elseif line1 =~ '^#n\%($\|\s\)' |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 454 | setl ft=sed |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 455 | |
| 456 | else |
| 457 | var lnum = 1 |
| 458 | while getline(lnum) =~ "^? " && lnum < line("$") |
| 459 | lnum += 1 |
| 460 | endwhile |
| 461 | if getline(lnum) =~ '^Index:\s\+\f\+$' |
| 462 | # CVS diff |
Bram Moolenaar | 0b70aeb | 2023-05-06 21:21:52 +0100 | [diff] [blame] | 463 | setl ft=diff |
Bram Moolenaar | 299d8e5 | 2022-02-13 20:32:02 +0000 | [diff] [blame] | 464 | |
| 465 | # locale input files: Formal Definitions of Cultural Conventions |
| 466 | # filename must be like en_US, fr_FR@euro or en_US.UTF-8 |
| 467 | elseif expand("%") =~ '\a\a_\a\a\($\|[.@]\)\|i18n$\|POSIX$\|translit_' |
| 468 | lnum = 1 |
| 469 | while lnum < 100 && lnum < line("$") |
| 470 | if getline(lnum) =~ '^LC_\(IDENTIFICATION\|CTYPE\|COLLATE\|MONETARY\|NUMERIC\|TIME\|MESSAGES\|PAPER\|TELEPHONE\|MEASUREMENT\|NAME\|ADDRESS\)$' |
| 471 | setf fdcc |
| 472 | break |
| 473 | endif |
| 474 | lnum += 1 |
| 475 | endwhile |
| 476 | endif |
| 477 | endif |
| 478 | enddef |