From 7ec99757365de73f12b206c205240508c8ad6ba6 Mon Sep 17 00:00:00 2001 From: Eli Barzilay Date: Fri, 22 Jun 2012 14:27:14 -0400 Subject: [PATCH] Move `regexp-replaces' from `ffi/unsafe' to `racket/private/string'. * The old function was removed completely, people will get it from `racket/base' anyway. * I also removed its documentation. I thought about leaving a note in, but if `define-ffi-definer' is the preferred style, then this should be done when there's a way to make `define-ffi-definer' use it. (Eg, some new #:keyword that adds a way to change the defined name.) * Note that the function is added to `racket/private/string' and not to `racket/string' because the latter deals only with strings, and the new function accepts byte strings too. It might be better to start a new `racket/regexp' module for these functions. --- collects/ffi/unsafe.rkt | 15 --------- collects/racket/private/string.rkt | 9 ++++- collects/scribblings/foreign/define.scrbl | 8 ++--- collects/scribblings/foreign/misc.scrbl | 35 -------------------- collects/scribblings/reference/regexps.scrbl | 30 ++++++++++++++--- collects/tests/racket/string.rktl | 11 +++++- 6 files changed, 47 insertions(+), 61 deletions(-) diff --git a/collects/ffi/unsafe.rkt b/collects/ffi/unsafe.rkt index cfdb3d85a5..9e35e33211 100644 --- a/collects/ffi/unsafe.rkt +++ b/collects/ffi/unsafe.rkt @@ -1624,21 +1624,6 @@ [else (error 'cblock->vector "expecting a non-void pointer, got ~s" cblock)])) -;; Useful for automatic definitions -;; If a provided regexp begins with a "^" or ends with a "$", then -;; `regexp-replace' is used, otherwise use `regexp-replace*'. -(define* (regexp-replaces x rs) - (let loop ([str (if (bytes? x) (bytes->string/utf-8 x) (format "~a" x))] - [rs rs]) - (if (null? rs) - str - (loop ((if (regexp-match #rx"^\\^|\\$$" - (if (regexp? (caar rs)) - (object-name (caar rs)) (caar rs))) - regexp-replace regexp-replace*) - (caar rs) str (cadar rs)) - (cdr rs))))) - (define killer-thread #f) (define* register-finalizer diff --git a/collects/racket/private/string.rkt b/collects/racket/private/string.rkt index 6b57b0799b..b4a7c9847c 100644 --- a/collects/racket/private/string.rkt +++ b/collects/racket/private/string.rkt @@ -9,7 +9,8 @@ regexp-split regexp-match-exact? regexp-try-match - -regexp-replace*) + -regexp-replace* + regexp-replaces) (require (for-syntax "stxcase-scheme.rkt")) ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; @@ -570,4 +571,10 @@ (string-length (path->string s)) (string-length s))]))))) + (define (regexp-replaces string replacements) + (let loop ([str string] [rs replacements]) + (if (null? rs) + str + (loop (regexp-replace* (caar rs) str (cadar rs)) (cdr rs))))) + ) diff --git a/collects/scribblings/foreign/define.scrbl b/collects/scribblings/foreign/define.scrbl index 2e1b87de46..a56c1f073c 100644 --- a/collects/scribblings/foreign/define.scrbl +++ b/collects/scribblings/foreign/define.scrbl @@ -30,10 +30,10 @@ The other options support further wrapping and configuration: @itemize[ @item{Before the extracted result is bound as @racket[_id], it is - passed to the result of @racket[_wrap-expr], which defaults to - @racket[values]. Expressions such as @racket[(allocator - _delete)] or @racket[(deallocator)] are useful as - @racket[_wrap-expr]s.} + passed to the result of @racket[_wrap-expr], which defaults to + @racket[values]. Expressions such as @racket[(allocator + _delete)] or @racket[(deallocator)] are useful as + @racket[_wrap-expr]s.} @item{The @racket[#:make-fail] and @racket[#:fail] options are mutually exclusive; if @racket[_make-fail-expr] is provided, it diff --git a/collects/scribblings/foreign/misc.scrbl b/collects/scribblings/foreign/misc.scrbl index 540ae623d0..b98afffb37 100644 --- a/collects/scribblings/foreign/misc.scrbl +++ b/collects/scribblings/foreign/misc.scrbl @@ -3,41 +3,6 @@ @title{Miscellaneous Support} - -@defproc[(regexp-replaces [objname (or/c string? bytes? symbol?)] - [substs (listof (list regexp? string?))]) - string?]{ - -A function that is convenient for many interfaces where the foreign -library has some naming convention that you want to use in your -interface as well. The @racket[objname] argument can be any value -that will be used to name the foreign object; it is first converted -into a string, and then modified according to the given -@racket[substs] list in sequence, where each element in this list is a -list of a regular expression and a substitution string. Usually, -@racket[regexp-replace*] is used to perform the substitution, except -for cases where the regular expression begins with a @litchar{^} or -ends with a @litchar{$}, in which case @racket[regexp-replace] is -used. - -For example, the following makes it convenient to define Racket -bindings such as @racket[foo-bar] for foreign names like -@racket[MyLib_foo_bar]: - -@racketblock[ -(define mylib (ffi-lib "mylib")) -(define-syntax defmyobj - (syntax-rules (:) - [(_ name : type ...) - (define name - (get-ffi-obj - (regexp-replaces 'name '((#rx"-" "_") - (#rx"^" "MyLib_"))) - mylib (_fun type ...)))])) -(defmyobj foo-bar : _int -> _int) -]} - - @defproc[(list->cblock [lst list?] [type ctype?]) any]{ Allocates a memory block of an appropriate size, and initializes it diff --git a/collects/scribblings/reference/regexps.scrbl b/collects/scribblings/reference/regexps.scrbl index 83105323be..bb7b7cc286 100644 --- a/collects/scribblings/reference/regexps.scrbl +++ b/collects/scribblings/reference/regexps.scrbl @@ -793,7 +793,7 @@ an end-of-file if @racket[input] is an input port). @defproc[(regexp-replace [pattern (or/c string? bytes? regexp? byte-regexp?)] [input (or/c string? bytes?)] - [insert (or/c string? bytes? + [insert (or/c string? bytes? ((string?) () #:rest (listof string?) . ->* . string?) ((bytes?) () #:rest (listof bytes?) . ->* . bytes?))] [input-prefix bytes? #""]) @@ -861,7 +861,7 @@ before the @litchar{\}. For example, the Racket constant @defproc[(regexp-replace* [pattern (or/c string? bytes? regexp? byte-regexp?)] [input (or/c string? bytes?)] - [insert (or/c string? bytes? + [insert (or/c string? bytes? ((string?) () #:rest (listof string?) . ->* . string?) ((bytes?) () #:rest (listof bytes?) . ->* . bytes?))] [start-pos exact-nonnegative-integer? 0] @@ -882,9 +882,9 @@ a portion of @racket[input] for matching; the default is the entire string or the stream up to an end-of-file. @examples[ -(regexp-replace* "([Mm])i ([a-zA-Z]*)" "mi cerveza Mi Mi Mi" +(regexp-replace* "([Mm])i ([a-zA-Z]*)" "mi cerveza Mi Mi Mi" "\\1y \\2") -(regexp-replace* "([Mm])i ([a-zA-Z]*)" "mi cerveza Mi Mi Mi" +(regexp-replace* "([Mm])i ([a-zA-Z]*)" "mi cerveza Mi Mi Mi" (lambda (all one two) (string-append (string-downcase one) "y" (string-upcase two)))) @@ -892,6 +892,27 @@ string or the stream up to an end-of-file. (display (regexp-replace* #rx"x" "12x4x6" "\\\\")) ]} +@defproc[(regexp-replaces [input (or/c string? bytes?)] + [replacements + (listof + (list/c (or/c string? bytes? regexp? byte-regexp?) + (or/c string? bytes? + ((string?) () #:rest (listof string?) . ->* . string?) + ((bytes?) () #:rest (listof bytes?) . ->* . bytes?))))]) + (or/c string? bytes?)]{ + +Performs a chain of @racket[regexp-replace*] operations, where each +element in @racket[replacements] specifies a replacement as a +@racket[(list pattern replacement)]. The replacements are done in +order, so later replacements can apply to previous insertions. + +@examples[ +(regexp-replaces "zero-or-more?" + '([#rx"-" "_"] [#rx"(.*)\\?$" "is_\\1"])) +(regexp-replaces "zero-or-more?" + '(["e" "o"] ["o" "oo"])) +]} + @defproc*[([(regexp-replace-quote [str string?]) string?] [(regexp-replace-quote [bstr bytes?]) bytes?])]{ @@ -905,4 +926,3 @@ Concretely, every @litchar{\} and @litchar{&} in @racket[str] or (regexp-replace "UT" "Go UT!" "A&M") (regexp-replace "UT" "Go UT!" (regexp-replace-quote "A&M")) ]} - diff --git a/collects/tests/racket/string.rktl b/collects/tests/racket/string.rktl index ab6bb40506..55a15b4bbe 100644 --- a/collects/tests/racket/string.rktl +++ b/collects/tests/racket/string.rktl @@ -357,8 +357,17 @@ (and ((* 100 (- bcpu bgc)) . < . (- scpu sgc)) "suspiciously long time for regexp string split"))) +;; ---------- regexp-replaces ---------- +(let () + (test "foo" regexp-replaces "foo" '()) + (test "is_zero_or_more" + regexp-replaces "zero-or-more?" + '([#rx"-" "_"] [#rx"(.*)\\?$" "is_\\1"])) + (test "zooroo-oor-mooroo?" + regexp-replaces "zero-or-more?" '(["e" "o"] ["o" "oo"]))) + ;; ---------- string-append* ---------- -(let ([t (λ (x . xs) (test ))]) +(let () (test "" string-append* '()) (test "" string-append* '("")) (test "" string-append* '("" ""))