mirror of
https://github.com/go-sylixos/elvish.git
synced 2024-12-12 17:27:50 +08:00
Replace prclose
and pwclose
with file:close
Rather than having specialized commands make a `file:pipe` object indexable so we can use the generic `file:close` command. This does not address existing problems; such as builtins not failing when writing to a `file:pipe` object if the read-end is closed. Related #1316
This commit is contained in:
parent
4717debfec
commit
3ded2fb772
|
@ -33,6 +33,9 @@ or compiled, even if it is not executed:
|
|||
- The `fopen` and `fclose` commands are deprecated. Use `file:open` and
|
||||
`file:close` instead.
|
||||
|
||||
- The `prclose` and `pwclose` commands are deprecated. Use `file:close`
|
||||
instead.
|
||||
|
||||
# Notable bugfixes
|
||||
|
||||
- Iterating over certain list slices no longer crash Elvish
|
||||
|
|
|
@ -132,9 +132,9 @@ func (cp *compiler) checkDeprecatedBuiltin(name string, r diag.Ranger) {
|
|||
case "pipe~":
|
||||
msg = `the "pipe" command is deprecated; use "file:pipe" instead`
|
||||
case "prclose~":
|
||||
msg = `the "prclose" command is deprecated; use "file:prclose" instead`
|
||||
msg = `the "prclose" command is deprecated; use "file:close $p[r]" instead`
|
||||
case "pwclose":
|
||||
msg = `the "pwclose" command is deprecated; use "file:pwclose" instead`
|
||||
msg = `the "pwclose" command is deprecated; use "file:close $p[w]" instead`
|
||||
default:
|
||||
return
|
||||
}
|
||||
|
|
|
@ -10,11 +10,9 @@ import (
|
|||
var Ns = eval.NsBuilder{}.AddGoFns("file:", fns).Ns()
|
||||
|
||||
var fns = map[string]interface{}{
|
||||
"close": close,
|
||||
"open": open,
|
||||
"pipe": pipe,
|
||||
"prclose": prclose,
|
||||
"pwclose": pwclose,
|
||||
"close": close,
|
||||
"open": open,
|
||||
"pipe": pipe,
|
||||
}
|
||||
|
||||
//elvdoc:fn open
|
||||
|
@ -64,16 +62,16 @@ func close(f vals.File) error {
|
|||
// file:pipe
|
||||
// ```
|
||||
//
|
||||
// Create a new Unix pipe that can be used in redirections.
|
||||
//
|
||||
// A pipe contains both the read FD and the write FD. When redirecting command
|
||||
// input to a pipe with `<`, the read FD is used. When redirecting command output
|
||||
// to a pipe with `>`, the write FD is used. It is not supported to redirect both
|
||||
// input and output with `<>` to a pipe.
|
||||
// Create a new pipe that can be used in redirections. A pipe contains a read-end and write-end.
|
||||
// Each pipe object is a [pseudo-map](#pseudo-map) with fields `r` (the read-end [file
|
||||
// object](./language.html#File)) and `w` (the write-end).
|
||||
|
||||
// When redirecting command input from a pipe with `<`, the read-end is used. When redirecting
|
||||
// command output to a pipe with `>`, the write-end is used. Redirecting both input and output with
|
||||
// `<>` to a pipe is not supported.
|
||||
//
|
||||
// Pipes have an OS-dependent buffer, so writing to a pipe without an active reader
|
||||
// does not necessarily block. Pipes **must** be explicitly closed with `prclose`
|
||||
// and `pwclose`.
|
||||
// does not necessarily block. Pipes **must** be explicitly closed with `file:close`.
|
||||
//
|
||||
// Putting values into pipes will cause those values to be discarded.
|
||||
//
|
||||
|
@ -85,42 +83,14 @@ func close(f vals.File) error {
|
|||
// ~> head -n1 < $p
|
||||
// lorem ipsum
|
||||
// ~> put 'lorem ipsum' > $p
|
||||
// ~> head -n1 < $p
|
||||
// # blocks
|
||||
// # $p should be closed with prclose and pwclose afterwards
|
||||
// ~> file:close $p[w] # close the write-end
|
||||
// ~> head -n1 < $p # blocks unless the write-end is closed
|
||||
// ~> file:close $p[r] # close the read-end
|
||||
// ```
|
||||
//
|
||||
// @cf prclose pwclose
|
||||
// @cf close
|
||||
|
||||
func pipe() (vals.Pipe, error) {
|
||||
r, w, err := os.Pipe()
|
||||
return vals.NewPipe(r, w), err
|
||||
}
|
||||
|
||||
//elvdoc:fn prclose
|
||||
//
|
||||
// ```elvish
|
||||
// file:prclose $pipe
|
||||
// ```
|
||||
//
|
||||
// Close the read end of a pipe.
|
||||
//
|
||||
// @cf pwclose pipe
|
||||
|
||||
func prclose(p vals.Pipe) error {
|
||||
return p.ReadEnd.Close()
|
||||
}
|
||||
|
||||
//elvdoc:fn pwclose
|
||||
//
|
||||
// ```elvish
|
||||
// file:pwclose $pipe
|
||||
// ```
|
||||
//
|
||||
// Close the write end of a pipe.
|
||||
//
|
||||
// @cf prclose pipe
|
||||
|
||||
func pwclose(p vals.Pipe) error {
|
||||
return p.WriteEnd.Close()
|
||||
}
|
||||
|
|
|
@ -14,19 +14,37 @@ func TestFile(t *testing.T) {
|
|||
}
|
||||
_, cleanup := testutil.InTestDir()
|
||||
defer cleanup()
|
||||
|
||||
TestWithSetup(t, setup,
|
||||
That(
|
||||
"echo haha > out3", "f = (file:open out3)",
|
||||
"slurp < $f", "file:close $f").Puts("haha\n"),
|
||||
That(`
|
||||
echo haha > out3
|
||||
f = (file:open out3)
|
||||
slurp < $f
|
||||
file:close $f
|
||||
`).Puts("haha\n"),
|
||||
|
||||
That(`p = (file:pipe)`, `echo haha > $p `, `pwclose $p`,
|
||||
`slurp < $p`, `prclose $p`).Puts("haha\n"),
|
||||
That(`
|
||||
p = (file:pipe)
|
||||
echo haha > $p
|
||||
file:close $p[w]
|
||||
slurp < $p
|
||||
file:close $p[r]
|
||||
`).Puts("haha\n"),
|
||||
|
||||
That(`p = (file:pipe)`, `echo Zeppelin > $p`, `file:pwclose $p`,
|
||||
`echo Sabbath > $p`, `slurp < $p`, `file:prclose $p`).Puts("Zeppelin\n"),
|
||||
That(`
|
||||
p = (file:pipe)
|
||||
echo Zeppelin > $p
|
||||
file:close $p[w]
|
||||
echo Sabbath > $p
|
||||
slurp < $p
|
||||
file:close $p[r]
|
||||
`).Puts("Zeppelin\n"),
|
||||
|
||||
That(`p = (file:pipe)`, `echo Legolas > $p`, `file:prclose $p`,
|
||||
`slurp < $p`).Throws(AnyError),
|
||||
That(`
|
||||
p = (file:pipe)
|
||||
echo Legolas > $p
|
||||
file:close $p[r]
|
||||
slurp < $p
|
||||
`).Throws(AnyError),
|
||||
)
|
||||
|
||||
}
|
||||
|
|
|
@ -44,3 +44,14 @@ func (p Pipe) Hash() uint32 {
|
|||
func (p Pipe) Repr(int) string {
|
||||
return fmt.Sprintf("<pipe{%v %v}>", p.ReadEnd.Fd(), p.WriteEnd.Fd())
|
||||
}
|
||||
|
||||
// Index returns the desired pipe endpoint that satisfies a reference such as `$p[r]`.
|
||||
func (p Pipe) Index(k interface{}) (interface{}, bool) {
|
||||
switch k {
|
||||
case "r":
|
||||
return p.ReadEnd, true
|
||||
case "w":
|
||||
return p.WriteEnd, true
|
||||
}
|
||||
return nil, false
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user