Merge pull request #2041 from github/emacs-vim-mode-lines

Emacs vim modelines
This commit is contained in:
Arfon Smith
2015-01-29 20:12:47 -06:00
14 changed files with 86 additions and 34 deletions

View File

@@ -11,6 +11,7 @@ require 'linguist/samples'
require 'linguist/file_blob' require 'linguist/file_blob'
require 'linguist/blob_helper' require 'linguist/blob_helper'
require 'linguist/strategy/filename' require 'linguist/strategy/filename'
require 'linguist/strategy/modeline'
require 'linguist/shebang' require 'linguist/shebang'
module Linguist module Linguist
@@ -94,6 +95,7 @@ module Linguist
end end
STRATEGIES = [ STRATEGIES = [
Linguist::Strategy::Modeline,
Linguist::Strategy::Filename, Linguist::Strategy::Filename,
Linguist::Shebang, Linguist::Shebang,
Linguist::Heuristics, Linguist::Heuristics,

View File

@@ -0,0 +1,30 @@
module Linguist
module Strategy
class Modeline
EmacsModeline = /-\*-\s*(?:mode:)?\s*(\w+);?\s*-\*-/
VimModeline = /\/\*\s*vim:\s*set\s*(?:ft|filetype)=(\w+):\s*\*\//
# Public: Detects language based on Vim and Emacs modelines
#
# blob - An object that quacks like a blob.
#
# Examples
#
# Modeline.call(FileBlob.new("path/to/file"))
#
# Returns an Array with one Language if the blob has a Vim or Emacs modeline
# that matches a Language name or alias. Returns an empty array if no match.
def self.call(blob, _ = nil)
Array(Language.find_by_alias(modeline(blob.data)))
end
# Public: Get the modeline from the first n-lines of the file
#
# Returns a String or nil
def self.modeline(data)
match = data.match(EmacsModeline) || data.match(VimModeline)
match[1] if match
end
end
end
end

View File

@@ -0,0 +1 @@
; -*-Smalltalk-*-

View File

@@ -0,0 +1 @@
; -*- mode: php;-*-

View File

@@ -0,0 +1,3 @@
/* vim: set filetype=prolog: */
# I am Prolog

3
test/fixtures/Data/Modelines/ruby vendored Normal file
View File

@@ -0,0 +1,3 @@
/* vim: set filetype=ruby: */
# I am Ruby

View File

@@ -0,0 +1,3 @@
/* vim: set ft=cpp: */
I would like to be C++ please.

View File

@@ -2,3 +2,21 @@ require "bundler/setup"
require "minitest/autorun" require "minitest/autorun"
require "mocha/setup" require "mocha/setup"
require "linguist" require "linguist"
def fixtures_path
File.expand_path("../fixtures", __FILE__)
end
def fixture_blob(name)
name = File.join(fixtures_path, name) unless name =~ /^\//
Linguist::FileBlob.new(name, fixtures_path)
end
def samples_path
File.expand_path("../../samples", __FILE__)
end
def sample_blob(name)
name = File.join(samples_path, name) unless name =~ /^\//
Linguist::FileBlob.new(name, samples_path)
end

View File

@@ -14,24 +14,6 @@ class TestBlob < Minitest::Test
Encoding.default_external = @original_external Encoding.default_external = @original_external
end end
def samples_path
File.expand_path("../../samples", __FILE__)
end
def fixtures_path
File.expand_path("../fixtures", __FILE__)
end
def sample_blob(name)
name = File.join(samples_path, name) unless name =~ /^\//
FileBlob.new(name, samples_path)
end
def fixture_blob(name)
name = File.join(fixtures_path, name) unless name =~ /^\//
FileBlob.new(name, fixtures_path)
end
def script_blob(name) def script_blob(name)
blob = sample_blob(name) blob = sample_blob(name)
blob.instance_variable_set(:@name, 'script') blob.instance_variable_set(:@name, 'script')

View File

@@ -3,10 +3,6 @@ require_relative "./helper"
class TestClassifier < Minitest::Test class TestClassifier < Minitest::Test
include Linguist include Linguist
def samples_path
File.expand_path("../../samples", __FILE__)
end
def fixture(name) def fixture(name)
File.read(File.join(samples_path, name)) File.read(File.join(samples_path, name))
end end

View File

@@ -3,10 +3,6 @@ require_relative "./helper"
class TestGenerated < Minitest::Test class TestGenerated < Minitest::Test
include Linguist include Linguist
def samples_path
File.expand_path("../../samples", __FILE__)
end
class DataLoadedError < StandardError; end class DataLoadedError < StandardError; end
def generated_without_loading_data(name) def generated_without_loading_data(name)

View File

@@ -3,10 +3,6 @@ require_relative "./helper"
class TestHeuristcs < Minitest::Test class TestHeuristcs < Minitest::Test
include Linguist include Linguist
def samples_path
File.expand_path("../../samples", __FILE__)
end
def fixture(name) def fixture(name)
File.read(File.join(samples_path, name)) File.read(File.join(samples_path, name))
end end

25
test/test_modelines.rb Normal file
View File

@@ -0,0 +1,25 @@
require_relative "./helper"
class TestModelines < Minitest::Test
include Linguist
def assert_modeline(language, blob)
assert_equal language, Linguist::Strategy::Modeline.call(blob).first
end
def test_modeline_strategy
assert_modeline Language["Ruby"], fixture_blob("Data/Modelines/ruby")
assert_modeline Language["C++"], fixture_blob("Data/Modelines/seeplusplus")
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["PHP"], fixture_blob("Data/Modelines/iamphp.inc")
end
def test_modeline_languages
assert_equal Language["Ruby"], fixture_blob("Data/Modelines/ruby").language
assert_equal Language["C++"], fixture_blob("Data/Modelines/seeplusplus").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["PHP"], fixture_blob("Data/Modelines/iamphp.inc").language
end
end

View File

@@ -3,10 +3,6 @@ require_relative "./helper"
class TestTokenizer < Minitest::Test class TestTokenizer < Minitest::Test
include Linguist include Linguist
def samples_path
File.expand_path("../../samples", __FILE__)
end
def tokenize(data) def tokenize(data)
data = File.read(File.join(samples_path, data.to_s)) if data.is_a?(Symbol) data = File.read(File.join(samples_path, data.to_s)) if data.is_a?(Symbol)
Tokenizer.tokenize(data) Tokenizer.tokenize(data)