rbx-linecache 1.3-universal-rubinius-2.0

Sign up to get free protection for your applications and to get access to all the features.
data/NEWS ADDED
@@ -0,0 +1,49 @@
1
+ 1.3
2
+ - CompiledMethod#lines tuple changes and allow rubinius 2.0.pre
3
+
4
+ 1.2
5
+ - Add CompiledMethod caching.
6
+
7
+ 1.1.1
8
+ March 15, 2011
9
+ - Cache compiled methods for rbx-trepanning
10
+
11
+ 1.1
12
+ February 23, 2011
13
+ - Minor revision to description and to tolerate all Rubinius 1.2.x versions
14
+
15
+ December 25, 2010
16
+ - Handle Rubinius eval_source to temp file remapping.
17
+
18
+ October 27, 2010
19
+ - First gemcutter rubinius release
20
+
21
+
22
+ 0.43
23
+ 06-12-08
24
+ - tolerance for finding windows extension in lib rather than ext.
25
+
26
+ 0.41
27
+ - add test/data/* to gem.
28
+
29
+ 0.4
30
+ - Credit Ryan Davis and ParseTree.
31
+
32
+ 0.3
33
+ - Add tracelines: get line numbers that can be stopped at.
34
+
35
+ - Add routines to allow line-number
36
+ remapping and filename remapping.
37
+
38
+ - Add access methods to get the number of lines in a file.
39
+
40
+ 0.2
41
+ - Make this work with ruby-debug-base. Add reload-on-change parameters.
42
+ add checkcache, cache, cached? sha1, and stat methods.
43
+
44
+ - Use SCRIPT_LINES__.
45
+
46
+ 0.1
47
+
48
+ - Initial release of LineCache, a module for reading and caching lines.
49
+
data/README ADDED
@@ -0,0 +1,50 @@
1
+ = LineCache - A module to read and cache file information of a Ruby program.
2
+
3
+ == SYNOPSIS
4
+
5
+ The LineCache module allows one to get any line from any file, caching
6
+ the lines and file information on first access to the file. Although
7
+ the file may be any file, the common use is when the file is a Ruby
8
+ script since parsing of the file is done to figure out where the
9
+ statement boundaries are.
10
+
11
+ The routines here may be is useful when a small random sets of lines
12
+ are read from a single file, in particular in a debugger to show
13
+ source lines.
14
+
15
+ == Summary
16
+
17
+ require 'linecache'
18
+ lines = LineCache::getlines('/tmp/myruby.rb')
19
+ # The following lines have same effect as the above.
20
+ $: << '/tmp'
21
+ Dir.chdir('/tmp') {lines = LineCache::getlines('myruby.rb')
22
+
23
+ line = LineCache::getline('/tmp/myruby.rb', 6)
24
+ # Note lines[6] == line (if /tmp/myruby.rb has 6 lines)
25
+
26
+ LineCache::clear_file_cache
27
+ LineCache::clear_file_cache('/tmp/myruby.rb')
28
+ LineCache::update_cache # Check for modifications of all cached files.
29
+
30
+ == Credits
31
+
32
+ This is a port of the module of the same name from the Python distribution.
33
+
34
+ The idea for how TraceLineNumbers works, and some code was taken
35
+ from ParseTree by Ryan Davis.
36
+
37
+ == Other stuff
38
+
39
+ Author:: Rocky Bernstein <rockyb@rubyforge.net>
40
+ License:: Copyright (c) 2007, 2008 Rocky Bernstein
41
+ Released under the GNU GPL 2 license
42
+
43
+ == Warranty
44
+
45
+ This program is distributed in the hope that it will be useful,
46
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
47
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
48
+ GNU General Public License for more details.
49
+
50
+ $Id: README 169 2009-02-08 17:19:33Z rockyb $
data/Rakefile ADDED
@@ -0,0 +1,97 @@
1
+ #!/usr/bin/env rake
2
+ # Are we Rubinius? The right versions of it?
3
+ raise RuntimeError,
4
+ 'This package is for Rubinius 1.2.[34] or 2.0.x only!' unless
5
+ Object.constants.include?('Rubinius') &&
6
+ Rubinius.constants.include?('VM') &&
7
+ Rubinius::VERSION =~ /1\.2\.[34]/ || Rubinius::VERSION =~ /2\.0/
8
+
9
+ require 'rubygems'
10
+ require 'rubygems/package_task'
11
+ require 'rdoc/task'
12
+ require 'rake/testtask'
13
+
14
+ ROOT_DIR = File.dirname(__FILE__)
15
+ Gemspec_filename = 'rbx-linecache.gemspec'
16
+ require File.join %W(#{ROOT_DIR} lib linecache)
17
+
18
+ def gemspec
19
+ @gemspec ||= eval(File.read(Gemspec_filename), binding, Gemspec_filename)
20
+ end
21
+
22
+ desc "Build the gem"
23
+ task :package=>:gem
24
+ task :gem=>:gemspec do
25
+ Dir.chdir(ROOT_DIR) do
26
+ sh "gem build #{Gemspec_filename}"
27
+ FileUtils.mkdir_p 'pkg'
28
+ FileUtils.mv("#{gemspec.file_name}", "pkg/")
29
+
30
+ # Now make a 2.0 package by changing 1.2 to 2.0 in the gemspec
31
+ # and creating another gemspec and moving that accordingly
32
+ lines = File.open(Gemspec_filename).readlines.map{|line|
33
+ line.gsub(/'universal', 'rubinius', '1\.2'/,
34
+ "'universal', 'rubinius', '2.0'");
35
+ }
36
+
37
+ two_filename = gemspec.file_name.gsub(/1\.2/, '2.0')
38
+ gemspec_filename2 = "rbx-linecache2.gemspec"
39
+ f = File.open(gemspec_filename2, "w")
40
+ f.write(lines); f.close
41
+ sh "gem build #{gemspec_filename2}"
42
+ FileUtils.mv("#{two_filename}", "pkg/")
43
+ end
44
+ end
45
+
46
+ task :default => [:test]
47
+
48
+ desc 'Install the gem locally'
49
+ task :install => :package do
50
+ Dir.chdir(ROOT_DIR) do
51
+ sh %{gem install --local pkg/#{gemspec.file_name}}
52
+ end
53
+ end
54
+
55
+ desc "Create a GNU-style ChangeLog via svn2cl"
56
+ task :ChangeLog do
57
+ system("svn2cl --authors=svn2cl_usermap")
58
+ end
59
+
60
+ desc 'Test units - the smaller tests'
61
+ Rake::TestTask.new(:'test') do |t|
62
+ t.test_files = FileList['test/test-*.rb']
63
+ # t.pattern = 'test/**/*test-*.rb' # instead of above
64
+ t.options = '--verbose' if $VERBOSE
65
+ end
66
+
67
+ desc "Generate the gemspec"
68
+ task :generate do
69
+ puts gemspec.to_ruby
70
+ end
71
+
72
+ desc "Validate the gemspec"
73
+ task :gemspec do
74
+ gemspec.validate
75
+ end
76
+
77
+ # --------- RDoc Documentation ------
78
+ desc "Generate rdoc documentation"
79
+ Rake::RDocTask.new("rdoc") do |rdoc|
80
+ rdoc.rdoc_dir = 'doc'
81
+ rdoc.title = "rbx-linecache #{LineCache::VERSION} Documentation"
82
+ rdoc.rdoc_files.include(%w(lib/*.rb))
83
+ end
84
+
85
+ desc "Same as rdoc"
86
+ task :doc => :rdoc
87
+
88
+ task :clobber_package do
89
+ FileUtils.rm_rf File.join(ROOT_DIR, 'pkg')
90
+ end
91
+
92
+ task :clobber_rdoc do
93
+ FileUtils.rm_rf File.join(ROOT_DIR, 'doc')
94
+ end
95
+
96
+ desc "Remove built files"
97
+ task :clean => [:clobber_package, :clobber_rdoc]
data/lib/linecache.rb ADDED
@@ -0,0 +1,560 @@
1
+ #!/usr/bin/env ruby
2
+ # Copyright (C) 2007, 2008, 2010, 2011
3
+ # Rocky Bernstein <rockyb@rubyforge.net>
4
+ #
5
+ # This program is free software; you can redistribute it and/or modify
6
+ # it under the terms of the GNU General Public License as published by
7
+ # the Free Software Foundation; either version 2 of the License, or
8
+ # (at your option) any later version.
9
+ #
10
+ # This program is distributed in the hope that it will be useful,
11
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
12
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
+ # GNU General Public License for more details.
14
+ #
15
+ # You should have received a copy of the GNU General Public License
16
+ # along with this program; if not, write to the Free Software
17
+ # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
18
+ # 02110-1301 USA.
19
+ #
20
+
21
+ # Author:: Rocky Bernstein (mailto:rockyb@rubyforge.net)
22
+ #
23
+ # = linecache
24
+ # A module to read and cache lines of a Ruby program.
25
+
26
+ # == SYNOPSIS
27
+ #
28
+ # The LineCache module allows one to get any line from any file,
29
+ # caching lines of the file on first access to the file. Although the
30
+ # file may be any file, the common use is when the file is a Ruby
31
+ # script since parsing of the file is done to figure out where the
32
+ # statement boundaries are.
33
+ #
34
+ # The routines here may be is useful when a small random sets of lines
35
+ # are read from a single file, in particular in a debugger to show
36
+ # source lines.
37
+ #
38
+ #
39
+ # require 'linecache'
40
+ # lines = LineCache::getlines('/tmp/myruby.rb')
41
+ # # The following lines have same effect as the above.
42
+ # $: << '/tmp'
43
+ # Dir.chdir('/tmp') {lines = LineCache::getlines('myruby.rb')
44
+ #
45
+ # line = LineCache::getline('/tmp/myruby.rb', 6)
46
+ # # Note lines[6] == line (if /tmp/myruby.rb has 6 lines)
47
+ #
48
+ # LineCache::clear_file_cache
49
+ # LineCache::clear_file_cache('/tmp/myruby.rb')
50
+ # LineCache::update_cache # Check for modifications of all cached files.
51
+ #
52
+ # Some parts of the interface is derived from the Python module of the
53
+ # same name.
54
+ #
55
+
56
+ require 'tempfile'
57
+ require 'digest/sha1'
58
+ require 'set'
59
+
60
+ require 'rubygems'
61
+ require 'require_relative'
62
+ require_relative 'tracelines'
63
+
64
+ # = module LineCache
65
+ # A module to read and cache lines of a Ruby program.
66
+ module LineCache
67
+ VERSION = '1.3'
68
+ LineCacheInfo = Struct.new(:stat, :line_numbers, :lines, :path,
69
+ :sha1, :compiled_method) unless
70
+ defined?(LineCacheInfo)
71
+
72
+ # The file cache. The key is a name as would be given by Ruby for
73
+ # __FILE__. The value is a LineCacheInfo object.
74
+ @@file_cache = {}
75
+ @@script_cache = {}
76
+
77
+
78
+ # Used for CodeRay syntax highlighting
79
+ @@ruby_highlighter = nil
80
+
81
+ # Maps a string filename (a String) to a key in @@file_cache (a
82
+ # String).
83
+ #
84
+ # One important use of @@file2file_remap is mapping the a full path
85
+ # of a file into the name stored in @@file_cache or given by Ruby's
86
+ # __FILE__. Applications such as those that get input from users,
87
+ # may want canonicalize a file name before looking it up. This map
88
+ # gives a way to do that.
89
+ #
90
+ # Another related use is when a template system is used. Here we'll
91
+ # probably want to remap not only the file name but also line
92
+ # ranges. Will probably use this for that, but I'm not sure.
93
+ @@file2file_remap = {}
94
+ @@file2file_remap_lines = {}
95
+
96
+ @@script2file = {}
97
+
98
+ module_function
99
+
100
+ def remove_script_temps
101
+ @@script2file.values.each do |filename|
102
+ File.unlink(filename) if File.exist?(filename)
103
+ end
104
+ end
105
+ at_exit { remove_script_temps }
106
+
107
+
108
+ # Clear the file cache entirely.
109
+ def clear_file_cache(filename=nil)
110
+ if filename
111
+ if @@file_cache[filename]
112
+ @@file_cache.delete(filename)
113
+ end
114
+ else
115
+ @@file_cache = {}
116
+ @@file2file_remap = {}
117
+ @@file2file_remap_lines = {}
118
+ end
119
+ end
120
+
121
+ # Remove syntax-formatted lines in the cache. Use this
122
+ # when you change the CodeRay syntax or Token formatting
123
+ # and want to redo how files may have previously been
124
+ # syntax marked.
125
+ def clear_file_format_cache
126
+ @@file_cache.each_pair do |fname, cache_info|
127
+ cache_info.lines.each_pair do |format, lines|
128
+ next if :plain == format
129
+ @@file_cache[fname].lines[format] = nil
130
+ end
131
+ end
132
+ end
133
+
134
+ # Clear the script cache entirely.
135
+ def clear_script_cache()
136
+ @@script_cache = {}
137
+ end
138
+
139
+ # Return an array of cached file names
140
+ def cached_files()
141
+ @@file_cache.keys
142
+ end
143
+
144
+ # Discard cache entries that are out of date. If +filename+ is +nil+
145
+ # all entries in the file cache +@@file_cache+ are checked.
146
+ # If we don't have stat information about a file, which can happen
147
+ # if the file was read from __SCRIPT_LINES but no corresponding file
148
+ # is found, it will be kept. Return a list of invalidated filenames.
149
+ # nil is returned if a filename was given but not found cached.
150
+ def checkcache(filename=nil, opts={})
151
+
152
+ if !filename
153
+ filenames = @@file_cache.keys()
154
+ elsif @@file_cache.member?(filename)
155
+ filenames = [filename]
156
+ else
157
+ return nil
158
+ end
159
+
160
+ result = []
161
+ for filename in filenames
162
+ next unless @@file_cache.member?(filename)
163
+ path = @@file_cache[filename].path
164
+ if File.exist?(path)
165
+ cache_info = @@file_cache[filename].stat
166
+ stat = File.stat(path)
167
+ if cache_info
168
+ if stat &&
169
+ (cache_info.size != stat.size or cache_info.mtime != stat.mtime)
170
+ result << filename
171
+ update_cache(filename, opts)
172
+ end
173
+ else
174
+ result << filename
175
+ update_cache(filename, opts)
176
+ end
177
+ end
178
+ end
179
+ return result
180
+ end
181
+
182
+ # Cache script if it's not already cached.
183
+ def cache_script(script, opts={})
184
+ if !@@script_cache.member?(script)
185
+ update_script_cache(script, opts)
186
+ end
187
+ script
188
+ end
189
+
190
+ # Cache file name or script object if it's not already cached.
191
+ # Return the expanded filename for it in the cache if a filename,
192
+ # or the script, or nil if we can't find the file.
193
+ def cache(file_or_script, reload_on_change=false)
194
+ if file_or_script.kind_of?(String)
195
+ cache_file(file_or_script, reload_on_change)
196
+ else
197
+ cache_script(file_or_script)
198
+ end
199
+ end
200
+
201
+ # Cache filename if it's not already cached.
202
+ # Return the expanded filename for it in the cache
203
+ # or nil if we can't find the file.
204
+ def cache_file(filename, reload_on_change=false, opts={})
205
+ if @@file_cache.member?(filename)
206
+ checkcache(filename) if reload_on_change
207
+ else
208
+ opts[:use_script_lines] = true
209
+ update_cache(filename, opts)
210
+ end
211
+ if @@file_cache.member?(filename)
212
+ @@file_cache[filename].path
213
+ else
214
+ nil
215
+ end
216
+ end
217
+
218
+ # Return true if file_or_script is cached
219
+ def cached?(file_or_script)
220
+ if file_or_script.kind_of?(String)
221
+ @@file_cache.member?(map_file(file_or_script))
222
+ else
223
+ cached_script?(file_or_script)
224
+ end
225
+ end
226
+
227
+ def cached_script?(script)
228
+ @@script_cache.member?(script)
229
+ end
230
+
231
+ def empty?(filename)
232
+ filename=map_file(filename)
233
+ !!@@file_cache[filename].lines[:plain]
234
+ end
235
+
236
+ # Get line +line_number+ from file named +filename+. Return nil if
237
+ # there was a problem. If a file named filename is not found, the
238
+ # function will look for it in the $: array.
239
+ #
240
+ # Examples:
241
+ #
242
+ # lines = LineCache::getline('/tmp/myfile.rb')
243
+ # # Same as above
244
+ # $: << '/tmp'
245
+ # lines = LineCache.getlines('myfile.rb')
246
+ #
247
+ def getline(file_or_script, line_number, opts={})
248
+ lines =
249
+ if file_or_script.kind_of?(String)
250
+ filename = map_file(file_or_script)
251
+ filename, line_number = map_file_line(filename, line_number)
252
+ getlines(filename, opts)
253
+ else
254
+ script_getlines(file_or_script)
255
+ end
256
+ if lines and (1..lines.size) === line_number
257
+ return lines[line_number-1]
258
+ else
259
+ return nil
260
+ end
261
+ end
262
+
263
+ # Read lines of +script+ and cache the results. However +script+ was
264
+ # previously cached use the results from the cache. Return nil
265
+ # if we can't get lines
266
+ def script_getlines(script, opts={})
267
+ format = opts[:output] || :plain
268
+ line_formats =
269
+ if @@script_cache.member?(script)
270
+ @@script_cache[script].lines
271
+ else
272
+ update_script_cache(script, opts)
273
+ if @@script_cache.member?(script)
274
+ @@script_cache[script].lines
275
+ else
276
+ nil
277
+ end
278
+ end
279
+ return nil unless line_formats
280
+ if format != :plain && !line_formats[format]
281
+ highlight_string(line_formats[:plain].join('')).split(/\n/)
282
+ else
283
+ line_formats[format]
284
+ end
285
+ end
286
+
287
+ # Read lines of +filename+ and cache the results. However +filename+ was
288
+ # previously cached use the results from the cache. Return nil
289
+ # if we can't get lines
290
+ def getlines(filename, opts={})
291
+ filename = map_file(filename)
292
+ checkcache(filename) if opts[:reload_on_change]
293
+ format = opts[:output] || :plain
294
+ if @@file_cache.member?(filename)
295
+ lines = @@file_cache[filename].lines
296
+ if opts[:output] && !lines[format]
297
+ lines[format] =
298
+ highlight_string(lines[:plain].join(''), format).split(/\n/)
299
+ end
300
+ return lines[format]
301
+ else
302
+ opts[:use_script_lines] = true
303
+ update_cache(filename, opts)
304
+ if @@file_cache.member?(filename)
305
+ return @@file_cache[filename].lines[format]
306
+ else
307
+ return nil
308
+ end
309
+ end
310
+ end
311
+
312
+ def highlight_string(string, output_type)
313
+ require 'rubygems'
314
+ begin
315
+ require 'coderay'
316
+ require 'term/ansicolor'
317
+ rescue LoadError
318
+ return string
319
+ end
320
+ @@ruby_highlighter ||= CodeRay::Duo[:ruby, output_type]
321
+ @@ruby_highlighter.encode(string)
322
+ end
323
+
324
+ # Return full filename path for filename
325
+ def path(filename)
326
+ return unless filename.kind_of?(String)
327
+ filename = map_file(filename)
328
+ return nil unless @@file_cache.member?(filename)
329
+ @@file_cache[filename].path
330
+ end
331
+
332
+ def remap_file(from_file, to_file)
333
+ @@file2file_remap[from_file] = to_file
334
+ cache_file(to_file)
335
+ end
336
+
337
+ def remap_file_lines(from_file, to_file, range, start)
338
+ range = (range..range) if range.kind_of?(Fixnum)
339
+ to_file = from_file unless to_file
340
+ if @@file2file_remap_lines[to_file]
341
+ # FIXME: need to check for overwriting ranges: whether
342
+ # they intersect or one encompasses another.
343
+ @@file2file_remap_lines[to_file] << [from_file, range, start]
344
+ else
345
+ @@file2file_remap_lines[to_file] = [[from_file, range, start]]
346
+ end
347
+ end
348
+ module_function :remap_file_lines
349
+
350
+ # Return any compiled method saved for a filename.
351
+ def compiled_method(filename)
352
+ if (file = map_file(filename)) && @@file_cache[file]
353
+ return @@file_cache[file].compiled_method
354
+ else
355
+ return nil
356
+ end
357
+ end
358
+
359
+ # Return SHA1 of filename.
360
+ def sha1(filename)
361
+ filename = map_file(filename)
362
+ return nil unless @@file_cache.member?(filename)
363
+ return @@file_cache[filename].sha1.hexdigest if
364
+ @@file_cache[filename].sha1
365
+ sha1 = Digest::SHA1.new
366
+ @@file_cache[filename].lines[:plain].each do |line|
367
+ sha1 << line + "\n"
368
+ end
369
+ @@file_cache[filename].sha1 = sha1
370
+ sha1.hexdigest
371
+ end
372
+
373
+ # Return the number of lines in filename
374
+ def size(file_or_script)
375
+ cache(file_or_script)
376
+ if file_or_script.kind_of?(String)
377
+ file_or_script = map_file(file_or_script)
378
+ return nil unless @@file_cache.member?(file_or_script)
379
+ @@file_cache[file_or_script].lines[:plain].length
380
+ else
381
+ return nil unless @@script_cache.member?(file_or_script)
382
+ @@script_cache[file_or_script].lines[:plain].length
383
+ end
384
+ end
385
+
386
+ # Return File.stat in the cache for filename.
387
+ def stat(filename)
388
+ return nil unless @@file_cache.member?(filename)
389
+ @@file_cache[filename].stat
390
+ end
391
+ module_function :stat
392
+
393
+ # Return an Array of breakpoints in filename.
394
+ # The list will contain an entry for each distinct line event call
395
+ # so it is possible (and possibly useful) for a line number appear more
396
+ # than once.
397
+ def trace_line_numbers(filename, reload_on_change=false)
398
+ fullname = cache(filename, reload_on_change)
399
+ return nil unless fullname
400
+ e = @@file_cache[filename]
401
+ unless e.line_numbers
402
+ e.line_numbers =
403
+ TraceLineNumbers.lnums_for_str_array(e.lines[:plain])
404
+ e.line_numbers = false unless e.line_numbers
405
+ end
406
+ e.line_numbers
407
+ end
408
+
409
+ def map_file(file)
410
+ @@file2file_remap[file] ? @@file2file_remap[file] : file
411
+ end
412
+
413
+ def map_script(script)
414
+ if @@script2file[script]
415
+ @@script2file[script]
416
+ else
417
+ # Doc says there's new takes an optional string parameter
418
+ # But it doesn't work for me
419
+ sha1 = Digest::SHA1.new
420
+ string = script.eval_source
421
+ sha1 << script.eval_source
422
+ tempfile = Tempfile.new(["eval-#{sha1.hexdigest[0...7]}-", '.rb'])
423
+ tempfile.open.puts(string)
424
+ tempfile.close
425
+ @@script2file[script] = tempfile.path
426
+ tempfile.path
427
+ end
428
+ end
429
+
430
+ def map_file_line(file, line)
431
+ if @@file2file_remap_lines[file]
432
+ @@file2file_remap_lines[file].each do |from_file, range, start|
433
+ if range === line
434
+ from_file = from_file || file
435
+ return [from_file, start+line-range.begin]
436
+ end
437
+ end
438
+ end
439
+ return [map_file(file), line]
440
+ end
441
+
442
+ def script_is_eval?(script)
443
+ !!script.eval_source
444
+ end
445
+
446
+ # Update a cache entry. If something is wrong, return nil. Return
447
+ # true if the cache was updated and false if not.
448
+ def update_script_cache(script, opts)
449
+ return false unless script_is_eval?(script)
450
+ string = opts[:string] || script.eval_source
451
+ lines = {:plain => string.split(/\n/)}
452
+ lines[opts[:output]] = highlight_string(string, opts[:output]) if
453
+ opts[:output]
454
+ @@script_cache[script] =
455
+ LineCacheInfo.new(nil, nil, lines, nil, opts[:sha1],
456
+ opts[:compiled_method])
457
+ return true
458
+ end
459
+
460
+ # Update a cache entry. If something's wrong, return nil. Return
461
+ # true if the cache was updated and false if not. If
462
+ # opts[:use_script_lines] is true, use that as the source for the
463
+ # lines of the file
464
+ def update_cache(filename, opts={})
465
+ return nil unless filename
466
+
467
+ @@file_cache.delete(filename)
468
+ path = File.expand_path(filename)
469
+
470
+ if File.exist?(path)
471
+ stat = File.stat(path)
472
+ elsif File.basename(filename) == filename
473
+ # try looking through the search path.
474
+ stat = nil
475
+ for dirname in $:
476
+ path = File.join(dirname, filename)
477
+ if File.exist?(path)
478
+ stat = File.stat(path)
479
+ break
480
+ end
481
+ end
482
+ return false unless stat
483
+ end
484
+ begin
485
+ fp = File.open(path, 'r')
486
+ raw_string = fp.read
487
+ fp.rewind
488
+ lines = {:plain => fp.readlines}
489
+ fp.close()
490
+ lines[opts[:output]] =
491
+ highlight_string(raw_string, opts[:output]).split(/\n/) if
492
+ opts[:output]
493
+ rescue
494
+ ## print '*** cannot open', path, ':', msg
495
+ return nil
496
+ end
497
+ @@file_cache[filename] =
498
+ LineCacheInfo.new(File.stat(path), nil, lines, path, nil,
499
+ opts[:compiled_method])
500
+ @@file2file_remap[path] = filename
501
+ return true
502
+ end
503
+ end
504
+
505
+ # example usage
506
+ if __FILE__ == $0
507
+ def yes_no(var)
508
+ return var ? "" : "not "
509
+ end
510
+
511
+ lines = LineCache::getlines(__FILE__)
512
+ puts "#{__FILE__} has #{LineCache.size(__FILE__)} lines"
513
+ line = LineCache::getline(__FILE__, 6)
514
+ puts "The 6th line is\n#{line}"
515
+ line = LineCache::remap_file(__FILE__, 'another_name')
516
+ puts LineCache::getline('another_name', 7)
517
+
518
+ puts("Files cached: #{LineCache::cached_files.inspect}")
519
+ LineCache::update_cache(__FILE__)
520
+ LineCache::checkcache(__FILE__)
521
+ puts "#{__FILE__} has #{LineCache::size(__FILE__)} lines"
522
+ puts "#{__FILE__} trace line numbers:\n" +
523
+ "#{LineCache::trace_line_numbers(__FILE__).to_a.sort.inspect}"
524
+ puts("#{__FILE__} is %scached." %
525
+ yes_no(LineCache::cached?(__FILE__)))
526
+ puts LineCache::stat(__FILE__).inspect
527
+ puts "Full path: #{LineCache::path(__FILE__)}"
528
+ LineCache::checkcache # Check all files in the cache
529
+ LineCache::clear_file_cache
530
+ puts("#{__FILE__} is now %scached." %
531
+ yes_no(LineCache::cached?(__FILE__)))
532
+ # digest = SCRIPT_LINES__.select{|k,v| k =~ /digest.rb$/}
533
+ # puts digest.first[0] if digest
534
+ line = LineCache::getline(__FILE__, 7)
535
+ puts "The 7th line is\n#{line}"
536
+ LineCache::remap_file_lines(__FILE__, 'test2', (10..20), 6)
537
+ puts LineCache::getline('test2', 10)
538
+ puts "Remapped 10th line of test2 is\n#{line}"
539
+ eval("loc = Rubinius::VM::backtrace(0)[0]
540
+ puts LineCache::getline(loc.static_scope.script, 1)")
541
+ eval("loc = Rubinius::VM::backtrace(0)[0]
542
+ puts LineCache::size(loc.static_scope.script)")
543
+ eval("loc = Rubinius::VM::backtrace(0)[0]
544
+ puts LineCache::map_script(loc.static_scope.script)")
545
+
546
+ # Try new ANSI Terminal syntax coloring
547
+ LineCache::clear_file_cache(__FILE__)
548
+ LineCache::update_cache(__FILE__, :output => :term)
549
+ 50.upto(60) do |i|
550
+ line = LineCache::getline(__FILE__, i, :output => :term)
551
+ # puts line.inspect
552
+ puts line
553
+ end
554
+ puts '-' * 20
555
+ 50.upto(60) do |i|
556
+ line = LineCache::getline(__FILE__, i)
557
+ # puts line.inspect
558
+ puts line
559
+ end
560
+ end