diff --git a/README.md b/README.md index 36bcbd50..2d661ef9 100644 --- a/README.md +++ b/README.md @@ -59,6 +59,9 @@ Alternatively, you can use Vim or Emacs style modelines to set the language for ##### Vim ``` +# Some examples of various styles: +vim: syntax=java +vim: set syntax=ruby: vim: set filetype=prolog: vim: set ft=cpp: ``` diff --git a/lib/linguist/strategy/modeline.rb b/lib/linguist/strategy/modeline.rb index f995d940..ece98a1f 100644 --- a/lib/linguist/strategy/modeline.rb +++ b/lib/linguist/strategy/modeline.rb @@ -1,8 +1,19 @@ module Linguist module Strategy class Modeline - EmacsModeline = /-\*-\s*(?:(?!mode)[\w-]+\s*:\s*(?:[\w+-]+)\s*;?\s*)*(?:mode\s*:)?\s*([\w+-]+)\s*(?:;\s*(?!mode)[\w-]+\s*:\s*[\w+-]+\s*)*;?\s*-\*-/i - VimModeline = /vim:\s*set.*\s(?:ft|filetype)=(\w+)\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 + + # First form vim modeline + # [text]{white}{vi:|vim:|ex:}[white]{options} + # ex: 'vim: syntax=perl' + VIM_MODELINE_1 = /(?:vim|vi|ex):\s*(?:ft|filetype|syntax)=(\w+)\s?/i + + # 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=perl:' + VIM_MODELINE_2 = /(?:vim|vi|Vim|ex):\s*se(?:t)?.*\s(?:ft|filetype|syntax)=(\w+)\s?.*:/i + + MODELINES = [EMACS_MODELINE, VIM_MODELINE_1, VIM_MODELINE_2] # Public: Detects language based on Vim and Emacs modelines # @@ -22,7 +33,7 @@ module Linguist # # Returns a String or nil def self.modeline(data) - match = data.match(EmacsModeline) || data.match(VimModeline) + match = MODELINES.map { |regex| data.match(regex) }.reject(&:nil?).first match[1] if match end end diff --git a/test/fixtures/Data/Modelines/ruby4 b/test/fixtures/Data/Modelines/ruby4 new file mode 100644 index 00000000..e3b50151 --- /dev/null +++ b/test/fixtures/Data/Modelines/ruby4 @@ -0,0 +1,3 @@ +# vim: filetype=ruby + +# I am Ruby diff --git a/test/fixtures/Data/Modelines/ruby5 b/test/fixtures/Data/Modelines/ruby5 new file mode 100644 index 00000000..10349050 --- /dev/null +++ b/test/fixtures/Data/Modelines/ruby5 @@ -0,0 +1,3 @@ +# vim: ft=ruby + +# I am Ruby diff --git a/test/fixtures/Data/Modelines/ruby6 b/test/fixtures/Data/Modelines/ruby6 new file mode 100644 index 00000000..a2b49dae --- /dev/null +++ b/test/fixtures/Data/Modelines/ruby6 @@ -0,0 +1,3 @@ +# vim: syntax=Ruby + +# I am Ruby diff --git a/test/fixtures/Data/Modelines/ruby7 b/test/fixtures/Data/Modelines/ruby7 new file mode 100644 index 00000000..1ed5b28f --- /dev/null +++ b/test/fixtures/Data/Modelines/ruby7 @@ -0,0 +1,3 @@ +# vim: se syntax=ruby: + +# I am Ruby diff --git a/test/fixtures/Data/Modelines/ruby8 b/test/fixtures/Data/Modelines/ruby8 new file mode 100644 index 00000000..8e854741 --- /dev/null +++ b/test/fixtures/Data/Modelines/ruby8 @@ -0,0 +1,3 @@ +# vim: set syntax=ruby: + +# I am Ruby diff --git a/test/fixtures/Data/Modelines/ruby9 b/test/fixtures/Data/Modelines/ruby9 new file mode 100644 index 00000000..ac82358d --- /dev/null +++ b/test/fixtures/Data/Modelines/ruby9 @@ -0,0 +1,3 @@ +# ex: syntax=ruby + +# I am Ruby diff --git a/test/test_modelines.rb b/test/test_modelines.rb index fd259782..85718955 100644 --- a/test/test_modelines.rb +++ b/test/test_modelines.rb @@ -11,6 +11,12 @@ class TestModelines < Minitest::Test assert_modeline Language["Ruby"], fixture_blob("Data/Modelines/ruby") assert_modeline Language["Ruby"], fixture_blob("Data/Modelines/ruby2") assert_modeline Language["Ruby"], fixture_blob("Data/Modelines/ruby3") + assert_modeline Language["Ruby"], fixture_blob("Data/Modelines/ruby4") + assert_modeline Language["Ruby"], fixture_blob("Data/Modelines/ruby5") + assert_modeline Language["Ruby"], fixture_blob("Data/Modelines/ruby6") + assert_modeline Language["Ruby"], fixture_blob("Data/Modelines/ruby7") + assert_modeline Language["Ruby"], fixture_blob("Data/Modelines/ruby8") + assert_modeline Language["Ruby"], fixture_blob("Data/Modelines/ruby9") assert_modeline Language["C++"], fixture_blob("Data/Modelines/seeplusplus") assert_modeline Language["C++"], fixture_blob("Data/Modelines/seeplusplusEmacs1") assert_modeline Language["C++"], fixture_blob("Data/Modelines/seeplusplusEmacs2")