2016-05-11 01:55:53 -04:00
|
|
|
.. _tutorial_xontrib:
|
|
|
|
|
|
|
|
************************************
|
2016-06-06 12:09:41 -04:00
|
|
|
Tutorial: Extensions (Xontribs)
|
2016-05-11 01:55:53 -04:00
|
|
|
************************************
|
|
|
|
Take a deep breath and prepare for some serious Show & Tell; it's time to
|
2016-05-11 03:48:16 -04:00
|
|
|
learn about xonsh extensions!
|
2016-05-11 01:55:53 -04:00
|
|
|
|
2022-05-05 00:32:20 +05:30
|
|
|
Xonsh comes with some default set of extensions. These can be viewed :py:mod:`here <xontrib>`.
|
|
|
|
|
|
|
|
Also checkout the list of `Awesome Contributions <https://xonsh.github.io/awesome-xontribs/>`_
|
|
|
|
from the community.
|
|
|
|
|
2016-05-11 01:55:53 -04:00
|
|
|
Overview
|
2022-05-05 00:32:20 +05:30
|
|
|
========
|
2016-05-11 01:55:53 -04:00
|
|
|
Xontributions, or ``xontribs``, are a set of tools and conventions for
|
|
|
|
extending the functionality of xonsh beyond what is provided by default. This
|
2016-05-11 03:48:16 -04:00
|
|
|
allows 3rd party developers and users to improve their xonsh experience without
|
2016-05-11 01:55:53 -04:00
|
|
|
having to go through the xonsh development and release cycle.
|
|
|
|
|
2016-05-11 03:48:16 -04:00
|
|
|
Many tools and libraries have extension capabilities. Here are some that we
|
2016-05-11 01:55:53 -04:00
|
|
|
took inspiration from for xonsh:
|
|
|
|
|
|
|
|
* `Sphinx <http://sphinx-doc.org/>`_: Extensions are just Python modules,
|
2016-05-11 03:48:16 -04:00
|
|
|
bundles some extensions with the main package, interface is a list of
|
2016-05-11 01:55:53 -04:00
|
|
|
string names.
|
2022-05-30 15:33:17 +05:30
|
|
|
* `IPython <https://ipython.readthedocs.io/en/stable/config/extensions/index.html>`_: Extensions are just Python modules
|
|
|
|
with some special functions to load/unload.
|
2016-05-11 01:55:53 -04:00
|
|
|
* `Oh My Zsh <http://ohmyz.sh/>`_: Centralized registry, autoloading, and
|
|
|
|
for a shell.
|
|
|
|
* `ESLint <http://eslint.org/>`_: Ability to use language package manager
|
|
|
|
to install/remove extensions.
|
|
|
|
|
|
|
|
Structure
|
2022-05-30 15:33:17 +05:30
|
|
|
================
|
|
|
|
Xontribs are modules with some special functions written
|
|
|
|
in either xonsh (``*.xsh``) or Python (``*.py``).
|
|
|
|
|
|
|
|
Here is a template:
|
|
|
|
|
|
|
|
.. code-block:: python
|
2022-06-17 22:09:12 +05:30
|
|
|
|
2022-05-30 15:33:17 +05:30
|
|
|
from xonsh.built_ins import XonshSession
|
|
|
|
|
|
|
|
def _load_xontrib_(xsh: XonshSession, **kwargs) -> dict:
|
|
|
|
"""
|
|
|
|
this function will be called when loading/reloading the xontrib.
|
|
|
|
|
|
|
|
Args:
|
|
|
|
xsh: the current xonsh session instance, serves as the interface to manipulate the session.
|
|
|
|
This allows you to register new aliases, history backends, event listeners ...
|
|
|
|
**kwargs: it is empty as of now. Kept for future proofing.
|
|
|
|
Returns:
|
|
|
|
dict: this will get loaded into the current execution context
|
|
|
|
"""
|
|
|
|
|
|
|
|
def _unload_xontrib_(xsh: XonshSession, **kwargs) -> dict:
|
|
|
|
"""If you want your extension to be unloadable, put that logic here"""
|
|
|
|
|
|
|
|
This _load_xontrib_() function is called after your extension is imported,
|
|
|
|
and the currently active :py:class:`xonsh.built_ins.XonshSession` instance is passed as the argument.
|
|
|
|
|
|
|
|
.. note::
|
|
|
|
|
|
|
|
Xontribs without ``_load_xontrib_`` are still supported.
|
|
|
|
But when such xontrib is loaded, variables listed
|
|
|
|
in ``__all__`` are placed in the current
|
|
|
|
execution context if defined.
|
|
|
|
|
2016-05-11 02:49:03 -04:00
|
|
|
Normally, these are stored and found in an
|
|
|
|
`implicit namespace package <https://www.python.org/dev/peps/pep-0420/>`_
|
|
|
|
called ``xontrib``. However, xontribs may be placed in any package or directory
|
|
|
|
that is on the ``$PYTHONPATH``.
|
|
|
|
|
2016-05-11 03:48:16 -04:00
|
|
|
If a module is in the ``xontrib`` namespace package, it can be referred to just
|
2016-05-11 02:49:03 -04:00
|
|
|
by its module name. If a module is in any other package, then it must be
|
2016-05-11 03:48:16 -04:00
|
|
|
referred to by its full package path, separated by ``.`` like you would in an
|
|
|
|
import statement. Of course, a module in ``xontrib`` may be referred to
|
2016-05-11 02:49:03 -04:00
|
|
|
with the full ``xontrib.myext``. But just calling it ``myext`` is a lot shorter
|
|
|
|
and one of the main advantages of placing an extension in the ``xontrib``
|
|
|
|
namespace package.
|
|
|
|
|
|
|
|
Here is a sample file system layout and what the xontrib names would be::
|
|
|
|
|
|
|
|
|- xontrib/
|
|
|
|
|- javert.xsh # "javert", because in xontrib
|
|
|
|
|- your.py # "your",
|
|
|
|
|- eyes/
|
|
|
|
|- __init__.py
|
|
|
|
|- scream.xsh # "eyes.scream", because eyes is in xontrib
|
|
|
|
|- mypkg/
|
|
|
|
|- __init__.py # a regular package with an init file
|
|
|
|
|- other.py # not a xontrib
|
|
|
|
|- show.py # "mypkg.show", full module name
|
|
|
|
|- tell.xsh # "mypkg.tell", full module name
|
|
|
|
|- subpkg/
|
|
|
|
|- __init__.py
|
|
|
|
|- done.py # "mypkg.subpkg.done", full module name
|
|
|
|
|
|
|
|
|
2022-05-30 15:33:17 +05:30
|
|
|
You can also use the `xontrib template <https://github.com/xonsh/xontrib-cookiecutter>`_ to easily
|
2016-09-15 22:14:16 +03:00
|
|
|
create the layout for your xontrib package.
|
|
|
|
|
|
|
|
|
2016-05-11 02:49:03 -04:00
|
|
|
Loading Xontribs
|
|
|
|
================
|
2022-05-05 00:32:20 +05:30
|
|
|
Xontribs may be loaded in a few different ways: from the config file
|
|
|
|
(e.g. ``~/.config/xonsh/rc.xsh``), dynamically at runtime with
|
2022-05-30 15:33:17 +05:30
|
|
|
the ``xontrib`` command, or its Python API.
|
2016-05-11 02:49:03 -04:00
|
|
|
|
2022-05-30 15:33:17 +05:30
|
|
|
Extensions are loaded via the ``xontrib load`` command.
|
|
|
|
This command may be run from anywhere in a xonshrc file or at any point
|
|
|
|
after xonsh has started up.
|
2016-05-11 02:49:03 -04:00
|
|
|
|
|
|
|
.. code-block:: xonsh
|
|
|
|
|
|
|
|
xontrib load myext mpl mypkg.show
|
|
|
|
|
2022-05-30 15:33:17 +05:30
|
|
|
The same can be done in Python as well
|
2016-05-11 02:49:03 -04:00
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
2022-05-30 15:33:17 +05:30
|
|
|
from xonsh.xontribs import xontribs_load
|
|
|
|
xontribs_load(['myext', 'mpl', 'mypkg.show'])
|
|
|
|
|
|
|
|
A xontrib can be unloaded from the current session using ``xontrib unload``
|
|
|
|
|
|
|
|
.. code-block:: xonsh
|
2022-06-17 22:09:12 +05:30
|
|
|
|
2022-05-30 15:33:17 +05:30
|
|
|
xontrib unload myext mpl mypkg.show
|
2016-05-11 02:49:03 -04:00
|
|
|
|
2022-06-17 22:09:12 +05:30
|
|
|
Xontribs can use `setuptools entrypoints <https://setuptools.pypa.io/en/latest/userguide/entry_point.html?highlight=entrypoints>`_
|
|
|
|
to mark themselves available for autoloading using the below format.
|
|
|
|
|
|
|
|
.. code-block:: ini
|
|
|
|
|
|
|
|
[options.entry_points]
|
|
|
|
xonsh.xontribs =
|
|
|
|
xontrib_name = path.to.the.module
|
|
|
|
|
|
|
|
Here the module should contain ``_load_xontrib_`` function as described above.
|
|
|
|
|
|
|
|
.. note::
|
|
|
|
|
|
|
|
Please make sure that importing the xontrib module and calling ``_load_xontrib_`` is fast enough.
|
|
|
|
Otherwise it will affect the shell's startup time.
|
|
|
|
Any other imports or heavy computations should be done in lazy manner whenever possible.
|
|
|
|
|
2016-05-11 01:55:53 -04:00
|
|
|
|
2016-05-11 03:44:39 -04:00
|
|
|
Listing Known Xontribs
|
|
|
|
======================
|
2016-05-11 12:27:50 -04:00
|
|
|
In addition to loading extensions, the ``xontrib`` command also allows you to
|
2022-05-05 00:32:20 +05:30
|
|
|
list the installed xontribs. This command will report if they are loaded
|
|
|
|
in the current session. To display this
|
2016-05-11 03:44:39 -04:00
|
|
|
information, pass the ``list`` action to the ``xontrib`` command:
|
|
|
|
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
|
|
|
|
>>> xontrib list
|
2022-05-05 00:32:20 +05:30
|
|
|
mpl not-loaded
|
|
|
|
myext not-loaded
|
2016-05-11 03:44:39 -04:00
|
|
|
|
|
|
|
|
2016-05-11 03:48:16 -04:00
|
|
|
For programmatic access, you may also have this command print a JSON formatted
|
2016-05-11 03:44:39 -04:00
|
|
|
string:
|
|
|
|
|
|
|
|
.. code-block:: xonshcon
|
|
|
|
|
|
|
|
>>> xontrib list --json mpl
|
|
|
|
{"mpl": {"loaded": false, "installed": true}}
|
|
|
|
|
|
|
|
Authoring Xontribs
|
2018-04-23 06:47:13 -04:00
|
|
|
==================
|
2016-05-11 03:44:39 -04:00
|
|
|
Writing a xontrib is as easy as writing a xonsh or Python file and sticking
|
|
|
|
it in a directory named ``xontrib/``. However, please do not place an
|
|
|
|
``__init__.py`` in the ``xontrib/`` directory. It is an
|
|
|
|
*implicit namespace package* and should not have one. See
|
|
|
|
`PEP 420 <https://www.python.org/dev/peps/pep-0420/>`_ for more details.
|
|
|
|
|
|
|
|
.. warning::
|
|
|
|
|
|
|
|
Do not place an ``__init__.py`` in the ``xontrib/`` directory!
|
|
|
|
|
|
|
|
If you plan on using ``*.xsh`` files in you xontrib, then you'll
|
|
|
|
have to add some hooks to distutils, setuptools, pip, etc. to install these
|
|
|
|
files. Try adding entries like the following entries to your ``setup()`` call
|
|
|
|
in your ``setup.py``:
|
|
|
|
|
|
|
|
.. code-block:: python
|
|
|
|
|
|
|
|
try:
|
|
|
|
from setuptools import setup
|
|
|
|
except ImportError:
|
|
|
|
from distutils.core import setup
|
|
|
|
|
|
|
|
setup(...,
|
|
|
|
packages=[..., 'xontrib'],
|
|
|
|
package_dir={..., 'xontrib': 'xontrib'},
|
|
|
|
package_data={..., 'xontrib': ['*.xsh']},
|
|
|
|
...)
|
|
|
|
|
|
|
|
Something similar can be done for any non-xontrib package or sub-package
|
|
|
|
that needs to distribute ``*.xsh`` files.
|
|
|
|
|
|
|
|
|
2016-05-11 01:55:53 -04:00
|
|
|
Tell Us About Your Xontrib!
|
|
|
|
===========================
|
2022-05-05 00:32:20 +05:30
|
|
|
We request that you register your xontrib with us.
|
|
|
|
We think that will make your contribution more discoverable.
|
2016-05-11 03:44:39 -04:00
|
|
|
|
2022-05-05 00:32:20 +05:30
|
|
|
To register a xontrib, create a ``PullRequest`` at
|
|
|
|
`Awesome-xontribs <https://github.com/xonsh/awesome-xontribs>`_
|
|
|
|
repository. Also, if you use Github to host your code,
|
|
|
|
please add `xonsh <https://github.com/topics/xonsh>`_ and `xontrib <https://github.com/topics/xontrib>`_
|
|
|
|
to the topics.
|
2016-05-11 03:44:39 -04:00
|
|
|
|
|
|
|
All of this let's users know that your xontrib is out there, ready to be used.
|
2018-04-23 06:47:13 -04:00
|
|
|
Of course, you're under no obligation to register your xontrib. Users will
|
2016-05-11 03:44:39 -04:00
|
|
|
still be able to load your xontrib, as long as they have it installed.
|
|
|
|
|
2016-06-06 12:09:41 -04:00
|
|
|
Go forth!
|