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;
};
//
nconconserver.cpp
#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--