module LineCache
module LineCache
¶ ↑
A module to read and cache lines of a Ruby program.
Constants
- LineCacheInfo
Public Class Methods
Source
# File lib/linecache19.rb, line 143 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
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.
Source
# File lib/linecache19.rb, line 158 def cached?(filename) @@file_cache.member?(unmap_file(filename)) end
Return true if filename is cached
Source
# File lib/linecache19.rb, line 101 def cached_files() @@file_cache.keys end
Return an array of cached file names
Source
# File lib/linecache19.rb, line 163 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
Source
# File lib/linecache19.rb, line 112 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
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.
Source
# File lib/linecache19.rb, line 93 def clear_file_cache() @@file_cache = {} @@file2file_remap = {} @@file2file_remap_lines = {} end
Clear the file cache entirely.
Source
# File lib/linecache19.rb, line 174 def empty?(filename) filename=unmap_file(filename) @@file_cache[filename].lines.empty? end
Source
# File lib/linecache19.rb, line 191 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
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')
Source
# File lib/linecache19.rb, line 206 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
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
Source
# File lib/linecache19.rb, line 219 def path(filename) filename = unmap_file(filename) return nil unless @@file_cache.member?(filename) @@file_cache[filename].path end
Return full filename path for filename
Source
# File lib/linecache19.rb, line 226 def remap_file(from_file, to_file) @@file2file_remap[to_file] = from_file end
Source
# File lib/linecache19.rb, line 231 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
Source
# File lib/linecache19.rb, line 245 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 SHA1 of filename.
Source
# File lib/linecache19.rb, line 260 def size(filename) filename = unmap_file(filename) return nil unless @@file_cache.member?(filename) @@file_cache[filename].lines.length end
Return the number of lines in filename
Source
# File lib/linecache19.rb, line 268 def stat(filename) return nil unless @@file_cache.member?(filename) @@file_cache[filename].stat end
Return File.stat in the cache for filename.
Source
# File lib/linecache19.rb, line 278 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
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.
Source
# File lib/linecache19.rb, line 291 def unmap_file(file) @@file2file_remap[file] ? @@file2file_remap[file] : file end
Source
# File lib/linecache19.rb, line 296 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
Source
# File lib/linecache19.rb, line 313 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] if "ruby19".respond_to?(:force_encoding) lines.each{|l| l.force_encoding(Encoding.default_external) } end @@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
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
Private Instance Methods
Source
# File lib/linecache19.rb, line 143 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
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.
Source
# File lib/linecache19.rb, line 158 def cached?(filename) @@file_cache.member?(unmap_file(filename)) end
Return true if filename is cached
Source
# File lib/linecache19.rb, line 101 def cached_files() @@file_cache.keys end
Return an array of cached file names
Source
# File lib/linecache19.rb, line 163 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
Source
# File lib/linecache19.rb, line 112 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
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.
Source
# File lib/linecache19.rb, line 93 def clear_file_cache() @@file_cache = {} @@file2file_remap = {} @@file2file_remap_lines = {} end
Clear the file cache entirely.
Source
# File lib/linecache19.rb, line 174 def empty?(filename) filename=unmap_file(filename) @@file_cache[filename].lines.empty? end
Source
# File lib/linecache19.rb, line 191 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
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')
Source
# File lib/linecache19.rb, line 206 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
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
Source
# File lib/linecache19.rb, line 219 def path(filename) filename = unmap_file(filename) return nil unless @@file_cache.member?(filename) @@file_cache[filename].path end
Return full filename path for filename
Source
# File lib/linecache19.rb, line 226 def remap_file(from_file, to_file) @@file2file_remap[to_file] = from_file end
Source
# File lib/linecache19.rb, line 231 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
Source
# File lib/linecache19.rb, line 245 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 SHA1 of filename.
Source
# File lib/linecache19.rb, line 260 def size(filename) filename = unmap_file(filename) return nil unless @@file_cache.member?(filename) @@file_cache[filename].lines.length end
Return the number of lines in filename
Source
# File lib/linecache19.rb, line 268 def stat(filename) return nil unless @@file_cache.member?(filename) @@file_cache[filename].stat end
Return File.stat in the cache for filename.
Source
# File lib/linecache19.rb, line 278 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
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.
Source
# File lib/linecache19.rb, line 291 def unmap_file(file) @@file2file_remap[file] ? @@file2file_remap[file] : file end
Source
# File lib/linecache19.rb, line 296 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
Source
# File lib/linecache19.rb, line 313 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] if "ruby19".respond_to?(:force_encoding) lines.each{|l| l.force_encoding(Encoding.default_external) } end @@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
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