Я использую нечестивое сочетание readline, boost :: spirit и фабричного шаблона для обработки всего этого. Это было бы почти так же нечестиво, если бы не было непритязательного синтаксиса Си для чтения строк:)
Внешний цикл выглядит так
while(true)
{
char *line(NULL);
line = readline((cmd.leaf() + " > ").c_str());
if (line && *line)
{
add_history(line);
int error = ParseLine(line,*s_g, std::cout);
free(line);
if (error == ErrQuit)
break;
if (error == ErrSave)
....
Каждая команда имеет функцию завершения и функцию синтаксического анализа / завершения
char **completeCreate(const std::vector<std::string> &, const char *text, int depth)
{
switch (depth)
{
case 1:
case 2:
{
return rl_completion_matches(text, rl_filename_completion_function);
break;
}
case 3:
{
return rl_completion_matches(text, rulesFill);
break;
}
}
return NULL;
}
Определяет завершитель для команды, которая принимает два аргумента, имя файла и строку, которая регистрируется с помощью механизма завершения readline через макрос factory +, который позволяет мне регистрировать все с помощью чего-то, похожего на это
REG_COMP (Создать, завершить создание);
На стороне парсера у меня аналогичная заводская настройка
int parseCreate(const std::vector<std::string> &names, Game &g, std::ostream &out)
{
if (names.size() != 4)
return parseHelpC(names, g, out);
if (!CreateGame(names[1],names[2],names[3],g))
return ErrGameCreation;
return ErrNone;
}
REG_PARSE(Create,"CardList PowerList RuleSet");
, которая обеспечивает фактическую логику и текст справки
Я пропустил огромное количество кода, который склеивает все воедино, но был бы рад поделиться с вами отвратительностью, являющейся основой кода (в настоящее время это частный репозиторий git). Я с нетерпением жду, чтобы увидеть, есть ли у кого-то работающее лучше.