view NOTES @ 9:822a2fe5bb51

move command window to separate file and other refactoring
author John W. Eaton <jwe@octave.org>
date Thu, 23 May 2019 12:36:26 -0400
parents 52c033864347
children bfa9aaa2d608
line wrap: on
line source

To build:

  qmake calc.pro
  make

Current terminal widget:

  * Run Octave in a separate thread.  On unixy, interact through pty.
    On Windows systems, use hidden console and mirror contents in Qt
    widget.

    Octave interpreter sees input directly, same as for normal
    terminal application.  Good, because no change in the way Octave
    accepts and parses input.  Bad because GUI is not in control of
    input and must arrange to communicate across threads.

    Terminal window can (in theory) be used to run other applications
    started from the system command (for example).  This feature works
    well enough for us to use less running as a separate process to
    handle paging output, but it doesn't work for all applications.
    For example, I am not able to run editors like Emacs or vi in the
    GUI terminal window.

    To make less work as the pager on Unixy systems, the Octave must
    fork, call setsid in the child to detach from the controlling
    terminal, and then exec the GUI.

    GUI must deal with threads when communicating with the
    interpreter.

Proposal:

  * GUI terminal widget is in control of input.

    Use callback interface for readline to handle command line
    editing.

    Use push parser to parse lines as they become available.  Push
    parser will return status of parse, either complete or needing
    more input.

    Uses the following readline callbacks to manage input and update
    the display.  We may need more in the future to handle other
    features.

      rl_getc_function
      rl_redisplay_function
      rl_completion_display_matches_hook

      rl_prep_term_function (do nothing)
      rl_deprep_term_function (do nothing)

   Call rl_callback_handler_install to setup readlines
   callback mode.  This sets the initial prompt and provides a pointer
   to a function that readline should call when a complete line of
   input is available.

   Call rl_callback_read_char when a character is available for
   readline to handle.  We currently store the character to read in a
   global value, then rl_get_function returns that character to
   readline.

   Call rl_callback_handler_remove when shutting down.

   To avoid global variables, it would be helpful if we could use
   lambda functions/functors as callbacks instead of plain C function
   pointers.

Questions:

  * With this arrangement, would the interpreter have to run in a
    separtae thread?

  * Example parser currently computes results
    immediately.  How do we deal with parsing multiple expressions and
    statements with this method?

  * Do we need text position markers to keep track of the prompt position
    (beginning of current line) when inserting or clearing text?


readline callback functions:

// -- Variable: rl_getc_func_t * rl_getc_function
//     If non-zero, Readline will call indirectly through this pointer to
//     get a character from the input stream.  By default, it is set to
//     `rl_getc', the default Readline character input function (*note
//     Character Input::).

// -- Variable: rl_voidfunc_t * rl_redisplay_function
//     If non-zero, Readline will call indirectly through this pointer to
//     update the display with the current contents of the editing buffer.
//     By default, it is set to `rl_redisplay', the default Readline
//     redisplay function (*note Redisplay::).

// -- Variable: rl_vintfunc_t * rl_prep_term_function
//     If non-zero, Readline will call indirectly through this pointer to
//     initialize the terminal.  The function takes a single argument, an
//     `int' flag that says whether or not to use eight-bit characters.
//     By default, this is set to `rl_prep_terminal' (*note Terminal
//     Management::).

// -- Variable: rl_voidfunc_t * rl_deprep_term_function
//     If non-zero, Readline will call indirectly through this pointer to
//     reset the terminal.  This function should undo the effects of
//     `rl_prep_term_function'.  By default, this is set to
//     `rl_deprep_terminal' (*note Terminal Management::).

// -- Function: void rl_callback_handler_install (const char *prompt,
//          rl_vcpfunc_t *lhandler)
//     Set up the terminal for readline I/O and display the initial
//     expanded value of PROMPT.  Save the value of LHANDLER to use as a
//     function to call when a complete line of input has been entered.
//     The function takes the text of the line as an argument.

// -- Function: void rl_callback_read_char (void)
//     Whenever an application determines that keyboard input is
//     available, it should call `rl_callback_read_char()', which will
//     read the next character from the current input source.  If that
//     character completes the line, `rl_callback_read_char' will invoke
//     the LHANDLER function saved by `rl_callback_handler_install' to
//     process the line.  Before calling the LHANDLER function, the
//     terminal settings are reset to the values they had before calling
//     `rl_callback_handler_install'.  If the LHANDLER function returns,
//     the terminal settings are modified for Readline's use again.
//     `EOF' is  indicated by calling LHANDLER with a `NULL' line.

// -- Function: void rl_callback_handler_remove (void)
//     Restore the terminal to its initial state and remove the line
//     handler.  This may be called from within a callback as well as
//     independently.  If the LHANDLER installed by
//     `rl_callback_handler_install' does not exit the program, either
//     this function or the function referred to by the value of
//     `rl_deprep_term_function' should be called before the program
//     exits to reset the terminal settings.

// -- Variable: rl_compdisp_func_t * rl_completion_display_matches_hook
//     If non-zero, then this is the address of a function to call when
//     completing a word would normally display the list of possible
//     matches.  This function is called in lieu of Readline displaying
//     the list.  It takes three arguments: (`char **'MATCHES, `int'
//     NUM_MATCHES, `int' MAX_LENGTH) where MATCHES is the array of
//     matching strings, NUM_MATCHES is the number of strings in that
//     array, and MAX_LENGTH is the length of the longest string in that
//     array.  Readline provides a convenience function,
//     `rl_display_match_list', that takes care of doing the display to
//     Readline's output stream.  That function may be called from this
//     hook.