2016-05-03 17:36:22 +00:00
|
|
|
// Prototypes for functions for reading data from stdin and passing to the parser. If stdin is a
|
|
|
|
// keyboard, it supplies a killring, history, syntax highlighting, tab-completion and various other
|
|
|
|
// features.
|
2005-10-04 15:11:39 +00:00
|
|
|
#ifndef FISH_READER_H
|
|
|
|
#define FISH_READER_H
|
|
|
|
|
2016-05-03 17:36:22 +00:00
|
|
|
#include <stddef.h>
|
2022-08-21 06:14:48 +00:00
|
|
|
#include <stdint.h>
|
2017-02-14 04:37:27 +00:00
|
|
|
|
2022-08-21 06:14:48 +00:00
|
|
|
#include <memory>
|
2022-08-21 21:51:33 +00:00
|
|
|
#include <string>
|
2022-08-21 06:14:48 +00:00
|
|
|
#include <utility>
|
2022-08-21 21:51:33 +00:00
|
|
|
#include <vector>
|
2005-10-04 15:11:39 +00:00
|
|
|
|
2012-02-11 01:54:21 +00:00
|
|
|
#include "common.h"
|
2012-02-24 20:13:35 +00:00
|
|
|
#include "complete.h"
|
2022-09-14 19:26:33 +00:00
|
|
|
#include "highlight.h"
|
2022-08-21 06:14:48 +00:00
|
|
|
#include "maybe.h"
|
2015-05-03 00:49:38 +00:00
|
|
|
#include "parse_constants.h"
|
2005-10-04 15:11:39 +00:00
|
|
|
|
2022-08-21 06:14:48 +00:00
|
|
|
class env_stack_t;
|
2018-09-09 09:25:51 +00:00
|
|
|
class environment_t;
|
2012-02-06 00:42:24 +00:00
|
|
|
class history_t;
|
2016-04-21 06:00:54 +00:00
|
|
|
class io_chain_t;
|
2020-01-16 01:14:47 +00:00
|
|
|
class parser_t;
|
2012-01-23 05:40:08 +00:00
|
|
|
|
2020-02-04 11:47:44 +00:00
|
|
|
/// An edit action that can be undone.
|
|
|
|
struct edit_t {
|
|
|
|
/// When undoing the edit we use this to restore the previous cursor position.
|
|
|
|
size_t cursor_position_before_edit = 0;
|
|
|
|
|
|
|
|
/// The span of text that is replaced by this edit.
|
|
|
|
size_t offset, length;
|
|
|
|
|
|
|
|
/// The strings that are removed and added by this edit, respectively.
|
|
|
|
wcstring old, replacement;
|
|
|
|
|
2021-01-05 21:40:09 +00:00
|
|
|
/// edit_t is only for contiguous changes, so to restore a group of arbitrary changes to the
|
|
|
|
/// command line we need to have a group id as forcibly coalescing changes is not enough.
|
|
|
|
maybe_t<int> group_id;
|
|
|
|
|
2020-02-04 11:47:44 +00:00
|
|
|
explicit edit_t(size_t offset, size_t length, wcstring replacement)
|
|
|
|
: offset(offset), length(length), replacement(std::move(replacement)) {}
|
|
|
|
|
2022-10-09 21:26:44 +00:00
|
|
|
explicit edit_t(source_range_t range, wcstring replacement)
|
|
|
|
: edit_t(range.start, range.length, std::move(replacement)) {}
|
|
|
|
|
2020-02-04 11:47:44 +00:00
|
|
|
/// Used for testing.
|
|
|
|
bool operator==(const edit_t &other) const;
|
|
|
|
};
|
|
|
|
|
2022-09-14 19:26:33 +00:00
|
|
|
/// Modify a string and its syntax highlighting according to the given edit.
|
2020-02-04 11:47:44 +00:00
|
|
|
/// Currently exposed for testing only.
|
2022-09-14 19:26:33 +00:00
|
|
|
void apply_edit(wcstring *target, std::vector<highlight_spec_t> *colors, const edit_t &edit);
|
2020-02-04 11:47:44 +00:00
|
|
|
|
|
|
|
/// The history of all edits to some command line.
|
|
|
|
struct undo_history_t {
|
|
|
|
/// The stack of edits that can be undone or redone atomically.
|
|
|
|
std::vector<edit_t> edits;
|
|
|
|
|
|
|
|
/// The position in the undo stack that corresponds to the current
|
|
|
|
/// state of the input line.
|
|
|
|
/// Invariants:
|
|
|
|
/// edits_applied - 1 is the index of the next edit to undo.
|
|
|
|
/// edits_applied is the index of the next edit to redo.
|
|
|
|
///
|
|
|
|
/// For example, if nothing was undone, edits_applied is edits.size().
|
|
|
|
/// If every single edit was undone, edits_applied is 0.
|
|
|
|
size_t edits_applied = 0;
|
|
|
|
|
|
|
|
/// Whether we allow the next edit to be grouped together with the
|
|
|
|
/// last one.
|
|
|
|
bool may_coalesce = false;
|
|
|
|
|
2021-01-05 21:40:09 +00:00
|
|
|
/// Whether to be more aggressive in coalescing edits. Ideally, it would be "force coalesce"
|
|
|
|
/// with guaranteed atomicity but as `edit_t` is strictly for contiguous changes, that guarantee
|
|
|
|
/// can't be made at this time.
|
|
|
|
bool try_coalesce = false;
|
|
|
|
|
2020-02-04 11:47:44 +00:00
|
|
|
/// Empty the history.
|
|
|
|
void clear();
|
|
|
|
};
|
|
|
|
|
2016-05-03 17:36:22 +00:00
|
|
|
/// Helper class for storing a command line.
|
|
|
|
class editable_line_t {
|
2020-02-04 11:47:44 +00:00
|
|
|
public:
|
|
|
|
const wcstring &text() const { return text_; }
|
|
|
|
|
2022-09-14 19:26:33 +00:00
|
|
|
const std::vector<highlight_spec_t> &colors() const { return colors_; }
|
|
|
|
void set_colors(std::vector<highlight_spec_t> colors) {
|
|
|
|
assert(colors.size() == size());
|
|
|
|
colors_ = std::move(colors);
|
|
|
|
}
|
|
|
|
|
2020-02-04 11:47:44 +00:00
|
|
|
size_t position() const { return position_; }
|
2020-02-04 11:47:44 +00:00
|
|
|
void set_position(size_t position) { position_ = position; }
|
2014-03-31 17:01:39 +00:00
|
|
|
|
2016-05-03 17:36:22 +00:00
|
|
|
// Gets the length of the text.
|
2020-02-04 11:47:44 +00:00
|
|
|
size_t size() const { return text().size(); }
|
2014-03-31 17:01:39 +00:00
|
|
|
|
2020-02-04 11:47:44 +00:00
|
|
|
bool empty() const { return text().empty(); }
|
2014-03-31 17:01:39 +00:00
|
|
|
|
2020-03-13 20:59:10 +00:00
|
|
|
wchar_t at(size_t idx) const { return text().at(idx); }
|
2020-02-04 11:47:44 +00:00
|
|
|
|
2022-09-14 11:32:13 +00:00
|
|
|
void clear();
|
2014-03-31 17:01:39 +00:00
|
|
|
|
2020-02-04 11:47:44 +00:00
|
|
|
/// Modify the commandline according to @edit. Most modifications to the
|
2020-02-09 17:39:14 +00:00
|
|
|
/// text should pass through this function.
|
2022-09-15 02:13:39 +00:00
|
|
|
void push_edit(edit_t edit, bool allow_coalesce);
|
2020-02-04 11:47:44 +00:00
|
|
|
|
|
|
|
/// Undo the most recent edit that was not yet undone. Returns true on success.
|
|
|
|
bool undo();
|
|
|
|
|
|
|
|
/// Redo the most recent undo. Returns true on success.
|
|
|
|
bool redo();
|
2021-01-05 21:40:09 +00:00
|
|
|
|
|
|
|
/// Start a logical grouping of command line edits that should be undone/redone together.
|
|
|
|
void begin_edit_group();
|
|
|
|
/// End a logical grouping of command line edits that should be undone/redone together.
|
|
|
|
void end_edit_group();
|
2022-09-14 11:35:44 +00:00
|
|
|
|
|
|
|
private:
|
2022-09-14 12:03:39 +00:00
|
|
|
/// Whether we want to append this string to the previous edit.
|
|
|
|
bool want_to_coalesce_insertion_of(const wcstring &str) const;
|
|
|
|
|
2022-09-14 11:35:44 +00:00
|
|
|
/// The command line.
|
|
|
|
wcstring text_;
|
2022-09-14 19:26:33 +00:00
|
|
|
/// Syntax highlighting.
|
|
|
|
std::vector<highlight_spec_t> colors_;
|
2022-09-14 11:35:44 +00:00
|
|
|
/// The current position of the cursor in the command line.
|
|
|
|
size_t position_ = 0;
|
|
|
|
|
2022-09-14 12:03:39 +00:00
|
|
|
/// The history of all edits.
|
|
|
|
undo_history_t undo_history_;
|
2022-09-14 11:35:44 +00:00
|
|
|
/// The nesting level for atomic edits, so that recursive invocations of start_edit_group()
|
|
|
|
/// are not ended by one end_edit_group() call.
|
|
|
|
int32_t edit_group_level_ = -1;
|
|
|
|
/// Monotonically increasing edit group, ignored when edit_group_level_ is -1. Allowed to wrap.
|
|
|
|
uint32_t edit_group_id_ = -1;
|
2014-01-26 08:41:30 +00:00
|
|
|
};
|
|
|
|
|
2016-05-03 17:36:22 +00:00
|
|
|
/// Read commands from \c fd until encountering EOF.
|
2020-01-28 19:39:26 +00:00
|
|
|
/// The fd is not closed.
|
2019-05-27 01:51:26 +00:00
|
|
|
int reader_read(parser_t &parser, int fd, const io_chain_t &io);
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2020-07-06 03:09:53 +00:00
|
|
|
/// Mark that we encountered SIGHUP and must (soon) exit. This is invoked from a signal handler.
|
2023-04-30 19:38:06 +00:00
|
|
|
extern "C" {
|
2020-07-06 03:09:53 +00:00
|
|
|
void reader_sighup();
|
2023-04-30 19:38:06 +00:00
|
|
|
}
|
2020-07-06 03:09:53 +00:00
|
|
|
|
2016-05-03 17:36:22 +00:00
|
|
|
/// Initialize the reader.
|
2005-09-20 13:26:39 +00:00
|
|
|
void reader_init();
|
2021-03-06 08:24:54 +00:00
|
|
|
void term_copy_modes();
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2016-05-03 17:36:22 +00:00
|
|
|
/// Restore the term mode at startup.
|
2013-10-26 22:22:20 +00:00
|
|
|
void restore_term_mode();
|
|
|
|
|
2017-07-28 04:32:49 +00:00
|
|
|
/// Change the history file for the current command reading context.
|
2018-09-09 05:13:54 +00:00
|
|
|
void reader_change_history(const wcstring &name);
|
2017-07-28 04:32:49 +00:00
|
|
|
|
2022-07-02 15:08:59 +00:00
|
|
|
/// Strategy for determining how the selection behaves.
|
|
|
|
enum class cursor_selection_mode_t : uint8_t {
|
|
|
|
/// The character at/after the cursor is excluded.
|
|
|
|
/// This is most useful with a line cursor shape.
|
|
|
|
exclusive,
|
|
|
|
/// The character at/after the cursor is included.
|
|
|
|
/// This is most useful with a block or underscore cursor shape.
|
|
|
|
inclusive,
|
|
|
|
};
|
|
|
|
|
|
|
|
void reader_change_cursor_selection_mode(cursor_selection_mode_t selection_mode);
|
|
|
|
|
2021-11-14 10:08:30 +00:00
|
|
|
/// Enable or disable autosuggestions based on the associated variable.
|
|
|
|
void reader_set_autosuggestion_enabled(const env_stack_t &vars);
|
2021-10-21 14:54:24 +00:00
|
|
|
|
2016-05-03 17:36:22 +00:00
|
|
|
/// Write the title to the titlebar. This function is called just before a new application starts
|
|
|
|
/// executing and just after it finishes.
|
|
|
|
///
|
|
|
|
/// \param cmd Command line string passed to \c fish_title if is defined.
|
2019-05-05 03:20:52 +00:00
|
|
|
/// \param parser The parser to use for autoloading fish_title.
|
2016-05-03 17:36:22 +00:00
|
|
|
/// \param reset_cursor_position If set, issue a \r so the line driver knows where we are
|
2019-05-05 03:20:52 +00:00
|
|
|
void reader_write_title(const wcstring &cmd, parser_t &parser, bool reset_cursor_position = true);
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2020-08-23 22:12:47 +00:00
|
|
|
/// Tell the reader that it needs to re-exec the prompt and repaint.
|
|
|
|
/// This may be called in response to e.g. a color variable change.
|
|
|
|
void reader_schedule_prompt_repaint();
|
2012-03-25 10:00:38 +00:00
|
|
|
|
2019-06-02 22:41:23 +00:00
|
|
|
/// Enqueue an event to the back of the reader's input queue.
|
|
|
|
class char_event_t;
|
|
|
|
void reader_queue_ch(const char_event_t &ch);
|
|
|
|
|
2016-05-03 17:36:22 +00:00
|
|
|
/// Return the value of the interrupted flag, which is set by the sigint handler, and clear it if it
|
2020-01-14 23:20:04 +00:00
|
|
|
/// was set. In practice this will return 0 or SIGINT.
|
|
|
|
int reader_test_and_clear_interrupted();
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2016-05-03 17:36:22 +00:00
|
|
|
/// Clear the interrupted flag unconditionally without handling anything. The flag could have been
|
|
|
|
/// set e.g. when an interrupt arrived just as we were ending an earlier \c reader_readline
|
|
|
|
/// invocation but before the \c is_interactive_read flag was cleared.
|
2013-01-20 21:23:27 +00:00
|
|
|
void reader_reset_interrupted();
|
|
|
|
|
2016-05-03 17:36:22 +00:00
|
|
|
/// Return the value of the interrupted flag, which is set by the sigint handler, and clear it if it
|
|
|
|
/// was set. If the current reader is interruptible, call \c reader_exit().
|
2013-01-22 10:00:02 +00:00
|
|
|
int reader_reading_interrupted();
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2016-05-03 17:36:22 +00:00
|
|
|
/// Read one line of input. Before calling this function, reader_push() must have been called in
|
|
|
|
/// order to set up a valid reader environment. If nchars > 0, return after reading that many
|
|
|
|
/// characters even if a full line has not yet been read. Note: the returned value may be longer
|
|
|
|
/// than nchars if a single keypress resulted in multiple characters being inserted into the
|
|
|
|
/// commandline.
|
2019-02-24 21:59:49 +00:00
|
|
|
maybe_t<wcstring> reader_readline(int nchars);
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2020-08-03 21:53:09 +00:00
|
|
|
/// Configuration that we provide to a reader.
|
|
|
|
struct reader_config_t {
|
|
|
|
/// Left prompt command, typically fish_prompt.
|
|
|
|
wcstring left_prompt_cmd{};
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2020-08-03 21:53:09 +00:00
|
|
|
/// Right prompt command, typically fish_right_prompt.
|
|
|
|
wcstring right_prompt_cmd{};
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2022-03-16 19:14:59 +00:00
|
|
|
/// Name of the event to trigger once we're set up.
|
|
|
|
wcstring event{};
|
|
|
|
|
2020-08-03 21:53:09 +00:00
|
|
|
/// Whether tab completion is OK.
|
|
|
|
bool complete_ok{false};
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2020-08-03 21:53:09 +00:00
|
|
|
/// Whether to perform syntax highlighting.
|
|
|
|
bool highlight_ok{false};
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2020-08-03 21:53:09 +00:00
|
|
|
/// Whether to perform syntax checking before returning.
|
|
|
|
bool syntax_check_ok{false};
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2020-08-03 21:53:09 +00:00
|
|
|
/// Whether to allow autosuggestions.
|
|
|
|
bool autosuggest_ok{false};
|
2012-11-08 03:59:20 +00:00
|
|
|
|
2020-08-03 21:53:09 +00:00
|
|
|
/// Whether to expand abbreviations.
|
|
|
|
bool expand_abbrev_ok{false};
|
2005-09-20 13:26:39 +00:00
|
|
|
|
2020-08-03 21:53:09 +00:00
|
|
|
/// Whether to exit on interrupt (^C).
|
|
|
|
bool exit_on_interrupt{false};
|
2012-11-18 10:43:35 +00:00
|
|
|
|
2020-08-03 21:53:09 +00:00
|
|
|
/// If set, do not show what is typed.
|
|
|
|
bool in_silent_mode{false};
|
2020-09-30 16:29:00 +00:00
|
|
|
|
|
|
|
/// The fd for stdin, default to actual stdin.
|
2020-10-31 17:14:50 +00:00
|
|
|
int in{0};
|
2020-08-03 21:53:09 +00:00
|
|
|
};
|
2013-07-17 07:38:04 +00:00
|
|
|
|
2022-10-28 00:13:27 +00:00
|
|
|
class reader_data_t;
|
|
|
|
bool check_exit_loop_maybe_warning(reader_data_t *data);
|
|
|
|
|
2021-07-18 17:05:27 +00:00
|
|
|
/// Push a new reader environment controlled by \p conf, using the given history name.
|
|
|
|
/// If \p history_name is empty, then save history in-memory only; do not write it to disk.
|
2020-08-03 21:53:09 +00:00
|
|
|
void reader_push(parser_t &parser, const wcstring &history_name, reader_config_t &&conf);
|
2013-01-20 21:23:27 +00:00
|
|
|
|
2020-08-03 21:53:09 +00:00
|
|
|
/// Return to previous reader environment.
|
|
|
|
void reader_pop();
|
2017-04-09 18:48:21 +00:00
|
|
|
|
2016-05-03 17:36:22 +00:00
|
|
|
/// The readers interrupt signal handler. Cancels all currently running blocks.
|
2023-04-30 19:38:06 +00:00
|
|
|
extern "C" {
|
2016-10-09 21:38:26 +00:00
|
|
|
void reader_handle_sigint();
|
2023-04-30 19:38:06 +00:00
|
|
|
}
|
2005-10-05 22:37:08 +00:00
|
|
|
|
2022-05-28 23:35:40 +00:00
|
|
|
/// \return whether fish is currently unwinding the stack in preparation to exit.
|
|
|
|
bool fish_is_unwinding_for_exit();
|
2006-05-14 10:16:23 +00:00
|
|
|
|
2016-05-03 17:36:22 +00:00
|
|
|
/// Given a command line and an autosuggestion, return the string that gets shown to the user.
|
|
|
|
/// Exposed for testing purposes only.
|
|
|
|
wcstring combine_command_and_autosuggestion(const wcstring &cmdline,
|
|
|
|
const wcstring &autosuggestion);
|
2014-01-17 20:53:01 +00:00
|
|
|
|
2022-10-09 21:26:44 +00:00
|
|
|
/// Expand at most one abbreviation at the given cursor position, updating the position if the
|
|
|
|
/// abbreviation wants to move the cursor. Use the parser to run any abbreviations which want
|
2022-11-27 21:04:00 +00:00
|
|
|
/// function calls. \return none if no abbreviations were expanded, otherwise the resulting
|
|
|
|
/// replacement.
|
2022-10-09 21:26:44 +00:00
|
|
|
struct abbrs_replacement_t;
|
|
|
|
maybe_t<abbrs_replacement_t> reader_expand_abbreviation_at_cursor(const wcstring &cmdline,
|
|
|
|
size_t cursor_pos,
|
|
|
|
parser_t &parser);
|
2013-07-17 07:38:04 +00:00
|
|
|
|
2016-05-03 17:36:22 +00:00
|
|
|
/// Apply a completion string. Exposed for testing only.
|
|
|
|
wcstring completion_apply_to_command_line(const wcstring &val_str, complete_flags_t flags,
|
|
|
|
const wcstring &command_line, size_t *inout_cursor_pos,
|
|
|
|
bool append_only);
|
2013-02-02 22:50:22 +00:00
|
|
|
|
2021-07-20 20:18:03 +00:00
|
|
|
/// Snapshotted state from the reader.
|
|
|
|
struct commandline_state_t {
|
|
|
|
wcstring text; // command line text, or empty if not interactive
|
|
|
|
size_t cursor_pos{0}; // position of the cursor, may be as large as text.size()
|
|
|
|
maybe_t<source_range_t> selection{}; // visual selection, or none if none
|
|
|
|
std::shared_ptr<history_t> history{}; // current reader history, or null if not interactive
|
|
|
|
bool pager_mode{false}; // pager is visible
|
2021-11-24 23:03:20 +00:00
|
|
|
bool pager_fully_disclosed{false}; // pager already shows everything if possible
|
2021-07-20 20:18:03 +00:00
|
|
|
bool search_mode{false}; // pager is visible and search is active
|
|
|
|
bool initialized{false}; // if false, the reader has not yet been entered
|
|
|
|
};
|
|
|
|
|
|
|
|
/// Get the command line state. This may be fetched on a background thread.
|
|
|
|
commandline_state_t commandline_get_state();
|
|
|
|
|
|
|
|
/// Set the command line text and position. This may be called on a background thread; the reader
|
|
|
|
/// will pick it up when it is done executing.
|
|
|
|
void commandline_set_buffer(wcstring text, size_t cursor_pos = -1);
|
|
|
|
|
2018-08-21 03:50:27 +00:00
|
|
|
/// Return the current interactive reads loop count. Useful for determining how many commands have
|
|
|
|
/// been executed between invocations of code.
|
2019-04-29 01:13:55 +00:00
|
|
|
uint64_t reader_run_count();
|
2018-08-21 03:50:27 +00:00
|
|
|
|
2020-08-02 20:37:19 +00:00
|
|
|
/// Returns the current "generation" of interactive status. Useful for determining whether the
|
|
|
|
/// previous command produced a status.
|
|
|
|
uint64_t reader_status_count();
|
|
|
|
|
2005-10-04 15:11:39 +00:00
|
|
|
#endif
|