Closed suntong closed 7 years ago
Works like a charm, as always, and super fast fix as well. :-) :+1:
Oh, I need a function/field that exposes the file-handle (io.Reader & io.Writer) for me to read/write files myself. Thanks.
It's a io.Reader/io.Writer in itself.
clix.Reader
implements io.Reader
// Read implementes io.Reader
func (r Reader) Read(data []byte) (n int, err error)
And, clix.Writer
implments io.Writer
// Write implementes io.Writer interface
func (w *Writer) Write(data []byte) (n int, err error)
oh, let me look at it... Thanks!
Hmm... my function is expecting a w io.Writer
parameter, can I pass a clix.Writer
variable e.g., argv.Writer
on https://github.com/mkideal/cli/blob/master/_examples/029-writer/main.go#L18, to the function? My Go knowledge on this part is blurred.
Of course. See io.Writer
:
// Writer is the interface that wraps the basic Write method.
//
// Write writes len(p) bytes from p to the underlying data stream.
// It returns the number of bytes written from p (0 <= n <= len(p))
// and any error encountered that caused the write to stop early.
// Write must return a non-nil error if it returns n < len(p).
// Write must not modify the slice data, even temporarily.
//
// Implementations must not retain p.
type Writer interface {
Write(p []byte) (n int, err error)
}
Oh, thanks for going the whole nine yards explaining it. My Go knowledge is really blurred on this part, your confirmation really helps.
😄 ,I just copy the go standard source code from go1.6/src/io/io.go
Can you add a function Name()
to give the file name please, for both Reader and Writer. Thx.
Oh, and better an indicator for the user to know whether they are rw to stdio or files as well please.
Hmm... on second thought, maybe when Name()
return nil
it means dealing with stdio?
hmm... sorry to bother you with some of my own code:
This is the code I'm porting from another go cli option package to cli:
fileo := argv.Fileo
if fileo == nil {
var err error
fileo, err = os.Create(
strings.Replace(argv.Filei.Name(), ".extold", ".extnew", 1))
check(err)
}
Basically, the code takes a mandatory input file, argv.Filei
, but the output file argv.Fileo
is optional, if it is not provided, build it from the name of input file.
Both the argv.Filei
and argv.Fileo
were of type *os.File
before, but now, I'm getting:
cannot convert nil to type ext.Writer
argv.Filei.Name undefined (type ext.Reader has no field or method Name)
cannot assign *os.File to fileo (type ext.Writer) in multiple assignment
cannot use fileo (type ext.Writer) as type io.Writer in argument to myFunc
ext.Writer does not implement io.Writer (Write method has pointer receiver)
What would you think the best way to fix it? Sorry for not being able to give clearer requirement prevously -- My Go knowledge is really blurred on this part.
Thx!
ext.Writer
is just a io.Writer, not
*os.File`.
fileo, err := os.Creat(strings.Replace(argv.Filei.Name(), ".extold", ".extnew", 1))
check(err)
argv.Fileo.SetWriter(fileo)
OMG!!! It's 2:30am your time right?
OK. that part is fixed. One more to go -- my function is expecting a w io.Writer parameter, but I cannot pass a clix.Writer variable:
cannot use fileo (type ext.Writer) as type io.Writer in argument to myFunc
ext.Writer does not implement io.Writer (Write method has pointer receiver)
BTW, I've just prepared a small demo file. https://gist.github.com/suntong/cb2bf3d3ada7d7941aac8ef338a815a1#file-dump-go
But don't look at it now. Have some sleep instead. No hurry.
OMG!!! It's 2:30am your time right?
- Yes.
Ah, cannot use fileo (type ext.Writer) as type io.Writer in argument to myFunc ext.Writer does not implement io.Writer (Write method has pointer receiver)
,It's a problem!
Have some rest now. Deal with it tomorrow.
Remember you can start with https://gist.github.com/suntong/cb2bf3d3ada7d7941aac8ef338a815a1#file-dump-go.
Good night.
Filei clix.Reader `cli:"*i,input" usage:"The file to dump from (mandatory)"`
Fileo clix.Writer `cli:"o,output" usage:"The dump output (default: .dump file of input)"`
should be replaced with
Filei *clix.Reader `cli:"*i,input" usage:"The file to dump from (mandatory)"`
Fileo *clix.Writer `cli:"o,output" usage:"The dump output (default: .dump file of input)"`
BTW, Global
of root command must be true, otherwise ctx.RootArgv()
is nil in subcommand!
My God. Alright it works. Now go to bed. :-)
Sleeping? Alright.
Let me whisper my question --
For Writer, if the parameter is optional, how to tell whether it is issued or not?
I've corrected my code according to all your above points. Now I have a code like this:
argv := ctx.Argv().(*dumpT)
if argv.Fileo == nil {
fileo, err := os.Create(
strings.Replace(argv.Filei.Name(), ".extold", ".extnew", 1))
check(err)
argv.Fileo.SetWriter(fileo)
}
fileo := argv.Fileo
Then the fileo
is passed to my function which is expecting a w io.Writer parameter. All are good.
The problem is that when the --output option is not specified, the output was written to stdout instead of my created file. I.e., need to tell whether it is issued or not somehow.
if argv.Fileo == nil
should be if argv.Fileo.IsStdout()
. I my CLI
, Writer
holds os.Stdout
if not specific
Wow, wasn't expecting you reply so soon.
Please rethink your architect, because the above sounds like you cannot tell whether the --output option is not specified, or specified but without a following file parameter.
ctx.IsSet("--output")
determins whether the --output
option is specified.
Perfect! Thx!
ctx.IsSet("--output") determins whether the --output option is specified.
mkideal, that ctx.IsSet
is interfering with the file reading --
take a look at the latest code at
https://gist.github.com/suntong/6658063cc0cf752f5d7ad5cc299f30bd
if ctx.IsSet("--Filei") { // --Filei option is specified
data, _ := ioutil.ReadAll(argv.Filei)
argv.Filei.Close()
//print(data)
dd = string(data)
print(dd)
}
The print
won't print anything, regardless whether get from pipe or from file.
However, if removing the enclosing if ctx.IsSet("--Filei")
call, the program works.
if ctx.IsSet("-i") { // --Filei option is specified
data, _ := ioutil.ReadAll(argv.Filei)
argv.Filei.Close()
//print(data)
dd = string(data)
print(dd)
}
Replace --Filei with -i or --input
Duh. Sorry!
clix.File
allows to read content from file or stdin, does something equivalent exist for write to file or stdout as well?io.Reader
&io.Writer
) for users to read/write files themselves.Thanks