URI: 
       Add an experimental indexer similar to stagit-gopher-index - stahg-gopher - Static Mercurial page generator for gopher
  HTML hg clone https://bitbucket.org/iamleot/stahg-gopher
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
   DIR changeset 5a0937d0d603b626e3def7ae5bcd9025cb0c0c4c
   DIR parent ed1ce8cb40899fbf91ae58ed9e2e1c20709a8850
  HTML Author: Leonardo Taccari <iamleot@gmail.com>
       Date:   Mon, 13 May 2019 21:41:38 
       
       Add an experimental indexer similar to stagit-gopher-index
       
       Parse <stagit-dir>/<stahg-dir> log.gph and generate an index similar
       to stagit-gopher-index.
       
       Still experimental!
       
       Diffstat:
        sta-log-gopher-index.py |  99 +++++++++++++++++++++++++++++++++++++++++++++++++
        1 files changed, 99 insertions(+), 0 deletions(-)
       ---
       diff -r ed1ce8cb4089 -r 5a0937d0d603 sta-log-gopher-index.py
       --- /dev/null   Thu Jan 01 00:00:00 1970 +0000
       +++ b/sta-log-gopher-index.py   Mon May 13 21:41:38 2019 +0200
       @@ -0,0 +1,99 @@
       +#!/usr/bin/env python3.7
       +
       +#
       +# Copyright (c) 2019 Leonardo Taccari
       +# All rights reserved.
       +# 
       +# Redistribution and use in source and binary forms, with or without
       +# modification, are permitted provided that the following conditions
       +# are met:
       +# 
       +# 1. Redistributions of source code must retain the above copyright
       +#    notice, this list of conditions and the following disclaimer.
       +# 2. Redistributions in binary form must reproduce the above copyright
       +#    notice, this list of conditions and the following disclaimer in the
       +#    documentation and/or other materials provided with the distribution.
       +# 
       +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
       +# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
       +# TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
       +# PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS
       +# BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
       +# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
       +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
       +# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
       +# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
       +# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
       +# POSSIBILITY OF SUCH DAMAGE.
       +#
       +
       +
       +import re
       +import os
       +
       +
       +def gph_escape_entry(text):
       +    """Render text entry `[...]' by escaping/translating characters"""
       +    escaped_text = text.expandtabs().replace('|', '\|')
       +
       +    return escaped_text
       +
       +
       +def shorten(text, n=80):
       +    """Shorten text to the first `n' character of first line"""
       +    s, _, _ = text.partition('\n')
       +
       +    if len(s) > n:
       +        s = s[:n - 1] + '…'
       +
       +    return s
       +
       +if __name__ == '__main__':
       +    import getopt
       +    import sys
       +
       +    def usage():
       +        print('usage: {} [-b baseprefix] stagit-dir|stahg-dir ...'.format(
       +               sys.argv[0]))
       +        exit(1)
       +
       +    try:
       +        opts, args = getopt.getopt(sys.argv[1:], 'b:')
       +    except:
       +        usage()
       +
       +    if len(args) == 0:
       +        usage()
       +
       +    base_prefix = ''
       +    limit = None
       +    for o, a in opts:
       +        if o == '-b':
       +            base_prefix = a
       +
       +    print('{:20}  {:40}  {}'.format('Name', 'Description', 'Last commit'))
       +    for sd in args:
       +        repo = description = date = ''
       +        repo = os.path.basename(os.path.normpath(sd))
       +        with open(os.path.join(sd, 'log.gph')) as f:
       +            for l in f:
       +                if not description and 'Log - ' in l:
       +                    description = l.split(' - ', maxsplit=2)[-1]
       +                    description = description.strip()
       +                # XXX: simplify that
       +                elif re.match('^\[1\|[0-9]+-[0-9]+-[0-9]+ [0-9]+:[0-9]+', l):
       +                    r = re.match('^\[1\|([0-9]+-[0-9]+-[0-9]+ [0-9]+:[0-9]+)', l)
       +                    date = r.group(1)
       +                    f.close()
       +                    break
       +
       +        if repo and description and date:
       +            print('[1|{desc}|{path}|server|port]'.format(
       +                desc=gph_escape_entry(
       +                    '{repo:20}  {description:40}  {date}'.format(
       +                        repo=repo,
       +                        description=shorten(description, 40),
       +                        date=date)),
       +                path='{base_path}{repo}'.format(
       +                    base_path=base_prefix,
       +                    repo=repo)))