#!/bin/sh # Copyright (c) 2010 - 2011 Vasileios Porpodas # # Permission is hereby granted, free of charge, to any person # obtaining a copy of this software and associated documentation # files (the "Software"), to deal in the Software without # restriction, including without limitation the rights to use, # copy, modify, merge, publish, distribute, sublicense, and/or sell # copies of the Software, and to permit persons to whom the # Software is furnished to do so, subject to the following # conditions: # # The above copyright notice and this permission notice shall be # included in all copies or substantial portions of the Software. # # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT # HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR # OTHER DEALINGS IN THE SOFTWARE. # # This software is licensed under GPL 3 License. http://gplv3.fsf.org/ # ABOUT # Slack-desc is a script that generates the slack-desc files for # Slackware linux packages (http://www.slackware.org). # It supports two modes of operation: # o the argument-based one # o the interactive one which guides you thourgh the process. # The output is printed on the screen. # EXAMPLE # a. argument-based: # ./slack-desc-gen "slack-desc" "0.01" "slackware slack-desc generator # script" "Slack-desc is a script that generates the slack-desc files # for slackware linux packages. It supports two modes of operation: the # argument-based one and the interactive one." "http://slack-desc-gen # .sourceforge.net" # # b. interactive: # ./slack-desc-gen -i # # # Read from stdin until newline or LIMIT # Usage: SIMPLEINPUT LIMIT simpleinput() { local limit=$1 read -a IN -n $limit $ECHO ${IN[@]} } # Read stdin until the special characters are typed in. # or until charecter LIMIT is reached. Return the input string up # to the LIMIT. # Usage: GETINPUT LIMIT getinput() { local limit=$1 local i=2 while [ "${ALL[i-2]}" != ";" ]||[ "${ALL[i-1]}" != ";" ] ;do if [ $i -gt $limit ];then $ECHO "Warning: Character limit of $limit exceeded." 1>&2 $ECHO -e $str exit -1 fi read -a IN -n 1 #convert newlines into spaces if [ "$IN" == "" ]; then IN=" "; fi ALL[i]=$IN str+=$IN i=$(($i+1)) done local max=$(($i - 4)) local str=`$ECHO $str|head -c $max` $ECHO -e $str } # Format the given STRING in slack-desc format using PKGNAME prefix. # Make sure that it takes up to LINES lines. # Usage: FORMAT PKGNAME "STRING" LINES format() { # LINES local max_lines=$3 local lines=1 local out="" local wordlist=( ) local i=0 # STRING for word in $2; do wordlist[$i]=$word i=$(($i + 1)) done local max=${#wordlist[@]} # "PKGNAME: " local fmted_pname="$1: " local linebuffer="${fmted_pname}" i=0; while [ $i -le $max ]; do if [ $lines -le $max_lines ] ; then local linebuffer_chars=`get_length "$linebuffer"` local next_word=${wordlist[$i]} local next_word_chars=$((`get_length $next_word`)) # Test if adding the next word will overflow the screen width. local test_chars=$(($linebuffer_chars + $next_word_chars + 1)) if [ $test_chars -lt $screen_width ]; then linebuffer+="$next_word " else lines=$(($lines + 1)) # commit linbuffer to the output buffer out+="$linebuffer\n" linebuffer="${fmted_pname}" # redo the last one. i=$(($i - 1)) fi else if [ $i -lt $((max)) ]; then OVERFLOW="Y" break fi fi i=$(($i + 1)) done if [ $lines -le $max_lines ]; then out+="$linebuffer\n" fi #This is a hack. all other checks are done in sanity_check() if [ "$OVERFLOW" == "Y" ]; then if [ ! "$DISABLED_CHECKS" == "N" ]; then # FORCE EXIT ON ERROR check_size "$description" $description_limit "FORCE" fi fi # line padding: add lines until we reach max_lines for ((i=lines; i < max_lines; i++ )); do out+="${fmted_pname}\n" done $PRINTF "$out" if [ "$OUTFILE" != "" ]; then $ECHO -e $out >> $OUTFILE fi } # Print help message. # Usage HELP_MESSAGE help_message() { $ECHO -e "Usage: $PKGNAME \"\" \"\" \"\" \"\" \"\" [ -r ] [ -n ]\n\ OR\n\ Usage: $PKGNAME -i [ -r ] [ -n ] // Interactive wizard (beta)\n\ \n\ Example: $PKGNAME \"slackdesc\" \"0.01\" \"slackware slack-desc generator tool\" \"$PKGNAME is a tool that generates the slack-desc files for Slackware linux packages. It supports two modes of operation: the argument-based one and the interactive one.\" \"http://slack-desc.sourceforge.net\" \n\ \n\ Arguments description\n\ -i Launch interactive wizard\n\ Single word; The name of the package (application name)\n\ The application version\n\ A short description that fits one line\n\ A description up to 7 lines long\n\ The project homepage. Should fit in 1 line\n\ -r Show handy ruler on top\n\ -n Disable sanity checks\n\ " } # Get a string's length (count of characters) # Usage: GET_LENGTH STRING get_length() { string="$@" # don't use $ECHO because it inserts extra newline chars, destroys count local length=`$PRINTF "$string"|$WC -c` $ECHO $length } # Parse the command line arguments # Usage PARSE_INPUT [ARG1] [ARG2] ... parse_input(){ if [ "$1" == "" ]||[ "$1" == "--help" ] || [ "$1" == "-help" ] || [ $# -eq 0 ]; then help_message exit -1 fi; SHOW_RULER="N" local INTERACTIVE="N" if [ "$1" == "-i" ] || [ "$1" == "--interactive" ] || [ "$1" == "-interactive" ]; then INTERACTIVE="Y" if [ "$2" == "-r" ]; then SHOW_RULER="Y" fi fi if [ "$6" == "-r" ]||[ "$7" == "-r" ]; then SHOW_RULER="Y" fi DISABLE_CHECKS="N" if [ "$6" == "-n" ]||[ "$7" == "-n" ]; then DISABLE_CHECKS="Y" fi package_name_limit=$(($screen_width-10)) version_limit=20 if [ "$INTERACTIVE" == "Y" ]; then $ECHO -e "\nEnter package name" local package_name="`simpleinput $package_name_limit`" local name_width=`get_length "${package_name} :"` homepage_limit=$(($screen_width - $name_width)) $ECHO -e "\nEnter application version" local version="`simpleinput $version_limit`" local version_width=`get_length "$version"` local package_name_width=`get_length "$package_name"` summary_limit=$(($screen_width - $name_width - $version_width - $package_name_width)) description_limit=$(($summary_limit * $desc_lines)) $ECHO -e "\nEnter package summary" local summary="`simpleinput $summary_limit`" $ECHO -e "\nEnter package description --> USE \";;\" TO END INPUT <--" local description="`getinput $description_limit`" $ECHO -e "\nEnter application's homepage" local homepage="`simpleinput $homepage_limit`" else package_name="$1" version="$2" summary="$3" description="$4" homepage="$5" local name_width=`get_length "${package_name}: "` homepage_limit=$(($screen_width - $name_width)) local version_width=`get_length "$version"` local package_name_width=`get_length "$package_name"` summary_limit=$(($screen_width - $name_width - $version_width - $package_name_width)) description_limit=$(($(($screen_width - $name_width -1)) * $desc_lines)) fi } # Check whether the STRING's size is less than or equal to MAX_LENGTH # If FORCE_ERROR is "FORCE" then ignore the check and fail. # Usage: CHECK_SIZE STRING MAX_LENGTH [FORCE_ERROR] check_size() { local string="$1" local length=$2 local FORCE_ERROR=$3 local chars=`get_length "$string"` if [ $chars -ge ${length} ]||[ "$FORCE_ERROR" == "FORCE" ]; then $ECHO "ERROR! string: "+${string} +" too big!" exit -1 fi } # Sanity checks about input's character lengths # Usage: SANITY_CHECKS sanity_checks(){ if [ ! "DISABLE_CHECKS" == "Y" ]; then check_size "$package_name" $package_name_limit check_size "$version" $version_limit check_size "$package_name: $package_name $version" $(($screen_width)) check_size "$summary" $summary_limit check_size "$package_name: $package_name $version $summary" $(($screen_width)) check_size "$homepage" $homepage_limit check_size "$description" $description_limit fi } # Print the |----habndy-ruler----...--| # Usage: HANDY_RULER handy_ruler() { if [ "$SHOW_RULER" == "Y" ]; then # $ECHO "appname|-----handy-ruler------------------------------------------------------|" local HANDY_RULER="${package_name}|-----handy-ruler--" check_size "$HANDY_RULER" $screen_width local chars=`get_length "$HANDY_RULER"` while [ $chars -lt $screen_width ]; do HANDY_RULER+="-" chars=`get_length "${HANDY_RULER}-"` done HANDY_RULER+="|" $ECHO "$HANDY_RULER" fi } # Print the slack-desc output # Usage: PRINT_OUTPUT print_output() { handy_ruler sanity_checks format ${package_name} "$package_name $version $summary" $summ_lines format ${package_name} "" $empty_line format ${package_name} "$description" $desc_lines format ${package_name} "$homepage" $homepage_lines } # Entry point # Usage: MAIN [ARG1] [ARG2] ... main() { parse_input "$1" "$2" "$3" "$4" "$5" "$6" "$7" print_output } # GENERAL CONFIGURATION # paths to programs used WC=wc PRINTF=printf ECHO=echo PKGNAME="slackdesc" summ_lines=1 empty_line=1 desc_lines=8 homepage_lines=1 screen_width=80 main "$1" "$2" "$3" "$4" "$5" "$6" "$7"