sage-shell-mode is an elisp package and provides an Emacs front
end for Sage.
sage-shell-mode provides two main features:
sage-shell-modeto run the Sage terminal inside Emacs.sage-shell:sage-modefor editing.sagesource files and sending their contents directly to the Sage terminal. This major mode is derived frompython-mode.
The package supports extensions with auto-complete-sage, helm-sage, anything-sage and ob-sagemath.
- Requirements
- Installation and Setup
- Aliases
- Basic Usage
- Input History
- Emulating Worksheets: code blocks
- Inline display of LaTeX outputs and plots (a port of
sage-view) - SageTeX
- Customization
- Extensions
- Screenshots
- Workaround for Flycheck
- License
- GNU Emacs 24.4 later.
- Local installation of Sage.
- The Emacs package deferred. This will be installed automatically if you follow the guide below.
The most convenient is to use the Emacs package manager to install sage-shell-mode from MELPA:
- See http://melpa.org/#/getting-started if you do not have a configuration for MELPA.
- Install
sage-shell-modebyM-x package-refresh-contentsM-x package-install RET sage-shell-mode.
(Alternatively, you can use =use-package= (available from MELPA) for installation and setup).
- Configuration.
Sage internally uses
IPythonto manage user interaction at the console,Jupytercell or, in our case,emacsbuffer. Due to IPython evolution (governed upstream Sage), this interaction has to be managed differently bysage-shell-modeaccording to theIpythonversion available, itself depending on Sage’s version. This configuration is governed by two customizable variables :sage-shell:use-prompt-toolkit, which must betfor Sage versions >= 7.4.beta0 and < 9.2.beta8, andnilotherwise ;sage-shell:use-simple-prompt, which must betfor Sage versions >= 9.2.beta9, andnilotherwise.
(Note : Sage 9.2.beta8 is a lost cause ; complain fiercely, then upgrade to something newer…).
The function
sage-shell:set-ipython-versiondoes this automatically, but takes a couple of seconds to execute at startup. Its use is controlled by the custom variablesage-shell:set-ipython-version-on-startup(tby default).Similarly,
sage-shell:check-ipython-version(controlled by the custom variablesage-shell:check-ipython-version-on-startup) checks that your options are acceptable to your IPython version, and will yell at you (in the*Messages*buffer) if this is not the case.By default, both functions are enabled at startup. A (reckless) user of (say) Sage 9.2.beta10 could shave a couple seconds startup time by setting :
(custom-set-variables '(sage-shell:use-prompt-toolkit nil) '(sage-shell:use-simple-prompt t) '(sage-shell:set-ipython-version-on-startup nil) '(sage-shell:check-ipython-version-on-startup nil))
in its
initfile (or in the:initclause of itssage-shell-modeuse-packagecall). - You can now run Sage inside Emacs by
M-x sage-shell:run-sage, if Emacs can find the executable file of Sage.If Emacs cannot find the executable file, add the following line to your Emacs init file:
(setq sage-shell:sage-root "/path/to/sage/root_directory")
And replace
/path/to/sage_root_directoryby the root directory of Sage, i.e.$SAGE_ROOT. If you do not know the root directory of Sage, evaluate the following code in a Sage terminal:import os; print os.environ["SAGE_ROOT"]
Alternatively, instead of setting
sage-shell:sage-root, you may set the variablesage-shell:sage-executable.(setq sage-shell:sage-executable "/path/to/sage/executable")
Here
/path/to/sage/executableis the path of the executable file of Sage. This may be a symbolic link.
Here is a sample configuration.
;; Run SageMath by M-x run-sage instead of M-x sage-shell:run-sage
(sage-shell:define-alias)
;; Turn on eldoc-mode in Sage terminal and in Sage source files
(add-hook 'sage-shell-mode-hook #'eldoc-mode)
(add-hook 'sage-shell:sage-mode-hook #'eldoc-mode)The official Emacs major mode for Sage used to be sage-mode. To avoid name conflicts
with this package, sage-shell-mode prefixes all names with sage-shell.
If you are not using sage-mode at all, you can define more convenient
aliases for sage-shell-mode by adding the following to your Emacs init file
after the line (require 'sage-shell-mode):
(sage-shell:define-alias)The following aliases will be defined:
| Original name | Alias |
|---|---|
| sage-shell:run-sage | run-sage |
| sage-shell:run-new-sage | run-new-sage |
| sage-shell:sage-mode | sage-mode |
| sage-shell:sage-mode-map | sage-mode-map |
| sage-shell:sage-mode-hook | sage-mode-hook |
This means e.g. that you can do M-x run-sage to run Sage, instead of M-x
sage-shell:run-sage.
You can start a Sage process by M-x sage-shell:run-sage. If you need
to open multiple Sage processes simultaneously, you can start new ones by
M-x sage-shell:run-new-sage. You can restart the current process by
M-x sage-shell:restart-sage.
| Command | Alias | Description |
|---|---|---|
| sage-shell:run-sage | run-sage | Run a Sage process. |
| sage-shell:run-new-sage | run-new-sage | Run another Sage process. |
| sage-shell:restart-sage | None | Restart the current Sage process. |
The major-mode of the Sage process buffer is sage-shell-mode.
The primary element of sage-shell-mode is interacting with the Sage process
you just started. The Sage process buffer communicates directly with a Sage
shell in the background and behaves very much like it. You just type and send
the command with <Enter>:
sage: 2+2
4
sage: (x^2 + 2*x + 1).factor()
(x + 1)^2
sage:The buffer behaves like an Emacs shell:
M-porC-upgoes through earlier input.- Previous input and output is retained earlier in the buffer. You can move around just as usual and e.g. copy from it or search.
- To exit, you can enter
quitat the prompt or typeC-d(bound tosage-shell:delchar-or-maybe-eof) at a blank line.
The buffer also behaves much like the Sage terminal:
<Tab> at the prompt completes the current word. It understands all Sage and
Python functions currently in scope, and it also completes attributes of
objects. If there are multiple possibilities, they are presented in another
window.
sage: G = graphs.PetersenGraph()
sage: G.<TAB>
<All methods on G are shown in a new buffer>
sage: G.charp<TAB>
<G.charp is completed uniquely to G.charpoly>By default, Tab completion uses completion-at-point. Alternatively, you can
use pcomplete by adding the following to your Emacs init file:
(setq sage-shell:completion-function 'pcomplete)You can also use auto-complete, anything or helm for
completion. This requires installing those extensions, see Extensions.
By writing the name of an object at the prompt, followed by ? and then RET,
you are shown the documentation of that object:
sage: G = graphs.PetersenGraph()
sage: G.charpoly?
<Documentation is shown in a new Sage Document buffer>This is identical to running C-c C-h and then typing the name of the object.
If you use ?? instead ? after a Sage object, then the source code for that object will be opened in a new buffer:
sage: G = graphs.PetersenGraph()
sage: G.charpoly??
<The file src/sage/graphs/generic_graph.py is opened at "def characteristic_polynomial(...):">| Key Stroke | Command | Description |
|---|---|---|
| RET | sage-shell:send-input | Evaluate the expression written at the prompt. |
| TAB | sage-shell-tab-command | Complete a partially written word or indent a line. |
| C-d | sage-shell:delchar-or-maybe-eof | Delete the next input character. End the Sage process if nothing is input. |
| C-c C-c | sage-shell:interrupt-subjob | Interrupt the current computation. |
| M-p | comint-previous-input | Go backward through input history. |
| M-n | sage-shell:next-input | Go forward through input history. |
| C-c C-o | sage-shell:delete-output | Remove all output from Sage since last input prompt. |
| C-c M-o | sage-shell:clear-current-buffer | Clear the entire Sage process buffer, leaving just the prompt. |
| C-c C-l | sage-shell:load-file | Asks for a file and loads it into Sage |
| C-c C-h | sage-shell:help | Ask for the name of a Sage object and show its documentation. |
| ? RET | sage-shell-help::describe-symbol | Show the documentation of the object directly preceding the ?. |
| ?? RET | sage-shell:find-source-in-view-mode | Visits the source code of the object directly preceding the ??. |
| C-c o | sage-shell:list-outputs | List inputs and outputs in a buffer. |
| C-c M-w | sage-shell:copy-previous-output-to-kill-ring | Copy the previous output to kill-ring |
For more commands and key-bindings see the help using M-x describe-mode
sage-shell-mode.
When you visit a file with the suffix .sage, then
sage-shell:sage-mode will be the major-mode of the buffer
automatically.
To switch to sage-shell:sage-mode on a .py file, run M-x
sage-shell:sage-mode. To use sage-shell:sage-mode every time you visit
that file, you can add the following magic comment at the first line of the
file:
# -*- mode: sage-shell:sage -*-If you’ve activated Aliases you can instead use the following magic comment:
# -*- mode: sage -*-The major mode sage-shell:sage-mode is almost the same as
python-mode. The following new key-bindings are added:
| Key | Command | Description |
|---|---|---|
| C-c C-c | sage-shell-edit:send-buffer | Evaluate the contents of the current buffer in the Sage process. |
| C-c C-r | sage-shell-edit:send-region | Evaluate the currently marked region in the Sage process. |
| C-c C-j | sage-shell-edit:send-line* | Evaluate the current line in the Sage process. |
| C-c C-l | sage-shell-edit:load-file | Load the current file in the Sage process. |
| C-c C-z | sage-shell-edit:pop-to-process-buffer | Select the Sage process buffer. |
If you run multiple Sage processes, use M-x sage-shell:set-process-buffer
to change which one will be used for the above functions.
To save the history of input evaluated in a Sage process and use in future
Sage process (using the M-p keybinding), add the following to your Emacs
init file:
(setq sage-shell:input-history-cache-file "~/.emacs.d/.sage_shell_input_history")The file name in the above line is the path for storing the inputs and you can change it to what you prefer.
Worksheets is a popular paradigm for structuring experiments in computer algebra systems, seen in Jupyter, the Sage Notebook, Maple and many other softwares.
sage-shell-mode supports a lightweight type of this workflow using “code blocks”.
Essentially, you structure your source file in logical blocks of code, representing both your library code and your experiments. For instance:
### Implement the new algorithm
def my_helper(a):
return a*2
def my_new_algorithm(x, y):
return my_helper(x) + my_helper(y)
### Check the new algorithm on small input
print my_new_algorithm(1, 2)
### Check the new algorithm on big input
print my_new_algorithm(100, 300)
### Check that my algorithm is commutative using random input
def my_random_number():
return randint(100, 200)
a, b = my_random_number(), my_random_number()
assert my_new_algorithm(a, b) == my_new_algorithm(b, a)The blocks of code are logically delimited by lines starting with ###.
In this case load(experiment.sage) is not a good alternative to the way one works with the Jupyter Notebook: rather, you want to evaluate the code block by block.
You also want to be able to modifying an earlier or later block, run that, and then return to the block in the middle, etc.
sage-shell-mode comes with a small set of functions for accommodating this. In sage-shell:sage-mode, the following functions are provided:
| Key | Command | Description |
|---|---|---|
| C-M-{ | sage-shell-blocks:backward | Move backward one block, i.e. to previous ### delimiter. |
| C-M-} | sage-shell-blocks:forward | Move forward one block, i.e. to next ### delimiter. |
| C-<return> | sage-shell-blocks:send-current | Send the block that the point is currently in to the Sage process |
In the Sage process buffer, the following functions are provided:
| Key | Command | Description |
|---|---|---|
| C-<return> | sage-shell-blocks:pull-next | Take the block from the last visited sage-shell:sage-mode buffer and send to the Sage process. |
As an example, if the point is in the body of my_new_algorithm, then C-<return> (or M-x sage-shell-blocks:send-current) would send the definitions of my_helper and my_new_algorithm to the Sage shell. Furthermore, it would print the “title” of the block:
sage: load('/tmp/sage_shell_mode3946wC1/sage_shell_mode_temp.sage')
--- Implement the new algorithm ---
sage:The delimiter ### can be changed by setq the variable sage-shell-blocs:delimiter.
This feature is a port of sage-view. This requires dvipng and preview.sty.
To enable inline display of LaTeX outputs and plots in sage-shell-mode buffer,
add the following code to your Emacs init file:
;; If you want to enable inline display of LaTeX outputs only,
;; uncomment the following line.
;; (setq sage-shell-view-default-commands 'output)
;; If you want to enable inline display of plots only,
;; uncomment the following line.
;; (setq sage-shell-view-default-commands 'plot)
(add-hook 'sage-shell-after-prompt-hook #'sage-shell-view-mode)You can use the following commands to enable/disable inline display of LaTeX outputs and plots.
| Command | Description |
|---|---|
sage-shell-view-toggle-inline-output | Toggle inline display of LaTeX outputs while SageMath process is running. |
sage-shell-view-toggle-inline-plots | Toggle inline display of plots while SageMath process is running. |
The following table shows some of customizable variables for sage-shell-view-mode.
For further customization, run M-x customize-group RET sage-shell-view RET.
| Customizable variable | Description | Default value |
sage-shell-view-default-commands | If equal to the symbol plots then will start inline plotting. If equal to the symbol output then will start typesetting output. Otherwise, if non-nil will start both. | t |
sage-shell-view-default-resolution | Resolution used when converting from PDF to PNG. This value is passed to the -r option of the ghostscript command. | 125 |
sage-shell-view-latex-foreground-color | Foreground color used in LaTeX image as string (e.g. “black”, “white”, “#de935f”) or nil. If it is nil, then the default foreground color will be used. | nil |
sage-shell-view-latex-background-color | Similar to sage-shell-view-latex-foreground-color for background color. | nil |
sage-shell-mode can be conveniently used when writing Sage-powered LaTeX files
using SageTeX.
When a Sage process is spawned by sage-shell:run-sage or
sage-shell:run-new-sage, then sage-shell-mode adds
$SAGE_ROOT/local/share/texmf/tex/generic/sagetex/ to the
environment variable TEXINPUTS in Emacs. If you do not want to
change the environment variable, set
sage-shell-sagetex:add-to-texinputs-p to nil.
Here is a list of commands for SageTeX. These commands load a
.sagetex.sage file generated by SageTeX to the existing Sage
process.
| Command | Run latex before loading | Run latex after loading |
|---|---|---|
| sage-shell-sagetex:load-file | No | No |
| sage-shell-sagetex:run-latex-and-load-file | Yes | No |
| sage-shell-sagetex:compile-file | Yes | Yes |
There are similar commands to above,
sage-shell-sagetex:load-current-file,
sage-shell-sagetex:run-latex-and-load-current-file and
sage-shell-sagetex:compile-current-file.
Here is a sample setting for AUCTeX users.
(eval-after-load "latex"
'(mapc (lambda (key-cmd) (define-key LaTeX-mode-map (car key-cmd) (cdr key-cmd)))
`((,(kbd "C-c s c") . sage-shell-sagetex:compile-current-file)
(,(kbd "C-c s C") . sage-shell-sagetex:compile-file)
(,(kbd "C-c s r") . sage-shell-sagetex:run-latex-and-load-current-file)
(,(kbd "C-c s R") . sage-shell-sagetex:run-latex-and-load-file)
(,(kbd "C-c s l") . sage-shell-sagetex:load-current-file)
(,(kbd "C-c s L") . sage-shell-sagetex:load-file)
(,(kbd "C-c C-z") . sage-shell-edit:pop-to-process-buffer))))For example, you can run sage-shell-sagetex:compile-current-file
by C-c s c in a LaTeX-mode buffer with this setting.
You can change a latex command used by
sage-shell-sagetex:compile-file and
sage-shell-sagetex:compile-current-file by setting
sage-shell-sagetex:latex-command or
sage-shell-sagetex:auctex-command-name.
If you are an AUCTeX user, then customize
sage-shell-sagetex:auctex-command-name to change the latex
command. The value of sage-shell-sagetex:auctex-command-name
should be a name of a command in TeX-command-list (i.e car of
an element of the list TeX-command-list), e.g.:
(setq sage-shell-sagetex:auctex-command-name "LaTeX")You can also use the variable sage-shell-sagetex:latex-command to
change the latex command. For example, if you want to run
latexmk after loading a .sagetex.sage file, then use the
following setting:
(setq sage-shell-sagetex:latex-command "latexmk")The default value of sage-shell-sagetex:latex-command is latex
-interaction=nonstopmode. If
sage-shell-sagetex:auctex-command-name is non-nil, then the
value of sage-shell-sagetex:latex-command is ignored.
To customize sage-shell-mode, M-x customize-group RET sage-shell,
M-x customize-group RET sage-shell-sagetex or
M-x customize-group RET sage-shell-view.
- auto-complete-sage provides an auto-complete source for
sage-shell-mode. - helm-sage provides a helm source for
sage-shell-mode. - anything-sage provides an anything source for
sage-shell-mode. - ob-sagemath provides org-babel functions for Sage.
Automatic indentation and syntax highlighting work.
Completion with auto-complete-sage.
Completion with helm-sage.
To use flycheck-mode in a sage-shell:sage-mode buffer and a
python-mode buffer, try the following code.
(dolist (ckr '(python-pylint python-flake8))
(flycheck-add-mode ckr 'sage-shell:sage-mode))
(defun sage-shell:flycheck-turn-on ()
"Enable flycheck-mode only in a file ended with py."
(when (let ((bfn (buffer-file-name)))
(and bfn (string-match (rx ".py" eol) bfn)))
(flycheck-mode 1)))
(add-hook 'python-mode-hook 'sage-shell:flycheck-turn-on)Licensed under the GPL.



