Previous | Table of Contents | Next |
Now youll look at the simplest of the three functions, the dirs() function, which lists the directory stack:
dirs() { # save IFS, then set it to : to access the # the items in _DIR_STACK individually. OLDIFS="$IFS" IFS=: # print each directory followed by a space for i in $_DIR_STACK do echo "$i \c" done # add a new line after all entries in _DIR_STACK # have been printed echo # restore IFS IFS="$OLDIFS" }
Here you use the same trick as you used in the lspath() function: save IFS and then set it to :, enabling you to list each of the items individually. The final echo is required to add a new line after all the entries are printed. Finally you restore IFS.
The pushd function is slightly more complicated than the dirs function. It needs to change to a requested directory and then add that directory to the top of the stack.
Your implementation is as follows:
pushd() { # set the requested directory, $REQ, to the first argument # If no argument is given, set REQ to . REQ="$1"; if [ -z "$REQ" ] ; then REQ=. ; fi # if $REQ is a directory, cd to the directory # if the cd is successful update $_DIR_STACK # otherwise issue the appropriate error messages if [ -d "$REQ" ] ; then cd "$REQ" > /dev/null 2>&1 if [ $? -eq 0 ] ; then _DIR_STACK="`pwd`:$_DIR_STACK" ; export _DIR_STACK ; dirs else echo "ERROR: Cannot change to directory $REQ." >&2 fi else echo "ERROR: $REQ is not a directory." >&2 fi unset REQ }
First check to see whether an argument was given by setting REQ to the value of $1. If no argument was given, assume that the user means the current directory.
Then check to see whether the requested directory is really a directory. If it is, change to that directory and then update the directory stack with the full path of the new directory. You cannot use the value in $REQ because it could be a relative path.
Finally print the contents of the stack by calling the dirs function. By doing this, this function does not have to know how to print the stack. You have to know that dirs prints the stack.
This enables you to change the implementation of a function, such as dirs, without affecting the other functions. The one thing to keep in mind is that if you change the arguments that a function, such as dirs, expects to receive, you must change all the other functions that use it. Otherwise, you might encounter strange errors and bugs.
The three important points here are
The popd() function is far more complicated than the other two. First look at the operations that it performs:
In order to make the first and second operations easy, implement a helper function for popd() called _popd_helper(). This function performs all the work; popd() is simply a wrapper around it. Frequently, you need to write functions in this manner: one function that simplifies the interface and one that performs the work.
The Helper Function
Look at _popd_helper first to see how the directory stack is manipulated:
_popd_helper() { # set the directory to pop to the first argument, if # this directory is empty, issue an error and return 1 # otherwise get rid of POPD from the arguments POPD="$1" if [ -z "$POPD" ] ; then echo "ERROR: The directory stack is empty." >&2 return 1 fi shift # if any more arguments remain, reinitalize the directory # stack, and then update it with the remaining items, # otherwise set the directory stack to null if [ -n "$1" ] ; then _DIR_STACK="$1" ; shift ; for i in $@ ; do _DIR_STACK="$_DIR_STACK:$i" ; done else _DIR_STACK= fi # if POPD is a directory cd to it, otherwise issue # an error message if [ -d "$POPD" ] ; then cd "$POPD" > /dev/null 2>&1 if [ $? -ne 0 ] ; then echo "ERROR: Could not cd to $POPD." >&2 fi pwd else echo "ERROR: $POPD is not a directory." >&2 fi export _DIR_STACK unset POPD }
This function expects the directory stack to be given to it as arguments, so the first thing that it checks is whether $1, the first argument, has any value. Do this by setting the variable POPD equal to $1 and then checking the contents of POPD.
If the directory stack is empty, issue an error message; otherwise, shorten the stack by using shift. At this point, you have taken care of the first operation.
Now, you have to check to see whether the directory stack is empty. Because the individual items in the stack are arguments to this function, you need to check whether $1, the new first argument, has any content. If it does, reinitialize the directory stack with this value and proceed to add all the remaining values back onto the stack. At this point, you have taken care of the second operation.
The last two operations are fairly trivial, and the last if statement takes care of them.
The Wrapper Function
Now that you know that the helper function expects all the directories on the stack to be given to it as arguments, you can write the wrapper function that translates the value of _DIR_STACK into separate arguments.
This process is fairly easy, thanks to the IFS trick. The popd() function is the following:
popd() { OLDIFS="$IFS" IFS=: _popd_helper $_DIR_STACK IFS="$OLDIFS" }
Previous | Table of Contents | Next |