Mercurial > octave-nkf
view liboctave/util/cmd-edit.cc @ 20651:e54ecb33727e
lo-array-gripes.cc: Remove FIXME's related to buffer size.
* lo-array-gripes.cc: Remove FIXME's related to buffer size. Shorten sprintf
buffers from 100 to 64 characters (still well more than 19 required).
Use 'const' decorator on constant value for clarity. Remove extra space
between variable and array bracket.
author | Rik <rik@octave.org> |
---|---|
date | Mon, 12 Oct 2015 21:13:47 -0700 |
parents | b70cc4bd8109 |
children |
line wrap: on
line source
/* Copyright (C) 1996-2015 John W. Eaton This file is part of Octave. Octave is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. Octave is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Octave; see the file COPYING. If not, see <http://www.gnu.org/licenses/>. */ #ifdef HAVE_CONFIG_H #include <config.h> #endif #include <cstdlib> #include <cstring> #include <string> #include <sys/types.h> #include <unistd.h> #include "quit.h" #include "cmd-edit.h" #include "cmd-hist.h" #include "file-ops.h" #include "lo-error.h" #include "lo-utils.h" #include "oct-env.h" #include "oct-mutex.h" #include "oct-time.h" #include "singleton-cleanup.h" command_editor *command_editor::instance = 0; 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; #if defined (USE_READLINE) #include <cstdio> #include <cstdlib> #include "oct-rl-edit.h" class gnu_readline : public command_editor { public: 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; gnu_readline (void); ~gnu_readline (void) { } void do_set_name (const std::string& n); std::string do_readline (const std::string& prompt, bool& eof); void do_set_input_stream (FILE *f); FILE *do_get_input_stream (void); void do_set_output_stream (FILE *f); FILE *do_get_output_stream (void); void do_redisplay (void); int do_terminal_rows (void); int do_terminal_cols (void); void do_clear_screen (bool skip_redisplay); void do_resize_terminal (void); void do_set_screen_size (int ht, int wd); std::string newline_chars (void); void do_restore_terminal_state (void); void do_blink_matching_paren (bool flag); bool do_erase_empty_line (bool flag); void do_set_basic_word_break_characters (const std::string& s); void do_set_completer_word_break_characters (const std::string& s); void do_set_basic_quote_characters (const std::string& s); void do_set_filename_quote_characters (const std::string& s); void do_set_completer_quote_characters (const std::string& s); void do_set_completion_append_character (char c); void do_set_completion_function (completion_fcn f); void do_set_quoting_function (quoting_fcn f); void do_set_dequoting_function (dequoting_fcn f); void do_set_char_is_quoted_function (char_is_quoted_fcn f); void do_set_user_accept_line_function (user_accept_line_fcn f); completion_fcn do_get_completion_function (void) const; quoting_fcn do_get_quoting_function (void) const; dequoting_fcn do_get_dequoting_function (void) const; char_is_quoted_fcn do_get_char_is_quoted_function (void) const; user_accept_line_fcn do_get_user_accept_line_function (void) const; string_vector do_generate_filename_completions (const std::string& text); 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_kill_full_line (void); void do_insert_text (const std::string& text); void do_newline (void); void do_accept_line (void); bool do_undo (void); void do_clear_undo_list (void); void set_startup_hook (startup_hook_fcn f); 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); void do_restore_event_hook (void); void do_read_init_file (const std::string& file); void do_re_read_init_file (void); bool do_filename_completion_desired (bool); bool do_filename_quoting_desired (bool); bool do_prefer_env_winsize (bool); void do_interrupt (bool); static int operate_and_get_next (int, int); static int history_search_backward (int, int); static int history_search_forward (int, int); private: startup_hook_fcn previous_startup_hook; pre_input_hook_fcn previous_pre_input_hook; event_hook_fcn previous_event_hook; completion_fcn completion_function; quoting_fcn quoting_function; dequoting_fcn dequoting_function; char_is_quoted_fcn char_is_quoted_function; user_accept_line_fcn user_accept_line_function; static char *command_generator (const char *text, int state); static char *command_quoter (char *text, int match_type, char *quote_pointer); static char *command_dequoter (char *text, int match_type); static int command_char_is_quoted (char *text, int index); static int command_accept_line (int count, int key); static char **command_completer (const char *text, int start, int end); }; 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) { // FIXME: need interface to rl_add_defun, rl_initialize, and // a function to set rl_terminal_name std::string term = octave_env::getenv ("TERM"); octave_rl_set_terminal_name (term.c_str ()); octave_rl_initialize (); do_blink_matching_paren (true); // Bind operate-and-get-next. octave_rl_add_defun ("operate-and-get-next", gnu_readline::operate_and_get_next, octave_rl_ctrl ('O')); // And the history search functions. octave_rl_add_defun ("history-search-backward", gnu_readline::history_search_backward, octave_rl_meta ('P')); octave_rl_add_defun ("history-search-forward", gnu_readline::history_search_forward, octave_rl_meta ('N')); } void gnu_readline::do_set_name (const std::string& nm) { ::octave_rl_set_name (nm.c_str ()); } std::string gnu_readline::do_readline (const std::string& prompt, bool& eof) { std::string retval; eof = false; const char *p = prompt.c_str (); BEGIN_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; char *line = ::octave_rl_readline (p); if (line) { retval = line; free (line); } else eof = true; END_INTERRUPT_IMMEDIATELY_IN_FOREIGN_CODE; return retval; } void gnu_readline::do_set_input_stream (FILE *f) { ::octave_rl_set_input_stream (f); } FILE * gnu_readline::do_get_input_stream (void) { return ::octave_rl_get_input_stream (); } void gnu_readline::do_set_output_stream (FILE *f) { ::octave_rl_set_output_stream (f); } FILE * gnu_readline::do_get_output_stream (void) { return ::octave_rl_get_output_stream (); } void gnu_readline::do_redisplay (void) { ::octave_rl_redisplay (); } // GNU readline handles SIGWINCH, so these values have a good chance // of being correct even if the window changes size (they may be // wrong if, for example, the luser changes the window size while the // pager is running, and the signal is handled by the pager instead of // us. int gnu_readline::do_terminal_rows (void) { int sh = ::octave_rl_screen_height (); return sh > 0 ? sh : 24; } int gnu_readline::do_terminal_cols (void) { int sw = ::octave_rl_screen_width (); return sw > 0 ? sw : 80; } void gnu_readline::do_clear_screen (bool skip_redisplay) { ::octave_rl_clear_screen (skip_redisplay); } void gnu_readline::do_resize_terminal (void) { ::octave_rl_resize_terminal (); } void gnu_readline::do_set_screen_size (int ht, int wd) { ::octave_rl_set_screen_size (ht, wd); } std::string gnu_readline::newline_chars (void) { return "\r\n"; } void gnu_readline::do_restore_terminal_state (void) { ::octave_rl_restore_terminal_state (); } void gnu_readline::do_blink_matching_paren (bool flag) { ::octave_rl_enable_paren_matching (flag ? 1 : 0); } bool gnu_readline::do_erase_empty_line (bool flag) { return ::octave_rl_erase_empty_line (flag ? 1 : 0); } void gnu_readline::do_set_basic_word_break_characters (const std::string& s) { ::octave_rl_set_basic_word_break_characters (s.c_str ()); } void gnu_readline::do_set_completer_word_break_characters (const std::string& s) { ::octave_rl_set_completer_word_break_characters (s.c_str ()); } void gnu_readline::do_set_basic_quote_characters (const std::string& s) { ::octave_rl_set_basic_quote_characters (s.c_str ()); } void gnu_readline::do_set_filename_quote_characters (const std::string& s) { ::octave_rl_set_filename_quote_characters (s.c_str ()); } void gnu_readline::do_set_completer_quote_characters (const std::string& s) { ::octave_rl_set_completer_quote_characters (s.c_str ()); } void gnu_readline::do_set_completion_append_character (char c) { ::octave_rl_set_completion_append_character (c); } void gnu_readline::do_set_completion_function (completion_fcn f) { completion_function = f; rl_attempted_completion_fcn_ptr fp = f ? gnu_readline::command_completer : 0; ::octave_rl_set_completion_function (fp); } void gnu_readline::do_set_quoting_function (quoting_fcn f) { quoting_function = f; rl_quoting_fcn_ptr fp = f ? gnu_readline::command_quoter : 0; ::octave_rl_set_quoting_function (fp); } void gnu_readline::do_set_dequoting_function (dequoting_fcn f) { dequoting_function = f; rl_dequoting_fcn_ptr fp = f ? gnu_readline::command_dequoter : 0; ::octave_rl_set_dequoting_function (fp); } void gnu_readline::do_set_char_is_quoted_function (char_is_quoted_fcn f) { char_is_quoted_function = f; rl_char_is_quoted_fcn_ptr fp = f ? gnu_readline::command_char_is_quoted : 0; ::octave_rl_set_char_is_quoted_function (fp); } void gnu_readline::do_set_user_accept_line_function (user_accept_line_fcn f) { user_accept_line_function = f; if (f) octave_rl_add_defun ("accept-line", gnu_readline::command_accept_line, ::octave_rl_ctrl ('M')); else octave_rl_add_defun ("accept-line", ::octave_rl_newline, ::octave_rl_ctrl ('M')); } gnu_readline::completion_fcn gnu_readline::do_get_completion_function (void) const { return completion_function; } gnu_readline::quoting_fcn gnu_readline::do_get_quoting_function (void) const { return quoting_function; } gnu_readline::dequoting_fcn gnu_readline::do_get_dequoting_function (void) const { return dequoting_function; } gnu_readline::char_is_quoted_fcn gnu_readline::do_get_char_is_quoted_function (void) const { return char_is_quoted_function; } gnu_readline::user_accept_line_fcn gnu_readline::do_get_user_accept_line_function (void) const { return user_accept_line_function; } string_vector gnu_readline::do_generate_filename_completions (const std::string& text) { string_vector retval; int n = 0; int count = 0; char *fn = 0; while (1) { fn = ::octave_rl_filename_completion_function (text.c_str (), count); if (fn) { if (count == n) { // Famous last words: Most large directories will not // have more than a few hundred files, so we should not // resize too many times even if the growth is linear... n += 100; retval.resize (n); } retval[count++] = fn; free (fn); } else break; } retval.resize (count); return retval; } std::string gnu_readline::do_get_line_buffer (void) const { 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_kill_full_line (void) { ::octave_rl_kill_full_line (); } void gnu_readline::do_insert_text (const std::string& text) { ::octave_rl_insert_text (text.c_str ()); } void gnu_readline::do_newline (void) { ::octave_rl_newline (1, '\n'); } void gnu_readline::do_accept_line (void) { command_accept_line (1, '\n'); } bool gnu_readline::do_undo (void) { return ::octave_rl_do_undo (); } void gnu_readline::do_clear_undo_list () { ::octave_rl_clear_undo_list (); } void gnu_readline::set_startup_hook (startup_hook_fcn f) { previous_startup_hook = ::octave_rl_get_startup_hook (); if (f != previous_startup_hook) ::octave_rl_set_startup_hook (f); } void gnu_readline::restore_startup_hook (void) { ::octave_rl_set_startup_hook (previous_startup_hook); } 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 (); ::octave_rl_set_event_hook (f); } void gnu_readline::restore_event_hook (void) { ::octave_rl_set_event_hook (previous_event_hook); } void gnu_readline::do_read_init_file (const std::string& file) { ::octave_rl_read_init_file (file.c_str ()); } void gnu_readline::do_re_read_init_file (void) { ::octave_rl_re_read_init_file (); } bool gnu_readline::do_filename_completion_desired (bool arg) { return ::octave_rl_filename_completion_desired (arg); } bool gnu_readline::do_filename_quoting_desired (bool arg) { return ::octave_rl_filename_quoting_desired (arg); } bool gnu_readline::do_prefer_env_winsize (bool arg) { return ::octave_rl_prefer_env_winsize (arg); } void gnu_readline::do_interrupt (bool arg) { ::octave_rl_done (arg); } int gnu_readline::operate_and_get_next (int /* count */, int /* c */) { // Accept the current line. command_editor::accept_line (); // Find the current line, and find the next line to use. int x_where = command_history::where (); int x_length = command_history::length (); if ((command_history::is_stifled () && (x_length >= command_history::max_input_history ())) || (x_where >= x_length - 1)) command_history::set_mark (x_where); else command_history::set_mark (x_where + 1); command_editor::add_startup_hook (command_history::goto_mark); return 0; } int gnu_readline::history_search_backward (int count, int c) { return octave_rl_history_search_backward (count, c); } int gnu_readline::history_search_forward (int count, int c) { return octave_rl_history_search_forward (count, c); } char * gnu_readline::command_generator (const char *text, int state) { char *retval = 0; completion_fcn f = command_editor::get_completion_function (); std::string tmp = f (text, state); size_t len = tmp.length (); if (len > 0) { retval = static_cast<char *> (gnulib::malloc (len+1)); strcpy (retval, tmp.c_str ()); } return retval; } char * gnu_readline::command_quoter (char *text, int matches, char *qcp) { char *retval = 0; quoting_fcn f = command_editor::get_quoting_function (); std::string tmp = f (text, matches, *qcp); size_t len = tmp.length (); if (len > 0) { retval = static_cast<char *> (gnulib::malloc (len+1)); strcpy (retval, tmp.c_str ()); } return retval; } char * gnu_readline::command_dequoter (char *text, int quote) { char *retval = 0; dequoting_fcn f = command_editor::get_dequoting_function (); std::string tmp = f (text, quote); size_t len = tmp.length (); if (len > 0) { retval = static_cast<char *> (gnulib::malloc (len+1)); strcpy (retval, tmp.c_str ()); } return retval; } int gnu_readline::command_char_is_quoted (char *text, int quote) { char_is_quoted_fcn f = command_editor::get_char_is_quoted_function (); return f (text, quote); } int gnu_readline::command_accept_line (int count, int key) { user_accept_line_fcn f = command_editor::get_user_accept_line_function (); if (f) f (::octave_rl_line_buffer ()); ::octave_rl_redisplay (); return ::octave_rl_newline (count, key); } char ** gnu_readline::command_completer (const char *text, int, int) { char **matches = 0; matches = ::octave_rl_completion_matches (text, gnu_readline::command_generator); return matches; } #endif class default_command_editor : public command_editor { public: default_command_editor (void) : command_editor (), input_stream (stdin), output_stream (stdout) { } ~default_command_editor (void) { } std::string do_readline (const std::string& prompt, bool& eof); void do_set_input_stream (FILE *f); FILE *do_get_input_stream (void); void do_set_output_stream (FILE *f); FILE *do_get_output_stream (void); string_vector do_generate_filename_completions (const std::string& text); 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_kill_full_line (void); void do_insert_text (const std::string& text); void do_newline (void); void do_accept_line (void); private: FILE *input_stream; FILE *output_stream; // No copying! default_command_editor (const default_command_editor&); default_command_editor& operator = (const default_command_editor&); }; std::string default_command_editor::do_readline (const std::string& prompt, bool& eof) { gnulib::fputs (prompt.c_str (), output_stream); gnulib::fflush (output_stream); return octave_fgetl (input_stream, eof); } void default_command_editor::do_set_input_stream (FILE *f) { input_stream = f; } FILE * default_command_editor::do_get_input_stream (void) { return input_stream; } void default_command_editor::do_set_output_stream (FILE *f) { output_stream = f; } FILE * default_command_editor::do_get_output_stream (void) { return output_stream; } string_vector default_command_editor::do_generate_filename_completions (const std::string&) { // FIXME return string_vector (); } std::string default_command_editor::do_get_line_buffer (void) const { 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_kill_full_line (void) { // FIXME } void default_command_editor::do_insert_text (const std::string&) { // FIXME } void default_command_editor::do_newline (void) { // FIXME } void default_command_editor::do_accept_line (void) { // FIXME } bool command_editor::instance_ok (void) { bool retval = true; if (! instance) { make_command_editor (); if (instance) singleton_cleanup_list::add (cleanup_instance); } if (! instance) { current_liboctave_error_handler ("unable to create command history object!"); retval = false; } return retval; } void command_editor::make_command_editor (void) { #if defined (USE_READLINE) instance = new gnu_readline (); #else instance = new default_command_editor (); #endif } void command_editor::force_default_editor (void) { delete instance; 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) { for (startup_hook_set_iterator p = startup_hook_set.begin (); p != startup_hook_set.end (); p++) { startup_hook_fcn f = *p; if (f) f (); } return 0; } 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 (); std::set<event_hook_fcn> hook_set (event_hook_set); event_hook_lock.unlock (); for (event_hook_set_iterator p = hook_set.begin (); p != hook_set.end (); p++) { event_hook_fcn f = *p; if (f) f (); } return 0; } void command_editor::set_name (const std::string& n) { if (instance_ok ()) instance->do_set_name (n); } std::string command_editor::readline (const std::string& prompt) { bool eof; return readline (prompt, eof); } std::string command_editor::readline (const std::string& prompt, bool& eof) { 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 command_editor::set_input_stream (FILE *f) { if (instance_ok ()) instance->do_set_input_stream (f); } FILE * command_editor::get_input_stream (void) { return (instance_ok ()) ? instance->do_get_input_stream () : 0; } void command_editor::set_output_stream (FILE *f) { if (instance_ok ()) instance->do_set_output_stream (f); } FILE * command_editor::get_output_stream (void) { return (instance_ok ()) ? instance->do_get_output_stream () : 0; } void command_editor::redisplay (void) { if (instance_ok ()) instance->do_redisplay (); } int command_editor::terminal_rows (void) { return (instance_ok ()) ? instance->do_terminal_rows () : -1; } int command_editor::terminal_cols (void) { return (instance_ok ()) ? instance->do_terminal_cols () : -1; } void command_editor::clear_screen (bool skip_redisplay) { if (instance_ok ()) instance->do_clear_screen (skip_redisplay); } void command_editor::resize_terminal (void) { if (instance_ok ()) instance->do_resize_terminal (); } void command_editor::set_screen_size (int ht, int wd) { if (instance_ok ()) instance->do_set_screen_size (ht, wd); } std::string command_editor::decode_prompt_string (const std::string& s) { return (instance_ok ()) ? instance->do_decode_prompt_string (s) : std::string (); } int command_editor::current_command_number (void) { return (instance_ok ()) ? instance->command_number : 0; } void command_editor::reset_current_command_number (int n) { if (instance_ok ()) instance->command_number = n; } void command_editor::increment_current_command_number (void) { if (instance_ok ()) instance->command_number++; } void command_editor::restore_terminal_state (void) { if (instance_ok ()) instance->do_restore_terminal_state (); } void command_editor::blink_matching_paren (bool flag) { if (instance_ok ()) instance->do_blink_matching_paren (flag); } bool command_editor::erase_empty_line (bool flag) { return instance_ok () ? instance->do_erase_empty_line (flag) : false; } void command_editor::set_basic_word_break_characters (const std::string& s) { if (instance_ok ()) instance->do_set_basic_word_break_characters (s); } void command_editor::set_completer_word_break_characters (const std::string& s) { if (instance_ok ()) instance->do_set_completer_word_break_characters (s); } void command_editor::set_basic_quote_characters (const std::string& s) { if (instance_ok ()) instance->do_set_basic_quote_characters (s); } void command_editor::set_filename_quote_characters (const std::string& s) { if (instance_ok ()) instance->do_set_filename_quote_characters (s); } void command_editor::set_completer_quote_characters (const std::string& s) { if (instance_ok ()) instance->do_set_completer_quote_characters (s); } void command_editor::set_completion_append_character (char c) { if (instance_ok ()) instance->do_set_completion_append_character (c); } void command_editor::set_completion_function (completion_fcn f) { if (instance_ok ()) instance->do_set_completion_function (f); } void command_editor::set_quoting_function (quoting_fcn f) { if (instance_ok ()) instance->do_set_quoting_function (f); } void command_editor::set_dequoting_function (dequoting_fcn f) { if (instance_ok ()) instance->do_set_dequoting_function (f); } void command_editor::set_char_is_quoted_function (char_is_quoted_fcn f) { if (instance_ok ()) instance->do_set_char_is_quoted_function (f); } void command_editor::set_user_accept_line_function (user_accept_line_fcn f) { if (instance_ok ()) instance->do_set_user_accept_line_function (f); } command_editor::completion_fcn command_editor::get_completion_function (void) { return (instance_ok ()) ? instance->do_get_completion_function () : 0; } command_editor::quoting_fcn command_editor::get_quoting_function (void) { return (instance_ok ()) ? instance->do_get_quoting_function () : 0; } command_editor::dequoting_fcn command_editor::get_dequoting_function (void) { return (instance_ok ()) ? instance->do_get_dequoting_function () : 0; } command_editor::char_is_quoted_fcn command_editor::get_char_is_quoted_function (void) { return (instance_ok ()) ? instance->do_get_char_is_quoted_function () : 0; } command_editor::user_accept_line_fcn command_editor::get_user_accept_line_function (void) { return (instance_ok ()) ? instance->do_get_user_accept_line_function () : 0; } string_vector command_editor::generate_filename_completions (const std::string& text) { return (instance_ok ()) ? instance->do_generate_filename_completions (text) : string_vector (); } std::string command_editor::get_line_buffer (void) { 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::kill_full_line (void) { if (instance_ok ()) instance->do_kill_full_line (); } void command_editor::insert_text (const std::string& text) { if (instance_ok ()) instance->do_insert_text (text); } void command_editor::newline (void) { if (instance_ok ()) instance->do_newline (); } void command_editor::accept_line (void) { if (instance_ok ()) instance->do_accept_line (); } bool command_editor::undo (void) { return instance_ok () ? instance->do_undo () : false; } void command_editor::clear_undo_list (void) { if (instance_ok ()) instance->do_clear_undo_list (); } void command_editor::add_startup_hook (startup_hook_fcn f) { if (instance_ok ()) { startup_hook_set.insert (f); instance->set_startup_hook (startup_handler); } } void command_editor::remove_startup_hook (startup_hook_fcn f) { if (instance_ok ()) { startup_hook_set_iterator p = startup_hook_set.find (f); if (p != startup_hook_set.end ()) startup_hook_set.erase (p); if (startup_hook_set.empty ()) instance->restore_startup_hook (); } } 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); if (instance_ok ()) { event_hook_set.insert (f); instance->set_event_hook (event_handler); } } void command_editor::remove_event_hook (event_hook_fcn f) { octave_autolock guard (event_hook_lock); if (instance_ok ()) { event_hook_set_iterator p = event_hook_set.find (f); if (p != event_hook_set.end ()) event_hook_set.erase (p); if (event_hook_set.empty ()) instance->restore_event_hook (); } } void command_editor::run_event_hooks (void) { event_handler (); } void command_editor::read_init_file (const std::string& file_arg) { if (instance_ok ()) { std::string file = file_ops::tilde_expand (file_arg); instance->do_read_init_file (file); } } void command_editor::re_read_init_file (void) { if (instance_ok ()) instance->do_re_read_init_file (); } bool command_editor::filename_completion_desired (bool arg) { return (instance_ok ()) ? instance->do_filename_completion_desired (arg) : false; } bool command_editor::filename_quoting_desired (bool arg) { return (instance_ok ()) ? instance->do_filename_quoting_desired (arg) : false; } bool command_editor::prefer_env_winsize (bool arg) { return (instance_ok ()) ? instance->do_prefer_env_winsize (arg) : false; } bool command_editor::interrupt (bool arg) { bool retval; if (instance_ok ()) { // Return the current interrupt state. retval = instance->interrupted; instance->do_interrupt (arg); instance->interrupted = arg; } else retval = false; return retval; } // Return a string which will be printed as a prompt. The string may // contain special characters which are decoded as follows: // // \a bell (ascii 07) // \d the date // \e escape (ascii 033) // \h the hostname up to the first '.' // \H the hostname // \n CRLF // \r CR // \s the name of the shell (program) // \t the time // \T the time in 12-hour hh:mm:ss format // \@ the time in 12-hour hh:mm am/pm format // \A the time in 24-hour hh:mm format // \u your username // \w the current working directory // \W the last element of PWD // \! the history number of this command // \# the command number of this command // \$ a $ or a # if you are root // \nnn character code nnn in octal // \\ a backslash // \[ begin a sequence of non-printing chars // \] end a sequence of non-printing chars std::string command_editor::do_decode_prompt_string (const std::string& s) { std::string result; std::string temp; size_t i = 0; size_t slen = s.length (); int c; while (i < slen) { c = s[i]; i++; if (c == '\\') { c = s[i]; switch (c) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': // Maybe convert an octal number. { int n = read_octal (s.substr (i, 3)); temp = "\\"; if (n != -1) { i += 3; temp[0] = n; } c = 0; goto add_string; } case 'a': { temp = '\a'; goto add_string; } case 'e': { temp = '\033'; goto add_string; } case 'r': { temp = '\r'; goto add_string; } case 'd': case 't': case 'T': case '@': case 'A': // Make the current time/date into a string. { octave_localtime now; if (c == 'd') temp = now.strftime ("%a %b %d"); else if (c == 't') temp = now.strftime ("%H:%M:%S"); else if (c == 'T') temp = now.strftime ("%I:%M:%S"); else if (c == '@') temp = now.strftime ("%I:%M %p"); else if (c == 'A') temp = now.strftime ("%H:%M"); goto add_string; } case 'n': { temp = newline_chars (); goto add_string; } case 's': { temp = octave_env::get_program_name (); temp = octave_env::base_pathname (temp); goto add_string; } case 'w': case 'W': { try { temp = octave_env::get_current_directory (); } catch (const octave_execution_exception&) { temp = ""; } std::string home_dir = octave_env::get_home_directory (); if (c == 'W' && (home_dir.empty () || temp != home_dir)) { if (temp != "/" && temp != "//") { size_t pos = temp.rfind ('/'); if (pos != std::string::npos && pos != 0) temp = temp.substr (pos + 1); } } else temp = octave_env::polite_directory_format (temp); goto add_string; } case 'u': { temp = octave_env::get_user_name (); goto add_string; } case 'H': { temp = octave_env::get_host_name (); goto add_string; } case 'h': { temp = octave_env::get_host_name (); size_t pos = temp.find ('.'); if (pos != std::string::npos) temp.resize (pos); goto add_string; } case '#': { char number_buffer[128]; sprintf (number_buffer, "%d", command_number); temp = number_buffer; goto add_string; } case '!': { char number_buffer[128]; int num = command_history::current_number (); if (num > 0) sprintf (number_buffer, "%d", num); else strcpy (number_buffer, "!"); temp = number_buffer; goto add_string; } case '$': { #if defined (HAVE_GETEUID) temp = (::geteuid () == 0 ? "#" : "$"); #else temp = "$"; #endif goto add_string; } #if defined (USE_READLINE) case '[': case ']': { temp.resize (1); temp[0] = ((c == '[') ? ::octave_rl_prompt_start_ignore () : ::octave_rl_prompt_end_ignore ()); goto add_string; } #endif case '\\': { temp = "\\"; goto add_string; } default: { temp = "\\ "; temp[1] = c; goto add_string; } add_string: { if (c) i++; result.append (temp); break; } } } else result += c; } 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. int command_editor::read_octal (const std::string& s) { int result = 0; int digits = 0; size_t i = 0; size_t slen = s.length (); while (i < slen && s[i] >= '0' && s[i] < '8') { digits++; result = (result * 8) + s[i] - '0'; i++; } if (! digits || result > 0777 || i < slen) result = -1; return result; } void command_editor::error (int err_num) { current_liboctave_error_handler ("%s", gnulib::strerror (err_num)); } void command_editor::error (const std::string& s) { current_liboctave_error_handler ("%s", s.c_str ()); }