It looks like we need to implement the ignore-eof option as an Input decorator.
The key point is that the option should only be effective for input from a terminal, and that we need to access the FD to test if the input is actually from the terminal.
It might be helpful to mention the decorator in the documentation comment for the interactive_read_eval_loop function (which is being implemented at the time of writing).
Unresolved questions:
[x] How do we test if the input is from a terminal? Directly extend the FdReader? Share the FD and system with the decorator? Share the FdReader instance with the decorator?
Share the FD and system between FdReader and the ignore-eof decorator.
Having an access to the FdReader in the decorator (either by direct composition or sharing by Rc) would be a bit awkward because the behavior of the decorator is not directly related with that of FdReader.
Sharing the FdReader instance by Rc would not be optimal because we would be making a double sharing layer.
[x] How can the lexer and parser continue to the next line after an EOF? Do we need some mechanism to reset the parser?
[x] If the Input object does not return to the lexer on an EOF and restarts reading the next line, can we avoid modifying the lexer or parser?
Yes, handling the EOF situation inside Input implementors keeps the lexer and parser from modifications. It's more coherent than scattering code fragments implementing the ignore-eof semantics around many modules in the yash-syntax crate.
When an Input instance returns an empty line, the LexerCore updates its InputState to EndOfInput, and the Input::next_line method will never be called after that. To make the lexer restartable, we would need to make it possible to revert the InputState to Alive. We would also need to reset the Token stored in the Parser so that it can continue parsing more tokens.
[x] On EOF, a warning message like "you need to type exit to quit the shell" should be printed. However, mentioning the exit built-in in the message in a hard-coded manner reduces the reusability of the implementation. Should we add a parameter to make the message configurable? Can we work around this issue by implementing the decorator in the yash-cli crate (which is not intended to be reusable)?
Implement the decorator in yash-env with a configurable error message and define the actual message in yash-cli when instantiating the decorator.
[x] What module is the best place for implementing the new decorator in?
It looks like we need to implement the ignore-eof option as an
Input
decorator.The key point is that the option should only be effective for input from a terminal, and that we need to access the FD to test if the input is actually from the terminal.
It might be helpful to mention the decorator in the documentation comment for the
interactive_read_eval_loop
function (which is being implemented at the time of writing).Unresolved questions:
FdReader
? Share the FD and system with the decorator? Share theFdReader
instance with the decorator?FdReader
and the ignore-eof decorator.FdReader
in the decorator (either by direct composition or sharing byRc
) would be a bit awkward because the behavior of the decorator is not directly related with that ofFdReader
.FdReader
instance byRc
would not be optimal because we would be making a double sharing layer.Input
object does not return to the lexer on an EOF and restarts reading the next line, can we avoid modifying the lexer or parser?Input
implementors keeps the lexer and parser from modifications. It's more coherent than scattering code fragments implementing the ignore-eof semantics around many modules in theyash-syntax
crate.Input
instance returns an empty line, theLexerCore
updates itsInputState
toEndOfInput
, and theInput::next_line
method will never be called after that. To make the lexer restartable, we would need to make it possible to revert theInputState
toAlive
. We would also need to reset theToken
stored in theParser
so that it can continue parsing more tokens.exit
to quit the shell" should be printed. However, mentioning the exit built-in in the message in a hard-coded manner reduces the reusability of the implementation. Should we add a parameter to make the message configurable? Can we work around this issue by implementing the decorator in the yash-cli crate (which is not intended to be reusable)?yash-env
with a configurable error message and define the actual message inyash-cli
when instantiating the decorator.