Sync bundle with TextMate repo

This commit is contained in:
Tom Robinson
2009-09-07 18:53:59 -07:00
parent 98e18340b7
commit f7c00df9a9
28 changed files with 1178 additions and 18 deletions
@@ -0,0 +1,70 @@
<?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>command</key>
<string>#!/usr/bin/env ruby
proto_re = /
^\s* # Start of the line and optional space
[+-]\s* # a plus or minus for method specifier
\([^)]+\) # the return type in brackets
((?:\n|[^{])*)
(?m:.*?)
\{
/x
previous_lines = STDIN.readlines[1..ENV['TM_LINE_NUMBER'].to_i - 1]
invocation_line = previous_lines[-1]
proto = previous_lines.join.scan(proto_re)[-1]
exit if proto.nil? or proto.empty?
last_proto_sel_with_types = proto[0].strip.sub(/^\s+/, '').sub(%r{\s*//.*$}, '').gsub(/\n\s*/, ' ')
params = []
params = last_proto_sel_with_types.scan(/(.+?):\((.+?)\)(\w+)/)
def format_specifier_for_type(type)
%w[int bool BOOL long].each { |t| return('%d') if type.include? t }
return '%c' if type == 'char'
return '%C' if type == 'unichar'
return '%s' if type == 'char*'
'%@'
end
def transformer_for(type, name)
return "CPStringFromRect(#{name})" if type == 'CPRect'
return "CPStringFromPoint(#{name})" if type == 'CPPoint'
return "CPStringFromSize(#{name})" if type == 'CPSize'
return "CPStringFromSelector(#{name})" if type == 'SEL'
name
end
print 'CPLog("[%@ '
if params.empty?
print last_proto_sel_with_types
else
print params.map { |param, type, name| param + ':' + format_specifier_for_type(type) }.join
end
print ']", [self class]'
print ', ' + params.map { |param, type, name| transformer_for(type, name) }.join(', ') unless params.empty?
print ");"
</string>
<key>input</key>
<string>document</string>
<key>name</key>
<string>CPLog() for Current Method</string>
<key>output</key>
<string>insertAsSnippet</string>
<key>scope</key>
<string>source.js.objj meta.scope.implementation</string>
<key>tabTrigger</key>
<string>logm</string>
<key>uuid</key>
<string>F220FEE6-6522-4281-8091-CF8C66AED44F</string>
</dict>
</plist>
@@ -0,0 +1,29 @@
<?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>command</key>
<string>
. "$TM_SUPPORT_PATH/lib/webpreview.sh"
html_header "Objective-J Bundle Help" "Objective-J"
"$TM_SUPPORT_PATH/lib/markdown_to_help.rb" "$TM_BUNDLE_SUPPORT/help/help.markdown"
html_footer</string>
<key>input</key>
<string>none</string>
<key>keyEquivalent</key>
<string></string>
<key>name</key>
<string>Help</string>
<key>output</key>
<string>showAsHTML</string>
<key>scope</key>
<string>source.js.objj</string>
<key>uuid</key>
<string>AF27A8B3-C87F-410A-915B-D83271FDDC00</string>
</dict>
</plist>
@@ -0,0 +1,320 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//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 ruby
require "#{ENV['TM_SUPPORT_PATH']}/lib/escape"
require ENV['TM_SUPPORT_PATH'] + "/lib/exit_codes"
class Lexer
include Enumerable
def initialize
@label = nil
@pattern = nil
@handler = nil
@input = nil
reset
yield self if block_given?
end
def input(&amp;reader)
if @input.is_a? self.class
@input.input(&amp;reader)
else
class &lt;&lt; reader
alias_method :next, :call
end
@input = reader
end
end
def add_token(label, pattern, &amp;handler)
unless @label.nil?
@input = clone
end
@label = label
@pattern = /(#{pattern})/
@handler = handler || lambda { |label, match| [label, match] }
reset
end
def next(peek = false)
while @tokens.empty? and not @finished
new_input = @input.next
if new_input.nil? or new_input.is_a? String
@buffer += new_input unless new_input.nil?
new_tokens = @buffer.split(@pattern)
while new_tokens.size &gt; 2 or (new_input.nil? and not new_tokens.empty?)
@tokens &lt;&lt; new_tokens.shift
@tokens &lt;&lt; @handler[@label, new_tokens.shift] unless new_tokens.empty?
end
@buffer = new_tokens.join
@finished = true if new_input.nil?
else
separator, new_token = @buffer.split(@pattern)
new_token = @handler[@label, new_token] unless new_token.nil?
@tokens.push( *[ separator,
new_token,
new_input ].select { |t| not t.nil? and t != "" } )
reset(:buffer)
end
end
peek ? @tokens.first : @tokens.shift
end
def peek
self.next(true)
end
def each
while token = self.next
yield token
end
end
private
def reset(*attrs)
@buffer = String.new if attrs.empty? or attrs.include? :buffer
@tokens = Array.new if attrs.empty? or attrs.include? :tokens
@finished = false if attrs.empty? or attrs.include? :finished
end
end
class ObjcParser
attr_reader :list
def initialize(args)
@list = args
end
def get_position
return nil,nil if @list.empty?
has_message = true
a = @list.pop
endings = [:close,:post_op,:at_string,:at_selector,:identifier]
openings = [:open,:return,:control]
if a.tt == :identifier &amp;&amp; !@list.empty? &amp;&amp; endings.include?(@list[-1].tt)
insert_point = find_object_start
else
@list &lt;&lt; a
has_message = false unless methodList
insert_point = find_object_start
end
return insert_point, has_message
end
def methodList
old = Array.new(@list)
a = selector_loop(@list)
if !a.nil? &amp;&amp; a.tt == :selector
if file_contains_selector? a.text
return true
else
internal = Array.new(@list)
b = a.text
until internal.empty?
tmp = selector_loop(internal)
return true if tmp.nil?
b = tmp.text + b
if file_contains_selector? b
@list = internal
return true
end
end
end
else
end
@list = old
return false
end
def file_contains_selector?(methodName)
fileNames = ["#{ENV['TM_BUNDLE_SUPPORT']}/cocoa.txt.gz"]
userMethods = "#{ENV['TM_PROJECT_DIRECTORY']}/.methods.TM_Completions.txt.gz"
fileNames += [userMethods] if File.exists? userMethods
candidates = []
fileNames.each do |fileName|
zGrepped = %x{zgrep ^#{e_sh methodName }[[:space:]] #{e_sh fileName }}
candidates += zGrepped.split("\n")
end
return !candidates.empty?
end
def selector_loop(l)
until l.empty?
obj = l.pop
case obj.tt
when :selector
return obj
when :close
return nil if match_bracket(obj.text,l).nil?
when :open
return nil
end
end
return nil
end
def match_bracket(type,l)
partner = {"]"=&gt;"[",")"=&gt;"(","}"=&gt;"{"}[type]
up = 1
until l.empty?
obj = l.pop
case obj.text
when type
up +=1
when partner
up -=1
end
return obj.beg if up == 0
end
end
def find_object_start
openings = [:operator,:selector,:open,:return,:control]
until @list.empty? || openings.include?(@list[-1].tt)
obj = @list.pop
case obj.tt
when :close
tmp = match_bracket(obj.text, @list)
b = tmp unless tmp.nil?
when :star
b, ate = eat_star(b,obj.beg)
return b unless ate
when :nil
b = nil
else
b = obj.beg
end
end
return b
end
def eat_star(prev, curr)
openings = [:operator,:selector,:open,:return,:control,:star]
if @list.empty? || openings.include?(@list[-1].tt)
return curr, true
else
return prev, false
end
end
end
if __FILE__ == $PROGRAM_NAME
require "stringio"
line = ENV['TM_CURRENT_LINE']
caret_placement =ENV['TM_LINE_INDEX'].to_i - 1
up = 0
pat = /"(?:\\.|[^"\\])*"|\[|\]/
line.scan(pat).each do |item|
case item
when "["
up+=1
when "]"
up -=1
end
end
if caret_placement ==-1
print "]$0" + e_sn(line[caret_placement+1..-1])
TextMate.exit_insert_snippet
end
if up != 0
print e_sn(line[0..caret_placement])+"]$0"+e_sn(line[caret_placement+1..-1])
TextMate.exit_insert_snippet
end
to_parse = StringIO.new(line[0..caret_placement])
lexer = Lexer.new do |l|
l.add_token(:return, /\breturn\b/)
l.add_token(:nil, /\bnil\b/)
l.add_token(:control, /\b(?:if|while|for|do)(?:\s*)\(/)# /\bif|while|for|do(?:\s*)\(/)
l.add_token(:at_string, /"(?:\\.|[^"\\])*"/)
l.add_token(:selector, /\b[A-Za-z_0-9]+:/)
l.add_token(:identifier, /\b[A-Za-z_0-9]+\b/)
l.add_token(:bind, /(?:-&gt;)|\./)
l.add_token(:post_op, /\+\+|\-\-/)
l.add_token(:at, /@/)
l.add_token(:star, /\*/)
l.add_token(:close, /\)|\]|\}/)
l.add_token(:open, /\(|\[|\{/)
l.add_token(:operator, /[&amp;-+\/=%!:\,\?;&lt;&gt;\|\~\^]/)
l.add_token(:terminator, /;\n*|\n+/)
l.add_token(:whitespace, /\s+/)
l.add_token(:unknown, /./)
l.input { to_parse.gets }
#l.input {STDIN.read}
end
offset = 0
tokenList = []
A = Struct.new(:tt, :text, :beg)
lexer.each do |token|
tokenList &lt;&lt; A.new(*(token&lt;&lt;offset)) unless [:whitespace,:terminator].include? token[0]
offset +=token[1].length
end
if tokenList.empty?
print e_sn(line[0..caret_placement])+"]$0"+e_sn(line[caret_placement+1..-1])
TextMate.exit_insert_snippet
end
par = ObjcParser.new(tokenList)
b, has_message = par.get_position
if !line[caret_placement+1].nil? &amp;&amp; line[caret_placement+1].chr == "]"
if b.nil? || par.list.empty? || par.list[-1].text == "["
print e_sn(line[0..caret_placement])+"]$0"+e_sn(line[caret_placement+2..-1])
TextMate.exit_insert_snippet
end
end
if b.nil?
print e_sn(line[0..caret_placement])+"]$0"+e_sn(line[caret_placement+1..-1])
elsif !has_message &amp;&amp; (b &lt; caret_placement )
print e_sn(line[0..b-1]) unless b == 0
ins = (/\s/ =~ line[caret_placement].chr ? "$0]" : " $0]")
print "[" +e_sn(line[b..caret_placement]) + ins +e_sn(line[caret_placement+1..-1])
elsif b &lt; caret_placement
print e_sn(line[0..b-1]) unless b == 0
print "[" +e_sn(line[b..caret_placement]) +"]$0"+e_sn(line[caret_placement+1..-1])
else
print e_sn(line[0..caret_placement])+"]$0"+e_sn(line[caret_placement+1..-1])
end
end
</string>
<key>fallbackInput</key>
<string>line</string>
<key>input</key>
<string>selection</string>
<key>keyEquivalent</key>
<string>]</string>
<key>name</key>
<string>Insert Matching Start Bracket</string>
<key>output</key>
<string>insertAsSnippet</string>
<key>scope</key>
<string>source.js.objj</string>
<key>uuid</key>
<string>CD025B3E-36B9-4E16-A81E-8DB6E8466CD1</string>
</dict>
</plist>
@@ -0,0 +1,42 @@
<?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>command</key>
<string>#!/usr/bin/env ruby
def e (str); str.gsub(/[$`\\]/, '\\\\\0'); end
line = STDIN.read
col = ENV['TM_LINE_INDEX'].to_i
left, right = line[0...col], line[col..-1]
if left =~ /(.*?)(\[)?(\w+)\s+$/ then
lead, bracket, cl = $1, $2, $3
right = line[col+1..-1] unless bracket.nil?
print "#{e lead}${1/.+/[/}[[#{e cl} alloc] init$0]"
print right.empty? ? ";" : "#{e right}"
else
# this is only if we were not able to interpret the line
print "#{e left}$0#{e right}"
end
</string>
<key>fallbackInput</key>
<string>line</string>
<key>input</key>
<string>selection</string>
<key>name</key>
<string>Insert [[… alloc] init]</string>
<key>output</key>
<string>insertAsSnippet</string>
<key>scope</key>
<string>source.js.objj</string>
<key>tabTrigger</key>
<string>alloc</string>
<key>uuid</key>
<string>DF55A80D-E733-4CE2-A318-D56789B18406</string>
</dict>
</plist>
@@ -53,8 +53,10 @@ else
end</string>
<key>input</key>
<string>none</string>
<key>keyEquivalent</key>
<string>@R</string>
<key>name</key>
<string>Open Document in Running Browser(s)</string>
<string>Run in Browsers</string>
<key>output</key>
<string>discard</string>
<key>scope</key>
@@ -37,8 +37,6 @@ ps -xc|grep -sq Camino &amp;&amp; osascript -e 'tell app "Camino"' -e 'activate'
</string>
<key>input</key>
<string>none</string>
<key>keyEquivalent</key>
<string>@r</string>
<key>name</key>
<string>Refresh Running Browser(s)</string>
<key>output</key>
@@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>beforeRunningCommand</key>
<string>saveActiveFile</string>
<key>command</key>
<string>
[[ ! -z $TM_OBJJ_MASTER_FILE ]] &amp;&amp; INDEXFILE="$TM_OBJJ_MASTER_FILE"
[[ ! -z $TM_PROJECT_DIRECTORY ]] &amp;&amp; INDEXFILE="$TM_PROJECT_DIRECTORY/index.html"
[[ ! -z $TM_DIRECTORY ]] &amp;&amp; INDEXFILE="$TM_DIRECTORY/index.html"
if [ -z "$INDEXFILE" ]; then
D=`dirname "$TM_FILEPATH"`
while [ -z `find "$D" -name index.html` ]; do
D=`dirname "$D"`
done
INDEXFILE="${D}/index.html"
fi
[[ -z $INDEXFILE ]] &amp;&amp; echo "No start file found. Please set the shell variable 'OBJJ_MASTER_FILE'" &amp;&amp; exit 206
cat &lt;&lt;-HTML
&lt;script type="text/javascript" charset="utf-8"&gt;
try {
if (TextMate.system("", function (task) { })) {
var __TM_confirm_Status;
alert = function(s){TextMate.system("\"$DIALOG\" -e -p '{messageTitle=\"JavaScript\";informativeText=\""+s.toString().replace(/\x27/g,"").replace(/\"/g,'\\\"')+"\";}'",null);};
confirm = function(s){TextMate.system("\"$DIALOG\" -e -p '{messageTitle=\"JavaScript\";informativeText=\""+s.toString().replace(/\x27/g,"").replace(/\"/g,'\\\"')+"\";buttonTitles=(\"OK\",\"Cancel\");}'",null).onreadoutput=function(s){__TM_confirm_Status = s != 1;};return(__TM_confirm_Status)};
}
} catch(e) {}
&lt;/script&gt;
&lt;base href="file://${INDEXFILE// /%20}"&gt;
HTML
cat "$INDEXFILE"
[[ ! -z $(grep 'objj_exception_setOutputStream' "$INDEXFILE") ]] &amp;&amp; exit 205
cat &lt;&lt;-JS
&lt;script type="text/javascript" charset="utf-8"&gt;
objj_exception_setOutputStream(function(aString) { console.log(aString);alert(aString) });
&lt;/script&gt;
JS
exit 205
</string>
<key>input</key>
<string>none</string>
<key>keyEquivalent</key>
<string>@r</string>
<key>name</key>
<string>Run</string>
<key>output</key>
<string>showAsTooltip</string>
<key>scope</key>
<string>source.js.objj</string>
<key>uuid</key>
<string>0C55A19B-3B2D-418F-B7FD-7E64B736F379</string>
</dict>
</plist>
@@ -0,0 +1,27 @@
<?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>command</key>
<string>cat &lt;&lt;-HTM
&lt;body onload='javascript:window.location.href="http://cappuccino.org/learn/documentation/"'&gt;
&lt;/body&gt;
HTM
exit 205
</string>
<key>input</key>
<string>none</string>
<key>keyEquivalent</key>
<string>^H</string>
<key>name</key>
<string>Show Documentation</string>
<key>output</key>
<string>showAsTooltip</string>
<key>scope</key>
<string>source.js.objj</string>
<key>uuid</key>
<string>344244D8-67A3-4F23-8270-397BD1696AC4</string>
</dict>
</plist>
@@ -0,0 +1,214 @@
<?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>command</key>
<string>[[ -z $OBJJ_HOME ]] &amp;&amp; echo "OBJJ_HOME wasn't set!" &amp;&amp; exit 206
[[ ! -d "$OBJJ_HOME/Documentation" ]] &amp;&amp; echo "Please copy the folder Documentation to $OBJJ_HOME" &amp;&amp; exit 206
function showUpClassPage {
cat &lt;&lt;-HTM
&lt;body onload='javascript:window.location.href="tm-file://$OBJJ_HOME/Documentation/class$1"'&gt;
&lt;/body&gt;
HTM
exit 205
}
function showUpPage {
cat &lt;&lt;-HTM
&lt;body onload='javascript:window.location.href="tm-file://$1"'&gt;
&lt;/body&gt;
HTM
exit 205
}
DOCHEAD=$(perl -e '
#$line_nr = defined($ENV{"TM_INPUT_START_LINE"}) ? $ENV{"TM_INPUT_START_LINE"} : 1;
$line_nr = 1;
$cur_line_nr = $ENV{"TM_LINE_NUMBER"};
$header = "";
while($cur_line_nr--&gt;$line_nr) {$header.=&lt;&gt;;}
$tail = &lt;&gt;;
$header .= substr($tail,0,$ENV{"TM_LINE_INDEX"});
print $header;
')
# caret is inside of a class name
if [ `echo $TM_SCOPE | grep -c 'support.class.cappuccino'` -gt 0 ]; then
n=$(echo $TM_CURRENT_WORD | perl -pe 's/(.)(.)(.*)/_$1_$2_$3/;s/(?&lt;!_)([A-Z])(?!_)/_$1/g;s/_{2,}/_/g')
showUpClassPage "$n.html"
fi
# caret is inside of a foundation class name
if [ `echo $TM_SCOPE | grep -c 'support.variable.cappuccino.foundation'` -gt 0 ]; then
[[ "$TM_CURRENT_WORD" == "CPApp" ]] &amp;&amp; showUpClassPage "_C_P_Application.html"
fi
# caret is inside of a objj function
if [ `echo $TM_SCOPE | grep -c 'support.function.cappuccino'` -gt 0 ]; then
FILE=$(ruby -e '
require File.join(ENV["TM_SUPPORT_PATH"], "lib/ui.rb")
require File.join(ENV["TM_SUPPORT_PATH"], "lib/exit_codes.rb")
cur_word = ""
cur_word &lt;&lt; ENV["TM_CURRENT_WORD"]
cur_word.sub!("CG", "C[GP]") if cur_word[0..1] == "CG" or cur_word[0..1] == "CP"
lg = %x{egrep -rl "C[GP]RectMake" '$OBJJ_HOME/Documentation'}
urls = lg.split(/\n/).sort
if urls.length == 1
print urls.first
else
display = urls.map{|x| x.split("/").last.sub!(".html","")}
index=TextMate::UI.menu(display)
if index != nil
print urls[index]
else
TextMate.exit_discard()
end
end
')
FUNC=$(echo -en $TM_CURRENT_WORD | perl -pe 's/^(C[PG])(.*)/C[PG]$2/')
ANKER=`cat "$FILE" | egrep -o "\"#$FUNC.*?\"" | sed -e 's/^"//;s/".*//' | head -n 1`
[[ ! -z "$ANKER" ]] &amp;&amp; showUpPage "$FILE$ANKER"
[[ ! -z $FILE ]] &amp;&amp; showUpPage "$FILE" &amp;&amp; exit 206
fi
# caret is inside of a constant
if [ `echo $TM_SCOPE | grep -c 'support.constant.cappuccino'` -gt 0 ]; then
FILE=$(ruby -e '
require File.join(ENV["TM_SUPPORT_PATH"], "lib/ui.rb")
require File.join(ENV["TM_SUPPORT_PATH"], "lib/exit_codes.rb")
lg = %x{egrep -rl #{ENV["TM_CURRENT_WORD"]} '$OBJJ_HOME/Documentation'}
urls = lg.split(/\n/).sort
if urls.length == 1
print urls.first
else
display = urls.map{|x| x.split("/").last.sub!(".html","")}
index=TextMate::UI.menu(display)
if index != nil
print urls[index]
else
TextMate.exit_discard()
end
end
')
[[ ! -z $FILE ]] &amp;&amp; showUpPage "$FILE" &amp;&amp; exit 206
fi
# caret is inside of [method]
if [ `echo $TM_SCOPE | grep -c 'meta.bracketed.js.objj'` -gt 0 ]; then
# find []
DECL=$(echo -en "$DOCHEAD" | perl -e '
undef $/;
$header = &lt;&gt;;
$header=~s/\n/ /g;
@arr=split(//,$header);$c=0;
for($i=$#arr;$i&gt;-1;$i--){$c-- if($arr[$i] eq "]");$c++ if($arr[$i] eq "[");last if $c&gt;0;}
if($i==-1) {
print "";
} else {
print substr($header,$i+1);
}
')
# find the class for a method
CLASS=$(echo -en "$DECL" | perl -e '
undef $/;
$header = &lt;&gt;;
substr($header,0) =~ m/^\s*(\w+).*/;
$f = $1;
if (defined($f)) {
if($f=~m/CPApp/) {
print "CPApplication";
} else {
print $f;
}
} else {
substr($header,1) =~ m/^\s*(\w+).*/;
$f = $1;
if(defined($f)) {
if($f=~m/CPApp/) {
print "CPApplication";
} else {
print $f;
}
}
}
')
if [ ! -e "$OBJJ_HOME/Documentation/classes/$CLASS.html" ]; then
CLASS=$(echo -en "$DOCHEAD" | ruby -e '
require File.join(ENV["TM_SUPPORT_PATH"], "lib/ui.rb")
require File.join(ENV["TM_SUPPORT_PATH"], "lib/exit_codes.rb")
known_classes = []
classes = []
lg = %x{cd '$OBJJ_HOME/Documentation/classes'; egrep -rl #{ENV["TM_CURRENT_WORD"]} .}
known_classes = lg.split(/\n/).map{|x| x.sub("\.html","").sub("./","") }.sort
if known_classes.empty?
lg = %x{ls '$OBJJ_HOME/Documentation/classes'}
known_classes = lg.split(/\n/).map{|x| x.sub("\.html","").sub("./","") }.sort
end
STDIN.read().scan(/\b[_]{0,2}[NC][APS]\w+(?=[^\.])\b/) {|c| classes &lt;&lt; c if ! classes.include?(c) &amp;&amp; known_classes.include?(c)}
classes.sort!
if classes != known_classes
classes &lt;&lt; "--"
classes += known_classes
end
if classes.length == 1
if classes.first != "--"
print classes.first
else
TextMate.exit_discard()
end
else
index=TextMate::UI.menu(classes)
if index != nil
print classes[index]
else
TextMate.exit_discard()
end
end
')
fi
[[ -z $CLASS ]] &amp;&amp; exit 200
[[ ! -e "$OBJJ_HOME/Documentation/classes/$CLASS.html" ]] &amp;&amp; echo "Nothing for '$CLASS'!" &amp;&amp; exit 206
# tries to find only the first method for 'method1: method2: etc'
FIRSTMETHOD=$(echo -en "$DECL" | perl -e '
undef $/;$d = &lt;&gt;;
$d=~m/\s*(\w+):/m;
print $1;
')
METHOD=${FIRSTMETHOD:-$TM_CURRENT_WORD}
# find the correct anker within CLASS.html
ANKER=`cat "$OBJJ_HOME/Documentation/classes/$CLASS.html" | egrep -o "\"#$METHOD.*?\"" | sed -e 's/^"//;s/".*//' | head -n 1`
[[ ! -z "$ANKER" ]] &amp;&amp; showUpClassPage "$CLASS.html$ANKER"
# check for inherited methods
ANKER=`cat "$OBJJ_HOME/Documentation/classes/$CLASS.html" | egrep -o "[^#\"]+?html#$METHOD" | head -n 1`
# echo $CLASS; echo $METHOD; echo $ANKER; exit 206
CLASS=$(echo -en "$ANKER" | perl -pe 's/(.*?)\.html.*/$1/;')
# find the correct anker within the new CLASS.html
ANKER=`cat "$OBJJ_HOME/Documentation/classes/$CLASS.html" | egrep -o "\"#$METHOD.*?\"" | sed -e 's/^"//;s/".*//' | head -n 1`
[[ ! -z "$ANKER" ]] &amp;&amp; showUpClassPage "$CLASS.html$ANKER"
# [[ ! -z "$ANKER" ]] &amp;&amp; showUpClassPage "$ANKER"
fi
exit 205</string>
<key>input</key>
<string>selection</string>
<key>keyEquivalent</key>
<string>^h</string>
<key>name</key>
<string>Documentation for Word</string>
<key>output</key>
<string>replaceSelectedText</string>
<key>scope</key>
<string>support.class.cappuccino, support.variable.cappuccino.foundation, meta.bracketed.js.objj, support.function.cappuccino</string>
<key>uuid</key>
<string>2D05A28A-2ED7-4A9A-9A5C-8625466BC77C</string>
</dict>
</plist>