mirror of
https://github.com/xonsh/xonsh.git
synced 2025-03-04 16:34:47 +01:00
Redirection no longer require a space
This commit is contained in:
parent
1a209547b8
commit
1b2a4a5e52
3 changed files with 61 additions and 8 deletions
15
news/nsredir.rst
Normal file
15
news/nsredir.rst
Normal file
|
@ -0,0 +1,15 @@
|
|||
**Added:**
|
||||
|
||||
* Subprocess redirection may now forego the whitespace between the
|
||||
redirection and a file name. For example,
|
||||
``echo hello world >/dev/null``.
|
||||
|
||||
**Changed:** None
|
||||
|
||||
**Deprecated:** None
|
||||
|
||||
**Removed:** None
|
||||
|
||||
**Fixed:** None
|
||||
|
||||
**Security:** None
|
|
@ -82,10 +82,10 @@ def check_tokens(inp, exp):
|
|||
return assert_tokens_equal(exp, obs)
|
||||
|
||||
|
||||
def check_tokens_subproc(inp, exp):
|
||||
def check_tokens_subproc(inp, exp, stop=-1):
|
||||
l = Lexer()
|
||||
l.input('$[{}]'.format(inp))
|
||||
obs = list(l)[1:-1]
|
||||
obs = list(l)[1:stop]
|
||||
return assert_tokens_equal(exp, obs)
|
||||
|
||||
|
||||
|
@ -242,11 +242,23 @@ def test_regex_globs():
|
|||
def test_float_literals(case):
|
||||
assert check_token(case, ['NUMBER', case, 0])
|
||||
|
||||
@pytest.mark.parametrize('case', [
|
||||
'2>1', 'err>out', 'o>', 'all>', 'e>o', 'e>', 'out>', '2>&1'
|
||||
])
|
||||
def test_ioredir(case):
|
||||
assert check_tokens_subproc(case, [('IOREDIRECT', case, 2)], stop=-2)
|
||||
|
||||
def test_ioredir():
|
||||
cases = ['2>1', 'err>out', 'o>', 'all>', 'e>o', 'e>', 'out>', '2>&1']
|
||||
for s in cases:
|
||||
assert check_tokens_subproc(s, [('IOREDIRECT', s, 2)])
|
||||
|
||||
@pytest.mark.parametrize('case', [
|
||||
'>', '>>', '<', 'e>',
|
||||
'> ', '>> ', '< ', 'e> ',
|
||||
])
|
||||
def test_redir_whitespace(case):
|
||||
inp = '![{}/path/to/file]'.format(case)
|
||||
l = Lexer()
|
||||
l.input(inp)
|
||||
obs = list(l)
|
||||
assert obs[2].type == 'WS'
|
||||
|
||||
|
||||
@pytest.mark.parametrize('s, exp', [
|
||||
|
|
|
@ -14,8 +14,9 @@ except ImportError:
|
|||
from xonsh.lazyasd import lazyobject
|
||||
from xonsh.platform import PYTHON_VERSION_INFO
|
||||
from xonsh.tokenize import (OP, IOREDIRECT, STRING, DOLLARNAME, NUMBER,
|
||||
SEARCHPATH, NEWLINE, INDENT, DEDENT, NL, COMMENT, ENCODING,
|
||||
ENDMARKER, NAME, ERRORTOKEN, tokenize, TokenError)
|
||||
SEARCHPATH, NEWLINE, INDENT, DEDENT, NL, COMMENT,
|
||||
ENCODING, ENDMARKER, NAME, ERRORTOKEN, GREATER,
|
||||
LESS, RIGHTSHIFT, tokenize, TokenError)
|
||||
|
||||
|
||||
@lazyobject
|
||||
|
@ -167,6 +168,24 @@ def handle_double_pipe(state, token):
|
|||
yield _new_token('OR', 'or', token.start)
|
||||
|
||||
|
||||
def handle_redirect(state, token):
|
||||
# The parser expects whitespace after a redirection in subproc mode.
|
||||
# If whitespace does not exist, we'll issue an empty whitespace
|
||||
# token before proceeding.
|
||||
state['last'] = token
|
||||
typ = token.type
|
||||
st = token.string
|
||||
key = (typ, st) if (typ, st) in token_map else typ
|
||||
yield _new_token(token_map[key], st, token.start)
|
||||
if state['pymode'][-1][0]:
|
||||
return
|
||||
# add a whitespace token after a redirection, if we need to
|
||||
next_tok = next(state['stream'])
|
||||
if next_tok.start == token.end:
|
||||
yield _new_token('WS', '', token.end)
|
||||
yield from handle_token(state, next_tok)
|
||||
|
||||
|
||||
def _make_matcher_handler(tok, typ, pymode, ender, handlers):
|
||||
matcher = (')' if tok.endswith('(') else
|
||||
'}' if tok.endswith('{') else
|
||||
|
@ -192,6 +211,13 @@ def special_handlers():
|
|||
ENDMARKER: handle_ignore,
|
||||
NAME: handle_name,
|
||||
ERRORTOKEN: handle_error_token,
|
||||
LESS: handle_redirect,
|
||||
GREATER: handle_redirect,
|
||||
RIGHTSHIFT: handle_redirect,
|
||||
IOREDIRECT: handle_redirect,
|
||||
(OP, '<'): handle_redirect,
|
||||
(OP, '>'): handle_redirect,
|
||||
(OP, '>>'): handle_redirect,
|
||||
(OP, ')'): handle_rparen,
|
||||
(OP, '}'): handle_rbrace,
|
||||
(OP, ']'): handle_rbracket,
|
||||
|
|
Loading…
Add table
Reference in a new issue