Nebula2探秘12-基于Windows命令行的Nebula控制台
happykevins文
“工欲善其事,必先利其器!”
本文创建了一个在命令窗口下的Nebula命令控制台.可以直接执行脚本指令,察看当前Nebula的系统状态,察看NOH树及当前工作对象信息,对于调试和控制Nebula2程序非常实用方便!
本来Nebula2在nGui系统中已经实现了一个叫做nGuiCmdEntry的控件,这个控件就具备即时执行脚本的功能,但我们在实际开发中可能会抛弃nGui而使用其他如CEGUI的界面系统进行替换,所以我们需要一个通用的解决方案:适用Windows控制台作为Nebula控制台的载体,于是就产生了本文的nConConServer。
在nConConServer中借鉴了nGuiCmdEntry中对用户输入脚本指令的处理方式,并加入了几条实用的全局指令,使用”-help”指令查看全局指令帮助,代码如下:
/*Nebula2-TutorialUtils*/
/*nConConServer-控制台下的Nebula2指令控制台*/
/*author:happykevins*/
/****************************************************************************/
#pragmaonce
#include"kernel/nkernelserver.h"
#include"kernel/nscriptserver.h"
#include"kernel/nautoref.h"
#defineKS_USE_STDOUT
#include"nkernelinfo.h"
#undefKS_USE_STDOUT
#defineLINE_BUF_MAX_SIZE512
#defineGLOBAL_CMD_TOKEN'-'
classnConConServer:publicnRoot
{
public:
///constructor
nConConServer();
///destructor
virtual~nConConServer();
///ToggleMode
voidToggleMode();
///PollCommands
voidPollCmd();
///ExecuteString
voidExecuteCommand(constchar*szCmdStr);
protected:
///seteditlinebuffer
voidSetEditLine(constchar*szCmdBuf);
///executethecurrentcommand
voidExecuteEditLine();
///checkingthechareffect
boolCheckingChar(charch);
///globalfunctioncheck
voidExecuteGlobal();
///addcurrentcommandtohistory
voidAddCommandToHistory();
///recallnextcommandinhistory
voidRecallNextCommand();
///recallpreviouscommandinhistory
voidRecallPrevCommand();
///setlocalcwd
voidSetCwd(nRoot*cwd);
///getlocalcwd(canreturn0)
nRoot*GetCwd();
///updatethetabcompletionstuff
voidUpdateTabComplete();
///performatabcompletion
voidDoTabCompletion();
private:
nKernelInfoHelperm_info;
boolm_bRecvCmd;
size_tm_nLineBufPtr;
charm_szLineBuf[LINE_BUF_MAX_SIZE];
nStringeditLine;
nAutoRef<nScriptServer>refScriptServer;
nRef<nRoot>refCwd;
};
#pragmawarning(push)
#pragmawarning(disable:42674244)
#include"nconconserver.h"
#include"nutildefs.h"
///----------------------------------------------------------------------------
///constructor
nConConServer::nConConServer():
m_bRecvCmd(false),
refScriptServer("/sys/servers/script")
{
}
///destructor
nConConServer::~nConConServer()
{
}
///ToggleMode
voidnConConServer::ToggleMode()
{
m_bRecvCmd=!m_bRecvCmd;
if(m_bRecvCmd)
{
//WelcomeText
printf(" ");
printf("%s ","=========================");
printf("%s ","ConConServerWelcome:)");
printf("%s ","=========================");
}
}
///PollCommands
voidnConConServer::PollCmd()
{
while(m_bRecvCmd)
{
printf(" :>");
memset(m_szLineBuf,0,LINE_BUF_MAX_SIZE);
m_nLineBufPtr=0;
charch;
while((ch=getchar())!=' ')
{
if(CheckingChar(ch))
{
continue;
}
m_szLineBuf[m_nLineBufPtr]=ch;
m_nLineBufPtr++;
}
m_szLineBuf[m_nLineBufPtr]='\0';
ExecuteCommand(m_szLineBuf);
}
}
///ExecuteString
voidnConConServer::ExecuteCommand(constchar*szCmdStr)
{
SetEditLine(m_szLineBuf);
ExecuteEditLine();
}
///seteditlinebuffer
voidnConConServer::SetEditLine(constchar*szCmdBuf)
{
editLine.Set(szCmdBuf);
}
///executethecurrentcommand
voidnConConServer::ExecuteEditLine()
{
//checkandrunglobalfunction
if(GLOBAL_CMD_TOKEN==editLine[0])
{
ExecuteGlobal();
return;
}
//checkifscriptserverisok
if(!refScriptServer.isvalid())
{
printf("Error:ScriptServerisnotStartup! ");
return;
}
nScriptServer*scriptServer=this->refScriptServer.get();
//makelocalcwdglobal
nKernelServer::Instance()->PushCwd(this->GetCwd());
//andrunthecommandthroughthescriptserver
nStringresult=0;
boolfailOnError=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();
//setnewlocalcwd
nRoot*newCwd=nKernelServer::Instance()->GetCwd();
if(newCwd!=this->GetCwd())
{
this->SetCwd(nKernelServer::Instance()->GetCwd());
this->UpdateTabComplete();
}
//restorepreviouscwd
nKernelServer::Instance()->PopCwd();
}
///checkingthechareffect
boolnConConServer::CheckingChar(charch)
{
returnfalse;
}
///globalfunctioncheck
voidnConConServer::ExecuteGlobal()
{
char*szRealCmd=m_szLineBuf+1;
if(0==strcmp("help",szRealCmd))
{
printf("%s ","=========================");
printf("%s ","ConConServerHelpList:)");
printf("%s ","=========================");
printf("%s ","*CommandList:");
printf("%s "," help:ShowthisText!");
printf("%s "," exit:ExitConConServerMode.");
printf("%s "," noh:DisplayaTreeViewofNebulaNOH.");
printf("%s "," cls:ShowCurrentRegisteredClassList.");
printf("%s "," cwd:ShowCurrentWorkingObjectInfo.");
printf("%s "," mtd:ShowtheMethodsthatCurrentWorkingObjectSupport.");
}
elseif(0==strcmp("exit",szRealCmd))
{
ToggleMode();
}
elseif(0==strcmp("noh",szRealCmd))
{
m_info.LogNOH(this->GetCwd()->GetFullName().Get());
}
elseif(0==strcmp("cls",szRealCmd))
{
m_info.LogCLS();
}
elseif(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());
}
elseif(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:'-'followsUnkownGlobleCommand!");
}
}
///addcurrentcommandtohistory
voidnConConServer::AddCommandToHistory()
{
//empty.
}
///recallnextcommandinhistory
voidnConConServer::RecallNextCommand()
{
//empty.
}
///recallpreviouscommandinhistory
voidnConConServer::RecallPrevCommand()
{
//empty.
}
///setlocalcwd
voidnConConServer::SetCwd(nRoot*cwd)
{
this->refCwd=cwd;
}
///getlocalcwd(canreturn0)
nRoot*nConConServer::GetCwd()
{
if(!this->refCwd.isvalid())
{
this->SetCwd(nKernelServer::Instance()->GetCwd());
}
returnthis->refCwd.get();
}
///updatethetabcompletionstuff
voidnConConServer::UpdateTabComplete()
{
//...
}
///performatabcompletion
voidnConConServer::DoTabCompletion()
{
//...
}
///----------------------------------------------------------------------------
///声明为Nebula2脚本支持类
nNebulaScriptModule(nConConServer,nconconserver,"nroot");
///ConConServer开关
staticvoidn_toggle(void*slf,nCmd*cmd);
///执行控制台指令
staticvoidn_exec(void*slf,nCmd*cmd);
///RegistCommands
voidnNebulaScriptInitCmds(nconconserver)(nClass*cl)
{
cl->BeginCmds();
cl->AddCmd("v_toggle_v",'TOGL',n_toggle);
cl->AddCmd("v_exec_s",'EXEC',n_exec);
cl->EndCmds();
}
///ToggleMode的脚本支持
staticvoidn_toggle(void*slf,nCmd*cmd)
{
nConConServer*self=(nConConServer*)slf;
self->ToggleMode();
}
///ExecCommand的脚本支持
staticvoidn_exec(void*slf,nCmd*cmd)
{
nConConServer*self=(nConConServer*)slf;
constchar*szCmdStr=cmd->In()->GetS();
self->ExecuteCommand(szCmdStr);
}
///----------------------------------------------------------------------------
#pragmawarning(pop)
其中ToggleMode()方法是切换到控制台模式的开关,已经加入了对脚本的支持,可以直接通过InputServer映射到一个按键上。
PollCmd()命令用于阻塞接受用户输入的指令。由于是以Windows控制台实现,所以只能以阻塞模式接受用户输入,在执行PollCmd()函数后应用程序会停止运行,直到用户在控制台中输入”-exit”指令,nConConServer才会把控制权释放掉。
下面给出nConConServer的使用事例代码:
/*Nebula2-Tutorial12*/
/*AConsoleServerforConsole*/
/*author:happykevins*/
/****************************************************************************/
///----------------------------------------------------------------------------
///+必要头文件
//nebula2includes
#include"kernel/nkernelserver.h"
#include"script/ntclserver.h"
//ConConServer头文件
#include"../NebulaUtils/nConConServer.h"
//Tutorial工具库:一些通用的宏定义
#include"../NebulaUtils/nutildefs.h"
///-必要头文件
///----------------------------------------------------------------------------
///----------------------------------------------------------------------------
///+链接库
#pragmacomment(lib,"wsock32.lib")
#pragmacomment(lib,"d_nkernel.lib")
#pragmacomment(lib,"d_nnebula.lib")
#pragmacomment(lib,"d_microtcl.lib")
///-链接库
///----------------------------------------------------------------------------
///----------------------------------------------------------------------------
///+声明使用的Nebula2Package&Module
nNebulaUseModule(ntclserver);
///-声明使用的Nebula2Package&Module
///----------------------------------------------------------------------------
nKernelServer*ks=NULL;
///----------------------------------------------------------------------------
///+初始化环境,创建需要的Server
///
boolInitApp()
{
///创建KernelServer
ks=n_new(nKernelServer);
///----------------------------------------------------------------------------
///+向KernelServer中添加Package&Module
nNebulaAddModule(ntclserver);
///+向KernelServer中添加Package&Module
///----------------------------------------------------------------------------
ks->New("ntclserver","/sys/servers/script");
returntrue;
}
///
///-初始化环境,创建需要的Server
///----------------------------------------------------------------------------
///----------------------------------------------------------------------------
///+退出程序,清理资源
///
boolCloseApp()
{
///销毁KernelServer
n_delete(ks);
returntrue;
}
///
///-退出程序,清理资源
///----------------------------------------------------------------------------
///----------------------------------------------------------------------------
///+Application
intmain(intargc,constchar**argv)
{
///初始化Application
if(!InitApp())
{
n_error("程序初始化失败! ");
return0;
}
///ConConServer
nConConServerconsole;
///切出ConConServer
console.ToggleMode();
///轮训控制台指令,(阻塞模式)
console.PollCmd();
///释放资源
if(!CloseApp())
{
n_error("释放资源失败! ");
return0;
}
return0;
}
///-Application
///----------------------------------------------------------------------------
--The End--