簡體   English   中英

跨平台,基於交互式文本的界面,具有命令完成功能

[英]Cross platform, Interactive text-based interface with command completion

有誰知道將提供基於文本的交互式界面的C ++庫? 我想創建一個應用程序的兩個版本; 一個基於控制台的程序,它將執行在命令行上或在控制台上交互式執行的任何操作以及基於GUI的程序(Mac Cocoa和Windows MFC)。 兩個版本都將共享一個通用的C ++后端。

對於基於控制台的程序,我希望類似的readline歷史能力(我不能使用,因為這個應用程序將是閉源),命令完成(例如Tab激活)。

也許有這樣的東西已經可用了嗎?

沒有特別的順序,(我沒有使用過它們),你應該看看:

如果沒有一個你喜歡你的另一種可能性,也許它甚至可能是首選。 將您的后端編寫為守護進程,並將前端作為一個愚蠢的程序,通過任何形式的進程間通信與后端進行通信。 然后,您可以使用任何GPLed庫為您的前端沒有任何問題,因為您可以將前端作為開源發布。 當然,這將暴露前端和后端之間的通信協議,所以你必須確保沒關系,當然還有其他人可能覺得有必要對你的前端進行自定義,甚至可能自己創建。 但是假設你的價值無論如何都在后端,這不應該造成特別的問題。 它甚至可能被認為是一個優點,它將允許任何有明智想法的人以新的和意想不到的方式使用您的軟件,只會增加您的軟件的受歡迎程度。

更新:我沒有找到一個令人滿意的(跨平台)解決方案的歷史/完成選項,所以我暫時忽略了它,但我想用我如何實現一個簡單的交互式類來更新這個問題。 這個界面不適合主流用戶,但我發現它在實現過程中測試我的代碼非常方便。 下面是可能幫助其他人的初始實現(請注意,此代碼引用了我尚未發布的方法和類型,因此不會立即編譯)

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM