#!/bin/ash
# *********************************************************************
# edittable: NoSQL trivial table editor. Requires a vi(1)-compatible
#	     full-screen editor.
#
# Copyright (c) 1998,2009 Carlo Strozzi
#
# 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; version 2 dated June, 1991.
#
# 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, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
#
# *********************************************************************

# Get local settings and apply defaults.
: ${TMPDIR:=/tmp} ${NOSQL_CHARSET:=utf-8}
: ${NOSQL_INSTALL:=@NOSQL_INSTALL@}
: ${SWU_INSTALL:=@SWU_INSTALL@}
: ${PATH:=@LOCAL_PATH@}

export NOSQL_INSTALL SWU_INSTALL PATH TMPDIR NOSQL_CHARSET

tab="	"			# Warning: this must be a physical TAB!
edit_format=
no_lock=
add_rec=
no_sort=

while [ $# -gt 0 ]
do
   case $1 in
	-l|--list)		edit_format=list ;;
	-L|--no-lock)		no_lock=1 ;;
	-a|--add-record)	add_rec=1 ;;
	-n|--no-sort)		no_sort=1 ;;
	-h|--help)
	     grep -v '^#' $NOSQL_INSTALL/help/edittable.txt
	     exit 0
	;;
	--show-copying)
	     cat $NOSQL_INSTALL/doc/COPYING
	     exit 1
	;;
	--show-warranty)
	     cat $NOSQL_INSTALL/doc/WARRANTY
	     exit 1
	;;
	-*) ;;				# Skip unknown options.
	*) args="$args $1" ;;
   esac
   shift
done

set - $args

if [ $# != 1 ]
then
   echo 'Usage: edittable [options] tablename' >&2
   exit 1
fi

tbl_path=$1

out_dir=`dirname $tbl_path`

cd $out_dir
if [ $? -ne 0 ]
then
   echo Could not access directory "'$out_dir'" >&2
   exit 1
fi

tbl_file=`basename $tbl_path`

# Lock the target table before doing anything.

if [ "$no_lock" != 1 ]
then
   lockfile -r0 $tbl_file.lock 2>/dev/null

   if [ $? -ne 0 ]
   then
      echo edittable: unable to lock "'$tbl_file'" for write >&2
      exit 1
   fi
   trap_list="$tbl_file.lock"
fi

# We must create the work files in the same directory as the
# target table for 'mv' to work as desired.

edit_tmp=`mktemp ./$tbl_file.XXXXXX` || exit $?
tbl_tmp=`mktemp ./$tbl_file.XXXXXX` || exit $?

# Set-up trapping on signals.
trap "rm -f $edit_tmp $tbl_tmp $trap_list" 0 
trap "exit 2" 1 2 3 15

istable < $tbl_file
if [ $? -ne 0 ]
then
   echo edittable: file "'$tbl_file'" is not a valid table >&2
   exit 1
fi

if test "X$edit_format" = X && grep -q \| $tbl_file
then
   echo "Found '|' characters in table, forced list format ... (wait)" >&2
   sleep 2
   edit_format=list
fi

if [ "$edit_format" = list ]
then
   if [ -n "$add_rec" ]
   then
      addrow < $tbl_file | tabletolist > $edit_tmp
   else
      tabletolist < $tbl_file > $edit_tmp
   fi
else
   # compute max. justified line length.
   set - $(widest -H -R -s \| -a 2 -i $tbl_file)
   if [ -n "$add_rec" ]
   then
      addrow --highlight < $tbl_file |
      prtable -b0 -l$1 -p0 -s\| > $edit_tmp
   else
      prtable -b0 -l$1 -p0 -s\| < $tbl_file > $edit_tmp
   fi
fi

# Try and figure-out user's preferences.
[ "$EDITOR" = "" ] && EDITOR=$VISUAL
[ "$EDITOR" = "" ] && EDITOR=vi

[ $EDITOR = vi ] && [ -n "$add_rec" ] && offset=+

while :
do
   if [ $EDITOR = vi ]
   then
      $EDITOR $offset $edit_tmp
   else
      $EDITOR $edit_tmp
   fi

   set --
   if [ "$edit_format" = list ]
   then
      plus=0
      set - `islist --verbose --edit < $edit_tmp`
   else
      plus=2
      set - $(frametable --unframe --edit < $edit_tmp)
   fi

   if [ "$2" = "" ]
   then
      break
   else
      offset=+`expr $2 + $plus`
      echo ''
      echo 'What shall I do ?'
      echo ''
      echo '1) Re-edit the table'
      echo '2) Quit without saving the changes'
      echo '3) Commit the changes anyway'
      printf '\n=> '

      # Read one line from the terminal.
      read edit_action

      [ "$edit_action" = "" ] && edit_action=2

      case $edit_action in
         1) continue ;;
         2) exit 4 ;;
         3) break ;;
      esac
   fi
done

# Keep the table sorted on the key column.
if [ "$edit_format" = list ]
then
   listtotable < $edit_tmp |
   if [ "X$no_sort" = X ]
   then
      filtertable -- sort "-t$tab" -k 1
   else
      cat
   fi > $tbl_tmp
else
   # Remove any residual highlight rows while converting back to table.
   frametable --unframe < $edit_tmp | sed '/^[=	]*$/d' |
   if [ "X$no_sort" = X ]
   then
      filtertable -- sort "-t$tab" -k 1
   else
      cat
   fi > $tbl_tmp
fi

old_mode=`swu-filemode $tbl_file`
[ $? -eq 0 ] || exit 1

chmod $old_mode $tbl_tmp || exit $?

if test -h $tbl_file
then
   # If the target table is a symbolic link then it cannot be
   # overwritten atomically and cp(1) must be used.
   echo "Warning: $tbl_file is a symbolic link, atomicity not possible" >&2
   cp $tbl_tmp $tbl_file || exit $?
else
   mv $tbl_tmp $tbl_file || exit $?
fi

# End of program.
