M tools/README-tools.md => tools/README-tools.md +27 -1
@@ 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
+```
A tools/list2map.sh => tools/list2map.sh +35 -0
@@ 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