#!/bin/bash
#
# ANGELSCRiPTS
# 
# created: Dharamsala 2007
# thierry.blanc@gmx.ch
#
# version 0.2.3-2
#
# join in and create some angels!!

#
# files required:
# angels.conf

# folders required:
# angels (with angels inside)s

conffile=/etc/angels.conf
if [[ ! -f "$conffile"  ]] ; then
  echo -e "$conffile not found \n exit"
  exit
fi

. "$conffile"
# exec 6>&2
# exec 2>>$ERRORLOG
#### create files/folders, if missing

#create tmp folder for command scripts
mkdir -p $ANGELDOTFOLDER
mkdir -p $CMDDIR
mkdir -p $ANSWERDIR
mkdir -p $VARIABLED
mkdir -p $VARDLOCAL
mkdir -p $TMP


# check for logfile
[[ ! -s "$LOGFILE" ]] && touch "$LOGFILE"

# create the directory for downloaded angels
if [[ ! -d "$WGETANGELS" ]]; then
        mkdir -p "$WGETANGELS"
        echo 'ENCODING="ISO-8859-1"
TITLE="directory for downloaded angels"' > "$WGETANGELS"/.directory.ngl
fi

# flags 
FLAGS=$ANGELDOTFOLDER/flags
if [[ ! -s "$FLAGS"  ]] ; then
cat <<EOF >"$FLAGS"
fBRACKETS=1             # show {{ braces
fINCLUDE_FILES=1        # show file or $file:...
fDEFVALUE=1             # show variable or value
fDUMMY=-1               # show dummy or commands
fVARHEIGHLIGHT=-1       # heighlight variable (value only)
EOF
fi
         


ORIGPATH="$PWD"

# name of file or link that called the script, i.e. angel, a number or (b,r,u)
SCRIPTNAME=${0##*/}

# prepare header file to give LASTxx variables
# LASTTYPE, LASTTITLE, LASTGROUP, ...
# LASTFILE becomes LASTANGEL!!!
sed '/^[^#]/s|^ *|LAST|;s|LASTFILE=|LASTANGEL=|' $SHEAD > $SHEAD.old 2>/dev/null
. $SHEAD.old

# set lastgroup, if not set
[[ -z "$LASTGROUP" ]] && LASTGROUP=$(echo "${LASTANGEL#$ANGELPATH}"| sed 's|/||')

# empty variable.d directory here, before precommands are executed!
[[ ! -z "$VARDLOCAL" ]] && rm "$VARDLOCAL"/* &>/dev/null

# read flags value
. $FLAGS

#### FUNCTIONS

function create_oneletter_commands ()
{ # create single-letter commands
        [[ ! -z  "$LINKS" ]]  && rm -f  "$LINKS"/* &>/dev/null
        pushd "$LINKS" >/dev/null       
        target=$(which angel)
        for i in `seq 1  16` r b f p n q u z d x h e
                do ln -s "$target" "$i" 2>/dev/null
        done
        popd &>/dev/null

}


function E_noangel ()
{ # check for angel file  
if [[ ! -e "$1" ]] ;then 
        echo "angel "$ACTIVEANGEL" does not exist!"
        exit 128
fi
}       

# check for errors in angel file
function futsch ()
{
        echo "syntax error in file $1"
        exit 127
}

function check_syntax ()
{
# $1 ngl-file
B='#PRECOMMANDS
#VARIABLES
#MAIN'

# check for TITLE TYPE in header
A=$(sed '0,/#PRECOMMANDS/!d' $1)
for i in "TYPE=" "TITLE="
do
        if ! echo "$A"|grep -q "$i" ;then
                futsch "$1 no $i"
        fi
done
#check for presence and right order
A=$(sed -nr '
/(^#PRECOMMANDS).*/s||\1|p
/(^#VARIABLES).*/s||\1|p
/(^#MAIN).*/s||\1|p
' $1)

[[ ! "$A" == "$B" ]] && futsch "$1"

}

#
function create_links () 
{
# $1 amount of links
        for ((i=1;i<=$1;i++))
                do  which $i &>2 || ln -s `which angel` "$LINKS/$i" 2>/dev/null
        done
}

# get functions

function get_angel () 
{ # get line no $1  from $SMAIN 
# $1 is position  
[[ -z "$1" ]] && return 127
EXTRACT=$(sed  $1'!d' $SMAIN )
}

function add_line ()
{ # adds a line to a file at the top 
# $2 is target file to set the type=
# $ section (future)
local line="$1"
sed -i '1s|$|\n'"$line"'|'   "$2"
}

function set_vars ()
{ # set standard variables according to input string
# set FILE TYPE TITLE UUID TAGS with line from $ANGEL or .index file
# $1 is input string : FILE::TYPE::TITLE::UUID::TAGS
# $2 is a list of variable names, if omitted standard is used

local u="$1"
local vars="${2:-FILE TYPE TITLE UUID TAGS}"
for i in $vars
do
        eval $i=\""${u//::*}"\"
        u="${u#*::}"
done
}

function get_reference ()
{
# $1 is reference UUID
# EXTRACT is : FILE::TYPE::TITLE::UUID::TAGS
local F
F=$(grep "::$1::" $(find "$ANGELPATH" -name ".index.txt" -printf "%p\n")| sed 's|/.index.txt:|/|')
EXTRACT="${F:-n/a}"
}

####  b, f, u  procedures

function go_up ()
{ # move up one directory
ACTIVEANGEL=$(dirname "$LASTANGEL" 2>/dev/null)
TYPE=directory
# stop at ANGELPATH; 
[[ "${#ACTIVEANGEL}" -lt "${#ANGELPATH}" ]] && ACTIVEANGEL="$ANGELPATH"
}

function one_down ()
{ # move the @-sign one line *down* in $1
# $1 = target file 
# if no @ sign then set it to 1st line
if ! grep -q "^@" "$1" ;then
        SED='1s|^|@|'
        else
        SED='   $q;
                /^@/{s///
                        N;
                        s/\n/\n@/
                    }'
fi
sed -i  "$SED" "$1"
}

function one_up ()
{ # move the @-sign one line *up* in $1
# $1 = target file 
# if no @ sign set, set it to last line
if ! grep -q "^@" "$1" ;then 
        SED='$s|^|@|'
        else
        SED='$!N
                /\n@/{
                        s/@//
                        s/^/@/
                     }
                        P
                        D'
fi
sed -i  "$SED"  "$1"
}

function update_logfile ()
{ # append latest used angel to logfile
        echo  "$ACTIVEANGEL"::"$TYPE"::"$TITLE" >> $LOGFILE
        # clear @-signs, uniq, set the "last command" sign to last command
        sed  's/^@//' "$LOGFILE"| uniq|sed '$s/^/@/' >"$LOGFILE.tmp"
        cp "$LOGFILE.tmp" "$LOGFILE"
}

function move_one ()
{ # move to the next or previous entry (ONE entry)
# $1 = target file 

# down/up in list (file) or end for last line of file (reset)
local direction=$2      

case $direction in 
        down) one_down "$1"
;;
        up) one_up "$1"
;;
        end)    sed -i 's|^@||;$s|^|@|' "$1"
                return
;;
esac

# set ACTIVEANGEL, TITLE and TYPE
EXTRACT=$(sed -n '/^@/{s|||;p} ' "$1")
[[ -z "$EXTRACT" ]] && exit 127

set_vars "$EXTRACT"
ACTIVEANGEL="$FILE"
LOGFILEUPDATE=no                # do not update the logfile
}

function renew_screen ()
{
# renew screen
ACTIVEANGEL="${LASTANGEL%.ngl}"
TYPE="$LASTTYPE"
}


function wget_angel ()
{

pushd $WGETANGELS 2>/dev/null

wget -O my.tar.gz "$1"
tar -xvvf my.tar.gz 

create_index $PWD
popd 2>/dev/null

if [[ ! -d  $ANGELPATH/imported ]]; then
        ln -s "$WGETANGELS" "$ANGELPATH/imported"
        create_index "$ANGELPATH"
fi
}

######## $ANGEL functions


function exec_header ()
{ 
# $1 = TYPE

. $SHEAD  # execute #HEADER > set TYPE, TITLE...
# if there is no group, create one based on filename
if [[ -z "$GROUP" ]] ; then
        local f="${ACTIVEANGEL#$ANGELPATH}"
        GROUP="${f//\/}"
fi

# add VARS to file
add_line "FILE=$ACTIVEANGEL" $SHEAD
add_line "TYPE=$1"  $SHEAD
add_line "GROUP=\"$GROUP\"" $SHEAD # if group exists, no effect
}


######## flag functions
function flag_onoff ()
{ # change the flag to opposite value 

local VALUE=$1
local FLAGNAME=$2

(( VALUE *= -1 ))
sed -ri  '/'$FLAGNAME'=/s/=.*/='$VALUE'/' $FLAGS
. $FLAGS
TYPE=show               # recreate showfile but not $ANGEL              
LOGFILEUPDATE=no

}

function flag_status ()
{ # display the value of a flag in human readable form
# $1    is value of flag  # name of flag
if [[ "$1" -eq -1 ]]
        then STATUS="off"
        else
        STATUS="on"
fi
}

######## insert functions
function insert_variable ()
{ # insert all variables stored in $VARIABLELIST in the place of the variable placeholder
# $1 = target file to insert variables
# $2 suppress style settings 

local style="" styleoff=""
if [[ "$fVARHEIGHLIGHT" -eq 1 && ! "$2" == "style_off" ]]; then
 style="$varcolor"
 styleoff="$varcoloroff"
fi

OFS=$IFS; IFS=$'\n'
for i in $(cat "$VARIABLELIST")
        do
        var="${i%%:*}"
        value="${i#*:}"
        sed -i 's|{{'"$var"'}}|'"$style$value$styleoff"'|g' "$1"
done
IFS=$OFS
}

function include_references ()
{ # insert file: title where a {{@ref: occurs
# with data from the corresponding angel
local ref link=101 string
sed  's|{{|\n|g' "$1"|sed -rn 's/^@ref:([^}]*)}}.*/\1/p' |while read ref
do
        get_reference "$ref"
        set_vars "$EXTRACT" "rfile rtype rtitle ruuid rtags"

        string="n/a$snormal"
        case "$rtype" in
                directory) string="$sCFOLDER${rfile##*/}: $sCTITLE$rtitle $snormal"
        ;;
                file) string="$sCFILE${rfile##*/}: $sCTITLE$rtitle $snormal"
        ;;
        esac
        # insert into file
        sed -i 's|{{@ref:'"$ref"'}}|'"$sCCMD$link$NUMSEP$string"'|g' "$1"

        # set link and create command
        [[ -z `which $link`  ]] && ln -s `which angel` "$LINKS/$link"
        echo "angel -r $ref" > "$CMDDIR/$link"
        ((link++))
done
}

function include_files ()
{ # include files into a file
# type is the indicator 
# {{@file:...}}-statements
# {{@include ...
# replace all {{@file: with the corresponing files

local FILE="$1"         # target file
local ttc="$2"          # type (@file)
local line text in_file
sed  's|{{|\n|g' "$FILE"| sed -rn '/^'"$ttc"':/{s|||;s|([^}]*)}}.*|\1|p}' | while read line
do
        if [[ "${line:0:1}"  == / ]] ;then      # prepend ANSERDIR
                in_file="$line"
        else
                in_file="$ANSWERDIR/$line"
        fi
        text=$(cat "$in_file"|sed  ':a;$!N;s|\n|\\n|g;$!ba')
        sed -i 's|{{'"$ttc:${line//|/\|}"'}}|'"${text//|/\|}"'|g' "$FILE"
done
}


function set_numbers ()
{ # set identifiers in a-commands with x to number
# replaces x with number; skips if x is followed by any char; adapts to identifier
local COUNT=0
sed -n '/^@[cd]md:/{s|||;p}' $SMAIN | while read -r cmd
do
        ID="${cmd%%:*}"
        [[  $ID == x* && "${#ID}" -gt 1 ]] || ((COUNT++))
        [[  $COUNT -le $ID ]] && COUNT=$ID 
        if [[ "${cmd:0:1}" == "x" ]]
        then sed -ri '0,/^@[cd]md:x/s|:x|:'"$COUNT"'|' $SMAIN
        fi
done
}


######## variable functions


function edit_angel ()
{
myfile="$1"
# directory or angel file
if [[ -z "$myfile" ]] ; then
        if [[ $LASTTYPE == directory ]] 
                then myfile="$LASTANGEL/".directory.ngl
        else
                myfile="$LASTANGEL".ngl
        fi
fi
# play around .... find out, if file has been changed
atime=$(ls -l "$myfile" --time-style=full|cut -d ' ' -f7)       
sudo $EDITOR "$myfile"
if [[ $atime == `ls -l $myfile --time-style=full|cut -d ' ' -f7` ]] 
        then 
         echo "file left unchanged." 
        else
         echo "file changed." ;fi
}

function create_variable_list ()
{ # extract the variables from various files and create variable.txt list
# $VARIABLELIST stores the FINAL values for a variable (one entry per variable)

# empty  variable list
echo >"$VARIABLELIST"

# create list from main variable directory
# variable-file is identified by $GROUP
# last entry in file is used
# this file stores  a choosen variable!
tac  "$VARIABLED/$GROUP" > "$VARIABLELIST".tmp 2>/dev/null

# variables from variable-section, main place for static variables
sed '/^#/d;1d;$d' $SVAR 2>/dev/null >> "$VARIABLELIST".tmp

# create first list of variable from main section (on-the-fly variable)
sed 's|[^{]{[^{]||g;s|[^}]}[^}]||g' "$SMAIN" |sed -n '/{{.*}}/{s|^[^{]*{{||;s|}}[^{]*{{|\n|g;s|}}[^{]*$||;p}'| sed -r '/^@/d;;s/^:(.*)/\1:\1/'>> "$VARIABLELIST".tmp

# from variable.d directory for variables created in the precommand section
if pushd "$VARDLOCAL" &>/dev/null ;then
        for i in *; do
                sed 's|^|'"$i"':|' "$i" 2>/dev/null >> "$VARIABLELIST".tmp
        done
        popd &>/dev/null
fi

# first value is used in loop, latter variable entries are ignored
while read -r line
do
        if ! grep -q "${line%%:*}" "$VARIABLELIST" 
                then echo "$line" >> "$VARIABLELIST" 
        fi
done<"$VARIABLELIST".tmp

sed -i '/^$/d;' "$VARIABLELIST"
}


function set_variables ()
{ # let user enter new values for a variable 

local DEF newdef VALUE answer
local myvar_group="$VARIABLED/$LASTGROUP"

# lines containing variable 
local LINES=$(sed '/{{[^@].*}}/!d;s|<[^>]*>||g;s|@cmdend||' "$SMAIN")

# show lines with variable
        echo "==== LINES with VARIABLES to SET =============="
        echo "$LINES"| sed 's/{{/'$sred'&/g;s/}}/&'$snormal'/g' 
        echo
        echo "==== VARIABLES ================== VALUE ========"

# show list of variables
        cat  $VARIABLELIST  | sed -r 's|:|                         :|;s|^(.{26}) *:|\1|'| cat -b -
        echo -n "     Choose a variable:  "
        read  -u 1 answer
        [[ ! "$answer" -gt 0  ]] && exit 127

# set $DEF to a variable according to choosen number
        DEF=$(sed -rn  $answer'p' "$VARIABLELIST"| cut -d: -f1 )
        [[ -z "$DEF" ]] && exit 127

# get list of stored alternatives for the variable
        VALUE=$(cat "$VARIABLELIST".tmp |sed -n '/^'"$DEF"':/{s///;p}'| sort| uniq | sed '/^[[:blank:]]*$/d' )

# show list of values for choosen variable 
        echo -e "     Values for \"$DEF\":"
        echo -e "$VALUE"  |cat -b -| sed 's/^/            /'
        echo -n "     Choose a value or press [enter] for new: "
        read answer
# promt for a new value or choose one from list
        if [[ -z "$answer" ]]; then             # just enter
                echo -n "     Enter a new value: " 
                read   -u 1  newdef     
        elif [[ -z  "${answer//[0-9]}" ]]  ;then        # variable stripped of numbers
                newdef=$(echo "$VALUE" |sed -n  "$answer"'p')
        else
                newdef="$answer"
        fi
        echo

# save variable
        # create group-file if not existing
        [[ ! -f "$myvar_group" ]] && touch  "$myvar_group"
        # delete entry if already there and append at the end
        sed -i '/'"$DEF:${newdef////\/}"'/d' "$myvar_group"
        # save new var
        echo -e "$DEF:$newdef" >> "$myvar_group"
        echo  "changed \"$DEF\" to \"$newdef\""
# update variablelist file
        sed  -i '/^'"$DEF"'/d' "$VARIABLELIST"
        echo -e "$DEF:$newdef" >> "$VARIABLELIST"
        echo -e "$DEF:$newdef" >> "$VARIABLELIST".tmp
}

function extract_commands
{ #extract the statements according to positional parameteres
local tmp="$TMP"/angelcmd
local file

# copy angel for commands
cat $SMAIN  > $tmp

# remove all old commands 
[[ ! -z "$CMDDIR" ]] && rm $CMDDIR/* 2>/dev/null

# change all variables to values 
insert_variable $tmp "style_off"
include_files "$tmp" "@file"

# extract all @cmd:xx-to-@cmdend statements and put them into $CMDDIR/xx as files
sed '/^@cmd/,/@cmdend$/!d;s|@cmdend$|\n|' $tmp|while read -r line
        do 
        i="$(echo "$line" | sed -rn 's|^@cmd:([^:]*).*|\1|p')" 
        if [[ ! -z "$i" ]] ;then
                file=$i # create link if needed
                [[ -z `which $i`  ]] && ln -s `which angel` "$LINKS/$file" 
        else 
                echo "$line" >> "$CMDDIR/$file"
        fi
done 

}


function execute_command ()
{ # execute a command 
CMD=$1
CMDFILE="$CMDDIR/$1"
local RESTORE

# check is command exists
if [[ ! -f "$CMDFILE" ]]; then
        echo "Sorry, command $CMD does not exist"
        exit $E_NO_FILE
fi

# backup command file BEFORE replacing ask statements
cp "$CMDFILE" "$CMDFILE".before

# check for {{@?}}-statements (ask-statements)
while grep -q "{{@?:.*}}" "$CMDFILE"
do
        echo -n "$(sed 's|[^{]{[^{]|NIL|' "$CMDFILE" |sed -nr '/\{\{/{s|^[^{]*\{\{@\?:([^}]*)\}\}.*|\1|p;q}' ) "
        read  -e ANSWER
        sed -ri '0,/\{\{[^}]*\}\}/s||'"$ANSWER"'|' "$CMDFILE"
        RESTORE=yes
done

# execute the command
# exec 2>&6     # redirect error to stdout not error.log
pushd "$ORIGPATH" &>/dev/null

echo "----- command -----"
cat "$CMDFILE"
echo "------ output -----"

. "$CMDFILE"

popd &>/dev/null
# exec 2>>$ERRORLOG
# restore command if needed
[[ $RESTORE == yes ]] && cp "$CMDFILE".before "$CMDFILE"
}

######## create functions

function create_newangel () 
{ # create a new angel in the current angel-dir
# $1 = filename for angel
local xfile xuuid lpath

xfile="$1"
xuuid=$(uuidgen)

[[ -z "$xfile" ]] && read -p "Enter a filename for new angel (default=newangel): " xfile
xfile="${xfile:-newangel}"; xfile="${xfile%.ngl}"

if [[ "$LASTTYPE" == directory ]];then
        lpath="$LASTANGEL"/$xfile.ngl
  else
        lpath="$(dirname "$FILE")/$xfile.ngl";fi

sudo cat <<EOF > "$lpath"
ENCODING="ISO-8859-1"
TYPE="file"
TITLE="$xfile"
TAGS=""
UUID="$xuuid"
GROUP=""
#PRECOMMANDS
#VARIABLES
#MAIN

@cmd:x
@cmdend

EOF

create_index "$(dirname $lpath)"
}

### create index 
function _create_index ()
{
# $1 = directory
# .directory.ngl contains informatinon about the directory
# .index.txt is the index for the directory
local directories files
# enter directory, return, if not possible
if ! pushd "$1" &>/dev/null ;then
        return
fi

echo > $TMP/directories         # empty file for directory enties
# find all *.ngl files and directories
# skips dot-files ; 
# squeezes data into one line for further search!
# for directories
for FILE in $(find -L . -maxdepth 1 -type d -printf "%P$IFS")
        do
        [[ -z "$FILE" ]] && continue
        TITLE="n/a";UUID='';TAGS=''
        if [[ -f "$FILE/.directory.ngl"  ]];then
                for ff in TITLE TAGS UUID; do
                        eval $(sed -n '/'"$ff"'/p' $FILE/.directory.ngl)
                done
        fi
        # print entry in .index.txt
        echo -e "$FILE::directory::$TITLE::$UUID::$TAGS" >> $TMP/directories
done
# for files
echo > $TMP/files       # empty file for angels (file) entries
for FILE in $(find . -maxdepth 1 -not -name ".*" -name "*.ngl" -printf "%P$IFS")
        do
        if [[  -f "$FILE" ]] 
        then
                TITLE="n/a";UUID='';TAGS=''
                echo $FILE
                # get parameters from file
                for ff in TITLE TAGS UUID; do
                        eval $(sed -n '0,/^#PRECOMMANDS/{/'"$ff"'=/p}' $FILE)
                done
                # print entry in .index.txt
                echo -e "${FILE%.ngl}::file::$TITLE::$UUID::$TAGS" >> $TMP/files
        fi
done

# create header 
header=$(cat ".directory.ngl")
[[ -z "$header" ]] &&  header="TITLE=\"n/a\""

# add header
echo "$header" > .index.txt
echo -n "#MAIN" >> .index.txt
# add tmp-file from before and sort it
cat  $TMP/directories| sort -g  >> .index.txt
cat  $TMP/files |sort -g  >> .index.txt

chgrp  angels .index.txt 2>/dev/null
chmod 664 .index.txt    2>/dev/null
popd &>/dev/null
}


function create_index ()
{ # create .index.xml file 
# -r    = recursive
# $1 [$2] = directory
case "$1" in 
        "")
        echo "Usage ${0##*/} [-r] directory"
        echo "  full path of directory needed!"
        echo "  use ${0##*/} --create-index \$PWD for present directory"
        exit
        ;;
        "-r") recursive=yes
                shift
        ;;
esac

if [[ ! -d "$1" ]] ;then
                echo "directory not found"
                exit
fi

base="${OLDPWD#$ANGELPATH/}"
if [[ "$recursive" == "yes" ]] ; then
        # finds all subdirectories, but....
        LIST=$(find "$1" -type d )
else
        LIST="$1"
fi 

echo "$LIST"
for i in $LIST 
do
        echo $i
        _create_index "$i"
done
}

#### end functions


####      BEGIN MAIN PROGRAM

# check, if  link directory is empty
[[ `ls "$LINKS"|wc -l` -lt 28 ]] && create_oneletter_commands

# check name of script that called this script 
case "$SCRIPTNAME" in 
        angel)  # base program, parse parameter 
                # options only for angel, not for links
                # start options 
                case "$1" in 
                "") # angel invoked witout arguments >> go basedir
                        TYPE=directory
                        ACTIVEANGEL="$ANGELPATH"
                ;;
                "-f")   # find in index-file, ie. filename,title,tags
                        # *ALL* parameters must match (logical and)
                        shift
                        TYPE=find
                        ACTIVEANGEL="$@"
                ;;
                "-F")   # full-text search      
                        exit            
                ;;
                "-r")   # reference: go to reference <uuid>
                        shift
                        get_reference "$1"
                        set_vars "$EXTRACT"
                        ACTIVEANGEL=$FILE
                ;;
                "-x")   # execute an angel-file
                        shift
                        ACTIVEANGEL="$PWD/$1"
                        [[ -f $ACTIVEANGEL ]] && TYPE=file
                        [[ -d $ACTIVEANGEL ]] && TYPE=directory
                ;;
                "-u")   # URL
                        shift
                        wget_angel "$1"
                        exit
                ;;      
                "-i")   # inactivate one letter links
                        [[ ! -z  "$LINKS" ]]  && rm -f  "$LINKS"/* &>/dev/null
                        exit
                ;;
                "-c") #create angel
                        set -x
                        shift
                        create_newangel "$1" 
                        exit
                ;;
                "-e")  shift
                        edit_angel "$1"
                        exit
                ;;
                --create-index) 
                        shift 
                        create_index $@
                        exit 0
                ;;
                --h*|-h*|yelp) # show help message
                        ACTIVEANGEL="$ANGELPATH/"help
                        TYPE=directory
                ;;
                # end options
                *)      # direct directory/file reference
                        file="${1%.ngl}"
                        if [[ -f "$ANGELPATH/$file.ngl" ]] ;then 
                                TYPE=file
                                ACTIVEANGEL="$ANGELPATH/$file"
                        elif [[ -d "$ANGELPATH/$1" ]] ;then
                                TYPE=directory
                                ACTIVEANGEL="$ANGELPATH/$1"
                        else
                                E_noangel
                        fi
                ;;
                esac
        ;;
# one-letter commands 
        b)      move_one "$LOGFILE" up          # back: previous selection 
        ;;
        f)      move_one "$LOGFILE" down        # forward: next selection
        ;;
        n)      move_one "$ANGELS_IN_DIR" down  # go next angel in dir
        ;;
        p)      move_one "$ANGELS_IN_DIR" up    # go previous angel in dir
        ;;
        u)      go_up                           # up one level
        ;;
        r)      renew_screen
        ;;
        d)      set_variables
                renew_screen
        ;;
#       ])      flag_onoff "$fBRACKETS" fBRACKETS
#       ;;
        z)      flag_onoff "$fINCLUDE_FILES" fINCLUDE_FILES 
                flag_status $fINCLUDE_FILES
                echo "Show files is" $STATUS
        ;;
        q)      flag_onoff "$fDEFVALUE" fDEFVALUE
                flag_status $fDEFVALUE
                echo "Show values is" $STATUS
        ;;
        x)      flag_onoff "$fDUMMY" fDUMMY
                flag_status $fDUMMY
                echo "Hide commands is" $STATUS
        ;;
        h)      flag_onoff "$fVARHEIGHLIGHT" fVARHEIGHLIGHT
                flag_status  $fVARHEIGHLIGHT
                echo "Highlighting variables is" $STATUS
        ;;
        e)      if [[ -z $1 ]]; then 
                        echo "argument required"
                else
                        echo "changed command \"$1\" temporarily to:"
                        sudo $EDITOR ~/.angels/`tty |sed 's|/||g'`/commands/$1
                        cat $_
                fi
                exit    
        ;;
# link is a number, choose entry from list
        [0-9]*) POS=$SCRIPTNAME
                case $LASTTYPE in
                directory) # show the directory or file with respective number
                        get_angel $POS          # get line $POS of $ANGEL file
                        set_vars "$EXTRACT"
                        ACTIVEANGEL="$LASTANGEL/$FILE"
                ;;
                file)   # execute the command
                        move_one "$LOGFILE" end  # reset log
                        execute_command $POS    
                        exit
                ;;
                find) 
                        get_angel $POS          # get line $POS of $ANGEL file
                        set_vars "$EXTRACT"
                        ACTIVEANGEL="$ANGELPATH/$FILE"
                ;;
                esac    
        ;;
esac




# create files $ANGEL and $SHOWFILE (list and display)
case $TYPE in 
directory)  # create $ANGEL file for case "directory"
        # check for angel
        E_noangel "$ACTIVEANGEL"
        pushd "$ACTIVEANGEL" &>/dev/null 
        # check if index file exists
        [[ ! -f .index.txt ]] && create_index "$PWD"
        
        # parse .index.txt file for head and main
        sed '0,/^#MAIN/!d' .index.txt > $SHEAD
        sed '/^#MAIN/,$!d;/^#MAIN/d;/^$/d' .index.txt> $SMAIN
        exec_header directory

        # create $ANGELS_IN_DIR, filter only lines with a file entry
        sed -n '/::file::/s|^|'"$ACTIVEANGEL"'/|p' $SMAIN  > "$ANGELS_IN_DIR" 
        # if more than 16 entries, create links
        LINKSNO=$(sed -n '$=' "$SMAIN")
        [[ "$LINKSNO" -gt 16 ]] && create_links $LINKSNO
;;
find)   # perform a search matching *ALL* positional parameters 
        # create $ANGEL file for case "find"
        # search for all positional parameters inclusive in title, tag, name
        # create header
        echo "ENCODING=\"ISO-8859-1\""  > "$SHEAD"
        echo -e "TYPE=find"  >> "$SHEAD"
        echo -e "FILE=\"$ACTIVEANGEL\"">> "$SHEAD"
        echo -e "TITLE=\"search results\"">> "$SHEAD"
        # execute #HEADER
        . $SHEAD  

        # create searchstring from @* for sed: /$1/!d; /$2/!d; /$3/!d ....
        SEARCHSTRING=$(echo "$ACTIVEANGEL" |sed -r 's|([^ ])|[\U\1\L\1]|g;s|^|/|;s| |/!d; /|g;s|$|/!d|')
        
        pushd  "$ANGELPATH" &>/dev/null
        echo > "$SMAIN"
        # check all .index-files files for search string 
        for i in $(find  -name ".index.txt" -printf "%P\n")
                do
                u="$(dirname "$i")/"; [[ "$u" == "./" ]] && u=""  # dirname behaviour
                sed '0,/#MAIN/d' $i| sed  "$SEARCHSTRING" | sed 's|^|'$u'|'>> "$SMAIN"
        done
        popd &>/dev/null
        sed -i '/^$/d' "$SMAIN"
        # create links if missing
        LINKSNO=$(sed -n '$=' "$SMAIN")
        [[ "$LINKSNO" -gt 16 ]] && create_links $LINKSNO
;;
file)   # create $ANGEL for file
        E_noangel "$ACTIVEANGEL".ngl
        check_syntax "$ACTIVEANGEL".ngl
        # parse activeangel to create head, pre, main
        sed '0,/^#PRECOMMANDS/!d' "$ACTIVEANGEL.ngl" > $SHEAD
        sed '/^#PRECOMMANDS/,/^#VARIABLES/!d' "$ACTIVEANGEL.ngl"> $SPRE
        sed '/^#VARIABLES/,/^#MAIN/!d' "$ACTIVEANGEL.ngl"> $SVAR
        sed '/^#MAIN/,$!d;/^#MAIN/d' "$ACTIVEANGEL.ngl"> $SMAIN
        exec_header file

        . $SPRE   # execute precommand section
        #include @include (source a script)
        include_files "$SMAIN" "@include"
        # extract variables and create variables.txt list
        create_variable_list 
        # delete variable values set inside main section, leave var-name only!
        sed  -i 's/\({{[^:@]\+\):[^}{]*\(}}\)/\1\2/g' "$SMAIN"
        # set automatic numbers, if needed
        set_numbers
        # extract the commands
        extract_commands
        # set references
        include_references "$SMAIN" 
;;
show)   # renew showfile
        ACTIVEANGEL="$LASTANGEL"
        TITLE="$LASTTITLE"
        TYPE=$LASTTYPE
        sed -i '1,3!d' $SHOWFILE
;;
esac

######## create showfile
# creates the first 3 lines with title and tags and filename
echo -e "$bold""$TITLE""$boldoff"  > $SHOWFILE
echo -e "     $TYPE: $red${ACTIVEANGEL#$ANGELPATH}" >> $SHOWFILE
echo -e "$normal$CTAGS     tags: $TAGS$normal" >> $SHOWFILE

case $TYPE in 
directory|find) # list directories first  then list files
        sed -r 's/(^[^:]*::[^:]*::[^:]*)::.*/\1/
                /::directory::/{
                        s||: '"$sCTITLE"'|
                        s|^|'"$sCFOLDER"'|
                        s|$|'"$snormal"'|
                        }
                /::file::/{
                        s||: '"$sCTITLE"'|
                        s|^|'"$sCFILE"'|
                        s|$|'"$snormal"'|
                        }' $SMAIN | sed '/^$/d' | cat -n >> "$SHOWFILE"
;;
file) #remove cmd- and dmd-statements, insert colours and adjust nicely
        SED=''
        # hide the commands, if DUMMY is set
        if [[ "$fDUMMY" -eq 1 ]]; then 
        # delete the commands when hide commands is on
        SED='   /^@cmd:[^:]*:/{
                        /^@cmd:/{s|||
                                s|:|'"$NUMSEP"':|
                                s|:|'"$sCCMDCOMMENT"'|1
                                s|^|'"$sCCMD"'|
                                s|$|'"$snormal"'|
                                p}
                        :a
                        /.*@cmdend$/d
                        s|.*||;
                        N
                        ba}
                        '
        fi
        # layout commands and ajust nicely (the unsolvable problem)
        SED1="$SED"'
                /^@[cd]md:/{
                                s///    
                                s|([^:]*:).*|\1|
                                s|^[^:]*$|&:|           # insert ':' if no
                                s|:|'"$NUMSEP"':|
                                h
                                        s|.| |g
                                        s|^.||
                                x
                                s|:||                   # delete : if not previously
                                N
                                s/\n *//
                                s|^|'"$sCCMD"'|
                                bip}
                G
                s|(.*)\n(.*)|\2\1|
                :ip
                /@[cd]mdend$/{ s||'"$snormal"'|
                                h
                                s|.*||
                                x
                                }'
        # fmt simulate, break line at col and preserve tabs in the beginning
        SED3='    /\t/s|$|\t|
                :a
                /^.{'"$COLS"'}/{
                s//&\a/
                Tc;tc
                :c
                /.*\a/{
                        s|^(.*) (.*)\a|\1\n\2|
                        tb      # change a space 
                        s|^(.*[-/;:])(.*)\a|\1\n\2|
                        tb      # if no space use one of -/;:
                        s|\a|\n|
                        :b      # hard core at col size
                        P
                        s|^.*\n||
                        /\t$/s|^|\t|
                        ba
                        }
                
                
                x
                s|.*||
                x
                }
                p
                ' 
        sed -r "$SED1" $SMAIN|sed -nr "$SED3"  >> $SHOWFILE
        # adjust showfile      - | fmt -s -w $COLS -t
        [[ "$fINCLUDE_FILES"  -eq 1 ]] && include_files "$SHOWFILE" "@file"
        # value of variable on or off   
        [[ "$fDEFVALUE"  -eq 1 ]] &&  insert_variable "$SHOWFILE" 
        # variablename of variable on or off    
#       [[ "$fDEFAULTNAME"  -eq -1 ]] && variablename_off
        # brackets on or off
#       [[ "$fBRACKETS" -eq 1 ]] && sed -i 's|{{||g;s|}}||g' $SHOWFILE
#       set colors
        sed -i 's/<black>/'"$sblack"'/g
        s/<red>/'"$sred"'/g
        s/<green>/'"$sgreen"'/g
        s/<yellow>/'"$syellow"'/g
        s/<blue>/'"$sblue"'/g
        s/<magenta>/'"$smagenta"'/g
        s/<cyan>/'"$scyan"'/g
        s/<white>/'"$swhite"'/g
        s/<normal>/'"$snormal"'/g

        s/<bold>/'"$sbold"'/g
        s/<\/bold>/'"$sboldoff"'/g
        s/<italics>/'"$sitalics"'/g
        s/<\/italics>/'"$sitalicsoff"'/g
        s/<ul>/'"$sul"'/g
        s/<\/ul>/'"$suloff"'/g
        s/<inv>/'"$sinv"'/g
        s/<\/inv>/'"$sinvoff"'/g'  $SHOWFILE
;;
esac

# display showfile
echo -e "`cat $SHOWFILE`$normal" |sed  '1,3!s|^|     |'

# add entry to logfile 
[[  $LOGFILEUPDATE == yes ]] && update_logfile