#ifndef input_handler_hh_INCLUDED #define input_handler_hh_INCLUDED #include "completion.hh" #include "constexpr_utils.hh" #include "context.hh" #include "face.hh" #include "normal.hh" #include "keys.hh" #include "string.hh" #include "utils.hh" #include "safe_ptr.hh" #include "display_buffer.hh" namespace Kakoune { enum class MenuEvent { Select, Abort, Validate }; using MenuCallback = std::function; enum class PromptEvent { Change, Abort, Validate }; using PromptCallback = std::function; enum class PromptFlags { None = 0, Password = 1 << 0, DropHistoryEntriesWithBlankPrefix = 1 << 1, Search = 1 << 2, }; constexpr bool with_bit_ops(Meta::Type) { return true; } using KeyCallback = std::function; class InputMode; enum class InsertMode : unsigned; enum class KeymapMode : char; enum class CursorMode; using PromptCompleter = std::function; class InputHandler : public SafeCountable { public: InputHandler(SelectionList selections, Context::Flags flags = Context::Flags::None, String name = ""); ~InputHandler(); // switch to insert mode void insert(InsertMode mode, int count); // repeat last insert mode key sequence void repeat_last_insert(); // enter prompt mode, callback is called on each change, // abort or validation with corresponding PromptEvent value // returns to normal mode after validation if callback does // not change the mode itself void prompt(StringView prompt, String initstr, String emptystr, Face prompt_face, PromptFlags flags, PromptCompleter completer, PromptCallback callback); void set_prompt_face(Face prompt_face); // enter menu mode, callback is called on each selection change, // abort or validation with corresponding MenuEvent value // returns to normal mode after validation if callback does // not change the mode itself void menu(Vector choices, MenuCallback callback); // execute callback on next keypress and returns to normal mode // if callback does not change the mode itself void on_next_key(KeymapMode mode, KeyCallback callback); // process the given key void handle_key(Key key); void start_recording(char reg); bool is_recording() const; void stop_recording(); char recording_reg() const { return m_recording_reg; } void reset_normal_mode(); Context& context() { return m_context; } const Context& context() const { return m_context; } DisplayLine mode_line() const; std::pair get_cursor_info() const; // Force an input handler into normal mode temporarily struct ScopedForceNormal { ScopedForceNormal(InputHandler& handler, NormalParams params); ~ScopedForceNormal(); private: InputHandler& m_handler; InputMode* m_mode; }; private: Context m_context; friend class InputMode; Vector, MemoryDomain::Client> m_mode_stack; InputMode& current_mode() const { return *m_mode_stack.back(); } void push_mode(InputMode* new_mode); void pop_mode(InputMode* current_mode); struct Insertion{ NestedBool recording; InsertMode mode; Vector keys; bool disable_hooks; int count; } m_last_insert = { {}, InsertMode::Insert, {}, false, 1 }; char m_recording_reg = 0; String m_recorded_keys; int m_recording_level = -1; int m_handle_key_level = 0; }; enum class AutoInfo { None = 0, Command = 1 << 0, OnKey = 1 << 1, Normal = 1 << 2 }; constexpr bool with_bit_ops(Meta::Type) { return true; } constexpr auto enum_desc(Meta::Type) { return make_array, 3>({ { AutoInfo::Command, "command"}, { AutoInfo::OnKey, "onkey"}, { AutoInfo::Normal, "normal" } }); } enum class AutoComplete { None = 0, Insert = 0b01, Prompt = 0b10 }; constexpr bool with_bit_ops(Meta::Type) { return true; } constexpr auto enum_desc(Meta::Type) { return make_array, 3>({ { AutoComplete::Insert, "insert"}, { AutoComplete::Prompt, "prompt" } }); } bool show_auto_info_ifn(StringView title, StringView info, AutoInfo mask, const Context& context); void hide_auto_info_ifn(const Context& context, bool hide); template void on_next_key_with_autoinfo(const Context& context, KeymapMode keymap_mode, Cmd cmd, StringView title, StringView info) { const bool hide = show_auto_info_ifn(title, info, AutoInfo::OnKey, context); context.input_handler().on_next_key( keymap_mode, [hide,cmd](Key key, Context& context) mutable { hide_auto_info_ifn(context, hide); cmd(key, context); }); } void scroll_window(Context& context, LineCount offset); } #endif // input_handler_hh_INCLUDED