28#if defined (HAVE_CONFIG_H)
52#include "builtin-defun-decls.h"
94quoting_filename (
const std::string& text,
int,
char quote)
107find_indexed_expression (
const std::string& text)
111 int pos = line.length () - text.length ();
117 while (pos >= 0 && (line[pos] ==
')' || line[pos] ==
'}'))
119 if (line[pos] ==
')')
124 while (curly_count + paren_count > 0 && --pos >= 0)
126 if (line[pos] ==
')')
128 else if (line[pos] ==
'(')
130 else if (line[pos] ==
'}')
132 else if (line[pos] ==
'{')
136 while (--pos >= 0 && line[pos] ==
' ')
140 while (pos >= 0 && (isalnum (line[pos]) || line[pos] ==
'_'))
144 return (line.substr (pos, last + 1 - pos));
146 return std::string ();
150generate_struct_completions (
const std::string& text,
151 std::string& prefix, std::string& hint)
155 std::size_t pos = text.rfind (
'.');
158 if (pos != std::string::npos)
160 if (pos == text.length ())
163 hint = text.substr (pos+1);
165 prefix = text.substr (0, pos);
170 prefix = find_indexed_expression (text);
173 std::string base_name = prefix;
175 pos = base_name.find_first_of (
"{(. ");
177 if (pos != std::string::npos)
178 base_name = base_name.substr (0, pos);
223looks_like_struct (
const std::string& text,
char prev_char)
225 bool retval = (! text.empty ()
226 && (text !=
"." || prev_char ==
')' || prev_char ==
'}')
227 && text.find_first_of (sys::file_ops::dir_sep_chars ()) == std::string::npos
228 && text.find (
"..") == std::string::npos
229 && text.rfind (
'.') != std::string::npos);
237generate_possible_completions (
const std::string& text, std::string& prefix,
238 std::string& hint,
bool& deemed_struct)
245 deemed_struct = looks_like_struct (text, prev_char);
248 names = generate_struct_completions (text, prefix, hint);
260is_completing_dirfns ()
262 static std::string dirfns_commands[] = {
"cd",
"isfile",
"isfolder",
"ls"};
263 static const std::size_t DIRFNS_COMMANDS_LENGTH = 4;
269 for (std::size_t i = 0; i < DIRFNS_COMMANDS_LENGTH; i++)
271 int index = line.find (dirfns_commands[i] +
' ');
284generate_completion (
const std::string& text,
int state)
288 static std::string prefix;
289 static std::string hint;
291 static std::size_t hint_len = 0;
293 static int list_index = 0;
294 static int name_list_len = 0;
295 static int name_list_total_len = 0;
299 static int matches = 0;
312 bool deemed_struct =
false;
314 if (is_completing_dirfns ())
317 name_list = generate_possible_completions (text, prefix, hint,
320 name_list_len = name_list.
numel ();
329 name_list.
append (file_name_list);
333 name_list_total_len = name_list.
numel ();
335 hint_len = hint.length ();
339 for (
int i = 0; i < name_list_len; i++)
340 if (hint == name_list[i].substr (0, hint_len))
344 if (name_list_total_len > 0 && matches > 0)
346 while (list_index < name_list_total_len)
348 std::string name = name_list[list_index];
352 if (hint == name.substr (0, hint_len))
356 if (list_index <= name_list_len && ! prefix.empty ())
357 retval = (prefix ==
"." ?
"" : prefix) +
'.' + name;
364 if (matches == 1 && looks_like_struct (retval, prev_char))
388internal_input_event_hook_fcn ()
404 : m_interpreter (interp), m_PS1 (R
"(octave:\#> )"), m_PS2 ("> "),
405 m_completion_append_char (
' '), m_gud_mode (false),
406 m_mfile_encoding (
"utf-8"), m_auto_repeat_debug_command (true),
407 m_last_debugging_command (
"\n"), m_input_event_hook_functions (),
408 m_initialized (false)
432 static const char *s =
"\t\n !\"\'*+-/:;<=>(){}[\\]^`~";
450 m_initialized = true;
470 "completion_append_char");
485 std::string saved_encoding = m_mfile_encoding;
496 if (m_mfile_encoding != saved_encoding)
498 if (m_mfile_encoding.empty ())
500 m_mfile_encoding =
"system";
504 std::transform (m_mfile_encoding.begin (),
505 m_mfile_encoding.end (),
506 m_mfile_encoding.begin (), ::tolower);
508 std::string encoding = (m_mfile_encoding.compare (
"system") == 0)
515 if (codec ==
reinterpret_cast<void *
> (-1))
517 m_mfile_encoding = saved_encoding;
519 error (
"mfile_encoding: conversion from encoding '%s' "
520 "not supported", encoding.c_str ());
522 error (
"mfile_encoding: error %d opening encoding '%s'",
523 errno, encoding.c_str ());
539load_path_dir (
const std::string& dir)
541 std::string lp_dir = dir;
544 std::size_t ipos = lp_dir.find_last_not_of (sys::file_ops::dir_sep_chars ());
545 if (ipos != std::string::npos)
546 lp_dir = lp_dir.erase (ipos+1);
549 ipos = lp_dir.find_last_of (sys::file_ops::dir_sep_chars ());
550 if (ipos != std::string::npos
551 && lp_dir.substr (ipos+1).compare (
"private") == 0)
553 lp_dir = lp_dir.erase (ipos);
554 ipos = lp_dir.find_last_of (sys::file_ops::dir_sep_chars ());
558 if (ipos != std::string::npos && lp_dir[ipos+1] ==
'@')
560 lp_dir = lp_dir.erase (ipos);
561 ipos = lp_dir.find_last_of (sys::file_ops::dir_sep_chars ());
565 while (ipos != std::string::npos && lp_dir[ipos+1] ==
'+')
567 lp_dir = lp_dir.erase (ipos);
568 ipos = lp_dir.find_last_of (sys::file_ops::dir_sep_chars ());
577 std::string enc = m_mfile_encoding;
579 const std::string key = sys::canonicalize_file_name (dir);
581 auto enc_it = m_dir_encoding.find (key);
582 if (enc_it != m_dir_encoding.end ())
583 enc = enc_it->second;
593 std::transform (enc.begin (), enc.end (), enc.begin (), ::tolower);
595 if (enc.compare (
"delete") == 0)
598 m_dir_encoding.erase (load_path_dir (dir));
601 else if (enc.compare (
"utf-8"))
610 if (codec ==
reinterpret_cast<void *
> (-1))
613 error (
"dir_encoding: conversion from encoding '%s' "
614 "not supported", enc.c_str ());
616 error (
"dir_encoding: error %d opening encoding '%s'.",
617 errno, enc.c_str ());
623 m_dir_encoding[load_path_dir (dir)] = enc;
633 "auto_repeat_debug_command");
639 std::string prompt_string = prompt +
"(yes or no) ";
647 if (input_buf ==
"yes")
649 else if (input_buf ==
"no")
652 message (
nullptr,
"Please answer yes or no.");
663 bool eval_error =
false;
687 return gnu_readline (s, eof);
697 std::string prompt = args(0).xstring_value (
"input: unrecognized argument");
699 bool read_as_string =
false;
703 = args(1).xstring_value (
"input: second argument must be 's'.");
704 if (literal.length () != 1 || literal[0] !=
's')
705 error (
"input: second argument must be 's'.");
707 read_as_string =
true;
720 if (input_buf.empty ())
721 error (
"input: reading user-input failed!");
723 std::size_t
len = input_buf.length ();
727 if (input_buf[
len - 1] !=
'\n')
733 if (input_buf.length () == 1 && input_buf[0] ==
'\n')
736 retval(0) = input_buf;
740 int parse_status = 0;
743 = m_interpreter.
eval_string (input_buf,
true, parse_status, nargout);
757 return ! m_input_event_hook_functions.
empty ();
763 m_input_event_hook_functions.
insert (hook_fcn.
id (), hook_fcn);
770 = m_input_event_hook_functions.
find (hook_fcn_id);
772 if (p == m_input_event_hook_functions.
end ())
775 m_input_event_hook_functions.
erase (p);
782 m_input_event_hook_functions.
clear ();
788 m_input_event_hook_functions.
run ();
792input_system::gnu_readline (
const std::string& s,
bool& eof)
const
800 if (! eof && retval.empty ())
832 bool history_skip_auto_repeated_debugging_command =
false;
849 && retval.find_first_not_of (
" \t\n\r") != std::string::npos)
863 history_skip_auto_repeated_debugging_command =
true;
868 if (! history_skip_auto_repeated_debugging_command)
876 if (! retval.empty () && retval.back () !=
'\n')
896 :
base_reader (interp), m_eof (false), m_input_queue ()
899 std::string
get_input (
const std::string& prompt,
bool& eof);
908 std::queue<std::string> m_input_queue;
910 static const std::string s_in_src;
924 file_reader (
interpreter& interp, FILE *f_arg,
const std::string& enc)
925 :
base_reader (interp), m_file (f_arg), m_encoding (enc) { }
927 std::string
get_input (
const std::string& prompt,
bool& eof);
937 std::string m_encoding;
939 static const std::string s_in_src;
946 eval_string_reader (
interpreter& interp,
const std::string& str)
950 std::string
get_input (
const std::string& prompt,
bool& eof);
958 std::string m_eval_string;
960 static const std::string s_in_src;
964 : m_rep (new terminal_reader (interp))
968 : m_rep (new file_reader (interp, file))
972 const std::string& enc)
973 : m_rep (new file_reader (interp, file, enc))
977 : m_rep (new eval_string_reader (interp, str))
980const std::string base_reader::s_in_src (
"invalid");
982const std::string terminal_reader::s_in_src (
"terminal");
992terminal_reader::get_input (
const std::string& prompt,
bool& eof)
998 if (m_input_queue.empty ())
1000 std::string input = octave_gets (prompt, m_eof);
1002 std::size_t
len = input.size ();
1021 std::size_t beg = 0;
1024 std::size_t end = input.find (
'\n', beg);
1026 if (end == std::string::npos)
1028 m_input_queue.push (input.substr (beg));
1033 m_input_queue.push (input.substr (beg, end-beg+1));
1039 std::string retval = m_input_queue.front ();
1040 m_input_queue.pop ();
1042 if (m_input_queue.empty ())
1048const std::string file_reader::s_in_src (
"file");
1051file_reader::get_input (
const std::string& ,
bool& eof)
1057 std::string src_str =
fgets (m_file, eof);
1059 std::string mfile_encoding;
1061 if (m_encoding.empty ())
1063 input_system& input_sys = m_interpreter.get_input_system ();
1067 mfile_encoding = m_encoding;
1069 std::string encoding;
1070 if (mfile_encoding.compare (
"system") == 0)
1074 std::transform (encoding.begin (), encoding.end (), encoding.begin (),
1078 encoding = mfile_encoding;
1080 if (encoding.compare (
"utf-8") == 0)
1083 if (src_str.compare (0, 3,
"\xef\xbb\xbf") == 0)
1084 src_str.erase (0, 3);
1088 if (string::u8_validate (
"get_input", src_str) > 0)
1090 "Invalid UTF-8 byte sequences have been replaced.");
1095 const char *src = src_str.c_str ();
1096 std::size_t srclen = src_str.length ();
1105 error (
"file_reader::get_input: "
1106 "converting from codepage '%s' to UTF-8: %s",
1107 encoding.c_str (), std::strerror (errno));
1111 src_str = std::string (
reinterpret_cast<char *
> (utf8_str), length);
1117const std::string eval_string_reader::s_in_src (
"eval_string");
1120eval_string_reader::get_input (
const std::string& ,
bool& eof)
1128 retval = m_eval_string;
1134 if (retval.empty ())
1179 int nargin = args.
length ();
1181 if (nargin < 1 || nargin > 2)
1203 int nargin = args.
length ();
1213 prompt = args(0).xstring_value (
"yes_or_no: PROMPT must be a string");
1236 int nargin = args.
length ();
1246 = args(0).xstring_value (
"keyboard: PROMPT must be a string");
1256DEFUN (completion_matches, args, nargout,
1283 std::string hint = args(0).string_value ();
1293 std::string cmd = generate_completion (hint, k);
1314 if (! list.empty ())
1327 for (
int i = 0; i <
len; i++)
1351DEFUN (readline_read_init_file, args, ,
1365 int nargin = args.
length ();
1374 std::string file = args(0).string_value ();
1382DEFUN (readline_re_read_init_file, args, ,
1400DEFMETHOD (add_input_event_hook, interp, args, ,
1420 int nargin = args.
length ();
1422 if (nargin < 1 || nargin > 2)
1428 user_data = args(1);
1436 return ovl (hook_fcn.
id ());
1439DEFMETHOD (remove_input_event_hook, interp, args, ,
1449 int nargin = args.
length ();
1451 if (nargin < 1 || nargin > 2)
1454 std::string hook_fcn_id = args(0).xstring_value (
"remove_input_event_hook: argument not valid as a hook function name or id");
1456 bool warn = (nargin < 2);
1461 warning (
"remove_input_event_hook: %s not found in list",
1462 hook_fcn_id.c_str ());
1506 return interp.
PS1 (args, nargout);
1528 return interp.
PS2 (args, nargout);
1531DEFMETHOD (completion_append_char, interp, args, nargout,
1558 int nargin = args.
length ();
1571DEFMETHOD (__gud_mode__, interp, args, nargout,
1579 return input_sys.
gud_mode (args, nargout);
1582DEFMETHOD (mfile_encoding, interp, args, nargout,
1615DEFALIAS (__mfile_encoding__, mfile_encoding);
1617DEFMETHOD (dir_encoding, interp, args, nargout,
1658 int nargin = args.
length ();
1660 if (nargin < 1 || nargin > 2)
1664 = args(0).xstring_value (
"dir_encoding: DIR must be a string");
1675 std::string encoding
1676 = args(1).xstring_value (
"dir_encoding: ENCODING must be a string");
1681 return ovl (retval);
1685DEFMETHOD (auto_repeat_debug_command, interp, args, nargout,
1704OCTAVE_END_NAMESPACE(octave)
void add(F &&fcn, Args &&... args)
void run(std::size_t num)
virtual std::string input_source() const
std::string octave_gets(const std::string &prompt, bool &eof)
virtual std::string get_input(const std::string &prompt, bool &eof)=0
virtual bool input_from_terminal() const
virtual bool input_from_eval_string() const
interpreter & m_interpreter
virtual bool input_from_file() const
static void set_quoting_function(quoting_fcn f)
static void set_completer_quote_characters(const std::string &s)
static string_vector generate_filename_completions(const std::string &text)
static char get_prev_char(int)
static void set_filename_quote_characters(const std::string &s)
static std::string readline(const std::string &prompt)
static void set_name(const std::string &n)
static void set_completer_word_break_characters(const std::string &s)
static void set_basic_word_break_characters(const std::string &s)
static void force_default_editor()
static void set_completion_function(completion_fcn f)
static void set_completion_append_character(char c)
static std::string get_line_buffer()
static void add_event_hook(event_hook_fcn f)
static void set_basic_quote_characters(const std::string &s)
static void re_read_init_file()
static void read_init_file(const std::string &file="")
static bool add(const std::string &)
void set_discard_warning_messages(bool flag)
octave_value discard_warning_messages(const octave_value_list &args, int nargout)
Provides threadsafe access to octave.
void append_history(const std::string &hist_entry)
void exit_debugger_event()
map_type::iterator iterator
void run(const octave_value_list &initial_args=octave_value_list())
iterator find(const std::string &id)
void insert(const std::string &id, const hook_function &f)
error_system & get_error_system()
output_system & get_output_system()
load_path & get_load_path()
octave_value_list eval_string(const std::string &eval_str, bool silent, int &parse_status, int nargout)
void handle_exception(const execution_exception &ee)
octave_value PS1(const octave_value_list &args, int nargout)
bool is_variable(const std::string &name) const
tree_evaluator & get_evaluator()
void recover_from_exception()
octave_value PS2(const octave_value_list &args, int nargout)
input_system & get_input_system()
event_manager & get_event_manager()
octave_idx_type length() const
bool is_classdef_object() const
string_vector map_keys() const
octave_idx_type numel() const
string_vector & append(const std::string &s)
string_vector & sort(bool make_uniq=false)
octave_idx_type numel() const
bool in_debug_repl() const
void keyboard(const std::string &prompt="debug> ")
OCTAVE_BEGIN_NAMESPACE(octave) static octave_value daspk_fcn
#define DEFMETHOD(name, interp_name, args_name, nargout_name, doc)
Macro to define a builtin method.
#define DEFUN(name, args_name, nargout_name, doc)
Macro to define a builtin function.
#define DEFALIAS(alias, name)
Macro to define an alias for another existing function name.
void warning(const char *fmt,...)
void warning_with_id(const char *id, const char *fmt,...)
void error(const char *fmt,...)
void message(const char *name, const char *fmt,...)
octave_value_list F__event_manager_gui_preference__(octave::interpreter &interp, const octave_value_list &args, int)
octave_value_list Fdrawnow(octave::interpreter &interp, const octave_value_list &args, int)
string_vector make_name_list()
void * octave_iconv_open_wrapper(const char *tocode, const char *fromcode)
int octave_iconv_close_wrapper(void *cd)
input_system & __get_input_system__()
interpreter & __get_interpreter__()
std::string fgets(FILE *f)
const char * octave_locale_charset_wrapper(void)
octave_value_list ovl(const OV_Args &... args)
Construct an octave_value_list with less typing.
int pipe_handler_error_count
uint8_t * octave_u8_conv_from_encoding(const char *fromcode, const char *src, size_t srclen, size_t *lengthp)
octave_value set_internal_variable(bool &var, const octave_value_list &args, int nargout, const char *nm)