lineio.scm 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. ;;; installed-scm-file
  2. ;;;; Copyright (C) 1996, 1998, 2001, 2003, 2006 Free Software Foundation, Inc.
  3. ;;;;
  4. ;;;; This library is free software; you can redistribute it and/or
  5. ;;;; modify it under the terms of the GNU Lesser General Public
  6. ;;;; License as published by the Free Software Foundation; either
  7. ;;;; version 2.1 of the License, or (at your option) any later version.
  8. ;;;;
  9. ;;;; This library is distributed in the hope that it will be useful,
  10. ;;;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  12. ;;;; Lesser General Public License for more details.
  13. ;;;;
  14. ;;;; You should have received a copy of the GNU Lesser General Public
  15. ;;;; License along with this library; if not, write to the Free Software
  16. ;;;; Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  17. ;;;;
  18. (define-module (ice-9 lineio)
  19. :use-module (ice-9 readline)
  20. :export (unread-string read-string lineio-port?
  21. make-line-buffering-input-port))
  22. ;;; {Line Buffering Input Ports}
  23. ;;;
  24. ;;; [This is a work-around to get past certain deficiencies in the capabilities
  25. ;;; of ports. Eventually, ports should be fixed and this module nuked.]
  26. ;;;
  27. ;;; A line buffering input port supports:
  28. ;;;
  29. ;;; read-string which returns the next line of input
  30. ;;; unread-string which pushes a line back onto the stream
  31. ;;;
  32. ;;; The implementation of unread-string is kind of limited; it doesn't
  33. ;;; interact properly with unread-char, or any of the other port
  34. ;;; reading functions. Only read-string will get you back the things that
  35. ;;; unread-string accepts.
  36. ;;;
  37. ;;; Normally a "line" is all characters up to and including a newline.
  38. ;;; If lines are put back using unread-string, they can be broken arbitrarily
  39. ;;; -- that is, read-string returns strings passed to unread-string (or
  40. ;;; shared substrings of them).
  41. ;;;
  42. ;; read-string port
  43. ;; unread-string port str
  44. ;; Read (or buffer) a line from PORT.
  45. ;;
  46. ;; Not all ports support these functions -- only those with
  47. ;; 'unread-string and 'read-string properties, bound to hooks
  48. ;; implementing these functions.
  49. ;;
  50. (define (unread-string str line-buffering-input-port)
  51. ((object-property line-buffering-input-port 'unread-string) str))
  52. ;;
  53. (define (read-string line-buffering-input-port)
  54. ((object-property line-buffering-input-port 'read-string)))
  55. (define (lineio-port? port)
  56. (not (not (object-property port 'read-string))))
  57. ;; make-line-buffering-input-port port
  58. ;; Return a wrapper for PORT. The wrapper handles read-string/unread-string.
  59. ;;
  60. ;; The port returned by this function reads newline terminated lines from PORT.
  61. ;; It buffers these characters internally, and parsels them out via calls
  62. ;; to read-char, read-string, and unread-string.
  63. ;;
  64. (define (make-line-buffering-input-port underlying-port)
  65. (let* (;; buffers - a list of strings put back by unread-string or cached
  66. ;; using read-line.
  67. ;;
  68. (buffers '())
  69. ;; getc - return the next character from a buffer or from the underlying
  70. ;; port.
  71. ;;
  72. (getc (lambda ()
  73. (if (not buffers)
  74. (read-char underlying-port)
  75. (let ((c (string-ref (car buffers) 0)))
  76. (if (= 1 (string-length (car buffers)))
  77. (set! buffers (cdr buffers))
  78. (set-car! buffers (substring (car buffers) 1)))
  79. c))))
  80. (propogate-close (lambda () (close-port underlying-port)))
  81. (self (make-soft-port (vector #f #f #f getc propogate-close) "r"))
  82. (unread-string (lambda (str)
  83. (and (< 0 (string-length str))
  84. (set! buffers (cons str buffers)))))
  85. (read-string (lambda ()
  86. (cond
  87. ((not (null? buffers))
  88. (let ((answer (car buffers)))
  89. (set! buffers (cdr buffers))
  90. answer))
  91. (else
  92. (read-line underlying-port 'concat)))))) ;handle-newline->concat
  93. (set-object-property! self 'unread-string unread-string)
  94. (set-object-property! self 'read-string read-string)
  95. self))