changeset 29335:3180f830d396 stable

line buffer input in terminal_reader class * input.cc (terminal_reader::m_eof, terminal_reader::m_input_queue): New data members. (terminal_reader::get_input): Cache multi-line input in m_input_queue and return buffered input one line at a time.
author John W. Eaton <jwe@octave.org>
date Wed, 27 Jan 2021 06:42:38 -0500
parents 1ceeab926dc6
children 036079c9ee12
files libinterp/corefcn/input.cc
diffstat 1 files changed, 60 insertions(+), 2 deletions(-) [+]
line wrap: on
line diff
--- a/libinterp/corefcn/input.cc	Wed Jan 27 13:32:04 2021 +0100
+++ b/libinterp/corefcn/input.cc	Wed Jan 27 06:42:38 2021 -0500
@@ -36,6 +36,7 @@
 
 #include <algorithm>
 #include <iostream>
+#include <queue>
 #include <sstream>
 #include <string>
 
@@ -796,7 +797,7 @@
   public:
 
     terminal_reader (interpreter& interp)
-      : base_reader (interp)
+      : base_reader (interp), m_eof (false), m_input_queue ()
     { }
 
     std::string get_input (const std::string& prompt, bool& eof);
@@ -807,6 +808,9 @@
 
   private:
 
+    bool m_eof;
+    std::queue<std::string> m_input_queue;
+
     static const std::string s_in_src;
   };
 
@@ -869,6 +873,13 @@
 
   const std::string terminal_reader::s_in_src ("terminal");
 
+  // If octave_gets returns multiple lines, we cache the input and
+  // return it one line at a time.  Multiple input lines may happen when
+  // using readline and bracketed paste mode is enabled, for example.
+  // Instead of queueing lines here, it might be better to modify the
+  // grammar in the parser to handle multiple lines when working
+  // interactively.  See also bug #59938.
+
   std::string
   terminal_reader::get_input (const std::string& prompt, bool& eof)
   {
@@ -876,7 +887,54 @@
 
     eof = false;
 
-    return octave_gets (prompt, eof);
+    if (m_input_queue.empty ())
+      {
+        std::string input = octave_gets (prompt, m_eof);
+
+        size_t len = input.size ();
+
+        if (len == 0)
+          {
+            if (m_eof)
+              {
+                eof = m_eof;
+                return input;
+              }
+            else
+              {
+                // Can this happen, or will the string returned from
+                // octave_gets always end in a newline character?
+
+                input = "\n";
+                len = 1;
+              }
+          }
+
+        size_t beg = 0;
+        while (beg < len)
+          {
+            size_t end = input.find ('\n', beg);
+
+            if (end == std::string::npos)
+              {
+                m_input_queue.push (input.substr (beg));
+                break;
+              }
+            else
+              {
+                m_input_queue.push (input.substr (beg, end-beg+1));
+                beg = end + 1;
+              }
+          }
+      }
+
+    std::string retval = m_input_queue.front ();
+    m_input_queue.pop ();
+
+    if (m_input_queue.empty ())
+      eof = m_eof;
+
+    return retval;
   }
 
   const std::string file_reader::s_in_src ("file");