#! /bin/sh # -*- ksh -*- # card --- smartly produce a printed reference card of a program # Copyright (c) 1998-2000 Akim Demaille, Miguel Santana # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 3, or (at your option) # any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, you can either send email to this # program's maintainer or write to: The Free Software Foundation, # Inc.; 59 Temple Place, Suite 330; Boston, MA 02111-1307, USA. # Author: Akim Demaille # Name by which this script was invoked. program=`echo "$0" | sed -e 's/[^\/]*\///g'` card_version='1.3' # Initialize variables. # Don't use `unset' since old bourne shells don't have this command. # Instead, assign them an empty value. # Some of these, like A2PS, may be inherited from the environment. a2ps=${A2PS-a2ps} a2ps_options=-Ecard commands= debug= form_feed= help="Try \`$program --help' for more information." LC_ALL="${LC_ALL-C}" export LC_ALL print_form_feeds=: RM="/bin/rm -rf" tmp_dir=`mktemp -d -t card.XXXXXX` || { echo "$program: Cannot create temporary dir!" >&2 ; exit 1; } tmp_file=$tmp_dir/card success=false verbose=: version_short="card $card_version (@GNU_PACKAGE@ @VERSION@)" usage="Usage: $program [OPTION]... PROGRAM... Print a reference card of the PROGRAMs thanks to their inline help. Options: -h, --help display this help and exit -v, --version display version information and exit -o, --output=FILE save the output in FILE -l, --language=LL print the help in the language LL (default: English) --command=CMD perform pretty-printing on the output of CMD (e.g. --command='netscape -help') Options for a2ps are given after \`--', for instance $ card -lfr a2ps -- -Pdisplay -4 News, updates and documentation: http://www.inf.enst.fr/~demaille/a2ps/ Report bugs to ." version="$version_short Written by Akim Demaille. Copyright (c) 1997-99 Akim Demaille, Miguel Santana This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." # List of the possible ways to get the on line help. # -flags is used with Solaris' CC. possible_options="--help -h -help -\? -flags" # Parse command line arguments. option_without_arguments='vhsqDf' # As a first step, fetch all the options meant for a2ps, i.e. # everything after `--'. jam="$$card$$" set dummy "${1+"$@"}" "$jam" shift while test "x$1" != "x$jam" && test "x$1" != "x--"; do set dummy "${1+"$@"}" "$1" shift shift done # If $[1] is `--', then from here to the JAM are a2ps arguments. if test "x$1" = x--; then shift while test "x$1" != "x$jam" do a2ps_options="$a2ps_options $1" shift done fi # The current $1 is JAM. Pop up the JAM, pop it up, pop it out. shift # Proceed to card's options parsing. # Push a token among the arguments that will be used to notice when # we ended options/arguments parsing. arg_sep="$$--$$" set dummy ${1+"$@"} "$arg_sep" shift while test "x$1" != "x$arg_sep"; do # Handle --option=value by splitting apart and putting back on argv. case "$1" in --*=*) opt=`echo "$1" | sed -e 's/=.*//'` val=`echo "$1" | sed -e 's/[^=]*=//'` shift set dummy "$opt" "$val" ${1+"$@"} shift ;; -[$option_without_arguments]?*) # Prefix $1 with x to avoid running `echo -na' for instance. opt=`echo "x$1" | sed -e 's/x-\(.\).*/-\1/'` rest=`echo "x$1" | sed -e 's/x-.\(.*\)/-\1/'` shift set dummy "$opt" "$rest" ${1+"$@"} shift ;; # This case needs to be protected so that the case `-??*' does # not split long options without arguments --*) ;; # This is an option with argument. Split apart and put back on argv. -??*) opt=`echo "x$1" | sed -e 's/x-\(.\).*/-\1/'` arg=`echo "x$1" | sed -e 's/x-.\(.*\)/\1/'` shift set dummy "$opt" "$arg" ${1+"$@"} shift ;; esac # Now, handle the options. $1 is the option *only*. If it has an # argument, it is now necessarily in $2 etc. Remember to shift # when fetching an argument. case "$1" in -v | --v*) echo "$version"; exit 0;; -h | --h*) echo "$usage"; exit 0;; -s|-q|--q*|--s*) verbose=: ;; -D | --debug) debug=: ;; -o|--output) shift a2ps_options="$a2ps_options --output=$1" ;; --lan*|-l) shift; LC_ALL=$1 ;; --com*|-c) shift; commands="$commands $optarg" ;; --no-*|-f) print_form_feeds= ;; --) # What remains are not options. shift while test "x$1" != "x$arg_sep"; do set dummy ${1+"$@"} "$1" shift shift done break;; -*) echo "$program: Unknown or ambiguous option \`$1'." >&2 echo "$program: Try \`--help' for more information." >&2 exit 1;; *) set dummy ${1+"$@"} "$1" shift ;; esac shift done # Pop the token shift # ARG now contains both options for a2ps and the true arguments. if test $# = 0 && test "X$commands" = X; then exec 1>&2 echo "$program: no program given" echo "$help" exit 1 fi # Create a tmp dir and be ready to clean up trap "$RM $tmp_dir" 0 1 2 15 case $LC_ALL in fr) footer="Engendré par $version_short" ;; *) footer="Generated by $version_short" ;; esac # Set -x now if debugging test -n "$debug" && set -x # The files to process are in "$@" for file do success=false filename=`echo "$file" | sed -e 's/[^\/]*\///g'` $verbose "Working on \`$filename'" case $LC_ALL in fr) title="Carte de référence pour $filename" ;; *) title="Reference card of $filename" ;; esac # Try to find the help message for opt in $possible_options do $verbose "Trying \`$file $opt'" ($file $opt >$tmp_dir/foo 2>&1) >/dev/null 2>&1 && success=: && break # Netscape for example is stupid enough to `exit 255' when properly fed # with -help, as recommanded by -help itself... If there are really # many lines, consider it is still a success. if test "$success" = false; then if test `wc -l <$tmp_dir/foo` -gt 10; then success=: && break fi fi done # If the help message has been found, process it with a2ps if $success; then $verbose "Success" if test -n "$form_feed"; then echo " " >>$tmp_file fi cat <>$tmp_file card_label($title) card_title($title) EOF cat $tmp_dir/foo >>$tmp_file # Be ready to insert a page break before next argument-program form_feed=$print_form_feeds else echo "$program: could not find help message for $file" exit 1 fi done SAVED_IFS="$IFS" IFS=" " for command in $commands do IFS="$SAVED_IFS" success=false case $LC_ALL in fr) title="Résultat de \`$command'" ;; *) title="Result of \`$command'" ;; esac (eval $command >$tmp_dir/foo 2>&1) >/dev/null 2>&1 && success=: # If the help message has been found, process it with a2ps if $success; then $verbose "Success" if test -n "$form_feed"; then echo " " >>$tmp_file fi cat <>$tmp_file card_label($title) card_title($title) EOF cat $tmp_dir/foo >>$tmp_file # Be ready to insert a page break before next argument-program form_feed=$print_form_feeds else echo "$program: command \"$command\" failed" exit 1 fi done IFS="$SAVED_IFS" # All the programs have been treated. Call a2ps on the produced file $a2ps $a2ps_options --footer="$footer" $tmp_file || exit 1 exit 0