]> gitweb.factorcode.org Git - factor.git/blob - core/io/io-docs.factor
Merge branch 'master' into experimental (untested!)
[factor.git] / core / io / io-docs.factor
1 USING: help.markup help.syntax quotations hashtables kernel
2 classes strings continuations destructors math ;
3 IN: io
4
5 HELP: stream-readln
6 { $values { "stream" "an input stream" } { "str/f" "a string or " { $link f } } }
7 { $contract "Reads a line of input from the stream. Outputs " { $link f } " on stream exhaustion." }
8 { $notes "Most code only works on one stream at a time and should instead use " { $link readln } "; see " { $link "stdio" } "." }
9 $io-error ;
10
11 HELP: stream-read1
12 { $values { "stream" "an input stream" } { "ch/f" "a character or " { $link f } } }
13 { $contract "Reads a character of input from the stream. Outputs " { $link f } " on stream exhaustion." }
14 { $notes "Most code only works on one stream at a time and should instead use " { $link read1 } "; see " { $link "stdio" } "." }
15 $io-error ;
16
17 HELP: stream-read
18 { $values { "n" "a non-negative integer" } { "stream" "an input stream" } { "str/f" "a string or " { $link f } } }
19 { $contract "Reads " { $snippet "n" } " characters of input from the stream. Outputs a truncated string or " { $link f } " on stream exhaustion." }
20 { $notes "Most code only works on one stream at a time and should instead use " { $link read } "; see " { $link "stdio" } "." }
21 $io-error ;
22
23 HELP: stream-read-until
24 { $values { "seps" string } { "stream" "an input stream" } { "str/f" "a string or " { $link f } } { "sep/f" "a character or " { $link f } } }
25 { $contract "Reads characters from the stream, until the first occurrence of a separator character, or stream exhaustion. In the former case, the separator character is pushed on the stack, and is not part of the output string. In the latter case, the entire stream contents are output, along with " { $link f } "." }
26 { $notes "Most code only works on one stream at a time and should instead use " { $link read-until } "; see " { $link "stdio" } "." }
27 $io-error ;
28
29 HELP: stream-read-partial
30 { $values
31      { "n" integer } { "stream" "an input stream" }
32      { "str/f" "a string or " { $link f } } }
33 { $description "Reads at most " { $snippet "n" } " characters from a stream and returns up to that many characters without blocking. If no characters are available, blocks until some are and returns them." } ;
34
35 HELP: stream-write1
36 { $values { "ch" "a character" } { "stream" "an output stream" } }
37 { $contract "Writes a character of output to the stream. If the stream does buffering, output may not be performed immediately; use " { $link stream-flush } " to force output." }
38 { $notes "Most code only works on one stream at a time and should instead use " { $link write1 } "; see " { $link "stdio" } "." }
39 $io-error ;
40
41 HELP: stream-write
42 { $values { "str" string } { "stream" "an output stream" } }
43 { $contract "Writes a string of output to the stream. If the stream does buffering, output may not be performed immediately; use " { $link stream-flush } " to force output." }
44 { $notes "Most code only works on one stream at a time and should instead use " { $link write } "; see " { $link "stdio" } "." }
45 $io-error ;
46
47 HELP: stream-flush
48 { $values { "stream" "an output stream" } }
49 { $contract "Waits for any pending output to complete." }
50 { $notes "With many output streams, written output is buffered and not sent to the underlying resource until either the buffer is full, or this word is called." }
51 { $notes "Most code only works on one stream at a time and should instead use " { $link flush } "; see " { $link "stdio" } "." }
52 $io-error ;
53
54 HELP: stream-nl
55 { $values { "stream" "an output stream" } }
56 { $contract "Writes a line terminator. If the stream does buffering, output may not be performed immediately; use " { $link stream-flush } " to force output." }
57 { $notes "Most code only works on one stream at a time and should instead use " { $link nl } "; see " { $link "stdio" } "." }
58 $io-error ;
59
60 HELP: stream-format
61 { $values { "str" string } { "style" "a hashtable" } { "stream" "an output stream" } }
62 { $contract "Writes formatted text to the stream. If the stream does buffering, output may not be performed immediately; use " { $link stream-flush } " to force output."
63 $nl
64 "The " { $snippet "style" } " hashtable holds character style information. See " { $link "character-styles" } "." }
65 { $notes "Most code only works on one stream at a time and should instead use " { $link format } "; see " { $link "stdio" } "." }
66 $io-error ;
67
68 HELP: make-block-stream
69 { $values { "style" "a hashtable" } { "stream" "an output stream" } { "stream'" "an output stream" } }
70 { $contract "Creates an output stream which wraps " { $snippet "stream" } " and adds " { $snippet "style" } " on calls to " { $link stream-write } " and " { $link stream-format } "."
71 $nl
72 "Unlike " { $link make-span-stream } ", this creates a new paragraph block in the output."
73 $nl
74 "The " { $snippet "style" } " hashtable holds paragraph style information. See " { $link "paragraph-styles" } "." }
75 { $notes "Most code only works on one stream at a time and should instead use " { $link with-nesting } "; see " { $link "stdio" } "." }
76 $io-error ;
77
78 HELP: stream-write-table
79 { $values { "table-cells" "a sequence of sequences of table cells" } { "style" "a hashtable" } { "stream" "an output stream" } }
80 { $contract "Prints a table of cells produced by " { $link with-cell } "."
81 $nl
82 "The " { $snippet "style" } " hashtable holds table style information. See " { $link "table-styles" } "." }
83 { $notes "Most code only works on one stream at a time and should instead use " { $link tabular-output } "; see " { $link "stdio" } "." }
84 $io-error ;
85
86 HELP: make-cell-stream
87 { $values { "style" hashtable } { "stream" "an output stream" } { "stream'" object } }
88 { $contract "Creates an output stream which writes to a table cell object." }
89 { $notes "Most code only works on one stream at a time and should instead use " { $link with-cell } "; see " { $link "stdio" } "." }
90 $io-error ;
91
92 HELP: make-span-stream
93 { $values { "style" "a hashtable" } { "stream" "an output stream" } { "stream'" "an output stream" } }
94 { $contract "Creates an output stream which wraps " { $snippet "stream" } " and adds " { $snippet "style" } " on calls to " { $link stream-write } " and " { $link stream-format } "."
95 $nl
96 "Unlike " { $link make-block-stream } ", the stream output is inline, and not nested in a paragraph block." }
97 { $notes "Most code only works on one stream at a time and should instead use " { $link with-style } "; see " { $link "stdio" } "." }
98 $io-error ;
99
100 HELP: stream-print
101 { $values { "str" string } { "stream" "an output stream" } }
102 { $description "Writes a newline-terminated string." }
103 { $notes "Most code only works on one stream at a time and should instead use " { $link print } "; see " { $link "stdio" } "." }
104 $io-error ;
105
106 HELP: stream-copy
107 { $values { "in" "an input stream" } { "out" "an output stream" } }
108 { $description "Copies the contents of one stream into another, closing both streams when done." } 
109 $io-error ;
110
111 HELP: input-stream
112 { $var-description "Holds an input stream for various implicit stream operations. Rebound using " { $link with-input-stream } " and " { $link with-input-stream* } "." } ;
113
114 HELP: output-stream
115 { $var-description "Holds an output stream for various implicit stream operations. Rebound using " { $link with-output-stream } " and " { $link with-output-stream* } "." } ;
116
117 HELP: error-stream
118 { $var-description "Holds an error stream." } ;
119
120 HELP: readln
121 { $values { "str/f" "a string or " { $link f } } }
122 { $description "Reads a line of input from " { $link input-stream } ". Outputs " { $link f } " on stream exhaustion." }
123 $io-error ;
124
125 HELP: read1
126 { $values { "ch/f" "a character or " { $link f } } }
127 { $description "Reads a character of input from " { $link input-stream } ". Outputs " { $link f } " on stream exhaustion." }
128 $io-error ;
129
130 HELP: read
131 { $values { "n" "a non-negative integer" } { "str/f" "a string or " { $link f } } }
132 { $description "Reads " { $snippet "n" } " characters of input from " { $link input-stream } ". Outputs a truncated string or " { $link f } " on stream exhaustion." }
133 $io-error ;
134
135 HELP: read-until
136 { $values { "seps" string } { "str/f" "a string or " { $link f } } { "sep/f" "a character or " { $link f } } }
137 { $contract "Reads characters from " { $link input-stream } ". until the first occurrence of a separator character, or stream exhaustion. In the former case, the separator character is pushed on the stack, and is not part of the output string. In the latter case, the entire stream contents are output, along with " { $link f } "." }
138 $io-error ;
139
140 HELP: read-partial
141 { $values
142      { "n" null }
143      { "str/f" null } }
144 { $description "Reads at most " { $snippet "n" } " characters from " { $link input-stream } " and returns up to that many characters without blocking. If no characters are available, blocks until some are and returns them." } ;
145
146 HELP: write1
147 { $values { "ch" "a character" } }
148 { $contract "Writes a character of output to " { $link output-stream } ". If the stream does buffering, output may not be performed immediately; use " { $link flush } " to force output." }
149 $io-error ;
150
151 HELP: write
152 { $values { "str" string } }
153 { $description "Writes a string of output to " { $link output-stream } ". If the stream does buffering, output may not be performed immediately; use " { $link flush } " to force output." }
154 $io-error ;
155
156 HELP: flush
157 { $description "Waits for any pending output on " { $link output-stream } " to complete." }
158 $io-error ;
159
160 HELP: nl
161 { $description "Writes a line terminator to " { $link output-stream } ". If the stream does buffering, output may not be performed immediately; use " { $link flush } " to force output." }
162 $io-error ;
163
164 HELP: format
165 { $values { "str" string } { "style" "a hashtable" } }
166 { $description "Writes formatted text to " { $link output-stream } ". If the stream does buffering, output may not be performed immediately; use " { $link flush } " to force output." }
167 { $notes "Details are in the documentation for " { $link stream-format } "." }
168 $io-error ;
169
170 HELP: with-nesting
171 { $values { "style" "a hashtable" } { "quot" quotation } }
172 { $description "Calls the quotation in a new dynamic scope with " { $link output-stream } " rebound to a nested paragraph stream, with formatting information applied." }
173 { $notes "Details are in the documentation for " { $link make-block-stream } "." }
174 $io-error ;
175
176 HELP: tabular-output
177 { $values { "style" "a hashtable" } { "quot" quotation } }
178 { $description "Calls a quotation which emits a series of equal-length table rows using " { $link with-row } ". The results are laid out in a tabular fashion on " { $link output-stream } "."
179 $nl
180 "The " { $snippet "style" } " hashtable holds table style information. See " { $link "table-styles" } "." }
181 { $examples
182     { $code
183         "{ { 1 2 } { 3 4 } }"
184         "H{ { table-gap { 10 10 } } } ["
185         "    [ [ [ [ . ] with-cell ] each ] with-row ] each"
186         "] tabular-output"
187     }
188 }
189 $io-error ;
190
191 HELP: with-row
192 { $values { "quot" quotation } }
193 { $description "Calls a quotation which emits a series of table cells using " { $link with-cell } ". This word can only be called inside the quotation given to " { $link tabular-output } "." }
194 $io-error ;
195
196 HELP: with-cell
197 { $values { "quot" quotation } }
198 { $description "Calls a quotation in a new scope with " { $link output-stream } " rebound. Output performed by the quotation is displayed in a table cell. This word can only be called inside the quotation given to " { $link with-row } "." }
199 $io-error ;
200
201 HELP: write-cell
202 { $values { "str" string } }
203 { $description "Outputs a table cell containing a single string. This word can only be called inside the quotation given to " { $link with-row } "." }
204 $io-error ;
205
206 HELP: with-style
207 { $values { "style" "a hashtable" } { "quot" quotation } }
208 { $description "Calls the quotation in a new dynamic scope where calls to " { $link write } ", " { $link format } " and other stream output words automatically inherit style settings from " { $snippet "style" } "." }
209 { $notes "Details are in the documentation for " { $link make-span-stream } "." }
210 $io-error ;
211
212 HELP: print
213 { $values { "string" string } }
214 { $description "Writes a newline-terminated string to " { $link output-stream } "." }
215 $io-error ;
216
217 HELP: with-input-stream
218 { $values { "stream" "an input stream" } { "quot" quotation } }
219 { $description "Calls the quotation in a new dynamic scope, with " { $link input-stream } " rebound to  " { $snippet "stream" } ". The stream is closed if the quotation returns or throws an error." } ;
220
221 HELP: with-output-stream
222 { $values { "stream" "an output stream" } { "quot" quotation } }
223 { $description "Calls the quotation in a new dynamic scope, with " { $link output-stream } " rebound to  " { $snippet "stream" } ". The stream is closed if the quotation returns or throws an error." } ;
224
225 HELP: with-streams
226 { $values { "input" "an input stream" } { "output" "an output stream" } { "quot" quotation } }
227 { $description "Calls the quotation in a new dynamic scope, with " { $link input-stream } " rebound to  " { $snippet "input" } " and " { $link output-stream } " rebound to  " { $snippet "output" } ". The stream is closed if the quotation returns or throws an error." } ;
228
229 HELP: with-streams*
230 { $values { "input" "an input stream" } { "output" "an output stream" } { "quot" quotation } }
231 { $description "Calls the quotation in a new dynamic scope, with " { $link input-stream } " rebound to  " { $snippet "input" } " and " { $link output-stream } " rebound to  " { $snippet "output" } "." }
232 { $notes "This word does not close the stream. Compare with " { $link with-streams } "." } ;
233
234 { with-input-stream with-input-stream* } related-words
235
236 { with-output-stream with-output-stream* } related-words
237
238 HELP: with-input-stream*
239 { $values { "stream" "an input stream" } { "quot" quotation } }
240 { $description "Calls the quotation in a new dynamic scope, with " { $link input-stream } " rebound to  " { $snippet "stream" } "." }
241 { $notes "This word does not close the stream. Compare with " { $link with-input-stream } "." } ;
242
243 HELP: with-output-stream*
244 { $values { "stream" "an output stream" } { "quot" quotation } }
245 { $description "Calls the quotation in a new dynamic scope, with " { $link output-stream } " rebound to  " { $snippet "stream" } "." }
246 { $notes "This word does not close the stream. Compare with " { $link with-output-stream } "." } ;
247
248 HELP: bl
249 { $description "Outputs a space character (" { $snippet "\" \"" } ") to " { $link output-stream } "." }
250 $io-error ;
251
252 HELP: lines
253 { $values { "stream" "an input stream" } { "seq" "a sequence of strings" } }
254 { $description "Reads lines of text until the stream is exhausted, collecting them in a sequence of strings." } ;
255
256 HELP: each-line
257 { $values { "quot" { $quotation "( str -- )" } } }
258 { $description "Calls the quotatin with successive lines of text, until the current " { $link input-stream } " is exhausted." } ;
259
260 HELP: contents
261 { $values { "stream" "an input stream" } { "str" string } }
262 { $description "Reads the entire contents of a stream into a string." }
263 $io-error ;
264
265 ARTICLE: "stream-protocol" "Stream protocol"
266 "The stream protocol consists of a large number of generic words, many of which are optional."
267 $nl
268 "Stream protocol words are rarely called directly, since code which only works with one stream at a time should be written use " { $link "stdio" } " instead, wrapping I/O operations such as " { $link read } " and " { $link write } " in " { $link with-input-stream } " and " { $link with-output-stream } "."
269 $nl
270 "All streams must implement the " { $link dispose } " word in addition to the stream protocol."
271 $nl
272 "These words are required for input streams:"
273 { $subsection stream-read1 }
274 { $subsection stream-read }
275 { $subsection stream-read-until }
276 { $subsection stream-readln }
277 { $subsection stream-read-partial }
278 "These words are required for output streams:"
279 { $subsection stream-flush }
280 { $subsection stream-write1 }
281 { $subsection stream-write }
282 { $subsection stream-format }
283 { $subsection stream-nl }
284 { $subsection make-span-stream }
285 { $subsection make-block-stream }
286 { $subsection make-cell-stream }
287 { $subsection stream-write-table }
288 { $see-also "io.timeouts" } ;
289
290 ARTICLE: "stdio" "Default input and output streams"
291 "Most I/O code only operates on one stream at a time. The " { $link input-stream } " and " { $link output-stream } " variables are implicit parameters used by many I/O words. Using this idiom improves code in three ways:"
292 { $list
293     { "Code becomes simpler because there is no need to keep a stream around on the stack." }
294     { "Code becomes more robust because " { $link with-input-stream } " and " { $link with-output-stream } " automatically close the streams if there is an error." }
295     { "Code becomes more reusable because it can be written to not worry about which stream is being used, and instead the caller can use " { $link with-input-stream } " or " { $link with-output-stream } " to specify the source or destination for I/O operations." }
296 }
297 "For example, here is a program which reads the first line of a file, converts it to an integer, then reads that many characters, and splits them into groups of 16:"
298 { $code
299     "USING: continuations kernel io io.files math.parser splitting ;"
300     "\"data.txt\" utf8 <file-reader>"
301     "dup stream-readln number>string over stream-read 16 group"
302     "swap dispose"
303 }
304 "This code has two problems: it has some unnecessary stack shuffling, and if either " { $link stream-readln } " or " { $link stream-read } " throws an I/O error, the stream is not closed because " { $link dispose } " is never reached. So we can add a call to " { $link with-disposal } " to ensure the stream is always closed:"
305 { $code
306     "USING: continuations kernel io io.files math.parser splitting ;"
307     "\"data.txt\" utf8 <file-reader> ["
308     "    dup stream-readln number>string over stream-read"
309     "    16 group"
310     "] with-disposal"
311 }
312 "This code is robust however it is more complex than it needs to be since. This is where the default stream words come in; using them, the above can be rewritten as follows:"
313 { $code
314     "USING: continuations kernel io io.files math.parser splitting ;"
315     "\"data.txt\" utf8 <file-reader> ["
316     "    readln number>string read 16 group"
317     "] with-input-stream"
318 }
319 "An even better implementation that takes advantage of a utility word:"
320 { $code
321     "USING: continuations kernel io io.files math.parser splitting ;"
322     "\"data.txt\" utf8 ["
323     "    readln number>string read 16 group"
324     "] with-file-reader"
325 }
326 "The default input stream is stored in a dynamically-scoped variable:"
327 { $subsection input-stream }
328 "Unless rebound in a child namespace, this variable will be set to a console stream for reading input from the user."
329 $nl
330 "Words reading from the default input stream:"
331 { $subsection read1 }
332 { $subsection read }
333 { $subsection read-until }
334 { $subsection readln }
335 { $subsection read-partial }
336 "A pair of combinators for rebinding the " { $link input-stream } " variable:"
337 { $subsection with-input-stream }
338 { $subsection with-input-stream* }
339 "The default output stream is stored in a dynamically-scoped variable:"
340 { $subsection output-stream }
341 "Unless rebound in a child namespace, this variable will be set to a console stream for showing output to the user."
342 $nl
343 "Words writing to the default input stream:"
344 { $subsection flush }
345 { $subsection write1 }
346 { $subsection write }
347 { $subsection print }
348 { $subsection nl }
349 { $subsection bl }
350 "Formatted output:"
351 { $subsection format }
352 { $subsection with-style }
353 { $subsection with-nesting }
354 "Tabular output:"
355 { $subsection tabular-output }
356 { $subsection with-row }
357 { $subsection with-cell }
358 { $subsection write-cell }
359 "A pair of combinators for rebinding the " { $link output-stream } " variable:"
360 { $subsection with-output-stream }
361 { $subsection with-output-stream* }
362 "A pair of combinators for rebinding both default streams at once:"
363 { $subsection with-streams }
364 { $subsection with-streams* } ;
365
366 ARTICLE: "stream-utils" "Stream utilities"
367 "There are a few useful stream-related words which are not generic, but merely built up from the stream protocol."
368 $nl
369 "First, a simple composition of " { $link stream-write } " and " { $link stream-nl } ":"
370 { $subsection stream-print }
371 "Processing lines one by one:"
372 { $subsection each-line }
373 "Sluring an entire stream into memory all at once:"
374 { $subsection lines }
375 { $subsection contents }
376 "Copying the contents of one stream to another:"
377 { $subsection stream-copy } ;
378
379 ARTICLE: "streams" "Streams"
380 "Input and output centers on the concept of a " { $emphasis "stream" } ", which is a source or sink of characters. Streams also support formatted output, which may be used to present styled text in a manner independent of output medium."
381 $nl
382 "A stream can either be passed around on the stack or bound to a dynamic variable and used as an implicit " { $emphasis "default stream" } "."
383 { $subsection "stream-protocol" }
384 { $subsection "stdio" }
385 { $subsection "stream-utils" }
386 { $see-also "io.streams.string" "io.streams.plain" "io.streams.duplex" } ;
387
388 ABOUT: "streams"