mirror of
https://github.com/KevinMidboe/linguist.git
synced 2025-12-07 20:08:48 +00:00
Merge pull request #2041 from github/emacs-vim-mode-lines
Emacs vim modelines
This commit is contained in:
@@ -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,
|
||||||
|
|||||||
30
lib/linguist/strategy/modeline.rb
Normal file
30
lib/linguist/strategy/modeline.rb
Normal 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
|
||||||
1
test/fixtures/Data/Modelines/example_smalltalk.md
vendored
Normal file
1
test/fixtures/Data/Modelines/example_smalltalk.md
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
; -*-Smalltalk-*-
|
||||||
1
test/fixtures/Data/Modelines/iamphp.inc
vendored
Normal file
1
test/fixtures/Data/Modelines/iamphp.inc
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
; -*- mode: php;-*-
|
||||||
3
test/fixtures/Data/Modelines/not_perl.pl
vendored
Normal file
3
test/fixtures/Data/Modelines/not_perl.pl
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
/* vim: set filetype=prolog: */
|
||||||
|
|
||||||
|
# I am Prolog
|
||||||
3
test/fixtures/Data/Modelines/ruby
vendored
Normal file
3
test/fixtures/Data/Modelines/ruby
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
/* vim: set filetype=ruby: */
|
||||||
|
|
||||||
|
# I am Ruby
|
||||||
3
test/fixtures/Data/Modelines/seeplusplus
vendored
Normal file
3
test/fixtures/Data/Modelines/seeplusplus
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
/* vim: set ft=cpp: */
|
||||||
|
|
||||||
|
I would like to be C++ please.
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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')
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
25
test/test_modelines.rb
Normal 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
|
||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user