/
Cocoa Method Signature Completion.tmCommand
198 lines (181 loc) · 5.71 KB
/
Cocoa Method Signature Completion.tmCommand
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>beforeRunningCommand</key>
<string>nop</string>
<key>bundleUUID</key>
<string>4679484F-6227-11D9-BFB1-000D93589AF6</string>
<key>command</key>
<string>#!/usr/bin/env ruby18
require ENV['TM_SUPPORT_PATH'] + "/lib/exit_codes"
require "#{ENV['TM_SUPPORT_PATH']}/lib/escape"
line = ENV['TM_CURRENT_LINE']
def construct_arg_name(arg)
a = arg.match(/(NS|AB|CI|CD)?(Mutable)?(([AEIOQUYi])?[A-Za-z_0-9]+)/)
unless a.nil?
(a[4].nil? ? "a": "an") + a[3].sub!(/\b\w/) { $&.upcase }
else
""
end
end
def prettify(cand, call)
stuff = cand.split("\t")
if stuff[0].count(":") > 0
name_array = stuff[0].split(":")
out = ""
begin
stuff[-(name_array.size)..-1].each_with_index do |arg,i|
if arg == "SEL"
out << name_array[i] + ":(SEL)"+ "aSelector "
else
out << name_array[i] + ":("+ arg.gsub(/ \*/,(ENV['TM_C_POINTER'] || " *").rstrip)+")"+ "#{construct_arg_name(arg)} "
end
end
rescue NoMethodError
out << stuff[0]
end
else
out = stuff[0]
end
out = "(#{stuff[5].gsub(/ \*/,(ENV['TM_C_POINTER'] || " *").rstrip)})#{out}" unless call || (stuff.size < 4)
return [out.chomp.strip, stuff[0], cand]
end
def snippet_generator(cand, start, call)
start = 0
stuff = cand[start..-1].split("\t")
if stuff[0].count(":") > 0
name_array = stuff[0].split(":")
name_array = [""] if name_array.empty?
out = ""
begin
stuff[-(name_array.size)..-1].each_with_index do |arg,i|
if arg == "SEL"
out << name_array[i] + ":(#{arg})${#{(i+1).to_s}:aSelector} "
else
out << name_array[i] + ":(#{arg.gsub(/ \*/,(ENV['TM_C_POINTER'] || " *").rstrip)})${#{(i+1).to_s}:#{construct_arg_name(arg)}} "
end
end
rescue NoMethodError
out << stuff[0]
end
else
out = stuff[0]
end
out = "(#{stuff[5].gsub(/ \*/,(ENV['TM_C_POINTER'] || " *").rstrip)})#{out}" unless (stuff.size < 4)
if ENV['TM_SCOPE'].include? "meta.scope.implementation.objc"
if stuff[5].match(/^void$/) || stuff[5].match(/IBAction/)
rv = ""
elsif stuff[5].match(/^BOOL$/)
rv = "\treturn ${1:Y}${1/^(?:(Y)|(N)|.*)/(?1:ES:(?2:O))/};\n"
else
rv = "\treturn nil;\n"
end
out = out.chomp.strip + "\n\{$0\n#{rv}\}"
else
out = out.chomp.strip + "$0;"
end
return out
end
def pop_up(candidates, searchTerm, call = true)
start = searchTerm.size
prettyCandidates = candidates.map { |candidate| prettify(candidate,call) }.sort
if prettyCandidates.size > 1
require "enumerator"
pruneList = []
prettyCandidates.each_cons(2) do |a|
pruneList << (a[0][0] != a[1][0]) # check if prettified versions are the same
end
pruneList << true
ind = -1
prettyCandidates = prettyCandidates.select do |a| #remove duplicates
pruneList[ind+=1]
end
end
prettyCandidates = prettyCandidates.sort {|x,y| x[1].downcase <=> y[1].downcase }
if prettyCandidates.size > 1
#index = start
#test = false
#while !test
# candidates.each_cons(2) do |a,b|
# break if test = (a[index].chr != b[index].chr || a[index].chr == "\t")
# end
# break if test
# searchTerm << candidates[0][index].chr
# index +=1
#end
show_dialog(prettyCandidates,start) do |c,s|
snippet_generator(c,s, call)
end
else
snippet_generator( candidates[0], start, call )
end
end
def show_dialog(prettyCandidates,start,&snip_gen)
require "#{ENV['TM_SUPPORT_PATH']}/lib/osx/plist"
pl = {'menuItems' => prettyCandidates.map { |pretty,junk, full | { 'title' => pretty, 'cand' => full} }}
io = open('|"$DIALOG" -u', "r+")
io << pl.to_plist
io.close_write
res = OSX::PropertyList::load(io.read)
if res.has_key? 'selectedMenuItem'
snip_gen.call( res['selectedMenuItem']['cand'], start )
else
"$0"
end
end
def candidates_or_exit(methodSearch, list, fileNames, notif = false)
x = candidate_list(methodSearch, list, fileNames, notif)
TextMate.exit_show_tool_tip "No completion available" if x.empty?
return x
end
def candidate_list(methodSearch, list, fileNames, notif = false)
candidates = []
fileNames.each do |fileName|
zGrepped = %x{ zgrep ^#{e_sh methodSearch } #{e_sh ENV['TM_BUNDLE_SUPPORT']}/#{fileName} }
candidates += zGrepped.split("\n")
end
# strip notifications
if notif
candidates = candidates.select {|cand| cand.match(/\tno\t/) }
else
candidates = candidates.reject {|cand| cand.match(/\tno\t/) }
end
return [] if candidates.empty?
if list.nil?
return candidates
else
n = []
candidates.each do |cand|
n << cand if list.include?(cand.split("\t")[0])
end
n = (n.empty? ? candidates : n)
return n
end
end
methodDeclaration = /^((?:\+|-)\s*)([a-zA-Z][a-zA-Z0-9:]*)$/
if k = line.match(methodDeclaration)
candidates = candidates_or_exit( k[2], nil, "CocoaMethods.txt.gz")
res =pop_up(candidates, k[2])
TextMate.exit_discard if res == "$0"
print k[1] + res
else
TextMate.exit_discard
end
</string>
<key>fallbackInput</key>
<string>line</string>
<key>input</key>
<string>selection</string>
<key>keyEquivalent</key>
<string>~</string>
<key>name</key>
<string>Completion: Partial Method Signature</string>
<key>output</key>
<string>insertAsSnippet</string>
<key>scope</key>
<string>meta.function.objc - (meta.argument-type.objc | meta.return-type.objc | meta.bracketed)</string>
<key>uuid</key>
<string>30E93FBA-5A81-4D94-8A03-9CD46FCA3CFA</string>
</dict>
</plist>