Class: FileType

Inherits:
Object
  • Object
show all
Includes:
Singleton
Defined in:
lib/riel/filetype.rb

Constant Summary collapse

BINARY =
"binary"
DIRECTORY =
"directory"
NONE =
"none"
TEXT =
"text"
UNKNOWN =
"unknown"
UNREADABLE =
"unreadable"
TEXT_EXTENSIONS =

extensions associated with files that are always text:

%w{ 
  c
  css
  el
  h
  html
  java
  mk
  php
  pl
  pm
  rb
  rbw
  txt
  xml
  yml
  yaml
}
NONTEXT_EXTENSIONS =

extensions associated with files that are never text:

%w{ 
  Z
  a
  bz2
  elc
  gif
  gz
  jar
  jpeg
  jpg
  mp3
  mpeg
  o
  obj
  pdf
  png
  ps
  tar
  wav
  zip
}
EXTENSION_REGEXP =
%r{ \. (\w+) $ }x

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeFileType

Returns a new instance of FileType.



61
62
63
64
65
66
67
68
69
70
71
72
# File 'lib/riel/filetype.rb', line 61

def initialize
  # the percentage of characters that we allow to be odd in a text file
  @odd_factor = 0.3

  # how many bytes (characters) of a file we test
  @test_length = 1024

  @known = Hash.new

  set_extensions(true,  *TEXT_EXTENSIONS)
  set_extensions(false, *NONTEXT_EXTENSIONS)
end

Class Method Details

.ascii?(c) ⇒ Boolean

Returns:

  • (Boolean)


161
162
163
# File 'lib/riel/filetype.rb', line 161

def self.ascii? c
  return self.instance.ascii? c
end

.nontext_extensionsObject



181
182
183
# File 'lib/riel/filetype.rb', line 181

def self.nontext_extensions
  return self.instance.nontext_extensions
end

.set_nontext(ext) ⇒ Object



173
174
175
# File 'lib/riel/filetype.rb', line 173

def self.set_nontext ext
  return self.instance.set_nontext ext
end

.set_text(ext) ⇒ Object



169
170
171
# File 'lib/riel/filetype.rb', line 169

def self.set_text ext
  return self.instance.set_text ext
end

.text?(file) ⇒ Boolean

Returns:

  • (Boolean)


185
186
187
# File 'lib/riel/filetype.rb', line 185

def self.text? file
  return self.instance.text? file
end

.text_extensionsObject



177
178
179
# File 'lib/riel/filetype.rb', line 177

def self.text_extensions
  return self.instance.text_extensions
end

.type(file) ⇒ Object



165
166
167
# File 'lib/riel/filetype.rb', line 165

def self.type file
  return self.instance.type file
end

Instance Method Details

#ascii?(c) ⇒ Boolean

Returns:

  • (Boolean)


74
75
76
77
# File 'lib/riel/filetype.rb', line 74

def ascii? c
  # from ctype.h
  (c.to_i & ~0x7f) == 0
end

#nontext_extensionsObject



119
120
121
# File 'lib/riel/filetype.rb', line 119

def nontext_extensions
  @known.keys.reject { |suf| @known[suf] }
end

#set_extensions(is_text, *exts) ⇒ Object



101
102
103
104
105
# File 'lib/riel/filetype.rb', line 101

def set_extensions(is_text, *exts)
  exts.each do |ext|
    @known[ext] = is_text
  end
end

#set_nontext(ext) ⇒ Object



111
112
113
# File 'lib/riel/filetype.rb', line 111

def set_nontext(ext)
  @known[ext] = false
end

#set_text(*ext) ⇒ Object



107
108
109
# File 'lib/riel/filetype.rb', line 107

def set_text(*ext)
  @known[ext] = true
end

#text?(file) ⇒ Boolean

Returns:

  • (Boolean)


123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
# File 'lib/riel/filetype.rb', line 123

def text? file
  return false unless File.exist?(file)
  
  if md = EXTENSION_REGEXP.match(file.to_s)
    suffix = md[1]
    if @known.include? suffix
      return @known[suffix]
    end
  end
  
  ntested = 0
  nodd = 0

  begin
    File.open(file) do |f|
      buf = f.read @test_length
      if buf
        buf.each_byte do |ch|
          ntested += 1
          
          # never allow null in a text file
          return false if ch.to_i == 0
          
          nodd += 1 unless ascii?(ch)
        end
      else
        # file had length of 0:
        return UNKNOWN
      end
    end
  rescue => e
    warn "file not readable: #{file}; error: #{e}"
    return UNREADABLE
  end

  nodd < ntested * @odd_factor
end

#text_extensionsObject



115
116
117
# File 'lib/riel/filetype.rb', line 115

def text_extensions
  @known.keys.select { |suf| @known[suf] }
end

#type(file) ⇒ Object



79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/riel/filetype.rb', line 79

def type file
  begin
    case File.stat(file).ftype
    when "directory"
      DIRECTORY
    when "file"
      if File.readable? file
        text?(file) ? TEXT : BINARY
      else
        UNREADABLE
      end
    else
      UNKNOWN
    end
  rescue Errno::ENOENT
    NONE
  rescue => e
    warn "file not readable: #{file}; error: #{e}"
    UNREADABLE
  end
end