Way back in January 2012, I
posted the following message about changing the terminal widget
in the GUI to handle input differently.
http://lists.gnu.org/archive/html/octave-maintainers/2012-01/msg00416.html
I included a simple example written with gtkmm to illustrate the
idea of having the terminal widget in the GUI be in control of
input and output and feed lines of text to the interpreter. To
properly handle input that spans multiple lines, a push parser
is used instead of the current pull parser. It worked as an
example, but was not much help for Octave since we are using
Qt. So now I've reworked it using Qt and you can find my
sources here:
http://hg.octave.org/jwe-qt-gui-with-push-parser
See the NOTES file for build instructions. That file also
contains the following list of open questions that will need to
be resolved if we are going to attempt a switch.
* With this arrangement, would the interpreter have to run in
a separate thread? As the example shows, it's not absolutely
necessary. It could offer some advantages, but only if it is
possible for the GUI to do useful things while the interpreter
is busy.
* If the interpreter is not running in a separate thread but
but the graphics engine is, then what happens to graphics
callbacks when the parser is in the middle of parsing an
_expression_? Or is this not an issue because separate parsers
can be used even if there is only one evaluator? Could it
ultimately be possible to have the evaluator running in multiple
threads?
* If the interpreter does run in a separate thread, we still
must wait for it to calculate and return a result so we can
synchronize input and output. Otherwise, we may print the next
prompt before the output from the previous _expression_ is
evaluated and printed. You'll see this behavior if you build
the example program with CALC_USE_INTERPRETER_THREAD defined.
* The example parser currently also performs evaluations and
computes results immediately so it doesn't properly handle
_expression_ lists that are split across multiple lines. Octave
wouldn't have this problem because we already build a parse tree
then execute it once it is complete.
* Do we need text position markers to keep track of the prompt
position (beginning of current line) when inserting or clearing
text? This doesn't seem necessary in the current example, but it
doesn't have functions that can clear the screen or otherwise
redraw prior output that would cause the position of the cursor
in the window to change.
* The example program doesn't attempt handle multi-line
prompts or prompts with invisible characters (color
specifications, for example). Fixing that will make the
redisplay function significantly more complex. See, for
example, how complicated the default rl_redisplay function is in
the readline library. Unless we actually write a terminal
emulator (like the current terminal widgets) then it is not
possible to use readline's rl_redisplay function directly.
* We'll need to implement a pager ourselves, since "less"
won't work in this simplified terminal widget.
* The system function may need to be modified so that external
programs that expect to be running in a terminal will continue
to work properly. On Unixy systems, this job can be done with
ptys. I guess Windows systems can use a hidden console? But if
these things are required, are we more or less back to were we
were before since we used a pty and hidden console to implement
the terminal widgets? I believe the Emacs start-process
function must do similar things, so we might be able to reuse
that code.
* If readline runs in the terminal widget, who owns the
command-line history? Either way, if the GUI is in control of
keyboard input, it will need access to the history list and
Octave will also need access for the history functions.
Now that I have an almost working (if quite simplistic) example
in Qt, I will attempt to modify Octave to use this approach.
From that, I expect many more questions to come up.
jwe