changeset 16572:d5ae5aa80d42

preserve pending command line input when running commands from GUI actions * QTerminal.h, QTerminal.cc (QTerminal::relay_command): Delete. * file-editor-tab.cc (file_editor_tab::run_file_callback): New argument, bp_info. Save pending command line input and execute command. (file_editor_tab::run_file): Use octave_link to execute file. * main-window.h, main-window.cc (main_window::execute_command_in_terminal): Rename from main_window::handle_command_double_clicked. Post event through octave_link to execute command. (main_window::construct_octave_qt_link): Connect _octave_qt_link::execute_command_in_terminal_signal to main_window::execute_command_in_terminal. (main_window::execute_command_callback): New function. (main_window::relay_command_signal): Delete signal. Remove all uses. * octave-qt-link.h, octave-qt-link.cc (octave_qt_link::do_execute_command_in_terminal): New function. (octave_qt_link::execute_command_in_terminal_signal): New signal. * terminal-dock-widget.h, terminal-dock-widget.cc (terminal_dock_widget::relay_command_signal): Delete signal. Remove all uses. * octave-link.h (octave_link::execute_command_in_terminal, octave_link::do_execute_command_in_terminal): New functions. * cmd-edit.h, cmd-edit.cc (command_editor::pre_input_hook_set): New variable. (gnu_readline::previous_pre_input_hook, command_editor::intial_input): New member variables. (command_editor::restore_pre_input_hook, command_editor::do_get_current_line, command_editor::do_replace_line, command_editor::set_pre_input_hook, gnu_readline::do_get_current_line, gnu_readline::do_replace_line, gnu_readline::set_pre_input_hook, command_editor::set_initial_input, gnu_readline::restore_pre_input_hook, default_command_editor::do_get_current_line, default_command_editor::do_replace_line, command_editor::insert_initial_input, command_editor::pre_input_handler, command_editor::get_current_line, command_editor::replace_line, command_editor::add_pre_input_hook, command_editor::do_insert_initial_input, command_editor::set_pre_input_hook, command_editor::restore_pre_input_hook): New functions. (command_editor::readline): Handle initial input. (command_editor::interrupt): Give argument a default value. * oct-rl-edit.h, oct-rl-edit.c (octave_rl_copy_line, octave_rl_replace_line, octave_rl_set_pre_input_hook, octave_rl_get_pre_input_hook): New functions. (rl_pre_input_hook_fcn_ptr): New typedef.
author John W. Eaton <jwe@octave.org>
date Thu, 25 Apr 2013 17:57:55 -0400
parents ab1df81adaa0
children 4d8462fe15b9
files libgui/qterminal/libqterminal/QTerminal.cc libgui/qterminal/libqterminal/QTerminal.h libgui/src/files-dock-widget.cc libgui/src/history-dock-widget.cc libgui/src/m-editor/file-editor-tab.cc libgui/src/m-editor/file-editor-tab.h libgui/src/m-editor/file-editor.cc libgui/src/main-window.cc libgui/src/main-window.h libgui/src/octave-qt-link.cc libgui/src/octave-qt-link.h libgui/src/terminal-dock-widget.cc libgui/src/terminal-dock-widget.h libgui/src/workspace-view.cc libinterp/interpfcn/octave-link.h liboctave/util/cmd-edit.cc liboctave/util/cmd-edit.h liboctave/util/oct-rl-edit.c liboctave/util/oct-rl-edit.h
diffstat 19 files changed, 298 insertions(+), 51 deletions(-) [+]
line wrap: on
line diff
--- a/libgui/qterminal/libqterminal/QTerminal.cc
+++ b/libgui/qterminal/libqterminal/QTerminal.cc
@@ -42,9 +42,3 @@
   else if (cursorType == "underline")
     setCursorType(QTerminalInterface::UnderlineCursor, cursorBlinking);
 }
-
-void
-QTerminal::relay_command (const QString& command)
-{
-  sendText (command);
-}
--- a/libgui/qterminal/libqterminal/QTerminal.h
+++ b/libgui/qterminal/libqterminal/QTerminal.h
@@ -38,7 +38,6 @@
 
     public slots:
         void notice_settings (const QSettings *settings);
-        void relay_command (const QString& text);
     };
 #else
     #include "unix/QUnixTerminalImpl.h"
@@ -52,7 +51,6 @@
 
     public slots:
         void notice_settings (const QSettings *settings);
-        void relay_command (const QString& command);
     };
 #endif
 
--- a/libgui/src/files-dock-widget.cc
+++ b/libgui/src/files-dock-widget.cc
@@ -177,7 +177,7 @@
            this, SLOT (set_current_directory (const QString &)));
 
   connect (this, SIGNAL (run_file_signal (const QString&)),
-           parent (), SLOT (handle_command_double_clicked (const QString&)));
+           parent (), SLOT (execute_command_in_terminal (const QString&)));
 
   QCompleter *completer = new QCompleter (_file_system_model, this);
   _current_directory->setCompleter (completer);
--- a/libgui/src/history-dock-widget.cc
+++ b/libgui/src/history-dock-widget.cc
@@ -48,7 +48,7 @@
            p, SLOT (report_status_message (const QString&)));
 
   connect (this, SIGNAL (command_double_clicked (const QString&)),
-           p, SLOT (handle_command_double_clicked (const QString&)));
+           p, SLOT (execute_command_in_terminal (const QString&)));
 
   construct ();
 }
--- a/libgui/src/m-editor/file-editor-tab.cc
+++ b/libgui/src/m-editor/file-editor-tab.cc
@@ -48,6 +48,8 @@
 #include "file-editor-tab.h"
 #include "file-editor.h"
 
+#include "cmd-edit.h"
+
 #include "builtin-defun-decls.h"
 #include "debug.h"
 #include "load-path.h"
@@ -355,9 +357,21 @@
 
 
 void
-file_editor_tab::run_file_callback (void)
+file_editor_tab::run_file_callback (const bp_info& info)
 {
-  // Maybe someday we will do something here?
+  if (file_in_path (info.file, info.dir))
+    {
+      std::string pending_input = command_editor::get_current_line ();
+
+      command_editor::set_initial_input (pending_input);
+
+      command_editor::replace_line (info.function_name);
+      command_editor::redisplay ();
+
+      // We are executing inside the command editor event loop.  Force
+      // the current line to be returned for processing.
+      command_editor::interrupt ();
+    }
 }
 
 void
@@ -372,15 +386,11 @@
   QFileInfo file_info (_file_name);
   QString dir = file_info.absolutePath ();
   QString function_name = file_info.fileName ();
+  function_name.chop (file_info.suffix ().length () + 1);
 
-  // We have to cut off the suffix, because octave appends it.
-  function_name.chop (file_info.suffix ().length () + 1);
-  emit process_octave_code (QString ("cd \'%1\'\n%2\n")
-                            .arg (dir).arg (function_name));
- 
-  // TODO: Sending a run event crashes for long scripts. Find out why.
-  // octave_link::post_event
-  //   (this, &file_editor_tab::run_file_callback, _file_name.toStdString ()));
+  bp_info info (_file_name, dir, function_name, 1);
+
+  octave_link::post_event (this, &file_editor_tab::run_file_callback, info);
 }
 
 void
--- a/libgui/src/m-editor/file-editor-tab.h
+++ b/libgui/src/m-editor/file-editor-tab.h
@@ -170,7 +170,7 @@
   int check_file_modified ();
   void do_comment_selected_text (bool comment);
 
-  void run_file_callback (void);
+  void run_file_callback (const bp_info& info);
 
   bool file_in_path (const std::string& file, const std::string& dir);
 
--- a/libgui/src/m-editor/file-editor.cc
+++ b/libgui/src/m-editor/file-editor.cc
@@ -1040,7 +1040,7 @@
            this, SLOT (handle_mru_add_file (const QString&)));
 
   connect (f, SIGNAL (process_octave_code (const QString&)),
-           parent (), SLOT (handle_command_double_clicked (const QString&)));
+           parent (), SLOT (execute_command_in_terminal (const QString&)));
   
   // Signals from the file_editor non-trivial operations
   connect (this, SIGNAL (fetab_settings_changed (const QSettings *)),
--- a/libgui/src/main-window.cc
+++ b/libgui/src/main-window.cc
@@ -188,11 +188,12 @@
 }
 
 void
-main_window::handle_command_double_clicked (const QString& command)
+main_window::execute_command_in_terminal (const QString& command)
 {
-  emit relay_command_signal (command);
+  octave_link::post_event (this, &main_window::execute_command_callback,
+                           command.toStdString ());
 
-  command_window->focus ();
+  focus_command_window ();
 }
 
 void
@@ -764,6 +765,10 @@
            this, SLOT (change_directory (QString)));
 
   connect (_octave_qt_link,
+           SIGNAL (execute_command_in_terminal_signal (QString)),
+           this, SLOT (execute_command_in_terminal (QString)));
+
+  connect (_octave_qt_link,
            SIGNAL (set_history_signal (const QStringList&)),
            history_window, SLOT (set_history (const QStringList&)));
 
@@ -1337,6 +1342,21 @@
 }
 
 void
+main_window::execute_command_callback (const std::string& command)
+{
+  std::string pending_input = command_editor::get_current_line ();
+
+  command_editor::set_initial_input (pending_input);
+
+  command_editor::replace_line (command);
+  command_editor::redisplay ();
+
+  // We are executing inside the command editor event loop.  Force
+  // the current line to be returned for processing.
+  command_editor::interrupt ();
+}
+
+void
 main_window::new_figure_callback (void)
 {
   Fbuiltin (ovl ("figure"));
--- a/libgui/src/main-window.h
+++ b/libgui/src/main-window.h
@@ -76,7 +76,6 @@
 
 signals:
   void settings_changed (const QSettings *);
-  void relay_command_signal (const QString&);
   void new_file_signal (const QString&);
   void open_file_signal (const QString&);
 
@@ -109,7 +108,7 @@
   void change_directory_up (void);
   void accept_directory_line_edit (void);
 
-  void handle_command_double_clicked (const QString& command);
+  void execute_command_in_terminal(const QString& dir);
 
   void handle_new_figure_request (void);
 
@@ -195,6 +194,8 @@
 
   void clear_history_callback (void);
 
+  void execute_command_callback (const std::string& command);
+
   void new_figure_callback (void);
 
   void change_directory_callback (const std::string& directory);
--- a/libgui/src/octave-qt-link.cc
+++ b/libgui/src/octave-qt-link.cc
@@ -243,6 +243,12 @@
 }
 
 void
+octave_qt_link::do_execute_command_in_terminal (const std::string& command)
+{
+  emit execute_command_in_terminal_signal (QString::fromStdString (command));
+}
+
+void
 octave_qt_link::do_set_workspace (bool top_level,
                                   const std::list<workspace_element>& ws)
 {
--- a/libgui/src/octave-qt-link.h
+++ b/libgui/src/octave-qt-link.h
@@ -91,6 +91,8 @@
 
   void do_change_directory (const std::string& dir);
 
+  void do_execute_command_in_terminal (const std::string& command);
+
   void do_set_workspace (bool top_level,
                          const std::list<workspace_element>& ws);
 
@@ -134,6 +136,8 @@
 
   void change_directory_signal (const QString& dir);
 
+  void execute_command_in_terminal_signal (const QString& command);
+
   void set_workspace_signal (bool top_level,
                              const QString& scopes,
                              const QStringList& symbols,
--- a/libgui/src/terminal-dock-widget.cc
+++ b/libgui/src/terminal-dock-widget.cc
@@ -44,17 +44,11 @@
   connect (this, SIGNAL (visibilityChanged (bool)),
            this, SLOT (handle_visibility (bool)));
 
-  connect (parent (), SIGNAL (relay_command_signal (const QString&)),
-           this, SLOT (relay_command (const QString&)));
-
   // Forward signals to QTerminal widget.
 
   connect (this, SIGNAL (notice_settings_signal (const QSettings *)),
            terminal, SLOT (notice_settings (const QSettings *)));
 
-  connect (this, SIGNAL (relay_command_signal (const QString&)),
-           terminal, SLOT (relay_command (const QString&)));
-
   connect (this, SIGNAL (copyClipboard_signal (void)),
            terminal, SLOT (copyClipboard (void)));
 
@@ -69,12 +63,6 @@
 }
 
 void
-terminal_dock_widget::relay_command (const QString& command)
-{
-  emit relay_command_signal (command);
-}
-
-void
 terminal_dock_widget::copyClipboard (void)
 {
   emit copyClipboard_signal ();
--- a/libgui/src/terminal-dock-widget.h
+++ b/libgui/src/terminal-dock-widget.h
@@ -43,8 +43,6 @@
 
   void notice_settings (const QSettings *settings);
 
-  void relay_command (const QString& command);
-
   void copyClipboard (void);
 
   void pasteClipboard (void);
@@ -55,8 +53,6 @@
 
   void notice_settings_signal (const QSettings *settings); 
 
-  void relay_command_signal (const QString& command);
-
   void copyClipboard_signal (void);
 
   void pasteClipboard_signal (void);
--- a/libgui/src/workspace-view.cc
+++ b/libgui/src/workspace-view.cc
@@ -75,7 +75,7 @@
            this, SLOT(contextmenu_requested (const QPoint&)));
 
   connect (this, SIGNAL (command_requested (const QString&)),
-           p, SLOT (handle_command_double_clicked (const QString&)));
+           p, SLOT (execute_command_in_terminal (const QString&)));
 }
 
 workspace_view::~workspace_view (void)
--- a/libinterp/interpfcn/octave-link.h
+++ b/libinterp/interpfcn/octave-link.h
@@ -193,6 +193,13 @@
       instance->do_change_directory (dir);
   }
 
+  // Preserves pending input.
+  static void execute_command_in_terminal (const std::string& command)
+  {
+    if (enabled ())
+      instance->do_execute_command_in_terminal (command);
+  }
+
   static void set_workspace (void);
 
   static void set_workspace (bool top_level,
@@ -370,6 +377,8 @@
 
   virtual void do_change_directory (const std::string& dir) = 0;
 
+  virtual void do_execute_command_in_terminal (const std::string& command) = 0;
+
   virtual void
   do_set_workspace (bool top_level,
                     const std::list<workspace_element>& ws) = 0;
--- a/liboctave/util/cmd-edit.cc
+++ b/liboctave/util/cmd-edit.cc
@@ -48,6 +48,8 @@
 
 std::set<command_editor::startup_hook_fcn> command_editor::startup_hook_set;
 
+std::set<command_editor::pre_input_hook_fcn> command_editor::pre_input_hook_set;
+
 std::set<command_editor::event_hook_fcn> command_editor::event_hook_set;
 
 static octave_mutex event_hook_lock;
@@ -66,6 +68,8 @@
 
   typedef command_editor::startup_hook_fcn startup_hook_fcn;
 
+  typedef command_editor::pre_input_hook_fcn pre_input_hook_fcn;
+
   typedef command_editor::event_hook_fcn event_hook_fcn;
 
   typedef command_editor::completion_fcn completion_fcn;
@@ -139,6 +143,10 @@
 
   std::string do_get_line_buffer (void) const;
 
+  std::string do_get_current_line (void) const;
+
+  void do_replace_line (const std::string& text, bool clear_undo);
+
   void do_insert_text (const std::string& text);
 
   void do_newline (void);
@@ -153,6 +161,10 @@
 
   void restore_startup_hook (void);
 
+  void set_pre_input_hook (pre_input_hook_fcn f);
+
+  void restore_pre_input_hook (void);
+
   void set_event_hook (event_hook_fcn f);
 
   void restore_event_hook (void);
@@ -179,6 +191,8 @@
 
   startup_hook_fcn previous_startup_hook;
 
+  pre_input_hook_fcn previous_pre_input_hook;
+
   event_hook_fcn previous_event_hook;
 
   completion_fcn completion_function;
@@ -205,6 +219,7 @@
 
 gnu_readline::gnu_readline ()
   : command_editor (), previous_startup_hook (0),
+    previous_pre_input_hook (0),
     previous_event_hook (0), completion_function (0),
     quoting_function (0), dequoting_function (0),
     char_is_quoted_function (0), user_accept_line_function (0)
@@ -522,6 +537,22 @@
   return ::octave_rl_line_buffer ();
 }
 
+std::string
+gnu_readline::do_get_current_line (void) const
+{
+  std::string retval;
+  char *buf = ::octave_rl_copy_line ();
+  retval = buf;
+  free (buf);
+  return retval;
+}
+
+void
+gnu_readline::do_replace_line (const std::string& text, bool clear_undo)
+{
+  ::octave_rl_replace_line (text.c_str (), clear_undo);
+}
+
 void
 gnu_readline::do_insert_text (const std::string& text)
 {
@@ -568,6 +599,21 @@
 }
 
 void
+gnu_readline::set_pre_input_hook (pre_input_hook_fcn f)
+{
+  previous_pre_input_hook = ::octave_rl_get_pre_input_hook ();
+
+  if (f != previous_pre_input_hook)
+    ::octave_rl_set_pre_input_hook (f);
+}
+
+void
+gnu_readline::restore_pre_input_hook (void)
+{
+  ::octave_rl_set_pre_input_hook (previous_pre_input_hook);
+}
+
+void
 gnu_readline::set_event_hook (event_hook_fcn f)
 {
   previous_event_hook = octave_rl_get_event_hook ();
@@ -767,7 +813,11 @@
 
   std::string do_get_line_buffer (void) const;
 
-  void do_insert_text (const std::string&);
+  std::string do_get_current_line (void) const;
+
+  void do_replace_line (const std::string& text, bool clear_undo);
+
+  void do_insert_text (const std::string& text);
 
   void do_newline (void);
 
@@ -832,6 +882,19 @@
   return "";
 }
 
+std::string
+default_command_editor::do_get_current_line (void) const
+{
+  // FIXME
+  return std::string ();
+}
+
+void
+default_command_editor::do_replace_line (const std::string&, bool)
+{
+  // FIXME
+}
+
 void
 default_command_editor::do_insert_text (const std::string&)
 {
@@ -891,6 +954,19 @@
   instance = new default_command_editor ();
 }
 
+void
+command_editor::set_initial_input (const std::string& text)
+{
+  if (instance_ok ())
+    instance->initial_input = text;
+}
+
+int
+command_editor::insert_initial_input (void)
+{
+  return instance_ok () ? instance->do_insert_initial_input () : 0;
+}
+
 int
 command_editor::startup_handler (void)
 {
@@ -907,6 +983,21 @@
 }
 
 int
+command_editor::pre_input_handler (void)
+{
+  for (pre_input_hook_set_iterator p = pre_input_hook_set.begin ();
+       p != pre_input_hook_set.end (); p++)
+    {
+      pre_input_hook_fcn f = *p;
+
+      if (f)
+        f ();
+    }
+
+  return 0;
+}
+
+int
 command_editor::event_handler (void)
 {
   event_hook_lock.lock ();
@@ -945,8 +1036,17 @@
 std::string
 command_editor::readline (const std::string& prompt, bool& eof)
 {
-  return (instance_ok ())
-    ? instance->do_readline (prompt, eof) : std::string ();
+  std::string retval;
+
+  if (instance_ok ())
+    {
+      if (! instance->initial_input.empty ())
+        add_pre_input_hook (command_editor::insert_initial_input);
+
+      retval = instance->do_readline (prompt, eof);
+    }
+
+  return retval;
 }
 
 void
@@ -1179,6 +1279,19 @@
   return (instance_ok ()) ? instance->do_get_line_buffer () : "";
 }
 
+std::string
+command_editor::get_current_line (void)
+{
+  return (instance_ok ()) ? instance->do_get_current_line () : "";
+}
+
+void
+command_editor::replace_line (const std::string& text, bool clear_undo)
+{
+  if (instance_ok ())
+    instance->do_replace_line (text, clear_undo);
+}
+
 void
 command_editor::insert_text (const std::string& text)
 {
@@ -1240,6 +1353,32 @@
 }
 
 void
+command_editor::add_pre_input_hook (pre_input_hook_fcn f)
+{
+  if (instance_ok ())
+    {
+      pre_input_hook_set.insert (f);
+
+      instance->set_pre_input_hook (pre_input_handler);
+    }
+}
+
+void
+command_editor::remove_pre_input_hook (pre_input_hook_fcn f)
+{
+  if (instance_ok ())
+    {
+      pre_input_hook_set_iterator p = pre_input_hook_set.find (f);
+
+      if (p != pre_input_hook_set.end ())
+        pre_input_hook_set.erase (p);
+
+      if (pre_input_hook_set.empty ())
+        instance->restore_pre_input_hook ();
+    }
+}
+
+void
 command_editor::add_event_hook (event_hook_fcn f)
 {
   octave_autolock guard (event_hook_lock);
@@ -1586,6 +1725,21 @@
   return result;
 }
 
+int
+command_editor::do_insert_initial_input (void)
+{
+  std::string input = initial_input;
+
+  initial_input = "";
+
+  do_insert_text (input);
+
+  // Is it really right to redisplay here?
+  do_redisplay ();
+
+  return 0;
+}
+
 // Return the octal number parsed from STRING, or -1 to indicate that
 // the string contained a bad number.
 
--- a/liboctave/util/cmd-edit.h
+++ b/liboctave/util/cmd-edit.h
@@ -37,12 +37,14 @@
 protected:
 
   command_editor (void)
-    : command_number (0), interrupted (false) { }
+    : command_number (0), interrupted (false), initial_input () { }
 
 public:
 
   typedef int (*startup_hook_fcn) (void);
 
+  typedef int (*pre_input_hook_fcn) (void);
+
   typedef int (*event_hook_fcn) (void);
 
   typedef std::string (*completion_fcn) (const std::string&, int);
@@ -123,6 +125,10 @@
 
   static std::string get_line_buffer (void);
 
+  static std::string get_current_line (void);
+
+  static void replace_line (const std::string& text, bool clear_undo = true);
+
   static void insert_text (const std::string& text);
 
   static void newline (void);
@@ -137,6 +143,10 @@
 
   static void remove_startup_hook (startup_hook_fcn f);
 
+  static void add_pre_input_hook (pre_input_hook_fcn f);
+
+  static void remove_pre_input_hook (pre_input_hook_fcn f);
+
   static void add_event_hook (event_hook_fcn f);
 
   static void remove_event_hook (event_hook_fcn f);
@@ -151,7 +161,7 @@
 
   static bool filename_quoting_desired (bool);
 
-  static bool interrupt (bool);
+  static bool interrupt (bool = true);
 
   static int current_command_number (void);
 
@@ -161,6 +171,10 @@
 
   static void force_default_editor (void);
 
+  static void set_initial_input (const std::string& text);
+
+  static int insert_initial_input (void);
+
 private:
 
   // No copying!
@@ -175,15 +189,22 @@
 
   static int startup_handler (void);
 
+  static int pre_input_handler (void);
+
   static int event_handler (void);
 
   static std::set<startup_hook_fcn> startup_hook_set;
 
+  static std::set<pre_input_hook_fcn> pre_input_hook_set;
+
   static std::set<event_hook_fcn> event_hook_set;
 
   typedef std::set<startup_hook_fcn>::iterator startup_hook_set_iterator;
   typedef std::set<startup_hook_fcn>::const_iterator startup_hook_set_const_iterator;
 
+  typedef std::set<pre_input_hook_fcn>::iterator pre_input_hook_set_iterator;
+  typedef std::set<pre_input_hook_fcn>::const_iterator pre_input_hook_set_const_iterator;
+
   typedef std::set<event_hook_fcn>::iterator event_hook_set_iterator;
   typedef std::set<event_hook_fcn>::const_iterator event_hook_set_const_iterator;
 
@@ -271,7 +292,11 @@
 
   virtual std::string do_get_line_buffer (void) const = 0;
 
-  virtual void do_insert_text (const std::string&) = 0;
+  virtual std::string do_get_current_line (void) const = 0;
+
+  virtual void do_replace_line (const std::string& text, bool clear_undo) = 0;
+
+  virtual void do_insert_text (const std::string& text) = 0;
 
   virtual void do_newline (void) = 0;
 
@@ -285,7 +310,11 @@
 
   virtual void restore_startup_hook (void) { }
 
-  virtual void set_event_hook (startup_hook_fcn) { }
+  virtual void set_pre_input_hook (pre_input_hook_fcn) { }
+
+  virtual void restore_pre_input_hook (void) { }
+
+  virtual void set_event_hook (event_hook_fcn) { }
 
   virtual void restore_event_hook (void) { }
 
@@ -299,6 +328,8 @@
 
   virtual void do_interrupt (bool) { }
 
+  int do_insert_initial_input (void);
+
   int read_octal (const std::string& s);
 
   void error (int);
@@ -309,6 +340,8 @@
   int command_number;
 
   bool interrupted;
+
+  std::string initial_input;
 };
 
 #endif
--- a/liboctave/util/oct-rl-edit.c
+++ b/liboctave/util/oct-rl-edit.c
@@ -123,6 +123,18 @@
     rl_deprep_term_function ();
 }
 
+char *
+octave_rl_copy_line (void)
+{
+  return rl_copy_text (0, rl_end);
+}
+
+void
+octave_rl_replace_line (const char *s, int clear_undo)
+{
+  rl_replace_line (s, clear_undo);
+}
+
 void
 octave_rl_insert_text (const char *s)
 {
@@ -325,6 +337,18 @@
 }
 
 void
+octave_rl_set_pre_input_hook (rl_pre_input_hook_fcn_ptr f)
+{
+  rl_pre_input_hook = f;
+}
+
+rl_pre_input_hook_fcn_ptr
+octave_rl_get_pre_input_hook (void)
+{
+  return rl_pre_input_hook;
+}
+
+void
 octave_rl_set_event_hook (rl_event_hook_fcn_ptr f)
 {
   rl_event_hook = f;
--- a/liboctave/util/oct-rl-edit.h
+++ b/liboctave/util/oct-rl-edit.h
@@ -25,6 +25,8 @@
 
 typedef int (*rl_startup_hook_fcn_ptr) (void);
 
+typedef int (*rl_pre_input_hook_fcn_ptr) (void);
+
 typedef int (*rl_event_hook_fcn_ptr) (void);
 
 typedef int (*rl_fcn_ptr) (int, int);
@@ -62,6 +64,10 @@
 
 extern void octave_rl_restore_terminal_state (void);
 
+extern char *octave_rl_copy_line (void);
+
+extern void octave_rl_replace_line (const char *s, int clear_undo);
+
 extern void octave_rl_insert_text (const char *);
 
 extern int octave_rl_newline (int, int);
@@ -123,6 +129,10 @@
 
 extern rl_startup_hook_fcn_ptr octave_rl_get_startup_hook (void);
 
+extern void octave_rl_set_pre_input_hook (rl_startup_hook_fcn_ptr);
+
+extern rl_pre_input_hook_fcn_ptr octave_rl_get_pre_input_hook (void);
+
 extern void octave_rl_set_event_hook (rl_event_hook_fcn_ptr f);
 
 extern rl_event_hook_fcn_ptr octave_rl_get_event_hook (void);