To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.

Statistics Download as Zip
| Branch: | Tag: | Revision:

root / .svn / pristine / 0f / 0f5d0b28aa88dc0b634f0aed6c20653f95af7206.svn-base @ 912:5e80956cc792

History | View | Annotate | Download (3.67 KB)

1 909:cbb26bc654de Chris
module CodeRay
2
3
  # = FileType
4
  #
5
  # A simple filetype recognizer.
6
  #
7
  # == Usage
8
  #
9
  #  # determine the type of the given
10
  #  lang = FileType[file_name]
11
  #
12
  #  # return :text if the file type is unknown
13
  #  lang = FileType.fetch file_name, :text
14
  #
15
  #  # try the shebang line, too
16
  #  lang = FileType.fetch file_name, :text, true
17
  module FileType
18
19
    UnknownFileType = Class.new Exception
20
21
    class << self
22
23
      # Try to determine the file type of the file.
24
      #
25
      # +filename+ is a relative or absolute path to a file.
26
      #
27
      # The file itself is only accessed when +read_shebang+ is set to true.
28
      # That means you can get filetypes from files that don't exist.
29
      def [] filename, read_shebang = false
30
        name = File.basename filename
31
        ext = File.extname(name).sub(/^\./, '')  # from last dot, delete the leading dot
32
        ext2 = filename.to_s[/\.(.*)/, 1]  # from first dot
33
34
        type =
35
          TypeFromExt[ext] ||
36
          TypeFromExt[ext.downcase] ||
37
          (TypeFromExt[ext2] if ext2) ||
38
          (TypeFromExt[ext2.downcase] if ext2) ||
39
          TypeFromName[name] ||
40
          TypeFromName[name.downcase]
41
        type ||= shebang(filename) if read_shebang
42
43
        type
44
      end
45
46
      # This works like Hash#fetch.
47
      #
48
      # If the filetype cannot be found, the +default+ value
49
      # is returned.
50
      def fetch filename, default = nil, read_shebang = false
51
        if default && block_given?
52
          warn 'Block supersedes default value argument; use either.'
53
        end
54
55
        if type = self[filename, read_shebang]
56
          type
57
        else
58
          return yield if block_given?
59
          return default if default
60
          raise UnknownFileType, 'Could not determine type of %p.' % filename
61
        end
62
      end
63
64
    protected
65
66
      def shebang filename
67
        return unless File.exist? filename
68
        File.open filename, 'r' do |f|
69
          if first_line = f.gets
70
            if type = first_line[TypeFromShebang]
71
              type.to_sym
72
            end
73
          end
74
        end
75
      end
76
77
    end
78
79
    TypeFromExt = {
80
      'c'        => :c,
81
      'cfc'      => :xml,
82
      'cfm'      => :xml,
83
      'clj'      => :clojure,
84
      'css'      => :css,
85
      'diff'     => :diff,
86
      'dpr'      => :delphi,
87
      'gemspec'  => :ruby,
88
      'groovy'   => :groovy,
89
      'gvy'      => :groovy,
90
      'h'        => :c,
91
      'haml'     => :haml,
92
      'htm'      => :page,
93
      'html'     => :page,
94
      'html.erb' => :erb,
95
      'java'     => :java,
96
      'js'       => :java_script,
97
      'json'     => :json,
98
      'mab'      => :ruby,
99
      'pas'      => :delphi,
100
      'patch'    => :diff,
101
      'php'      => :php,
102
      'php3'     => :php,
103
      'php4'     => :php,
104
      'php5'     => :php,
105
      'prawn'    => :ruby,
106
      'py'       => :python,
107
      'py3'      => :python,
108
      'pyw'      => :python,
109
      'rake'     => :ruby,
110
      'raydebug' => :raydebug,
111
      'rb'       => :ruby,
112
      'rbw'      => :ruby,
113
      'rhtml'    => :erb,
114
      'rjs'      => :ruby,
115
      'rpdf'     => :ruby,
116
      'ru'       => :ruby,
117
      'rxml'     => :ruby,
118
      # 'sch'      => :scheme,
119
      'sql'      => :sql,
120
      # 'ss'       => :scheme,
121
      'xhtml'    => :page,
122
      'xml'      => :xml,
123
      'yaml'     => :yaml,
124
      'yml'      => :yaml,
125
    }
126
    for cpp_alias in %w[cc cpp cp cxx c++ C hh hpp h++ cu]
127
      TypeFromExt[cpp_alias] = :cpp
128
    end
129
130
    TypeFromShebang = /\b(?:ruby|perl|python|sh)\b/
131
132
    TypeFromName = {
133
      'Capfile'  => :ruby,
134
      'Rakefile' => :ruby,
135
      'Rantfile' => :ruby,
136
      'Gemfile'  => :ruby,
137
    }
138
139
  end
140
141
end