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
|
module Strategy
|
||||||
class Modeline
|
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
|
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
|
# Start modeline. Could be `vim:`, `vi:` or `ex:`
|
||||||
# [text]{white}{vi:|vim:|ex:}[white]{options}
|
(?:
|
||||||
# ex: 'vim: syntax=ruby'
|
(?:\s|^)
|
||||||
VIM_MODELINE_1 = /(?:vim|vi|ex):\s*(?:ft|filetype|syntax)=(\w+)\s?/i
|
vi
|
||||||
|
(?:m[<=>]?\d+|m)? # Version-specific modeline
|
||||||
|
|
|
||||||
|
(?!^)\s
|
||||||
|
ex
|
||||||
|
)
|
||||||
|
|
||||||
# Second form vim modeline (compatible with some versions of Vi)
|
# If the option-list begins with `set ` or `se `, it indicates an alternative
|
||||||
# [text]{white}{vi:|vim:|Vim:|ex:}[white]se[t] {options}:[text]
|
# modeline syntax partly-compatible with older versions of Vi. Here, the colon
|
||||||
# ex: 'vim set syntax=ruby:'
|
# serves as a terminator for an option sequence, delimited by whitespace.
|
||||||
VIM_MODELINE_2 = /(?:vim|vi|Vim|ex):\s*se(?:t)?.*\s(?:ft|filetype|syntax)=(\w+)\s?.*:/i
|
(?=
|
||||||
|
# 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
|
# Scope of the search for modelines
|
||||||
# Number of lines to check at the beginning and at the end of the file
|
# 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["Text"], fixture_blob("Data/Modelines/fundamentalEmacs.c")
|
||||||
assert_modeline Language["Prolog"], fixture_blob("Data/Modelines/not_perl.pl")
|
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["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 Language["PHP"], fixture_blob("Data/Modelines/iamphp.inc")
|
||||||
assert_modeline nil, sample_blob("C/main.c")
|
assert_modeline nil, sample_blob("C/main.c")
|
||||||
end
|
end
|
||||||
@@ -51,6 +53,8 @@ class TestModelines < Minitest::Test
|
|||||||
assert_equal Language["Text"], fixture_blob("Data/Modelines/fundamentalEmacs.c").language
|
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["Prolog"], fixture_blob("Data/Modelines/not_perl.pl").language
|
||||||
assert_equal Language["Smalltalk"], fixture_blob("Data/Modelines/example_smalltalk.md").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
|
assert_equal Language["PHP"], fixture_blob("Data/Modelines/iamphp.inc").language
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
Reference in New Issue
Block a user