A module to read and cache lines of a Ruby program.
Cache filename if it's not already cached. Return the expanded filename for it in the cache or nil if we can't find the file.
# File lib/linecache19.rb, line 147 def cache(filename, reload_on_change=false) if @@file_cache.member?(filename) checkcache(filename) if reload_on_change else update_cache(filename, true) end if @@file_cache.member?(filename) @@file_cache[filename].path else nil end end
Return true if filename is cached
# File lib/linecache19.rb, line 162 def cached?(filename) @@file_cache.member?(unmap_file(filename)) end
Return an array of cached file names
# File lib/linecache19.rb, line 105 def cached_files() @@file_cache.keys end
# File lib/linecache19.rb, line 167 def cached_script?(filename) # In 1.8.6, the SCRIPT_LINES__ filename key can be unqualified # In 1.9.1 it's the fully qualified name if RUBY_VERSION < "1.9" SCRIPT_LINES__.member?(unmap_file(filename)) else SCRIPT_LINES__.member?(File.expand_path(unmap_file(filename))) end end
Discard cache entries that are out of date. If filename
is
nil
all entries in the file cache +@@file_cache+ are checked.
If we don't have stat information about a file, which can happen if the
file was read from SCRIPT_LINES__ but no corresponding file is found, it
will be kept. Return a list of invalidated filenames. nil is returned if a
filename was given but not found cached.
# File lib/linecache19.rb, line 116 def checkcache(filename=nil, use_script_lines=false) if !filename filenames = @@file_cache.keys() elsif @@file_cache.member?(filename) filenames = [filename] else return nil end result = [] for filename in filenames next unless @@file_cache.member?(filename) path = @@file_cache[filename].path if File.exist?(path) cache_info = @@file_cache[filename].stat stat = File.stat(path) if stat && (cache_info.size != stat.size or cache_info.mtime != stat.mtime) result << filename update_cache(filename, use_script_lines) end end end return result end
Clear the file cache entirely.
# File lib/linecache19.rb, line 97 def clear_file_cache() @@file_cache = {} @@file2file_remap = {} @@file2file_remap_lines = {} end
# File lib/linecache19.rb, line 178 def empty?(filename) filename=unmap_file(filename) @@file_cache[filename].lines.empty? end
Get line line_number
from file named filename
.
Return nil if there was a problem. If a file named filename is not found,
the function will look for it in the $: array.
Examples:
lines = LineCache::getline('/tmp/myfile.rb') # Same as above $: << '/tmp' lines = LineCache.getlines('myfile.rb')
# File lib/linecache19.rb, line 195 def getline(filename, line_number, reload_on_change=true) filename = unmap_file(filename) filename, line_number = unmap_file_line(filename, line_number) lines = getlines(filename, reload_on_change) if lines and (1..lines.size) === line_number return lines[line_number-1] else return nil end end
Read lines of filename
and cache the results. However
filename
was previously cached use the results from the cache.
Return nil if we can't get lines
# File lib/linecache19.rb, line 210 def getlines(filename, reload_on_change=false) filename = unmap_file(filename) checkcache(filename) if reload_on_change if @@file_cache.member?(filename) return @@file_cache[filename].lines else update_cache(filename, true) return @@file_cache[filename].lines if @@file_cache.member?(filename) end end
Return full filename path for filename
# File lib/linecache19.rb, line 223 def path(filename) filename = unmap_file(filename) return nil unless @@file_cache.member?(filename) @@file_cache[filename].path end
# File lib/linecache19.rb, line 230 def remap_file(from_file, to_file) @@file2file_remap[to_file] = from_file end
# File lib/linecache19.rb, line 235 def remap_file_lines(from_file, to_file, range, start) range = (range..range) if range.is_a?(Fixnum) to_file = from_file unless to_file if @@file2file_remap_lines[to_file] # FIXME: need to check for overwriting ranges: whether # they intersect or one encompasses another. @@file2file_remap_lines[to_file] << [from_file, range, start] else @@file2file_remap_lines[to_file] = [[from_file, range, start]] end end
Return SHA1 of filename.
# File lib/linecache19.rb, line 249 def sha1(filename) filename = unmap_file(filename) return nil unless @@file_cache.member?(filename) return @@file_cache[filename].sha1.hexdigest if @@file_cache[filename].sha1 sha1 = Digest::SHA1.new @@file_cache[filename].lines.each do |line| sha1 << line end @@file_cache[filename].sha1 = sha1 sha1.hexdigest end
Return the number of lines in filename
# File lib/linecache19.rb, line 264 def size(filename) filename = unmap_file(filename) return nil unless @@file_cache.member?(filename) @@file_cache[filename].lines.length end
Return File.stat in the cache for filename.
# File lib/linecache19.rb, line 272 def stat(filename) return nil unless @@file_cache.member?(filename) @@file_cache[filename].stat end
Return an Array of breakpoints in filename. The list will contain an entry for each distinct line event call so it is possible (and possibly useful) for a line number appear more than once.
# File lib/linecache19.rb, line 282 def trace_line_numbers(filename, reload_on_change=false) fullname = cache(filename, reload_on_change) return nil unless fullname e = @@file_cache[filename] unless e.line_numbers e.line_numbers = TraceLineNumbers.lnums_for_str_array(e.lines) e.line_numbers = false unless e.line_numbers end e.line_numbers end
# File lib/linecache19.rb, line 295 def unmap_file(file) @@file2file_remap[file] ? @@file2file_remap[file] : file end
# File lib/linecache19.rb, line 300 def unmap_file_line(file, line) if @@file2file_remap_lines[file] @@file2file_remap_lines[file].each do |from_file, range, start| if range === line from_file = from_file || file return [from_file, start+line-range.begin] end end end return [file, line] end
Update a cache entry. If something's wrong, return nil. Return true if the cache was updated and false if not. If use_script_lines is true, use that as the source for the lines of the file
# File lib/linecache19.rb, line 317 def update_cache(filename, use_script_lines=false) return nil unless filename @@file_cache.delete(filename) path = File.expand_path(filename) if use_script_lines list = [filename] list << @@file2file_remap[path] if @@file2file_remap[path] list.each do |name| if !SCRIPT_LINES__[name].nil? && SCRIPT_LINES__[name] != true begin stat = File.stat(name) rescue stat = nil end lines = SCRIPT_LINES__[name] @@file_cache[filename] = LineCacheInfo.new(stat, nil, lines, path, nil) @@file2file_remap[path] = filename return true end end end if File.exist?(path) stat = File.stat(path) elsif File.basename(filename) == filename # try looking through the search path. stat = nil for dirname in $: path = File.join(dirname, filename) if File.exist?(path) stat = File.stat(path) break end end return false unless stat end begin fp = File.open(path, 'r') lines = fp.readlines() fp.close() rescue ## print '*** cannot open', path, ':', msg return nil end @@file_cache[filename] = LineCacheInfo.new(File.stat(path), nil, lines, path, nil) @@file2file_remap[path] = filename return true end