mirror of https://github.com/axmolengine/axmol.git
Merge pull request #5342 from heliclei/console-user-command
closed #4063 :revise CCConsole to support more easily for adding custom command.
This commit is contained in:
commit
58d3311da0
|
@ -30,8 +30,8 @@
|
||||||
#include <cctype>
|
#include <cctype>
|
||||||
#include <locale>
|
#include <locale>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@
|
||||||
|
|
||||||
NS_CC_BEGIN
|
NS_CC_BEGIN
|
||||||
|
|
||||||
|
//TODO: these general utils should be in a seperate class
|
||||||
//
|
//
|
||||||
// Trimming functions were taken from: http://stackoverflow.com/a/217605
|
// Trimming functions were taken from: http://stackoverflow.com/a/217605
|
||||||
//
|
//
|
||||||
|
@ -82,6 +82,22 @@ static std::string &trim(std::string &s) {
|
||||||
return ltrim(rtrim(s));
|
return ltrim(rtrim(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::string> &split(const std::string &s, char delim, std::vector<std::string> &elems) {
|
||||||
|
std::stringstream ss(s);
|
||||||
|
std::string item;
|
||||||
|
while (std::getline(ss, item, delim)) {
|
||||||
|
elems.push_back(item);
|
||||||
|
}
|
||||||
|
return elems;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<std::string> split(const std::string &s, char delim) {
|
||||||
|
std::vector<std::string> elems;
|
||||||
|
split(s, delim, elems);
|
||||||
|
return elems;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// helper free functions
|
// helper free functions
|
||||||
|
|
||||||
|
@ -229,8 +245,6 @@ Console::Console()
|
||||||
: _listenfd(-1)
|
: _listenfd(-1)
|
||||||
, _running(false)
|
, _running(false)
|
||||||
, _endThread(false)
|
, _endThread(false)
|
||||||
, _userCommands(nullptr)
|
|
||||||
, _maxUserCommands(0)
|
|
||||||
, _sendDebugStrings(false)
|
, _sendDebugStrings(false)
|
||||||
{
|
{
|
||||||
// VS2012 doesn't support initializer list, so we create a new array and assign its elements to '_command'.
|
// VS2012 doesn't support initializer list, so we create a new array and assign its elements to '_command'.
|
||||||
|
@ -262,10 +276,10 @@ Console::Console()
|
||||||
{ "texture", "Flush or print the TextureCache info. Args: [flush | ] ", std::bind(&Console::commandTextures, this, std::placeholders::_1, std::placeholders::_2) },
|
{ "texture", "Flush or print the TextureCache info. Args: [flush | ] ", std::bind(&Console::commandTextures, this, std::placeholders::_1, std::placeholders::_2) },
|
||||||
};
|
};
|
||||||
|
|
||||||
_maxCommands = sizeof(commands)/sizeof(commands[0]);
|
;
|
||||||
for (int i = 0; i < _maxCommands; ++i)
|
for (int i = 0; i < sizeof(commands)/sizeof(commands[0]); ++i)
|
||||||
{
|
{
|
||||||
_commands[i] = commands[i];
|
_commands.insert ( std::pair<std::string,Command>(commands[i].name,commands[i]) );
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -282,7 +296,6 @@ bool Console::listenOnTCP(int port)
|
||||||
char serv[30];
|
char serv[30];
|
||||||
|
|
||||||
snprintf(serv, sizeof(serv)-1, "%d", port );
|
snprintf(serv, sizeof(serv)-1, "%d", port );
|
||||||
serv[sizeof(serv)-1]=0;
|
|
||||||
|
|
||||||
bzero(&hints, sizeof(struct addrinfo));
|
bzero(&hints, sizeof(struct addrinfo));
|
||||||
hints.ai_flags = AI_PASSIVE;
|
hints.ai_flags = AI_PASSIVE;
|
||||||
|
@ -364,13 +377,11 @@ void Console::stop()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Console::setUserCommands(Command *commands, int numberOfCommands)
|
void Console::addCommand(const Command& cmd)
|
||||||
{
|
{
|
||||||
_userCommands = commands;
|
_commands[cmd.name]=cmd;
|
||||||
_maxUserCommands = numberOfCommands;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// commands
|
// commands
|
||||||
//
|
//
|
||||||
|
@ -379,26 +390,17 @@ void Console::commandHelp(int fd, const std::string &args)
|
||||||
{
|
{
|
||||||
const char help[] = "\nAvailable commands:\n";
|
const char help[] = "\nAvailable commands:\n";
|
||||||
write(fd, help, sizeof(help));
|
write(fd, help, sizeof(help));
|
||||||
for(int i=0; i<_maxCommands; ++i) {
|
for(auto it=_commands.begin();it!=_commands.end();++it)
|
||||||
mydprintf(fd, "\t%s", _commands[i].name);
|
{
|
||||||
ssize_t tabs = strlen(_commands[i].name) / 8;
|
auto cmd = it->second;
|
||||||
|
mydprintf(fd, "\t%s", cmd.name);
|
||||||
|
ssize_t tabs = strlen(cmd.name) / 8;
|
||||||
tabs = 3 - tabs;
|
tabs = 3 - tabs;
|
||||||
for(int j=0;j<tabs;j++){
|
for(int j=0;j<tabs;j++){
|
||||||
mydprintf(fd, "\t");
|
mydprintf(fd, "\t");
|
||||||
}
|
}
|
||||||
mydprintf(fd,"%s\n", _commands[i].help);
|
mydprintf(fd,"%s\n", cmd.help);
|
||||||
}
|
}
|
||||||
|
|
||||||
// User commands
|
|
||||||
for(int i=0; i<_maxUserCommands; ++i) {
|
|
||||||
mydprintf(fd, "\t%s", _userCommands[i].name);
|
|
||||||
ssize_t tabs = strlen(_userCommands[i].name) / 8;
|
|
||||||
tabs = 3 - tabs;
|
|
||||||
for(int j=0;j<tabs;j++){
|
|
||||||
mydprintf(fd, "\t");
|
|
||||||
}
|
|
||||||
mydprintf(fd,"%s\n", _userCommands[i].help);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Console::commandExit(int fd, const std::string &args)
|
void Console::commandExit(int fd, const std::string &args)
|
||||||
|
@ -437,6 +439,7 @@ void Console::commandConfig(int fd, const std::string& args)
|
||||||
Scheduler *sched = Director::getInstance()->getScheduler();
|
Scheduler *sched = Director::getInstance()->getScheduler();
|
||||||
sched->performFunctionInCocosThread( [&](){
|
sched->performFunctionInCocosThread( [&](){
|
||||||
mydprintf(fd, "%s", Configuration::getInstance()->getInfo().c_str());
|
mydprintf(fd, "%s", Configuration::getInstance()->getInfo().c_str());
|
||||||
|
sendPrompt(fd);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -467,7 +470,6 @@ void Console::commandResolution(int fd, const std::string& args)
|
||||||
(int)visibleRect.origin.x, (int)visibleRect.origin.y,
|
(int)visibleRect.origin.x, (int)visibleRect.origin.y,
|
||||||
(int)visibleRect.size.width, (int)visibleRect.size.height
|
(int)visibleRect.size.width, (int)visibleRect.size.height
|
||||||
);
|
);
|
||||||
sendPrompt(fd);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
int width, height, policy;
|
int width, height, policy;
|
||||||
|
@ -554,46 +556,45 @@ void Console::commandTextures(int fd, const std::string& args)
|
||||||
|
|
||||||
bool Console::parseCommand(int fd)
|
bool Console::parseCommand(int fd)
|
||||||
{
|
{
|
||||||
auto r = readline(fd);
|
char buf[512];
|
||||||
|
auto r = readline(fd, buf, sizeof(buf)-1);
|
||||||
if(r < 1)
|
if(r < 1)
|
||||||
|
{
|
||||||
|
const char err[] = "Unknown error!\n";
|
||||||
|
sendPrompt(fd);
|
||||||
|
write(fd, err, sizeof(err));
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
std::string cmdLine;
|
||||||
|
|
||||||
bool found=false;
|
std::vector<std::string> args;
|
||||||
for(int i=0; i < _maxCommands; ++i) {
|
cmdLine = std::string(buf);
|
||||||
ssize_t commandLen = strlen(_commands[i].name);
|
|
||||||
if( strncmp(_buffer, _commands[i].name,commandLen) == 0 ) {
|
args = split(cmdLine, ' ');
|
||||||
// XXX TODO FIXME
|
if(args.empty())
|
||||||
// Ideally this loop should execute the function in the cocos2d according to a variable
|
{
|
||||||
// But clang crashes in runtime when doing that (bug in clang, not in the code).
|
const char err[] = "Unknown command. Type 'help' for options\n";
|
||||||
// So, unfortunately, the only way to fix it was to move that logic to the callback itself
|
write(fd, err, sizeof(err));
|
||||||
|
sendPrompt(fd);
|
||||||
std::string args;
|
return false;
|
||||||
if(strlen(_buffer) >= commandLen+2) {
|
|
||||||
args = std::string(&_buffer[commandLen]+1);
|
|
||||||
args = trim(args);
|
|
||||||
}
|
|
||||||
_commands[i].callback(fd, args);
|
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// user commands
|
auto it = _commands.find(trim(args[0]));
|
||||||
for(int i=0; i < _maxUserCommands && !found; ++i) {
|
if(it != _commands.end())
|
||||||
ssize_t commandLen = strlen(_userCommands[i].name);
|
{
|
||||||
if( strncmp(_buffer, _userCommands[i].name,commandLen) == 0 ) {
|
std::string args2;
|
||||||
std::string args;
|
for(int i = 1; i < args.size(); ++i)
|
||||||
if(strlen(_buffer) >= commandLen+2) {
|
{
|
||||||
args = std::string(&_buffer[commandLen]+1);
|
if(i > 1)
|
||||||
args = trim(args);
|
{
|
||||||
|
args2 += ' ';
|
||||||
}
|
}
|
||||||
_userCommands[i].callback(fd, args);
|
args2 += trim(args[i]);
|
||||||
found = true;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
auto cmd = it->second;
|
||||||
|
cmd.callback(fd, args2);
|
||||||
if(!found && strcmp(_buffer, "\r\n")!=0) {
|
}else if(strcmp(buf, "\r\n") != 0) {
|
||||||
const char err[] = "Unknown command. Type 'help' for options\n";
|
const char err[] = "Unknown command. Type 'help' for options\n";
|
||||||
write(fd, err, sizeof(err));
|
write(fd, err, sizeof(err));
|
||||||
}
|
}
|
||||||
|
@ -608,19 +609,17 @@ bool Console::parseCommand(int fd)
|
||||||
//
|
//
|
||||||
|
|
||||||
|
|
||||||
ssize_t Console::readline(int fd)
|
ssize_t Console::readline(int fd, char* ptr, int maxlen)
|
||||||
{
|
{
|
||||||
int maxlen = sizeof(_buffer)-1;
|
|
||||||
ssize_t n, rc;
|
ssize_t n, rc;
|
||||||
char c, *ptr;
|
char c;
|
||||||
|
|
||||||
ptr = _buffer;
|
for( n=1; n<maxlen-1; n++ ) {
|
||||||
|
|
||||||
for( n=1; n<maxlen; n++ ) {
|
|
||||||
if( (rc = read(fd, &c, 1 )) ==1 ) {
|
if( (rc = read(fd, &c, 1 )) ==1 ) {
|
||||||
*ptr++ = c;
|
*ptr++ = c;
|
||||||
if( c=='\n' )
|
if(c == '\n') {
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
} else if( rc == 0 ) {
|
} else if( rc == 0 ) {
|
||||||
return 0;
|
return 0;
|
||||||
} else if( errno == EINTR ) {
|
} else if( errno == EINTR ) {
|
||||||
|
|
|
@ -39,10 +39,10 @@ typedef int ssize_t;
|
||||||
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <map>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
#include "ccMacros.h"
|
#include "ccMacros.h"
|
||||||
|
@ -92,16 +92,16 @@ public:
|
||||||
/** stops the Console. 'stop' will be called at destruction time as well */
|
/** stops the Console. 'stop' will be called at destruction time as well */
|
||||||
void stop();
|
void stop();
|
||||||
|
|
||||||
/** sets user tokens */
|
/** add custom command */
|
||||||
void setUserCommands( Command* commands, int numberOfCommands);
|
void addCommand(const Command& cmd);
|
||||||
|
|
||||||
/** log something in the console */
|
/** log something in the console */
|
||||||
void log(const char *buf);
|
void log(const char *buf);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void loop();
|
void loop();
|
||||||
ssize_t readline(int fd);
|
ssize_t readline(int fd, char *buf, int maxlen);
|
||||||
bool parseCommand(int fd);
|
bool parseCommand(int fd);
|
||||||
|
|
||||||
void addClient();
|
void addClient();
|
||||||
|
|
||||||
// Add commands here
|
// Add commands here
|
||||||
|
@ -125,13 +125,7 @@ protected:
|
||||||
bool _running;
|
bool _running;
|
||||||
bool _endThread;
|
bool _endThread;
|
||||||
|
|
||||||
char _buffer[512];
|
std::map<std::string, Command> _commands;
|
||||||
|
|
||||||
struct Command _commands[64];
|
|
||||||
int _maxCommands;
|
|
||||||
struct Command *_userCommands;
|
|
||||||
int _maxUserCommands;
|
|
||||||
|
|
||||||
|
|
||||||
// strings generated by cocos2d sent to the remote console
|
// strings generated by cocos2d sent to the remote console
|
||||||
bool _sendDebugStrings;
|
bool _sendDebugStrings;
|
||||||
|
|
|
@ -175,7 +175,7 @@ ConsoleCustomCommand::ConsoleCustomCommand()
|
||||||
write(fd, "\n",1);
|
write(fd, "\n",1);
|
||||||
}},
|
}},
|
||||||
};
|
};
|
||||||
_console->setUserCommands(&commands[0],1);
|
_console->addCommand(commands[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConsoleCustomCommand::~ConsoleCustomCommand()
|
ConsoleCustomCommand::~ConsoleCustomCommand()
|
||||||
|
|
Loading…
Reference in New Issue