mirror of
https://github.com/xonsh/xonsh.git
synced 2025-03-04 16:34:47 +01:00
1077 lines
40 KiB
ReStructuredText
1077 lines
40 KiB
ReStructuredText
.. _tutorial:
|
|
|
|
*******************
|
|
Tutorial
|
|
*******************
|
|
xonsh is a shell language and command prompt. Unlike other shells, xonsh is
|
|
based on Python, with additional syntax added that makes calling subprocess
|
|
commands, manipulating the environment, and dealing with the file system
|
|
easily. The xonsh command prompt gives users interactive access to the xonsh
|
|
language.
|
|
|
|
While all Python code is also xonsh, not all BASH code can be used in xonsh.
|
|
That would defeat the purpose, and Python is better anyway! Still, xonsh is
|
|
BASH-wards compatible in the ways that matter, such as for running commands,
|
|
reading in the BASH environment, and utilizing BASH tab completion.
|
|
|
|
The purpose of this tutorial is to teach you xonsh. There are many excellent
|
|
guides out there for learning Python, and this will not join their ranks.
|
|
Similarly, you'd probably get the most out of this tutorial if you have already
|
|
used a command prompt or interactive interpreter.
|
|
|
|
Let's dive in!
|
|
|
|
Starting xonsh
|
|
========================
|
|
Assuming you have successfully installed xonsh (see http://xonsh.org),
|
|
you can start up the xonsh interpreter via the ``xonsh`` command. Suppose
|
|
you are in a lesser terminal:
|
|
|
|
.. code-block:: bash
|
|
|
|
bash $ xonsh
|
|
snail@home ~ $
|
|
|
|
Now we are in a xonsh shell. Our username happens to be ``snail``, our
|
|
hostname happens to be ``home``, and we are in our home directory (``~``).
|
|
Alternatively, you can setup your terminal emulator (xterm, gnome-terminal,
|
|
etc) to run xonsh automatically when it starts up. This is recommended.
|
|
|
|
Basics
|
|
=======================
|
|
The xonsh language is based on Python, and the xonsh shell uses Python to
|
|
interpret any input it receives. This makes simple things, like arithmetic,
|
|
simple:
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> 1 + 1
|
|
2
|
|
|
|
.. note:: From here on we'll be using ``>>>`` to prefix (or prompt) any
|
|
xonsh input. This follows the Python convention and helps trick
|
|
syntax highlighting, though ``$`` is more traditional for shells.
|
|
|
|
Since this is just Python, we are able import modules, print values,
|
|
and use other built-in Python functionality:
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> import sys
|
|
>>> print(sys.version)
|
|
3.4.2 |Continuum Analytics, Inc.| (default, Oct 21 2014, 17:16:37)
|
|
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)]
|
|
|
|
|
|
We can also create and use literal data types, such as ints, floats, lists,
|
|
sets, and dictionaries. Everything that you are used to if you already know
|
|
Python is there:
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> d = {'xonsh': True}
|
|
>>> d.get('bash', False)
|
|
False
|
|
|
|
The xonsh shell also supports multi-line input for more advanced flow control.
|
|
The multi-line mode is automatically entered whenever the first line of input
|
|
is not syntactically valid on its own. Multi-line mode is then exited when
|
|
enter (or return) is pressed when the cursor is in the first column.
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> if True:
|
|
... print(1)
|
|
... else:
|
|
... print(2)
|
|
...
|
|
1
|
|
|
|
Flow control, of course, includes loops.
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> for i, x in enumerate('xonsh'):
|
|
... print(i, x)
|
|
...
|
|
0 x
|
|
1 o
|
|
2 n
|
|
3 s
|
|
4 h
|
|
|
|
We can also define and call functions and classes. I'll mostly spare you the
|
|
details, but this *is* pretty cool:
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> def f():
|
|
... return "xonsh"
|
|
...
|
|
>>> f()
|
|
'xonsh'
|
|
|
|
For easier indentation, Shift+Tab will enter 4 spaces.
|
|
And that about wraps it up for the basics section. It is just like Python.
|
|
|
|
Environment Variables
|
|
=======================
|
|
Environment variables are written as ``$`` followed by a name. For example,
|
|
``$HOME``, ``$PWD``, and ``$PATH``.
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> $HOME
|
|
'/home/snail'
|
|
|
|
You can set (and export) environment variables like you would set any other
|
|
variable in Python. The same is true for deleting them too.
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> $GOAL = 'Become the Lord of the Files'
|
|
>>> print($GOAL)
|
|
Become the Lord of the Files
|
|
>>> del $GOAL
|
|
|
|
Very nice. All environment variables live in the built-in
|
|
``__xonsh_env__`` mapping. You can access this mapping directly, but in most
|
|
situations, you shouldn't need to.
|
|
|
|
Like other variables in Python, environment variables have a type. Sometimes
|
|
this type is imposed based on the variable name. The current rules are pretty
|
|
simple:
|
|
|
|
* ``\w*PATH``: any variable whose name ends in PATH is a list of strings.
|
|
* ``\w*DIRS``: any variable whose name ends in DIRS is a list of strings.
|
|
* ``XONSH_HISTORY_SIZE``: this variable is an int.
|
|
* ``CASE_SENSITIVE_COMPLETIONS``: this variable is a boolean.
|
|
|
|
xonsh will automatically convert back and forth to untyped (string-only)
|
|
representations of the environment as needed (mostly by subprocess commands).
|
|
When in xonsh, you'll always have the typed version. Here are a couple of
|
|
PATH examples:
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> $PATH
|
|
['/home/snail/.local/bin', '/home/snail/sandbox/bin',
|
|
'/home/snail/miniconda3/bin', '/usr/local/bin', '/usr/local/sbin',
|
|
'/usr/bin', '/usr/sbin', '/bin', '/sbin', '.']
|
|
>>> $LD_LIBRARY_PATH
|
|
['/home/snail/.local/lib', '']
|
|
|
|
Also note that *any* Python object can go into the environment. It is sometimes
|
|
useful to have more sophisticated types, like functions, in the environment.
|
|
There are handful of environment variables that xonsh considers special.
|
|
They can be seen in the table below:
|
|
|
|
========================== ============================= ================================
|
|
variable default description
|
|
========================== ============================= ================================
|
|
PROMPT xonsh.environ.DEFAULT_PROMPT The prompt text. May contain
|
|
keyword arguments which are
|
|
auto-formatted (see `Customizing
|
|
the Prompt`_ below).
|
|
MULTILINE_PROMPT ``'.'`` Prompt text for 2nd+ lines of
|
|
input, may be str or
|
|
function which returns a str.
|
|
TITLE xonsh.environ.DEFAULT_TITLE The title text for the window
|
|
in which xonsh is running.
|
|
Formatted in the same manner
|
|
as PROMPT (see `Customizing the
|
|
Prompt`_ below).
|
|
FORMATTER_DICT xonsh.environ.FORMATTER_DICT Dictionary containing variables
|
|
to be used when formatting PROMPT
|
|
and TITLE (see `Customizing the
|
|
Prompt`_ below).
|
|
XONSHRC ``'~/.xonshrc'`` Location of run control file
|
|
XONSH_HISTORY_SIZE 8128 Number of items to store in the
|
|
history.
|
|
XONSH_HISTORY_FILE ``'~/.xonsh_history'`` Location of history file
|
|
XONSH_INTERACTIVE ``True`` if xonsh is running
|
|
interactively, and ``False``
|
|
otherwise.
|
|
BASH_COMPLETIONS ``[] or ['/etc/...']`` This is a list of strings that
|
|
specifies where the BASH
|
|
completion files may be found.
|
|
The default values are platform
|
|
dependent, but sane. To
|
|
specify an alternate list,
|
|
do so in the run control file.
|
|
SUGGEST_COMMANDS ``True`` When a user types an invalid
|
|
command, xonsh will try to offer
|
|
suggestions of similar valid
|
|
commands if this is ``True``.
|
|
SUGGEST_THRESHOLD ``3`` An error threshold. If the
|
|
Levenshtein distance between the
|
|
entered command and a valid
|
|
command is less than this value,
|
|
the valid command will be
|
|
offered as a suggestion.
|
|
SUGGEST_MAX_NUM ``5`` xonsh will show at most this
|
|
many suggestions in response to
|
|
an invalid command. If
|
|
negative, there is no limit to
|
|
how many suggestions are shown.
|
|
SHELL_TYPE ``'readline'`` Which shell is used.
|
|
Currently two shell types are
|
|
supported: ``'readline'`` that
|
|
is backed by python's readline
|
|
module and ``'prompt_toolkit'``
|
|
that uses external library of
|
|
the same name. For using
|
|
prompt_toolkit shell you need
|
|
to have `prompt_toolkit
|
|
<https://github.com/jonathanslenders/python-prompt-toolkit>`_
|
|
library installed. To specify
|
|
which shell should be used, do
|
|
so in the run control file.
|
|
CDPATH ``[]`` A list of paths to be used as
|
|
roots for a `cd`, breaking
|
|
compatibility with bash, xonsh
|
|
always prefer an existing
|
|
relative path.
|
|
XONSH_SHOW_TRACEBACK Not defined Controls if a traceback is shown when
|
|
exceptions occur in the shell.
|
|
Set ``'True'`` to always show
|
|
or ``'False'`` to always hide.
|
|
If undefined then traceback is
|
|
hidden but a notice is shown on
|
|
how to enable the traceback.
|
|
CASE_SENSITIVE_COMPLETIONS True on Linux otherwise False Sets whether completions should
|
|
be case sesistive or case
|
|
insensitive.
|
|
========================== ============================= ================================
|
|
|
|
Environment Lookup with ``${}``
|
|
================================
|
|
The ``$NAME`` is great as long as you know the name of the environment
|
|
variable you want to look up. But what if you want to construct the name
|
|
programmatically, or read it from another variable? Enter the ``${}``
|
|
operator.
|
|
|
|
.. warning:: In BASH, ``$NAME`` and ``${NAME}`` are syntactically equivalent.
|
|
In xonsh, they have separate meanings.
|
|
|
|
We can place any valid Python expression inside of the curly braces in
|
|
``${<expr>}``. This result of this expression will then be used to look up a
|
|
value in the environment. In fact, ``${<expr>}`` is the same as doing
|
|
``__xonsh_env__[<expr>]``, but much nicer to look at. Here are a couple of
|
|
examples in action:
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> x = 'USER'
|
|
>>> ${x}
|
|
'snail'
|
|
>>> ${'HO' + 'ME'}
|
|
'/home/snail'
|
|
|
|
Not bad, xonsh, not bad.
|
|
|
|
|
|
Running Commands
|
|
==============================
|
|
As a shell, xonsh is meant to make running commands easy and fun.
|
|
Running subprocess commands should work like any other in any other shell.
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> echo "Yoo hoo"
|
|
Yoo hoo
|
|
>>> cd xonsh
|
|
>>> ls
|
|
build docs README.rst setup.py xonsh __pycache__
|
|
dist license scripts tests xonsh.egg-info
|
|
>>> dir scripts
|
|
xonsh xonsh.bat
|
|
>>> git status
|
|
On branch master
|
|
Your branch is up-to-date with 'origin/master'.
|
|
Changes not staged for commit:
|
|
(use "git add <file>..." to update what will be committed)
|
|
(use "git checkout -- <file>..." to discard changes in working directory)
|
|
|
|
modified: docs/tutorial.rst
|
|
|
|
no changes added to commit (use "git add" and/or "git commit -a")
|
|
>>> exit
|
|
|
|
This should feel very natural.
|
|
|
|
|
|
Python-mode vs Subprocess-mode
|
|
================================
|
|
It is sometimes helpful to make the distinction between lines that operate
|
|
in pure Python mode and lines that use shell-specific syntax, edit the
|
|
execution environment, and run commands. Unfortunately, it is not always
|
|
clear from the syntax alone what mode is desired. This ambiguity stems from
|
|
most command line utilities looking a lot like Python operators.
|
|
|
|
Take the case of ``ls -l``. This is valid Python code, though it could
|
|
have also been written as ``ls - l`` or ``ls-l``. So how does xonsh know
|
|
that ``ls -l`` is meant to be run in subprocess-mode?
|
|
|
|
For any given line that only contains an expression statement (expr-stmt,
|
|
see the Python AST docs for more information), if the left-most name cannot
|
|
be found as a current variable name xonsh will try to parse the line as a
|
|
subprocess command instead. In the above, if ``ls`` is not a variable,
|
|
then subprocess mode will be attempted. If parsing in subprocess mode fails,
|
|
then the line is left in Python-mode.
|
|
|
|
In the following example, we will list the contents of the directory
|
|
with ``ls -l``. Then we'll make new variable names ``ls`` and ``l`` and then
|
|
subtract them. Finally, we will delete ``ls`` and ``l`` and be able to list
|
|
the directories again.
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> # this will be in subproc-mode, because ls doesn't exist
|
|
>>> ls -l
|
|
total 0
|
|
-rw-rw-r-- 1 snail snail 0 Mar 8 15:46 xonsh
|
|
>>> # set an ls variable to force python-mode
|
|
>>> ls = 44
|
|
>>> l = 2
|
|
>>> ls -l
|
|
42
|
|
>>> # deleting ls will return us to supbroc-mode
|
|
>>> del ls
|
|
>>> ls -l
|
|
total 0
|
|
-rw-rw-r-- 1 snail snail 0 Mar 8 15:46 xonsh
|
|
|
|
The determination between Python- and subprocess-modes is always done in the
|
|
safest possible way. If anything goes wrong, it will favor Python-mode.
|
|
The determination between the two modes is done well ahead of any execution.
|
|
You do not need to worry about partially executed commands - that is
|
|
impossible.
|
|
|
|
If you absolutely want to run a subprocess command, you can always
|
|
force xonsh to do so with the syntax that we will see in the following
|
|
sections.
|
|
|
|
|
|
Captured Subprocess with ``$()``
|
|
================================
|
|
The ``$(<expr>)`` operator in xonsh executes a subprocess command and
|
|
*captures* the output. The expression in the parentheses will be run and
|
|
stdout will be returned as string. This is similar to how ``$()`` performs in
|
|
BASH. For example,
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> $(ls -l)
|
|
'total 0\n-rw-rw-r-- 1 snail snail 0 Mar 8 15:46 xonsh\n'
|
|
|
|
The ``$()`` operator is an expression itself. This means that we can
|
|
assign the results to a variable or perform any other manipulations we want.
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> x = $(ls -l)
|
|
>>> print(x.upper())
|
|
TOTAL 0
|
|
-RW-RW-R-- 1 SNAIL SNAIL 0 MAR 8 15:46 XONSH
|
|
|
|
While in subprocess-mode or inside of a captured subprocess, we can always
|
|
still query the environment with ``$NAME`` variables.
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> $(echo $HOME)
|
|
'/home/snail\n'
|
|
|
|
Uncaptured Subprocess with ``$[]``
|
|
===================================
|
|
Uncaptured subprocess are denoted with the ``$[<expr>]`` operator. They are
|
|
the same as ``$()`` captured subprocesses in almost every way. The only
|
|
difference is that the subprocess's stdout passes directly through xonsh and
|
|
to the screen. The return value of ``$[]`` is always ``None``.
|
|
|
|
In the following, we can see that the results of ``$[]`` are automatically
|
|
printed and the return value is not a string.
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> x = $[ls -l]
|
|
total 0
|
|
-rw-rw-r-- 1 snail snail 0 Mar 8 15:46 xonsh
|
|
>>> x is None
|
|
True
|
|
|
|
Previously when we automatically entered subprocess-mode, uncaptured
|
|
subprocesses were used. Thus ``ls -l`` and ``$[ls -l]`` are usually
|
|
equivalent.
|
|
|
|
Python Evaluation with ``@()``
|
|
===============================
|
|
|
|
The ``@(<expr>)`` operator from will evaluate arbitrary Python code in
|
|
subprocess mode, and the result will be appended to the subprocess command
|
|
list. If the result is a string, it is appended to the argument list.
|
|
If the result is a list or other non-string sequence, the contents are
|
|
converted to strings and appended to the argument list in order. Otherwise, the
|
|
result is automatically converted to a string. For example,
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> x = 'xonsh'
|
|
>>> y = 'party'
|
|
>>> echo @(x + ' ' + y)
|
|
xonsh party
|
|
>>> echo @(2+2)
|
|
4
|
|
>>> echo @([42, 'yo'])
|
|
42 yo
|
|
|
|
This syntax can be used inside of a captured or uncaptured subprocess, and can
|
|
be used to generate any of the tokens in the subprocess command list.
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> out = $(echo @(x + ' ' + y))
|
|
>>> out
|
|
'xonsh party\n'
|
|
>>> @("ech" + "o") "hey"
|
|
hey
|
|
|
|
Thus, ``@()`` allows us to create complex commands in Python-mode and then
|
|
feed them to a subprocess as needed. For example:
|
|
|
|
.. code-block:: xonsh
|
|
|
|
for i in range(20):
|
|
$[touch @('file%02d' % i)]
|
|
|
|
|
|
Nesting Subprocesses
|
|
=====================================
|
|
Though I am begging you not to abuse this, it is possible to nest the
|
|
subprocess operators that we have seen so far (``$()``, ``$[]``, ``${}``,
|
|
``@()``). An instance of ``ls -l`` that is on the wrong side of the border of
|
|
the absurd is shown below:
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> $[$(echo ls) @('-' + $(echo l).strip())]
|
|
total 0
|
|
-rw-rw-r-- 1 snail snail 0 Mar 8 15:46 xonsh
|
|
|
|
With great power, and so forth...
|
|
|
|
.. note:: Nesting these subprocess operators inside of ``$()`` and/or ``$[]``
|
|
works, because the contents of those operators are executed in
|
|
subprocess mode. Since ``@()`` and ``${}`` run their contents in
|
|
Python mode, it is not possible to nest other subprocess operators
|
|
inside of them.
|
|
|
|
Pipes
|
|
====================
|
|
|
|
In subprocess-mode, xonsh allows you to use the ``|`` character to pipe
|
|
together commands as you would in other shells.
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> env | uniq | sort | grep PATH
|
|
DATAPATH=/usr/share/MCNPX/v260/Data/
|
|
DEFAULTS_PATH=/usr/share/gconf/awesome-gnome.default.path
|
|
LD_LIBRARY_PATH=/home/snail/.local/lib:
|
|
MANDATORY_PATH=/usr/share/gconf/awesome-gnome.mandatory.path
|
|
PATH=/home/snail/.local/bin:/home/snail/sandbox/bin:/usr/local/bin
|
|
XDG_SEAT_PATH=/org/freedesktop/DisplayManager/Seat0
|
|
XDG_SESSION_PATH=/org/freedesktop/DisplayManager/Session0
|
|
|
|
This is only available in subprocess-mode because ``|`` is otherwise a
|
|
Python operator.
|
|
If you are unsure of what pipes are, there are many great references out there.
|
|
You should be able to find information on StackOverflow or Google.
|
|
|
|
|
|
Input/Output Redirection
|
|
====================================
|
|
|
|
xonsh also allows you to redirect ``stdin``, ``stdout``, and/or ``stderr``.
|
|
This allows you to control where the output of a command is sent, and where
|
|
it receives its input from. xonsh has its own syntax for these operations,
|
|
but, for compatibility purposes, xonsh also support Bash-like syntax.
|
|
|
|
The basic operations are "write to" (``>``), "append to" (``>>``), and "read
|
|
from" (``<``). The details of these are perhaps best explained through
|
|
examples.
|
|
|
|
Redirecting ``stdout``
|
|
----------------------
|
|
|
|
All of the following examples will execute ``COMMAND`` and write its regular
|
|
output (stdout) to a file called ``output.txt``, creating it if it does not
|
|
exist:
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> COMMAND > output.txt
|
|
>>> COMMAND out> output.txt
|
|
>>> COMMAND o> output.txt
|
|
>>> COMMAND 1> output.txt # included for Bash compatibility
|
|
|
|
These can be made to append to ``output.txt`` instead of overwriting its contents
|
|
by replacing ``>`` with ``>>`` (note that ``>>`` will still create the file if it
|
|
does not exist).
|
|
|
|
Redirecting ``stderr``
|
|
----------------------
|
|
|
|
All of the following examples will execute ``COMMAND`` and write its error
|
|
output (stderr) to a file called ``errors.txt``, creating it if it does not
|
|
exist:
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> COMMAND err> errors.txt
|
|
>>> COMMAND e> errors.txt
|
|
>>> COMMAND 2> errors.txt # included for Bash compatibility
|
|
|
|
As above, replacing ``>`` with ``>>`` will cause the error output to be
|
|
appended to ``errors.txt``, rather than replacing its contents.
|
|
|
|
Combining Streams
|
|
----------------------
|
|
|
|
It is possible to send all of ``COMMAND``'s output (both regular output and
|
|
error output) to the same location. All of the following examples accomplish
|
|
that task:
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> COMMAND all> combined.txt
|
|
>>> COMMAND a> combined.txt
|
|
>>> COMMAND &> combined.txt # included for Bash compatibility
|
|
|
|
It is also possible to explicitly merge stderr into stdout so that error
|
|
messages are reported to the same location as regular output. You can do this
|
|
with the following syntax:
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> COMMAND err>out
|
|
>>> COMMAND err>o
|
|
>>> COMMAND e>out
|
|
>>> COMMAND e>o
|
|
>>> COMMAND 2>&1 # included for Bash compatibility
|
|
|
|
This merge can be combined with other redirections, including pipes (see the
|
|
section on `Pipes`_ above):
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> COMMAND err>out | COMMAND2
|
|
>>> COMMAND e>o > combined.txt
|
|
|
|
It is worth noting that this last example is equivalent to: ``COMMAND a> combined.txt``
|
|
|
|
Redirecting ``stdin``
|
|
---------------------
|
|
|
|
It is also possible to have a command read its input from a file, rather
|
|
than from ``stdin``. The following examples demonstrate two ways to accomplish this:
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> COMMAND < input.txt
|
|
>>> < input.txt COMMAND
|
|
|
|
Combining I/O Redirects
|
|
------------------------
|
|
|
|
It is worth noting that all of these redirections can be combined. Below is
|
|
one example of a complicated redirect.
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> COMMAND1 e>o < input.txt | COMMAND2 > output.txt e>> errors.txt
|
|
|
|
This line will run ``COMMAND1`` with the contents of ``input.txt`` fed in on
|
|
stdin, and will pipe all output (stdout and stderr) to ``COMMAND2``; the
|
|
regular output of this command will be redirected to ``output.txt``, and the
|
|
error output will be appended to ``errors.txt``.
|
|
|
|
|
|
Background Jobs
|
|
===============
|
|
|
|
Typically, when you start a program running in xonsh, xonsh itself will pause
|
|
and wait for that program to terminate. Sometimes, though, you may want to
|
|
continue giving commands to xonsh while that program is running. In subprocess
|
|
mode, you can start a process "in the background" (i.e., in a way that allows
|
|
continued use of the shell) by adding an ampersand (``&``) to the end of your
|
|
command. Background jobs are very useful when running programs with graphical
|
|
user interfaces.
|
|
|
|
The following shows an example with ``emacs``.
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> emacs &
|
|
>>>
|
|
|
|
Note that the prompt is returned to you after emacs is started.
|
|
|
|
Job Control
|
|
===========
|
|
|
|
If you start a program in the foreground (with no ampersand), you can suspend
|
|
that program's execution and return to the xonsh prompt by pressing Control-Z.
|
|
This will give control of the terminal back to xonsh, and will keep the program
|
|
paused in the background.
|
|
|
|
.. note:: Suspending processes via Control-Z is not yet supported when
|
|
running on Windows.
|
|
|
|
To unpause the program and bring it back to the foreground, you can use the
|
|
``fg`` command. To unpause the program have it continue in the background
|
|
(giving you continued access to the xonsh prompt), you can use the ``bg``
|
|
command.
|
|
|
|
You can get a listing of all currently running jobs with the ``jobs`` command.
|
|
|
|
Each job has a unique identifier (starting with 1 and counting upward). By
|
|
default, the ``fg`` and ``bg`` commands operate on the job that was started
|
|
most recently. You can bring older jobs to the foreground or background by
|
|
specifying the appropriate ID; for example, ``fg 1`` brings the job with ID 1
|
|
to the foreground.
|
|
|
|
String Literals in Subprocess-mode
|
|
====================================
|
|
Strings can be used to escape special characters in subprocess-mode. The
|
|
contents of the string are passed directly to the subprocess command as a
|
|
single argument. So whenever you are in doubt, or if there is a xonsh syntax
|
|
error because of a filename, just wrap the offending portion in a string.
|
|
|
|
A common use case for this is files with spaces in their names. This
|
|
detestable practice refuses to die. "No problem!" says xonsh, "I have
|
|
strings." Let's see it go!
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> touch "sp ace"
|
|
>>> ls -l
|
|
total 0
|
|
-rw-rw-r-- 1 snail snail 0 Mar 8 17:50 sp ace
|
|
-rw-rw-r-- 1 snail snail 0 Mar 8 15:46 xonsh
|
|
|
|
Spaces in filenames, of course, are just the beginning.
|
|
|
|
|
|
Filename Globbing with ``*``
|
|
===============================
|
|
Filename globbing with the ``*`` character is also allowed in subprocess-mode.
|
|
This simply uses Python's glob module under-the-covers. See there for more
|
|
details. As an example, start with a lovely bunch of xonshs:
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> touch xonsh conch konk quanxh
|
|
>>> ls
|
|
conch konk quanxh xonsh
|
|
>>> ls *h
|
|
conch quanxh xonsh
|
|
>>> ls *o*
|
|
conch konk xonsh
|
|
|
|
This is not available in Python-mode, because multiplication is pretty
|
|
important.
|
|
|
|
|
|
Regular Expression Filename Globbing with Backticks
|
|
=====================================================
|
|
If you have ever felt that normal globbing could use some more octane,
|
|
then regex globbing is the tool for you! Any string that uses backticks
|
|
(`````) instead of quotes (``'``, ``"``) is interpreted as a regular
|
|
expression to match filenames against. Like with regular globbing, a
|
|
list of successful matches is returned. In Python-mode, this is just a
|
|
list of strings. In subprocess-mode, each filename becomes its own argument
|
|
to the subprocess command.
|
|
|
|
Let's see a demonstration with some simple filenames:
|
|
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> touch a aa aaa aba abba aab aabb abcba
|
|
>>> ls `a(a+|b+)a`
|
|
aaa aba abba
|
|
>>> print(`a(a+|b+)a`)
|
|
['aaa', 'aba', 'abba']
|
|
>>> len(`a(a+|b+)a`)
|
|
3
|
|
|
|
Other than the regex matching, this functions in the same way as normal
|
|
globbing.
|
|
For more information, please see the documentation for the ``re`` module in
|
|
the Python standard library.
|
|
|
|
.. warning:: This backtick syntax has very different from that of BASH. In
|
|
BASH, backticks means to run a captured subprocess ``$()``.
|
|
|
|
|
|
Help & Superhelp with ``?`` & ``??``
|
|
=====================================================
|
|
From IPython, xonsh allows you to inspect objects with question marks.
|
|
A single question mark (``?``) is used to display normal level of help.
|
|
Double question marks (``??``) are used to display higher level of help,
|
|
called superhelp. Superhelp usually includes source code if the object was
|
|
written in pure Python.
|
|
|
|
Let's start by looking at the help for the int type:
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> int?
|
|
Type: type
|
|
String form: <class 'int'>
|
|
Init definition: (self, *args, **kwargs)
|
|
Docstring:
|
|
int(x=0) -> integer
|
|
int(x, base=10) -> integer
|
|
|
|
Convert a number or string to an integer, or return 0 if no arguments
|
|
are given. If x is a number, return x.__int__(). For floating point
|
|
numbers, this truncates towards zero.
|
|
|
|
If x is not a number or if base is given, then x must be a string,
|
|
bytes, or bytearray instance representing an integer literal in the
|
|
given base. The literal can be preceded by '+' or '-' and be surrounded
|
|
by whitespace. The base defaults to 10. Valid bases are 0 and 2-36.
|
|
Base 0 means to interpret the base from the string as an integer literal.
|
|
>>> int('0b100', base=0)
|
|
4
|
|
<class 'int'>
|
|
|
|
Now, let's look at the superhelp for the xonsh built-in that enables
|
|
regex globbing:
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> __xonsh_regexpath__??
|
|
Type: function
|
|
String form: <function regexpath at 0x7fef91612950>
|
|
File: /home/scopatz/.local/lib/python3.4/site-packages/xonsh-0.1-py3.4.egg/xonsh/built_ins.py
|
|
Definition: (s)
|
|
Source:
|
|
def regexpath(s):
|
|
"""Takes a regular expression string and returns a list of file
|
|
paths that match the regex.
|
|
"""
|
|
s = expand_path(s)
|
|
return reglob(s)
|
|
<function regexpath at 0x7fef91612950>
|
|
|
|
Note that both help and superhelp return the object that they are inspecting.
|
|
This allows you to chain together help inside of other operations and
|
|
ask for help several times in an object hierarchy. For instance, let's get
|
|
help for both the dict type and its key() method simultaneously:
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> dict?.keys??
|
|
Type: type
|
|
String form: <class 'dict'>
|
|
Init definition: (self, *args, **kwargs)
|
|
Docstring:
|
|
dict() -> new empty dictionary
|
|
dict(mapping) -> new dictionary initialized from a mapping object's
|
|
(key, value) pairs
|
|
dict(iterable) -> new dictionary initialized as if via:
|
|
d = {}
|
|
for k, v in iterable:
|
|
d[k] = v
|
|
dict(**kwargs) -> new dictionary initialized with the name=value pairs
|
|
in the keyword argument list. For example: dict(one=1, two=2)
|
|
Type: method_descriptor
|
|
String form: <method 'keys' of 'dict' objects>
|
|
Docstring: D.keys() -> a set-like object providing a view on D's keys
|
|
<method 'keys' of 'dict' objects>
|
|
|
|
Of course, for subprocess commands, you still want to use the ``man`` command.
|
|
|
|
|
|
Compile, Evaluate, & Execute
|
|
================================
|
|
Like Python and BASH, xonsh provides built-in hooks to compile, evaluate,
|
|
and execute strings of xonsh code. To prevent this functionality from having
|
|
serious name collisions with the Python built-in ``compile()``, ``eval()``,
|
|
and ``exec()`` functions, the xonsh equivalents all append an 'x'. So for
|
|
xonsh code you want to use the ``compilex()``, ``evalx()``, and ``execx()``
|
|
functions. If you don't know what these do, you probably don't need them.
|
|
|
|
|
|
Aliases
|
|
==============================
|
|
Another important xonsh built-in is the ``aliases`` mapping. This is
|
|
like a dictionary that effects how subprocess commands are run. If you are
|
|
familiar with the BASH ``alias`` built-in, this is similar. Alias command
|
|
matching only occurs for the first element of a subprocess command.
|
|
|
|
The keys of ``aliases`` are strings that act as commands in subprocess-mode.
|
|
The values are lists of strings, where the first element is the command and
|
|
the rest are the arguments. You can also set the value to a string, in which
|
|
case it will be converted to a list automatically with ``shlex.split``.
|
|
|
|
For example, the following creates several aliases for the ``git``
|
|
version control software. Both styles (list of strings and single
|
|
string) are shown:
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> aliases['g'] = 'git status -sb'
|
|
>>> aliases['gco'] = 'git checkout'
|
|
>>> aliases['gp'] = ['git', 'pull']
|
|
|
|
If you were to run ``gco feature-fabulous`` with the above aliases in effect,
|
|
the command would reduce to ``['git', 'checkout', 'feature-fabulous']`` before
|
|
being executed.
|
|
|
|
Lastly, if an alias value is a function (or other callable), then this
|
|
function is called *instead* of going to a subprocess command. Such functions
|
|
must have the following signature:
|
|
|
|
.. code-block:: python
|
|
|
|
def mycmd(args, stdin=None):
|
|
"""args will be a list of strings representing the arguments to this
|
|
command. stdin will be a string, if present. This is used to pipe
|
|
the output of the previous command into this one.
|
|
"""
|
|
# do whatever you want! Anything you print to stdout or stderr
|
|
# will be captured for you automatically. This allows callable
|
|
# aliases to support piping.
|
|
print('I go to stdout and will be printed or piped')
|
|
|
|
# Note: that you have access to the xonsh
|
|
# built-ins if you 'import builtins'. For example, if you need the
|
|
# environment, you could do to following:
|
|
import builtins
|
|
env = builtins.__xonsh_env__
|
|
|
|
# The return value of the function can either be None,
|
|
return
|
|
|
|
# a single string representing stdout
|
|
return 'I am out of here'
|
|
|
|
# or you can build up strings for stdout and stderr and then
|
|
# return a (stdout, stderr) tuple. Both of these may be
|
|
# either a str or None. Any results returned like this will be
|
|
# concatenated with the strings printed elsewhere in the function.
|
|
stdout = 'I commanded'
|
|
stderr = None
|
|
return stdout, stderr
|
|
|
|
We can dynamically alter the aliases present simply by modifying the
|
|
built-in mapping. Here is an example using a function value:
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> aliases['banana'] = lambda args, stdin=None: ('My spoon is tooo big!', None)
|
|
>>> banana
|
|
'My spoon is tooo big!'
|
|
|
|
Aliasing is a powerful way that xonsh allows you to seamlessly interact to
|
|
with Python and subprocess.
|
|
|
|
Up, Down, Tab
|
|
==============
|
|
The up and down keys search history matching from the start of the line,
|
|
much like they do in the IPython shell.
|
|
|
|
Tab completion is present as well. In Python-mode you are able to complete
|
|
based on the variable names in the current builtins, globals, and locals,
|
|
as well as xonsh languages keywords & operator, files & directories, and
|
|
environment variable names. In subprocess-mode, you additionally complete
|
|
on any file names on your ``$PATH``, alias keys, and full BASH completion
|
|
for the commands themselves.
|
|
|
|
Customizing the Prompt
|
|
======================
|
|
Customizing the prompt is probably the most common reason for altering an
|
|
environment variable. The ``PROMPT`` variable can be a string, or it can be a
|
|
function (of no arguments) that returns a string. The result can contain
|
|
keyword arguments, which will be replaced automatically:
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> $PROMPT = '{user}@{hostname}:{cwd} > '
|
|
snail@home:~ > # it works!
|
|
snail@home:~ > $PROMPT = lambda: '{user}@{hostname}:{cwd} >> '
|
|
snail@home:~ >> # so does that!
|
|
|
|
By default, the following variables are available for use:
|
|
* ``user``: The username of the current user
|
|
* ``hostname``: The name of the host computer
|
|
* ``cwd``: The current working directory
|
|
* ``cwd_dir``: The dirname of the current working directory, e.g. ``/path/to`` in
|
|
``/path/to/xonsh``.
|
|
* ``cwd_base``: The basename of the current working directory, e.g. ``xonsh`` in
|
|
``/path/to/xonsh``.
|
|
* ``curr_branch``: The name of the current git branch (preceded by space),
|
|
if any.
|
|
* ``branch_color``: ``{BOLD_GREEN}`` if the current git branch is clean,
|
|
otherwise ``{BOLD_RED}``
|
|
|
|
You can also color your prompt easily by inserting keywords such as ``{GREEN}``
|
|
or ``{BOLD_BLUE}``. Colors have the form shown below:
|
|
|
|
* ``(QUALIFIER\_)COLORNAME``: Inserts an ANSI color code
|
|
* ``COLORNAME`` can be any of: ``BLACK``, ``RED``, ``GREEN``, ``YELLOW``,
|
|
``BLUE``, ``PURPLE``, ``CYAN``, or ``WHITE``
|
|
* ``QUALIFIER`` is optional and can be any of: ``BOLD``, ``UNDERLINE``,
|
|
``BACKGROUND``, ``INTENSE``, ``BOLD_INTENSE``, or
|
|
``BACKGROUND_INTENSE``
|
|
* ``NO_COLOR``: Resets any previously used color codes
|
|
|
|
You can make use of additional variables beyond these by adding them to the
|
|
``FORMATTER_DICT`` environment variable. The values in this dictionary
|
|
should be strings (which will be inserted into the prompt verbatim), or
|
|
functions of no arguments (which will be called each time the prompt is
|
|
generated, and the results of those calls will be inserted into the prompt).
|
|
For example:
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
snail@home ~ $ $FORMATTER_DICT['test'] = "hey"
|
|
snail@home ~ $ $PROMPT = "{test} {cwd} $ "
|
|
hey ~ $
|
|
hey ~ $ import random
|
|
hey ~ $ $FORMATTER_DICT['test'] = lambda: random.randint(1,9)
|
|
3 ~ $
|
|
5 ~ $
|
|
2 ~ $
|
|
8 ~ $
|
|
|
|
If a function in ``$FORMATTER_DICT`` returns ``None``, the ``None`` will be
|
|
interpreted as an empty string.
|
|
|
|
|
|
Executing Commands and Scripts
|
|
==============================
|
|
When started with the ``-c`` flag and a command, xonsh will execute that command
|
|
and exit, instead of entering the command loop.
|
|
|
|
.. code-block:: bash
|
|
|
|
bash $ xonsh -c "echo @(7+3)"
|
|
10
|
|
|
|
Longer scripts can be run either by specifying a filename containing the script,
|
|
or by feeding them to xonsh via stdin. For example, consider the following
|
|
script, stored in ``test.xsh``:
|
|
|
|
.. code-block:: xonsh
|
|
|
|
#!/usr/bin/env xonsh
|
|
|
|
ls
|
|
|
|
print('removing files')
|
|
rm `file\d+.txt`
|
|
|
|
ls
|
|
|
|
print('adding files')
|
|
# This is a comment
|
|
for i, x in enumerate("xonsh"):
|
|
echo @(x) > @("file%d.txt" % i)
|
|
|
|
print($(ls).replace('\n', ' '))
|
|
|
|
|
|
This script could be run by piping its contents to xonsh:
|
|
|
|
.. code-block:: bash
|
|
|
|
bash $ cat test.xsh | xonsh
|
|
file0.txt file1.txt file2.txt file3.txt file4.txt test_script.sh
|
|
removing files
|
|
test_script.sh
|
|
adding files
|
|
file0.txt file1.txt file2.txt file3.txt file4.txt test_script.sh
|
|
|
|
or by invoking xonsh with its filename as an argument:
|
|
|
|
.. code-block:: bash
|
|
|
|
bash $ xonsh test.xsh
|
|
file0.txt file1.txt file2.txt file3.txt file4.txt test_script.sh
|
|
removing files
|
|
test_script.sh
|
|
adding files
|
|
file0.txt file1.txt file2.txt file3.txt file4.txt test_script.sh
|
|
|
|
xonsh scripts can also accept arguments. These arguments are made available to
|
|
the script in two different ways:
|
|
|
|
#. In either mode, as individual variables ``$ARG<n>`` (e.g., ``$ARG1``)
|
|
#. In Python mode only, as a list ``$ARGS``
|
|
|
|
For example, consider a slight variation of the example script from above that
|
|
operates on a given argument, rather than on the string ``'xonsh'`` (notice how
|
|
``$ARGS`` and ``$ARG1`` are used):
|
|
|
|
.. code-block:: xonsh
|
|
|
|
#!/usr/bin/env xonsh
|
|
|
|
print($ARGS)
|
|
|
|
ls
|
|
|
|
print('removing files')
|
|
rm `file\d+.txt`
|
|
|
|
ls
|
|
|
|
print('adding files')
|
|
# This is a comment
|
|
for i, x in enumerate($ARG1):
|
|
echo @(x) > @("file%d.txt" % i)
|
|
|
|
print($(ls).replace('\n', ' '))
|
|
print()
|
|
|
|
.. code-block:: bash
|
|
|
|
bash $ xonsh test2.xsh snails
|
|
['test_script.sh', 'snails']
|
|
file0.txt file1.txt file2.txt file3.txt file4.txt file5.txt test_script.sh
|
|
removing files
|
|
test_script.sh
|
|
adding files
|
|
file0.txt file1.txt file2.txt file3.txt file4.txt file5.txt test_script.sh
|
|
|
|
bash $ echo @(' '.join($(cat @('file%d.txt' % i)).strip() for i in range(6)))
|
|
s n a i l s
|
|
|
|
Importing Xonsh (``*.xsh``)
|
|
==============================
|
|
You can import xonsh source files with the ``*.xsh`` file extension using
|
|
the normal Python syntax. Say you had a file called ``mine.xsh``, you could
|
|
therefore perform a Bash-like source into your current shell with the
|
|
following:
|
|
|
|
.. code-block:: xonsh
|
|
|
|
from mine import *
|
|
|
|
|
|
That's All, Folks
|
|
======================
|
|
To leave xonsh, hit ``Ctrl-D``, type ``EOF``, type ``quit``, or type ``exit``.
|
|
On Windows you can also type ``Ctrl-Z``.
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
>>> exit
|
|
|
|
Now it is your turn.
|