bopher-ng

A better Gopher client in pure Bash
git clone git://git.luxferre.top/bopher-ng.git
Log | Files | Refs | README | LICENSE

commit aa3a2522037842c627b4e994fb8c42b549b37b72
parent f9a9be171c97c0b1386949602c9ebf83b735b6b7
Author: Luxferre <lux@ferre>
Date:   Mon,  3 Apr 2023 19:14:01 +0300

Added list2map.sh tool

Diffstat:
Mtools/README-tools.md | 28+++++++++++++++++++++++++++-
Atools/list2map.sh | 35+++++++++++++++++++++++++++++++++++
2 files changed, 62 insertions(+), 1 deletion(-)

diff --git a/tools/README-tools.md b/tools/README-tools.md @@ -2,7 +2,7 @@ Bopher Tools is a small collection of simple shell scripts that: -- are written in pure Bash with no external dependencies; +- are written in pure Bash with no external dependencies (unless explicitly stated otherwise); - are totally independent from each other (but can be combined in the true spirit of Unix philosophy); - only accept input from stdin and only output their results into stdout; - aim to ease your life when it comes to creating and publishing your own content in Gopherspace. @@ -133,3 +133,29 @@ When running `cat example.gmi | bash gmi2txt.sh 67 5`, this file translates to t See ya! ``` + +## `list2map.sh` + +This tool, which probably is the smallest but the most sophisticated one in the entire collection, accepts the list of files and directories (possibly generated with `find` command) and generates, line by line, a portion of Gophermap based on their type (for this, it requires the external `file` command dependency), root directory name and hostname/port number optionally passed to the script on invocation. The tool automatically applies the following rules: + +- only the basename part of the file/directory is used as the entry name/description; +- if the file is a directory (MIME type `inode/directory`), the generated selector will actually refer to the `index.map` file in that directory and the entry type will be 1; +- files (or directories) named `index.map` are not themselves included in the output; +- if the file's MIME type starts with `text`, the entry type will be set to 0, otherwise it will be set to 9. + +Note that the tool itself doesn't do any filtering on input names or how they are presented. All filtering, if necessary, should be done on the `find` invocation step. + +Example - build a Gophermap fragment from this repo's starting directory, excluding all dotfiles, using `.` as root and assuming we'll serve this map from `example.com:777`: +``` +$ find . ! -path '.' ! -path '*/.*' | bash tools/list2map.sh . example.com 777 +0COPYING /COPYING example.com 777 +1tools /tools/index.map example.com 777 +0gopherinfo.sh /tools/gopherinfo.sh example.com 777 +0phlow.sh /tools/phlow.sh example.com 777 +0gmi2map.sh /tools/gmi2map.sh example.com 777 +0gmi2txt.sh /tools/gmi2txt.sh example.com 777 +0README-tools.md /tools/README-tools.md example.com 777 +0list2map.sh /tools/list2map.sh example.com 777 +0bopher-ng.sh /bopher-ng.sh example.com 777 +0README.md /README.md example.com 777 +``` diff --git a/tools/list2map.sh b/tools/list2map.sh @@ -0,0 +1,35 @@ +#!/bin/bash +# A simple tool for Gophermap fragment generation from existing file/directory lists +# Depends on file external command to determine the type +# +# Usage: find [root] [params] | list2map.sh +# +# Created by Luxferre in 2023, released into public domain + +shopt -s extglob # enable extended pattern matching (just to be sure) + +RDIR="$1" # root directory, no substitution if empty +THOST="$2" # can be empty per spec +TPORT="$3" # can be empty too +INDEXFILE='index.map' # the basename to consider an index file + +typequery() { # external command wrapper to fetch the file's MIME type + local res="$(file -Nn --mime-type "$1")" + printf '%s' "${res##*: }" +} + +while read -rs fpath; do # fully line-based operation + ftype="$(typequery "$fpath")" # MIME type here + bname="${fpath##*/}" # basename here + [[ "$bname" == "$INDEXFILE" ]] && continue # skip index map + etype=9 # default map entry type is binary until proven otherwise + esel="${fpath##$RDIR}" # if RDIR is empty, they are the same + if [[ "$ftype" == 'inode/directory' ]]; then # it's a directory + etype=1 + esel="${esel}/${INDEXFILE}" # update the selector + elif [[ "${ftype%%/*}" == 'text' ]]; then # update etype for text files + etype=0 + fi + # output the RFC-compliant Gophermap line + printf '%s%s\t%s\t%s\t%s\r\n' "$etype" "$bname" "$esel" "$THOST" "$TPORT" +done