#################################################################
# FCD : "Find" Change Directory
# Put this code at the bottom of .kshrc
# Fred Brunet 1994
#################################################################


#################################################################
# This logic exits .kshrc if $FCD is already defined.  It keeps 
# fcd from being called by subsequent subshells (.kshrc is run 
# by ksh for each subshell). Make sure that these lines come 
# before the definition of fcd but after anything else you want 
# called in each ksh subshell.
#################################################################
if [ $FCD ]
then
    return
else
    FCD="fcd"
    export FCD
fi


echo "Loading fcd- type \"fcd\" for information"

##################################################################
# function: addline(directory)
#----------------------------------------------------------------#
# Add line to file list for future lookup.                       #
##################################################################
addline()
{
    error=0
    echo "Enter full path of $Newline: \c"
    read Fullpath
    if [ -d $Fullpath ]
    then
        echo $Fullpath >> $HOME/fcd.list
        Flist=$Fullpath
    else
        echo "Sorry, can't find that directory!"
        error=1
    fi
}

###############################################################
# function:usage
#-------------------------------------------------------------#
# Print a usage screen.                                       #
###############################################################
function usage
{
	echo "  Usage- fcd directory"
	echo "         fcd -e directory for extended search"
	echo "         fcd -p to add current directory to list"
	echo "         fcd -r to recursively scan directories under current"
	echo "\n\n"
}

#######################################################################
# function: fcd
#---------------------------------------------------------------------#
# Accept a string from the user and search for that string in Filedir.#
# "cd" to the found directory.                                        #
#######################################################################
function fcd
{
    error=0
    FileDir=$HOME/fcd.list
    Duplist=$HOME/fcd.dup

	###################################################################
	# Print usage screen if no parameters given.
	#
    if [ $# = 0 ]
    then
		usage
        return 0
    fi

	# Set expanded search flag.
	Extend="NO"

	###################################################################
	# Handle special cases.
	#
	case $1 in
	"-e")
	    ###############################################################
		# Toggle extended search mode.
		#
        if [ $# != 2 ]
        then
            echo "Error: insufficient parameters ($#)"
            echo "Usage: fcd -e directory"
            return 2
        fi
        Extend="YES"          # Init extended search flag on
        shift                 # Make 2nd parameter 1st to skip "-e"
		;;

	"/")
	    ###############################################################
		# Go to root instead of searching for slash.  Slash is in every
		# line of the database.
		#
        cd /
        return 0
		;;

	"-p")
	    ###############################################################
		# Add current directory to fcd database.  Fcd returns right
		# after this switch is passed (no other parameters are 
		# processed).
		#
        CurDir=$(pwd)

		#
		# Don't add a duplicate if directory is already in database.
        grep "$CurDir\$" $FileDir > /dev/null  
        if [ $? != 0 ]
        then
            echo $CurDir >> $FileDir
            return 0
        else
            echo "Current directory $CurDir\n is already in $FileDir"
            return 1
        fi
		;;

	"-r")
	    ###############################################################
		# Add all directories under current directory to the database.
		#
		echo "Scanning directories under $PWD"
		find $PWD -type d -print >> $FileDir
		cat "$FileDir" | sort | uniq > $Duplist
		if [ $? = 0 ]
		then
			echo "Sorted and cleaned up $FileDir"
			mv $Duplist $FileDir
		fi
		return 0
		;;
	esac

	###################################################################
	# Create a new database if none exists.
	#
    if [ ! -f $FileDir ] 
    then
        echo "Creating new $FileDir in $HOME.  It may take a while..."
        find $HOME -type d -print > $FileDir
    fi
    
	###################################################################
	# Search in extended or regular mode for directory.
	#
    if [ $Extend = "YES" ]               # search full line for match
    then
        grep $1 $FileDir > $Duplist
    else
        grep $1'$' $FileDir > $Duplist   # search end of line for match
    fi

	###################################################################
	# Count the matches found.
	#
    lines=`wc -l $Duplist | awk '{print $1}'`

	
	###################################################################
	# Customization 2-9-94- search for 4gs, 4gm directories
	# THIS WILL NOT APPEAR IN THE ARTICLE
	if [ $lines = 0 ]
	then
        grep $1.4g.$ $FileDir > $Duplist
    	lines=`wc -l $Duplist | awk '{print $1}'`
	fi
	# end custom
	###################################################################


	###################################################################
	# Process the matches
	###################################################################
    case $lines in
    0)
		###############################################################
		# No matches. Let the user update the database, if desired..
		#
        echo "Not found- add(y/n)?\c "
        read ans
        if [ $ans = 'y' ]
        then
            Newline=$1
            addline $Newline
            if [ $error = 1 ]
            then
                return 1
            fi
        else
            return 1
        fi
        ;;

    1)
		###############################################################
		# One match. Assign it to the cd list.
		#
        Flist=`cat $Duplist`
        ;;
    *)
		###############################################################
		# More than one match.  Print a list for the user.
		#
        awk ' { printf "%2d : %s\n", NR, $0 }' $Duplist
        echo "Which of the above do you mean (enter number or 'q' for none)? \c"
        read lineno


		###############################################################
		# Get the line number from the user. 'q' is a special 
		# case to choose none.
		#
        if [ $lineno = 'q' ]
        then
			echo "Removing possible duplicates from file list..."
			cat "$FileDir" | sort | uniq > $Duplist
			if [ $? = 0 ]
			then
				echo "Sorted and cleaned up $FileDir"
				mv $Duplist $FileDir
			fi
            return 1
        fi

		###############################################################
		# Make the user enter 1-lines or q.
		#
        while [ $lineno -gt $lines -o $lineno -lt 1 -o $lineno = 'q' ]
        do
            echo "Valid input: 1-$lines or q.  Reenter number: \c"
            read lineno
        done

		# Do nothing if user wants to quit.
        if [ $lineno = 'q' ]
        then
            return 1
        fi

		###############################################################
		# Pick the directory at the line the user chooses.
		#
        Flist=`sed -n "${lineno}p" $Duplist`
        ;;
    esac
        
	
	###################################################################
	# Show the user the directory chosen in case they don't 
	# have "pwd" as part of the ksh PS1. 
	#
    echo $Flist


	###################################################################
	# Go to the directory chosen.  This is actually the only 
	# line that MUST be run in the current process for fcd to
	# work.
    cd $Flist 2> /dev/null


	###################################################################
	# If cd failed, remove the defunct entry from the database.
	#
	if [ $? != 0 ]
	then
		echo "Removing defunct $Flist from $FileDir"
		cat $FileDir | grep -v $Flist > $Duplist
		if [ $? = 0 ]
		then
			mv $Duplist $FileDir
		else
			echo "An error occurred while editing $FileDir.  It may be damaged."
		fi
	fi
}

####################################################################
# Run the function.
fcd $1
 


