Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
marvel
GitHub Repository: marvel/qnf
Path: blob/master/elisp/slime/swank-gray.lisp
990 views
1
;;;; -*- Mode: lisp; indent-tabs-mode: nil -*-
2
;;;
3
;;; swank-gray.lisp --- Gray stream based IO redirection.
4
;;;
5
;;; Created 2003
6
;;;
7
;;; This code has been placed in the Public Domain. All warranties
8
;;; are disclaimed.
9
;;;
10
11
(in-package :swank-backend)
12
13
(defclass slime-output-stream (fundamental-character-output-stream)
14
((output-fn :initarg :output-fn)
15
(buffer :initform (make-string 8000))
16
(fill-pointer :initform 0)
17
(column :initform 0)
18
(lock :initform (make-lock :name "buffer write lock"))))
19
20
(defmacro with-slime-output-stream (stream &body body)
21
`(with-slots (lock output-fn buffer fill-pointer column) ,stream
22
(call-with-lock-held lock (lambda () ,@body))))
23
24
(defmethod stream-write-char ((stream slime-output-stream) char)
25
(with-slime-output-stream stream
26
(setf (schar buffer fill-pointer) char)
27
(incf fill-pointer)
28
(incf column)
29
(when (char= #\newline char)
30
(setf column 0))
31
(when (= fill-pointer (length buffer))
32
(finish-output stream)))
33
char)
34
35
(defmethod stream-write-string ((stream slime-output-stream) string
36
&optional start end)
37
(with-slime-output-stream stream
38
(let* ((start (or start 0))
39
(end (or end (length string)))
40
(len (length buffer))
41
(count (- end start))
42
(free (- len fill-pointer)))
43
(when (>= count free)
44
(stream-finish-output stream))
45
(cond ((< count len)
46
(replace buffer string :start1 fill-pointer
47
:start2 start :end2 end)
48
(incf fill-pointer count))
49
(t
50
(funcall output-fn (subseq string start end))))
51
(let ((last-newline (position #\newline string :from-end t
52
:start start :end end)))
53
(setf column (if last-newline
54
(- end last-newline 1)
55
(+ column count))))))
56
string)
57
58
(defmethod stream-line-column ((stream slime-output-stream))
59
(with-slime-output-stream stream column))
60
61
(defmethod stream-line-length ((stream slime-output-stream))
62
75)
63
64
(defmethod stream-finish-output ((stream slime-output-stream))
65
(with-slime-output-stream stream
66
(unless (zerop fill-pointer)
67
(funcall output-fn (subseq buffer 0 fill-pointer))
68
(setf fill-pointer 0)))
69
nil)
70
71
(defmethod stream-force-output ((stream slime-output-stream))
72
(stream-finish-output stream))
73
74
(defmethod stream-fresh-line ((stream slime-output-stream))
75
(with-slime-output-stream stream
76
(cond ((zerop column) nil)
77
(t (terpri stream) t))))
78
79
(defclass slime-input-stream (fundamental-character-input-stream)
80
((input-fn :initarg :input-fn)
81
(buffer :initform "") (index :initform 0)
82
(lock :initform (make-lock :name "buffer read lock"))))
83
84
(defmethod stream-read-char ((s slime-input-stream))
85
(call-with-lock-held
86
(slot-value s 'lock)
87
(lambda ()
88
(with-slots (buffer index input-fn) s
89
(when (= index (length buffer))
90
(let ((string (funcall input-fn)))
91
(cond ((zerop (length string))
92
(return-from stream-read-char :eof))
93
(t
94
(setf buffer string)
95
(setf index 0)))))
96
(assert (plusp (length buffer)))
97
(prog1 (aref buffer index) (incf index))))))
98
99
(defmethod stream-listen ((s slime-input-stream))
100
(call-with-lock-held
101
(slot-value s 'lock)
102
(lambda ()
103
(with-slots (buffer index) s
104
(< index (length buffer))))))
105
106
(defmethod stream-unread-char ((s slime-input-stream) char)
107
(call-with-lock-held
108
(slot-value s 'lock)
109
(lambda ()
110
(with-slots (buffer index) s
111
(decf index)
112
(cond ((eql (aref buffer index) char)
113
(setf (aref buffer index) char))
114
(t
115
(warn "stream-unread-char: ignoring ~S (expected ~S)"
116
char (aref buffer index)))))))
117
nil)
118
119
(defmethod stream-clear-input ((s slime-input-stream))
120
(call-with-lock-held
121
(slot-value s 'lock)
122
(lambda ()
123
(with-slots (buffer index) s
124
(setf buffer ""
125
index 0))))
126
nil)
127
128
(defmethod stream-line-column ((s slime-input-stream))
129
nil)
130
131
(defmethod stream-line-length ((s slime-input-stream))
132
75)
133
134
135
;;; CLISP extensions
136
137
;; We have to define an additional method for the sake of the C
138
;; function listen_char (see src/stream.d), on which SYS::READ-FORM
139
;; depends.
140
141
;; We could make do with either of the two methods below.
142
143
(defmethod stream-read-char-no-hang ((s slime-input-stream))
144
(call-with-lock-held
145
(slot-value s 'lock)
146
(lambda ()
147
(with-slots (buffer index) s
148
(when (< index (length buffer))
149
(prog1 (aref buffer index) (incf index)))))))
150
151
;; This CLISP extension is what listen_char actually calls. The
152
;; default method would call STREAM-READ-CHAR-NO-HANG, so it is a bit
153
;; more efficient to define it directly.
154
155
(defmethod stream-read-char-will-hang-p ((s slime-input-stream))
156
(with-slots (buffer index) s
157
(= index (length buffer))))
158
159
160
;;;
161
162
(defimplementation make-output-stream (write-string)
163
(make-instance 'slime-output-stream :output-fn write-string))
164
165
(defimplementation make-input-stream (read-string)
166
(make-instance 'slime-input-stream :input-fn read-string))
167
168