1 #ifndef command_manager_hh_INCLUDED
2 #define command_manager_hh_INCLUDED
3
4 #include "coord.hh"
5 #include "completion.hh"
6 #include "array_view.hh"
7 #include "shell_manager.hh"
8 #include "parameters_parser.hh"
9 #include "string.hh"
10 #include "optional.hh"
11 #include "utils.hh"
12 #include "hash_map.hh"
13
14 #include <functional>
15 #include <initializer_list>
16
17 namespace Kakoune
18 {
19
20 class Context;
21 using CommandParameters = ConstArrayView<String>;
22 using CommandFunc = std::function<void (const ParametersParser& parser,
23 Context& context,
24 const ShellContext& shell_context)>;
25
26 using CommandCompleter = std::function<Completions (const Context& context,
27 CompletionFlags,
28 CommandParameters,
29 size_t, ByteCount)>;
30
31 using CommandHelper = std::function<String (const Context& context, CommandParameters)>;
32
33 enum class CommandFlags
34 {
35 None = 0,
36 Hidden = 1,
37 };
with_bit_ops(Meta::Type<CommandFlags>)38 constexpr bool with_bit_ops(Meta::Type<CommandFlags>) { return true; }
39
40 struct CommandInfo { String name, info; };
41
42 struct Token
43 {
44 enum class Type
45 {
46 Raw,
47 RawQuoted,
48 RawEval,
49 ShellExpand,
50 RegisterExpand,
51 OptionExpand,
52 ValExpand,
53 ArgExpand,
54 FileExpand,
55 CommandSeparator
56 };
57
58 Type type;
59 ByteCount pos;
60 String content;
61 bool terminated = false;
62 };
63
64 struct ParseState
65 {
66 StringView str;
67 const char* pos;
68
operator boolKakoune::ParseState69 operator bool() const { return pos != str.end(); }
70 };
71
72 class CommandParser
73 {
74 public:
75 CommandParser(StringView command_line);
76 Optional<Token> read_token(bool throw_on_unterminated);
77
pos() const78 const char* pos() const { return m_state.pos; }
done() const79 bool done() const { return not m_state; }
80
81 private:
82 ParseState m_state;
83 };
84
85 class CommandManager : public Singleton<CommandManager>
86 {
87 public:
88 void execute(StringView command_line, Context& context,
89 const ShellContext& shell_context = ShellContext{});
90
91 void execute_single_command(CommandParameters params,
92 Context& context,
93 const ShellContext& shell_context);
94
95
96 Completions complete(const Context& context, CompletionFlags flags,
97 StringView command_line, ByteCount cursor_pos);
98
99 Completions complete(const Context& context, CompletionFlags flags,
100 CommandParameters params,
101 size_t token_to_complete, ByteCount pos_in_token);
102
103 Optional<CommandInfo> command_info(const Context& context,
104 StringView command_line) const;
105
106 bool command_defined(StringView command_name) const;
107
108 void register_command(String command_name, CommandFunc func,
109 String docstring,
110 ParameterDesc param_desc,
111 CommandFlags flags = CommandFlags::None,
112 CommandHelper helper = CommandHelper(),
113 CommandCompleter completer = CommandCompleter());
114
115 Completions complete_command_name(const Context& context, StringView query) const;
116
clear_last_complete_command()117 void clear_last_complete_command() { m_last_complete_command = String{}; }
118
119 bool module_defined(StringView module_name) const;
120
121 void register_module(String module_name, String commands);
122
123 void load_module(StringView module_name, Context& context);
124
125 Completions complete_module_name(StringView query) const;
126
127 private:
128 struct Command
129 {
130 CommandFunc func;
131 String docstring;
132 ParameterDesc param_desc;
133 CommandFlags flags;
134 CommandHelper helper;
135 CommandCompleter completer;
136 };
137 using CommandMap = HashMap<String, Command, MemoryDomain::Commands>;
138 CommandMap m_commands;
139 String m_last_complete_command;
140 int m_command_depth = 0;
141
142 struct Module
143 {
144 enum class State
145 {
146 Registered,
147 Loading,
148 Loaded
149 };
150 State state = State::Registered;
151 String commands;
152 };
153 using ModuleMap = HashMap<String, Module, MemoryDomain::Commands>;
154 ModuleMap m_modules;
155 };
156
157 String expand(StringView str, const Context& context,
158 const ShellContext& shell_context = ShellContext{});
159
160 String expand(StringView str, const Context& context,
161 const ShellContext& shell_context,
162 const FunctionRef<String (String)>& postprocess);
163
164 }
165
166 #endif // command_manager_hh_INCLUDED
167