Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
3-manifolds
GitHub Repository: 3-manifolds/Sage_macOS
Path: blob/main/Sage_framework/files/sage
173 views
#!/usr/bin/env bash

# WARNING: this function is copy/pasted from both src/bin/sage-env and
# the top-level "sage" script. Please keep them synchronized.
resolvelinks() {
    # $in is what still needs to be converted (normally has no starting slash)
    in="$1"
    # $out is the part which is converted (normally ends with trailing slash)
    out="./"

    # Move stuff from $in to $out
    while [ -n "$in" ]; do
        # Normalize $in by replacing consecutive slashes by one slash
        in=$(echo "${in}" | sed 's://*:/:g')

        # If $in starts with a slash, remove it and set $out to the root
        in_without_slash=${in#/}
        if [ "$in" != "$in_without_slash" ]; then
            in=$in_without_slash
            out="/"
            continue
        fi

        # Check that the directory $out exists by trying to cd to it.
        # If this fails, then cd will show an error message (unlike
        # test -d "$out"), so no need to be more verbose.
        ( cd "$out" ) || return $?


        # Get the first component of $in
        f=${in%%/*}

        # If it is not a symbolic link, simply move it to $out
        if [ ! -L "$out$f" ]; then
            in=${in#"$f"}
            out="$out$f"

            # If the new $in starts with a slash, move it to $out
            in_without_slash=${in#/}
            if [ "$in" != "$in_without_slash" ]; then
                in=$in_without_slash
                out="$out/"
            fi
            continue
        fi

        # Now resolve the symbolic link "$f"
        f_resolved=`readlink -n "$out$f" 2>/dev/null`
        status=$?
        # status 127 means readlink could not be found.
        if [ $status -eq 127 ]; then
            # We don't have "readlink", try a stupid "ls" hack instead.
            # This will fail if we have filenames like "a -> b".
            fls=`ls -l "$out$f" 2>/dev/null`
            status=$?
            f_resolved=${fls##*-> }

            # If $fls equals $f_resolved, then certainly
            # something is wrong
            if [ $status -eq 0 -a "$fls" = "$f_resolved" ]; then
                echo >&2 "Cannot parse output from ls -l '$out$f'"
                return 1
            fi
        fi
        if [ $status -ne 0 ]; then
            echo >&2 "Cannot read symbolic link '$out$f'"
            return $status
        fi

        # In $in, replace $f by $f_resolved (leave $out alone)
        in="${in#${f}}"
        in="${f_resolved}${in}"
    done

    # Return $out
    echo "$out"
}

# Resolve the links in $0 so that local/bin/sage can be executed from
# a symlink (Issue #30888).
SELF=$(resolvelinks "${0}")

#####################################################################
# Set up the version-specific symlink in /var/tmp (macOS)
#####################################################################

SAVED_CWD="`pwd`"
CURDIR=$(resolvelinks "`dirname $0`")
cd "$CURDIR/../../../../../../"
VERSION_DIR="`pwd`"
cd "$SAVED_CWD"
runpath_sh=$VERSION_DIR/local/var/lib/sage/runpath.sh
if [ -x "$runpath_sh" ]; then
    . "$runpath_sh"
else
    echo >&2 "Could not find runpath.sh."
    echo >&2 "The SageMath symlink is probably misconfigured."    
fi

# Check that the installation specific symlink points to this sage
# root directory.  If not, try to reset it.  Strangely, this script
# can get called a second time and when that happens we will have
# $TARGET == $SAGE_SYMLINK.  We had better not set the symlink to
# point to itself!

if [ -L $SAGE_SYMLINK ] || ! [ -e $SAGE_SYMLINK ]; then
    OLD_VERSION_DIR=`readlink $SAGE_SYMLINK`
    if [ "$VERSION_DIR" != "$OLD_VERSION_DIR" ] && [ "$VERSION_DIR" != "$SAGE_SYMLINK" ]; then
        rm -f $SAGE_SYMLINK 2> /dev/null
        if [ $? -ne 0 ]; then
            OWNER=$(stat -f '%Su' $SAGE_SYMLINK)
            echo
            echo "Oh no!"
            echo "You do not have permission to reconfigure this SageMath."
            echo "Please ask $OWNER to open the app."
            echo
            read -p "The app will exit when you press a key."
            exit
        fi
        if [ "$VERSION_DIR" != "$SAGE_SYMLINK" ]; then 
            ln -s "$VERSION_DIR" "$SAGE_SYMLINK"
        fi
    fi
fi

# Display the current version of Sage
# usage: sage_version [-v]
#   -v    display the full version banner including release date
sage_version() {
    if [ -f "${SELF}-version.sh" ]; then
        . "${SELF}-version.sh"
    else
        . "$SAGE_ROOT/src/bin/sage-version.sh"
    fi

    if [ "$1" = "-v" ]; then
        echo "${SAGE_VERSION_BANNER}"
    else
        echo "${SAGE_VERSION}"
    fi
}

usage() {
    sage_version -v
    ####  1.......................26..................................................78
    ####  |.....................--.|...................................................|
    echo
    echo "Running Sage:"
    if command -v sage-ipython &>/dev/null; then
        echo
        echo "  file.[sage|py|spyx] -- run given .sage, .py or .spyx file"
        echo "  -c <cmd>            -- evaluate cmd as sage code"
        echo "  --notebook=[...]    -- start the Sage notebook (valid options are"
        echo "                         'default', 'jupyter', 'jupyterlab', and 'export')"
        echo "                         Current default is 'jupyter'"
        echo "  -n, --notebook      -- shortcut for --notebook=default"
        echo "  --nodotsage         -- run Sage without using the user's .sage directory:"
        echo "                         create and use a temporary .sage directory instead"
        echo "  -t [options] <--all|files|dir>"
        echo "                      -- test examples in .py, .pyx, .sage, .tex or .rst files"
        echo "                         selected options:"
        echo "                           --long - include lines with the phrase 'long time'"
        echo "                           --verbose - print debugging output during the test"
        echo "                           --optional - controls which optional tests are run"
        echo "                           --help - show all testing options"
    else
        echo "                         (not installed currently, "
        echo "                          to install, run sage --pip install sagemath-repl)"
    fi
    echo
    echo "Running external programs:"
    echo
    command -v gap &>/dev/null && \
    echo "  --gap [...]         -- run Sage's Gap with given arguments"
    command -v gp &>/dev/null && \
    echo "  --gp [...]          -- run Sage's PARI/GP calculator with given arguments"
    echo "  --pip [...]         -- invoke pip, the Python package manager"
    command -v maxima &>/dev/null && \
    echo "  --maxima [...]      -- run Sage's Maxima with given arguments"
    command -v mwrank &>/dev/null && \
    echo "  --mwrank [...]      -- run Sage's mwrank with given arguments"
    echo "  --python [...], --python3 [...] -- run the Python 3 interpreter"
    command -v R &>/dev/null && \
    echo "  -R [...]            -- run Sage's R with given arguments"
    command -v singular &>/dev/null && \
    echo "  --singular [...]    -- run Sage's singular with given arguments"
    echo
    echo "Getting help:"
    echo
    echo "  -v, --version       -- display Sage version information"
    echo "  -h, -?, --help      -- print this help message"
    echo "  --advanced          -- list all command line options"
    if [ -d "$SAGE_ROOT" ]; then
        exec "$SAGE_ROOT/build/bin/sage-site" "-h"
    fi
    exit 0
}

# 'usage_advanced', which prints a longer help message, is defined
# below, after sourcing sage-env.

# Determine SAGE_ROOT, SAGE_LOCAL, and SAGE_VENV.
unset SAGE_VENV
if [ -x "${SELF}-config" ]; then
    # optional sage-config console script, installed by sage_conf
    export SAGE_ROOT=$("${SELF}-config" SAGE_ROOT)
    export SAGE_LOCAL=$("${SELF}-config" SAGE_LOCAL)
fi
if [ -f "${SELF}-src-env-config" ]; then
    # Not installed script, present only in src/bin/
    SAGE_SRC_ENV_CONFIG=1
    . "${SELF}-src-env-config" >&2
fi
if [ -z "$SAGE_VENV" -a -x "${SELF}-venv-config" ]; then
    # installed by setup.py
    export SAGE_VENV=$("${SELF}-venv-config" SAGE_VENV)
fi
if [ -f "${SELF}-env-config" ]; then
    # As of Issue #22731, sage-env-config is optional.
    . "${SELF}-env-config" >&2
fi

#####################################################################
# Special options to be processed without sage-env
#####################################################################

# 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 "${SELF}" "$@"
    status=$?
    rm -rf "$DOT_SAGE"
    exit $status
fi

# build_sage, sage -b, sage -br, etc. could also be moved to
# build/bin/sage-site. See #29111; but OTOH #34627.

build_sage() {
    ( cd "$SAGE_ROOT" && make sagelib-no-deps ) || exit $?
}

# Check for '-i' etc. before sourcing sage-env: running "make"
# should be run outside of the Sage shell.
if [ "$1" = '-f' ]; then
    # -f is an alias for -i -f
    set -- -i "$@"
fi
if [ "$1" = '-i' ]; then
    if [ -z "$2" ]; then
        PACKAGE="the package"
    else
        PACKAGE=$2 
    fi
    echo "Sorry, this binary distribution does not support installing sage packages."
    echo "If $PACKAGE is available from pypi you may install it by running"
    echo "    %pip install $PACKAGE"
    echo "from the sage prompt."
    exit 1
fi
#####################################################################
# Report information about the Sage environment
#####################################################################

if [ "$1" = '-dumpversion' -o "$1" = '--dumpversion' ]; then
        sage_version
        exit 0
fi

if [ "$1" = '-v' -o "$1" = '-version' -o "$1" = '--version' ]; then
        sage_version -v
        exit 0
fi

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


#####################################################################
# Source sage-env ($SELF is the name of this "sage" script, so we can just
# append -env to that). We redirect stdout to stderr, which is safer
# for scripts.
#####################################################################
if [ -f "${SELF}-env" ]; then
    . "${SELF}-env" >&2
    if [ $? -ne 0 ]; then
        echo >&2 "Error setting environment variables by sourcing '${SELF}-env';"
        echo >&2 "possibly contact sage-devel (see http://groups.google.com/group/sage-devel)."
        exit 1
    fi
fi

if [ -f "${SELF}-src-env-config.in" ]; then
    # The sage script is being run out of SAGE_ROOT/src/bin.
    # In this case, put this directory in the front of the PATH.
    export PATH="$SAGE_SRC/bin:$PATH"
fi

if [ -z "$DOT_SAGE" ]; then
    export DOT_SAGE="$HOME/.sage"
fi

#####################################################################
# Special environment variables used for the macOS app to prevent
# writing into the application bundle and breaking the signature.
# and to block warnings about using "if x is 1" and to find the
# Jupyter kernel.
#####################################################################
export PYTHONPYCACHEPREFIX="$DOT_SAGE/pycache"
export PIP_CONFIG_FILE="$SAGE_SYMLINK/Resources/pip.conf"
export PYTHONWARNINGS=ignore
if ! [ -e /usr/local/share/jupyter/kernels/SageMath-"$SAGE_VERSION"/kernel.json ]; then
    export JUPYTER_PATH=$SAGE_SYMLINK/Resources/jupyter
fi

#####################################################################
# Helper functions
#####################################################################

# Prepare for running Sage, either interactively or non-interactively.
sage_setup() {
    # Check that we're not in a source tarball which hasn't been built yet (#13561).
    if [ "$SAGE_SRC_ENV_CONFIG" = 1 ] && [ ! -z "$SAGE_VENV" ] && [ ! -x "$SAGE_VENV/bin/sage" ]; then
        echo >&2 '************************************************************************'
        echo >&2 'It seems that you are attempting to run Sage from an unpacked source'
        echo >&2 'tarball, but you have not compiled it yet (or maybe the build has not'
        echo >&2 'finished). You should run `make` in the SAGE_ROOT directory first.'
        echo >&2 'If you did not intend to build Sage from source, you should download'
        echo >&2 'a binary tarball instead. Read README.txt for more information.'
        echo >&2 '************************************************************************'
        exit 1
    fi

    if [ ! -d "$IPYTHONDIR" ]; then
        # make sure that $DOT_SAGE exists so that ipython will happily
        # create its config directories there.  If DOT_SAGE doesn't
        # exist, ipython complains.
        mkdir -p -m 700 "$DOT_SAGE"
    fi
    sage-cleaner &>/dev/null &
}


# Start an interactive Sage session, this function never returns.
interactive_sage() {
    sage_setup
    exec sage-ipython "$@" -i
}

#####################################################################
# sage --advanced
#####################################################################

usage_advanced() {
    sage_version -v
    ####  1.......................26..................................................78
    ####  |.....................--.|...................................................|
    echo
    if command -v sage-ipython &>/dev/null; then
        echo "Running Sage, the most common options:"
        echo
        echo "  file.[sage|py|spyx] -- run given .sage, .py or .spyx file"
        echo "  -c cmd              -- evaluate cmd as sage code. For example,"
        echo "                         \"sage -c 'print(factor(35))'\" will"
        echo "                         print \"5 * 7\"."
        echo
        echo "Running Sage, other options:"
        echo
        echo "  --preparse file.sage -- preparse \"file.sage\", and produce"
        echo "                          the corresponding Python file"
        echo "                          \"file.sage.py\""
        echo "  -q                  -- quiet; start with no banner"
        echo "  --min               -- do not populate global namespace"
        echo "                         (must be first option)"
        echo "  --nodotsage         -- run Sage without using the user's"
        echo "                         .sage directory: create and use a temporary"
        echo "                         .sage directory instead."
        echo "  --gthread, --qthread, --q4thread, --wthread, --pylab"
        echo "                      -- pass the option through to IPython"
        echo "  --simple-prompt     -- pass the option through to IPython: use"
        echo "                         this option with sage-shell mode in emacs"
        echo "  --gdb               -- run Sage under the control of gdb"
        echo "  --lldb              -- run Sage under the control of lldb"
    else
        echo "Running Sage:"
        echo "                         (not installed currently, "
        echo "                          to install, run sage --pip install sagemath-repl)"
    fi
    echo
    echo "Running external programs:"
    echo
    echo "  --cython [...]      -- run Cython with the given arguments"
    command -v cython &>/dev/null || \
    echo "                         (not installed, run sage --pip install cython)"
    echo "  --ecl [...], --lisp [...]  -- run Sage's copy of ECL (Embeddable"
    echo "                                Common Lisp) with the given arguments"
    echo "  --gap [...]         -- run Sage's Gap with the given arguments"
    echo "  --gap3 [...]        -- run Sage's Gap3 with the given arguments"
    command -v gap3 &>/dev/null || \
    echo "                         (not installed currently, run sage -i gap3)"
    echo "  --git [...]         -- run Sage's Git with the given arguments"
    echo "  --gp [...]          -- run Sage's PARI/GP calculator with the"
    echo "                         given arguments"
    echo "  --ipython [...], --ipython3 [...]"
    echo "                      -- run Sage's IPython using the default"
    echo "                         environment (not Sage), passing additional"
    echo "                         additional options to IPython"
    echo "  --jupyter [...]     -- run Sage's Jupyter with given arguments"
    echo "  --kash [...]        -- run Sage's Kash with the given arguments"
    command -v kash &>/dev/null || \
    echo "                         (not installed currently, run sage -i kash)"
    echo "  --M2 [...]          -- run Sage's Macaulay2 with the given arguments"
    command -v M2 &>/dev/null || \
    echo "                         (not installed currently, run sage -i macaulay2)"
    echo "  --maxima [...]      -- run Sage's Maxima with the given arguments"
    echo "  --mwrank [...]      -- run Sage's mwrank with the given arguments"
    echo "  --pip [...]         -- invoke pip, the Python package manager"
    echo "  --polymake [...]    -- run Sage's Polymake with given arguments"
    command -v polymake &>/dev/null || \
    echo "                         (not installed currently, run sage -i polymake)"
    echo "  --python [...], --python3 [...]"
    echo "                      -- run the Python 3 interpreter"
    echo "  -R [...]            -- run Sage's R with the given arguments"
    echo "  --singular [...]    -- run Sage's singular with the given arguments"
    echo "  --sqlite3 [...]     -- run Sage's sqlite3 with given arguments"
    echo
    echo "Running the notebook:"
    echo
    echo "  -n [...], --notebook=[...]"
    echo "                      -- start the notebook; valid options include"
    echo "                         'default', 'jupyter', 'jupyterlab', and 'export'."
    echo "                         Current default is 'jupyter'."
    echo "                         Run \"sage --notebook --help\" for more details."
    echo
    ####  1.......................26..................................................78
    ####  |.....................--.|...................................................|
    echo
    echo "Some developer utilities:"
    echo
    if [ -n "$SAGE_SRC" -a -d "$SAGE_SRC" ]; then
        echo "  --grep [options] <string>"
        echo "                      -- regular expression search through the Sage"
        echo "                         library for \"string\". Any options will"
        echo "                         get passed to the \"grep\" command."
        echo "  --grepdoc [options] <string>"
        echo "                      -- regular expression search through the"
        echo "                         Sage documentation for \"string\"."
        echo "  --search_src ...    -- same as --grep"
        echo "  --search_doc ...    -- same as --grepdoc"
    fi
    echo "  --sh [...]         -- run a shell with Sage environment variables"
    echo "                        as they are set in the runtime of Sage"
    echo "  --cleaner          -- run the Sage cleaner.  This cleans up after Sage,"
    echo "                        removing temporary directories and spawned processes."
    echo "                        (This gets run by Sage automatically, so it is usually"
    echo "                        not necessary to run it separately.)"
    ####  1.......................26..................................................78
    ####  |.....................--.|...................................................|
    echo "File conversion:"
    echo
    echo "  --rst2ipynb [...]   -- Generates Jupyter notebook (.ipynb) from standalone"
    echo "                         reStructuredText source."
    command -v rst2ipynb &>/dev/null || \
    echo "                         (not installed currently, run sage -i rst2ipynb)"
    echo "  --ipynb2rst [...]   -- Generates a reStructuredText source file from"
    echo "                         a Jupyter notebook (.ipynb)."
    echo "  --sws2rst <sws doc> -- Generates a reStructuredText source file from"
    echo "                         a Sage worksheet (.sws) document."
    command -v sage-sws2rst >&/dev/null || \
    echo "                         (not installed currently, run sage -i sage_sws2rst)"
    echo
    ####  1.......................26..................................................78
    ####  |.....................--.|...................................................|
    echo "Getting help:"
    echo
    echo "  -v, --version       -- display Sage version information"
    echo "  --dumpversion       -- print brief Sage version"
    echo "  -h, -?, --help      -- print a short help message"
    echo "  --advanced          -- list all command line options"
    if [ -d "$SAGE_ROOT" ]; then
        exec "$SAGE_ROOT/build/bin/sage-site" "--advanced"
    fi
    echo
    exit 0
}

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


#####################################################################
# Running Sage
#####################################################################

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

if [ "$1" = '-q' ]; then
    shift
    export SAGE_BANNER=no
fi

if [ $# -eq 0 ]; then
    interactive_sage
fi

#####################################################################
# Other basic options
#####################################################################

if [ "$1" = '-c' ]; then
    shift
    sage_setup
    unset TERM  # See Issue #12263
    exec sage-eval "$@"
fi

if [ "$1" = '-preparse' -o "$1" = "--preparse" ]; then
    shift
    exec sage-preparse "$@"
fi

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

#####################################################################
# Run Sage's versions of Python, pip, IPython, Jupyter.
#####################################################################

if [ "$1" = '-pip' -o "$1" = '--pip' -o "$1" = "--pip3" ]; then
    shift
    exec python3 -m pip --disable-pip-version-check "$@"
fi

if [ "$1" = '-python' -o "$1" = '--python' -o  "$1" = '-python3' -o "$1" = '--python3' ]; then
    shift
    exec python3 "$@"
fi

if [ "$1" = '-ipython' -o "$1" = '--ipython' -o "$1" = '-ipython3' -o "$1" = '--ipython3' ]; then
    shift
    exec ipython3 "$@"
fi

if [ "$1" = '-jupyter' -o "$1" = '--jupyter' ]; then
    shift
    exec jupyter "$@"
fi

#####################################################################
# Run Sage's versions of its component packages
#####################################################################

if [ "$1" = "-cython" -o "$1" = '--cython' -o "$1" = '-pyrex' -o "$1" = "--pyrex" ]; then
    shift
    exec cython "$@"
fi

if [ "$1" = '-gap' -o "$1" = '--gap' ]; then
    shift
    # Use "-A" to avoid warnings about missing packages. The gap
    # interface and libgap within sage both already do this.
    exec gap -A "$@"
fi

if [ "$1" = '-gap3' -o "$1" = '--gap3' ]; then
    shift
    exec gap3 "$@"
fi

if [ "$1" = '-gp' -o "$1" = '--gp' ]; then
    shift
    exec gp "$@"
fi

if [ "$1" = '-polymake' -o "$1" = '--polymake' ]; then
    shift
    exec polymake "$@"
fi

if [ "$1" = '-singular' -o "$1" = '--singular' ]; then
    shift
    exec Singular "$@"
fi

if [ "$1" = '-sqlite3' -o "$1" = '--sqlite3' ]; then
    shift
    exec sqlite3 "$@"
fi

if [ "$1" = '-ecl' -o "$1" = '--ecl' ]; then
    shift
    exec ecl "$@"
fi

if [ "$1" = '-lisp' -o "$1" = '--lisp' ]; then
    shift
    exec ecl "$@"
fi

if [ "$1" = '-kash' -o "$1" = '--kash' ]; then
    shift
    exec kash "$@"
fi

if [ "$1" = '-maxima' -o "$1" = '--maxima' ]; then
    shift
    maxima_cmd=$(sage-config MAXIMA 2>/dev/null)
    if [ -z "${maxima_cmd}" ]; then
        maxima_cmd="maxima"
    fi
    exec $maxima_cmd "$@"
fi

if [ "$1" = '-mwrank' -o "$1" = '--mwrank' ]; then
    shift
    exec mwrank "$@"
fi

if [ "$1" = '-M2' -o "$1" = '--M2' ]; then
    shift
    exec M2 "$@"
fi

if [ "$1" = '-R' -o "$1" = '--R' ]; then
    shift
    exec R "$@"
fi

if [ "$1" = '-git' -o "$1" = '--git' ]; then
    shift
    exec git "$@"
fi

#####################################################################
# sage --sh and sage --buildsh
#####################################################################

if [ "$1" = '-sh' -o "$1" = '--sh' -o "$1" = '-buildsh' -o "$1" = '--buildsh' ]; 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)
    if [ -z "$SAGE_SHPROMPT_PREFIX" ]; then
        SAGE_SHPROMPT_PREFIX=sage-sh
    fi
    if [ "$1" = '-buildsh' -o "$1" = '--buildsh' ]; then
        if [ ! -r "$SAGE_ROOT"/build/bin/sage-build-env-config ]; then
           echo "error: '$SAGE_ROOT' does not contain build/bin/sage-build-env-config.  Run configure first."
           exit 1
        fi
        . "$SAGE_ROOT"/build/bin/sage-build-env-config || (echo "error:  Error sourcing $SAGE_ROOT/build/bin/sage-build-env-config"; exit 1)
        . "$SAGE_ROOT"/build/bin/sage-build-env || (echo "error:  Error sourcing $SAGE_ROOT/build/bin/sage-build-env"; exit 1)
        export SAGE_SHPROMPT_PREFIX=sage-buildsh
        # We export it so that recursive invocation of 'sage-sh' from a sage-buildsh shows the sage-buildsh prompt;
        # this makes sense because all environment variables set in build/bin/sage-build-env-config
        # and build/bin/sage-build-env are exported.
    fi
    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_SHPROMPT_PREFIX)\[$(tput sgr0)\] \u@\h:\W\$ "
            else
                PS1="($SAGE_SHPROMPT_PREFIX) \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_SHPROMPT_PREFIX)$(tput sgr0) $USER@`hostname -s`:\${PWD##*/}$ "
            else
                PS1="($SAGE_SHPROMPT_PREFIX) $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_SHPROMPT_PREFIX)$(tput sgr0) $USER@`hostname -s`:\${PWD##*/}$ "
            else
                PS1="($SAGE_SHPROMPT_PREFIX) $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_SHPROMPT_PREFIX)%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_SHPROMPT_PREFIX) $ '
            ;;
    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

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

if [ "$1" = '-rst2ipynb' -o "$1" = '--rst2ipynb' ]; then
    shift
    rst2ipynb --kernel=sagemath "$@"
    status="${?}"
    if [ "${status}" -eq "127" ] ; then echo 'rst2ipynb is not installed, please run "sage -i rst2ipynb"' ; fi
    exit ${status}
fi

if [ "$1" = '-ipynb2rst' -o "$1" = '--ipynb2rst' ]; then
    shift
    exec sage-ipynb2rst "$@"
fi

if [ "$1" = '-sws2rst' -o "$1" = '--sws2rst' ]; then
    shift
    exec sage-sws2rst "$@"
fi

#####################################################################
# The notebook, grep, building Sage, testing Sage
#####################################################################


if [[ "$1" =~ ^--notebook=.* || "$1" =~ ^-n=.* || "$1" =~ ^-notebook=.* ]] ; then
    sage-cleaner &>/dev/null &
    exec sage-notebook "$@"
fi

if [ "$1" = "-notebook" -o "$1" = '--notebook' -o "$1" = '-n' ]; then
    sage-cleaner &>/dev/null &
    exec sage-notebook "$@"
fi

if [ "$1" = "-bn" -o "$1" = "--build-and-notebook" ]; then
    shift
    build_sage
    sage-cleaner &>/dev/null &
    exec sage-notebook --notebook=default "$@"
fi

if [ -n "$SAGE_SRC" -a -d "$SAGE_SRC" ]; then
    # Source inspection facilities, supported on sage-the-distribution and on distributions
    # that package the Sage sources.
    if [ "$1" = '-grep' -o "$1" = "--grep" -o "$1" = "-search_src" -o "$1" = "--search_src" ]; then
        shift
        sage-grep "$@"
        exit 0
    fi

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

if [ "$1" = '-r' ]; then
    shift
    interactive_sage
fi

exec-runtests() {
    sage_setup
    export PYTHONIOENCODING="utf-8"  # Fix encoding for doctests
    exec sage-runtests "$@"
}

if [ "$1" = '-t' -o "$1" = '-tp' ]; then
    if [ "$1" = '-tp' ]; then
        shift
        exec-runtests -p "$@"
    else
        shift
        exec-runtests "$@"
    fi
fi

if [ "$1" = '-tnew' ]; then
    shift
    exec-runtests --new "$@"
fi

if [ "$1" = '-testall' -o "$1" = "--testall" ]; then
    shift
    exec-runtests -a "$@"
fi

if [ "$1" = '-fixdoctests' -o "$1" = '--fixdoctests' ]; then
    shift
    exec sage-fixdoctests "$@"
fi

if [ "$1" = "-coverage" -o "$1" = "--coverage" ]; then
    shift
    exec sage-coverage "$@"
fi

if [ "$1" = "-coverageall" -o "$1" = "--coverageall" ]; then
    shift
    exec sage-coverage --all "$@"
fi

if [ "$1" = '-startuptime' -o "$1" = '--startuptime' ]; then
    exec sage-startuptime.py "$@"
fi

if [ "$1" = '-fiximports' -o "$1" = '--fiximports' ]; then
    shift
    exec sage-python -m sage.misc.replace_dot_all "$@"
fi

if [ "$1" = '-fixdistributions' -o "$1" = '--fixdistributions' ]; then
    shift
    exec sage-python -m sage.misc.package_dir "$@"
fi

if [ "$1" = '-tox' -o "$1" = '--tox' ]; then
    shift
    if [ -n "$SAGE_SRC" -a -f "$SAGE_SRC/tox.ini" ]; then
        if command -v tox >/dev/null ; then
            exec tox -c "$SAGE_SRC" "$@"
        else
            echo "Run 'sage -i tox' to install"
            exit 1
        fi
    else
        echo >&2 "error: Sage source directory or tox.ini not available"
        exit 1
    fi
fi

if [ "$1" = '-pytest' -o "$1" = '--pytest' ]; then
    shift
    if [ -n "$SAGE_SRC" -a -f "$SAGE_SRC/tox.ini" ]; then
        if command -v pytest >/dev/null ; then
            # If no non-option arguments are given, provide one
            for a in $*; do
                case $a in
                    -*) ;;
                    *)  exec pytest --rootdir="$SAGE_SRC" --doctest "$@"
                esac
            done
            exec pytest --rootdir="$SAGE_SRC" --doctest "$@" "$SAGE_SRC"
        else
            echo "Run 'sage -i pytest' to install"
            exit 1
        fi
    else
        echo >&2 "error: Sage source directory or tox.ini not available"
        exit 1
    fi
fi

#####################################################################
# Building the Sage documentation
#####################################################################

if [ "$1" = "-docbuild" -o "$1" = "--docbuild" ]; then
    shift

    # Issue #30002: ensure an English locale so that it is possible to
    # scrape out warnings by pattern matching.
    export LANG=C
    export LANGUAGE=C

    # See #30351: bugs in macOS implementations of openblas/libgopm can cause
    # docbuild to hang if multiple OpenMP threads are allowed.
    if [ `uname` = 'Darwin' ]; then
        export OMP_NUM_THREADS=1
    fi

    # Issue #33650: Make sure that user configuration of Jupyter does not
    # shadow our sagemath kernel when jupyter-sphinx is invoked
    export JUPYTER_CONFIG_DIR=/doesnotexist
    export JUPYTER_CONFIG_PATH=/doesnotexist
    export JUPYTER_DATA_DIR=/doesnotexist
    export JUPYTER_PATH=/doesnotexist

    # Redirect stdin from /dev/null. This helps with running TeX which
    # tends to ask interactive questions if something goes wrong. These
    # cause the build to hang. If stdin is /dev/null, TeX just aborts.
    exec sage-python -m sage_docbuild "$@" </dev/null
fi

#####################################################################
# Creating and handling Sage distributions
#####################################################################

# The following could be moved to build/bin/sage-site. See #29111.

if [ "$1" = '--location' ]; then
    # Ignore
    exit 0
fi

if [ "$1" = '-installed' -o "$1" = "--installed" ]; then
    shift
    exec sage-list-packages all --installed-only $@
fi

if [ "$1" = '-sdist' -o "$1" = "--sdist" ]; then
    shift
    exec sage-sdist "$@"
fi

#####################################################################
# Debugging tools
#####################################################################

if [ "$1" = '-gdb' -o "$1" = "--gdb" ]; then
    shift
    sage_setup
    if [ "$SAGE_DEBUG" != "yes" ]; then
        gdb --eval-command "run" \
            -args python "${SELF}-ipython" "$@" -i
    else
        sage_dir=$(sage-python -c 'import os, sage; print(os.path.dirname(sage.__file__))')
        cygdb "$sage_dir" "$SAGE_SRC/sage" \
            -- --eval-command "run" \
            -args python "${SELF}-ipython" "$@" -i
    fi
    exit $?
fi

if [ "$1" = '-lldb' -o "$1" = "--lldb" ]; then
    shift
    sage_setup
    lldb --one-line "process launch --tty" --one-line "cont" -- python "${SELF}-ipython" "$@"
fi

if [ "$1" = '-valgrind' -o "$1" = "--valgrind" -o "$1" = '-memcheck' -o "$1" = "--memcheck" ]; then
    shift
    sage_setup
    exec sage-valgrind "$@"
fi

if [ "$1" = '-massif' -o "$1" = "--massif" ]; then
    shift
    sage_setup
    exec sage-massif "$@"
fi

if [ "$1" = '-cachegrind' -o "$1" = "--cachegrind" ]; then
    shift
    sage_setup
    exec sage-cachegrind "$@"
fi

if [ "$1" = '-callgrind' -o "$1" = "--callgrind" ]; then
    shift
    sage_setup
    exec sage-callgrind "$@"
fi

if [ "$1" = '-omega' -o "$1" = "--omega" ]; then
    shift
    sage_setup
    exec sage-omega "$@"
fi

if [ "$1" = '-gthread' -o "$1" = '-qthread' -o "$1" = '-q4thread' -o "$1" = '-wthread' -o "$1" = '-pylab' -o "$1" = '--simple-prompt' -o "$1" = '-simple-prompt' ]; then
    # Intentionally no "shift" here
    interactive_sage "$@"
fi

case "$1" in
    -*)
        # Delegate further option handling to the non-installed sage-site script.
        # (These options become unavailable if the directory $SAGE_ROOT is removed.)
        if [ -d "$SAGE_ROOT" ]; then
            exec "$SAGE_ROOT/build/bin/sage-site" "$@"
            # fallthrough if there is no sage-site script
        fi
        echo "Error: unknown option: $1"
        exit 1
        ;;
esac

if [ $# -ge 1 ]; then
    T=`echo "$1" | sed -e "s/.*\.//"`
    if [ "$T" = "spkg" ]; then
        echo "Error: Installing old-style SPKGs is no longer supported."
        exit 1
    fi
    sage_setup
    unset TERM  # See Issue #12263
    # sage-run rejects all command line options as the first argument.
    exec sage-run "$@"
fi