New command window widget

I’m attaching a very simple proof-of-concept patch for a new command window widget for the GUI. It is not at all ready for serious use, but I wanted to try to work out the details of how Octave should start when the GUI gathers input and passes it to the interpreter, especially when entering partial input (like a FOR loop over several lines of input). There are a probably a lot of other issues to work out, but this patch could be a good starting point.

Some notes:

  • It uses a simple QLineEdit widget to accept input one line at a time and a separate QTextBrowser widget to display output. Input lines are also echoed in the output window, prefixed with a marker. I’m not suggesting that this is what the new terminal should look like. It was just convenient to build it this way for experimentation given my limited Qt skills.

  • The GUI is currently not using readline. Even if we do eventually use readline for command editing in the GUI widget, we will use it in “callback mode”. So instead of having the readline event loop hook function execute callback functions, the interpreter does this job itself. This arrangement also opens the possibility of having the Octave interpreter act as a server that simply processes requests from a client. The server could be working in a separate thread or process from the client.

  • Also as an experiment, I made the CLI work in the same way. So now with this patch, if Octave starts in command line mode it starts a separate thread to gather input and passes that to the interpreter thread for evaluation. Currently, this CLI mode is also not using readline, but that should be fairly simple to fix.

  • Now that we aren’t running “less” in the command window, we don’t need to fork and exec at startup to call setsid. So the startup process is much simpler.

  • It is now possible to start Octave in CLI mode and then start the GUI by executing a command at the prompt (currently __event_manager_start_gui__, but eventually will be hooked up to the “desktop” function for compatibility). Then it is also possible to close the GUI window and return to the CLI. To do that, you must use the system window manager (the [x] on the title bar, for example) to close the window. Executing the “quit” function will quit the interpreter and exit both the CLI and the GUI.

  • If the GUI is started from the CLI, the–enable-experimental-terminal-widgetn the interpreter will be running as a server for both and will accept input from both. I’m not sure whether that is a good thing, so maybe we will want to disable input from the CLI while the GUI is active?

  • Graphics windows are independent of the GUI. So also if running the GUI from the CLI, plot windows are not closed when the GUI window is closed (unless exiting the entire application).

To try this new feature, apply the attached changeset, run bootstrap to update the configure script, and add “–enable-experimental-terminal-widget” to your usual configure options.

new-terminal-diffs.txt (40.7 KB)

1 Like

I remember now that we already have a page on the wiki giving some details about this topic:

The wiki is not a great place for discussion, but this forum may also not be the best for recording issues about the new terminal window widget. Suggestions about where to discuss/record ideas?

Task tracker?
Although I have started some tasks there that are now waiting for other people’s input and I have to conclude that it isn’t quite in everyone’s focus, so to say :slight_smile:

Or maybe the patch tracker.

I gave it try.
‘event_manager_start_gui’ didn’t work (“error: ‘event_manager_start_gui’ undefined near line 1, column 1” that is, I found a “zombie” lt-octave-gui that I didn’ t know how to acess. kill -9 was needed.
But after perusing the patch I found ‘event_manager_start_gui’ and that did work.

Entering the command in a separate line is obviously primitive, think of copying a block of code, but yes this is proof of concept.
Being able to start the GUI from the CLI is a nice thing.
Closing the GUI indeed leaves plots made from the GUI “alive”. But that also goes for e.g., an undocked GUI editor. Trying to edit a file then (only the “Recent files” option is not greyed-out) leads to a core dump.

That’s as far as I got.

Oops, I was a victim of formatting. I edited my original post to use preformatted text markup so it displays __event_manager_start_gui__ correctly.

Yes, I certainly don’t intend this to be the way the terminal will work. It should eventually look like the current terminal. It was just simple for me to do it this way now with my limited Qt skills. The real point is figuring out how communication between the GUI and the Octave “interpreter server” can work.

OK. Well, I haven’t done a lot of testing yet. I expect to do a bit more work on this and periodically post updated patches.

Yeah, that seems like a good place for this. I’ll post future patches there.

I suppose quite a few bug reports can be closed with a reference to that patch report then :slight_smile:

Would a separate branch for the development of this feature be more practicable than exchanging patch files?

Maybe, but I think it’s OK to work with a separate patch until we have something that works. Even then, I intend to preserve the old terminal widget for now with conditionals that will allow configuring Octave to use the old or new widget.

I am currently working on some of the issues in the GUI probably caused by the new GUI startup order. Should these changes go into the same patch or in separate patches on top of your initial patch?

What are the problems? At this point, maybe it’s best to post info here about what’s not working and proposed patches that would be needed in addition to my original experimental patch.


From first tests, I see the following issues:

  • No empty editor tab in visible editor at startup
  • Menu shortcuts in the main window not working
  • Running scripts from the editor
  • Executing commands from the history widget

Or is this working for others and it is my build?

I didn’t attempt to duplicate the signals/slots in the current QTerminal interface so I’m not surprised that these things aren’t working.

Another thing we have to work out is how to handle functions like input that perform user interaction in the terminal window. Previously that automatically worked because stdin/stdout/stderr were all filtered directly through the terminal widget. But I don’t think that will work if we have Octave running as a “server”, possibly across a network connection. So we need to work out some set of signals that can be passed through the event_manager object.

Probably that whole event_manager thing and communication between the GUI and the Octave interpreter needs to be simplified/generalized. See also this topic on the maintainers mailing list that includes some discussion about simplifying the event_manager link between the Octave interpreter and GUI applications:

Naturally, the signal/slot interface of the old terminal does not exist in the new proof of concept. But it is merely the changed startup sequence which, e.g., prevents the main window from executing some initialization code. Before duplicating portions of code, I am going to check how things can be rearranged/simplified in the existing code for being sort of more “compatible” to the new approach.

Qt and event handling aren’t really my area of expertise. So at the moment, I’ll probably not be able to give more support than simple testing (mostly anectodal, but hopefully somewhat useful).
I tried jwe’s patch on Ubuntu 20.10 on top of hg id 4363b185d31f. (It no longer applies cleanly. But easy enough to rebase.)
I started Octave with ./run-octave in CLI mode. After that, I started the GUI with __event_manager_start_gui__. I had to resize the GUI slightly to make it appear properly. Before that it was mostly a black canvas. Maybe a side effect of the missing initialization Torsten was writing about.
I tried to check the persistent figures by executing demo light. I probably shouldn’t have done that because that left the command line in the GUI irresponsive to any further input. That is probably the related to the incomplete user interaction that jwe was hinting at with the input function.
I then closed the GUI hoping to be able to recover from that state on the CLI. And the CLI indeed showed “Press <enter> to continue:”. But the CLI was stuck as well and I had to kill the Octave process.

I also tried by cross-compiling with the patch for Windows: Entering non-ASCII characters (bug #47571) seems to be working with that approach. :+1:
I’m attaching a patch for MXE Octave that adds a new configure option --enable-experimental-terminal-widget (MXE-Octave-commandline-widget.patch (2.6 KB)). The Octave source ball used in MXE Octave needs to be created from an Octave repository with jwe’s patch for that configure option to have any effect.

Please find “attached” a version of the base patch, that applies to the current default branch without conflicts:

new-terminal-diffs-v01.patch (41.8 KB)

Attached a patch on top of the base patch, that uses terminal font and colors from the preferences:

new-terminal-diffs__addon_01.patch (11.0 KB)

After changeset you can start the new terminal widget by using the command line options --experimental-terminal-widget --gui. Please note the following (from the commit message):

This changeset provides a new experimental proof-of-concept cross-platform command window. It is intended to demonstrate how communication between the GUI command window and the Octave interpreter can work when the GUI is completely responsible for user input instead of having the interpreter wait for input inside readline.

This initial implementation uses a simple text box for input and a separate text edit area for output. This design is not intended to be the final arrangement, but was easy to implement for demonstration purposes. These changes also make it possible to run the command-line version of Octave in a similar client-server mode with a function gathering input in one thread and the Octave intepreter running in another.

The new command window is not intended to provide a general-purpose terminal window. So running something like “system (‘emacs’)” will not bring up an instance of Emacs running in the command window. This also means that it will no longer be possible to use an external output pager such as “less” in the command window. OTOH, it is also no longer necessary to fork and exec a separate process on some Unixy systems when Octave starts solely to give up the controlling terminal so that “less” will function properly.

With the new terminal window, it is now possible to start Octave in command line mode and later open the GUI desktop window and then return to the command line when the GUI window is closed.

Some things that need to be finished:

  • Merge the input and output windows so that command input and output are interleaved as they are in a normal command window.

  • Provide real readline command editing in the GUI command window and at the client-server CLI prompt. We can use the readline callback interface for the GUI and the normal readline interface for the CLI. With this design, the command widget and the CLI front end hold a copy of the command history. They do not need to communicate with the interpreter to navigate the command history.

  • Create interpreter_event messages for handling user input so that the interpreter can ask the GUI to gather user input for functions like “input”.

  • Consider passing results back to the command widget as octave_value objects and allowing the command widget to format and display them instead of passing formatted text from the interpreter to the command widget.

  • Provide an output pager feature for the GUI command window? Maybe this feature is not necessary since we have scroll bars in the GUI and we can also have the GUI ask the user whether to display output if it is large.

is there something short of a full pager that would optionally just provide a ‘press Enter to continue’ when the output spans more than the current number of display lines?

I’m sure we could add simple pager-like features to the command window widget that would allow partial output to be displayed and remaining output to be discarded.