~chambln/public-inbox

Add syntax coloring for Gemini markup via `awk` v1 SUPERSEDED

Peter Marinov
Peter Marinov: 1
 Add syntax coloring for Gemini markup via `awk`

 4 files changed, 90 insertions(+), 2 deletions(-)
Peter Marinov
Hello Greg,

On Mon, May 17, 2021 at 11:12:07PM +0100, Gregory Chamberlain wrote:
Next
Peter Marinov
Hello Greg,

On Tue, May 18, 2021 at 11:52:47PM +0100, Gregory Chamberlain wrote:
Next
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/22751/mbox | git am -3
Learn more about email & git
View this thread in the archives

[PATCH] Add syntax coloring for Gemini markup via `awk` Export this patch

Peter Marinov
* Requires GNU Awk

* To try quickly inside the repo:
  $ cat README.gmi | gawk -f gmi_color.awk

* This commit DOESN'T change the `make install` procedure, it is not
  clear what is a suitable location for the file gmi_color.awk
---
 README.gmi    |  1 +
 README.md     |  1 +
 gmi           |  4 +--
 gmi_color.awk | 86 +++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 90 insertions(+), 2 deletions(-)
 create mode 100644 gmi_color.awk

diff --git a/README.gmi b/README.gmi
index 3599001..82515cb 100644
--- a/README.gmi
+++ b/README.gmi
@@ -11,6 +11,7 @@ Tiny Gemini browser written in POSIX-compliant shell.
* less
* fzf
* xdg-open (for following non-Gemini links)
* GNU Awk

## Installation

diff --git a/README.md b/README.md
index 79a0257..c44f2f3 100644
--- a/README.md
+++ b/README.md
@@ -11,6 +11,7 @@ Tiny Gemini browser written in POSIX-compliant shell.
* less
* fzf
* xdg-open (for following non-Gemini links)
* GNU Awk

## Installation

diff --git a/gmi b/gmi
index a28275c..aab3ee5 100755
--- a/gmi
+++ b/gmi
@@ -75,8 +75,8 @@ main() {
            case $mimetype in
                text/*)
                    printf %s "$body" |
                        iconv -f "$charset" |
                        less -Ps"$(printf %s "$uri" | sed 's/\./\\./g')"
                        iconv -f "$charset" | gawk -f gmi_color.awk |
                        less --raw -Ps"$(printf %s "$uri" | sed 's/\./\\./g')"
                    {
                        [ "$2" ] && printf '<= %s Back\n' "$2"
                        printf '=> .. Up\n'
diff --git a/gmi_color.awk b/gmi_color.awk
new file mode 100644
index 0000000..d4b0c9c
--- /dev/null
+++ b/gmi_color.awk
@@ -0,0 +1,86 @@
# gmi_color.awk
#
# Markup highlighting of Gemini pages for ANSI terminal
#
# IMPORTANT:
# It uses GNU Awk syntax, it won't work with mawk for example

func print_folded(long_line, prefix) {
  # Split words into an array
  split(long_line, list_of_words)

  line_len = 0
  for(i in list_of_words) {
    # 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
}

# URL
match($0, /^(=>) ([^ \t]+).(.*)/, arr) {
  if (code_section == 0)
  {
    print "\033[0;36m" arr[1], arr[2] "\033[0;35m,\n\t\033[1m", arr[3] "\033[0m"
    next
  }
}

# Quote
match($0, /^>(.*)/, arr) {
  if (code_section == 0)
  {
    printf("\033[0;34m")
    print_folded(arr[1], "> ")
    printf("\033[0m")
    next
  }
}

# Code section
/^```/ {
  if (code_section == 0)
      # Activate color for code section
      print "\033[0;32m```"
  else
      # Remove color at the end of the code section
      print "```\033[0m"
  code_section = 1 - code_section
  next
}

# Heading
/^#.*/ {
  if (code_section == 0)
  {
    print "\033[0m\033[1m" $0 "\033[0m"
    next
  }
}

# Everything else -- the plain text of the file
{
  # Outaide code sections: Wrap long lines, print short lines and as-is
  if (code_section == 0)
    print_folded($0, "\033[0m")
  else
    print("\033[0;32m" $0)
}
-- 
2.25.1
This is really cool.  Thanks for sharing!  In the interest of
portability and customisability, I'd like to make this feature
optional.  I have an idea for how to achieve this fairly tidily, but
I'll explain it later in this message.

Last night I rewrote gmi, almost from scratch, with the help of various
caffeinated beverages.  I hope to publish the results as soon as I get
it cleaned up.  It will be the same in spirit but more robust.

This was part of an effort to fix a number of issues, not least of
which was a bug where downloads of binary files, such as images, became
corrupt on disk.  I discovered this was due to the shell's command
substition deleting null bytes in the body.  So that's fixed in this
new, rewritten version which I'll push to the repo soon.

Anyway, here's my idea: we write a separate program -- a pager
specifically designed for text/gemini -- that invokes less(1) but with
your gmi_color.awk as a kind-of preprocessor.  Then we patch gmi to
optionally use any pager the user desires, perhaps via an environment
variable like PAGER or GMI_PAGER.  What do you think?

Greg.