Mercurial > octave
changeset 21798:12e7456f7619
Tab completion of multiple directory levels. (bug #44095)
* cmd-edit.h, cmd-edit.cc (gnu_readline::completer_quote_characters):
New static data member.
(gnu_readline::completion_hook_fcn): New typedef.
(looks_like_filename): New static function.
(gnu_readline::do_set_completer_quote_characters): Set
octave_quote_characters instead of calling
octave_rl_set_completer_quote_characters directly.
(gnu_readline::do_completer_word_break_hook): New static function.
(gnu_readline::do_set_completer_word_break_hook): New function.
(gnu_readline::do_set_completer_word_break_characters):
Also set completer_word_break_hook.
* oct-rl-edit.h, oct-rl-edit.c (rl_completion_hook_fcn_ptr):
New typedef.
(octave_rl_get_completer_word_break_characters,
octave_rl_set_completion_word_break_hook): New functions.
author | Lachlan Andrew <lachlanbis@gmail.com> |
---|---|
date | Tue, 31 May 2016 12:51:52 +1000 |
parents | e5f083f9704e |
children | ddd00394d4fe |
files | liboctave/util/cmd-edit.cc liboctave/util/cmd-edit.h liboctave/util/oct-rl-edit.c liboctave/util/oct-rl-edit.h |
diffstat | 4 files changed, 105 insertions(+), 1 deletions(-) [+] |
line wrap: on
line diff
--- a/liboctave/util/cmd-edit.cc Mon May 30 10:44:24 2016 -0400 +++ b/liboctave/util/cmd-edit.cc Tue May 31 12:51:52 2016 +1000 @@ -37,6 +37,7 @@ #include "cmd-edit.h" #include "cmd-hist.h" #include "file-ops.h" +#include "file-stat.h" #include "lo-error.h" #include "lo-utils.h" #include "oct-env.h" @@ -53,6 +54,8 @@ namespace octave { + char *do_completer_word_break_hook (); + command_editor *command_editor::instance = 0; std::set<command_editor::startup_hook_fcn> command_editor::startup_hook_set; @@ -217,6 +220,8 @@ user_accept_line_fcn user_accept_line_function; + static std::string completer_quote_characters; + static char *command_generator (const char *text, int state); static char *command_quoter (char *text, int match_type, char *quote_pointer); @@ -227,8 +232,12 @@ static int command_accept_line (int count, int key); static char **command_completer (const char *text, int start, int end); + + static char *do_completer_word_break_hook (); }; + std::string gnu_readline::completer_quote_characters = ""; + gnu_readline::gnu_readline () : command_editor (), previous_startup_hook (0), previous_pre_input_hook (0), @@ -401,6 +410,10 @@ gnu_readline::do_set_completer_word_break_characters (const std::string& s) { ::octave_rl_set_completer_word_break_characters (s.c_str ()); + + ::octave_rl_set_completion_word_break_hook + (gnu_readline::do_completer_word_break_hook); + } void @@ -418,7 +431,7 @@ void gnu_readline::do_set_completer_quote_characters (const std::string& s) { - ::octave_rl_set_completer_quote_characters (s.c_str ()); + completer_quote_characters = s; } void @@ -514,6 +527,75 @@ return user_accept_line_function; } + // True if the last "word" of the string line (delimited by delim) is + // an existing directory. Used by do_completer_word_break_hook. + + static bool + looks_like_filename (const char *line, char delim) + { + bool retval = false; + + const char *s = strrchr (line, delim); + + if (s) + { + // Remove incomplete component. + const char *f = strrchr (line, octave::sys::file_ops::dir_sep_char ()); + + if (s[1] == '~' || (f && f != s)) + { + // For something like "A /b", f==s; don't assume a file. + + std::string candidate_filename = s+1; + + candidate_filename = candidate_filename.substr (0, f - s); + + // Handles any complete ~<username>, but doesn't expand usernames. + + if (candidate_filename[0] == '~') + candidate_filename + = octave::sys::file_ops::tilde_expand (candidate_filename); + + octave::sys::file_stat fs (candidate_filename); + + retval = fs.is_dir (); + } + } + + return retval; + } + + // Decide whether to interpret partial commands like "abc/def" as a + // filename or division. Return the set of delimiters appropriate for + // the decision. + + char * + gnu_readline::do_completer_word_break_hook () + { + static char *dir_sep = strdup (" '\""); + + std::string word; + std::string line = get_line_buffer (); + + // For now, assume space or quote delimiter for file names. + const char *l = line.c_str (); + + if (looks_like_filename (l, ' ') || looks_like_filename (l, '\'') + || looks_like_filename (l, '"')) + { + ::octave_rl_set_completer_quote_characters (completer_quote_characters.c_str ()); + + return dir_sep; + } + else + { + ::octave_rl_set_completer_quote_characters (""); + + return octave_rl_get_completer_word_break_characters (); + } + } + + string_vector gnu_readline::do_generate_filename_completions (const std::string& text) {
--- a/liboctave/util/cmd-edit.h Mon May 30 10:44:24 2016 -0400 +++ b/liboctave/util/cmd-edit.h Tue May 31 12:51:52 2016 +1000 @@ -53,6 +53,8 @@ typedef std::string (*completion_fcn) (const std::string&, int); + typedef char * (*completion_hook_fcn) (); + typedef std::string (*quoting_fcn) (const std::string&, int, char); typedef std::string (*dequoting_fcn) (const std::string&, int); @@ -276,6 +278,8 @@ virtual void do_set_completer_word_break_characters (const std::string&) { } + virtual void do_set_completer_word_break_hook (completion_hook_fcn) { } + virtual void do_set_basic_quote_characters (const std::string&) { } virtual void do_set_filename_quote_characters (const std::string&) { }
--- a/liboctave/util/oct-rl-edit.c Mon May 30 10:44:24 2016 -0400 +++ b/liboctave/util/oct-rl-edit.c Tue May 31 12:51:52 2016 +1000 @@ -297,6 +297,18 @@ rl_completer_word_break_characters = ss; } +char * +octave_rl_get_completer_word_break_characters (void) +{ + return rl_completer_word_break_characters; +} + +void +octave_rl_set_completion_word_break_hook (rl_completion_hook_fcn_ptr f) +{ + rl_completion_word_break_hook = f; +} + void octave_rl_set_basic_quote_characters (const char *s) {
--- a/liboctave/util/oct-rl-edit.h Mon May 30 10:44:24 2016 -0400 +++ b/liboctave/util/oct-rl-edit.h Tue May 31 12:51:52 2016 +1000 @@ -37,6 +37,8 @@ typedef char * (*rl_completer_fcn_ptr) (const char *, int); +typedef char * (*rl_completion_hook_fcn_ptr) (void); + typedef char * (*rl_quoting_fcn_ptr) (char *, int, char *); typedef char * (*rl_dequoting_fcn_ptr) (char *, int); @@ -118,6 +120,10 @@ extern void octave_rl_set_completer_word_break_characters (const char *); +extern char *octave_rl_get_completer_word_break_characters (void); + +extern void octave_rl_set_completion_word_break_hook (rl_completion_hook_fcn_ptr); + extern void octave_rl_set_basic_quote_characters (const char *); extern void octave_rl_set_filename_quote_characters (const char *);