melo / search-in-project-with-ack-tmcommand
- Source
- Commits
- Network (0)
- Issues (0)
- Downloads (0)
- Wiki (1)
- Graphs
-
Branch:
master
search-in-project-with-ack-tmcommand / SearchInProjectWithAck.tmCommand
| f84de58e » | melo | 2008-06-02 | 1 | <?xml version="1.0" encoding="UTF-8"?> | |
| 2 | <!DOCTYPE plist PUBLIC "-//Apple Computer//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> | ||||
| 3 | <plist version="1.0"> | ||||
| 4 | <dict> | ||||
| 5 | <key>beforeRunningCommand</key> | ||||
| 6 | <string>nop</string> | ||||
| 7 | <key>bundleUUID</key> | ||||
| 8 | <string>5A9D4FC6-6CBE-11D9-A21B-000D93589AF6</string> | ||||
| 9 | <key>command</key> | ||||
| 10 | <string>#!/usr/bin/env ruby -rcgi | ||||
| 11 | |||||
| 12 | # By Henrik Nyh <http://henrik.nyh.se> 2007-06-26 | ||||
| 13 | # Free to modify and redistribute with credit. | ||||
| 14 | # | ||||
| 15 | # Updated to use with ack by Pedro Melo <melo@simplicidade.org> 2008-05-26 | ||||
| a035a3a2 » | Corey Jewett | 2008-06-02 | 16 | # Support for TM_SELECTED_FILES by Corey Jewett <ml@syntheticplayground.com> 2008-05-30 | |
| f84de58e » | melo | 2008-06-02 | 17 | # | |
| a598b52a » | melo | 2008-08-11 | 18 | # 2008-08-11 (melo): Added flag ':' you must start your query with a : to | |
| 19 | # search only in the "selected files". I added this because using the | ||||
| 20 | # selected files ends up not being something that I commonly do. | ||||
| 21 | # | ||||
| 22 | # | ||||
| 99044e23 » | melo | 2008-06-02 | 23 | # **NOTE WELL**: TextMate does not inherit your PATH, so if you this | |
| 24 | # command does not find it define the environment variable | ||||
| 25 | # TM_ACK_COMMAND_PATH in your Preferences > Advanced > Shell Variables with | ||||
| 26 | # the full path of your copy of the ack command. | ||||
| 27 | # | ||||
| f84de58e » | melo | 2008-06-02 | 28 | ||
| ebebc2a2 » | melo | 2008-06-04 | 29 | %w{ui web_preview escape textmate tm/process}.each { |lib| require "%s/lib/%s" % [ENV['TM_SUPPORT_PATH'], lib] } | |
| dbb9155b » | Luke Daley | 2008-06-04 | 30 | ||
| ebebc2a2 » | melo | 2008-06-04 | 31 | ack_cmd=ENV['TM_ACK_COMMAND_PATH'] || ENV['TM_ACK'] || 'ack' | |
| dbb9155b » | Luke Daley | 2008-06-04 | 32 | TextMate.require_cmd(ack_cmd) | |
| f84de58e » | melo | 2008-06-02 | 33 | ||
| ebebc2a2 » | melo | 2008-06-04 | 34 | NAME = "Search in Project with ack" | |
| f84de58e » | melo | 2008-06-02 | 35 | HEAD = <<-HTML | |
| ebebc2a2 » | melo | 2008-06-04 | 36 | <style type="text/css"> | |
| f84de58e » | melo | 2008-06-02 | 37 | table { font-size:0.9em; border-collapse:collapse; border-bottom:1px solid #555; } | |
| 38 | h2 { font-size:1.3em; } | ||||
| 39 | td { vertical-align:top; white-space:nowrap; padding:0.4em 1em; } | ||||
| 40 | tr td:first-child { text-align:right; padding-right:1.5em; } | ||||
| 41 | tr.binary { background:#E8AFA8; } | ||||
| 42 | tr.binary.odd { background:#E0A7A2; } | ||||
| 43 | tr#empty { border-bottom:1px solid #FFF; } | ||||
| 44 | tr#empty td { text-align:center; } | ||||
| 45 | tr.newFile, tr.binary { border-top:1px solid #555; } | ||||
| 46 | .keyword { font-weight:bold; margin:0 0.1em; } | ||||
| 47 | .ellipsis { color:#777; margin:0 0.5em; } | ||||
| 48 | </style> | ||||
| ebebc2a2 » | melo | 2008-06-04 | 49 | <script type="text/javascript"> | |
| f84de58e » | melo | 2008-06-02 | 50 | function reveal_file(path) { | |
| ebebc2a2 » | melo | 2008-06-04 | 51 | const quote = '"'; | |
| 52 | const command = "osascript -e ' tell app "+quote+"Finder"+quote+"' " + | ||||
| 53 | " -e 'reveal (POSIX file " +quote+path+quote + ")' " + | ||||
| 54 | " -e 'activate' " + | ||||
| 55 | " -e 'end' "; | ||||
| f84de58e » | melo | 2008-06-02 | 56 | TextMate.system(command, null); | |
| 57 | } | ||||
| 58 | |||||
| 59 | function findPos(obj) { | ||||
| 60 | var curleft = curtop = 0; | ||||
| 61 | if (obj.offsetParent) { | ||||
| 62 | curleft = obj.offsetLeft | ||||
| 63 | curtop = obj.offsetTop | ||||
| 64 | while (obj = obj.offsetParent) { | ||||
| 65 | curleft += obj.offsetLeft | ||||
| 66 | curtop += obj.offsetTop | ||||
| 67 | } | ||||
| 68 | } | ||||
| 69 | return {left: curleft, top: curtop}; | ||||
| 70 | } | ||||
| 71 | |||||
| 72 | function resizeTableToFit() { | ||||
| ebebc2a2 » | melo | 2008-06-04 | 73 | var table = document.getElementsByTagName("table")[0]; | |
| f84de58e » | melo | 2008-06-02 | 74 | const minWidth = 450, minHeight = 250; | |
| 75 | |||||
| 76 | var pos = findPos(table); | ||||
| 77 | var tableFitWidth = table.offsetWidth + pos.left * 2; | ||||
| 78 | var tableFitHeight = table.offsetHeight + pos.top + 50; | ||||
| 79 | var screenFitWidth = screen.width - 150; | ||||
| 80 | var screenFitHeight = screen.height - 150; | ||||
| 81 | |||||
| 82 | var setWidth = tableFitWidth > screenFitWidth ? screenFitWidth : tableFitWidth; | ||||
| 83 | var setHeight = tableFitHeight > screenFitHeight ? screenFitHeight : tableFitHeight; | ||||
| 84 | setWidth = setWidth < minWidth ? minWidth : setWidth; | ||||
| 85 | setHeight = setHeight < minHeight ? minHeight : setHeight; | ||||
| 86 | |||||
| 87 | window.resizeTo(setWidth, setHeight); | ||||
| 88 | } | ||||
| 89 | |||||
| 90 | </script> | ||||
| 91 | HTML | ||||
| 92 | |||||
| 93 | RESIZE_TABLE = <<-HTML | ||||
| ebebc2a2 » | melo | 2008-06-04 | 94 | <script type="text/javascript"> | |
| f84de58e » | melo | 2008-06-02 | 95 | resizeTableToFit(); | |
| 96 | </script> | ||||
| 97 | HTML | ||||
| 98 | |||||
| 99 | def ellipsize_path(path) | ||||
| ebebc2a2 » | melo | 2008-06-04 | 100 | path.sub(/^(.{30})(.{10,})(.{30})$/) { "#$1?#$3" } | |
| f84de58e » | melo | 2008-06-02 | 101 | end | |
| 102 | |||||
| 103 | def escape(string) | ||||
| 104 | CGI.escapeHTML(string) | ||||
| 105 | end | ||||
| 106 | |||||
| 107 | def bail(message) | ||||
| 108 | puts <<-HTML | ||||
| 109 | <h2>#{ message }</h2> | ||||
| 110 | HTML | ||||
| 111 | html_footer | ||||
| 112 | exit | ||||
| 113 | end | ||||
| 114 | |||||
| ebebc2a2 » | melo | 2008-06-04 | 115 | directory = ENV['TM_PROJECT_DIRECTORY'] || | |
| 116 | ( ENV['TM_FILEPATH'] && File.dirname(ENV['TM_FILEPATH']) ) | ||||
| f84de58e » | melo | 2008-06-02 | 117 | ||
| 118 | puts html_head( | ||||
| 119 | :window_title => NAME, | ||||
| 120 | :page_title => NAME, | ||||
| ebebc2a2 » | melo | 2008-06-04 | 121 | :sub_title => directory || "Error", | |
| f84de58e » | melo | 2008-06-02 | 122 | :html_head => HEAD | |
| 123 | ) | ||||
| 124 | |||||
| ebebc2a2 » | melo | 2008-06-04 | 125 | bail("Not in a saved file") unless directory | |
| f84de58e » | melo | 2008-06-02 | 126 | ||
| ebebc2a2 » | melo | 2008-06-04 | 127 | query = TextMate::UI.request_string(:title => "Search in Project with ack", :prompt => "Find this:", :default => %x{pbpaste -pboard find}) | |
| 128 | bail("Search aborted") unless query | ||||
| a598b52a » | melo | 2008-08-11 | 129 | ||
| 130 | if query[0,1] == ':' | ||||
| 131 | query[0,1] = '' | ||||
| 132 | use_selected_files = true | ||||
| 133 | else | ||||
| 134 | use_selected_files = false | ||||
| 135 | end | ||||
| 136 | |||||
| ebebc2a2 » | melo | 2008-06-04 | 137 | IO.popen('pbcopy -pboard find', 'w') { |copy| copy.print query } | |
| f84de58e » | melo | 2008-06-02 | 138 | ||
| 139 | puts <<-HTML | ||||
| ebebc2a2 » | melo | 2008-06-04 | 140 | <h2>Searching for #{ escape(query) }</h2> | |
| f84de58e » | melo | 2008-06-02 | 141 | HTML | |
| 142 | |||||
| a598b52a » | melo | 2008-08-11 | 143 | if use_selected_files | |
| 144 | selected_files=TextMate.selected_files | ||||
| 145 | end | ||||
| cb09ae8b » | melo | 2008-06-02 | 146 | ||
| 147 | if selected_files | ||||
| bf09f165 » | melo | 2008-08-11 | 148 | command = [ack_cmd, "-H", '--', query, selected_files] | |
| cb09ae8b » | melo | 2008-06-02 | 149 | puts <<-HTML | |
| a598b52a » | melo | 2008-08-11 | 150 | <p><small>Search limited to #{ escape(selected_files.join(' ')) }</small></p> | |
| cb09ae8b » | melo | 2008-06-02 | 151 | HTML | |
| a035a3a2 » | Corey Jewett | 2008-06-02 | 152 | else | |
| dbb9155b » | Luke Daley | 2008-06-04 | 153 | Dir.chdir(directory) | |
| bf09f165 » | melo | 2008-08-11 | 154 | command = [ack_cmd, '--', query] | |
| a035a3a2 » | Corey Jewett | 2008-06-02 | 155 | end | |
| f84de58e » | melo | 2008-06-02 | 156 | ||
| cb09ae8b » | melo | 2008-06-02 | 157 | puts <<-HTML | |
| 158 | <table> | ||||
| 159 | HTML | ||||
| 160 | |||||
| dbb9155b » | Luke Daley | 2008-06-04 | 161 | # Used to highlight matches | |
| 162 | query_re = Regexp.new( Regexp.escape(CGI.escapeHTML(query)), Regexp::IGNORECASE) | ||||
| f84de58e » | melo | 2008-06-02 | 163 | ||
| dbb9155b » | Luke Daley | 2008-06-04 | 164 | last_path = path = i = nil | |
| ebebc2a2 » | melo | 2008-06-04 | 165 | err = "" | |
| dbb9155b » | Luke Daley | 2008-06-04 | 166 | alternate = true | |
| 167 | lines = 0 | ||||
| f84de58e » | melo | 2008-06-02 | 168 | ||
| dbb9155b » | Luke Daley | 2008-06-04 | 169 | TextMate::Process.run(command, :interactive_input => false) do |line, type| | |
| 170 | case type | ||||
| 171 | when :err | ||||
| 172 | err << line | ||||
| 173 | when :out | ||||
| 174 | lines = lines + 1 | ||||
| f84de58e » | melo | 2008-06-02 | 175 | line.gsub!(/^([^:]+):(\d+):(.*)$/) do | |
| 176 | |||||
| 177 | relative_path, line_number, content = $1, $2, $3.strip | ||||
| a035a3a2 » | Corey Jewett | 2008-06-02 | 178 | ||
| ebebc2a2 » | melo | 2008-06-04 | 179 | relative_path.sub!(directory + "/", '') if selected_files | |
| a035a3a2 » | Corey Jewett | 2008-06-02 | 180 | ||
| ebebc2a2 » | melo | 2008-06-04 | 181 | path = directory + '/' + relative_path | |
| 182 | url = "txmt://open/?url=file://#{path}&line=#{line_number}" | ||||
| 183 | fname = "%s:%s" % [ellipsize_path(relative_path), line_number]; | ||||
| 184 | fname = ":%s" % [ line_number ] if (path == last_path); | ||||
| f84de58e » | melo | 2008-06-02 | 185 | ||
| 186 | content = escape(content). | ||||
| 187 | # Highlight keywords | ||||
| ebebc2a2 » | melo | 2008-06-04 | 188 | gsub(query_re) { %{<a href="#{url}"><strong class="keyword">#$&</strong></a>} }. | |
| f84de58e » | melo | 2008-06-02 | 189 | # Ellipsize before, between and after keywords | |
| 190 | gsub(%r{(^[^<]{25}|</strong>[^<]{15})([^<]{20,})([^<]{15}<strong|[^<]{25}$)}) do | ||||
| ebebc2a2 » | melo | 2008-06-04 | 191 | %{#$1<span class="ellipsis" title="#{escape($2)}">?</span>#$3} | |
| f84de58e » | melo | 2008-06-02 | 192 | end | |
| 193 | <<-HTML | ||||
| 194 | |||||
| ebebc2a2 » | melo | 2008-06-04 | 195 | <tr class="#{ 'odd' unless (alternate = (not alternate)) } #{ 'newFile' if (path != last_path) }"> | |
| f84de58e » | melo | 2008-06-02 | 196 | <td> | |
| ebebc2a2 » | melo | 2008-06-04 | 197 | <a href="#{ url }" title="#{ "%s:%s" % [path, line_number] }"> | |
| f84de58e » | melo | 2008-06-02 | 198 | #{ fname } | |
| 199 | </a> | ||||
| 200 | </td> | ||||
| 201 | <td>#{ content }</td> | ||||
| 202 | </tr> | ||||
| 203 | |||||
| 204 | HTML | ||||
| 205 | end | ||||
| 206 | puts line | ||||
| 207 | last_path = path | ||||
| 208 | end | ||||
| dbb9155b » | Luke Daley | 2008-06-04 | 209 | end | |
| f84de58e » | melo | 2008-06-02 | 210 | ||
| dbb9155b » | Luke Daley | 2008-06-04 | 211 | if lines | |
| ebebc2a2 » | melo | 2008-06-04 | 212 | # A paragraph inside the table ends up at the top even though it's output | |
| dbb9155b » | Luke Daley | 2008-06-04 | 213 | # at the end. Something of a hack :) | |
| 214 | puts <<-HTML | ||||
| ebebc2a2 » | melo | 2008-06-04 | 215 | <p>#{lines} matching line#{lines==1 ? '' : 's'}:</p> | |
| dbb9155b » | Luke Daley | 2008-06-04 | 216 | #{RESIZE_TABLE} | |
| 217 | HTML | ||||
| 218 | else | ||||
| 219 | puts <<-HTML | ||||
| ebebc2a2 » | melo | 2008-06-04 | 220 | <tr id="empty"><td colspan="2">No results.</td></tr> | |
| dbb9155b » | Luke Daley | 2008-06-04 | 221 | HTML | |
| 222 | end | ||||
| 223 | |||||
| 224 | if $? != 0 | ||||
| ebebc2a2 » | melo | 2008-06-04 | 225 | TextMate::UI.alert(:critical, "Search In Project With Ack Error", err) | |
| dbb9155b » | Luke Daley | 2008-06-04 | 226 | TextMate.exit_discard | |
| f84de58e » | melo | 2008-06-02 | 227 | end | |
| 228 | |||||
| 99044e23 » | melo | 2008-06-02 | 229 | # TODO: see how to detect command not found in ruby and suggest using | |
| 230 | # TM_ACK_COMMAND_PATH to solve it | ||||
| 231 | |||||
| f84de58e » | melo | 2008-06-02 | 232 | puts <<-HTML | |
| 233 | </table> | ||||
| 234 | HTML | ||||
| 235 | |||||
| 236 | html_footer | ||||
| dbb9155b » | Luke Daley | 2008-06-04 | 237 | ||
| 238 | TextMate.exit_show_html | ||||
| f84de58e » | melo | 2008-06-02 | 239 | </string> | |
| 240 | <key>input</key> | ||||
| 241 | <string>none</string> | ||||
| 242 | <key>keyEquivalent</key> | ||||
| 243 | <string>@F</string> | ||||
| 244 | <key>name</key> | ||||
| 245 | <string>Search in Project with ack</string> | ||||
| 246 | <key>output</key> | ||||
| 247 | <string>showAsHTML</string> | ||||
| 248 | <key>uuid</key> | ||||
| 249 | <string>0B537D91-B21D-4A52-BFD8-D1E73669E2BD</string> | ||||
| 250 | </dict> | ||||
| 251 | </plist> | ||||
