Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Newer
Older
100644 591 lines (510 sloc) 15.73 kB
0872058 @josh Fix name escaping
josh authored
1 require 'escape_utils'
329ad99 @josh Add Langauge#escaped_name
josh authored
2 require 'yaml'
bf11900 @charliesome prefer to load from languages.json if it exists
charliesome authored
3 begin
cd74333 @bkeepers Use yajl since it is already a dependency
bkeepers authored
4 require 'yajl'
bf11900 @charliesome prefer to load from languages.json if it exists
charliesome authored
5 rescue LoadError
6 end
a1e3b86 @josh Add Language class
josh authored
7
804e23e @josh Extract seperate language detection method
josh authored
8 require 'linguist/classifier'
3bc17e8 @tnm Start on basic heuristic approach
tnm authored
9 require 'linguist/heuristics'
80e8ee7 @josh Rename Sample -> Samples
josh authored
10 require 'linguist/samples'
529d3fa @arfon Explictly load FileBlob
arfon authored
11 require 'linguist/file_blob'
8c7b54d @arfon Fixing BlobHelper loading issue
arfon authored
12 require 'linguist/blob_helper'
c1a9737 @bkeepers Try strategies until one language is returned
bkeepers authored
13 require 'linguist/strategy/filename'
e536eea @arfon Basic Vim modeline detection strategy
arfon authored
14 require 'linguist/strategy/modeline'
fd85f7f @bkeepers consolidate shebang logic
bkeepers authored
15 require 'linguist/shebang'
a775b00 @josh Load extensions from samples
josh authored
16
a1e3b86 @josh Add Language class
josh authored
17 module Linguist
176aad0 @carlosgaldino fixing typo
carlosgaldino authored
18 # Language names that are recognizable by GitHub. Defined languages
a830a05 @josh More language docs
josh authored
19 # can be highlighted, searched and listed under the Top Languages page.
20 #
176aad0 @carlosgaldino fixing typo
carlosgaldino authored
21 # Languages are defined in `lib/linguist/languages.yml`.
a1e3b86 @josh Add Language class
josh authored
22 class Language
cbd6973 @josh Test all languages can by found by name
josh authored
23 @languages = []
43807c6 @josh Create a separate index for lookup
josh authored
24 @index = {}
6041dda @josh Add Language#find_by_extension
josh authored
25 @name_index = {}
ba7c2c7 @josh Add language aliases
josh authored
26 @alias_index = {}
413c881 @charliesome add @primary_extension_index to ensure we don't have duped primary exts
charliesome authored
27
28 @extension_index = Hash.new { |h,k| h[k] = [] }
7a6202a @eschulte language interpreters and shebang lines
eschulte authored
29 @interpreter_index = Hash.new { |h,k| h[k] = [] }
413c881 @charliesome add @primary_extension_index to ensure we don't have duped primary exts
charliesome authored
30 @filename_index = Hash.new { |h,k| h[k] = [] }
a1e3b86 @josh Add Language class
josh authored
31
8f46cd0 @josh Try to classify language types
josh authored
32 # Valid Languages types
ee519ae @gjtorikian Add helper method to retrieve languages by type
gjtorikian authored
33 TYPES = [:data, :markup, :programming, :prose]
8f46cd0 @josh Try to classify language types
josh authored
34
ee519ae @gjtorikian Add helper method to retrieve languages by type
gjtorikian authored
35 # Detect languages by a specific type
36 #
37 # type - A symbol that exists within TYPES
38 #
39 # Returns an array
40 def self.by_type(type)
41 all.select { |h| h.type == type }
42 end
43
5f54801 @josh Document Language class
josh authored
44 # Internal: Create a new Language object
45 #
46 # attributes - A hash of attributes
47 #
48 # Returns a Language object
80ff388 @josh Add Language#extensions
josh authored
49 def self.create(attributes = {})
50 language = new(attributes)
a1e3b86 @josh Add Language class
josh authored
51
cbd6973 @josh Test all languages can by found by name
josh authored
52 @languages << language
53
5d2e9e0 @josh Raise don't warn
josh authored
54 # All Language names should be unique. Raise if there is a duplicate.
a75a57e @josh Make Language name finder case sensitive
josh authored
55 if @name_index.key?(language.name)
5d2e9e0 @josh Raise don't warn
josh authored
56 raise ArgumentError, "Duplicate language name: #{language.name}"
a583a60 @josh Warn about duplicate language names and extensions
josh authored
57 end
58
a75a57e @josh Make Language name finder case sensitive
josh authored
59 # Language name index
751360e @aroben Make Language.[] and Language.find_by(alias|name) ignore case
aroben authored
60 @index[language.name.downcase] = @name_index[language.name.downcase] = language
a1e3b86 @josh Add Language class
josh authored
61
ba7c2c7 @josh Add language aliases
josh authored
62 language.aliases.each do |name|
5d2e9e0 @josh Raise don't warn
josh authored
63 # All Language aliases should be unique. Raise if there is a duplicate.
ba7c2c7 @josh Add language aliases
josh authored
64 if @alias_index.key?(name)
5d2e9e0 @josh Raise don't warn
josh authored
65 raise ArgumentError, "Duplicate alias: #{name}"
ba7c2c7 @josh Add language aliases
josh authored
66 end
67
751360e @aroben Make Language.[] and Language.find_by(alias|name) ignore case
aroben authored
68 @index[name.downcase] = @alias_index[name.downcase] = language
ba7c2c7 @josh Add language aliases
josh authored
69 end
70
6041dda @josh Add Language#find_by_extension
josh authored
71 language.extensions.each do |extension|
c773911 @josh Separate filename and extension configuration
josh authored
72 if extension !~ /^\./
5d2e9e0 @josh Raise don't warn
josh authored
73 raise ArgumentError, "Extension is missing a '.': #{extension.inspect}"
c773911 @josh Separate filename and extension configuration
josh authored
74 end
75
41e1b7b @pchaigno Detection by extension made case-insensitive
pchaigno authored
76 @extension_index[extension.downcase] << language
1e453a2 @josh Be explicit about ambiguous extensions
josh authored
77 end
a583a60 @josh Warn about duplicate language names and extensions
josh authored
78
7a6202a @eschulte language interpreters and shebang lines
eschulte authored
79 language.interpreters.each do |interpreter|
80 @interpreter_index[interpreter] << language
81 end
82
c773911 @josh Separate filename and extension configuration
josh authored
83 language.filenames.each do |filename|
6014bd0 @josh Change find_by_filename api to return all matching languages
josh authored
84 @filename_index[filename] << language
6041dda @josh Add Language#find_by_extension
josh authored
85 end
86
a1e3b86 @josh Add Language class
josh authored
87 language
88 end
89
fd32938 @bkeepers Extract strategies for detecting the language
bkeepers authored
90 STRATEGIES = [
e536eea @arfon Basic Vim modeline detection strategy
arfon authored
91 Linguist::Strategy::Modeline,
fd85f7f @bkeepers consolidate shebang logic
bkeepers authored
92 Linguist::Shebang,
4543c7a @arfon Use the shebang strategy first
arfon authored
93 Linguist::Strategy::Filename,
fd32938 @bkeepers Extract strategies for detecting the language
bkeepers authored
94 Linguist::Heuristics,
bf4baff @bkeepers Move call method into existing Classifier class
bkeepers authored
95 Linguist::Classifier
fd32938 @bkeepers Extract strategies for detecting the language
bkeepers authored
96 ]
8d7b4f8 @bkeepers Extract filename strategy
bkeepers authored
97
804e23e @josh Extract seperate language detection method
josh authored
98 # Public: Detects the Language of the blob.
99 #
f5e4789 @vmg Properly handle detection of binary files
vmg authored
100 # blob - an object that includes the Linguist `BlobHelper` interface;
65eaf98 @vmg docs
vmg authored
101 # see Linguist::LazyBlob and Linguist::FileBlob for examples
804e23e @josh Extract seperate language detection method
josh authored
102 #
103 # Returns Language or nil.
c4260ae @vmg Use Rugged when computing Repository stats
vmg authored
104 def self.detect(blob)
df55043 @bkeepers Bail earlier if the file is empty.
bkeepers authored
105 # Bail early if the blob is binary or empty.
106 return nil if blob.likely_binary? || blob.binary? || blob.empty?
f5e4789 @vmg Properly handle detection of binary files
vmg authored
107
e832652 @bkeepers Pass blob to instrumentation
bkeepers authored
108 Linguist.instrument("linguist.detection", :blob => blob) do
fd76335 @charliesome add instrumentation to detection and classification
charliesome authored
109 # Call each strategy until one candidate is returned.
9a86b9a @arfon Instrument all calls and pass the blob, strategy and language candida…
arfon authored
110 languages = []
a1010b8 @arfon Actually return the strategy
arfon authored
111 returning_strategy = nil
9a86b9a @arfon Instrument all calls and pass the blob, strategy and language candida…
arfon authored
112
113 STRATEGIES.each do |strategy|
a1010b8 @arfon Actually return the strategy
arfon authored
114 returning_strategy = strategy
9a86b9a @arfon Instrument all calls and pass the blob, strategy and language candida…
arfon authored
115 candidates = Linguist.instrument("linguist.strategy", :blob => blob, :strategy => strategy, :candidates => languages) do
116 strategy.call(blob, languages)
117 end
fd76335 @charliesome add instrumentation to detection and classification
charliesome authored
118 if candidates.size == 1
9a86b9a @arfon Instrument all calls and pass the blob, strategy and language candida…
arfon authored
119 languages = candidates
120 break
fd76335 @charliesome add instrumentation to detection and classification
charliesome authored
121 elsif candidates.size > 1
122 # More than one candidate was found, pass them to the next strategy.
9a86b9a @arfon Instrument all calls and pass the blob, strategy and language candida…
arfon authored
123 languages = candidates
fd76335 @charliesome add instrumentation to detection and classification
charliesome authored
124 else
9a86b9a @arfon Instrument all calls and pass the blob, strategy and language candida…
arfon authored
125 # No candidates, try the next strategy
fd76335 @charliesome add instrumentation to detection and classification
charliesome authored
126 end
804e23e @josh Extract seperate language detection method
josh authored
127 end
9a86b9a @arfon Instrument all calls and pass the blob, strategy and language candida…
arfon authored
128
a1010b8 @arfon Actually return the strategy
arfon authored
129 Linguist.instrument("linguist.detected", :blob => blob, :strategy => returning_strategy, :language => languages.first)
3dcdc11 @bkeepers Avoid passing block to detected instrumenter
bkeepers authored
130
131 languages.first
fd76335 @charliesome add instrumentation to detection and classification
charliesome authored
132 end
804e23e @josh Extract seperate language detection method
josh authored
133 end
134
2130e79 @josh These are public
josh authored
135 # Public: Get all Languages
cbd6973 @josh Test all languages can by found by name
josh authored
136 #
137 # Returns an Array of Languages
138 def self.all
139 @languages
140 end
141
5f54801 @josh Document Language class
josh authored
142 # Public: Look up Language by its proper name.
143 #
a75a57e @josh Make Language name finder case sensitive
josh authored
144 # name - The String name of the Language
5f54801 @josh Document Language class
josh authored
145 #
146 # Examples
147 #
148 # Language.find_by_name('Ruby')
149 # # => #<Language name="Ruby">
150 #
151 # Returns the Language or nil if none was found.
a1e3b86 @josh Add Language class
josh authored
152 def self.find_by_name(name)
851c93a @arfon Don't blow up if empty string/nil passed to alias methods
arfon authored
153 return nil if name.to_s.empty?
3180c5d @Ryman Allow delimiting by comma in the language name
Ryman authored
154 name && (@name_index[name.downcase] || @name_index[name.split(',').first.downcase])
a1e3b86 @josh Add Language class
josh authored
155 end
156
ba7c2c7 @josh Add language aliases
josh authored
157 # Public: Look up Language by one of its aliases.
5f54801 @josh Document Language class
josh authored
158 #
a75a57e @josh Make Language name finder case sensitive
josh authored
159 # name - A String alias of the Language
5f54801 @josh Document Language class
josh authored
160 #
161 # Examples
162 #
ba7c2c7 @josh Add language aliases
josh authored
163 # Language.find_by_alias('cpp')
164 # # => #<Language name="C++">
5f54801 @josh Document Language class
josh authored
165 #
5d0e948 @pchaigno Remove last mentions of lexer
pchaigno authored
166 # Returns the Language or nil if none was found.
ba7c2c7 @josh Add language aliases
josh authored
167 def self.find_by_alias(name)
851c93a @arfon Don't blow up if empty string/nil passed to alias methods
arfon authored
168 return nil if name.to_s.empty?
3180c5d @Ryman Allow delimiting by comma in the language name
Ryman authored
169 name && (@alias_index[name.downcase] || @alias_index[name.split(',').first.downcase])
09618cf @josh Extract a separate method for find_by_filename
josh authored
170 end
171
6014bd0 @josh Change find_by_filename api to return all matching languages
josh authored
172 # Public: Look up Languages by filename.
c773911 @josh Separate filename and extension configuration
josh authored
173 #
174 # filename - The path String.
175 #
176 # Examples
177 #
178 # Language.find_by_filename('foo.rb')
6014bd0 @josh Change find_by_filename api to return all matching languages
josh authored
179 # # => [#<Language name="Ruby">]
c773911 @josh Separate filename and extension configuration
josh authored
180 #
6014bd0 @josh Change find_by_filename api to return all matching languages
josh authored
181 # Returns all matching Languages or [] if none were found.
c773911 @josh Separate filename and extension configuration
josh authored
182 def self.find_by_filename(filename)
bd694c6 @pchaigno Custom File.extname method which returns the filename if it is an ext…
pchaigno authored
183 basename = File.basename(filename)
c466675 @bkeepers Use the first extension with languages defined
bkeepers authored
184
185 # find the first extension with language definitions
186 extname = FileBlob.new(filename).extensions.detect do |e|
187 !@extension_index[e].empty?
188 end
189
190 (@filename_index[basename] + @extension_index[extname]).compact.uniq
228d896 @bkeepers Add Language.find_by_extension
bkeepers authored
191 end
192
193 # Public: Look up Languages by file extension.
194 #
195 # extname - The extension String.
196 #
197 # Examples
198 #
ffbe95d @aroben Fix docs
aroben authored
199 # Language.find_by_extension('.rb')
228d896 @bkeepers Add Language.find_by_extension
bkeepers authored
200 # # => [#<Language name="Ruby">]
201 #
97a1adc @aroben Allow extensions without a leading dot
aroben authored
202 # Language.find_by_extension('rb')
203 # # => [#<Language name="Ruby">]
204 #
228d896 @bkeepers Add Language.find_by_extension
bkeepers authored
205 # Returns all matching Languages or [] if none were found.
206 def self.find_by_extension(extname)
97a1adc @aroben Allow extensions without a leading dot
aroben authored
207 extname = ".#{extname}" unless extname.start_with?(".")
41e1b7b @pchaigno Detection by extension made case-insensitive
pchaigno authored
208 @extension_index[extname.downcase]
c773911 @josh Separate filename and extension configuration
josh authored
209 end
210
9020d7c @bkeepers Deprecate find_by_shebang
bkeepers authored
211 # DEPRECATED
7a6202a @eschulte language interpreters and shebang lines
eschulte authored
212 def self.find_by_shebang(data)
9020d7c @bkeepers Deprecate find_by_shebang
bkeepers authored
213 @interpreter_index[Shebang.interpreter(data)]
7a6202a @eschulte language interpreters and shebang lines
eschulte authored
214 end
215
fd85f7f @bkeepers consolidate shebang logic
bkeepers authored
216 # Public: Look up Languages by interpreter.
217 #
218 # interpreter - String of interpreter name
219 #
220 # Examples
221 #
222 # Language.find_by_interpreter("bash")
223 # # => [#<Language name="Bash">]
224 #
225 # Returns the matching Language
226 def self.find_by_interpreter(interpreter)
227 @interpreter_index[interpreter]
228 end
229
230
5d0e948 @pchaigno Remove last mentions of lexer
pchaigno authored
231 # Public: Look up Language by its name.
5f54801 @josh Document Language class
josh authored
232 #
a75a57e @josh Make Language name finder case sensitive
josh authored
233 # name - The String name of the Language
5f54801 @josh Document Language class
josh authored
234 #
235 # Examples
236 #
237 # Language['Ruby']
238 # # => #<Language name="Ruby">
239 #
240 # Language['ruby']
241 # # => #<Language name="Ruby">
242 #
7c2a887 @josh Return nil if no Language is found
josh authored
243 # Returns the Language or nil if none was found.
5f54801 @josh Document Language class
josh authored
244 def self.[](name)
997c0fc @arfon Catching one more edge case
arfon authored
245 return nil if name.to_s.empty?
3180c5d @Ryman Allow delimiting by comma in the language name
Ryman authored
246 name && (@index[name.downcase] || @index[name.split(',').first.downcase])
5f54801 @josh Document Language class
josh authored
247 end
248
249 # Public: A List of popular languages
250 #
251 # Popular languages are sorted to the top of language chooser
252 # dropdowns.
253 #
254 # This list is configured in "popular.yml".
255 #
5d0e948 @pchaigno Remove last mentions of lexer
pchaigno authored
256 # Returns an Array of Languages.
c2e5065 @josh Add list of popular languages
josh authored
257 def self.popular
cbd6973 @josh Test all languages can by found by name
josh authored
258 @popular ||= all.select(&:popular?).sort_by { |lang| lang.name.downcase }
c2e5065 @josh Add list of popular languages
josh authored
259 end
260
5f54801 @josh Document Language class
josh authored
261 # Public: A List of non-popular languages
262 #
263 # Unpopular languages appear below popular ones in language
264 # chooser dropdowns.
265 #
266 # This list is created from all the languages not listed in "popular.yml".
267 #
5d0e948 @pchaigno Remove last mentions of lexer
pchaigno authored
268 # Returns an Array of Languages.
c2e5065 @josh Add list of popular languages
josh authored
269 def self.unpopular
cbd6973 @josh Test all languages can by found by name
josh authored
270 @unpopular ||= all.select(&:unpopular?).sort_by { |lang| lang.name.downcase }
c2e5065 @josh Add list of popular languages
josh authored
271 end
272
c3d6fc5 @josh Colors!
josh authored
273 # Public: A List of languages with assigned colors.
274 #
275 # Returns an Array of Languages.
276 def self.colors
277 @colors ||= all.select(&:color).sort_by { |lang| lang.name.downcase }
278 end
279
3b7b202 @josh State Ace compatible languages
josh authored
280 # Public: A List of languages compatible with Ace.
281 #
4e5da23 @gjtorikian Add `warn` message indicating deprecation
gjtorikian authored
282 # TODO: Remove this method in a 5.x release. Every language now needs an ace_mode
283 # key, so this function isn't doing anything unique anymore.
284 #
3b7b202 @josh State Ace compatible languages
josh authored
285 # Returns an Array of Languages.
286 def self.ace_modes
4e5da23 @gjtorikian Add `warn` message indicating deprecation
gjtorikian authored
287 warn "This method will be deprecated in a future 5.x release. Every language now has an `ace_mode` set."
ad77857 @gjtorikian This `reject` is no longer necessary
gjtorikian authored
288 @ace_modes ||= all.select(&:ace_mode).sort_by { |lang| lang.name.downcase }
3b7b202 @josh State Ace compatible languages
josh authored
289 end
290
5f54801 @josh Document Language class
josh authored
291 # Internal: Initialize a new Language
292 #
293 # attributes - A hash of attributes
80ff388 @josh Add Language#extensions
josh authored
294 def initialize(attributes = {})
5f54801 @josh Document Language class
josh authored
295 # @name is required
296 @name = attributes[:name] || raise(ArgumentError, "missing name")
297
8f46cd0 @josh Try to classify language types
josh authored
298 # Set type
299 @type = attributes[:type] ? attributes[:type].to_sym : nil
300 if @type && !TYPES.include?(@type)
301 raise ArgumentError, "invalid type: #{@type}"
302 end
303
c3d6fc5 @josh Colors!
josh authored
304 @color = attributes[:color]
305
ba7c2c7 @josh Add language aliases
josh authored
306 # Set aliases
307 @aliases = [default_alias_name] + (attributes[:aliases] || [])
308
4a10b27 @vmg Remove Pygments
vmg authored
309 # Load the TextMate scope name or try to guess one
e5b6001 @vmg Add support for TextMate scopes
vmg authored
310 @tm_scope = attributes[:tm_scope] || begin
311 context = case @type
312 when :data, :markup, :prose
313 'text'
314 when :programming, nil
315 'source'
316 end
317 "#{context}.#{@name.downcase}"
318 end
319
3b7b202 @josh State Ace compatible languages
josh authored
320 @ace_mode = attributes[:ace_mode]
ebd6077 @josh Add wrap flag to text languages
josh authored
321 @wrap = attributes[:wrap] || false
3b7b202 @josh State Ace compatible languages
josh authored
322
90e2f1c @josh Make search term explicit
josh authored
323 # Set legacy search term
324 @search_term = attributes[:search_term] || default_alias_name
5f54801 @josh Document Language class
josh authored
325
326 # Set extensions or default to [].
80ff388 @josh Add Language#extensions
josh authored
327 @extensions = attributes[:extensions] || []
7a6202a @eschulte language interpreters and shebang lines
eschulte authored
328 @interpreters = attributes[:interpreters] || []
c773911 @josh Separate filename and extension configuration
josh authored
329 @filenames = attributes[:filenames] || []
7c0fe46 @josh Add Language#lexer
josh authored
330
8f46cd0 @josh Try to classify language types
josh authored
331 # Set popular, and searchable flags
9501f6b @josh Add searchable flag to langauge
josh authored
332 @popular = attributes.key?(:popular) ? attributes[:popular] : false
333 @searchable = attributes.key?(:searchable) ? attributes[:searchable] : true
a881cde @josh Add language groups
josh authored
334
335 # If group name is set, save the name so we can lazy load it later
336 if attributes[:group_name]
337 @group = nil
338 @group_name = attributes[:group_name]
339
340 # Otherwise we can set it to self now
341 else
342 @group = self
343 end
5f54801 @josh Document Language class
josh authored
344 end
7c0fe46 @josh Add Language#lexer
josh authored
345
5f54801 @josh Document Language class
josh authored
346 # Public: Get proper name
347 #
348 # Examples
349 #
350 # # => "Ruby"
351 # # => "Python"
352 # # => "Perl"
353 #
354 # Returns the name String
355 attr_reader :name
356
8f46cd0 @josh Try to classify language types
josh authored
357 # Public: Get type.
358 #
359 # Returns a type Symbol or nil.
360 attr_reader :type
361
c3d6fc5 @josh Colors!
josh authored
362 # Public: Get color.
363 #
364 # Returns a hex color String.
365 attr_reader :color
366
ba7c2c7 @josh Add language aliases
josh authored
367 # Public: Get aliases
368 #
369 # Examples
370 #
371 # Language['C++'].aliases
372 # # => ["cpp"]
373 #
374 # Returns an Array of String names
375 attr_reader :aliases
376
90e2f1c @josh Make search term explicit
josh authored
377 # Deprecated: Get code search term
5f54801 @josh Document Language class
josh authored
378 #
379 # Examples
380 #
381 # # => "ruby"
382 # # => "python"
383 # # => "perl"
384 #
385 # Returns the name String
90e2f1c @josh Make search term explicit
josh authored
386 attr_reader :search_term
5f54801 @josh Document Language class
josh authored
387
e5b6001 @vmg Add support for TextMate scopes
vmg authored
388 # Public: Get the name of a TextMate-compatible scope
389 #
390 # Returns the scope
391 attr_reader :tm_scope
392
3b7b202 @josh State Ace compatible languages
josh authored
393 # Public: Get Ace mode
394 #
395 # Examples
396 #
397 # # => "text"
398 # # => "javascript"
399 # # => "c_cpp"
400 #
401 # Returns a String name or nil
402 attr_reader :ace_mode
403
ebd6077 @josh Add wrap flag to text languages
josh authored
404 # Public: Should language lines be wrapped
405 #
406 # Returns true or false
407 attr_reader :wrap
408
5f54801 @josh Document Language class
josh authored
409 # Public: Get extensions
410 #
411 # Examples
412 #
c773911 @josh Separate filename and extension configuration
josh authored
413 # # => ['.rb', '.rake', ...]
5f54801 @josh Document Language class
josh authored
414 #
415 # Returns the extensions Array
416 attr_reader :extensions
417
7a6202a @eschulte language interpreters and shebang lines
eschulte authored
418 # Public: Get interpreters
419 #
420 # Examples
421 #
422 # # => ['awk', 'gawk', 'mawk' ...]
423 #
424 # Returns the interpreters Array
425 attr_reader :interpreters
426
c773911 @josh Separate filename and extension configuration
josh authored
427 # Public: Get filenames
428 #
429 # Examples
430 #
431 # # => ['Rakefile', ...]
432 #
433 # Returns the extensions Array
434 attr_reader :filenames
bc7596a @arfon Removing second binary? check
arfon authored
435
2d82071 @nox Delete primary_extension from language data
nox authored
436 # Deprecated: Get primary extension
437 #
438 # Defaults to the first extension but can be overridden
439 # in the languages.yml.
440 #
441 # The primary extension can not be nil. Tests should verify this.
442 #
443 # This method is only used by app/helpers/gists_helper.rb for creating
444 # the language dropdown. It really should be using `name` instead.
445 # Would like to drop primary extension.
446 #
447 # Returns the extension String.
448 def primary_extension
449 extensions.first
450 end
451
329ad99 @josh Add Langauge#escaped_name
josh authored
452 # Public: Get URL escaped name.
453 #
454 # Examples
455 #
456 # "C%23"
457 # "C%2B%2B"
458 # "Common%20Lisp"
459 #
460 # Returns the escaped String.
461 def escaped_name
0872058 @josh Fix name escaping
josh authored
462 EscapeUtils.escape_url(name).gsub('+', '%20')
329ad99 @josh Add Langauge#escaped_name
josh authored
463 end
464
ba7c2c7 @josh Add language aliases
josh authored
465 # Internal: Get default alias name
5f54801 @josh Document Language class
josh authored
466 #
ba7c2c7 @josh Add language aliases
josh authored
467 # Returns the alias name String
468 def default_alias_name
7c0fe46 @josh Add Language#lexer
josh authored
469 name.downcase.gsub(/\s/, '-')
470 end
c37c10a @josh Add Language#find_by_lexer
josh authored
471
a881cde @josh Add language groups
josh authored
472 # Public: Get Language group
473 #
474 # Returns a Language
475 def group
476 @group ||= Language.find_by_name(@group_name)
477 end
478
5f54801 @josh Document Language class
josh authored
479 # Public: Is it popular?
480 #
481 # Returns true or false
c2e5065 @josh Add list of popular languages
josh authored
482 def popular?
483 @popular
484 end
485
5f54801 @josh Document Language class
josh authored
486 # Public: Is it not popular?
487 #
488 # Returns true or false
c2e5065 @josh Add list of popular languages
josh authored
489 def unpopular?
490 !popular?
491 end
492
9501f6b @josh Add searchable flag to langauge
josh authored
493 # Public: Is it searchable?
494 #
495 # Unsearchable languages won't by indexed by solr and won't show
496 # up in the code search dropdown.
497 #
498 # Returns true or false
499 def searchable?
500 @searchable
501 end
502
5f54801 @josh Document Language class
josh authored
503 # Public: Return name as String representation
b78bdc6 @josh Add Language#to_s
josh authored
504 def to_s
505 name
506 end
507
ef1ea9a @josh Language#eql?
josh authored
508 def ==(other)
509 eql?(other)
510 end
511
512 def eql?(other)
513 equal?(other)
514 end
6f22ca4 @josh Add Language hash
josh authored
515
516 def hash
517 name.hash
518 end
6efdaed @josh Nicer Language inspect
josh authored
519
520 def inspect
521 "#<#{self.class} name=#{name}>"
522 end
a1e3b86 @josh Add Language class
josh authored
523 end
524
015af19 @bkeepers Move `Samples::DATA` constant to `Samples.cache` method
bkeepers authored
525 extensions = Samples.cache['extnames']
526 interpreters = Samples.cache['interpreters']
527 filenames = Samples.cache['filenames']
c2e5065 @josh Add list of popular languages
josh authored
528 popular = YAML.load_file(File.expand_path("../popular.yml", __FILE__))
529
bf11900 @charliesome prefer to load from languages.json if it exists
charliesome authored
530 languages_yml = File.expand_path("../languages.yml", __FILE__)
531 languages_json = File.expand_path("../languages.json", __FILE__)
532
cd74333 @bkeepers Use yajl since it is already a dependency
bkeepers authored
533 if File.exist?(languages_json) && defined?(Yajl)
534 languages = Yajl.load(File.read(languages_json))
bf11900 @charliesome prefer to load from languages.json if it exists
charliesome authored
535 else
536 languages = YAML.load_file(languages_yml)
537 end
538
539 languages.each do |name, options|
a775b00 @josh Load extensions from samples
josh authored
540 options['extensions'] ||= []
7a6202a @eschulte language interpreters and shebang lines
eschulte authored
541 options['interpreters'] ||= []
36da52e @josh Move specific filename samples into their own dir
josh authored
542 options['filenames'] ||= []
afedf25 @josh Store extnames in samples.yml
josh authored
543
544 if extnames = extensions[name]
545 extnames.each do |extname|
41e1b7b @pchaigno Detection by extension made case-insensitive
pchaigno authored
546 if !options['extensions'].index { |x| x.downcase.end_with? extname.downcase }
8a42f76 @bkeepers Remove .script! hack
bkeepers authored
547 warn "#{name} has a sample with extension (#{extname.downcase}) that isn't explicitly defined in languages.yml"
afedf25 @josh Store extnames in samples.yml
josh authored
548 options['extensions'] << extname
a775b00 @josh Load extensions from samples
josh authored
549 end
550 end
afedf25 @josh Store extnames in samples.yml
josh authored
551 end
36da52e @josh Move specific filename samples into their own dir
josh authored
552
7a6202a @eschulte language interpreters and shebang lines
eschulte authored
553 if interpreters == nil
554 interpreters = {}
555 end
556
557 if interpreter_names = interpreters[name]
558 interpreter_names.each do |interpreter|
559 if !options['interpreters'].include?(interpreter)
560 options['interpreters'] << interpreter
561 end
562 end
563 end
564
afedf25 @josh Store extnames in samples.yml
josh authored
565 if fns = filenames[name]
566 fns.each do |filename|
567 if !options['filenames'].include?(filename)
568 options['filenames'] << filename
36da52e @josh Move specific filename samples into their own dir
josh authored
569 end
570 end
a775b00 @josh Load extensions from samples
josh authored
571 end
572
f44b311 @josh Remove unused var
josh authored
573 Language.create(
f52afec @josh Allow primary extension override
josh authored
574 :name => name,
c3d6fc5 @josh Colors!
josh authored
575 :color => options['color'],
f52afec @josh Allow primary extension override
josh authored
576 :type => options['type'],
577 :aliases => options['aliases'],
6e872c1 @vmg Pass `tm_scope` overrides
vmg authored
578 :tm_scope => options['tm_scope'],
3b7b202 @josh State Ace compatible languages
josh authored
579 :ace_mode => options['ace_mode'],
ebd6077 @josh Add wrap flag to text languages
josh authored
580 :wrap => options['wrap'],
f52afec @josh Allow primary extension override
josh authored
581 :group_name => options['group'],
cd75493 @bkeepers Extensions aren't actually required
bkeepers authored
582 :searchable => options.fetch('searchable', true),
f52afec @josh Allow primary extension override
josh authored
583 :search_term => options['search_term'],
cd75493 @bkeepers Extensions aren't actually required
bkeepers authored
584 :extensions => Array(options['extensions']),
7a6202a @eschulte language interpreters and shebang lines
eschulte authored
585 :interpreters => options['interpreters'].sort,
f52afec @josh Allow primary extension override
josh authored
586 :filenames => options['filenames'],
587 :popular => popular.include?(name)
c2e5065 @josh Add list of popular languages
josh authored
588 )
a1e3b86 @josh Add Language class
josh authored
589 end
590 end
Something went wrong with that request. Please try again.