Created
July 29, 2017 20:17
-
-
Save greggirwin/2dfe6bc45f596592c890b52d1d7f9475 to your computer and use it in GitHub Desktop.
RGrep (Rebol Grep)
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
| REBOL [ | |
| Title: "Grep in REBOL" | |
| File: %rgrep.r | |
| Author: "Gregg Irwin" | |
| Version: 0.0.2 | |
| Comment: { | |
| rgrep searches one or more input files for lines containing a match | |
| to a specified pattern. Refinements on EXEC are a shot at familiar | |
| switches used with GREP. Not sure if we need them, though /quiet does | |
| allow a nice optimization as we can break out on the first match. | |
| By default: | |
| It prints the matching lines. | |
| It is case insensitive. | |
| At its core, rgrep uses rawk. | |
| Could be part of a shell emulator called RUSH - REBOL Unix SHell. :) | |
| } | |
| history: [ | |
| 0.0.1 [01-Mar-2002 {Intitial Release}] | |
| 0.0.2 [10-Apr-2002 | |
| {Changed 'files parameter to 'sources to match new RAWK.} | |
| ] | |
| ] | |
| TBD: [ | |
| {Figure out how we want to return results for more processing. | |
| It should be easy to return a block of filenames with the count, | |
| or a block of line numbers. Printing the results is nice, but | |
| building tools for pipe and filter processing means we need to | |
| be able to pass results around easily.} | |
| {Instead of just files, could you pass in other series! types? | |
| rawk would need to build in support for that as well, but think | |
| of the possibilities! Maybe adding a RESULTS word in the object | |
| which is populated when EXEC runs. Then the user can just | |
| interrogate it, copy it out, etc.} | |
| {Regex support for patterns, beyond simple wildcards.} | |
| {/custom refinement for specifying a custom pattern, or even a | |
| complete rawk program.} | |
| {/quiet works like grep, but wouldn't it be nice to have a switch | |
| that let us get *all* the results but without dumping them to the | |
| screen?} | |
| ] | |
| Example: { | |
| rgrep/exec "greP" read %. | |
| rgrep/exec/case "grep" read %. | |
| rgrep/exec/any "gR?p" read %. | |
| rgrep/exec/case/any "gr?p" read %. | |
| } | |
| ] | |
| include/check %rawk.r | |
| rgrep-ctx: make object! [ | |
| set 'rgrep func [ | |
| {Search files for lines containing a match to pattern. | |
| (This is what you call to use rgrep)} | |
| pattern [string!] | |
| sources [block! any-string!] | |
| /deep "Recurse into sub-directories" | |
| /list "List only file names with matching lines." | |
| /count "List files and the number of lines that matched in each." | |
| /quiet "Return only true or false (i.e. whether a match was found)." | |
| /invert "Invert test. Success if no match." | |
| /case "Make comparison case sensitive" | |
| /any "Enables the * and ? wildcards" | |
| /callback cbk-fn [function!] "Progress callback function. Just called for 'begin-file and 'end right now. Should take one arg." | |
| /local prog result pat ct line-ct | |
| ][ | |
| ; Do we want to return a block of info? | |
| ;info-blk: [count 0 lines []] | |
| ;line-info: [number 0 data ""] | |
| ct: 0 | |
| ; We want to build a rule like one of the following. Looking at the | |
| ; code to build it, would it be clearer just to list the hard-coded | |
| ; cases and use EITHER to select them (handling /invert after)? | |
| ;[find __ pattern] [find/case __ pattern] [find/any __ pattern] | |
| ;[find/case/any __ pattern] | |
| pat: reduce compose/deep [ | |
| (either invert [to-lit-word 'not][]) | |
| to-path [find (either case ['case][]) (either any ['any] [])] | |
| '__ 'pattern | |
| ] | |
| ;print mold pat | |
| ; Would it help us to define a common action to build upon? | |
| ;act: copy [result: true] | |
| ; Default rawk program, if no refinements are used. | |
| prog: reduce [ | |
| pat [print [_fnr tab _filename tab mold trim __] result: true] | |
| ;'begin-file [print ["Searching:" _filename "for" mold pattern]] | |
| 'begin-file [cbk-fn ['begin-file _filename pattern]] | |
| ] | |
| ; Now, we'll check for each refinement they may have passed us. | |
| ; Each one basically indicates a different mode of operation. | |
| ; We just use a slightly different rawk program for each one. | |
| if list [ | |
| prog: reduce [ | |
| pat [ct: add ct 1 print _filename result: true next-file] | |
| 'begin [print ["Found" mold pattern "in:"]] | |
| 'end [print [ct "files contained" mold pattern]] | |
| ] | |
| ] | |
| if count [ | |
| prog: reduce [ | |
| pat [ct: add ct 1 line-ct: add line-ct 1 result: true] | |
| 'begin-file [line-ct: 0] | |
| 'end-file [if line-ct > 0 [print [_filename tab line-ct]]] | |
| 'end [print [ct "lines contained" mold pattern]] | |
| ] | |
| ] | |
| if quiet [ | |
| prog: reduce [ | |
| pat [result: true exit] | |
| ] | |
| ] | |
| ; Now the rawk program has been set and we can run it. | |
| ;print mold prog | |
| result: false | |
| either deep [rawk/deep sources prog] [rawk sources prog] | |
| print [rawk-ctx/_nr "total lines searched"] | |
| result | |
| ] | |
| ] | |
| ; rgrep/exec/case/any "gr?p" read %. | |
| ; print "" | |
| ; print "find grep /invert" | |
| ; rgrep/exec/invert "grep" read %. | |
| ; print "" | |
| ; rgrep/exec "file" read %. | |
| ; print "" | |
| ; | |
| ; print "/list option" | |
| ; rgrep/exec/list "file" read %. | |
| ; print "" | |
| ; | |
| ; print ["/quiet result:" rgrep/exec/quiet "file" read %.] | |
| ; print ["/quiet result:" rgrep/exec/quiet random "2#3%4lks09(*SD)" read %.] | |
| ; print "" | |
| ; print ["/quiet/invert result:" rgrep/exec/quiet/invert "file" read %.] | |
| ; print ["/quiet/invert result:" rgrep/exec/quiet/invert random "2#3%4lks09(*SD)" read %.] | |
| ; print "" | |
| ; print "/count option" | |
| ; rgrep/exec/count "file" read %. | |
| ; print "" | |
| ; print "/invert/count option" | |
| ; rgrep/exec/invert/count "file" read %. | |
| ; print "" | |
| ;change-dir %/c/rebol/gregg/ | |
| ;rgrep/exec "file" read %. | |
| ; change-dir %../nix-shell/ | |
| ; ;print read %. | |
| ; print "/count option" | |
| ; rgrep/exec/count "file" read %. | |
| ; print "" | |
| ; print "/list option" | |
| ; rgrep/exec/list "file" read %. | |
| ; print "" | |
| ; change-dir %../../fromM/ | |
| ; ;print read %. | |
| ; ;print "default: ginger" | |
| ; ;rgrep/exec "ginger" read %. | |
| ; ;print "" | |
| ; print "/count option" | |
| ; rgrep/exec/count "ginger" read %. | |
| ; print "" | |
| ; print "/list option" | |
| ; rgrep/exec/list "ginger" read %. | |
| ; print "" | |
| ; print "/quiet option" | |
| ; print rgrep/exec/quiet "ginger" read %. | |
| ; print "" | |
| ; | |
| ; change-dir %/c/rebol/scripts/library/ | |
| ; ;print read %. | |
| ; print {"carl" /count option} | |
| ; rgrep/exec/count "carl" read %. | |
| ; print "" | |
| ; print {"carl" /list option} | |
| ; rgrep/exec/list "carl" read %. | |
| ; print "" | |
| ; | |
| ; halt | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment