1 //////////////////////////////////////////////////////////////////////// 2 // 3 // Copyright (C) 1993-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 // Get command input interactively or from files. 27 28 #if defined (HAVE_CONFIG_H) 29 # include "config.h" 30 #endif 31 32 #include <cstdio> 33 #include <cstdlib> 34 #include <cstring> 35 #include <cassert> 36 37 #include <algorithm> 38 #include <iostream> 39 #include <queue> 40 #include <sstream> 41 #include <string> 42 43 #include "cmd-edit.h" 44 #include "file-ops.h" 45 #include "iconv-wrappers.h" 46 #include "localcharset-wrapper.h" 47 #include "oct-string.h" 48 #include "quit.h" 49 #include "str-vec.h" 50 #include "uniconv-wrappers.h" 51 52 #include "builtin-defun-decls.h" 53 #include "defun.h" 54 #include "error.h" 55 #include "errwarn.h" 56 #include "event-manager.h" 57 #include "help.h" 58 #include "hook-fcn.h" 59 #include "input.h" 60 #include "interpreter-private.h" 61 #include "interpreter.h" 62 #include "load-path.h" 63 #include "octave.h" 64 #include "oct-map.h" 65 #include "oct-hist.h" 66 #include "interpreter.h" 67 #include "event-manager.h" 68 #include "ovl.h" 69 #include "ov-fcn-handle.h" 70 #include "ov-usr-fcn.h" 71 #include "pager.h" 72 #include "parse.h" 73 #include "pt-eval.h" 74 #include "pt-stmt.h" 75 #include "sighandlers.h" 76 #include "sysdep.h" 77 #include "interpreter.h" 78 #include "unwind-prot.h" 79 #include "utils.h" 80 #include "variables.h" 81 82 // The time we last printed a prompt. 83 octave::sys::time Vlast_prompt_time = 0.0; 84 85 // TRUE after a call to completion_matches. 86 bool octave_completion_matches_called = false; 87 88 // TRUE if the plotting system has requested a call to drawnow at 89 // the next user prompt. 90 bool Vdrawnow_requested = false; 91 92 // TRUE if we are recording line numbers in a source file. 93 // Always true except when debugging and taking input directly from 94 // the terminal. 95 bool Vtrack_line_num = true; 96 97 namespace octave 98 { 99 static std::string quoting_filename(const std::string & text,int,char quote)100 quoting_filename (const std::string& text, int, char quote) 101 { 102 if (quote) 103 return text; 104 else 105 return ("'" + text); 106 } 107 108 // Try to parse a partial command line in reverse, excluding trailing TEXT. 109 // If it appears a variable has been indexed by () or {}, 110 // return that expression, 111 // to allow autocomplete of field names of arrays of structures. 112 static std::string find_indexed_expression(const std::string & text)113 find_indexed_expression (const std::string& text) 114 { 115 std::string line = command_editor::get_line_buffer (); 116 117 int pos = line.length () - text.length (); 118 int curly_count = 0; 119 int paren_count = 0; 120 121 int last = --pos; 122 123 while (pos >= 0 && (line[pos] == ')' || line[pos] == '}')) 124 { 125 if (line[pos] == ')') 126 paren_count++; 127 else 128 curly_count++; 129 130 while (curly_count + paren_count > 0 && --pos >= 0) 131 { 132 if (line[pos] == ')') 133 paren_count++; 134 else if (line[pos] == '(') 135 paren_count--; 136 else if (line[pos] == '}') 137 curly_count++; 138 else if (line[pos] == '{') 139 curly_count--; 140 } 141 142 while (--pos >= 0 && line[pos] == ' ') 143 ; 144 } 145 146 while (pos >= 0 && (isalnum (line[pos]) || line[pos] == '_')) 147 pos--; 148 149 if (++pos >= 0) 150 return (line.substr (pos, last + 1 - pos)); 151 else 152 return std::string (); 153 } 154 155 static string_vector generate_struct_completions(const std::string & text,std::string & prefix,std::string & hint)156 generate_struct_completions (const std::string& text, 157 std::string& prefix, std::string& hint) 158 { 159 string_vector names; 160 161 std::size_t pos = text.rfind ('.'); 162 bool array = false; 163 164 if (pos != std::string::npos) 165 { 166 if (pos == text.length ()) 167 hint = ""; 168 else 169 hint = text.substr (pos+1); 170 171 prefix = text.substr (0, pos); 172 173 if (prefix == "") 174 { 175 array = true; 176 prefix = find_indexed_expression (text); 177 } 178 179 std::string base_name = prefix; 180 181 pos = base_name.find_first_of ("{(. "); 182 183 if (pos != std::string::npos) 184 base_name = base_name.substr (0, pos); 185 186 interpreter& interp 187 = __get_interpreter__ ("generate_struct_completions"); 188 189 if (interp.is_variable (base_name)) 190 { 191 int parse_status; 192 193 error_system& es = interp.get_error_system (); 194 195 unwind_protect frame; 196 197 frame.add_method (es, &error_system::set_discard_warning_messages, 198 es.discard_warning_messages ()); 199 200 es.discard_warning_messages (true); 201 202 try 203 { 204 octave_value tmp 205 = interp.eval_string (prefix, true, parse_status); 206 207 frame.run (); 208 209 if (tmp.is_defined () 210 && (tmp.isstruct () || tmp.isjava () || tmp.is_classdef_object ())) 211 names = tmp.map_keys (); 212 } 213 catch (const execution_exception&) 214 { 215 interp.recover_from_exception (); 216 } 217 } 218 } 219 220 // Undo look-back that found the array expression, 221 // but insert an extra "." to distinguish from the non-struct case. 222 if (array) 223 prefix = "."; 224 225 return names; 226 } 227 228 // FIXME: this will have to be much smarter to work "correctly". 229 static bool looks_like_struct(const std::string & text,char prev_char)230 looks_like_struct (const std::string& text, char prev_char) 231 { 232 bool retval = (! text.empty () 233 && (text != "." || prev_char == ')' || prev_char == '}') 234 && text.find_first_of (sys::file_ops::dir_sep_chars ()) == std::string::npos 235 && text.find ("..") == std::string::npos 236 && text.rfind ('.') != std::string::npos); 237 238 return retval; 239 } 240 241 // FIXME: make this generate filenames when appropriate. 242 243 static string_vector generate_possible_completions(const std::string & text,std::string & prefix,std::string & hint,bool & deemed_struct)244 generate_possible_completions (const std::string& text, std::string& prefix, 245 std::string& hint, bool& deemed_struct) 246 { 247 string_vector names; 248 249 prefix = ""; 250 251 char prev_char = command_editor::get_prev_char (text.length ()); 252 deemed_struct = looks_like_struct (text, prev_char); 253 254 if (deemed_struct) 255 names = generate_struct_completions (text, prefix, hint); 256 else 257 names = make_name_list (); 258 259 // Sort and remove duplicates. 260 261 names.sort (true); 262 263 return names; 264 } 265 266 static bool is_completing_dirfns(void)267 is_completing_dirfns (void) 268 { 269 static std::string dirfns_commands[] = {"cd", "isfile", "isfolder", "ls"}; 270 static const std::size_t dirfns_commands_length = 4; 271 272 bool retval = false; 273 274 std::string line = command_editor::get_line_buffer (); 275 276 for (std::size_t i = 0; i < dirfns_commands_length; i++) 277 { 278 int index = line.find (dirfns_commands[i] + ' '); 279 280 if (index == 0) 281 { 282 retval = true; 283 break; 284 } 285 } 286 287 return retval; 288 } 289 290 static std::string generate_completion(const std::string & text,int state)291 generate_completion (const std::string& text, int state) 292 { 293 std::string retval; 294 295 static std::string prefix; 296 static std::string hint; 297 298 static std::size_t hint_len = 0; 299 300 static int list_index = 0; 301 static int name_list_len = 0; 302 static int name_list_total_len = 0; 303 static string_vector name_list; 304 static string_vector file_name_list; 305 306 static int matches = 0; 307 308 if (state == 0) 309 { 310 list_index = 0; 311 312 prefix = ""; 313 314 hint = text; 315 316 // No reason to display symbols while completing a 317 // file/directory operation. 318 319 bool deemed_struct = false; 320 321 if (is_completing_dirfns ()) 322 name_list = string_vector (); 323 else 324 name_list = generate_possible_completions (text, prefix, hint, 325 deemed_struct); 326 327 name_list_len = name_list.numel (); 328 329 // If the line was something like "a{1}." then text = "." but 330 // we don't want to expand all the . files. 331 if (! deemed_struct) 332 { 333 334 file_name_list = command_editor::generate_filename_completions (text); 335 336 name_list.append (file_name_list); 337 338 } 339 340 name_list_total_len = name_list.numel (); 341 342 hint_len = hint.length (); 343 344 matches = 0; 345 346 for (int i = 0; i < name_list_len; i++) 347 if (hint == name_list[i].substr (0, hint_len)) 348 matches++; 349 } 350 351 if (name_list_total_len > 0 && matches > 0) 352 { 353 while (list_index < name_list_total_len) 354 { 355 std::string name = name_list[list_index]; 356 357 list_index++; 358 359 if (hint == name.substr (0, hint_len)) 360 { 361 // Special case: array reference forces prefix="." 362 // in generate_struct_completions () 363 if (list_index <= name_list_len && ! prefix.empty ()) 364 retval = (prefix == "." ? "" : prefix) + '.' + name; 365 else 366 retval = name; 367 368 char prev_char = 369 command_editor::get_prev_char (text.length ()); 370 371 if (matches == 1 && looks_like_struct (retval, prev_char)) 372 { 373 // Don't append anything, since we don't know 374 // whether it should be '(' or '.'. 375 376 command_editor::set_completion_append_character ('\0'); 377 } 378 else 379 { 380 input_system& input_sys 381 = __get_input_system__ ("generate_completion"); 382 383 command_editor::set_completion_append_character 384 (input_sys.completion_append_char ()); 385 } 386 387 break; 388 } 389 } 390 } 391 392 return retval; 393 } 394 internal_input_event_hook_fcn(void)395 static int internal_input_event_hook_fcn (void) 396 { 397 octave_quit (); 398 399 input_system& input_sys 400 = __get_input_system__ ("internal_input_event_hook_fcn"); 401 402 input_sys.run_input_event_hooks (); 403 404 return 0; 405 } 406 407 // Use literal "octave" in default setting for PS1 instead of 408 // "\\s" to avoid setting the prompt to "octave.exe" or 409 // "octave-gui", etc. 410 input_system(interpreter & interp)411 input_system::input_system (interpreter& interp) 412 : m_interpreter (interp), m_PS1 (R"(octave:\#> )"), m_PS2 ("> "), 413 m_completion_append_char (' '), m_gud_mode (false), 414 m_mfile_encoding ("system"), m_auto_repeat_debug_command (true), 415 m_last_debugging_command ("\n"), m_input_event_hook_functions (), 416 m_initialized (false) 417 { } 418 initialize(bool line_editing)419 void input_system::initialize (bool line_editing) 420 { 421 if (m_initialized) 422 return; 423 424 // Force default line editor if we don't want readline editing. 425 if (! line_editing) 426 { 427 command_editor::force_default_editor (); 428 return; 429 } 430 431 // If we are using readline, this allows conditional parsing of the 432 // .inputrc file. 433 434 command_editor::set_name ("Octave"); 435 436 // FIXME: this needs to include a comma too, but that 437 // causes trouble for the new struct element completion code. 438 439 static const char *s = "\t\n !\"\'*+-/:;<=>(){}[\\]^`~"; 440 441 command_editor::set_basic_word_break_characters (s); 442 443 command_editor::set_completer_word_break_characters (s); 444 445 command_editor::set_basic_quote_characters (R"(")"); 446 447 command_editor::set_filename_quote_characters (" \t\n\\\"'@<>=;|&()#$`?*[!:{"); 448 449 command_editor::set_completer_quote_characters (R"('")"); 450 451 command_editor::set_completion_function (generate_completion); 452 453 command_editor::set_quoting_function (quoting_filename); 454 455 command_editor::add_event_hook (internal_input_event_hook_fcn); 456 457 m_initialized = true; 458 } 459 460 octave_value 461 input_system::PS1 (const octave_value_list& args, int nargout) 462 { 463 return set_internal_variable (m_PS1, args, nargout, "PS1"); 464 } 465 466 octave_value 467 input_system::PS2 (const octave_value_list& args, int nargout) 468 { 469 return set_internal_variable (m_PS2, args, nargout, "PS2"); 470 } 471 472 octave_value 473 input_system::completion_append_char (const octave_value_list& args, 474 int nargout) 475 { 476 return set_internal_variable (m_completion_append_char, args, nargout, 477 "completion_append_char"); 478 } 479 480 octave_value 481 input_system::gud_mode (const octave_value_list& args, int nargout) 482 { 483 return set_internal_variable (m_gud_mode, args, nargout, "__gud_mode__"); 484 } 485 486 octave_value 487 input_system::mfile_encoding (const octave_value_list& args, int nargout) 488 { 489 // Save current value in case there is an error in the additional 490 // validation below. 491 492 std::string saved_encoding = m_mfile_encoding; 493 494 // We must pass the actual variable to change here for temporary 495 // "local" settings to work properly. 496 497 octave_value retval 498 = set_internal_variable (m_mfile_encoding, args, nargout, 499 "__mfile_encoding__"); 500 501 // Additional validation if the encoding has changed. 502 503 if (m_mfile_encoding != saved_encoding) 504 { 505 if (m_mfile_encoding.empty ()) 506 { 507 m_mfile_encoding = "system"; 508 } 509 else 510 { 511 std::transform (m_mfile_encoding.begin (), 512 m_mfile_encoding.end (), 513 m_mfile_encoding.begin (), ::tolower); 514 515 std::string encoding = (m_mfile_encoding.compare ("system") == 0) 516 ? octave_locale_charset_wrapper () : m_mfile_encoding; 517 518 // Check for valid encoding name. 519 void *codec 520 = octave_iconv_open_wrapper (encoding.c_str (), "utf-8"); 521 522 if (codec == reinterpret_cast<void *> (-1)) 523 { 524 m_mfile_encoding = saved_encoding; 525 if (errno == EINVAL) 526 error ("__mfile_encoding__: conversion from encoding '%s' " 527 "not supported", encoding.c_str ()); 528 else 529 error ("__mfile_encoding__: error %d opening encoding '%s'.", 530 errno, encoding.c_str ()); 531 } 532 else 533 octave_iconv_close_wrapper (codec); 534 } 535 536 } 537 538 // Synchronize the related gui preference for editor encoding 539 feval ("__event_manager_gui_preference__", 540 ovl ("editor/default_encoding", m_mfile_encoding)); 541 542 return retval; 543 } 544 545 octave_value 546 input_system::auto_repeat_debug_command (const octave_value_list& args, 547 int nargout) 548 { 549 return set_internal_variable (m_auto_repeat_debug_command, args, nargout, 550 "auto_repeat_debug_command"); 551 } 552 553 bool input_system::yes_or_no (const std::string& prompt) 554 { 555 std::string prompt_string = prompt + "(yes or no) "; 556 557 while (1) 558 { 559 bool eof = false; 560 561 std::string input_buf = interactive_input (prompt_string, eof); 562 563 if (input_buf == "yes") 564 return true; 565 else if (input_buf == "no") 566 return false; 567 else 568 message (nullptr, "Please answer yes or no."); 569 } 570 } 571 572 std::string input_system::interactive_input (const std::string& s, bool& eof) 573 { 574 Vlast_prompt_time.stamp (); 575 576 if (Vdrawnow_requested && m_interpreter.interactive ()) 577 { 578 bool eval_error = false; 579 580 try 581 { 582 Fdrawnow (m_interpreter); 583 } 584 catch (const execution_exception& e) 585 { 586 eval_error = true; 587 588 m_interpreter.handle_exception (e); 589 } 590 591 flush_stdout (); 592 593 // We set Vdrawnow_requested to false even if there is an error in 594 // drawnow so that the error doesn't reappear at every prompt. 595 596 Vdrawnow_requested = false; 597 598 if (eval_error) 599 return "\n"; 600 } 601 602 return gnu_readline (s, eof); 603 } 604 605 // If the user simply hits return, this will produce an empty matrix. 606 607 octave_value_list 608 input_system::get_user_input (const octave_value_list& args, int nargout) 609 { 610 octave_value_list retval; 611 612 int read_as_string = 0; 613 614 if (args.length () == 2) 615 read_as_string++; 616 617 std::string prompt = args(0).xstring_value ("input: unrecognized argument"); 618 619 output_system& output_sys = m_interpreter.get_output_system (); 620 621 output_sys.reset (); 622 623 octave_diary << prompt; 624 625 bool eof = false; 626 627 std::string input_buf = interactive_input (prompt.c_str (), eof); 628 629 if (input_buf.empty ()) 630 error ("input: reading user-input failed!"); 631 632 std::size_t len = input_buf.length (); 633 634 octave_diary << input_buf; 635 636 if (input_buf[len - 1] != '\n') 637 octave_diary << "\n"; 638 639 if (read_as_string) 640 { 641 // FIXME: fix gnu_readline and octave_gets instead! 642 if (input_buf.length () == 1 && input_buf[0] == '\n') 643 retval(0) = ""; 644 else 645 retval(0) = input_buf; 646 } 647 else 648 { 649 int parse_status = 0; 650 651 retval 652 = m_interpreter.eval_string (input_buf, true, parse_status, nargout); 653 654 tree_evaluator& tw = m_interpreter.get_evaluator (); 655 656 if (! tw.in_debug_repl () && retval.empty ()) 657 retval(0) = Matrix (); 658 } 659 660 return retval; 661 } 662 663 bool input_system::have_input_event_hooks (void) const 664 { 665 return ! m_input_event_hook_functions.empty (); 666 } 667 668 void input_system::add_input_event_hook (const hook_function& hook_fcn) 669 { 670 m_input_event_hook_functions.insert (hook_fcn.id (), hook_fcn); 671 } 672 673 bool input_system::remove_input_event_hook (const std::string& hook_fcn_id) 674 { 675 hook_function_list::iterator p 676 = m_input_event_hook_functions.find (hook_fcn_id); 677 678 if (p == m_input_event_hook_functions.end ()) 679 return false; 680 681 m_input_event_hook_functions.erase (p); 682 return true; 683 } 684 685 void input_system::clear_input_event_hooks (void) 686 { 687 m_input_event_hook_functions.clear (); 688 } 689 690 void input_system::run_input_event_hooks (void) 691 { 692 m_input_event_hook_functions.run (); 693 } 694 695 std::string 696 input_system::gnu_readline (const std::string& s, bool& eof) const 697 { 698 octave_quit (); 699 700 eof = false; 701 702 std::string retval = command_editor::readline (s, eof); 703 704 if (! eof && retval.empty ()) 705 retval = "\n"; 706 707 return retval; 708 } 709 710 std::string base_reader::octave_gets (const std::string& prompt, bool& eof) 711 { 712 octave_quit (); 713 714 eof = false; 715 716 std::string retval; 717 718 // Process pre input event hook function prior to flushing output and 719 // printing the prompt. 720 721 tree_evaluator& tw = m_interpreter.get_evaluator (); 722 723 event_manager& evmgr = m_interpreter.get_event_manager (); 724 725 if (m_interpreter.interactive ()) 726 { 727 if (! tw.in_debug_repl ()) 728 evmgr.exit_debugger_event (); 729 730 evmgr.pre_input_event (); 731 732 evmgr.set_workspace (); 733 } 734 735 bool history_skip_auto_repeated_debugging_command = false; 736 737 input_system& input_sys = m_interpreter.get_input_system (); 738 739 pipe_handler_error_count = 0; 740 741 output_system& output_sys = m_interpreter.get_output_system (); 742 743 output_sys.reset (); 744 745 octave_diary << prompt; 746 747 retval = input_sys.interactive_input (prompt, eof); 748 749 // There is no need to update the load_path cache if there is no 750 // user input. 751 if (retval != "\n" 752 && retval.find_first_not_of (" \t\n\r") != std::string::npos) 753 { 754 load_path& lp = m_interpreter.get_load_path (); 755 756 lp.update (); 757 758 if (tw.in_debug_repl ()) 759 input_sys.last_debugging_command (retval); 760 else 761 input_sys.last_debugging_command ("\n"); 762 } 763 else if (tw.in_debug_repl () && input_sys.auto_repeat_debug_command ()) 764 { 765 retval = input_sys.last_debugging_command (); 766 history_skip_auto_repeated_debugging_command = true; 767 } 768 769 if (retval != "\n") 770 { 771 if (! history_skip_auto_repeated_debugging_command) 772 { 773 if (command_history::add (retval)) 774 evmgr.append_history (retval); 775 } 776 777 octave_diary << retval; 778 779 if (! retval.empty () && retval.back () != '\n') 780 octave_diary << "\n"; 781 } 782 else 783 octave_diary << "\n"; 784 785 // Process post input event hook function after the internal history 786 // list has been updated. 787 788 if (m_interpreter.interactive ()) 789 evmgr.post_input_event (); 790 791 return retval; 792 } 793 794 class 795 terminal_reader : public base_reader 796 { 797 public: 798 799 terminal_reader (interpreter& interp) 800 : base_reader (interp), m_eof (false), m_input_queue () 801 { } 802 803 std::string get_input (const std::string& prompt, bool& eof); 804 805 std::string input_source (void) const { return s_in_src; } 806 807 bool input_from_terminal (void) const { return true; } 808 809 private: 810 811 bool m_eof; 812 std::queue<std::string> m_input_queue; 813 814 static const std::string s_in_src; 815 }; 816 817 class 818 file_reader : public base_reader 819 { 820 public: 821 822 file_reader (interpreter& interp, FILE *f_arg) 823 : base_reader (interp), m_file (f_arg) { } 824 825 std::string get_input (const std::string& prompt, bool& eof); 826 827 std::string input_source (void) const { return s_in_src; } 828 829 bool input_from_file (void) const { return true; } 830 831 private: 832 833 FILE *m_file; 834 835 static const std::string s_in_src; 836 }; 837 838 class 839 eval_string_reader : public base_reader 840 { 841 public: 842 843 eval_string_reader (interpreter& interp, const std::string& str) 844 : base_reader (interp), m_eval_string (str) 845 { } 846 847 std::string get_input (const std::string& prompt, bool& eof); 848 849 std::string input_source (void) const { return s_in_src; } 850 851 bool input_from_eval_string (void) const { return true; } 852 853 private: 854 855 std::string m_eval_string; 856 857 static const std::string s_in_src; 858 }; 859 860 input_reader::input_reader (interpreter& interp) 861 : m_rep (new terminal_reader (interp)) 862 { } 863 864 input_reader::input_reader (interpreter& interp, FILE *file) 865 : m_rep (new file_reader (interp, file)) 866 { } 867 868 input_reader::input_reader (interpreter& interp, const std::string& str) 869 : m_rep (new eval_string_reader (interp, str)) 870 { } 871 872 const std::string base_reader::s_in_src ("invalid"); 873 874 const std::string terminal_reader::s_in_src ("terminal"); 875 876 // If octave_gets returns multiple lines, we cache the input and 877 // return it one line at a time. Multiple input lines may happen when 878 // using readline and bracketed paste mode is enabled, for example. 879 // Instead of queueing lines here, it might be better to modify the 880 // grammar in the parser to handle multiple lines when working 881 // interactively. See also bug #59938. 882 883 std::string 884 terminal_reader::get_input (const std::string& prompt, bool& eof) 885 { 886 octave_quit (); 887 888 eof = false; 889 890 if (m_input_queue.empty ()) 891 { 892 std::string input = octave_gets (prompt, m_eof); 893 894 std::size_t len = input.size (); 895 896 if (len == 0) 897 { 898 if (m_eof) 899 { 900 eof = m_eof; 901 return input; 902 } 903 else 904 { 905 // Can this happen, or will the string returned from 906 // octave_gets always end in a newline character? 907 908 input = "\n"; 909 len = 1; 910 } 911 } 912 913 std::size_t beg = 0; 914 while (beg < len) 915 { 916 std::size_t end = input.find ('\n', beg); 917 918 if (end == std::string::npos) 919 { 920 m_input_queue.push (input.substr (beg)); 921 break; 922 } 923 else 924 { 925 m_input_queue.push (input.substr (beg, end-beg+1)); 926 beg = end + 1; 927 } 928 } 929 } 930 931 std::string retval = m_input_queue.front (); 932 m_input_queue.pop (); 933 934 if (m_input_queue.empty ()) 935 eof = m_eof; 936 937 return retval; 938 } 939 940 const std::string file_reader::s_in_src ("file"); 941 942 std::string 943 file_reader::get_input (const std::string& /*prompt*/, bool& eof) 944 { 945 octave_quit (); 946 947 eof = false; 948 949 std::string src_str = octave_fgets (m_file, eof); 950 951 input_system& input_sys = m_interpreter.get_input_system (); 952 953 std::string mfile_encoding = input_sys.mfile_encoding (); 954 955 std::string encoding; 956 if (mfile_encoding.compare ("system") == 0) 957 { 958 encoding = octave_locale_charset_wrapper (); 959 // encoding identifiers should consist of ASCII only characters 960 std::transform (encoding.begin (), encoding.end (), encoding.begin (), 961 ::tolower); 962 } 963 else 964 encoding = mfile_encoding; 965 966 if (encoding.compare ("utf-8") == 0) 967 { 968 // Check for BOM and strip it 969 if (src_str.compare (0, 3, "\xef\xbb\xbf") == 0) 970 src_str.erase (0, 3); 971 972 // replace invalid portions of the string 973 // FIXME: Include file name that corresponds to m_file. 974 if (string::u8_validate ("get_input", src_str) > 0) 975 warning_with_id ("octave:get_input:invalid_utf8", 976 "Invalid UTF-8 byte sequences have been replaced."); 977 } 978 else 979 { 980 // convert encoding to UTF-8 before returning string 981 const char *src = src_str.c_str (); 982 std::size_t srclen = src_str.length (); 983 984 std::size_t length; 985 uint8_t *utf8_str; 986 987 utf8_str = octave_u8_conv_from_encoding (encoding.c_str (), src, srclen, 988 &length); 989 990 if (! utf8_str) 991 error ("file_reader::get_input: " 992 "converting from codepage '%s' to UTF-8: %s", 993 encoding.c_str (), std::strerror (errno)); 994 995 unwind_protect frame; 996 frame.add_fcn (::free, static_cast<void *> (utf8_str)); 997 998 src_str = std::string (reinterpret_cast<char *> (utf8_str), length); 999 } 1000 1001 return src_str; 1002 } 1003 1004 const std::string eval_string_reader::s_in_src ("eval_string"); 1005 1006 std::string 1007 eval_string_reader::get_input (const std::string& /*prompt*/, bool& eof) 1008 { 1009 octave_quit (); 1010 1011 eof = false; 1012 1013 std::string retval; 1014 1015 retval = m_eval_string; 1016 1017 // Clear the eval string so that the next call will return 1018 // an empty character string with EOF = true. 1019 m_eval_string = ""; 1020 1021 if (retval.empty ()) 1022 eof = true; 1023 1024 return retval; 1025 } 1026 } 1027 1028 DEFMETHOD (input, interp, args, nargout, 1029 doc: /* -*- texinfo -*- 1030 @deftypefn {} {@var{ans} =} input (@var{prompt}) 1031 @deftypefnx {} {@var{ans} =} input (@var{prompt}, "s") 1032 Print @var{prompt} and wait for user input. 1033 1034 For example, 1035 1036 @example 1037 input ("Pick a number, any number! ") 1038 @end example 1039 1040 @noindent 1041 prints the prompt 1042 1043 @example 1044 Pick a number, any number! 1045 @end example 1046 1047 @noindent 1048 and waits for the user to enter a value. The string entered by the user 1049 is evaluated as an expression, so it may be a literal constant, a variable 1050 name, or any other valid Octave code. 1051 1052 The number of return arguments, their size, and their class depend on the 1053 expression entered. 1054 1055 If you are only interested in getting a literal string value, you can call 1056 @code{input} with the character string @qcode{"s"} as the second argument. 1057 This tells Octave to return the string entered by the user directly, without 1058 evaluating it first. 1059 1060 Because there may be output waiting to be displayed by the pager, it is a 1061 good idea to always call @code{fflush (stdout)} before calling @code{input}. 1062 This will ensure that all pending output is written to the screen before 1063 your prompt. 1064 @seealso{yes_or_no, kbhit, pause, menu, listdlg} 1065 @end deftypefn */) 1066 { 1067 int nargin = args.length (); 1068 1069 if (nargin < 1 || nargin > 2) 1070 print_usage (); 1071 1072 octave::input_system& input_sys = interp.get_input_system (); 1073 1074 return input_sys.get_user_input (args, std::max (nargout, 1)); 1075 } 1076 1077 DEFMETHOD (yes_or_no, interp, args, , 1078 doc: /* -*- texinfo -*- 1079 @deftypefn {} {@var{ans} =} yes_or_no ("@var{prompt}") 1080 Ask the user a yes-or-no question. 1081 1082 Return logical true if the answer is yes or false if the answer is no. 1083 1084 Takes one argument, @var{prompt}, which is the string to display when asking 1085 the question. @var{prompt} should end in a space; @code{yes-or-no} adds the 1086 string @samp{(yes or no) } to it. The user must confirm the answer with 1087 @key{RET} and can edit it until it has been confirmed. 1088 @seealso{input} 1089 @end deftypefn */) 1090 { 1091 int nargin = args.length (); 1092 1093 if (nargin > 1) 1094 print_usage (); 1095 1096 octave::input_system& input_sys = interp.get_input_system (); 1097 1098 std::string prompt; 1099 1100 if (nargin == 1) 1101 prompt = args(0).xstring_value ("yes_or_no: PROMPT must be a string"); 1102 1103 return ovl (input_sys.yes_or_no (prompt)); 1104 } 1105 1106 DEFMETHOD (keyboard, interp, args, , 1107 doc: /* -*- texinfo -*- 1108 @deftypefn {} {} keyboard () 1109 @deftypefnx {} {} keyboard ("@var{prompt}") 1110 Stop m-file execution and enter debug mode. 1111 1112 When the @code{keyboard} function is executed, Octave prints a prompt and 1113 waits for user input. The input strings are then evaluated and the results 1114 are printed. This makes it possible to examine the values of variables 1115 within a function, and to assign new values if necessary. To leave the 1116 prompt and return to normal execution type @samp{return} or @samp{dbcont}. 1117 The @code{keyboard} function does not return an exit status. 1118 1119 If @code{keyboard} is invoked without arguments, a default prompt of 1120 @samp{debug> } is used. 1121 @seealso{dbstop, dbcont, dbquit} 1122 @end deftypefn */) 1123 { 1124 int nargin = args.length (); 1125 1126 if (nargin > 1) 1127 print_usage (); 1128 1129 octave::tree_evaluator& tw = interp.get_evaluator (); 1130 1131 if (nargin == 1) 1132 { 1133 std::string prompt 1134 = args(0).xstring_value ("keyboard: PROMPT must be a string"); 1135 1136 tw.keyboard (prompt); 1137 } 1138 else 1139 tw.keyboard (); 1140 1141 return ovl (); 1142 } 1143 1144 DEFUN (completion_matches, args, nargout, 1145 doc: /* -*- texinfo -*- 1146 @deftypefn {} {} completion_matches (@var{hint}) 1147 Generate possible completions given @var{hint}. 1148 1149 This function is provided for the benefit of programs like Emacs which 1150 might be controlling Octave and handling user input. The current 1151 command number is not incremented when this function is called. This is 1152 a feature, not a bug. 1153 @end deftypefn */) 1154 { 1155 if (args.length () != 1) 1156 print_usage (); 1157 1158 octave_value retval; 1159 1160 std::string hint = args(0).string_value (); 1161 1162 int n = 32; 1163 1164 string_vector list (n); 1165 1166 int k = 0; 1167 1168 for (;;) 1169 { 1170 std::string cmd = octave::generate_completion (hint, k); 1171 1172 if (! cmd.empty ()) 1173 { 1174 if (k == n) 1175 { 1176 n *= 2; 1177 list.resize (n); 1178 } 1179 1180 list[k++] = cmd; 1181 } 1182 else 1183 { 1184 list.resize (k); 1185 break; 1186 } 1187 } 1188 1189 if (nargout > 0) 1190 { 1191 if (! list.empty ()) 1192 retval = list; 1193 else 1194 retval = ""; 1195 } 1196 else 1197 { 1198 // We don't use string_vector::list_in_columns here 1199 // because it will be easier for Emacs if the names 1200 // appear in a single column. 1201 1202 int len = list.numel (); 1203 1204 for (int i = 0; i < len; i++) 1205 octave_stdout << list[i] << "\n"; 1206 } 1207 1208 octave_completion_matches_called = true; 1209 1210 return retval; 1211 } 1212 1213 /* 1214 %!assert (ischar (completion_matches (""))) 1215 %!assert (ischar (completion_matches ("a"))) 1216 %!assert (ischar (completion_matches (" "))) 1217 %!assert (isempty (completion_matches (" "))) 1218 %!assert (any (strcmp ("abs", deblank (cellstr (completion_matches ("")))))) 1219 %!assert (any (strcmp ("abs", deblank (cellstr (completion_matches ("a")))))) 1220 %!assert (any (strcmp ("abs", deblank (cellstr (completion_matches ("ab")))))) 1221 %!assert (any (strcmp ("abs", deblank (cellstr (completion_matches ("abs")))))) 1222 %!assert (! any (strcmp ("abs", deblank (cellstr (completion_matches ("absa")))))) 1223 1224 %!error completion_matches () 1225 %!error completion_matches (1, 2) 1226 */ 1227 1228 DEFUN (readline_read_init_file, args, , 1229 doc: /* -*- texinfo -*- 1230 @deftypefn {} {} readline_read_init_file (@var{file}) 1231 Read the readline library initialization file @var{file}. 1232 1233 If @var{file} is omitted, read the default initialization file 1234 (normally @file{~/.inputrc}). 1235 1236 @xref{Readline Init File, , , readline, GNU Readline Library}, 1237 for details. 1238 @seealso{readline_re_read_init_file} 1239 @end deftypefn */) 1240 { 1241 int nargin = args.length (); 1242 1243 if (nargin > 1) 1244 print_usage (); 1245 1246 if (nargin == 0) 1247 octave::command_editor::read_init_file (); 1248 else 1249 { 1250 std::string file = args(0).string_value (); 1251 1252 octave::command_editor::read_init_file (file); 1253 } 1254 1255 return ovl (); 1256 } 1257 1258 DEFUN (readline_re_read_init_file, args, , 1259 doc: /* -*- texinfo -*- 1260 @deftypefn {} {} readline_re_read_init_file () 1261 Re-read the last readline library initialization file that was read. 1262 1263 @xref{Readline Init File, , , readline, GNU Readline Library}, 1264 for details. 1265 @seealso{readline_read_init_file} 1266 @end deftypefn */) 1267 { 1268 if (args.length () != 0) 1269 print_usage (); 1270 1271 octave::command_editor::re_read_init_file (); 1272 1273 return ovl (); 1274 } 1275 1276 DEFMETHOD (add_input_event_hook, interp, args, , 1277 doc: /* -*- texinfo -*- 1278 @deftypefn {} {@var{id} =} add_input_event_hook (@var{fcn}) 1279 @deftypefnx {} {@var{id} =} add_input_event_hook (@var{fcn}, @var{data}) 1280 Add the named function or function handle @var{fcn} to the list of functions 1281 to call periodically when Octave is waiting for input. 1282 1283 The function should have the form 1284 1285 @example 1286 @var{fcn} (@var{data}) 1287 @end example 1288 1289 If @var{data} is omitted, Octave calls the function without any arguments. 1290 1291 The returned identifier may be used to remove the function handle from the 1292 list of input hook functions. 1293 @seealso{remove_input_event_hook} 1294 @end deftypefn */) 1295 { 1296 int nargin = args.length (); 1297 1298 if (nargin < 1 || nargin > 2) 1299 print_usage (); 1300 1301 octave_value user_data; 1302 1303 if (nargin == 2) 1304 user_data = args(1); 1305 1306 octave::input_system& input_sys = interp.get_input_system (); 1307 1308 hook_function hook_fcn (args(0), user_data); 1309 1310 input_sys.add_input_event_hook (hook_fcn); 1311 1312 return ovl (hook_fcn.id ()); 1313 } 1314 1315 DEFMETHOD (remove_input_event_hook, interp, args, , 1316 doc: /* -*- texinfo -*- 1317 @deftypefn {} {} remove_input_event_hook (@var{name}) 1318 @deftypefnx {} {} remove_input_event_hook (@var{fcn_id}) 1319 Remove the named function or function handle with the given identifier 1320 from the list of functions to call periodically when Octave is waiting 1321 for input. 1322 @seealso{add_input_event_hook} 1323 @end deftypefn */) 1324 { 1325 int nargin = args.length (); 1326 1327 if (nargin < 1 || nargin > 2) 1328 print_usage (); 1329 1330 std::string hook_fcn_id = args(0).xstring_value ("remove_input_event_hook: argument not valid as a hook function name or id"); 1331 1332 bool warn = (nargin < 2); 1333 1334 octave::input_system& input_sys = interp.get_input_system (); 1335 1336 if (! input_sys.remove_input_event_hook (hook_fcn_id) && warn) 1337 warning ("remove_input_event_hook: %s not found in list", 1338 hook_fcn_id.c_str ()); 1339 1340 return ovl (); 1341 } 1342 1343 DEFMETHOD (PS1, interp, args, nargout, 1344 doc: /* -*- texinfo -*- 1345 @deftypefn {} {@var{val} =} PS1 () 1346 @deftypefnx {} {@var{old_val} =} PS1 (@var{new_val}) 1347 @deftypefnx {} {} PS1 (@var{new_val}, "local") 1348 Query or set the primary prompt string. 1349 1350 When executing interactively, Octave displays the primary prompt when it is 1351 ready to read a command. 1352 1353 The default value of the primary prompt string is @qcode{'octave:\#> '}. 1354 To change it, use a command like 1355 1356 @example 1357 PS1 ("\\u@@\\H> ") 1358 @end example 1359 1360 @noindent 1361 which will result in the prompt @samp{boris@@kremvax> } for the user 1362 @samp{boris} logged in on the host @samp{kremvax.kgb.su}. Note that two 1363 backslashes are required to enter a backslash into a double-quoted 1364 character string. @xref{Strings}. 1365 1366 You can also use ANSI escape sequences if your terminal supports them. 1367 This can be useful for coloring the prompt. For example, 1368 1369 @example 1370 PS1 ('\[\033[01;31m\]\s:\#> \[\033[0m\]') 1371 @end example 1372 1373 @noindent 1374 will give the default Octave prompt a red coloring. 1375 1376 When called from inside a function with the @qcode{"local"} option, the 1377 variable is changed locally for the function and any subroutines it calls. 1378 The original variable value is restored when exiting the function. 1379 @seealso{PS2, PS4} 1380 @end deftypefn */) 1381 { 1382 octave::input_system& input_sys = interp.get_input_system (); 1383 1384 return input_sys.PS1 (args, nargout); 1385 } 1386 1387 DEFMETHOD (PS2, interp, args, nargout, 1388 doc: /* -*- texinfo -*- 1389 @deftypefn {} {@var{val} =} PS2 () 1390 @deftypefnx {} {@var{old_val} =} PS2 (@var{new_val}) 1391 @deftypefnx {} {} PS2 (@var{new_val}, "local") 1392 Query or set the secondary prompt string. 1393 1394 The secondary prompt is printed when Octave is expecting additional input to 1395 complete a command. For example, if you are typing a @code{for} loop that 1396 spans several lines, Octave will print the secondary prompt at the beginning 1397 of each line after the first. The default value of the secondary prompt 1398 string is @qcode{"> "}. 1399 1400 When called from inside a function with the @qcode{"local"} option, the 1401 variable is changed locally for the function and any subroutines it calls. 1402 The original variable value is restored when exiting the function. 1403 @seealso{PS1, PS4} 1404 @end deftypefn */) 1405 { 1406 octave::input_system& input_sys = interp.get_input_system (); 1407 1408 return input_sys.PS2 (args, nargout); 1409 } 1410 1411 DEFMETHOD (completion_append_char, interp, args, nargout, 1412 doc: /* -*- texinfo -*- 1413 @deftypefn {} {@var{val} =} completion_append_char () 1414 @deftypefnx {} {@var{old_val} =} completion_append_char (@var{new_val}) 1415 @deftypefnx {} {} completion_append_char (@var{new_val}, "local") 1416 Query or set the internal character variable that is appended to 1417 successful command-line completion attempts. 1418 1419 The default value is @qcode{" "} (a single space). 1420 1421 When called from inside a function with the @qcode{"local"} option, the 1422 variable is changed locally for the function and any subroutines it calls. 1423 The original variable value is restored when exiting the function. 1424 @end deftypefn */) 1425 { 1426 octave::input_system& input_sys = interp.get_input_system (); 1427 1428 return input_sys.completion_append_char (args, nargout); 1429 } 1430 1431 DEFMETHOD (__request_drawnow__, , args, , 1432 doc: /* -*- texinfo -*- 1433 @deftypefn {} {} __request_drawnow__ () 1434 @deftypefnx {} {} __request_drawnow__ (@var{flag}) 1435 Undocumented internal function. 1436 @end deftypefn */) 1437 { 1438 int nargin = args.length (); 1439 1440 if (nargin > 1) 1441 print_usage (); 1442 1443 if (nargin == 0) 1444 Vdrawnow_requested = true; 1445 else 1446 Vdrawnow_requested = args(0).bool_value (); 1447 1448 return ovl (); 1449 } 1450 1451 DEFMETHOD (__gud_mode__, interp, args, nargout, 1452 doc: /* -*- texinfo -*- 1453 @deftypefn {} {} __gud_mode__ () 1454 Undocumented internal function. 1455 @end deftypefn */) 1456 { 1457 octave::input_system& input_sys = interp.get_input_system (); 1458 1459 return input_sys.gud_mode (args, nargout); 1460 } 1461 1462 DEFMETHOD (__mfile_encoding__, interp, args, nargout, 1463 doc: /* -*- texinfo -*- 1464 @deftypefn {} {@var{current_encoding} =} __mfile_encoding__ (@var{new_encoding}) 1465 Set and query the codepage that is used for reading .m files. 1466 @end deftypefn */) 1467 { 1468 octave::input_system& input_sys = interp.get_input_system (); 1469 1470 return input_sys.mfile_encoding (args, nargout); 1471 } 1472 1473 DEFMETHOD (auto_repeat_debug_command, interp, args, nargout, 1474 doc: /* -*- texinfo -*- 1475 @deftypefn {} {@var{val} =} auto_repeat_debug_command () 1476 @deftypefnx {} {@var{old_val} =} auto_repeat_debug_command (@var{new_val}) 1477 @deftypefnx {} {} auto_repeat_debug_command (@var{new_val}, "local") 1478 Query or set the internal variable that controls whether debugging 1479 commands are automatically repeated when the input line is empty (typing 1480 just @key{RET}). 1481 1482 When called from inside a function with the @qcode{"local"} option, the 1483 variable is changed locally for the function and any subroutines it calls. 1484 The original variable value is restored when exiting the function. 1485 @end deftypefn */) 1486 { 1487 octave::input_system& input_sys = interp.get_input_system (); 1488 1489 return input_sys.auto_repeat_debug_command (args, nargout); 1490 } 1491 1492 // Always define these functions. The macro is intended to allow the 1493 // declarations to be hidden, not so that Octave will not provide the 1494 // functions if they are requested. 1495 1496 // #if defined (OCTAVE_USE_DEPRECATED_FUNCTIONS) 1497 1498 bool 1499 octave_yes_or_no (const std::string& prompt) 1500 { 1501 octave::input_system& input_sys 1502 = octave::__get_input_system__ ("set_default_prompts"); 1503 1504 return input_sys.yes_or_no (prompt); 1505 } 1506 1507 void 1508 remove_input_event_hook_functions (void) 1509 { 1510 octave::input_system& input_sys 1511 = octave::__get_input_system__ ("remove_input_event_hook_functions"); 1512 1513 input_sys.clear_input_event_hooks (); 1514 } 1515 1516 // Fix things up so that input can come from the standard input. This 1517 // may need to become much more complicated, which is why it's in a 1518 // separate function. 1519 1520 FILE * 1521 get_input_from_stdin (void) 1522 { 1523 octave::command_editor::set_input_stream (stdin); 1524 return octave::command_editor::get_input_stream (); 1525 } 1526 1527 // #endif 1528