# HG changeset patch
# User Libor Morkovsky <liborek@gmail.com>
# Date 1435935149 14400
#      Fri Jul 03 10:52:29 2015 -0400
# Node ID 58bc41f1a906202da3d2d74ae54002b5cb89c904
# Parent  1c5a86b7f83876a47c6fe43f190bbb582b59e6ee
directory commands can autocomplete across slash (bug #44095)

diff -r 1c5a86b7f838 -r 58bc41f1a906 libinterp/corefcn/input.cc
--- a/libinterp/corefcn/input.cc	Sat Oct 10 16:52:59 2015 -0700
+++ b/libinterp/corefcn/input.cc	Fri Jul 03 10:52:29 2015 -0400
@@ -353,18 +353,21 @@ generate_possible_completions (const std
 static bool
 is_completing_dirfns (void)
 {
-  static std::string dirfns_commands[] = {"cd", "ls"};
-  static const size_t dirfns_commands_length = 2;
+  // List of functions which should cause directory matching.
+  static std::string dirfns[] = {"cd ", "ls ", "dir ", "load ", "save ",
+                                 "saveas ", "edit ", "exist ", "run ",
+                                 "source ", "addpath "};
+  // Pre-compute values for 6.5X speed-up at run-time.
+  static int dirfns_len[] = {3, 3, 5, 5, 5, 7, 5, 6, 4, 7, 8};
+  static const size_t num_dirfns = sizeof (dirfns) / sizeof (dirfns[0]);
 
   bool retval = false;
 
   std::string line = command_editor::get_line_buffer ();
 
-  for (size_t i = 0; i < dirfns_commands_length; i++)
+  for (size_t i = 0; i < num_dirfns; i++)
     {
-      int index = line.find (dirfns_commands[i] + " ");
-
-      if (index == 0)
+      if (line.compare (0, dirfns_len[i], dirfns[i]) == 0)
         {
           retval = true;
           break;
@@ -374,6 +377,18 @@ is_completing_dirfns (void)
   return retval;
 }
 
+const char *
+dir_word_breaker()
+{
+  // if completing a path, do not break into words on that many chars
+  if (is_completing_dirfns ()) {
+    return " \t\n";
+  }
+
+  // otherwise use the default
+  return 0;
+}
+
 static std::string
 generate_completion (const std::string& text, int state)
 {
@@ -493,6 +508,8 @@ initialize_command_input (void)
   command_editor::set_filename_quote_characters (" \t\n\\\"'@<>=;|&()#$`?*[!:{");
   command_editor::set_completer_quote_characters ("'\"");
 
+  command_editor::set_word_break_function (dir_word_breaker);
+
   command_editor::set_completion_function (generate_completion);
 
   command_editor::set_quoting_function (quoting_filename);
diff -r 1c5a86b7f838 -r 58bc41f1a906 liboctave/util/cmd-edit.cc
--- a/liboctave/util/cmd-edit.cc	Sat Oct 10 16:52:59 2015 -0700
+++ b/liboctave/util/cmd-edit.cc	Fri Jul 03 10:52:29 2015 -0400
@@ -74,6 +74,8 @@ public:
 
   typedef command_editor::completion_fcn completion_fcn;
 
+  typedef command_editor::word_break_fcn word_break_fcn;
+
   gnu_readline (void);
 
   ~gnu_readline (void) { }
@@ -124,6 +126,8 @@ public:
 
   void do_set_completion_function (completion_fcn f);
 
+  void do_set_word_break_function (word_break_fcn f);
+
   void do_set_quoting_function (quoting_fcn f);
 
   void do_set_dequoting_function (dequoting_fcn f);
@@ -134,6 +138,8 @@ public:
 
   completion_fcn do_get_completion_function (void) const;
 
+  word_break_fcn do_get_word_break_function (void) const;
+
   quoting_fcn do_get_quoting_function (void) const;
 
   dequoting_fcn do_get_dequoting_function (void) const;
@@ -205,6 +211,8 @@ private:
 
   completion_fcn completion_function;
 
+  word_break_fcn word_break_function;
+
   quoting_fcn quoting_function;
 
   dequoting_fcn dequoting_function;
@@ -223,11 +231,12 @@ private:
   static int command_accept_line (int count, int key);
 
   static char **command_completer (const char *text, int start, int end);
+  static const char *word_breaker ();
 };
 
 gnu_readline::gnu_readline ()
   : command_editor (), previous_startup_hook (0),
-    previous_pre_input_hook (0),
+    previous_pre_input_hook (0), word_break_function(0),
     previous_event_hook (0), completion_function (0),
     quoting_function (0), dequoting_function (0),
     char_is_quoted_function (0), user_accept_line_function (0)
@@ -435,6 +444,16 @@ gnu_readline::do_set_completion_function
 }
 
 void
+gnu_readline::do_set_word_break_function (word_break_fcn f)
+{
+  word_break_function = f;
+
+  rl_word_break_fcn_ptr fp = f ? gnu_readline::word_breaker : 0;
+
+  ::octave_rl_set_word_break_function (fp);
+}
+
+void
 gnu_readline::do_set_quoting_function (quoting_fcn f)
 {
   quoting_function = f;
@@ -486,6 +505,12 @@ gnu_readline::do_get_completion_function
   return completion_function;
 }
 
+gnu_readline::word_break_fcn
+gnu_readline::do_get_word_break_function (void) const
+{
+  return word_break_function;
+}
+
 gnu_readline::quoting_fcn
 gnu_readline::do_get_quoting_function (void) const
 {
@@ -817,6 +842,13 @@ gnu_readline::command_completer (const c
   return matches;
 }
 
+const char *
+gnu_readline::word_breaker ()
+{
+  word_break_fcn f = command_editor::get_word_break_function ();
+  return f();
+}
+
 #endif
 
 class
@@ -1255,6 +1287,13 @@ command_editor::set_completion_function 
 }
 
 void
+command_editor::set_word_break_function (word_break_fcn f)
+{
+  if (instance_ok ())
+    instance->do_set_word_break_function (f);
+}
+
+void
 command_editor::set_quoting_function (quoting_fcn f)
 {
   if (instance_ok ())
@@ -1289,6 +1328,13 @@ command_editor::get_completion_function 
          ? instance->do_get_completion_function () : 0;
 }
 
+command_editor::word_break_fcn
+command_editor::get_word_break_function (void)
+{
+  return (instance_ok ())
+    ? instance->do_get_word_break_function () : 0;
+}
+
 command_editor::quoting_fcn
 command_editor::get_quoting_function (void)
 {
diff -r 1c5a86b7f838 -r 58bc41f1a906 liboctave/util/cmd-edit.h
--- a/liboctave/util/cmd-edit.h	Sat Oct 10 16:52:59 2015 -0700
+++ b/liboctave/util/cmd-edit.h	Fri Jul 03 10:52:29 2015 -0400
@@ -49,6 +49,8 @@ public:
 
   typedef std::string (*completion_fcn) (const std::string&, int);
 
+  typedef const char * (*word_break_fcn) (void);
+
   typedef std::string (*quoting_fcn) (const std::string&, int, char);
 
   typedef std::string (*dequoting_fcn) (const std::string&, int);
@@ -107,6 +109,8 @@ public:
 
   static void set_completion_function (completion_fcn f);
 
+  static void set_word_break_function (word_break_fcn f);
+
   static void set_quoting_function (quoting_fcn f);
 
   static void set_dequoting_function (dequoting_fcn f);
@@ -117,6 +121,8 @@ public:
 
   static completion_fcn get_completion_function (void);
 
+  static word_break_fcn get_word_break_function (void);
+
   static quoting_fcn get_quoting_function (void);
 
   static dequoting_fcn get_dequoting_function (void);
@@ -282,6 +288,8 @@ protected:
 
   virtual void do_set_completion_function (completion_fcn) { }
 
+  virtual void do_set_word_break_function (word_break_fcn) { }
+
   virtual void do_set_quoting_function (quoting_fcn) { }
 
   virtual void do_set_dequoting_function (dequoting_fcn) { }
@@ -292,6 +300,8 @@ protected:
 
   virtual completion_fcn do_get_completion_function (void) const { return 0; }
 
+  virtual word_break_fcn do_get_word_break_function (void) const { return 0; }
+
   virtual quoting_fcn do_get_quoting_function (void) const { return 0; }
 
   virtual dequoting_fcn do_get_dequoting_function (void) const { return 0; }
diff -r 1c5a86b7f838 -r 58bc41f1a906 liboctave/util/oct-rl-edit.c
--- a/liboctave/util/oct-rl-edit.c	Sat Oct 10 16:52:59 2015 -0700
+++ b/liboctave/util/oct-rl-edit.c	Fri Jul 03 10:52:29 2015 -0400
@@ -335,6 +335,12 @@ octave_rl_set_completion_function (rl_at
 }
 
 void
+octave_rl_set_word_break_function (rl_word_break_fcn_ptr f)
+{
+  rl_completion_word_break_hook = f;
+}
+
+void
 octave_rl_set_quoting_function (rl_quoting_fcn_ptr f)
 {
   rl_filename_quoting_function = f;
diff -r 1c5a86b7f838 -r 58bc41f1a906 liboctave/util/oct-rl-edit.h
--- a/liboctave/util/oct-rl-edit.h	Sat Oct 10 16:52:59 2015 -0700
+++ b/liboctave/util/oct-rl-edit.h	Fri Jul 03 10:52:29 2015 -0400
@@ -39,6 +39,8 @@ typedef char * (*rl_quoting_fcn_ptr) (ch
 
 typedef char * (*rl_dequoting_fcn_ptr) (char *, int);
 
+typedef const char * (*rl_word_break_fcn_ptr) (void);
+
 typedef int (*rl_char_is_quoted_fcn_ptr) (char *, int);
 
 typedef int (*rl_command_fcn_ptr) (int, int);
@@ -128,6 +130,9 @@ extern void
 octave_rl_set_completion_function (rl_attempted_completion_fcn_ptr);
 
 extern void
+octave_rl_set_word_break_function (rl_word_break_fcn_ptr);
+
+extern void
 octave_rl_set_quoting_function (rl_quoting_fcn_ptr);
 
 extern void
