Nebula2探秘12-基于Windows命令行的Nebula控制台
happykevins文
“工欲善其事,必先利其器!”
本文创建了一个在命令窗口下的Nebula命令控制台.可以直接执行脚本指令,察看当前Nebula的系统状态,察看NOH树及当前工作对象信息,对于调试和控制Nebula2程序非常实用方便!
本来Nebula2在nGui系统中已经实现了一个叫做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--
Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=1412709