mirror of
https://github.com/KevinMidboe/linguist.git
synced 2025-10-29 17:50:22 +00:00
Associate each heuristic rule to a file extension
This commit is contained in:
@@ -13,11 +13,14 @@ module Linguist
|
|||||||
# ])
|
# ])
|
||||||
#
|
#
|
||||||
# Returns an Array of languages, or empty if none matched or were inconclusive.
|
# Returns an Array of languages, or empty if none matched or were inconclusive.
|
||||||
def self.call(blob, languages)
|
def self.call(blob, candidates)
|
||||||
data = blob.data
|
data = blob.data
|
||||||
|
|
||||||
@heuristics.each do |heuristic|
|
@heuristics.each do |heuristic|
|
||||||
return Array(heuristic.call(data)) if heuristic.matches?(languages)
|
if heuristic.matches?(blob.name)
|
||||||
|
languages = Array(heuristic.call(data))
|
||||||
|
return languages if languages.any? || languages.all? { |l| candidates.include?(l) }
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
[] # No heuristics matched
|
[] # No heuristics matched
|
||||||
@@ -38,22 +41,22 @@ module Linguist
|
|||||||
# end
|
# end
|
||||||
# end
|
# end
|
||||||
#
|
#
|
||||||
def self.disambiguate(*languages, &heuristic)
|
def self.disambiguate(extension, &heuristic)
|
||||||
@heuristics << new(languages, &heuristic)
|
@heuristics << new(extension, &heuristic)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Internal: Array of defined heuristics
|
# Internal: Array of defined heuristics
|
||||||
@heuristics = []
|
@heuristics = []
|
||||||
|
|
||||||
# Internal
|
# Internal
|
||||||
def initialize(languages, &heuristic)
|
def initialize(extension, &heuristic)
|
||||||
@languages = languages
|
@extension = extension
|
||||||
@heuristic = heuristic
|
@heuristic = heuristic
|
||||||
end
|
end
|
||||||
|
|
||||||
# Internal: Check if this heuristic matches the candidate languages.
|
# Internal: Check if this heuristic matches the candidate languages.
|
||||||
def matches?(candidates)
|
def matches?(filename)
|
||||||
candidates.any? && candidates.all? { |l| @languages.include?(l.name) }
|
filename.end_with?(@extension)
|
||||||
end
|
end
|
||||||
|
|
||||||
# Internal: Perform the heuristic
|
# Internal: Perform the heuristic
|
||||||
@@ -64,7 +67,7 @@ module Linguist
|
|||||||
# Common heuristics
|
# Common heuristics
|
||||||
ObjectiveCRegex = /^[ \t]*@(interface|class|protocol|property|end|synchronised|selector|implementation)\b/
|
ObjectiveCRegex = /^[ \t]*@(interface|class|protocol|property|end|synchronised|selector|implementation)\b/
|
||||||
|
|
||||||
disambiguate "BitBake", "BlitzBasic" do |data|
|
disambiguate ".bb" do |data|
|
||||||
if /^\s*; /.match(data) || data.include?("End Function")
|
if /^\s*; /.match(data) || data.include?("End Function")
|
||||||
Language["BlitzBasic"]
|
Language["BlitzBasic"]
|
||||||
elsif /^\s*(# |include|require)\b/.match(data)
|
elsif /^\s*(# |include|require)\b/.match(data)
|
||||||
@@ -72,7 +75,7 @@ module Linguist
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
disambiguate "C#", "Smalltalk" do |data|
|
disambiguate ".cs" do |data|
|
||||||
if /![\w\s]+methodsFor: /.match(data)
|
if /![\w\s]+methodsFor: /.match(data)
|
||||||
Language["Smalltalk"]
|
Language["Smalltalk"]
|
||||||
elsif /^\s*namespace\s*[\w\.]+\s*{/.match(data) || /^\s*\/\//.match(data)
|
elsif /^\s*namespace\s*[\w\.]+\s*{/.match(data) || /^\s*\/\//.match(data)
|
||||||
@@ -80,7 +83,7 @@ module Linguist
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
disambiguate "Objective-C", "C++", "C" do |data|
|
disambiguate ".h" do |data|
|
||||||
if ObjectiveCRegex.match(data)
|
if ObjectiveCRegex.match(data)
|
||||||
Language["Objective-C"]
|
Language["Objective-C"]
|
||||||
elsif (/^\s*#\s*include <(cstdint|string|vector|map|list|array|bitset|queue|stack|forward_list|unordered_map|unordered_set|(i|o|io)stream)>/.match(data) ||
|
elsif (/^\s*#\s*include <(cstdint|string|vector|map|list|array|bitset|queue|stack|forward_list|unordered_map|unordered_set|(i|o|io)stream)>/.match(data) ||
|
||||||
@@ -89,7 +92,7 @@ module Linguist
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
disambiguate "Perl", "Perl6", "Prolog" do |data|
|
disambiguate ".pl" do |data|
|
||||||
if data.include?("use v6")
|
if data.include?("use v6")
|
||||||
Language["Perl6"]
|
Language["Perl6"]
|
||||||
elsif data.match(/use strict|use\s+v?5\./)
|
elsif data.match(/use strict|use\s+v?5\./)
|
||||||
@@ -99,7 +102,7 @@ module Linguist
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
disambiguate "ECL", "Prolog" do |data|
|
disambiguate ".ecl" do |data|
|
||||||
if /^[^#]+:-/.match(data)
|
if /^[^#]+:-/.match(data)
|
||||||
Language["Prolog"]
|
Language["Prolog"]
|
||||||
elsif data.include?(":=")
|
elsif data.include?(":=")
|
||||||
@@ -107,7 +110,7 @@ module Linguist
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
disambiguate "IDL", "Prolog", "INI", "QMake" do |data|
|
disambiguate ".pro" do |data|
|
||||||
if /^[^#]+:-/.match(data)
|
if /^[^#]+:-/.match(data)
|
||||||
Language["Prolog"]
|
Language["Prolog"]
|
||||||
elsif data.include?("last_client=")
|
elsif data.include?("last_client=")
|
||||||
@@ -119,7 +122,7 @@ module Linguist
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
disambiguate "GAP", "Scilab" do |data|
|
disambiguate ".tst" do |data|
|
||||||
if (data.include?("gap> "))
|
if (data.include?("gap> "))
|
||||||
Language["GAP"]
|
Language["GAP"]
|
||||||
# Heads up - we don't usually write heuristics like this (with no regex match)
|
# Heads up - we don't usually write heuristics like this (with no regex match)
|
||||||
@@ -128,7 +131,7 @@ module Linguist
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
disambiguate "Common Lisp", "OpenCL", "Cool" do |data|
|
disambiguate ".cl" do |data|
|
||||||
if /^\s*\((defun|in-package|defpackage) /i.match(data)
|
if /^\s*\((defun|in-package|defpackage) /i.match(data)
|
||||||
Language["Common Lisp"]
|
Language["Common Lisp"]
|
||||||
elsif /^class/x.match(data)
|
elsif /^class/x.match(data)
|
||||||
@@ -138,7 +141,7 @@ module Linguist
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
disambiguate "Hack", "PHP" do |data|
|
disambiguate ".php" do |data|
|
||||||
if data.include?("<?hh")
|
if data.include?("<?hh")
|
||||||
Language["Hack"]
|
Language["Hack"]
|
||||||
elsif /<?[^h]/.match(data)
|
elsif /<?[^h]/.match(data)
|
||||||
@@ -146,7 +149,7 @@ module Linguist
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
disambiguate "Scala", "SuperCollider" do |data|
|
disambiguate ".sc" do |data|
|
||||||
if /\^(this|super)\./.match(data) || /^\s*(\+|\*)\s*\w+\s*{/.match(data) || /^\s*~\w+\s*=\./.match(data)
|
if /\^(this|super)\./.match(data) || /^\s*(\+|\*)\s*\w+\s*{/.match(data) || /^\s*~\w+\s*=\./.match(data)
|
||||||
Language["SuperCollider"]
|
Language["SuperCollider"]
|
||||||
elsif /^\s*import (scala|java)\./.match(data) || /^\s*val\s+\w+\s*=/.match(data) || /^\s*class\b/.match(data)
|
elsif /^\s*import (scala|java)\./.match(data) || /^\s*val\s+\w+\s*=/.match(data) || /^\s*class\b/.match(data)
|
||||||
@@ -154,7 +157,7 @@ module Linguist
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
disambiguate "AsciiDoc", "AGS Script", "Public Key" do |data|
|
disambiguate ".asc" do |data|
|
||||||
if /^(----[- ]BEGIN|ssh-(rsa|dss)) /.match(data)
|
if /^(----[- ]BEGIN|ssh-(rsa|dss)) /.match(data)
|
||||||
Language["Public Key"]
|
Language["Public Key"]
|
||||||
elsif /^[=-]+(\s|\n)|{{[A-Za-z]/.match(data)
|
elsif /^[=-]+(\s|\n)|{{[A-Za-z]/.match(data)
|
||||||
@@ -164,7 +167,7 @@ module Linguist
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
disambiguate "FORTRAN", "Forth", "Formatted" do |data|
|
disambiguate ".for" do |data|
|
||||||
if /^: /.match(data)
|
if /^: /.match(data)
|
||||||
Language["Forth"]
|
Language["Forth"]
|
||||||
elsif /^([c*][^a-z]| (subroutine|program)\s|\s*!)/i.match(data)
|
elsif /^([c*][^a-z]| (subroutine|program)\s|\s*!)/i.match(data)
|
||||||
@@ -172,7 +175,7 @@ module Linguist
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
disambiguate "F#", "Forth", "GLSL", "Filterscript" do |data|
|
disambiguate ".fs" do |data|
|
||||||
if /^(: |new-device)/.match(data)
|
if /^(: |new-device)/.match(data)
|
||||||
Language["Forth"]
|
Language["Forth"]
|
||||||
elsif /^\s*(#light|import|let|module|namespace|open|type)/.match(data)
|
elsif /^\s*(#light|import|let|module|namespace|open|type)/.match(data)
|
||||||
@@ -184,7 +187,7 @@ module Linguist
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
disambiguate "Limbo", "M", "MUF", "Mathematica", "Matlab", "Mercury", "Objective-C" do |data|
|
disambiguate ".m" do |data|
|
||||||
if ObjectiveCRegex.match(data)
|
if ObjectiveCRegex.match(data)
|
||||||
Language["Objective-C"]
|
Language["Objective-C"]
|
||||||
elsif data.include?(":- module")
|
elsif data.include?(":- module")
|
||||||
@@ -202,11 +205,11 @@ module Linguist
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
disambiguate "Gosu", "JavaScript" do |data|
|
disambiguate ".gs" do |data|
|
||||||
Language["Gosu"] if /^uses java\./.match(data)
|
Language["Gosu"] if /^uses java\./.match(data)
|
||||||
end
|
end
|
||||||
|
|
||||||
disambiguate "LoomScript", "LiveScript" do |data|
|
disambiguate ".ls" do |data|
|
||||||
if /^\s*package\s*[\w\.\/\*\s]*\s*{/.match(data)
|
if /^\s*package\s*[\w\.\/\*\s]*\s*{/.match(data)
|
||||||
Language["LoomScript"]
|
Language["LoomScript"]
|
||||||
else
|
else
|
||||||
@@ -214,7 +217,7 @@ module Linguist
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
disambiguate "Common Lisp", "NewLisp" do |data|
|
disambiguate ".lisp" do |data|
|
||||||
if /^\s*\((defun|in-package|defpackage) /i.match(data)
|
if /^\s*\((defun|in-package|defpackage) /i.match(data)
|
||||||
Language["Common Lisp"]
|
Language["Common Lisp"]
|
||||||
elsif /^\s*\(define /.match(data)
|
elsif /^\s*\(define /.match(data)
|
||||||
@@ -222,7 +225,7 @@ module Linguist
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
disambiguate "TypeScript", "XML" do |data|
|
disambiguate ".ts" do |data|
|
||||||
if data.include?("<TS ")
|
if data.include?("<TS ")
|
||||||
Language["XML"]
|
Language["XML"]
|
||||||
else
|
else
|
||||||
@@ -230,7 +233,7 @@ module Linguist
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
disambiguate "Frege", "Forth", "Text" do |data|
|
disambiguate ".fr" do |data|
|
||||||
if /^(: |also |new-device|previous )/.match(data)
|
if /^(: |also |new-device|previous )/.match(data)
|
||||||
Language["Forth"]
|
Language["Forth"]
|
||||||
elsif /^\s*(import|module|package|data|type) /.match(data)
|
elsif /^\s*(import|module|package|data|type) /.match(data)
|
||||||
@@ -240,7 +243,7 @@ module Linguist
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
disambiguate "PLSQL", "SQLPL", "PLpgSQL", "SQL" do |data|
|
disambiguate ".sql" do |data|
|
||||||
if /^\\i\b|AS \$\$|LANGUAGE '+plpgsql'+/i.match(data) || /SECURITY (DEFINER|INVOKER)/i.match(data) || /BEGIN( WORK| TRANSACTION)?;/i.match(data)
|
if /^\\i\b|AS \$\$|LANGUAGE '+plpgsql'+/i.match(data) || /SECURITY (DEFINER|INVOKER)/i.match(data) || /BEGIN( WORK| TRANSACTION)?;/i.match(data)
|
||||||
#Postgres
|
#Postgres
|
||||||
Language["PLpgSQL"]
|
Language["PLpgSQL"]
|
||||||
@@ -256,7 +259,7 @@ module Linguist
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
disambiguate "D", "DTrace", "Makefile" do |data|
|
disambiguate ".d" do |data|
|
||||||
if /^module /.match(data)
|
if /^module /.match(data)
|
||||||
Language["D"]
|
Language["D"]
|
||||||
elsif /^((dtrace:::)?BEGIN|provider |#pragma (D (option|attributes)|ident)\s)/.match(data)
|
elsif /^((dtrace:::)?BEGIN|provider |#pragma (D (option|attributes)|ident)\s)/.match(data)
|
||||||
@@ -266,7 +269,7 @@ module Linguist
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
disambiguate "OCaml", "Standard ML" do |data|
|
disambiguate ".ml" do |data|
|
||||||
if /(^\s*module)|let rec |match\s+(\S+\s)+with/.match(data)
|
if /(^\s*module)|let rec |match\s+(\S+\s)+with/.match(data)
|
||||||
Language["OCaml"]
|
Language["OCaml"]
|
||||||
elsif /=> |case\s+(\S+\s)+of/.match(data)
|
elsif /=> |case\s+(\S+\s)+of/.match(data)
|
||||||
@@ -274,7 +277,7 @@ module Linguist
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
disambiguate "NL", "NewLisp" do |data|
|
disambiguate ".nl" do |data|
|
||||||
if /^(b|g)[0-9]+ /.match(data)
|
if /^(b|g)[0-9]+ /.match(data)
|
||||||
Language["NL"]
|
Language["NL"]
|
||||||
else
|
else
|
||||||
@@ -282,7 +285,7 @@ module Linguist
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
disambiguate "Rust", "RenderScript" do |data|
|
disambiguate ".rs" do |data|
|
||||||
if /^(use |fn |mod |pub |macro_rules|impl|#!?\[)/.match(data)
|
if /^(use |fn |mod |pub |macro_rules|impl|#!?\[)/.match(data)
|
||||||
Language["Rust"]
|
Language["Rust"]
|
||||||
elsif /#include|#pragma\s+(rs|version)|__attribute__/.match(data)
|
elsif /#include|#pragma\s+(rs|version)|__attribute__/.match(data)
|
||||||
@@ -290,7 +293,7 @@ module Linguist
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
disambiguate "Common Lisp", "Lex", "Groff" do |data|
|
disambiguate ".l" do |data|
|
||||||
if data.include?("(def(un|macro)\s")
|
if data.include?("(def(un|macro)\s")
|
||||||
Language["Common Lisp"]
|
Language["Common Lisp"]
|
||||||
elsif /^(%[%{}]xs|<.*>)/.match(data)
|
elsif /^(%[%{}]xs|<.*>)/.match(data)
|
||||||
|
|||||||
Reference in New Issue
Block a user