920 lines
34 KiB
Plaintext
920 lines
34 KiB
Plaintext
|
#!/bin/sh
|
||
|
|
||
|
VERSION=2.0-rc1
|
||
|
|
||
|
if [ ! "$EDITOR" ]; then
|
||
|
EDITOR=vi
|
||
|
fi
|
||
|
|
||
|
MARGIN=67
|
||
|
FORMAT=html
|
||
|
INDEX=vee.html
|
||
|
DIR=.vee
|
||
|
DRAFT="$DIR/.vee.tmp.$$"
|
||
|
USE_EDITOR=1
|
||
|
LISTENSTDIN=0
|
||
|
_CUSTOM_UMASK= # use -U to force to 0022 or -u to set something during post
|
||
|
PUBLISHED=$(date "+%m/%d/%Y") # date formated for index page entry
|
||
|
SORT_NEWEST="sort -t. -nr" # sorts all new to old
|
||
|
SORT_OLDEST="sort -t. -n" # sorts all old to new
|
||
|
RAWEXT=raw # default .raw (non-HTML) files, can change to .txt or something else in .veerc
|
||
|
# also used for updating $GOPHERMAP when $GOPHERMODE is 1 (-g) or 2 (-G)
|
||
|
DATE=$(date)
|
||
|
YEAR=$(date "+%Y")
|
||
|
TIME=$(date "+%Y-%m-%dT%H:%M:%S")
|
||
|
SEC=$(date "+%s")
|
||
|
TITLE=
|
||
|
DEFAULT_TITLE="Entry #$SEC (pid: $$)";
|
||
|
HEADERTXT= # text or $(cat some.header.txt)
|
||
|
FOOTERTXT="Powered by vee<br/>Copyright © 2006-$YEAR"
|
||
|
TOP_TPL=./vee-top.tpl # if file exists, used to generate top of HTML post by OUTPUT_TOP func
|
||
|
BOT_TPL=./vee-bottom.tpl # if file exists, used to generate bottom of HTML post by OUTPUT_BOT func
|
||
|
OUTPUT_TOP=output_top # default template processor, uses TOP_TPL
|
||
|
OUTPUT_BOT=output_bottom # default template processor, use s BOT_TPL
|
||
|
|
||
|
# PRE/POST Format Hooks; used in both HTML and Gopher modes; to differentiate, $1 is always
|
||
|
# going to be 'html' or 'gopher'
|
||
|
PREFORMAT_HOOK=./vee-pre # the hook is assumed to be executable, else it is ignored
|
||
|
POSTFORMAT_HOOK=./vee-post # the hook is assumed to be executable, esle it is ignored
|
||
|
|
||
|
# Gopher defaults
|
||
|
GOPHERMODE=0 # -g set it to 1, -G sets it to 2; set in .veerc to skip always typing -g or -G
|
||
|
GOPHER_FORMAT=txt # extension for files linked in gophermap
|
||
|
GOPHERMAP=gophermap # pretty standard, so low chance of this needing to be changed
|
||
|
OUTPUT_TOP_GOPHER= # may define a top "template" function for gopher posts
|
||
|
OUTPUT_BOT_GOPHER= # may define a bottom "template" function for gopher posts
|
||
|
# gophermap header text and footer text - sorry didn't separate them out like was done
|
||
|
# for the HTML support (but these can be customized in a .veerc!)
|
||
|
GOPHERMAP_HEADER="Welcome to my Gophertunnel!"
|
||
|
GOPHERMAP_FOOTER="Carl Spackler: [preparing to dynamite the gopher tunnel] In the immortal words of Jean Paul Sartre, Au revoir, gopher."
|
||
|
|
||
|
guess_arch()
|
||
|
{ case $(uname) in
|
||
|
Linux) ARCH='linux'
|
||
|
;;
|
||
|
FreeBSD) ARCH='freebsd'
|
||
|
;;
|
||
|
NetBSD) ARCH='netbsd'
|
||
|
;;
|
||
|
Darwin) ARCH='macosx'
|
||
|
;;
|
||
|
*) ARCH='unknown'
|
||
|
;;
|
||
|
esac
|
||
|
}
|
||
|
|
||
|
ARCH='unknown'
|
||
|
guess_arch
|
||
|
|
||
|
# define custom formatting define custom functions file; see example in # vee/sample-custom-format/vee-custom.sh
|
||
|
FORMAT_FUNC=format_with_groff
|
||
|
FORMAT_DISPATCHER=default_set_format_func
|
||
|
FORMAT_CUSTOM_DISPATCHER=custom_set_format_func
|
||
|
FORMAT_CUSTOM_DEFS=./vee-custom.sh # path is relative to -d DIR, where .veerc resides
|
||
|
|
||
|
UPDATE_INDEX=default_update_index
|
||
|
CUSTOM_SETUP=default_setup
|
||
|
|
||
|
#
|
||
|
# vee is a zero configuration, commandline blog tool that
|
||
|
# requires NO installation other than dropping the vee
|
||
|
# script into your ~/bin, or someother directory in your PATH
|
||
|
#
|
||
|
# vee accepts input when in batch mode (-b), so it is well
|
||
|
# suited for use in batch situations, such as in a cronjob
|
||
|
#
|
||
|
|
||
|
# System utilities required via PATH:
|
||
|
# cat, cd, date, env, find, fmt, fold, grep, groff,
|
||
|
# head, ls, pwd, sort, tail, which
|
||
|
#
|
||
|
# vee provided utilities that must also be in PATH:
|
||
|
# vee (duh!), veels, veecat
|
||
|
#
|
||
|
|
||
|
disclaimer()
|
||
|
{ echo "Copyright (c) 2007-infinity /me"
|
||
|
echo "Permission is hereby granted, free of charge, to any person"
|
||
|
echo "obtaining a copy of this software and associated documentation"
|
||
|
echo "files (the \"Software\"), to deal in the Software without"
|
||
|
echo "restriction, including without limitation the rights to use,"
|
||
|
echo "copy, modify, merge, publish, distribute, sublicense, and/or"
|
||
|
echo "sell copies of the Software, and to permit persons to whom the"
|
||
|
echo "Software is furnished to do so, subject to the following"
|
||
|
echo "conditions:"
|
||
|
echo "The above copyright notice and this permission notice shall be"
|
||
|
echo "included in all copies or substantial portions of the Software."
|
||
|
echo "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY"
|
||
|
echo "KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE"
|
||
|
echo "WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE"
|
||
|
echo "AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT"
|
||
|
echo "HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,"
|
||
|
echo "WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING"
|
||
|
echo "FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR"
|
||
|
echo "OTHER DEALINGS IN THE SOFTWARE."
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# vee - the minimal, zero configuration command line blog thingy
|
||
|
#
|
||
|
# Contact (bugs, patches, suggestions)
|
||
|
# https://git.sdf.org/pifty/phlea/issues
|
||
|
#
|
||
|
# Instructions:
|
||
|
# 1. put in directory accessible via PATH
|
||
|
# 2. go to a web visible directory and type 'vee'
|
||
|
# 3. put in your title and write your post in vi
|
||
|
# 4. tell your mom to visit: http://..../yourdir/vee.html
|
||
|
# 5. tell your gen Z nephew to visit your gopherhole :E
|
||
|
#
|
||
|
# Tips:
|
||
|
#
|
||
|
# 1 You can force the index to be index.html using "-I", or
|
||
|
# you can specify the index with "-i somefile.html". But,
|
||
|
# if you do this, you'll have to specify this for all other
|
||
|
# commands, otherwise vee defaults to vee.html
|
||
|
#
|
||
|
# 2 vee respects your EDITOR environmental variable
|
||
|
#
|
||
|
# 3 What you do with vee.html or the formatting is up to you :)
|
||
|
#
|
||
|
# 4 Gopher support (-g|-G) may be lacking some parity with http/s
|
||
|
# support, but with feedback this can be fixed and go well beyond
|
||
|
#
|
||
|
|
||
|
# CREDITS
|
||
|
# Francois Saint-Jacques (fsaintjacques@networkdump.com) supplied 2nd patch ever :)
|
||
|
# efbeha (efbeha@gmail.com) - supplied first patch ever :)
|
||
|
# Oliver @ forums.bsdnexus.com
|
||
|
# arun @ chat.taucher.net #bsd
|
||
|
# J65nko @ bsdforums.com
|
||
|
|
||
|
default_set_format_func()
|
||
|
{ case $1 in
|
||
|
default) FORMAT_FUNC=format_with_groff
|
||
|
;;
|
||
|
groff) FORMAT_FUNC=format_with_groff
|
||
|
;;
|
||
|
fold) FORMAT_FUNC=format_with_fold
|
||
|
;;
|
||
|
fmt) FORMAT_FUNC=format_with_fmt
|
||
|
;;
|
||
|
none) FORMAT_FUNC=with_no_formatting
|
||
|
;;
|
||
|
# if not a supplied format, see if it is in the custom format file, if it exists
|
||
|
*) if [ -e "$FORMAT_CUSTOM_DEFS" ]; then
|
||
|
# call dispatch function that is defined in
|
||
|
# the custom format file, pass on format nickname
|
||
|
$FORMAT_CUSTOM_DISPATCHER "$1"
|
||
|
else
|
||
|
echo "bad format type"
|
||
|
die_cleanly
|
||
|
fi
|
||
|
esac
|
||
|
}
|
||
|
|
||
|
usage()
|
||
|
{ echo " "
|
||
|
echo " "
|
||
|
echo " .----------------. .----------------. .----------------. "
|
||
|
echo " | .--------------. || .--------------. || .--------------. | "
|
||
|
echo " | | ____ ____ | || | _________ | || | _________ | | "
|
||
|
echo " | ||_ _| |_ _| | || | |_ ___ | | || | |_ ___ | | | "
|
||
|
echo " | | \ \ / / | || | | |_ \_| | || | | |_ \_| | | "
|
||
|
echo " | | \ \ / / | || | | _| _ | || | | _| _ | | "
|
||
|
echo " | | \ ' / | || | _| |___/ | | || | _| |___/ | | | "
|
||
|
echo " | | \_/ | || | |_________| | || | |_________| | | "
|
||
|
echo " | | | || | | || | | | "
|
||
|
echo " | '--------------' || '--------------' || '--------------' | "
|
||
|
echo " '----------------' '----------------' '----------------' "
|
||
|
echo " the Zero-conf, commandline blog tool thingy "
|
||
|
echo " .... now with GopherMode! ("gopherlog" support) "
|
||
|
echo " (see -g|-G) "
|
||
|
echo " "
|
||
|
echo "Version: $VERSION "
|
||
|
echo " "
|
||
|
echo "Options: "
|
||
|
echo " -b Batch mode; used when piping in msg via stdin "
|
||
|
echo " -B file Define bottom template; default is ./vee-bottom.tpl "
|
||
|
echo " -c [1-9\d*] Specify the number of characters 'fold' allows per line "
|
||
|
echo " this only applies when 'fold' (-f) is used "
|
||
|
echo " -d 'publis_dir' Specify the directory .vee is in - defaults to PWD "
|
||
|
echo " -D Debug mode with, set -x "
|
||
|
echo " -f 'format' Option for setting formatinstead of the default, groff; "
|
||
|
echo " 'groff', 'fmt', 'fold', and 'none' are all supported "
|
||
|
echo " -g Update the gophermap file with the INDEX "
|
||
|
echo " -G Exclusively update the gophermap file rather than INDEX "
|
||
|
echo " Note: for -g|-G, the gophermap is merely appended to, there"
|
||
|
echo " is no maintaining of the order from newest first to last; "
|
||
|
echo " -g|-G will create the gophermap if it isn't found. "
|
||
|
echo " -h Prints this blurb "
|
||
|
echo " -i 'custom.html' Specify a custom index file over the default "
|
||
|
echo " -I force index file to be \"index.html\" "
|
||
|
echo " -l edit latest post's *.raw; used with '-r' publishes changes;"
|
||
|
echo " calls reformat automatically; "
|
||
|
echo " -L [1-9\d*] edit the Nth latest, relative to last post; lp starts at 1"
|
||
|
echo " -m 'message ...' Epecify entry message at commandline and avoid vi "
|
||
|
echo " -n Lists all entries, newest first, then quits "
|
||
|
echo " -o Lists all entries, oldest first, then quits "
|
||
|
echo " -p See what *raw files don't have an entry in the INDEX "
|
||
|
echo " -P Forever deletes all *raw and formatted files associated with"
|
||
|
echo " posts that are listed with -p; "
|
||
|
echo " -r [1-9\d*] Reformats the Nth latest post "
|
||
|
echo " -R reformats _all_ .vee/*.raw files; -c applies as well "
|
||
|
echo " -s 'summary' Placed below title in INDEX "
|
||
|
echo " -t 'title' Specify title at commandline and avoid annoying default prompt"
|
||
|
echo " -T file Define top template; default is ./vee-top.tpl "
|
||
|
echo " -u <octal> Temporarily set umask to <octal> "
|
||
|
echo " -U Temporarily set umask to 0022 "
|
||
|
echo " -v Version and exit "
|
||
|
echo " -x hook Defines hook if not using default "./vee-pre"; hook "
|
||
|
echo " must be executable, i.e., chmod 755 vee-pre "
|
||
|
echo " "
|
||
|
echo "Examples: "
|
||
|
echo " "
|
||
|
echo "%vee "
|
||
|
echo " "
|
||
|
echo " user will be prompted for title and presented with vi "
|
||
|
echo " "
|
||
|
echo " if no default dir/files are found, they will be created "
|
||
|
echo " "
|
||
|
echo "%vee -t \"this is the title\" "
|
||
|
echo " "
|
||
|
echo " user will just be presented with a vi session; "
|
||
|
echo " "
|
||
|
echo "%cat text.txt | vee -b -t \"my title\" -m \"text to go before stdin\" "
|
||
|
echo " "
|
||
|
echo " This publishes contents of text.txt with provided title; -m's msg will be "
|
||
|
echo " shown above the cat'd text. This means of publishing content is well suited "
|
||
|
echo " for use with cronjobs or batch processes. It also works when GopherMode! is "
|
||
|
echo " invoked (-g|-G). "
|
||
|
echo " "
|
||
|
echo "%vee -l # edit and reformat the latest post "
|
||
|
echo "%vee -L 5 # allows one to edit and reformats the fifth latest post "
|
||
|
echo "%vee -r 8 # reformats the 8th latest post "
|
||
|
echo "%vee -n # see which post is the 8th latest post "
|
||
|
echo "%vee -R # reformats ALL posts that have *.raw files "
|
||
|
echo " "
|
||
|
echo "To delete a post forever: "
|
||
|
echo " "
|
||
|
echo "1) delete the entry in the INDEX "
|
||
|
echo " "
|
||
|
echo "2) purge the entry: "
|
||
|
echo " %vee -p # make sure it is the one you want to purge "
|
||
|
echo " %vee -P # purge it! "
|
||
|
echo " "
|
||
|
echo " brings up the latest entry as a vi sessions; when changes are save, "
|
||
|
echo " all messages are reformatted "
|
||
|
echo " "
|
||
|
echo " :E We Need to Talk About Gopher Support :E "
|
||
|
echo " "
|
||
|
echo "vee supports the creation of content in the gophersphere by formatting text-only"
|
||
|
echo "posts using the provided formatters (meant for text-only anyway). vee also goes"
|
||
|
echo "a step further and generates the gophermap (index listing) for you. "
|
||
|
echo " "
|
||
|
echo "All of the vee commands immediately above *should* work when GopherMode! is on"
|
||
|
echo "which is as simple as adding the -g xor -G flags. -g invokes the Gopher bits "
|
||
|
echo "*and* the default www support. -G only invokes the Gopher bits. Not using -g "
|
||
|
echo " or -G only involes the traditional www support. "
|
||
|
echo " "
|
||
|
echo "Usage examples from above, with GopherMode! enabled: "
|
||
|
echo " "
|
||
|
echo "%vee -l -G # edit and reformat the latest post "
|
||
|
echo "%vee -L 5 -g # allows one to edit and reformats the fifth latest post "
|
||
|
echo "%vee -r 8 -G # reformats the 8th latest post "
|
||
|
echo "%vee -n # see which post is the 8th latest post "
|
||
|
echo "%vee -R -g # reformats ALL posts that have *.raw files "
|
||
|
echo " "
|
||
|
echo "Notes: "
|
||
|
echo " "
|
||
|
echo "0. Reminder - vee requires zero configurations to start, but *can* be coed "
|
||
|
echo " by creating a .veerc file. This is also the case when in GopherGeb!Mode "
|
||
|
echo " "
|
||
|
echo "1. Batch mode looks for piped input via STDIN; if none after a short time, "
|
||
|
echo " message creation fails UNLESS something was passed in via '-m' as well. "
|
||
|
echo " If nothing was passed in via '-t' for the title, some default is used; "
|
||
|
echo " This is set at the top of the script as 'DEFAULT_TITLE'. "
|
||
|
echo " "
|
||
|
echo "2. Interactive mode (default) prompts for a title if no '-t' is provided. "
|
||
|
echo " Such is the case even if '-m' is used. If '-m' is not used in this "
|
||
|
echo " "
|
||
|
echo "3. Gopher support (-g|-G) is limited and users may discover weird issues with "
|
||
|
echo " updating posts or the batch reformatting options. It's a best effort. Also "
|
||
|
echo " the gophermap is fully regenerated whenever a new post is added; for a large"
|
||
|
echo " number of posts this may take a few seconds. "
|
||
|
echo " "
|
||
|
echo "4. Patches are welcome; the goal is not more feature bloat, but a nicer "
|
||
|
echo " way of dealing with STDIN, etc and reports/fixes for any weird gopher phlog"
|
||
|
echo " bugs or UX would be greatly welcomed. vee development laid dormant for years,"
|
||
|
echo " being used as a niche static site generator. But the rediscovery of Gopher "
|
||
|
echo " by the masses has made adding Gopher support a high priority. "
|
||
|
echo " "
|
||
|
disclaimer
|
||
|
exit 1
|
||
|
}
|
||
|
|
||
|
default_update_html_index()
|
||
|
{ echo "<!-- ;$SEC; -->$PUBLISHED:<a href=\"$1\"> $3</a>" >> $INDEX
|
||
|
if [ -n "$SUMMARY" ]; then
|
||
|
SEC=$(expr "$SEC" - 1)
|
||
|
echo "<!-- ;$SEC; -->$SUMMARY" >> "$INDEX"
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
default_update_gophermap()
|
||
|
{ # rebuild the entire $GOPHERMAP
|
||
|
# toggle IFS if in -b mode
|
||
|
if [ 1 -eq $LISTENSTDIN ]; then
|
||
|
_OLDIFS=$IFS
|
||
|
IFS=$OLDIFS
|
||
|
fi
|
||
|
if [ -e $GOPHERMAP ]; then
|
||
|
echo Found existing $GOPHERMAP, renaming to $GOPHERMAP.bkp
|
||
|
mv $GOPHERMAP $GOPHERMAP.bkp #(be nice, just move to the side)
|
||
|
fi
|
||
|
default_setup_gophermap # initialize gophermap
|
||
|
for f in $(veels -d "$DIR" -e "$GOPHER_FORMAT"); do
|
||
|
_RAW=$(echo $f | sed 's/$GOPHER_FORMAT/$RAWEXT/')
|
||
|
_TITLE=$(echo $_RAW | veecat -t)
|
||
|
_DATE=$(echo $_RAW | veecat -d | awk '{print $3 " " $2 " " $6}') #e.g., Fri May 29 09:02:12 UTC 2020
|
||
|
# creating a symlink to $DIR because the default $DIR
|
||
|
# starts with a '.' and the gopher server seems to not
|
||
|
# want to serve files in such a directory
|
||
|
fileLink=$(echo $f | sed "s/$DIR/phlogsrc/")
|
||
|
# seems relative paths can't be directories that start
|
||
|
# with a dot (e.g., ".vee")
|
||
|
ln -s $DIR phlogsrc > /dev/null 2>&1 # rather than check if link exists, just try it and hide error
|
||
|
printf "0[$_DATE] $_TITLE\t$fileLink\n" >> $GOPHERMAP
|
||
|
done
|
||
|
echo >> $GOPHERMAP
|
||
|
echo >> $GOPHERMAP
|
||
|
echo $GOPHERMAP_FOOTER | fmt -w 67 >> $GOPHERMAP
|
||
|
echo >> $GOPHERMAP
|
||
|
echo >> $GOPHERMAP
|
||
|
echo Generated with vee. >> $GOPHERMAP
|
||
|
# toggle IFS back if temporarily set to interactive IFS above
|
||
|
if [ 1 -eq $LISTENSTDIN ]; then
|
||
|
IFS=$_OLDIFS
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
#"$FINAL" "$gFINAL" "$RAW" "$gRAW" "$TITLE"
|
||
|
default_update_index()
|
||
|
{
|
||
|
if [ 2 != $GOPHERMODE ]; then
|
||
|
default_update_html_index "$1" "$3" "$5"
|
||
|
fi
|
||
|
if [ 0 != $GOPHERMODE ]; then
|
||
|
default_update_gophermap "$2" "$4" "$5"
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
output_top()
|
||
|
{ echo "$HEADERTXT" > "$FINAL"
|
||
|
if [ -e "$TOP_TPL" ]; then
|
||
|
cat "$TOP_TPL" >> "$FINAL"
|
||
|
else
|
||
|
echo "<!-- <?xml version=\"1.0\" encoding=\"UTF-8\" ?> --><!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"><html xmlns=\"http://www.w3.org/1999/xhtml\">" >> "$FINAL"
|
||
|
echo "<meta http-equiv=\"Content-Type\" CONTENT=\"text/html; charset=UTF-8\">" >> "$FINAL"
|
||
|
echo " <head><title>$TITLE - $DATE</title></head>" >> "$FINAL"
|
||
|
echo " <body>" >> "$FINAL"
|
||
|
echo " <pre>" >> "$FINAL"
|
||
|
echo "<a href=\"../$INDEX\">[index]</a><a href=\"./$RAWNAME\">[raw]</a><a href=\"../\">[main]</a>" >> "$FINAL"
|
||
|
fi
|
||
|
echo >> "$FINAL"
|
||
|
}
|
||
|
|
||
|
output_bottom()
|
||
|
{ echo >> "$FINAL"
|
||
|
echo -- >> "$FINAL"
|
||
|
echo "$FOOTERTXT" >> "$FINAL"
|
||
|
if [ -e "$BOT_TPL" ]; then
|
||
|
cat "$BOT_TPL" >> "$FINAL"
|
||
|
else
|
||
|
echo " </pre>" >> "$FINAL"
|
||
|
echo " </body>" >> "$FINAL"
|
||
|
echo "</html>" >> "$FINAL"
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
# begin formatting funcs
|
||
|
|
||
|
format_with_groff()
|
||
|
{ #sed 1liner from http://sed.sourceforge.net/sed1line.txt
|
||
|
if [ "html" = "$_OUTPUT_TYPE" ]; then
|
||
|
groff -man -Tascii "$RAW" > $$.tmp.$RAWEXT
|
||
|
sed '/^$/N;/\n$/D' < $$.tmp.$RAWEXT > $$.tmp.final
|
||
|
cat $$.tmp.final >> "$FINAL"
|
||
|
fi
|
||
|
if [ "gopher" = "$_OUTPUT_TYPE" ]; then
|
||
|
groff -man -Tascii "$gRAW" > $$.tmp.$RAWEXT
|
||
|
sed '/^$/N;/\n$/D' < $$.tmp.$RAWEXT > $$.tmp.final
|
||
|
cat $$.tmp.final > "$gFINAL"
|
||
|
fi
|
||
|
rm $$.tmp.$RAWEXT $$.tmp.final
|
||
|
}
|
||
|
|
||
|
format_with_fmt()
|
||
|
{ if [ 0 -lt $MARGIN ]; then
|
||
|
if [ "html" = $_OUTPUT_TYPE ]; then
|
||
|
fmt -w $MARGIN "$RAW" > $$.tmp.$RAWEXT
|
||
|
cat $$.tmp.$RAWEXT >> "$FINAL"
|
||
|
fi
|
||
|
if [ "gopher" = $_OUTPUT_TYPE ]; then
|
||
|
fmt -w $MARGIN "$gRAW" > $$.tmp.$RAWEXT
|
||
|
cat $$.tmp.$RAWEXT > "$gFINAL"
|
||
|
fi
|
||
|
rm $$.tmp.$RAWEXT
|
||
|
else
|
||
|
with_no_formatting
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
format_with_fold()
|
||
|
{ if [ 0 -lt $MARGIN ]; then
|
||
|
if [ "html" = $_OUTPUT_TYPE ]; then
|
||
|
fold -s -w $MARGIN "$RAW" > $$.tmp.$RAWEXT
|
||
|
cat $$.tmp.$RAWEXT >> "$FINAL"
|
||
|
fi
|
||
|
if [ "gopher" = $_OUTPUT_TYPE ]; then
|
||
|
fold -s -w $MARGIN "$gRAW" > $$.tmp.$RAWEXT
|
||
|
cat $$.tmp.$RAWEXT > "$gFINAL"
|
||
|
fi
|
||
|
rm $$.tmp.$RAWEXT
|
||
|
else
|
||
|
with_no_formatting
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
with_no_formatting()
|
||
|
{ if [ "html" = $_OUTPUT_TYPE ]; then
|
||
|
cat "$RAW" >> "$FINAL"
|
||
|
fi
|
||
|
if [ "gopher" = $_OUTPUT_TYPE ]; then
|
||
|
cat "$gRAW" > "$gFINAL"
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# preformat hook has been changed to NOT be a filter;
|
||
|
#
|
||
|
# $1 is 'html' or 'gopher'
|
||
|
#
|
||
|
preformat()
|
||
|
{ if [ -x "$PREFORMAT_HOOK" ]; then
|
||
|
"$PREFORMAT_HOOK" "$1"
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
#
|
||
|
# this hook is for any things to do after the post; a good example for use
|
||
|
# would be to integrate git or another SCM; another is a notification script
|
||
|
#
|
||
|
# $1 is 'html' or 'gopher'
|
||
|
#
|
||
|
postformat()
|
||
|
{ if [ -x "$POSTFORMAT_HOOK" ]; then
|
||
|
"$POSTFORMAT_HOOK" "$1"
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
# dispatches formatting based on $GOPHERMODE; sets $_OUTPUT_TYPE
|
||
|
# for called functions to know for what $_OUTPUT_TYPE they're doing stuff
|
||
|
|
||
|
format_main_html()
|
||
|
{ FINAL=$DIR/$1
|
||
|
FINALNAME=$1
|
||
|
RAW=$DIR/$2
|
||
|
RAWNAME=$2
|
||
|
preformat $_OUTPUT_TYPE # expecting 'html'
|
||
|
if [ ! -e "$RAW" ]; then
|
||
|
echo "$DATE" > "$RAW" # in RAW, line 1 is date
|
||
|
echo >> "$RAW"
|
||
|
echo "$TITLE" >> "$RAW" # in RAW, line 2 is title
|
||
|
echo >> "$RAW"
|
||
|
echo "--" >> "$RAW"
|
||
|
echo >> "$RAW" # this blank line is important
|
||
|
cat "$DRAFT" >> "$RAW"
|
||
|
fi
|
||
|
$OUTPUT_TOP
|
||
|
$FORMAT_FUNC
|
||
|
$OUTPUT_BOT
|
||
|
postformat $_OUTPUT_TYPE # expecting 'html'
|
||
|
}
|
||
|
|
||
|
format_main_gopher()
|
||
|
{ gFINAL=$DIR/$1
|
||
|
gFINALNAME=$1
|
||
|
gRAW=$DIR/$2
|
||
|
gRAWNAME=$2
|
||
|
preformat $_OUTPUT_TYPE # expecting 'gopher'
|
||
|
if [ ! -e "$gRAW" ]; then
|
||
|
echo "$DATE" > "$gRAW" # in gRAW, line 1 is date
|
||
|
echo >> "$gRAW"
|
||
|
echo "$TITLE" >> "$gRAW" # in gRAW, line 2 is title
|
||
|
echo >> "$gRAW"
|
||
|
echo "--" >> "$gRAW"
|
||
|
echo >> "$gRAW" # this blank line is important
|
||
|
cat "$DRAFT" >> "$gRAW"
|
||
|
fi
|
||
|
$OUTPUT_TOP_GOPHER # NOTE: not set by default
|
||
|
$FORMAT_FUNC
|
||
|
$OUTPUT_BOT_GOPHER # NOTE not set by default
|
||
|
postformat $_OUTPUT_TYPE # expecting 'gopher'
|
||
|
}
|
||
|
|
||
|
format_main()
|
||
|
{ if [ 2 != $GOPHERMODE ]; then
|
||
|
_OUTPUT_TYPE=html # tracks formatting type
|
||
|
format_main_html "$1" "$3"
|
||
|
fi
|
||
|
|
||
|
if [ 0 != $GOPHERMODE ]; then
|
||
|
_OUTPUT_TYPE=gopher # tracks formatting type
|
||
|
format_main_gopher "$2" "$3"
|
||
|
fi
|
||
|
_OUTPUT_TYPE=none
|
||
|
}
|
||
|
|
||
|
reformat_singleton()
|
||
|
{ if [ -e "$DIR/$1.$RAWEXT" ]; then
|
||
|
cat "$DIR/$1.$RAWEXT" > "$DRAFT"
|
||
|
format_main "$1.$FORMAT" "$1.$GOPHER_FORMAT" "$1.$RAWEXT"
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
reformat_all()
|
||
|
{
|
||
|
for f in $(veels -d "$DIR" -r); do
|
||
|
# From: Randall R Schulz <rrschulz at cris dot com>
|
||
|
FULLNAME="$f"
|
||
|
DIR=${FULLNAME%/*}
|
||
|
FILE=${FULLNAME##*/}
|
||
|
MAXBASE=${FILE%.*}
|
||
|
MINBASE=${FILE%%.*}
|
||
|
MAXSUF=${FILE#*.}
|
||
|
MINSUF=${FILE##*.}
|
||
|
_TITLE=$(echo $f | veecat -t)
|
||
|
echo "..reformatting '$_TITLE'"
|
||
|
reformat_singleton "$MAXBASE"
|
||
|
done
|
||
|
}
|
||
|
|
||
|
list_newest_first()
|
||
|
{ COUNT=1
|
||
|
for _RAW in $(veels -d "$DIR"); do
|
||
|
_TITLE=$(echo $_RAW | veecat -t)
|
||
|
_DATE=$(echo $_RAW | veecat -d)
|
||
|
printf "%4d) " "$COUNT"
|
||
|
echo $_DATE - $_TITLE
|
||
|
COUNT=$(expr $COUNT + 1)
|
||
|
done
|
||
|
}
|
||
|
|
||
|
list_oldest_first()
|
||
|
{ COUNT=1
|
||
|
for _RAW in $(veels -d "$DIR" -r); do
|
||
|
_TITLE=$(echo $_RAW | veecat -t)
|
||
|
_DATE=$(echo $_RAW | veecat -d)
|
||
|
printf "%4d) " "$COUNT"
|
||
|
echo $_DATE - $_TITLE
|
||
|
COUNT=$(expr $COUNT + 1)
|
||
|
done
|
||
|
}
|
||
|
|
||
|
get_path2post()
|
||
|
{
|
||
|
GOAL=$1
|
||
|
COUNT=1
|
||
|
for FILE in $(veels -d "$DIR"); do
|
||
|
FULLNAME=$FILE
|
||
|
DIR=${FULLNAME%/*}
|
||
|
FILE=${FULLNAME##*/}
|
||
|
MAXBASE=${FILE%.*}
|
||
|
if [ "$COUNT" -eq "$GOAL" ]; then
|
||
|
echo "$MAXBASE"
|
||
|
break
|
||
|
fi
|
||
|
COUNT=$(expr "$COUNT" + 1)
|
||
|
done
|
||
|
}
|
||
|
|
||
|
purge_entries()
|
||
|
{ LEVEL=$1
|
||
|
COUNT=0
|
||
|
if [ ! -e "$INDEX" ]; then
|
||
|
echo "Can't find index, \"$INDEX\""
|
||
|
die_cleanly
|
||
|
fi
|
||
|
for FILE in $(veels -d "$DIR"); do
|
||
|
FULLNAME=$FILE
|
||
|
DIR=${FULLNAME%/*}
|
||
|
FILE=${FULLNAME##*/}
|
||
|
MAXBASE=${FILE%.*}
|
||
|
ENTRY=$(grep "$MAXBASE" "$INDEX")
|
||
|
if [ -z "$ENTRY" ]; then
|
||
|
COUNT=$(expr "$COUNT" + 1)
|
||
|
if [ "$LEVEL" -eq 1 ]; then
|
||
|
echo "$DIR/$FILE (not really purged, use -P for realz)"
|
||
|
elif [ "$LEVEL" -eq 2 ]; then
|
||
|
echo "$DIR/$MAXBASE[.$RAWEXT,$FORMAT] (delebed)"
|
||
|
rm -f "$DIR/$MAXBASE"*
|
||
|
fi
|
||
|
fi
|
||
|
done
|
||
|
if [ "$LEVEL" -eq 1 ]; then
|
||
|
echo "use -P to remove all $COUNT entrie(s)"
|
||
|
elif [ "$LEVEL" -eq 2 ]; then
|
||
|
echo "removed $COUNT entrie(s)..."
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
die_cleanly()
|
||
|
{ if [ -e "$DRAFT" ]; then
|
||
|
rm -f "$DRAFT"
|
||
|
fi
|
||
|
exit 0
|
||
|
}
|
||
|
|
||
|
_POST2REFORMAT=0
|
||
|
_REFORMATALL=0
|
||
|
_PURGELEVEL=0
|
||
|
_POST2EDIT=0
|
||
|
SUMMARY=
|
||
|
MESSAGE=
|
||
|
SET_DEFAULT_FORMAT_FUNC=
|
||
|
|
||
|
# get opts ! stdin append to anything passed in by -m
|
||
|
while getopts 'DgGf:m:t:T:c:d:i:IbB:hRr:lL:novx:X:Pps:u:U' option; do
|
||
|
case $option in
|
||
|
u) _CUSTOM_UMASK=$OPTARG
|
||
|
;;
|
||
|
U) _CUSTOM_UMASK=0022
|
||
|
;;
|
||
|
D) set -x
|
||
|
echo Setting debug mode with, set -x
|
||
|
;;
|
||
|
g) # Gopher mode 1: output .txt and update $GOPHERMAP along side of HTML
|
||
|
GOPHERMODE=1
|
||
|
;;
|
||
|
G) # Gopher mode 2: treat as gopher phlog only (skip HTML stuff)
|
||
|
GOPHERMODE=2
|
||
|
;;
|
||
|
i) INDEX=$OPTARG # specify INDEX to $OPTARG
|
||
|
;;
|
||
|
I) INDEX="index.html" # force INDEX to index.html
|
||
|
;;
|
||
|
d) if [ -d "$OPTARG" ]; then
|
||
|
cd "$OPTARG"
|
||
|
else
|
||
|
echo "$OPTARG" is not a directory!
|
||
|
die_cleanly
|
||
|
fi
|
||
|
;;
|
||
|
r) _POST2REFORMAT=$OPTARG
|
||
|
;;
|
||
|
R) _REFORMATALL=1
|
||
|
;;
|
||
|
b) LISTENSTDIN=1
|
||
|
USE_EDITOR=0
|
||
|
;;
|
||
|
B) BOT_TPL=$OPTARG
|
||
|
;;
|
||
|
f) SET_DEFAULT_FORMAT_FUNC=$OPTARG
|
||
|
;;
|
||
|
c) MARGIN=$OPTARG
|
||
|
;;
|
||
|
l) _POST2EDIT=1
|
||
|
;;
|
||
|
L) _POST2EDIT=$OPTARG
|
||
|
;;
|
||
|
m) MESSAGE=$OPTARG
|
||
|
USE_EDITOR=0
|
||
|
;;
|
||
|
n) list_newest_first
|
||
|
die_cleanly
|
||
|
;;
|
||
|
o) list_oldest_first
|
||
|
die_cleanly
|
||
|
;;
|
||
|
s) SUMMARY=$OPTARG
|
||
|
;;
|
||
|
t) TITLE=$OPTARG
|
||
|
;;
|
||
|
T) TOP_TPL=$OPTARG
|
||
|
;;
|
||
|
v) echo $VERSION
|
||
|
die_cleanly
|
||
|
;;
|
||
|
p) _PURGELEVEL=1
|
||
|
;;
|
||
|
P) _PURGELEVEL=2
|
||
|
;;
|
||
|
h) usage | less
|
||
|
die_cleanly
|
||
|
;;
|
||
|
x) PREFORMAT_HOOK=$OPTARG
|
||
|
;;
|
||
|
?) #usage | less
|
||
|
die_cleanly
|
||
|
;;
|
||
|
esac
|
||
|
done
|
||
|
|
||
|
post_opts()
|
||
|
{
|
||
|
if [ -n "$_CUSTOM_UMASK" ]; then
|
||
|
umask "$_CUSTOM_UMASK"
|
||
|
fi
|
||
|
if [ $LISTENSTDIN -ne 1 ]; then
|
||
|
# brute check for umask 0022 if not using -b ($LISTENSTDIN -eq 1)
|
||
|
if [ $(umask) != "0022" ]; then
|
||
|
_default=yes
|
||
|
read -p "Would you like to temporarily set umask to 0022, to create files that are world readable [$_default]?" tmp_set_umask
|
||
|
if [ -z "$tmp_set_umask" ]; then
|
||
|
tmp_set_umask=$_default
|
||
|
fi
|
||
|
if [ "$tmp_set_umask" = "yes" ]; then
|
||
|
echo
|
||
|
umask 0022 && \
|
||
|
echo OK. To avoid this message in the future use -U, set umask in your login environment, or set the _CUSTOM_UMASK variable in your ./.veerc.
|
||
|
fi
|
||
|
fi
|
||
|
else
|
||
|
echo Warning: umask should be set to 0022. Your files may not be visible to others.
|
||
|
fi
|
||
|
|
||
|
if [ -e "$FORMAT_CUSTOM_DEFS" ]; then
|
||
|
. "$FORMAT_CUSTOM_DEFS"
|
||
|
fi
|
||
|
|
||
|
if [ -n "$SET_DEFAULT_FORMAT_FUNC" ]; then
|
||
|
"$FORMAT_DISPATCHER" "$SET_DEFAULT_FORMAT_FUNC" # default is set_format_func
|
||
|
fi
|
||
|
|
||
|
if [ "$_PURGELEVEL" -ge 1 ]; then
|
||
|
purge_entries "$_PURGELEVEL"
|
||
|
die_cleanly
|
||
|
fi
|
||
|
|
||
|
if [ "$_POST2EDIT" -ge 1 ]; then
|
||
|
LATEST=$(get_path2post "$_POST2EDIT")
|
||
|
$EDITOR "$DIR/$LATEST.$RAWEXT"
|
||
|
_POST2REFORMAT=$_POST2EDIT
|
||
|
fi
|
||
|
|
||
|
if [ "$_POST2REFORMAT" -ge 1 ]; then
|
||
|
LATEST=$(get_path2post "$_POST2REFORMAT")
|
||
|
reformat_singleton "$LATEST"
|
||
|
if [ 0 != $GOPHERMODE ]; then
|
||
|
default_update_gophermap
|
||
|
fi
|
||
|
die_cleanly
|
||
|
fi
|
||
|
|
||
|
# if "-R", or reformat all, is set
|
||
|
if [ "$_REFORMATALL" -eq 1 ]; then
|
||
|
# future may yield seperate "rebuild reindex" functionality
|
||
|
reformat_all
|
||
|
if [ 0 != $GOPHERMODE ]; then
|
||
|
default_update_gophermap
|
||
|
fi
|
||
|
die_cleanly
|
||
|
fi
|
||
|
|
||
|
# blocks vee -l (without the -r) from going on
|
||
|
if [ "$_POST2EDIT" -ge 1 ]; then
|
||
|
die_cleanly
|
||
|
fi
|
||
|
|
||
|
# Batch message creation: -m and stdin
|
||
|
# handles -m
|
||
|
if [ -n "$MESSAGE" ]; then
|
||
|
echo "$MESSAGE" >> "$DRAFT"
|
||
|
fi
|
||
|
|
||
|
if [ $LISTENSTDIN -eq 1 ]; then
|
||
|
OLDIFS=$IFS
|
||
|
IFS="" # ensures that leading spaces are retained
|
||
|
while read -r IN <&0 ; do # break after 1 sec of no stdin
|
||
|
echo "$IN" # echo's stdin back out so user can see
|
||
|
echo "$IN" >> "$DRAFT"
|
||
|
LISTENSTDIN=1
|
||
|
USE_EDITOR=0
|
||
|
done
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
# generates INDEX file if none exists
|
||
|
default_setup_html()
|
||
|
{ if [ ! -e "$INDEX" ]; then
|
||
|
echo
|
||
|
echo "...creating $INDEX"
|
||
|
echo "<!-- ;10000000000000000000000000; open pre tag --><!-- <?xml version=\"1.0\" encoding=\"UTF-8\" ?> --><!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\"><html xmlns=\"http://www.w3.org/1999/xhtml\"><head><title>my vee index</title><meta http-equiv=\"Content-Type\" CONTENT=\"text/html; charset=UTF-8\"></head><body><pre>" >> "$INDEX"
|
||
|
# header stuff
|
||
|
echo "<!-- ;100000000000000000000000; fixed content -->" >> "$INDEX"
|
||
|
echo "<!-- ;10000000000000000000000; fixed content -->" >> "$INDEX"
|
||
|
echo "<!-- ;1000000000000000000000; fixed content -->" >> "$INDEX"
|
||
|
# footer stuff
|
||
|
echo "<!-- ;3; fixed content -->" >> "$INDEX"
|
||
|
echo "<!-- ;2; fixed content -->" >> "$INDEX"
|
||
|
echo "<!-- ;1; fixed content -->Powered by vee" >> "$INDEX"
|
||
|
echo "<!-- ;0; closing pre tag --></pre></body></html>" >> "$INDEX"
|
||
|
echo
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
default_setup_gophermap()
|
||
|
{ if [ ! -e "$GOPHERMAP" ]; then
|
||
|
echo
|
||
|
echo "...generating updated $GOPHERMAP"
|
||
|
echo $GOPHERMAP_HEADER > $GOPHERMAP
|
||
|
echo >> $GOPHERMAP
|
||
|
echo >> $GOPHERMAP
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
default_setup()
|
||
|
{
|
||
|
if [ 2 != $GOPHERMODE ]; then
|
||
|
default_setup_html
|
||
|
fi
|
||
|
if [ 0 != $GOPHERMODE ]; then
|
||
|
default_setup_gophermap
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
use_editor()
|
||
|
{ if [ $USE_EDITOR -eq 1 ]; then
|
||
|
OK=0
|
||
|
$EDITOR "$DRAFT" && OK=1
|
||
|
if [ "$OK" -ne 1 ]; then
|
||
|
echo there has been a problem with your editor session
|
||
|
exit
|
||
|
fi
|
||
|
#else
|
||
|
#echo ...vi mode off
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
# ask for title if not set with -t and not in batch mode
|
||
|
# if in batch mode with no -t set, use default title below
|
||
|
get_title()
|
||
|
{ if [ -z "$TITLE" ]; then
|
||
|
TITLE=$DEFAULT_TITLE
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
read_config()
|
||
|
{ if [ -e ./.veerc ]; then
|
||
|
. ./.veerc
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
# this case statement may be overkill if "sort -t';' -nr -k2,2" works across platforms
|
||
|
sort_index()
|
||
|
{ if [ -e "$INDEX" ]; then
|
||
|
case $ARCH in
|
||
|
linux) sort -t';' +0f -1 +1nr "$INDEX" > ".$INDEX.$$.sorted"
|
||
|
;;
|
||
|
freebsd) sort -t';' +0f -1 +1nr "$INDEX" > ".$INDEX.$$.sorted"
|
||
|
;;
|
||
|
netbsd) sort -t';' +0f -1 +1nr "$INDEX" > ".$INDEX.$$.sorted"
|
||
|
;;
|
||
|
macosx) # -k2,2 sorts by second field as delimted by -t';' - this may actually work
|
||
|
# for all platforms
|
||
|
sort -t';' -nr -k2,2 "$INDEX" > ".$INDEX.$$.sorted"
|
||
|
;;
|
||
|
*) sort -t';' +0f -1 +1nr "$INDEX" > ".$INDEX.$$.sorted"
|
||
|
;;
|
||
|
esac
|
||
|
mv ".$INDEX.$$.sorted" "$INDEX" # "rebuild $INDEX
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
#-- main program body
|
||
|
mkdir -p "$DIR" || echo "found $DIR ..."
|
||
|
|
||
|
read_config # done after all options are read in, could look in -d before
|
||
|
# opts are processed though so opts could override defaults
|
||
|
# and config file .. yeah do that
|
||
|
post_opts # process options
|
||
|
"$CUSTOM_SETUP" # initialized indexes, can be defined in .veerc
|
||
|
get_title
|
||
|
use_editor
|
||
|
|
||
|
main()
|
||
|
{ if [ -e "$DRAFT" ]; then
|
||
|
RAWFILE="$SEC.$$.$TIME.$RAWEXT" # uses process id, $$, assuming there will
|
||
|
# not be duplicate process ids within 1 sec of each other
|
||
|
format_main "$SEC.$$.$TIME.$FORMAT" "$SEC.$$.$TIME.$GOPHER_FORMAT" "$RAWFILE"
|
||
|
"$UPDATE_INDEX" "$FINAL" "$gFINAL" "$RAW" "$gRAW" "$TITLE"
|
||
|
sort_index
|
||
|
die_cleanly
|
||
|
else
|
||
|
echo Error! "$DRAFT" not found
|
||
|
fi
|
||
|
}
|
||
|
|
||
|
main
|