Architecture of Command-Line Interface prototype¶
Class diagram (created with Visual Paradigm
):
The main class is
cli.shell.Shell
.It prompts user for an input, then passes it to a
cli.preprocessor.Preprocessor
.Then, the preprocessed string goes to
cli.lexer.Lexer
.After that, lexems are parsed by
cli.parser.Parser
.These three steps are clearly separated and are testable by themselves.
Parser makes a
cli.commands.RunnableCommand
out of stream of lexems.cli.commands.RunnableCommand
represents a command (in broad sense), sothat
echo
, wc
, assignment and others, as well as pipes havetheir respective class counterparts. The former must inherit from
cli.commands.SingleCommand
,the latter - from
cli.commands.CommandChain
.Commands run in an environment. It is represented by
cli.environment.Environment
.Commands read from
cli.streams.InputStream
-s and write to cli.streams.OutputStream
.When a pipe is processed, the first command’s OutputStream is converted to the second command’s InputStream.
RunnableCommand provides a simple interface to run a command, given
cli.streams.InputStream
and cli.environment.Environment
. The returnedvalue is
cli.commands.RunnableCommandResult
, which is an abstraction on return value.Each command (like
echo
and exit
) is implemented as a separate classin
cli.commands
or cli.single_command
. This allows easy extension.On the other hand, commands do not know about each other, so they need to implement
their argument parsing by themselves.
Commands interact with each other using return codes. One exception from this rule
is
exit
command - it throws cli.exceptions.ExitException
on run,so that shell can exit immediately.