Last active
October 14, 2015 00:17
-
-
Save adunsmoor/4278182 to your computer and use it in GitHub Desktop.
A threaded invocation of grep with a little GUI to display results.
This file contains hidden or 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
!/bin/env tclsh | |
# Ahran's Threaded Grep (ATGrep) | |
# | |
# This code is license free | |
# and comes without a warranty. | |
# If your hard drive melts | |
# or network crashes | |
# all I ask is that you don't blame me. | |
# | |
# :-) | |
# | |
# atgrep.tcl /tmp '*.txt' Event | |
array set search { | |
root "." | |
files "*.txt" | |
pattern "Event" | |
textwidget "" | |
active false | |
} | |
if { [llength $argv] >= 3} { | |
set search(root) [lindex $argv 0] | |
set search(files) [lindex $argv 1] | |
set search(pattern) [lindex $argv 2] | |
} | |
proc build_gui {} { | |
package require Tk | |
global search | |
label .l1 -text "Directory: " | |
entry .dir -textvar search(root) | |
bind .dir <Return> {do_search; break} | |
label .l2 -text "File Pattern:" | |
entry .files -textvar search(files) | |
bind .files <Return> {do_search; break} | |
label .l3 -text "Search Pattern:" | |
entry .search -textvar search(pattern) | |
bind .search <Return> {do_search; break} | |
button .go -text "Search" -command {do_search} | |
# TODO: lots of missing validation. spaces in the file patterns should | |
# indicate separate file searchs, for example. Right now that'll probably | |
# cause a stack trace. | |
frame .f | |
text .f.text -wrap none -xscrollcommand [list .f.hs set] -yscrollcommand [list .f.vs set] | |
scrollbar .f.hs -orient horizontal -command [list .f.text xview] | |
scrollbar .f.vs -orient vertical -command [list .f.text yview] | |
pack .f.vs -side right -fill y | |
pack .f.hs -side bottom -fill x | |
pack .f.text -fill both -expand yes | |
set search(textwidget) .f.text | |
grid .l1 -row 0 -column 0 | |
grid .dir -row 0 -column 1 | |
grid .l2 -row 0 -column 2 | |
grid .files -row 0 -column 3 | |
grid .l3 -row 0 -column 4 | |
grid .search -row 0 -column 5 -sticky ew | |
grid .go -row 0 -column 6 | |
grid .f -row 1 -column 0 -sticky nsew -columnspan 7 | |
grid columnconfigure . 5 -weight 1 | |
grid rowconfigure . 1 -weight 1 | |
wm protocol . WM_DELETE_WINDOW exit | |
} | |
# Handle output of the search asynchronously so results are visible before | |
# everything has been searched. | |
proc _get_search_results {pfd args} { | |
global search | |
if { [eof $pfd] } { | |
set search(active) false | |
return | |
} | |
set line "" | |
if { [gets $pfd line] > 0 } { | |
#TODO: make the filename clickable or something. | |
$search(textwidget) configure -state normal | |
$search(textwidget) insert end $line\n | |
$search(textwidget) configure -state disabled | |
} | |
} | |
proc do_search {} { | |
global search | |
# TODO: lots of fun and exciting things like updating a progress | |
# bar and disabling the search button if a search is active etc. | |
if { $search(active) } { | |
bell | |
return | |
} | |
# clear the text area | |
set search(active) true | |
$search(textwidget) configure -state normal | |
$search(textwidget) delete 1.0 end | |
$search(textwidget) configure -state disabled | |
# Here's the parallel magic. | |
# | |
# Query the system for the number of cpus | |
set cpus [exec grep processor /proc/cpuinfo | wc -l] | |
# Then xargs can break the job up in to N cpus with the -P option | |
# (don't forget -n, too) | |
# | |
# NOTE: hiden directories can really slow things down | |
set pfd [open [list | \ | |
find $search(root) \ | |
-name .svn -prune -o \ | |
-name .zfs -prune -o \ | |
-type f -name $search(files) -print0 | \ | |
xargs -0 -P$cpus -n1 grep -Hn $search(pattern)]] | |
# Collect results asynchronously. | |
fconfigure $pfd -buffering line -blocking 0 | |
fileevent $pfd readable [list _get_search_results $pfd] | |
vwait search(active) | |
close $pfd | |
} | |
build_gui | |
# entering event loop... | |
vwait mainloop |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment