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

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

问题描述

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



对于基于控制台的程序,我想要类似的历史功能 readline (我无法使用此应用程序将被关闭源)与命令完成(例如Tab激活)。

$ b $

解决方案

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



Interact .h:

  #ifndef INTERACT_H 
#define INTERACT_H

类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;
};

类交互
{
私人:
静态日志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();

/ **
*主'交互'循环。
*
* @如果循环正常退出则返回true,否则返回false。
* /
bool interact();

private:
//函数
#define DEFFUNC(f)void FUNC _ ## f(const InteractCommand& command,const StringVector& args)
DEFFUNC (数据库);
DEFFUNC(dirs);
DEFFUNC(exit);
DEFFUNC(help);
#undef DEFFUNC


/ **
*打印指定命令的使用信息。
*
* @param命令打印用法的命令。
* /
static void usage(const InteractCommand& command);

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

#endif // INTERACT_H

Interact.cpp:

  #includeInteract.h

Log Interact :: m_log(Interact);

#define IFUNC(f)& Interact :: FUNC _ ## f
InteractCommand Interact :: m_commands [] =
{
{database < file> | close,使用数据库< file>或关闭打开的数据库,IFUNC(数据库)},
{dirs,dir [,dir ...]目录扫描,IFUNC(dirs)},
{exit,0,退出,IFUNC(退出)},
{帮助,0,打印帮助 help)}
};
#undef IFUNC

无符号Interact :: m_numCommands = sizeof(m_commands)/ sizeof(m_commands [0]);

Interact :: Interact(MusicDatabase& database,StringVector& dirs):
m_stop(false),
m_database(database),
m_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 if(strncasecmp(args [0] .c_str(),m_commands [i] .command,args [0]。 length())== 0)
break;
if(i (this-> * m_commands [i] .func)(m_commands [i],args);
else
cout<< 未知命令< 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<< 数据库未打开< endl
}
else
{
if(!m_database.open(args [1]))
{
cout< 无法打开数据库< 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 {
describeCommand(descr,m_commands [i]);
cout<<描述& endl
}
}

void Interact :: usage(const InteractCommand& command)
{
string descr;
describeCommand(descr,command);
cout<< usage:< endl
cout<<描述< 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);
}


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.

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?

解决方案

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:

#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:

#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天全站免登陆