From 86a2c93b3b62a1decad326fd66ed5cc1a9e64d5f Mon Sep 17 00:00:00 2001 From: Phillip Lord Date: Mon, 18 Jul 2016 23:28:05 +0100 Subject: [PATCH] Support standard input, output and error streams * doc/lispref/streams.texi: Update doc * lisp/simple.el (external-standard-input): New function * src/fns.c (external-standard-input-read-char, external-standard-input-read-line): New functions * src/print.c: (external-standard-output, external-standard-input): New functions --- doc/lispref/streams.texi | 38 +++++++++++++++++++++++- lisp/simple.el | 15 ++++++++++ src/fns.c | 62 ++++++++++++++++++++++++++++++++++++++++ src/print.c | 19 ++++++++++++ 4 files changed, 133 insertions(+), 1 deletion(-) diff --git a/doc/lispref/streams.texi b/doc/lispref/streams.texi index 41bc71e6aea..63a64947618 100644 --- a/doc/lispref/streams.texi +++ b/doc/lispref/streams.texi @@ -142,7 +142,7 @@ A symbol as input stream is equivalent to the symbol's function definition (if any). @end table - Here is an example of reading from a stream that is a buffer, showing +Here is an example of reading from a stream that is a buffer, showing where point is located before and after: @example @@ -265,6 +265,20 @@ reader encountered the open parenthesis, decided that it ended the input, and unread it. Another attempt to read from the stream at this point would read @samp{()} and return @code{nil}. +One function that is specifically designed for use as an input stream +is: + +@cindex @code{external-standard-input} +@defun external-standard-input &optional char +This function reads a single character from the system standard input +(as opposed to @var{standard-input}) and functions as a stream. Note, +however, that if Emacs is running in a terminal its use can be +unpredictable. +@end defun + +As with @code{external-standard-output}, this function is +predominately useful for debugging. + @node Input Functions @section Input Functions @@ -530,6 +544,28 @@ Now we can put the output in the proper order by reversing the list: Calling @code{concat} converts the list to a string so you can see its contents more clearly. +Two functions which are specifically designed for use as output +streams: + +@defun external-standard-output +@cindex @code{external-standard-output} output stream +Prints to the system standard output (as opposed to the +@var{standard-output}), regardless of whether Emacs is running +interactively or not. +@end defun + +@defun external-standard-error +@cindex @code{external-standard-error} output stream +Prints to the system standard error, regardless of whether Emacs is +running interactively or not. +@end defun + +These functions are predominately useful for debugging, as they are a +mechanism for producing output that does not change any buffer. Note, +however, that if Emacs is running in a terminal their use can affect +the display unpredictably. + + @node Output Functions @section Output Functions diff --git a/lisp/simple.el b/lisp/simple.el index a757876328b..17697f9be2b 100644 --- a/lisp/simple.el +++ b/lisp/simple.el @@ -8718,6 +8718,21 @@ to capitalize ARG words." (capitalize-region (region-beginning) (region-end)) (capitalize-word arg))) +(defvar external-standard-input-pushback nil + "Pushback character for `external-standard-input'.") + +(defun external-standard-input (&optional char) + "Read a character from the system standard input. + +If CHAR is non-nil, then do not read but return CHAR +on the next invocation." + (if char + (setq external-standard-input-pushback char) + (if (eq nil external-standard-input-pushback) + (external-standard-input-read-char) + (let ((rtn external-standard-input-pushback)) + (setq external-standard-input-pushback nil) + rtn)))) (provide 'simple) diff --git a/src/fns.c b/src/fns.c index c318608e4ce..72a7e3ab820 100644 --- a/src/fns.c +++ b/src/fns.c @@ -5082,6 +5082,65 @@ If nil, use the current buffer." */ ) return make_digest_string (digest, SHA1_DIGEST_SIZE); } +DEFUN ("external-standard-input-read-char",Fexternal_standard_input_read_char, Sexternal_standard_input_read_char, 0, 0, 0, + doc: /* Read a single character from the system standard input. + +Returns -1 if standard input is at the end.*/) + (void) +{ + int c; + Lisp_Object val; + + c = getchar(); + XSETINT(val,c); + + return val; +} + +DEFUN ("external-standard-input-read-line", Fexternal_standard_input_read_line, Sexternal_standard_input_read_line, 0, 0, 0, + doc: /* Read a line from the system standard input.*/) + (void) +{ + ptrdiff_t size, len; + char *line; + Lisp_Object val; + int c; + + val = Qnil; + size = 100; + len = 0; + line = xmalloc (size); + + while ((c = getchar ()) != '\n' && c != '\r') + { + if (c == EOF) + { + if (errno != 0) + break; + } + else + { + if (len == size) + line = xpalloc (line, &size, 1, -1, sizeof *line); + line[len++] = c; + } + } + + if (len || c == '\n' || c == '\r') + { + val = make_string (line, len); + xfree (line); + } + else + { + xfree (line); + error ("Error reading from stdin"); + } + + return val; +} + + void syms_of_fns (void) @@ -5249,4 +5308,7 @@ this variable. */); defsubr (&Ssecure_hash); defsubr (&Sbuffer_hash); defsubr (&Slocale_info); + defsubr (&Sexternal_standard_input_read_char); + defsubr (&Sexternal_standard_input_read_line); + } diff --git a/src/print.c b/src/print.c index 5531210e1b8..25f0afbf972 100644 --- a/src/print.c +++ b/src/print.c @@ -769,6 +769,22 @@ to make it write to the debugging output. */) return character; } +DEFUN ("external-standard-output", Fexternal_standard_output, Sexternal_standard_output, 1, 1, 0, + doc: /* Output character CHARACTER to system standard output. */) + (Lisp_Object character) +{ + CHECK_NUMBER (character); + printchar_to_stream (XINT(character), stdout); + return character; +} + +DEFUN ("external-standard-error", Fexternal_standard_error, Sexternal_standard_error, 1, 1, 0, + doc: /* Output character CHARACTER to system standard error. */) + (Lisp_Object character) +{ + return Fexternal_debugging_output (character); +} + /* This function is never called. Its purpose is to prevent print_output_debug_flag from being optimized away. */ @@ -2307,7 +2323,10 @@ priorities. */); defsubr (&Sprinc); defsubr (&Sprint); defsubr (&Sterpri); + defsubr (&Sexternal_standard_output); + defsubr (&Sexternal_standard_error); defsubr (&Swrite_char); + defsubr (&Sredirect_debugging_output); DEFSYM (Qprint_escape_newlines, "print-escape-newlines"); -- 2.39.5