mirror of
				https://github.com/KevinMidboe/linguist.git
				synced 2025-10-29 17:50:22 +00:00 
			
		
		
		
	Revise patterns for Vim modeline detection
The current expressions fail to match certain permutations of options:
    vim: noexpandtab: ft=javascript:
    vim: titlestring=foo\ ft=notperl ft=javascript:
Version-specific modelines are also unaccounted for:
    vim600: set foldmethod=marker ft=javascript:   # >= Vim 6.0
    vim<600: set ft=javascript:                    # <  Vim 6.0
See http://vimdoc.sourceforge.net/htmldoc/options.html#modeline
			
			
This commit is contained in:
		| @@ -2,18 +2,67 @@ module Linguist | ||||
|   module Strategy | ||||
|     class Modeline | ||||
|       EMACS_MODELINE = /-\*-\s*(?:(?!mode)[\w-]+\s*:\s*(?:[\w+-]+)\s*;?\s*)*(?:mode\s*:)?\s*([\w+-]+)\s*(?:;\s*(?!mode)[\w-]+\s*:\s*[\w+-]+\s*)*;?\s*-\*-/i | ||||
|       VIM_MODELINE   = / | ||||
|  | ||||
|       # First form vim modeline | ||||
|       # [text]{white}{vi:|vim:|ex:}[white]{options} | ||||
|       # ex: 'vim: syntax=ruby' | ||||
|       VIM_MODELINE_1 = /(?:vim|vi|ex):\s*(?:ft|filetype|syntax)=(\w+)\s?/i | ||||
|         # Start modeline. Could be `vim:`, `vi:` or `ex:` | ||||
|         (?: | ||||
|           (?:\s|^) | ||||
|           vi | ||||
|           (?:m[<=>]?\d+|m)? # Version-specific modeline | ||||
|           | | ||||
|           (?!^)\s | ||||
|           ex | ||||
|         ) | ||||
|  | ||||
|       # Second form vim modeline (compatible with some versions of Vi) | ||||
|       # [text]{white}{vi:|vim:|Vim:|ex:}[white]se[t] {options}:[text] | ||||
|       # ex: 'vim set syntax=ruby:' | ||||
|       VIM_MODELINE_2 = /(?:vim|vi|Vim|ex):\s*se(?:t)?.*\s(?:ft|filetype|syntax)=(\w+)\s?.*:/i | ||||
|         # If the option-list begins with `set ` or `se `, it indicates an alternative | ||||
|         # modeline syntax partly-compatible with older versions of Vi. Here, the colon | ||||
|         # serves as a terminator for an option sequence, delimited by whitespace. | ||||
|         (?= | ||||
|           # So we have to ensure the modeline ends with a colon | ||||
|           : (?=\s* set? \s [^\n:]+ :) | | ||||
|  | ||||
|       MODELINES = [EMACS_MODELINE, VIM_MODELINE_1, VIM_MODELINE_2] | ||||
|           # Otherwise, it isn't valid syntax and should be ignored | ||||
|           : (?!\s* set? \s) | ||||
|         ) | ||||
|  | ||||
|         # Possible (unrelated) `option=value` pairs to skip past | ||||
|         (?: | ||||
|           # Option separator. Vim uses whitespace or colons to separate options (except if | ||||
|           # the alternate "vim: set " form is used, where only whitespace is used) | ||||
|           (?: | ||||
|             \s | ||||
|             | | ||||
|             \s* : \s* # Note that whitespace around colons is accepted too: | ||||
|           )           # vim: noai :  ft=ruby:noexpandtab | ||||
|  | ||||
|           # Option's name. All recognised Vim options have an alphanumeric form. | ||||
|           \w* | ||||
|  | ||||
|           # Possible value. Not every option takes an argument. | ||||
|           (?: | ||||
|             # Whitespace between name and value is allowed: `vim: ft   =ruby` | ||||
|             \s*= | ||||
|  | ||||
|             # Option's value. Might be blank; `vim: ft= ` says "use no filetype". | ||||
|             (?: | ||||
|               [^\\\s] # Beware of escaped characters: titlestring=\ ft=ruby | ||||
|               |       # will be read by Vim as { titlestring: " ft=ruby" }. | ||||
|               \\. | ||||
|             )* | ||||
|           )? | ||||
|         )* | ||||
|  | ||||
|         # The actual filetype declaration | ||||
|         [\s:] (?:filetype|ft|syntax) \s*= | ||||
|  | ||||
|         # Language's name | ||||
|         (\w+) | ||||
|  | ||||
|         # Ensure it's followed by a legal separator | ||||
|         (?=\s|:|$) | ||||
|       /xi | ||||
|  | ||||
|       MODELINES = [EMACS_MODELINE, VIM_MODELINE] | ||||
|  | ||||
|       # Scope of the search for modelines | ||||
|       # Number of lines to check at the beginning and at the end of the file | ||||
|   | ||||
							
								
								
									
										3
									
								
								test/fixtures/Data/Modelines/iamjs.pl
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								test/fixtures/Data/Modelines/iamjs.pl
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| # vim: noexpandtab: ft=javascript | ||||
|  | ||||
| "It's JavaScript, baby"; | ||||
							
								
								
									
										4
									
								
								test/fixtures/Data/Modelines/iamjs2.pl
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								test/fixtures/Data/Modelines/iamjs2.pl
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,4 @@ | ||||
| # vim:noexpandtab titlestring=hi\|there\\\ ft=perl ts=4 | ||||
| # vim:noexpandtab titlestring=hi|there\\ ft=javascript ts=4 | ||||
|  | ||||
| "Still JavaScript, bruh"; | ||||
| @@ -30,6 +30,8 @@ class TestModelines < Minitest::Test | ||||
|     assert_modeline Language["Text"], fixture_blob("Data/Modelines/fundamentalEmacs.c") | ||||
|     assert_modeline Language["Prolog"], fixture_blob("Data/Modelines/not_perl.pl") | ||||
|     assert_modeline Language["Smalltalk"], fixture_blob("Data/Modelines/example_smalltalk.md") | ||||
|     assert_modeline Language["JavaScript"], fixture_blob("Data/Modelines/iamjs.pl") | ||||
|     assert_modeline Language["JavaScript"], fixture_blob("Data/Modelines/iamjs2.pl") | ||||
|     assert_modeline Language["PHP"], fixture_blob("Data/Modelines/iamphp.inc") | ||||
|     assert_modeline nil, sample_blob("C/main.c") | ||||
|   end | ||||
| @@ -51,6 +53,8 @@ class TestModelines < Minitest::Test | ||||
|     assert_equal Language["Text"], fixture_blob("Data/Modelines/fundamentalEmacs.c").language | ||||
|     assert_equal Language["Prolog"], fixture_blob("Data/Modelines/not_perl.pl").language | ||||
|     assert_equal Language["Smalltalk"], fixture_blob("Data/Modelines/example_smalltalk.md").language | ||||
|     assert_equal Language["JavaScript"], fixture_blob("Data/Modelines/iamjs.pl").language | ||||
|     assert_equal Language["JavaScript"], fixture_blob("Data/Modelines/iamjs2.pl").language | ||||
|     assert_equal Language["PHP"], fixture_blob("Data/Modelines/iamphp.inc").language | ||||
|   end | ||||
| end | ||||
|   | ||||
		Reference in New Issue
	
	Block a user