您的位置:首页 > 其它

Nebula2探秘12-基于Windows命令行的Nebula控制台

2008-06-10 12:25 369 查看
Nebula2探秘12-基于Windows命令行的Nebula控制台happykevins文 “工欲善其事,必先利其器!”本文创建了一个在命令窗口下的Nebula命令控制台.可以直接执行脚本指令,察看当前Nebula的系统状态,察看NOH树及当前工作对象信息,对于调试和控制Nebula2程序非常实用方便!本来Nebula2在nGui系统中已经实现了一个叫做nGuiCmdEntry的控件,这个控件就具备即时执行脚本的功能,但我们在实际开发中可能会抛弃nGui而使用其他如CEGUI的界面系统进行替换,所以我们需要一个通用的解决方案:适用Windows控制台作为Nebula控制台的载体,于是就产生了本文的nConConServer。在nConConServer中借鉴了nGuiCmdEntry中对用户输入脚本指令的处理方式,并加入了几条实用的全局指令,使用”-help”指令查看全局指令帮助,代码如下:  /****************************************************************************/
/*    Nebula2 - Tutorial Utils                                                */
/*  nConConServer - 控制台下的Nebula2指令控制台                                */
/*  author: happykevins                                                        */
/****************************************************************************/
#pragma once

#include "kernel/nkernelserver.h"
#include "kernel/nscriptserver.h"
#include "kernel/nautoref.h"

#define KS_USE_STDOUT
#include "nkernelinfo.h"
#undef KS_USE_STDOUT

#define LINE_BUF_MAX_SIZE  512
#define GLOBAL_CMD_TOKEN   '-'

class nConConServer : public nRoot
{
public:
    /// constructor
    nConConServer();
    /// destructor
    virtual ~nConConServer();
    /// Toggle Mode
    void ToggleMode();
    /// Poll Commands
    void PollCmd();
    /// Execute String
    void ExecuteCommand(const char* szCmdStr);

protected:
    /// set edit line buffer
    void SetEditLine(const char* szCmdBuf);
    /// execute the current command
    void ExecuteEditLine();
    /// checking the char effect
    bool CheckingChar(char ch);
    /// global function check
    void ExecuteGlobal();
    /// add current command to history
    void AddCommandToHistory();
    /// recall next command in history
    void RecallNextCommand();
    /// recall previous command in history
    void RecallPrevCommand();
    /// set local cwd
    void SetCwd(nRoot* cwd);
    /// get local cwd (can return 0)
    nRoot* GetCwd();
    /// update the tab completion stuff
    void UpdateTabComplete();
    /// perform a tab completion
    void DoTabCompletion();

private:
    nKernelInfoHelper m_info;
    bool m_bRecvCmd;

    size_t m_nLineBufPtr;
    char m_szLineBuf[LINE_BUF_MAX_SIZE];

    nString editLine;
    
    nAutoRef refScriptServer;
    nRef refCwd;
}; // nconconserver.cpp
#pragma warning(push)
#pragma warning(disable: 4267 4244)

#include "nconconserver.h"
#include "nutildefs.h"
///----------------------------------------------------------------------------

/// constructor
nConConServer::nConConServer() :
    m_bRecvCmd(false),
    refScriptServer("/sys/servers/script")
{
}

/// destructor
nConConServer::~nConConServer()
{
}

/// Toggle Mode
void nConConServer::ToggleMode()
{
    m_bRecvCmd = !m_bRecvCmd;

    if ( m_bRecvCmd )
    {
        // Welcome Text
        printf(" ");
        printf("%s ", "=========================");
        printf("%s ", " ConConServer Welcome :)" );
        printf("%s ", "=========================");
    }
}

/// Poll Commands
void nConConServer::PollCmd()
{
    while ( m_bRecvCmd )
    {
        printf(" :>");
        memset(m_szLineBuf, 0, LINE_BUF_MAX_SIZE);
        m_nLineBufPtr = 0;
        char ch;
        while ( (ch = getchar()) != ' ' )
        {
            if ( CheckingChar(ch) )
            {
                continue;
            }

            m_szLineBuf[m_nLineBufPtr] = ch;
            m_nLineBufPtr++;
        }
        m_szLineBuf[m_nLineBufPtr] = '/0';

        ExecuteCommand(m_szLineBuf);
    }
}

/// Execute String
void nConConServer::ExecuteCommand(const char* szCmdStr)
{
    SetEditLine(m_szLineBuf);
    ExecuteEditLine();
}

/// set edit line buffer
void nConConServer::SetEditLine(const char* szCmdBuf)
{
    editLine.Set(szCmdBuf);
}

/// execute the current command
void nConConServer::ExecuteEditLine()
{
    // check and run global function
    if ( GLOBAL_CMD_TOKEN == editLine[0] )
    {
        ExecuteGlobal();
        return;
    }

    // check if script server is ok
    if ( !refScriptServer.isvalid() )
    {
        printf("Error: Script Server is not Startup! ");
        return;
    }

    nScriptServer* scriptServer = this->refScriptServer.get();

    // make local cwd global
    nKernelServer::Instance()->PushCwd(this->GetCwd());

    // and run the command through the script server
    nString result = 0;
    bool failOnError = scriptServer->GetFailOnError();
    scriptServer->SetFailOnError(false);
    scriptServer->Run(this->editLine.Get(), result);
    scriptServer->SetFailOnError(failOnError);
    if (result.IsValid())
    {
        printf("%s ", result.Get());
    }
    this->AddCommandToHistory();
    this->editLine.Clear();

    // set new local cwd
    nRoot* newCwd = nKernelServer::Instance()->GetCwd();
    if (newCwd != this->GetCwd())
    {
        this->SetCwd(nKernelServer::Instance()->GetCwd());
        this->UpdateTabComplete();
    }

    // restore previous cwd
    nKernelServer::Instance()->PopCwd();
}

/// checking the char effect
bool nConConServer::CheckingChar(char ch)
{
    return false;
}

/// global function check
void nConConServer::ExecuteGlobal()
{
    char* szRealCmd = m_szLineBuf + 1;

    if ( 0 == strcmp("help", szRealCmd) )
    {
        printf("%s ", "=========================");
        printf("%s ", "ConConServer Help List :)");
        printf("%s ", "=========================");
        printf("%s ", "*Command List:           ");
        printf("%s ", " help: Show this Text!");
        printf("%s ", " exit: Exit ConConServer Mode.");
        printf("%s ", " noh : Display a Tree View of Nebula NOH.");
        printf("%s ", " cls : Show Current Registered Class List.");
        printf("%s ", " cwd : Show Current Working Object Info.");
        printf("%s ", " mtd : Show the Methods that Current Working Object Support.");
    }
    else if ( 0 == strcmp("exit", szRealCmd) )
    {
        ToggleMode();
    }
    else if ( 0 == strcmp("noh", szRealCmd) )
    {
        m_info.LogNOH(this->GetCwd()->GetFullName().Get());
    }
    else if ( 0 == strcmp("cls", szRealCmd) )
    {
        m_info.LogCLS();
    }
    else if ( 0 == strcmp("cwd", szRealCmd) )
    {
        printf("CWD   : %s ", this->GetCwd()->GetFullName().Get() );
        printf("Class : %s ", this->GetCwd()->GetClass()->GetProperName() );
        printf("Parent: %s ", this->GetCwd()->GetClass()->GetSuperClass()->GetProperName() );
    }
    else if ( 0 == strcmp("mtd", szRealCmd) )
    {
        nHashList* obj = this->GetCwd()->GetClass()->GetCmdList();

        nCmdProto* node = (nCmdProto*)obj->GetHead();

        do
        {
            printf("%s ", node->GetProtoDef());
        } while ( (node = (nCmdProto*)node->GetSucc()) );
    }
    else
    {
        printf("%s ", "Error: '-' follows Unkown Globle Command!");
    }
}

/// add current command to history
void nConConServer::AddCommandToHistory()
{
    // empty.
}
/// recall next command in history
void nConConServer::RecallNextCommand()
{
    // empty.
}
/// recall previous command in history
void nConConServer::RecallPrevCommand()
{
    // empty.
}
/// set local cwd
void nConConServer::SetCwd(nRoot* cwd)
{
    this->refCwd = cwd;
}
/// get local cwd (can return 0)
nRoot* nConConServer::GetCwd()
{
    if ( !this->refCwd.isvalid() )
    {
        this->SetCwd(nKernelServer::Instance()->GetCwd());
    }
    return this->refCwd.get();
}
/// update the tab completion stuff
void nConConServer::UpdateTabComplete()
{
    // ...
}
/// perform a tab completion
void nConConServer::DoTabCompletion()
{
    // ...
}

///----------------------------------------------------------------------------

/// 声明为Nebula2脚本支持类
nNebulaScriptModule(nConConServer, nconconserver, "nroot");

/// ConConServer开关
static void n_toggle(void* slf, nCmd* cmd);
/// 执行控制台指令
static void n_exec(void* slf, nCmd* cmd);

/// Regist Commands
void nNebulaScriptInitCmds(nconconserver) (nClass* cl)
{
    cl->BeginCmds();
    cl->AddCmd("v_toggle_v",    'TOGL',    n_toggle);
    cl->AddCmd("v_exec_s",        'EXEC',    n_exec);
    cl->EndCmds();
}

/// ToggleMode的脚本支持
static void n_toggle(void* slf, nCmd* cmd)
{
    nConConServer* self = (nConConServer*) slf;
    self->ToggleMode();
}

/// ExecCommand的脚本支持
static void n_exec(void* slf, nCmd* cmd)
{
    nConConServer* self = (nConConServer*) slf;
    const char* szCmdStr = cmd->In()->GetS();
    self->ExecuteCommand(szCmdStr);
}

///----------------------------------------------------------------------------
#pragma warning(pop)
     其中ToggleMode()方法是切换到控制台模式的开关,已经加入了对脚本的支持,可以直接通过InputServer映射到一个按键上。    PollCmd()命令用于阻塞接受用户输入的指令。由于是以Windows控制台实现,所以只能以阻塞模式接受用户输入,在执行PollCmd()函数后应用程序会停止运行,直到用户在控制台中输入”-exit”指令,nConConServer才会把控制权释放掉。    下面给出nConConServer的使用事例代码:/****************************************************************************/
/*    Nebula2 - Tutorial 12                                                    */
/*  A Console Server for Console                                            */
/*  author: happykevins                                                        */
/****************************************************************************/

///----------------------------------------------------------------------------
/// +必要头文件

// nebula2 includes
#include "kernel/nkernelserver.h"
#include "script/ntclserver.h"

// ConConServer头文件
#include "../NebulaUtils/nConConServer.h"

// Tutorial工具库:一些通用的宏定义
#include "../NebulaUtils/nutildefs.h"

/// -必要头文件
///----------------------------------------------------------------------------

///----------------------------------------------------------------------------
/// +链接库
#pragma comment(lib, "wsock32.lib")
#pragma comment(lib, "d_nkernel.lib")
#pragma comment(lib, "d_nnebula.lib")
#pragma comment(lib, "d_microtcl.lib")
/// -链接库
///----------------------------------------------------------------------------

///----------------------------------------------------------------------------
/// +声明使用的Nebula2 Package&Module
nNebulaUseModule(ntclserver);
/// -声明使用的Nebula2 Package&Module
///----------------------------------------------------------------------------
nKernelServer* ks = NULL;

///----------------------------------------------------------------------------
/// +初始化环境,创建需要的Server
///
bool InitApp()
{
    /// 创建KernelServer
    ks = n_new(nKernelServer);

    ///----------------------------------------------------------------------------
    ///    +向KernelServer中添加Package&Module
    nNebulaAddModule(ntclserver);
    ///    +向KernelServer中添加Package&Module
    ///----------------------------------------------------------------------------
    ks->New("ntclserver",            "/sys/servers/script");

    return true;
}
///
/// -初始化环境,创建需要的Server
///----------------------------------------------------------------------------

///----------------------------------------------------------------------------
/// +退出程序,清理资源
///
bool CloseApp()
{
    /// 销毁KernelServer
    n_delete(ks);

    return true;
}
///
/// -退出程序,清理资源
///----------------------------------------------------------------------------

///----------------------------------------------------------------------------
/// +Application
int main(int argc, const char** argv)
{
    /// 初始化Application
    if ( !InitApp() )
    {
        n_error("程序初始化失败! ");
        return 0;
    }
    
    /// ConConServer
    nConConServer console;

    /// 切出ConConServer
    console.ToggleMode();
    /// 轮训控制台指令,(阻塞模式)
    console.PollCmd();

    /// 释放资源
    if ( !CloseApp() )
    {
        n_error("释放资源失败! ");
        return 0;
    }

    return 0;
}
/// -Application
///----------------------------------------------------------------------------
--The End-- 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: