| 61 | }; |
| 62 | |
| 63 | ReadlineLineReader::ReadlineLineReader( |
| 64 | const Suggest & suggest_, const String & history_file_path_, bool multiline_, Patterns extenders_, Patterns delimiters_) |
| 65 | : LineReader(history_file_path_, multiline_, std::move(extenders_), std::move(delimiters_)) |
| 66 | { |
| 67 | suggest = &suggest_; |
| 68 | |
| 69 | if (!history_file_path.empty()) |
| 70 | { |
| 71 | int res = read_history(history_file_path.c_str()); |
| 72 | if (res) |
| 73 | std::cerr << "Cannot read history from file " + history_file_path + ": "+ errnoToString(errno) << std::endl; |
| 74 | } |
| 75 | |
| 76 | /// Added '.' to the default list. Because it is used to separate database and table. |
| 77 | rl_basic_word_break_characters = word_break_characters; |
| 78 | |
| 79 | /// Not append whitespace after single suggestion. Because whitespace after function name is meaningless. |
| 80 | rl_completion_append_character = '\0'; |
| 81 | |
| 82 | rl_completion_entry_function = generate; |
| 83 | |
| 84 | /// Install Ctrl+C signal handler that will be used in interactive mode. |
| 85 | |
| 86 | if (rl_initialize()) |
| 87 | throw std::runtime_error("Cannot initialize readline"); |
| 88 | |
| 89 | auto clear_prompt_or_exit = [](int) |
| 90 | { |
| 91 | /// This is signal safe. |
| 92 | ssize_t res = write(STDOUT_FILENO, "\n", 1); |
| 93 | |
| 94 | /// Allow to quit client while query is in progress by pressing Ctrl+C twice. |
| 95 | /// (First press to Ctrl+C will try to cancel query by InterruptListener). |
| 96 | if (res == 1 && rl_line_buffer[0] && !RL_ISSTATE(RL_STATE_DONE)) |
| 97 | { |
| 98 | rl_replace_line("", 0); |
| 99 | if (rl_forced_update_display()) |
| 100 | _exit(0); |
| 101 | } |
| 102 | else |
| 103 | { |
| 104 | /// A little dirty, but we struggle to find better way to correctly |
| 105 | /// force readline to exit after returning from the signal handler. |
| 106 | _exit(0); |
| 107 | } |
| 108 | }; |
| 109 | |
| 110 | if (signal(SIGINT, clear_prompt_or_exit) == SIG_ERR) |
| 111 | throw std::runtime_error(std::string("Cannot set signal handler for readline: ") + errnoToString(errno)); |
| 112 | |
| 113 | rl_variable_bind("completion-ignore-case", "on"); |
| 114 | // TODO: it doesn't work |
| 115 | // history_write_timestamps = 1; |
| 116 | } |
| 117 | |
| 118 | ReadlineLineReader::~ReadlineLineReader() |
| 119 | { |
nothing calls this directly
no test coverage detected