跨平台,命令完成交互式文本界面 [英] Cross platform, Interactive text-based interface with command completion

查看:264
本文介绍了跨平台,命令完成交互式文本界面的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

有谁知道一个C ++库,将提供一个基于文本的交互界面的?我想创建一个应用程序的两个版本;一个基于控制台程序,将执行在命令行或交互的控制台,以及一个基于GUI的程序(可可的M​​ac和Windows MFC)给出的任何行动。两个版本都将共享一个通用的C ++后端。

Does anyone know of a C++ library that will provide a text-based interactive interface? I want to create two versions of an application; a console based program that will perform whatever actions are given on the command line or interactively at the console as well as a GUI based program (Mac Cocoa and Windows MFC). Both versions will share a common C++ backend.

对于基于控制台的程序,我想类似病史能力的readline (其中我不能使用,因为这应用程序将命令完成关闭源)(选项卡激活为例)。

For the console based program I would like similar history abilities to readline (which I cannot use as this application will be closed source) with command completion (Tab-activated for example).

或许有这样的事情已经可用?

Perhaps there is something like this already available?

推荐答案

更​​新:我还没有找到一个满意的(跨平台)解决历史/完成选项,所以我忽略了暂时,但我想更新如何,我实现了一个简单的交互类的这个问题。此接口不会成为主流用户的,但我发现它在实施过程中测试我的code非常方便。下面是最初的实现,可能会帮助别人了(注意,这code参考方法和类型我都没有公布,所以将不编译开箱)

Update: I haven't found a satisfactory (cross-platform) solution to the history/completion option, so I've ignored that for the time being, but I wanted to update this question with how I've implemented a simple interactive class. This interface won't be for mainstream user's but I'm finding it very handy for testing my code during implementation. Below is the initial implementation that might help others out (note that this code references methods and types I have not published, so won't compile out of the box)

Interact.h:

Interact.h:

#ifndef INTERACT_H
#define INTERACT_H

class Interact;
class InteractCommand;
typedef  void (Interact::*PF_FUNC)(const InteractCommand &command, const StringVector &args);

struct InteractCommand
{
    const char *command;
    const char *argDesc;
    const char *desc;
    PF_FUNC func;
};

class Interact
{
private:
    static Log m_log;
    static InteractCommand m_commands[];
    static unsigned m_numCommands;

    bool m_stop;
    Database &m_database;
    StringVector &m_dirs;

public:
    Interact(Database &database, StringVector &dirs);
    ~Interact();

    /**
     * Main 'interact' loop.
     *
     * @return true if the loop exitted normally, else false if an error occurred.
     */
    bool interact();

private:
    // Functions
#define DEFFUNC(f) void FUNC_##f(const InteractCommand &command, const StringVector &args)
    DEFFUNC(database);
    DEFFUNC(dirs);
    DEFFUNC(exit);
    DEFFUNC(help);
#undef DEFFUNC


    /**
     * Print usage information for the specified command.
     *
     * @param command The command to print usage for.
     */
    static void usage(const InteractCommand &command);

    static void describeCommand(string &dest, const InteractCommand &command);
};

#endif // INTERACT_H

Interact.cpp:

Interact.cpp:

#include "Interact.h"

Log Interact::m_log("Interact");

#define IFUNC(f) &Interact::FUNC_##f
InteractCommand Interact::m_commands[] = 
{
    { "database", "<file>|close", "Use database <file> or close opened database", IFUNC(database) },
    { "dirs", "dir[,dir...]", "Set the directories to scan", IFUNC(dirs) },
    { "exit", 0, "Exit", IFUNC(exit) },
    { "help", 0, "Print help", IFUNC(help) }
};
#undef IFUNC

unsigned Interact::m_numCommands = sizeof(m_commands) / sizeof(m_commands[0]);

Interact::Interact(MusicDatabase &database, StringVector &dirs) :
    m_stop(false),
    m_database(database),
    m_dirs(dirs)
{
}

Interact::~Interact()
{
}

bool Interact::interact()
{
    string line;
    StringVector args;
    unsigned i;

    m_stop = false;
    while (!m_stop)
    {
        args.clear();
        cout << "> ";
        if (!getline(cin, line) || cin.eof())
            break;
        else if (cin.fail())
            return false;

        if (!Util::splitString(line, " ", args) || args.size() == 0)
            continue;

        for (i = 0; i < m_numCommands; i++)
            if (strncasecmp(args[0].c_str(), m_commands[i].command, args[0].length()) == 0)
                break;
        if (i < m_numCommands)
            (this->*m_commands[i].func)(m_commands[i], args);
        else
            cout << "Unknown command '" << args[0] << "'" << endl;
    }
    return true;
}

void Interact::FUNC_database(const InteractCommand &command, const StringVector &args)
{
    if (args.size() != 2)
    {
        usage(command);
        return;
    }

    if (args[1] == "close")
    {
        if (m_database.opened())
            m_database.close();
        else
            cout << "Database is not open" << endl;
    }
    else
    {
        if (!m_database.open(args[1]))
        {
            cout << "Failed to open database" << endl;
        }
    }
}

void Interact::FUNC_dirs(const InteractCommand &command, const StringVector &args)
{
    if (args.size() == 1)
    {
        usage(command);
        return;
    }
    // TODO

}

void Interact::FUNC_exit(const InteractCommand &command, const StringVector &args)
{
    m_stop = true;
}

void Interact::FUNC_help(const InteractCommand &command, const StringVector &/*args*/)
{
    string descr;
    for (unsigned i = 0; i < m_numCommands; i++)
    {
        describeCommand(descr, m_commands[i]);
        cout << descr << endl;
    }
}

void Interact::usage(const InteractCommand &command)
{
    string descr;
    describeCommand(descr, command);
    cout << "usage: " << endl;
    cout << descr << endl;
}

void Interact::describeCommand(string &dest, const InteractCommand &command)
{
    dest.clear();
    string cmdStr = command.command;
    if (command.argDesc != 0)
    {
        cmdStr += " ";
        cmdStr += command.argDesc;
    }
    Util::format(dest, "  %-30s%s", cmdStr.c_str(), command.desc);
}

这篇关于跨平台,命令完成交互式文本界面的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆