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

2007-04-28     推荐:2714316    收藏:1756053    评论:0     来源:e800开发者频道

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

您可以针对本文进行:[评论]  [收藏]  [推荐]   [查看原文链接]  
我想发表评论:
用户名密码
  • 匿名发表
    验证码: