mirror of
https://github.com/xonsh/xonsh.git
synced 2025-03-06 09:20:57 +01:00
commit
b69fb9ab4b
69 changed files with 1198 additions and 289 deletions
|
@ -40,10 +40,8 @@ before_install:
|
|||
|
||||
install:
|
||||
- if [[ $BUILD_DOCS = true ]]; then
|
||||
python setup.py install;
|
||||
pip install -r requirements-docs.txt;
|
||||
pip install pygments prompt_toolkit<2 ply psutil ipykernel matplotlib;
|
||||
pip install doctr;
|
||||
python setup.py install;
|
||||
else
|
||||
pip install -r requirements-tests.txt;
|
||||
fi
|
||||
|
|
|
@ -435,7 +435,7 @@ def rewrite_imports(name, pkg, order, imps):
|
|||
for start, stop, s in replacements[::-1]:
|
||||
lines[start] = s
|
||||
for i in range(stop - start - 1):
|
||||
del lines[start+1]
|
||||
del lines[start + 1]
|
||||
return ''.join(lines)
|
||||
|
||||
|
||||
|
@ -524,8 +524,8 @@ def rewrite_init(pkg, order, debug='DEBUG'):
|
|||
if start + 1 == stop:
|
||||
lines.insert(stop, s)
|
||||
else:
|
||||
lines[start+1] = s
|
||||
lines = lines[:start+2] + lines[stop:]
|
||||
lines[start + 1] = s
|
||||
lines = lines[:start + 2] + lines[stop:]
|
||||
init = '\n'.join(lines) + '\n'
|
||||
with open(fname, 'w', encoding='utf-8', errors='surrogateescape') as f:
|
||||
f.write(init)
|
||||
|
|
|
@ -1,20 +1,22 @@
|
|||
name: py34-xonsh-test
|
||||
channels:
|
||||
- conda-forge
|
||||
- defaults
|
||||
dependencies:
|
||||
- python=3.4
|
||||
- pygments
|
||||
- prompt_toolkit<2.0
|
||||
- prompt_toolkit
|
||||
- ply
|
||||
- pytest
|
||||
- pytest-timeout
|
||||
- numpy
|
||||
- psutil
|
||||
- matplotlib=1.5.3
|
||||
- matplotlib
|
||||
- flake8
|
||||
- coverage
|
||||
- pyflakes
|
||||
- pytest-cov
|
||||
- codecov
|
||||
# conda forge doesn't have the following for Python v3.4
|
||||
- pip:
|
||||
- pytest-flake8
|
||||
- codecov
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
name: py35-xonsh-test
|
||||
channels:
|
||||
- conda-forge
|
||||
- defaults
|
||||
dependencies:
|
||||
- python=3.5
|
||||
- pygments
|
||||
- prompt_toolkit<2.0
|
||||
- prompt_toolkit
|
||||
- ply
|
||||
- pytest
|
||||
- pytest-timeout
|
||||
- numpy
|
||||
- psutil
|
||||
- matplotlib=1.5.3
|
||||
- matplotlib
|
||||
- flake8
|
||||
- coverage
|
||||
- pyflakes
|
||||
- pytest-cov
|
||||
- pip:
|
||||
- pytest-flake8
|
||||
- codecov
|
||||
- pytest-flake8
|
||||
- codecov
|
||||
|
|
|
@ -1,20 +1,20 @@
|
|||
name: py36-xonsh-test
|
||||
channels:
|
||||
- conda-forge
|
||||
- defaults
|
||||
dependencies:
|
||||
- python=3.6
|
||||
- pygments
|
||||
- prompt_toolkit<2.0
|
||||
- prompt_toolkit
|
||||
- ply
|
||||
- pytest
|
||||
- pytest-timeout
|
||||
- numpy
|
||||
- psutil
|
||||
- matplotlib=1.5.3
|
||||
- matplotlib
|
||||
- flake8
|
||||
- coverage
|
||||
- pyflakes
|
||||
- pytest-cov
|
||||
- pip:
|
||||
- pytest-flake8
|
||||
- codecov
|
||||
- pytest-flake8
|
||||
- codecov
|
||||
|
|
|
@ -25,7 +25,11 @@ spec = importlib.util.find_spec('prompt_toolkit')
|
|||
if spec is not None:
|
||||
# hacky runaround to import PTK-specific events
|
||||
builtins.__xonsh_env__ = Env()
|
||||
from xonsh.ptk.shell import events
|
||||
from xonsh.platform import ptk_version_info
|
||||
if ptk_version_info()[0] < 2:
|
||||
from xonsh.ptk.shell import events
|
||||
else:
|
||||
from xonsh.ptk2.shell import events
|
||||
else:
|
||||
from xonsh.events import events
|
||||
|
||||
|
|
17
news/ptk_2.0.rst
Normal file
17
news/ptk_2.0.rst
Normal file
|
@ -0,0 +1,17 @@
|
|||
**Added:**
|
||||
|
||||
* Support for ``prompt_toolkit 2.0``
|
||||
* The ``--shell-type`` (``$SHELL_TYPE``) may now be specified using
|
||||
shortcuts, such as ``rl`` for ``readline`` and ``ptk2`` for
|
||||
``prompt_toolkit2``. See ``xonsh --help`` for a full listing
|
||||
of available aliases.
|
||||
|
||||
**Changed:** None
|
||||
|
||||
**Deprecated:** None
|
||||
|
||||
**Removed:** None
|
||||
|
||||
**Fixed:** None
|
||||
|
||||
**Security:** None
|
|
@ -1,4 +1,10 @@
|
|||
cloud_sptheme
|
||||
numpydoc==0.5
|
||||
Sphinx==1.5.6
|
||||
prompt_toolkit<2
|
||||
numpydoc
|
||||
Sphinx
|
||||
prompt_toolkit
|
||||
pygments
|
||||
ply
|
||||
psutil
|
||||
ipykernel
|
||||
matplotlib
|
||||
doctr
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
ply==3.8
|
||||
py==1.4.31
|
||||
pyflakes==1.2.3
|
||||
pytest==2.9.2
|
||||
pytest-flake8==0.5
|
||||
pytest-cov==2.3.0
|
||||
pytest-timeout==1.0.0
|
||||
prompt-toolkit<2
|
||||
pygments==2.1.3
|
||||
codecov==2.0.5
|
||||
flake8==2.6.2
|
||||
coverage==4.2
|
||||
ply
|
||||
py
|
||||
pytest
|
||||
pytest-flake8
|
||||
pytest-cov
|
||||
pytest-timeout
|
||||
prompt-toolkit
|
||||
pygments
|
||||
codecov
|
||||
flake8
|
||||
pyflakes<1.7.0,>=1.5.0
|
||||
coverage
|
||||
|
|
6
setup.py
6
setup.py
|
@ -304,8 +304,8 @@ def main():
|
|||
url='https://github.com/xonsh/xonsh',
|
||||
platforms='Cross Platform',
|
||||
classifiers=['Programming Language :: Python :: 3'],
|
||||
packages=['xonsh', 'xonsh.ply.ply', 'xonsh.ptk', 'xonsh.parsers',
|
||||
'xonsh.xoreutils', 'xontrib',
|
||||
packages=['xonsh', 'xonsh.ply.ply', 'xonsh.ptk', 'xonsh.ptk2',
|
||||
'xonsh.parsers', 'xonsh.xoreutils', 'xontrib',
|
||||
'xonsh.completers', 'xonsh.history', 'xonsh.prompt',
|
||||
'xonsh.lib'],
|
||||
package_dir={'xonsh': 'xonsh', 'xontrib': 'xontrib', 'xonsh.lib': 'xonsh/lib'},
|
||||
|
@ -332,7 +332,7 @@ def main():
|
|||
}
|
||||
skw['cmdclass']['develop'] = xdevelop
|
||||
skw['extras_require'] = {
|
||||
'ptk': ['prompt-toolkit<2.0.0'],
|
||||
'ptk': ['prompt-toolkit'],
|
||||
'pygments': ['pygments'],
|
||||
'win': ['win_unicode_console'],
|
||||
'mac': ['gnureadline'],
|
||||
|
|
|
@ -21,6 +21,7 @@ def Shell(*args, **kwargs):
|
|||
@pytest.fixture
|
||||
def shell(xonsh_builtins, xonsh_execer, monkeypatch):
|
||||
"""Xonsh Shell Mock"""
|
||||
Shell.shell_type_aliases = {'rl': 'readline'}
|
||||
monkeypatch.setattr(xonsh.main, 'Shell', Shell)
|
||||
|
||||
|
||||
|
|
|
@ -5,18 +5,21 @@ try:
|
|||
except ImportError:
|
||||
pytest.mark.skip(msg='prompt_toolkit is not available')
|
||||
|
||||
from xonsh.ptk.history import PromptToolkitHistory
|
||||
from xonsh.ptk2.history import PromptToolkitHistory
|
||||
|
||||
from tools import skip_if_lt_ptk2
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def history_obj():
|
||||
"""Instantiate `PromptToolkitHistory` and append a line string"""
|
||||
hist = PromptToolkitHistory(load_prev=False)
|
||||
hist.append('line10')
|
||||
hist.append_string('line10')
|
||||
return hist
|
||||
|
||||
|
||||
@skip_if_lt_ptk2
|
||||
def test_obj(history_obj):
|
||||
assert ['line10'] == history_obj.strings
|
||||
assert ['line10'] == history_obj.get_strings()
|
||||
assert len(history_obj) == 1
|
||||
assert ['line10'] == [x for x in history_obj]
|
||||
|
|
|
@ -5,13 +5,13 @@ from collections import namedtuple
|
|||
from unittest.mock import MagicMock, patch
|
||||
|
||||
import pytest
|
||||
from prompt_toolkit.interface import CommandLineInterface
|
||||
from prompt_toolkit.application import Application
|
||||
from prompt_toolkit.document import Document
|
||||
from prompt_toolkit.buffer import Buffer, AcceptAction
|
||||
from prompt_toolkit.buffer import Buffer
|
||||
|
||||
from xonsh.tools import ON_WINDOWS
|
||||
|
||||
from tools import DummyEnv
|
||||
from tools import DummyEnv, skip_if_lt_ptk2
|
||||
|
||||
|
||||
Context = namedtuple('Context', ['indent', 'buffer', 'accept', 'cli', 'cr'])
|
||||
|
@ -22,10 +22,10 @@ def ctx():
|
|||
"""Context in which the ptk multiline functionality will be tested."""
|
||||
builtins.__xonsh_env__ = DummyEnv()
|
||||
builtins.__xonsh_env__['INDENT'] = ' '
|
||||
from xonsh.ptk.key_bindings import carriage_return
|
||||
from xonsh.ptk2.key_bindings import carriage_return
|
||||
ptk_buffer = Buffer()
|
||||
ptk_buffer.accept_action = MagicMock(name='accept', spec=AcceptAction)
|
||||
cli = MagicMock(name='cli', spec=CommandLineInterface)
|
||||
ptk_buffer.accept_action = MagicMock(name='accept')
|
||||
cli = MagicMock(name='cli', spec=Application)
|
||||
yield Context(indent=' ',
|
||||
buffer=ptk_buffer,
|
||||
accept=ptk_buffer.accept_action,
|
||||
|
@ -34,6 +34,7 @@ def ctx():
|
|||
del builtins.__xonsh_env__
|
||||
|
||||
|
||||
@skip_if_lt_ptk2
|
||||
def test_colon_indent(ctx):
|
||||
document = Document('for i in range(5):')
|
||||
ctx.buffer.set_document(document)
|
||||
|
@ -41,6 +42,7 @@ def test_colon_indent(ctx):
|
|||
assert ctx.buffer.document.current_line == ctx.indent
|
||||
|
||||
|
||||
@skip_if_lt_ptk2
|
||||
def test_dedent(ctx):
|
||||
document = Document('\n'+ctx.indent+'pass')
|
||||
ctx.buffer.set_document(document)
|
||||
|
@ -53,23 +55,25 @@ def test_dedent(ctx):
|
|||
assert ctx.buffer.document.current_line == ctx.indent
|
||||
|
||||
|
||||
@skip_if_lt_ptk2
|
||||
def test_nodedent(ctx):
|
||||
'''don't dedent if first line of ctx.buffer'''
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch('xonsh.ptk.key_bindings.can_compile', mock):
|
||||
with patch('xonsh.ptk2.key_bindings.can_compile', mock):
|
||||
document = Document('pass')
|
||||
ctx.buffer.set_document(document)
|
||||
ctx.cr(ctx.buffer, ctx.cli)
|
||||
assert ctx.accept.mock_calls is not None
|
||||
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch('xonsh.ptk.key_bindings.can_compile', mock):
|
||||
with patch('xonsh.ptk2.key_bindings.can_compile', mock):
|
||||
document = Document(ctx.indent+'pass')
|
||||
ctx.buffer.set_document(document)
|
||||
ctx.cr(ctx.buffer, ctx.cli)
|
||||
assert ctx.accept.mock_calls is not None
|
||||
|
||||
|
||||
@skip_if_lt_ptk2
|
||||
def test_continuation_line(ctx):
|
||||
document = Document('\nsecond line')
|
||||
ctx.buffer.set_document(document)
|
||||
|
@ -77,9 +81,10 @@ def test_continuation_line(ctx):
|
|||
assert ctx.buffer.document.current_line == ''
|
||||
|
||||
|
||||
@skip_if_lt_ptk2
|
||||
def test_trailing_slash(ctx):
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch('xonsh.ptk.key_bindings.can_compile', mock):
|
||||
with patch('xonsh.ptk2.key_bindings.can_compile', mock):
|
||||
document = Document('this line will \\')
|
||||
ctx.buffer.set_document(document)
|
||||
ctx.cr(ctx.buffer, ctx.cli)
|
||||
|
@ -89,18 +94,20 @@ def test_trailing_slash(ctx):
|
|||
assert ctx.accept.mock_calls is not None
|
||||
|
||||
|
||||
@skip_if_lt_ptk2
|
||||
def test_cant_compile_newline(ctx):
|
||||
mock = MagicMock(return_value=False)
|
||||
with patch('xonsh.ptk.key_bindings.can_compile', mock):
|
||||
with patch('xonsh.ptk2.key_bindings.can_compile', mock):
|
||||
document = Document('for i in (1, 2, ')
|
||||
ctx.buffer.set_document(document)
|
||||
ctx.cr(ctx.buffer, ctx.cli)
|
||||
assert ctx.buffer.document.current_line == ''
|
||||
|
||||
|
||||
@skip_if_lt_ptk2
|
||||
def test_can_compile_and_executes(ctx):
|
||||
mock = MagicMock(return_value=True)
|
||||
with patch('xonsh.ptk.key_bindings.can_compile', mock):
|
||||
with patch('xonsh.ptk2.key_bindings.can_compile', mock):
|
||||
document = Document('ls')
|
||||
ctx.buffer.set_document(document)
|
||||
ctx.cr(ctx.buffer, ctx.cli)
|
||||
|
|
|
@ -1,6 +1,5 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Tests the xonsh replay functionality."""
|
||||
from __future__ import unicode_literals, print_function
|
||||
import os
|
||||
import builtins
|
||||
|
||||
|
@ -21,7 +20,7 @@ def ctx():
|
|||
"""Create a global Shell instance to use in all the test."""
|
||||
ctx = {'PATH': []}
|
||||
execer = Execer(xonsh_ctx=ctx)
|
||||
builtins.__xonsh_shell__ = Shell(execer=execer, ctx=ctx)
|
||||
builtins.__xonsh_shell__ = Shell(execer=execer, ctx=ctx, shell_type='none')
|
||||
yield
|
||||
del builtins.__xonsh_shell__
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ import pytest
|
|||
|
||||
from xonsh.environ import Env
|
||||
from xonsh.base_shell import BaseShell
|
||||
from xonsh.platform import ptk_version_info
|
||||
|
||||
|
||||
VER_3_4 = (3, 4)
|
||||
|
@ -48,6 +49,9 @@ skip_if_on_darwin = pytest.mark.skipif(ON_DARWIN, reason='not Mac friendly')
|
|||
|
||||
skip_if_on_travis = pytest.mark.skipif(ON_TRAVIS, reason='not Travis CI friendly')
|
||||
|
||||
skip_if_lt_ptk2 = pytest.mark.skipif(ptk_version_info()[0] < 2,
|
||||
reason="prompt-tollkit <2")
|
||||
|
||||
|
||||
def sp(cmd):
|
||||
return subprocess.check_output(cmd, universal_newlines=True)
|
||||
|
|
|
@ -96,7 +96,7 @@ class Aliases(cabc.MutableMapping):
|
|||
cabc.Sequence):
|
||||
word_idx = line.find(word)
|
||||
expansion = ' '.join(self.get(word))
|
||||
line = line[:word_idx] + expansion + line[word_idx+len(word):]
|
||||
line = line[:word_idx] + expansion + line[word_idx + len(word):]
|
||||
return line
|
||||
|
||||
#
|
||||
|
@ -298,7 +298,7 @@ def source_alias(args, stdin=None):
|
|||
src += '\n'
|
||||
ctx = builtins.__xonsh_ctx__
|
||||
updates = {'__file__': fpath, '__name__': os.path.abspath(fpath)}
|
||||
with env.swap(ARGS=args[i+1:]), swap_values(ctx, updates):
|
||||
with env.swap(ARGS=args[i + 1:]), swap_values(ctx, updates):
|
||||
try:
|
||||
builtins.execx(src, 'exec', ctx, filename=fpath)
|
||||
except Exception:
|
||||
|
@ -455,7 +455,7 @@ def make_default_aliases():
|
|||
'xexec': xexec,
|
||||
'source': source_alias,
|
||||
'source-zsh': ['source-foreign', 'zsh', '--sourcer=source'],
|
||||
'source-bash': ['source-foreign', 'bash', '--sourcer=source'],
|
||||
'source-bash': ['source-foreign', 'bash', '--sourcer=source'],
|
||||
'source-cmd': source_cmd,
|
||||
'source-foreign': source_foreign,
|
||||
'history': xhm.history_main,
|
||||
|
|
|
@ -113,15 +113,15 @@ def _ansi_expand_style(cmap):
|
|||
if key == 'NO_COLOR':
|
||||
continue
|
||||
elif len(val) == 0:
|
||||
cmap['BOLD_'+key] = '1'
|
||||
cmap['UNDERLINE_'+key] = '4'
|
||||
cmap['BOLD_UNDERLINE_'+key] = '1;4'
|
||||
cmap['BACKGROUND_'+key] = val
|
||||
cmap['BOLD_' + key] = '1'
|
||||
cmap['UNDERLINE_' + key] = '4'
|
||||
cmap['BOLD_UNDERLINE_' + key] = '1;4'
|
||||
cmap['BACKGROUND_' + key] = val
|
||||
else:
|
||||
cmap['BOLD_'+key] = '1;' + val
|
||||
cmap['UNDERLINE_'+key] = '4;' + val
|
||||
cmap['BOLD_UNDERLINE_'+key] = '1;4;' + val
|
||||
cmap['BACKGROUND_'+key] = val.replace('38', '48', 1)
|
||||
cmap['BOLD_' + key] = '1;' + val
|
||||
cmap['UNDERLINE_' + key] = '4;' + val
|
||||
cmap['BOLD_UNDERLINE_' + key] = '1;4;' + val
|
||||
cmap['BACKGROUND_' + key] = val.replace('38', '48', 1)
|
||||
|
||||
|
||||
def _bw_style():
|
||||
|
@ -143,7 +143,7 @@ def _bw_style():
|
|||
'RED': '',
|
||||
'WHITE': '',
|
||||
'YELLOW': '',
|
||||
}
|
||||
}
|
||||
_ansi_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -242,7 +242,7 @@ def _default_style():
|
|||
'BACKGROUND_INTENSE_PURPLE': '0;105', # PURPLE
|
||||
'BACKGROUND_INTENSE_CYAN': '0;106', # CYAN
|
||||
'BACKGROUND_INTENSE_WHITE': '0;107', # WHITE
|
||||
}
|
||||
}
|
||||
return style
|
||||
|
||||
|
||||
|
@ -265,7 +265,7 @@ def _monokai_style():
|
|||
'INTENSE_RED': '38;5;197',
|
||||
'INTENSE_WHITE': '38;5;15',
|
||||
'INTENSE_YELLOW': '38;5;186',
|
||||
}
|
||||
}
|
||||
_ansi_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -293,7 +293,7 @@ def _algol_style():
|
|||
'RED': '38;5;09',
|
||||
'WHITE': '38;5;102',
|
||||
'YELLOW': '38;5;09',
|
||||
}
|
||||
}
|
||||
_ansi_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -317,7 +317,7 @@ def _algol_nu_style():
|
|||
'RED': '38;5;09',
|
||||
'WHITE': '38;5;102',
|
||||
'YELLOW': '38;5;09',
|
||||
}
|
||||
}
|
||||
_ansi_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -365,7 +365,7 @@ def _borland_style():
|
|||
'RED': '38;5;124',
|
||||
'WHITE': '38;5;145',
|
||||
'YELLOW': '38;5;124',
|
||||
}
|
||||
}
|
||||
_ansi_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -461,7 +461,7 @@ def _fruity_style():
|
|||
'RED': '38;5;09',
|
||||
'WHITE': '38;5;187',
|
||||
'YELLOW': '38;5;202',
|
||||
}
|
||||
}
|
||||
_ansi_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -485,7 +485,7 @@ def _igor_style():
|
|||
'RED': '38;5;166',
|
||||
'WHITE': '38;5;163',
|
||||
'YELLOW': '38;5;166',
|
||||
}
|
||||
}
|
||||
_ansi_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -509,7 +509,7 @@ def _lovelace_style():
|
|||
'RED': '38;5;124',
|
||||
'WHITE': '38;5;102',
|
||||
'YELLOW': '38;5;130',
|
||||
}
|
||||
}
|
||||
_ansi_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -533,7 +533,7 @@ def _manni_style():
|
|||
'RED': '38;5;124',
|
||||
'WHITE': '38;5;145',
|
||||
'YELLOW': '38;5;166',
|
||||
}
|
||||
}
|
||||
_ansi_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -557,7 +557,7 @@ def _murphy_style():
|
|||
'RED': '38;5;124',
|
||||
'WHITE': '38;5;145',
|
||||
'YELLOW': '38;5;166',
|
||||
}
|
||||
}
|
||||
_ansi_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -581,7 +581,7 @@ def _native_style():
|
|||
'RED': '38;5;124',
|
||||
'WHITE': '38;5;145',
|
||||
'YELLOW': '38;5;124',
|
||||
}
|
||||
}
|
||||
_ansi_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -605,7 +605,7 @@ def _paraiso_dark_style():
|
|||
'RED': '38;5;203',
|
||||
'WHITE': '38;5;79',
|
||||
'YELLOW': '38;5;214',
|
||||
}
|
||||
}
|
||||
_ansi_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -629,7 +629,7 @@ def _paraiso_light_style():
|
|||
'RED': '38;5;16',
|
||||
'WHITE': '38;5;102',
|
||||
'YELLOW': '38;5;214',
|
||||
}
|
||||
}
|
||||
_ansi_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -653,7 +653,7 @@ def _pastie_style():
|
|||
'RED': '38;5;124',
|
||||
'WHITE': '38;5;145',
|
||||
'YELLOW': '38;5;130',
|
||||
}
|
||||
}
|
||||
_ansi_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -677,7 +677,7 @@ def _perldoc_style():
|
|||
'RED': '38;5;124',
|
||||
'WHITE': '38;5;145',
|
||||
'YELLOW': '38;5;166',
|
||||
}
|
||||
}
|
||||
_ansi_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -701,7 +701,7 @@ def _rrt_style():
|
|||
'RED': '38;5;09',
|
||||
'WHITE': '38;5;117',
|
||||
'YELLOW': '38;5;09',
|
||||
}
|
||||
}
|
||||
_ansi_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -725,7 +725,7 @@ def _tango_style():
|
|||
'RED': '38;5;124',
|
||||
'WHITE': '38;5;15',
|
||||
'YELLOW': '38;5;94',
|
||||
}
|
||||
}
|
||||
_ansi_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -749,7 +749,7 @@ def _trac_style():
|
|||
'RED': '38;5;124',
|
||||
'WHITE': '38;5;145',
|
||||
'YELLOW': '38;5;100',
|
||||
}
|
||||
}
|
||||
_ansi_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -773,7 +773,7 @@ def _vim_style():
|
|||
'RED': '38;5;160',
|
||||
'WHITE': '38;5;188',
|
||||
'YELLOW': '38;5;160',
|
||||
}
|
||||
}
|
||||
_ansi_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -797,7 +797,7 @@ def _vs_style():
|
|||
'RED': '38;5;124',
|
||||
'WHITE': '38;5;31',
|
||||
'YELLOW': '38;5;124',
|
||||
}
|
||||
}
|
||||
_ansi_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -821,7 +821,7 @@ def _xcode_style():
|
|||
'RED': '38;5;160',
|
||||
'WHITE': '38;5;60',
|
||||
'YELLOW': '38;5;94',
|
||||
}
|
||||
}
|
||||
_ansi_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -853,13 +853,13 @@ ANSI_STYLES = LazyDict({
|
|||
'vim': _vim_style,
|
||||
'vs': _vs_style,
|
||||
'xcode': _xcode_style,
|
||||
}, globals(), 'ANSI_STYLES')
|
||||
}, globals(), 'ANSI_STYLES')
|
||||
|
||||
del (_algol_style, _algol_nu_style, _autumn_style, _borland_style, _bw_style,
|
||||
_colorful_style, _default_style, _emacs_style, _friendly_style,
|
||||
_fruity_style, _igor_style, _lovelace_style, _manni_style,
|
||||
_monokai_style, _murphy_style, _native_style, _paraiso_dark_style,
|
||||
_paraiso_light_style, _pastie_style, _perldoc_style, _rrt_style,
|
||||
_paraiso_light_style, _pastie_style, _perldoc_style, _rrt_style,
|
||||
_tango_style, _trac_style, _vim_style, _vs_style, _xcode_style)
|
||||
|
||||
|
||||
|
@ -872,13 +872,13 @@ def make_ansi_style(palette):
|
|||
for name, t in BASE_XONSH_COLORS.items():
|
||||
closest = find_closest_color(t, palette)
|
||||
if len(closest) == 3:
|
||||
closest = ''.join([a*2 for a in closest])
|
||||
closest = ''.join([a * 2 for a in closest])
|
||||
short = rgb2short(closest)[0]
|
||||
style[name] = '38;5;' + short
|
||||
style['BOLD_'+name] = '1;38;5;' + short
|
||||
style['UNDERLINE_'+name] = '4;38;5;' + short
|
||||
style['BOLD_UNDERLINE_'+name] = '1;4;38;5;' + short
|
||||
style['BACKGROUND_'+name] = '48;5;' + short
|
||||
style['BOLD_' + name] = '1;38;5;' + short
|
||||
style['UNDERLINE_' + name] = '4;38;5;' + short
|
||||
style['BOLD_UNDERLINE_' + name] = '1;4;38;5;' + short
|
||||
style['BACKGROUND_' + name] = '48;5;' + short
|
||||
return style
|
||||
|
||||
|
||||
|
|
|
@ -478,9 +478,9 @@ def pdump(s, **kwargs):
|
|||
closer = closers[openers.find(s[i])]
|
||||
j = s.rfind(closer)
|
||||
if j == -1 or j <= i:
|
||||
return s[:i+1] + '\n' + textwrap.indent(pdump(s[i+1:]), ' ')
|
||||
pre = s[:i+1] + '\n'
|
||||
mid = s[i+1:j]
|
||||
return s[:i + 1] + '\n' + textwrap.indent(pdump(s[i + 1:]), ' ')
|
||||
pre = s[:i + 1] + '\n'
|
||||
mid = s[i + 1:j]
|
||||
post = '\n' + s[j:]
|
||||
mid = textwrap.indent(pdump(mid), ' ')
|
||||
if '(' in post or '[' in post or '{' in post:
|
||||
|
|
|
@ -375,7 +375,7 @@ class BaseShell(object):
|
|||
rtn=info['rtn'],
|
||||
out=info.get('out', None),
|
||||
ts=info['ts']
|
||||
)
|
||||
)
|
||||
if hist is not None:
|
||||
hist.append(info)
|
||||
hist.last_cmd_rtn = hist.last_cmd_out = None
|
||||
|
@ -436,7 +436,7 @@ class BaseShell(object):
|
|||
self.reset_buffer()
|
||||
return src, code
|
||||
lincont = get_line_continuation()
|
||||
if src.endswith(lincont+'\n'):
|
||||
if src.endswith(lincont + '\n'):
|
||||
self.need_more_lines = True
|
||||
return src, None
|
||||
try:
|
||||
|
|
|
@ -22,7 +22,7 @@ def _splitpath(path, sofar=[]):
|
|||
|
||||
@lazyobject
|
||||
def _CHARACTER_MAP():
|
||||
cmap = {chr(o): '_%s' % chr(o+32) for o in range(65, 91)}
|
||||
cmap = {chr(o): '_%s' % chr(o + 32) for o in range(65, 91)}
|
||||
cmap.update({'.': '_.', '_': '__'})
|
||||
return cmap
|
||||
|
||||
|
|
|
@ -303,7 +303,7 @@ def CLUT():
|
|||
('253', 'dadada'),
|
||||
('254', 'e4e4e4'),
|
||||
('255', 'eeeeee'),
|
||||
]
|
||||
]
|
||||
|
||||
|
||||
def _str2hex(hexstr):
|
||||
|
@ -358,8 +358,8 @@ def rgb_to_256(rgb):
|
|||
res = []
|
||||
for part in parts:
|
||||
i = 0
|
||||
while i < len(incs)-1:
|
||||
s, b = incs[i], incs[i+1] # smaller, bigger
|
||||
while i < len(incs) - 1:
|
||||
s, b = incs[i], incs[i + 1] # smaller, bigger
|
||||
if s <= part <= b:
|
||||
s1 = abs(s - part)
|
||||
b1 = abs(b - part)
|
||||
|
@ -391,11 +391,11 @@ def rgb_to_ints(rgb):
|
|||
if len(rgb) == 6:
|
||||
return tuple([int(h, 16) for h in RE_RGB6.split(rgb)[1:4]])
|
||||
else:
|
||||
return tuple([int(h*2, 16) for h in RE_RGB3.split(rgb)[1:4]])
|
||||
return tuple([int(h * 2, 16) for h in RE_RGB3.split(rgb)[1:4]])
|
||||
|
||||
|
||||
def color_dist(x, y):
|
||||
return math.sqrt((x[0]-y[0])**2 + (x[1]-y[1])**2 + (x[2]-y[2])**2)
|
||||
return math.sqrt((x[0] - y[0])**2 + (x[1] - y[1])**2 + (x[2] - y[2])**2)
|
||||
|
||||
|
||||
def find_closest_color(x, palette):
|
||||
|
|
|
@ -41,6 +41,7 @@ class Completer(object):
|
|||
res = out
|
||||
lprefix = len(prefix)
|
||||
if res is not None and len(res) != 0:
|
||||
def sortkey(s): return s.lstrip(''''"''').lower()
|
||||
def sortkey(s):
|
||||
return s.lstrip(''''"''').lower()
|
||||
return tuple(sorted(res, key=sortkey)), lprefix
|
||||
return set(), lprefix
|
||||
|
|
|
@ -31,4 +31,4 @@ def default_completers():
|
|||
('import', complete_import),
|
||||
('python', complete_python),
|
||||
('path', complete_path),
|
||||
])
|
||||
])
|
||||
|
|
|
@ -110,9 +110,9 @@ def _dots(prefix):
|
|||
if slash == '\\':
|
||||
slash = ''
|
||||
if prefix in {'', '.'}:
|
||||
return ('.'+slash, '..'+slash)
|
||||
return ('.' + slash, '..' + slash)
|
||||
elif prefix == '..':
|
||||
return ('..'+slash,)
|
||||
return ('..' + slash,)
|
||||
else:
|
||||
return ()
|
||||
|
||||
|
|
|
@ -24,7 +24,7 @@ def XONSH_EXPR_TOKENS():
|
|||
'+', '-', '/', '//', '%', '**', '|', '&', '~', '^', '>>', '<<', '<',
|
||||
'<=', '>', '>=', '==', '!=', ',', '?', '??', '$(',
|
||||
'${', '$[', '...', '![', '!(', '@(', '@$(', '@',
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@xl.lazyobject
|
||||
|
@ -36,7 +36,7 @@ def XONSH_STMT_TOKENS():
|
|||
'yield ', '-', '/', '//', '%', '**', '|', '&', '~', '^', '>>', '<<',
|
||||
'<', '<=', '->', '=', '+=', '-=', '*=', '/=', '%=', '**=',
|
||||
'>>=', '<<=', '&=', '^=', '|=', '//=', ';', ':', '..',
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@xl.lazyobject
|
||||
|
@ -95,7 +95,7 @@ def complete_python_mode(prefix, line, start, end, ctx):
|
|||
if not (prefix.startswith('@(') or prefix.startswith('${')):
|
||||
return set()
|
||||
prefix_start = prefix[:2]
|
||||
python_matches = complete_python(prefix[2:], line, start-2, end-2, ctx)
|
||||
python_matches = complete_python(prefix[2:], line, start - 2, end - 2, ctx)
|
||||
if isinstance(python_matches, cabc.Sequence):
|
||||
python_matches = python_matches[0]
|
||||
return set(prefix_start + i for i in python_matches)
|
||||
|
|
|
@ -29,5 +29,5 @@ def justify(s, max_length, left_pad=0):
|
|||
characters long, padding all lines but the first on the left with the
|
||||
string left_pad.
|
||||
"""
|
||||
txt = textwrap.wrap(s, width=max_length, subsequent_indent=' '*left_pad)
|
||||
txt = textwrap.wrap(s, width=max_length, subsequent_indent=' ' * left_pad)
|
||||
return '\n'.join(txt)
|
||||
|
|
|
@ -405,7 +405,7 @@ def DEFAULT_DOCS():
|
|||
'AUTO_SUGGEST_IN_COMPLETIONS': VarDocs(
|
||||
'Places the auto-suggest result as the first option in the completions. '
|
||||
'This enables you to tab complete the auto-suggestion.'
|
||||
),
|
||||
),
|
||||
'BASH_COMPLETIONS': VarDocs(
|
||||
'This is a list (or tuple) of strings that specifies where the '
|
||||
'``bash_completion`` script may be found. '
|
||||
|
@ -614,7 +614,7 @@ def DEFAULT_DOCS():
|
|||
'Completions display is evaluated and presented whenever a key is '
|
||||
'pressed. This avoids the need to press TAB, except to cycle through '
|
||||
'the possibilities. This currently only affects the prompt-toolkit shell.'
|
||||
),
|
||||
),
|
||||
'UPDATE_OS_ENVIRON': VarDocs(
|
||||
"If True ``os_environ`` will always be updated "
|
||||
"when the xonsh environment changes. The environment can be reset to "
|
||||
|
|
|
@ -255,7 +255,7 @@ class EventManager:
|
|||
def _mkevent(name, species=Event, doc=None):
|
||||
# NOTE: Also used in `xonsh_events` test fixture
|
||||
# (A little bit of magic to enable docstrings to work right)
|
||||
return type(name, (species,), {'__doc__': doc, '__module__': 'xonsh.events', '__qualname__': 'events.'+name})()
|
||||
return type(name, (species,), {'__doc__': doc, '__module__': 'xonsh.events', '__qualname__': 'events.' + name})()
|
||||
|
||||
def transmogrify(self, name, species):
|
||||
"""
|
||||
|
|
|
@ -194,9 +194,9 @@ class Execer(object):
|
|||
input = '\n'.join(lines)
|
||||
continue
|
||||
|
||||
if last_error_line > 1 and lines[idx-1].rstrip()[-1:] == ':':
|
||||
if last_error_line > 1 and lines[idx - 1].rstrip()[-1:] == ':':
|
||||
# catch non-indented blocks and raise error.
|
||||
prev_indent = len(lines[idx-1]) - len(lines[idx-1].lstrip())
|
||||
prev_indent = len(lines[idx - 1]) - len(lines[idx - 1].lstrip())
|
||||
curr_indent = len(lines[idx]) - len(lines[idx].lstrip())
|
||||
if prev_indent == curr_indent:
|
||||
raise original_error
|
||||
|
|
|
@ -49,8 +49,8 @@ except ImportError:
|
|||
raise TypeError("expected __fspath__() to return str or bytes, "
|
||||
"not " + type(path).__name__)
|
||||
|
||||
raise TypeError("expected str, bytes or os.PathLike object, not "
|
||||
+ path_type.__name__)
|
||||
raise TypeError("expected str, bytes or os.PathLike object, not " +
|
||||
path_type.__name__)
|
||||
|
||||
def _fscodec():
|
||||
encoding = sys.getfilesystemencoding()
|
||||
|
|
|
@ -35,7 +35,7 @@ _object_init_docstring = LazyObject(lambda: object.__init__.__doc__,
|
|||
_builtin_type_docstrings = LazyObject(lambda: {
|
||||
t.__doc__
|
||||
for t in (types.ModuleType, types.MethodType, types.FunctionType)
|
||||
}, globals(), '_builtin_type_docstrings')
|
||||
}, globals(), '_builtin_type_docstrings')
|
||||
|
||||
_builtin_func_type = LazyObject(lambda: type(all), globals(),
|
||||
'_builtin_func_type')
|
||||
|
@ -50,7 +50,7 @@ info_fields = LazyObject(lambda: [
|
|||
# These won't be printed but will be used to determine how to
|
||||
# format the object
|
||||
'ismagic', 'isalias', 'isclass', 'argspec', 'found', 'name'
|
||||
], globals(), 'info_fields')
|
||||
], globals(), 'info_fields')
|
||||
|
||||
|
||||
def object_info(**kw):
|
||||
|
|
|
@ -73,7 +73,7 @@ class XonshKernel(Kernel):
|
|||
if n == 0:
|
||||
return
|
||||
lower = range(0, n, chunksize)
|
||||
upper = range(chunksize, n+chunksize, chunksize)
|
||||
upper = range(chunksize, n + chunksize, chunksize)
|
||||
for l, u in zip(lower, upper):
|
||||
response = {'name': name, 'text': s[l:u], }
|
||||
self.send_response(self.iopub_socket, 'stream', response)
|
||||
|
|
|
@ -42,7 +42,7 @@ class LazyObject(object):
|
|||
'load': load,
|
||||
'ctx': ctx,
|
||||
'name': name,
|
||||
}
|
||||
}
|
||||
|
||||
def _lazy_obj(self):
|
||||
d = self._lasdo
|
||||
|
@ -258,7 +258,7 @@ class BackgroundModuleProxy(types.ModuleType):
|
|||
self.__dct__ = {
|
||||
'loaded': False,
|
||||
'modname': modname,
|
||||
}
|
||||
}
|
||||
|
||||
def __getattribute__(self, name):
|
||||
passthrough = frozenset({'__dct__', '__class__', '__spec__'})
|
||||
|
|
|
@ -242,7 +242,7 @@ def special_handlers():
|
|||
(ERRORTOKEN, ' '): handle_error_space,
|
||||
(ERRORTOKEN, '\\\n'): handle_error_linecont,
|
||||
(ERRORTOKEN, '\\\r\n'): handle_error_linecont,
|
||||
}
|
||||
}
|
||||
_make_matcher_handler('(', 'LPAREN', True, ')', sh)
|
||||
_make_matcher_handler('[', 'LBRACKET', True, ']', sh)
|
||||
_make_matcher_handler('{', 'LBRACE', True, '}', sh)
|
||||
|
@ -426,6 +426,6 @@ class Lexer(object):
|
|||
'DOLLAR_LBRACKET', # $[
|
||||
'ATDOLLAR_LPAREN', # @$(
|
||||
'ERRORTOKEN', # whoops!
|
||||
) + tuple(i.upper() for i in kwmod.kwlist)
|
||||
) + tuple(i.upper() for i in kwmod.kwlist)
|
||||
self._tokens = t
|
||||
return self._tokens
|
||||
|
|
|
@ -167,7 +167,7 @@ def parser():
|
|||
'Possible options: readline, prompt_toolkit, random. '
|
||||
'Warning! If set this overrides $SHELL_TYPE variable.',
|
||||
dest='shell_type',
|
||||
choices=('readline', 'prompt_toolkit', 'best', 'random'),
|
||||
choices=tuple(Shell.shell_type_aliases.keys()),
|
||||
default=None)
|
||||
p.add_argument('--timings',
|
||||
help='Prints timing information before the prompt is shown. '
|
||||
|
|
|
@ -2197,7 +2197,7 @@ class BaseParser(object):
|
|||
pass
|
||||
elif isinstance(p1, ast.Slice) or \
|
||||
any([isinstance(x, ast.Slice) for x in p2]):
|
||||
p1 = ast.ExtSlice(dims=[p1]+p2)
|
||||
p1 = ast.ExtSlice(dims=[p1] + p2)
|
||||
else:
|
||||
p1.value = ast.Tuple(elts=[p1.value] + [x.value for x in p2],
|
||||
ctx=ast.Load(), lineno=p1.lineno,
|
||||
|
|
|
@ -146,6 +146,15 @@ def ptk_above_min_supported():
|
|||
return ptk_version_info()[:2] >= minimum_required_ptk_version
|
||||
|
||||
|
||||
@functools.lru_cache(1)
|
||||
def ptk_shell_type():
|
||||
"""Returns the prompt_toolkit shell type based on the installed version."""
|
||||
if ptk_version_info()[:2] < (2, 0):
|
||||
return 'prompt_toolkit1'
|
||||
else:
|
||||
return 'prompt_toolkit2'
|
||||
|
||||
|
||||
@functools.lru_cache(1)
|
||||
def ptk_below_max_supported():
|
||||
ptk_max_version_cutoff = (2, 0)
|
||||
|
@ -181,7 +190,7 @@ def pathsplit(p):
|
|||
without a drive.
|
||||
"""
|
||||
n = len(p)
|
||||
while n and p[n-1] not in seps:
|
||||
while n and p[n - 1] not in seps:
|
||||
n -= 1
|
||||
pre = p[:n]
|
||||
pre = pre.rstrip(seps) or pre
|
||||
|
@ -274,14 +283,14 @@ if PYTHON_VERSION_INFO < (3, 5, 0):
|
|||
return self.__path__.is_dir()
|
||||
else:
|
||||
return not self.__path__.is_symlink() \
|
||||
and self.__path__.is_dir()
|
||||
and self.__path__.is_dir()
|
||||
|
||||
def is_file(self, *, follow_symlinks=True):
|
||||
if follow_symlinks:
|
||||
return self.__path__.is_file()
|
||||
else:
|
||||
return not self.__path__.is_symlink() \
|
||||
and self.__path__.is_file()
|
||||
and self.__path__.is_file()
|
||||
|
||||
def stat(self, *, follow_symlinks=True):
|
||||
return os.stat(self.path, follow_symlinks=follow_symlinks)
|
||||
|
|
|
@ -802,8 +802,7 @@ def for_type_by_name(type_module, type_name, func, dtp=None):
|
|||
#: printers for the default singletons
|
||||
_singleton_pprinters = LazyObject(lambda: dict.fromkeys(
|
||||
map(id, [None, True, False, Ellipsis,
|
||||
NotImplemented]), _repr_pprint),
|
||||
globals(), '_singleton_pprinters')
|
||||
NotImplemented]), _repr_pprint), globals(), '_singleton_pprinters')
|
||||
|
||||
|
||||
def _defaultdict_pprint(obj, p, cycle):
|
||||
|
|
|
@ -96,9 +96,9 @@ class QueueReader:
|
|||
"""Returns whether or not the queue is fully read and the reader is
|
||||
closed.
|
||||
"""
|
||||
return (self.closed
|
||||
and (self.thread is None or not self.thread.is_alive())
|
||||
and self.queue.empty())
|
||||
return (self.closed and
|
||||
(self.thread is None or not self.thread.is_alive()) and
|
||||
self.queue.empty())
|
||||
|
||||
def read_queue(self):
|
||||
"""Reads a single chunk from the queue. This is blocking if
|
||||
|
@ -272,7 +272,7 @@ def _expand_console_buffer(cols, max_offset, expandsize, orig_posize, fd):
|
|||
# expand it so that we can read from it successfully.
|
||||
if cols == 0:
|
||||
return orig_posize[-1], max_offset, orig_posize
|
||||
rows = ((max_offset + expandsize)//cols) + 1
|
||||
rows = ((max_offset + expandsize) // cols) + 1
|
||||
winutils.set_console_screen_buffer_size(cols, rows, fd=fd)
|
||||
orig_posize = orig_posize[:3] + (rows,)
|
||||
max_offset = (rows - 1) * cols
|
||||
|
@ -328,7 +328,7 @@ def populate_console(reader, fd, buffer, chunksize, queue, expandsize=None):
|
|||
x, y, cols, rows = posize = winutils.get_position_size(fd)
|
||||
pre_x = pre_y = -1
|
||||
orig_posize = posize
|
||||
offset = (cols*y) + x
|
||||
offset = (cols * y) + x
|
||||
max_offset = (rows - 1) * cols
|
||||
# I believe that there is a bug in PTK that if we reset the
|
||||
# cursor position, the cursor on the next prompt is accidentally on
|
||||
|
@ -340,7 +340,7 @@ def populate_console(reader, fd, buffer, chunksize, queue, expandsize=None):
|
|||
# winutils.set_console_cursor_position(x, y, fd=fd)
|
||||
while True:
|
||||
posize = winutils.get_position_size(fd)
|
||||
offset = (cols*y) + x
|
||||
offset = (cols * y) + x
|
||||
if ((posize[1], posize[0]) <= (y, x) and posize[2:] == (cols, rows)) or \
|
||||
(pre_x == x and pre_y == y):
|
||||
# already at or ahead of the current cursor position.
|
||||
|
@ -382,11 +382,11 @@ def populate_console(reader, fd, buffer, chunksize, queue, expandsize=None):
|
|||
time.sleep(reader.timeout)
|
||||
continue
|
||||
cur_x, cur_y = posize[0], posize[1]
|
||||
cur_offset = (cols*cur_y) + cur_x
|
||||
beg_offset = (cols*y) + x
|
||||
cur_offset = (cols * cur_y) + cur_x
|
||||
beg_offset = (cols * y) + x
|
||||
end_offset = beg_offset + nread
|
||||
if end_offset > cur_offset and cur_offset != max_offset:
|
||||
buf = buf[:cur_offset-end_offset]
|
||||
buf = buf[:cur_offset - end_offset]
|
||||
# convert to lines
|
||||
xshift = cols - x
|
||||
yshift = (nread // cols) + (1 if nread % cols > 0 else 0)
|
||||
|
@ -895,7 +895,7 @@ class PopenThread(threading.Thread):
|
|||
if s is None:
|
||||
rtn = self.returncode
|
||||
if rtn is not None and rtn != 0:
|
||||
s = (-1*rtn, rtn < 0 if ON_WINDOWS else os.WCOREDUMP(rtn))
|
||||
s = (-1 * rtn, rtn < 0 if ON_WINDOWS else os.WCOREDUMP(rtn))
|
||||
return s
|
||||
|
||||
@signal.setter
|
||||
|
@ -1345,15 +1345,14 @@ class ProcProxyThread(threading.Thread):
|
|||
# run the function itself
|
||||
try:
|
||||
with STDOUT_DISPATCHER.register(sp_stdout), \
|
||||
STDERR_DISPATCHER.register(sp_stderr), \
|
||||
redirect_stdout(STDOUT_DISPATCHER), \
|
||||
redirect_stderr(STDERR_DISPATCHER):
|
||||
STDERR_DISPATCHER.register(sp_stderr), \
|
||||
redirect_stdout(STDOUT_DISPATCHER), \
|
||||
redirect_stderr(STDERR_DISPATCHER):
|
||||
r = self.f(self.args, sp_stdin, sp_stdout, sp_stderr, spec)
|
||||
except SystemExit as e:
|
||||
r = e.code if isinstance(e.code, int) else int(bool(e.code))
|
||||
except OSError as e:
|
||||
status = still_writable(self.c2pwrite) and \
|
||||
still_writable(self.errwrite)
|
||||
status = still_writable(self.c2pwrite) and still_writable(self.errwrite)
|
||||
if status:
|
||||
# stdout and stderr are still writable, so error must
|
||||
# come from function itself.
|
||||
|
@ -1671,13 +1670,13 @@ def SIGNAL_MESSAGES():
|
|||
signal.SIGILL: 'Illegal instructions',
|
||||
signal.SIGTERM: 'Terminated',
|
||||
signal.SIGSEGV: 'Segmentation fault',
|
||||
}
|
||||
}
|
||||
if ON_POSIX:
|
||||
sm.update({
|
||||
signal.SIGQUIT: 'Quit',
|
||||
signal.SIGHUP: 'Hangup',
|
||||
signal.SIGKILL: 'Killed',
|
||||
})
|
||||
})
|
||||
return sm
|
||||
|
||||
|
||||
|
@ -1811,8 +1810,8 @@ class CommandPipeline:
|
|||
timeout = builtins.__xonsh_env__.get('XONSH_PROC_FREQUENCY')
|
||||
# get the correct stdout
|
||||
stdout = proc.stdout
|
||||
if ((stdout is None or spec.stdout is None or not safe_readable(stdout))
|
||||
and spec.captured_stdout is not None):
|
||||
if ((stdout is None or spec.stdout is None or not safe_readable(stdout)) and
|
||||
spec.captured_stdout is not None):
|
||||
stdout = spec.captured_stdout
|
||||
if hasattr(stdout, 'buffer'):
|
||||
stdout = stdout.buffer
|
||||
|
@ -1841,8 +1840,8 @@ class CommandPipeline:
|
|||
return
|
||||
# get the correct stderr
|
||||
stderr = proc.stderr
|
||||
if ((stderr is None or spec.stderr is None or not safe_readable(stderr))
|
||||
and spec.captured_stderr is not None):
|
||||
if ((stderr is None or spec.stderr is None or not safe_readable(stderr)) and
|
||||
spec.captured_stderr is not None):
|
||||
stderr = spec.captured_stderr
|
||||
if hasattr(stderr, 'buffer'):
|
||||
stderr = stderr.buffer
|
||||
|
|
|
@ -66,7 +66,7 @@ def _dynamically_collapsed_pwd():
|
|||
max(1, remaining_space_for_text // (len(pwd) - i))))
|
||||
remaining_space_for_text -= part_len
|
||||
if len(part) > part_len:
|
||||
reduced_part = part[0:part_len-len(elision_char)] + elision_char
|
||||
reduced_part = part[0:part_len - len(elision_char)] + elision_char
|
||||
parts.append(reduced_part)
|
||||
else:
|
||||
parts.append(part)
|
||||
|
|
|
@ -86,13 +86,13 @@ def _get_stash(gitdir):
|
|||
|
||||
def _gitoperation(gitdir):
|
||||
files = (
|
||||
('rebase-merge', 'REBASE'),
|
||||
('rebase-apply', 'AM/REBASE'),
|
||||
('MERGE_HEAD', 'MERGING'),
|
||||
('CHERRY_PICK_HEAD', 'CHERRY-PICKING'),
|
||||
('REVERT_HEAD', 'REVERTING'),
|
||||
('BISECT_LOG', 'BISECTING'),
|
||||
)
|
||||
('rebase-merge', 'REBASE'),
|
||||
('rebase-apply', 'AM/REBASE'),
|
||||
('MERGE_HEAD', 'MERGING'),
|
||||
('CHERRY_PICK_HEAD', 'CHERRY-PICKING'),
|
||||
('REVERT_HEAD', 'REVERTING'),
|
||||
('BISECT_LOG', 'BISECTING'),
|
||||
)
|
||||
return [f[1] for f in files
|
||||
if os.path.exists(os.path.join(gitdir, f[0]))]
|
||||
|
||||
|
|
|
@ -29,7 +29,7 @@ class PromptToolkitCompleter(Completer):
|
|||
should_complete = (
|
||||
complete_event.completion_requested or
|
||||
env.get('UPDATE_COMPLETIONS_ON_KEYPRESS')
|
||||
)
|
||||
)
|
||||
# Only generate completions when the user hits tab.
|
||||
if not should_complete or self.completer is None:
|
||||
return
|
||||
|
|
|
@ -149,9 +149,9 @@ def whitespace_or_bracket_before(cli):
|
|||
"""Check if there is whitespace or an opening
|
||||
bracket to the left of the cursor"""
|
||||
d = cli.current_buffer.document
|
||||
return bool(d.cursor_position == 0
|
||||
or d.char_before_cursor.isspace()
|
||||
or d.char_before_cursor in '([{')
|
||||
return bool(d.cursor_position == 0 or
|
||||
d.char_before_cursor.isspace() or
|
||||
d.char_before_cursor in '([{')
|
||||
|
||||
|
||||
@Condition
|
||||
|
@ -159,9 +159,9 @@ def whitespace_or_bracket_after(cli):
|
|||
"""Check if there is whitespace or a closing
|
||||
bracket to the right of the cursor"""
|
||||
d = cli.current_buffer.document
|
||||
return bool(d.is_cursor_at_the_end_of_line
|
||||
or d.current_char.isspace()
|
||||
or d.current_char in ')]}')
|
||||
return bool(d.is_cursor_at_the_end_of_line or
|
||||
d.current_char.isspace() or
|
||||
d.current_char in ')]}')
|
||||
|
||||
|
||||
def load_xonsh_bindings(key_bindings_manager):
|
||||
|
|
|
@ -46,7 +46,7 @@ class PromptToolkitShell(BaseShell):
|
|||
'enable_auto_suggest_bindings': True,
|
||||
'enable_search': True,
|
||||
'enable_abort_and_exit_bindings': True,
|
||||
}
|
||||
}
|
||||
self.key_bindings_manager = KeyBindingManager(**key_bindings_manager_args)
|
||||
load_xonsh_bindings(self.key_bindings_manager)
|
||||
# This assumes that PromptToolkitShell is a singleton
|
||||
|
@ -218,11 +218,11 @@ class PromptToolkitShell(BaseShell):
|
|||
dots = builtins.__xonsh_env__.get('MULTILINE_PROMPT')
|
||||
dots = dots() if callable(dots) else dots
|
||||
if dots is None:
|
||||
return [(Token, ' '*(width + 1))]
|
||||
return [(Token, ' ' * (width + 1))]
|
||||
basetoks = self.format_color(dots)
|
||||
baselen = sum(len(t[1]) for t in basetoks)
|
||||
if baselen == 0:
|
||||
return [(Token, ' '*(width + 1))]
|
||||
return [(Token, ' ' * (width + 1))]
|
||||
toks = basetoks * (width // baselen)
|
||||
n = width % baselen
|
||||
count = 0
|
||||
|
@ -234,7 +234,7 @@ class PromptToolkitShell(BaseShell):
|
|||
elif newcount <= n:
|
||||
toks.append(tok)
|
||||
else:
|
||||
toks.append((tok[0], tok[1][:n-count]))
|
||||
toks.append((tok[0], tok[1][:n - count]))
|
||||
count = newcount
|
||||
if n <= count:
|
||||
break
|
||||
|
|
5
xonsh/ptk2/__init__.py
Normal file
5
xonsh/ptk2/__init__.py
Normal file
|
@ -0,0 +1,5 @@
|
|||
# must come before ptk / pygments imports
|
||||
from xonsh.lazyasd import load_module_in_background
|
||||
|
||||
load_module_in_background('pkg_resources', debug='XONSH_DEBUG',
|
||||
replacements={'pygments.plugin': 'pkg_resources'})
|
110
xonsh/ptk2/completer.py
Normal file
110
xonsh/ptk2/completer.py
Normal file
|
@ -0,0 +1,110 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Completer implementation to use with prompt_toolkit."""
|
||||
import os
|
||||
import builtins
|
||||
|
||||
from prompt_toolkit.layout.dimension import LayoutDimension
|
||||
from prompt_toolkit.completion import Completer, Completion
|
||||
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
|
||||
|
||||
|
||||
class PromptToolkitCompleter(Completer):
|
||||
"""Simple prompt_toolkit Completer object.
|
||||
|
||||
It just redirects requests to normal Xonsh completer.
|
||||
"""
|
||||
|
||||
def __init__(self, completer, ctx, shell):
|
||||
"""Takes instance of xonsh.completer.Completer, the xonsh execution
|
||||
context, and the shell instance itself.
|
||||
"""
|
||||
self.completer = completer
|
||||
self.ctx = ctx
|
||||
self.shell = shell
|
||||
self.hist_suggester = AutoSuggestFromHistory()
|
||||
|
||||
def get_completions(self, document, complete_event):
|
||||
"""Returns a generator for list of completions."""
|
||||
env = builtins.__xonsh_env__
|
||||
should_complete = (
|
||||
complete_event.completion_requested or
|
||||
env.get('UPDATE_COMPLETIONS_ON_KEYPRESS')
|
||||
)
|
||||
# Only generate completions when the user hits tab.
|
||||
if not should_complete or self.completer is None:
|
||||
return
|
||||
# generate actual completions
|
||||
line = document.current_line.lstrip()
|
||||
line_ex = builtins.aliases.expand_alias(line)
|
||||
|
||||
endidx = document.cursor_position_col
|
||||
begidx = (line[:endidx].rfind(' ') + 1
|
||||
if line[:endidx].rfind(' ') >= 0 else 0)
|
||||
prefix = line[begidx:endidx]
|
||||
expand_offset = len(line_ex) - len(line)
|
||||
# get normal completions
|
||||
completions, l = self.completer.complete(prefix, line_ex,
|
||||
begidx + expand_offset,
|
||||
endidx + expand_offset,
|
||||
self.ctx)
|
||||
# completions from auto suggest
|
||||
sug_comp = None
|
||||
if env.get('AUTO_SUGGEST') and env.get('AUTO_SUGGEST_IN_COMPLETIONS'):
|
||||
sug_comp = self.suggestion_completion(document, line)
|
||||
if sug_comp is None:
|
||||
pass
|
||||
elif len(completions) == 0:
|
||||
completions = (sug_comp,)
|
||||
else:
|
||||
completions = set(completions)
|
||||
completions.discard(sug_comp)
|
||||
completions = (sug_comp,) + tuple(sorted(completions))
|
||||
# reserve space, if needed.
|
||||
if len(completions) <= 1:
|
||||
pass
|
||||
elif len(os.path.commonprefix(completions)) <= len(prefix):
|
||||
self.reserve_space()
|
||||
# Find common prefix (strip quoting)
|
||||
c_prefix = os.path.commonprefix([a.strip('\'"') for a in completions])
|
||||
# Find last split symbol, do not trim the last part
|
||||
while c_prefix:
|
||||
if c_prefix[-1] in r'/\.:@,':
|
||||
break
|
||||
c_prefix = c_prefix[:-1]
|
||||
# yield completions
|
||||
if sug_comp is None:
|
||||
pre = min(document.cursor_position_col - begidx, len(c_prefix))
|
||||
else:
|
||||
pre = len(c_prefix)
|
||||
for comp in completions:
|
||||
# do not display quote
|
||||
disp = comp[pre:].strip('\'"')
|
||||
yield Completion(comp, -l, display=disp)
|
||||
|
||||
def suggestion_completion(self, document, line):
|
||||
"""Provides a completion based on the current auto-suggestion."""
|
||||
app = self.shell.prompter.app
|
||||
sug = self.hist_suggester.get_suggestion(app.current_buffer, document)
|
||||
if sug is None:
|
||||
return None
|
||||
comp, _, _ = sug.text.partition(' ')
|
||||
_, _, prev = line.rpartition(' ')
|
||||
return prev + comp
|
||||
|
||||
def reserve_space(self):
|
||||
app = builtins.__xonsh_shell__.shell.prompter.app
|
||||
window = app.layout.container.children[0].content.children[1].content
|
||||
|
||||
if window and window.render_info:
|
||||
h = window.render_info.content_height
|
||||
r = builtins.__xonsh_env__.get('COMPLETIONS_MENU_ROWS')
|
||||
size = h + r
|
||||
|
||||
def comp_height(cli):
|
||||
# If there is an autocompletion menu to be shown, make sure that o
|
||||
# layout has at least a minimal height in order to display it.
|
||||
if not cli.is_done:
|
||||
return LayoutDimension(min=size)
|
||||
else:
|
||||
return LayoutDimension()
|
||||
window._height = comp_height
|
41
xonsh/ptk2/history.py
Normal file
41
xonsh/ptk2/history.py
Normal file
|
@ -0,0 +1,41 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""History object for use with prompt_toolkit."""
|
||||
import builtins
|
||||
|
||||
import prompt_toolkit.history
|
||||
|
||||
|
||||
class PromptToolkitHistory(prompt_toolkit.history.History):
|
||||
"""History class that implements the prompt-toolkit history interface
|
||||
with the xonsh backend.
|
||||
"""
|
||||
|
||||
def __init__(self, load_prev=True, *args, **kwargs):
|
||||
"""Initialize history object."""
|
||||
super().__init__()
|
||||
self.load_prev = load_prev
|
||||
|
||||
def store_string(self, entry):
|
||||
pass
|
||||
|
||||
def load_history_strings(self):
|
||||
"""Loads synchronous history strings"""
|
||||
if not self.load_prev:
|
||||
return
|
||||
hist = builtins.__xonsh_history__
|
||||
if hist is None:
|
||||
return
|
||||
for cmd in hist.all_items():
|
||||
line = cmd['inp'].rstrip()
|
||||
strs = self.get_strings()
|
||||
if len(strs) == 0 or line != strs[-1]:
|
||||
yield line
|
||||
|
||||
def __getitem__(self, index):
|
||||
return self.get_strings()[index]
|
||||
|
||||
def __len__(self):
|
||||
return len(self.get_strings())
|
||||
|
||||
def __iter__(self):
|
||||
return iter(self.get_strings())
|
371
xonsh/ptk2/key_bindings.py
Normal file
371
xonsh/ptk2/key_bindings.py
Normal file
|
@ -0,0 +1,371 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""Key bindings for prompt_toolkit xonsh shell."""
|
||||
import builtins
|
||||
|
||||
from prompt_toolkit.enums import DEFAULT_BUFFER
|
||||
from prompt_toolkit.filters import (Condition, IsMultiline, HasSelection,
|
||||
EmacsInsertMode, ViInsertMode)
|
||||
from prompt_toolkit.keys import Keys
|
||||
from prompt_toolkit.application.current import get_app
|
||||
|
||||
from xonsh.aliases import xonsh_exit
|
||||
from xonsh.tools import check_for_partial_string, get_line_continuation
|
||||
from xonsh.shell import transform_command
|
||||
|
||||
env = builtins.__xonsh_env__
|
||||
DEDENT_TOKENS = frozenset(['raise', 'return', 'pass', 'break', 'continue'])
|
||||
|
||||
|
||||
def carriage_return(b, cli, *, autoindent=True):
|
||||
"""Preliminary parser to determine if 'Enter' key should send command to the
|
||||
xonsh parser for execution or should insert a newline for continued input.
|
||||
|
||||
Current 'triggers' for inserting a newline are:
|
||||
- Not on first line of buffer and line is non-empty
|
||||
- Previous character is a colon (covers if, for, etc...)
|
||||
- User is in an open paren-block
|
||||
- Line ends with backslash
|
||||
- Any text exists below cursor position (relevant when editing previous
|
||||
multiline blocks)
|
||||
"""
|
||||
doc = b.document
|
||||
at_end_of_line = _is_blank(doc.current_line_after_cursor)
|
||||
current_line_blank = _is_blank(doc.current_line)
|
||||
|
||||
indent = env.get('INDENT') if autoindent else ''
|
||||
|
||||
partial_string_info = check_for_partial_string(doc.text)
|
||||
in_partial_string = (partial_string_info[0] is not None and
|
||||
partial_string_info[1] is None)
|
||||
|
||||
# indent after a colon
|
||||
if (doc.current_line_before_cursor.strip().endswith(':') and
|
||||
at_end_of_line):
|
||||
b.newline(copy_margin=autoindent)
|
||||
b.insert_text(indent, fire_event=False)
|
||||
# if current line isn't blank, check dedent tokens
|
||||
elif (not current_line_blank and
|
||||
doc.current_line.split(maxsplit=1)[0] in DEDENT_TOKENS and
|
||||
doc.line_count > 1):
|
||||
b.newline(copy_margin=autoindent)
|
||||
b.delete_before_cursor(count=len(indent))
|
||||
elif (not doc.on_first_line and not current_line_blank):
|
||||
b.newline(copy_margin=autoindent)
|
||||
elif (doc.current_line.endswith(get_line_continuation())):
|
||||
b.newline(copy_margin=autoindent)
|
||||
elif (doc.find_next_word_beginning() is not None and
|
||||
(any(not _is_blank(i) for i in doc.lines_from_current[1:]))):
|
||||
b.newline(copy_margin=autoindent)
|
||||
elif not current_line_blank and not can_compile(doc.text):
|
||||
b.newline(copy_margin=autoindent)
|
||||
elif current_line_blank and in_partial_string:
|
||||
b.newline(copy_margin=autoindent)
|
||||
else:
|
||||
try:
|
||||
b.accept_action.validate_and_handle(cli, b)
|
||||
except AttributeError: # PTK 2.0
|
||||
b.validate_and_handle()
|
||||
|
||||
|
||||
def _is_blank(l):
|
||||
return len(l.strip()) == 0
|
||||
|
||||
|
||||
def can_compile(src):
|
||||
"""Returns whether the code can be compiled, i.e. it is valid xonsh."""
|
||||
src = src if src.endswith('\n') else src + '\n'
|
||||
src = transform_command(src, show_diff=False)
|
||||
src = src.lstrip()
|
||||
try:
|
||||
builtins.__xonsh_execer__.compile(src, mode='single', glbs=None,
|
||||
locs=builtins.__xonsh_ctx__)
|
||||
rtn = True
|
||||
except SyntaxError:
|
||||
rtn = False
|
||||
except Exception:
|
||||
rtn = True
|
||||
return rtn
|
||||
|
||||
|
||||
@Condition
|
||||
def tab_insert_indent():
|
||||
"""Check if <Tab> should insert indent instead of starting autocompletion.
|
||||
Checks if there are only whitespaces before the cursor - if so indent
|
||||
should be inserted, otherwise autocompletion.
|
||||
|
||||
"""
|
||||
before_cursor = get_app().current_buffer.document.current_line_before_cursor
|
||||
|
||||
return bool(before_cursor.isspace())
|
||||
|
||||
|
||||
@Condition
|
||||
def beginning_of_line():
|
||||
"""Check if cursor is at beginning of a line other than the first line in a
|
||||
multiline document
|
||||
"""
|
||||
app = get_app()
|
||||
before_cursor = app.current_buffer.document.current_line_before_cursor
|
||||
|
||||
return bool(len(before_cursor) == 0 and
|
||||
not app.current_buffer.document.on_first_line)
|
||||
|
||||
|
||||
@Condition
|
||||
def end_of_line():
|
||||
"""Check if cursor is at the end of a line other than the last line in a
|
||||
multiline document
|
||||
"""
|
||||
d = get_app().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)
|
||||
|
||||
|
||||
@Condition
|
||||
def should_confirm_completion():
|
||||
"""Check if completion needs confirmation"""
|
||||
return (builtins.__xonsh_env__.get('COMPLETIONS_CONFIRM') and
|
||||
get_app().current_buffer.complete_state)
|
||||
|
||||
|
||||
# Copied from prompt-toolkit's key_binding/bindings/basic.py
|
||||
@Condition
|
||||
def ctrl_d_condition():
|
||||
"""Ctrl-D binding is only active when the default buffer is selected and
|
||||
empty.
|
||||
"""
|
||||
if builtins.__xonsh_env__.get("IGNOREEOF"):
|
||||
raise EOFError
|
||||
else:
|
||||
app = get_app()
|
||||
try:
|
||||
buffer_name = app.current_buffer_name
|
||||
except AttributeError: # PTK 2.0
|
||||
buffer_name = app.current_buffer.name
|
||||
|
||||
return buffer_name == DEFAULT_BUFFER and not app.current_buffer.text
|
||||
|
||||
|
||||
@Condition
|
||||
def autopair_condition():
|
||||
"""Check if XONSH_AUTOPAIR is set"""
|
||||
return builtins.__xonsh_env__.get("XONSH_AUTOPAIR", False)
|
||||
|
||||
|
||||
@Condition
|
||||
def whitespace_or_bracket_before():
|
||||
"""Check if there is whitespace or an opening
|
||||
bracket to the left of the cursor"""
|
||||
d = get_app().current_buffer.document
|
||||
return bool(d.cursor_position == 0 or
|
||||
d.char_before_cursor.isspace() or
|
||||
d.char_before_cursor in '([{')
|
||||
|
||||
|
||||
@Condition
|
||||
def whitespace_or_bracket_after():
|
||||
"""Check if there is whitespace or a closing
|
||||
bracket to the right of the cursor"""
|
||||
d = get_app().current_buffer.document
|
||||
return bool(d.is_cursor_at_the_end_of_line or
|
||||
d.current_char.isspace() or
|
||||
d.current_char in ')]}')
|
||||
|
||||
|
||||
def load_xonsh_bindings(key_bindings):
|
||||
"""
|
||||
Load custom key bindings.
|
||||
"""
|
||||
handle = key_bindings.add
|
||||
has_selection = HasSelection()
|
||||
insert_mode = ViInsertMode() | EmacsInsertMode()
|
||||
|
||||
@handle(Keys.Tab, filter=tab_insert_indent)
|
||||
def insert_indent(event):
|
||||
"""
|
||||
If there are only whitespaces before current cursor position insert
|
||||
indent instead of autocompleting.
|
||||
"""
|
||||
event.cli.current_buffer.insert_text(env.get('INDENT'))
|
||||
|
||||
@handle(Keys.ControlX, Keys.ControlE, filter=~has_selection)
|
||||
def open_editor(event):
|
||||
""" Open current buffer in editor """
|
||||
event.current_buffer.open_in_editor(event.cli)
|
||||
|
||||
@handle(Keys.BackTab, filter=insert_mode)
|
||||
def insert_literal_tab(event):
|
||||
""" Insert literal tab on Shift+Tab instead of autocompleting """
|
||||
b = event.current_buffer
|
||||
if b.complete_state:
|
||||
b.complete_previous()
|
||||
else:
|
||||
event.cli.current_buffer.insert_text(env.get('INDENT'))
|
||||
|
||||
@handle('(', filter=autopair_condition & whitespace_or_bracket_after)
|
||||
def insert_right_parens(event):
|
||||
event.cli.current_buffer.insert_text('(')
|
||||
event.cli.current_buffer.insert_text(')', move_cursor=False)
|
||||
|
||||
@handle(')', filter=autopair_condition)
|
||||
def overwrite_right_parens(event):
|
||||
buffer = event.cli.current_buffer
|
||||
if buffer.document.current_char == ')':
|
||||
buffer.cursor_position += 1
|
||||
else:
|
||||
buffer.insert_text(')')
|
||||
|
||||
@handle('[', filter=autopair_condition & whitespace_or_bracket_after)
|
||||
def insert_right_bracket(event):
|
||||
event.cli.current_buffer.insert_text('[')
|
||||
event.cli.current_buffer.insert_text(']', move_cursor=False)
|
||||
|
||||
@handle(']', filter=autopair_condition)
|
||||
def overwrite_right_bracket(event):
|
||||
buffer = event.cli.current_buffer
|
||||
|
||||
if buffer.document.current_char == ']':
|
||||
buffer.cursor_position += 1
|
||||
else:
|
||||
buffer.insert_text(']')
|
||||
|
||||
@handle('{', filter=autopair_condition & whitespace_or_bracket_after)
|
||||
def insert_right_brace(event):
|
||||
event.cli.current_buffer.insert_text('{')
|
||||
event.cli.current_buffer.insert_text('}', move_cursor=False)
|
||||
|
||||
@handle('}', filter=autopair_condition)
|
||||
def overwrite_right_brace(event):
|
||||
buffer = event.cli.current_buffer
|
||||
|
||||
if buffer.document.current_char == '}':
|
||||
buffer.cursor_position += 1
|
||||
else:
|
||||
buffer.insert_text('}')
|
||||
|
||||
@handle('\'', filter=autopair_condition)
|
||||
def insert_right_quote(event):
|
||||
buffer = event.cli.current_buffer
|
||||
|
||||
if buffer.document.current_char == '\'':
|
||||
buffer.cursor_position += 1
|
||||
elif whitespace_or_bracket_before(event.cli)\
|
||||
and whitespace_or_bracket_after(event.cli):
|
||||
buffer.insert_text('\'')
|
||||
buffer.insert_text('\'', move_cursor=False)
|
||||
else:
|
||||
buffer.insert_text('\'')
|
||||
|
||||
@handle('"', filter=autopair_condition)
|
||||
def insert_right_double_quote(event):
|
||||
buffer = event.cli.current_buffer
|
||||
|
||||
if buffer.document.current_char == '"':
|
||||
buffer.cursor_position += 1
|
||||
elif whitespace_or_bracket_before(event.cli)\
|
||||
and whitespace_or_bracket_after(event.cli):
|
||||
buffer.insert_text('"')
|
||||
buffer.insert_text('"', move_cursor=False)
|
||||
else:
|
||||
buffer.insert_text('"')
|
||||
|
||||
@handle(Keys.Backspace, filter=autopair_condition)
|
||||
def delete_brackets_or_quotes(event):
|
||||
"""Delete empty pair of brackets or quotes"""
|
||||
buffer = event.cli.current_buffer
|
||||
before = buffer.document.char_before_cursor
|
||||
after = buffer.document.current_char
|
||||
|
||||
if any([before == b and after == a
|
||||
for (b, a) in ['()', '[]', '{}', "''", '""']]):
|
||||
buffer.delete(1)
|
||||
|
||||
buffer.delete_before_cursor(1)
|
||||
|
||||
@handle(Keys.ControlD, filter=ctrl_d_condition)
|
||||
def call_exit_alias(event):
|
||||
"""Use xonsh exit function"""
|
||||
b = event.cli.current_buffer
|
||||
try:
|
||||
b.accept_action.validate_and_handle(event.cli, b)
|
||||
except AttributeError: # PTK 2.0
|
||||
b.validate_and_handle()
|
||||
xonsh_exit([])
|
||||
|
||||
@handle(Keys.ControlJ, filter=IsMultiline())
|
||||
@handle(Keys.ControlM, filter=IsMultiline())
|
||||
def multiline_carriage_return(event):
|
||||
""" Wrapper around carriage_return multiline parser """
|
||||
b = event.cli.current_buffer
|
||||
carriage_return(b, event.cli)
|
||||
|
||||
@handle(Keys.ControlJ, filter=should_confirm_completion)
|
||||
@handle(Keys.ControlM, filter=should_confirm_completion)
|
||||
def enter_confirm_completion(event):
|
||||
"""Ignore <enter> (confirm completion)"""
|
||||
event.current_buffer.complete_state = None
|
||||
|
||||
@handle(Keys.Escape, filter=should_confirm_completion)
|
||||
def esc_cancel_completion(event):
|
||||
"""Use <ESC> to cancel completion"""
|
||||
event.cli.current_buffer.cancel_completion()
|
||||
|
||||
@handle(Keys.Escape, Keys.ControlJ)
|
||||
def execute_block_now(event):
|
||||
"""Execute a block of text irrespective of cursor position"""
|
||||
b = event.cli.current_buffer
|
||||
try:
|
||||
b.accept_action.validate_and_handle(event.cli, b)
|
||||
except AttributeError: # PTK 2.0
|
||||
b.validate_and_handle()
|
||||
|
||||
@handle(Keys.Left, filter=beginning_of_line)
|
||||
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=end_of_line)
|
||||
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)
|
||||
|
||||
@handle(Keys.ControlI, filter=insert_mode)
|
||||
def generate_completions(event):
|
||||
"""
|
||||
Tab-completion: where the first tab completes the common suffix and the
|
||||
second tab lists all the completions.
|
||||
|
||||
Notes
|
||||
-----
|
||||
This method was forked from the mainline prompt-toolkit repo.
|
||||
Copyright (c) 2014, Jonathan Slenders, All rights reserved.
|
||||
"""
|
||||
b = event.current_buffer
|
||||
|
||||
try:
|
||||
start_completion = event.cli.start_completion
|
||||
except AttributeError: # PTK 2.0
|
||||
start_completion = event.current_buffer.start_completion
|
||||
|
||||
def second_tab():
|
||||
if b.complete_state:
|
||||
b.complete_next()
|
||||
else:
|
||||
start_completion(select_first=False)
|
||||
|
||||
# On the second tab-press, or when already navigating through
|
||||
# completions.
|
||||
if event.is_repeat or b.complete_state:
|
||||
second_tab()
|
||||
else:
|
||||
start_completion(insert_common_part=True, select_first=False)
|
321
xonsh/ptk2/shell.py
Normal file
321
xonsh/ptk2/shell.py
Normal file
|
@ -0,0 +1,321 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
"""The prompt_toolkit based xonsh shell."""
|
||||
import sys
|
||||
import builtins
|
||||
|
||||
from xonsh.events import events
|
||||
from xonsh.base_shell import BaseShell
|
||||
from xonsh.shell import transform_command
|
||||
from xonsh.tools import print_exception, carriage_return
|
||||
from xonsh.platform import HAS_PYGMENTS, ON_WINDOWS
|
||||
from xonsh.style_tools import partial_color_tokenize, _TokenType, DEFAULT_STYLE_DICT
|
||||
from xonsh.lazyimps import pygments, pyghooks, winutils
|
||||
from xonsh.ptk2.history import PromptToolkitHistory
|
||||
from xonsh.ptk2.completer import PromptToolkitCompleter
|
||||
from xonsh.ptk2.key_bindings import load_xonsh_bindings
|
||||
|
||||
from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
|
||||
from prompt_toolkit.lexers import PygmentsLexer
|
||||
from prompt_toolkit.enums import EditingMode
|
||||
from prompt_toolkit.key_binding import KeyBindings
|
||||
from prompt_toolkit.history import ThreadedHistory
|
||||
from prompt_toolkit.shortcuts import print_formatted_text as ptk_print
|
||||
from prompt_toolkit.shortcuts import CompleteStyle
|
||||
from prompt_toolkit.shortcuts.prompt import PromptSession
|
||||
from prompt_toolkit.formatted_text import PygmentsTokens
|
||||
from prompt_toolkit.styles.pygments import (style_from_pygments_cls,
|
||||
style_from_pygments_dict, pygments_token_to_classname)
|
||||
|
||||
|
||||
Token = _TokenType()
|
||||
|
||||
events.transmogrify('on_ptk_create', 'LoadEvent')
|
||||
events.doc('on_ptk_create', """
|
||||
on_ptk_create(prompter: PromptSession, history: PromptToolkitHistory, completer: PromptToolkitCompleter, bindings: KeyBindings) ->
|
||||
|
||||
Fired after prompt toolkit has been initialized
|
||||
""")
|
||||
|
||||
|
||||
class PromptToolkit2Shell(BaseShell):
|
||||
"""The xonsh shell for prompt_toolkit v2."""
|
||||
|
||||
def __init__(self, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
if ON_WINDOWS:
|
||||
winutils.enable_virtual_terminal_processing()
|
||||
self._first_prompt = True
|
||||
self.history = ThreadedHistory(PromptToolkitHistory())
|
||||
self.prompter = PromptSession(history=self.history)
|
||||
self.pt_completer = PromptToolkitCompleter(self.completer, self.ctx, self)
|
||||
self.key_bindings = KeyBindings()
|
||||
load_xonsh_bindings(self.key_bindings)
|
||||
# This assumes that PromptToolkit2Shell is a singleton
|
||||
events.on_ptk_create.fire(
|
||||
prompter=self.prompter,
|
||||
history=self.history,
|
||||
completer=self.pt_completer,
|
||||
bindings=self.key_bindings,
|
||||
)
|
||||
|
||||
def singleline(self, auto_suggest=None, enable_history_search=True,
|
||||
multiline=True, **kwargs):
|
||||
"""Reads a single line of input from the shell. The store_in_history
|
||||
kwarg flags whether the input should be stored in PTK's in-memory
|
||||
history.
|
||||
"""
|
||||
events.on_pre_prompt.fire()
|
||||
env = builtins.__xonsh_env__
|
||||
mouse_support = env.get('MOUSE_SUPPORT')
|
||||
auto_suggest = auto_suggest if env.get('AUTO_SUGGEST') else None
|
||||
completions_display = env.get('COMPLETIONS_DISPLAY')
|
||||
if completions_display == 'multi':
|
||||
complete_style = CompleteStyle.MULTI_COLUMN
|
||||
complete_while_typing = env.get('UPDATE_COMPLETIONS_ON_KEYPRESS')
|
||||
if complete_while_typing:
|
||||
# PTK requires history search to be none when completing while typing
|
||||
enable_history_search = False
|
||||
if HAS_PYGMENTS:
|
||||
self.styler.style_name = env.get('XONSH_COLOR_STYLE')
|
||||
completer = None if completions_display == 'none' else self.pt_completer
|
||||
|
||||
if env.get('UPDATE_PROMPT_ON_KEYPRESS'):
|
||||
get_prompt_tokens = self.prompt_tokens
|
||||
get_rprompt_tokens = self.rprompt_tokens
|
||||
get_bottom_toolbar_tokens = self.bottom_toolbar_tokens
|
||||
else:
|
||||
get_prompt_tokens = self.prompt_tokens()
|
||||
get_rprompt_tokens = self.rprompt_tokens()
|
||||
get_bottom_toolbar_tokens = self.bottom_toolbar_tokens()
|
||||
|
||||
if env.get('VI_MODE'):
|
||||
editing_mode = EditingMode.VI
|
||||
else:
|
||||
editing_mode = EditingMode.EMACS
|
||||
|
||||
prompt_args = {
|
||||
'mouse_support': mouse_support,
|
||||
'auto_suggest': auto_suggest,
|
||||
'message': get_prompt_tokens,
|
||||
'rprompt': get_rprompt_tokens,
|
||||
'bottom_toolbar': get_bottom_toolbar_tokens,
|
||||
'completer': completer,
|
||||
'multiline': multiline,
|
||||
'editing_mode': editing_mode,
|
||||
'prompt_continuation': self.continuation_tokens,
|
||||
'enable_history_search': enable_history_search,
|
||||
'reserve_space_for_menu': 0,
|
||||
'key_bindings': self.key_bindings,
|
||||
'complete_style': complete_style,
|
||||
'complete_while_typing': complete_while_typing,
|
||||
}
|
||||
if builtins.__xonsh_env__.get('COLOR_INPUT'):
|
||||
if HAS_PYGMENTS:
|
||||
prompt_args['lexer'] = PygmentsLexer(pyghooks.XonshLexer)
|
||||
style = style_from_pygments_cls(
|
||||
pyghooks.xonsh_style_proxy(self.styler))
|
||||
else:
|
||||
style_dict = {
|
||||
pygments_token_to_classname(key.__name__): value
|
||||
for key, value in DEFAULT_STYLE_DICT
|
||||
}
|
||||
style = style_from_pygments_dict(style_dict)
|
||||
|
||||
prompt_args['style'] = style
|
||||
|
||||
line = self.prompter.prompt(**prompt_args)
|
||||
events.on_post_prompt.fire()
|
||||
return line
|
||||
|
||||
def _push(self, line):
|
||||
"""Pushes a line onto the buffer and compiles the code in a way that
|
||||
enables multiline input.
|
||||
"""
|
||||
code = None
|
||||
self.buffer.append(line)
|
||||
if self.need_more_lines:
|
||||
return None, code
|
||||
src = ''.join(self.buffer)
|
||||
src = transform_command(src)
|
||||
try:
|
||||
code = self.execer.compile(src,
|
||||
mode='single',
|
||||
glbs=self.ctx,
|
||||
locs=None)
|
||||
self.reset_buffer()
|
||||
except Exception: # pylint: disable=broad-except
|
||||
self.reset_buffer()
|
||||
print_exception()
|
||||
return src, None
|
||||
return src, code
|
||||
|
||||
def cmdloop(self, intro=None):
|
||||
"""Enters a loop that reads and execute input from user."""
|
||||
if intro:
|
||||
print(intro)
|
||||
auto_suggest = AutoSuggestFromHistory()
|
||||
self.push = self._push
|
||||
while not builtins.__xonsh_exit__:
|
||||
try:
|
||||
line = self.singleline(auto_suggest=auto_suggest)
|
||||
if not line:
|
||||
self.emptyline()
|
||||
else:
|
||||
line = self.precmd(line)
|
||||
self.default(line)
|
||||
except (KeyboardInterrupt, SystemExit):
|
||||
self.reset_buffer()
|
||||
except EOFError:
|
||||
if builtins.__xonsh_env__.get("IGNOREEOF"):
|
||||
print('Use "exit" to leave the shell.', file=sys.stderr)
|
||||
else:
|
||||
break
|
||||
|
||||
def prompt_tokens(self):
|
||||
"""Returns a list of (token, str) tuples for the current prompt."""
|
||||
p = builtins.__xonsh_env__.get('PROMPT')
|
||||
try:
|
||||
p = self.prompt_formatter(p)
|
||||
except Exception: # pylint: disable=broad-except
|
||||
print_exception()
|
||||
toks = partial_color_tokenize(p)
|
||||
if self._first_prompt:
|
||||
carriage_return()
|
||||
self._first_prompt = False
|
||||
self.settitle()
|
||||
return PygmentsTokens(toks)
|
||||
|
||||
def rprompt_tokens(self):
|
||||
"""Returns a list of (token, str) tuples for the current right
|
||||
prompt.
|
||||
"""
|
||||
p = builtins.__xonsh_env__.get('RIGHT_PROMPT')
|
||||
# self.prompt_formatter does handle empty strings properly,
|
||||
# but this avoids descending into it in the common case of
|
||||
# $RIGHT_PROMPT == ''.
|
||||
if isinstance(p, str) and len(p) == 0:
|
||||
return []
|
||||
try:
|
||||
p = self.prompt_formatter(p)
|
||||
except Exception: # pylint: disable=broad-except
|
||||
print_exception()
|
||||
toks = partial_color_tokenize(p)
|
||||
return PygmentsTokens(toks)
|
||||
|
||||
def bottom_toolbar_tokens(self):
|
||||
"""Returns a list of (token, str) tuples for the current bottom
|
||||
toolbar.
|
||||
"""
|
||||
p = builtins.__xonsh_env__.get('BOTTOM_TOOLBAR')
|
||||
if not p:
|
||||
return
|
||||
try:
|
||||
p = self.prompt_formatter(p)
|
||||
except Exception: # pylint: disable=broad-except
|
||||
print_exception()
|
||||
toks = partial_color_tokenize(p)
|
||||
return PygmentsTokens(toks)
|
||||
|
||||
def continuation_tokens(self, width, line_number, is_soft_wrap=False):
|
||||
"""Displays dots in multiline prompt"""
|
||||
if is_soft_wrap:
|
||||
return ''
|
||||
width = width - 1
|
||||
dots = builtins.__xonsh_env__.get('MULTILINE_PROMPT')
|
||||
dots = dots() if callable(dots) else dots
|
||||
if dots is None:
|
||||
return [(Token, ' ' * (width + 1))]
|
||||
basetoks = self.format_color(dots)
|
||||
baselen = sum(len(t[1]) for t in basetoks)
|
||||
if baselen == 0:
|
||||
return [(Token, ' ' * (width + 1))]
|
||||
toks = basetoks * (width // baselen)
|
||||
n = width % baselen
|
||||
count = 0
|
||||
for tok in basetoks:
|
||||
slen = len(tok[1])
|
||||
newcount = slen + count
|
||||
if slen == 0:
|
||||
continue
|
||||
elif newcount <= n:
|
||||
toks.append(tok)
|
||||
else:
|
||||
toks.append((tok[0], tok[1][:n - count]))
|
||||
count = newcount
|
||||
if n <= count:
|
||||
break
|
||||
toks.append((Token, ' ')) # final space
|
||||
return PygmentsTokens(toks)
|
||||
|
||||
def format_color(self, string, hide=False, force_string=False, **kwargs):
|
||||
"""Formats a color string using Pygments. This, therefore, returns
|
||||
a list of (Token, str) tuples. If force_string is set to true, though,
|
||||
this will return a color formatted string.
|
||||
"""
|
||||
tokens = partial_color_tokenize(string)
|
||||
if force_string and HAS_PYGMENTS:
|
||||
env = builtins.__xonsh_env__
|
||||
self.styler.style_name = env.get('XONSH_COLOR_STYLE')
|
||||
proxy_style = pyghooks.xonsh_style_proxy(self.styler)
|
||||
formatter = pyghooks.XonshTerminal256Formatter(style=proxy_style)
|
||||
s = pygments.format(tokens, formatter)
|
||||
return s
|
||||
elif force_string:
|
||||
print("To force colorization of string, install Pygments")
|
||||
return tokens
|
||||
else:
|
||||
return tokens
|
||||
|
||||
def print_color(self, string, end='\n', **kwargs):
|
||||
"""Prints a color string using prompt-toolkit color management."""
|
||||
if isinstance(string, str):
|
||||
tokens = partial_color_tokenize(string + end)
|
||||
else:
|
||||
# assume this is a list of (Token, str) tuples and just print
|
||||
tokens = string
|
||||
tokens = PygmentsTokens(tokens)
|
||||
if HAS_PYGMENTS:
|
||||
env = builtins.__xonsh_env__
|
||||
self.styler.style_name = env.get('XONSH_COLOR_STYLE')
|
||||
proxy_style = style_from_pygments_cls(pyghooks.xonsh_style_proxy(self.styler))
|
||||
else:
|
||||
proxy_style = style_from_pygments_dict(DEFAULT_STYLE_DICT)
|
||||
ptk_print(tokens, style=proxy_style)
|
||||
|
||||
def color_style_names(self):
|
||||
"""Returns an iterable of all available style names."""
|
||||
if not HAS_PYGMENTS:
|
||||
return ['For other xonsh styles, please install pygments']
|
||||
return pygments.styles.get_all_styles()
|
||||
|
||||
def color_style(self):
|
||||
"""Returns the current color map."""
|
||||
if not HAS_PYGMENTS:
|
||||
return DEFAULT_STYLE_DICT
|
||||
env = builtins.__xonsh_env__
|
||||
self.styler.style_name = env.get('XONSH_COLOR_STYLE')
|
||||
return self.styler.styles
|
||||
|
||||
def restore_tty_sanity(self):
|
||||
"""An interface for resetting the TTY stdin mode. This is highly
|
||||
dependent on the shell backend. Also it is mostly optional since
|
||||
it only affects ^Z backgrounding behaviour.
|
||||
"""
|
||||
# PTK does not seem to need any specialization here. However,
|
||||
# if it does for some reason in the future...
|
||||
# The following writes an ANSI escape sequence that sends the cursor
|
||||
# to the end of the line. This has the effect of restoring ECHO mode.
|
||||
# See http://unix.stackexchange.com/a/108014/129048 for more details.
|
||||
# This line can also be replaced by os.system("stty sane"), as per
|
||||
# http://stackoverflow.com/questions/19777129/interactive-python-interpreter-run-in-background#comment29421919_19778355
|
||||
# However, it is important to note that not termios-based solution
|
||||
# seems to work. My guess is that this is because termios restoration
|
||||
# needs to be performed by the subprocess itself. This fix is important
|
||||
# when subprocesses don't properly restore the terminal attributes,
|
||||
# like Python in interactive mode. Also note that the sequences "\033M"
|
||||
# and "\033E" seem to work too, but these are technically VT100 codes.
|
||||
# I used the more primitive ANSI sequence to maximize compatibility.
|
||||
# -scopatz 2017-01-28
|
||||
# if not ON_POSIX:
|
||||
# return
|
||||
# sys.stdout.write('\033[9999999C\n')
|
|
@ -273,7 +273,7 @@ def code_by_name(name, styles):
|
|||
pass
|
||||
elif 'hex' in fg:
|
||||
for p in fg.split('_'):
|
||||
codes.append('#'+p[3:] if p.startswith('hex') else p)
|
||||
codes.append('#' + p[3:] if p.startswith('hex') else p)
|
||||
else:
|
||||
fgtok = getattr(Color, fg.upper())
|
||||
if fgtok in styles:
|
||||
|
@ -284,7 +284,7 @@ def code_by_name(name, styles):
|
|||
if len(bg) == 0:
|
||||
pass
|
||||
elif bg.startswith('background_hex'):
|
||||
codes.append('bg:#'+bg[14:])
|
||||
codes.append('bg:#' + bg[14:])
|
||||
else:
|
||||
bgtok = getattr(Color, bg.upper())
|
||||
if bgtok in styles:
|
||||
|
@ -540,7 +540,7 @@ if hasattr(pygments.style, 'ansicolors'):
|
|||
Generic.Output: '#ansidarkblue',
|
||||
Generic.Traceback: '#ansidarkblue',
|
||||
Error: '#ansired',
|
||||
}, globals(), 'XONSH_BASE_STYLE')
|
||||
}, globals(), 'XONSH_BASE_STYLE')
|
||||
else:
|
||||
XONSH_BASE_STYLE = LazyObject(lambda: {
|
||||
Whitespace: "#bbbbbb",
|
||||
|
@ -548,9 +548,9 @@ else:
|
|||
Comment.Preproc: "noitalic #BC7A00",
|
||||
Keyword: "bold #008000",
|
||||
Keyword.Pseudo: "nobold",
|
||||
Keyword.Type: "nobold #B00040",
|
||||
Operator: "#666666",
|
||||
Operator.Word: "bold #AA22FF",
|
||||
Keyword.Type: "nobold #B00040",
|
||||
Operator: "#666666",
|
||||
Operator.Word: "bold #AA22FF",
|
||||
Name.Builtin: "#008000",
|
||||
Name.Function: "#0000FF",
|
||||
Name.Class: "bold #0000FF",
|
||||
|
@ -667,7 +667,7 @@ KNOWN_COLORS = LazyObject(lambda: frozenset([
|
|||
'UNDERLINE_YELLOW',
|
||||
'WHITE',
|
||||
'YELLOW',
|
||||
]), globals(), 'KNOWN_COLORS')
|
||||
]), globals(), 'KNOWN_COLORS')
|
||||
|
||||
|
||||
def _expand_style(cmap):
|
||||
|
@ -676,13 +676,13 @@ def _expand_style(cmap):
|
|||
if key is Color.NO_COLOR:
|
||||
continue
|
||||
_, _, key = str(key).rpartition('.')
|
||||
cmap[getattr(Color, 'BOLD_'+key)] = 'bold ' + val
|
||||
cmap[getattr(Color, 'UNDERLINE_'+key)] = 'underline ' + val
|
||||
cmap[getattr(Color, 'BOLD_UNDERLINE_'+key)] = 'bold underline ' + val
|
||||
cmap[getattr(Color, 'BOLD_' + key)] = 'bold ' + val
|
||||
cmap[getattr(Color, 'UNDERLINE_' + key)] = 'underline ' + val
|
||||
cmap[getattr(Color, 'BOLD_UNDERLINE_' + key)] = 'bold underline ' + val
|
||||
if val == 'noinherit':
|
||||
cmap[getattr(Color, 'BACKGROUND_'+key)] = val
|
||||
cmap[getattr(Color, 'BACKGROUND_' + key)] = val
|
||||
else:
|
||||
cmap[getattr(Color, 'BACKGROUND_'+key)] = 'bg:' + val
|
||||
cmap[getattr(Color, 'BACKGROUND_' + key)] = 'bg:' + val
|
||||
|
||||
|
||||
def _bw_style():
|
||||
|
@ -704,7 +704,7 @@ def _bw_style():
|
|||
Color.RED: 'noinherit',
|
||||
Color.WHITE: 'noinherit',
|
||||
Color.YELLOW: 'noinherit',
|
||||
}
|
||||
}
|
||||
_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -823,7 +823,7 @@ def _algol_style():
|
|||
Color.RED: '#FF0000',
|
||||
Color.WHITE: '#888',
|
||||
Color.YELLOW: '#FF0000',
|
||||
}
|
||||
}
|
||||
_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -847,7 +847,7 @@ def _algol_nu_style():
|
|||
Color.RED: '#FF0000',
|
||||
Color.WHITE: '#888',
|
||||
Color.YELLOW: '#FF0000',
|
||||
}
|
||||
}
|
||||
_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -871,7 +871,7 @@ def _autumn_style():
|
|||
Color.RED: '#aa0000',
|
||||
Color.WHITE: '#aaaaaa',
|
||||
Color.YELLOW: '#aa5500',
|
||||
}
|
||||
}
|
||||
_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -895,7 +895,7 @@ def _borland_style():
|
|||
Color.RED: '#aa0000',
|
||||
Color.WHITE: '#aaaaaa',
|
||||
Color.YELLOW: '#a61717',
|
||||
}
|
||||
}
|
||||
_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -919,7 +919,7 @@ def _colorful_style():
|
|||
Color.RED: '#A00000',
|
||||
Color.WHITE: '#bbbbbb',
|
||||
Color.YELLOW: '#A60',
|
||||
}
|
||||
}
|
||||
_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -943,7 +943,7 @@ def _emacs_style():
|
|||
Color.RED: '#A00000',
|
||||
Color.WHITE: '#bbbbbb',
|
||||
Color.YELLOW: '#BB6622',
|
||||
}
|
||||
}
|
||||
_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -967,7 +967,7 @@ def _friendly_style():
|
|||
Color.RED: '#A00000',
|
||||
Color.WHITE: '#bbbbbb',
|
||||
Color.YELLOW: '#c65d09',
|
||||
}
|
||||
}
|
||||
_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -991,7 +991,7 @@ def _fruity_style():
|
|||
Color.RED: '#ff0007',
|
||||
Color.WHITE: '#cdcaa9',
|
||||
Color.YELLOW: '#fb660a',
|
||||
}
|
||||
}
|
||||
_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -1015,7 +1015,7 @@ def _igor_style():
|
|||
Color.RED: '#C34E00',
|
||||
Color.WHITE: '#CC00A3',
|
||||
Color.YELLOW: '#C34E00',
|
||||
}
|
||||
}
|
||||
_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -1039,7 +1039,7 @@ def _lovelace_style():
|
|||
Color.RED: '#c02828',
|
||||
Color.WHITE: '#888888',
|
||||
Color.YELLOW: '#b85820',
|
||||
}
|
||||
}
|
||||
_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -1063,7 +1063,7 @@ def _manni_style():
|
|||
Color.RED: '#AA0000',
|
||||
Color.WHITE: '#AAAAAA',
|
||||
Color.YELLOW: '#CC3300',
|
||||
}
|
||||
}
|
||||
_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -1087,7 +1087,7 @@ def _murphy_style():
|
|||
Color.RED: '#A00000',
|
||||
Color.WHITE: '#bbbbbb',
|
||||
Color.YELLOW: '#c65d09',
|
||||
}
|
||||
}
|
||||
_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -1111,7 +1111,7 @@ def _native_style():
|
|||
Color.RED: '#a61717',
|
||||
Color.WHITE: '#aaaaaa',
|
||||
Color.YELLOW: '#a61717',
|
||||
}
|
||||
}
|
||||
_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -1135,7 +1135,7 @@ def _paraiso_dark_style():
|
|||
Color.RED: '#ef6155',
|
||||
Color.WHITE: '#5bc4bf',
|
||||
Color.YELLOW: '#f99b15',
|
||||
}
|
||||
}
|
||||
_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -1159,7 +1159,7 @@ def _paraiso_light_style():
|
|||
Color.RED: '#2f1e2e',
|
||||
Color.WHITE: '#8d8687',
|
||||
Color.YELLOW: '#f99b15',
|
||||
}
|
||||
}
|
||||
_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -1183,7 +1183,7 @@ def _pastie_style():
|
|||
Color.RED: '#aa0000',
|
||||
Color.WHITE: '#bbbbbb',
|
||||
Color.YELLOW: '#aa6600',
|
||||
}
|
||||
}
|
||||
_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -1207,7 +1207,7 @@ def _perldoc_style():
|
|||
Color.RED: '#aa0000',
|
||||
Color.WHITE: '#a7a7a7',
|
||||
Color.YELLOW: '#cb6c20',
|
||||
}
|
||||
}
|
||||
_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -1231,7 +1231,7 @@ def _rrt_style():
|
|||
Color.RED: '#ff0000',
|
||||
Color.WHITE: '#87ceeb',
|
||||
Color.YELLOW: '#ff0000',
|
||||
}
|
||||
}
|
||||
_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -1255,7 +1255,7 @@ def _tango_style():
|
|||
Color.RED: '#a40000',
|
||||
Color.WHITE: '#f8f8f8',
|
||||
Color.YELLOW: '#8f5902',
|
||||
}
|
||||
}
|
||||
_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -1279,7 +1279,7 @@ def _trac_style():
|
|||
Color.RED: '#aa0000',
|
||||
Color.WHITE: '#aaaaaa',
|
||||
Color.YELLOW: '#808000',
|
||||
}
|
||||
}
|
||||
_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -1303,7 +1303,7 @@ def _vim_style():
|
|||
Color.RED: '#cd0000',
|
||||
Color.WHITE: '#cccccc',
|
||||
Color.YELLOW: '#cd0000',
|
||||
}
|
||||
}
|
||||
_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -1327,7 +1327,7 @@ def _vs_style():
|
|||
Color.RED: '#a31515',
|
||||
Color.WHITE: '#2b91af',
|
||||
Color.YELLOW: '#a31515',
|
||||
}
|
||||
}
|
||||
_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -1351,7 +1351,7 @@ def _xcode_style():
|
|||
Color.RED: '#C41A16',
|
||||
Color.WHITE: '#3F6E75',
|
||||
Color.YELLOW: '#836C28',
|
||||
}
|
||||
}
|
||||
_expand_style(style)
|
||||
return style
|
||||
|
||||
|
@ -1383,7 +1383,7 @@ STYLES = LazyDict({
|
|||
'vim': _vim_style,
|
||||
'vs': _vs_style,
|
||||
'xcode': _xcode_style,
|
||||
}, globals(), 'STYLES')
|
||||
}, globals(), 'STYLES')
|
||||
|
||||
del (_algol_style, _algol_nu_style, _autumn_style, _borland_style, _bw_style,
|
||||
_colorful_style, _default_style, _emacs_style, _friendly_style,
|
||||
|
@ -1401,10 +1401,10 @@ def make_pygments_style(palette):
|
|||
for name, t in BASE_XONSH_COLORS.items():
|
||||
color = find_closest_color(t, palette)
|
||||
style[getattr(Color, name)] = '#' + color
|
||||
style[getattr(Color, 'BOLD_'+name)] = 'bold #' + color
|
||||
style[getattr(Color, 'UNDERLINE_'+name)] = 'underline #' + color
|
||||
style[getattr(Color, 'BOLD_UNDERLINE_'+name)] = 'bold underline #' + color
|
||||
style[getattr(Color, 'BACKGROUND_'+name)] = 'bg:#' + color
|
||||
style[getattr(Color, 'BOLD_' + name)] = 'bold #' + color
|
||||
style[getattr(Color, 'UNDERLINE_' + name)] = 'underline #' + color
|
||||
style[getattr(Color, 'BOLD_UNDERLINE_' + name)] = 'bold underline #' + color
|
||||
style[getattr(Color, 'BACKGROUND_' + name)] = 'bg:#' + color
|
||||
return style
|
||||
|
||||
|
||||
|
|
|
@ -94,7 +94,7 @@ def _discover_lexers():
|
|||
'.sql': ('pygments.lexers.sql', 'SqlLexer'),
|
||||
'.txt': ('pygments.lexers.special', 'TextLexer'),
|
||||
'.html': ('pygments.lexers.html', 'HtmlLexer'),
|
||||
}
|
||||
}
|
||||
exts = {}
|
||||
lexers = {'exts': exts}
|
||||
if DEBUG:
|
||||
|
@ -109,8 +109,8 @@ def _discover_lexers():
|
|||
filename = filename[1:]
|
||||
if '*' in filename:
|
||||
continue
|
||||
if (DEBUG and filename in exts and exts[filename] != val
|
||||
and filename not in default_exts):
|
||||
if (DEBUG and filename in exts and exts[filename] != val and
|
||||
filename not in default_exts):
|
||||
duplicates[filename].add(val)
|
||||
duplicates[filename].add(exts[filename])
|
||||
exts[filename] = val
|
||||
|
@ -144,16 +144,16 @@ def _discover_formatters():
|
|||
filename = filename[1:]
|
||||
if '*' in filename:
|
||||
continue
|
||||
if (DEBUG and filename in exts and exts[filename] != val
|
||||
and filename not in default_exts):
|
||||
if (DEBUG and filename in exts and exts[filename] != val and
|
||||
filename not in default_exts):
|
||||
duplicates[filename].add(val)
|
||||
duplicates[filename].add(exts[filename])
|
||||
exts[filename] = val
|
||||
# add names and aliases
|
||||
names[cls.name] = val
|
||||
for alias in cls.aliases:
|
||||
if (DEBUG and alias in names and names[alias] != val
|
||||
and alias not in default_names):
|
||||
if (DEBUG and alias in names and names[alias] != val and
|
||||
alias not in default_names):
|
||||
duplicates[alias].add(val)
|
||||
duplicates[alias].add(names[alias])
|
||||
names[alias] = val
|
||||
|
@ -180,8 +180,8 @@ def _discover_styles():
|
|||
cls = get_style_by_name(name)
|
||||
mod = inspect.getmodule(cls)
|
||||
val = (mod.__name__, cls.__name__)
|
||||
if (DEBUG and name in names and names[name] != val
|
||||
and name not in default_names):
|
||||
if (DEBUG and name in names and names[name] != val and
|
||||
name not in default_names):
|
||||
duplicates[name].add(val)
|
||||
duplicates[name].add(names[name])
|
||||
names[name] = val
|
||||
|
@ -208,8 +208,8 @@ def _discover_filters():
|
|||
cls = type(filter)
|
||||
mod = inspect.getmodule(cls)
|
||||
val = (mod.__name__, cls.__name__)
|
||||
if (DEBUG and name in names and names[name] != val
|
||||
and name not in default_names):
|
||||
if (DEBUG and name in names and names[name] != val and
|
||||
name not in default_names):
|
||||
duplicates[name].add(val)
|
||||
duplicates[name].add(names[name])
|
||||
names[name] = val
|
||||
|
|
|
@ -24,7 +24,7 @@ def _limited_traceback(excinfo):
|
|||
tb = extract_tb(excinfo.tb)
|
||||
try:
|
||||
idx = [__file__ in e for e in tb].index(True)
|
||||
return format_list(tb[idx+1:])
|
||||
return format_list(tb[idx + 1:])
|
||||
except ValueError:
|
||||
return format_list(tb)
|
||||
|
||||
|
|
|
@ -305,7 +305,7 @@ class ReadlineShell(BaseShell, cmd.Cmd):
|
|||
(False, False, False, True, False): False,
|
||||
(False, False, False, False, True): False,
|
||||
(False, False, False, False, False): False,
|
||||
}
|
||||
}
|
||||
self.cmdqueue = collections.deque()
|
||||
|
||||
def __del__(self):
|
||||
|
@ -360,8 +360,8 @@ class ReadlineShell(BaseShell, cmd.Cmd):
|
|||
'{PURPLE}({NO_COLOR}q{PURPLE}){NO_COLOR}uit '
|
||||
'{YELLOW}==={NO_COLOR}')
|
||||
while len(lines) > h - 1:
|
||||
print(''.join(lines[:h-1]), end='', flush=True, file=sys.stderr)
|
||||
lines = lines[h-1:]
|
||||
print(''.join(lines[:h - 1]), end='', flush=True, file=sys.stderr)
|
||||
lines = lines[h - 1:]
|
||||
print(more_msg, end='', flush=True, file=sys.stderr)
|
||||
q = sys.stdin.read(1).lower()
|
||||
print(flush=True, file=sys.stderr)
|
||||
|
|
|
@ -8,7 +8,7 @@ import builtins
|
|||
import warnings
|
||||
|
||||
from xonsh.platform import (best_shell_type, has_prompt_toolkit,
|
||||
ptk_above_min_supported, ptk_below_max_supported)
|
||||
ptk_above_min_supported, ptk_shell_type)
|
||||
from xonsh.tools import XonshError, print_exception
|
||||
from xonsh.events import events
|
||||
import xonsh.history.main as xhm
|
||||
|
@ -93,6 +93,22 @@ class Shell(object):
|
|||
readline version of shell should be used.
|
||||
"""
|
||||
|
||||
shell_type_aliases = {
|
||||
'b': 'best',
|
||||
'best': 'best',
|
||||
'ptk': 'prompt_toolkit',
|
||||
'ptk1': 'prompt_toolkit1',
|
||||
'ptk2': 'prompt_toolkit2',
|
||||
'prompt-toolkit': 'prompt_toolkit',
|
||||
'prompt_toolkit': 'prompt_toolkit',
|
||||
'prompt-toolkit1': 'prompt_toolkit1',
|
||||
'prompt-toolkit2': 'prompt_toolkit2',
|
||||
'rand': 'random',
|
||||
'random': 'random',
|
||||
'rl': 'readline',
|
||||
'readline': 'readline',
|
||||
}
|
||||
|
||||
def __init__(self, execer, ctx=None, shell_type=None, **kwargs):
|
||||
"""
|
||||
Parameters
|
||||
|
@ -105,7 +121,7 @@ class Shell(object):
|
|||
this no additional context is computed and this is used
|
||||
directly.
|
||||
shell_type : str, optional
|
||||
The shell type to start, such as 'readline', 'prompt_toolkit',
|
||||
The shell type to start, such as 'readline', 'prompt_toolkit1',
|
||||
or 'random'.
|
||||
"""
|
||||
self.execer = execer
|
||||
|
@ -123,6 +139,7 @@ class Shell(object):
|
|||
# This bricks interactive xonsh
|
||||
# Can happen from the use of .xinitrc, .xsession, etc
|
||||
shell_type = 'best'
|
||||
shell_type = self.shell_type_aliases.get(shell_type, shell_type)
|
||||
if shell_type == 'best' or shell_type is None:
|
||||
shell_type = best_shell_type()
|
||||
elif shell_type == 'random':
|
||||
|
@ -137,19 +154,15 @@ class Shell(object):
|
|||
'supported. Please update prompt-toolkit. Using '
|
||||
'readline instead.')
|
||||
shell_type = 'readline'
|
||||
elif not ptk_below_max_supported():
|
||||
warnings.warn('prompt-toolkit version 2.0 is not yet '
|
||||
'supported. Please see Github PR #2570 for '
|
||||
'latest status. To use prompt-toolkit now you '
|
||||
'can downgrade to version 1.x with\n'
|
||||
'xpip install "prompt_toolkit<2"\n'
|
||||
'Starting xonsh with readline shell instead.')
|
||||
shell_type = 'readline'
|
||||
else:
|
||||
shell_type = ptk_shell_type()
|
||||
self.shell_type = env['SHELL_TYPE'] = shell_type
|
||||
# actually make the shell
|
||||
if shell_type == 'none':
|
||||
from xonsh.base_shell import BaseShell as shell_class
|
||||
elif shell_type == 'prompt_toolkit':
|
||||
elif shell_type == 'prompt_toolkit2':
|
||||
from xonsh.ptk2.shell import PromptToolkit2Shell as shell_class
|
||||
elif shell_type == 'prompt_toolkit1':
|
||||
from xonsh.ptk.shell import PromptToolkitShell as shell_class
|
||||
elif shell_type == 'readline':
|
||||
from xonsh.readline_shell import ReadlineShell as shell_class
|
||||
|
|
|
@ -250,7 +250,7 @@ KNOWN_COLORS = LazyObject(lambda: frozenset([
|
|||
'UNDERLINE_YELLOW',
|
||||
'WHITE',
|
||||
'YELLOW',
|
||||
]), globals(), 'KNOWN_COLORS')
|
||||
]), globals(), 'KNOWN_COLORS')
|
||||
|
||||
DEFAULT_STYLE_DICT = LazyObject(lambda: {
|
||||
Token: '',
|
||||
|
@ -419,5 +419,5 @@ DEFAULT_STYLE_DICT = LazyObject(lambda: {
|
|||
Token.Scrollbar.Arrow: 'bg:#ansiblack #ansiwhite bold',
|
||||
Token.Scrollbar.Button: 'bg:#ansiblack',
|
||||
Token.Text: '',
|
||||
Token.Text.Whitespace: '#ansilightgray'},
|
||||
globals(), 'DEFAULT_STYLE_DICT')
|
||||
Token.Text.Whitespace: '#ansilightgray',
|
||||
}, globals(), 'DEFAULT_STYLE_DICT')
|
||||
|
|
|
@ -301,7 +301,7 @@ def setup_timings():
|
|||
width = max(len(s) for s, _ in times) + 2
|
||||
header_format = '|{{:<{}}}|{{:^11}}|{{:^11}}|'.format(width)
|
||||
entry_format = '|{{:<{}}}|{{:^11.3f}}|{{:^11.3f}}|'.format(width)
|
||||
sepline = '|{}|{}|{}|'.format('-'*width, '-'*11, '-'*11)
|
||||
sepline = '|{}|{}|{}|'.format('-' * width, '-' * 11, '-' * 11)
|
||||
# Print result table
|
||||
print(' Debug level: {}'.format(os.getenv('XONSH_DEBUG', 'Off')))
|
||||
print(sepline)
|
||||
|
|
|
@ -238,7 +238,7 @@ _redir_map = (
|
|||
# stdout to stderr
|
||||
'out>err', 'out>&2', '1>err', 'out>e', 'out>2', 'o>err', 'o>&2',
|
||||
'1>&2', 'o>e', '1>e', 'o>2', '1>2',
|
||||
)
|
||||
)
|
||||
IORedirect = group(group(*_redir_map), '{}>>?'.format(group(*_redir_names)))
|
||||
_redir_check = set(_redir_map)
|
||||
_redir_check = {'{}>'.format(i) for i in _redir_names}.union(_redir_check)
|
||||
|
|
|
@ -165,8 +165,8 @@ class EnvPath(collections.MutableSequence):
|
|||
# make TypeError's message as informative as possible
|
||||
# when given an invalid initialization sequence
|
||||
raise TypeError(
|
||||
"EnvPath's initialization sequence should only "
|
||||
"contain str, bytes and pathlib.Path entries")
|
||||
"EnvPath's initialization sequence should only "
|
||||
"contain str, bytes and pathlib.Path entries")
|
||||
self._l = args
|
||||
else:
|
||||
raise TypeError('EnvPath cannot be initialized with items '
|
||||
|
@ -272,9 +272,8 @@ class DefaultNotGivenType(object):
|
|||
|
||||
DefaultNotGiven = DefaultNotGivenType()
|
||||
|
||||
BEG_TOK_SKIPS = LazyObject(
|
||||
lambda: frozenset(['WS', 'INDENT', 'NOT', 'LPAREN']),
|
||||
globals(), 'BEG_TOK_SKIPS')
|
||||
BEG_TOK_SKIPS = LazyObject(lambda: frozenset(['WS', 'INDENT', 'NOT', 'LPAREN']),
|
||||
globals(), 'BEG_TOK_SKIPS')
|
||||
END_TOK_TYPES = LazyObject(lambda: frozenset(['SEMI', 'AND', 'OR', 'RPAREN']),
|
||||
globals(), 'END_TOK_TYPES')
|
||||
RE_END_TOKS = LazyObject(lambda: re.compile('(;|and|\&\&|or|\|\||\))'),
|
||||
|
@ -499,7 +498,7 @@ def get_logical_line(lines, idx):
|
|||
n = 1
|
||||
nlines = len(lines)
|
||||
linecont = get_line_continuation()
|
||||
while idx > 0 and lines[idx-1].endswith(linecont):
|
||||
while idx > 0 and lines[idx - 1].endswith(linecont):
|
||||
idx -= 1
|
||||
start = idx
|
||||
line = lines[idx]
|
||||
|
@ -524,9 +523,9 @@ def replace_logical_line(lines, logical, idx, n):
|
|||
lines[idx] = logical
|
||||
return
|
||||
space = ' '
|
||||
for i in range(idx, idx+n-1):
|
||||
for i in range(idx, idx + n - 1):
|
||||
a = len(lines[i])
|
||||
b = logical.find(space, a-1)
|
||||
b = logical.find(space, a - 1)
|
||||
if b < 0:
|
||||
# no space found
|
||||
lines[i] = logical
|
||||
|
@ -535,7 +534,7 @@ def replace_logical_line(lines, logical, idx, n):
|
|||
# found space to split on
|
||||
lines[i] = logical[:b] + linecont
|
||||
logical = logical[b:]
|
||||
lines[idx+n-1] = logical
|
||||
lines[idx + n - 1] = logical
|
||||
|
||||
|
||||
def is_balanced(expr, ltok, rtok):
|
||||
|
@ -1468,7 +1467,7 @@ HISTORY_UNITS = LazyObject(lambda: {
|
|||
'tb': ('b', _tb_to_b),
|
||||
'terabyte': ('b', _tb_to_b),
|
||||
'terabytes': ('b', _tb_to_b),
|
||||
}, globals(), 'HISTORY_UNITS')
|
||||
}, globals(), 'HISTORY_UNITS')
|
||||
"""Maps lowercase unit names to canonical name and conversion utilities."""
|
||||
|
||||
|
||||
|
@ -1708,7 +1707,7 @@ RE_STRING_CONT = LazyDict({
|
|||
"'": lambda: re.compile(r"((\\(.|\n))|([^'\\]))*"),
|
||||
'"""': lambda: re.compile(r'((\\(.|\n))|([^"\\])|("(?!""))|\n)*'),
|
||||
"'''": lambda: re.compile(r"((\\(.|\n))|([^'\\])|('(?!''))|\n)*"),
|
||||
}, globals(), 'RE_STRING_CONT')
|
||||
}, globals(), 'RE_STRING_CONT')
|
||||
"""Dictionary mapping starting quote sequences to regular expressions that
|
||||
match the contents of a string beginning with those quotes (not including the
|
||||
terminating quotes)"""
|
||||
|
@ -1975,7 +1974,7 @@ def columnize(elems, width=80, newline='\n'):
|
|||
# we might be able to fit another column.
|
||||
ncols += 1
|
||||
nrows = nelem // ncols
|
||||
columns = [sizes[i*nrows:(i+1)*nrows] for i in range(ncols)]
|
||||
columns = [sizes[i * nrows:(i + 1) * nrows] for i in range(ncols)]
|
||||
last_longest_row = longest_row
|
||||
else:
|
||||
# we can't fit another column
|
||||
|
@ -1984,7 +1983,7 @@ def columnize(elems, width=80, newline='\n'):
|
|||
break
|
||||
pad = (width - last_longest_row + ncols) // ncols
|
||||
pad = pad if pad > 1 else 1
|
||||
data = [elems[i*nrows:(i+1)*nrows] for i in range(ncols)]
|
||||
data = [elems[i * nrows:(i + 1) * nrows] for i in range(ncols)]
|
||||
colwidths = [max(map(len, d)) + pad for d in data]
|
||||
colwidths[-1] -= pad
|
||||
row_t = ''.join(['{{row[{i}]: <{{w[{i}]}}}}'.format(i=i) for i in range(ncols)])
|
||||
|
|
|
@ -17,8 +17,7 @@ from xonsh.proc import STDOUT_CAPTURE_KINDS
|
|||
import xonsh.prompt.cwd as prompt
|
||||
|
||||
terminal = LazyObject(lambda: importlib.import_module(
|
||||
'pygments.formatters.terminal'),
|
||||
globals(), 'terminal')
|
||||
'pygments.formatters.terminal'), globals(), 'terminal')
|
||||
|
||||
|
||||
class TracerType(object):
|
||||
|
@ -203,7 +202,7 @@ _TRACER_MAIN_ACTIONS = {
|
|||
'del': _off,
|
||||
'stop': _off,
|
||||
'color': _color,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
def tracermain(args=None, stdin=None, stdout=None, stderr=None, spec=None):
|
||||
|
|
|
@ -395,7 +395,7 @@ def CONSOLE_SCREEN_BUFFER_INFO():
|
|||
("wAttributes", WORD),
|
||||
("srWindow", SMALL_RECT),
|
||||
("dwMaximumWindowSize", COORD),
|
||||
]
|
||||
]
|
||||
|
||||
return _CONSOLE_SCREEN_BUFFER_INFO
|
||||
|
||||
|
@ -408,7 +408,7 @@ def GetConsoleScreenBufferInfo():
|
|||
gcsbi.argtypes = (
|
||||
HANDLE,
|
||||
POINTER(CONSOLE_SCREEN_BUFFER_INFO),
|
||||
)
|
||||
)
|
||||
gcsbi.restype = BOOL
|
||||
return gcsbi
|
||||
|
||||
|
@ -469,7 +469,7 @@ def SetConsoleScreenBufferSize():
|
|||
scsbs.argtypes = (
|
||||
HANDLE, # _In_ HANDLE hConsoleOutput
|
||||
COORD, # _In_ COORD dwSize
|
||||
)
|
||||
)
|
||||
scsbs.restype = BOOL
|
||||
return scsbs
|
||||
|
||||
|
@ -503,7 +503,7 @@ def SetConsoleCursorPosition():
|
|||
sccp.argtypes = (
|
||||
HANDLE, # _In_ HANDLE hConsoleOutput
|
||||
COORD, # _In_ COORD dwCursorPosition
|
||||
)
|
||||
)
|
||||
sccp.restype = BOOL
|
||||
return sccp
|
||||
|
||||
|
|
|
@ -481,7 +481,7 @@ class PrettyFormatter(Visitor):
|
|||
s += '\n'
|
||||
t = sorted(node.responses.items())
|
||||
t = ['{0!r}: {1}'.format(k, self.visit(v)) for k, v in t]
|
||||
s += textwrap.indent(',\n'.join(t), 2*self.indent)
|
||||
s += textwrap.indent(',\n'.join(t), 2 * self.indent)
|
||||
s += '\n' + self.indent + '}'
|
||||
if node.converter is not None:
|
||||
s += ',\n' + self.indent + 'converter={0!r}'.format(node.converter)
|
||||
|
@ -620,7 +620,7 @@ class StateVisitor(Visitor):
|
|||
p = path[-1]
|
||||
if isinstance(p, int) and abs(p) + (p >= 0) > len(loc):
|
||||
i = abs(p) + (p >= 0) - len(loc)
|
||||
ex = [None]*i
|
||||
ex = [None] * i
|
||||
loc.extend(ex)
|
||||
loc[p] = val
|
||||
|
||||
|
|
|
@ -117,7 +117,7 @@ _XONFIG_SOURCE_FOREIGN_SHELL_COMMAND = collections.defaultdict(
|
|||
bash='source-bash',
|
||||
cmd='source-cmd',
|
||||
zsh='source-zsh',
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def _dump_xonfig_foreign_shell(path, value):
|
||||
|
@ -608,13 +608,13 @@ def STRIP_COLOR_RE():
|
|||
def _align_string(string, align='<', fill=' ', width=80):
|
||||
""" Align and pad a color formatted string """
|
||||
linelen = len(STRIP_COLOR_RE.sub('', string))
|
||||
padlen = max(width-linelen, 0)
|
||||
padlen = max(width - linelen, 0)
|
||||
if align == '^':
|
||||
return fill*(padlen//2) + string + fill*(padlen//2 + padlen % 2)
|
||||
return fill * (padlen // 2) + string + fill * (padlen // 2 + padlen % 2)
|
||||
elif align == '>':
|
||||
return fill*padlen + string
|
||||
return fill * padlen + string
|
||||
elif align == '<':
|
||||
return string + fill*padlen
|
||||
return string + fill * padlen
|
||||
else:
|
||||
return string
|
||||
|
||||
|
|
|
@ -118,7 +118,7 @@ def _list(ns):
|
|||
for d in data:
|
||||
name = d['name']
|
||||
lname = len(name)
|
||||
s += "{PURPLE}" + name + "{NO_COLOR} " + " "*(nname - lname)
|
||||
s += "{PURPLE}" + name + "{NO_COLOR} " + " " * (nname - lname)
|
||||
if d['installed']:
|
||||
s += '{GREEN}installed{NO_COLOR} '
|
||||
else:
|
||||
|
@ -154,7 +154,7 @@ def _create_xontrib_parser():
|
|||
_MAIN_XONTRIB_ACTIONS = {
|
||||
'load': _load,
|
||||
'list': _list,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@unthreadable
|
||||
|
|
|
@ -36,7 +36,7 @@ def _uptime_osx():
|
|||
bt = struct.unpack_from('@qq', bt)
|
||||
else:
|
||||
raise ValueError('length of boot time not understood: ' + repr(bt))
|
||||
bt = bt[0] + bt[1]*1e-6
|
||||
bt = bt[0] + bt[1] * 1e-6
|
||||
if bt == 0.0:
|
||||
return None
|
||||
_BOOTTIME = bt
|
||||
|
|
|
@ -19,11 +19,11 @@ def bash_preproc(cmd, **kw):
|
|||
|
||||
@events.on_ptk_create
|
||||
def custom_keybindings(bindings, **kw):
|
||||
handler = bindings.registry.add_binding
|
||||
handler = bindings.add
|
||||
insert_mode = ViInsertMode() | EmacsInsertMode()
|
||||
|
||||
@Condition
|
||||
def last_command_exists(cli):
|
||||
def last_command_exists():
|
||||
return len(__xonsh_history__) > 0
|
||||
|
||||
@handler(Keys.Escape, '.', filter=last_command_exists &
|
||||
|
|
|
@ -8,6 +8,7 @@ import matplotlib.pyplot as plt
|
|||
|
||||
from xonsh.tools import print_color, ON_WINDOWS
|
||||
|
||||
|
||||
try:
|
||||
# Use iterm2_tools as an indicator for the iterm2 terminal emulator
|
||||
from iterm2_tools.images import display_image_bytes
|
||||
|
@ -79,19 +80,19 @@ def figure_to_tight_array(fig, width, height, minimal=True):
|
|||
# perform reversible operations to produce an optimally tight layout
|
||||
dpi = dpi_fig
|
||||
subplotpars = {
|
||||
k: getattr(fig.subplotpars, k)
|
||||
for k in ['wspace', 'hspace', 'bottom', 'top', 'left', 'right']
|
||||
}
|
||||
k: getattr(fig.subplotpars, k)
|
||||
for k in ['wspace', 'hspace', 'bottom', 'top', 'left', 'right']
|
||||
}
|
||||
|
||||
# set the figure dimensions to the terminal size
|
||||
fig.set_size_inches(width/dpi, height/dpi, forward=True)
|
||||
fig.set_size_inches(width / dpi, height / dpi, forward=True)
|
||||
width, height = fig.canvas.get_width_height()
|
||||
|
||||
# remove all space between subplots
|
||||
fig.subplots_adjust(wspace=0, hspace=0)
|
||||
# move all subplots to take the entirety of space in the figure
|
||||
# leave only one line for top and bottom
|
||||
fig.subplots_adjust(bottom=1/height, top=1-1/height, left=0, right=1)
|
||||
fig.subplots_adjust(bottom=1 / height, top=1 - 1 / height, left=0, right=1)
|
||||
|
||||
# reduce font size in order to reduce text impact on the image
|
||||
font_size = matplotlib.rcParams['font.size']
|
||||
|
@ -110,7 +111,7 @@ def figure_to_tight_array(fig, width, height, minimal=True):
|
|||
matplotlib.rcParams.update({'font.size': font_size})
|
||||
|
||||
# reset the axis positions and figure dimensions
|
||||
fig.set_size_inches(w/dpi, h/dpi, forward=True)
|
||||
fig.set_size_inches(w / dpi, h / dpi, forward=True)
|
||||
fig.subplots_adjust(**subplotpars)
|
||||
else:
|
||||
fig.dpi = dpi_fig
|
||||
|
|
|
@ -18,7 +18,7 @@ class VoxHandler:
|
|||
create = subparsers.add_parser(
|
||||
'new', aliases=['create'],
|
||||
help='Create a new virtual environment'
|
||||
)
|
||||
)
|
||||
create.add_argument('name', metavar='ENV',
|
||||
help='The environments to create')
|
||||
|
||||
|
@ -48,7 +48,7 @@ class VoxHandler:
|
|||
activate = subparsers.add_parser(
|
||||
'activate', aliases=['workon', 'enter'],
|
||||
help='Activate virtual environment'
|
||||
)
|
||||
)
|
||||
activate.add_argument('name', metavar='ENV',
|
||||
help='The environment to activate')
|
||||
subparsers.add_parser('deactivate', aliases=['exit'], help='Deactivate current virtual environment')
|
||||
|
@ -83,7 +83,7 @@ class VoxHandler:
|
|||
if cmd is None:
|
||||
self.parser.print_usage()
|
||||
else:
|
||||
getattr(self, 'cmd_'+cmd)(args, stdin)
|
||||
getattr(self, 'cmd_' + cmd)(args, stdin)
|
||||
|
||||
def cmd_new(self, args, stdin=None):
|
||||
"""Create a virtual environment in $VIRTUALENV_HOME with python3's ``venv``.
|
||||
|
|
|
@ -236,7 +236,7 @@ class Vox(collections.abc.Mapping):
|
|||
bin_, lib, inc = _subdir_names()
|
||||
for dirpath, dirnames, _ in os.walk(self.venvdir):
|
||||
if bin_ in dirnames and lib in dirnames:
|
||||
yield dirpath[len(self.venvdir)+1:] # +1 is to remove the separator
|
||||
yield dirpath[len(self.venvdir) + 1:] # +1 is to remove the separator
|
||||
# Don't recurse in to the special dirs
|
||||
dirnames.remove(bin_)
|
||||
dirnames.remove(lib) # This one in particular is likely to be quite large.
|
||||
|
|
|
@ -15,7 +15,7 @@ def custom_keybindings(bindings, **kw):
|
|||
# Alt+Left and Alt+Right still jump over smaller word segments.
|
||||
# See https://github.com/xonsh/xonsh/issues/2403
|
||||
|
||||
handler = bindings.registry.add_binding
|
||||
handler = bindings.add
|
||||
|
||||
@handler(Keys.ControlLeft)
|
||||
def ctrl_left(event):
|
||||
|
|
Loading…
Add table
Reference in a new issue