[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[COMMITTED] poke: new internal terminal pager
From: |
Jose E. Marchesi |
Subject: |
[COMMITTED] poke: new internal terminal pager |
Date: |
Sat, 29 Jan 2022 15:25:55 +0100 |
User-agent: |
Gnus/5.13 (Gnus v5.13) Emacs/28.0.50 (gnu/linux) |
This patch introduces basic paging support in the poke
terminal (pk-term). A new poke setting `pager' has been introduced to
control whether paging takes effect. It's default value is `no'. You
can change this setting (for example in your ~/.pokerc) like this:
.set pager yes
Note that I am applying this in `master' but not in maint/poke-2. The
pager works, but I think it needs to be used a little and improved
before being released. An example of a thing to improve is to
remove (erase) the "--More--" lines when continuing.
2022-01-29 Jose E. Marchesi <jemarch@gnu.org>
* poke/pk-cmd-set.c (pk_cmd_set_pager): New function.
(set_pager_cmd): New variable.
(pk_cmd_set_init): Add set_pager command.
* poke/pk-repl.c (pk_repl): Use pager (conditionally) when
executing commands in the repl.
* poke/pk-settings.pk: Setting for `pager'.
* poke/pk-term.c (screen_lines): New variable.
(screen_cols): Likewise.
(pager_active_p): Likewise.
(nlines): Likewise.
(pk_term_init): Initialize terminal dimensions.
(pk_term_start_pager): New function.
(pk_term_stop_pager): Likewise.
(pk_puts_paged): Likewise.
(pk_puts): Call pk_puts_paged when necessary.
(pk_printf): Output via pk_puts.
* poke/poke.c: New global poke_pager_p.
---
ChangeLog | 20 +++++++++
poke/pk-cmd-set.c | 57 ++++++++++++++++++++++++-
poke/pk-repl.c | 3 ++
poke/pk-settings.pk | 15 +++++++
poke/pk-term.c | 121 ++++++++++++++++++++++++++++++++++++++++++++++++++--
poke/pk-term.h | 4 ++
poke/poke.c | 5 +++
poke/poke.h | 1 +
8 files changed, 222 insertions(+), 4 deletions(-)
diff --git a/ChangeLog b/ChangeLog
index 81315c27..92888a76 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,25 @@
2022-01-29 Jose E. Marchesi <jemarch@gnu.org>
+ * poke/pk-cmd-set.c (pk_cmd_set_pager): New function.
+ (set_pager_cmd): New variable.
+ (pk_cmd_set_init): Add set_pager command.
+ * poke/pk-repl.c (pk_repl): Use pager (conditionally) when
+ executing commands in the repl.
+ * poke/pk-settings.pk: Setting for `pager'.
+ * poke/pk-term.c (screen_lines): New variable.
+ (screen_cols): Likewise.
+ (pager_active_p): Likewise.
+ (nlines): Likewise.
+ (pk_term_init): Initialize terminal dimensions.
+ (pk_term_start_pager): New function.
+ (pk_term_stop_pager): Likewise.
+ (pk_puts_paged): Likewise.
+ (pk_puts): Call pk_puts_paged when necessary.
+ (pk_printf): Output via pk_puts.
+ * poke/poke.c: New global poke_pager_p.
+
+2022-01-29 Jose E. Marchesi <jemarch@gnu.org>
+
* poke/poke.c (parse_args_2): Really restore proper behavior with
-l and unhandled exceptions.
diff --git a/poke/pk-cmd-set.c b/poke/pk-cmd-set.c
index 99fbd36d..4b10eb7d 100644
--- a/poke/pk-cmd-set.c
+++ b/poke/pk-cmd-set.c
@@ -182,8 +182,56 @@ pk_cmd_set_error_on_warning (int argc, struct pk_cmd_arg
argv[],
return 1;
}
+
+static int
+pk_cmd_set_pager (int argc, struct pk_cmd_arg argv[], uint64_t uflags)
+{
+ /* set error-on-warning {yes,no} */
+
+ const char *arg;
+
+ /* Note that it is not possible to distinguish between no argument
+ and an empty unique string argument. Therefore, argc should be
+ always 1 here, and we determine when no value was specified by
+ checking whether the passed string is empty or not. */
+
+ if (argc != 2)
+ assert (0);
+
+ arg = PK_CMD_ARG_STR (argv[1]);
+
+ if (*arg == '\0')
+ {
+ if (poke_pager_p)
+ pk_puts ("yes\n");
+ else
+ pk_puts ("no\n");
+ }
+ else
+ {
+ if (STREQ (arg, "yes"))
+ poke_pager_p = 1;
+ else if (STREQ (arg, "no"))
+ poke_pager_p = 0;
+ else
+ {
+ pk_term_class ("error");
+ pk_puts (_("error: "));
+ pk_term_end_class ("error");
+ pk_puts (_("pager should be one of `yes' or `no'\n"));
+ return 0;
+ }
+ }
+
+ return 1;
+}
+
extern struct pk_cmd null_cmd; /* pk-cmd.c */
+const struct pk_cmd set_pager_cmd =
+ {"pager", "s?", "", 0, NULL, NULL, pk_cmd_set_pager,
+ "set pager (yes|no)", NULL};
+
const struct pk_cmd set_error_on_warning_cmd =
{"error-on-warning", "s?", "", 0, NULL, NULL, pk_cmd_set_error_on_warning,
"set error-on-warning (yes|no)", NULL};
@@ -224,7 +272,7 @@ pk_cmd_set_init ()
nsettings = pk_array_nelem (registry_settings);
set_cmds = xmalloc (sizeof (struct pk_cmd *)
- * (pk_int_value (nsettings) + 2));
+ * (pk_int_value (nsettings) + 3));
for (i = 0; i < pk_int_value (nsettings); ++i)
{
@@ -265,6 +313,13 @@ pk_cmd_set_init ()
/* Add error-on-warning. */
set_cmds[i++] = &set_error_on_warning_cmd;
+ /* Add set-pager. */
+ set_cmds[i++] = &set_pager_cmd;
+
+ /* NOTE: if you add more C-handled commands here like
+ `error-on-warning' and `set-pager', please do not forget to
+ update the xmalloc count above. */
+
/* Finish set_cmds with the null command. */
set_cmds[i] = &null_cmd;
}
diff --git a/poke/pk-repl.c b/poke/pk-repl.c
index b256163c..76c9df6f 100644
--- a/poke/pk-repl.c
+++ b/poke/pk-repl.c
@@ -383,7 +383,10 @@ pk_repl (void)
add_history (line);
#endif
+ if (poke_pager_p)
+ pk_term_start_pager ();
pk_cmd_exec (line);
+ pk_term_stop_pager ();
}
free (line);
}
diff --git a/poke/pk-settings.pk b/poke/pk-settings.pk
index 99796bf0..63d8ee75 100644
--- a/poke/pk-settings.pk
+++ b/poke/pk-settings.pk
@@ -535,6 +535,21 @@ turn warnings into errors.
This setting is `no' by default.",
};
+/* Likewise for `pager'. */
+
+pk_help_add_topic
+ :entry Poke_HelpEntry {
+ category = "settings",
+ topic = "pager",
+ summary = "whether to use the terminal pager",
+ synopsis = ".set pager {yes,no}",
+ description = "\
+This setting determines whether the output of poke commands will
+be paged or not. Each page will have the height of the terminal.
+
+This setting is `no' by default.",
+ };
+
/* Dump current settings. */
fun pk_settings_dump = void:
diff --git a/poke/pk-term.c b/poke/pk-term.c
index d191f6fd..ef908301 100644
--- a/poke/pk-term.c
+++ b/poke/pk-term.c
@@ -18,17 +18,29 @@
#include <config.h>
-#include <stdlib.h> /* For exit. */
+#include <stdlib.h> /* For exit and getenv. */
#include <assert.h> /* For assert. */
#include <string.h>
#include <unistd.h> /* For isatty */
#include <textstyle.h>
#include <assert.h>
#include <xalloc.h>
+#include <xstrndup.h>
+#include <stdio.h>
+#include <termios.h>
+#include <termcap.h>
#include "poke.h"
#include "pk-utils.h"
+/* Several variables related to the pager. */
+
+static int screen_lines;
+static int screen_cols;
+
+static int pager_active_p;
+static int nlines = 1;
+
/* Default style to use when the user doesn't specify a style file.
We provide two defaults: one for dark backgrounds (the default) and
another for bright backgrounds. */
@@ -244,6 +256,28 @@ pk_term_init (int argc, char *argv[])
register_color (default_bgcolor, -1, -1, -1);
}
#endif
+
+ /* Get the terminal dimensions using termcap. */
+ {
+ char *termtype = getenv ("TERM");
+ static char term_buffer[2048];
+
+ if (termtype == NULL)
+ {
+ /* Stupid defaults. */
+ screen_cols = 80;
+ screen_lines = 25;
+ }
+
+ if (tgetent (term_buffer, termtype) < 0)
+ fputs ("error: could not access the termcap database; ignoring TERM.\n",
+ stderr);
+ else
+ {
+ screen_cols = tgetnum ("co");
+ screen_lines = tgetnum ("li");
+ }
+ }
}
void
@@ -261,10 +295,91 @@ pk_term_flush ()
ostream_flush (pk_ostream, FLUSH_THIS_STREAM);
}
+
+void
+pk_term_start_pager (void)
+{
+ pager_active_p = 1;
+ nlines = 1;
+}
+
+void
+pk_term_stop_pager (void)
+{
+ pager_active_p = 0;
+}
+
+static void
+pk_puts_paged (const char *lines)
+{
+ char *start, *end;
+
+
+ start = (char *) lines;
+
+ do
+ {
+ char *line;
+
+ end = strchrnul (start, '\n');
+ line = xstrndup (start, end - start + 1);
+
+ ostream_write_str (pk_ostream, line);
+ free (line);
+ start = end + 1;
+ if (*end != '\0')
+ nlines++;
+
+ if (nlines >= screen_lines)
+ {
+ struct termios old_termios;
+ struct termios new_termios;
+
+ ostream_write_str (pk_ostream, "--More--");
+ ostream_flush (pk_ostream, FLUSH_THIS_STREAM);
+
+ /* Set stdin in non-buffered mode. */
+ tcgetattr (0, &old_termios);
+ memcpy (&new_termios, &old_termios, sizeof (struct termios));
+ new_termios.c_lflag &= ~(ICANON | ECHO);
+ new_termios.c_cc[VTIME] = 0;
+ new_termios.c_cc[VMIN] = 1;
+ tcsetattr (0, TCSANOW, &new_termios);
+
+ /* Wait for a key and process it. */
+ while (1)
+ {
+ int c = fgetc (stdin);
+
+ if (c == '\n')
+ {
+ nlines--;
+ break;
+ }
+ if (c == ' ')
+ {
+ nlines = 1;
+ break;
+ }
+
+ /* Ding! 8-) */
+ fprintf (stderr, "\007");
+ }
+
+ /* Restore stdin to buffered-mode. */
+ tcsetattr (0, TCSANOW, &old_termios);
+ ostream_write_str (pk_ostream, "\n");
+ }
+ } while (*end != '\0');
+}
+
void
pk_puts (const char *str)
{
- ostream_write_str (pk_ostream, str);
+ if (pager_active_p)
+ pk_puts_paged (str);
+ else
+ ostream_write_str (pk_ostream, str);
}
__attribute__ ((__format__ (__printf__, 1, 2)))
@@ -280,7 +395,7 @@ pk_printf (const char *format, ...)
assert (r != -1);
va_end (ap);
- ostream_write_str (pk_ostream, str);
+ pk_puts (str);
free (str);
}
diff --git a/poke/pk-term.h b/poke/pk-term.h
index 15a5db01..e1ce4a3a 100644
--- a/poke/pk-term.h
+++ b/poke/pk-term.h
@@ -60,4 +60,8 @@ extern struct pk_color pk_term_get_bgcolor (void);
extern void pk_term_set_color (struct pk_color color);
extern void pk_term_set_bgcolor (struct pk_color color);
+/* Paging. */
+extern void pk_term_start_pager (void);
+extern void pk_term_stop_pager (void);
+
#endif /* PK_TERM_H */
diff --git a/poke/poke.c b/poke/poke.c
index 76ff9a69..b589729d 100644
--- a/poke/poke.c
+++ b/poke/poke.c
@@ -128,6 +128,11 @@ pk_compiler poke_compiler;
int poke_load_init_file = 1;
+/* The following global indicates whether to use the terminal
+ pager. It defaults to 0. */
+
+int poke_pager_p;
+
/* Command line options management. */
enum
diff --git a/poke/poke.h b/poke/poke.h
index c09bf005..8508dd68 100644
--- a/poke/poke.h
+++ b/poke/poke.h
@@ -31,6 +31,7 @@
extern int poke_interactive_p;
extern int poke_quiet_p;
extern int poke_exit_p;
+extern int poke_pager_p;
#if HAVE_HSERVER
extern int poke_hserver_p;
#endif
--
2.11.0
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [COMMITTED] poke: new internal terminal pager,
Jose E. Marchesi <=