2023-02-13 10:57:10 +08:00
|
|
|
#pragma once
|
|
|
|
|
2023-03-04 00:13:03 +08:00
|
|
|
#include <VTUtils.hpp>
|
2023-03-03 11:06:26 +08:00
|
|
|
#include <CKDefines.hpp>
|
2023-02-13 10:57:10 +08:00
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
2023-03-03 11:06:26 +08:00
|
|
|
#include <deque>
|
|
|
|
|
|
|
|
namespace Unvirt::CmdHelper {
|
|
|
|
|
|
|
|
class CmdSplitter {
|
|
|
|
public:
|
|
|
|
CmdSplitter();
|
|
|
|
CmdSplitter(const CmdSplitter&) = delete;
|
|
|
|
CmdSplitter& operator=(const CmdSplitter&) = delete;
|
|
|
|
~CmdSplitter();
|
|
|
|
|
|
|
|
const std::deque<std::string> Convert(const std::string& u8cmd);
|
|
|
|
private:
|
|
|
|
char mCmdChar;
|
|
|
|
std::string* mBuffer;
|
|
|
|
std::deque<std::string>* mResult;
|
|
|
|
|
|
|
|
enum class StateType : int {
|
|
|
|
SPACE,
|
|
|
|
SINGLE,
|
|
|
|
DOUBLE,
|
|
|
|
ESCAPE,
|
|
|
|
NORMAL
|
|
|
|
};
|
|
|
|
StateType mState, mPreState;
|
|
|
|
|
|
|
|
inline void ProcSpace(void) {
|
|
|
|
switch (mCmdChar) {
|
|
|
|
case '\'':
|
|
|
|
mState = StateType::SINGLE;
|
|
|
|
break;
|
|
|
|
case '"':
|
|
|
|
mState = StateType::DOUBLE;
|
|
|
|
break;
|
|
|
|
case '\\':
|
|
|
|
mState = StateType::ESCAPE;
|
|
|
|
mPreState = StateType::NORMAL;
|
|
|
|
break;
|
|
|
|
case ' ':
|
|
|
|
break; // skip blank
|
|
|
|
default:
|
|
|
|
mBuffer->push_back(mCmdChar);
|
|
|
|
mState = StateType::NORMAL;
|
|
|
|
break;
|
2023-02-13 10:57:10 +08:00
|
|
|
}
|
2023-03-03 11:06:26 +08:00
|
|
|
}
|
|
|
|
inline void ProcSingle(void) {
|
|
|
|
switch (mCmdChar) {
|
|
|
|
case '\'':
|
|
|
|
mState = StateType::NORMAL;
|
|
|
|
break;
|
|
|
|
case '"':
|
|
|
|
mBuffer->push_back('"');
|
|
|
|
break;
|
|
|
|
case '\\':
|
|
|
|
mState = StateType::ESCAPE;
|
|
|
|
mPreState = StateType::SINGLE;
|
|
|
|
break;
|
|
|
|
case ' ':
|
|
|
|
mBuffer->push_back(' ');
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
mBuffer->push_back(mCmdChar);
|
|
|
|
break;
|
2023-02-13 10:57:10 +08:00
|
|
|
}
|
2023-03-03 11:06:26 +08:00
|
|
|
}
|
|
|
|
inline void ProcDouble(void) {
|
|
|
|
switch (mCmdChar) {
|
|
|
|
case '\'':
|
|
|
|
mBuffer->push_back('\'');
|
|
|
|
break;
|
|
|
|
case '"':
|
|
|
|
mState = StateType::NORMAL;
|
|
|
|
break;
|
|
|
|
case '\\':
|
|
|
|
mState = StateType::ESCAPE;
|
|
|
|
mPreState = StateType::DOUBLE;
|
|
|
|
break;
|
|
|
|
case ' ':
|
|
|
|
mBuffer->push_back(' ');
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
mBuffer->push_back(mCmdChar);
|
|
|
|
break;
|
2023-02-13 10:57:10 +08:00
|
|
|
}
|
2023-03-03 11:06:26 +08:00
|
|
|
}
|
|
|
|
inline void ProcEscape(void) {
|
|
|
|
// add itself
|
|
|
|
mBuffer->push_back(mCmdChar);
|
|
|
|
// restore state
|
|
|
|
mState = mPreState;
|
|
|
|
}
|
|
|
|
inline void ProcNormal(void) {
|
|
|
|
switch (mCmdChar) {
|
|
|
|
case '\'':
|
|
|
|
mBuffer->push_back('\'');
|
|
|
|
break;
|
|
|
|
case '"':
|
|
|
|
mBuffer->push_back('"');
|
|
|
|
break;
|
|
|
|
case '\\':
|
|
|
|
mState = StateType::ESCAPE;
|
|
|
|
mPreState = StateType::NORMAL;
|
|
|
|
break;
|
|
|
|
case ' ':
|
|
|
|
mResult->push_back(*mBuffer);
|
|
|
|
mBuffer->clear();
|
|
|
|
mState = StateType::SPACE;
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
mBuffer->push_back(mCmdChar);
|
|
|
|
break;
|
2023-02-13 10:57:10 +08:00
|
|
|
}
|
2023-03-03 11:06:26 +08:00
|
|
|
}
|
|
|
|
};
|
2023-02-13 10:57:10 +08:00
|
|
|
|
2023-03-03 11:06:26 +08:00
|
|
|
class ArgParser {
|
|
|
|
public:
|
|
|
|
ArgParser() {}
|
|
|
|
ArgParser(const ArgParser&) = delete;
|
|
|
|
ArgParser& operator=(const ArgParser&) = delete;
|
|
|
|
~ArgParser() {}
|
2023-02-13 16:52:00 +08:00
|
|
|
|
2023-03-03 16:05:32 +08:00
|
|
|
static bool ParseInt(const std::deque<std::string>& cmd, const size_t expected_index, int32_t& result);
|
|
|
|
static bool ParseString(const std::deque<std::string>& cmd, const size_t expected_index, std::string& result);
|
|
|
|
static bool ParseSwitch(const std::deque<std::string>& cmd, const size_t expected_index, const std::vector<std::string>& switches, std::string& gotten);
|
2023-03-03 11:06:26 +08:00
|
|
|
};
|
2023-02-13 16:52:00 +08:00
|
|
|
|
2023-03-03 11:06:26 +08:00
|
|
|
class InteractiveCmd {
|
|
|
|
public:
|
|
|
|
InteractiveCmd();
|
|
|
|
InteractiveCmd(const InteractiveCmd&) = delete;
|
|
|
|
InteractiveCmd& operator=(const InteractiveCmd&) = delete;
|
|
|
|
~InteractiveCmd();
|
2023-02-13 16:52:00 +08:00
|
|
|
|
2023-03-03 11:06:26 +08:00
|
|
|
void Run(void);
|
2023-02-13 10:57:10 +08:00
|
|
|
|
2023-03-03 11:06:26 +08:00
|
|
|
private:
|
|
|
|
void GetCmdLine(std::string& u8cmd);
|
|
|
|
void PrintHelp(void);
|
|
|
|
void PrintArgParseError(const std::deque<std::string>& cmd, size_t pos);
|
|
|
|
void PrintCommonError(const char* u8_fmt, ...);
|
2023-02-13 10:57:10 +08:00
|
|
|
|
2023-03-03 16:05:32 +08:00
|
|
|
void ProcLoad(const std::deque<std::string>& cmd);
|
|
|
|
void ProcUnLoad(const std::deque<std::string>& cmd);
|
|
|
|
void ProcInfo(const std::deque<std::string>& cmd);
|
|
|
|
void ProcLs(const std::deque<std::string>& cmd);
|
2023-03-04 00:13:03 +08:00
|
|
|
void ProcItems(const std::deque<std::string>& cmd);
|
2023-03-04 11:11:36 +08:00
|
|
|
void ProcEncoding(const std::deque<std::string>& cmd);
|
|
|
|
void ProcTemp(const std::deque<std::string>& cmd);
|
|
|
|
|
|
|
|
bool HasOpenedFile(void);
|
|
|
|
void ClearDocument(void);
|
|
|
|
void PrintMinContextMsg(const std::string& msg);
|
2023-02-13 10:57:10 +08:00
|
|
|
|
2023-03-03 11:06:26 +08:00
|
|
|
CmdSplitter m_CmdSplitter;
|
2023-03-03 16:05:32 +08:00
|
|
|
size_t m_PageLen;
|
2023-03-03 11:06:26 +08:00
|
|
|
LibCmo::CK2::CKMinContext* m_Ctx;
|
2023-03-03 16:05:32 +08:00
|
|
|
LibCmo::CK2::CKFile* m_File;
|
2023-03-03 11:06:26 +08:00
|
|
|
LibCmo::CK2::CKFileDocument* m_Doc;
|
|
|
|
};
|
2023-02-13 22:13:30 +08:00
|
|
|
|
2023-03-03 11:06:26 +08:00
|
|
|
}
|