kakoune/src/input_handler.hh
Maxime Coste 0942cd5084 InputHandler: handle of last insert keys happening in nested modes
Move recording of keys to the input handler itself instead of the
Insert mode so that eventual nested modes (potentially introduced
by <a-;> will get their keys recorded as well).

Fixes #1680
2017-11-08 14:39:52 +08:00

173 lines
4.6 KiB
C++

#ifndef input_handler_hh_INCLUDED
#define input_handler_hh_INCLUDED
#include "completion.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<void (int, MenuEvent, Context&)>;
enum class PromptEvent
{
Change,
Abort,
Validate
};
using PromptCallback = std::function<void (StringView, PromptEvent, Context&)>;
enum class PromptFlags
{
None = 0,
Password = 1 << 0,
DropHistoryEntriesWithBlankPrefix = 1 << 1,
};
constexpr bool with_bit_ops(Meta::Type<PromptFlags>) { return true; }
using KeyCallback = std::function<void (Key, Context&)>;
class InputMode;
enum class InsertMode : unsigned;
enum class KeymapMode : char;
enum class CursorMode;
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,
Completer 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<DisplayLine> 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<CursorMode, DisplayCoord> 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<RefPtr<InputMode>, 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<Key> 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<AutoInfo>) { return true; }
constexpr auto enum_desc(Meta::Type<AutoInfo>)
{
return make_array<EnumDesc<AutoInfo>, 3>({
{ AutoInfo::Command, "command"},
{ AutoInfo::OnKey, "onkey"},
{ AutoInfo::Normal, "normal" }
});
}
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<typename Cmd>
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