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 / vendor / gems / coderay-0.9.7 / lib / coderay / helpers / file_type.rb @ 442:753f1380d6bc

History | View | Annotate | Download (6.34 KB)

1
#!/usr/bin/env ruby
2
module CodeRay
3

    
4
# = FileType
5
#
6
# A simple filetype recognizer.
7
#
8
# Copyright (c) 2006 by murphy (Kornelius Kalnbach) <murphy rubychan de>
9
#
10
# License:: LGPL / ask the author
11
# Version:: 0.1 (2005-09-01)
12
#
13
# == Documentation
14
#
15
#  # determine the type of the given
16
#   lang = FileType[ARGV.first]
17
#  
18
#   # return :plaintext if the file type is unknown
19
#   lang = FileType.fetch ARGV.first, :plaintext
20
#  
21
#   # try the shebang line, too
22
#   lang = FileType.fetch ARGV.first, :plaintext, true
23
module FileType
24

    
25
  UnknownFileType = Class.new Exception
26

    
27
  class << self
28

    
29
    # Try to determine the file type of the file.
30
    #
31
    # +filename+ is a relative or absolute path to a file.
32
    #
33
    # The file itself is only accessed when +read_shebang+ is set to true.
34
    # That means you can get filetypes from files that don't exist.
35
    def [] filename, read_shebang = false
36
      name = File.basename filename
37
      ext = File.extname(name).sub(/^\./, '')  # from last dot, delete the leading dot
38
      ext2 = filename.to_s[/\.(.*)/, 1]  # from first dot
39

    
40
      type =
41
        TypeFromExt[ext] ||
42
        TypeFromExt[ext.downcase] ||
43
        (TypeFromExt[ext2] if ext2) ||
44
        (TypeFromExt[ext2.downcase] if ext2) ||
45
        TypeFromName[name] ||
46
        TypeFromName[name.downcase]
47
      type ||= shebang(filename) if read_shebang
48

    
49
      type
50
    end
51

    
52
    def shebang filename
53
      begin
54
        File.open filename, 'r' do |f|
55
          if first_line = f.gets
56
            if type = first_line[TypeFromShebang]
57
              type.to_sym
58
            end
59
          end
60
        end
61
      rescue IOError
62
        nil
63
      end
64
    end
65

    
66
    # This works like Hash#fetch.
67
    #
68
    # If the filetype cannot be found, the +default+ value
69
    # is returned.
70
    def fetch filename, default = nil, read_shebang = false
71
      if default and block_given?
72
        warn 'block supersedes default value argument'
73
      end
74

    
75
      unless type = self[filename, read_shebang]
76
        return yield if block_given?
77
        return default if default
78
        raise UnknownFileType, 'Could not determine type of %p.' % filename
79
      end
80
      type
81
    end
82

    
83
  end
84

    
85
  TypeFromExt = {
86
    'c' => :c,
87
    'css' => :css,
88
    'diff' => :diff,
89
    'dpr' => :delphi,
90
    'groovy' => :groovy,
91
    'gvy' => :groovy,
92
    'h' => :c,
93
    'htm' => :html,
94
    'html' => :html,
95
    'html.erb' => :rhtml,
96
    'java' => :java,
97
    'js' => :java_script,
98
    'json' => :json,
99
    'mab' => :ruby,
100
    'pas' => :delphi,
101
    'patch' => :diff,
102
    'php' => :php,
103
    'php3' => :php,
104
    'php4' => :php,
105
    'php5' => :php,
106
    'py' => :python,
107
    'py3' => :python,
108
    'pyw' => :python,
109
    'rake' => :ruby,
110
    'raydebug' => :debug,
111
    'rb' => :ruby,
112
    'rbw' => :ruby,
113
    'rhtml' => :rhtml,
114
    'rxml' => :ruby,
115
    'sch' => :scheme,
116
    'sql' => :sql,
117
    'ss' => :scheme,
118
    'xhtml' => :xhtml,
119
    'xml' => :xml,
120
    'yaml' => :yaml,
121
    'yml' => :yaml,
122
  }
123
  for cpp_alias in %w[cc cpp cp cxx c++ C hh hpp h++ cu]
124
    TypeFromExt[cpp_alias] = :cpp
125
  end
126

    
127
  TypeFromShebang = /\b(?:ruby|perl|python|sh)\b/
128

    
129
  TypeFromName = {
130
    'Rakefile' => :ruby,
131
    'Rantfile' => :ruby,
132
  }
133

    
134
end
135

    
136
end
137

    
138
if $0 == __FILE__
139
  $VERBOSE = true
140
  eval DATA.read, nil, $0, __LINE__ + 4
141
end
142

    
143
__END__
144
require 'test/unit'
145

146
class FileTypeTests < Test::Unit::TestCase
147
  
148
  include CodeRay
149
  
150
  def test_fetch
151
    assert_raise FileType::UnknownFileType do
152
      FileType.fetch ''
153
    end
154

155
    assert_throws :not_found do
156
      FileType.fetch '.' do
157
        throw :not_found
158
      end
159
    end
160

161
    assert_equal :default, FileType.fetch('c', :default)
162

163
    stderr, fake_stderr = $stderr, Object.new
164
    $err = ''
165
    def fake_stderr.write x
166
      $err << x
167
    end
168
    $stderr = fake_stderr
169
    FileType.fetch('c', :default) { }
170
    assert_equal "block supersedes default value argument\n", $err
171
    $stderr = stderr
172
  end
173

174
  def test_ruby
175
    assert_equal :ruby, FileType['test.rb']
176
    assert_equal :ruby, FileType['test.java.rb']
177
    assert_equal :java, FileType['test.rb.java']
178
    assert_equal :ruby, FileType['C:\\Program Files\\x\\y\\c\\test.rbw']
179
    assert_equal :ruby, FileType['/usr/bin/something/Rakefile']
180
    assert_equal :ruby, FileType['~/myapp/gem/Rantfile']
181
    assert_equal :ruby, FileType['./lib/tasks\repository.rake']
182
    assert_not_equal :ruby, FileType['test_rb']
183
    assert_not_equal :ruby, FileType['Makefile']
184
    assert_not_equal :ruby, FileType['set.rb/set']
185
    assert_not_equal :ruby, FileType['~/projects/blabla/rb']
186
  end
187

188
  def test_c
189
    assert_equal :c, FileType['test.c']
190
    assert_equal :c, FileType['C:\\Program Files\\x\\y\\c\\test.h']
191
    assert_not_equal :c, FileType['test_c']
192
    assert_not_equal :c, FileType['Makefile']
193
    assert_not_equal :c, FileType['set.h/set']
194
    assert_not_equal :c, FileType['~/projects/blabla/c']
195
  end
196

197
  def test_cpp
198
    assert_equal :cpp, FileType['test.c++']
199
    assert_equal :cpp, FileType['test.cxx']
200
    assert_equal :cpp, FileType['test.hh']
201
    assert_equal :cpp, FileType['test.hpp']
202
    assert_equal :cpp, FileType['test.cu']
203
    assert_equal :cpp, FileType['test.C']
204
    assert_not_equal :cpp, FileType['test.c']
205
    assert_not_equal :cpp, FileType['test.h']
206
  end
207

208
  def test_html
209
    assert_equal :html, FileType['test.htm']
210
    assert_equal :xhtml, FileType['test.xhtml']
211
    assert_equal :xhtml, FileType['test.html.xhtml']
212
    assert_equal :rhtml, FileType['_form.rhtml']
213
    assert_equal :rhtml, FileType['_form.html.erb']
214
  end
215

216
  def test_yaml
217
    assert_equal :yaml, FileType['test.yml']
218
    assert_equal :yaml, FileType['test.yaml']
219
    assert_equal :yaml, FileType['my.html.yaml']
220
    assert_not_equal :yaml, FileType['YAML']
221
  end
222

223
  def test_pathname
224
    require 'pathname'
225
    pn = Pathname.new 'test.rb'
226
    assert_equal :ruby, FileType[pn]
227
    dir = Pathname.new '/etc/var/blubb'
228
    assert_equal :ruby, FileType[dir + pn]
229
    assert_equal :cpp, FileType[dir + 'test.cpp']
230
  end
231

232
  def test_no_shebang
233
    dir = './test'
234
    if File.directory? dir
235
      Dir.chdir dir do
236
        assert_equal :c, FileType['test.c']
237
      end
238
    end
239
  end
240
  
241
  def test_shebang_empty_file
242
    require 'tmpdir'
243
    tmpfile = File.join(Dir.tmpdir, 'bla')
244
    File.open(tmpfile, 'w') { }  # touch
245
    assert_equal nil, FileType[tmpfile]
246
  end
247
  
248
  def test_shebang
249
    require 'tmpdir'
250
    tmpfile = File.join(Dir.tmpdir, 'bla')
251
    File.open(tmpfile, 'w') { |f| f.puts '#!/usr/bin/env ruby' }
252
    assert_equal :ruby, FileType[tmpfile, true]
253
  end
254

255
end