-
Notifications
You must be signed in to change notification settings - Fork 116
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Ability to pipe to cmd2 commands #978
Comments
I think we'll have to use something like a double pipe Lots of thoughts come to mind for a change like this.
|
I don't have a clear concept of exactly how this feature would/should work. Without one we can't design it. Does anyone else have a clear concept of how they think it should work? |
Hello, I tried (before reading documentation) to do some I do not have a clear concept of how it should work, but I can tell you how I would like it to work (I hope both are not exclusive 😉) Some of the commands I developed ask the user for some data (depending on cli args, or intermediate choices), those datas are either strings, integers, yes/no, that kind of things. They are all validated by a carriage return. The user input is either read using I tried to create a script containing my command followed by the user input and pass it to Please let me know if you need more precision on my use case. |
Hello, May be i not understand why the Pipe The pipe is describe from long time ago by the POSIX documentation. That is two file descriptor from STDIN, STDOUT, STDERR. How integrate it to I can take a look, to code the pipe() function as describe by POSIX, but i'm not sure how integrate inside teh actual code The doucle |
I have take a look about pipe, but that is all ready exist on os.pipe() and os.pipe2() https://docs.python.org/3/library/os.html#os.pipe and https://docs.python.org/3/library/os.html#os.pipe2 (look to be teh True POSIX pipe) As describe by POSIX requirements, the os.pipe() should be couple with os.fork(), and the File Descritor should us a POSIX FD. that is done by it type of code: https://www.tutorialspoint.com/python/os_pipe.htm #!/usr/bin/python
import os, sys
print "The child will write text to a pipe and "
print "the parent will read the text written by child..."
# file descriptors r, w for reading and writing
r, w = os.pipe()
processid = os.fork()
if processid:
# This is the parent process
# Closes file descriptor w
os.close(w)
r = os.fdopen(r)
print "Parent reading"
str = r.read()
print "text =", str
sys.exit(0)
else:
# This is the child process
os.close(r)
w = os.fdopen(w, 'w')
print "Child writing"
w.write("Text written by child...")
w.close()
print "Child closing"
sys.exit(0) A good documentation can be found here: https://epsi-rns.github.io/code/2017/04/17/python-pipe-and-fork.html |
Here POSIX description of a PIPE:
|
Here a exemple about oilsshell , that is not a pure POSIX Pipe but that look correct. That method can be use on cmd2 and look more easy to implement. # Create private named pipes for this instance. Anonymous pipes don't work,
# because they can't be inherited.
fifo_stdin = os.path.join(THIS_DIR, '_tmp/stdin')
fifo_stdout = os.path.join(THIS_DIR, '_tmp/stdout')
fifo_stderr = os.path.join(THIS_DIR, '_tmp/stderr')
try:
os.mkfifo(fifo_stdin)
os.mkfifo(fifo_stdout)
os.mkfifo(fifo_stderr)
except OSError as e:
log('error making fifos: %s', e) https://github.com/oilshell/shell-protocols/blob/master/coprocess/fcli_invoke.py It look i'm a rare guy concerne by the internal Cmd2 command PIPE. That due to the fact i have start a project arround Cmd2 it consite to create a autonomus, one file binary SHELL. https://gitlab.com/Tuuux/galaxie-shell It look very strange to have Cmd2 without True PIPE , and no plan to integrate it ... What is the next step ? |
@Hierosme The concerns of the Supporting a pure pipe syntax where you can pipe from/to cmd2 commands as well as shell commands multiple times would be a great feature, but it would also very significantly complicate our parsing logic as well as how we resolve command aliases/macros. We would like to implement this feature because we realize it would be a great and natural thing for our users, but we want to make sure we don't unduly burden the maintenance of cmd2 in order to make that happen. If you have any good ideas for how to implement this in cmd2 without breaking existing features and in a way that would be maintainable, we would absolutely love a PR ;-) |
Hi @tleonhardt , I'm iterested to take a look, and in case send a PR :) or i minima push here my feedback. Has i understand, how macro/alias (may be sub SHELL command) are implemented will certainly be the pain source . I suppose true POSIX fork will be not allow ... Then i'll try approch with io.StringIO and io.BytesIO and hope add capapility to PIPE huge thing. We should have something in a "system wait" state, it permit to accept a Keyboard Interruption. I hope give some good news soon. Regards |
I have take a look, and have a better view now. Actually The good thing is During tests i have see I'll continue to look, for now i'll test the workarround with SetupTools |
@Hierosme Just curious, did you ever look into this more? |
Yes i have a working pipe implementation for CMD https://codeberg.org/Tuuux/galaxie-shell/src/branch/develop/glxshell/lib/ush.py#L160 After have succes the pipe on CMD i have take a look on CMD2 but i lake knowledge about CMD2 Any feedback or assistance anout CMD2 integration is welcome |
Well this sucks, I was all ready to integrate cmd2 into a project, with grandiose ideas of allowing piping from one command to another in a modularized data manipulation library. Naturally I thought doing something like |
There is another option you might consider, which would not require any changes to cmd2, and which may be similar enough to the stdin/stdout thing that you could make it work. You can create a series of commands in |
Hello, In fact on a True POSIX Pipe only frist and last command work on the true STDIN / STDOUT of the source executor... That really simple, it have Two function
The code is really simple i reput here: care about it line: the sub process run function is POSIX one, then acces a env (where actual os.environ is copy of it parent env). That is how POSIX want deal with child process you have to copy you env to the child env. That is a big POSIX requirement def onecmd(self, line):
cmd, arg, line = self.parseline(line)
if not line:
return self.emptyline()
if cmd is None:
return self.default("cmd is None for: %s" % line)
self.lastcmd = line
if line == "EOF":
self.lastcmd = ""
if cmd == "":
return self.default("cmd is '' for: %s" % line)
# return self.default(line)
else:
if "|" in line:
return self.run_multiple_commands(line)
else:
return self.run_simple_command(cmd, arg, line)
def run_multiple_commands(self, line):
# save stdin and stdout for restoring later on
s_in, s_out = (0, 0)
s_in = os.dup(0)
s_out = os.dup(1)
# first command takes command from stdin
fdin = os.dup(s_in)
# iterate over all the commands that are piped
for command in line.split("|"):
# fdin will be stdin if it's the first iteration
# and the readable end of the pipe if not.
os.dup2(fdin, 0)
os.close(fdin)
# restore stdout if this is the last command
if command == line.split("|")[-1]:
fdout = os.dup(s_out)
else:
fdin, fdout = os.pipe()
# redirect stdout to pipe
os.dup2(fdout, 1)
os.close(fdout)
# make tasks it use sys.stdin or/and sys.stdout
tmp_cmd, tmp_arg, tmp_line = self.parseline(command)
self.run_simple_command(tmp_cmd, tmp_arg, tmp_line)
# restore stdout and stdin
os.dup2(s_in, 0)
os.dup2(s_out, 1)
os.close(s_in)
os.close(s_out)
def run_simple_command(self, cmd, arg, line):
if hasattr(self, "do_%s" % cmd):
func = getattr(self, "do_%s" % cmd)
return func(arg)
else:
pr = subprocess.run(line.split(" "), env=self.environ)
self.exit_code = pr.returncode Regards |
One feature of a "normal" shell that
cmd2
applications are currently missing is the ability for acmd2
command to pipe output to othercmd2
commands - it is limited to piping output to shell commands only. Occasionally this limitation feels significant. I know it can be worked around by creating a custom Python script and using therun_pyscript
command to run that, but it would be much more natural if we could just pipe output to other cmd2 commands.I have no idea how easy or difficult implementing this feature might be. But we should at least explore the possibility.
This would be a great "big new feature" to include in a 2.0 release.
The text was updated successfully, but these errors were encountered: