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

来源:互联网 发布:http转换https linux 编辑:程序博客网 时间:2024/04/29 06:49

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

happykevins文

工欲善其事,必先利其器!”

本文创建了一个在命令窗口下的Nebula命令控制台.可以直接执行脚本指令,察看当前Nebula的系统状态,察看NOH树及当前工作对象信息,对于调试和控制Nebula2程序非常实用方便!

本来Nebula2nGui系统中已经实现了一个叫做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
<nScriptServer> refScriptServer;
    nRef
<nRoot> 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--

 




原创粉丝点击