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 */
/* ************************************************************************** */
#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_SIZE512
#define GLOBAL_CMD_TOKEN'-'
class nConConServer: public nRoot
{
public :
/// constructor
nConConServer();
/// destructor
virtual ~ nConConServer();
/// ToggleMode
void ToggleMode();
/// PollCommands
void PollCmd();
/// ExecuteString
void ExecuteCommand( const char * szCmdStr);
protected :
/// seteditlinebuffer
void SetEditLine( const char * szCmdBuf);
/// executethecurrentcommand
void ExecuteEditLine();
/// checkingthechareffect
bool CheckingChar( char ch);
/// globalfunctioncheck
void ExecuteGlobal();
/// addcurrentcommandtohistory
void AddCommandToHistory();
/// recallnextcommandinhistory
void RecallNextCommand();
/// recallpreviouscommandinhistory
void RecallPrevCommand();
/// setlocalcwd
void SetCwd(nRoot * cwd);
/// getlocalcwd(canreturn0)
nRoot * GetCwd();
/// updatethetabcompletionstuff
void UpdateTabComplete();
/// performatabcompletion
void DoTabCompletion();
private :
nKernelInfoHelperm_info;
bool m_bRecvCmd;
size_tm_nLineBufPtr;
char m_szLineBuf[LINE_BUF_MAX_SIZE];
nStringeditLine;
nAutoRef < nScriptServer > refScriptServer;
nRef < nRoot > refCwd;
};
#pragma warning(push)
#pragma warning(disable:42674244)
#include " nconconserver.h "
#include " nutildefs.h "
/// ----------------------------------------------------------------------------
/// constructor
nConConServer::nConConServer():
m_bRecvCmd( false ),
refScriptServer( " /sys/servers/script " )
{
}
/// destructor
nConConServer:: ~ nConConServer()
{
}
/// ToggleMode
void nConConServer::ToggleMode()
{
m_bRecvCmd = ! m_bRecvCmd;
if (m_bRecvCmd)
{
// WelcomeText
printf( " " );
printf( " %s " , " ========================= " );
printf( " %s " , " ConConServerWelcome:) " );
printf( " %s " , " ========================= " );
}
}
/// PollCommands
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);
}
}
/// ExecuteString
void nConConServer::ExecuteCommand( const char * szCmdStr)
{
SetEditLine(m_szLineBuf);
ExecuteEditLine();
}
/// seteditlinebuffer
void nConConServer::SetEditLine( const char * szCmdBuf)
{
editLine.Set(szCmdBuf);
}
/// executethecurrentcommand
void nConConServer::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 ;
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();
// setnewlocalcwd
nRoot * newCwd = nKernelServer::Instance() -> GetCwd();
if (newCwd != this -> GetCwd())
{
this -> SetCwd(nKernelServer::Instance() -> GetCwd());
this -> UpdateTabComplete();
}
// restorepreviouscwd
nKernelServer::Instance() -> PopCwd();
}
/// checkingthechareffect
bool nConConServer::CheckingChar( char ch)
{
return false ;
}
/// globalfunctioncheck
void nConConServer::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. " );
}
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:'-'followsUnkownGlobleCommand! " );
}
}
/// addcurrentcommandtohistory
void nConConServer::AddCommandToHistory()
{
// empty.
}
/// recallnextcommandinhistory
void nConConServer::RecallNextCommand()
{
// empty.
}
/// recallpreviouscommandinhistory
void nConConServer::RecallPrevCommand()
{
// empty.
}
/// setlocalcwd
void nConConServer::SetCwd(nRoot * cwd)
{
this -> refCwd = cwd;
}
/// getlocalcwd(canreturn0)
nRoot * nConConServer::GetCwd()
{
if ( ! this -> refCwd.isvalid())
{
this -> SetCwd(nKernelServer::Instance() -> GetCwd());
}
return this -> refCwd. get ();
}
/// updatethetabcompletionstuff
void nConConServer::UpdateTabComplete()
{
// ...
}
/// performatabcompletion
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);
/// RegistCommands
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-Tutorial12 */
/* AConsoleServerforConsole */
/* author:happykevins */
/* ************************************************************************** */
/// ----------------------------------------------------------------------------
/// +必要头文件
// nebula2includes
#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")
/// -链接库
/// ----------------------------------------------------------------------------
/// ----------------------------------------------------------------------------
/// +声明使用的Nebula2Package&Module
nNebulaUseModule(ntclserver);
/// -声明使用的Nebula2Package&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
nConConServerconsole;
/// 切出ConConServer
console.ToggleMode();
/// 轮训控制台指令,(阻塞模式)
console.PollCmd();
/// 释放资源
if ( ! CloseApp())
{
n_error( " 释放资源失败! " );
return 0 ;
}
return 0 ;
}
/// -Application
/// ----------------------------------------------------------------------------
--The End--