elves / elvish

Powerful scripting language & versatile interactive shell

Home Page:https://elv.sh/

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Augment `file:open` to allow cloning a file object

krader1961 opened this issue · comments

A discussion earlier today on the chat channel caused me to notice there isn't a way to clone a file object. In particular you can't capture the current stdout file object doing this:

var log-file = (file:open /dev/stdout)

That is because the output capture changes what /dev/stdout refers to and isn't portable.

The original context was an Elvish user who has a function which outputs values they want to capture and log messages to the byte stream they do not want to capture. Here is a stylized example of what they were trying to do using I/O redirection to make it work:

> try { var v = (put 1; echo test >&3) 3>&1 } catch e { }
test

There are problems with using I/O redirection to make that work. First, it's clumsy and hard to discover how to do correctly. Second, they sometimes want the logged output to go to a file so now you have to change all the 3>&1 expressions to 3>log-file. Third, having to do it everywhere you use commands that write log messages to stdout you don't want to capture is very annoying. My proposal is to enhance file:open to accept a literal special source syntax. For example:

> var log-out = (file:open &3) 3>&1
> try { var v = (put 1; echo test >$log-out) } catch e { }
test

That example can also be improved further by defining a log function that captures the log-out variable then using that rather than echo. See also #247.