mirror of
https://github.com/xonsh/xonsh.git
synced 2025-03-04 08:24:40 +01:00
cl fix
This commit is contained in:
commit
230174235d
19 changed files with 332 additions and 70 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -33,3 +33,6 @@ include/
|
||||||
|
|
||||||
# Mac
|
# Mac
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
|
||||||
|
# Editor project files
|
||||||
|
*.komodo*
|
||||||
|
|
|
@ -3,6 +3,6 @@ python:
|
||||||
- 3.4
|
- 3.4
|
||||||
- 3.5
|
- 3.5
|
||||||
install:
|
install:
|
||||||
- pip install ply nose pygments prompt_toolkit
|
- pip install -r requirements-tests.txt
|
||||||
script:
|
script:
|
||||||
- nosetests -q
|
- nosetests -q
|
||||||
|
|
|
@ -15,7 +15,9 @@ Current Developments
|
||||||
on Windows. This functionality can be enabled/disabled with the
|
on Windows. This functionality can be enabled/disabled with the
|
||||||
$INTENSIFY_COLORS_ON_WIN environment variable.
|
$INTENSIFY_COLORS_ON_WIN environment variable.
|
||||||
* Added ``Ellipsis`` lookup to ``__xonsh_env__`` to allow environment variable checks, e.g. ``'HOME' in ${...}``
|
* Added ``Ellipsis`` lookup to ``__xonsh_env__`` to allow environment variable checks, e.g. ``'HOME' in ${...}``
|
||||||
|
* Added an option to update ``os.environ`` every time the xonsh environment changes.
|
||||||
|
This disabled by default, but can be enabled by setting ``$UPDATE_OS_ENVIRON`` to
|
||||||
|
True.
|
||||||
|
|
||||||
**Changed:**
|
**Changed:**
|
||||||
|
|
||||||
|
@ -25,6 +27,9 @@ Current Developments
|
||||||
loading bash completions.
|
loading bash completions.
|
||||||
* rc files are now compiled and cached, to avoid re-parsing when they haven't
|
* rc files are now compiled and cached, to avoid re-parsing when they haven't
|
||||||
changed.
|
changed.
|
||||||
|
* Left and Right arrows in the ``prompt_toolkit`` shell now wrap in multiline
|
||||||
|
environments
|
||||||
|
* Regexpath matching with backticks, now returns an empty list in python mode.
|
||||||
|
|
||||||
**Deprecated:** None
|
**Deprecated:** None
|
||||||
|
|
||||||
|
@ -33,9 +38,11 @@ Current Developments
|
||||||
**Fixed:**
|
**Fixed:**
|
||||||
|
|
||||||
* Fixed bug with loading prompt-toolkit shell < v0.57.
|
* Fixed bug with loading prompt-toolkit shell < v0.57.
|
||||||
|
* Fixed bug with prompt-toolkit completion when the cursor is not at the end of the line
|
||||||
|
|
||||||
**Security:** None
|
**Security:** None
|
||||||
|
|
||||||
|
|
||||||
v0.2.7
|
v0.2.7
|
||||||
====================
|
====================
|
||||||
**Added:**
|
**Added:**
|
||||||
|
@ -82,7 +89,6 @@ v0.2.7
|
||||||
argument to be deleted.
|
argument to be deleted.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
**Removed:**
|
**Removed:**
|
||||||
|
|
||||||
* The ``xonsh.tools.TERM_COLORS`` mapping has been axed, along with all
|
* The ``xonsh.tools.TERM_COLORS`` mapping has been axed, along with all
|
||||||
|
|
24
docs/add_to_shell.rst
Normal file
24
docs/add_to_shell.rst
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
Additional Setup
|
||||||
|
================
|
||||||
|
|
||||||
|
If you want to use xonsh as your default shell, you will first have to add xonsh to `/etc/shells`.
|
||||||
|
|
||||||
|
First ensure that xonsh is on your ``$PATH``
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ which xonsh
|
||||||
|
|
||||||
|
Then, as root, add xonsh to the shell list
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
# echo $(which xonsh) >> /etc/shells
|
||||||
|
|
||||||
|
To change shells, run
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ chsh -s $(which xonsh)
|
||||||
|
|
||||||
|
You will have to log out and log back in before the changes take effect.
|
|
@ -59,4 +59,5 @@ For those of you who want the gritty details.
|
||||||
jupyter_kernel
|
jupyter_kernel
|
||||||
wizard
|
wizard
|
||||||
xonfig
|
xonfig
|
||||||
|
vox
|
||||||
|
|
||||||
|
|
17
docs/dependencies.rst
Normal file
17
docs/dependencies.rst
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
Dependencies
|
||||||
|
============
|
||||||
|
Xonsh currently has the following external dependencies,
|
||||||
|
|
||||||
|
*Run Time:*
|
||||||
|
|
||||||
|
#. Python v3.4+
|
||||||
|
#. PLY
|
||||||
|
#. prompt-toolkit (optional)
|
||||||
|
#. Jupyter (optional)
|
||||||
|
#. setproctitle (optional)
|
||||||
|
|
||||||
|
*Documentation:*
|
||||||
|
|
||||||
|
#. `Sphinx <http://sphinx-doc.org/>`_ (which uses `reStructuredText <http://sphinx-doc.org/rest.html>`_)
|
||||||
|
#. Numpydoc
|
||||||
|
#. Cloud Sphinx Theme
|
|
@ -74,10 +74,34 @@ If you want to lint the entire code base run::
|
||||||
|
|
||||||
How to Test
|
How to Test
|
||||||
================
|
================
|
||||||
First, install nose: http://nose.readthedocs.org/en/latest/. Second, ensure
|
|
||||||
your cwd is the root directory of the project (i.e., the one containing the
|
Ensure your cwd is the root directory of the project (i.e., the one containing the
|
||||||
.git directory).
|
.git directory).
|
||||||
|
|
||||||
|
----------------------------------
|
||||||
|
Dependencies
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
Prep your environment for running the tests::
|
||||||
|
|
||||||
|
$ pip install requirements-tests.txt
|
||||||
|
|
||||||
|
|
||||||
|
----------------------------------
|
||||||
|
Running the Tests - Basic
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
Run all the tests using Nose::
|
||||||
|
|
||||||
|
$ nosetests -q
|
||||||
|
|
||||||
|
Use "-q" to keep nose from outputing a dot for every test. There are A LOT of tests
|
||||||
|
and you will waste time waiting for all the dots to get pushed through stdout.
|
||||||
|
|
||||||
|
----------------------------------
|
||||||
|
Running the Tests - Advanced
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
To perform all unit tests::
|
To perform all unit tests::
|
||||||
|
|
||||||
$ scripts/run_tests.xsh all
|
$ scripts/run_tests.xsh all
|
||||||
|
|
|
@ -93,6 +93,6 @@ manually use the ``$[]`` or ``$()`` operators on your code.
|
||||||
|
|
||||||
5. Context-sensitive parsing is gross
|
5. Context-sensitive parsing is gross
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
Yes, context-sensitive parsing is gross. But the point of xonsh is that it
|
Yes, context-sensitive parsing is gross. But the point of xonsh is that it uses xontext-sensitive parsing and
|
||||||
is ultimately a lot less gross than other shell languages, such as BASH.
|
is ultimately a lot less gross than other shell languages, such as BASH.
|
||||||
Furthermore, its use is heavily limited here.
|
Furthermore, its use is heavily limited here.
|
||||||
|
|
|
@ -72,6 +72,16 @@ alike.
|
||||||
=========
|
=========
|
||||||
Contents
|
Contents
|
||||||
=========
|
=========
|
||||||
|
**Installation:**
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:titlesonly:
|
||||||
|
:maxdepth: 1
|
||||||
|
|
||||||
|
linux
|
||||||
|
osx
|
||||||
|
windows
|
||||||
|
|
||||||
**Guides:**
|
**Guides:**
|
||||||
|
|
||||||
.. toctree::
|
.. toctree::
|
||||||
|
@ -106,52 +116,6 @@ Contents
|
||||||
faq
|
faq
|
||||||
todo
|
todo
|
||||||
|
|
||||||
============
|
|
||||||
Installation
|
|
||||||
============
|
|
||||||
You can install xonsh using conda, pip, or from source.
|
|
||||||
|
|
||||||
**conda:**
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
$ conda install -c xonsh xonsh
|
|
||||||
|
|
||||||
.. note:: For the bleeding edge development version use ``conda install -c xonsh/channel/dev xonsh``
|
|
||||||
|
|
||||||
|
|
||||||
**pip:**
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
$ pip install xonsh
|
|
||||||
|
|
||||||
**source:** Download the source `from github <https://github.com/scopatz/xonsh>`_
|
|
||||||
(`zip file <https://github.com/scopatz/xonsh/archive/master.zip>`_), then run
|
|
||||||
the following from the source directory,
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
$ python setup.py install
|
|
||||||
|
|
||||||
Arch Linux users can install xonsh from the Arch User Repository with e.g.
|
|
||||||
yaourt or aura:
|
|
||||||
|
|
||||||
**yaourt:**
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
$ yaourt -Sa xonsh # yaourt will call sudo when needed
|
|
||||||
|
|
||||||
**aura:**
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
$ sudo aura -A xonsh
|
|
||||||
|
|
||||||
If you run into any problems, please let us know!
|
|
||||||
|
|
||||||
|
|
||||||
==========
|
==========
|
||||||
Comparison
|
Comparison
|
||||||
==========
|
==========
|
||||||
|
@ -264,8 +228,7 @@ Xonsh currently has the following external dependencies,
|
||||||
|
|
||||||
*Documentation:*
|
*Documentation:*
|
||||||
|
|
||||||
#. `Sphinx <http://sphinx-doc.org/>` (which uses
|
#. `Sphinx <http://sphinx-doc.org/>`_ (which uses `reStructuredText <http://sphinx-doc.org/rest.html>`_)
|
||||||
`reStructuredText <http://sphinx-doc.org/rest.html>`)
|
|
||||||
#. Numpydoc
|
#. Numpydoc
|
||||||
#. Cloud Sphinx Theme
|
#. Cloud Sphinx Theme
|
||||||
|
|
||||||
|
|
60
docs/linux.rst
Normal file
60
docs/linux.rst
Normal file
|
@ -0,0 +1,60 @@
|
||||||
|
==========================
|
||||||
|
Linux Guide
|
||||||
|
==========================
|
||||||
|
|
||||||
|
Installation
|
||||||
|
============
|
||||||
|
|
||||||
|
You can install xonsh using ``conda``, ``pip``, or from source.
|
||||||
|
|
||||||
|
**conda:**
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ conda install -c xonsh xonsh
|
||||||
|
|
||||||
|
.. note:: For the bleeding edge development version use ``conda install -c xonsh/channel/dev xonsh``
|
||||||
|
|
||||||
|
|
||||||
|
**pip:**
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ pip install xonsh
|
||||||
|
|
||||||
|
|
||||||
|
**source:** Download the source `from github <https://github.com/scopatz/xonsh>`_
|
||||||
|
(`zip file <https://github.com/scopatz/xonsh/archive/master.zip>`_), then run
|
||||||
|
the following from the source directory,
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ python setup.py install
|
||||||
|
|
||||||
|
|
||||||
|
Arch Linux users can install xonsh from the Arch User Repository with e.g.
|
||||||
|
``yaourt``, ``aura``, ``pacaur``, ``PKGBUILD``, etc...:
|
||||||
|
|
||||||
|
**yaourt:**
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ yaourt -Sa xonsh # yaourt will call sudo when needed
|
||||||
|
|
||||||
|
**aura:**
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ sudo aura -A xonsh
|
||||||
|
|
||||||
|
**pacaur:**
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ pacaur -S xonsh
|
||||||
|
|
||||||
|
If you run into any problems, please let us know!
|
||||||
|
|
||||||
|
.. include:: add_to_shell.rst
|
||||||
|
|
||||||
|
.. include:: dependencies.rst
|
37
docs/osx.rst
Normal file
37
docs/osx.rst
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
==========================
|
||||||
|
OSX Guide
|
||||||
|
==========================
|
||||||
|
|
||||||
|
Installation
|
||||||
|
============
|
||||||
|
|
||||||
|
You can install xonsh using conda, pip, or from source.
|
||||||
|
|
||||||
|
**conda:**
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ conda install -c xonsh xonsh
|
||||||
|
|
||||||
|
.. note:: For the bleeding edge development version use ``conda install -c xonsh/channel/dev xonsh``
|
||||||
|
|
||||||
|
|
||||||
|
**pip:**
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ pip install xonsh
|
||||||
|
|
||||||
|
|
||||||
|
**source:** Download the source `from github <https://github.com/scopatz/xonsh>`_
|
||||||
|
(`zip file <https://github.com/scopatz/xonsh/archive/master.zip>`_), then run
|
||||||
|
the following from the source directory,
|
||||||
|
|
||||||
|
.. code-block:: bash
|
||||||
|
|
||||||
|
$ python setup.py install
|
||||||
|
|
||||||
|
|
||||||
|
.. include:: add_to_shell.rst
|
||||||
|
|
||||||
|
.. include:: dependencies.rst
|
|
@ -134,9 +134,31 @@ variable in Python. The same is true for deleting them too.
|
||||||
Become the Lord of the Files
|
Become the Lord of the Files
|
||||||
>>> del $GOAL
|
>>> del $GOAL
|
||||||
|
|
||||||
Very nice. All environment variables live in the built-in
|
Very nice.
|
||||||
``__xonsh_env__`` mapping. You can access this mapping directly, but in most
|
|
||||||
situations, you shouldn't need to.
|
__xonsh_env__
|
||||||
|
--------------
|
||||||
|
|
||||||
|
All environment variables live in the built-in ``__xonsh_env__`` mapping. You can access this
|
||||||
|
mapping directly, but in most situations, you shouldn't need to.
|
||||||
|
|
||||||
|
One helpful method on the __xonsh_env__ is :func:`~xonsh.environ.Env.swap`. It can be used to temporarily set an
|
||||||
|
environment variable:
|
||||||
|
|
||||||
|
|
||||||
|
.. code-block:: xonshcon
|
||||||
|
|
||||||
|
>>> with __xonsh_env__.swap(SOMEVAR='foo'):
|
||||||
|
... echo $SOMEVAR
|
||||||
|
...
|
||||||
|
...
|
||||||
|
foo
|
||||||
|
>>> echo $SOMEVAR
|
||||||
|
|
||||||
|
>>>
|
||||||
|
|
||||||
|
Environment Types
|
||||||
|
-----------------
|
||||||
|
|
||||||
Like other variables in Python, environment variables have a type. Sometimes
|
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
|
this type is imposed based on the variable name. The current rules are pretty
|
||||||
|
|
4
requirements-tests.txt
Normal file
4
requirements-tests.txt
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
ply
|
||||||
|
nose
|
||||||
|
prompt-toolkit
|
||||||
|
pygments
|
|
@ -72,5 +72,35 @@ def test_HISTCONTROL():
|
||||||
assert_true('ignoreerr' in env['HISTCONTROL'])
|
assert_true('ignoreerr' in env['HISTCONTROL'])
|
||||||
assert_true('ignoredups' in env['HISTCONTROL'])
|
assert_true('ignoredups' in env['HISTCONTROL'])
|
||||||
|
|
||||||
|
def test_swap():
|
||||||
|
|
||||||
|
env = Env(VAR='wakka')
|
||||||
|
assert_equal(env['VAR'], 'wakka')
|
||||||
|
|
||||||
|
# positional arg
|
||||||
|
with env.swap({'VAR': 'foo'}):
|
||||||
|
assert_equal(env['VAR'], 'foo')
|
||||||
|
|
||||||
|
# make sure the environment goes back outside the context manager
|
||||||
|
assert_equal(env['VAR'], 'wakka')
|
||||||
|
|
||||||
|
# kwargs only
|
||||||
|
with env.swap(VAR1='foo', VAR2='bar'):
|
||||||
|
assert_equal(env['VAR1'], 'foo')
|
||||||
|
assert_equal(env['VAR2'], 'bar')
|
||||||
|
|
||||||
|
# positional and kwargs
|
||||||
|
with env.swap({'VAR3': 'baz'}, VAR1='foo', VAR2='bar'):
|
||||||
|
assert_equal(env['VAR1'], 'foo')
|
||||||
|
assert_equal(env['VAR2'], 'bar')
|
||||||
|
assert_equal(env['VAR3'], 'baz')
|
||||||
|
|
||||||
|
# make sure the environment goes back outside the context manager
|
||||||
|
assert_equal(env['VAR'], 'wakka')
|
||||||
|
assert 'VAR1' not in env
|
||||||
|
assert 'VAR2' not in env
|
||||||
|
assert 'VAR3' not in env
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
nose.runmodule()
|
nose.runmodule()
|
||||||
|
|
|
@ -266,13 +266,14 @@ def reglob(path, parts=None, i=None):
|
||||||
return paths
|
return paths
|
||||||
|
|
||||||
|
|
||||||
def regexpath(s):
|
def regexpath(s, pymode=False):
|
||||||
"""Takes a regular expression string and returns a list of file
|
"""Takes a regular expression string and returns a list of file
|
||||||
paths that match the regex.
|
paths that match the regex.
|
||||||
"""
|
"""
|
||||||
s = expand_path(s)
|
s = expand_path(s)
|
||||||
o = reglob(s)
|
o = reglob(s)
|
||||||
return o if len(o) != 0 else [s]
|
no_match = [] if pymode else [s]
|
||||||
|
return o if len(o) != 0 else no_match
|
||||||
|
|
||||||
|
|
||||||
def globpath(s, ignore_case=False):
|
def globpath(s, ignore_case=False):
|
||||||
|
|
|
@ -85,6 +85,7 @@ DEFAULT_ENSURERS = {
|
||||||
'RAISE_SUBPROC_ERROR': (is_bool, to_bool, bool_to_str),
|
'RAISE_SUBPROC_ERROR': (is_bool, to_bool, bool_to_str),
|
||||||
'RIGHT_PROMPT': (is_string, ensure_string, ensure_string),
|
'RIGHT_PROMPT': (is_string, ensure_string, ensure_string),
|
||||||
'TEEPTY_PIPE_DELAY': (is_float, float, str),
|
'TEEPTY_PIPE_DELAY': (is_float, float, str),
|
||||||
|
'UPDATE_OS_ENVIRON': (is_bool, to_bool, bool_to_str),
|
||||||
'XONSHRC': (is_env_path, str_to_env_path, env_path_to_str),
|
'XONSHRC': (is_env_path, str_to_env_path, env_path_to_str),
|
||||||
'XONSH_COLOR_STYLE': (is_string, ensure_string, ensure_string),
|
'XONSH_COLOR_STYLE': (is_string, ensure_string, ensure_string),
|
||||||
'XONSH_ENCODING': (is_string, ensure_string, ensure_string),
|
'XONSH_ENCODING': (is_string, ensure_string, ensure_string),
|
||||||
|
@ -194,6 +195,7 @@ DEFAULT_VALUES = {
|
||||||
'SUGGEST_THRESHOLD': 3,
|
'SUGGEST_THRESHOLD': 3,
|
||||||
'TEEPTY_PIPE_DELAY': 0.01,
|
'TEEPTY_PIPE_DELAY': 0.01,
|
||||||
'TITLE': DEFAULT_TITLE,
|
'TITLE': DEFAULT_TITLE,
|
||||||
|
'UPDATE_OS_ENVIRON': False,
|
||||||
'VI_MODE': False,
|
'VI_MODE': False,
|
||||||
'WIN_UNICODE_CONSOLE': True,
|
'WIN_UNICODE_CONSOLE': True,
|
||||||
'XDG_CONFIG_HOME': os.path.expanduser(os.path.join('~', '.config')),
|
'XDG_CONFIG_HOME': os.path.expanduser(os.path.join('~', '.config')),
|
||||||
|
@ -394,6 +396,9 @@ DEFAULT_DOCS = {
|
||||||
"in the same manner as $PROMPT, see 'Customizing the Prompt' "
|
"in the same manner as $PROMPT, see 'Customizing the Prompt' "
|
||||||
'http://xon.sh/tutorial.html#customizing-the-prompt.',
|
'http://xon.sh/tutorial.html#customizing-the-prompt.',
|
||||||
default='xonsh.environ.DEFAULT_TITLE'),
|
default='xonsh.environ.DEFAULT_TITLE'),
|
||||||
|
'UPDATE_OS_ENVIRON': VarDocs("If True os.environ will always be updated "
|
||||||
|
"when the xonsh environment changes. The environment can be reset to "
|
||||||
|
"the default value by calling '__xonsh_env__.undo_replace_env()'"),
|
||||||
'VI_MODE': VarDocs(
|
'VI_MODE': VarDocs(
|
||||||
"Flag to enable 'vi_mode' in the 'prompt_toolkit' shell."),
|
"Flag to enable 'vi_mode' in the 'prompt_toolkit' shell."),
|
||||||
'VIRTUAL_ENV': VarDocs(
|
'VIRTUAL_ENV': VarDocs(
|
||||||
|
@ -491,6 +496,7 @@ class Env(MutableMapping):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
"""If no initial environment is given, os.environ is used."""
|
"""If no initial environment is given, os.environ is used."""
|
||||||
self._d = {}
|
self._d = {}
|
||||||
|
self._orig_env = None
|
||||||
self.ensurers = {k: Ensurer(*v) for k, v in DEFAULT_ENSURERS.items()}
|
self.ensurers = {k: Ensurer(*v) for k, v in DEFAULT_ENSURERS.items()}
|
||||||
self.defaults = DEFAULT_VALUES
|
self.defaults = DEFAULT_VALUES
|
||||||
self.docs = DEFAULT_DOCS
|
self.docs = DEFAULT_DOCS
|
||||||
|
@ -499,14 +505,17 @@ class Env(MutableMapping):
|
||||||
for key, val in dict(*args, **kwargs).items():
|
for key, val in dict(*args, **kwargs).items():
|
||||||
self[key] = val
|
self[key] = val
|
||||||
self._detyped = None
|
self._detyped = None
|
||||||
self._orig_env = None
|
|
||||||
|
@staticmethod
|
||||||
|
def detypeable(val):
|
||||||
|
return not (callable(val) or isinstance(val, MutableMapping))
|
||||||
|
|
||||||
def detype(self):
|
def detype(self):
|
||||||
if self._detyped is not None:
|
if self._detyped is not None:
|
||||||
return self._detyped
|
return self._detyped
|
||||||
ctx = {}
|
ctx = {}
|
||||||
for key, val in self._d.items():
|
for key, val in self._d.items():
|
||||||
if callable(val) or isinstance(val, MutableMapping):
|
if not self.detypeable(val):
|
||||||
continue
|
continue
|
||||||
if not isinstance(key, string_types):
|
if not isinstance(key, string_types):
|
||||||
key = str(key)
|
key = str(key)
|
||||||
|
@ -563,16 +572,27 @@ class Env(MutableMapping):
|
||||||
return vd
|
return vd
|
||||||
|
|
||||||
@contextmanager
|
@contextmanager
|
||||||
def swap(self, other):
|
def swap(self, other=None, **kwargs):
|
||||||
"""Provides a context manager for temporarily swapping out certain
|
"""Provides a context manager for temporarily swapping out certain
|
||||||
environment variables with other values. On exit from the context
|
environment variables with other values. On exit from the context
|
||||||
manager, the original values are restored.
|
manager, the original values are restored.
|
||||||
"""
|
"""
|
||||||
old = {}
|
old = {}
|
||||||
for k, v in other.items():
|
|
||||||
|
# single positional argument should be a dict-like object
|
||||||
|
if other is not None:
|
||||||
|
for k, v in other.items():
|
||||||
|
old[k] = self.get(k, NotImplemented)
|
||||||
|
self[k] = v
|
||||||
|
|
||||||
|
# kwargs could also have been sent in
|
||||||
|
for k, v in kwargs.items():
|
||||||
old[k] = self.get(k, NotImplemented)
|
old[k] = self.get(k, NotImplemented)
|
||||||
self[k] = v
|
self[k] = v
|
||||||
|
|
||||||
yield self
|
yield self
|
||||||
|
|
||||||
|
# restore the values
|
||||||
for k, v in old.items():
|
for k, v in old.items():
|
||||||
if v is NotImplemented:
|
if v is NotImplemented:
|
||||||
del self[k]
|
del self[k]
|
||||||
|
@ -613,12 +633,23 @@ class Env(MutableMapping):
|
||||||
if not ensurer.validate(val):
|
if not ensurer.validate(val):
|
||||||
val = ensurer.convert(val)
|
val = ensurer.convert(val)
|
||||||
self._d[key] = val
|
self._d[key] = val
|
||||||
self._detyped = None
|
if self.detypeable(val):
|
||||||
|
self._detyped = None
|
||||||
|
if self.get('UPDATE_OS_ENVIRON'):
|
||||||
|
if self._orig_env is None:
|
||||||
|
self.replace_env()
|
||||||
|
else:
|
||||||
|
dval = ensurer.detype(val)
|
||||||
|
os.environ[key] = dval
|
||||||
|
|
||||||
def __delitem__(self, key):
|
def __delitem__(self, key):
|
||||||
del self._d[key]
|
val = self._d.pop(key)
|
||||||
self._detyped = None
|
if self.detypeable(val):
|
||||||
|
self._detyped = None
|
||||||
|
if self.get('UPDATE_OS_ENVIRON'):
|
||||||
|
if key in os.environ:
|
||||||
|
del os.environ[key]
|
||||||
|
|
||||||
def get(self, key, default=None):
|
def get(self, key, default=None):
|
||||||
"""The environment will look up default values from its own defaults if a
|
"""The environment will look up default values from its own defaults if a
|
||||||
default is not given here.
|
default is not given here.
|
||||||
|
|
|
@ -25,7 +25,7 @@ class PromptToolkitCompleter(Completer):
|
||||||
if complete_event.completion_requested:
|
if complete_event.completion_requested:
|
||||||
line = document.current_line.lstrip()
|
line = document.current_line.lstrip()
|
||||||
endidx = document.cursor_position_col
|
endidx = document.cursor_position_col
|
||||||
begidx = line.rfind(' ') + 1 if line.rfind(' ') >= 0 else 0
|
begidx = line[:endidx].rfind(' ') + 1 if line[:endidx].rfind(' ') >= 0 else 0
|
||||||
prefix = line[begidx:endidx]
|
prefix = line[begidx:endidx]
|
||||||
completions, l = self.completer.complete(prefix,
|
completions, l = self.completer.complete(prefix,
|
||||||
line,
|
line,
|
||||||
|
|
|
@ -70,6 +70,28 @@ class TabShouldInsertIndentFilter(Filter):
|
||||||
|
|
||||||
return bool(before_cursor.isspace())
|
return bool(before_cursor.isspace())
|
||||||
|
|
||||||
|
class BeginningOfLine(Filter):
|
||||||
|
"""
|
||||||
|
Check if cursor is at beginning of a line other than the first line
|
||||||
|
in a multiline document
|
||||||
|
"""
|
||||||
|
def __call__(self, cli):
|
||||||
|
before_cursor = cli.current_buffer.document.current_line_before_cursor
|
||||||
|
|
||||||
|
return bool(len(before_cursor) == 0
|
||||||
|
and not cli.current_buffer.document.on_first_line)
|
||||||
|
|
||||||
|
class EndOfLine(Filter):
|
||||||
|
"""
|
||||||
|
Check if cursor is at the end of a line other than the last line
|
||||||
|
in a multiline document
|
||||||
|
"""
|
||||||
|
def __call__(self, cli):
|
||||||
|
d = cli.current_buffer.document
|
||||||
|
at_end = d.is_cursor_at_the_end_of_line
|
||||||
|
last_line = d.is_cursor_at_the_end
|
||||||
|
|
||||||
|
return bool(at_end and not last_line)
|
||||||
|
|
||||||
def can_compile(src):
|
def can_compile(src):
|
||||||
"""Returns whether the code can be compiled, i.e. it is valid xonsh."""
|
"""Returns whether the code can be compiled, i.e. it is valid xonsh."""
|
||||||
|
@ -109,6 +131,21 @@ def load_xonsh_bindings(key_bindings_manager):
|
||||||
b = event.cli.current_buffer
|
b = event.cli.current_buffer
|
||||||
carriage_return(b, event.cli)
|
carriage_return(b, event.cli)
|
||||||
|
|
||||||
|
@handle(Keys.Left, filter=BeginningOfLine())
|
||||||
|
def wrap_cursor_back(event):
|
||||||
|
"""Move cursor to end of previous line unless at beginning of document"""
|
||||||
|
b = event.cli.current_buffer
|
||||||
|
b.cursor_up(count=1)
|
||||||
|
relative_end_index = b.document.get_end_of_line_position()
|
||||||
|
b.cursor_right(count=relative_end_index)
|
||||||
|
|
||||||
|
@handle(Keys.Right, filter=EndOfLine())
|
||||||
|
def wrap_cursor_forward(event):
|
||||||
|
"""Move cursor to beginning of next line unless at end of document"""
|
||||||
|
b = event.cli.current_buffer
|
||||||
|
relative_begin_index = b.document.get_start_of_line_position()
|
||||||
|
b.cursor_left(count=abs(relative_begin_index))
|
||||||
|
b.cursor_down(count=1)
|
||||||
|
|
||||||
def _is_blank(l):
|
def _is_blank(l):
|
||||||
return len(l.strip()) == 0
|
return len(l.strip()) == 0
|
||||||
|
|
|
@ -993,6 +993,8 @@ def expandvars(path):
|
||||||
var = eval(var, builtins.__xonsh_ctx__)
|
var = eval(var, builtins.__xonsh_ctx__)
|
||||||
if _is_in_env(var):
|
if _is_in_env(var):
|
||||||
value = _get_env_string(var)
|
value = _get_env_string(var)
|
||||||
|
elif var is Ellipsis:
|
||||||
|
value = dollar + brace + '...' + rbrace
|
||||||
else:
|
else:
|
||||||
value = dollar + brace + var + rbrace
|
value = dollar + brace + var + rbrace
|
||||||
except:
|
except:
|
||||||
|
|
Loading…
Add table
Reference in a new issue