add port->string, file->string, etc.
svn: r12388
This commit is contained in:
parent
209b252f2c
commit
a6d953b6f5
|
@ -44,20 +44,21 @@
|
||||||
(let ([c (read-bytes-avail! s src)])
|
(let ([c (read-bytes-avail! s src)])
|
||||||
(cond
|
(cond
|
||||||
[(number? c)
|
[(number? c)
|
||||||
(for-each
|
(let loop ([dests dests])
|
||||||
(lambda (dest)
|
(unless (null? dests)
|
||||||
(let loop ([start 0])
|
(let loop ([start 0])
|
||||||
(unless (= start c)
|
(unless (= start c)
|
||||||
(let ([c2 (write-bytes-avail s dest start c)])
|
(let ([c2 (write-bytes-avail s (car dests) start c)])
|
||||||
(loop (+ start c2))))))
|
(loop (+ start c2)))))
|
||||||
dests)
|
(loop (cdr dests))))
|
||||||
(loop)]
|
(loop)]
|
||||||
[(procedure? c)
|
[(procedure? c)
|
||||||
(let ([v (let-values ([(l col p) (port-next-location src)])
|
(let ([v (let-values ([(l col p) (port-next-location src)])
|
||||||
(c (object-name src) l col p))])
|
(c (object-name src) l col p))])
|
||||||
(for-each
|
(let loop ([dests dests])
|
||||||
(lambda (dest) (write-special v dest))
|
(unless (null? dests)
|
||||||
dests))
|
(write-special v (car dests))
|
||||||
|
(loop (cdr dests)))))
|
||||||
(loop)]
|
(loop)]
|
||||||
[else
|
[else
|
||||||
;; Must be EOF
|
;; Must be EOF
|
||||||
|
|
|
@ -10,7 +10,18 @@
|
||||||
|
|
||||||
fold-files
|
fold-files
|
||||||
find-files
|
find-files
|
||||||
pathlist-closure)
|
pathlist-closure
|
||||||
|
|
||||||
|
file->string
|
||||||
|
file->bytes
|
||||||
|
file->value
|
||||||
|
file->lines
|
||||||
|
file->bytes-lines
|
||||||
|
display-to-file
|
||||||
|
write-to-file
|
||||||
|
display-list-to-file)
|
||||||
|
|
||||||
|
(require "private/portlines.ss")
|
||||||
|
|
||||||
;; utility: sorted dirlist so functions are deterministic
|
;; utility: sorted dirlist so functions are deterministic
|
||||||
(define (sorted-dirlist [dir (current-directory)])
|
(define (sorted-dirlist [dir (current-directory)])
|
||||||
|
@ -331,3 +342,95 @@
|
||||||
(loop2 base (if (or (member base r) (member base paths))
|
(loop2 base (if (or (member base r) (member base paths))
|
||||||
new (cons base new)))
|
new (cons base new)))
|
||||||
(loop (cdr paths) (append (reverse new) r))))))))
|
(loop (cdr paths) (append (reverse new) r))))))))
|
||||||
|
|
||||||
|
(define (check-path who f)
|
||||||
|
(unless (path-string? f)
|
||||||
|
(raise-type-error who "path string" f)))
|
||||||
|
|
||||||
|
(define (check-file-mode who file-mode)
|
||||||
|
(unless (memq file-mode '(binary text))
|
||||||
|
(raise-type-error who "'binary or 'text" file-mode)))
|
||||||
|
|
||||||
|
(define (file->x who f file-mode read-x x-append)
|
||||||
|
(check-path who f)
|
||||||
|
(check-file-mode who file-mode)
|
||||||
|
(let ([sz (file-size f)])
|
||||||
|
(call-with-input-file*
|
||||||
|
f
|
||||||
|
#:mode file-mode
|
||||||
|
(lambda (in)
|
||||||
|
;; There's a good chance that `file-size' gets all the data:
|
||||||
|
(let ([s (read-x sz in)])
|
||||||
|
;; ... but double-check:
|
||||||
|
(let ([more (let loop ()
|
||||||
|
(let ([l (read-x 4096 in)])
|
||||||
|
(if (eof-object? l)
|
||||||
|
null
|
||||||
|
(cons l (loop)))))])
|
||||||
|
(if (null? more)
|
||||||
|
s
|
||||||
|
(apply x-append (cons s more)))))))))
|
||||||
|
|
||||||
|
(define (file->string f #:mode [mode 'binary])
|
||||||
|
(file->x 'file->string f mode read-string string-append))
|
||||||
|
|
||||||
|
(define (file->bytes f #:mode [mode 'binary])
|
||||||
|
(file->x 'file->bytes f mode read-bytes bytes-append))
|
||||||
|
|
||||||
|
(define (file->value f #:mode [file-mode 'binary])
|
||||||
|
(check-path 'file->value f)
|
||||||
|
(check-file-mode 'file->value file-mode)
|
||||||
|
(let ([sz (file-size f)])
|
||||||
|
(call-with-input-file*
|
||||||
|
f
|
||||||
|
#:mode file-mode
|
||||||
|
read)))
|
||||||
|
|
||||||
|
(define (file->x-lines who f line-mode file-mode read-line)
|
||||||
|
(check-path who f)
|
||||||
|
(check-mode who line-mode)
|
||||||
|
(check-file-mode who file-mode)
|
||||||
|
(call-with-input-file*
|
||||||
|
f
|
||||||
|
#:mode file-mode
|
||||||
|
(lambda (p) (port->x-lines who p line-mode read-line))))
|
||||||
|
|
||||||
|
(define (file->lines f #:line-mode [line-mode 'any] #:mode [file-mode 'binary])
|
||||||
|
(file->x-lines 'file->lines f line-mode file-mode read-line))
|
||||||
|
|
||||||
|
(define (file->bytes-lines f #:line-mode [line-mode 'any] #:mode [file-mode 'binary])
|
||||||
|
(file->x-lines 'file->bytes-lines f line-mode file-mode read-bytes-line))
|
||||||
|
|
||||||
|
(define (->file who f mode exists write)
|
||||||
|
(unless (path-string? f)
|
||||||
|
(raise-type-error who "path string" f))
|
||||||
|
(unless (memq mode '(binary text))
|
||||||
|
(raise-type-error who "'binary or 'text" mode))
|
||||||
|
(unless (memq exists '(error append update replace truncate truncate/replace))
|
||||||
|
(raise-type-error who "'error, 'append, 'update, 'replace, 'truncate, or 'truncate/replace" exists))
|
||||||
|
(call-with-output-file*
|
||||||
|
f
|
||||||
|
#:mode mode
|
||||||
|
#:exists exists
|
||||||
|
write))
|
||||||
|
|
||||||
|
(define (display-to-file s f
|
||||||
|
#:mode [mode 'binary]
|
||||||
|
#:exists [exists 'error])
|
||||||
|
(->file 'display-to-file f mode exists (lambda (p) (display s p))))
|
||||||
|
|
||||||
|
(define (write-to-file s f
|
||||||
|
#:mode [mode 'binary]
|
||||||
|
#:exists [exists 'error])
|
||||||
|
(->file 'write-to-file f mode exists (lambda (p) (write s p))))
|
||||||
|
|
||||||
|
(define (display-list-to-file l f
|
||||||
|
#:mode [mode 'binary]
|
||||||
|
#:exists [exists 'error]
|
||||||
|
#:separator [newline #"\n"])
|
||||||
|
(unless (list? l)
|
||||||
|
(raise-type-error 'display-list-to-file "list" l))
|
||||||
|
(->file 'display-list-to-file f mode exists
|
||||||
|
(lambda (p)
|
||||||
|
(do-lines->port l p newline))))
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,37 @@
|
||||||
|
|
||||||
(module port scheme/base
|
(module port scheme/base
|
||||||
(require mzlib/port)
|
(require mzlib/port
|
||||||
|
"private/portlines.ss")
|
||||||
(provide (except-out (all-from-out mzlib/port)
|
(provide (except-out (all-from-out mzlib/port)
|
||||||
strip-shell-command-start)))
|
strip-shell-command-start)
|
||||||
|
port->string
|
||||||
|
port->bytes
|
||||||
|
port->lines
|
||||||
|
port->bytes-lines
|
||||||
|
display-list)
|
||||||
|
|
||||||
|
(define (port->string-port who p)
|
||||||
|
(unless (input-port? p)
|
||||||
|
(raise-type-error who "input-port" p))
|
||||||
|
(let ([s (open-output-string)])
|
||||||
|
(copy-port p s)
|
||||||
|
s))
|
||||||
|
|
||||||
|
(define (port->string [p (current-input-port)])
|
||||||
|
(get-output-string (port->string-port 'port->string p)))
|
||||||
|
|
||||||
|
(define (port->bytes [p (current-input-port)])
|
||||||
|
(get-output-bytes (port->string-port 'port->bytes p) #t))
|
||||||
|
|
||||||
|
(define (port->lines [p (current-input-port)] #:line-mode [mode 'any])
|
||||||
|
(port->x-lines 'port->lines p mode read-line))
|
||||||
|
|
||||||
|
(define (port->bytes-lines [p (current-input-port)] #:line-mode [mode 'any])
|
||||||
|
(port->x-lines 'port->bytes-lines p mode read-bytes-line))
|
||||||
|
|
||||||
|
(define (display-list l [p (current-output-port)] #:separator [newline #"\n"])
|
||||||
|
(unless (list? l)
|
||||||
|
(raise-type-error 'display-list "list" l))
|
||||||
|
(unless (output-port? p)
|
||||||
|
(raise-type-error 'display-list "output-port" p))
|
||||||
|
(do-lines->port l p newline)))
|
||||||
|
|
24
collects/scheme/private/portlines.ss
Normal file
24
collects/scheme/private/portlines.ss
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
#lang scheme/base
|
||||||
|
|
||||||
|
(provide port->x-lines
|
||||||
|
check-mode
|
||||||
|
do-lines->port)
|
||||||
|
|
||||||
|
(define (check-mode who mode)
|
||||||
|
(unless (memq mode '(linefeed return return-linefeed any any-one))
|
||||||
|
(raise-type-error who "'linefeed, 'return, 'return-linefeed, 'any, or 'any-one" mode)))
|
||||||
|
|
||||||
|
(define (port->x-lines who p mode read-line)
|
||||||
|
(unless (input-port? p)
|
||||||
|
(raise-type-error who "input-port" p))
|
||||||
|
(check-mode who mode)
|
||||||
|
(let loop ([l null])
|
||||||
|
(let ([line (read-line p mode)])
|
||||||
|
(if (eof-object? line)
|
||||||
|
(reverse l)
|
||||||
|
(loop (cons line l))))))
|
||||||
|
|
||||||
|
(define (do-lines->port l p newline)
|
||||||
|
(for ([i (in-list l)])
|
||||||
|
(display i p)
|
||||||
|
(display newline p)))
|
|
@ -536,6 +536,82 @@ module path.}
|
||||||
|
|
||||||
@note-lib[scheme/file]
|
@note-lib[scheme/file]
|
||||||
|
|
||||||
|
@defproc[(file->string [path path-string?]
|
||||||
|
[#:mode mode-flag (or/c 'binary 'text) 'binary])
|
||||||
|
string?]{
|
||||||
|
|
||||||
|
Reads all characters from @scheme[path] and returns them as a string.
|
||||||
|
The @scheme[mode-flag] argument is the same as for
|
||||||
|
@scheme[open-input-file].}
|
||||||
|
|
||||||
|
@defproc[(file->bytes [path path-string?]
|
||||||
|
[#:mode mode-flag (or/c 'binary 'text) 'binary])
|
||||||
|
bytes?]{
|
||||||
|
|
||||||
|
Reads all characters from @scheme[path] and returns them as a
|
||||||
|
@tech{byte string}. The @scheme[mode-flag] argument is the same as
|
||||||
|
for @scheme[open-input-file].}
|
||||||
|
|
||||||
|
@defproc[(file->lines [path path-string?]
|
||||||
|
[#:mode mode-flag (or/c 'binary 'text) 'binary]
|
||||||
|
[#:line-mode line-mode (or/c 'linefeed 'return 'return-linefeed 'any 'any-one) 'any])
|
||||||
|
bytes?]{
|
||||||
|
|
||||||
|
Read all characters from @scheme[path], breaking them into lines. The
|
||||||
|
@scheme[line-mode] argument is the same as the second argument to
|
||||||
|
@scheme[read-line], but the default is @scheme['any] instead of
|
||||||
|
@scheme['linefeed]. The @scheme[mode-flag] argument is the same as for
|
||||||
|
@scheme[open-input-file].}
|
||||||
|
|
||||||
|
@defproc[(file->value [path path-string?]
|
||||||
|
[#:mode mode-flag (or/c 'binary 'text) 'binary])
|
||||||
|
bytes?]{
|
||||||
|
|
||||||
|
Reads a single S-expression from @scheme[path] using @scheme[read].
|
||||||
|
The @scheme[mode-flag] argument is the same as for
|
||||||
|
@scheme[open-input-file].}
|
||||||
|
|
||||||
|
@defproc[(file->bytes-lines [path path-string?]
|
||||||
|
[#:mode mode-flag (or/c 'binary 'text) 'binary]
|
||||||
|
[#:line-mode line-mode (or/c 'linefeed 'return 'return-linefeed 'any 'any-one) 'any])
|
||||||
|
bytes?]{
|
||||||
|
|
||||||
|
Like @scheme[file->lines], but reading bytes and collecting them into
|
||||||
|
lines like @scheme[read-bytes-line].}
|
||||||
|
|
||||||
|
@defproc[(display-to-file [v any/c]
|
||||||
|
[path path-string?]
|
||||||
|
[#:mode mode-flag (or/c 'binary 'text) 'binary]
|
||||||
|
[#:exists exists-flag (or/c 'error 'append 'update
|
||||||
|
'replace 'truncate 'truncate/replace) 'error])
|
||||||
|
void?]{
|
||||||
|
|
||||||
|
Uses @scheme[display] to print each @scheme[v] to @scheme[path]. The @scheme[mode-flag] and
|
||||||
|
@scheme[exists-flag] arguments are the same as for
|
||||||
|
@scheme[open-output-file].}
|
||||||
|
|
||||||
|
@defproc[(write-to-file [v any/c]
|
||||||
|
[path path-string?]
|
||||||
|
[#:mode mode-flag (or/c 'binary 'text) 'binary]
|
||||||
|
[#:exists exists-flag (or/c 'error 'append 'update
|
||||||
|
'replace 'truncate 'truncate/replace) 'error])
|
||||||
|
void?]{
|
||||||
|
|
||||||
|
Like @scheme[display-to-file], but using @scheme[write] instead of @scheme[display].}
|
||||||
|
|
||||||
|
@defproc[(display-list-to-file [lst list?]
|
||||||
|
[path path-string?]
|
||||||
|
[#:separator separator any/c #"\n"]
|
||||||
|
[#:mode mode-flag (or/c 'binary 'text) 'binary]
|
||||||
|
[#:exists exists-flag (or/c 'error 'append 'update
|
||||||
|
'replace 'truncate 'truncate/replace) 'error])
|
||||||
|
void?]{
|
||||||
|
|
||||||
|
Displays each element of @scheme[lst] to @scheme[path], adding
|
||||||
|
@scheme[separator] after each element. The @scheme[mode-flag] and
|
||||||
|
@scheme[exists-flag] arguments are the same as for
|
||||||
|
@scheme[open-output-file].}
|
||||||
|
|
||||||
@defproc[(copy-directory/files [src path-string?][dest path-string?])
|
@defproc[(copy-directory/files [src path-string?][dest path-string?])
|
||||||
void?]{
|
void?]{
|
||||||
|
|
||||||
|
|
|
@ -2,12 +2,48 @@
|
||||||
@(require "mz.ss"
|
@(require "mz.ss"
|
||||||
(for-label scheme/port))
|
(for-label scheme/port))
|
||||||
|
|
||||||
@title{More Port Constructors and Events}
|
@title[#:tag "port-lib"]{More Port Constructors, Procedures, and Events}
|
||||||
|
|
||||||
@note-lib-only[scheme/port]
|
@note-lib-only[scheme/port]
|
||||||
|
|
||||||
@; ----------------------------------------------------------------------
|
@; ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
@section{Port String and List Conversions}
|
||||||
|
|
||||||
|
@defproc[(port->string [in input-port? (current-input-port)]) string?]{
|
||||||
|
|
||||||
|
Reads all characters from @scheme[in] and returns them as a string.}
|
||||||
|
|
||||||
|
@defproc[(port->bytes [in input-port? (current-input-port)]) bytes?]{
|
||||||
|
|
||||||
|
Reads all bytes from @scheme[in] and returns them as a @tech{byte string}.}
|
||||||
|
|
||||||
|
@defproc[(port->lines [in input-port? (current-input-port)]
|
||||||
|
[#:line-mode line-mode (or/c 'linefeed 'return 'return-linefeed 'any 'any-one) 'any])
|
||||||
|
(listof string?)]{
|
||||||
|
|
||||||
|
Read all characters from @scheme[in], breaking them into lines. The
|
||||||
|
@scheme[line-mode] argument is the same as the second argument to
|
||||||
|
@scheme[read-line], but the default is @scheme['any] instead of
|
||||||
|
@scheme['linefeed].}
|
||||||
|
|
||||||
|
@defproc[(port->bytes-lines [in input-port? (current-input-port)]
|
||||||
|
[#:line-mode line-mode (or/c 'linefeed 'return 'return-linefeed 'any 'any-one) 'any])
|
||||||
|
(listof bytes?)]{
|
||||||
|
|
||||||
|
Like @scheme[port->lines], but reading bytes and collecting them into
|
||||||
|
lines like @scheme[read-bytes-line].}
|
||||||
|
|
||||||
|
@defproc[(display-list [lst list?]
|
||||||
|
[out output-port? (current-output-port)]
|
||||||
|
[#:separator separator any/c #"\n"])
|
||||||
|
void?]{
|
||||||
|
|
||||||
|
Use @scheme[display] to each each element of @scheme[lst] to @scheme[out], adding
|
||||||
|
@scheme[separator] after each element.}
|
||||||
|
|
||||||
|
@; ----------------------------------------------------------------------
|
||||||
|
|
||||||
@section{Creating Ports}
|
@section{Creating Ports}
|
||||||
|
|
||||||
@defproc[(input-port-append [close-at-eof? any/c][in input-port?] ...) input-port?]{
|
@defproc[(input-port-append [close-at-eof? any/c][in input-port?] ...) input-port?]{
|
||||||
|
|
|
@ -3,10 +3,56 @@
|
||||||
|
|
||||||
(Section 'file)
|
(Section 'file)
|
||||||
|
|
||||||
(require mzlib/file
|
(require scheme/file
|
||||||
mzlib/process
|
mzlib/process
|
||||||
mzlib/list)
|
mzlib/list)
|
||||||
|
|
||||||
|
(define tmp-name "tmp0-filelib")
|
||||||
|
(when (file-exists? tmp-name) (delete-file tmp-name))
|
||||||
|
(display-list-to-file '("a" "b" "c") tmp-name #:separator #"\r\n" #:mode 'binary)
|
||||||
|
(test "a\r\nb\r\nc\r\n" file->string tmp-name #:mode 'binary)
|
||||||
|
(test #"a\r\nb\r\nc\r\n" file->bytes tmp-name)
|
||||||
|
(test '("a" "b" "c") file->lines tmp-name)
|
||||||
|
(test '(#"a" #"b" #"c") file->bytes-lines tmp-name)
|
||||||
|
(test '("a" "b" "c") file->lines tmp-name #:line-mode 'any #:mode 'binary)
|
||||||
|
(test '(#"a" #"b" #"c") file->bytes-lines tmp-name #:line-mode 'any #:mode 'text)
|
||||||
|
(err/rt-test (display-to-file #"a\nb" tmp-name) exn:fail:filesystem:exists?)
|
||||||
|
(display-to-file #"a\nb" tmp-name #:exists 'truncate)
|
||||||
|
(test #"a\nb" file->bytes tmp-name)
|
||||||
|
(display-to-file "\u03BB" tmp-name #:exists 'truncate)
|
||||||
|
(test #"\316\273" file->bytes tmp-name)
|
||||||
|
(write-to-file "\u03BB" tmp-name #:exists 'truncate)
|
||||||
|
(test #"\"\316\273\"" file->bytes tmp-name)
|
||||||
|
(test "\u03BB" file->value tmp-name)
|
||||||
|
(define tmp-name "tmp0-filelib")
|
||||||
|
|
||||||
|
(define-syntax-rule (err/rt-chk-test (op arg ...))
|
||||||
|
(err/rt-test (op arg ...) (check-msg 'op)))
|
||||||
|
(define (check-msg op)
|
||||||
|
(lambda (exn)
|
||||||
|
(regexp-match (format "^~a: " op) (exn-message exn))))
|
||||||
|
(err/rt-chk-test (file->string 'x))
|
||||||
|
(err/rt-chk-test (file->bytes 'x))
|
||||||
|
(err/rt-chk-test (file->string "x" #:mode 'other))
|
||||||
|
(err/rt-chk-test (file->bytes "x" #:mode 'other))
|
||||||
|
(err/rt-chk-test (file->value "x" #:mode 'other))
|
||||||
|
(err/rt-chk-test (display-list-to-file 10 "x"))
|
||||||
|
(err/rt-chk-test (display-list-to-file '(10) "x" #:mode 'other))
|
||||||
|
(err/rt-chk-test (display-list-to-file '(10) "x" #:exists 'other))
|
||||||
|
(err/rt-chk-test (file->lines "x" #:line-mode 'junk))
|
||||||
|
(err/rt-chk-test (file->lines "x" #:mode 'other))
|
||||||
|
(err/rt-chk-test (file->bytes-lines "x" #:line-mode 'junk))
|
||||||
|
(err/rt-chk-test (file->bytes-lines "x" #:mode 'other))
|
||||||
|
(err/rt-chk-test (display-to-file "y" "x" #:exists 'other))
|
||||||
|
(err/rt-chk-test (display-to-file "y" "x" #:mode 'other))
|
||||||
|
(err/rt-chk-test (write-to-file #"y" "x" #:exists 'other))
|
||||||
|
(err/rt-chk-test (write-to-file #"y" "x" #:mode 'other))
|
||||||
|
(err/rt-chk-test (display-list-to-file 'y "x"))
|
||||||
|
(err/rt-chk-test (display-list-to-file '(y) "x" #:exists 'other))
|
||||||
|
(err/rt-chk-test (display-list-to-file '(y) "x" #:mode 'other))
|
||||||
|
|
||||||
|
;; ----------------------------------------
|
||||||
|
|
||||||
(parameterize ([current-directory (current-load-relative-directory)])
|
(parameterize ([current-directory (current-load-relative-directory)])
|
||||||
(let ([rel (find-files values)]
|
(let ([rel (find-files values)]
|
||||||
[abs (find-files values (current-directory))])
|
[abs (find-files values (current-directory))])
|
||||||
|
|
|
@ -5,7 +5,31 @@
|
||||||
|
|
||||||
(define SLEEP-TIME 0.1)
|
(define SLEEP-TIME 0.1)
|
||||||
|
|
||||||
(require mzlib/port)
|
(require scheme/port)
|
||||||
|
|
||||||
|
;; ----------------------------------------
|
||||||
|
|
||||||
|
(let* ([p (lambda () (open-input-string "hello\r\nthere"))])
|
||||||
|
(test "hello\r\nthere" port->string (p))
|
||||||
|
(test #"hello\r\nthere" port->bytes (p))
|
||||||
|
(test '("hello" "there") port->lines (p))
|
||||||
|
(test '(#"hello" #"there") port->bytes-lines (p))
|
||||||
|
(test '("hello\r" "there") port->lines (p) #:line-mode 'linefeed)
|
||||||
|
(test '(#"hello\r" #"there") port->bytes-lines (p) #:line-mode 'linefeed)
|
||||||
|
(test '("hello" "" "there") port->lines (p) #:line-mode 'any-one)
|
||||||
|
(test '(#"hello" #"" #"there") port->bytes-lines (p) #:line-mode 'any-one))
|
||||||
|
|
||||||
|
(let* ([x (make-string 50000 #\x)]
|
||||||
|
[p (lambda () (open-input-string x))])
|
||||||
|
(test (string-length x) 'long-string (string-length (port->string (p))))
|
||||||
|
(test (string-length x) 'long-string (bytes-length (port->bytes (p)))))
|
||||||
|
|
||||||
|
(let ([p (open-output-bytes)])
|
||||||
|
(display-list '(1 2 3) p)
|
||||||
|
(test "1\n2\n3\n" get-output-string p))
|
||||||
|
(let ([p (open-output-bytes)])
|
||||||
|
(display-list '(1 2 3) p #:separator #"!!")
|
||||||
|
(test "1!!2!!3!!" get-output-string p))
|
||||||
|
|
||||||
;; ----------------------------------------
|
;; ----------------------------------------
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
Version 4.1.2.4
|
Version 4.1.2.4
|
||||||
Added call-with-immediate-continuation-mark
|
Added call-with-immediate-continuation-mark
|
||||||
|
In scheme/port: added port->string, port->bytes, port->lines
|
||||||
|
port->bytes-lines, and display-list
|
||||||
|
In scheme/file: added file->string, file->bytes, file->lines,
|
||||||
|
file->bytes-lines, write-to-file, display-to-file,
|
||||||
|
and display-list-to-file
|
||||||
|
|
||||||
Version 4.1.2.3
|
Version 4.1.2.3
|
||||||
Added variable-reference? and empty #%variable-reference form
|
Added variable-reference? and empty #%variable-reference form
|
||||||
|
|
Loading…
Reference in New Issue
Block a user