[racket] programmatic file editing
Neil Van Dyke wrote at 06/07/2012 01:14 AM:
> That was toy example of a call to "progedit", like a test case, and
> not very clear. In a real program, you'd programmatically build the
> list you pass to the "#:insert" keyword argument of "progedit". So,
> you would only add the (0 "#lang setup/infotab\n") to that list if you
> found through other means that you needed to add a #lang line.
> "progedit" itself only performs the inserts, deletes, and replaces.
This isn't a big point, but I might as well get more mileage out of my
test cases by using them for illustration...
Here's an example of using "progedit" to programmatically edit the
source file of a simple language to set the variable "name" to value
"Jane", either by editing an existing form or adding a new form to the file.
Notice that the "#:inserts" and "#:replaces" arguments to "progedit" are
constructed at run time, based on what we parse from the input file.
(define (demonstrate-define-name-as-jane in-str)
(let ((in (open-input-string in-str)))
(let loop ((name-stx #f))
(let ((stx (read-syntax 'my-source in)))
(if (eof-object? stx)
(let-values (((inserts replaces)
(if name-stx
(values '()
`((,name-stx ,#'"Jane")))
(values `((#f #\newline
,#'(define name "Jane")
#\newline))
'())))
((out) (open-output-string)))
(progedit-ports #:in-port (open-input-string in-str)
#:out-port out
#:deletes '()
#:inserts inserts
#:replaces replaces)
(get-output-string out))
(syntax-parse stx
(((~datum define) (~datum name) VAL)
(if name-stx
(raise-syntax-error
'foo
"(define name VAL) occurred multiple times"
stx
#f
(list name-stx))
(loop #'VAL)))
(_ (loop name-stx))))))))
In this case, we see that "name" is set to "John", so we replace "John"
with "Jane":
(demonstrate-define-name-as-jane
"(define honorific \"Dr.\")\n\n(define name \"John\")\n\n(define age
29)\n")
;;==> "(define honorific \"Dr.\")\n\n(define name \"Jane\")\n\n(define
age 29)\n"
In this case, "name" isn't set to anything, so we add a new "define
name" form to the end of the file:
(demonstrate-define-name-as-jane
"(define honorific \"Dr.\")\n\n(define age 29)\n")
;;==> "(define honorific \"Dr.\")\n\n(define age 29)\n\n(define name
\"Jane\")\n"
Neil V.