1 //////////////////////////////////////////////////////////////////////// 2 // 3 // Copyright (C) 1996-2021 The Octave Project Developers 4 // 5 // See the file COPYRIGHT.md in the top-level directory of this 6 // distribution or <https://octave.org/copyright/>. 7 // 8 // This file is part of Octave. 9 // 10 // Octave is free software: you can redistribute it and/or modify it 11 // under the terms of the GNU General Public License as published by 12 // the Free Software Foundation, either version 3 of the License, or 13 // (at your option) any later version. 14 // 15 // Octave is distributed in the hope that it will be useful, but 16 // WITHOUT ANY WARRANTY; without even the implied warranty of 17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 // GNU General Public License for more details. 19 // 20 // You should have received a copy of the GNU General Public License 21 // along with Octave; see the file COPYING. If not, see 22 // <https://www.gnu.org/licenses/>. 23 // 24 //////////////////////////////////////////////////////////////////////// 25 26 #if ! defined (octave_cmd_edit_h) 27 #define octave_cmd_edit_h 1 28 29 #include "octave-config.h" 30 31 #include <cstdio> 32 33 #include <set> 34 #include <string> 35 36 #include "str-vec.h" 37 38 namespace octave 39 { 40 class 41 OCTAVE_API 42 command_editor 43 { 44 protected: 45 command_editor(void)46 command_editor (void) 47 : m_command_number (1), m_rows (24), m_cols (80), m_interrupted (false), 48 m_interrupt_event_loop (false), m_initial_input () 49 { } 50 51 public: 52 53 typedef int (*startup_hook_fcn) (void); 54 55 typedef int (*pre_input_hook_fcn) (void); 56 57 typedef int (*event_hook_fcn) (void); 58 59 typedef std::string (*completion_fcn) (const std::string&, int); 60 61 typedef char * (*completion_hook_fcn) (); 62 63 typedef std::string (*quoting_fcn) (const std::string&, int, char); 64 65 typedef std::string (*dequoting_fcn) (const std::string&, int); 66 67 typedef int (*char_is_quoted_fcn) (const std::string&, int); 68 69 typedef void (*user_accept_line_fcn) (const std::string&); 70 71 // No copying! 72 73 command_editor (const command_editor&) = delete; 74 75 command_editor& operator = (const command_editor&) = delete; 76 77 virtual ~command_editor (void) = default; 78 79 static void set_name (const std::string& n); 80 81 static std::string readline (const std::string& prompt); 82 83 static std::string readline (const std::string& prompt, bool& eof); 84 85 static void set_input_stream (FILE *f); 86 87 static FILE * get_input_stream (void); 88 89 static void set_output_stream (FILE *f); 90 91 static FILE * get_output_stream (void); 92 93 static void redisplay (void); 94 95 static int terminal_rows (void); 96 97 static int terminal_cols (void); 98 99 static void clear_screen (bool skip_redisplay = false); 100 101 static void resize_terminal (void); 102 103 static void set_screen_size (int ht, int wd); 104 105 static std::string decode_prompt_string (const std::string& s); 106 107 static void restore_terminal_state (void); 108 109 static void blink_matching_paren (bool flag); 110 111 static bool erase_empty_line (bool flag); 112 113 static void set_basic_word_break_characters (const std::string& s); 114 115 static void set_completer_word_break_characters (const std::string& s); 116 117 static void set_basic_quote_characters (const std::string& s); 118 119 static void set_filename_quote_characters (const std::string& s); 120 121 static void set_completer_quote_characters (const std::string& s); 122 123 static void set_completion_append_character (char c); 124 125 static void set_completion_function (completion_fcn f); 126 127 static void set_quoting_function (quoting_fcn f); 128 129 static void set_dequoting_function (dequoting_fcn f); 130 131 static void set_char_is_quoted_function (char_is_quoted_fcn f); 132 133 static void set_user_accept_line_function (user_accept_line_fcn f); 134 135 static completion_fcn get_completion_function (void); 136 137 static quoting_fcn get_quoting_function (void); 138 139 static dequoting_fcn get_dequoting_function (void); 140 141 static char_is_quoted_fcn get_char_is_quoted_function (void); 142 143 static user_accept_line_fcn get_user_accept_line_function (void); 144 145 static string_vector generate_filename_completions (const std::string& text); 146 147 static std::string get_line_buffer (void); 148 149 static std::string get_current_line (void); 150 151 static char get_prev_char (int); 152 153 static void replace_line (const std::string& text, bool clear_undo = true); 154 155 static void kill_full_line (void); 156 157 static void insert_text (const std::string& text); 158 159 static void newline (void); 160 161 static void accept_line (void); 162 163 static bool undo (void); 164 165 static void clear_undo_list (void); 166 167 static void add_startup_hook (startup_hook_fcn f); 168 169 static void remove_startup_hook (startup_hook_fcn f); 170 171 static void add_pre_input_hook (pre_input_hook_fcn f); 172 173 static void remove_pre_input_hook (pre_input_hook_fcn f); 174 175 static void add_event_hook (event_hook_fcn f); 176 177 static void remove_event_hook (event_hook_fcn f); 178 179 static void run_event_hooks (void); 180 181 static void read_init_file (const std::string& file = ""); 182 183 static void re_read_init_file (void); 184 185 static bool filename_completion_desired (bool); 186 187 static bool filename_quoting_desired (bool); 188 189 static bool prefer_env_winsize (bool); 190 191 static bool interrupt (bool = true); 192 193 static void interrupt_event_loop (bool flag = true); 194 195 static bool event_loop_interrupted (void); 196 197 static int current_command_number (void); 198 199 static void reset_current_command_number (int n); 200 201 static void increment_current_command_number (void); 202 203 static void force_default_editor (void); 204 205 static void set_initial_input (const std::string& text); 206 207 static int insert_initial_input (void); 208 209 private: 210 211 static bool instance_ok (void); 212 213 static void make_command_editor (void); 214 215 static int startup_handler (void); 216 217 static int pre_input_handler (void); 218 219 static int event_handler (void); 220 221 static std::set<startup_hook_fcn> startup_hook_set; 222 223 static std::set<pre_input_hook_fcn> pre_input_hook_set; 224 225 static std::set<event_hook_fcn> event_hook_set; 226 227 // The real thing. 228 static command_editor *s_instance; 229 cleanup_instance(void)230 static void cleanup_instance (void) 231 { 232 delete s_instance; 233 s_instance = nullptr; 234 } 235 236 static void handle_interrupt_signal (void); 237 238 protected: 239 240 // To use something other than the GNU readline library, derive a new 241 // class from command_editor, overload these functions as 242 // necessary, and make instance point to the new class. 243 do_set_name(const std::string &)244 virtual void do_set_name (const std::string&) { } 245 do_readline(const std::string & prompt)246 std::string do_readline (const std::string& prompt) 247 { 248 bool eof; 249 250 return do_readline (prompt, eof); 251 } 252 253 virtual std::string do_readline (const std::string&, bool&) = 0; 254 255 virtual void do_set_input_stream (FILE *) = 0; 256 257 virtual FILE * do_get_input_stream (void) = 0; 258 259 virtual void do_set_output_stream (FILE *) = 0; 260 261 virtual FILE * do_get_output_stream (void) = 0; 262 do_redisplay(void)263 virtual void do_redisplay (void) { } 264 do_terminal_rows(void)265 virtual int do_terminal_rows (void) { return m_rows; } 266 do_terminal_cols(void)267 virtual int do_terminal_cols (void) { return m_cols; } 268 do_clear_screen(bool)269 virtual void do_clear_screen (bool) { } 270 do_resize_terminal(void)271 virtual void do_resize_terminal (void) { } 272 do_set_screen_size(int ht,int wd)273 virtual void do_set_screen_size (int ht, int wd) 274 { 275 m_rows = ht; 276 m_cols = wd; 277 } 278 279 virtual std::string do_decode_prompt_string (const std::string&); 280 newline_chars(void)281 virtual std::string newline_chars (void) { return "\n"; } 282 do_restore_terminal_state(void)283 virtual void do_restore_terminal_state (void) { } 284 do_blink_matching_paren(bool)285 virtual void do_blink_matching_paren (bool) { } 286 do_erase_empty_line(bool)287 virtual bool do_erase_empty_line (bool) { return false; } 288 do_set_basic_word_break_characters(const std::string &)289 virtual void do_set_basic_word_break_characters (const std::string&) { } 290 do_set_completer_word_break_characters(const std::string &)291 virtual void do_set_completer_word_break_characters (const std::string&) { } 292 do_set_completer_word_break_hook(completion_hook_fcn)293 virtual void do_set_completer_word_break_hook (completion_hook_fcn) { } 294 do_set_basic_quote_characters(const std::string &)295 virtual void do_set_basic_quote_characters (const std::string&) { } 296 do_set_filename_quote_characters(const std::string &)297 virtual void do_set_filename_quote_characters (const std::string&) { } 298 do_set_completer_quote_characters(const std::string &)299 virtual void do_set_completer_quote_characters (const std::string&) { } 300 do_set_completion_append_character(char)301 virtual void do_set_completion_append_character (char) { } 302 do_set_completion_function(completion_fcn)303 virtual void do_set_completion_function (completion_fcn) { } 304 do_set_quoting_function(quoting_fcn)305 virtual void do_set_quoting_function (quoting_fcn) { } 306 do_set_dequoting_function(dequoting_fcn)307 virtual void do_set_dequoting_function (dequoting_fcn) { } 308 do_set_char_is_quoted_function(char_is_quoted_fcn)309 virtual void do_set_char_is_quoted_function (char_is_quoted_fcn) { } 310 do_set_user_accept_line_function(user_accept_line_fcn)311 virtual void do_set_user_accept_line_function (user_accept_line_fcn) { } 312 do_get_completion_function(void)313 virtual completion_fcn do_get_completion_function (void) const { return nullptr; } 314 do_get_quoting_function(void)315 virtual quoting_fcn do_get_quoting_function (void) const { return nullptr; } 316 do_get_dequoting_function(void)317 virtual dequoting_fcn do_get_dequoting_function (void) const { return nullptr; } 318 do_get_char_is_quoted_function(void)319 virtual char_is_quoted_fcn do_get_char_is_quoted_function (void) const 320 { return nullptr; } 321 do_get_user_accept_line_function(void)322 virtual user_accept_line_fcn do_get_user_accept_line_function (void) const 323 { return nullptr; } 324 325 virtual string_vector 326 do_generate_filename_completions (const std::string& text) = 0; 327 328 virtual std::string do_get_line_buffer (void) const = 0; 329 330 virtual std::string do_get_current_line (void) const = 0; 331 332 virtual char do_get_prev_char (int) const = 0; 333 334 virtual void do_replace_line (const std::string& text, bool clear_undo) = 0; 335 336 virtual void do_kill_full_line (void) = 0; 337 338 virtual void do_insert_text (const std::string& text) = 0; 339 340 virtual void do_newline (void) = 0; 341 342 virtual void do_accept_line (void) = 0; 343 do_undo(void)344 virtual bool do_undo (void) { return false; } 345 do_clear_undo_list(void)346 virtual void do_clear_undo_list (void) { } 347 set_startup_hook(startup_hook_fcn)348 virtual void set_startup_hook (startup_hook_fcn) { } 349 restore_startup_hook(void)350 virtual void restore_startup_hook (void) { } 351 set_pre_input_hook(pre_input_hook_fcn)352 virtual void set_pre_input_hook (pre_input_hook_fcn) { } 353 restore_pre_input_hook(void)354 virtual void restore_pre_input_hook (void) { } 355 set_event_hook(event_hook_fcn)356 virtual void set_event_hook (event_hook_fcn) { } 357 restore_event_hook(void)358 virtual void restore_event_hook (void) { } 359 do_read_init_file(const std::string &)360 virtual void do_read_init_file (const std::string&) { } 361 do_re_read_init_file(void)362 virtual void do_re_read_init_file (void) { } 363 do_filename_completion_desired(bool)364 virtual bool do_filename_completion_desired (bool) { return false; } 365 do_filename_quoting_desired(bool)366 virtual bool do_filename_quoting_desired (bool) { return false; } 367 do_prefer_env_winsize(bool)368 virtual bool do_prefer_env_winsize (bool) { return false; } 369 do_interrupt(bool)370 virtual void do_interrupt (bool) { } 371 do_handle_interrupt_signal(void)372 virtual void do_handle_interrupt_signal (void) { } 373 do_interrupt_event_loop(bool arg)374 void do_interrupt_event_loop (bool arg) { m_interrupt_event_loop = arg; } 375 do_event_loop_interrupted(void)376 bool do_event_loop_interrupted (void) const 377 { 378 return m_interrupt_event_loop; 379 } 380 381 int do_insert_initial_input (void); 382 383 int read_octal (const std::string& s); 384 385 void error (int); 386 387 void error (const std::string&); 388 389 // The current command number. 390 int m_command_number; 391 392 int m_rows; 393 int m_cols; 394 395 bool m_interrupted; 396 397 bool m_interrupt_event_loop; 398 399 std::string m_initial_input; 400 }; 401 } 402 403 #endif 404