Created
August 6, 2008 22:24
-
-
Save lmarlow/4291 to your computer and use it in GitHub Desktop.
Grep in Project TextMate command from http://henrik.nyh.se/2007/06/grep-in-project-command-for-textmate
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Grep in Project.tmCommand | |
========================= | |
Orginally from http://henrik.nyh.se/2007/06/grep-in-project-command-for-textmate | |
* Added a few more patterns of files to ignore | |
* Use 'git grep' instead of 'find | xargs grep' for quicker searches in git projects |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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>5A9D4FC6-6CBE-11D9-A21B-000D93589AF6</string> | |
<key>command</key> | |
<string>#!/usr/bin/env ruby -rcgi | |
# By Henrik Nyh <http://henrik.nyh.se> 2007-06-26 | |
# Free to modify and redistribute with credit. | |
%w{ui web_preview escape}.each { |lib| require "%s/lib/%s" % [ENV['TM_SUPPORT_PATH'], lib] } | |
NAME = "Grep in Project" | |
HEAD = <<-HTML | |
<style type="text/css"> | |
table { font-size:0.9em; border-collapse:collapse; border-bottom:1px solid #555; } | |
h2 { font-size:1.3em; } | |
tr { background:#FFF; } | |
tr.odd { background:#EEE; } | |
td { vertical-align:top; white-space:nowrap; padding:0.4em 1em; color:#000 !important; } | |
tr td:first-child { text-align:right; padding-right:1.5em; } | |
td a { color:#00F !important; } | |
tr.binary { background:#E8AFA8; } | |
tr.binary.odd { background:#E0A7A2; } | |
tr#empty { border-bottom:1px solid #FFF; } | |
tr#empty td { text-align:center; } | |
tr.newFile, tr.binary { border-top:1px solid #555; } | |
.keyword { font-weight:bold; background:#F6D73A; margin:0 0.1em; } | |
.ellipsis { color:#777; margin:0 0.5em; } | |
</style> | |
<script type="text/javascript"> | |
function reveal_file(path) { | |
const quote = '"'; | |
const command = "osascript -e ' tell app "+quote+"Finder"+quote+"' " + | |
" -e 'reveal (POSIX file " +quote+path+quote + ")' " + | |
" -e 'activate' " + | |
" -e 'end' "; | |
TextMate.system(command, null); | |
} | |
function findPos(obj) { | |
var curleft = curtop = 0; | |
if (obj.offsetParent) { | |
curleft = obj.offsetLeft | |
curtop = obj.offsetTop | |
while (obj = obj.offsetParent) { | |
curleft += obj.offsetLeft | |
curtop += obj.offsetTop | |
} | |
} | |
return {left: curleft, top: curtop}; | |
} | |
function resizeTableToFit() { | |
var table = document.getElementsByTagName("table")[0]; | |
const minWidth = 450, minHeight = 250; | |
var pos = findPos(table); | |
var tableFitWidth = table.offsetWidth + pos.left * 2; | |
var tableFitHeight = table.offsetHeight + pos.top + 50; | |
var screenFitWidth = screen.width - 150; | |
var screenFitHeight = screen.height - 150; | |
var setWidth = tableFitWidth > screenFitWidth ? screenFitWidth : tableFitWidth; | |
var setHeight = tableFitHeight > screenFitHeight ? screenFitHeight : tableFitHeight; | |
setWidth = setWidth < minWidth ? minWidth : setWidth; | |
setHeight = setHeight < minHeight ? minHeight : setHeight; | |
window.resizeTo(setWidth, setHeight); | |
} | |
</script> | |
HTML | |
RESIZE_TABLE = <<-HTML | |
<script type="text/javascript"> | |
resizeTableToFit(); | |
</script> | |
HTML | |
def ellipsize_path(path) | |
path.sub(/^(.{30})(.{10,})(.{30})$/) { "#$1⋯#$3" } | |
end | |
def escape(string) | |
CGI.escapeHTML(string) | |
end | |
def bail(message) | |
puts <<-HTML | |
<h2>#{ message }</h2> | |
HTML | |
html_footer | |
exit | |
end | |
directory = ENV['TM_PROJECT_DIRECTORY'] || | |
( ENV['TM_FILEPATH'] && File.dirname(ENV['TM_FILEPATH']) ) | |
puts html_head( | |
:window_title => NAME, | |
:page_title => NAME, | |
:sub_title => directory || "Error", | |
:html_head => HEAD | |
) | |
bail("Not in a saved file") unless directory | |
query = TextMate::UI.request_string(:title => "Grep in Project", :prompt => "Find this:", :default => %x{pbpaste -pboard find}) | |
bail("Search aborted") unless query | |
IO.popen('pbcopy -pboard find', 'w') { |copy| copy.print query } | |
puts <<-HTML | |
<h2>Searching for “#{ escape(query) }”</h2> | |
<table> | |
HTML | |
# TODO: Respect ENV['TM_SELECTED_FILES'] | |
if File.directory?(File.join(directory, '.git')) | |
command = %{cd "#{directory}"; git --no-pager grep -n #{e_sh query}} | |
else | |
command = %{cd "#{directory}"; find . \\( -path '*/.git' -or -path '*/.svn' -or -path '*/vendor' -or -path '*/tmp' -or -path '*/test/coverage' -or -path '*/log' -or -path '*.log' -or -path '*.gz' \\) -prune -or -type f -print0 | xargs -0 grep -nr --ignore-case --fixed-strings --exclude='*.log' #{e_sh query}} | |
end | |
IO.popen(command) do |pipe| | |
# Used to highlight matches | |
query_re = Regexp.new( Regexp.escape(CGI.escapeHTML(query)), Regexp::IGNORECASE) | |
last_path = path = i = nil | |
pipe.each_with_index do |line, i| | |
if line =~ /^(Binary file )(.*?) matches/ | |
prefix, file = $1, $2 | |
path = File.join(directory, file) | |
puts <<-HTML | |
<tr class="binary #{ 'odd' unless i%2==0 }"> | |
<td> | |
#{ prefix } | |
<a href="javascript:reveal_file('#{ escape(path) }')" title="#{ escape(path) }">#{ ellipsize_path(file) }</a> | |
</td> | |
<td></td> | |
</tr> | |
#{ RESIZE_TABLE if i%100==0 } | |
HTML | |
next | |
end | |
line.gsub!(/^([^:]+):(\d+):(.*)$/) do | |
relative_path, line_number, content = $1, $2, $3.strip | |
path = File.join(directory, file) | |
url = "txmt://open/?url=file://#{path}&line=#{line_number}" | |
content = escape(content). | |
# Highlight keywords | |
gsub(query_re) { %{<strong class="keyword">#$&</strong>} }. | |
# Ellipsize before, between and after keywords | |
gsub(%r{(^[^<]{25}|</strong>[^<]{15})([^<]{20,})([^<]{15}<strong|[^<]{25}$)}) do | |
%{#$1<span class="ellipsis" title="#{escape($2)}">⋯</span>#$3} | |
end | |
<<-HTML | |
<tr class="#{ 'odd' unless i%2==0 } #{ 'newFile' if (path != last_path) }"> | |
<td> | |
<a href="#{ url }" title="#{ "%s:%s" % [path, line_number] }"> | |
#{ "%s:%s" % [ellipsize_path(relative_path), line_number] } | |
</a> | |
</td> | |
<td>#{ content }</td> | |
</tr> | |
HTML | |
end | |
puts line | |
last_path = path | |
end | |
if i | |
# A paragraph inside the table ends up at the top even though it's output | |
# at the end. Something of a hack :) | |
i += 1 | |
puts <<-HTML | |
<p>#{i} matching line#{i==1 ? '' : 's'}:</p> | |
#{RESIZE_TABLE} | |
HTML | |
else | |
puts <<-HTML | |
<tr id="empty"><td colspan="2">No results.</td></tr> | |
HTML | |
end | |
end | |
puts <<-HTML | |
</table> | |
HTML | |
html_footer | |
</string> | |
<key>input</key> | |
<string>none</string> | |
<key>keyEquivalent</key> | |
<string>@F</string> | |
<key>name</key> | |
<string>Grep in Project</string> | |
<key>output</key> | |
<string>showAsHTML</string> | |
<key>uuid</key> | |
<string>3B7E16C9-0D34-42D4-8431-06CB7D819655</string> | |
</dict> | |
</plist> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment