1 // Header file for the low level input library. 2 #ifndef INPUT_COMMON_H 3 #define INPUT_COMMON_H 4 5 #include <stddef.h> 6 7 #include <queue> 8 9 #include "common.h" 10 #include "maybe.h" 11 12 enum class readline_cmd_t { 13 beginning_of_line, 14 end_of_line, 15 forward_char, 16 backward_char, 17 forward_single_char, 18 forward_word, 19 backward_word, 20 forward_bigword, 21 backward_bigword, 22 history_search_backward, 23 history_search_forward, 24 history_prefix_search_backward, 25 history_prefix_search_forward, 26 delete_char, 27 backward_delete_char, 28 kill_line, 29 yank, 30 yank_pop, 31 complete, 32 complete_and_search, 33 pager_toggle_search, 34 beginning_of_history, 35 end_of_history, 36 backward_kill_line, 37 kill_whole_line, 38 kill_word, 39 kill_bigword, 40 backward_kill_word, 41 backward_kill_path_component, 42 backward_kill_bigword, 43 history_token_search_backward, 44 history_token_search_forward, 45 self_insert, 46 self_insert_notfirst, 47 transpose_chars, 48 transpose_words, 49 upcase_word, 50 downcase_word, 51 capitalize_word, 52 togglecase_char, 53 togglecase_selection, 54 execute, 55 beginning_of_buffer, 56 end_of_buffer, 57 repaint_mode, 58 repaint, 59 force_repaint, 60 up_line, 61 down_line, 62 suppress_autosuggestion, 63 accept_autosuggestion, 64 begin_selection, 65 swap_selection_start_stop, 66 end_selection, 67 kill_selection, 68 insert_line_under, 69 insert_line_over, 70 forward_jump, 71 backward_jump, 72 forward_jump_till, 73 backward_jump_till, 74 func_and, 75 func_or, 76 expand_abbr, 77 delete_or_exit, 78 exit, 79 cancel_commandline, 80 cancel, 81 undo, 82 redo, 83 begin_undo_group, 84 end_undo_group, 85 repeat_jump, 86 disable_mouse_tracking, 87 // NOTE: This one has to be last. 88 reverse_repeat_jump 89 }; 90 91 // The range of key codes for inputrc-style keyboard functions. 92 enum { R_END_INPUT_FUNCTIONS = static_cast<int>(readline_cmd_t::reverse_repeat_jump) + 1 }; 93 94 /// Represents an event on the character input stream. 95 enum class char_event_type_t : uint8_t { 96 /// A character was entered. 97 charc, 98 99 /// A readline event. 100 readline, 101 102 /// end-of-file was reached. 103 eof, 104 105 /// An event was handled internally, or an interrupt was received. Check to see if the reader 106 /// loop should exit. 107 check_exit, 108 }; 109 110 /// Hackish: the input style, which describes how char events (only) are applied to the command 111 /// line. Note this is set only after applying bindings; it is not set from readb(). 112 enum class char_input_style_t : uint8_t { 113 // Insert characters normally. 114 normal, 115 116 // Insert characters only if the cursor is not at the beginning. Otherwise, discard them. 117 notfirst, 118 }; 119 120 class char_event_t { 121 union { 122 /// Set if the type is charc. 123 wchar_t c; 124 125 /// Set if the type is readline. 126 readline_cmd_t rl; 127 } v_{}; 128 129 public: 130 /// The type of event. 131 char_event_type_t type; 132 133 /// The style to use when inserting characters into the command line. 134 char_input_style_t input_style{char_input_style_t::normal}; 135 136 /// The sequence of characters in the input mapping which generated this event. 137 /// Note that the generic self-insert case does not have any characters, so this would be empty. 138 wcstring seq{}; 139 is_char()140 bool is_char() const { return type == char_event_type_t::charc; } 141 is_eof()142 bool is_eof() const { return type == char_event_type_t::eof; } 143 is_check_exit()144 bool is_check_exit() const { return type == char_event_type_t::check_exit; } 145 is_readline()146 bool is_readline() const { return type == char_event_type_t::readline; } 147 get_char()148 wchar_t get_char() const { 149 assert(type == char_event_type_t::charc && "Not a char type"); 150 return v_.c; 151 } 152 maybe_char()153 maybe_t<wchar_t> maybe_char() const { 154 if (type == char_event_type_t::charc) { 155 return v_.c; 156 } else { 157 return none(); 158 } 159 } 160 get_readline()161 readline_cmd_t get_readline() const { 162 assert(type == char_event_type_t::readline && "Not a readline type"); 163 return v_.rl; 164 } 165 char_event_t(wchar_t c)166 /* implicit */ char_event_t(wchar_t c) : type(char_event_type_t::charc) { v_.c = c; } 167 168 /* implicit */ char_event_t(readline_cmd_t rl, wcstring seq = {}) type(char_event_type_t::readline)169 : type(char_event_type_t::readline), seq(std::move(seq)) { 170 v_.rl = rl; 171 } 172 char_event_t(char_event_type_t type)173 /* implicit */ char_event_t(char_event_type_t type) : type(type) { 174 assert(type != char_event_type_t::charc && type != char_event_type_t::readline && 175 "Cannot create a char event with this constructor"); 176 } 177 }; 178 179 /// Adjust the escape timeout. 180 class environment_t; 181 void update_wait_on_escape_ms(const environment_t &vars); 182 183 /// A class which knows how to produce a stream of input events. 184 /// This is a base class; you may subclass it for its override points. 185 class input_event_queue_t { 186 public: 187 /// Construct from a file descriptor \p in, and an interrupt handler \p handler. 188 explicit input_event_queue_t(int in = STDIN_FILENO); 189 190 /// Function used by input_readch to read bytes from stdin until enough bytes have been read to 191 /// convert them to a wchar_t. Conversion is done using mbrtowc. If a character has previously 192 /// been read and then 'unread' using \c input_common_unreadch, that character is returned. 193 char_event_t readch(); 194 195 /// Like readch(), except it will wait at most WAIT_ON_ESCAPE milliseconds for a 196 /// character to be available for reading. 197 /// \return none on timeout, the event on success. 198 maybe_t<char_event_t> readch_timed(); 199 200 /// Enqueue a character or a readline function to the queue of unread characters that 201 /// readch will return before actually reading from fd 0. 202 void push_back(const char_event_t &ch); 203 204 /// Add a character or a readline function to the front of the queue of unread characters. This 205 /// will be the next character returned by readch. 206 void push_front(const char_event_t &ch); 207 208 /// Add multiple characters or readline events to the front of the queue of unread characters. 209 /// The order of the provided events is not changed, i.e. they are not inserted in reverse 210 /// order. 211 template <typename Iterator> insert_front(const Iterator begin,const Iterator end)212 void insert_front(const Iterator begin, const Iterator end) { 213 queue_.insert(queue_.begin(), begin, end); 214 } 215 216 /// Override point for when we are about to (potentially) block in select(). The default does 217 /// nothing. 218 virtual void prepare_to_select(); 219 220 /// Override point for when when select() is interrupted by a signal. The default does nothing. 221 virtual void select_interrupted(); 222 223 virtual ~input_event_queue_t(); 224 225 private: 226 /// \return if we have any lookahead. has_lookahead()227 bool has_lookahead() const { return !queue_.empty(); } 228 229 /// \return the next event in the queue, or none if the queue is empty. 230 maybe_t<char_event_t> try_pop(); 231 232 int in_{0}; 233 std::deque<char_event_t> queue_; 234 }; 235 236 #endif 237