Nix 2.93.3
Lix: A modern, delicious implementation of the Nix package manager; unstable internal interfaces
Loading...
Searching...
No Matches
args.hh
Go to the documentation of this file.
1#pragma once
3
6#include "lix/libutil/json-fwd.hh"
8#include "lix/libutil/ref.hh"
9
10#include <functional>
11#include <map>
12#include <memory>
13#include <limits>
14
15#include <optional>
16#include <set>
17#include <filesystem>
18
19
20namespace nix {
21
22enum class HashType : char;
23
24class MultiCommand;
25
26class RootArgs;
27
28class AddCompletions;
29
30class Args
31{
32public:
33
37 virtual std::string description() { return ""; }
38
39 virtual bool forceImpureByDefault() { return false; }
40
44 virtual std::string doc() { return ""; }
45
46 virtual AsyncIoRoot & aio() = 0;
47
48protected:
49
55 static const size_t ArityAny = std::numeric_limits<size_t>::max();
56
65 struct Handler
66 {
67 std::function<void(std::vector<std::string>)> fun;
68 size_t arity;
69
70 Handler() {}
71
72 Handler(std::function<void(std::vector<std::string>)> && fun)
73 : fun(std::move(fun))
74 , arity(ArityAny)
75 { }
76
77 Handler(std::function<void()> && handler)
78 : fun([handler{std::move(handler)}](std::vector<std::string>) { handler(); })
79 , arity(0)
80 { }
81
82 Handler(std::function<void(std::string)> && handler)
83 : fun([handler{std::move(handler)}](std::vector<std::string> ss) {
84 handler(std::move(ss[0]));
85 })
86 , arity(1)
87 { }
88
89 Handler(std::function<void(std::string, std::string)> && handler)
90 : fun([handler{std::move(handler)}](std::vector<std::string> ss) {
91 handler(std::move(ss[0]), std::move(ss[1]));
92 })
93 , arity(2)
94 { }
95
96 Handler(std::vector<std::string> * dest)
97 : fun([=](std::vector<std::string> ss) { *dest = ss; })
98 , arity(ArityAny)
99 { }
100
101 Handler(std::string * dest)
102 : fun([=](std::vector<std::string> ss) { *dest = ss[0]; })
103 , arity(1)
104 { }
105
106 Handler(std::optional<std::string> * dest)
107 : fun([=](std::vector<std::string> ss) { *dest = ss[0]; })
108 , arity(1)
109 { }
110
111 template<class T>
112 Handler(T * dest, const T & val)
113 : fun([=](std::vector<std::string> ss) { *dest = val; })
114 , arity(0)
115 { }
116
117 template<class I>
118 Handler(I * dest)
119 : fun([=](std::vector<std::string> ss) {
120 *dest = string2IntWithUnitPrefix<I>(ss[0]);
121 })
122 , arity(1)
123 { }
124
125 template<class I>
126 Handler(std::optional<I> * dest)
127 : fun([=](std::vector<std::string> ss) {
128 *dest = string2IntWithUnitPrefix<I>(ss[0]);
129 })
130 , arity(1)
131 { }
132 };
133
143 typedef void CompleterFun(AddCompletions &, size_t, std::string_view);
144
151 typedef std::function<CompleterFun> CompleterClosure;
152
159 struct Flag
160 {
161 typedef std::shared_ptr<Flag> ptr;
162
163 std::string longName;
164 std::set<std::string> aliases;
165 char shortName = 0;
166 std::string description;
167 std::string category;
168 Strings labels;
169 Handler handler;
170 CompleterClosure completer;
171
172 std::optional<ExperimentalFeature> experimentalFeature;
173
174 static Flag mkHashTypeFlag(std::string && longName, HashType * ht);
175 static Flag mkHashTypeOptFlag(std::string && longName, std::optional<HashType> * oht);
176 };
177
182 std::map<std::string, Flag::ptr> longFlags;
183
188 std::map<char, Flag::ptr> shortFlags;
189
196 virtual bool processFlag(Strings::iterator & pos, Strings::iterator end);
197
205 {
206 std::string label;
207 bool optional = false;
208 Handler handler;
209 CompleterClosure completer;
210 };
211
221 std::list<ExpectedArg> expectedArgs;
233 std::list<ExpectedArg> processedArgs;
234
246 virtual bool processArgs(const Strings & args, bool finish);
247
248 virtual Strings::iterator rewriteArgs(Strings & args, Strings::iterator pos)
249 {
250 return pos;
251 }
252
253 std::set<std::string> hiddenCategories;
254
259 virtual void initialFlagsProcessed() {}
260
264 virtual std::optional<std::reference_wrapper<RootArgs>> asRootArgs() {
265 return std::nullopt;
266 }
267
268public:
269
270 void addFlag(Flag && flag);
271
272 void removeFlag(const std::string & longName);
273
274 void expectArgs(ExpectedArg && arg)
275 {
276 expectedArgs.emplace_back(std::move(arg));
277 }
278
282 void expectArg(const std::string & label, std::string * dest, bool optional = false)
283 {
284 expectArgs({
285 .label = label,
286 .optional = optional,
287 .handler = {dest}
288 });
289 }
290
294 void expectArgs(const std::string & label, std::vector<std::string> * dest)
295 {
296 expectArgs({
297 .label = label,
298 .handler = {dest}
299 });
300 }
301
302 static CompleterFun completePath;
303
304 static CompleterFun completeDir;
305
306 virtual JSON toJSON();
307
308 friend class MultiCommand;
309
319 MultiCommand * parent = nullptr;
320
325 RootArgs & getRoot();
326};
327
332struct Command : virtual public Args
333{
334 friend class MultiCommand;
335
336 virtual ~Command() { }
337
341 virtual void run() = 0;
342
343 typedef int Category;
344
345 static constexpr Category catDefault = 0;
346 static constexpr Category catCustom = 1000;
347
348 virtual std::optional<ExperimentalFeature> experimentalFeature ();
349
350 virtual Category category() { return catDefault; }
351};
352
353using CommandMap = std::map<std::string, std::function<ref<Command>(AsyncIoRoot &)>>;
354
359class MultiCommand : public Command
360{
361public:
362 CommandMap commands;
363 Strings customCommandSearchPaths;
364 bool isExternalSubcommand;
365
366 std::map<Command::Category, std::string> categories;
367
371 std::optional<std::pair<std::string, ref<Command>>> command;
372
373 MultiCommand(const CommandMap & commands, bool allowExternal = false);
374
375 bool processFlag(Strings::iterator & pos, Strings::iterator end) override;
376
377 bool processArgs(const Strings & args, bool finish) override;
378
379 JSON toJSON() override;
380};
381
386class ExternalCommand : virtual public Command
387{
388 Strings externalArgv;
389 AsyncIoRoot & aio_;
390public:
391 std::filesystem::path absoluteBinaryPath;
392 static constexpr std::string_view lixExternalPrefix = "lix-";
393
394 ExternalCommand(AsyncIoRoot & aio, std::filesystem::path absoluteBinaryPath);
395
396 virtual bool processFlag(Strings::iterator & pos, Strings::iterator end) override;
397 virtual bool processArgs(const Strings & args, bool finish) override;
398 virtual void run() override;
399 virtual std::optional<ExperimentalFeature> experimentalFeature () override {
400 return Xp::LixCustomSubCommands;
401 }
402
403 // Create a custom category section.
404 virtual Category category() override { return catCustom; }
405
406 virtual AsyncIoRoot & aio() override { return aio_; }
407};
408
409/* This returns a Command handle
410 * if the command name exist in one of the search paths and points to an executable regular file.
411 *
412 * i.e. if $searchpath/$command exist for any $searchpath in `searchPaths` and $searchpath/$command links to an executable regular file.
413 */
414std::optional<ref<Command>> searchForCustomSubcommand(const std::string_view & command, const Strings & searchPaths);
415/* This will read all directories in searchPaths one by one and look for all executable regular files which starts with `$prefix-`.
416 * Finally, it will return the list of commands stripped of their `$prefix` prefix.
417 *
418 * If you need to know about a specific command, prefer `searchForCustomSubcommand`.
419 */
420Strings searchForAllAvailableCustomSubcommands(const std::string_view & prefix, const Strings & searchPaths);
421
423 std::string completion;
424 std::string description;
425
426 bool operator<(const Completion & other) const;
427};
428
439{
440public:
441
445 enum class Type {
446 Normal,
447 Filenames,
448 Attrs,
449 };
450
456 virtual void setType(Type type) = 0;
457
461 virtual void add(std::string completion, std::string description = "") = 0;
462};
463
464}
Definition args.hh:439
virtual void setType(Type type)=0
virtual void add(std::string completion, std::string description="")=0
Type
Definition args.hh:445
Definition args.hh:31
MultiCommand * parent
Definition args.hh:319
virtual std::optional< std::reference_wrapper< RootArgs > > asRootArgs()
Definition args.hh:264
virtual bool processFlag(Strings::iterator &pos, Strings::iterator end)
Definition args.cc:146
std::list< ExpectedArg > expectedArgs
Definition args.hh:221
void CompleterFun(AddCompletions &, size_t, std::string_view)
Definition args.hh:143
std::list< ExpectedArg > processedArgs
Definition args.hh:233
virtual std::string description()
Definition args.hh:37
std::function< CompleterFun > CompleterClosure
Definition args.hh:151
RootArgs & getRoot()
Definition args.cc:61
void expectArgs(const std::string &label, std::vector< std::string > *dest)
Definition args.hh:294
virtual std::string doc()
Definition args.hh:44
virtual void initialFlagsProcessed()
Definition args.hh:259
std::map< char, Flag::ptr > shortFlags
Definition args.hh:188
virtual bool processArgs(const Strings &args, bool finish)
Definition args.cc:221
std::map< std::string, Flag::ptr > longFlags
Definition args.hh:182
void expectArg(const std::string &label, std::string *dest, bool optional=false)
Definition args.hh:282
static const size_t ArityAny
Definition args.hh:55
virtual void run() override
Definition args.cc:592
virtual bool processArgs(const Strings &args, bool finish) override
Definition args.cc:583
virtual bool processFlag(Strings::iterator &pos, Strings::iterator end) override
Definition args.cc:574
Definition args.hh:360
bool processFlag(Strings::iterator &pos, Strings::iterator end) override
Definition args.cc:531
std::optional< std::pair< std::string, ref< Command > > > command
Definition args.hh:371
bool processArgs(const Strings &args, bool finish) override
Definition args.cc:538
@ Normal
Definition sqlite.hh:24
N string2IntWithUnitPrefix(std::string_view s)
Definition strings.hh:157
Definition args.hh:205
Definition args.hh:160
Definition args.hh:66
Definition async.hh:39
Definition args.hh:333
virtual void run()=0
Definition args.hh:422