Skip to content

Commit 5711fb8

Browse files
committed
Rework “Open Require” (⇧⌘D) to work inside gems and for require_relative
The command previously used ruby 1.8 and therefore would only search for includes and gems using ruby 1.8’s load path. Furthermore, it would not support `require_relative` nor would it handle a `require` inside of a gem (since that `require` would be relative to the gem’s load path). The previous command would, when used on a line without a `require` or `load` statement, search the entire file and present a menu. I have not replicated this behavior, as it’s not something I have ever used myself. I think a better behavior would be to open an input dialog, like the C bundle’s Quick Open. Lastly, the load path used is that of the ruby found via PATH, ideally it should use TM_RUBY (when set).
1 parent 556da23 commit 5711fb8

File tree

1 file changed

+56
-36
lines changed

1 file changed

+56
-36
lines changed

Commands/Open Require.tmCommand

Lines changed: 56 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -5,63 +5,83 @@
55
<key>beforeRunningCommand</key>
66
<string>nop</string>
77
<key>command</key>
8-
<string>#!/usr/bin/env ruby18
8+
<string>#!/usr/bin/env ruby
9+
require 'shellwords'
910
10-
require "#{ENV['TM_SUPPORT_PATH']}/lib/ui.rb"
11-
require "#{ENV['TM_SUPPORT_PATH']}/lib/textmate.rb"
12-
13-
REQUIRE_RE = /^\s*(?:require|load)\s*(['"])([^'"#]+?)(?:\.rb)?\1[ \t]*$/
11+
# Return ‘mail-2.7.1’ given: ‘/path/to/mail-2.7.1/lib/mail.rb’, ‘/path/to’
12+
def get_child_of_directory(descendent, directory)
13+
parent, child = File.split(descendent)
14+
unless child.start_with?('/')
15+
parent == directory ? child : get_child_of_directory(parent, directory)
16+
end
17+
end
1418
15-
Dir.chdir(ENV['TM_DIRECTORY']) if ENV.has_key?('TM_DIRECTORY')
19+
def global_search_paths
20+
res = $LOAD_PATH
1621
17-
gems_installed = begin
18-
require 'rubygems'
19-
true
20-
rescue LoadError
21-
false
22-
end
22+
if current_file = ENV['TM_FILEPATH']
23+
gem_dirs = Gem::Specification.dirs.map { |dir| File.expand_path('../gems', dir) }
24+
if gem_dir = gem_dirs.find { |dir| current_file.start_with?(dir) }
25+
if full_name = get_child_of_directory(current_file, gem_dir)
26+
Gem::Specification.find_all_by_full_name(full_name).each do |spec|
27+
res = spec.full_require_paths + res
28+
end
29+
end
30+
end
31+
end
2332
24-
requires = if ENV['TM_CURRENT_LINE'].to_s =~ REQUIRE_RE
25-
["#{$2}.rb"]
26-
else
27-
$stdin.read.scan(REQUIRE_RE).map { |_, path| "#{path}.rb" }
28-
end
29-
abort 'No includes found.' if requires.empty?
33+
res
34+
end
3035
31-
file = if requires.size &gt; 1
32-
choice = TextMate::UI.menu(requires) or exit
33-
requires[choice]
34-
else
35-
requires.pop
36-
end
37-
dir = $LOAD_PATH.find { |dir| File.exist? File.join(dir, file) }
38-
if not dir and gems_installed and gem_spec = Gem::GemPathSearcher.new.find(file)
39-
dir = File.join(gem_spec.full_gem_path, gem_spec.require_path)
36+
def find_in_search_path(file, search_paths)
37+
search_paths.map { |path| File.join(path, file) }.find { |path| File.exist?(path) }
4038
end
4139
42-
if file and dir
43-
dir.sub!(%r{\A\.(?=/|\z)}, ENV['TM_DIRECTORY']) if ENV['TM_DIRECTORY']
44-
file_path = File.join(dir, file)
45-
# puts file_path
46-
TextMate.go_to :file =&gt; file_path
47-
exit
40+
if ENV['TM_CURRENT_LINE'] =~ /^\s*(?:require(_relative)?|load)\s*(['"])(.+?)(?:\.rb)?\2(?:\s+|$)?/
41+
search_paths = $1 ? [ ENV['TM_DIRECTORY'] ] : global_search_paths
42+
name, file = $3, "#$3.rb"
43+
44+
unless path = find_in_search_path(file, search_paths)
45+
begin
46+
if gem_spec = Gem::Specification.find_by_name(name)
47+
path = find_in_search_path(file, gem_spec.full_require_paths)
48+
end
49+
rescue Gem::MissingSpecError =&gt; e
50+
end
51+
end
52+
53+
if path
54+
%x{ "$TM_MATE" #{path.shellescape} }
55+
else
56+
puts "Unable to locate ‘#{file}’. Locations searched:"
57+
puts search_paths.map { |path| "• #{path}" }.join("\n")
58+
end
4859
else
49-
puts "File not found: #{file}"
60+
puts "No require, require_relative, or"
61+
puts "load statement found in current line."
5062
end
5163
</string>
5264
<key>fallbackInput</key>
5365
<string>document</string>
5466
<key>input</key>
5567
<string>selection</string>
68+
<key>inputFormat</key>
69+
<string>text</string>
5670
<key>keyEquivalent</key>
5771
<string>@D</string>
5872
<key>name</key>
5973
<string>Open Require</string>
60-
<key>output</key>
61-
<string>showAsTooltip</string>
74+
<key>outputCaret</key>
75+
<string>afterOutput</string>
76+
<key>outputFormat</key>
77+
<string>text</string>
78+
<key>outputLocation</key>
79+
<string>toolTip</string>
6280
<key>scope</key>
6381
<string>source.ruby</string>
6482
<key>uuid</key>
6583
<string>8646378E-91F5-4771-AC7C-43FC49A93576</string>
84+
<key>version</key>
85+
<integer>2</integer>
6686
</dict>
6787
</plist>

0 commit comments

Comments
 (0)