include: co/flag.h.
#Basic concepts
co.flag is a command line and config file parsing library. Its principle is very simple, define global variables in code, then parse the command line parameters and/or config file when the program starts, and update the value of these global variables.
#flag variable
The global variable defined by macros in co.flag
are called flag variable. For example, the following code defines a flag variable, the variable name is FLG_x
.
DEF_int32(x, 0, "xxx"); // int32 FLG_x = 0;
co.flag
supports 7 types of flag variable:
bool, int32, int64, uint32, uint64, double, string
Every flag variable has a default value, and a new value can be passed to it from command-line or config file. Take the previously FLG_x
as an example, we can use -x=23
in command line, or x = 23
in the config file, to set a new value for it.
#command line flag
Command line parameters appear in the form of -x=y
, where x
is called a command line flag (hereinafter referred to as flag). The flag x
in command line corresponds to the global variable FLG_x
in the code, and -x=y
in command line is equivalent to setting the value of FLG_x
to y
.
co.flag
is designed to be very flexible:
-
-x=y
can omit the preceding-
, abbreviated asx=y
. -
-x=y
can also be written as-x y
. -
x=y
can be preceded by any number of-
. -
For bool type flags,
-b=true
can be abbreviated as-b
. -
Example
# b, i, s are all flags, xx is not a flag
./exe -b -i=32 -s=hello xx
#APIs
#flag::parse
co::vector<fastring> parse(int argc, char** argv);
void parse(const fastring& path);
-
Added in v3.0.1.
-
The first parse function, parse the command line parameters and config file, and update value of the flag variables. It usually needs to be called once at the beginning of the main function. Generally speaking, it does the following steps:
- Preprocess the command line parameters, the value of
FLG_config
may be updated then. - If
FLG_config
is not empty, parse the config file specified by it, and update value of the flag variables. - Parse other command line parameters and update value of the flag variables.
- If
FLG_mkconf
is true, generate a config file and terminate the program. - If
FLG_daemon
is true, run the program as a daemon (for Linux only). - When any error occurs, print the error message and terminate the program immediately.
- If no error occurs, return the non-flag list. For example, when executing
./exe x y
, this function will return["x", "y"]
.
- Preprocess the command line parameters, the value of
-
The second parse function, parses the config file and updates value of the flag variables. The parameter
path
is the path of the config file. When any error occurs, print the error message and terminate the program.
flag::init
Since v3.0.1,flag::init()
has been marked as deprecated, please useflag::parse()
instead.
- Example
#include "co/flag.h"
int main(int argc, char** argv) {
flag::parse(argc, argv);
}
#flag::set_value
fastring set_value(const fastring& name, const fastring& value)
-
Added in v3.0. Set value of a flag variable,
name
is the flag name. -
This function is not thread-safe and usually needs to be called at the beginning of the main function.
-
Example
DEF_bool(b, false, "");
DEF_int32(i, 0, "");
DEF_string(s, "", "");
int main(int argc, char** argv) {
flag::set_value("b", "true"); // FLG_b -> true
flag::set_value("i", "23"); // FLG_i -> 23
flag::set_value("s", "xx"); // FLG_s -> "xx"
flag::parse(argc, argv);
}
#flag::alias
bool alias(const char* name, const char* new_name);
-
Added in v3.0. Add an alias to a flag, in command line or config file you can replace the original name with the alias.
-
This function is not thread safe and needs to be called before
flag::parse()
. -
Example
DEF_bool(all, false, "");
int main(int argc, char** argv) {
flag::alias("all", "a");
flag::parse(argc, argv);
}
#Use flag variable in the code
#Define a flag variable
DEF_bool(name, value, help, ...)
DEF_int32(name, value, help, ...)
DEF_int64(name, value, help, ...)
DEF_uint32(name, value, help, ...)
DEF_uint64(name, value, help, ...)
DEF_double(name, value, help, ...)
DEF_string(name, value, help, ...)
-
The above 7 macros are used to define 7 different types of flag variables.
-
The parameter
name
is the flag name, the corresponding global variable name isFLG_name
, the parametervalue
is the default value, and the parameterhelp
is comment for the flag. -
A flag variable is a global variable and generally should not be defined in the header file.
-
The name of the flag variable is unique, and we cannot define two flag variables with the same name.
-
The flag variable is generally defined outside the namespace, otherwise it may be not possible to use FLG_name to access the flag variable.
-
Example
DEF_bool(b, false, "comments"); // bool FLG_b = false;
DEF_int32(i32, 32, "comments"); // int32 FLG_i32 = 32;
DEF_int64(i64, 64, "comments"); // int64 FLG_i64 = 64;
DEF_uint32(u32, 0, "comments"); // uint32 FLG_u32 = 0;
DEF_uint64(u64, 0, "comments"); // uint64 FLG_u64 = 0;
DEF_double(d, 2.0, "comments"); // double FLG_d = 2.0;
DEF_string(s, "x", "comments"); // fastring& FLG_s = ...;
Since v3.0.1,DEF_string
actually defines a reference tofastring
.
#Add alias for a flag
-
Added in v3.0, when defining a flag variable, you can add any number of aliases to the flag.
-
In command line or config file, alias can be used instead of the original name.
-
Example
DEF_bool(debug, false, ""); // no alias
DEF_bool(debug, false, "", d); // d is an alias of debug
DEF_bool(debug, false, "", d, dbg); // 2 aliases
#Declare the flag variable
DEC_bool(name)
DEC_int32(name)
DEC_int64(name)
DEC_uint32(name)
DEC_uint64(name)
DEC_double(name)
DEC_string(name)
-
The 7 macros above are used to declare 7 different types of flag variables.
-
The parameter
name
is the flag name, and the corresponding global variable name isFLG_name
. -
A flag variable can be defined only once, but it can be declared multiple times, which can be declared wherever needed.
-
The flag variable is generally declared outside the namespace, otherwise it may be not possible to use FLG_name to access the flag variable.
-
Example
DEC_bool(b); // extern bool FLG_b;
DEC_int32(i32); // extern int32 FLG_i32;
DEC_int64(i64); // extern int64 FLG_i64;
DEC_uint32(u32); // extern uint32 FLG_u32;
DEC_uint64(u64); // extern uint64 FLG_u64;
DEC_double(d); // extern double FLG_d;
DEC_string(s); // extern fastring& FLG_s;
#Use the flag variable
Once a flag variable is defined or declared, we can use it the same as an ordinary variable.
#include "co/flag.h"
DEC_bool(b);
DEF_string(s, "hello", "xxx");
int main(int argc, char** argv) {
flag::parse(argc, argv);
if (!FLG_b) std::cout << "b is false" << std::endl;
FLG_s += " world";
std::cout << FLG_s << std::endl;
return 0;
}
#Use flag in command line
#Set value of flags
Suppose the following flags are defined in the program:
DEF_bool(x, false, "bool x");
DEF_bool(y, false, "bool y");
DEF_int32(i, -32, "int32");
DEF_uint64(u, 64, "uint64");
DEF_string(s, "nice", "string");
When the program starts, we can modify value of the flag variables through command line parameters:
# -x=y, x=y, -x y, the three are equivalent
./xx -i=8 u=88 -s=xxx
./xx -i 8 -u 88 -s "hello world"
./xx -i8 # -i=8, only for single-letter named integer flags
# When a bool type is set to true, the value can be omitted
./xx -x # -x=true
# Multiple single-letter named bool flags can be combined and set to true
./xx -xy # -x=true -y=true
# Integer type flags can have units k, m, g, t, p, not case sensitive
./xx -i -4k # i=-4096
# Integer type flags can pass octal or hexadecimal numbers
./xx i=032 # i=26 octal
./xx u=0xff # u=255 hexadecimal
#Show Help Information
co.flag
supports using --help
command to print the help information of the program:
$ ./xx --help
usage: $exe [-flag] [value]
$exe -x -i 8k -s ok # x=true, i=8192, s="ok"
$exe -- # print all flags
$exe -mkconf # generate config file
$exe -conf xx.conf # run with config file
flags:
-n int32
type: int32 default: 0
from: test/flag.cc
-s string
type: string default: "hello world"
from: test/flag.cc
#List all flags
co.flag
provides --
command to list all the flags defined in the program:
$ ./xx --
flags:
-boo bool flag
type: bool default: false
from: test/flag.cc
-co_sched_num number of coroutine schedulers, default: os::cpunum()
type: uint32 default: os::cpunum()
from: src/co/sched.cc
#Show version of the program
-
version
is a flag defined inside coost. You can use the-version
command to print version information. -
version
is empty by default, its value should be set before callingflag::parse()
. -
Example
#include "co/flag.h"
int main(int argc, char** argv) {
FLG_version = "v3.0.0";
flag::parse(argc, argv);
return 0;
}
$ ./xx -version
v3.0.0
#config file
#config file format
The config file format of co.flag
is flexible:
-
One config item per line, each config item corresponds to a flag, and the form is unified as
x = y
, which looks clear at a glance. -
#
or//
are for comments. -
#
or//
in quotation marks are not comments. -
Ignore the blank characters at the beginning or end of the line.
-
Blank characters can be added before or after the
=
sign. -
\
can be used to continue a line to avoid too long a line. -
The string does not support escaping to avoid ambiguity.
-
The string can be enclosed in double quotes, single quotes or 3 back quotes.
-
Sample config file
# config file: xx.conf
boo = true # bool type
s = # empty string
s = hello \
world # s = "helloworld"
s = "http://github.com" # # or // in quotation marks are not comments
s = "I'm ok" # enclose the string in double quotes
s ='how are "U"' # enclose the string in single quotes
s = ```I'm "ok"``` # enclose the string in 3 back quotes
i32 = 4k # 4096, integers can have units k, m, g, t, p, not case sensitive
i32 = 032 # octal, i32 = 26
i32 = 0xff # hexadecimal, i32 = 255
pi = 3.14159 # double type
#Generate config file
mkconf
is a flag defined internally in coost, which is a switch for automatically generating config file.- You can use
-mkconf
to generate a config file in command line.
./xx -mkconf # Generate xx.conf
./xx -mkconf -x u=88 # Custom config item value
#Adjust the order of config items
In the automatically generated config file, the config items are sorted by flag level, file name, and code line number. If the user wants some config items to be ranked higher, the flag level can be set to a smaller value, otherwise, the flag level can be set to a larger value.
When defining a flag, you can use #n
at the beginning of the comment to specify the flag level, n must be an integer between 0 and 9. If the comment is not empty, there must be a space after n. When not specified, the default flag level is 5.
DEF_bool(x, false, "comments"); // The default level is 5
DEF_bool(y, false, "#3"); // The level is 3, and the comment is empty
DEF_bool(z, false, "#3 comments"); // The level is 3
#Prohibit config items from being generated in the config file
Flags whose comments start with .
, are hidden flags, which will not be present in the config file, but can be found with the --
command in command line. A flag with an empty comment is completely invisible and will neither be generated in the config file nor be found with the --
command.
DEF_bool(x, false, ".say something here");
DEF_string(s, "good", "");
#Specify the config file when the program starts
config
is a flag defined internally in coost, which is the path of the config file. It has an aliasconf
.- You can use
-config
to specify the config file in command line. - Another way, you can modify the value of
FLG_config
to specify the config file, before callingflag::parse()
.
./xx -config xx.conf
./xx -conf xx.conf
# If the config file name ends with .conf or config,
# and it is the first non-flag parameter in command line,
# -config can be omitted.
./xx xx.conf
./xx xx.conf -x
#Custom help information
-
help
is a flag defined in coost, which stores the help information of the program. This information can be seen with the command--help
in command line. -
FLG_help
is empty by default, and the default help information provided by coost is used. -
You can modify the value of
FLG_help
before callingflag::parse()
to customize the help information. -
Example
#include "co/flag.h"
int main(int argc, char** argv) {
FLG_help << "usage:\n"
<< "\t./xx -ip 127.0.0.1 -port 7777\n";
flag::parse(argc, argv);
return 0;
}
#Run program as a daemon
-
daemon
is a flag defined in coost. If it is true, the program will run as a daemon. It only works on Linux platform. -
You can use
-daemon
in command line to make the program run in the background as a daemon. -
Example
./xx -daemon