#!/usr/bin/env bash

usage() {
    echo "----------------------------------------------------------------------"
    grep -i version "$SAGE_LOCAL/bin/sage-banner"
    echo "----------------------------------------------------------------------"
    echo
    ####  1.......................26..................................................78
    ####  |.....................--.|...................................................|
    echo "Optional arguments:"
    echo "  file.<sage|py|spyx> -- run given .sage, .py or .spyx files"
    echo "  -advanced           -- list all command line options"
    echo "  -c <cmd>            -- Evaluates cmd as sage code"
    echo "  -gap [...]          -- run Sage's Gap with given arguments"
    echo "  -gp [...]           -- run Sage's PARI/GP calculator with given arguments"
    echo "  -h, -?              -- print this help message"
    echo "  -inotebook [...]    -- start the *insecure* Sage notebook"
    echo "  -maxima [...]       -- run Sage's Maxima with given arguments"
    echo "  -mwrank [...]       -- run Sage's mwrank with given arguments"
    echo "  -n, -notebook [...] -- start the Sage notebook (options are the same"
    echo "                         as for the notebook command in Sage)"
    echo "  -python [...]       -- run the Python interpreter"
    echo "  -R [...]            -- run Sage's R with given arguments"
    echo "  -singular [...]     -- run Sage's singular with given arguments"
    echo "  -sqlite3 [...]      -- run Sage's sqlite3 with given arguments"
    echo "  -root               -- print the Sage root directory"
    echo "  --nodotsage         -- run Sage without using the user's .sage directory:"
    echo "                         create and use a temporary .sage directory instead"
    echo "  -t [options] <files|dir>"
    echo "                      -- test examples in .py, .pyx, .sage or .tex files"
    echo "                         options:"
    echo "                           -long  -- include lines with the phrase 'long time'"
    echo "                           -verbose  -- print debugging output during the test"
    echo "                           -optional  -- also test all #optional examples"
    echo "                           -only-optional <tag1,...,tagn>  -- only run tests"
    echo "                            including one of the #optional tags"
    echo "                           -randorder[=seed]  -- randomize order of tests"
    echo "  -testall [options]  -- test all source files, docs, and examples.  options"
    echo "                         like -t"
    echo "  -v, -version        -- print the Sage version"
    exit 0
}

usage_advanced() {
    echo "----------------------------------------------------------------------"
    grep -i version "$SAGE_LOCAL/bin/sage-banner"
    echo "----------------------------------------------------------------------"
    echo
    ####  1.......................26..................................................78
    ####  |.....................--.|...................................................|
    echo "Running Sage:"
    echo "  file.[sage|py|spyx] -- run given .sage, .py or .spyx files"
    echo "  -advanced           -- print this advanced help message"
    echo "  -c <cmd>            -- Evaluates cmd as sage code"
    echo "  -h, -?              -- print short help message"
    echo "  -min [...]          -- do not populate global namespace (must be first"
    echo "                         option)"
    echo "  -np                 -- run with no output prompts (useful for making"
    echo "                         doctests)"
    echo "  -preparse <file.sage> -- preparse file.sage and produce corresponding file.sage.py"
    echo "  -q                  -- quiet; start with no banner"
    echo "  -root               -- print the Sage root directory"
    echo "  -gthread, -qthread, -q4thread, -wthread, -pylab"
    echo "                      -- pass the option through to ipython"
    echo "  -v, -version        -- print the Sage version"

    echo
    ####  1.......................26..................................................78
    ####  |.....................--.|...................................................|
    echo "Running the notebook:"
    echo "  -inotebook [...]    -- start the *insecure* Sage notebook"
    echo "  -n, -notebook [...] -- start the Sage notebook (options are the same"
    echo "                         as for the notebook command in Sage)"

    echo
    ####  1.......................26..................................................78
    ####  |.....................--.|...................................................|
    echo "Running external programs:"
    echo "  -cleaner            -- run the Sage cleaner"
    echo "  -cython [...]       -- run Cython with given arguments"
    echo "  -ecl [...]          -- run Common Lisp"
    echo "  -gap [...]          -- run Sage's Gap with given arguments"
    echo "  -gdb                -- run Sage under the control of gdb"
    echo "  -gdb-ipython        -- run Sage's IPython under the control of gdb"
    echo "  -gp [...]           -- run Sage's PARI/GP calculator with given arguments"
    echo "  -ipython [...]      -- run Sage's IPython using the default environment (not"
    echo "                         Sage), passing additional options to IPython"
    echo "  -kash [...]         -- run Sage's Kash with given arguments"
    test -x "$SAGE_LOCAL/bin/kash" || \
    echo "                         (not installed currently, run sage -i kash)"
    echo "  -lisp [...]         -- run Lisp interpreter included with Sage"
    echo "  -M2 [...]           -- run Sage's Macaulay2 with given arguments"
    test -x "$SAGE_LOCAL/bin/M2" || \
    echo "                         (not installed currently, run sage -i macaulay2)"
    echo "  -maxima [...]       -- run Sage's Maxima with given arguments"
    echo "  -mwrank [...]       -- run Sage's mwrank with given arguments"
    echo "  -python [...]       -- run the Python interpreter"
    echo "  -R [...]            -- run Sage's R with given arguments"
    echo "  -sh [...]           -- run \$SHELL ($SHELL) with Sage environment variables"
    echo "  -singular [...]     -- run Sage's singular with given arguments"
    echo "  -sqlite3 [...]      -- run Sage's sqlite3 with given arguments"
    echo "  -twistd [...]       -- run Twisted server"

    echo
    ####  1.......................26..................................................78
    ####  |.....................--.|...................................................|
    echo "Documentation:"
    echo "  -coverage <files>   -- give info about doctest coverage of files"
    echo "  -coverageall        -- give summary info about doctest coverage of all"
    echo "                         files in the Sage library"
    echo "  -search_src <string> -- search through all the Sage library code for string"
    echo "  -search_doc <string> -- search through the Sage documentation for string"
    echo "  -grep <string>      -- same as -search_src"
    echo "  -grepdoc <string>   -- same as -search_doc"

    echo
    ####  1.......................26..................................................78
    ####  |.....................--.|...................................................|
    echo "File conversion:"
    echo "  -rst2txt [...]      -- Generates Sage worksheet text file from standalone"
    echo "                         reStructuredText source."
    echo "  -rst2sws [...]      -- Generates Sage worksheet (.sws) from standalone"
    echo "                         reStructuredText source."

    echo
    ####  1.......................26..................................................78
    ####  |.....................--.|...................................................|
    echo "Valgrind memory debugging:"
    echo "  -cachegrind         -- run Sage using Valgrind's cachegrind tool.  The log"
    echo "                         files are named sage-cachegrind.PID can be found in"
    echo "                         $DOT_SAGE"
    echo "  -callgrind          -- run Sage using Valgrind's callgrind tool.  The log"
    echo "                         files are named sage-callgrind.PID can be found in"
    echo "                         $DOT_SAGE"
    echo "  -massif             -- run Sage using Valgrind's massif tool.  The log"
    echo "                         files are named sage-massif.PID can be found in"
    echo "                         $DOT_SAGE"
    echo "  -memcheck           -- run Sage using Valgrind's memcheck tool.  The log"
    echo "                         files are named sage-memcheck.PID can be found in"
    echo "                         $DOT_SAGE"
    echo "  -valgrind           -- this is an alias for -memcheck"
    echo
    echo "You can also use -- before a long option, e.g., 'sage --optional'."
    echo
    exit 0
}

# Save the current directory, so we can change back after startup
# If pwd fails, we fall back to SAGE_ROOT
CUR=`pwd` || CUR="$SAGE_ROOT"
export CUR

cd "$SAGE_ROOT"

# Check for '--nodotsage' before sourcing sage-env; otherwise sage-env
# will already have set some environment variables with the old
# setting for DOT_SAGE.
if [ "$1" = '--nodotsage' ]; then
    export DOT_SAGE=`mktemp -d ${TMPDIR:-/tmp}/dotsageXXXXXX`
    shift
    command "$0" "$@"
    status=$?
    rm -rf "$DOT_SAGE"
    exit $status
fi

# Sage startup script passes some funny options, which are
# best ignored.
if [ $# -eq 3 ]; then
   if [ "$1" = '-i' -a "$2" = '-colors' ]; then
       shift
       shift
       shift
   fi
fi

if [ $# -gt 0 ]; then
  if [ "$1" = '-h' -o "$1" = '-?' -o "$1" = '-help' -o "$1" = '--help' ]; then
     usage
  fi
  if [ "$1" = "-advanced" -o "$1" = "--advanced" ]; then
     usage_advanced
  fi
fi


LOGFILE="$DOT_SAGE/sage.log"
LOGOPT=""

sage_setup() {
    # Display the startup banner
    if [ "$SAGE_BANNER" != "no" ]; then
        cat "$SAGE_LOCAL/bin/sage-banner"
    fi

    cd "$SAGE_ROOT/local/bin"
    IPYTHONDIR="$DOT_SAGE/ipython" && export IPYTHONDIR
    IPYTHONRC="ipythonrc" && export IPYTHONRC
    if [ ! -d "$IPYTHONDIR" ]; then
        mkdir -p "$DOT_SAGE"
        cp -r "$SAGE_ROOT/ipython" "$DOT_SAGE/"
    fi
    sage-cleaner &>/dev/null &
}


# Below the command
# _=sage.misc.interpreter.do_prefilter_paste('',False)

# It is very important in the following assignments
# that there is no whitespace after the backslashes.

if [ $# -gt 0 ]; then
    if [ "$1" = "-np" ]; then
       LOGOPT="-prompt_out=\\r $LOGOPT"
       shift
    fi
fi

sage() {
    sage_setup
    sage-ipython "$@" -i
}

if [ $# -eq 0 ]; then
    sage
    exit $?
fi

if [ "$1" = '-cleaner' -o "$1" = '--cleaner' ]; then
    sage-cleaner
    exit $?
fi

if [ "$1" = '-min' -o "$1" = '--min' ]; then
    SAGE_IMPORTALL="no"
    export SAGE_IMPORTALL
    shift
    exec sage "$@"
fi

#####################################################################
# Report information about the Sage environment
#####################################################################

if [ "$1" = '-v' -o "$1" = '-version' -o "$1" = '--version' ]; then
    sed -n -e '/Version/s/^[ |]\{1,\}//;/Version/s/[ |]\{1,\}$//p' \
        "$SAGE_LOCAL"/bin/sage-banner
    exit $?
fi

if [ "$1" = '-root'  -o "$1" = '--root' ]; then
    echo "$SAGE_ROOT"
    exit 0
fi

#####################################################################
# Run Sage's versions of the standard Algebra/Geometry etc. software
#####################################################################

if [ "$1" = '-axiom' -o "$1" = '--axiom' ]; then
    cd "$CUR"
    shift
    axiom "$@"
    exit $?
fi

if [ "$1" = '-gap' -o "$1" = '--gap' ]; then
    cd "$CUR"
    shift
    gap "$@"
    exit $?
fi

if [ "$1" = '-gp'  -o "$1" = '--gp' ]; then
    cd "$CUR"
    shift
    gp "$@"
    exit $?
fi

if [ "$1" = '-singular'  -o "$1" = '--singular' ]; then
    cd "$CUR"
    shift
    singular "$@"
    exit $?
fi

if [ "$1" = '-sqlite3'  -o "$1" = '--sqlite3' ]; then
    cd "$CUR"
    shift
    sqlite3 "$@"
    exit $?
fi

if [ "$1" = '-twistd'  -o "$1" = '--twistd' ]; then
    cd "$CUR"
    shift
    python $(which twistd) "$@"
    exit $?
fi

if [ "$1" = '-ecl'  -o "$1" = '--ecl' ]; then
    cd "$CUR"
    shift
    ecl "$@"
    exit $?
fi

if [ "$1" = '-lisp'  -o "$1" = '--lisp' ]; then
    cd "$CUR"
    shift
    ecl "$@"
    exit $?
fi

if [ "$1" = '-kash'  -o "$1" = '--kash' ]; then
    cd "$CUR"
    shift
    kash "$@"
    exit $?
fi

if [ "$1" = '-maxima'  -o "$1" = '--maxima' ]; then
    cd "$CUR"
    shift
    maxima "$@"
    exit $?
fi

if [ "$1" = '-mwrank'  -o "$1" = '--mwrank' ]; then
    cd "$CUR"
    shift
    mwrank "$@"
    exit $?
fi

if [ "$1" = '-M2'  -o "$1" = '--M2' ]; then
    cd "$CUR"
    shift
    M2 "$@"
    exit $?
fi

if [ "$1" = '-python'  -o "$1" = '--python' ]; then
    cd "$CUR"
    shift
    python "$@"
    exit $?
fi

if [ "$1" = '-R'  -o "$1" = '--R' ]; then
    cd "$CUR"
    shift
    R "$@"
    exit $?
fi

if [ "$1" = '-ipython'  -o "$1" = '--ipython' ]; then
    cd "$CUR"
    shift
    ipython "$@"
    exit $?
fi

if [ "$1" = '-sh'  -o "$1" = '--sh' ]; then
    # AUTHORS:
    # - Carl Witty and William Stein: initial version
    # - Craig Citro: add options for not loading profile
    # - Martin Albrecht: fix zshell prompt (#11866)
    # - John Palmieri: shorten the prompts, and don't print messages if
    #   there are more arguments to 'sage -sh' (#11790)
    cd "$CUR"
    shift
    # If $SHELL is unset, default to bash
    if [ -z "$SHELL" ]; then
        export SHELL=bash
    fi
    # We must start a new shell with no .profile or .bashrc files
    # processed, so that we know our path is correct
    SHELL_NAME=`basename "$SHELL"`
    # Check for SAGE_SHPROMPT.  If defined, use for the prompt.  If
    # not, check for already-defined $PS1, and if defined use that.
    # $PS1 should only be available if it is defined in
    # $DOT_SAGE/sagerc.
    if [ -n "$SAGE_SHPROMPT" ]; then
        oldPS1=$SAGE_SHPROMPT
    elif [ -n "$PS1" ]; then
        oldPS1=$PS1
    fi
    # Set the default prompt.  If available, use reverse video to
    # highlight the string "(sage-sh)".
    if tput rev &>/dev/null; then
        color_prompt=yes
    fi
    case "$SHELL_NAME" in
        bash)
            SHELL_OPTS="--norc"
            if [ "$color_prompt" = yes ]; then
                PS1="\[$(tput rev)\](sage-sh)\[$(tput sgr0)\] \u@\h:\W\$ "
            else
                PS1="(sage-sh) \u@\h:\w\$ "
            fi
            export PS1
            ;;
        csh)
            # csh doesn't seem to allow the specification of a different
            # .cshrc file, and the prompt can only be set in this file, so
            # don't bother changing the prompt.
            SHELL_OPTS="-f"
            ;;
        ksh)
            SHELL_OPTS="-p"
            if [ "$color_prompt" = yes ] ; then
                PS1="$(tput rev)(sage-sh)$(tput sgr0) $USER@`hostname -s`:\${PWD##*/}$ "
            else
                PS1="(sage-sh) $USER@`hostname -s`:\${PWD##*/}$ "
            fi
            export PS1
            ;;
        sh)
            # We don't really know which shell "sh" is (it could be
            # bash, but this is not guaranteed), so we don't set
            # SHELL_OPTS.
            if [ "$color_prompt" = yes ] ; then
                PS1="$(tput rev)(sage-sh)$(tput sgr0) $USER@`hostname -s`:\${PWD##*/}$ "
            else
                PS1="(sage-sh) $USER@`hostname -s`:\${PWD}$ "
            fi
            export PS1
            ;;
        tcsh)
            # tcsh doesn't seem to allow the specification of a different
            # .tcshrc file, and the prompt can only be set in this file, so
            # don't bother changing the prompt.
            SHELL_OPTS="-f"
            ;;
        zsh)
            PS1="%S(sage-sh)%s %n@%m:%~$ "
            # In zsh, the system /etc/zshenv is *always* run,
            # and this may change the path (like on OSX), so we'll 
            # create a temporary .zshenv to reset the path
            ZDOTDIR=$DOT_SAGE && export ZDOTDIR
            cat >"$ZDOTDIR/.zshenv" <<EOF
PATH="$PATH" && export PATH
EOF
            SHELL_OPTS=" -d"
            export PS1
            ;;
        *)
            export PS1='(sage-sh) $ '
            ;;
    esac
    if [ -n "$oldPS1" ]; then
        PS1="$oldPS1"
        export PS1
    fi
    if [ $# -eq 0 ]; then
        # No arguments, so print informative message...
        echo >&2
        echo >&2 "Starting subshell with Sage environment variables set.  Don't forget"
        echo >&2 "to exit when you are done.  Beware:"
        echo >&2 " * Do not do anything with other copies of Sage on your system."
        echo >&2 " * Do not use this for installing Sage packages using \"sage -i\" or for"
        echo >&2 "   running \"make\" at Sage's root directory.  These should be done"
        echo >&2 "   outside the Sage shell."
        echo >&2
        if [ -n "$SHELL_OPTS" ]; then
            echo >&2 "Bypassing shell configuration files..."
            echo >&2
        fi
        echo >&2 "Note: SAGE_ROOT=$SAGE_ROOT"
        "$SHELL" $SHELL_OPTS "$@"
        status=$?
        echo "Exited Sage subshell." 1>&2
    else
        exec "$SHELL" $SHELL_OPTS "$@"
        # If 'exec' returns, an error occurred:
        status=$?
        echo >&2 "Fatal error: 'exec \"$SHELL\" \"$@\"' failed!"
    fi
    exit $status
fi

if [ "$1" = '-gdb-ipython'  -o "$1" = '--gdb-ipython' ]; then
    cd "$CUR"
    shift
    sage-gdb-ipython "$@"
    exit $?
fi

#####################################################################
# Test coverage of a module?
#####################################################################

if [ "$1" = "-coverage" -o "$1" = "--coverage" ]; then
   cd "$CUR"
   shift
   sage-coverage "$@"
   exit $?
fi

if [ "$1" = "-coverageall" -o "$1" = "--coverageall" ]; then
   cd "$CUR"
   shift
   sage-coverageall "$@"
   exit $?
fi

#####################################################################
# File conversion
#####################################################################

if [ "$1" = '-rst2txt' -o "$1" = '--rst2txt' ]; then
    cd "$CUR"
    shift
    sage-rst2txt "$@"
    exit $?
fi

if [ "$1" = '-rst2sws' -o "$1" = '--rst2sws' ]; then
    cd "$CUR"
    shift
    sage-rst2sws "$@"
    exit $?
fi

#####################################################################
# Run Sage's versions of the standard Algebra/Geometry etc. software
#####################################################################

if [ "$1" = "-notebook"  -o "$1" = '--notebook' -o "$1" = '-n' ]; then
   cd "$CUR"
   shift
   sage-cleaner &>/dev/null &
   sage-notebook "$@"
   exit $?
fi

if [ "$1" = "-inotebook"  -o "$1" = '--inotebook' ]; then
   cd "$CUR"
   shift
   sage-cleaner &>/dev/null &
   sage-notebook-insecure "$@"
   exit $?
fi

if [ "$1" = "-log" -o "$1" = "--log" ]; then
   sage-log
   exit 0
fi

if [ "$1" = '-grep' -o "$1" = "--grep" -o "$1" = "-search_src" -o "$1" = "--search_src" ]; then
   SAGE_BANNER="no"
   sage_setup
   shift
   sage-grep "$@"
   exit 0
fi

if [ "$1" = '-grepdoc' -o "$1" = "--grepdoc" -o "$1" = "-search_doc" -o "$1" = "--search_doc" ]; then
   SAGE_BANNER="no"
   sage_setup
   shift
   sage-grepdoc "$@"
   exit 0
fi

if [ "$1" = '-q' ]; then
   SAGE_BANNER="no"
   sage_setup
   shift
   sage "$@"
   exit $?
fi

if [ "$1" = '-t' ]; then
   if ! [  -f  "$DOT_SAGE"/init.sage ]; then
      echo >&2 "init.sage does not exist ... creating"
      touch "$DOT_SAGE"/init.sage
   fi
   cd "$CUR"
   shift
   sage-test "$@"
   exit $?
fi

if [ "$1" = '-tp' ]; then
   if ! [  -f  "$DOT_SAGE"/init.sage ]; then
      echo >&2 "init.sage does not exist ... creating"
      touch "$DOT_SAGE"/init.sage
   fi
   cd "$CUR"
   shift
   sage-ptest "$@"
   exit $?
fi

if [ "$1" = '-tnew' ]; then
   cd "$CUR"
   shift
   sage-test-new "$@"
   exit $?
fi

if [ "$1" = '-testall' -o "$1" = "--testall" ]; then
   shift
   sage-maketest "$@"
   exit $?
fi

if [ "$1" = '-c' ]; then
   cd "$CUR"
   shift
   SAGE_BANNER="no"
   sage_setup
   unset TERM  # See Trac #12263
   sage-eval "$@"
   exit $?
fi

if [ "$1" = '-gdb' -o "$1" = "--gdb" ]; then
    sage_setup
    sage-gdb
    exit $?
fi

if [ "$1" = '-preparse' -o "$1" = "--preparse" ]; then
    shift
    cd "$SAGE_LOCAL/bin/"
    sage-preparse "$CUR" "$@"
    exit $?
fi

if [ "$1" = "-cython" -o "$1" = '--cython' -o "$1" = '-pyrex' -o "$1" = "--pyrex" ]; then
    shift
    cd "$CUR"
    sage-cython "$@"
    exit $?
fi

if [ "$1" = '-valgrind' -o "$1" = "--valgrind" -o "$1" = '-memcheck' -o "$1" = "--memcheck" ]; then
    sage_setup
    sage-valgrind
    exit $?
fi

if [ "$1" = '-massif' -o "$1" = "--massif" ]; then
    sage_setup
    sage-massif
    exit $?
fi

if [ "$1" = '-cachegrind' -o "$1" = "--cachegrind" ]; then
    sage_setup
    sage-cachegrind
    exit $?
fi

if [ "$1" = '-callgrind' -o "$1" = "--callgrind" ]; then
    sage_setup
    sage-callgrind
    exit $?
fi

if [ "$1" = '-startuptime' -o "$1" = '--startuptime' ]; then
    python "$SAGE_LOCAL"/bin/sage-startuptime.py
    exit $?
fi
if [ "$1" = '-gthread' -o "$1" = '-qthread' -o "$1" = '-q4thread' -o "$1" = '-wthread' -o "$1" = '-pylab' ]; then
    sage "$1"
    exit $?
fi

if [ $# -ge 1 ]; then
   T=`echo "$1" | sed -e "s/.*\.//"`
   if [ "$T " = "spkg " ]; then
       install "" "$@"
       exit $?
   fi
   cd "$SAGE_LOCAL/bin/"
   SAGE_BANNER="no"
   sage_setup 
   unset TERM  # See Trac #12263
   sage-run "$CUR" "$@"
   exit $?
fi
