2015-03-08 01:01:59 -06:00
|
|
|
|
.. _tutorial:
|
|
|
|
|
|
|
|
|
|
*******************
|
|
|
|
|
Tutorial
|
|
|
|
|
*******************
|
2015-03-22 15:48:26 -04:00
|
|
|
|
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
|
2015-10-06 18:18:25 -07:00
|
|
|
|
easy. The xonsh command prompt gives users interactive access to the xonsh
|
2015-03-22 15:48:26 -04:00
|
|
|
|
language.
|
2015-03-08 01:01:59 -06:00
|
|
|
|
|
2016-06-04 15:36:21 -04:00
|
|
|
|
While all Python code is also xonsh, not all Bash code can be used in xonsh.
|
2015-03-22 15:48:26 -04:00
|
|
|
|
That would defeat the purpose, and Python is better anyway! Still, xonsh is
|
2016-06-04 15:36:21 -04:00
|
|
|
|
Bash-wards compatible in the ways that matter, such as for running commands,
|
|
|
|
|
reading in the Bash environment, and utilizing Bash tab completion.
|
2015-03-08 01:01:59 -06:00
|
|
|
|
|
|
|
|
|
The purpose of this tutorial is to teach you xonsh. There are many excellent
|
2015-03-22 15:48:26 -04:00
|
|
|
|
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.
|
2015-03-08 01:01:59 -06:00
|
|
|
|
|
|
|
|
|
Let's dive in!
|
|
|
|
|
|
|
|
|
|
Starting xonsh
|
|
|
|
|
========================
|
2016-02-10 02:43:04 -05:00
|
|
|
|
Assuming you have successfully installed xonsh (see http://xon.sh),
|
2015-03-08 01:01:59 -06:00
|
|
|
|
you can start up the xonsh interpreter via the ``xonsh`` command. Suppose
|
|
|
|
|
you are in a lesser terminal:
|
|
|
|
|
|
2016-08-18 14:18:57 -04:00
|
|
|
|
.. code-block:: console
|
2015-03-08 01:01:59 -06:00
|
|
|
|
|
2016-08-18 14:18:57 -04:00
|
|
|
|
$ xonsh
|
2015-03-08 01:50:48 -06:00
|
|
|
|
snail@home ~ $
|
2015-03-08 01:01:59 -06:00
|
|
|
|
|
|
|
|
|
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 (``~``).
|
2015-03-22 15:48:26 -04:00
|
|
|
|
Alternatively, you can setup your terminal emulator (xterm, gnome-terminal,
|
2015-03-08 20:52:56 -05:00
|
|
|
|
etc) to run xonsh automatically when it starts up. This is recommended.
|
2015-03-08 01:01:59 -06:00
|
|
|
|
|
|
|
|
|
Basics
|
|
|
|
|
=======================
|
2015-03-22 15:48:26 -04:00
|
|
|
|
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,
|
2015-03-08 01:50:48 -06:00
|
|
|
|
simple:
|
|
|
|
|
|
2015-03-30 20:50:20 -05:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-08 01:50:48 -06:00
|
|
|
|
|
|
|
|
|
>>> 1 + 1
|
|
|
|
|
2
|
|
|
|
|
|
2015-03-22 15:48:26 -04:00
|
|
|
|
.. note:: From here on we'll be using ``>>>`` to prefix (or prompt) any
|
|
|
|
|
xonsh input. This follows the Python convention and helps trick
|
2015-03-08 01:50:48 -06:00
|
|
|
|
syntax highlighting, though ``$`` is more traditional for shells.
|
|
|
|
|
|
2015-03-22 15:48:26 -04:00
|
|
|
|
Since this is just Python, we are able import modules, print values,
|
2015-03-08 01:50:48 -06:00
|
|
|
|
and use other built-in Python functionality:
|
|
|
|
|
|
2015-03-30 20:50:20 -05:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-08 01:50:48 -06:00
|
|
|
|
|
|
|
|
|
>>> import sys
|
|
|
|
|
>>> print(sys.version)
|
2015-03-22 15:48:26 -04:00
|
|
|
|
3.4.2 |Continuum Analytics, Inc.| (default, Oct 21 2014, 17:16:37)
|
2015-03-08 01:50:48 -06:00
|
|
|
|
[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,
|
2015-03-22 15:48:26 -04:00
|
|
|
|
sets, and dictionaries. Everything that you are used to if you already know
|
2015-03-08 01:50:48 -06:00
|
|
|
|
Python is there:
|
|
|
|
|
|
2015-03-30 20:50:20 -05:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-08 01:50:48 -06:00
|
|
|
|
|
|
|
|
|
>>> d = {'xonsh': True}
|
|
|
|
|
>>> d.get('bash', False)
|
|
|
|
|
False
|
|
|
|
|
|
2015-03-22 15:48:26 -04:00
|
|
|
|
The xonsh shell also supports multi-line input for more advanced flow control.
|
2015-03-08 20:52:56 -05:00
|
|
|
|
The multi-line mode is automatically entered whenever the first line of input
|
2015-03-22 15:48:26 -04:00
|
|
|
|
is not syntactically valid on its own. Multi-line mode is then exited when
|
2015-03-08 01:50:48 -06:00
|
|
|
|
enter (or return) is pressed when the cursor is in the first column.
|
|
|
|
|
|
2015-03-30 20:50:20 -05:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-08 01:50:48 -06:00
|
|
|
|
|
|
|
|
|
>>> if True:
|
|
|
|
|
... print(1)
|
|
|
|
|
... else:
|
|
|
|
|
... print(2)
|
|
|
|
|
...
|
|
|
|
|
1
|
|
|
|
|
|
|
|
|
|
Flow control, of course, includes loops.
|
|
|
|
|
|
2015-03-30 20:50:20 -05:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-08 01:50:48 -06:00
|
|
|
|
|
|
|
|
|
>>> for i, x in enumerate('xonsh'):
|
|
|
|
|
... print(i, x)
|
|
|
|
|
...
|
|
|
|
|
0 x
|
|
|
|
|
1 o
|
|
|
|
|
2 n
|
|
|
|
|
3 s
|
|
|
|
|
4 h
|
|
|
|
|
|
2015-03-22 15:48:26 -04:00
|
|
|
|
We can also define and call functions and classes. I'll mostly spare you the
|
2015-03-08 01:50:48 -06:00
|
|
|
|
details, but this *is* pretty cool:
|
|
|
|
|
|
2015-03-30 20:50:20 -05:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-08 01:50:48 -06:00
|
|
|
|
|
|
|
|
|
>>> def f():
|
|
|
|
|
... return "xonsh"
|
|
|
|
|
...
|
|
|
|
|
>>> f()
|
|
|
|
|
'xonsh'
|
|
|
|
|
|
2015-03-19 17:39:10 +02:00
|
|
|
|
For easier indentation, Shift+Tab will enter 4 spaces.
|
2015-03-22 15:48:26 -04:00
|
|
|
|
And that about wraps it up for the basics section. It is just like Python.
|
2015-03-08 15:11:36 -05:00
|
|
|
|
|
|
|
|
|
Environment Variables
|
|
|
|
|
=======================
|
2015-03-22 15:48:26 -04:00
|
|
|
|
Environment variables are written as ``$`` followed by a name. For example,
|
|
|
|
|
``$HOME``, ``$PWD``, and ``$PATH``.
|
2015-03-08 15:11:36 -05:00
|
|
|
|
|
2015-03-30 20:50:20 -05:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-08 15:11:36 -05:00
|
|
|
|
|
|
|
|
|
>>> $HOME
|
|
|
|
|
'/home/snail'
|
|
|
|
|
|
2015-03-22 15:48:26 -04:00
|
|
|
|
You can set (and export) environment variables like you would set any other
|
2015-03-08 15:11:36 -05:00
|
|
|
|
variable in Python. The same is true for deleting them too.
|
|
|
|
|
|
2015-03-31 01:10:19 -05:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-08 15:11:36 -05:00
|
|
|
|
|
|
|
|
|
>>> $GOAL = 'Become the Lord of the Files'
|
|
|
|
|
>>> print($GOAL)
|
|
|
|
|
Become the Lord of the Files
|
|
|
|
|
>>> del $GOAL
|
|
|
|
|
|
2016-04-01 01:41:23 -04:00
|
|
|
|
Very nice.
|
|
|
|
|
|
2016-06-21 04:55:33 +03:00
|
|
|
|
The Environment Itself ``${...}``
|
|
|
|
|
---------------------------------
|
2016-06-21 04:45:29 +03:00
|
|
|
|
|
|
|
|
|
All environment variables live in the built-in ``${...}`` (aka ``__xonsh_env__``) mapping.
|
|
|
|
|
You can access this mapping directly, but in most situations, you shouldn’t need to.
|
|
|
|
|
|
2016-06-21 05:00:38 +03:00
|
|
|
|
If you want for example to check if an environment variable is present in your current
|
|
|
|
|
session (say, in your awesome new ``xonsh`` script) you can use the membership operator:
|
2016-09-21 13:27:34 +03:00
|
|
|
|
|
2016-06-21 05:00:38 +03:00
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
|
|
|
|
|
|
>>> 'HOME' in ${...}
|
|
|
|
|
True
|
|
|
|
|
|
2017-06-07 11:51:06 -04:00
|
|
|
|
To get information about a specific environment variable you can use the
|
2016-09-21 13:27:34 +03:00
|
|
|
|
:func:`~xonsh.environ.Env.help` method.
|
|
|
|
|
|
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
|
|
|
|
|
|
>>> ${...}.help('XONSH_DEBUG')
|
|
|
|
|
|
2016-06-21 04:55:33 +03:00
|
|
|
|
One helpful method on the ``${...}`` is :func:`~xonsh.environ.Env.swap`.
|
|
|
|
|
It can be used to temporarily set an environment variable:
|
2016-06-21 04:45:29 +03:00
|
|
|
|
|
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
|
|
|
|
|
|
>>> with ${...}.swap(SOMEVAR='foo'):
|
|
|
|
|
... echo $SOMEVAR
|
|
|
|
|
...
|
|
|
|
|
...
|
|
|
|
|
foo
|
|
|
|
|
>>> echo $SOMEVAR
|
|
|
|
|
|
|
|
|
|
>>>
|
|
|
|
|
|
2016-06-21 05:08:54 +03:00
|
|
|
|
Environment Lookup with ``${<expr>}``
|
2016-06-21 05:20:55 +03:00
|
|
|
|
-------------------------------------
|
2016-06-21 04:27:23 +03:00
|
|
|
|
|
|
|
|
|
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
|
2016-06-21 04:34:30 +03:00
|
|
|
|
value in the environment. Here are a couple of examples in action:
|
2016-06-21 04:27:23 +03:00
|
|
|
|
|
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
|
|
|
|
|
|
>>> x = 'USER'
|
|
|
|
|
>>> ${x}
|
|
|
|
|
'snail'
|
|
|
|
|
>>> ${'HO' + 'ME'}
|
|
|
|
|
'/home/snail'
|
|
|
|
|
|
|
|
|
|
Not bad, xonsh, not bad.
|
|
|
|
|
|
2016-04-01 01:41:23 -04:00
|
|
|
|
Environment Types
|
|
|
|
|
-----------------
|
2015-03-08 15:11:36 -05:00
|
|
|
|
|
|
|
|
|
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:
|
|
|
|
|
|
2015-08-04 22:24:25 -05:00
|
|
|
|
* ``\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.
|
2015-03-08 15:11:36 -05:00
|
|
|
|
* ``XONSH_HISTORY_SIZE``: this variable is an int.
|
2015-08-04 22:24:25 -05:00
|
|
|
|
* ``CASE_SENSITIVE_COMPLETIONS``: this variable is a boolean.
|
2015-03-08 15:11:36 -05:00
|
|
|
|
|
|
|
|
|
xonsh will automatically convert back and forth to untyped (string-only)
|
|
|
|
|
representations of the environment as needed (mostly by subprocess commands).
|
2015-03-22 15:48:26 -04:00
|
|
|
|
When in xonsh, you'll always have the typed version. Here are a couple of
|
2015-03-08 15:11:36 -05:00
|
|
|
|
PATH examples:
|
|
|
|
|
|
2015-03-31 01:10:19 -05:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-08 15:11:36 -05:00
|
|
|
|
|
|
|
|
|
>>> $PATH
|
2015-03-22 15:48:26 -04:00
|
|
|
|
['/home/snail/.local/bin', '/home/snail/sandbox/bin',
|
|
|
|
|
'/home/snail/miniconda3/bin', '/usr/local/bin', '/usr/local/sbin',
|
2015-03-08 15:11:36 -05:00
|
|
|
|
'/usr/bin', '/usr/sbin', '/bin', '/sbin', '.']
|
|
|
|
|
>>> $LD_LIBRARY_PATH
|
2015-03-08 17:57:12 -05:00
|
|
|
|
['/home/snail/.local/lib', '']
|
2015-03-08 15:11:36 -05:00
|
|
|
|
|
|
|
|
|
Also note that *any* Python object can go into the environment. It is sometimes
|
2015-03-08 20:52:56 -05:00
|
|
|
|
useful to have more sophisticated types, like functions, in the environment.
|
2015-03-08 15:11:36 -05:00
|
|
|
|
There are handful of environment variables that xonsh considers special.
|
2015-08-29 16:35:46 -04:00
|
|
|
|
They can be seen on the `Environment Variables page <envvars.html>`_.
|
2015-03-08 15:11:36 -05:00
|
|
|
|
|
2016-01-10 19:56:07 -05:00
|
|
|
|
.. note:: In subprocess mode, referencing an undefined environment variable
|
|
|
|
|
will produce an empty string. In Python mode, however, a
|
|
|
|
|
``KeyError`` will be raised if the variable does not exist in the
|
|
|
|
|
environment.
|
|
|
|
|
|
2015-03-08 16:58:10 -05:00
|
|
|
|
Running Commands
|
|
|
|
|
==============================
|
2015-03-22 15:48:26 -04:00
|
|
|
|
As a shell, xonsh is meant to make running commands easy and fun.
|
2015-03-08 16:58:10 -05:00
|
|
|
|
Running subprocess commands should work like any other in any other shell.
|
|
|
|
|
|
2015-03-31 01:10:19 -05:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-08 16:58:10 -05:00
|
|
|
|
|
|
|
|
|
>>> echo "Yoo hoo"
|
|
|
|
|
Yoo hoo
|
|
|
|
|
>>> cd xonsh
|
|
|
|
|
>>> ls
|
2015-03-09 10:54:59 +01:00
|
|
|
|
build docs README.rst setup.py xonsh __pycache__
|
2015-03-08 16:58:10 -05:00
|
|
|
|
dist license scripts tests xonsh.egg-info
|
2015-05-16 01:37:06 -04:00
|
|
|
|
>>> dir scripts
|
|
|
|
|
xonsh xonsh.bat
|
2015-03-08 16:58:10 -05:00
|
|
|
|
>>> 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
|
2015-03-22 15:48:26 -04:00
|
|
|
|
in pure Python mode and lines that use shell-specific syntax, edit the
|
2015-03-08 20:52:56 -05:00
|
|
|
|
execution environment, and run commands. Unfortunately, it is not always
|
2015-03-08 16:58:10 -05:00
|
|
|
|
clear from the syntax alone what mode is desired. This ambiguity stems from
|
|
|
|
|
most command line utilities looking a lot like Python operators.
|
|
|
|
|
|
2015-03-22 15:48:26 -04:00
|
|
|
|
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
|
2015-03-08 16:58:10 -05:00
|
|
|
|
that ``ls -l`` is meant to be run in subprocess-mode?
|
|
|
|
|
|
2015-03-22 15:48:26 -04:00
|
|
|
|
For any given line that only contains an expression statement (expr-stmt,
|
2016-08-21 14:58:07 -04:00
|
|
|
|
see the Python AST docs for more information), if all the names cannot
|
2016-08-23 08:45:51 -04:00
|
|
|
|
be found as current variables xonsh will try to parse the line as a
|
2016-09-03 13:13:13 +08:00
|
|
|
|
subprocess command instead. In the above, if ``ls`` and ``l`` are not
|
2016-08-21 14:58:07 -04:00
|
|
|
|
variables, then subprocess mode will be attempted. If parsing in subprocess
|
|
|
|
|
mode fails, then the line is left in Python-mode.
|
2015-03-08 16:58:10 -05:00
|
|
|
|
|
2015-03-22 15:48:26 -04:00
|
|
|
|
In the following example, we will list the contents of the directory
|
2015-03-08 16:58:10 -05:00
|
|
|
|
with ``ls -l``. Then we'll make new variable names ``ls`` and ``l`` and then
|
2015-03-22 15:48:26 -04:00
|
|
|
|
subtract them. Finally, we will delete ``ls`` and ``l`` and be able to list
|
2015-03-08 16:58:10 -05:00
|
|
|
|
the directories again.
|
|
|
|
|
|
2015-03-31 01:10:19 -05:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-08 16:58:10 -05:00
|
|
|
|
|
|
|
|
|
>>> # 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
|
2016-08-21 14:58:07 -04:00
|
|
|
|
>>> # set ls and l variables to force python-mode
|
2015-03-08 16:58:10 -05:00
|
|
|
|
>>> ls = 44
|
|
|
|
|
>>> l = 2
|
|
|
|
|
>>> ls -l
|
|
|
|
|
42
|
2017-06-07 11:51:06 -04:00
|
|
|
|
>>> # deleting ls will return us to subproc-mode
|
2015-03-08 16:58:10 -05:00
|
|
|
|
>>> 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.
|
2015-03-22 15:48:26 -04:00
|
|
|
|
You do not need to worry about partially executed commands - that is
|
2015-03-08 16:58:10 -05:00
|
|
|
|
impossible.
|
|
|
|
|
|
2015-05-16 01:37:06 -04:00
|
|
|
|
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.
|
2015-03-08 16:58:10 -05:00
|
|
|
|
|
|
|
|
|
|
2016-10-15 20:12:10 +03:00
|
|
|
|
Quoting
|
|
|
|
|
=======
|
|
|
|
|
|
|
|
|
|
Single or double quotes can be used to remove the special meaning
|
|
|
|
|
of certain characters or words to xonsh. If a subprocess command
|
|
|
|
|
contains characters that collide with xonsh syntax then quotes
|
|
|
|
|
must be used to force xonsh to not interpret them.
|
|
|
|
|
|
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
|
|
|
|
|
|
>>> echo ${
|
|
|
|
|
...
|
|
|
|
|
SyntaxError: <xonsh-code>:1:5: ('code: {',)
|
2016-10-15 23:43:22 +03:00
|
|
|
|
echo ${
|
2016-10-15 20:12:10 +03:00
|
|
|
|
^
|
|
|
|
|
>>> echo '${'
|
|
|
|
|
${
|
|
|
|
|
|
|
|
|
|
.. warning:: There is no notion of an escaping character in xonsh like the
|
2017-01-03 12:56:44 +01:00
|
|
|
|
backslash (\\) in bash.
|
2016-10-15 20:12:10 +03:00
|
|
|
|
|
|
|
|
|
|
2016-03-12 19:33:01 -05:00
|
|
|
|
Captured Subprocess with ``$()`` and ``!()``
|
|
|
|
|
============================================
|
2015-03-22 15:48:26 -04:00
|
|
|
|
The ``$(<expr>)`` operator in xonsh executes a subprocess command and
|
2016-03-12 19:33:01 -05:00
|
|
|
|
*captures* some information about that command.
|
|
|
|
|
|
|
|
|
|
The ``$()`` syntax captures and returns the standard output stream of the
|
2016-06-04 15:36:21 -04:00
|
|
|
|
command as a Python string. This is similar to how ``$()`` performs in Bash.
|
2016-03-12 19:33:01 -05:00
|
|
|
|
For example,
|
2015-03-08 16:58:10 -05:00
|
|
|
|
|
2015-03-30 22:20:22 -05:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-08 16:58:10 -05:00
|
|
|
|
|
|
|
|
|
>>> $(ls -l)
|
|
|
|
|
'total 0\n-rw-rw-r-- 1 snail snail 0 Mar 8 15:46 xonsh\n'
|
|
|
|
|
|
2016-03-12 19:33:01 -05:00
|
|
|
|
The ``!()`` syntax captured more information about the command, as an instance
|
2017-01-24 05:31:55 +00:00
|
|
|
|
of a class called ``CommandPipeline``. This object contains more information
|
2016-03-12 19:33:01 -05:00
|
|
|
|
about the result of the given command, including the return code, the process
|
2016-06-09 12:47:07 +10:00
|
|
|
|
id, the standard output and standard error streams, and information about how
|
2016-03-12 19:33:01 -05:00
|
|
|
|
input and output were redirected. For example:
|
|
|
|
|
|
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
|
|
|
|
|
|
>>> !(ls nonexistent_directory)
|
2017-01-24 05:31:55 +00:00
|
|
|
|
CommandPipeline(stdin=<_io.BytesIO object at 0x7f1948182bf8>, stdout=<_io.BytesIO object at 0x7f1948182af0>, stderr=<_io.BytesIO object at 0x7f19483a6200>, pid=26968, returncode=2, args=['ls', 'nonexistent_directory'], alias=['ls', '--color=auto', '-v'], stdin_redirect=['<stdin>', 'r'], stdout_redirect=[9, 'wb'], stderr_redirect=[11, 'w'], timestamps=[1485235484.5016758, None], executed_cmd=['ls', '--color=auto', '-v', 'nonexistent_directory'], input=None, output=, errors=None)
|
2016-03-12 19:33:01 -05:00
|
|
|
|
|
|
|
|
|
This object will be "truthy" if its return code was 0, and it is equal (via
|
|
|
|
|
``==``) to its return code. It also hashes to its return code. This allows
|
|
|
|
|
for some interesting new kinds of interactions with subprocess commands, for
|
|
|
|
|
example:
|
|
|
|
|
|
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
|
|
|
|
|
|
def check_file(file):
|
2016-03-16 12:30:45 -04:00
|
|
|
|
if !(test -e @(file)):
|
|
|
|
|
if !(test -f @(file)) or !(test -d @(file)):
|
2016-03-12 19:33:01 -05:00
|
|
|
|
print("File is a regular file or directory")
|
|
|
|
|
else:
|
|
|
|
|
print("File is not a regular file or directory")
|
|
|
|
|
else:
|
|
|
|
|
print("File does not exist")
|
|
|
|
|
|
|
|
|
|
def wait_until_google_responds():
|
2016-03-16 12:30:45 -04:00
|
|
|
|
while not !(ping -c 1 google.com):
|
2016-03-12 19:33:01 -05:00
|
|
|
|
sleep 1
|
|
|
|
|
|
|
|
|
|
|
2017-01-24 05:31:55 +00:00
|
|
|
|
If you iterate over the ``CommandPipeline`` object, it will yield lines of its
|
2016-06-09 21:32:34 -04:00
|
|
|
|
output. Using this, you can quickly and cleanly process output from commands.
|
|
|
|
|
Additionally, these objects expose a method ``itercheck``, which behaves the same
|
|
|
|
|
as the built-in iterator but raises ``XonshCalledProcessError`` if the process
|
|
|
|
|
had a nonzero return code.
|
2016-06-09 05:12:21 -04:00
|
|
|
|
|
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
|
|
|
|
|
|
def get_wireless_interface():
|
|
|
|
|
"""Returns devicename of first connected wifi, None otherwise"""
|
|
|
|
|
for line in !(nmcli device):
|
|
|
|
|
dev, typ, state, conn_name = line.split(None, 3)
|
|
|
|
|
if typ == 'wifi' and state == 'connected':
|
|
|
|
|
return dev
|
|
|
|
|
|
|
|
|
|
def grep_path(path, regexp):
|
|
|
|
|
"""Recursively greps `path` for perl `regexp`
|
|
|
|
|
|
|
|
|
|
Returns a dict of 'matches' and 'failures'.
|
|
|
|
|
Matches are files that contain the given regexp.
|
|
|
|
|
Failures are files that couldn't be scanned.
|
|
|
|
|
"""
|
|
|
|
|
matches = []
|
|
|
|
|
failures = []
|
|
|
|
|
|
|
|
|
|
try:
|
2016-06-09 21:32:34 -04:00
|
|
|
|
for match in !(grep -RPl @(regexp) @(str(path))).itercheck():
|
2016-06-09 05:12:21 -04:00
|
|
|
|
matches.append(match)
|
|
|
|
|
except XonshCalledProcessError as error:
|
|
|
|
|
for line in error.stderr.split('\n'):
|
|
|
|
|
if not line.strip():
|
|
|
|
|
continue
|
|
|
|
|
filename = line.split('grep: ', 1)[1].rsplit(':', 1)[0]
|
|
|
|
|
failures.append(filename)
|
|
|
|
|
return {'matches': matches, 'failures': failures}
|
|
|
|
|
|
|
|
|
|
|
2016-03-12 19:33:01 -05:00
|
|
|
|
The ``$()`` and ``!()`` operators are expressions themselves. This means that
|
|
|
|
|
we can assign the results to a variable or perform any other manipulations we
|
|
|
|
|
want.
|
2015-03-08 16:58:10 -05:00
|
|
|
|
|
2015-03-30 22:20:22 -05:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-08 16:58:10 -05:00
|
|
|
|
|
|
|
|
|
>>> x = $(ls -l)
|
|
|
|
|
>>> print(x.upper())
|
|
|
|
|
TOTAL 0
|
|
|
|
|
-RW-RW-R-- 1 SNAIL SNAIL 0 MAR 8 15:46 XONSH
|
2016-03-12 19:33:01 -05:00
|
|
|
|
>>> y = !(ls -l)
|
|
|
|
|
>>> print(y.returncode)
|
|
|
|
|
0
|
2016-03-16 12:30:45 -04:00
|
|
|
|
>>> print(y.rtn) # alias to returncode
|
|
|
|
|
0
|
2016-03-12 19:33:01 -05:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
.. warning:: Job control is not implemented for captured subprocesses.
|
2015-03-08 16:58:10 -05:00
|
|
|
|
|
2015-03-22 15:48:26 -04:00
|
|
|
|
While in subprocess-mode or inside of a captured subprocess, we can always
|
2016-03-12 19:33:01 -05:00
|
|
|
|
still query the environment with ``$NAME`` variables or the ``${}`` syntax,
|
|
|
|
|
or inject Python values with the ``@()`` operator:
|
2015-03-08 16:58:10 -05:00
|
|
|
|
|
2015-03-31 01:10:19 -05:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-08 16:58:10 -05:00
|
|
|
|
|
|
|
|
|
>>> $(echo $HOME)
|
|
|
|
|
'/home/snail\n'
|
|
|
|
|
|
2016-03-12 19:33:01 -05:00
|
|
|
|
Uncaptured Subprocess with ``$[]`` and ``![]``
|
2016-03-16 01:51:11 -04:00
|
|
|
|
===============================================
|
2016-03-12 19:33:01 -05:00
|
|
|
|
Uncaptured subprocesses are denoted with the ``$[]`` and ``![]`` operators. They are
|
2015-03-22 15:48:26 -04:00
|
|
|
|
the same as ``$()`` captured subprocesses in almost every way. The only
|
2015-03-08 16:58:10 -05:00
|
|
|
|
difference is that the subprocess's stdout passes directly through xonsh and
|
2015-03-22 15:48:26 -04:00
|
|
|
|
to the screen. The return value of ``$[]`` is always ``None``.
|
2015-03-08 16:58:10 -05:00
|
|
|
|
|
2015-03-08 17:22:23 -05:00
|
|
|
|
In the following, we can see that the results of ``$[]`` are automatically
|
2018-04-04 12:39:38 -04:00
|
|
|
|
printed, and that the return value is not a string.
|
2015-03-08 16:58:10 -05:00
|
|
|
|
|
2015-03-31 01:10:19 -05:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-08 16:58:10 -05:00
|
|
|
|
|
|
|
|
|
>>> x = $[ls -l]
|
|
|
|
|
total 0
|
2015-03-08 17:57:12 -05:00
|
|
|
|
-rw-rw-r-- 1 snail snail 0 Mar 8 15:46 xonsh
|
2015-03-08 16:58:10 -05:00
|
|
|
|
>>> x is None
|
|
|
|
|
True
|
|
|
|
|
|
2016-03-12 19:33:01 -05:00
|
|
|
|
The ``![]`` operator is similar to the ``!()`` in that it returns an object
|
|
|
|
|
containing information about the result of executing the given command.
|
|
|
|
|
However, its standard output and standard error streams are directed to the
|
|
|
|
|
terminal, and the resulting object is not displayed. For example
|
|
|
|
|
|
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
|
|
|
|
|
|
>>> x = ![ls -l] and ![echo "hi"]
|
|
|
|
|
total 0
|
|
|
|
|
-rw-rw-r-- 1 snail snail 0 Mar 8 15:46 xonsh
|
|
|
|
|
hi
|
|
|
|
|
|
|
|
|
|
|
2015-03-20 17:30:24 -04:00
|
|
|
|
Python Evaluation with ``@()``
|
|
|
|
|
===============================
|
2015-03-22 15:48:26 -04:00
|
|
|
|
|
2016-06-02 23:53:55 -05:00
|
|
|
|
The ``@(<expr>)`` operator form works in subprocess mode, and will evaluate
|
2016-06-11 01:53:11 -04:00
|
|
|
|
arbitrary Python code. The result is 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
|
2016-06-11 20:52:47 -04:00
|
|
|
|
and appended to the argument list in order. If the result in the first position
|
|
|
|
|
is a function, it is treated as an alias (see the section on `Aliases`_ below),
|
|
|
|
|
even if it was not explicitly added to the ``aliases`` mapping. Otherwise, the
|
|
|
|
|
result is automatically converted to a string. For example,
|
2015-03-20 17:30:24 -04:00
|
|
|
|
|
2015-03-31 01:10:19 -05:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-20 17:30:24 -04:00
|
|
|
|
|
|
|
|
|
>>> x = 'xonsh'
|
|
|
|
|
>>> y = 'party'
|
|
|
|
|
>>> echo @(x + ' ' + y)
|
|
|
|
|
xonsh party
|
|
|
|
|
>>> echo @(2+2)
|
|
|
|
|
4
|
2015-03-28 17:55:48 -05:00
|
|
|
|
>>> echo @([42, 'yo'])
|
|
|
|
|
42 yo
|
2017-01-04 14:09:42 +01:00
|
|
|
|
>>> echo "hello" | @(lambda a, s=None: s.read().strip() + " world\n")
|
2016-06-11 20:52:47 -04:00
|
|
|
|
hello world
|
2018-05-04 14:24:30 -04:00
|
|
|
|
>>> @(['echo', 'hello', 'world'])
|
2018-05-04 12:18:22 -04:00
|
|
|
|
hello world
|
2018-05-04 14:27:07 -04:00
|
|
|
|
>>> @('echo hello world') # note that strings are not split automatically
|
2018-05-04 14:24:30 -04:00
|
|
|
|
xonsh: subprocess mode: command not found: echo hello world
|
2018-05-04 12:18:22 -04:00
|
|
|
|
|
2015-03-20 17:30:24 -04:00
|
|
|
|
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.
|
|
|
|
|
|
2015-03-30 20:50:20 -05:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-20 17:30:24 -04:00
|
|
|
|
|
|
|
|
|
>>> out = $(echo @(x + ' ' + y))
|
|
|
|
|
>>> out
|
|
|
|
|
'xonsh party\n'
|
|
|
|
|
>>> @("ech" + "o") "hey"
|
|
|
|
|
hey
|
|
|
|
|
|
2015-03-22 15:48:26 -04:00
|
|
|
|
Thus, ``@()`` allows us to create complex commands in Python-mode and then
|
2015-03-20 17:30:24 -04:00
|
|
|
|
feed them to a subprocess as needed. For example:
|
|
|
|
|
|
2016-10-25 11:01:03 -04:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-20 17:30:24 -04:00
|
|
|
|
|
|
|
|
|
for i in range(20):
|
|
|
|
|
$[touch @('file%02d' % i)]
|
|
|
|
|
|
2016-05-21 22:29:48 -04:00
|
|
|
|
Command Substitution with ``@$()``
|
|
|
|
|
==================================
|
|
|
|
|
|
|
|
|
|
A common use of the ``@()`` and ``$()`` operators is allowing the output of a
|
|
|
|
|
command to replace the command itself (command substitution):
|
|
|
|
|
``@([i.strip() for i in $(cmd).split()])``. Xonsh offers a
|
|
|
|
|
short-hand syntax for this operation: ``@$(cmd)``.
|
|
|
|
|
|
|
|
|
|
Consider the following example:
|
|
|
|
|
|
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
|
|
|
|
|
|
>>> # this returns a string representing stdout
|
|
|
|
|
>>> $(which ls)
|
|
|
|
|
'ls --color=auto\n'
|
|
|
|
|
|
|
|
|
|
>>> # this attempts to run the command, but as one argument
|
|
|
|
|
>>> # (looks for 'ls --color=auto\n' with spaces and newline)
|
|
|
|
|
>>> @($(which ls).strip())
|
|
|
|
|
xonsh: subprocess mode: command not found: ls --color=auto
|
|
|
|
|
|
|
|
|
|
>>> # this actually executes the intended command
|
|
|
|
|
>>> @([i.strip() for i in $(which ls).split()])
|
|
|
|
|
some_file some_other_file
|
|
|
|
|
|
|
|
|
|
>>> # this does the same thing, but is much more concise
|
|
|
|
|
>>> @$(which ls)
|
|
|
|
|
some_file some_other_file
|
|
|
|
|
|
2015-03-08 16:58:10 -05:00
|
|
|
|
|
2015-03-08 17:22:23 -05:00
|
|
|
|
Nesting Subprocesses
|
|
|
|
|
=====================================
|
2015-03-20 17:30:24 -04:00
|
|
|
|
Though I am begging you not to abuse this, it is possible to nest the
|
|
|
|
|
subprocess operators that we have seen so far (``$()``, ``$[]``, ``${}``,
|
2016-05-21 22:29:48 -04:00
|
|
|
|
``@()``, ``@$()``). An instance of ``ls -l`` that is on the wrong side of the
|
|
|
|
|
border of the absurd is shown below:
|
2015-03-08 17:22:23 -05:00
|
|
|
|
|
2016-05-28 19:13:06 -04:00
|
|
|
|
.. code-block:: console
|
2015-03-08 17:22:23 -05:00
|
|
|
|
|
2016-05-21 22:29:48 -04:00
|
|
|
|
>>> $[@$(which @($(echo ls).strip())) @('-' + $(printf 'l'))]
|
2015-03-08 17:22:23 -05:00
|
|
|
|
total 0
|
2015-03-08 17:57:12 -05:00
|
|
|
|
-rw-rw-r-- 1 snail snail 0 Mar 8 15:46 xonsh
|
2015-03-08 17:22:23 -05:00
|
|
|
|
|
|
|
|
|
With great power, and so forth...
|
|
|
|
|
|
2015-03-20 17:30:24 -04:00
|
|
|
|
.. note:: Nesting these subprocess operators inside of ``$()`` and/or ``$[]``
|
2016-02-15 21:11:30 +01:00
|
|
|
|
works because the contents of those operators are executed in
|
2015-03-20 17:30:24 -04:00
|
|
|
|
subprocess mode. Since ``@()`` and ``${}`` run their contents in
|
|
|
|
|
Python mode, it is not possible to nest other subprocess operators
|
|
|
|
|
inside of them.
|
|
|
|
|
|
2015-05-20 14:43:20 -04:00
|
|
|
|
Pipes
|
|
|
|
|
====================
|
2015-03-20 17:30:24 -04:00
|
|
|
|
|
2015-03-08 17:22:23 -05:00
|
|
|
|
In subprocess-mode, xonsh allows you to use the ``|`` character to pipe
|
|
|
|
|
together commands as you would in other shells.
|
|
|
|
|
|
2015-03-31 01:10:19 -05:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-08 17:22:23 -05:00
|
|
|
|
|
|
|
|
|
>>> env | uniq | sort | grep PATH
|
|
|
|
|
DATAPATH=/usr/share/MCNPX/v260/Data/
|
|
|
|
|
DEFAULTS_PATH=/usr/share/gconf/awesome-gnome.default.path
|
2015-03-08 17:57:12 -05:00
|
|
|
|
LD_LIBRARY_PATH=/home/snail/.local/lib:
|
2015-03-08 17:22:23 -05:00
|
|
|
|
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
|
|
|
|
|
|
2015-03-22 15:48:26 -04:00
|
|
|
|
This is only available in subprocess-mode because ``|`` is otherwise a
|
2015-03-08 17:49:18 -05:00
|
|
|
|
Python operator.
|
2015-03-08 20:52:56 -05:00
|
|
|
|
If you are unsure of what pipes are, there are many great references out there.
|
2015-03-08 17:22:23 -05:00
|
|
|
|
You should be able to find information on StackOverflow or Google.
|
|
|
|
|
|
2016-02-10 02:13:07 -05:00
|
|
|
|
Logical Subprocess And
|
|
|
|
|
=======================
|
|
|
|
|
|
2016-02-29 21:18:22 -05:00
|
|
|
|
Subprocess-mode also allows you to use the ``and`` operator to chain together
|
|
|
|
|
subprocess commands. The truth value of a command is evaluated as whether
|
|
|
|
|
its return code is zero (i.e. ``proc.returncode == 0``). Like in Python,
|
|
|
|
|
if the command evaluates to ``False``, subsequent commands will not be executed.
|
2016-02-10 02:13:07 -05:00
|
|
|
|
For example, suppose we want to lists files that may or may not exist:
|
|
|
|
|
|
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
|
|
|
|
|
|
>>> touch exists
|
|
|
|
|
>>> ls exists and ls doesnt
|
|
|
|
|
exists
|
|
|
|
|
/bin/ls: cannot access doesnt: No such file or directory
|
|
|
|
|
|
2016-02-29 21:18:22 -05:00
|
|
|
|
However, if you list the file that doesn't exist first,
|
2016-02-10 02:13:07 -05:00
|
|
|
|
you would have only seen the error:
|
|
|
|
|
|
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
|
|
2016-02-29 21:18:22 -05:00
|
|
|
|
>>> ls doesnt and ls exists
|
2016-02-10 02:13:07 -05:00
|
|
|
|
/bin/ls: cannot access doesnt: No such file or directory
|
|
|
|
|
|
|
|
|
|
Also, don't worry. Xonsh directly translates the ``&&`` operator into ``and``
|
|
|
|
|
for you. It is less Pythonic, of course, but it is your shell!
|
|
|
|
|
|
|
|
|
|
Logical Subprocess Or
|
|
|
|
|
=======================
|
|
|
|
|
|
2016-02-29 21:18:22 -05:00
|
|
|
|
Much like with ``and``, you can use the ``or`` operator to chain together
|
|
|
|
|
subprocess commands. The difference, to be certain, is that
|
2016-02-10 02:13:07 -05:00
|
|
|
|
subsequent commands will be executed only if the
|
|
|
|
|
if the return code is non-zero (i.e. a failure). Using the file example
|
|
|
|
|
from above:
|
|
|
|
|
|
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
|
|
|
|
|
|
>>> ls exists or ls doesnt
|
|
|
|
|
exists
|
|
|
|
|
|
|
|
|
|
This doesn't even try to list a non-existent file!
|
2016-02-29 21:18:22 -05:00
|
|
|
|
However, if you list the file that doesn't exist first,
|
2016-02-10 02:13:07 -05:00
|
|
|
|
you will see the error and then the file that does exist:
|
|
|
|
|
|
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
|
|
2016-02-29 21:18:22 -05:00
|
|
|
|
>>> ls doesnt or ls exists
|
2016-02-10 02:13:07 -05:00
|
|
|
|
/bin/ls: cannot access doesnt: No such file or directory
|
|
|
|
|
exists
|
|
|
|
|
|
|
|
|
|
Never fear! Xonsh also directly translates the ``||`` operator into ``or``,
|
|
|
|
|
too. Your muscle memory is safe now, here with us.
|
2015-05-20 14:43:20 -04:00
|
|
|
|
|
2015-05-19 21:55:11 -04:00
|
|
|
|
Input/Output Redirection
|
|
|
|
|
====================================
|
2015-03-08 17:22:23 -05:00
|
|
|
|
|
2015-05-19 21:55:11 -04:00
|
|
|
|
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
|
2015-05-20 14:43:20 -04:00
|
|
|
|
it receives its input from. xonsh has its own syntax for these operations,
|
2015-07-25 01:58:56 -06:00
|
|
|
|
but, for compatibility purposes, xonsh also support Bash-like syntax.
|
2015-03-08 17:49:18 -05:00
|
|
|
|
|
2015-05-20 14:43:20 -04:00
|
|
|
|
The basic operations are "write to" (``>``), "append to" (``>>``), and "read
|
|
|
|
|
from" (``<``). The details of these are perhaps best explained through
|
|
|
|
|
examples.
|
2015-03-22 15:48:26 -04:00
|
|
|
|
|
2016-10-31 15:21:23 +05:30
|
|
|
|
.. note:: The target of the redirection should be separated by a space,
|
|
|
|
|
otherwise xonsh will raise a SyntaxError.
|
|
|
|
|
|
2015-05-20 14:43:20 -04:00
|
|
|
|
Redirecting ``stdout``
|
|
|
|
|
----------------------
|
2015-03-08 17:49:18 -05:00
|
|
|
|
|
2015-05-20 14:43:20 -04:00
|
|
|
|
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:
|
2015-03-08 17:49:18 -05:00
|
|
|
|
|
2015-03-31 01:10:19 -05:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-08 17:49:18 -05:00
|
|
|
|
|
2015-05-19 21:55:11 -04:00
|
|
|
|
>>> COMMAND > output.txt
|
|
|
|
|
>>> COMMAND out> output.txt
|
|
|
|
|
>>> COMMAND o> output.txt
|
2015-07-25 01:58:56 -06:00
|
|
|
|
>>> COMMAND 1> output.txt # included for Bash compatibility
|
2015-05-20 14:43:20 -04:00
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
2015-05-19 21:55:11 -04:00
|
|
|
|
>>> COMMAND err> errors.txt
|
|
|
|
|
>>> COMMAND e> errors.txt
|
2015-07-25 01:58:56 -06:00
|
|
|
|
>>> COMMAND 2> errors.txt # included for Bash compatibility
|
2015-05-20 14:43:20 -04:00
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
2015-05-19 21:55:11 -04:00
|
|
|
|
>>> COMMAND all> combined.txt
|
|
|
|
|
>>> COMMAND a> combined.txt
|
2015-07-25 01:58:56 -06:00
|
|
|
|
>>> COMMAND &> combined.txt # included for Bash compatibility
|
2015-05-20 14:43:20 -04:00
|
|
|
|
|
|
|
|
|
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
|
2017-01-11 23:29:28 -05:00
|
|
|
|
>>> COMMAND 2>&1 # included for Bash compatibility
|
2015-05-20 14:43:20 -04:00
|
|
|
|
|
|
|
|
|
This merge can be combined with other redirections, including pipes (see the
|
|
|
|
|
section on `Pipes`_ above):
|
|
|
|
|
|
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
|
|
|
|
|
|
>>> COMMAND err>out | COMMAND2
|
2015-05-19 21:55:11 -04:00
|
|
|
|
>>> COMMAND e>o > combined.txt
|
2015-05-20 14:43:20 -04:00
|
|
|
|
|
|
|
|
|
It is worth noting that this last example is equivalent to: ``COMMAND a> combined.txt``
|
|
|
|
|
|
2017-01-11 23:29:28 -05:00
|
|
|
|
Similarly, you can also send stdout to stderr with the following syntax:
|
|
|
|
|
|
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
|
|
|
|
|
|
>>> COMMAND out>err
|
|
|
|
|
>>> COMMAND out>e
|
|
|
|
|
>>> COMMAND o>err
|
|
|
|
|
>>> COMMAND o>e
|
|
|
|
|
>>> COMMAND 1>&2 # included for Bash compatibility
|
|
|
|
|
|
2015-05-20 14:43:20 -04:00
|
|
|
|
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
|
|
|
|
|
|
2015-05-19 21:55:11 -04:00
|
|
|
|
>>> COMMAND < input.txt
|
|
|
|
|
>>> < input.txt COMMAND
|
|
|
|
|
|
2015-05-20 14:43:20 -04:00
|
|
|
|
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``.
|
2015-05-19 21:55:11 -04:00
|
|
|
|
|
2015-03-08 17:57:12 -05:00
|
|
|
|
|
2015-04-06 17:13:43 -04:00
|
|
|
|
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``.
|
2015-03-08 20:33:33 -05:00
|
|
|
|
|
2015-03-31 01:10:19 -05:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-08 20:33:33 -05:00
|
|
|
|
|
|
|
|
|
>>> emacs &
|
|
|
|
|
>>>
|
|
|
|
|
|
2015-04-06 17:13:43 -04:00
|
|
|
|
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.
|
|
|
|
|
|
2015-05-16 01:37:06 -04:00
|
|
|
|
.. note:: Suspending processes via Control-Z is not yet supported when
|
|
|
|
|
running on Windows.
|
|
|
|
|
|
2015-04-06 17:13:43 -04:00
|
|
|
|
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
|
2016-06-08 18:43:39 -07:00
|
|
|
|
to the foreground. Additionally, specify "+" for the most recent job and "-"
|
|
|
|
|
for the second most recent job.
|
2015-03-08 20:33:33 -05:00
|
|
|
|
|
2015-03-08 17:57:12 -05:00
|
|
|
|
String Literals in Subprocess-mode
|
|
|
|
|
====================================
|
2015-03-22 15:48:26 -04:00
|
|
|
|
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
|
2015-03-08 17:57:12 -05:00
|
|
|
|
single argument. So whenever you are in doubt, or if there is a xonsh syntax
|
2015-03-22 15:48:26 -04:00
|
|
|
|
error because of a filename, just wrap the offending portion in a string.
|
2015-03-08 17:57:12 -05:00
|
|
|
|
|
2015-03-22 15:48:26 -04:00
|
|
|
|
A common use case for this is files with spaces in their names. This
|
2015-03-08 17:57:12 -05:00
|
|
|
|
detestable practice refuses to die. "No problem!" says xonsh, "I have
|
|
|
|
|
strings." Let's see it go!
|
|
|
|
|
|
2015-03-31 01:10:19 -05:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-08 17:57:12 -05:00
|
|
|
|
|
|
|
|
|
>>> 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
|
|
|
|
|
|
2015-12-19 17:18:21 -05:00
|
|
|
|
By default, the name of an environment variable inside a string will be
|
|
|
|
|
replaced by the contents of that variable (in subprocess mode only). For
|
|
|
|
|
example:
|
2015-03-08 17:57:12 -05:00
|
|
|
|
|
2015-12-19 17:18:21 -05:00
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
|
|
|
|
|
|
>>> print("my home is $HOME")
|
|
|
|
|
my home is $HOME
|
|
|
|
|
>>> echo "my home is $HOME"
|
|
|
|
|
my home is /home/snail
|
|
|
|
|
|
|
|
|
|
You can avoid this expansion within a particular command by forcing the strings
|
|
|
|
|
to be evaluated in Python mode using the ``@()`` syntax:
|
|
|
|
|
|
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
|
|
|
|
|
|
>>> echo "my home is $HOME"
|
|
|
|
|
my home is /home/snail
|
|
|
|
|
>>> echo @("my home is $HOME")
|
|
|
|
|
my home is $HOME
|
|
|
|
|
|
|
|
|
|
You can also disable environment variable expansion completely by setting
|
|
|
|
|
``$EXPAND_ENV_VARS`` to ``False``.
|
2015-03-08 17:57:12 -05:00
|
|
|
|
|
2015-03-08 19:06:39 -05:00
|
|
|
|
Filename Globbing with ``*``
|
|
|
|
|
===============================
|
|
|
|
|
Filename globbing with the ``*`` character is also allowed in subprocess-mode.
|
2015-03-08 20:52:56 -05:00
|
|
|
|
This simply uses Python's glob module under-the-covers. See there for more
|
2015-03-08 19:06:39 -05:00
|
|
|
|
details. As an example, start with a lovely bunch of xonshs:
|
|
|
|
|
|
2015-03-31 01:10:19 -05:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-08 19:06:39 -05:00
|
|
|
|
|
|
|
|
|
>>> touch xonsh conch konk quanxh
|
|
|
|
|
>>> ls
|
|
|
|
|
conch konk quanxh xonsh
|
|
|
|
|
>>> ls *h
|
|
|
|
|
conch quanxh xonsh
|
|
|
|
|
>>> ls *o*
|
|
|
|
|
conch konk xonsh
|
|
|
|
|
|
2016-02-15 21:11:30 +01:00
|
|
|
|
This is not available in Python-mode because multiplication is pretty
|
2015-03-08 19:06:39 -05:00
|
|
|
|
important.
|
|
|
|
|
|
|
|
|
|
|
2016-06-08 22:47:21 -04:00
|
|
|
|
Advanced Path Search with Backticks
|
|
|
|
|
===================================
|
|
|
|
|
|
|
|
|
|
xonsh offers additional ways to find path names beyond regular globbing, both
|
|
|
|
|
in Python mode and in subprocess mode.
|
|
|
|
|
|
|
|
|
|
Regular Expression Globbing
|
|
|
|
|
---------------------------
|
|
|
|
|
|
2015-03-22 15:48:26 -04:00
|
|
|
|
If you have ever felt that normal globbing could use some more octane,
|
2015-03-08 19:06:39 -05:00
|
|
|
|
then regex globbing is the tool for you! Any string that uses backticks
|
2015-03-22 15:48:26 -04:00
|
|
|
|
(`````) instead of quotes (``'``, ``"``) is interpreted as a regular
|
|
|
|
|
expression to match filenames against. Like with regular globbing, a
|
2015-03-08 19:06:39 -05:00
|
|
|
|
list of successful matches is returned. In Python-mode, this is just a
|
2015-03-08 20:52:56 -05:00
|
|
|
|
list of strings. In subprocess-mode, each filename becomes its own argument
|
|
|
|
|
to the subprocess command.
|
2015-03-08 19:06:39 -05:00
|
|
|
|
|
|
|
|
|
Let's see a demonstration with some simple filenames:
|
|
|
|
|
|
|
|
|
|
|
2015-03-31 01:10:19 -05:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-08 19:06:39 -05:00
|
|
|
|
|
|
|
|
|
>>> 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
|
|
|
|
|
|
2016-06-11 22:36:29 -04:00
|
|
|
|
This same kind of search is performed if the backticks are prefaced with ``r``.
|
2017-06-07 11:51:06 -04:00
|
|
|
|
So the following expressions are equivalent: ```test``` and ``r`test```.
|
2016-06-08 22:47:21 -04:00
|
|
|
|
|
2015-03-22 15:48:26 -04:00
|
|
|
|
Other than the regex matching, this functions in the same way as normal
|
2016-06-08 22:47:21 -04:00
|
|
|
|
globbing. For more information, please see the documentation for the ``re``
|
|
|
|
|
module in the Python standard library.
|
2015-03-08 19:06:39 -05:00
|
|
|
|
|
2017-01-03 17:20:38 +01:00
|
|
|
|
.. warning:: In Xonsh, the meaning of backticks is very different from their
|
|
|
|
|
meaning in Bash.
|
2017-01-03 17:23:51 +01:00
|
|
|
|
In Bash, backticks mean to run a captured subprocess
|
|
|
|
|
(``$()`` in Xonsh).
|
2015-03-08 19:06:39 -05:00
|
|
|
|
|
|
|
|
|
|
2016-06-08 22:47:21 -04:00
|
|
|
|
Normal Globbing
|
|
|
|
|
---------------
|
|
|
|
|
|
|
|
|
|
In subprocess mode, normal globbing happens without any special syntax.
|
|
|
|
|
However, the backtick syntax has an additional feature: it is available inside
|
|
|
|
|
of Python mode as well as subprocess mode.
|
|
|
|
|
|
2016-06-11 22:36:29 -04:00
|
|
|
|
Similarly to regex globbing, normal globbing can be performed (either in Python
|
|
|
|
|
mode or subprocess mode) by using the ``g````:
|
2016-06-08 22:47:21 -04:00
|
|
|
|
|
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
|
|
|
|
|
|
>>> touch a aa aaa aba abba aab aabb abcba
|
|
|
|
|
>>> ls a*b*
|
|
|
|
|
aab aabb aba abba abcba
|
|
|
|
|
>>> ls g`a*b*`
|
|
|
|
|
aab aabb aba abba abcba
|
|
|
|
|
>>> print(g`a*b*`)
|
|
|
|
|
['aab', 'aabb', 'abba', 'abcba', 'aba']
|
|
|
|
|
>>> len(g`a*b*`)
|
|
|
|
|
5
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Custom Path Searches
|
|
|
|
|
--------------------
|
|
|
|
|
|
|
|
|
|
In addition, if normal globbing and regular expression globbing are not enough,
|
2016-06-11 22:36:29 -04:00
|
|
|
|
xonsh allows you to specify your own search functions.
|
2016-06-08 22:47:21 -04:00
|
|
|
|
|
2016-06-11 22:36:29 -04:00
|
|
|
|
A search function is defined as a function of a single argument (a string) that
|
|
|
|
|
returns a list of possible matches to that string. Search functions can then
|
|
|
|
|
be used with backticks with the following syntax: ``@<name>`test```
|
2016-06-08 22:47:21 -04:00
|
|
|
|
|
2016-06-16 00:38:49 -04:00
|
|
|
|
The following example shows the form of these functions:
|
2016-06-08 22:47:21 -04:00
|
|
|
|
|
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
|
|
2016-06-11 22:36:29 -04:00
|
|
|
|
>>> def foo(s):
|
2016-06-16 00:38:49 -04:00
|
|
|
|
... return [i for i in os.listdir('.') if i.startswith(s)]
|
|
|
|
|
>>> @foo`aa`
|
|
|
|
|
['aa', 'aaa', 'aab', 'aabb']
|
2016-06-08 22:47:21 -04:00
|
|
|
|
|
|
|
|
|
|
2016-10-17 15:17:38 +02:00
|
|
|
|
Path Output
|
|
|
|
|
-----------
|
2016-10-17 15:18:30 +02:00
|
|
|
|
|
2016-10-17 15:17:38 +02:00
|
|
|
|
Using the ``p`` modifier with either regex or glob backticks changes the
|
|
|
|
|
return type from a list of strings to a list of :class:`pathlib.Path` objects:
|
2016-10-17 15:18:30 +02:00
|
|
|
|
|
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
|
|
2016-10-17 15:17:38 +02:00
|
|
|
|
>>> p`.*`
|
|
|
|
|
[Path('foo'), Path('bar')]
|
|
|
|
|
>>> [x for x in pg`**` if x.is_symlink()]
|
|
|
|
|
[Path('a_link')]
|
2016-10-17 15:18:30 +02:00
|
|
|
|
|
|
|
|
|
|
2016-10-19 15:05:42 +02:00
|
|
|
|
Path Literals
|
|
|
|
|
-------------
|
2016-10-17 15:18:30 +02:00
|
|
|
|
|
2016-10-19 15:05:42 +02:00
|
|
|
|
Path objects can be instantiated directly using *p-string* syntax. Path objects
|
|
|
|
|
can be converted back to plain strings with `str()`, and this conversion is
|
|
|
|
|
handled implicitly in subprocess mode.
|
2016-10-17 21:20:45 +02:00
|
|
|
|
|
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
|
|
2016-10-19 15:05:42 +02:00
|
|
|
|
>>> mypath = p'/foo/bar'
|
|
|
|
|
>>> mypath
|
|
|
|
|
Path('/foo/bar')
|
|
|
|
|
>>> mypath.stem
|
|
|
|
|
'bar'
|
|
|
|
|
>>> echo @(mypath)
|
|
|
|
|
/foo/bar
|
2016-10-17 21:20:45 +02:00
|
|
|
|
|
2016-10-17 15:18:30 +02:00
|
|
|
|
|
2015-03-08 19:06:39 -05:00
|
|
|
|
Help & Superhelp with ``?`` & ``??``
|
|
|
|
|
=====================================================
|
|
|
|
|
From IPython, xonsh allows you to inspect objects with question marks.
|
2016-02-15 21:11:30 +01:00
|
|
|
|
A single question mark (``?``) is used to display the normal level of help.
|
|
|
|
|
Double question marks (``??``) are used to display a higher level of help,
|
2015-03-08 19:06:39 -05:00
|
|
|
|
called superhelp. Superhelp usually includes source code if the object was
|
2015-03-22 15:48:26 -04:00
|
|
|
|
written in pure Python.
|
2015-03-08 19:06:39 -05:00
|
|
|
|
|
|
|
|
|
Let's start by looking at the help for the int type:
|
|
|
|
|
|
2015-03-31 01:10:19 -05:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-08 19:06:39 -05:00
|
|
|
|
|
|
|
|
|
>>> 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:
|
|
|
|
|
|
2015-03-30 20:50:20 -05:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-08 19:06:39 -05:00
|
|
|
|
|
2017-01-03 17:58:28 +01:00
|
|
|
|
>>> __xonsh_regexsearch__??
|
|
|
|
|
Type: function
|
|
|
|
|
String form: <function regexsearch at 0x7efc8b367d90>
|
|
|
|
|
File: /usr/local/lib/python3.5/dist-packages/xonsh/built_ins.py
|
|
|
|
|
Definition: (s)
|
2015-03-08 19:06:39 -05:00
|
|
|
|
Source:
|
2017-01-03 17:58:28 +01:00
|
|
|
|
def regexsearch(s):
|
2015-03-08 19:06:39 -05:00
|
|
|
|
s = expand_path(s)
|
|
|
|
|
return reglob(s)
|
2017-01-11 23:29:28 -05:00
|
|
|
|
|
|
|
|
|
|
2017-01-03 17:58:28 +01:00
|
|
|
|
<function xonsh.built_ins.regexsearch>
|
2015-03-08 19:06:39 -05:00
|
|
|
|
|
|
|
|
|
Note that both help and superhelp return the object that they are inspecting.
|
2015-03-22 15:48:26 -04:00
|
|
|
|
This allows you to chain together help inside of other operations and
|
2015-03-08 20:52:56 -05:00
|
|
|
|
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:
|
2015-03-08 19:06:39 -05:00
|
|
|
|
|
2015-03-30 20:50:20 -05:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-08 19:06:39 -05:00
|
|
|
|
|
|
|
|
|
>>> 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.
|
|
|
|
|
|
|
|
|
|
|
2015-03-08 19:19:30 -05:00
|
|
|
|
Compile, Evaluate, & Execute
|
|
|
|
|
================================
|
2016-06-04 15:36:21 -04:00
|
|
|
|
Like Python and Bash, xonsh provides built-in hooks to compile, evaluate,
|
2015-03-08 19:19:30 -05:00
|
|
|
|
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
|
2015-03-22 15:48:26 -04:00
|
|
|
|
xonsh code you want to use the ``compilex()``, ``evalx()``, and ``execx()``
|
2015-03-08 19:19:30 -05:00
|
|
|
|
functions. If you don't know what these do, you probably don't need them.
|
|
|
|
|
|
2015-03-08 17:57:12 -05:00
|
|
|
|
|
2015-03-08 20:06:59 -05:00
|
|
|
|
Aliases
|
|
|
|
|
==============================
|
2015-03-22 15:48:26 -04:00
|
|
|
|
Another important xonsh built-in is the ``aliases`` mapping. This is
|
2016-02-15 21:11:30 +01:00
|
|
|
|
like a dictionary that affects how subprocess commands are run. If you are
|
2016-06-04 15:36:21 -04:00
|
|
|
|
familiar with the Bash ``alias`` built-in, this is similar. Alias command
|
2015-03-08 20:06:59 -05:00
|
|
|
|
matching only occurs for the first element of a subprocess command.
|
|
|
|
|
|
|
|
|
|
The keys of ``aliases`` are strings that act as commands in subprocess-mode.
|
2016-02-15 21:11:30 +01:00
|
|
|
|
The values are lists of strings, where the first element is the command, and
|
2015-03-22 03:34:02 +01:00
|
|
|
|
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``.
|
2015-03-08 20:06:59 -05:00
|
|
|
|
|
2015-08-19 01:16:47 -04:00
|
|
|
|
For example, the following creates several aliases for the ``git``
|
|
|
|
|
version control software. Both styles (list of strings and single
|
|
|
|
|
string) are shown:
|
2015-03-08 20:06:59 -05:00
|
|
|
|
|
2015-08-19 01:16:47 -04:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-08 20:06:59 -05:00
|
|
|
|
|
2015-08-19 01:16:47 -04:00
|
|
|
|
>>> aliases['g'] = 'git status -sb'
|
|
|
|
|
>>> aliases['gco'] = 'git checkout'
|
|
|
|
|
>>> aliases['gp'] = ['git', 'pull']
|
2015-03-08 20:06:59 -05:00
|
|
|
|
|
2015-08-19 01:16:47 -04:00
|
|
|
|
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.
|
2015-03-22 15:48:26 -04:00
|
|
|
|
|
2016-06-11 20:52:47 -04:00
|
|
|
|
|
|
|
|
|
Callable Aliases
|
|
|
|
|
----------------
|
2015-03-22 15:48:26 -04:00
|
|
|
|
Lastly, if an alias value is a function (or other callable), then this
|
2015-03-08 20:52:56 -05:00
|
|
|
|
function is called *instead* of going to a subprocess command. Such functions
|
2016-10-04 20:51:45 -04:00
|
|
|
|
may have one of the following signatures:
|
2015-03-08 20:06:59 -05:00
|
|
|
|
|
2015-03-31 01:10:19 -05:00
|
|
|
|
.. code-block:: python
|
2015-03-08 20:06:59 -05:00
|
|
|
|
|
2016-10-04 20:51:45 -04:00
|
|
|
|
def mycmd0():
|
|
|
|
|
"""This form takes no arguments but may return output or a return code.
|
|
|
|
|
"""
|
|
|
|
|
return "some output."
|
|
|
|
|
|
|
|
|
|
def mycmd1(args):
|
|
|
|
|
"""This form takes a single argument, args. This is a list of strings
|
|
|
|
|
representing the arguments to this command. Feel free to parse them
|
|
|
|
|
however you wish!
|
|
|
|
|
"""
|
|
|
|
|
# perform some action.
|
|
|
|
|
return 0
|
|
|
|
|
|
|
|
|
|
def mycmd2(args, stdin=None):
|
|
|
|
|
"""This form takes two arguments. The args list like above, as a well
|
|
|
|
|
as standard input. stdin will be a file like object that the command
|
|
|
|
|
can read from, if the user piped input to this command. If no input
|
|
|
|
|
was provided this will be None.
|
2015-03-08 20:06:59 -05:00
|
|
|
|
"""
|
2015-03-22 15:48:26 -04:00
|
|
|
|
# do whatever you want! Anything you print to stdout or stderr
|
|
|
|
|
# will be captured for you automatically. This allows callable
|
2015-03-10 20:29:28 -05:00
|
|
|
|
# aliases to support piping.
|
|
|
|
|
print('I go to stdout and will be printed or piped')
|
|
|
|
|
|
|
|
|
|
# Note: that you have access to the xonsh
|
2015-03-08 20:06:59 -05:00
|
|
|
|
# built-ins if you 'import builtins'. For example, if you need the
|
2015-03-10 20:29:28 -05:00
|
|
|
|
# environment, you could do to following:
|
2015-07-25 01:58:56 -06:00
|
|
|
|
import builtins
|
2015-03-10 20:29:28 -05:00
|
|
|
|
env = builtins.__xonsh_env__
|
|
|
|
|
|
|
|
|
|
# The return value of the function can either be None,
|
|
|
|
|
return
|
|
|
|
|
|
2015-03-11 01:40:48 -05:00
|
|
|
|
# a single string representing stdout
|
|
|
|
|
return 'I am out of here'
|
|
|
|
|
|
2015-03-22 15:48:26 -04:00
|
|
|
|
# or you can build up strings for stdout and stderr and then
|
2015-03-10 20:29:28 -05:00
|
|
|
|
# return a (stdout, stderr) tuple. Both of these may be
|
2015-03-22 15:48:26 -04:00
|
|
|
|
# either a str or None. Any results returned like this will be
|
2015-03-10 20:29:28 -05:00
|
|
|
|
# concatenated with the strings printed elsewhere in the function.
|
2015-03-08 20:06:59 -05:00
|
|
|
|
stdout = 'I commanded'
|
|
|
|
|
stderr = None
|
|
|
|
|
return stdout, stderr
|
|
|
|
|
|
2015-11-27 11:36:18 -07:00
|
|
|
|
# Lastly, a 3-tuple return value can be used to include an integer
|
|
|
|
|
# return code indicating failure (> 0 return code). In the previous
|
|
|
|
|
# examples the return code would be 0/success.
|
|
|
|
|
return (None, "I failed", 2)
|
|
|
|
|
|
2016-10-04 20:51:45 -04:00
|
|
|
|
def mycmd3(args, stdin=None, stdout=None):
|
|
|
|
|
"""This form has three parameters. The first two are the same as above.
|
|
|
|
|
The last argument represents the standard output. This is a file-like
|
|
|
|
|
object that the command may write too.
|
|
|
|
|
"""
|
|
|
|
|
# you can either use stdout
|
|
|
|
|
stdout.write("Hello, ")
|
|
|
|
|
# or print()!
|
|
|
|
|
print("Mom!")
|
|
|
|
|
return
|
2016-06-11 20:52:47 -04:00
|
|
|
|
|
2016-10-04 20:51:45 -04:00
|
|
|
|
def mycmd4(args, stdin=None, stdout=None, stderr=None):
|
2016-10-06 00:43:01 -04:00
|
|
|
|
"""The next form of subprocess callables takes all of the
|
2016-10-04 20:51:45 -04:00
|
|
|
|
arguments shown above as well as the standard error stream.
|
|
|
|
|
As with stdout, this is a write-only file-like object.
|
2016-06-11 20:52:47 -04:00
|
|
|
|
"""
|
|
|
|
|
# This form allows "streaming" data to stdout and stderr
|
|
|
|
|
import time
|
|
|
|
|
for i in range(5):
|
|
|
|
|
time.sleep(i)
|
|
|
|
|
print(i, file=stdout)
|
|
|
|
|
|
|
|
|
|
# In this form, the return value should be a single integer
|
|
|
|
|
# representing the "return code" of the alias (zero if successful,
|
|
|
|
|
# non-zero otherwise)
|
|
|
|
|
return 0
|
|
|
|
|
|
2016-10-06 00:43:01 -04:00
|
|
|
|
def mycmd5(args, stdin=None, stdout=None, stderr=None, spec=None):
|
|
|
|
|
"""Lastly, the final form of subprocess callables takes all of the
|
2017-06-07 11:51:06 -04:00
|
|
|
|
arguments shown above as well as a subprocess specification
|
2016-10-06 00:43:01 -04:00
|
|
|
|
SubprocSpec object. This holds many attributes that dictate how
|
|
|
|
|
the command is being run. For instance this can be useful for
|
|
|
|
|
knowing if the process is captured by $() or !().
|
|
|
|
|
"""
|
|
|
|
|
import xonsh.proc
|
|
|
|
|
if spec.captured in xonsh.proc.STDOUT_CAPTURE_KINDS:
|
|
|
|
|
end = ''
|
|
|
|
|
else:
|
|
|
|
|
end = '\n'
|
|
|
|
|
# Now we'll get a newline if the user is at the terminal, and no
|
|
|
|
|
# newline if we are captured
|
|
|
|
|
print('Hi Mom!', end=end)
|
|
|
|
|
return 0
|
|
|
|
|
|
2016-06-11 20:52:47 -04:00
|
|
|
|
|
2016-08-09 11:17:30 -07:00
|
|
|
|
Adding, Modifying, and Removing Aliases
|
|
|
|
|
---------------------------------------
|
|
|
|
|
|
2015-03-22 15:48:26 -04:00
|
|
|
|
We can dynamically alter the aliases present simply by modifying the
|
2015-03-08 20:06:59 -05:00
|
|
|
|
built-in mapping. Here is an example using a function value:
|
|
|
|
|
|
2015-03-30 20:50:20 -05:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-08 20:06:59 -05:00
|
|
|
|
|
2016-06-06 14:58:17 -04:00
|
|
|
|
>>> def _banana(args, stdin=None):
|
|
|
|
|
... return ('My spoon is tooo big!', None)
|
|
|
|
|
>>> aliases['banana'] = _banana
|
2015-03-22 15:48:26 -04:00
|
|
|
|
>>> banana
|
2015-03-08 20:06:59 -05:00
|
|
|
|
'My spoon is tooo big!'
|
|
|
|
|
|
2016-08-09 11:17:30 -07:00
|
|
|
|
|
|
|
|
|
To redefine an alias, simply assign a new function, here using a python lambda
|
|
|
|
|
with keyword arguments:
|
|
|
|
|
|
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
|
|
2016-10-04 20:51:45 -04:00
|
|
|
|
>>> aliases['banana'] = lambda: "Banana for scale.\n"
|
2016-08-09 11:17:30 -07:00
|
|
|
|
>>> banana
|
|
|
|
|
Banana for scale.
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
Removing an alias is as easy as deleting the key from the alias dictionary:
|
|
|
|
|
|
|
|
|
|
.. code-block:: xonshcon
|
2016-08-21 14:58:07 -04:00
|
|
|
|
|
2016-08-09 11:17:30 -07:00
|
|
|
|
>>> del aliases['banana']
|
|
|
|
|
|
2016-06-06 14:58:17 -04:00
|
|
|
|
.. note::
|
|
|
|
|
|
|
|
|
|
Alias functions should generally be defined with a leading underscore.
|
|
|
|
|
Otherwise, they may shadow the alias itself, as Python variables take
|
|
|
|
|
precedence over aliases when xonsh executes commands.
|
|
|
|
|
|
2016-06-11 20:52:47 -04:00
|
|
|
|
|
|
|
|
|
Anonymous Aliases
|
|
|
|
|
-----------------
|
|
|
|
|
As mentioned above, it is also possible to treat functions outside this mapping
|
|
|
|
|
as aliases, by wrapping them in ``@()``. For example:
|
|
|
|
|
|
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
|
|
|
|
|
|
>>> @(_banana)
|
|
|
|
|
'My spoon is tooo big!'
|
2017-01-05 10:58:26 +01:00
|
|
|
|
>>> echo "hello" | @(lambda args, stdin=None: stdin.read().strip() + ' ' + args[0] + '\n') world
|
2016-06-11 20:52:47 -04:00
|
|
|
|
hello world
|
|
|
|
|
|
|
|
|
|
|
2016-10-29 21:11:08 -04:00
|
|
|
|
Unthreadable Aliases
|
2016-06-11 20:52:47 -04:00
|
|
|
|
-----------------------
|
2016-10-30 10:47:32 -04:00
|
|
|
|
Usually, callable alias commands will be run in a separate thread so that
|
2016-06-11 20:52:47 -04:00
|
|
|
|
they may be run in the background. However, some aliases may need to be
|
|
|
|
|
executed on the thread that they were called from. This is mostly useful for
|
|
|
|
|
debuggers and profilers. To make an alias run in the foreground, decorate its
|
2017-02-12 11:01:24 +08:00
|
|
|
|
function with the ``xonsh.tools.unthreadable`` decorator.
|
2016-02-04 21:48:59 -05:00
|
|
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
|
2017-02-12 11:01:24 +08:00
|
|
|
|
from xonsh.tools import unthreadable
|
2016-02-04 21:48:59 -05:00
|
|
|
|
|
2016-10-29 21:11:08 -04:00
|
|
|
|
@unthreadable
|
2016-06-06 14:58:17 -04:00
|
|
|
|
def _mycmd(args, stdin=None):
|
2016-02-04 21:48:59 -05:00
|
|
|
|
return 'In your face!'
|
|
|
|
|
|
2016-06-06 14:58:17 -04:00
|
|
|
|
aliases['mycmd'] = _mycmd
|
|
|
|
|
|
2016-10-29 21:11:08 -04:00
|
|
|
|
Uncapturable Aliases
|
|
|
|
|
-----------------------
|
2016-10-30 10:47:32 -04:00
|
|
|
|
Also, callable aliases by default will be executed such that their output is
|
2016-10-29 21:11:08 -04:00
|
|
|
|
captured (like most commands in xonsh that don't enter alternate mode).
|
|
|
|
|
However, some aliases may want to run alternate-mode commands themselves.
|
2016-10-30 10:47:32 -04:00
|
|
|
|
Thus the callable alias can't be captured without dire consequences (tm).
|
2016-10-29 21:11:08 -04:00
|
|
|
|
To prevent this, you can declare a callable alias uncapturable. This is mostly
|
|
|
|
|
useful for aliases that then open up text editors, pagers, or the like.
|
2016-10-30 10:47:32 -04:00
|
|
|
|
To make an alias uncapturable, decorate its
|
2017-02-12 11:01:24 +08:00
|
|
|
|
function with the ``xonsh.tools.uncapturable`` decorator. This is probably
|
2016-10-29 21:11:08 -04:00
|
|
|
|
best used in conjunction with the ``unthreadable`` decorator. For example:
|
|
|
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
|
2017-02-12 11:01:24 +08:00
|
|
|
|
from xonsh.tools import unthreadable, uncapturable
|
2016-10-29 21:11:08 -04:00
|
|
|
|
|
|
|
|
|
@uncapturable
|
|
|
|
|
@unthreadable
|
|
|
|
|
def _myvi():
|
|
|
|
|
vi my.txt
|
|
|
|
|
|
|
|
|
|
aliases['myvi'] = _myvi
|
|
|
|
|
|
|
|
|
|
-------------
|
|
|
|
|
|
2015-03-22 15:52:02 -04:00
|
|
|
|
Aliasing is a powerful way that xonsh allows you to seamlessly interact to
|
2015-03-22 15:48:26 -04:00
|
|
|
|
with Python and subprocess.
|
2015-03-08 20:47:35 -05:00
|
|
|
|
|
2017-06-07 11:51:06 -04:00
|
|
|
|
.. warning:: If ``FOREIGN_ALIASES_OVERRIDE`` environment variable is False
|
2016-10-29 21:11:08 -04:00
|
|
|
|
(the default) then foreign shell aliases that try to override
|
2017-06-07 11:51:06 -04:00
|
|
|
|
xonsh aliases will be ignored. Setting of this environment variable
|
2017-12-18 20:33:42 -08:00
|
|
|
|
must happen outside if xonsh, i.e. in the process that starts xonsh.
|
2016-09-10 22:03:21 +03:00
|
|
|
|
|
2016-09-10 20:45:14 +03:00
|
|
|
|
|
2015-03-08 20:47:35 -05:00
|
|
|
|
Up, Down, Tab
|
|
|
|
|
==============
|
2015-03-22 15:48:26 -04:00
|
|
|
|
The up and down keys search history matching from the start of the line,
|
2015-03-08 20:47:35 -05:00
|
|
|
|
much like they do in the IPython shell.
|
|
|
|
|
|
2016-06-02 12:17:27 -04:00
|
|
|
|
Tab completion is present as well. By default, 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
|
2016-06-04 15:36:21 -04:00
|
|
|
|
on the names of executable files on your ``$PATH``, alias keys, and full Bash
|
2016-06-02 14:28:29 -04:00
|
|
|
|
completion for the commands themselves.
|
2015-03-08 20:47:35 -05:00
|
|
|
|
|
2016-06-02 12:08:13 -04:00
|
|
|
|
xonsh also provides a means of modifying the behavior of the tab completer. More
|
|
|
|
|
detail is available on the `Tab Completion page <tutorial_completers.html>`_.
|
2015-03-08 20:47:35 -05:00
|
|
|
|
|
2017-01-18 13:44:40 -05:00
|
|
|
|
.. _customprompt:
|
|
|
|
|
|
2015-04-03 21:49:31 -04:00
|
|
|
|
Customizing the Prompt
|
|
|
|
|
======================
|
2016-06-07 17:50:40 -04:00
|
|
|
|
Customizing the prompt by modifying ``$PROMPT`` is probably the most common
|
|
|
|
|
reason for altering an environment variable.
|
|
|
|
|
|
|
|
|
|
.. note:: Note that the ``$PROMPT`` variable will never be inherited from a
|
|
|
|
|
parent process (regardless of whether that parent is a foreign shell
|
|
|
|
|
or an instance of xonsh).
|
|
|
|
|
|
|
|
|
|
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:
|
2015-04-03 21:49:31 -04:00
|
|
|
|
|
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
|
|
|
|
|
|
>>> $PROMPT = '{user}@{hostname}:{cwd} > '
|
|
|
|
|
snail@home:~ > # it works!
|
2015-08-02 18:49:45 -05:00
|
|
|
|
snail@home:~ > $PROMPT = lambda: '{user}@{hostname}:{cwd} >> '
|
2015-04-03 21:49:31 -04:00
|
|
|
|
snail@home:~ >> # so does that!
|
2015-05-20 14:43:20 -04:00
|
|
|
|
|
2015-04-03 21:49:31 -04:00
|
|
|
|
By default, the following variables are available for use:
|
2016-02-20 15:24:19 -05:00
|
|
|
|
|
2015-04-03 21:49:31 -04:00
|
|
|
|
* ``user``: The username of the current user
|
|
|
|
|
* ``hostname``: The name of the host computer
|
2016-05-28 17:35:56 -04:00
|
|
|
|
* ``cwd``: The current working directory, you may use ``$DYNAMIC_CWD_WIDTH`` to
|
2017-01-03 19:28:29 +01:00
|
|
|
|
set a maximum width for this variable and ``$DYNAMIC_CWD_ELISION_CHAR`` to
|
|
|
|
|
set the character used in shortened path.
|
2015-11-29 20:38:23 -05:00
|
|
|
|
* ``short_cwd``: A shortened form of the current working directory; e.g.,
|
|
|
|
|
``/path/to/xonsh`` becomes ``/p/t/xonsh``
|
2015-08-13 08:54:47 -04:00
|
|
|
|
* ``cwd_dir``: The dirname of the current working directory, e.g. ``/path/to`` in
|
2015-08-04 18:04:21 -05:00
|
|
|
|
``/path/to/xonsh``.
|
2015-08-13 08:54:47 -04:00
|
|
|
|
* ``cwd_base``: The basename of the current working directory, e.g. ``xonsh`` in
|
2015-08-04 18:04:21 -05:00
|
|
|
|
``/path/to/xonsh``.
|
2016-07-15 18:28:41 -07:00
|
|
|
|
* ``env_name``: The name of active virtual environment, if any.
|
2016-07-01 20:30:13 +03:00
|
|
|
|
* ``curr_branch``: The name of the current git branch, if any.
|
2015-05-13 22:52:49 -04:00
|
|
|
|
* ``branch_color``: ``{BOLD_GREEN}`` if the current git branch is clean,
|
2016-06-09 22:52:41 -04:00
|
|
|
|
otherwise ``{BOLD_RED}``. This is yellow if the branch color could not be
|
|
|
|
|
determined.
|
|
|
|
|
* ``branch_bg_color``: Like, ``{branch_color}``, but sets a background color
|
|
|
|
|
instead.
|
2016-07-12 03:02:15 -04:00
|
|
|
|
* ``prompt_end``: ``#`` if the user has root/admin permissions ``$`` otherwise
|
2015-12-05 15:37:00 -05:00
|
|
|
|
* ``current_job``: The name of the command currently running in the
|
|
|
|
|
foreground, if any.
|
2016-07-12 03:02:15 -04:00
|
|
|
|
* ``vte_new_tab_cwd``: Issues VTE escape sequence for opening new tabs in the
|
|
|
|
|
current working directory on some linux terminals. This is not usually needed.
|
2016-09-03 13:13:13 +08:00
|
|
|
|
* ``gitstatus``: Informative git status, like ``[master|MERGING|+1…2]``, you
|
|
|
|
|
may use `$XONSH_GITSTATUS_* <envvars.html>`_ to customize the styling.
|
2015-04-03 21:49:31 -04:00
|
|
|
|
|
|
|
|
|
You can also color your prompt easily by inserting keywords such as ``{GREEN}``
|
|
|
|
|
or ``{BOLD_BLUE}``. Colors have the form shown below:
|
2015-05-20 14:43:20 -04:00
|
|
|
|
|
2016-02-20 15:24:19 -05:00
|
|
|
|
* ``NO_COLOR``: Resets any previously used color codes
|
2016-02-29 21:18:22 -05:00
|
|
|
|
* ``COLORNAME``: Inserts a color code for the following basic colors,
|
2016-02-20 15:24:19 -05:00
|
|
|
|
which come in regular (dark) and intense (light) forms:
|
|
|
|
|
|
2016-02-29 21:18:22 -05:00
|
|
|
|
- ``BLACK`` or ``INTENSE_BLACK``
|
2016-02-20 15:24:19 -05:00
|
|
|
|
- ``RED`` or ``INTENSE_RED``
|
|
|
|
|
- ``GREEN`` or ``INTENSE_GREEN``
|
|
|
|
|
- ``YELLOW`` or ``INTENSE_YELLOW``
|
|
|
|
|
- ``BLUE`` or ``INTENSE_BLUE``
|
|
|
|
|
- ``PURPLE`` or ``INTENSE_PURPLE``
|
|
|
|
|
- ``CYAN`` or ``INTENSE_CYAN``
|
|
|
|
|
- ``WHITE`` or ``INTENSE_WHITE``
|
|
|
|
|
|
2016-02-29 21:18:22 -05:00
|
|
|
|
* ``#HEX``: A ``#`` before a len-3 or len-6 hex code will use that
|
|
|
|
|
hex color, or the nearest approximation that that is supported by
|
2016-02-20 15:24:19 -05:00
|
|
|
|
the shell and terminal. For example, ``#fff`` and ``#fafad2`` are
|
|
|
|
|
both valid.
|
2017-06-07 11:51:06 -04:00
|
|
|
|
* ``BACKGROUND_`` may be added to the beginning of a color name or hex
|
2016-02-20 15:24:19 -05:00
|
|
|
|
color to set a background color. For example, ``BACKGROUND_INTENSE_RED``
|
|
|
|
|
and ``BACKGROUND_#123456`` can both be used.
|
|
|
|
|
* ``bg#HEX`` or ``BG#HEX`` are shortcuts for setting a background hex color.
|
|
|
|
|
Thus you can set ``bg#0012ab`` or the uppercase version.
|
|
|
|
|
* ``BOLD_`` is a prefix qualifier that may be used with any foreground color.
|
|
|
|
|
For example, ``BOLD_RED`` and ``BOLD_#112233`` are OK!
|
2016-02-29 21:18:22 -05:00
|
|
|
|
* ``UNDERLINE_`` is a prefix qualifier that also may be used with any
|
2016-02-20 15:24:19 -05:00
|
|
|
|
foreground color. For example, ``UNDERLINE_GREEN``.
|
2016-02-29 21:18:22 -05:00
|
|
|
|
* Or any other combination of qualifiers, such as
|
|
|
|
|
``BOLD_UNDERLINE_INTENSE_BLACK``, which is the most metal color you
|
2016-02-20 15:24:19 -05:00
|
|
|
|
can use!
|
2015-04-03 21:49:31 -04:00
|
|
|
|
|
|
|
|
|
You can make use of additional variables beyond these by adding them to the
|
2016-11-02 16:06:35 +02:00
|
|
|
|
``PROMPT_FIELDS`` environment variable. The values in this dictionary
|
2015-04-03 21:49:31 -04:00
|
|
|
|
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:
|
|
|
|
|
|
2016-05-20 17:58:50 -04:00
|
|
|
|
.. code-block:: console
|
2015-04-03 21:49:31 -04:00
|
|
|
|
|
2016-11-02 16:06:35 +02:00
|
|
|
|
snail@home ~ $ $PROMPT_FIELDS['test'] = "hey"
|
2015-04-03 21:49:31 -04:00
|
|
|
|
snail@home ~ $ $PROMPT = "{test} {cwd} $ "
|
2015-05-20 14:43:20 -04:00
|
|
|
|
hey ~ $
|
2015-04-03 21:49:31 -04:00
|
|
|
|
hey ~ $ import random
|
2016-11-02 16:06:35 +02:00
|
|
|
|
hey ~ $ $PROMPT_FIELDS['test'] = lambda: random.randint(1,9)
|
2015-05-20 14:43:20 -04:00
|
|
|
|
3 ~ $
|
|
|
|
|
5 ~ $
|
|
|
|
|
2 ~ $
|
|
|
|
|
8 ~ $
|
2015-04-03 21:49:31 -04:00
|
|
|
|
|
2015-09-11 10:26:51 -04:00
|
|
|
|
Environment variables and functions are also available with the ``$``
|
|
|
|
|
prefix. For example:
|
|
|
|
|
|
2016-05-20 17:58:50 -04:00
|
|
|
|
.. code-block:: console
|
2015-09-11 10:26:51 -04:00
|
|
|
|
|
|
|
|
|
snail@home ~ $ $PROMPT = "{$LANG} >"
|
|
|
|
|
en_US.utf8 >
|
2015-08-02 18:49:45 -05:00
|
|
|
|
|
2016-11-02 16:06:35 +02:00
|
|
|
|
Note that some entries of the ``$PROMPT_FIELDS`` are not always applicable, for
|
2016-07-01 20:30:13 +03:00
|
|
|
|
example, ``curr_branch`` returns ``None`` if the current directory is not in a
|
|
|
|
|
repository. The ``None`` will be interpreted as an empty string.
|
|
|
|
|
|
|
|
|
|
But let's consider a problem:
|
|
|
|
|
|
|
|
|
|
.. code-block:: console
|
|
|
|
|
|
|
|
|
|
snail@home ~/xonsh $ $PROMPT = "{cwd_base} [{curr_branch}] $ "
|
|
|
|
|
xonsh [master] $ cd ..
|
|
|
|
|
~ [] $
|
|
|
|
|
|
|
|
|
|
We want the branch to be displayed in square brackets, but we also don't want
|
|
|
|
|
the brackets (and the extra space) to be displayed when there is no branch. The
|
|
|
|
|
solution is to add a nested format string (separated with a colon) that will be
|
|
|
|
|
invoked only if the value is not ``None``:
|
|
|
|
|
|
|
|
|
|
.. code-block:: console
|
|
|
|
|
|
|
|
|
|
snail@home ~/xonsh $ $PROMPT = "{cwd_base}{curr_branch: [{}]} $ "
|
|
|
|
|
xonsh [master] $ cd ..
|
|
|
|
|
~ $
|
|
|
|
|
|
|
|
|
|
The curly brackets act as a placeholder, because the additional part is an
|
|
|
|
|
ordinary format string. What we're doing here is equivalent to this expression:
|
|
|
|
|
|
|
|
|
|
.. code-block:: python
|
2016-07-20 21:27:17 -04:00
|
|
|
|
|
2016-07-01 20:30:13 +03:00
|
|
|
|
" [{}]".format(curr_branch()) if curr_branch() is not None else ""
|
|
|
|
|
|
|
|
|
|
|
2015-03-22 15:36:48 -04:00
|
|
|
|
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.
|
|
|
|
|
|
2016-08-18 14:18:57 -04:00
|
|
|
|
.. code-block:: console
|
2015-03-22 15:36:48 -04:00
|
|
|
|
|
2016-08-18 14:18:57 -04:00
|
|
|
|
$ xonsh -c "echo @(7+3)"
|
2015-03-22 15:36:48 -04:00
|
|
|
|
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
|
2015-03-31 01:10:19 -05:00
|
|
|
|
script, stored in ``test.xsh``:
|
2015-03-22 15:36:48 -04:00
|
|
|
|
|
2016-10-25 11:01:03 -04:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-22 15:36:48 -04:00
|
|
|
|
|
|
|
|
|
#!/usr/bin/env xonsh
|
2015-05-20 14:43:20 -04:00
|
|
|
|
|
2015-04-03 22:15:13 -04:00
|
|
|
|
ls
|
2015-05-20 14:43:20 -04:00
|
|
|
|
|
2015-03-22 15:36:48 -04:00
|
|
|
|
print('removing files')
|
2015-04-03 22:15:13 -04:00
|
|
|
|
rm `file\d+.txt`
|
2015-05-20 14:43:20 -04:00
|
|
|
|
|
2015-04-03 22:15:13 -04:00
|
|
|
|
ls
|
2015-05-20 14:43:20 -04:00
|
|
|
|
|
2015-03-22 15:48:26 -04:00
|
|
|
|
print('adding files')
|
2015-03-22 15:36:48 -04:00
|
|
|
|
# This is a comment
|
|
|
|
|
for i, x in enumerate("xonsh"):
|
2016-05-20 17:58:50 -04:00
|
|
|
|
echo @(x) > @("file{0}.txt".format(i))
|
2015-05-20 14:43:20 -04:00
|
|
|
|
|
2015-03-22 15:36:48 -04:00
|
|
|
|
print($(ls).replace('\n', ' '))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
This script could be run by piping its contents to xonsh:
|
|
|
|
|
|
2016-08-18 14:18:57 -04:00
|
|
|
|
.. code-block:: console
|
2015-03-22 15:36:48 -04:00
|
|
|
|
|
2016-08-18 14:18:57 -04:00
|
|
|
|
$ cat test.xsh | xonsh
|
2015-03-22 15:36:48 -04:00
|
|
|
|
file0.txt file1.txt file2.txt file3.txt file4.txt test_script.sh
|
|
|
|
|
removing files
|
|
|
|
|
test_script.sh
|
|
|
|
|
adding files
|
2015-03-22 15:48:26 -04:00
|
|
|
|
file0.txt file1.txt file2.txt file3.txt file4.txt test_script.sh
|
|
|
|
|
|
2015-03-22 15:36:48 -04:00
|
|
|
|
or by invoking xonsh with its filename as an argument:
|
|
|
|
|
|
2016-08-18 14:18:57 -04:00
|
|
|
|
.. code-block:: console
|
2015-03-22 15:36:48 -04:00
|
|
|
|
|
2016-08-18 14:18:57 -04:00
|
|
|
|
$ xonsh test.xsh
|
2015-03-22 15:36:48 -04:00
|
|
|
|
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
|
|
|
|
|
|
2017-12-18 20:33:42 -08:00
|
|
|
|
xonsh scripts can also accept command line arguments and parameters.
|
2017-10-05 18:00:51 -04:00
|
|
|
|
These arguments are made available to the script in two different ways:
|
2015-04-01 20:01:35 -05:00
|
|
|
|
|
|
|
|
|
#. In either mode, as individual variables ``$ARG<n>`` (e.g., ``$ARG1``)
|
2015-03-23 01:15:48 -05:00
|
|
|
|
#. In Python mode only, as a list ``$ARGS``
|
2015-03-22 15:36:48 -04:00
|
|
|
|
|
2015-03-22 15:48:26 -04:00
|
|
|
|
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):
|
2015-03-22 15:36:48 -04:00
|
|
|
|
|
2016-05-11 01:55:53 -04:00
|
|
|
|
|
2016-10-25 11:01:03 -04:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-22 15:36:48 -04:00
|
|
|
|
|
|
|
|
|
#!/usr/bin/env xonsh
|
2015-05-20 14:43:20 -04:00
|
|
|
|
|
2015-03-22 15:36:48 -04:00
|
|
|
|
print($ARGS)
|
2015-05-20 14:43:20 -04:00
|
|
|
|
|
2015-04-03 22:15:13 -04:00
|
|
|
|
ls
|
2015-05-20 14:43:20 -04:00
|
|
|
|
|
2015-03-22 15:36:48 -04:00
|
|
|
|
print('removing files')
|
2015-04-03 22:15:13 -04:00
|
|
|
|
rm `file\d+.txt`
|
2015-05-20 14:43:20 -04:00
|
|
|
|
|
2015-04-03 22:15:13 -04:00
|
|
|
|
ls
|
2015-05-20 14:43:20 -04:00
|
|
|
|
|
2015-03-22 15:36:48 -04:00
|
|
|
|
print('adding files')
|
|
|
|
|
# This is a comment
|
|
|
|
|
for i, x in enumerate($ARG1):
|
2016-05-20 17:58:50 -04:00
|
|
|
|
echo @(x) > @("file{0}.txt".format(i))
|
2015-05-20 14:43:20 -04:00
|
|
|
|
|
2015-03-22 15:36:48 -04:00
|
|
|
|
print($(ls).replace('\n', ' '))
|
|
|
|
|
print()
|
|
|
|
|
|
2016-05-11 01:55:53 -04:00
|
|
|
|
|
2016-08-18 14:18:57 -04:00
|
|
|
|
.. code-block:: console
|
2015-03-22 15:36:48 -04:00
|
|
|
|
|
2016-08-18 14:18:57 -04:00
|
|
|
|
$ xonsh test2.xsh snails
|
2015-03-22 15:36:48 -04:00
|
|
|
|
['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
|
2015-03-22 15:48:26 -04:00
|
|
|
|
|
2016-08-18 14:18:57 -04:00
|
|
|
|
$ echo @(' '.join($(cat @('file%d.txt' % i)).strip() for i in range(6)))
|
2015-03-22 15:36:48 -04:00
|
|
|
|
s n a i l s
|
2015-03-08 20:47:35 -05:00
|
|
|
|
|
2016-02-29 21:18:22 -05:00
|
|
|
|
Additionally, if the script should exit if a command fails, set the
|
|
|
|
|
environment variable ``$RAISE_SUBPROC_ERROR = True`` at the top of the
|
|
|
|
|
file. Errors in Python mode will already raise exceptions and so this
|
2016-02-15 21:11:30 +01:00
|
|
|
|
is roughly equivalent to Bash's ``set -e``.
|
2016-02-04 21:48:59 -05:00
|
|
|
|
|
|
|
|
|
Furthermore, you can also toggle the ability to print source code lines with the
|
2017-06-07 11:51:06 -04:00
|
|
|
|
``trace on`` and ``trace off`` commands. This is roughly equivalent to
|
2016-02-04 21:48:59 -05:00
|
|
|
|
Bash's ``set -x`` or Python's ``python -m trace``, but you know, better.
|
2016-01-24 12:08:50 -05:00
|
|
|
|
|
2015-03-29 18:56:25 -05:00
|
|
|
|
Importing Xonsh (``*.xsh``)
|
|
|
|
|
==============================
|
2015-04-01 20:01:35 -05:00
|
|
|
|
You can import xonsh source files with the ``*.xsh`` file extension using
|
2016-02-15 21:11:30 +01:00
|
|
|
|
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
|
2015-03-29 18:56:25 -05:00
|
|
|
|
following:
|
|
|
|
|
|
2016-10-25 11:01:03 -04:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-29 18:56:25 -05:00
|
|
|
|
|
|
|
|
|
from mine import *
|
|
|
|
|
|
|
|
|
|
|
2015-03-08 20:47:35 -05:00
|
|
|
|
That's All, Folks
|
|
|
|
|
======================
|
2015-05-16 01:37:06 -04:00
|
|
|
|
To leave xonsh, hit ``Ctrl-D``, type ``EOF``, type ``quit``, or type ``exit``.
|
2016-02-15 21:11:30 +01:00
|
|
|
|
On Windows, you can also type ``Ctrl-Z``.
|
2015-03-08 20:47:35 -05:00
|
|
|
|
|
2015-03-31 01:10:19 -05:00
|
|
|
|
.. code-block:: xonshcon
|
2015-03-08 20:47:35 -05:00
|
|
|
|
|
|
|
|
|
>>> exit
|
|
|
|
|
|
|
|
|
|
Now it is your turn.
|