#!/bin/sh ########################################################################### # # Window Maker window manager # # Copyright (c) 2021 Christophe CURIS # Copyright (c) 2021 Window Maker Team # # 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 2 of the License, 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, see . # ########################################################################### # # replace-generated-content.sh: # Re-generate some list of things and replace it in an existing file # # The script can generate these kind of information: # # - a list of man pages (--man-pages), in which case the following fields # are available for the template replacement: # \1: file for the man page, with directories removed, with '.html' extension # \2: name of the man page, taken from the file name # \3: section of the page, taken from the file name # \4: one line description, taken from the man page's NAME section # # The 'template' argument provides the template on how to generate one line # with the new content, the '\n' being replaced with the values explained # above. # # The 'marker' arguments tells the script where the content is to be placed # in the edited file: # - the beginning of generated content is located from the line containing # the pattern 'start ' + the marker text # - the end is marked by 'end ' + marker # No content outside the start/end is modified. When inserting the content # the script is re-using the indentation that was found in the line with the # start marker. # ########################################################################### # # For portability, we stick to the same sh+awk constraint as Autotools to # limit problems, see for example: # http://www.gnu.org/software/autoconf/manual/autoconf-2.69/html_node/Portable-Shell.html # ########################################################################### # Report an error on stderr and exit with status 2 to tell make that we could # not do what we were asked arg_error() { echo "`basename $0`: $@" >&2 exit 2 } # print help and exit with success status print_help() { echo "$0: replace lines by new content" echo "Usage: $0 options... file" echo "valid options are:" echo " --template string : template text for generating the data" echo " --man-pages list : content from the list of these man pages" echo " --marker mark : comment mark surrounding the data to update" exit 0 } # Extract command line arguments while [ $# -gt 0 ]; do case $1 in --man-pages) shift man_pages="$man_pages $1 " ;; --marker) shift [ "x$mark" = "x" ] || arg_error "only 1 marker can be specified (option: --marker)" mark=$1 ;; --template) shift [ "x$template" = "x" ] || arg_error "only 1 template can be specified (option: --template)" template="$1" ;; -h|-help|--help) print_help ;; -*) arg_error "unknow option '$1'" ;; *) [ -z "$edit_file" ] || arg_error "only 1 file to modify can be specified" edit_file=$1 ;; esac shift done # Check consistency of command-line [ -z "$edit_file" ] && arg_error "no file to update was specified" [ -f "$edit_file" ] || arg_error "file \"$edit_file\" cannot be read" [ -z "$template" ] && arg_error "Template for generation not specified" [ -z "$mark" ] && arg_error "No content mark specified" [ -z "$man_pages" ] && arg_error "No input list provided" # Make sure the file to edit contains the appropriate marks grep "start $mark" "$edit_file" > /dev/null || arg_error "Start mark \"start $mark\" not found in \"$edit_file\" (option: --marker)" grep "end $mark" "$edit_file" > /dev/null || arg_error "End mark \"end $mark\" not found in \"$edit_file\"" ########################################################################### # Generate the content from the list of man pages provided ########################################################################### if [ -n "$man_pages" ]; then parse_man_page() { # Build the name of the HTML file from the man page name target=`echo $1 | sed 's,[^/]*/,,g ; s/\.[^.]*$//' `.html section=`echo $1 | sed 's/^.*\.\([^.]*\)$/\1/' ` # Extract the name and the description from the .SH NAME sed -n '/^\.SH "*NAME"*$/ { n s/^\([^ ]*\) *\\- */'$target':\1:'$section':/ :append_next_line N /\n\./ b end_section_found s/[ \t]*\n[ \t]*/ / b append_next_line :end_section_found s/[ \t]*\n\..*$// s/\\f[BIPR]//g p }' $1 } content=` for file in $man_pages ; do parse_man_page $file done ` nb_fields=4 fi ########################################################################### # Convert the content to the specified format ########################################################################### for i in `seq 2 $nb_fields`; do sed_from="$sed_from\\([^:]*\\):" done sed_from="^$sed_from\\(.*\\)\$" content=`echo "$content" | sed -e "s,$sed_from,$template," ` ########################################################################### # Replace the content in the file ########################################################################### # We are working in 2 steps because we cannot edit in place # In step one we remove the existing content from the file purged_file=`sed -e "/start $mark/ { p :search_end N s/^.*\n// /end $mark/! b search_end }" "$edit_file" ` # Convert the content to an AWK array awk_start=`echo "$content" | awk ' BEGIN { print "BEGIN {"; } { # Add a backslash before the double-quotes line = ""; while (1) { idx = index($0, "\""); if (idx == 0) break; line = line substr($0, 1, idx - 1) "\\\\\""; $0 = substr($0, idx + 1); } print " content[" NR "] = \"" line $0 "\";"; } END { print " nb_content = " NR ";"; print "}"; } ' ` # In step two we insert the generated content between the marks awk_cmd=' # When the start mark is found, insert the generated content /start '"$mark"'/ { print; # Isolate the indentation so it can be applied to all generated lines sub(/[^ \t].*$/, ""); for (i = 1; i <= nb_content; i++) { print $0 content[i]; } # Thanks to the pre-processing done, the next line will be the end mark next; } # All the rest of the file is kept as-is { print } ' echo "$purged_file" | awk "$awk_start$awk_cmd" > "$edit_file" || exit $?