├── test ├── fixtures │ ├── blank │ ├── file.txt │ ├── txt │ ├── coffee │ │ ├── empty.coffee │ │ ├── hello.coffee │ │ ├── empty.js │ │ ├── hello.js │ │ ├── classes.coffee │ │ ├── intro.coffee │ │ ├── intro.js │ │ └── classes.js │ ├── foo.txt │ ├── md │ ├── defun.kt │ ├── hello.gsp │ ├── README │ ├── dude.el │ ├── dude.js │ ├── dump.sql │ ├── file.json │ ├── foo.rb │ ├── grit.rb │ ├── script.foo │ ├── tender.md │ ├── hello.ahk │ ├── script.sh │ ├── hello.haml │ ├── script.bash │ ├── script.zsh │ ├── .gvimrc │ ├── script.rb │ ├── .bashrc │ ├── .zlogin │ ├── .zshrc │ ├── script.nu │ ├── script.pl │ ├── .profile │ ├── Rakefile │ ├── hello.vark │ ├── script.js │ ├── script.mrb │ ├── script.py │ ├── .bash_profile │ ├── foo.nim │ ├── hello.ik │ ├── hello.rs │ ├── script.groovy │ ├── test-perl.pl │ ├── wrong_shebang.rb │ ├── script2.rb │ ├── .gitconfig │ ├── Foo.m │ ├── subdir │ │ └── Rakefile │ ├── zip │ ├── dog.o │ ├── foo.bin │ ├── foo.pdf │ ├── foo.png │ ├── git.exe │ ├── test-perl2.pl │ ├── hello-r.R │ ├── hello.pbc │ ├── script.rake │ ├── foo bar.jar │ ├── hello.h │ ├── linguist.gem │ ├── octocat.ai │ ├── octocat.png │ ├── octocat.psd │ ├── hello-rebol.r │ ├── hello.pir │ ├── hello.pasm │ ├── pkg │ │ └── linguist.gem │ ├── Foo.h │ ├── hello.c │ ├── Capfile │ ├── bar.h │ ├── bar.hpp │ ├── hello.cpp │ ├── .vimrc │ ├── hello.n │ ├── hello.m │ ├── .gemrc │ ├── dude-thing-okay--001.patch │ ├── script.scala │ ├── script.rkt │ ├── Hello.gst │ ├── hello-var.gsp │ ├── FooAppDelegate.h │ ├── Hello.gsx │ ├── screen.sass │ ├── matlab_function.m │ ├── hello-resources.gsp │ ├── screen.scss │ ├── FooAppDelegate.m │ ├── program.dpr │ ├── bar.gsp │ ├── test-prolog.pl │ ├── matlab_script.m │ ├── fft.cl │ ├── hello-pagedirective.gsp │ ├── build.gradle │ ├── github.po │ ├── Foo.sig │ ├── hello.s │ ├── scribble.scrbl │ ├── cuda.cu │ ├── center.scpt │ ├── center.applescript │ ├── Foo.sml │ ├── git.deb │ ├── Foo.ml │ ├── BCR2000.sc │ ├── xproc.xqm │ ├── Person.gs │ ├── build.sbt │ ├── drupal.module │ └── asteroids.sps ├── test_repository.rb ├── test_pedantic.rb ├── test_pathname.rb ├── test_mime.rb ├── test_language.rb └── test_blob.rb ├── .gitignore ├── Gemfile ├── Rakefile ├── .travis.yml ├── lib ├── linguist.rb └── linguist │ ├── popular.yml │ ├── file_blob.rb │ ├── vendor.yml │ ├── mimes.yml │ ├── repository.rb │ ├── pathname.rb │ ├── mime.rb │ ├── language.rb │ ├── blob_helper.rb │ └── languages.yml ├── linguist.gemspec ├── LICENSE ├── bin └── linguist └── README.md /test/fixtures/blank: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/fixtures/file.txt: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | Gemfile.lock 2 | -------------------------------------------------------------------------------- /test/fixtures/txt: -------------------------------------------------------------------------------- 1 | Text 2 | -------------------------------------------------------------------------------- /test/fixtures/coffee/empty.coffee: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /test/fixtures/foo.txt: -------------------------------------------------------------------------------- 1 | foo 2 | -------------------------------------------------------------------------------- /test/fixtures/md: -------------------------------------------------------------------------------- 1 | MD 2 | == 3 | -------------------------------------------------------------------------------- /test/fixtures/defun.kt: -------------------------------------------------------------------------------- 1 | defunkt 2 | -------------------------------------------------------------------------------- /test/fixtures/hello.gsp: -------------------------------------------------------------------------------- 1 | print("hello") -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source :rubygems 2 | gemspec 3 | -------------------------------------------------------------------------------- /test/fixtures/README: -------------------------------------------------------------------------------- 1 | README 2 | ====== 3 | -------------------------------------------------------------------------------- /test/fixtures/dude.el: -------------------------------------------------------------------------------- 1 | (print "Dude!") 2 | -------------------------------------------------------------------------------- /test/fixtures/dude.js: -------------------------------------------------------------------------------- 1 | alert("dude!") 2 | -------------------------------------------------------------------------------- /test/fixtures/dump.sql: -------------------------------------------------------------------------------- 1 | DROP ALL TABLES 2 | -------------------------------------------------------------------------------- /test/fixtures/file.json: -------------------------------------------------------------------------------- 1 | {"foo": "bar"} 2 | -------------------------------------------------------------------------------- /test/fixtures/foo.rb: -------------------------------------------------------------------------------- 1 | module Foo 2 | end 3 | -------------------------------------------------------------------------------- /test/fixtures/grit.rb: -------------------------------------------------------------------------------- 1 | module Grit 2 | end 3 | -------------------------------------------------------------------------------- /test/fixtures/script.foo: -------------------------------------------------------------------------------- 1 | #!/bin/foo 2 | ??? 3 | -------------------------------------------------------------------------------- /test/fixtures/tender.md: -------------------------------------------------------------------------------- 1 | Tender 2 | ====== 3 | -------------------------------------------------------------------------------- /test/fixtures/hello.ahk: -------------------------------------------------------------------------------- 1 | MsgBox, Hello`, World! 2 | -------------------------------------------------------------------------------- /test/fixtures/script.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | echo "sh" 3 | -------------------------------------------------------------------------------- /test/fixtures/hello.haml: -------------------------------------------------------------------------------- 1 | %p 2 | Hello, 3 | World! 4 | -------------------------------------------------------------------------------- /test/fixtures/script.bash: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | echo "bash" 3 | -------------------------------------------------------------------------------- /test/fixtures/script.zsh: -------------------------------------------------------------------------------- 1 | #!/bin/zsh 2 | echo "zsh" 3 | -------------------------------------------------------------------------------- /test/fixtures/.gvimrc: -------------------------------------------------------------------------------- 1 | " no toolbar 2 | set guioptions-=T 3 | -------------------------------------------------------------------------------- /test/fixtures/script.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | puts "Ruby" 3 | -------------------------------------------------------------------------------- /test/fixtures/.bashrc: -------------------------------------------------------------------------------- 1 | export PATH="/usr/local/bin:/usr/bin:/bin" 2 | -------------------------------------------------------------------------------- /test/fixtures/.zlogin: -------------------------------------------------------------------------------- 1 | export PATH="/usr/local/bin:/usr/bin:/bin" 2 | -------------------------------------------------------------------------------- /test/fixtures/.zshrc: -------------------------------------------------------------------------------- 1 | export PATH="/usr/local/bin:/usr/bin:/bin" 2 | -------------------------------------------------------------------------------- /test/fixtures/coffee/hello.coffee: -------------------------------------------------------------------------------- 1 | console.log "Hello, World!" 2 | -------------------------------------------------------------------------------- /test/fixtures/script.nu: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env nush 2 | (puts "Hello") 3 | -------------------------------------------------------------------------------- /test/fixtures/script.pl: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/perl 2 | print "Perl\n" 3 | -------------------------------------------------------------------------------- /test/fixtures/.profile: -------------------------------------------------------------------------------- 1 | export PATH="/usr/local/bin:/usr/bin:/bin" 2 | -------------------------------------------------------------------------------- /test/fixtures/Rakefile: -------------------------------------------------------------------------------- 1 | task :default do 2 | puts "Rake" 3 | end 4 | -------------------------------------------------------------------------------- /test/fixtures/coffee/empty.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | 3 | }).call(this); 4 | -------------------------------------------------------------------------------- /test/fixtures/hello.vark: -------------------------------------------------------------------------------- 1 | function hello() { 2 | print("hello") 3 | } -------------------------------------------------------------------------------- /test/fixtures/script.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | console.log("Node") 3 | -------------------------------------------------------------------------------- /test/fixtures/script.mrb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env macruby 2 | puts "MacRuby" 3 | -------------------------------------------------------------------------------- /test/fixtures/script.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python2.4 2 | print "Python" 3 | -------------------------------------------------------------------------------- /test/fixtures/.bash_profile: -------------------------------------------------------------------------------- 1 | export PATH="/usr/local/bin:/usr/bin:/bin" 2 | -------------------------------------------------------------------------------- /test/fixtures/foo.nim: -------------------------------------------------------------------------------- 1 | # Hello world program 2 | 3 | echo "Hello world!" 4 | -------------------------------------------------------------------------------- /test/fixtures/hello.ik: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ioke 2 | 3 | "Hello world." println 4 | -------------------------------------------------------------------------------- /test/fixtures/hello.rs: -------------------------------------------------------------------------------- 1 | fn main() { 2 | log "Hello, world!"; 3 | } 4 | -------------------------------------------------------------------------------- /test/fixtures/script.groovy: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env groovy 2 | println "Groovy!" 3 | -------------------------------------------------------------------------------- /test/fixtures/test-perl.pl: -------------------------------------------------------------------------------- 1 | #!/usr/bin/perl 2 | print "Hello, world!\n"; 3 | -------------------------------------------------------------------------------- /test/fixtures/wrong_shebang.rb: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | puts "Not Python" 3 | -------------------------------------------------------------------------------- /test/fixtures/script2.rb: -------------------------------------------------------------------------------- 1 | #! /usr/bin/env ruby -w -Ilib:test 2 | echo "Ruby" 3 | -------------------------------------------------------------------------------- /test/fixtures/.gitconfig: -------------------------------------------------------------------------------- 1 | [user] 2 | name = Josh Peek 3 | email = josh@github.com 4 | -------------------------------------------------------------------------------- /test/fixtures/Foo.m: -------------------------------------------------------------------------------- 1 | #import "Foo.h" 2 | 3 | 4 | @implementation Foo 5 | 6 | @end 7 | -------------------------------------------------------------------------------- /test/fixtures/subdir/Rakefile: -------------------------------------------------------------------------------- 1 | task :default do 2 | puts "Rake (subdir)" 3 | end 4 | -------------------------------------------------------------------------------- /test/fixtures/zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgdm/linguist/master/test/fixtures/zip -------------------------------------------------------------------------------- /test/fixtures/dog.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgdm/linguist/master/test/fixtures/dog.o -------------------------------------------------------------------------------- /test/fixtures/foo.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgdm/linguist/master/test/fixtures/foo.bin -------------------------------------------------------------------------------- /test/fixtures/foo.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgdm/linguist/master/test/fixtures/foo.pdf -------------------------------------------------------------------------------- /test/fixtures/foo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgdm/linguist/master/test/fixtures/foo.png -------------------------------------------------------------------------------- /test/fixtures/git.exe: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgdm/linguist/master/test/fixtures/git.exe -------------------------------------------------------------------------------- /test/fixtures/test-perl2.pl: -------------------------------------------------------------------------------- 1 | 2 | # Perl file without shebang 3 | print "Hello, world!\n"; 4 | -------------------------------------------------------------------------------- /test/fixtures/hello-r.R: -------------------------------------------------------------------------------- 1 | hello <- function() { 2 | print("hello, world!") 3 | } 4 | hello() 5 | -------------------------------------------------------------------------------- /test/fixtures/hello.pbc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgdm/linguist/master/test/fixtures/hello.pbc -------------------------------------------------------------------------------- /test/fixtures/script.rake: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env rake 2 | task :default do 3 | puts "Rake" 4 | end 5 | -------------------------------------------------------------------------------- /test/fixtures/coffee/hello.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | console.log("Hello, World!"); 3 | }).call(this); 4 | -------------------------------------------------------------------------------- /test/fixtures/foo bar.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgdm/linguist/master/test/fixtures/foo bar.jar -------------------------------------------------------------------------------- /test/fixtures/hello.h: -------------------------------------------------------------------------------- 1 | #ifndef HELLO_H 2 | #define HELLO_H 3 | 4 | void hello(); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /test/fixtures/linguist.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgdm/linguist/master/test/fixtures/linguist.gem -------------------------------------------------------------------------------- /test/fixtures/octocat.ai: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgdm/linguist/master/test/fixtures/octocat.ai -------------------------------------------------------------------------------- /test/fixtures/octocat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgdm/linguist/master/test/fixtures/octocat.png -------------------------------------------------------------------------------- /test/fixtures/octocat.psd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgdm/linguist/master/test/fixtures/octocat.psd -------------------------------------------------------------------------------- /test/fixtures/hello-rebol.r: -------------------------------------------------------------------------------- 1 | REBOL [] 2 | hello: func [] [ 3 | print "hello, world!" 4 | ] 5 | hello 6 | -------------------------------------------------------------------------------- /test/fixtures/hello.pir: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env parrot 2 | 3 | .sub 'main' :main 4 | say "Hello!" 5 | .end 6 | -------------------------------------------------------------------------------- /test/fixtures/hello.pasm: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env parrot 2 | 3 | .pcc_sub :main main: 4 | say "Hello!" 5 | end 6 | -------------------------------------------------------------------------------- /test/fixtures/pkg/linguist.gem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mgdm/linguist/master/test/fixtures/pkg/linguist.gem -------------------------------------------------------------------------------- /test/fixtures/Foo.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | 4 | @interface Foo : NSObject { 5 | 6 | } 7 | 8 | @end 9 | -------------------------------------------------------------------------------- /test/fixtures/hello.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | int main() 4 | { 5 | printf("Hello World\n"); 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'rake/testtask' 2 | 3 | task :default => :test 4 | 5 | Rake::TestTask.new do |t| 6 | t.warning = true 7 | end 8 | -------------------------------------------------------------------------------- /test/fixtures/Capfile: -------------------------------------------------------------------------------- 1 | load 'deploy' 2 | Dir['vendor/plugins/*/recipes/*.rb'].each { |plugin| load(plugin) } 3 | load 'config/deploy' 4 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | rvm: 2 | - 1.8.7 3 | - 1.9.2 4 | - jruby 5 | - rbx 6 | - ree 7 | 8 | notifications: 9 | disabled: true 10 | -------------------------------------------------------------------------------- /test/fixtures/bar.h: -------------------------------------------------------------------------------- 1 | class Bar 2 | { 3 | protected: 4 | 5 | char *name; 6 | 7 | public: 8 | 9 | void hello(); 10 | } 11 | -------------------------------------------------------------------------------- /test/fixtures/bar.hpp: -------------------------------------------------------------------------------- 1 | class Bar 2 | { 3 | protected: 4 | 5 | char *name; 6 | 7 | public: 8 | 9 | void hello(); 10 | } 11 | -------------------------------------------------------------------------------- /test/fixtures/hello.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | using namespace std; 4 | 5 | int main() 6 | { 7 | cout << "Hello World" << endl; 8 | } 9 | -------------------------------------------------------------------------------- /test/fixtures/.vimrc: -------------------------------------------------------------------------------- 1 | set nocompatible 2 | set ignorecase 3 | set incsearch 4 | set smartcase 5 | set showmatch 6 | set showcmd 7 | 8 | syntax on 9 | -------------------------------------------------------------------------------- /test/fixtures/hello.n: -------------------------------------------------------------------------------- 1 | using System.Console; 2 | 3 | module Program 4 | { 5 | Main() : void 6 | { 7 | WriteLine("Hello world"); 8 | } 9 | } -------------------------------------------------------------------------------- /test/fixtures/hello.m: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | int main(int argc, char *argv[]) 4 | { 5 | NSLog(@"Hello, World!\n"); 6 | return 0; 7 | } 8 | -------------------------------------------------------------------------------- /test/fixtures/.gemrc: -------------------------------------------------------------------------------- 1 | gem: --local --gen-rdoc --run-tests 2 | rdoc: --inline-source --line-numbers 3 | gempath: 4 | - /usr/local/rubygems 5 | - /home/gavin/.rubygems 6 | -------------------------------------------------------------------------------- /lib/linguist.rb: -------------------------------------------------------------------------------- 1 | require 'linguist/blob_helper' 2 | require 'linguist/language' 3 | require 'linguist/mime' 4 | require 'linguist/pathname' 5 | require 'linguist/repository' 6 | -------------------------------------------------------------------------------- /test/fixtures/dude-thing-okay--001.patch: -------------------------------------------------------------------------------- 1 | diff --git a/lib/linguist.rb b/lib/linguist.rb 2 | index d472341..8ad9ffb 100644 3 | --- a/lib/linguist.rb 4 | +++ b/lib/linguist.rb 5 | -------------------------------------------------------------------------------- /test/fixtures/script.scala: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | exec scala "$0" "$@" 3 | !# 4 | 5 | object HelloWorld { 6 | def main(args: Array[String]) { 7 | println("Hello, world!") 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /test/fixtures/script.rkt: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | #| -*- scheme -*- 3 | exec racket -um "$0" "$@" 4 | |# 5 | 6 | (require racket/file racket/path racket/list racket/string 7 | (for-syntax racket/base)) 8 | -------------------------------------------------------------------------------- /test/fixtures/Hello.gst: -------------------------------------------------------------------------------- 1 | <%!-- defined in Hello.gst --%> 2 | 3 | <%@ params( users : Collection ) %> 4 | 5 | <% for( user in users ) { %> 6 | 7 | ${user.LastName}, ${user.FirstName}, ${user.Department} <% } %> -------------------------------------------------------------------------------- /test/fixtures/hello-var.gsp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Testing with SiteMesh and ${example} 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /test/fixtures/FooAppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface FooAppDelegate : NSObject { 4 | @private 5 | NSWindow *window; 6 | } 7 | 8 | @property (assign) IBOutlet NSWindow *window; 9 | 10 | @end 11 | -------------------------------------------------------------------------------- /test/fixtures/Hello.gsx: -------------------------------------------------------------------------------- 1 | package example 2 | 3 | enhancement Hello : String { 4 | 5 | function toPerson() : Person { 6 | var vals = this.split(",") 7 | return new Person( vals[0], vals[1] as int, Relationship.valueOf( vals[2] ) ) ) 8 | } 9 | } -------------------------------------------------------------------------------- /test/fixtures/screen.sass: -------------------------------------------------------------------------------- 1 | $blue: #3bbfce 2 | $margin: 16px 3 | 4 | .content-navigation 5 | border-color: $blue 6 | color: darken($blue, 9%) 7 | 8 | .border 9 | padding: $margin / 2 10 | margin: $margin / 2 11 | border-color: $blue 12 | -------------------------------------------------------------------------------- /test/fixtures/matlab_function.m: -------------------------------------------------------------------------------- 1 | function ret = matlab_function(A,B) 2 | % Simple function adding two values and displaying the return value 3 | 4 | ret = A+B; 5 | % Display the return value 6 | disp('Return value in function'); 7 | disp(ret); 8 | 9 | 10 | -------------------------------------------------------------------------------- /test/fixtures/hello-resources.gsp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Testing with Resources 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /test/fixtures/screen.scss: -------------------------------------------------------------------------------- 1 | $blue: #3bbfce; 2 | $margin: 16px; 3 | 4 | .content-navigation { 5 | border-color: $blue; 6 | color: 7 | darken($blue, 9%); 8 | } 9 | 10 | .border { 11 | padding: $margin / 2; 12 | margin: $margin / 2; 13 | border-color: $blue; 14 | } 15 | -------------------------------------------------------------------------------- /test/fixtures/FooAppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "FooAppDelegate.h" 2 | 3 | @implementation FooAppDelegate 4 | 5 | @synthesize window; 6 | 7 | - (void)applicationDidFinishLaunching:(NSNotification *)aNotification 8 | { 9 | // Insert code here to initialize your application 10 | } 11 | 12 | @end 13 | -------------------------------------------------------------------------------- /test/fixtures/program.dpr: -------------------------------------------------------------------------------- 1 | program gmail; 2 | 3 | uses 4 | Forms, 5 | Unit2 in 'Unit2.pas' {Form2}; 6 | 7 | {$R *.res} 8 | 9 | begin 10 | Application.Initialize; 11 | Application.MainFormOnTaskbar := True; 12 | Application.CreateForm(TForm2, Form2); 13 | Application.Run; 14 | end. 15 | -------------------------------------------------------------------------------- /test/fixtures/bar.gsp: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Testing with SiteMesh and Resources 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /test/fixtures/test-prolog.pl: -------------------------------------------------------------------------------- 1 | /* Prolog test file */ 2 | male(john). 3 | male(peter). 4 | 5 | female(vick). 6 | female(christie). 7 | 8 | parents(john, peter, christie). 9 | parents(vick, peter, christie). 10 | 11 | /* X is a brother of Y */ 12 | brother(X, Y) :- male(X), parents(X, F, M), parents(Y, F, M). 13 | -------------------------------------------------------------------------------- /test/fixtures/matlab_script.m: -------------------------------------------------------------------------------- 1 | % Matlab example script 2 | 3 | %Call matlab_function function which resides in the same directory 4 | 5 | value1 = 5 % semicolon at end of line is not mandatory, only suppresses output to command line. 6 | value2 = 3 7 | 8 | % Calculate sum of value1 and value2 9 | result = matlab_function(value1,value2); 10 | 11 | disp('called from script') 12 | disp(result); 13 | -------------------------------------------------------------------------------- /test/fixtures/fft.cl: -------------------------------------------------------------------------------- 1 | double run_fftw(int n,const float * x,float * y) 2 | { 3 | fftwf_plan p1 = fftwf_plan_dft_1d(n,(fftwf_complex *)x,(fftwf_complex *)y, 4 | FFTW_FORWARD,FFTW_ESTIMATE); 5 | const int nops = 10; 6 | double t = cl::realTime(); 7 | for (int op = 0;op < nops;op++) { 8 | fftwf_execute(p1); 9 | } 10 | t = (cl::realTime() - t)/(double)nops; 11 | fftwf_destroy_plan(p1); 12 | return t; 13 | } 14 | -------------------------------------------------------------------------------- /lib/linguist/popular.yml: -------------------------------------------------------------------------------- 1 | # Popular languages appear at the top of language dropdowns 2 | # 3 | # This file should only be edited by GitHub staff 4 | 5 | - ActionScript 6 | - Bash 7 | - C 8 | - C# 9 | - C++ 10 | - CSS 11 | - Common Lisp 12 | - Diff 13 | - Emacs Lisp 14 | - Erlang 15 | - HTML 16 | - Haskell 17 | - Java 18 | - JavaScript 19 | - Lua 20 | - Objective-C 21 | - PHP 22 | - Perl 23 | - Python 24 | - Ruby 25 | - SQL 26 | - Scala 27 | - Scheme 28 | - TeX 29 | - XML 30 | -------------------------------------------------------------------------------- /test/fixtures/hello-pagedirective.gsp: -------------------------------------------------------------------------------- 1 | <%@ page contentType="text/html;charset=UTF-8" %> 2 | 3 | 4 | 5 | Using page directive tag 6 | 7 | 8 |
9 | Download 10 |
11 |
12 | Print 13 |
14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /test/fixtures/coffee/classes.coffee: -------------------------------------------------------------------------------- 1 | class Animal 2 | constructor: (@name) -> 3 | 4 | move: (meters) -> 5 | alert @name + " moved " + meters + "m." 6 | 7 | class Snake extends Animal 8 | move: -> 9 | alert "Slithering..." 10 | super 5 11 | 12 | class Horse extends Animal 13 | move: -> 14 | alert "Galloping..." 15 | super 45 16 | 17 | sam = new Snake "Sammy the Python" 18 | tom = new Horse "Tommy the Palomino" 19 | 20 | sam.move() 21 | tom.move() 22 | -------------------------------------------------------------------------------- /linguist.gemspec: -------------------------------------------------------------------------------- 1 | Gem::Specification.new do |s| 2 | s.name = 'linguist' 3 | s.version = '1.0.0' 4 | s.summary = "GitHub Language detection" 5 | 6 | s.files = Dir['lib/**/*'] 7 | s.executables << 'linguist' 8 | 9 | s.add_dependency 'charlock_holmes', '~> 0.6.6' 10 | s.add_dependency 'escape_utils', '~> 0.2.3' 11 | s.add_dependency 'mime-types', '~> 1.16' 12 | s.add_dependency 'pygments.rb', '~> 0.2.1' 13 | s.add_development_dependency 'rake' 14 | end 15 | -------------------------------------------------------------------------------- /test/fixtures/coffee/intro.coffee: -------------------------------------------------------------------------------- 1 | # Assignment: 2 | number = 42 3 | opposite = true 4 | 5 | # Conditions: 6 | number = -42 if opposite 7 | 8 | # Functions: 9 | square = (x) -> x * x 10 | 11 | # Arrays: 12 | list = [1, 2, 3, 4, 5] 13 | 14 | # Objects: 15 | math = 16 | root: Math.sqrt 17 | square: square 18 | cube: (x) -> x * square x 19 | 20 | # Splats: 21 | race = (winner, runners...) -> 22 | print winner, runners 23 | 24 | # Existence: 25 | alert "I knew it!" if elvis? 26 | 27 | # Array comprehensions: 28 | cubes = (math.cube num for num in list) 29 | -------------------------------------------------------------------------------- /test/fixtures/build.gradle: -------------------------------------------------------------------------------- 1 | task echoDirListViaAntBuilder() { 2 | description = 'Uses the built-in AntBuilder instance to echo and list files' 3 | //Docs: http://ant.apache.org/manual/Types/fileset.html 4 | 5 | //Echo the Gradle project name via the ant echo plugin 6 | ant.echo(message: project.name) 7 | ant.echo(path) 8 | ant.echo("${projectDir}/samples") 9 | 10 | //Gather list of files in a subdirectory 11 | ant.fileScanner{ 12 | fileset(dir:"samples") 13 | }.each{ 14 | //Print each file to screen with the CWD (projectDir) path removed. 15 | println it.toString() - "${projectDir}" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /test/test_repository.rb: -------------------------------------------------------------------------------- 1 | require 'linguist/repository' 2 | 3 | require 'test/unit' 4 | 5 | class TestRepository < Test::Unit::TestCase 6 | include Linguist 7 | 8 | def repo(base_path) 9 | Repository.from_directory(base_path) 10 | end 11 | 12 | def linguist_repo 13 | repo(File.expand_path("../..", __FILE__)) 14 | end 15 | 16 | def test_linguist_language 17 | assert_equal Language['JavaScript'], linguist_repo.language 18 | end 19 | 20 | def test_linguist_languages 21 | assert linguist_repo.languages[Language['Ruby']] > 30_000 22 | assert linguist_repo.languages[Language['Python']] < 1000 23 | end 24 | 25 | def test_linguist_size 26 | assert linguist_repo.size > 30_000 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /test/fixtures/github.po: -------------------------------------------------------------------------------- 1 | # SOME DESCRIPTIVE TITLE. 2 | # Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER 3 | # This file is distributed under the same license as the PACKAGE package. 4 | # FIRST AUTHOR , YEAR. 5 | # 6 | #, fuzzy 7 | msgid "" 8 | msgstr "" 9 | "Project-Id-Version: x\n" 10 | "POT-Creation-Date: 2009-02-15 09:22+0100\n" 11 | "PO-Revision-Date: 2009-02-15 09:22+0100\n" 12 | "Last-Translator: FULL NAME \n" 13 | "Language-Team: LANGUAGE \n" 14 | "MIME-Version: 1.0\n" 15 | "Content-Type: text/plain; charset=UTF-8\n" 16 | "Content-Transfer-Encoding: 8bit\n" 17 | "Plural-Forms: nplurals=INTEGER; plural=EXPRESSION;\n" 18 | 19 | #: tools/files/simple_translation.rb:1 20 | msgid "a translation" 21 | msgstr "" 22 | -------------------------------------------------------------------------------- /test/fixtures/Foo.sig: -------------------------------------------------------------------------------- 1 | 2 | signature LAZY_BASE = 3 | sig 4 | type 'a lazy 5 | exception Undefined 6 | val force: 'a lazy -> 'a 7 | val delay: (unit -> 'a) -> 'a lazy 8 | val undefined: 'a lazy 9 | end 10 | 11 | signature LAZY' = 12 | sig 13 | include LAZY_BASE 14 | val isUndefined: 'a lazy -> bool 15 | val inject : 'a -> 'a lazy 16 | val toString: ('a -> string) -> 'a lazy -> string 17 | val eq: ''a lazy * ''a lazy -> bool 18 | val eqBy: ('a * 'a -> bool) -> 'a lazy * 'a lazy -> bool 19 | val compare: ('a * 'a -> order) -> 'a lazy * 'a lazy -> order 20 | val map: ('a -> 'b) -> 'a lazy -> 'b lazy 21 | 22 | structure Ops: 23 | sig 24 | val ! : 'a lazy -> 'a (* force *) 25 | val ? : 'a -> 'a lazy (* inject *) 26 | end 27 | end 28 | -------------------------------------------------------------------------------- /test/fixtures/coffee/intro.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var cubes, list, math, num, number, opposite, race, square; 3 | var __slice = Array.prototype.slice; 4 | number = 42; 5 | opposite = true; 6 | if (opposite) { 7 | number = -42; 8 | } 9 | square = function(x) { 10 | return x * x; 11 | }; 12 | list = [1, 2, 3, 4, 5]; 13 | math = { 14 | root: Math.sqrt, 15 | square: square, 16 | cube: function(x) { 17 | return x * square(x); 18 | } 19 | }; 20 | race = function() { 21 | var runners, winner; 22 | winner = arguments[0], runners = 2 <= arguments.length ? __slice.call(arguments, 1) : []; 23 | return print(winner, runners); 24 | }; 25 | if (typeof elvis !== "undefined" && elvis !== null) { 26 | alert("I knew it!"); 27 | } 28 | cubes = (function() { 29 | var _i, _len, _results; 30 | _results = []; 31 | for (_i = 0, _len = list.length; _i < _len; _i++) { 32 | num = list[_i]; 33 | _results.push(math.cube(num)); 34 | } 35 | return _results; 36 | })(); 37 | }).call(this); 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2011 GitHub, Inc. 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /test/fixtures/hello.s: -------------------------------------------------------------------------------- 1 | .cstring 2 | LC0: 3 | .ascii "Hello World\0" 4 | .text 5 | .globl _main 6 | _main: 7 | LFB3: 8 | pushq %rbp 9 | LCFI0: 10 | movq %rsp, %rbp 11 | LCFI1: 12 | leaq LC0(%rip), %rdi 13 | call _puts 14 | movl $0, %eax 15 | leave 16 | ret 17 | LFE3: 18 | .section __TEXT,__eh_frame,coalesced,no_toc+strip_static_syms+live_support 19 | EH_frame1: 20 | .set L$set$0,LECIE1-LSCIE1 21 | .long L$set$0 22 | LSCIE1: 23 | .long 0x0 24 | .byte 0x1 25 | .ascii "zR\0" 26 | .byte 0x1 27 | .byte 0x78 28 | .byte 0x10 29 | .byte 0x1 30 | .byte 0x10 31 | .byte 0xc 32 | .byte 0x7 33 | .byte 0x8 34 | .byte 0x90 35 | .byte 0x1 36 | .align 3 37 | LECIE1: 38 | .globl _main.eh 39 | _main.eh: 40 | LSFDE1: 41 | .set L$set$1,LEFDE1-LASFDE1 42 | .long L$set$1 43 | LASFDE1: 44 | .long LASFDE1-EH_frame1 45 | .quad LFB3-. 46 | .set L$set$2,LFE3-LFB3 47 | .quad L$set$2 48 | .byte 0x0 49 | .byte 0x4 50 | .set L$set$3,LCFI0-LFB3 51 | .long L$set$3 52 | .byte 0xe 53 | .byte 0x10 54 | .byte 0x86 55 | .byte 0x2 56 | .byte 0x4 57 | .set L$set$4,LCFI1-LCFI0 58 | .long L$set$4 59 | .byte 0xd 60 | .byte 0x6 61 | .align 3 62 | LEFDE1: 63 | .subsections_via_symbols 64 | -------------------------------------------------------------------------------- /bin/linguist: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env ruby 2 | 3 | require 'linguist/file_blob' 4 | require 'linguist/repository' 5 | 6 | path = ARGV[0] || Dir.pwd 7 | 8 | if File.directory?(path) 9 | repo = Linguist::Repository.from_directory(path) 10 | repo.languages.sort_by { |_, size| size }.reverse.each do |language, size| 11 | percentage = ((size / repo.size.to_f) * 100).round 12 | puts "%-4s %s" % ["#{percentage}%", language] 13 | end 14 | elsif File.file?(path) 15 | blob = Linguist::FileBlob.new(path, Dir.pwd) 16 | type = if blob.text? 17 | 'Text' 18 | elsif blob.image? 19 | 'Image' 20 | else 21 | 'Binary' 22 | end 23 | 24 | puts "#{blob.name}: #{blob.loc} lines (#{blob.sloc} sloc)" 25 | puts " type: #{type}" 26 | puts " extension: #{blob.pathname.extname}" 27 | puts " mime type: #{blob.mime_type}" 28 | puts " language: #{blob.language}" 29 | 30 | if blob.large? 31 | puts " blob is to large to be shown" 32 | end 33 | 34 | if blob.generated? 35 | puts " appears to be generated source code" 36 | end 37 | 38 | if blob.vendored? 39 | puts " appears to be a vendored file" 40 | end 41 | else 42 | abort "usage: linguist " 43 | end 44 | -------------------------------------------------------------------------------- /test/fixtures/scribble.scrbl: -------------------------------------------------------------------------------- 1 | #lang scribble/manual 2 | @(require scribble/bnf "utils.rkt") 3 | 4 | @title{Scribble: The Racket Documentation Tool} 5 | 6 | @author["Matthew Flatt" "Eli Barzilay"] 7 | 8 | Scribble is a collection of tools for creating prose 9 | documents---papers, books, library documentation, etc.---in HTML or 10 | PDF (via Latex) form. More generally, Scribble helps you write 11 | programs that are rich in textual content, whether the content is 12 | prose to be typeset or any other form of text to be generated 13 | programmatically. 14 | 15 | This document is itself written using Scribble. You can see its source 16 | at 17 | @(let ([url "http://git.racket-lang.org/plt/tree/HEAD:/collects/scribblings/scribble"]) 18 | (link url url)), 19 | starting with the @filepath{scribble.scrbl} file. 20 | 21 | @table-of-contents[] 22 | 23 | @; ------------------------------------------------------------------------ 24 | @include-section["how-to-paper.scrbl"] 25 | @include-section["reader.scrbl"] 26 | @include-section["generic.scrbl"] 27 | @include-section["plt.scrbl"] 28 | @include-section["lp.scrbl"] 29 | @include-section["text.scrbl"] 30 | @include-section["internals.scrbl"] 31 | @include-section["running.scrbl"] 32 | 33 | @index-section[] 34 | -------------------------------------------------------------------------------- /lib/linguist/file_blob.rb: -------------------------------------------------------------------------------- 1 | require 'linguist/blob_helper' 2 | 3 | module Linguist 4 | # A FileBlob is a wrapper around a File object to make it quack 5 | # like a Grit::Blob. It provides the basic interface: `name`, 6 | # `data`, and `size`. 7 | class FileBlob 8 | include BlobHelper 9 | 10 | # Public: Initialize a new FileBlob from a path 11 | # 12 | # path - A path String that exists on the file system. 13 | # base_path - Optional base to relativize the path 14 | # 15 | # Returns a FileBlob. 16 | def initialize(path, base_path = nil) 17 | @path = path 18 | @name = base_path ? path.sub("#{base_path}/", '') : path 19 | end 20 | 21 | # Public: Filename 22 | # 23 | # Examples 24 | # 25 | # FileBlob.new("/path/to/linguist/lib/linguist.rb").name 26 | # # => "/path/to/linguist/lib/linguist.rb" 27 | # 28 | # FileBlob.new("/path/to/linguist/lib/linguist.rb", 29 | # "/path/to/linguist").name 30 | # # => "lib/linguist.rb" 31 | # 32 | # Returns a String 33 | attr_reader :name 34 | 35 | # Public: Read file contents. 36 | # 37 | # Returns a String. 38 | def data 39 | File.read(@path) 40 | end 41 | 42 | # Public: Get byte size 43 | # 44 | # Returns an Integer. 45 | def size 46 | File.size(@path) 47 | end 48 | end 49 | end 50 | -------------------------------------------------------------------------------- /lib/linguist/vendor.yml: -------------------------------------------------------------------------------- 1 | # Vendored files and directories are excluded from language 2 | # statistics. 3 | # 4 | # Lines in this file are Regexps that are matched against the file 5 | # pathname. 6 | # 7 | # Please add additional test coverage to 8 | # `test/test_blob.rb#test_vendored` if you make any changes. 9 | 10 | ## Vendor Conventions ## 11 | 12 | # Caches 13 | - cache/ 14 | 15 | # C deps 16 | # https://github.com/joyent/node 17 | - ^deps/ 18 | - ^tools/ 19 | 20 | # Node depedencies 21 | - ^node_modules/ 22 | 23 | # Rails vendor/ 24 | - ^vendor/ 25 | 26 | 27 | ## Commonly Bundled JavaScript frameworks ## 28 | 29 | # jQuery 30 | - (^|/)jquery([^.]*)(\.min)?\.js$ 31 | - (^|/)jquery\-\d\.\d\.\d(\.min)?\.js$ 32 | 33 | # Prototype 34 | - (^|/)prototype(.*)\.js$ 35 | - (^|/)effects\.js$ 36 | - (^|/)controls\.js$ 37 | - (^|/)dragdrop\.js$ 38 | 39 | # MooTools 40 | - (^|/)mootools([^.]*)\d+\.\d+.\d+([^.]*)\.js$ 41 | 42 | # Dojo 43 | - (^|/)dojo\.js$ 44 | 45 | # MochiKit 46 | - (^|/)MochiKit\.js$ 47 | 48 | # YUI 49 | - (^|/)yahoo-([^.]*)\.js$ 50 | - (^|/)yui([^.]*)\.js$ 51 | 52 | # LESS css 53 | - (^|/)less([^.]*)(\.min)?\.js$ 54 | - (^|/)less\-\d+\.\d+\.\d+(\.min)?\.js$ 55 | 56 | # WYS editors 57 | - (^|/)ckeditor\.js$ 58 | - (^|/)tiny_mce([^.]*)\.js$ 59 | 60 | 61 | ## Python ## 62 | 63 | # Fabric 64 | - ^fabfile\.py$ 65 | 66 | 67 | ## Obj-C ## 68 | 69 | # Sparkle 70 | - (^|/)Sparkle/ 71 | -------------------------------------------------------------------------------- /test/fixtures/cuda.cu: -------------------------------------------------------------------------------- 1 | void foo() 2 | { 3 | cudaArray* cu_array; 4 | texture tex; 5 | 6 | // Allocate array 7 | cudaChannelFormatDesc description = cudaCreateChannelDesc(); 8 | cudaMallocArray(&cu_array, &description, width, height); 9 | 10 | // Copy image data to array 11 | cudaMemcpyToArray(cu_array, image, width*height*sizeof(float), cudaMemcpyHostToDevice); 12 | 13 | // Set texture parameters (default) 14 | tex.addressMode[0] = cudaAddressModeClamp; 15 | tex.addressMode[1] = cudaAddressModeClamp; 16 | tex.filterMode = cudaFilterModePoint; 17 | tex.normalized = false; // do not normalize coordinates 18 | 19 | // Bind the array to the texture 20 | cudaBindTextureToArray(tex, cu_array); 21 | 22 | // Run kernel 23 | dim3 blockDim(16, 16, 1); 24 | dim3 gridDim((width + blockDim.x - 1)/ blockDim.x, (height + blockDim.y - 1) / blockDim.y, 1); 25 | kernel<<< gridDim, blockDim, 0 >>>(d_data, height, width); 26 | 27 | // Unbind the array from the texture 28 | cudaUnbindTexture(tex); 29 | } //end foo() 30 | 31 | __global__ void kernel(float* odata, int height, int width) 32 | { 33 | unsigned int x = blockIdx.x*blockDim.x + threadIdx.x; 34 | unsigned int y = blockIdx.y*blockDim.y + threadIdx.y; 35 | if (x < width && y < height) { 36 | float c = tex2D(tex, x, y); 37 | odata[y*width+x] = c; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /test/test_pedantic.rb: -------------------------------------------------------------------------------- 1 | require 'test/unit' 2 | 3 | class TestPedantic < Test::Unit::TestCase 4 | Lib = File.expand_path("../../lib/linguist", __FILE__) 5 | 6 | def file(name) 7 | File.read(File.join(Lib, name)) 8 | end 9 | 10 | def test_language_names_are_sorted 11 | languages = [] 12 | file("languages.yml").lines.each do |line| 13 | if line =~ /^(\w+):$/ 14 | languages << $1 15 | end 16 | end 17 | assert_sorted languages 18 | end 19 | 20 | def test_extensions_are_sorted 21 | extensions = nil 22 | file("languages.yml").lines.each do |line| 23 | if line =~ /^ extensions:$/ 24 | extensions = [] 25 | elsif extensions && line =~ /^ - \.(\w+)$/ 26 | extensions << $1 27 | else 28 | assert_sorted extensions if extensions 29 | extensions = nil 30 | end 31 | end 32 | end 33 | 34 | def test_filenames_are_sorted 35 | filenames = nil 36 | file("languages.yml").lines.each do |line| 37 | if line =~ /^ filenames:$/ 38 | filenames = [] 39 | elsif filenames && line =~ /^ - \.(\w+)$/ 40 | filenames << $1 41 | else 42 | assert_sorted filenames if filenames 43 | filenames = nil 44 | end 45 | end 46 | end 47 | 48 | def assert_sorted(list) 49 | previous = nil 50 | list.each do |item| 51 | if previous && previous > item 52 | flunk "#{previous} should come after #{item}" 53 | end 54 | previous = item 55 | end 56 | end 57 | end 58 | -------------------------------------------------------------------------------- /test/fixtures/coffee/classes.js: -------------------------------------------------------------------------------- 1 | (function() { 2 | var Animal, Horse, Snake, sam, tom; 3 | var __hasProp = Object.prototype.hasOwnProperty, __extends = function(child, parent) { 4 | for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } 5 | function ctor() { this.constructor = child; } 6 | ctor.prototype = parent.prototype; 7 | child.prototype = new ctor; 8 | child.__super__ = parent.prototype; 9 | return child; 10 | }; 11 | Animal = (function() { 12 | function Animal(name) { 13 | this.name = name; 14 | } 15 | Animal.prototype.move = function(meters) { 16 | return alert(this.name + " moved " + meters + "m."); 17 | }; 18 | return Animal; 19 | })(); 20 | Snake = (function() { 21 | __extends(Snake, Animal); 22 | function Snake() { 23 | Snake.__super__.constructor.apply(this, arguments); 24 | } 25 | Snake.prototype.move = function() { 26 | alert("Slithering..."); 27 | return Snake.__super__.move.call(this, 5); 28 | }; 29 | return Snake; 30 | })(); 31 | Horse = (function() { 32 | __extends(Horse, Animal); 33 | function Horse() { 34 | Horse.__super__.constructor.apply(this, arguments); 35 | } 36 | Horse.prototype.move = function() { 37 | alert("Galloping..."); 38 | return Horse.__super__.move.call(this, 45); 39 | }; 40 | return Horse; 41 | })(); 42 | sam = new Snake("Sammy the Python"); 43 | tom = new Horse("Tommy the Palomino"); 44 | sam.move(); 45 | tom.move(); 46 | }).call(this); 47 | -------------------------------------------------------------------------------- /test/fixtures/center.scpt: -------------------------------------------------------------------------------- 1 | set windowWidth to 800 2 | set windowHeight to 600 3 | delay 0.1 4 | 5 | set AppleScript's text item delimiters to "x" 6 | 7 | set res to text returned of (display dialog "Enter the width x height:" default answer ((windowWidth & windowHeight) as text)) 8 | 9 | if res is "" then 10 | display dialog "You need to enter a correct response" 11 | return 12 | end if 13 | set {windowWidth, windowHeight} to text items of res 14 | 15 | set AppleScript's text item delimiters to "" 16 | 17 | tell application "Safari" 18 | set screen_width to (do JavaScript "screen.availWidth" in document 1) 19 | set screen_height to (do JavaScript "screen.availHeight" in document 1) 20 | end tell 21 | 22 | tell application "System Events" 23 | set myFrontMost to name of first item of (processes whose frontmost is true) 24 | end tell 25 | 26 | tell application "Finder" 27 | set {desktopTop, desktopLeft, desktopRight, desktopBottom} to bounds of desktop 28 | end tell 29 | 30 | try 31 | tell application "System Events" 32 | tell process myFrontMost 33 | set {{w, h}} to size of drawer of window 1 34 | end tell 35 | end tell 36 | on error 37 | set {w, h} to {0, 0} 38 | end try 39 | 40 | tell application "System Events" 41 | tell process myFrontMost 42 | try 43 | set {{w, h}} to size of drawer of window 1 44 | on error 45 | set {w, h} to {0, 0} 46 | end try 47 | set position of window 1 to {((screen_width - windowWidth) / 2), ((screen_height - windowHeight) / 2.0) - desktopTop} 48 | set size of window 1 to {windowWidth -w, windowHeight} 49 | end tell 50 | end tell -------------------------------------------------------------------------------- /test/fixtures/center.applescript: -------------------------------------------------------------------------------- 1 | set windowWidth to 800 2 | set windowHeight to 600 3 | delay 0.1 4 | 5 | set AppleScript's text item delimiters to "x" 6 | 7 | set res to text returned of (display dialog "Enter the width x height:" default answer ((windowWidth & windowHeight) as text)) 8 | 9 | if res is "" then 10 | display dialog "You need to enter a correct response" 11 | return 12 | end if 13 | set {windowWidth, windowHeight} to text items of res 14 | 15 | set AppleScript's text item delimiters to "" 16 | 17 | tell application "Safari" 18 | set screen_width to (do JavaScript "screen.availWidth" in document 1) 19 | set screen_height to (do JavaScript "screen.availHeight" in document 1) 20 | end tell 21 | 22 | tell application "System Events" 23 | set myFrontMost to name of first item of (processes whose frontmost is true) 24 | end tell 25 | 26 | tell application "Finder" 27 | set {desktopTop, desktopLeft, desktopRight, desktopBottom} to bounds of desktop 28 | end tell 29 | 30 | try 31 | tell application "System Events" 32 | tell process myFrontMost 33 | set {{w, h}} to size of drawer of window 1 34 | end tell 35 | end tell 36 | on error 37 | set {w, h} to {0, 0} 38 | end try 39 | 40 | tell application "System Events" 41 | tell process myFrontMost 42 | try 43 | set {{w, h}} to size of drawer of window 1 44 | on error 45 | set {w, h} to {0, 0} 46 | end try 47 | set position of window 1 to {((screen_width - windowWidth) / 2), ((screen_height - windowHeight) / 2.0) - desktopTop} 48 | set size of window 1 to {windowWidth -w, windowHeight} 49 | end tell 50 | end tell -------------------------------------------------------------------------------- /test/fixtures/Foo.sml: -------------------------------------------------------------------------------- 1 | 2 | structure LazyBase:> LAZY_BASE = 3 | struct 4 | type 'a lazy = unit -> 'a 5 | 6 | exception Undefined 7 | 8 | fun delay f = f 9 | 10 | fun force f = f() 11 | 12 | val undefined = fn () => raise Undefined 13 | end 14 | 15 | structure LazyMemoBase:> LAZY_BASE = 16 | struct 17 | 18 | datatype 'a susp = NotYet of unit -> 'a 19 | | Done of 'a 20 | 21 | type 'a lazy = unit -> 'a susp ref 22 | 23 | exception Undefined 24 | 25 | fun delay f = 26 | let 27 | val r = ref (NotYet f) 28 | in 29 | fn () => r 30 | end 31 | 32 | fun force f = 33 | case f() of 34 | ref (Done x) => x 35 | | r as ref (NotYet f') => 36 | let 37 | val a = f'() 38 | in 39 | r := Done a 40 | ; a 41 | end 42 | 43 | val undefined = fn () => raise Undefined 44 | end 45 | 46 | functor LazyFn(B: LAZY_BASE): LAZY' = 47 | struct 48 | 49 | open B 50 | 51 | fun inject x = delay (fn () => x) 52 | 53 | fun isUndefined x = 54 | (ignore (force x) 55 | ; false) 56 | handle Undefined => true 57 | 58 | fun toString f x = if isUndefined x then "_|_" else f (force x) 59 | 60 | fun eqBy p (x,y) = p(force x,force y) 61 | fun eq (x,y) = eqBy op= (x,y) 62 | fun compare p (x,y) = p(force x,force y) 63 | 64 | structure Ops = 65 | struct 66 | val ! = force 67 | val ? = inject 68 | end 69 | 70 | fun map f x = delay (fn () => f (force x)) 71 | 72 | end 73 | 74 | structure Lazy' = LazyFn(LazyBase) 75 | structure LazyMemo = LazyFn(LazyMemoBase) 76 | -------------------------------------------------------------------------------- /test/fixtures/git.deb: -------------------------------------------------------------------------------- 1 | git000644 000765 000024 00000000010 11631477457 011700 0ustar00joshstaff000000 000000 git.deb 2 | -------------------------------------------------------------------------------- /test/fixtures/Foo.ml: -------------------------------------------------------------------------------- 1 | (* 2 | Copyright © 2011 MLstate 3 | 4 | This file is part of OPA. 5 | 6 | OPA is free software: you can redistribute it and/or modify it under the 7 | terms of the GNU Affero General Public License, version 3, as published by 8 | the Free Software Foundation. 9 | 10 | OPA is distributed in the hope that it will be useful, but WITHOUT ANY 11 | WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 12 | FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for 13 | more details. 14 | 15 | You should have received a copy of the GNU Affero General Public License 16 | along with OPA. If not, see . 17 | *) 18 | (* 19 | @author Louis Gesbert 20 | **) 21 | 22 | type 'a t = ('a -> unit) -> unit 23 | 24 | module Ops = struct 25 | let (@>) f k = f k 26 | let (|>) x k = k x 27 | end 28 | open Ops 29 | 30 | module List = struct 31 | let rec map f l k = match l with 32 | | [] -> [] |> k 33 | | hd::tl -> f hd @> fun hd -> map f tl @> fun tl -> hd::tl |> k 34 | 35 | let rec fold f acc l k = match l with 36 | | [] -> acc |> k 37 | | hd::tl -> f acc hd @> fun acc -> fold f acc tl @> k 38 | end 39 | 40 | module Option = struct 41 | let rec map f opt k = match opt with 42 | | None -> None |> k 43 | | Some x -> f x @> fun x -> Some x |> k 44 | end 45 | 46 | module Lazy = struct 47 | type 'a t = { 48 | push : (unit -> unit) -> unit; 49 | mutable value : 'a option; 50 | mutable waiters : ('a -> unit) list; 51 | cps : ('a -> unit) -> unit; 52 | } 53 | 54 | let make push cps = { 55 | push = push; 56 | value = None; 57 | waiters = []; 58 | cps = cps; 59 | } 60 | 61 | let force l k = 62 | match l.value with 63 | | Some x -> x |> k 64 | | None when l.waiters != [] -> 65 | l.waiters <- k::l.waiters 66 | | None -> 67 | l.waiters <- k::l.waiters; 68 | l.cps 69 | @> function x -> 70 | Base.List.iter (fun k -> l.push (fun () -> k x)) l.waiters; 71 | l.value <- Some x; 72 | l.waiters <- [] 73 | 74 | let get_state cps = cps.value 75 | 76 | let lazy_from_val x = { 77 | push = (fun _ -> ()); 78 | value = Some x; 79 | waiters = []; 80 | cps = fun k -> k x; 81 | } 82 | end 83 | -------------------------------------------------------------------------------- /lib/linguist/mimes.yml: -------------------------------------------------------------------------------- 1 | # Additional types to add to MIME::Types 2 | # 3 | # MIME types are used to set the Content-Type of raw binary blobs. All text 4 | # blobs are served as text/plain regardless of their type to ensure they 5 | # open in the browser rather than downloading. 6 | # 7 | # The encoding helps determine whether a file should be treated as plain 8 | # text or binary. By default, a mime type's encoding is base64 (binary). 9 | # These types will show a "View Raw" link. To force a type to render as 10 | # plain text, set it to 8bit for UTF-8. text/* types will be treated as 11 | # text by default. 12 | # 13 | # @ : 14 | # 15 | # type - mediatype/subtype 16 | # extensions - comma seperated extension list 17 | # encoding - base64 (binary), 7bit (ASCII), 8bit (UTF-8), or 18 | # quoted-printable (Printable ASCII). 19 | # 20 | # Follows same format as mime-types data file 21 | # https://github.com/halostatue/mime-types/blob/master/lib/mime/types.rb.data 22 | # 23 | # Any additions or modifications (even trivial) should have corresponding 24 | # test change in `test/test_mime.rb`. 25 | 26 | # TODO: Lookup actual types 27 | application/octet-stream @a,blend,gem,graffle,ipa,lib,mcz,nib,o,ogv,otf,pfx,pigx,plgx,psd,sib,spl,sqlite3,swc,ucode,xpi 28 | 29 | # Please keep this list alphabetized 30 | application/java-archive @ear,war 31 | application/netcdf :8bit 32 | application/ogg @ogg 33 | application/postscript :base64 34 | application/vnd.adobe.air-application-installer-package+zip @air 35 | application/vnd.mozilla.xul+xml :8bit 36 | application/vnd.oasis.opendocument.presentation @odp 37 | application/vnd.oasis.opendocument.spreadsheet @ods 38 | application/vnd.oasis.opendocument.text @odt 39 | application/vnd.openofficeorg.extension @oxt 40 | application/vnd.openxmlformats-officedocument.presentationml.presentation @pptx 41 | application/x-chrome-extension @crx 42 | application/x-iwork-keynote-sffkey @key 43 | application/x-iwork-numbers-sffnumbers @numbers 44 | application/x-iwork-pages-sffpages @pages 45 | application/x-ms-xbap @xbap :8bit 46 | application/x-parrot-bytecode @pbc 47 | application/x-shockwave-flash @swf 48 | application/x-silverlight-app @xap 49 | application/x-supercollider @sc :8bit 50 | application/x-troff-ms :8bit 51 | application/x-wais-source :8bit 52 | application/xaml+xml @xaml :8bit 53 | image/x-icns @icns 54 | text/cache-manifest @manifest 55 | text/plain @cu,cxx 56 | text/x-nemerle @n 57 | text/x-nimrod @nim 58 | text/x-ocaml @ml,mli,mll,mly,sig,sml 59 | text/x-rust @rs,rc 60 | text/x-scheme @rkt,scm,sls,sps,ss 61 | -------------------------------------------------------------------------------- /test/fixtures/BCR2000.sc: -------------------------------------------------------------------------------- 1 | BCR2000 { 2 | var controls, 3 | controlBuses, 4 | rangedControlBuses, 5 | responders 6 | ; 7 | 8 | *new { 9 | ^super.new.init; 10 | } 11 | 12 | init { 13 | controls = Dictionary.new(108); 14 | controlBuses = Dictionary.new(108); 15 | rangedControlBuses = Dictionary.new(108); 16 | 17 | this.createCCResponders; 18 | } 19 | 20 | createCCResponders { 21 | responders = Array.fill(108, {|i| 22 | CCResponder({|src, chan, num, val| 23 | [src, chan, num, val].postln; 24 | 25 | // Write to controls 26 | controls.put(i + 1, val); 27 | 28 | // Write to bus (converted to scalar 0..1) 29 | controlBuses.put(i + 1, Bus.control(Server.default)); 30 | controlBuses.at(i + 1).value = val / 127; 31 | }, 32 | // Adjust values as/if needed 33 | nil, // src 34 | nil, // chan 35 | nil, // num 36 | nil // value 37 | ) 38 | }); 39 | } 40 | 41 | // Value from BCR 42 | at {arg controlNum; 43 | ^controls.at(controlNum) 44 | } 45 | 46 | // Convert to 0..1 47 | scalarAt {arg controlNum; 48 | ^controls.at(controlNum) / 127 49 | } 50 | 51 | // Get a bus 52 | busAt {arg controlNum; 53 | ^controlBuses.at(controlNum) 54 | } 55 | 56 | /* 57 | busRangeAt(arg controlNum, lo, hi; 58 | if (rangedControlBuses.at(controlNum).isNil, { 59 | rangedControlBuses.put(controlNum, Bus.control(Server.default)) 60 | }); 61 | 62 | // Left to right order of operations 63 | //rangedControlBuses.put( 64 | bus.value = hi - lo * controls.at(controlNum) + lo; 65 | 66 | ^bus 67 | } 68 | */ 69 | } 70 | 71 | /* Scratch 72 | Dictionary 73 | b = BCR2000(); 74 | b.at(4); 75 | b.scalarAt(4); 76 | b.controls[5].get; 77 | throw 78 | z = Dictionary.new(2); 79 | z.at(\1); 80 | Array.fill(10, {|i| i.postln;}) 81 | (2 + 3).asSymbol; 82 | 83 | 84 | SynthDef(\x, { 85 | arg amp = 0.01, 86 | freq = 1200, 87 | modDepth = 0.7, 88 | modFreq = 2 89 | ; 90 | 91 | var 92 | carrier, 93 | modulator 94 | ; 95 | 96 | modulator = SinOsc.ar(modFreq, mul: modDepth); 97 | carrier = Saw.ar(freq, add: modulator, mul: amp); 98 | 99 | Out.ar([0,1], carrier) 100 | }).store; 101 | 102 | 103 | x = Synth(\x); 104 | x.set(\modDepth, 1); 105 | x.set(\modFreq, 64); 106 | 107 | x.map(\modFreq, b.busAt( 108 | 109 | 110 | 111 | ControlSpec 112 | */ 113 | 114 | 115 | -------------------------------------------------------------------------------- /lib/linguist/repository.rb: -------------------------------------------------------------------------------- 1 | require 'linguist/file_blob' 2 | 3 | module Linguist 4 | # A Repository is an abstraction of a Grit::Repo or a basic file 5 | # system tree. It holds a list of paths pointing to Blobish objects. 6 | # 7 | # Its primary purpose is for gathering language statistics across 8 | # the entire project. 9 | class Repository 10 | # Public: Initialize a new Repository from a File directory 11 | # 12 | # base_path - A path String 13 | # 14 | # Returns a Repository 15 | def self.from_directory(base_path) 16 | new Dir["#{base_path}/**/*"]. 17 | select { |f| File.file?(f) }. 18 | map { |path| FileBlob.new(path, base_path) } 19 | end 20 | 21 | # Public: Initialize a new Repository 22 | # 23 | # enum - Enumerator that responds to `each` and 24 | # yields Blob objects 25 | # 26 | # Returns a Repository 27 | def initialize(enum) 28 | @enum = enum 29 | @computed_stats = false 30 | @language = @size = nil 31 | @sizes = Hash.new { 0 } 32 | end 33 | 34 | # Public: Returns a breakdown of language stats. 35 | # 36 | # Examples 37 | # 38 | # # => { Language['Ruby'] => 46319, 39 | # Language['JavaScript'] => 258 } 40 | # 41 | # Returns a Hash of Language keys and Integer size values. 42 | def languages 43 | compute_stats 44 | @sizes 45 | end 46 | 47 | # Public: Get primary Language of repository. 48 | # 49 | # Returns a Language 50 | def language 51 | compute_stats 52 | @language 53 | end 54 | 55 | # Public: Get the total size of the repository. 56 | # 57 | # Returns a byte size Integer 58 | def size 59 | compute_stats 60 | @size 61 | end 62 | 63 | # Internal: Compute language breakdown for each blob in the Repository. 64 | # 65 | # Returns nothing 66 | def compute_stats 67 | return if @computed_stats 68 | 69 | @enum.each do |blob| 70 | # Skip vendored or generated blobs 71 | next if blob.vendored? || blob.generated? || blob.language.nil? 72 | 73 | # Only include programming languages 74 | if blob.language.type == :programming 75 | @sizes[blob.language.group] += blob.size 76 | end 77 | end 78 | 79 | # Compute total size 80 | @size = @sizes.inject(0) { |s,(k,v)| s + v } 81 | 82 | # Get primary language 83 | if primary = @sizes.max_by { |(_, size)| size } 84 | @language = primary[0] 85 | end 86 | 87 | @computed_stats = true 88 | 89 | nil 90 | end 91 | end 92 | end 93 | -------------------------------------------------------------------------------- /test/test_pathname.rb: -------------------------------------------------------------------------------- 1 | require 'linguist/pathname' 2 | 3 | require 'test/unit' 4 | require 'pygments' 5 | 6 | class TestPathname < Test::Unit::TestCase 7 | include Linguist 8 | 9 | Lexer = Pygments::Lexer 10 | 11 | def test_to_s 12 | assert_equal "file.rb", Pathname.new("file.rb").to_s 13 | end 14 | 15 | def test_basename 16 | assert_equal 'file.rb', Pathname.new("file.rb").basename 17 | assert_equal 'file.rb', Pathname.new("./file.rb").basename 18 | assert_equal 'file.rb', Pathname.new("sub/dir/file.rb").basename 19 | assert_equal '.profile', Pathname.new(".profile").basename 20 | end 21 | 22 | def test_extname 23 | assert_equal '.rb', Pathname.new("file.rb").extname 24 | assert_equal '.rb', Pathname.new("./file.rb").extname 25 | assert_equal '.rb', Pathname.new("sub/dir/file.rb").extname 26 | assert_equal '', Pathname.new(".profile").extname 27 | end 28 | 29 | def test_language 30 | assert_nil Pathname.new(".rb").language 31 | 32 | assert_equal Language['Ruby'], Pathname.new("file.rb").language 33 | assert_equal Language['Ruby'], Pathname.new("./file.rb").language 34 | assert_equal Language['Ruby'], Pathname.new("sub/dir/file.rb").language 35 | 36 | assert_equal Language['Ruby'], Pathname.new("Rakefile").language 37 | assert_equal Language['Ruby'], Pathname.new("vendor/Rakefile").language 38 | assert_equal Language['Ruby'], Pathname.new("./Rakefile").language 39 | 40 | assert_equal Language['Gentoo Ebuild'], Pathname.new("file.ebuild").language 41 | assert_equal Language['Python'], Pathname.new("itty.py").language 42 | assert_equal Language['Nu'], Pathname.new("itty.nu").language 43 | 44 | assert_nil Pathname.new("defun.kt").language 45 | end 46 | 47 | def test_lexer 48 | assert_equal Lexer['Ruby'], Pathname.new("file.rb").lexer 49 | assert_equal Lexer['Ruby'], Pathname.new("Rakefile").lexer 50 | assert_equal Lexer['Bash'], Pathname.new("file.ebuild").lexer 51 | assert_equal Lexer['Python'], Pathname.new("itty.py").lexer 52 | assert_equal Lexer['Scheme'], Pathname.new("itty.nu").lexer 53 | assert_equal Lexer['Text only'], Pathname.new("defun.kt").lexer 54 | end 55 | 56 | def test_mime_type 57 | assert_equal 'application/ruby', Pathname.new("file.rb").mime_type 58 | assert_equal 'application/javascript', Pathname.new("file.js").mime_type 59 | assert_equal 'application/python', Pathname.new("itty.py").mime_type 60 | assert_equal 'text/plain', Pathname.new("defun.kt").mime_type 61 | end 62 | 63 | def test_content_type 64 | assert_equal 'text/plain; charset=utf8', Pathname.new("file.txt").content_type 65 | assert_equal 'text/plain; charset=utf8', Pathname.new("file.rb").content_type 66 | assert_equal 'image/png', Pathname.new("octocat.png").content_type 67 | end 68 | end 69 | -------------------------------------------------------------------------------- /test/fixtures/xproc.xqm: -------------------------------------------------------------------------------- 1 | (: ------------------------------------------------------------------------------------- 2 | 3 | xproc.xqm - core xqm contains entry points, primary eval-step function and 4 | control functions. 5 | 6 | ---------------------------------------------------------------------------------------- :) 7 | xquery version "3.0" encoding "UTF-8"; 8 | 9 | module namespace xproc = "http://xproc.net/xproc"; 10 | 11 | (: declare namespaces :) 12 | declare namespace p="http://www.w3.org/ns/xproc"; 13 | declare namespace c="http://www.w3.org/ns/xproc-step"; 14 | declare namespace err="http://www.w3.org/ns/xproc-error"; 15 | 16 | (: module imports :) 17 | (: import module namespace util = "http://xproc.net/xproc/util" at "util1.xqm"; :) 18 | import module namespace const = "http://xproc.net/xproc/const" at "const.xqm"; 19 | import module namespace parse = "http://xproc.net/xproc/parse" at "parse.xqm"; 20 | import module namespace u = "http://xproc.net/xproc/util" at "util.xqm"; 21 | 22 | (: declare options :) 23 | declare boundary-space preserve; 24 | declare option saxon:output "indent=yes"; 25 | 26 | (: declare functions :) 27 | declare variable $xproc:run-step := xproc:run#6; 28 | declare variable $xproc:parse-and-eval := (); 29 | declare variable $xproc:declare-step := (); 30 | declare variable $xproc:choose := (); 31 | declare variable $xproc:try := (); 32 | declare variable $xproc:catch := (); 33 | declare variable $xproc:group := (); 34 | declare variable $xproc:for-each := (); 35 | declare variable $xproc:viewport := (); 36 | declare variable $xproc:library := (); 37 | declare variable $xproc:pipeline := (); 38 | declare variable $xproc:variable := (); 39 | 40 | 41 | (: list all declared namespaces :) 42 | (: -------------------------------------------------------------------------- :) 43 | declare function xproc:enum-namespaces($pipeline){ 44 | (: -------------------------------------------------------------------------- :) 45 | {u:enum-ns({$pipeline})} 46 | }; 47 | 48 | (: entry point :) 49 | (: -------------------------------------------------------------------------- :) 50 | declare function xproc:run($pipeline,$stdin,$dflag,$tflag,$bindings,$options){ 51 | (: -------------------------------------------------------------------------- :) 52 | 53 | (: STEP I: preprocess :) 54 | let $validate := () 55 | let $namespaces := xproc:enum-namespaces($pipeline) 56 | let $parse := parse:explicit-bindings( parse:AST(parse:explicit-name(parse:explicit-type($pipeline)))) 57 | let $ast := element p:declare-step {$parse/@*, 58 | parse:pipeline-step-sort( $parse/*, () ) 59 | } 60 | 61 | (: STEP II: eval AST :) 62 | let $eval_result := () 63 | 64 | (: STEP III: serialize and return results :) 65 | let $serialized_result := $pipeline 66 | 67 | return 68 | $serialized_result 69 | }; 70 | 71 | -------------------------------------------------------------------------------- /lib/linguist/pathname.rb: -------------------------------------------------------------------------------- 1 | require 'linguist/language' 2 | require 'linguist/mime' 3 | require 'pygments' 4 | 5 | module Linguist 6 | # Similar to ::Pathname, Linguist::Pathname wraps a path string and 7 | # provides helpful query methods. Its useful when you only have a 8 | # filename but not a blob and need to figure out the language of the file. 9 | class Pathname 10 | # Public: Initialize a Pathname 11 | # 12 | # path - A filename String. The file may or maybe actually exist. 13 | # 14 | # Returns a Pathname. 15 | def initialize(path) 16 | @path = path 17 | end 18 | 19 | # Public: Get the basename of the path 20 | # 21 | # Examples 22 | # 23 | # Pathname.new('sub/dir/file.rb').basename 24 | # # => 'file.rb' 25 | # 26 | # Returns a String. 27 | def basename 28 | File.basename(@path) 29 | end 30 | 31 | # Public: Get the extname of the path 32 | # 33 | # Examples 34 | # 35 | # Pathname.new('.rb').extname 36 | # # => '.rb' 37 | # 38 | # Pathname.new('file.rb').extname 39 | # # => '.rb' 40 | # 41 | # Returns a String. 42 | def extname 43 | File.extname(@path) 44 | end 45 | 46 | # Public: Get the language of the path 47 | # 48 | # The path extension name is the only heuristic used to detect the 49 | # language name. 50 | # 51 | # Examples 52 | # 53 | # Pathname.new('file.rb').language 54 | # # => Language['Ruby'] 55 | # 56 | # Returns a Language or nil if none was found. 57 | def language 58 | @language ||= Language.find_by_filename(@path) 59 | end 60 | 61 | # Internal: Get the lexer of the path 62 | # 63 | # Returns a Lexer. 64 | def lexer 65 | language ? language.lexer : Pygments::Lexer.find_by_name('Text only') 66 | end 67 | 68 | # Public: Get the mime type 69 | # 70 | # Examples 71 | # 72 | # Pathname.new('index.html').mime_type 73 | # # => 'text/html' 74 | # 75 | # Returns a mime type String. 76 | def mime_type 77 | @mime_type ||= Mime.mime_for(extname) 78 | end 79 | 80 | # Public: Get the Content-Type header 81 | # 82 | # This value is used when serving raw blobs. 83 | # 84 | # Examples 85 | # 86 | # Pathname.new('file.txt').content_type 87 | # # => 'text/plain; charset=utf-8' 88 | # 89 | # Returns a content type String. 90 | def content_type 91 | @content_type ||= binary? ? mime_type : 'text/plain; charset=utf8' 92 | end 93 | 94 | # Public: Is the path binary? 95 | # 96 | # Return true or false 97 | def binary? 98 | @binary ||= Mime.binary?(extname) 99 | end 100 | 101 | # Public: Return self as String 102 | # 103 | # Returns a String 104 | def to_s 105 | @path.dup 106 | end 107 | 108 | def eql?(other) 109 | other.is_a?(self.class) && @path == other.to_s 110 | end 111 | alias_method :==, :eql? 112 | end 113 | end 114 | -------------------------------------------------------------------------------- /test/fixtures/Person.gs: -------------------------------------------------------------------------------- 1 | package example 2 | 3 | uses java.util.* 4 | 5 | uses java.io.File 6 | 7 | class Person extends Contact implements IEmailable { 8 | 9 | var _name : String 10 | var _age : Integer as Age 11 | var _relationship : Relationship as readonly RelationshipOfPerson 12 | 13 | delegate _emailHelper represents IEmailable 14 | 15 | enum Relationship { 16 | FRIEND, 17 | FAMILY, 18 | BUSINESS_CONTACT 19 | } 20 | 21 | // Map of names to people 22 | static var ALL_PEOPLE = new HashMap() 23 | 24 | /* Constructs a new Person */ 25 | construct( name : String, age : Integer, relationship : Relationship ) { 26 | _name = name 27 | _age = age 28 | _relationship = relationship 29 | _emailHelper = new EmailHelper( this ) 30 | } 31 | 32 | property get Name():String{ 33 | return _name 34 | } 35 | 36 | property set Name(name : String){ 37 | _name = name 38 | } 39 | 40 | /* Implement IEmailable#getEmailName() */ 41 | override function getEmailName():String{ 42 | return Name 43 | } 44 | 45 | function incrementAge() { 46 | _age++ 47 | } 48 | 49 | @Deprecated 50 | function printPersonInfo() { 51 | print( "Person { Name : ${Name}, Age : ${Age}, Relationship : ${RelationshipOfPerson} }" ) 52 | } 53 | 54 | static function addPerson(p : Person){ 55 | if(ALL_PEOPLE.containsKey(p?.Name)) { 56 | throw new IllegalArgumentException( "There is already someone named '${p.Name}'." ) 57 | } 58 | ALL_PEOPLE[p.Name] = p 59 | } 60 | 61 | static function addAllPeople( contacts : List ) { 62 | for( contact in contacts ) { 63 | if( contact typeis Person and not ALL_PEOPLE.containsKey( contact.Name )) { 64 | addPerson( contact ) 65 | } 66 | } 67 | } 68 | 69 | static function getAllPeopleOlderThanNOrderedByName( age : int ) { 70 | var allPeople = ALL_PEOPLE.Values 71 | 72 | return allPeople.where( \ p -> p.Age > age ).orderBy( \ p -> p.Name ) 73 | } 74 | 75 | static function loadPersonFromDB( id : Integer ) { 76 | using( var conn = DBConnectionManager.getConnection(), 77 | var stmt = conn.prepareStatement( "SELECT name, age, relationship FROM PEOPLE WHERE ID=?") ){ 78 | 79 | stmt.setInt( 0, 0 ) 80 | var result = stmt.executeQuery() 81 | if( result.next() ) { 82 | addPerson( new Person( result.getString( "name" ), 83 | result.getInt( "age" ), 84 | Relationship.valueOf( result.getString( "relationship" ) ) ) ) 85 | 86 | } 87 | } 88 | } 89 | 90 | /* Loads in people from a CSV */ 91 | static function loadFromFile( file : File ) { 92 | file.eachLine( \ line -> { 93 | if( line.HasContent ) { 94 | addPerson( line.toPerson() ) 95 | } 96 | }) 97 | } 98 | 99 | /* Save people to a CSV */ 100 | static function saveToFile( file : File ) { 101 | using( var writer = new FileWriter( file ) ) { 102 | print( PersonCSVTemplate.renderToString( ALL_PEOPLE.Values ) ) 103 | PersonCSVTemplate.render( writer, ALL_PEOPLE.Values ) 104 | } 105 | } 106 | } -------------------------------------------------------------------------------- /lib/linguist/mime.rb: -------------------------------------------------------------------------------- 1 | require 'mime/types' 2 | require 'yaml' 3 | 4 | # Register additional mime type extensions 5 | # 6 | # Follows same format as mime-types data file 7 | # https://github.com/halostatue/mime-types/blob/master/lib/mime/types.rb.data 8 | File.read(File.expand_path("../mimes.yml", __FILE__)).lines.each do |line| 9 | # Regexp was cargo culted from mime-types lib 10 | next unless line =~ %r{^ 11 | #{MIME::Type::MEDIA_TYPE_RE} 12 | (?:\s@([^\s]+))? 13 | (?:\s:(#{MIME::Type::ENCODING_RE}))? 14 | }x 15 | 16 | mediatype = $1 17 | subtype = $2 18 | extensions = $3 19 | encoding = $4 20 | 21 | # Lookup existing mime type 22 | mime_type = MIME::Types["#{mediatype}/#{subtype}"].first || 23 | # Or create a new instance 24 | MIME::Type.new("#{mediatype}/#{subtype}") 25 | 26 | if extensions 27 | extensions.split(/,/).each do |extension| 28 | mime_type.extensions << extension 29 | end 30 | end 31 | 32 | if encoding 33 | mime_type.encoding = encoding 34 | end 35 | 36 | # Kind of hacky, but we need to reindex the mime type after making changes 37 | MIME::Types.add_type_variant(mime_type) 38 | MIME::Types.index_extensions(mime_type) 39 | end 40 | 41 | module Linguist 42 | module Mime 43 | # Internal: Look up mime type for extension. 44 | # 45 | # ext - The extension String. May include leading "." 46 | # 47 | # Examples 48 | # 49 | # Mime.mime_for('.html') 50 | # # => 'text/html' 51 | # 52 | # Mime.mime_for('txt') 53 | # # => 'text/plain' 54 | # 55 | # Return mime type String otherwise falls back to 'text/plain'. 56 | def self.mime_for(ext) 57 | mime_type = lookup_mime_type_for(ext) 58 | mime_type ? mime_type.simplified : 'text/plain' 59 | end 60 | 61 | # Internal: Determine if extension or mime type is binary. 62 | # 63 | # ext_or_mime_type - A file extension ".exe" or 64 | # mime type "application/octet-stream". 65 | # 66 | # Returns true or false 67 | def self.binary?(ext_or_mime_type) 68 | mime_type = lookup_mime_type_for(ext_or_mime_type) 69 | mime_type ? mime_type.binary? : false 70 | end 71 | 72 | # Internal: Determine if extension or mime type is plain text. 73 | # 74 | # ext_or_mime_type - A file extension ".txt" or mime type "text/plain". 75 | # 76 | # Returns true or false 77 | def self.text?(ext_or_mime_type) 78 | !binary?(ext_or_mime_type) 79 | end 80 | 81 | # Internal: Lookup mime type for extension or mime type 82 | # 83 | # ext_or_mime_type - A file extension ".txt" or mime type "text/plain". 84 | # 85 | # Returns a MIME::Type 86 | def self.lookup_mime_type_for(ext_or_mime_type) 87 | ext_or_mime_type ||= '' 88 | 89 | if ext_or_mime_type =~ /\w+\/\w+/ 90 | guesses = ::MIME::Types[ext_or_mime_type] 91 | else 92 | guesses = ::MIME::Types.type_for(ext_or_mime_type) 93 | end 94 | 95 | # Prefer text mime types over binary 96 | guesses.detect { |type| type.ascii? } || 97 | 98 | # Otherwise use the first guess 99 | guesses.first 100 | end 101 | end 102 | end 103 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Linguist 2 | 3 | We use this library at GitHub to detect blob languages, highlight code, ignore binary files, suppress generated files in diffs and generate language breakdown graphs. 4 | 5 | ## Features 6 | 7 | ### Language detection 8 | 9 | Linguist defines the list of all languages known to GitHub in a [yaml file](https://github.com/github/linguist/blob/master/lib/linguist/languages.yml). In order for a file to be highlighted, a language and lexer must be defined there. 10 | 11 | Most languages are detected by their file extension. This is the fastest and most common situation. For script files, which are usually extensionless, we do "deep content inspection"™ and check the shebang of the file. Checking the file's contents may also be used for disambiguating languages. C, C++ and Obj-C all use `.h` files. Looking for common keywords, we are usually able to guess the correct language. 12 | 13 | In the actual GitHub app we deal with `Grit::Blob` objects. For testing, there is a simple `FileBlob` API. 14 | 15 | Linguist::FileBlob.new("lib/linguist.rb").language.name #=> "Ruby" 16 | 17 | Linguist::FileBlob.new("bin/linguist").language.name #=> "Ruby" 18 | 19 | See [lib/linguist/language.rb](https://github.com/github/linguist/blob/master/lib/linguist/language.rb) and [lib/linguist/languages.yml](https://github.com/github/linguist/blob/master/lib/linguist/languages.yml). 20 | 21 | ### Syntax Highlighting 22 | 23 | The actual syntax highlighting is handled by our Pygments wrapper, [Albino](https://github.com/github/albino). Linguist provides a [Lexer abstraction](https://github.com/github/linguist/blob/master/lib/linguist/lexer.rb) that determines which highlighter should be used on a file. 24 | 25 | We typically run on a prerelease version of Pygments to get early access to new lexers. The [lexers.yml](https://github.com/github/linguist/blob/master/lib/linguist/lexers.yml) file is a dump of the lexers we have available on our server. If there is a new lexer in pygments-main not on the list, [open an issue](https://github.com/github/linguist/issues) and we'll try to upgrade it soon. 26 | 27 | ### MIME type detection 28 | 29 | Most of the MIME types handling is done by the Ruby [mime-types gem](https://github.com/halostatue/mime-types/blob/master/lib/mime/types.rb.data). But we have our own list of additions and overrides. To add or modify this list, see [lib/linguist/mimes.yml](https://github.com/github/linguist/blob/master/lib/linguist/mimes.yml). 30 | 31 | MIME types are used to set the Content-Type of raw binary blobs which are served from a special `raw.github.com` domain. However, all text blobs are served as `text/plain` regardless of their type to ensure they open in the browser rather than downloading. 32 | 33 | The MIME type also determines whether a blob is binary or plain text. So if you're seeing a blob that says "View Raw" and it is actually plain text, the mime type and encoding probably needs to be explicitly stated. 34 | 35 | Linguist::FileBlob.new("linguist.zip").binary? #=> true 36 | 37 | See [lib/linguist/mimes.yml](https://github.com/github/linguist/blob/master/lib/linguist/mimes.yml). 38 | 39 | ### Stats 40 | 41 | The [Language Graph](https://github.com/github/linguist/graphs/languages) is built by aggregating the languages of all repo's blobs. The top language in the graph determines the project's primary language. Collectively, these stats make up the [Top Languages](https://github.com/languages) page. 42 | 43 | The repository stats API can be used on a directory: 44 | 45 | project = Linguist::Repository.from_directory(".") 46 | project.language.name #=> "Ruby" 47 | project.languages #=> { "Ruby" => 0.98, 48 | "Shell" => 0.02 } 49 | 50 | These stats are also printed out by the binary. Try running `linguist` on itself: 51 | 52 | $ bundle exec linguist lib/ 53 | 100% Ruby 54 | 55 | #### Ignore vendored files 56 | 57 | Checking other code into your git repo is a common practice. But this often inflates your project's language stats and may even cause your project to be labeled as another language. We are able to identify some of these files and directories and exclude them. 58 | 59 | Linguist::FileBlob.new("vendor/plugins/foo.rb").vendored? # => true 60 | 61 | See [Linguist::BlobHelper#vendored?](https://github.com/github/linguist/blob/master/lib/linguist/blob_helper.rb) and [lib/linguist/vendor.yml](https://github.com/github/linguist/blob/master/lib/linguist/vendor.yml). 62 | 63 | #### Generated file detection 64 | 65 | Not all plain text files are true source files. Generated files like minified js and compiled CoffeeScript can be detected and excluded from language stats. As an extra bonus, these files are suppressed in Diffs. 66 | 67 | Linguist::FileBlob.new("underscore.min.js").generated? # => true 68 | 69 | See [Linguist::BlobHelper#generated?](https://github.com/github/linguist/blob/master/lib/linguist/blob_helper.rb). 70 | 71 | ## Installation 72 | 73 | To get it, clone the repo and run [Bundler](http://gembundler.com/) to install its dependencies. 74 | 75 | git clone https://github.com/github/linguist.git 76 | cd linguist/ 77 | bundle install 78 | 79 | To run the tests: 80 | 81 | bundle exec rake test 82 | 83 | *Since this code is specific to GitHub, is not published as a official rubygem.* 84 | 85 | ## Contributing 86 | 87 | 1. Fork it. 88 | 2. Create a branch (`git checkout -b detect-foo-language`) 89 | 3. Make your changes 90 | 4. Run the tests (`bundle install` then `bundle exec rake`) 91 | 5. Commit your changes (`git commit -am "Added detection for the new Foo language"`) 92 | 6. Push to the branch (`git push origin detect-foo-language`) 93 | 7. Create a [Pull Request](http://help.github.com/pull-requests/) from your branch. 94 | 8. Promote it. Get others to drop in and +1 it. 95 | -------------------------------------------------------------------------------- /test/fixtures/build.sbt: -------------------------------------------------------------------------------- 1 | // set the name of the project 2 | name := "My Project" 3 | 4 | version := "1.0" 5 | 6 | organization := "org.myproject" 7 | 8 | // add a test dependency on ScalaCheck 9 | libraryDependencies += "org.scala-tools.testing" %% "scalacheck" % "1.8" % "test" 10 | 11 | // add compile dependencies on some dispatch modules 12 | libraryDependencies ++= Seq( 13 | "net.databinder" %% "dispatch-meetup" % "0.7.8", 14 | "net.databinder" %% "dispatch-twitter" % "0.7.8" 15 | ) 16 | 17 | // Set a dependency based partially on a val. 18 | { 19 | val libosmVersion = "2.5.2-RC1" 20 | libraryDependencies += "net.sf.travelingsales" % "osmlib" % libosmVersion from "http://downloads.sourceforge.net/project/travelingsales/libosm/"+libosmVersion+"/libosm-"+libosmVersion+".jar" 21 | } 22 | 23 | // reduce the maximum number of errors shown by the Scala compiler 24 | maxErrors := 20 25 | 26 | // increase the time between polling for file changes when using continuous execution 27 | pollInterval := 1000 28 | 29 | // append several options to the list of options passed to the Java compiler 30 | javacOptions ++= Seq("-source", "1.5", "-target", "1.5") 31 | 32 | // append -deprecation to the options passed to the Scala compiler 33 | scalacOptions += "-deprecation" 34 | 35 | // set the Scala version used for the project 36 | scalaVersion := "2.9.0-SNAPSHOT" 37 | 38 | // define the statements initially evaluated when entering 'console', 'console-quick', or 'console-project' 39 | initialCommands := """ 40 | import System.{currentTimeMillis => now} 41 | def time[T](f: => T): T = { 42 | val start = now 43 | try { f } finally { println("Elapsed: " + (now - start)/1000.0 + " s") } 44 | } 45 | """ 46 | 47 | // set the initial commands when entering 'console' only 48 | initialCommands in console := "import myproject._" 49 | 50 | // set the main class for packaging the main jar 51 | // 'run' will still auto-detect and prompt 52 | // change Compile to Test to set it for the test jar 53 | mainClass in (Compile, packageBin) := Some("myproject.MyMain") 54 | 55 | // set the main class for the main 'run' task 56 | // change Compile to Test to set it for 'test:run' 57 | mainClass in (Compile, run) := Some("myproject.MyMain") 58 | 59 | // add /input to the files that '~' triggers on 60 | watchSources <+= baseDirectory map { _ / "input" } 61 | 62 | // add a maven-style repository 63 | resolvers += "name" at "url" 64 | 65 | // add a sequence of maven-style repositories 66 | resolvers ++= Seq("name" at "url") 67 | 68 | // define the repository to publish to 69 | publishTo := Some("name" at "url") 70 | 71 | // set Ivy logging to be at the highest level 72 | ivyLoggingLevel := UpdateLogging.Full 73 | 74 | // disable updating dynamic revisions (including -SNAPSHOT versions) 75 | offline := true 76 | 77 | // set the prompt (for this build) to include the project id. 78 | shellPrompt in ThisBuild := { state => Project.extract(state).currentRef.project + "> " } 79 | 80 | // set the prompt (for the current project) to include the username 81 | shellPrompt := { state => System.getProperty("user.name") + "> " } 82 | 83 | // disable printing timing information, but still print [success] 84 | showTiming := false 85 | 86 | // disable printing a message indicating the success or failure of running a task 87 | showSuccess := false 88 | 89 | // change the format used for printing task completion time 90 | timingFormat := { 91 | import java.text.DateFormat 92 | DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT) 93 | } 94 | 95 | // disable using the Scala version in output paths and artifacts 96 | crossPaths := false 97 | 98 | // fork a new JVM for 'run' and 'test:run' 99 | fork := true 100 | 101 | // fork a new JVM for 'test:run', but not 'run' 102 | fork in Test := true 103 | 104 | // add a JVM option to use when forking a JVM for 'run' 105 | javaOptions += "-Xmx2G" 106 | 107 | // only use a single thread for building 108 | parallelExecution := false 109 | 110 | // Execute tests in the current project serially 111 | // Tests from other projects may still run concurrently. 112 | parallelExecution in Test := false 113 | 114 | // set the location of the JDK to use for compiling Java code. 115 | // if 'fork' is true, this is used for 'run' as well 116 | javaHome := Some(file("/usr/lib/jvm/sun-jdk-1.6")) 117 | 118 | // Use Scala from a directory on the filesystem instead of retrieving from a repository 119 | scalaHome := Some(file("/home/user/scala/trunk/")) 120 | 121 | // don't aggregate clean (See FullConfiguration for aggregation details) 122 | aggregate in clean := false 123 | 124 | // only show warnings and errors on the screen for compilations. 125 | // this applies to both test:compile and compile and is Info by default 126 | logLevel in compile := Level.Warn 127 | 128 | // only show warnings and errors on the screen for all tasks (the default is Info) 129 | // individual tasks can then be more verbose using the previous setting 130 | logLevel := Level.Warn 131 | 132 | // only store messages at info and above (the default is Debug) 133 | // this is the logging level for replaying logging with 'last' 134 | persistLogLevel := Level.Debug 135 | 136 | // only show 10 lines of stack traces 137 | traceLevel := 10 138 | 139 | // only show stack traces up to the first sbt stack frame 140 | traceLevel := 0 141 | 142 | // add SWT to the unmanaged classpath 143 | unmanagedJars in Compile += file("/usr/share/java/swt.jar") 144 | 145 | // publish test jar, sources, and docs 146 | publishArtifact in Test := true 147 | 148 | // disable publishing of main docs 149 | publishArtifact in (Compile, packageDoc) := false 150 | 151 | // change the classifier for the docs artifact 152 | artifactClassifier in packageDoc := Some("doc") 153 | 154 | // Copy all managed dependencies to /lib_managed/ 155 | // This is essentially a project-local cache and is different 156 | // from the lib_managed/ in sbt 0.7.x. There is only one 157 | // lib_managed/ in the build root (not per-project). 158 | retrieveManaged := true 159 | 160 | /* Specify a file containing credentials for publishing. The format is: 161 | realm=Sonatype Nexus Repository Manager 162 | host=nexus.scala-tools.org 163 | user=admin 164 | password=admin123 165 | */ 166 | credentials += Credentials(Path.userHome / ".ivy2" / ".credentials") 167 | 168 | // Directly specify credentials for publishing. 169 | credentials += Credentials("Sonatype Nexus Repository Manager", "nexus.scala-tools.org", "admin", "admin123") 170 | -------------------------------------------------------------------------------- /test/fixtures/drupal.module: -------------------------------------------------------------------------------- 1 | ' . t('About') . ''; 16 | $output .= '

' . t('The PHP filter module adds a PHP filter to your site, for use with text formats. This filter adds the ability to execute PHP code in any text field that uses a text format (such as the body of a content item or the text of a comment). PHP is a general-purpose scripting language widely-used for web development, and is the language with which Drupal has been developed. For more information, see the online handbook entry for the PHP filter module.', array('@filter' => url('admin/help/filter'), '@php-net' => 'http://www.php.net', '@php' => 'http://drupal.org/handbook/modules/php/')) . '

'; 17 | $output .= '

' . t('Uses') . '

'; 18 | $output .= '
'; 19 | $output .= '
' . t('Enabling execution of PHP in text fields') . '
'; 20 | $output .= '
' . t('The PHP filter module allows users with the proper permissions to include custom PHP code that will get executed when pages of your site are processed. While this is a powerful and flexible feature if used by a trusted user with PHP experience, it is a significant and dangerous security risk in the hands of a malicious or inexperienced user. Even a trusted user may accidentally compromise the site by entering malformed or incorrect PHP code. Only the most trusted users should be granted permission to use the PHP filter, and all PHP code added through the PHP filter should be carefully examined before use. Example PHP snippets can be found on Drupal.org.', array('@php-snippets' => url('http://drupal.org/handbook/customization/php-snippets'))) . '
'; 21 | $output .= '
'; 22 | return $output; 23 | } 24 | } 25 | 26 | /** 27 | * Implements hook_permission(). 28 | */ 29 | function php_permission() { 30 | return array( 31 | 'use PHP for settings' => array( 32 | 'title' => t('Use PHP for settings'), 33 | 'restrict access' => TRUE, 34 | ), 35 | ); 36 | } 37 | 38 | /** 39 | * Evaluate a string of PHP code. 40 | * 41 | * This is a wrapper around PHP's eval(). It uses output buffering to capture both 42 | * returned and printed text. Unlike eval(), we require code to be surrounded by 43 | * tags; in other words, we evaluate the code as if it were a stand-alone 44 | * PHP file. 45 | * 46 | * Using this wrapper also ensures that the PHP code which is evaluated can not 47 | * overwrite any variables in the calling code, unlike a regular eval() call. 48 | * 49 | * @param $code 50 | * The code to evaluate. 51 | * @return 52 | * A string containing the printed output of the code, followed by the returned 53 | * output of the code. 54 | * 55 | * @ingroup php_wrappers 56 | */ 57 | function php_eval($code) { 58 | global $theme_path, $theme_info, $conf; 59 | 60 | // Store current theme path. 61 | $old_theme_path = $theme_path; 62 | 63 | // Restore theme_path to the theme, as long as php_eval() executes, 64 | // so code evaluated will not see the caller module as the current theme. 65 | // If theme info is not initialized get the path from theme_default. 66 | if (!isset($theme_info)) { 67 | $theme_path = drupal_get_path('theme', $conf['theme_default']); 68 | } 69 | else { 70 | $theme_path = dirname($theme_info->filename); 71 | } 72 | 73 | ob_start(); 74 | print eval('?>' . $code); 75 | $output = ob_get_contents(); 76 | ob_end_clean(); 77 | 78 | // Recover original theme path. 79 | $theme_path = $old_theme_path; 80 | 81 | return $output; 82 | } 83 | 84 | /** 85 | * Tips callback for php filter. 86 | */ 87 | function _php_filter_tips($filter, $format, $long = FALSE) { 88 | global $base_url; 89 | if ($long) { 90 | $output = '

' . t('Using custom PHP code') . '

'; 91 | $output .= '

' . t('Custom PHP code may be embedded in some types of site content, including posts and blocks. While embedding PHP code inside a post or block is a powerful and flexible feature when used by a trusted user with PHP experience, it is a significant and dangerous security risk when used improperly. Even a small mistake when posting PHP code may accidentally compromise your site.') . '

'; 92 | $output .= '

' . t('If you are unfamiliar with PHP, SQL, or Drupal, avoid using custom PHP code within posts. Experimenting with PHP may corrupt your database, render your site inoperable, or significantly compromise security.') . '

'; 93 | $output .= '

' . t('Notes:') . '

'; 94 | $output .= '
  • ' . t('Remember to double-check each line for syntax and logic errors before saving.') . '
  • '; 95 | $output .= '
  • ' . t('Statements must be correctly terminated with semicolons.') . '
  • '; 96 | $output .= '
  • ' . t('Global variables used within your PHP code retain their values after your script executes.') . '
  • '; 97 | $output .= '
  • ' . t('register_globals is turned off. If you need to use forms, understand and use the functions in the Drupal Form API.', array('@formapi' => url('http://api.drupal.org/api/group/form_api/7'))) . '
  • '; 98 | $output .= '
  • ' . t('Use a print or return statement in your code to output content.') . '
  • '; 99 | $output .= '
  • ' . t('Develop and test your PHP code using a separate test script and sample database before deploying on a production site.') . '
  • '; 100 | $output .= '
  • ' . t('Consider including your custom PHP code within a site-specific module or template.php file rather than embedding it directly into a post or block.') . '
  • '; 101 | $output .= '
  • ' . t('Be aware that the ability to embed PHP code within content is provided by the PHP Filter module. If this module is disabled or deleted, then blocks and posts with embedded PHP may display, rather than execute, the PHP code.') . '
'; 102 | $output .= '

' . t('A basic example: Creating a "Welcome" block that greets visitors with a simple message.') . '

'; 103 | $output .= '
  • ' . t('

    Add a custom block to your site, named "Welcome" . With its text format set to "PHP code" (or another format supporting PHP input), add the following in the Block body:

    104 |
    105 | print t(\'Welcome visitor! Thank you for visiting.\');
    106 | 
    ') . '
  • '; 107 | $output .= '
  • ' . t('

    To display the name of a registered user, use this instead:

    108 |
    109 | global $user;
    110 | if ($user->uid) {
    111 |   print t(\'Welcome @name! Thank you for visiting.\', array(\'@name\' => format_username($user)));
    112 | }
    113 | else {
    114 |   print t(\'Welcome visitor! Thank you for visiting.\');
    115 | }
    116 | 
    ') . '
'; 117 | $output .= '

' . t('Drupal.org offers some example PHP snippets, or you can create your own with some PHP experience and knowledge of the Drupal system.', array('@drupal' => url('http://drupal.org'), '@php-snippets' => url('http://drupal.org/handbook/customization/php-snippets'))) . '

'; 118 | return $output; 119 | } 120 | else { 121 | return t('You may post PHP code. You should include <?php ?> tags.'); 122 | } 123 | } 124 | 125 | /** 126 | * Implements hook_filter_info(). 127 | * 128 | * Provide PHP code filter. Use with care. 129 | */ 130 | function php_filter_info() { 131 | $filters['php_code'] = array( 132 | 'title' => t('PHP evaluator'), 133 | 'description' => t('Executes a piece of PHP code. The usage of this filter should be restricted to administrators only!'), 134 | 'process callback' => 'php_eval', 135 | 'tips callback' => '_php_filter_tips', 136 | 'cache' => FALSE, 137 | ); 138 | return $filters; 139 | } 140 | 141 | -------------------------------------------------------------------------------- /test/test_mime.rb: -------------------------------------------------------------------------------- 1 | require 'linguist/mime' 2 | 3 | require 'test/unit' 4 | 5 | class TestMime < Test::Unit::TestCase 6 | include Linguist 7 | 8 | def test_extension_lookup 9 | # Default to plain text if we have no idea. 10 | assert_equal 'text/plain', Mime.mime_for(nil) 11 | assert_equal 'text/plain', Mime.mime_for('') 12 | 13 | # Add an assertion to this list if you add/change any extensions 14 | # in mimes.yml. Its still useful to test even trivial cases since 15 | # MIME::Type's extension lookup may return multiple matches and we 16 | # only pick one of them. Please keep this list alphabetized. 17 | assert_equal 'application/chrome-extension', Mime.mime_for('.crx') 18 | assert_equal 'application/debian-package', Mime.mime_for('.deb') 19 | assert_equal 'application/iwork-keynote-sffkey', Mime.mime_for('.key') 20 | assert_equal 'application/iwork-numbers-sffnumbers', Mime.mime_for('.numbers') 21 | assert_equal 'application/iwork-pages-sffpages', Mime.mime_for('.pages') 22 | assert_equal 'application/java-archive', Mime.mime_for('.ear') 23 | assert_equal 'application/java-archive', Mime.mime_for('.jar') 24 | assert_equal 'application/java-archive', Mime.mime_for('.war') 25 | assert_equal 'application/javascript', Mime.mime_for('.js') 26 | assert_equal 'application/latex', Mime.mime_for('.latex') 27 | assert_equal 'application/ms-xbap', Mime.mime_for('.xbap') 28 | assert_equal 'application/octet-stream', Mime.mime_for('.dll') 29 | assert_equal 'application/octet-stream', Mime.mime_for('.dmg') 30 | assert_equal 'application/octet-stream', Mime.mime_for('.exe') 31 | assert_equal 'application/perl', Mime.mime_for('.pl') 32 | assert_equal 'application/perl', Mime.mime_for('.pm') 33 | assert_equal 'application/postscript', Mime.mime_for('.ai') 34 | assert_equal 'application/postscript', Mime.mime_for('.eps') 35 | assert_equal 'application/postscript', Mime.mime_for('.ps') 36 | assert_equal 'application/python', Mime.mime_for('.py') 37 | assert_equal 'application/ruby', Mime.mime_for('.rb') 38 | assert_equal 'application/sh', Mime.mime_for('.sh') 39 | assert_equal 'application/shockwave-flash', Mime.mime_for('.swf') 40 | assert_equal 'application/silverlight-app', Mime.mime_for('.xap') 41 | assert_equal 'application/supercollider', Mime.mime_for('.sc') 42 | assert_equal 'application/vnd.adobe.air-application-installer-package+zip', Mime.mime_for('.air') 43 | assert_equal 'application/vnd.oasis.opendocument.presentation', Mime.mime_for('.odp') 44 | assert_equal 'application/vnd.oasis.opendocument.spreadsheet', Mime.mime_for('.ods') 45 | assert_equal 'application/vnd.oasis.opendocument.text', Mime.mime_for('.odt') 46 | assert_equal 'application/vnd.openofficeorg.extension', Mime.mime_for('.oxt') 47 | assert_equal 'application/vnd.openxmlformats-officedocument.presentationml.presentation', Mime.mime_for('.pptx') 48 | assert_equal 'application/xaml+xml', Mime.mime_for('.xaml') 49 | assert_equal 'text/cache-manifest', Mime.mime_for('.manifest') 50 | assert_equal 'text/html', Mime.mime_for('.html') 51 | assert_equal 'text/nemerle', Mime.mime_for('.n') 52 | assert_equal 'text/nimrod', Mime.mime_for('.nim') 53 | assert_equal 'text/ocaml', Mime.mime_for('.ml') 54 | assert_equal 'text/ocaml', Mime.mime_for('.sig') 55 | assert_equal 'text/ocaml', Mime.mime_for('.sml') 56 | assert_equal 'text/plain', Mime.mime_for('.c') 57 | assert_equal 'text/plain', Mime.mime_for('.cc') 58 | assert_equal 'text/plain', Mime.mime_for('.cpp') 59 | assert_equal 'text/plain', Mime.mime_for('.cu') 60 | assert_equal 'text/plain', Mime.mime_for('.cxx') 61 | assert_equal 'text/plain', Mime.mime_for('.h') 62 | assert_equal 'text/plain', Mime.mime_for('.hh') 63 | assert_equal 'text/plain', Mime.mime_for('.hpp') 64 | assert_equal 'text/plain', Mime.mime_for('.kt') 65 | assert_equal 'text/rust', Mime.mime_for('.rs') 66 | assert_equal 'text/rust', Mime.mime_for('.rc') 67 | assert_equal 'video/quicktime', Mime.mime_for('.mov') 68 | end 69 | 70 | def test_binary 71 | assert Mime.binary?('application/octet-stream') 72 | 73 | # Add an assertion for any binary mime types added to mimes.yml. 74 | # Please keep this list alphabetized. 75 | assert Mime.binary?('application/java-archive') 76 | assert Mime.binary?('application/ogg') 77 | assert Mime.binary?('application/pdf') 78 | assert Mime.binary?('application/postscript') 79 | assert Mime.binary?('application/x-gzip') 80 | assert Mime.binary?('application/x-shockwave-flash') 81 | assert Mime.binary?('application/x-silverlight-app') 82 | assert Mime.binary?('application/zip') 83 | assert Mime.binary?('audio/mp4') 84 | assert Mime.binary?('image/gif') 85 | assert Mime.binary?('image/jpeg') 86 | assert Mime.binary?('image/png') 87 | 88 | # Legacy. Prefer testing mime types instead of extensions. 89 | assert Mime.binary?('.a') 90 | assert Mime.binary?('.air') 91 | assert Mime.binary?('.blend') 92 | assert Mime.binary?('.crx') 93 | assert Mime.binary?('.deb') 94 | assert Mime.binary?('.dmg') 95 | assert Mime.binary?('.exe') 96 | assert Mime.binary?('.gem') 97 | assert Mime.binary?('.graffle') 98 | assert Mime.binary?('.gz') 99 | assert Mime.binary?('.icns') 100 | assert Mime.binary?('.ipa') 101 | assert Mime.binary?('.key') 102 | assert Mime.binary?('.lib') 103 | assert Mime.binary?('.mcz') 104 | assert Mime.binary?('.mov') 105 | assert Mime.binary?('.mp3') 106 | assert Mime.binary?('.nib') 107 | assert Mime.binary?('.numbers') 108 | assert Mime.binary?('.o') 109 | assert Mime.binary?('.odp') 110 | assert Mime.binary?('.ods') 111 | assert Mime.binary?('.odt') 112 | assert Mime.binary?('.ogg') 113 | assert Mime.binary?('.ogv') 114 | assert Mime.binary?('.otf') 115 | assert Mime.binary?('.pages') 116 | assert Mime.binary?('.pfx') 117 | assert Mime.binary?('.pigx') 118 | assert Mime.binary?('.plgx') 119 | assert Mime.binary?('.pptx') 120 | assert Mime.binary?('.psd') 121 | assert Mime.binary?('.sib') 122 | assert Mime.binary?('.so') 123 | assert Mime.binary?('.spl') 124 | assert Mime.binary?('.sqlite3') 125 | assert Mime.binary?('.swc') 126 | assert Mime.binary?('.swf') 127 | assert Mime.binary?('.tar') 128 | assert Mime.binary?('.ucode') 129 | assert Mime.binary?('.xpi') 130 | assert Mime.binary?('.zip') 131 | end 132 | 133 | def test_text 134 | # By default, assume the plain text. 135 | assert Mime.text?(nil) 136 | assert Mime.text?('') 137 | 138 | assert Mime.text?('text/plain') 139 | 140 | # Add an assertion for any text mime types added to mimes.yml. 141 | # Please keep this list alphabetized. 142 | assert Mime.text?('application/atom+xml') 143 | assert Mime.text?('application/javascript') 144 | assert Mime.text?('application/json') 145 | assert Mime.text?('application/perl') 146 | assert Mime.text?('application/rdf+xml') 147 | assert Mime.text?('application/sh') 148 | assert Mime.text?('application/x-ms-xbap') 149 | assert Mime.text?('application/x-perl') 150 | assert Mime.text?('application/x-python') 151 | assert Mime.text?('application/x-ruby') 152 | assert Mime.text?('application/xaml+xml') 153 | assert Mime.text?('application/xhtml+xml') 154 | assert Mime.text?('application/xml') 155 | assert Mime.text?('text/cache-manifest') 156 | assert Mime.text?('text/css') 157 | assert Mime.text?('text/csv') 158 | assert Mime.text?('text/html') 159 | assert Mime.text?('text/javascript') 160 | assert Mime.text?('text/plain') 161 | assert Mime.text?('text/x-nimrod') 162 | assert Mime.text?('text/x-nemerle') 163 | 164 | # Legacy. Prefer testing mime types instead of extensions. 165 | assert Mime.text?('.cu') 166 | assert Mime.text?('.js') 167 | assert Mime.text?('.latex') 168 | assert Mime.text?('.ms') 169 | assert Mime.text?('.nc') 170 | assert Mime.text?('.pl') 171 | assert Mime.text?('.pm') 172 | assert Mime.text?('.py') 173 | assert Mime.text?('.rb') 174 | assert Mime.text?('.sc') 175 | assert Mime.text?('.sh') 176 | assert Mime.text?('.sig') 177 | assert Mime.text?('.sml') 178 | assert Mime.text?('.sps') 179 | assert Mime.text?('.src') 180 | assert Mime.text?('.tcl') 181 | assert Mime.text?('.texi') 182 | assert Mime.text?('.texinfo') 183 | assert Mime.text?('.xul') 184 | end 185 | end 186 | -------------------------------------------------------------------------------- /lib/linguist/language.rb: -------------------------------------------------------------------------------- 1 | require 'yaml' 2 | require 'pygments' 3 | 4 | module Linguist 5 | # Language names that are recognizable by GitHub. Defined languages 6 | # can be highlighted, searched and listed under the Top Languages page. 7 | # 8 | # Languages are defined in `lib/linguist/languages.yml`. 9 | class Language 10 | @languages = [] 11 | @overrides = {} 12 | @index = {} 13 | @name_index = {} 14 | @alias_index = {} 15 | @extension_index = {} 16 | @filename_index = {} 17 | 18 | # Valid Languages types 19 | TYPES = [:data, :markup, :programming] 20 | 21 | # Internal: Test if extension maps to multiple Languages. 22 | # 23 | # Returns true or false. 24 | def self.ambiguous?(extension) 25 | @overrides.include?(extension) 26 | end 27 | 28 | # Include?: Return overridden extensions. 29 | # 30 | # Returns extensions Array. 31 | def self.overridden_extensions 32 | @overrides.keys 33 | end 34 | 35 | # Internal: Create a new Language object 36 | # 37 | # attributes - A hash of attributes 38 | # 39 | # Returns a Language object 40 | def self.create(attributes = {}) 41 | language = new(attributes) 42 | 43 | @languages << language 44 | 45 | # All Language names should be unique. Warn if there is a duplicate. 46 | if @name_index.key?(language.name) 47 | warn "Duplicate language name: #{language.name}" 48 | end 49 | 50 | # Language name index 51 | @index[language.name] = @name_index[language.name] = language 52 | 53 | language.aliases.each do |name| 54 | # All Language aliases should be unique. Warn if there is a duplicate. 55 | if @alias_index.key?(name) 56 | warn "Duplicate alias: #{name}" 57 | end 58 | 59 | @index[name] = @alias_index[name] = language 60 | end 61 | 62 | language.extensions.each do |extension| 63 | if extension !~ /^\./ 64 | warn "Extension is missing a '.': #{extension.inspect}" 65 | end 66 | 67 | unless ambiguous?(extension) 68 | # Index the extension with a leading ".": ".rb" 69 | @extension_index[extension] = language 70 | 71 | # Index the extension without a leading ".": "rb" 72 | @extension_index[extension.sub(/^\./, '')] = language 73 | end 74 | end 75 | 76 | language.overrides.each do |extension| 77 | if extension !~ /^\./ 78 | warn "Extension is missing a '.': #{extension.inspect}" 79 | end 80 | 81 | @overrides[extension] = language 82 | end 83 | 84 | language.filenames.each do |filename| 85 | @filename_index[filename] = language 86 | end 87 | 88 | language 89 | end 90 | 91 | # Public: Get all Languages 92 | # 93 | # Returns an Array of Languages 94 | def self.all 95 | @languages 96 | end 97 | 98 | # Public: Look up Language by its proper name. 99 | # 100 | # name - The String name of the Language 101 | # 102 | # Examples 103 | # 104 | # Language.find_by_name('Ruby') 105 | # # => # 106 | # 107 | # Returns the Language or nil if none was found. 108 | def self.find_by_name(name) 109 | @name_index[name] 110 | end 111 | 112 | # Public: Look up Language by one of its aliases. 113 | # 114 | # name - A String alias of the Language 115 | # 116 | # Examples 117 | # 118 | # Language.find_by_alias('cpp') 119 | # # => # 120 | # 121 | # Returns the Lexer or nil if none was found. 122 | def self.find_by_alias(name) 123 | @alias_index[name] 124 | end 125 | 126 | # Public: Look up Language by extension. 127 | # 128 | # extension - The extension String. May include leading "." 129 | # 130 | # Examples 131 | # 132 | # Language.find_by_extension('.rb') 133 | # # => # 134 | # 135 | # Returns the Language or nil if none was found. 136 | def self.find_by_extension(extension) 137 | @extension_index[extension] 138 | end 139 | 140 | # Public: Look up Language by filename. 141 | # 142 | # filename - The path String. 143 | # 144 | # Examples 145 | # 146 | # Language.find_by_filename('foo.rb') 147 | # # => # 148 | # 149 | # Returns the Language or nil if none was found. 150 | def self.find_by_filename(filename) 151 | basename, extname = File.basename(filename), File.extname(filename) 152 | @filename_index[basename] || @extension_index[extname] 153 | end 154 | 155 | # Public: Look up Language by its name or lexer. 156 | # 157 | # name - The String name of the Language 158 | # 159 | # Examples 160 | # 161 | # Language['Ruby'] 162 | # # => # 163 | # 164 | # Language['ruby'] 165 | # # => # 166 | # 167 | # Returns the Language or nil if none was found. 168 | def self.[](name) 169 | @index[name] 170 | end 171 | 172 | # Public: A List of popular languages 173 | # 174 | # Popular languages are sorted to the top of language chooser 175 | # dropdowns. 176 | # 177 | # This list is configured in "popular.yml". 178 | # 179 | # Returns an Array of Lexers. 180 | def self.popular 181 | @popular ||= all.select(&:popular?).sort_by { |lang| lang.name.downcase } 182 | end 183 | 184 | # Public: A List of non-popular languages 185 | # 186 | # Unpopular languages appear below popular ones in language 187 | # chooser dropdowns. 188 | # 189 | # This list is created from all the languages not listed in "popular.yml". 190 | # 191 | # Returns an Array of Lexers. 192 | def self.unpopular 193 | @unpopular ||= all.select(&:unpopular?).sort_by { |lang| lang.name.downcase } 194 | end 195 | 196 | # Internal: Initialize a new Language 197 | # 198 | # attributes - A hash of attributes 199 | def initialize(attributes = {}) 200 | # @name is required 201 | @name = attributes[:name] || raise(ArgumentError, "missing name") 202 | 203 | # Set type 204 | @type = attributes[:type] ? attributes[:type].to_sym : nil 205 | if @type && !TYPES.include?(@type) 206 | raise ArgumentError, "invalid type: #{@type}" 207 | end 208 | 209 | # Set aliases 210 | @aliases = [default_alias_name] + (attributes[:aliases] || []) 211 | 212 | # Lookup Lexer object 213 | @lexer = Pygments::Lexer.find_by_name(attributes[:lexer] || name) || 214 | raise(ArgumentError, "#{@name} is missing lexer") 215 | 216 | # Set legacy search term 217 | @search_term = attributes[:search_term] || default_alias_name 218 | 219 | # Set extensions or default to []. 220 | @extensions = attributes[:extensions] || [] 221 | @overrides = attributes[:overrides] || [] 222 | @filenames = attributes[:filenames] || [] 223 | 224 | @primary_extension = attributes[:primary_extension] || default_primary_extension || extensions.first 225 | 226 | # Prepend primary extension unless its already included 227 | if primary_extension && !extensions.include?(primary_extension) 228 | @extensions = [primary_extension] + extensions 229 | end 230 | 231 | # Set popular, and searchable flags 232 | @popular = attributes.key?(:popular) ? attributes[:popular] : false 233 | @searchable = attributes.key?(:searchable) ? attributes[:searchable] : true 234 | 235 | # If group name is set, save the name so we can lazy load it later 236 | if attributes[:group_name] 237 | @group = nil 238 | @group_name = attributes[:group_name] 239 | 240 | # Otherwise we can set it to self now 241 | else 242 | @group = self 243 | end 244 | end 245 | 246 | # Public: Get proper name 247 | # 248 | # Examples 249 | # 250 | # # => "Ruby" 251 | # # => "Python" 252 | # # => "Perl" 253 | # 254 | # Returns the name String 255 | attr_reader :name 256 | 257 | # Public: Get type. 258 | # 259 | # Returns a type Symbol or nil. 260 | attr_reader :type 261 | 262 | # Public: Get aliases 263 | # 264 | # Examples 265 | # 266 | # Language['C++'].aliases 267 | # # => ["cpp"] 268 | # 269 | # Returns an Array of String names 270 | attr_reader :aliases 271 | 272 | # Deprecated: Get code search term 273 | # 274 | # Examples 275 | # 276 | # # => "ruby" 277 | # # => "python" 278 | # # => "perl" 279 | # 280 | # Returns the name String 281 | attr_reader :search_term 282 | 283 | # Public: Get Lexer 284 | # 285 | # Returns the Lexer 286 | attr_reader :lexer 287 | 288 | # Public: Get extensions 289 | # 290 | # Examples 291 | # 292 | # # => ['.rb', '.rake', ...] 293 | # 294 | # Returns the extensions Array 295 | attr_reader :extensions 296 | 297 | # Deprecated: Get primary extension 298 | # 299 | # Defaults to the first extension but can be overriden 300 | # in the languages.yml. 301 | # 302 | # The primary extension can not be nil. Tests should verify this. 303 | # 304 | # This attribute is only used by app/helpers/gists_helper.rb for 305 | # creating the language dropdown. It really should be using `name` 306 | # instead. Would like to drop primary extension. 307 | # 308 | # Returns the extension String. 309 | attr_reader :primary_extension 310 | 311 | # Internal: Get overridden extensions. 312 | # 313 | # Returns the extensions Array. 314 | attr_reader :overrides 315 | 316 | # Public: Get filenames 317 | # 318 | # Examples 319 | # 320 | # # => ['Rakefile', ...] 321 | # 322 | # Returns the extensions Array 323 | attr_reader :filenames 324 | 325 | # Internal: Get default alias name 326 | # 327 | # Returns the alias name String 328 | def default_alias_name 329 | name.downcase.gsub(/\s/, '-') 330 | end 331 | 332 | # Internal: Get default primary extension. 333 | # 334 | # Returns the extension String. 335 | def default_primary_extension 336 | extensions.first 337 | end 338 | 339 | # Public: Get Language group 340 | # 341 | # Returns a Language 342 | def group 343 | @group ||= Language.find_by_name(@group_name) 344 | end 345 | 346 | # Public: Is it popular? 347 | # 348 | # Returns true or false 349 | def popular? 350 | @popular 351 | end 352 | 353 | # Public: Is it not popular? 354 | # 355 | # Returns true or false 356 | def unpopular? 357 | !popular? 358 | end 359 | 360 | # Public: Is it searchable? 361 | # 362 | # Unsearchable languages won't by indexed by solr and won't show 363 | # up in the code search dropdown. 364 | # 365 | # Returns true or false 366 | def searchable? 367 | @searchable 368 | end 369 | 370 | # Public: Highlight syntax of text 371 | # 372 | # text - String of code to be highlighted 373 | # options - A Hash of options (defaults to {}) 374 | # 375 | # Returns html String 376 | def colorize(text, options = {}) 377 | lexer.highlight(text, options = {}) 378 | end 379 | 380 | # Public: Return name as String representation 381 | def to_s 382 | name 383 | end 384 | 385 | def ==(other) 386 | eql?(other) 387 | end 388 | 389 | def eql?(other) 390 | equal?(other) 391 | end 392 | 393 | def hash 394 | name.hash 395 | end 396 | end 397 | 398 | popular = YAML.load_file(File.expand_path("../popular.yml", __FILE__)) 399 | 400 | YAML.load_file(File.expand_path("../languages.yml", __FILE__)).each do |name, options| 401 | Language.create( 402 | :name => name, 403 | :type => options['type'], 404 | :aliases => options['aliases'], 405 | :lexer => options['lexer'], 406 | :group_name => options['group'], 407 | :searchable => options.key?('searchable') ? options['searchable'] : true, 408 | :search_term => options['search_term'], 409 | :extensions => options['extensions'], 410 | :primary_extension => options['primary_extension'], 411 | :overrides => options['overrides'], 412 | :filenames => options['filenames'], 413 | :popular => popular.include?(name) 414 | ) 415 | end 416 | end 417 | -------------------------------------------------------------------------------- /test/fixtures/asteroids.sps: -------------------------------------------------------------------------------- 1 | (import (rnrs) 2 | (only (surfage s1 lists) filter-map) 3 | (gl) 4 | (glut) 5 | (dharmalab records define-record-type) 6 | (dharmalab math basic) 7 | (agave glu compat) 8 | (agave geometry pt) 9 | (agave glamour window) 10 | (agave glamour misc) 11 | (surfage s19 time) 12 | (surfage s27 random-bits) 13 | (surfage s42 eager-comprehensions)) 14 | 15 | ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 16 | ;; utilities 17 | ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 18 | 19 | (define (say . args) 20 | (for-each display args) 21 | (newline)) 22 | 23 | ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 24 | 25 | (define (gl-translate-pt p) 26 | (glTranslated (pt-x p) (pt-y p) 0.0)) 27 | 28 | ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 29 | 30 | (define (radians x) (* x (/ pi 180))) 31 | 32 | (define (degrees x) (* x (/ 180 pi))) 33 | 34 | ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 35 | 36 | (define (angle->pt a) 37 | (pt (cos a) 38 | (sin a))) 39 | 40 | ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 41 | 42 | (define (current-time-in-nanoseconds) 43 | (let ((val (current-time))) 44 | (+ (* (time-second val) 1000000000) 45 | (time-nanosecond val)))) 46 | 47 | (define (current-time-in-seconds) 48 | (/ (current-time-in-nanoseconds) 49 | 1000.0 ;; micro 50 | 1000.0 ;; milli 51 | 1000.0)) 52 | 53 | (define base-time (current-time-in-seconds)) 54 | 55 | (define (time-step) (- (current-time-in-seconds) base-time)) 56 | 57 | ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 58 | 59 | (define score 0) 60 | 61 | (define level 1) 62 | 63 | (define ships 3) 64 | 65 | ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 66 | ;; spaceship 67 | ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 68 | 69 | (define-record-type++ spaceship 70 | (fields (mutable pos) 71 | (mutable vel) 72 | (mutable theta) 73 | (mutable force))) 74 | 75 | ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 76 | ;; particle 77 | ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 78 | 79 | (define-record-type++ particle 80 | (fields (mutable pos) 81 | (mutable vel) 82 | (mutable birth) 83 | (mutable lifetime) 84 | (mutable color))) 85 | 86 | (define particles '()) 87 | 88 | ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 89 | ;; bullet 90 | ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 91 | 92 | (define-record-type++ bullet 93 | (fields (mutable pos) 94 | (mutable vel) 95 | (mutable birth))) 96 | 97 | (define bullets '()) 98 | 99 | ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 100 | ;; asteroid 101 | ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 102 | 103 | (define-record-type++ asteroid 104 | (fields (mutable pos) 105 | (mutable vel) 106 | (mutable radius))) 107 | 108 | (define number-of-starting-asteroids 4) 109 | 110 | (define asteroids #f) 111 | 112 | ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 113 | ;; bullet-pack 114 | ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 115 | 116 | (define-record-type++ bullet-pack 117 | (fields (mutable pos) 118 | (mutable vel))) 119 | 120 | (define pack #f) 121 | 122 | (is-bullet-pack pack) 123 | 124 | ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 125 | 126 | (initialize-glut) 127 | 128 | (window (size 800 400) 129 | (title "Asteroids") 130 | (reshape (width height))) 131 | 132 | (random-source-randomize! default-random-source) 133 | 134 | ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 135 | 136 | (define (pt-wrap p) 137 | (pt (mod (pt-x p) width) 138 | (mod (pt-y p) height))) 139 | 140 | ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 141 | 142 | (define ship 143 | (make-spaceship (pt (/ width 2.0) (/ height 2.0)) 144 | (pt 0.0 0.0) 145 | 0.0 146 | 0.0)) 147 | 148 | (is-spaceship ship) 149 | 150 | (define ammo 0) 151 | 152 | ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 153 | 154 | (set! asteroids 155 | (list-ec (: i number-of-starting-asteroids) 156 | (make-asteroid (pt (inexact (random-integer width)) 157 | (inexact (random-integer height))) 158 | (pt (inexact (+ -50 (random-integer 100))) 159 | (inexact (+ -50 (random-integer 100)))) 160 | 50.0))) 161 | 162 | ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 163 | 164 | (set! pack (make-bullet-pack (pt (inexact (random-integer width)) 165 | (inexact (random-integer height))) 166 | (pt (inexact (+ -50 (random-integer 100))) 167 | (inexact (+ -50 (random-integer 100)))))) 168 | 169 | ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 170 | 171 | (buffered-display-procedure 172 | (lambda () 173 | (background 0.0) 174 | 175 | ;; ship 176 | 177 | (glColor3f 0.0 1.0 0.0) 178 | 179 | (gl-matrix-excursion 180 | (gl-translate-pt ship.pos) 181 | (glRotated 90.0 0.0 1.0 0.0) 182 | (glRotated (degrees ship.theta) -1.0 0.0 0.0) 183 | (glutWireCone 10.0 30.0 5 5)) 184 | 185 | ;; particles 186 | 187 | (for-each 188 | (lambda (par) 189 | 190 | (let ((c (particle-color par))) 191 | (glColor3f (vector-ref c 0) 192 | (vector-ref c 1) 193 | (vector-ref c 2))) 194 | 195 | (gl-matrix-excursion 196 | (gl-translate-pt (particle-pos par)) 197 | (glutWireSphere 2.0 5 5))) 198 | particles) 199 | 200 | ;; bullets 201 | 202 | (glColor3f 0.0 0.0 1.0) 203 | 204 | (for-each 205 | (lambda (bullet) 206 | (gl-matrix-excursion 207 | (gl-translate-pt (bullet-pos bullet)) 208 | (glutWireSphere 5.0 10 10))) 209 | bullets) 210 | 211 | ;; asteroids 212 | 213 | (glColor3f 1.0 0.0 0.0) 214 | 215 | (for-each 216 | (lambda (asteroid) 217 | (gl-matrix-excursion 218 | (gl-translate-pt (asteroid-pos asteroid)) 219 | (glutWireSphere (asteroid-radius asteroid) 10 10))) 220 | asteroids) 221 | 222 | ;; bullet-pack 223 | 224 | (glColor3f 0.0 0.0 1.0) 225 | 226 | (gl-matrix-excursion 227 | (gl-translate-pt pack.pos) 228 | (glutWireCube 10.0)) 229 | 230 | )) 231 | 232 | ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 233 | 234 | (define last-time (current-time-in-seconds)) 235 | 236 | (define dt 0) 237 | 238 | (define (update-system) 239 | 240 | (set! dt (- (current-time-in-seconds) last-time)) 241 | 242 | (set! last-time (current-time-in-seconds)) 243 | 244 | (ship.pos! (pt-wrap (pt+ ship.pos (pt*n ship.vel dt)))) 245 | 246 | (pack.pos! (pt-wrap (pt+ pack.pos (pt*n pack.vel dt)))) 247 | 248 | (set! particles 249 | (filter-map 250 | (lambda (par) 251 | (is-particle par) 252 | (cond ((> (- (current-time-in-seconds) par.birth) par.lifetime) #f) 253 | (else (par.pos! (pt+ par.pos (pt*n par.vel dt))) 254 | par))) 255 | particles)) 256 | 257 | (set! bullets 258 | (filter-map 259 | (lambda (bullet) 260 | (is-bullet bullet) 261 | (cond ((> (- (current-time-in-seconds) bullet.birth) 2.0) #f) 262 | (else (bullet.pos! (pt+ bullet.pos (pt*n bullet.vel dt))) 263 | bullet))) 264 | bullets)) 265 | 266 | (set! asteroids 267 | (filter-map 268 | (lambda (a) 269 | (is-asteroid a) 270 | (a.pos! (pt-wrap (pt+ a.pos (pt*n a.vel dt)))) 271 | (if (< a.radius 10.0) #f a)) 272 | asteroids)) 273 | 274 | ;; bullet asteroid contact 275 | 276 | (for-each 277 | (lambda (b) 278 | (is-bullet b) 279 | (for-each 280 | (lambda (a) 281 | (is-asteroid a) 282 | (when (<= (pt-distance b.pos a.pos) 283 | a.radius) 284 | 285 | (begin (set! score (+ score 1)) 286 | (say "score: " score) 287 | #f) 288 | 289 | (set! asteroids 290 | (append 291 | (list-ec (: i 4) 292 | (make-asteroid a.pos 293 | (pt (+ -50.0 (random-integer 100)) 294 | (+ -50.0 (random-integer 100))) 295 | (/ a.radius 2.0))) 296 | asteroids)) 297 | (a.radius! 0.1) 298 | (b.birth! 0.0) 299 | 300 | (set! particles 301 | (append (list-ec (: i 100) 302 | (make-particle a.pos 303 | (pt*n (angle->pt 304 | (radians 305 | (random-integer 360))) 306 | 307 | (random-integer 100) 308 | 309 | ) 310 | (current-time-in-seconds) 311 | 1.0 312 | (vector 1.0 1.0 1.0))) 313 | particles)))) 314 | asteroids)) 315 | bullets) 316 | 317 | (for-each 318 | (lambda (a) 319 | (is-asteroid a) 320 | (when (<= (pt-distance a.pos ship.pos) a.radius) 321 | 322 | (set! particles 323 | (append (list-ec (: i 100) 324 | (make-particle ship.pos 325 | (pt*n (angle->pt 326 | (radians 327 | (random-integer 360))) 328 | (random-integer 100)) 329 | (current-time-in-seconds) 330 | 1.0 331 | (vector 0.0 1.0 1.0))) 332 | particles)) 333 | 334 | (set! ship (make-spaceship (pt (/ width 2.0) (/ height 2.0)) 335 | (pt 0.0 0.0) 336 | 0.0 337 | 0.0)) 338 | 339 | )) 340 | asteroids) 341 | 342 | (when (null? asteroids) 343 | (set! level (+ level 1)) 344 | (display "level: ") 345 | (display level) 346 | (newline) 347 | (set! asteroids 348 | (list-ec (: i (+ number-of-starting-asteroids level)) 349 | (make-asteroid (pt (inexact (random-integer width)) 350 | (inexact (random-integer height))) 351 | (pt (inexact (+ -50 (random-integer 100))) 352 | (inexact (+ -50 (random-integer 100)))) 353 | 50.0)))) 354 | 355 | ;; ship pack contact 356 | 357 | (when (<= (pt-distance ship.pos pack.pos) 10.0) 358 | (set! ammo (+ ammo 5)) 359 | (set! pack (make-bullet-pack (pt (inexact (random-integer width)) 360 | (inexact (random-integer height))) 361 | (pt (inexact (+ -50 (random-integer 100))) 362 | (inexact (+ -50 (random-integer 100)))))) 363 | (say "ammo: " ammo)) 364 | 365 | ) 366 | 367 | ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 368 | 369 | (glutIdleFunc 370 | (lambda () 371 | (update-system) 372 | (glutPostRedisplay))) 373 | 374 | (glutKeyboardFunc 375 | (lambda (key x y) 376 | (case (integer->char key) 377 | 378 | ((#\w) 379 | 380 | (ship.vel! (pt+ ship.vel (pt*n (angle->pt ship.theta) 50.0))) 381 | 382 | (set! particles 383 | (append (list-ec (: i 10) 384 | (make-particle ship.pos 385 | (pt*n 386 | (angle->pt 387 | (+ ship.theta 388 | (radians 180.0) 389 | (radians (+ -45 (random-integer 90))) 390 | )) 391 | (random-integer 50) 392 | ) 393 | (current-time-in-seconds) 394 | 1.0 395 | (vector 1.0 1.0 0.0))) 396 | particles)) 397 | 398 | ) 399 | 400 | ((#\a) (ship.theta! (+ ship.theta (radians 20.0)))) 401 | ((#\d) (ship.theta! (- ship.theta (radians 20.0)))) 402 | 403 | ((#\s) (ship.vel! (pt 0.0 0.0))) 404 | 405 | ((#\x) (ship.theta! (+ ship.theta (radians 180.0)))) 406 | 407 | ((#\space) 408 | 409 | (when (> ammo 0) 410 | 411 | (set! ammo (- ammo 1)) 412 | 413 | (set! bullets 414 | (cons 415 | (make-bullet ship.pos 416 | (pt+ ship.vel 417 | (pt*n (angle->pt ship.theta) 400.0)) 418 | (current-time-in-seconds)) 419 | bullets))) 420 | 421 | (say "ammo: " ammo) 422 | ) 423 | ))) 424 | 425 | ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 426 | 427 | (say "w - Thrusters") 428 | (say "a/d - Left/Right") 429 | (say "s - Stop") 430 | (say "x - Flip") 431 | (say "spc - Laser") 432 | 433 | ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 434 | 435 | (glutMainLoop) 436 | -------------------------------------------------------------------------------- /test/test_language.rb: -------------------------------------------------------------------------------- 1 | require 'linguist/language' 2 | 3 | require 'test/unit' 4 | require 'pygments' 5 | 6 | class TestLanguage < Test::Unit::TestCase 7 | include Linguist 8 | 9 | Lexer = Pygments::Lexer 10 | 11 | def test_ambiguous_extensions 12 | assert Language.ambiguous?('.h') 13 | assert_equal Language['C'], Language.find_by_extension('h') 14 | 15 | assert Language.ambiguous?('.m') 16 | assert_equal Language['Objective-C'], Language.find_by_extension('m') 17 | 18 | assert Language.ambiguous?('.pl') 19 | assert_equal Language['Perl'], Language.find_by_extension('pl') 20 | 21 | assert Language.ambiguous?('.r') 22 | assert_equal Language['R'], Language.find_by_extension('r') 23 | end 24 | 25 | def test_lexer 26 | assert_equal Lexer['ActionScript 3'], Language['ActionScript'].lexer 27 | assert_equal Lexer['Bash'], Language['Gentoo Ebuild'].lexer 28 | assert_equal Lexer['Bash'], Language['Gentoo Eclass'].lexer 29 | assert_equal Lexer['Bash'], Language['Shell'].lexer 30 | assert_equal Lexer['C'], Language['OpenCL'].lexer 31 | assert_equal Lexer['C'], Language['XS'].lexer 32 | assert_equal Lexer['C++'], Language['C++'].lexer 33 | assert_equal Lexer['Coldfusion HTML'], Language['ColdFusion'].lexer 34 | assert_equal Lexer['Fortran'], Language['FORTRAN'].lexer 35 | assert_equal Lexer['Gherkin'], Language['Cucumber'].lexer 36 | assert_equal Lexer['HTML'], Language['HTML'].lexer 37 | assert_equal Lexer['HTML+Django/Jinja'], Language['HTML+Django'].lexer 38 | assert_equal Lexer['HTML+PHP'], Language['HTML+PHP'].lexer 39 | assert_equal Lexer['Java'], Language['ChucK'].lexer 40 | assert_equal Lexer['Java'], Language['Groovy'].lexer 41 | assert_equal Lexer['Java'], Language['Java'].lexer 42 | assert_equal Lexer['JavaScript'], Language['JSON'].lexer 43 | assert_equal Lexer['JavaScript'], Language['JavaScript'].lexer 44 | assert_equal Lexer['MOOCode'], Language['Moocode'].lexer 45 | assert_equal Lexer['MuPAD'], Language['mupad'].lexer 46 | assert_equal Lexer['NASM'], Language['Assembly'].lexer 47 | assert_equal Lexer['OCaml'], Language['F#'].lexer 48 | assert_equal Lexer['OCaml'], Language['OCaml'].lexer 49 | assert_equal Lexer['OCaml'], Language['Standard ML'].lexer 50 | assert_equal Lexer['Ooc'], Language['ooc'].lexer 51 | assert_equal Lexer['REBOL'], Language['Rebol'].lexer 52 | assert_equal Lexer['RHTML'], Language['HTML+ERB'].lexer 53 | assert_equal Lexer['RHTML'], Language['RHTML'].lexer 54 | assert_equal Lexer['Ruby'], Language['Mirah'].lexer 55 | assert_equal Lexer['Ruby'], Language['Ruby'].lexer 56 | assert_equal Lexer['S'], Language['R'].lexer 57 | assert_equal Lexer['Scheme'], Language['Emacs Lisp'].lexer 58 | assert_equal Lexer['Scheme'], Language['Nu'].lexer 59 | assert_equal Lexer['Scheme'], Language['Racket'].lexer 60 | assert_equal Lexer['Scheme'], Language['Scheme'].lexer 61 | assert_equal Lexer['TeX'], Language['TeX'].lexer 62 | assert_equal Lexer['Text only'], Language['Text'].lexer 63 | assert_equal Lexer['aspx-vb'], Language['ASP'].lexer 64 | assert_equal Lexer['haXe'], Language['HaXe'].lexer 65 | assert_equal Lexer['reStructuredText'], Language['reStructuredText'].lexer 66 | end 67 | 68 | def test_find_by_alias 69 | assert_equal Language['ASP'], Language.find_by_alias('asp') 70 | assert_equal Language['ASP'], Language.find_by_alias('aspx') 71 | assert_equal Language['ASP'], Language.find_by_alias('aspx-vb') 72 | assert_equal Language['ActionScript'], Language.find_by_alias('as3') 73 | assert_equal Language['Assembly'], Language.find_by_alias('nasm') 74 | assert_equal Language['Batchfile'], Language.find_by_alias('bat') 75 | assert_equal Language['C#'], Language.find_by_alias('c#') 76 | assert_equal Language['C#'], Language.find_by_alias('csharp') 77 | assert_equal Language['C'], Language.find_by_alias('c') 78 | assert_equal Language['C++'], Language.find_by_alias('c++') 79 | assert_equal Language['C++'], Language.find_by_alias('cpp') 80 | assert_equal Language['ColdFusion'], Language.find_by_alias('cfm') 81 | assert_equal Language['Common Lisp'], Language.find_by_alias('common-lisp') 82 | assert_equal Language['Common Lisp'], Language.find_by_alias('lisp') 83 | assert_equal Language['Darcs Patch'], Language.find_by_alias('dpatch') 84 | assert_equal Language['Emacs Lisp'], Language.find_by_alias('elisp') 85 | assert_equal Language['Emacs Lisp'], Language.find_by_alias('emacs-lisp') 86 | assert_equal Language['Gettext Catalog'], Language.find_by_alias('pot') 87 | assert_equal Language['HTML'], Language.find_by_alias('html') 88 | assert_equal Language['HTML+ERB'], Language.find_by_alias('html+erb') 89 | assert_equal Language['IRC log'], Language.find_by_alias('irc') 90 | assert_equal Language['JSON'], Language.find_by_alias('json') 91 | assert_equal Language['Java Server Pages'], Language.find_by_alias('jsp') 92 | assert_equal Language['Java'], Language.find_by_alias('java') 93 | assert_equal Language['JavaScript'], Language.find_by_alias('javascript') 94 | assert_equal Language['JavaScript'], Language.find_by_alias('js') 95 | assert_equal Language['Literate Haskell'], Language.find_by_alias('lhs') 96 | assert_equal Language['Literate Haskell'], Language.find_by_alias('literate-haskell') 97 | assert_equal Language['Parrot Internal Representation'], Language.find_by_alias('pir') 98 | assert_equal Language['Pure Data'], Language.find_by_alias('pure-data') 99 | assert_equal Language['Raw token data'], Language.find_by_alias('raw') 100 | assert_equal Language['Ruby'], Language.find_by_alias('rb') 101 | assert_equal Language['Ruby'], Language.find_by_alias('ruby') 102 | assert_equal Language['Scheme'], Language.find_by_alias('scheme') 103 | assert_equal Language['Shell'], Language.find_by_alias('bash') 104 | assert_equal Language['Shell'], Language.find_by_alias('sh') 105 | assert_equal Language['Shell'], Language.find_by_alias('shell') 106 | assert_equal Language['Shell'], Language.find_by_alias('zsh') 107 | assert_equal Language['TeX'], Language.find_by_alias('tex') 108 | assert_equal Language['VimL'], Language.find_by_alias('vim') 109 | assert_equal Language['VimL'], Language.find_by_alias('viml') 110 | assert_equal Language['reStructuredText'], Language.find_by_alias('rst') 111 | end 112 | 113 | def test_groups 114 | # Test a couple identity cases 115 | assert_equal Language['Perl'], Language['Perl'].group 116 | assert_equal Language['Python'], Language['Python'].group 117 | assert_equal Language['Ruby'], Language['Ruby'].group 118 | 119 | # Test a few special groups 120 | assert_equal Language['Assembly'], Language['GAS'].group 121 | assert_equal Language['C'], Language['OpenCL'].group 122 | assert_equal Language['Haskell'], Language['Literate Haskell'].group 123 | assert_equal Language['Java'], Language['Java Server Pages'].group 124 | assert_equal Language['Python'], Language['Cython'].group 125 | assert_equal Language['Python'], Language['NumPy'].group 126 | assert_equal Language['Shell'], Language['Batchfile'].group 127 | assert_equal Language['Shell'], Language['Gentoo Ebuild'].group 128 | assert_equal Language['Shell'], Language['Gentoo Eclass'].group 129 | assert_equal Language['Shell'], Language['Tcsh'].group 130 | 131 | # Ensure everyone has a group 132 | Language.all.each do |language| 133 | assert language.group, "#{language} has no group" 134 | end 135 | end 136 | 137 | # Used for code search indexing. Changing any of these values may 138 | # require reindexing repositories. 139 | def test_search_term 140 | assert_equal 'perl', Language['Perl'].search_term 141 | assert_equal 'python', Language['Python'].search_term 142 | assert_equal 'ruby', Language['Ruby'].search_term 143 | assert_equal 'common-lisp', Language['Common Lisp'].search_term 144 | assert_equal 'html+erb', Language['HTML+ERB'].search_term 145 | assert_equal 'max/msp', Language['Max/MSP'].search_term 146 | assert_equal 'pure-data', Language['Pure Data'].search_term 147 | 148 | assert_equal 'aspx-vb', Language['ASP'].search_term 149 | assert_equal 'as3', Language['ActionScript'].search_term 150 | assert_equal 'nasm', Language['Assembly'].search_term 151 | assert_equal 'bat', Language['Batchfile'].search_term 152 | assert_equal 'csharp', Language['C#'].search_term 153 | assert_equal 'cpp', Language['C++'].search_term 154 | assert_equal 'cfm', Language['ColdFusion'].search_term 155 | assert_equal 'dpatch', Language['Darcs Patch'].search_term 156 | assert_equal 'ocaml', Language['F#'].search_term 157 | assert_equal 'pot', Language['Gettext Catalog'].search_term 158 | assert_equal 'irc', Language['IRC log'].search_term 159 | assert_equal 'lhs', Language['Literate Haskell'].search_term 160 | assert_equal 'ruby', Language['Mirah'].search_term 161 | assert_equal 'raw', Language['Raw token data'].search_term 162 | assert_equal 'bash', Language['Shell'].search_term 163 | assert_equal 'vim', Language['VimL'].search_term 164 | assert_equal 'jsp', Language['Java Server Pages'].search_term 165 | assert_equal 'rst', Language['reStructuredText'].search_term 166 | end 167 | 168 | def test_popular 169 | assert Language['Ruby'].popular? 170 | assert Language['Perl'].popular? 171 | assert Language['Python'].popular? 172 | assert Language['Assembly'].unpopular? 173 | assert Language['Brainfuck'].unpopular? 174 | end 175 | 176 | def test_programming 177 | assert_equal :programming, Language['JavaScript'].type 178 | assert_equal :programming, Language['Perl'].type 179 | assert_equal :programming, Language['Python'].type 180 | assert_equal :programming, Language['Ruby'].type 181 | end 182 | 183 | def test_markup 184 | assert_equal :markup, Language['HTML'].type 185 | assert_equal :markup, Language['YAML'].type 186 | end 187 | 188 | def test_other 189 | assert_nil Language['Brainfuck'].type 190 | assert_nil Language['Makefile'].type 191 | end 192 | 193 | def test_searchable 194 | assert Language['Ruby'].searchable? 195 | assert !Language['Gettext Catalog'].searchable? 196 | assert !Language['SQL'].searchable? 197 | end 198 | 199 | def test_find_by_name 200 | ruby = Language['Ruby'] 201 | assert_equal ruby, Language.find_by_name('Ruby') 202 | end 203 | 204 | def test_find_all_by_name 205 | Language.all.each do |language| 206 | assert_equal language, Language.find_by_name(language.name) 207 | assert_equal language, Language[language.name] 208 | end 209 | end 210 | 211 | def test_find_all_by_alias 212 | Language.all.each do |language| 213 | language.aliases.each do |name| 214 | assert_equal language, Language.find_by_alias(name) 215 | assert_equal language, Language[name] 216 | end 217 | end 218 | end 219 | 220 | def test_find_by_extension 221 | assert_equal Language['Ruby'], Language.find_by_extension('.rb') 222 | assert_equal Language['Ruby'], Language.find_by_extension('rb') 223 | assert_equal Language['Groff'], Language.find_by_extension('man') 224 | assert_equal Language['Groff'], Language.find_by_extension('1') 225 | assert_equal Language['Groff'], Language.find_by_extension('2') 226 | assert_equal Language['Groff'], Language.find_by_extension('3') 227 | assert_equal Language['PHP'], Language.find_by_extension('php') 228 | assert_equal Language['PHP'], Language.find_by_extension('php3') 229 | assert_equal Language['PHP'], Language.find_by_extension('php4') 230 | assert_equal Language['PHP'], Language.find_by_extension('php5') 231 | assert_nil Language.find_by_extension('.kt') 232 | end 233 | 234 | def test_find_all_by_extension 235 | Language.all.each do |language| 236 | language.extensions.each do |extension| 237 | unless Language.ambiguous?(extension) 238 | assert_equal language, Language.find_by_extension(extension) 239 | end 240 | end 241 | end 242 | end 243 | 244 | def test_find_by_filename 245 | assert_equal Language['Ruby'], Language.find_by_filename('foo.rb') 246 | assert_equal Language['Ruby'], Language.find_by_filename('foo/bar.rb') 247 | assert_equal Language['Ruby'], Language.find_by_filename('Rakefile') 248 | assert_nil Language.find_by_filename('rb') 249 | assert_nil Language.find_by_filename('.rb') 250 | assert_nil Language.find_by_filename('.kt') 251 | end 252 | 253 | def test_find 254 | assert_equal 'Ruby', Language['Ruby'].name 255 | assert_equal 'Ruby', Language['ruby'].name 256 | assert_equal 'C++', Language['C++'].name 257 | assert_equal 'C++', Language['c++'].name 258 | assert_equal 'C++', Language['cpp'].name 259 | assert_equal 'C#', Language['C#'].name 260 | assert_equal 'C#', Language['c#'].name 261 | assert_equal 'C#', Language['csharp'].name 262 | assert_nil Language['defunkt'] 263 | end 264 | 265 | def test_name 266 | assert_equal 'Perl', Language['Perl'].name 267 | assert_equal 'Python', Language['Python'].name 268 | assert_equal 'Ruby', Language['Ruby'].name 269 | end 270 | 271 | def test_error_without_name 272 | assert_raise ArgumentError do 273 | Language.new :name => nil 274 | end 275 | end 276 | 277 | def test_extensions 278 | assert Language['Perl'].extensions.include?('.pl') 279 | assert Language['Python'].extensions.include?('.py') 280 | assert Language['Ruby'].extensions.include?('.rb') 281 | end 282 | 283 | def test_primary_extension 284 | assert_equal '.pl', Language['Perl'].primary_extension 285 | assert_equal '.py', Language['Python'].primary_extension 286 | assert_equal '.rb', Language['Ruby'].primary_extension 287 | 288 | # This is a nasty requirement, but theres some code in GitHub that 289 | # expects this. Really want to drop this. 290 | Language.all.each do |language| 291 | assert language.primary_extension, "#{language} has no primary extension" 292 | end 293 | end 294 | 295 | def test_eql 296 | assert Language['Ruby'].eql?(Language['Ruby']) 297 | assert !Language['Ruby'].eql?(Language['Python']) 298 | assert !Language['Ruby'].eql?(Language.new(:name => 'Ruby')) 299 | end 300 | 301 | 302 | def test_colorize 303 | assert_equal <<-HTML, Language['Text'].colorize("Hello") 304 |
Hello
305 | 
306 |
307 | HTML 308 | 309 | assert_equal <<-HTML, Language['Ruby'].colorize("def foo\n 'foo'\nend\n") 310 |
def foo
311 |   'foo'
312 | end
313 | 
314 |
315 | HTML 316 | end 317 | end 318 | -------------------------------------------------------------------------------- /lib/linguist/blob_helper.rb: -------------------------------------------------------------------------------- 1 | require 'linguist/language' 2 | require 'linguist/mime' 3 | require 'linguist/pathname' 4 | 5 | require 'charlock_holmes' 6 | require 'escape_utils' 7 | require 'pygments' 8 | require 'yaml' 9 | 10 | module Linguist 11 | # BlobHelper is a mixin for Blobish classes that respond to "name", 12 | # "data" and "size" such as Grit::Blob. 13 | module BlobHelper 14 | # Internal: Get a Pathname wrapper for Blob#name 15 | # 16 | # Returns a Pathname. 17 | def pathname 18 | Pathname.new(name || "") 19 | end 20 | 21 | # Public: Get the extname of the path 22 | # 23 | # Examples 24 | # 25 | # blob(name='foo.rb').extname 26 | # # => '.rb' 27 | # 28 | # Returns a String 29 | def extname 30 | pathname.extname 31 | end 32 | 33 | # Public: Get the actual blob mime type 34 | # 35 | # Examples 36 | # 37 | # # => 'text/plain' 38 | # # => 'text/html' 39 | # 40 | # Returns a mime type String. 41 | def mime_type 42 | @mime_type ||= pathname.mime_type 43 | end 44 | 45 | # Public: Get the Content-Type header value 46 | # 47 | # This value is used when serving raw blobs. 48 | # 49 | # Examples 50 | # 51 | # # => 'text/plain; charset=utf-8' 52 | # # => 'application/octet-stream' 53 | # 54 | # Returns a content type String. 55 | def content_type 56 | @content_type ||= binary? ? mime_type : "text/plain; charset=#{encoding.downcase}" 57 | end 58 | 59 | # Public: Get the Content-Disposition header value 60 | # 61 | # This value is used when serving raw blobs. 62 | # 63 | # # => "attachment; filename=file.tar" 64 | # # => "inline" 65 | # 66 | # Returns a content disposition String. 67 | def disposition 68 | if text? || image? 69 | 'inline' 70 | else 71 | "attachment; filename=#{EscapeUtils.escape_url(pathname.basename)}" 72 | end 73 | end 74 | 75 | def encoding 76 | if hash = detect_encoding 77 | hash[:encoding] 78 | end 79 | end 80 | 81 | # Try to guess the encoding 82 | # 83 | # Returns: a Hash, with :encoding, :confidence, :type 84 | # this will return nil if an error occurred during detection or 85 | # no valid encoding could be found 86 | def detect_encoding 87 | @detect_encoding ||= CharlockHolmes::EncodingDetector.new.detect(data) if data 88 | end 89 | 90 | # Public: Is the blob binary? 91 | # 92 | # Return true or false 93 | def binary? 94 | if mime_type = Mime.lookup_mime_type_for(pathname.extname) 95 | mime_type.binary? 96 | else 97 | encoding.nil? || detect_encoding[:type] == :binary 98 | end 99 | end 100 | 101 | # Public: Is the blob text? 102 | # 103 | # Return true or false 104 | def text? 105 | !binary? 106 | end 107 | 108 | # Public: Is the blob a supported image format? 109 | # 110 | # Return true or false 111 | def image? 112 | ['.png', '.jpg', '.jpeg', '.gif'].include?(extname) 113 | end 114 | 115 | MEGABYTE = 1024 * 1024 116 | 117 | # Public: Is the blob too big to load? 118 | # 119 | # Return true or false 120 | def large? 121 | size.to_i > MEGABYTE 122 | end 123 | 124 | # Public: Is the blob viewable? 125 | # 126 | # Non-viewable blobs will just show a "View Raw" link 127 | # 128 | # Return true or false 129 | def viewable? 130 | text? && !large? 131 | end 132 | 133 | vendored_paths = YAML.load_file(File.expand_path("../vendor.yml", __FILE__)) 134 | VendoredRegexp = Regexp.new(vendored_paths.join('|')) 135 | 136 | # Public: Is the blob in a vendored directory? 137 | # 138 | # Vendored files are ignored by language statistics. 139 | # 140 | # See "vendor.yml" for a list of vendored conventions that match 141 | # this pattern. 142 | # 143 | # Return true or false 144 | def vendored? 145 | name =~ VendoredRegexp ? true : false 146 | end 147 | 148 | # Public: Get each line of data 149 | # 150 | # Requires Blob#data 151 | # 152 | # Returns an Array of lines 153 | def lines 154 | @lines ||= (viewable? && data) ? data.split("\n", -1) : [] 155 | end 156 | 157 | # Public: Get number of lines of code 158 | # 159 | # Requires Blob#data 160 | # 161 | # Returns Integer 162 | def loc 163 | lines.size 164 | end 165 | 166 | # Public: Get number of source lines of code 167 | # 168 | # Requires Blob#data 169 | # 170 | # Returns Integer 171 | def sloc 172 | lines.grep(/\S/).size 173 | end 174 | 175 | # Internal: Compute average line length. 176 | # 177 | # Returns Integer. 178 | def average_line_length 179 | if lines.any? 180 | lines.inject(0) { |n, l| n += l.length } / lines.length 181 | else 182 | 0 183 | end 184 | end 185 | 186 | # Public: Is the blob a generated file? 187 | # 188 | # Generated source code is supressed in diffs and is ignored by 189 | # language statistics. 190 | # 191 | # Requires Blob#data 192 | # 193 | # Includes: 194 | # - XCode project XML files 195 | # - Visual Studio project XNL files 196 | # - Minified JavaScript 197 | # 198 | # Please add additional test coverage to 199 | # `test/test_blob.rb#test_generated` if you make any changes. 200 | # 201 | # Return true or false 202 | def generated? 203 | if xcode_project_file? || visual_studio_project_file? 204 | true 205 | elsif generated_coffeescript? || minified_javascript? || generated_net_docfile? 206 | true 207 | else 208 | false 209 | end 210 | end 211 | 212 | # Internal: Is the blob an XCode project file? 213 | # 214 | # Generated if the file extension is an XCode project 215 | # file extension. 216 | # 217 | # Returns true of false. 218 | def xcode_project_file? 219 | ['.xib', '.nib', '.pbxproj', '.xcworkspacedata', '.xcuserstate'].include?(extname) 220 | end 221 | 222 | # Internal: Is the blob a Visual Studio project file? 223 | # 224 | # Generated if the file extension is a Visual Studio project 225 | # file extension. 226 | # 227 | # Returns true of false. 228 | def visual_studio_project_file? 229 | ['.csproj', '.dbproj', '.fsproj', '.pyproj', '.rbproj', '.vbproj', '.vcxproj', '.wixproj', '.resx', '.sln', '.vdproj', '.isproj'].include?(extname) 230 | end 231 | 232 | # Internal: Is the blob minified JS? 233 | # 234 | # Consider JS minified if the average line length is 235 | # greater then 100c. 236 | # 237 | # Returns true or false. 238 | def minified_javascript? 239 | return unless extname == '.js' 240 | average_line_length > 100 241 | end 242 | 243 | # Internal: Is the blob JS generated by CoffeeScript? 244 | # 245 | # Requires Blob#data 246 | # 247 | # CoffeScript is meant to output JS that would be difficult to 248 | # tell if it was generated or not. Look for a number of patterns 249 | # outputed by the CS compiler. 250 | # 251 | # Return true or false 252 | def generated_coffeescript? 253 | return unless extname == '.js' 254 | 255 | if lines[0] == '(function() {' && # First line is module closure opening 256 | lines[-2] == '}).call(this);' && # Second to last line closes module closure 257 | lines[-1] == '' # Last line is blank 258 | 259 | score = 0 260 | 261 | lines.each do |line| 262 | if line =~ /var / 263 | # Underscored temp vars are likely to be Coffee 264 | score += 1 * line.gsub(/(_fn|_i|_len|_ref|_results)/).count 265 | 266 | # bind and extend functions are very Coffee specific 267 | score += 3 * line.gsub(/(__bind|__extends|__hasProp|__indexOf|__slice)/).count 268 | end 269 | end 270 | 271 | # Require a score of 3. This is fairly arbitrary. Consider 272 | # tweaking later. 273 | score >= 3 274 | else 275 | false 276 | end 277 | end 278 | 279 | # Internal: Is this a generated documentation file for a .NET assembly? 280 | # 281 | # Requires Blob#data 282 | # 283 | # .NET developers often check in the XML Intellisense file along with an 284 | # assembly - however, these don't have a special extension, so we have to 285 | # dig into the contents to determine if it's a docfile. Luckily, these files 286 | # are extremely structured, so recognizing them is easy. 287 | # 288 | # Returns true or false 289 | def generated_net_docfile? 290 | return false unless extname.downcase == ".xml" 291 | return false unless lines.count > 3 292 | 293 | # .NET Docfiles always open with and their first tag is an 294 | # tag 295 | return lines[1].include?("") && 296 | lines[2].include?("") && 297 | lines[-2].include?("") 298 | end 299 | 300 | # Public: Should the blob be indexed for searching? 301 | # 302 | # Excluded: 303 | # - Files over 0.1MB 304 | # - Non-text files 305 | # - Langauges marked as not searchable 306 | # - Generated source files 307 | # 308 | # Please add additional test coverage to 309 | # `test/test_blob.rb#test_indexable` if you make any changes. 310 | # 311 | # Return true or false 312 | def indexable? 313 | if binary? 314 | false 315 | elsif language.nil? 316 | false 317 | elsif !language.searchable? 318 | false 319 | elsif generated? 320 | false 321 | elsif size > 100 * 1024 322 | false 323 | else 324 | true 325 | end 326 | end 327 | 328 | # Public: Detects the Language of the blob. 329 | # 330 | # May load Blob#data 331 | # 332 | # Returns a Language or nil if none is detected 333 | def language 334 | if defined? @language 335 | @language 336 | else 337 | @language = guess_language 338 | end 339 | end 340 | 341 | # Internal: Guess language 342 | # 343 | # Please add additional test coverage to 344 | # `test/test_blob.rb#test_language` if you make any changes. 345 | # 346 | # Returns a Language or nil 347 | def guess_language 348 | return if binary? 349 | 350 | # Disambiguate between multiple language extensions 351 | disambiguate_extension_language || 352 | 353 | # See if there is a Language for the extension 354 | pathname.language || 355 | 356 | # Look for idioms in first line 357 | first_line_language || 358 | 359 | # Try to detect Language from shebang line 360 | shebang_language 361 | end 362 | 363 | # Internal: Get the lexer of the blob. 364 | # 365 | # Returns a Lexer. 366 | def lexer 367 | language ? language.lexer : Pygments::Lexer.find_by_name('Text only') 368 | end 369 | 370 | # Internal: Disambiguates between multiple language extensions. 371 | # 372 | # Delegates to "guess_EXTENSION_language". 373 | # 374 | # Please add additional test coverage to 375 | # `test/test_blob.rb#test_language` if you add another method. 376 | # 377 | # Returns a Language or nil. 378 | def disambiguate_extension_language 379 | if Language.ambiguous?(extname) 380 | name = "guess_#{extname.sub(/^\./, '')}_language" 381 | send(name) if respond_to?(name) 382 | end 383 | end 384 | 385 | # Internal: Guess language of header files (.h). 386 | # 387 | # Returns a Language. 388 | def guess_h_language 389 | if lines.grep(/^@(interface|property|private|public|end)/).any? 390 | Language['Objective-C'] 391 | elsif lines.grep(/^class |^\s+(public|protected|private):/).any? 392 | Language['C++'] 393 | else 394 | Language['C'] 395 | end 396 | end 397 | 398 | # Internal: Guess language of .m files. 399 | # 400 | # Objective-C heuristics: 401 | # * Keywords 402 | # 403 | # Matlab heuristics: 404 | # * Leading function keyword 405 | # * "%" comments 406 | # 407 | # Returns a Language. 408 | def guess_m_language 409 | # Objective-C keywords 410 | if lines.grep(/^#import|@(interface|implementation|property|synthesize|end)/).any? 411 | Language['Objective-C'] 412 | 413 | # File function 414 | elsif lines.first.to_s =~ /^function / 415 | Language['Matlab'] 416 | 417 | # Matlab comment 418 | elsif lines.grep(/^%/).any? 419 | Language['Matlab'] 420 | 421 | # Fallback to Objective-C, don't want any Matlab false positives 422 | else 423 | Language['Objective-C'] 424 | end 425 | end 426 | 427 | # Internal: Guess language of .pl files 428 | # 429 | # The rules for disambiguation are: 430 | # 431 | # 1. Many perl files begin with a shebang 432 | # 2. Most Prolog source files have a rule somewhere (marked by the :- operator) 433 | # 3. Default to Perl, because it is more popular 434 | # 435 | # Returns a Language. 436 | def guess_pl_language 437 | if shebang_script == 'perl' 438 | Language['Perl'] 439 | elsif lines.grep(/:-/).any? 440 | Language['Prolog'] 441 | else 442 | Language['Perl'] 443 | end 444 | end 445 | 446 | # Internal: Guess language of .r files. 447 | # 448 | # Returns a Language. 449 | def guess_r_language 450 | if lines.grep(/(rebol|(:\s+func|make\s+object!|^\s*context)\s*\[)/i).any? 451 | Language['Rebol'] 452 | else 453 | Language['R'] 454 | end 455 | end 456 | 457 | # Internal: Guess language of .gsp files. 458 | # 459 | # Returns a Language. 460 | def guess_gsp_language 461 | if lines.grep(/<%|<%@|\$\{|<%| 'ruby' 490 | # 491 | # '#!/usr/bin/env ruby' 492 | # # => 'ruby' 493 | # 494 | # '#!/usr/bash/python2.4' 495 | # # => 'python' 496 | # 497 | # Please add additional test coverage to 498 | # `test/test_blob.rb#test_shebang_script` if you make any changes. 499 | # 500 | # Returns a script name String or nil 501 | def shebang_script 502 | # Fail fast if blob isn't viewable? 503 | return unless viewable? 504 | 505 | if lines.any? && (match = lines[0].match(/(.+)\n?/)) && (bang = match[0]) =~ /^#!/ 506 | bang.sub!(/^#! /, '#!') 507 | tokens = bang.split(' ') 508 | pieces = tokens.first.split('/') 509 | if pieces.size > 1 510 | script = pieces.last 511 | else 512 | script = pieces.first.sub('#!', '') 513 | end 514 | 515 | script = script == 'env' ? tokens[1] : script 516 | 517 | # python2.4 => python 518 | if script =~ /((?:\d+\.?)+)/ 519 | script.sub! $1, '' 520 | end 521 | 522 | # Check for multiline shebang hacks that exec themselves 523 | # 524 | # #!/bin/sh 525 | # exec foo "$0" "$@" 526 | # 527 | if script == 'sh' && 528 | lines[0...5].any? { |l| l.match(/exec (\w+).+\$0.+\$@/) } 529 | script = $1 530 | end 531 | 532 | script 533 | end 534 | end 535 | 536 | # Internal: Get Language for shebang script 537 | # 538 | # Returns the Language or nil 539 | def shebang_language 540 | if script = shebang_script 541 | Language[script] 542 | end 543 | end 544 | 545 | # Public: Highlight syntax of blob 546 | # 547 | # options - A Hash of options (defaults to {}) 548 | # 549 | # Returns html String 550 | def colorize(options = {}) 551 | return if !text? || large? 552 | options[:options] ||= {} 553 | options[:options][:encoding] ||= encoding 554 | lexer.highlight(data, options) 555 | end 556 | 557 | # Public: Highlight syntax of blob without the outer highlight div 558 | # wrapper. 559 | # 560 | # options - A Hash of options (defaults to {}) 561 | # 562 | # Returns html String 563 | def colorize_without_wrapper(options = {}) 564 | return if !text? || large? 565 | if text = colorize(options) 566 | text[%r{
(.*?)
\s*
}m, 1] 567 | else 568 | '' 569 | end 570 | end 571 | 572 | Language.overridden_extensions.each do |extension| 573 | name = "guess_#{extension.sub(/^\./, '')}_language".to_sym 574 | unless instance_methods.map(&:to_sym).include?(name) 575 | warn "Language##{name} was not defined" 576 | end 577 | end 578 | end 579 | end 580 | -------------------------------------------------------------------------------- /test/test_blob.rb: -------------------------------------------------------------------------------- 1 | require 'linguist/file_blob' 2 | 3 | require 'test/unit' 4 | require 'mime/types' 5 | require 'pygments' 6 | 7 | class TestBlob < Test::Unit::TestCase 8 | include Linguist 9 | 10 | Lexer = Pygments::Lexer 11 | 12 | def fixtures_path 13 | File.expand_path("../fixtures", __FILE__) 14 | end 15 | 16 | def blob(name) 17 | FileBlob.new(File.join(fixtures_path, name), fixtures_path) 18 | end 19 | 20 | def test_name 21 | assert_equal "foo.rb", blob("foo.rb").name 22 | end 23 | 24 | def test_pathname 25 | assert_equal Pathname.new("foo.rb"), blob("foo.rb").pathname 26 | end 27 | 28 | def test_mime_type 29 | assert_equal "application/octet-stream", blob("dog.o").mime_type 30 | assert_equal "application/postscript", blob("octocat.ai").mime_type 31 | assert_equal "application/ruby", blob("grit.rb").mime_type 32 | assert_equal "application/sh", blob("script.sh").mime_type 33 | assert_equal "application/xml", blob("bar.xml").mime_type 34 | assert_equal "text/plain", blob("README").mime_type 35 | end 36 | 37 | def test_content_type 38 | assert_equal "application/octet-stream", blob("dog.o").content_type 39 | assert_equal "application/pdf", blob("foo.pdf").content_type 40 | assert_equal "image/png", blob("foo.png").content_type 41 | assert_equal "text/plain; charset=iso-8859-2", blob("README").content_type 42 | assert_equal "text/plain; charset=iso-8859-1", blob("script.pl").content_type 43 | assert_equal "text/plain; charset=iso-8859-1", blob("script.py").content_type 44 | assert_equal "text/plain; charset=iso-8859-1", blob("script.rb").content_type 45 | assert_equal "text/plain; charset=iso-8859-1", blob("script.sh").content_type 46 | end 47 | 48 | def test_disposition 49 | assert_equal "attachment; filename=foo+bar.jar", blob("foo bar.jar").disposition 50 | assert_equal "attachment; filename=foo.bin", blob("foo.bin").disposition 51 | assert_equal "attachment; filename=linguist.gem", blob("pkg/linguist.gem").disposition 52 | assert_equal "attachment; filename=octocat.ai", blob("octocat.ai").disposition 53 | assert_equal "inline", blob("README").disposition 54 | assert_equal "inline", blob("foo.txt").disposition 55 | assert_equal "inline", blob("grit.rb").disposition 56 | assert_equal "inline", blob("octocat.png").disposition 57 | end 58 | 59 | def test_data 60 | assert_equal "module Foo\nend\n", blob("foo.rb").data 61 | end 62 | 63 | def test_lines 64 | assert_equal ["module Foo", "end", ""], blob("foo.rb").lines 65 | end 66 | 67 | def test_size 68 | assert_equal 15, blob("foo.rb").size 69 | end 70 | 71 | def test_loc 72 | assert_equal 3, blob("foo.rb").loc 73 | end 74 | 75 | def test_sloc 76 | assert_equal 2, blob("foo.rb").sloc 77 | end 78 | 79 | def test_encoding 80 | assert_equal "ISO-8859-2", blob("README").encoding 81 | assert_equal "ISO-8859-1", blob("dump.sql").encoding 82 | assert_equal "UTF-8", blob("file.txt").encoding 83 | assert_nil blob("dog.o").encoding 84 | end 85 | 86 | def test_binary 87 | assert blob("git.deb").binary? 88 | assert blob("git.exe").binary? 89 | assert blob("hello.pbc").binary? 90 | assert blob("linguist.gem").binary? 91 | assert blob("octocat.ai").binary? 92 | assert blob("octocat.png").binary? 93 | assert blob("zip").binary? 94 | assert !blob("README").binary? 95 | assert !blob("file.txt").binary? 96 | assert !blob("foo.rb").binary? 97 | assert !blob("script.pl").binary? 98 | end 99 | 100 | def test_text 101 | assert blob("README").text? 102 | assert blob("dump.sql").text? 103 | assert blob("file.json").text? 104 | assert blob("file.txt").text? 105 | assert blob("md").text? 106 | assert blob("script.sh").text? 107 | assert blob("tender.md").text? 108 | assert blob("txt").text? 109 | end 110 | 111 | def test_image 112 | assert blob("octocat.gif").image? 113 | assert blob("octocat.jpeg").image? 114 | assert blob("octocat.jpg").image? 115 | assert blob("octocat.png").image? 116 | assert !blob("octocat.ai").image? 117 | assert !blob("octocat.psd").image? 118 | end 119 | 120 | def test_viewable 121 | assert blob("README").viewable? 122 | assert blob("foo.rb").viewable? 123 | assert blob("script.pl").viewable? 124 | assert !blob("linguist.gem").viewable? 125 | assert !blob("octocat.ai").viewable? 126 | assert !blob("octocat.png").viewable? 127 | end 128 | 129 | def test_generated 130 | assert !blob("README").generated? 131 | assert blob("MainMenu.xib").generated? 132 | assert blob("MainMenu.nib").generated? 133 | assert blob("project.pbxproj").generated? 134 | 135 | # Visual Studio Files 136 | assert blob("project.csproj").generated? 137 | assert blob("project.dbproj").generated? 138 | assert blob("project.isproj").generated? 139 | assert blob("project.pyproj").generated? 140 | assert blob("project.rbproj").generated? 141 | assert blob("project.vbproj").generated? 142 | assert blob("project.vdproj").generated? 143 | assert blob("project.vcxproj").generated? 144 | assert blob("project.wixproj").generated? 145 | assert blob("project.resx").generated? 146 | assert blob("project.sln").generated? 147 | 148 | # Generated .NET Docfiles 149 | assert blob("net_docfile.xml").generated? 150 | 151 | # Long line 152 | assert !blob("uglify.js").generated? 153 | 154 | # Inlined JS, but mostly code 155 | assert !blob("json2_backbone.js").generated? 156 | 157 | # Minified JS 158 | assert !blob("jquery-1.6.1.js").generated? 159 | assert blob("jquery-1.6.1.min.js").generated? 160 | assert blob("jquery-1.4.2.min.js").generated? 161 | 162 | # CoffeScript JS 163 | 164 | # These examples are to basic to tell 165 | assert !blob("coffee/empty.js").generated? 166 | assert !blob("coffee/hello.js").generated? 167 | 168 | assert blob("coffee/intro.js").generated? 169 | assert blob("coffee/classes.js").generated? 170 | end 171 | 172 | def test_vendored 173 | assert !blob("README").vendored? 174 | 175 | # Node depedencies 176 | assert blob("node_modules/coffee-script/lib/coffee-script.js").vendored? 177 | 178 | # Rails vendor/ 179 | assert blob("vendor/plugins/will_paginate/lib/will_paginate.rb").vendored? 180 | 181 | # C deps 182 | assert blob("deps/http_parser/http_parser.c").vendored? 183 | assert blob("deps/v8/src/v8.h").vendored? 184 | 185 | # Prototype 186 | assert !blob("public/javascripts/application.js").vendored? 187 | assert blob("public/javascripts/prototype.js").vendored? 188 | assert blob("public/javascripts/effects.js").vendored? 189 | assert blob("public/javascripts/controls.js").vendored? 190 | assert blob("public/javascripts/dragdrop.js").vendored? 191 | 192 | # jQuery 193 | assert blob("jquery.js").vendored? 194 | assert blob("public/javascripts/jquery.js").vendored? 195 | assert blob("public/javascripts/jquery.min.js").vendored? 196 | assert blob("public/javascripts/jquery-1.5.2.js").vendored? 197 | assert blob("public/javascripts/jquery-1.6.1.js").vendored? 198 | assert blob("public/javascripts/jquery-1.6.1.min.js").vendored? 199 | assert !blob("public/javascripts/jquery.github.menu.js").vendored? 200 | 201 | # MooTools 202 | assert blob("public/javascripts/mootools-core-1.3.2-full-compat.js").vendored? 203 | assert blob("public/javascripts/mootools-core-1.3.2-full-compat-yc.js").vendored? 204 | 205 | # Dojo 206 | assert blob("public/javascripts/dojo.js").vendored? 207 | 208 | # MochiKit 209 | assert blob("public/javascripts/MochiKit.js").vendored? 210 | 211 | # YUI 212 | assert blob("public/javascripts/yahoo-dom-event.js").vendored? 213 | assert blob("public/javascripts/yahoo-min.js").vendored? 214 | assert blob("public/javascripts/yuiloader-dom-event.js").vendored? 215 | 216 | # LESS 217 | assert blob("public/javascripts/less-1.1.0.js").vendored? 218 | assert blob("public/javascripts/less-1.1.0.min.js").vendored? 219 | 220 | # WYS editors 221 | assert blob("public/javascripts/ckeditor.js").vendored? 222 | assert blob("public/javascripts/tiny_mce.js").vendored? 223 | assert blob("public/javascripts/tiny_mce_popup.js").vendored? 224 | assert blob("public/javascripts/tiny_mce_src.js").vendored? 225 | 226 | # Fabric 227 | assert blob("fabfile.py").vendored? 228 | 229 | # WAF 230 | assert blob("waf").vendored? 231 | end 232 | 233 | def test_indexable 234 | assert blob("file.txt").indexable? 235 | assert blob("foo.rb").indexable? 236 | assert !blob("defun.kt").indexable? 237 | assert !blob("dump.sql").indexable? 238 | assert !blob("github.po").indexable? 239 | assert !blob("linguist.gem").indexable? 240 | end 241 | 242 | def test_language 243 | assert_equal Language['C'], blob("hello.c").language 244 | assert_equal Language['C'], blob("hello.h").language 245 | assert_equal Language['C++'], blob("bar.h").language 246 | assert_equal Language['C++'], blob("bar.hpp").language 247 | assert_equal Language['C++'], blob("hello.cpp").language 248 | assert_equal Language['C++'], blob("cuda.cu").language 249 | assert_equal Language['GAS'], blob("hello.s").language 250 | assert_equal Language['Objective-C'], blob("Foo.h").language 251 | assert_equal Language['Objective-C'], blob("Foo.m").language 252 | assert_equal Language['Objective-C'], blob("FooAppDelegate.h").language 253 | assert_equal Language['Objective-C'], blob("FooAppDelegate.m").language 254 | assert_equal Language['Objective-C'], blob("hello.m").language 255 | assert_equal Language['OpenCL'], blob("fft.cl").language 256 | assert_equal Language['Ruby'], blob("foo.rb").language 257 | assert_equal Language['Ruby'], blob("script.rb").language 258 | assert_equal Language['Ruby'], blob("wrong_shebang.rb").language 259 | assert_nil blob("octocat.png").language 260 | 261 | # .pl disambiguation 262 | assert_equal Language['Prolog'], blob("test-prolog.pl").language 263 | assert_equal Language['Perl'], blob("test-perl.pl").language 264 | assert_equal Language['Perl'], blob("test-perl2.pl").language 265 | 266 | # .m disambiguation 267 | assert_equal Language['Objective-C'], blob("Foo.m").language 268 | assert_equal Language['Objective-C'], blob("hello.m").language 269 | assert_equal Language['Matlab'], blob("matlab_function.m").language 270 | assert_equal Language['Matlab'], blob("matlab_script.m").language 271 | 272 | # .r disambiguation 273 | assert_equal Language['R'], blob("hello-r.R").language 274 | assert_equal Language['Rebol'], blob("hello-rebol.r").language 275 | 276 | # ML 277 | assert_equal Language['OCaml'], blob("Foo.ml").language 278 | assert_equal Language['Standard ML'], blob("Foo.sig").language 279 | assert_equal Language['Standard ML'], blob("Foo.sml").language 280 | 281 | # Config files 282 | assert_equal Language['INI'], blob(".gitconfig").language 283 | assert_equal Language['Shell'], blob(".bash_profile").language 284 | assert_equal Language['Shell'], blob(".bashrc").language 285 | assert_equal Language['Shell'], blob(".profile").language 286 | assert_equal Language['Shell'], blob(".zlogin").language 287 | assert_equal Language['Shell'], blob(".zshrc").language 288 | assert_equal Language['VimL'], blob(".gvimrc").language 289 | assert_equal Language['VimL'], blob(".vimrc").language 290 | assert_equal Language['YAML'], blob(".gemrc").language 291 | 292 | assert_nil blob("blank").language 293 | assert_nil blob("README").language 294 | 295 | # https://github.com/xquery/xprocxq/blob/master/src/xquery/xproc.xqm 296 | assert_equal Language['XQuery'], blob("xproc.xqm").language 297 | 298 | # https://github.com/wycats/osx-window-sizing/blob/master/center.applescript 299 | assert_equal Language['AppleScript'], blob("center.scpt").language 300 | assert_equal Language['AppleScript'], blob("center.applescript").language 301 | 302 | # https://github.com/Araq/Nimrod/tree/master/examples 303 | assert_equal Language['Nimrod'], blob("foo.nim").language 304 | 305 | # http://supercollider.sourceforge.net/ 306 | # https://github.com/drichert/BCR2000.sc/blob/master/BCR2000.sc 307 | assert_equal Language['SuperCollider'], blob("BCR2000.sc").language 308 | 309 | # https://github.com/harrah/xsbt/wiki/Quick-Configuration-Examples 310 | assert_equal Language['Scala'], blob('build.sbt').language 311 | 312 | # https://github.com/gradleware/oreilly-gradle-book-examples/blob/master/ant-antbuilder/build.gradle 313 | assert_equal Language['Groovy'], blob("build.gradle").language 314 | 315 | # http://docs.racket-lang.org/scribble/ 316 | assert_equal Language['Racket'], blob("scribble.scrbl").language 317 | 318 | # https://github.com/drupal/drupal/blob/7.x/modules/php/php.module 319 | assert_equal Language['PHP'], blob("drupal.module").language 320 | 321 | # https://github.com/googleapi/googleapi/blob/master/demos/gmail_demo/gmail.dpr 322 | assert_equal Language['Delphi'], blob("program.dpr").language 323 | 324 | # https://github.com/philiplaureano/Nemerle.FizzBuzz/blob/master/FizzBuzz/FizzBuzzer.n 325 | assert_equal Language['Nemerle'], blob("hello.n").language 326 | 327 | # https://github.com/dharmatech/agave/blob/master/demos/asteroids.sps 328 | assert_equal Language['Scheme'], blob("asteroids.sps").language 329 | 330 | # https://github.com/graydon/rust 331 | assert_equal Language['Rust'], blob("hello.rs").language 332 | 333 | # https://github.com/olabini/ioke 334 | assert_equal Language['Ioke'], blob("hello.ik").language 335 | 336 | # https://github.com/parrot/parrot 337 | assert_equal Language['Parrot Internal Representation'], blob("hello.pir").language 338 | assert_equal Language['Parrot Assembly'], blob("hello.pasm").language 339 | 340 | # http://gosu-lang.org 341 | assert_equal Language['Gosu'], blob("Hello.gsx").language 342 | assert_equal Language['Gosu'], blob("hello.gsp").language 343 | assert_equal Language['Gosu'], blob("Hello.gst").language 344 | assert_equal Language['Gosu'], blob("hello.vark").language 345 | 346 | # Groovy Server Pages 347 | assert_equal Language['Groovy Server Pages'], blob("bar.gsp").language 348 | assert_equal Language['Groovy Server Pages'], blob("hello-resources.gsp").language 349 | assert_equal Language['Groovy Server Pages'], blob("hello-pagedirective.gsp").language 350 | assert_equal Language['Groovy Server Pages'], blob("hello-var.gsp").language 351 | 352 | # https://github.com/Lexikos/AutoHotkey_L 353 | assert_equal Language['AutoHotkey'], blob("hello.ahk").language 354 | 355 | # Haml 356 | assert_equal Language['Haml'], blob("hello.haml").language 357 | assert_equal Language['HTML'], blob("hello.haml").language.group 358 | 359 | # Sass 360 | assert_equal Language['Sass'], blob("screen.sass").language 361 | assert_equal Language['CSS'], blob("screen.sass").language.group 362 | assert_equal Language['SCSS'], blob("screen.scss").language 363 | assert_equal Language['CSS'], blob("screen.scss").language.group 364 | end 365 | 366 | def test_lexer 367 | assert_equal Lexer['Diff'], blob("dude-thing-okay--001.patch").lexer 368 | assert_equal Lexer['JavaScript'], blob("dude.js").lexer 369 | assert_equal Lexer['Ruby'], blob("Capfile").lexer 370 | assert_equal Lexer['Ruby'], blob("grit.rb").lexer 371 | assert_equal Lexer['Scheme'], blob("dude.el").lexer 372 | assert_equal Lexer['Text only'], blob("README").lexer 373 | end 374 | 375 | def test_shebang_script 376 | assert_equal 'sh', blob("script.sh").shebang_script 377 | assert_equal 'bash', blob("script.bash").shebang_script 378 | assert_equal 'zsh', blob("script.zsh").shebang_script 379 | assert_equal 'perl', blob("script.pl").shebang_script 380 | assert_equal 'ruby', blob("script.rb").shebang_script 381 | assert_equal 'ruby', blob("script2.rb").shebang_script 382 | assert_equal 'python', blob("script.py").shebang_script 383 | assert_equal 'node', blob("script.js").shebang_script 384 | assert_equal 'groovy', blob("script.groovy").shebang_script 385 | assert_equal 'macruby', blob("script.mrb").shebang_script 386 | assert_equal 'rake', blob("script.rake").shebang_script 387 | assert_equal 'foo', blob("script.foo").shebang_script 388 | assert_equal 'nush', blob("script.nu").shebang_script 389 | assert_equal 'scala', blob("script.scala").shebang_script 390 | assert_equal 'racket', blob("script.rkt").shebang_script 391 | assert_equal nil, blob("foo.rb").shebang_script 392 | end 393 | 394 | def test_shebang_language 395 | assert_equal Language['Shell'], blob("script.sh").shebang_language 396 | assert_equal Language['Shell'], blob("script.bash").shebang_language 397 | assert_equal Language['Shell'], blob("script.zsh").shebang_language 398 | assert_equal Language['Perl'], blob("script.pl").shebang_language 399 | assert_equal Language['Ruby'], blob("script.rb").shebang_language 400 | assert_equal Language['Python'], blob("script.py").shebang_language 401 | assert_equal Language['JavaScript'], blob("script.js").shebang_language 402 | assert_equal Language['Groovy'], blob("script.groovy").shebang_language 403 | assert_equal Language['Ruby'], blob("script.mrb").shebang_language 404 | assert_equal Language['Ruby'], blob("script.rake").shebang_language 405 | assert_equal Language['Nu'], blob("script.nu").shebang_language 406 | assert_equal Language['Scala'], blob("script.scala").shebang_language 407 | assert_equal Language['Racket'], blob("script.rkt").shebang_language 408 | assert_equal nil, blob("script.foo").shebang_language 409 | assert_equal nil, blob("foo.rb").shebang_language 410 | end 411 | 412 | def test_colorize 413 | assert_equal <<-HTML, blob("foo.rb").colorize 414 |
module Foo
415 | end
416 | 
417 |
418 | HTML 419 | end 420 | 421 | def test_colorize_without_wrapper 422 | assert_equal <<-HTML, blob("foo.rb").colorize_without_wrapper 423 | module Foo 424 | end 425 | HTML 426 | end 427 | end 428 | -------------------------------------------------------------------------------- /lib/linguist/languages.yml: -------------------------------------------------------------------------------- 1 | # Defines all Languages known to GitHub. 2 | # 3 | # All languages have an associated lexer for syntax highlighting. It 4 | # defaults to name.downcase, which covers most cases. Make sure the 5 | # lexer exists in lexers.yml. This is a list of available in our 6 | # version of pygments. 7 | # 8 | # type - Either data, programming, markup, or nil 9 | # lexer - An explicit lexer String (defaults to name.downcase) 10 | # aliases - An Array of additional aliases (implicitly 11 | # includes name.downcase) 12 | # extension - An Array of associated extensions 13 | # primary_extension - A String for the main extension associated with 14 | # the langauge. (defaults to extensions.first) 15 | # overrides - An Array of extensions that takes precedence over conflicts 16 | # searchable - Boolean flag to enable searching (defaults to true) 17 | # search_term - Deprecated: Some languages maybe indexed under a 18 | # different alias. Avoid defining new exceptions. 19 | # 20 | # Any additions or modifications (even trivial) should have corresponding 21 | # test change in `test/test_blob.rb`. 22 | # 23 | # Please keep this list alphabetized. 24 | 25 | ASP: 26 | type: programming 27 | lexer: aspx-vb 28 | search_term: aspx-vb 29 | aliases: 30 | - aspx 31 | - aspx-vb 32 | primary_extension: .asp 33 | extensions: 34 | - .asax 35 | - .ascx 36 | - .ashx 37 | - .asmx 38 | - .asp 39 | - .aspx 40 | - .axd 41 | 42 | ActionScript: 43 | type: programming 44 | lexer: ActionScript 3 45 | search_term: as3 46 | aliases: 47 | - as3 48 | extensions: 49 | - .as 50 | 51 | Ada: 52 | type: programming 53 | extensions: 54 | - .adb 55 | - .ads 56 | 57 | AppleScript: 58 | primary_extension: .scpt 59 | extensions: 60 | - .applescript 61 | - .scpt 62 | 63 | Arc: 64 | type: programming 65 | lexer: Text only 66 | extensions: 67 | - .arc 68 | 69 | Assembly: 70 | type: programming 71 | lexer: NASM 72 | search_term: nasm 73 | aliases: 74 | - nasm 75 | extensions: 76 | - .asm 77 | 78 | AutoHotkey: 79 | type: programming 80 | lexer: autohotkey 81 | aliases: 82 | - ahk 83 | extensions: 84 | - .ahk 85 | 86 | Batchfile: 87 | type: programming 88 | group: Shell 89 | search_term: bat 90 | aliases: 91 | - bat 92 | primary_extension: .bat 93 | extensions: 94 | - .bat 95 | - .cmd 96 | 97 | Befunge: 98 | extensions: 99 | - .befunge 100 | 101 | BlitzMax: 102 | extensions: 103 | - .bmx 104 | 105 | Boo: 106 | type: programming 107 | extensions: 108 | - .boo 109 | 110 | Brainfuck: 111 | extensions: 112 | - .b 113 | - .bf 114 | 115 | C: 116 | type: programming 117 | overrides: 118 | - .h 119 | primary_extension: .c 120 | extensions: 121 | - .c 122 | - .h 123 | 124 | C#: 125 | type: programming 126 | search_term: csharp 127 | aliases: 128 | - csharp 129 | extensions: 130 | - .cs 131 | 132 | C++: 133 | type: programming 134 | search_term: cpp 135 | aliases: 136 | - cpp 137 | primary_extension: .cpp 138 | extensions: 139 | - .c++ 140 | - .cc 141 | - .cpp 142 | - .cu 143 | - .cxx 144 | - .h 145 | - .h++ 146 | - .hh 147 | - .hpp 148 | - .hxx 149 | - .tcc 150 | 151 | C-ObjDump: 152 | type: data 153 | lexer: c-objdump 154 | extensions: 155 | - .c-objdump 156 | 157 | CMake: 158 | extensions: 159 | - .cmake 160 | - .cmake.in 161 | filenames: 162 | - CMakeLists.txt 163 | 164 | CSS: 165 | extensions: 166 | - .css 167 | 168 | ChucK: 169 | lexer: Java 170 | extensions: 171 | - .ck 172 | 173 | Clojure: 174 | type: programming 175 | primary_extension: .clj 176 | extensions: 177 | - .clj 178 | - .cljs 179 | 180 | CoffeeScript: 181 | type: programming 182 | aliases: 183 | - coffee 184 | extensions: 185 | - .coffee 186 | filenames: 187 | - Cakefile 188 | 189 | ColdFusion: 190 | type: programming 191 | lexer: Coldfusion HTML 192 | search_term: cfm 193 | aliases: 194 | - cfm 195 | primary_extension: .cfm 196 | extensions: 197 | - .cfc 198 | - .cfm 199 | 200 | Common Lisp: 201 | type: programming 202 | aliases: 203 | - lisp 204 | primary_extension: .lisp 205 | extensions: 206 | - .lisp 207 | - .ny 208 | 209 | Cpp-ObjDump: 210 | type: data 211 | lexer: cpp-objdump 212 | extensions: 213 | - .cppobjdump 214 | - .c++objdump 215 | - .cxx-objdump 216 | 217 | Cucumber: 218 | lexer: Gherkin 219 | extensions: 220 | - .feature 221 | 222 | Cython: 223 | type: programming 224 | group: Python 225 | primary_extension: .pyx 226 | extensions: 227 | - .pxd 228 | - .pxi 229 | - .pyx 230 | 231 | D: 232 | type: programming 233 | extensions: 234 | - .d 235 | - .di 236 | 237 | D-ObjDump: 238 | type: data 239 | lexer: d-objdump 240 | extensions: 241 | - .d-objdump 242 | 243 | Darcs Patch: 244 | search_term: dpatch 245 | aliases: 246 | - dpatch 247 | extensions: 248 | - .darcspatch 249 | - .dpatch 250 | 251 | Delphi: 252 | type: programming 253 | primary_extension: .pas 254 | extensions: 255 | - .dpr 256 | - .pas 257 | 258 | Diff: 259 | extensions: 260 | - .diff 261 | - .patch 262 | 263 | Dylan: 264 | type: programming 265 | extensions: 266 | - .dylan 267 | 268 | Eiffel: 269 | type: programming 270 | lexer: Text only 271 | extensions: 272 | - .e 273 | 274 | Emacs Lisp: 275 | type: programming 276 | lexer: Scheme 277 | aliases: 278 | - elisp 279 | primary_extension: .el 280 | extensions: 281 | - .el 282 | - .emacs 283 | 284 | Erlang: 285 | type: programming 286 | primary_extension: .erl 287 | extensions: 288 | - .erl 289 | - .hrl 290 | 291 | F#: 292 | type: programming 293 | lexer: OCaml 294 | search_term: ocaml 295 | extensions: 296 | - .fs 297 | - .fsi 298 | - .fsx 299 | 300 | FORTRAN: 301 | type: programming 302 | lexer: Fortran 303 | primary_extension: .f90 304 | extensions: 305 | - .F 306 | - .F90 307 | - .f 308 | - .f90 309 | 310 | Factor: 311 | type: programming 312 | extensions: 313 | - .factor 314 | 315 | Fancy: 316 | type: programming 317 | primary_extension: .fy 318 | extensions: 319 | - .fancypack 320 | - .fy 321 | 322 | GAS: 323 | type: programming 324 | group: Assembly 325 | primary_extension: .s 326 | extensions: 327 | - .S 328 | - .s 329 | 330 | Genshi: 331 | extensions: 332 | - .kid 333 | 334 | Gentoo Ebuild: 335 | group: Shell 336 | lexer: Bash 337 | extensions: 338 | - .ebuild 339 | 340 | Gentoo Eclass: 341 | group: Shell 342 | lexer: Bash 343 | extensions: 344 | - .eclass 345 | 346 | Gettext Catalog: 347 | search_term: pot 348 | searchable: false 349 | aliases: 350 | - pot 351 | extensions: 352 | - .po 353 | - .pot 354 | 355 | Go: 356 | type: programming 357 | extensions: 358 | - .go 359 | 360 | Gosu: 361 | type: programming 362 | primary_extension: .gs 363 | extensions: 364 | - .gs 365 | - .gsp 366 | - .gst 367 | - .gsx 368 | - .vark 369 | 370 | Groff: 371 | primary_extension: .man 372 | extensions: 373 | - '.1' 374 | - '.2' 375 | - '.3' 376 | - '.4' 377 | - '.5' 378 | - '.6' 379 | - '.7' 380 | - .man 381 | 382 | Groovy: 383 | type: programming 384 | lexer: Java 385 | primary_extension: .groovy 386 | extensions: 387 | - .gradle 388 | - .groovy 389 | 390 | Groovy Server Pages: 391 | group: Groovy 392 | lexer: Java Server Page 393 | overrides: 394 | - .gsp 395 | aliases: 396 | - gsp 397 | extensions: 398 | - .gsp 399 | 400 | HTML: 401 | type: markup 402 | primary_extension: .html 403 | extensions: 404 | - .htm 405 | - .html 406 | - .xhtml 407 | - .xslt 408 | 409 | HTML+Django: 410 | type: markup 411 | group: HTML 412 | lexer: HTML+Django/Jinja 413 | extensions: 414 | - .mustache 415 | 416 | HTML+ERB: 417 | type: markup 418 | group: HTML 419 | lexer: RHTML 420 | primary_extension: .erb 421 | extensions: 422 | - .erb 423 | - .html.erb 424 | 425 | HTML+PHP: 426 | type: markup 427 | group: HTML 428 | extensions: 429 | - .phtml 430 | 431 | HaXe: 432 | type: programming 433 | lexer: haXe 434 | extensions: 435 | - .hx 436 | - .hxml 437 | - .mtt 438 | 439 | Haml: 440 | group: HTML 441 | type: markup 442 | extensions: 443 | - .haml 444 | 445 | Haskell: 446 | type: programming 447 | extensions: 448 | - .hs 449 | - .hsc 450 | 451 | INI: 452 | type: data 453 | extensions: 454 | - .cfg 455 | - .ini 456 | - .prefs 457 | - .properties 458 | filenames: 459 | - .gitconfig 460 | 461 | IRC log: 462 | lexer: IRC logs 463 | search_term: irc 464 | aliases: 465 | - irc 466 | extensions: 467 | - .weechatlog 468 | 469 | Io: 470 | type: programming 471 | extensions: 472 | - .io 473 | 474 | Ioke: 475 | type: programming 476 | extensions: 477 | - .ik 478 | 479 | JSON: 480 | type: data 481 | group: JavaScript 482 | lexer: JavaScript 483 | searchable: false 484 | extensions: 485 | - .json 486 | 487 | Java: 488 | type: programming 489 | extensions: 490 | - .java 491 | - .pde 492 | 493 | Java Server Pages: 494 | group: Java 495 | lexer: Java Server Page 496 | search_term: jsp 497 | aliases: 498 | - jsp 499 | extensions: 500 | - .jsp 501 | 502 | JavaScript: 503 | type: programming 504 | aliases: 505 | - js 506 | - node 507 | primary_extension: .js 508 | extensions: 509 | - .jake 510 | - .js 511 | - .jsm 512 | - .jss 513 | - .jsx 514 | - .sjs 515 | - .ssjs 516 | filenames: 517 | - Jakefile 518 | 519 | LLVM: 520 | extensions: 521 | - .ll 522 | 523 | LilyPond: 524 | lexer: Text only 525 | primary_extension: .ly 526 | extensions: 527 | - .ily 528 | - .ly 529 | 530 | Literate Haskell: 531 | type: programming 532 | group: Haskell 533 | search_term: lhs 534 | aliases: 535 | - lhs 536 | extensions: 537 | - .lhs 538 | 539 | Lua: 540 | type: programming 541 | primary_extension: .lua 542 | extensions: 543 | - .lua 544 | - .nse 545 | 546 | Makefile: 547 | extensions: 548 | - .mak 549 | filenames: 550 | - Makefile 551 | 552 | Mako: 553 | extensions: 554 | - .mao 555 | 556 | Markdown: 557 | type: markup 558 | lexer: Text only 559 | primary_extension: .md 560 | extensions: 561 | - .markdown 562 | - .md 563 | - .mkd 564 | - .mkdown 565 | - .ron 566 | 567 | Matlab: 568 | type: programming 569 | primary_extension: .matlab 570 | extensions: 571 | - .m 572 | - .matlab 573 | 574 | Max/MSP: 575 | type: programming 576 | lexer: Text only 577 | extensions: 578 | - .mxt 579 | 580 | MiniD: # Legacy 581 | searchable: false 582 | primary_extension: .minid # Dummy extension 583 | 584 | Mirah: 585 | type: programming 586 | lexer: Ruby 587 | search_term: ruby 588 | extensions: 589 | - .duby 590 | - .mir 591 | - .mirah 592 | 593 | Moocode: 594 | lexer: MOOCode 595 | extensions: 596 | - .moo 597 | 598 | Myghty: 599 | extensions: 600 | - .myt 601 | 602 | Nemerle: 603 | type: programming 604 | extensions: 605 | - .n 606 | 607 | Nimrod: 608 | extensions: 609 | - .nim 610 | 611 | Nu: 612 | type: programming 613 | lexer: Scheme 614 | aliases: 615 | - nush 616 | extensions: 617 | - .nu 618 | filenames: 619 | - Nukefile 620 | 621 | NumPy: 622 | group: Python 623 | primary_extension: .numpy 624 | extensions: 625 | - .numpy 626 | - .numpyw 627 | - .numsc 628 | 629 | OCaml: 630 | type: programming 631 | primary_extension: .ml 632 | extensions: 633 | - .ml 634 | - .mli 635 | - .mll 636 | - .mly 637 | 638 | ObjDump: 639 | type: data 640 | lexer: objdump 641 | extensions: 642 | - .objdump 643 | 644 | Objective-C: 645 | type: programming 646 | overrides: 647 | - .m 648 | primary_extension: .m 649 | extensions: 650 | - .h 651 | - .m 652 | - .mm 653 | 654 | Objective-J: 655 | type: programming 656 | extensions: 657 | - .j 658 | - .sj 659 | 660 | OpenCL: 661 | type: programming 662 | group: C 663 | lexer: C 664 | extensions: 665 | - .cl 666 | 667 | PHP: 668 | type: programming 669 | extensions: 670 | - .aw 671 | - .ctp 672 | - .php 673 | - .php3 674 | - .php4 675 | - .php5 676 | - .phpt 677 | 678 | Parrot: 679 | type: programming 680 | lexer: Text only 681 | primary_extension: .parrot # Dummy extension 682 | 683 | Parrot Internal Representation: 684 | group: Parrot 685 | type: programming 686 | lexer: Text only 687 | aliases: 688 | - pir 689 | extensions: 690 | - .pir 691 | 692 | Parrot Assembly: 693 | group: Parrot 694 | type: programming 695 | lexer: Text only 696 | aliases: 697 | - pasm 698 | extensions: 699 | - .pasm 700 | 701 | Perl: 702 | type: programming 703 | overrides: 704 | - .pl 705 | primary_extension: .pl 706 | extensions: 707 | - .PL 708 | - .perl 709 | - .ph 710 | - .pl 711 | - .pm 712 | - .pod 713 | - .psgi 714 | - .t 715 | 716 | Prolog: 717 | type: programming 718 | extensions: 719 | - .pl 720 | - .pro 721 | - .prolog 722 | 723 | Pure Data: 724 | type: programming 725 | lexer: Text only 726 | extensions: 727 | - .pd 728 | 729 | Python: 730 | type: programming 731 | primary_extension: .py 732 | extensions: 733 | - .py 734 | - .pyw 735 | - .wsgi 736 | 737 | Python traceback: 738 | type: data 739 | group: Python 740 | lexer: Python Traceback 741 | searchable: false 742 | extensions: 743 | - .pytb 744 | 745 | R: 746 | type: programming 747 | lexer: S 748 | overrides: 749 | - .r 750 | primary_extension: .r 751 | extensions: 752 | - .R 753 | - .r 754 | 755 | RHTML: 756 | type: markup 757 | group: HTML 758 | extensions: 759 | - .rhtml 760 | 761 | Racket: 762 | type: programming 763 | lexer: Scheme 764 | primary_extension: .rkt 765 | extensions: 766 | - .rkt 767 | - .rktd 768 | - .rktl 769 | - .scrbl 770 | 771 | Raw token data: 772 | search_term: raw 773 | aliases: 774 | - raw 775 | extensions: 776 | - .raw 777 | 778 | Rebol: 779 | type: programming 780 | lexer: REBOL 781 | extensions: 782 | - .r 783 | - .r2 784 | - .r3 785 | - .rebol 786 | 787 | Redcode: 788 | extensions: 789 | - .cw 790 | 791 | Ruby: 792 | type: programming 793 | aliases: 794 | - jruby 795 | - macruby 796 | - rake 797 | - rb 798 | - rbx 799 | primary_extension: .rb 800 | extensions: 801 | - .builder 802 | - .gemspec 803 | - .god 804 | - .irbrc 805 | - .rake 806 | - .rb 807 | - .rbuild 808 | - .rbw 809 | - .rbx 810 | - .ru 811 | - .thor 812 | - .watchr 813 | filenames: 814 | - Capfile 815 | - Rakefile 816 | - Thorfile 817 | - Gemfile 818 | - Guardfile 819 | - Vagrantfile 820 | 821 | Rust: 822 | type: programming 823 | lexer: Text only 824 | primary_extension: .rs 825 | extensions: 826 | - .rc 827 | - .rs 828 | 829 | SCSS: 830 | type: markup 831 | group: CSS 832 | extensions: 833 | - .scss 834 | 835 | SQL: 836 | type: data 837 | searchable: false 838 | extensions: 839 | - .sql 840 | 841 | Sass: 842 | type: markup 843 | group: CSS 844 | extensions: 845 | - .sass 846 | 847 | Scala: 848 | type: programming 849 | primary_extension: .scala 850 | extensions: 851 | - .sbt 852 | - .scala 853 | 854 | Scheme: 855 | type: programming 856 | primary_extension: .scm 857 | extensions: 858 | - .scm 859 | - .sls 860 | - .sps 861 | - .ss 862 | 863 | Self: 864 | type: programming 865 | lexer: Text only 866 | extensions: 867 | - .self 868 | 869 | Shell: 870 | type: programming 871 | lexer: Bash 872 | search_term: bash 873 | aliases: 874 | - sh 875 | - bash 876 | - zsh 877 | primary_extension: .sh 878 | extensions: 879 | - .bash 880 | - .sh 881 | - .zsh 882 | filenames: 883 | - .bash_profile 884 | - .bashrc 885 | - .profile 886 | - .zlogin 887 | - .zsh 888 | - .zshrc 889 | 890 | Smalltalk: 891 | type: programming 892 | extensions: 893 | - .st 894 | 895 | Smarty: 896 | extensions: 897 | - .tpl 898 | 899 | Standard ML: 900 | lexer: OCaml 901 | aliases: 902 | - sml 903 | primary_extension: .sml 904 | extensions: 905 | - .sig 906 | - .sml 907 | 908 | SuperCollider: 909 | type: programming 910 | lexer: Text only 911 | extensions: 912 | - .sc 913 | 914 | Tcl: 915 | type: programming 916 | extensions: 917 | - .tcl 918 | 919 | Tcsh: 920 | type: programming 921 | group: Shell 922 | primary_extension: .tcsh 923 | extensions: 924 | - .csh 925 | - .tcsh 926 | 927 | TeX: 928 | type: markup 929 | primary_extension: .tex 930 | extensions: 931 | - .aux 932 | - .cls 933 | - .sty 934 | - .tex 935 | - .toc 936 | 937 | Text: 938 | type: data 939 | lexer: Text only 940 | extensions: 941 | - .txt 942 | 943 | Textile: 944 | type: markup 945 | lexer: Text only 946 | extensions: 947 | - .textile 948 | 949 | Twig: 950 | type: markup 951 | group: PHP 952 | lexer: HTML+Django/Jinja 953 | extensions: 954 | - .twig 955 | 956 | VHDL: 957 | type: programming 958 | lexer: Text only 959 | primary_extension: .vhd 960 | extensions: 961 | - .vhd 962 | - .vhdl 963 | 964 | Vala: 965 | type: programming 966 | extensions: 967 | - .vala 968 | 969 | Verilog: 970 | type: programming 971 | lexer: Text only 972 | extensions: 973 | - .v 974 | 975 | VimL: 976 | type: programming 977 | search_term: vim 978 | aliases: 979 | - vim 980 | extensions: 981 | - .vim 982 | filenames: 983 | - .gvimrc 984 | - .vimrc 985 | 986 | Visual Basic: 987 | type: programming 988 | lexer: VB.net 989 | primary_extension: .vb 990 | extensions: 991 | - .bas 992 | - .frx 993 | - .vb 994 | - .vba 995 | - .vbs 996 | 997 | XML: 998 | type: markup 999 | primary_extension: .xml 1000 | extensions: 1001 | - .glade 1002 | - .kml 1003 | - .mxml 1004 | - .plist 1005 | - .rdf 1006 | - .rss 1007 | - .svg 1008 | - .wsdl 1009 | - .wxi 1010 | - .wxl 1011 | - .wxs 1012 | - .xaml 1013 | - .xml 1014 | - .xsd 1015 | - .xsl 1016 | - .xul 1017 | filenames: 1018 | - .classpath 1019 | - .project 1020 | 1021 | XQuery: 1022 | type: programming 1023 | extensions: 1024 | - .xq 1025 | - .xqm 1026 | - .xquery 1027 | - .xqy 1028 | 1029 | XS: 1030 | lexer: C 1031 | extensions: 1032 | - .xs 1033 | 1034 | YAML: 1035 | type: markup 1036 | primary_extension: .yml 1037 | extensions: 1038 | - .yaml 1039 | - .yml 1040 | filenames: 1041 | - .gemrc 1042 | 1043 | mupad: 1044 | lexer: MuPAD 1045 | extensions: 1046 | - .mu 1047 | 1048 | ooc: 1049 | type: programming 1050 | lexer: Ooc 1051 | extensions: 1052 | - .ooc 1053 | 1054 | reStructuredText: 1055 | type: markup 1056 | search_term: rst 1057 | aliases: 1058 | - rst 1059 | extensions: 1060 | - .rst 1061 | - .rest 1062 | --------------------------------------------------------------------------------