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