~chambln/public-inbox

lessgmi: A pager for GMI files with configurable colors v1 PROPOSED

Peter Marinov
Peter Marinov: 1
 lessgmi: A pager for GMI files with configurable colors

 2 files changed, 137 insertions(+), 8 deletions(-)
Export patchset (mbox)
How do I use this?

Copy & paste the following snippet into your terminal to import this patchset into git:

curl -s https://lists.sr.ht/~chambln/public-inbox/patches/22873/mbox | git am -3
Learn more about email & git
View this thread in the archives

[PATCH] lessgmi: A pager for GMI files with configurable colors Export this patch

Peter Marinov
* Implemented in the most-AWK-compatible script.

  Tested to work with `mawk` (default on Ubuntu) and `gawk` (GNU Awk
  installed separately)

  mawk v1.3.4
  gawk v5.0.1

* 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)

* Uses environment variable GMI_COLORS or default colors

* The awk script can be installed into $(PREFIX)/share/$(PROGRAM)/ or
  it can be used directly from the same folder as `lessgmi`
---
 contrib/gmi_color.awk | 125 ++++++++++++++++++++++++++++++++++++++++++
 contrib/lessgmi       |  20 ++++---
 2 files changed, 137 insertions(+), 8 deletions(-)
 create mode 100755 contrib/gmi_color.awk

diff --git a/contrib/gmi_color.awk b/contrib/gmi_color.awk
new file mode 100755
index 0000000..86d1f35
--- /dev/null
+++ b/contrib/gmi_color.awk
@@ -0,0 +1,125 @@
#!/usr/bin/awk -f

# gmi_color.awk
#
# Markup highlighting of Gemini pages for ANSI terminal
#

# ANSI Escape Sequences at
# https://gist.github.com/fnky/458719343aabd01cfb17a3a4f7296797


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

  # Use environment variable to set colors, or use defaults
  if (length(ENVIRON["GMI_COLORS"]) > 0)
    color_set = ENVIRON["GMI_COLORS"]
  else
    color_set = "*e[0;36m *e[0;35m*e[1m *e[0;34m *e[0;32m *e[0m*e[1m"

  # Subsusute "*e" with actual ESC character
  gsub(/\*e[[]/, "\033[", color_set)

  # Split into an array
  split(color_set, gmi_colors)

  ANSI_NO_COLOR = "\033[0m"
  ANSI_URL1 = gmi_colors[1]
  ANSI_URL2 = gmi_colors[2]
  ANSI_QUOTE = gmi_colors[3]
  ANSI_CODE = gmi_colors[4]
  ANSI_HEADING = gmi_colors[5]
}

# 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)
}
diff --git a/contrib/lessgmi b/contrib/lessgmi
index 922cb95..3da4e6a 100755
--- a/contrib/lessgmi
+++ b/contrib/lessgmi
@@ -1,11 +1,15 @@
#!/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
# Look for script into install path $(PREFIX)/share/$(PROGRAM)/
SHARE=${0%/*}/../share/${0##*/}
[ -x $SHARE/gmi_color.awk ] && AWK_SCRIPT=$SHARE/gmi_color.awk

# Or in same folder as `lessgmi`
BASE=${0%/*}
[ -x $BASE/gmi_color.awk ] && AWK_SCRIPT=$BASE/gmi_color.awk

$AWK_SCRIPT "$@" | less -r
-- 
2.25.1