Gregory Chamberlain: 1 lessgmi -- A self-contained pager for GMI files Peter Marinov: 1 lessgmi -- A self-contained pager for GMI files 2 files changed, 111 insertions(+), 9 deletions(-)
Copy & paste the following snippet into your terminal to import this patchset into git:
curl -s https://lists.sr.ht/~chambln/public-inbox/patches/22855/mbox | git am -3Learn more about email & git
* Implemented in the most-AWK-compatible script. Tested to work with `mawk` (default on Ubuntu) and `gawk` (GNU Awk installed separately)
Works fine for me with gawk and original-awk. However, testing with mawk 1.3.3 I get the following error: mawk: line 6: illegal reference to array list_of_wordsPeter Marinov <pmar21@sonic.net>Hello Greg, I'm using v1.3.4 of `mawk`. I tried running it on my work machine too (a Mac, with `brew install mawk`) and there was a problem with the HERE document in the script. What OS are you using? Could you try the new patch I've sent you just minutes ago, it has a split `lessgmi` and the awk script?Any idea why that might be?
* Implements wrapping of long lines It takes care of proper folding and formatting of quote sections (starting with "> ") and free text sections, keeps code sections verbatim (no folding applied) * Placed the script as a HERE document for an entirely self-contained `lessgmi` pager --- contrib/lessgmi | 118 ++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 110 insertions(+), 8 deletions(-) diff --git a/contrib/lessgmi b/contrib/lessgmi index 922cb95..b615eab 100755 --- a/contrib/lessgmi +++ b/contrib/lessgmi @@ -1,11 +1,113 @@ -#!/bin/sh +#!/bin/sh -Ceu # A wrapper around `less` that can color .gmi files -if command -v gawk >/dev/null 2>&1; then - # TODO: Official install is probably /usr/share/gmi? - gawk -f contrib/gmi_color_gawk.awk -- "$@" -else - # TODO: fall back to plain `awk`, for the moment fall-back on plain `cat` - cat -- "$@" -fi | less -r +# ANSI Escape Sequences at +# https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797 + +AWK_GMI_SCRIPT=$(cat) <<'EOF' +function print_folded(long_line, prefix) { + # Split words into an array + split(long_line, list_of_words) + + line_len = 0 + num_words = length(list_of_words) + + for(i = 1; i <= num_words; i++) { + # Check if we go beyond width of the block + if ((line_len + length(list_of_words[i])) > 78) { + line_len = 0 + printf("\n") + } + + # Print prefix + if (line_len == 0) + printf(prefix) + + line_len += length(list_of_words[i]) + 1 + printf("%s ", list_of_words[i]) + } + + # Handle case of empty lines + if (length(long_line) == 0) + printf(prefix) + + # The line ends with a new-line + printf("\n") +} + +BEGIN { + code_section = 0 + + ANSI_NO_COLOR = "\033[0m" + ANSI_URL1 = "\033[0;36m" + ANSI_URL2 = "\033[0;35m\033[1m" + ANSI_QUOTE = "\033[0;34m" + ANSI_CODE = "\033[0;32m" + ANSI_HEADING = "\033[0m\033[1m" +} + +# URL +/^=> / { + if (code_section == 0) + { + # Split line into URL elements + split($0, e) + + # Print the elements with individual colors + printf("%s%s %s%s,", ANSI_URL1, e[1], e[2], ANSI_NO_COLOR) + printf("\n\t%s%s", ANSI_URL2, e[3]) + printf("%s\n", ANSI_NO_COLOR) + next + } +} + +# Quote +/^>/ { + if (code_section == 0) + { + # Strip leading "> " + line = substr($0, 2) + + # Print folded block + setting color + using "> " as a line prefix + print_folded(line, ANSI_QUOTE "> ") + + # Switch off color at the end of the quote block + printf("%s", ANSI_NO_COLOR) + next + } +} + +# Code section +/^```/ { + if (code_section == 0) + # Activate color for code section + printf("%s```\n", ANSI_CODE) + else + # Remove color at the end of the code section + printf("%s```%s\n", ANSI_CODE, ANSI_NO_COLOR) + code_section = 1 - code_section + next +} + +# Heading +/^#.*/ { + if (code_section == 0) + { + printf("%s%s%s\n", ANSI_HEADING, $0, ANSI_NO_COLOR) + next + } +} + +# Everything else, the text of the file that is not prefixed by any markup +{ + if (code_section == 0) + # Outside code section, fold long lines, prefix = switch off the color + print_folded($0, ANSI_NO_COLOR) + else + # Inside code section, print line unmodified (no folding), apply color for code + printf("%s%s\n", ANSI_CODE, $0) +} +EOF + +awk "$AWK_GMI_SCRIPT" | less -r -- 2.25.1
Hi Peter, > * Implemented in the most-AWK-compatible script. > > Tested to work with `mawk` (default on Ubuntu) and `gawk` (GNU Awk > installed separately) Works fine for me with gawk and original-awk. However, testing with mawk 1.3.3 I get the following error: mawk: line 6: illegal reference to array list_of_words
Peter Marinov <pmar21@sonic.net>Hello Greg, I'm using v1.3.4 of `mawk`. I tried running it on my work machine too (a Mac, with `brew install mawk`) and there was a problem with the HERE document in the script. What OS are you using? Could you try the new patch I've sent you just minutes ago, it has a split `lessgmi` and the awk script?
Any idea why that might be? > A PROBLEM: > > `lessgmi` can only receive content via a pipe, I simply couldn't make > it operate via a file from the command line, I hope you can make that > work so it is a proper pager (I imagine people might use it to open > local .gmi files) > > Example: > cat README.gmi | lessgmi = Works > lessgmi READM.gmi = Doesn't That can be done like so: diff --git a/contrib/lessgmi b/contrib/lessgmi index b615eab..98a351c 100755 --- a/contrib/lessgmi +++ b/contrib/lessgmi @@ -110,4 +110,4 @@ BEGIN { } EOF -awk "$AWK_GMI_SCRIPT" | less -r +awk -- "$AWK_GMI_SCRIPT" "$@" | less -r --
Peter Marinov <pmar21@sonic.net>Thanks, this worked on Linux but failed on the Mac. I'm not sure why, for one thing `bash` on the Mac is an ancient version. I don't know, I plaied with it and couln't figure it out.
Having such a large script in a heredoc feels wrong somehow, but at least it’s all together in one executable. I mean, it’s like 99% Awk and 1% shell. There is just one command: awk "$AWK_GMI_SCRIPT" | less -r Surely it makes more sense to invoke less from inside Awk, if that’s possible?
Peter Marinov <pmar21@sonic.net>I agree, the HERE document was too much. I've split the script as before. I think you can invoke external programs from awk but I don't see how you can pipe into `less` with this method, I only imagine if that goes via a temp file, I feel that is less elegant. I've used your technique from pandoc-rss about how to reach the auxiliary awk script from `lessgmi`, if you add this to the `make install` it should work from ~/.local or /usr or any other PREFIX
Also, I think we have our creative differences when it comes to the colouring and typesetting of Gemtext. And that’s fine. We can distribute a number of gemtext pagers along with gmi, and/or separately. Users are at liberty to use whatever pager they like.
Peter Marinov <pmar21@sonic.net>So, I agree that the colors are an individual thing, that's why I added a way for it to be configured via an environment variable or it falls back on the default colors. To try it use this as a starting point in your shell (bash) prompt: export GMI_COLORS="*e[0;36m *e[0;35m*e[1m *e[0;34m *e[0;32m *e[0m*e[1m"
Going back to my earlier idea about the pager being a separate program in its own right, I’m going to extract the shorter Awk script I wrote out of gmi itself and into its own executable, akin to what you’ve done here. Then I’ll find a way to make it clear to users how to use their preferred pager both within and without gmi.
Peter Marinov <pmar21@sonic.net>I think the overall structure is your call. The idea of an individual pager `lessgmi` is useful standalone or invoked from `gmi` (by default or via a setting) --pe https://hangar118.sdf.org
Greg.