From d6463465f7bb95cc15e02d589186a6c3107e6fbe Mon Sep 17 00:00:00 2001 From: Kaz Kylheku Date: Tue, 3 Jun 2025 07:38:02 -0700 Subject: listener: new *listener-ignore-eof* variable. * parser.c (listener_ignore_eof_s): New symbol variable. (repl): Copy the value of *listener-ignore-eof* into a local variable, which is reloaded after each command evaluation. On EOF, handle the cases involving the variable: positive integers count down, any other integer values quit, any non-nil value prevents quitting. (parse_init): Initialize listener_ignore_eof_s with interned symbol, and register the *listener-ignore-eof* variable. * txr.1: Documented. --- parser.c | 32 +++++++++++++++++++++++++++++--- txr.1 | 27 +++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/parser.c b/parser.c index 0237d12f..bdaa52b3 100644 --- a/parser.c +++ b/parser.c @@ -82,7 +82,7 @@ val parser_s, unique_s, circref_s; val listener_hist_len_s, listener_multi_line_p_s, listener_sel_inclusive_p_s; val listener_pprint_s, listener_greedy_eval_s, listener_auto_compound_s; -val listener_auto_infix_s; +val listener_auto_infix_s, listener_ignore_eof_s; val rec_source_loc_s, read_unknown_structs_s, read_bad_json_s, read_json_int_s; val json_s; val intr_s; @@ -1684,9 +1684,11 @@ val repl(val bindings, val in_stream, val out_stream, val env) val greedy_eval = lookup_global_var(listener_greedy_eval_s); val auto_parens = lookup_global_var(listener_auto_compound_s); val auto_infix = lookup_global_var(listener_auto_infix_s); + val ignore_eof = lookup_global_var(listener_ignore_eof_s); val rw_f = func_f1v(out_stream, repl_warning); val saved_dyn_env = set_dyn_env(make_env(nil, nil, dyn_env)); val brackets = mkstring(num_fast(repl_level), chr('>')); + val ignore_eof_count = cdr(ignore_eof); cnum i; env_vbind(dyn_env, stderr_s, out_stream); @@ -1783,14 +1785,34 @@ val repl(val bindings, val in_stream, val out_stream, val env) switch (lino_get_error(ls)) { case lino_intr: put_line(lit("** intr"), out_stream); - goto contin; + break; case lino_eof: + if (ignore_eof_count) { + if (integerp(ignore_eof_count)) { + ignore_eof_count = pred(ignore_eof_count); + if (plusp(ignore_eof_count)) { + format(out_stream, lit("** EOF will be ignored ~s more time~a\n"), + ignore_eof_count, + if3(ignore_eof_count != one, lit("s"), lit("")), nao); + } else if (ignore_eof_count == zero) { + put_line(lit("** Next EOF will terminate"), + out_stream); + ignore_eof_count = nil; + } else { + done = t; + } + } else { + put_line(lit("** EOF ignored by user preference"), out_stream); + } + } else { + done = t; + } break; default: put_line(lit("** error reading interactive input"), out_stream); + done = t; break; } - done = t; goto contin; } @@ -1869,6 +1891,8 @@ val repl(val bindings, val in_stream, val out_stream, val env) } } + ignore_eof_count = cdr(ignore_eof); + uw_pop_frame(&uw_handler); uw_catch (exsym, exvals) { @@ -2380,6 +2404,7 @@ void parse_init(void) listener_greedy_eval_s = intern(lit("*listener-greedy-eval-p*"), user_package); listener_auto_compound_s = intern(lit("*listener-auto-compound-p*"), user_package); listener_auto_infix_s = intern(lit("*listener-auto-infix-p*"), user_package); + listener_ignore_eof_s = intern(lit("*listener-ignore-eof*"), user_package); rec_source_loc_s = intern(lit("*rec-source-loc*"), user_package); read_unknown_structs_s = intern(lit("*read-unknown-structs*"), user_package); read_bad_json_s = intern(lit("*read-bad-json*"), user_package); @@ -2406,6 +2431,7 @@ void parse_init(void) reg_var(listener_greedy_eval_s, nil); reg_var(listener_auto_compound_s, nil); reg_var(listener_auto_infix_s, nil); + reg_var(listener_ignore_eof_s, nil); reg_var(rec_source_loc_s, nil); reg_var(read_unknown_structs_s, nil); reg_var(read_bad_json_s, nil); diff --git a/txr.1 b/txr.1 index 1878f628..88d18692 100644 --- a/txr.1 +++ b/txr.1 @@ -98472,6 +98472,33 @@ and then this is treated by auto infix mode as ultimately expanding to .codn "(+ (- x) y))" . +.coNP Special Variable @ *listener-ignore-eof* +.desc +The special variable +.code *listener-ignore-eof* +controls what happens when the +.key Ctrl-D +key is issued to quit, or the input device indicates a true +EOF condition. +Under the default value of the variable, which is +.codn nil , +the listener will quit. + +If the variable is given an integer value, and if that value +is positive, then the listener will ignore that many +consecutive EOF indications. Then if one more EOF indication +is given without an intervening command, the listener +will quit. + +If a zero or negative integer value is given, the behavior is +the same as the default +.code nil +value: quit on EOF. + +If any non-integer value is given other than +.codn nil , +then the listener will not quit on EOF. + .coNP Special Variable @ *doc-url* .desc The special variable -- cgit v1.2.3