sage-shell-mode
is an elisp package and provides an Emacs front
end for Sage.
sage-shell-mode
provides two main features:
sage-shell-mode
to run the Sage terminal inside Emacs.sage-shell:sage-mode
for editing.sage
source 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-mode
byM-x package-refresh-contents
M-x package-install RET sage-shell-mode
.
(Alternatively, you can use =use-package= (available from MELPA) for installation and setup).
- Configuration.
Sage internally uses
IPython
to manage user interaction at the console,Jupyter
cell or, in our case,emacs
buffer. Due to IPython evolution (governed upstream Sage), this interaction has to be managed differently bysage-shell-mode
according to theIpython
version available, itself depending on Sage’s version. This configuration is governed by two customizable variables :sage-shell:use-prompt-toolkit
, which must bet
for Sage versions >= 7.4.beta0 and < 9.2.beta8, andnil
otherwise ;sage-shell:use-simple-prompt
, which must bet
for Sage versions >= 9.2.beta9, andnil
otherwise.
(Note : Sage 9.2.beta8 is a lost cause ; complain fiercely, then upgrade to something newer…).
The function
sage-shell:set-ipython-version
does 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
(t
by 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
init
file (or in the:init
clause of itssage-shell-mode
use-package
call). - 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_directory
by 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/executable
is 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-p
orC-up
goes 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
quit
at 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.