How do you set up cliv2 for command line inputs $ cli_command < input.txt > output.txt
wakatara opened this issue · comments
I'm re-writing an old fortran 77 piece of code into Go. The scientists are used to using it like:
water < input_file.txt
and then having it walk them through the command parameters it needs (druid style).
I googled and looked and can't seem to find any documentation on how to accomplush that (though assume if I make the input file the first expected argument it might work? I thought I should ask the question since I haven't seen it mentioned anywhere in the docs (or missed it totally) and I imagine other people might want to find this for the google juice it gives.
thanks!
PS> I've already used cliv2 to write one of my long standing little cli apps, harsh and it's been great, so just wanted to say thanks for writing a simple, easy to use framework that doesn't overcomplicate. I prefer cliv2 over all the alternatives I evaluated.
@wakatara There are multiple ways to do this
cat input_file.txt | xargs water
or
water $(< input_file.txt )
Hmmm... interesting. Thanks for the quick response. Is there any way to support the water < input_file.txt
convention? Mostly because it is a learned behaviour amongst the science folks I am dealing with, and I imagine any deviation from what they're used to is gonna cause moans.
Out of curiosity, is there any way to have the cli v2 handle that argument syntax in the future? (I find most people do not know how to use xargs but are familiar with the < > and | operators. Also, I have to admit... I would not even have guessed at the
water $(< input_file.txt )
Have never seen that one before, myself. (though am not exactly a bash expert.... :-/ ).
@wakatara I guess that the
water < input_file.txt
works on Windows/DOS cmdline ? otherwise you are going against Unix/Bash conventions. Here are some options https://stackoverflow.com/questions/6980090/how-to-read-from-a-file-or-standard-input-in-bash
cli v2 will definitely not support this. If you'd like it can be considered for v3
No, this is totally how it gets done on linux/unix, I mean... with almost every utility I've ever used. Something like:
$ water < input.txt > output.txt
is very common afaik. And certainly in science with most cli apps.
Would love for it to be considered for v3. I have to admit I thought it was strange it did not work that way.
Wy do you say it goes against unix/bash conventions. I mean, I think I've used this pattern with cli apps for over 20 years. cliv2 not supporting it surprised me.
Ah sorry yes it is the unix way :headslap . But the intent of the <
operator is different. The <
operator sends the contents of the file to stdin of the process. Thats different from the args that the process consumes. Here is an example
$ cat > ~/scratch/tmp.args
-al
$ ls < ~/scratch/tmp.args
go.mod go.sum main.go
$ ls -al
total 20
drwxr-xr-x 2 foo foo 4096 May 16 10:45 .
drwxr-xr-x 55 foo foo 4096 May 16 10:41 ..
-rw-r--r-- 1 foo foo 335 May 16 14:18 go.mod
-rw-r--r-- 1 foo foo 764 May 16 10:47 go.sum
-rw-r--r-- 1 foo foo 650 May 16 10:47 main.go
$ ls < ~/scratch/tmp.args
go.mod go.sum main.go
@wakatara I've been thinking about this a bit more. You can have your cli app do this
app := &App{...}
b, err := io.ReadAll(os.Stdin)
if err != nil {
panic(err)
}
app.Run(strings.Split(string(b), "\n"))
That should give you the behavior you want.
Hmmm... this looks good! I am just about to try it out and see if it works in a bit.
Just a question though... if I am rewriting this app (cause the original fortran 77 code won't even compile on a modern fortran compiler anymore... 8-// ), so that I am using a combo of switches and want to use directed input:
$ sublimate --volitile 18.0 --albedo 0.04 --radius 1000 --phasefunc 0.04 < input.txt
I am assuming this approach does not work? (have not tried it, but that's kinda where I want to take the new cli.
PS> Omg though. Thanks so much for continuing to think about this and taking a shot at it. I would not have thought of that approach tbh.
This should give you the behavior you want
args := []string{}
app := &App{...}
b, err := io.ReadAll(os.Stdin)
if err != nil {
panic(err)
}
split_input = strings.Split(string(b), "\n")
args = append(args, os.Args...)
args = append(args, split_input...)
app.Run(args)
@wakatara I am closing this for now since there are no changes on urfave/cli for this.
This should give you the behavior you want
args := []string{} app := &App{...} b, err := io.ReadAll(os.Stdin) if err != nil { panic(err) } split_input = strings.Split(string(b), "\n") args = append(args, os.Args...) args = append(args, split_input...) app.Run(args)
This looks great. I am quite sure I would not have puzzled this out. Thanks so much. Would love to see this baked into v3 though!
Awesome. Sounds amazing. 😁
Woo!! Thank you! Excellent timing as I am working on something for this (and an older app based on v2 over xmas. =]
Thanks for all your work on this!
@dearchap Just checked version numbers on the repo. When are you thinking of cutting the 3.0 release?