# Encoding: UTF-8 [{beforeRunningCommand: "nop", bundleUUID: "4679484F-6227-11D9-BFB1-000D93589AF6", command: "#!/usr/bin/env ruby\nrequire ENV['TM_SUPPORT_PATH'] + \"/lib/exit_codes\"\nrequire \"\#{ENV['TM_SUPPORT_PATH']}/lib/escape\"\nif ENV['DIALOG'] =~ /2$/\n require \"\#{ENV['TM_BUNDLE_SUPPORT']}/objc_completion2\"\nelse\n require \"\#{ENV['TM_BUNDLE_SUPPORT']}/objc_completion\"\nend\n\ndef stripComments(line)\n line.gsub(/((['\"])(?:\\\\.|.)*?\\2)|\\/\\*.*?\\*\\/|\\/\\/[^\\n\\r]*/m) do |s| \n if $1\n s\n else\n ' ' * s.length()\n end\n end\nend\n\nclass String\n def index_of_nth_occurrence_of(n, ch)\n self.unpack(\"U*\").each_with_index do |e, i|\n return i if e == ch && (n -= 1) == 0\n end\n return -1\n end\nend\n\ndef caret_position(line)\n tmp = ENV['TM_LINE_NUMBER'].to_i - ENV['TM_INPUT_START_LINE'].to_i\n if tmp > 0\n caret_placement = line.index_of_nth_occurrence_of(tmp,?\\n) + ENV['TM_LINE_INDEX'].to_i\n else\n caret_placement =ENV['TM_LINE_INDEX'].to_i-ENV['TM_INPUT_START_LINE_INDEX'].to_i - 1\n end\nend\n\nline = ENV['TM_CURRENT_LINE']\ncaret_placement = caret_position(line)\nres = ObjCFallbackCompletion.new(stripComments(line) , caret_placement).print\n os = 0\nprint res", input: "none", keyEquivalent: "~", name: "Completion: Fallback", output: "insertAsSnippet", scope: "source.objc, source.objc++", uuid: "88754B0F-D8DB-4796-9D02-058B756C606D"}, {beforeRunningCommand: "nop", bundleUUID: "4679484F-6227-11D9-BFB1-000D93589AF6", command: "#!/usr/bin/env ruby\nrequire ENV['TM_SUPPORT_PATH'] + \"/lib/exit_codes\"\nrequire \"\#{ENV['TM_SUPPORT_PATH']}/lib/escape\"\n\nif ENV['DIALOG'] =~ /2$/\n require \"\#{ENV['TM_BUNDLE_SUPPORT']}/objc_selector_completion2\"\nelse\n require \"\#{ENV['TM_BUNDLE_SUPPORT']}/objc_selector_completion\"\nend\n\ndef stripComments(line)\n line.gsub(/((['\"])(?:\\\\.|.)*?\\2)|\\/\\*.*?\\*\\/|\\/\\/[^\\n\\r]*/m) do |s| \n if $1\n s\n else\n ' ' * s.length()\n end\n end\nend\n\n\ndef caret_position(line)\n tmp = ENV['TM_LINE_NUMBER'].to_i - ENV['TM_INPUT_START_LINE'].to_i\n if tmp > 0\n caret_placement = line.index_of_nth_occurrence_of(tmp,?\\n) + ENV['TM_LINE_INDEX'].to_i\n else\n caret_placement =ENV['TM_LINE_INDEX'].to_i-ENV['TM_INPUT_START_LINE_INDEX'].to_i - 1\n end\nend\n\nline = STDIN.read\n\ncaret_placement = caret_position(line)\n\nres = ObjcSelectorCompletion.new(stripComments(line) , caret_placement).print\nprint res", disableOutputAutoIndent: true, fallbackInput: "scope", input: "selection", keyEquivalent: "~", name: "Completion: Inside @selector", output: "insertAsSnippet", scope: "meta.selector.objc", uuid: "F929835A-C9F7-4934-87BD-05FD11C4435B"}, {beforeRunningCommand: "nop", bundleUUID: "4679484F-6227-11D9-BFB1-000D93589AF6", command: "#!/usr/bin/env ruby\n\n\n\nrequire ENV['TM_SUPPORT_PATH'] + \"/lib/exit_codes\"\nrequire \"\#{ENV['TM_SUPPORT_PATH']}/lib/escape\"\nif ENV['DIALOG'] =~ /2$/\n require \"\#{ENV['TM_BUNDLE_SUPPORT']}/objc_completion2\"\nelse\n require \"\#{ENV['TM_BUNDLE_SUPPORT']}/objc_completion\"\nend\n\ndef stripComments(line)\n line.gsub(/((['\"])(?:\\\\.|.)*?\\2)|\\/\\*.*?\\*\\/|\\/\\/[^\\n\\r]*/m) do |s| \n if $1\n s\n else\n s.split(\"\\n\").map{|e| ' ' * e.length() }.join(\"\\n\")\n end\n end\nend\n\nclass String\n def index_of_nth_occurrence_of(n, ch)\n self.unpack(\"U*\").each_with_index do |e, i|\n return i if e == ch && (n -= 1) == 0\n end\n return -1\n end\nend\n\ndef caret_position(line)\n tmp = ENV['TM_LINE_NUMBER'].to_i - ENV['TM_INPUT_START_LINE'].to_i\n if tmp > 0\n caret_placement = line.index_of_nth_occurrence_of(tmp,?\\n) + ENV['TM_LINE_INDEX'].to_i\n else\n caret_placement =ENV['TM_LINE_INDEX'].to_i-ENV['TM_INPUT_START_LINE_INDEX'].to_i - 1\n end\nend\n\nif ENV['TERMINAL_MATE_NEW']\n class ObjCMethodCompletion\n def show_dialog(prettyCandidates,start,&snip_gen)\n require \"\#{ENV['TM_SUPPORT_PATH']}/lib/osx/plist\"\n pl = {'menuItems' => prettyCandidates.map { |pretty, junk, full | { 'title' => pretty, 'cand' => full} }}\n pl.to_plist\n res = pl['menuItems'][0]\n snip_gen.call( res['cand'], start )\n end\n end\n \n class TextMateEarlyExitException < RuntimeError\n end\n \n module TextMate\n module_function\n def exit_show_tool_tip(out = nil)\n print out if out\n raise TextMateEarlyExitException, \"show tool kit\"\n end\n \n def exit_discard(out = nil)\n print out if out\n raise TextMateEarlyExitException, \"exit discard\"\n end\n end\n \n \n \n tc = [\n {:tmVars => {'TM_LINE_NUMBER' => '19', 'TM_INPUT_START_LINE' => '19', 'TM_LINE_INDEX' => '8', 'TM_INPUT_START_LINE_INDEX' => '0'}, :line => '[self ad]'},\n {:tmVars => {'TM_LINE_NUMBER' => '20', 'TM_INPUT_START_LINE' => '20', 'TM_LINE_INDEX' => '20', 'TM_INPUT_START_LINE_INDEX' => '0'}, :line => '[[NSStrig alloc] ini]'},\n {:tmVars => {'TM_LINE_NUMBER' => '19', 'TM_INPUT_START_LINE' => '19', 'TM_LINE_INDEX' => '8', 'TM_INPUT_START_LINE_INDEX' => '0'}, :line => '[self adbl]'},\n {:tmVars => {'TM_LINE_NUMBER' => '21', 'TM_INPUT_START_LINE' => '21', 'TM_LINE_INDEX' => '26', 'TM_INPUT_START_LINE_INDEX' => '0'}, :line => '[NSObject isKindOfClass:NS]'},\n {:tmVars => {'TM_LINE_NUMBER' => '22', 'TM_INPUT_START_LINE' => '22', 'TM_LINE_INDEX' => '18', 'TM_INPUT_START_LINE_INDEX' => '0'}, :line => '[sto setObject:for]'},\n {:tmVars => {'TM_LINE_NUMBER' => '23', 'TM_INPUT_START_LINE' => '23', 'TM_LINE_INDEX' => '22', 'TM_INPUT_START_LINE_INDEX' => '0'}, :line => '[sto setObject:for for]'},\n {:tmVars => {'TM_LINE_NUMBER' => '24', 'TM_INPUT_START_LINE' => '24', 'TM_LINE_INDEX' => '21', 'TM_INPUT_START_LINE_INDEX' => '0'}, :line => '[sto setObject:for + ]'},\n {:tmVars => {'TM_LINE_NUMBER' => '25', 'TM_INPUT_START_LINE' => '25', 'TM_LINE_INDEX' => '5', 'TM_INPUT_START_LINE_INDEX' => '0'}, :line => '[obj ]'},\n {:tmVars => {'TM_LINE_NUMBER' => '26', 'TM_INPUT_START_LINE' => '26', 'TM_LINE_INDEX' => '7', 'TM_INPUT_START_LINE_INDEX' => '0'}, :line => '[NSObje]'},\n {:tmVars => {'TM_LINE_NUMBER' => '27', 'TM_INPUT_START_LINE' => '27', 'TM_LINE_INDEX' => '5', 'TM_INPUT_START_LINE_INDEX' => '0'}, :line => '[obj ]'},\n {:tmVars => {'TM_LINE_NUMBER' => '28', 'TM_INPUT_START_LINE' => '28', 'TM_LINE_INDEX' => '6', 'TM_INPUT_START_LINE_INDEX' => '0'}, :line => '[obj t]'},\n {:tmVars => {'TM_LINE_NUMBER' => '11','TM_INPUT_START_LINE' => '11','TM_LINE_INDEX' => '11','TM_INPUT_START_LINE_INDEX' => '0'}, :line => '[obj t:b:av]'},\n {:tmVars => {'TM_LINE_NUMBER' => '30', 'TM_INPUT_START_LINE' => '30', 'TM_LINE_INDEX' => '19', 'TM_INPUT_START_LINE_INDEX' => '0'}, :line => '[obj set:[NSString ]]'},\n {:tmVars => {'TM_LINE_NUMBER' => '31', 'TM_INPUT_START_LINE' => '31', 'TM_LINE_INDEX' => '30', 'TM_INPUT_START_LINE_INDEX' => '0'}, :line => '[obj set:[NSString role:@\"eu\" ]]'},\n {:tmVars => {'TM_LINE_NUMBER' => '32', 'TM_INPUT_START_LINE' => '32', 'TM_LINE_INDEX' => '35', 'TM_INPUT_START_LINE_INDEX' => '0'}, :line => '[obj set:[NSString role:@\"eu\" forYo]]'},\n {:tmVars => {'TM_LINE_NUMBER' => '33', 'TM_INPUT_START_LINE' => '33', 'TM_LINE_INDEX' => '40', 'TM_INPUT_START_LINE_INDEX' => '0'}, :line => '[obj set:[NSString role:@\"eu\" forYou:sel]]'},\n {:tmVars => {'TM_LINE_NUMBER' => '34', 'TM_INPUT_START_LINE' => '34', 'TM_LINE_INDEX' => '26', 'TM_INPUT_START_LINE_INDEX' => '0'}, :line => '[obj postNotificationName: object:NSString *]'},\n {:tmVars => {'TM_LINE_NUMBER'=> '7','TM_INPUT_START_LINE'=> '6','TM_LINE_INDEX'=> '55', 'TM_INPUT_START_LINE_INDEX' => '0'}, :line => \"[[NSNotificationCenter defaultCenter] addObserver:self\\n selector:@selector(colorPicker:) ]\"}]\n\n \n ENV['TM_BUNDLE_SUPPORT'] = \"/Library/Application Support/TextMate/Bundles/Objective-C.tmbundle/Support\"\n tc.each do |element|\n element[:tmVars].each do |key,value|\n ENV[key] = value\n end\n caret_placement = caret_position(element[:line])\nbegin\n res = ObjCMethodCompletion.new(element[:line] , caret_placement).print\nrescue NoMethodError => boom\n\n puts \"error in:\" + element.inspect\n\n puts boom\n \nrescue TextMateEarlyExitException => boom\n puts \"Early Exit\"\nend\n \n end\n \nelse\nline = STDIN.read\ncaret_placement = caret_position(line)\nif ENV['TM_SCOPE'].include? \"meta.bracketed.objc\"\n res, os = ObjCMethodCompletion.new(stripComments(line) , caret_placement).print\nelse\n res = ObjCFallbackCompletion.new(stripComments(line) , caret_placement).print\n os = 0\nend\nif res\n print e_sn(line[0..caret_placement]) + res + e_sn(line[caret_placement + 1 + os..-1]) \nelse\n TextMate.exit_discard\nend\nend\n", disableOutputAutoIndent: true, fallbackInput: "scope", input: "selection", keyEquivalent: "~", name: "Completion: Inside Brackets", output: "insertAsSnippet", scope: "meta.function-with-body.objc | meta.bracketed.objc", uuid: "478FBA1D-C11C-4D53-BE95-8B8ABB5F15DC"}, {beforeRunningCommand: "nop", bundleUUID: "4679484F-6227-11D9-BFB1-000D93589AF6", command: "#!/usr/bin/env ruby\nrequire ENV['TM_SUPPORT_PATH'] + \"/lib/exit_codes\"\nrequire \"\#{ENV['TM_SUPPORT_PATH']}/lib/escape\"\n\nline = ENV['TM_CURRENT_LINE']\n\ndef construct_arg_name(arg)\n\ta = arg.match(/(NS|AB|CI|CD)?(Mutable)?(([AEIOQUYi])?[A-Za-z_0-9]+)/)\n\tunless a.nil?\n\t\t(a[4].nil? ? \"a\": \"an\") + a[3].sub!(/\\b\\w/) { $&.upcase }\n\telse\n\t\t\"\"\n\tend\nend\n\ndef prettify(cand, call)\n stuff = cand.split(\"\\t\")\n if stuff[0].count(\":\") > 0\n name_array = stuff[0].split(\":\")\n out = \"\"\n begin\n stuff[-(name_array.size)..-1].each_with_index do |arg,i|\n if arg == \"SEL\"\n out << name_array[i] + \":(SEL)\"+ \"aSelector \"\n else\n out << name_array[i] + \":(\"+ arg.gsub(/ \\*/,(ENV['TM_C_POINTER'] || \" *\").rstrip)+\")\"+ \"\#{construct_arg_name(arg)} \"\n end\n end\n rescue NoMethodError\n out << stuff[0]\n end\n else\n out = stuff[0]\n end\n out = \"(\#{stuff[5].gsub(/ \\*/,(ENV['TM_C_POINTER'] || \" *\").rstrip)})\#{out}\" unless call || (stuff.size < 4)\n\n return [out.chomp.strip, stuff[0], cand]\nend\n\ndef snippet_generator(cand, start, call)\nstart = 0\n stuff = cand[start..-1].split(\"\\t\")\n if stuff[0].count(\":\") > 0\n\n name_array = stuff[0].split(\":\")\n name_array = [\"\"] if name_array.empty? \n out = \"\"\n begin\n stuff[-(name_array.size)..-1].each_with_index do |arg,i|\n if arg == \"SEL\"\n out << name_array[i] + \":(\#{arg})${\#{(i+1).to_s}:aSelector} \" \n else\n out << name_array[i] + \":(\#{arg.gsub(/ \\*/,(ENV['TM_C_POINTER'] || \" *\").rstrip)})${\#{(i+1).to_s}:\#{construct_arg_name(arg)}} \"\n end\n end\n rescue NoMethodError\n out << stuff[0]\n end\n else\n out = stuff[0]\n end\nout = \"(\#{stuff[5].gsub(/ \\*/,(ENV['TM_C_POINTER'] || \" *\").rstrip)})\#{out}\" unless (stuff.size < 4)\n if ENV['TM_SCOPE'].include? \"meta.scope.implementation.objc\"\n if stuff[5].match(/^void$/) || stuff[5].match(/IBAction/)\n rv = \"\"\n elsif stuff[5].match(/^BOOL$/)\n rv = \"\\treturn ${1:Y}${1/^(?:(Y)|(N)|.*)/(?1:ES:(?2:O))/};\\n\"\n else\n rv = \"\\treturn nil;\\n\"\n end\n \n out = out.chomp.strip + \"\\n\\{$0\\n\#{rv}\\}\"\n else\n out = out.chomp.strip + \"$0;\"\n end\n return out\nend\n\ndef pop_up(candidates, searchTerm, call = true)\n start = searchTerm.size\n prettyCandidates = candidates.map { |candidate| prettify(candidate,call) }.sort\n\nif prettyCandidates.size > 1\n require \"enumerator\"\n pruneList = [] \n\n prettyCandidates.each_cons(2) do |a| \n pruneList << (a[0][0] != a[1][0]) # check if prettified versions are the same\n end\n pruneList << true\n ind = -1\n prettyCandidates = prettyCandidates.select do |a| #remove duplicates\n pruneList[ind+=1] \n end\n end\n prettyCandidates = prettyCandidates.sort {|x,y| x[1].downcase <=> y[1].downcase }\n if prettyCandidates.size > 1\n #index = start\n #test = false\n #while !test\n # candidates.each_cons(2) do |a,b|\n # break if test = (a[index].chr != b[index].chr || a[index].chr == \"\\t\")\n # end\n # break if test\n # searchTerm << candidates[0][index].chr\n # index +=1\n #end\n \n show_dialog(prettyCandidates,start) do |c,s|\n\t\t\tsnippet_generator(c,s, call)\n\t\tend\n else\n snippet_generator( candidates[0], start, call )\n end\nend\n\ndef show_dialog(prettyCandidates,start,&snip_gen)\n require \"\#{ENV['TM_SUPPORT_PATH']}/lib/osx/plist\"\n pl = {'menuItems' => prettyCandidates.map { |pretty,junk, full | { 'title' => pretty, 'cand' => full} }}\n io = open('|\"$DIALOG\" -u', \"r+\")\n io << pl.to_plist\n io.close_write\n res = OSX::PropertyList::load(io.read)\n if res.has_key? 'selectedMenuItem'\n snip_gen.call( res['selectedMenuItem']['cand'], start )\n else\n \"$0\"\n end\nend\n\ndef candidates_or_exit(methodSearch, list, fileNames, notif = false)\n\tx = candidate_list(methodSearch, list, fileNames, notif)\n TextMate.exit_show_tool_tip \"No completion available\" if x.empty?\n return x\nend\n\ndef candidate_list(methodSearch, list, fileNames, notif = false)\n candidates = []\n fileNames.each do |fileName|\n zGrepped = %x{ zgrep ^\#{e_sh methodSearch } \#{e_sh ENV['TM_BUNDLE_SUPPORT']}/\#{fileName} }\n candidates += zGrepped.split(\"\\n\")\n end\n # strip notifications\n if notif\n\t candidates = candidates.select {|cand| cand.match(/\\tno\\t/) }\n\telse\n candidates = candidates.reject {|cand| cand.match(/\\tno\\t/) }\n end\n return [] if candidates.empty?\n if list.nil?\n return candidates\n else\n n = []\n candidates.each do |cand|\n n << cand if list.include?(cand.split(\"\\t\")[0])\n end\n n = (n.empty? ? candidates : n)\n\n return n\n end\nend\n\nmethodDeclaration = /^((?:\\+|-)\\s*)([a-zA-Z][a-zA-Z0-9:]*)$/\n\nif k = line.match(methodDeclaration)\n candidates = candidates_or_exit( k[2], nil, \"cocoa.txt.gz\")\n res =pop_up(candidates, k[2])\n TextMate.exit_discard if res == \"$0\"\n print k[1] + res\nelse\n TextMate.exit_discard\nend\n", fallbackInput: "line", input: "selection", keyEquivalent: "~", name: "Completion: Partial Method Signature", output: "insertAsSnippet", scope: "meta.function.objc - (meta.argument-type.objc | meta.return-type.objc | meta.bracketed)", uuid: "30E93FBA-5A81-4D94-8A03-9CD46FCA3CFA"}, {beforeRunningCommand: "nop", command: "#!/usr/bin/env ruby -wKU\nprint STDIN.read.sub(/\\A\\[(.*\\])[^\\]]*\\]\\z/, '\\\\1')\n", fallbackInput: "scope", input: "selection", keyEquivalent: "^@\x7F", name: "Delete Outer Method Call", output: "replaceSelectedText", scope: "meta.bracketed.objc", uuid: "E802FA1A-1E2E-4F8A-957F-C1533CE57400"}, {beforeRunningCommand: "nop", bundleUUID: "4679484F-6227-11D9-BFB1-000D93589AF6", command: "#!/usr/bin/env ruby\n\nif `defaults read /System/Library/CoreServices/SystemVersion ProductVersion` !~ /10\\.4\\..*/\n require ENV['TM_BUNDLE_SUPPORT'] + '/lib/docset_query.rb'\n documentation_for_selector\n exit\nend\n\nline = STDIN.read\ncaret_placement = 0\ntmp = ENV['TM_LINE_NUMBER'].to_i - ENV['TM_INPUT_START_LINE'].to_i\nif tmp > 0\nclass String\n def index_of_nth_occurrence_of(n, ch)\n self.unpack(\"U*\").each_with_index do |e, i|\n return i if e == ch && (n -= 1) == 0\n end\n return -1\n end\nend\n caret_placement += line.index_of_nth_occurrence_of(tmp,?\\n) + ENV['TM_LINE_INDEX'].to_i\nelse\n caret_placement =ENV['TM_LINE_INDEX'].to_i-ENV['TM_INPUT_START_LINE_INDEX'].to_i - 1\nend\n\ndef match_iter(rgxp,str)\n offset = 0\n while m = str.match(rgxp)\n yield [m[0], m.begin(0) + offset, m[0].length]\n str = m.post_match\n offset += m.end(0)\n end\nend\n\ndef loadHTMLPage(url,className,methodName, ref)\n className = \"NSObject\" if ref\n m = open(url).read.match(/(\\#\\/\\/apple_ref\\/[^\"]+?\\/\#{className}\\/\#{methodName})\"/)\n url += m[1] if m\n TextMate.exit_show_html \"<meta http-equiv='Refresh' content='0;URL=tm-file://\#{url}'>\"\nend\n\npat = /(\"(\\\\.|[^\"\\\\])*\"|\\[|\\]|@selector\\([^\\)]*\\)|[a-zA-Z][a-zA-Z0-9]*:)/\n\nup = 0\nstart = [0]\n#Count [\nmatch_iter(pat , line[0..caret_placement]) do |tok, beg, len|\n t = tok[0].chr\n if t == \"[\"\n start << beg\n elsif t == \"]\"\n start.pop\n end\nend\n\nup = 0\nlast = line.length\nmatch_iter(pat , line[caret_placement+1..line.length]) do |tok, beg, len|\n t = tok[0].chr\n if t == \"[\"\n up +=1\n elsif t == \"]\"\n if up == 0\n last = beg + caret_placement\n break\n end\n up -=1\n end\nend\n\nup =-1\nlist = \"\"\nif line.match(/^(-|\\+)/)\n start[-1] = 0\n last = line.length\n up = 0\nend\n\nmatch_iter(pat , line[start[-1]..last]) do |tok, beg, len|\n t = tok[0].chr\n if t == \"[\"\n up +=1\n elsif t == \"]\"\n up -=1\n elsif t !='\"' and t !='@' and up == 0\n list << tok\n end\nend\n\nif list == \"\"\n m = line[start[-1]..last].match(/([a-zA-Z][a-zA-Z0-9]*:?)\\s*(;)?$/)\n if m\n list = m[1]\n last = m.begin(0)\n end\nend\n\nrequire \"\#{ENV['TM_SUPPORT_PATH']}/lib/escape\"\nzGrepped = %x{ zgrep ^\#{e_sh list + \"[[:space:]]\"} \#{e_sh ENV['TM_BUNDLE_SUPPORT']}/cocoa.txt.gz }\ncandidates = zGrepped.split(\"\\n\") #.map{|e| e.split[1]}\nrequire ENV['TM_SUPPORT_PATH'] + \"/lib/exit_codes.rb\"\nTextMate.exit_show_tool_tip \"No documentation found for:\\n\#{list}\" if candidates.empty?\nif candidates.size > 1 # if more than 1 candidate disambiguate\n m = line[start[-1]..last].match(/^(\\[\\s*)+([A-Z][a-zA-Z0-9]*)/)\n old = candidates\n if m\n candidates = candidates.select{|e| e.split(\"\\t\")[2] == m[2] }\n\n end\n candidates = old if candidates.empty?\nend\n\nif candidates.size > 1\n require \"\#{ENV['TM_SUPPORT_PATH']}/lib/osx/plist\"\n dialog_path = \"\#{ENV['TM_SUPPORT_PATH']}/bin/tm_dialog\"\n#pl = {'menuItems' => prettyCandidates.map { |pretty, full | { 'title' => pretty, 'cand' => full} }} \nplist = { 'menuItems' => candidates.map do |cand|\n {'title' => \"[\#{cand.split(\"\\t\")[3].match /[^;]+/} \#{cand.split(\"\\t\")[0]}]\", 'full' => cand} \n end\n }.to_plist\nlk = candidates.map do |cand|\n {'title' => \"[\#{cand.split(\"\\t\")[3]} \#{cand.split(\"\\t\")[0]}]\", 'full' => cand} \n end\n\n\n res = OSX::PropertyList::load(%x{\#{e_sh dialog_path} -up \#{e_sh plist} })\n if res.has_key? 'selectedMenuItem'\n\tresult = res['selectedMenuItem']['full']\n else\n TextMate.exit_discard \n end\nelse\n result = candidates[0]\nend\n\n#file:///Developer/ADC%20Reference%20Library/documentation/Cocoa/Reference/ApplicationKit/Classes/NSApplication_Class/Reference/Reference.html#//apple_ref/c/data/NSApplicationDidFinishLaunchingNotification\n#file:///Developer/ADC%20Reference%20Library/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/occ/clm/NSObject/alloc\n#file:///Developer/ADC%20Reference%20Library/documentation/GraphicsImaging/Reference/QuartzCoreFramework/Classes/CIColor_Class/Reference/Reference.html#//apple_ref/occ/clm/CIColor/colorWithRed:green:blue:alpha:\n#file:///Developer/ADC%20Reference%20Library/documentation/Cocoa/Reference/Foundation/Protocols/NSObject_Protocol/Reference/Reference.html#//apple_ref/occ/intfm/NSObject/autorelease\n\nref = false # used for proper HTML anchoring of delegate methods\n\nmethodName, framework,behaviors,nsClass, methodType = result.split(\"\\t\")\nsemi = nsClass.index(\";\")\nif semi.nil?\n className = nsClass\nelse\n className = nsClass[0..semi-1]\n if className == \"NSObject\" # hopefully this will get most delegate methods right\n className = nsClass[semi + 1 ..-1]\n ref = true\n end\nend\n\n\n tLeopard = {\"AK\" => \"/Developer/Documentation/DocSets/com.apple.ADC_Reference_Library.CoreReference.docset/Contents/Resources/Documents/documentation/Cocoa/Reference/ApplicationKit/\",\n \"F\" => \"/Developer/Documentation/DocSets/com.apple.ADC_Reference_Library.CoreReference.docset/Contents/Resources/Documents/documentation/Cocoa/Reference/Foundation/\", \n \"CI\" => \"/Developer/ADC Reference Library/documentation/GraphicsImaging/Reference/QuartzCoreFramework/\",\n \"WK\" => \"/Developer/Documentation/DocSets/com.apple.ADC_Reference_Library.CoreReference.docset/Contents/Resources/Documents/documentation/Cocoa/Reference/WebKit/\",\n \"CD\" => \"/Developer/ADC Reference Library/documentation/Cocoa/Reference/CoreDataFramework/\",\n \"Cl\" => \"Classes/\#{className}_Class/Reference/\",\n \"Pr\" => \"Protocols/\#{className}_Protocol/Reference/\",\n\t\"Q\" => \"file:///Developer/Documentation/DocSets/com.apple.ADC_Reference_Library.CoreReference.docset/Contents/Resources/Documents/documentation/GraphicsImaging/Reference/QuartzFramework/\"\n }\n\n \nt = {\"AK\" => \"/Developer/ADC Reference Library/documentation/Cocoa/Reference/ApplicationKit/\",\n \"F\" => \"/Developer/ADC Reference Library/documentation/Cocoa/Reference/Foundation/\", \n \"CI\" => \"/Developer/ADC Reference Library/documentation/GraphicsImaging/Reference/QuartzCoreFramework/\",\n\"WK\" => \"/Developer/ADC Reference Library/documentation/Cocoa/Reference/WebKit/\",\n \"CD\" => \"/Developer/ADC Reference Library/documentation/Cocoa/Reference/CoreDataFramework/\",\n \"Cl\" => \"Classes/\#{className}_Class/Reference/\",\n \"Pr\" => \"Protocols/\#{className}_Protocol/Reference/\", \n}\n\n url = \"\"\n url=t[framework] + t[behaviors] unless t[framework].nil?\n if File.exist?(url + \"Reference.html\")\n url += \"Reference.html\"\n loadHTMLPage(url,className,methodName,ref)\n elsif File.exist?(url + \"\#{className}.html\")\n url += \"\#{className}.html\"\n loadHTMLPage(url,className,methodName,ref)\n end\n url=tLeopard[framework] + tLeopard[behaviors] unless tLeopard[framework].nil?\n if File.exist?(url + \"Reference.html\")\n url += \"Reference.html\"\n loadHTMLPage(url,className,methodName,ref)\n elsif File.exist?(url + \"\#{className}.html\")\n url += \"\#{className}.html\"\n loadHTMLPage(url,className,methodName,ref)\n end\nTextMate.exit_show_tool_tip \"We found the selector, but the file on disk was not found. Debug info:\\n\#{result.gsub(/\\t/, ', ')}\"\n", fallbackInput: "scope", input: "selection", keyEquivalent: "^h", name: "Documentation for Selector", output: "showAsTooltip", scope: "meta.bracketed.objc | meta.function.objc", uuid: "8AF46225-833C-473E-8EEC-F21C581636F6"}, {beforeRunningCommand: "nop", command: "if [[ \"$(defaults read /System/Library/CoreServices/SystemVersion ProductVersion)\" == 10.6.* ]]; then\n \"${TM_RUBY:-ruby}\" -r\"$TM_BUNDLE_SUPPORT/lib/docset_query.rb\" -e 'documentation_for_word'\n exit\nfi\n\nif [[ \"$(defaults read /System/Library/CoreServices/SystemVersion ProductVersion)\" == 10.5.* ]]; then\n \"${TM_RUBY:-ruby}\" -r\"$TM_BUNDLE_SUPPORT/lib/docset_query.rb\" -e 'documentation_for_word'\n exit\nfi\n\ndoc_path=\"/Developer/ADC Reference Library/documentation/Cocoa/Reference\"\ndoc_path2=\"/Developer/Documentation/DocSets/com.apple.ADC_Reference_Library.CoreReference.docset/Contents/Resources/Documents/documentation/Cocoa/Reference\"\n\nif [[ -d \"$doc_path2\" ]]; then\n\tdoc_path=$doc_path2\nfi\n\nword=${TM_SELECTED_TEXT:-$TM_CURRENT_WORD}\n\n# first check our doc_references.txt\nreference=$(zgrep -w \"^$word\" \"$TM_BUNDLE_SUPPORT/doc_references.txt.gz\"|cut -f2)\nif [[ -n \"$reference\" ]]; then\n\tfile=\"$doc_path/$reference\"\n\t[[ -f \"${file%#*}\" ]] && exit_show_html \"<meta http-equiv='Refresh' content='0;URL=tm-file://${file// /%20}'>\"\nfi\n\n# then see if there's a file named after the word (class)\nfolders=( \"Foundation\" \"ApplicationKit\" \"WebKit\" )\nfor (( i = 0; i < ${#folders[@]}; i++ )); do\n\tfile=\"$doc_path/${folders[$i]}/ObjC_classic/Classes/$word.html\"\n\t[[ -f \"$file\" ]] && exit_show_html \"<meta http-equiv='Refresh' content='0;URL=tm-file://${file// /%20}'>\"\ndone\n\n# then see if there's a file named after the class in Xcode 2.3 or later\nfolders=( \"Foundation\" \"ApplicationKit\" \"WebKit\" )\nfor (( i = 0; i < ${#folders[@]}; i++ )); do\n\tfile=\"$doc_path/${folders[$i]}/Classes/${word}_Class/index.html\"\n\t[[ -f \"$file\" ]] && exit_show_html \"<meta http-equiv='Refresh' content='0;URL=tm-file://${file// /%20}'>\"\ndone\n\n# finally try man (PolyglotMan)\ntry_man () {\n\tif man -w \"$word\" &>/dev/null; then\n\t\tpage=$(\"$TM_SUPPORT_PATH/bin/html_man.sh\" -a \"$word\")\n\t\techo \"<meta http-equiv='Refresh' content='0;URL=tm-file://$page'>\"\n\t\texit_show_html\n\tfi\n}\n\nMANSECT=${MANSECT:-2:3:4:5:6:7:8:9} try_man\ntry_man\n\necho \"Couldn’t find documentation for “${word}”\"\n", fallbackInput: "word", input: "none", keyEquivalent: "^h", name: "Documentation for Word / Selection", output: "showAsTooltip", scope: "source.c, source.c++, source.objc, source.objc++, (source.objc support | source.objc++ support) - support.function.any-method", uuid: "2E0F350A-7B23-11D9-B084-000D93589AF6"}, {beforeRunningCommand: "nop", bundleUUID: "4679484F-6227-11D9-BFB1-000D93589AF6", command: ". \"$TM_SUPPORT_PATH/lib/webpreview.sh\"\nhtml_header \"Objective-C Bundle Help\" \"Objective-C\"\n\"$TM_SUPPORT_PATH/lib/markdown_to_help.rb\" <<'MARKDOWN'\n\n# Introduction\n\nThis document describes the commands of the Objective-C bundle and is a recommended read, since not all features are easy to discover.\n\nIn addition to this help file there are also 3 screencasts dedicated to showing Objective-C features (the links below are to more info about the screencast):\n\n 1. The [most recent][SC1] is by Joachim Mårtensson and shows completion, bracket matching, reformatting methods, and documentation lookup.\n 2. [Objective-C Part 2][SC2] by Allan Odgaard.\n 3. [Graceful Objective-C Snippets][SC3] by Allan Odgaard.\n\nYou can see [all screencasts here][AllCasts].\n\n[SC1]: http://macromates.com/screencast/TextMateObjCScreenCast.mov\n[SC2]: http://macromates.com/blog/archives/2006/04/29/objective-c-part-2-screencast/\n[SC3]: http://macromates.com/blog/archives/2006/03/17/graceful-objective-c-snippets/\n[AllCasts]: http://macromates.com/screencasts\n\n# Code Completion\n\nCode Completion is activated using the ⌥⎋ key equivalent. Code completion is available in several places which will be the topic of the next few sections.\n\n## Within Brackets\n\nA method call in Objective-C consists of three different types (though not all method calls take arguments):\n\n\t[«receiver» «selector»:«argument»]\n\nThe completion support can help you with all three parts, which will be explained in the following three sections.\n\n### Receiver\n\nA partially typed receiver can be completed, here candidates are all Cocoa classes (class objects). For example if we have:\n\n\t[NSObje‸ ]\n\nThen the list of possible completions will contain `NSObject` and `NSObjectController`.\n\n### Selector\n\nWhen the receiver is a class object, like in the following example:\n\n\t[NSString ‸]\n\nThen the candidates are all methods implemented by that class, in the above example, that would be all `NSString` class methods.\n\nIf the selector is partially typed, and the receiver is not a known class object, as is the case below:\n\n\t[object setV‸]\n\nThen a list is shown with all Cocoa methods starting with `setV`.\n\nCurrently the list of completion candidates are only filtered to those implemented by `object`, when object is a method local variable of a type that has been indexed.\n\nOne exception is when the receiver is itself a method call, for example in the following case:\n\n\t[[object string] ‸]\n\nHere only methods implemented by `NSString` are suggested, since it is know that the result of the `string` selector is an `NSString` object.\n\nFor selectors with multiple arguments, it is possible to activate completion when entering the name of a later argument, for example:\n\n\t[object setObject:name forK‸]\n\nWill list all methods starting with `setObject:forK`.\n\n### Argument\n\nWhen at the argument position, like here:\n\n [NSString stringWithCString:\"foo\" encoding:‸]\n\nThe completion command will check the argument type and find all constants which match that type. In the above example that would be all string encoding constants.\n\n## Outside of Brackets\n\nThe completion command will give different suggestions based on the caret’s scope. To see the current scope you can press ⌃⇧P. The 6 different scopes are marked below:\n\n\t@interface MyClass : NSO‸₁ <NSObj‸₂>\n\t{\n\t\tNSSt‸₃\n\t}\n\t@end\n\t\n\t@implementation MyClass\n\t- (id)init\n\t{\n\t\tif(self = [super init])\n\t\t{\n\t\t\tNSArr‸₄\n\t\t}\n\t\treturn self;\n\t}\n\t- windowW‸₅\n\t- (NSStr‸₆)stringFromString(NSSt‸₆<NSCod‸₂>)\n\t@end\n\nThe candidates suggested for the 6 different scopes are:\n\n 1. Known Cocoa classes.\n 2. Known Cocoa protocols.\n 3. Same as 1, but a variable name will also be inserted. For example the above will suggest `NSString` and `NSStream`. If we pick the former, it will insert `NSString *aString`.\n 4. Same as 3, but completion of known (C, C++, and Cocoa) functions is also suggested.\n 5. Here completion candidates are known Cocoa methods, but inserted as when implementing the method. For example in the above, one of the suggestions is `windowWillClose`, which when selected, will have the line changed to: `- (void)windowWillClose:(NSNotification *)aNotification`.\n 6. Same as 1, but an asterisk (`*`) is inserted.\n\n## Completing User Methods\n\nBy default completion candidates comes from the various Apple frameworks (mostly under the Cocoa umbrella).\n\nIf you wish to have your own methods and classes shown as completion candidates, you can invoke the *Index Headers for Completion* command.\n\nThis scans all headers in the current project folder and saves the result as `.methods.TM_Completions.txt.gz` and `.classes.TM_Completions.txt.gz` in your project folder.\n\nYou can later re-run the command to update the index.\n\n# Bracket Matching\n\n## Wrapping Selectors\n\nWhen you want to send a message (selector) to an object, you need to wrap both the object and message in square brackets (`[object message]`). Even if you did not put an opening bracket at the start of the expression, there is no need to go back and place it, since TextMate is smart enough to figure out where to place the start bracket, when typing an unmatched close bracket.\n\nHere are two simple examples:\n\n obj message‸ → [obj message]\n \n obj message:arg‸ → [obj message:arg]\n\nAn ambiguity exists when sending multi-argument messages to the object. For example if we have:\n\n obj message:arg otherMessage:arg2‸\n\nThen there are two candidates for the outcome:\n\n 1. [obj message:arg otherMessage:arg2]\n 2. obj message:[arg otherMessage:arg2]\n\nIf `message:otherMessage:` is a known Cocoa method or one of your indexed methods, then the first one is picked, otherwise the second one.\n\n## Wrapping Objects\n\nIf you type a closing bracket after a single word, it is assumed that this word is an object to which you want to send a message, e.g.:\n\n obj‸ → [obj ‸]\n\nThe space is only inserted if there is not already a space after the object.\n\n## General\n\nThe bracket completion is aware of quite a few C and Objective-C constructs and will not wrap when it does not make (much) sense.\n\n\tnil‸ → nil] // no messaging nil\n\treturn self‸ → return [self ‸]\n\tNSArray arrayWithObjects:names, urls, nil‸\n\t → [NSArray arrayWithObjects:names, urls, nil]\n\nHere is how the bracket matcher (basically) works:\n\n 1. If there is a word to the left of the caret, try to find an object to the left of it.\n 2. If the above failed, look for a message that takes an argument. If found, try to find even more such messages compare them with known Cocoa methods as we go, if no known Cocoa methods are found we use only the first matched message. try to find an object to the left of the message.\n 3. If neither 1 or 2, we have a single object, wrap it and insert the caret between the brackets.\n \n# Reformatting\n\n## Method Calls\n\nPressing ⌃Q when the caret is inside a multi-part method call will align the method-parts around the colon (`:`). For example the following:\n\n\t[NSEvent enterExitEventWithType:anEventType location:aPoint\n\t\tmodifierFlags:flags timestamp:aTimeInterval\n\t\twindowNumber:number context:aGraphicsContext\n\t\teventNumber:x trackingNumber:tracker userData:data]\n\nWill be reformatted as:\n\n\t[NSEvent enterExitEventWithType:anEventType\n\t location:aPoint\n\t modifierFlags:flags\n\t timestamp:aTimeInterval\n\t windowNumber:number\n\t context:aGraphicsContext\n\t eventNumber:x\n\t trackingNumber:tracker\n\t userData:data]\n\nBy default the inner brackets will be reformatted if the brackets are nested, move the caret to a non nested area to get the outer methods reformatted.\n\n## Method Implementations\n\nLike with method calls, we can reformat method implementations using ⌃Q. If for example we implemented the method above, and our source looks like this:\n\n\t+ (NSEvent *)enterExitEventWithType:(NSEventType)type\n\tlocation:(NSPoint)location modifierFlags:(unsigned int)flags\n\ttimestamp:(NSTimeInterval)time windowNumber:(int)windowNumber\n\tcontext:(NSGraphicsContext *)context eventNumber:(int)eventNumber\n\ttrackingNumber:(int)trackingNumber userData:(void *)userData\n\t{\n\t\n\t}\n\nThen we can reformat it easily using ⌃Q on the first line, and we get:\n\n\t+ (NSEvent *)enterExitEventWithType:(NSEventType)type\n\t location:(NSPoint)location\n\t modifierFlags:(unsigned int)flags\n\t timestamp:(NSTimeInterval)time\n\t windowNumber:(int)windowNumber\n\t context:(NSGraphicsContext *)context\n\t eventNumber:(int)eventNumber\n\t trackingNumber:(int)trackingNumber\n\t userData:(void*)userData\n\t{\n\t\n\t}\n\n# Documentation Look-up\n\nPressing ⌃H when the caret is on a class name, method call, function name, constant, or similar, will (for most known Cocoa stuff) find the appropriate spot in the documentation.\n\nThere are actually two documentation look-up commands (for two different scopes), so generally use the ⌃H key equivalent rather than the menu item.\n\n# Snippets\n\nThe Objective-C bundle has specialized several of the snippets for different scopes.\n\nAn example is shown below:\n\n\t@interface MyClass : NSObject\n\t{\n\t}\n\tm‸\n\t@end\n\t\n\t@implementation MyClass\n\tm‸\n\t\n\t- (void)myMethod\n\t{\n\t\tlog‸\n\t}\n\t@end\n\t\n\tvoid MyFunction ()\n\t{\n\t\tlog‸\n\t}\n\nHere we have entered both the tab trigger `m` and `log` in two different scopes. If we press tab (⇥) to expand all four tab triggers, then the resulting code becomes:\n\n\t@interface MyClass : NSObject\n\t{\n\t}\n\t- (id‸)method:(id)anArgument;\n\t@end\n\t\n\t@implementation MyClass\n\t- (id‸)method:(id)anArgument\n\t{\n\t\treturn nil;\n\t}\n\t\n\t- (void)myMethod\n\t{\n\t\tNSLog(@\"%s‸\", _cmd);\n\t}\n\t@end\n\t\n\tvoid MyFunction ()\n\t{\n\t\tNSLog(@\"‸\");\n\t}\n\nWhat’s interesting here is that the `m` tab trigger expands to a full method implementation inside `@implementation…@end`, but only a prototype when inside `@interface…@end`. Likewise the `log` tab trigger will only output the `_cmd` variable when called from inside a method (where it is available).\n\nAll the accessor snippets are likewise specialized for `@implementation` and `@interface`, though only one set appears in the menu (so use the tab trigger to get the proper one).\n\nIn addition to specializing the snippets for different scopes, a lot of other magic has also been put into them. If for example you add `%d` to the format string of the `NSLog` snippet, then an argument placeholder is automatically inserted. The method snippet will remove the `return nil;` line if you change the return type to `void`, and it will let the argument variable’s name match its type, for example if you change the type from `id` to `NSString*` then the variable becomes `aString`.\n\n# Credits\n\nThe cool stuff in this bundle is done by Joachim Mårtensson.\n\nAdditional work by Chris Thomas and Allan Odgaard. The initial bracket matcher (which served us well for a long time) was done by Rob Rix.\n\nMARKDOWN\nhtml_footer", input: "none", name: "Help", output: "showAsHTML", scope: "source.objc, source.objc++", uuid: "AFB40870-6F83-4211-9362-0538287B52A9"}, {beforeRunningCommand: "nop", bundleUUID: "4679484F-6227-11D9-BFB1-000D93589AF6", command: "if [[ -d \"$TM_PROJECT_DIRECTORY\" ]]; then\n find -E \"$TM_PROJECT_DIRECTORY\" -regex '.*/(_darcs|CVS|\\..*)' -prune -or -name '*.h' -print0 | ruby \"$TM_BUNDLE_SUPPORT/generateMethodList.rb\" -c \"$TM_PROJECT_DIRECTORY/.classes.TM_Completions.txt\" -m \"$TM_PROJECT_DIRECTORY/.methods.TM_Completions.txt\" -w \"$TM_BUNDLE_SUPPORT/CocoaClassesWithFramework.txt.gz\";\n gzip -f \"$TM_PROJECT_DIRECTORY/.methods.TM_Completions.txt\";\n gzip -f \"$TM_PROJECT_DIRECTORY/.classes.TM_Completions.txt\";\n echo \"indexing complete\";\n else\n echo \"no Project Path found\";\nfi", fallbackInput: "word", input: "none", name: "Index Headers for Completion", output: "showAsTooltip", scope: "source.objc, source.objc++", uuid: "42B1691B-DC28-4743-9B18-C8D51B70722C"}, {beforeRunningCommand: "nop", command: "#!/usr/bin/env ruby\n\n# Inserts a [super method] call suitable for the current method.\n# \n# The command is inserted as a snippet with each parameter as a tabstop\n# An opening bracket is inserted if necessary, and a semicolon is\n# added after the closing bracket if there is nothing else on the line.\n# \n# The command uses heuristics to find which method implementation is\n# being edited. It should be reasonably tolerant to various coding styles,\n# including different bracket and indentation styles.\n\nproto_re = /\n ^\\s* # Start of the line and optional space\n [+-]\\s* # a plus or minus for method specifier\n \\([^)]+\\) # the return type in brackets\n ((?:\\n|[^{])*) \n (?m:.*?) \n \\{ \n /x\n\nprevious_lines = STDIN.readlines[1..ENV['TM_LINE_NUMBER'].to_i - 1]\ninvocation_line = previous_lines[-1]\nproto = previous_lines.join.scan(proto_re)[-1]\n\nexit if proto.nil? or proto.empty?\n\nlast_proto_sel_with_types = proto[0].strip.sub(/^\\s+/, '').sub(%r{\\s*//.*$}, '').gsub(/\\n\\s*/, ' ')\n\ntabstop = 0\n\nlast_proto_sel_with_types.gsub!(/\\([^)]+\\)\\s*(([A-Za-z0-9_][A-Za-z0-9_]*))/) do |match|\n %Q{${\#{tabstop += 1}:\#$1}}\nend\n\nprint '[' if invocation_line[ENV[\"TM_LINE_INDEX\"].to_i - 1] != ?[\nprint 'super '\nprint last_proto_sel_with_types\nprint \"]\"\nprint \";\" if invocation_line =~ /^\\s+$/\n", fallbackInput: "scope", input: "document", name: "Insert Call to Super", output: "insertAsSnippet", scope: "source.objc meta.scope.implementation, source.objc++ meta.scope.implementation", tabTrigger: "super", uuid: "DA9B35AF-938D-4166-8576-E8E3C73F0739"}, {beforeRunningCommand: "nop", bundleUUID: "4679484F-6227-11D9-BFB1-000D93589AF6", command: "#!/usr/bin/env ruby\nrequire \"\#{ENV['TM_SUPPORT_PATH']}/lib/escape\"\nrequire ENV['TM_SUPPORT_PATH'] + \"/lib/exit_codes\"\n\nclass Lexer\n include Enumerable\n def initialize\n @label = nil\n @pattern = nil\n @handler = nil\n @input = nil\n \n reset\n \n yield self if block_given?\n end\n \n def input(&reader)\n if @input.is_a? self.class\n @input.input(&reader)\n else\n class << reader\n alias_method :next, :call\n end\n \n @input = reader\n end\n end\n \n def add_token(label, pattern, &handler)\n unless @label.nil?\n @input = clone\n end\n \n @label = label\n @pattern = /(\#{pattern})/\n @handler = handler || lambda { |label, match| [label, match] }\n \n reset\n end\n \n def next(peek = false)\n while @tokens.empty? and not @finished\n new_input = @input.next\n if new_input.nil? or new_input.is_a? String\n @buffer += new_input unless new_input.nil?\n new_tokens = @buffer.split(@pattern)\n while new_tokens.size > 2 or (new_input.nil? and not new_tokens.empty?)\n @tokens << new_tokens.shift\n @tokens << @handler[@label, new_tokens.shift] unless new_tokens.empty?\n end\n @buffer = new_tokens.join\n @finished = true if new_input.nil?\n else\n separator, new_token = @buffer.split(@pattern)\n new_token = @handler[@label, new_token] unless new_token.nil?\n @tokens.push( *[ separator,\n new_token,\n new_input ].select { |t| not t.nil? and t != \"\" } )\n reset(:buffer)\n end\n end\n peek ? @tokens.first : @tokens.shift\n end\n \n def peek\n self.next(true)\n end\n \n def each\n while token = self.next\n yield token\n end\n end\n \n private\n \n def reset(*attrs)\n @buffer = String.new if attrs.empty? or attrs.include? :buffer\n @tokens = Array.new if attrs.empty? or attrs.include? :tokens\n @finished = false if attrs.empty? or attrs.include? :finished\n end\nend\n\n\nclass ObjcParser\n\t\n\tattr_reader :list\n def initialize(args)\n @list = args\n end\n \n def get_position\n return nil,nil if @list.empty?\n\thas_message = true\n\n a = @list.pop\n endings = [:close,:post_op,:at_string,:at_selector,:identifier]\nopenings = [:open,:return,:control]\n if a.tt == :identifier && !@list.empty? && endings.include?(@list[-1].tt)\n insert_point = find_object_start\n else\n @list << a\n\thas_message = false unless methodList\n insert_point = find_object_start\n end\nreturn insert_point, has_message\n end\n \n def methodList\n \told = Array.new(@list)\n\n a = selector_loop(@list)\n if !a.nil? && a.tt == :selector\n if file_contains_selector? a.text\n return true\n else\n internal = Array.new(@list)\n b = a.text\n until internal.empty?\n tmp = selector_loop(internal)\n return true if tmp.nil?\n b = tmp.text + b\n if file_contains_selector? b\n @list = internal\n return true\n end\n end\n end\n\telse\n end\n@list = old\nreturn false\n end\n \n def file_contains_selector?(methodName)\n fileNames = [\"\#{ENV['TM_BUNDLE_SUPPORT']}/cocoa.txt.gz\"]\n userMethods = \"\#{ENV['TM_PROJECT_DIRECTORY']}/.methods.TM_Completions.txt.gz\"\n\n fileNames += [userMethods] if File.exists? userMethods\n candidates = []\n fileNames.each do |fileName|\n zGrepped = %x{zgrep ^\#{e_sh methodName }[[:space:]] \#{e_sh fileName }}\n candidates += zGrepped.split(\"\\n\")\n end\n\n return !candidates.empty?\n end\n \n def selector_loop(l)\n until l.empty?\n obj = l.pop\n case obj.tt\n when :selector\n return obj\n when :close\n return nil if match_bracket(obj.text,l).nil?\n when :open\n return nil\n end\n end\n return nil\n end\n \n def match_bracket(type,l)\n partner = {\"]\"=>\"[\",\")\"=>\"(\",\"}\"=>\"{\"}[type]\n up = 1\n until l.empty?\n obj = l.pop\n case obj.text\n when type\n up +=1\n when partner\n up -=1\n end\n return obj.beg if up == 0\n end\n end\n \n def find_object_start\n openings = [:operator,:selector,:open,:return,:control]\n until @list.empty? || openings.include?(@list[-1].tt)\n obj = @list.pop\n case obj.tt\n when :close\n tmp = match_bracket(obj.text, @list)\n b = tmp unless tmp.nil?\n when :star\n b, ate = eat_star(b,obj.beg)\n return b unless ate\n when :nil\n b = nil\n else\n b = obj.beg\n end\n end\n return b\n end\n\n def eat_star(prev, curr)\n openings = [:operator,:selector,:open,:return,:control,:star]\n if @list.empty? || openings.include?(@list[-1].tt)\n return curr, true\n else\n return prev, false\n end\n end\nend\n\nif __FILE__ == $PROGRAM_NAME\n require \"stringio\"\n line = ENV['TM_CURRENT_LINE']\n caret_placement =ENV['TM_LINE_INDEX'].to_i - 1\n\n up = 0\n pat = /\"(?:\\\\.|[^\"\\\\])*\"|\\[|\\]/\n line.scan(pat).each do |item|\n case item\n when \"[\"\n up+=1\n when \"]\"\n up -=1\n end\n end\n if caret_placement ==-1\n print \"]$0\" + e_sn(line[caret_placement+1..-1])\n TextMate.exit_insert_snippet\n end\n\n if up != 0 \n print e_sn(line[0..caret_placement])+\"]$0\"+e_sn(line[caret_placement+1..-1])\n TextMate.exit_insert_snippet\n end\n \n to_parse = StringIO.new(line[0..caret_placement])\n lexer = Lexer.new do |l|\n l.add_token(:return, /\\breturn\\b/)\n l.add_token(:nil, /\\bnil\\b/)\n l.add_token(:control, /\\b(?:if|while|for|do)(?:\\s*)\\(/)# /\\bif|while|for|do(?:\\s*)\\(/)\n l.add_token(:at_string, /\"(?:\\\\.|[^\"\\\\])*\"/)\n l.add_token(:selector, /\\b[A-Za-z_0-9]+:/)\n l.add_token(:identifier, /\\b[A-Za-z_0-9]+\\b/)\n l.add_token(:bind, /(?:->)|\\./)\n l.add_token(:post_op, /\\+\\+|\\-\\-/)\n l.add_token(:at, /@/)\n l.add_token(:star, /\\*/)\n l.add_token(:close, /\\)|\\]|\\}/)\n l.add_token(:open, /\\(|\\[|\\{/)\n l.add_token(:operator, /[&-+\\/=%!:\\,\\?;<>\\|\\~\\^]/)\n\n l.add_token(:terminator, /;\\n*|\\n+/)\n l.add_token(:whitespace, /\\s+/)\n l.add_token(:unknown, /./) \n \n l.input { to_parse.gets }\n #l.input {STDIN.read}\n end\n\n offset = 0\n tokenList = []\n A = Struct.new(:tt, :text, :beg)\n\n lexer.each do |token| \n tokenList << A.new(*(token<<offset)) unless [:whitespace,:terminator].include? token[0]\n offset +=token[1].length\n end\n if tokenList.empty?\n print e_sn(line[0..caret_placement])+\"]$0\"+e_sn(line[caret_placement+1..-1])\n TextMate.exit_insert_snippet\n end\n \n par = ObjcParser.new(tokenList)\n b, has_message = par.get_position\n\n if !line[caret_placement+1].nil? && line[caret_placement+1].chr == \"]\"\n if b.nil? || par.list.empty? || par.list[-1].text == \"[\"\n\t\t\tprint e_sn(line[0..caret_placement])+\"]$0\"+e_sn(line[caret_placement+2..-1])\n \tTextMate.exit_insert_snippet\n\t\tend\n end\n\n if b.nil?\n print e_sn(line[0..caret_placement])+\"]$0\"+e_sn(line[caret_placement+1..-1])\n elsif !has_message && (b < caret_placement )\n print e_sn(line[0..b-1]) unless b == 0\n ins = (/\\s/ =~ line[caret_placement].chr ? \"$0]\" : \" $0]\")\n print \"[\" +e_sn(line[b..caret_placement]) + ins +e_sn(line[caret_placement+1..-1])\n elsif b < caret_placement \n print e_sn(line[0..b-1]) unless b == 0\n print \"[\" +e_sn(line[b..caret_placement]) +\"]$0\"+e_sn(line[caret_placement+1..-1]) \n else\n print e_sn(line[0..caret_placement])+\"]$0\"+e_sn(line[caret_placement+1..-1])\n end\nend\n", fallbackInput: "line", input: "selection", keyEquivalent: "]", name: "Insert Matching Start Bracket", output: "insertAsSnippet", scope: "source.objc - string - comment, source.objc++ - string - comment", uuid: "DB16585F-4D78-412B-B468-38AD54C254B5"}, {beforeRunningCommand: "nop", command: "#!/usr/bin/env ruby\n\nproto_re = /\n ^\\s* # Start of the line and optional space\n [+-]\\s* # a plus or minus for method specifier\n \\([^)]+\\) # the return type in brackets\n ((?:\\n|[^@{])*) \n (?m:[\\s;]*) \n \\{ \n /x\n\nprevious_lines = STDIN.readlines[1..ENV['TM_LINE_NUMBER'].to_i - 1]\ninvocation_line = previous_lines[-1]\n\nproto = previous_lines.join.scan(proto_re)[-1]\n\nexit if proto.nil? or proto.empty?\n\nlast_proto_sel_with_types = proto[0].strip.sub(/^\\s+/, '').sub(%r{\\s*//.*$}, '').gsub(/\\n\\s*/, ' ')\n\nparams = []\nparams = last_proto_sel_with_types.scan(/(.+?)\\s*:\\s*\\((.+?)\\)\\s*(\\w+)/)\n\ndef format_specifier_for_type(type)\n type = type.gsub(/\\s*const\\s*/, '')\n %w[int bool BOOL long NSInteger NSUInteger size_t].each { |t| return('%d') if type.include? t }\n %w[float double CGFloat].each { |t| return('%f') if type.include? t }\n return '%c' if type == 'char'\n return '%C' if type == 'unichar'\n return '%s' if type.include?('char*') || type.include?('string')\n '%@'\nend\n\ndef transformer_for(type, name)\n case type\n when 'NSRect': \"NSStringFromRect(\#{name})\"\n when 'NSRange': \"NSStringFromRange(\#{name})\"\n when 'NSPoint': \"NSStringFromPoint(\#{name})\"\n when 'NSSize': \"NSStringFromSize(\#{name})\"\n when 'SEL': \"NSStringFromSelector(\#{name})\"\n when /string/: \"\#{name}.c_str()\"\n else name\n end\nend\n\nprint 'NSLog(@\"[%@ '\nif params.empty?\n print last_proto_sel_with_types\nelse\n print params.map { |param, type, name| param + ':' + format_specifier_for_type(type) }.join\nend\nprint ']\", [self class]'\nprint ', ' + params.map { |param, type, name| transformer_for(type, name) }.join(', ') unless params.empty?\nprint \");\"\n", input: "document", name: "Insert NSLog() for Current Method", output: "insertAsSnippet", scope: "source.objc meta.scope.implementation, source.objc++ meta.scope.implementation", tabTrigger: "logm", uuid: "C5624A26-E661-46EE-AA6A-14E6B678CFF9"}, {beforeRunningCommand: "nop", command: "#!/usr/bin/env ruby\n\ndef e (str); str.gsub(/[$`\\\\]/, '\\\\\\\\\\0'); end\n\nline = STDIN.read\ncol = ENV['TM_LINE_INDEX'].to_i\n\nleft, right = line[0...col], line[col..-1]\n\nif left =~ /(.*?)(\\[)?(\\w+)\\s+$/ then\n lead, bracket, cl = $1, $2, $3\n right = line[col+1..-1] unless bracket.nil?\n print \"\#{e lead}${1/.+/[/}[[\#{e cl} alloc] init$0]${1: autorelease]}\"\n print right.empty? ? \";\" : \"\#{e right}\"\nelse\n # this is only if we were not able to interpret the line\n print \"\#{e left}$0\#{e right}\"\nend\n", fallbackInput: "line", input: "selection", name: "Insert [[[… alloc] init] autorelease]", output: "insertAsSnippet", scope: "source.objc, source.objc++", tabTrigger: "alloc", uuid: "EA820F17-FD1D-4E7A-9961-E75F7D360968"}, {beforeRunningCommand: "nop", command: "#!/usr/bin/env ruby -wKU\n#\n# Possible improvements:\n# • Preserve empty lines between methods taken from the clipboard\n# • Make the “parser” conform to the actual Objective-C spec\n#\nrequire ENV['TM_SUPPORT_PATH'] + '/lib/exit_codes'\n\nmethods = []\n\n%x{ pbpaste }.scan(/^\n \\s*\n ([-+]) # Class or object method\n (\\s* \\( ([^\\)]+) \\))? # Optional return type\n (\\s* [a-z0-9_]+) # Method name\n\n # Zero or more parameters:\n\n ( (\\s* [a-z0-9_]*) # Optional name of parameter\n : # Mandatory colon\n (\\s* \\( [^\\)]+ \\))? # Optional type of parameter\n (\\s* [a-z0-9_]+) # Parameter name (might be optional)\n (\\s* , \\s* ...)? # Optional var-args notation\n )*\n\n (?=\\s* ;?) # Optional semicolon\n\n/ix) do\n rettype = $3.to_s.strip\n methods << [$&.strip.gsub(' *)', (ENV['TM_C_POINTER'] || ' *').rstrip + ')'), rettype]\nend\n\nTextMate::exit_show_tool_tip('No methods found on the clipboard') if methods.empty?\n\nif ENV['TM_SCOPE'] !~ /meta.implementation.objc/\n methods.each { |(proto, rettype)| puts \"\#{proto};\" }\nelse\n tabstop = 0\n puts(methods.map do |(proto, rettype)|\n ret = case rettype\n when \"void\", \"IBAction\"\n \"\"\n when \"BOOL\"\n \"\\treturn ${\#{tabstop+=1}:Y}${1/^(?:(Y)|(N)|.*)/(?1:ES:(?2:O))/};\\n\"\n else\n \"\\treturn ${\#{tabstop+=1}:nil};\\n\"\n end\n \"\#{proto}\\n{\\n\#{ret}}\\n\"\n end.join(\"\\n\"))\nend\n", fallbackInput: "line", input: "none", keyEquivalent: "^V", name: "Paste Implementation / Interface", output: "insertAsSnippet", scope: "meta.interface-or-protocol.objc, meta.implementation.objc", uuid: "CB5EC7EC-35B7-4FD8-9045-31CCC379D474"}, {beforeRunningCommand: "nop", command: "pbpaste|head -n1|perl -pe's/:\\(.+?\\)\\w+\\s*/:/g'|perl -pe's/^[-+]\\s*\\(.+?\\)\\s*|\\s+|;//g'", input: "none", keyEquivalent: "^V", name: "Paste selector", output: "afterSelectedText", scope: "meta.selector.objc", uuid: "D9CA98D1-7564-4CCB-8156-9A06210A1A7F"}, {beforeRunningCommand: "nop", bundleUUID: "4679484F-6227-11D9-BFB1-000D93589AF6", command: "#!/usr/bin/env ruby\nrequire \"\#{ENV['TM_SUPPORT_PATH']}/lib/escape\"\n\nline = STDIN.read\noffset = ENV['TM_INPUT_START_COLUMN'].to_i - 1\ncaret_placement = 0\ntmp = ENV['TM_LINE_NUMBER'].to_i - ENV['TM_INPUT_START_LINE'].to_i\nif tmp > 0\nclass String\n def index_of_nth_occurrence_of(n, ch)\n self.unpack(\"U*\").each_with_index do |e, i|\n return i if e == ch && (n -= 1) == 0\n end\n return -1\n end\nend\n caret_placement += line.index_of_nth_occurrence_of(tmp,?\\n) + ENV['TM_LINE_INDEX'].to_i\nelse\n caret_placement =ENV['TM_LINE_INDEX'].to_i-ENV['TM_INPUT_START_LINE_INDEX'].to_i - 1\nend\n\ndef match_iter(rgxp,str)\n offset = 0\n while m = str.match(rgxp)\n yield [m[0], m.begin(0) + offset, m[0].length]\n str = m.post_match\n offset += m.end(0)\n end\nend\n\npat = /(\"(\\\\.|[^\"\\\\])*\"|\\[|\\]|@selector\\([^\\)]*\\)|[a-zA-Z][a-zA-Z0-9]*:)/\nup = 0\nlist = []\n\nup = 0\npat = /(\"(\\\\.|[^\"\\\\])*\"|\\[|\\]|@selector\\([^\\)]*\\)|[a-zA-Z][a-zA-Z0-9]*:)/\nstart = [0]\nmatch_iter(pat , line[0..caret_placement]) do |tok, beg, len|\n t = tok[0].chr\n if t == \"[\"\n start << beg\n elsif t == \"]\"\n start.pop\n end\nend\n\n\nup = 0\nlast = line.length\nmatch_iter(pat , line[caret_placement+1..line.length]) do |tok, beg, len|\n t = tok[0].chr\n if t == \"[\"\n up +=1\n elsif t == \"]\"\n if up == 0\n last = beg + caret_placement + 1\n break\n end\n up -=1\n end\nend\n\nlist = []\nprefix = \"\"\nprefix = line[0..start[-1]-1] unless start[-1] == 0\nsuffix = line[last+1..-1]\nl = line[start[-1]..last]\nup = -1\n\nmatch_iter(pat , l) do |tok, beg, len|\n t = tok[0].chr\n if t == \"[\"\n up +=1\n elsif t == \"]\"\n up -=1\n elsif t !='\"' and t !='@' and up == 0\n list << [beg,len]\n end\nend\n\nlist << [l.length,0]\noffset += start[-1]\nif list.length > 2\n print e_sn(prefix+ l[0...list[1][0]].strip)\n #check to if the first \"selector:\" is not in the first line\n if k = line[0...start[-1]+list[0][0]].rindex(\"\\n\")\n firstIndex = list[0][0]+list[0][1]- k -1\n offset = start[-1]\n else\n firstIndex = list[0][0] + list[0][1] \n end\n (1..(list.length() -2)).each do |ind|\n list[ind][1]+list[ind][0]\n b = (b = firstIndex-list[ind][1]+offset) > 0 ? b : 0\n print e_sn(\"\\n\" + \" \"*b + l[(list[ind][0])...(list[ind+1][0])].strip)\n end\n print e_sn(suffix) unless suffix.nil?\nelse\n print e_sn(line)\nend\n", fallbackInput: "scope", input: "selection", keyEquivalent: "^q", name: "Reformat Method Call", output: "replaceSelectedText", scope: "meta.bracketed.objc", uuid: "8957C99F-88F5-42CC-B355-AAC6BF3FDF8D"}, {beforeRunningCommand: "nop", command: "#!/usr/bin/env ruby\ntext = STDIN.read\n\ntext.gsub!(/(\\([^\\)]+)\\s+(\\*\\))/, '\\1\\2')\n\noffset_to_first_colon = text.index(':')\n\nargument_triplets = text.scan /(.+?):\\s*\\((.+?)\\)\\s*([^\\s]*)\\s*/\n\nprint(argument_triplets.collect do |triplet|\n\tsprintf \"%\#{offset_to_first_colon}s:(%s)%s\", triplet[0], triplet[1], triplet[2]\nend.join(\"\\n\"))\n\nprint $1 if text.match /(\\n+)\\z/", fallbackInput: "scope", input: "selection", keyEquivalent: "^q", name: "Reformat Method Signature", output: "replaceSelectedText", scope: "meta.function.objc", uuid: "122E10C1-DFA2-4A9E-9B17-8EBFA6E10CC7"}]