I'm trying to make a basic (but specialized) command-line file search tool in Racket for my own personal use. Here is what I have so far:
#! /usr/bin/env racket
#lang racket/base
(require racket/path)
(require racket/cmdline)
(require racket/string)
(define (basename f)
(path->string (file-name-from-path f)))
(define (plain-name? path)
(regexp-match? "^[A-Za-z]+$" (basename path)))
(define (find-csv root [name ""] [loc ""] [owner ""] [max 10000])
(define m 0)
(for ([f (in-directory root plain-name?)]
#:when (and (file-exists? f)
(filename-extension f)
(bytes=? #"csv" (filename-extension f))
(string-contains? (path->string f) loc)
(string-contains? (basename f) name))
#:break (>= m max))
(set! m (add1 m))
(displayln f)))
(define args
(command-line
#:once-each
[("-n" "--max-paths") "Maximum number of file paths to return" (max 10000)]
[("-o" "--owner") "Limit search to certain owners" (owner "")]
[("-t" "--template") "Limit search to certain templates" (template "")]
[("-l" "--location")
"Limit search to directory structure containing location"
(loc "")]
[("-p" "--root-path") "Look under the root path" (root "/home/wdkrnls")]))
My first issue is that I'm getting an error when trying to run it via
./list-files.rkt
list-files.rkt:30:55: owner: unbound identifier in module
in: owner
context...:
standard-module-name-resolver
This use of command-line
looks like it follows the greeting example in the Racket documentation, but racket seems to be looking for defined functions where I'm just trying to specify default values to variables I'd like to make available to my find-csv
function.
My second issue is it's not clear to me from the documentation how I am supposed to use these arguments to call find-csv
from the command line. The example in the documentation only covers a very basic case of one argument. I have no required arguments, but several optional ones.
Can you give me any pointers? Thanks.
In the example in the documentation, all of the flags toggle parameters that are used to communicate the flag settings to the later processing step (which isn't shown in the example).
So in your particular case, you would define parameters like this:
(define max (make-parameter 10000))
(define owner (make-parameter ""))
(define template (make-parameter "")
(define loc (make-parameter ""))
(define root (make-parameter "/home/wdkrnls"))
where the arguments here are the parameter default values. Then you can either call find-csv
with the parameter value (by using the parameter as a function, e.g., like (max)
), or you can change find-csv
so that it doesn't take any arguments and instead just accesses the parameters directly.
Also, your flag syntax is probably not quite right. You probably want something like this for each one:
[("-n" "--max-paths") max-arg
"Maximum number of file paths to return"
(max max-arg)]
Note the max-arg
name that's added. You need that to actually set the parameter to the value provided by the user.