XEP: | 2 |
Title: | Xonsh Operators Proposal - Single operator approach |
Author: | anki-code |
Status: | Ready to review |
Created: | 2020-10-30 |
Xonsh-Version: | 0.9.24 |
The first command substitution operator (now most known as $()
)
was created in 1979 and until nowadays it was used to split the one command output and push it as arguments to another command.
In xonsh the command substitution operator has the same syntax - $()
- but in xonsh it returns the pure output from
one command to another. This behavior not well-known, not expected and leads to a constant need to strip
-ping
and split
-ting the output of the original command. This brings the syntax overhead to xonsh commands. This is unexpected
behavior for new users. And finally this blurs the difference between another xonsh operators.
The goal of this proposal is to suggest a new behavior for the command substitution operator and changes in another operators to make the behavior more common and consistent and also with shortening the syntax overhead during usage the command substitution operators.
This proposal have no goal to create exactly the same behavior and syntax as in previous shells in the shells history. Also this proposal has no goal to support backwards compatibility exactly. The most use cases was designed with maximization of backwards compatibility in mind but the operators in xonsh are located very close to the core functionality and to achieve the real improvement of syntax and logic it requires move away from the backwards compatibility.
Merge $()
and !()
operators into one $()
operator and remove !()
with ![]
.
Operators changes:
Mode | Current | Proposed |
---|---|---|
Python | $() returns output string. |
$() returns CommandPipeline object. |
Subproc | $() returns output string. |
$() returns list of lines from output without trailing new line symbol. |
Python | $[] returns None . |
$[] returns HiddenCommandPipeline object. |
Both | !() exists. |
!() removed. |
Both | ![] exists. |
![] removed. |
CommandPipeline
(CP
) class changes:
- Add
str
representation the same asCP.out
. - Remove trailing new lines in
CP.out
,CP.lines
andCP.__iter__
. - Add all string methods
i.e. the
$().split()
will returnCP.out.split()
that is IFS analogue in fact. - Add all string methods
for lines i.e.
$().lines_find(txt)
will return[l.find(txt) for l in CP.lines]
.
The source in XEP-2-examples.xsh.
There is Github repo xonsh2 that was built by my-xonsh-fork
from xonsh-xep-2 repository that has XEP-2 changes. The installation of xonsh2
will not affect your host xonsh installation. You can install xonsh2 and: run it, create .xonshrc_2
, add to
the shebang (#!/usr/bin/env xonsh2
), run scripts (xonsh2 my.xsh
), put xontribs to xontrib2
directory
and load it via xontrib2 load
. Original xonsh will live shoulder to shoulder with xonsh2 in fact.
Install and try:
## You can try in docker instead of local host:
# docker run --rm -it python:3.6-slim /bin/bash -c 'apt update; apt install -y git; /bin/bash'
pip install -U git+https://github.com/anki-code/xonsh2
xonsh2
Feel free to make pull requests or create issues in the xonsh-xep-2 repository if you like the XEP-2 approach.
The table of use cases compares the syntax of the current xonsh and the proposed (first line and second line accordingly):
Use case | Subproc current / proposed | Python current / proposed |
---|---|---|
Get single argument. ✅ Becomes shorter. |
|
|
Get multiple arguments. ✅ Becomes shorter. |
|
|
Get output as concatenated lines. ✅ Describing of what we want to get explicitly. |
|
|
Custom output splitting. ✅ Becomes shorter. |
The similar as python mode. |
|
Apply string function to every line. ✅ Becomes shorter. |
The similar as python mode. |
|
Single argument in grep. ✅ Fixed the bug. |
Wrong output of all lines in current version. One correct single line in XEP-2. |
Not applicable. |
Python substitution in subproc mode. ✅ Fixed the substitution expectations. |
Unwanted new line in the directory name in current version. The name of the directory as expected (also in case it has spaces) in XEP-2. |
Not applicable. |
Syntax to remember. ✅ Less syntax to remember. |
Remember the meaning of One |
The same as subproc. |
Feel free to suggest your use cases.
To achieve smooth releasing this proposal suggests to start versioning xonsh the similar way as Python.
Create distinct xonsh version - xonsh2
- with changes from this proposal.
-
From @scopatz: I think using
$() in xonsh to split into a list of arguments is a neat idea, but it would necessitate the addition of some default or configurable way to split those arguments. For example, should $ () be split by lines or by whitespace (like effectively what Bash does)?Answer: To get IFS-like custom separation this proposal suggests to do
$().split(sep)
explicitly. -
From @scopatz: What do we do with the @$() operator? The initial idea for @$() what that you could register transformation functions (like a decorator), that would modify output. For example, @upper$() would uppercase the output. Or you could apply many times, like @split@upper(). Then what we have now would just be the default value: @split$() == @$(). However, this was never fully done, so maybe it is better to drop the syntax entirely.
Answer: Do nothing because it's a syntax sugar for getting words from output. We suggest to keep short calls using this operator unchanged.
-
From @laloch: What about leading and trailing whitespace around the
$()
operator? Can you domkdir -p /tmp/$(whoami)/garbage
?Answer: Detailed answer.
-
From @daniel-shimon: How to get the complete output?
Answer: By using CP.raw_out.