Improve CLI

This commit is contained in:
Martchus 2017-06-10 22:26:12 +02:00
parent 593e72f121
commit 2dfe0ac902
3 changed files with 350 additions and 354 deletions

View File

@ -31,7 +31,7 @@ InputMuter::InputMuter()
#if defined(PLATFORM_UNIX)
tcgetattr(STDIN_FILENO, &m_attr);
termios newAttr = m_attr;
newAttr.c_lflag &= ~ECHO;
newAttr.c_lflag &= ~static_cast<unsigned int>(ECHO);
tcsetattr(STDIN_FILENO, TCSANOW, &newAttr);
#elif defined(PLATFORM_WINDOWS)
m_cinHandle = GetStdHandle(STD_INPUT_HANDLE);
@ -143,7 +143,7 @@ void InteractiveCli::processCommand(const string &cmd)
pwd();
} else if (CMD_P("cd")) {
cd(param);
} else if (CMD("ls")) {
} else if (CMD2("ls", "l")) {
ls();
} else if (CMD2("tree", "t")) {
tree();
@ -239,7 +239,8 @@ void InteractiveCli::openFile(const string &file, bool readOnly)
{
if (m_file.isOpen()) {
m_o << "file \"" << m_file.path() << "\" currently open; close first" << endl;
} else {
return;
}
m_file.setPath(file);
try {
try {
@ -269,23 +270,25 @@ void InteractiveCli::openFile(const string &file, bool readOnly)
m_currentEntry = nullptr;
}
m_modified = false;
}
}
void InteractiveCli::closeFile()
{
if (m_file.isOpen()) {
if (!m_file.isOpen()) {
m_o << "no file was opened" << endl;
return;
}
m_file.clear();
m_currentEntry = nullptr;
m_o << "file closed" << endl;
} else {
m_o << "no file was opened" << endl;
}
}
void InteractiveCli::saveFile()
{
if (m_file.isOpen()) {
if (!m_file.isOpen()) {
m_o << "nothing to save; no file opened or created" << endl;
return;
}
try {
try {
m_file.save(*m_file.password());
@ -309,16 +312,15 @@ void InteractiveCli::saveFile()
m_file.clear();
}
m_modified = false;
} else {
m_o << "nothing to save; no file opened or created" << endl;
}
}
void InteractiveCli::createFile(const string &file)
{
if (m_file.isOpen()) {
m_o << "file \"" << m_file.path() << "\" currently open; close first" << endl;
} else {
return;
}
m_file.setPath(file);
try {
try {
@ -331,7 +333,7 @@ void InteractiveCli::createFile(const string &file)
m_o << "IO error occured when creating file \"" << file << "\"" << endl;
throw ios_base::failure(what);
}
} catch (exception &e) {
} catch (const exception &e) {
if (*e.what() != 0) {
m_o << e.what() << endl;
}
@ -339,27 +341,29 @@ void InteractiveCli::createFile(const string &file)
m_currentEntry = nullptr;
}
m_modified = false;
}
}
void InteractiveCli::changePassphrase()
{
if (m_file.isOpen()) {
m_o << "can not set passphrase; no file opened or created" << endl;
return;
}
try {
m_file.setPassword(askForPassphrase(true));
m_modified = true;
m_o << "passphrase changed; use save to apply" << endl;
} catch (runtime_error &) {
} catch (const runtime_error &) {
m_o << "passphrase has not changed" << endl;
}
} else {
m_o << "can not set passphrase; no file opened or created" << endl;
}
}
void InteractiveCli::removePassphrase()
{
if (m_file.isOpen()) {
if (!m_file.isOpen()) {
m_o << "nothing to remove; no file opened or created" << endl;
return;
}
if (*m_file.password()) {
m_file.clearPassword();
m_o << "passphrase removed; use save to apply" << endl;
@ -367,63 +371,63 @@ void InteractiveCli::removePassphrase()
} else {
m_o << "nothing to remove; no passphrase present on current file" << endl;
}
} else {
m_o << "nothing to remove; no file opened or created" << endl;
}
}
void InteractiveCli::pwd()
{
if (m_file.isOpen()) {
if (!m_file.isOpen()) {
m_o << "no file open" << endl;
return;
}
auto path = m_currentEntry->path();
m_o << path.front() << ": /";
path.pop_front();
m_o << joinStrings(path, "/") << endl;
} else {
m_o << "no file open" << endl;
}
}
void InteractiveCli::cd(const string &path)
{
if (m_file.isOpen()) {
if (!m_file.isOpen()) {
m_o << "can not change directory; no file open" << endl;
return;
}
if (Entry *entry = resolvePath(path)) {
m_currentEntry = entry;
m_o << "changed to \"" << entry->label() << "\"" << endl;
}
} else {
m_o << "can not change directory; no file open" << endl;
}
}
void InteractiveCli::ls()
{
if (m_file.isOpen()) {
if (!m_file.isOpen()) {
m_o << "can not list any entires; no file open" << endl;
return;
}
switch (m_currentEntry->type()) {
case EntryType::Account: {
m_o << "fields:";
for (const Field &field : static_cast<AccountEntry *>(m_currentEntry)->fields()) {
m_o << " " << field.name();
m_o << "\n" << field.name();
}
break;
}
case EntryType::Node: {
m_o << "entries:";
for (const Entry *entry : static_cast<NodeEntry *>(m_currentEntry)->children()) {
m_o << " " << entry->label();
m_o << "\n" << entry->label();
}
break;
}
}
m_o << endl;
} else {
m_o << "can not list any entires; no file open" << endl;
}
}
void InteractiveCli::tree()
{
if (m_file.isOpen()) {
if (!m_file.isOpen()) {
m_o << "can not print tree; no file open" << endl;
return;
}
function<void(const Entry *entry, unsigned char level)> printEntries;
printEntries = [&printEntries, this](const Entry *entry, unsigned char level) {
for (unsigned char i = 0; i < level; ++i) {
@ -437,14 +441,14 @@ void InteractiveCli::tree()
}
};
printEntries(m_currentEntry, 0);
} else {
m_o << "can not print tree; no file open" << endl;
}
}
void InteractiveCli::makeEntry(EntryType entryType, const string &label)
{
if (m_file.isOpen()) {
if (!m_file.isOpen()) {
m_o << "can not make entry; no file open" << endl;
return;
}
switch (m_currentEntry->type()) {
case EntryType::Node:
switch (entryType) {
@ -460,14 +464,14 @@ void InteractiveCli::makeEntry(EntryType entryType, const string &label)
case EntryType::Account:
m_o << "can not make entry; current entry is no node entry" << endl;
}
} else {
m_o << "can not make entry; no file open" << endl;
}
}
void InteractiveCli::removeEntry(const string &path)
{
if (m_file.isOpen()) {
if (!m_file.isOpen()) {
m_o << "can not remove entry; no file open" << endl;
return;
}
if (Entry *entry = resolvePath(path)) {
if (entry == m_file.rootEntry()) {
m_o << "can not remove root entry" << endl;
@ -480,14 +484,14 @@ void InteractiveCli::removeEntry(const string &path)
m_modified = true;
}
}
} else {
m_o << "can not remove entry; no file open" << endl;
}
}
void InteractiveCli::renameEntry(const string &path)
{
if (m_file.isOpen()) {
if (!m_file.isOpen()) {
m_o << "can not rename entry; no file open" << endl;
return;
}
if (Entry *entry = resolvePath(path)) {
string label;
m_o << "enter new name: " << endl;
@ -500,14 +504,14 @@ void InteractiveCli::renameEntry(const string &path)
m_modified = true;
}
}
} else {
m_o << "can not rename entry; no file open" << endl;
}
}
void InteractiveCli::moveEntry(const string &path)
{
if (m_file.isOpen()) {
if (!m_file.isOpen()) {
m_o << "can not rename entry; no file open" << endl;
return;
}
if (Entry *entry = resolvePath(path)) {
string newParentPath;
m_o << "enter path of new parent: " << endl;
@ -534,15 +538,19 @@ void InteractiveCli::moveEntry(const string &path)
}
}
}
} else {
m_o << "can not rename entry; no file open" << endl;
}
}
void InteractiveCli::readField(const string &fieldName)
{
if (m_file.isOpen()) {
if (m_currentEntry->type() == EntryType::Account) {
if (!m_file.isOpen()) {
m_o << "can not read field; no file open" << endl;
return;
}
if (m_currentEntry->type() != EntryType::Account) {
m_o << "can not read field; current entry is no account entry" << endl;
return;
}
const vector<Field> &fields = static_cast<AccountEntry *>(m_currentEntry)->fields();
bool valuesFound = false;
for (const Field &field : fields) {
@ -554,18 +562,18 @@ void InteractiveCli::readField(const string &fieldName)
if (!valuesFound) {
m_o << "field \"" << fieldName << "\" does not exist" << endl;
}
} else {
m_o << "can not read field; current entry is no account entry" << endl;
}
} else {
m_o << "can not read field; no file open" << endl;
}
}
void InteractiveCli::setField(bool useMuter, const string &fieldName)
{
if (m_file.isOpen()) {
if (m_currentEntry->type() == EntryType::Account) {
if (!m_file.isOpen()) {
m_o << "can not set field; no file open" << endl;
return;
}
if (m_currentEntry->type() != EntryType::Account) {
m_o << "can not set field; current entry is no account entry" << endl;
return;
}
vector<Field> &fields = static_cast<AccountEntry *>(m_currentEntry)->fields();
unsigned int valuesFound = 0;
string value;
@ -626,33 +634,36 @@ void InteractiveCli::setField(bool useMuter, const string &fieldName)
m_o << valuesFound << " values updated" << endl;
m_modified = true;
}
} else {
m_o << "can not set field; current entry is no account entry" << endl;
}
} else {
m_o << "can not set field; no file open" << endl;
}
}
void InteractiveCli::removeField(const string &fieldName)
{
if (m_file.isOpen()) {
if (m_currentEntry->type() == EntryType::Account) {
if (!m_file.isOpen()) {
m_o << "can not remove field; no file open" << endl;
return;
}
if (m_currentEntry->type() != EntryType::Account) {
m_o << "can not remove field; current entry is no account entry" << endl;
return;
}
vector<Field> &fields = static_cast<AccountEntry *>(m_currentEntry)->fields();
unsigned int valuesFound = 0;
for (Field &field : fields) {
for (const Field &field : fields) {
if (field.name() == fieldName) {
++valuesFound;
}
}
switch (valuesFound) {
valuesFound = 0;
case 0:
m_o << "can not remove field; specified field \"" << fieldName << "\" not found" << endl;
break;
case 1:
fields.erase(remove_if(fields.begin(), fields.end(), [&fieldName](Field &field) { return field.name() == fieldName; }));
m_o << "field removed" << endl;
m_modified = true;
break;
default:
valuesFound = 0;
fields.erase(remove_if(fields.begin(), fields.end(), [this, &fieldName, &valuesFound](Field &field) {
if (field.name() == fieldName) {
m_o << "remove " << ++valuesFound << ". occurrence? [y]=yes, different key=no " << endl;
@ -663,25 +674,9 @@ void InteractiveCli::removeField(const string &fieldName)
return false;
}
}));
}
switch (valuesFound) {
case 0:
m_o << "can not remove field; specified field \"" << fieldName << "\" not found" << endl;
break;
case 1:
m_o << "field removed" << endl;
m_modified = true;
break;
default:
m_o << valuesFound << " fields removed" << endl;
m_modified = true;
}
} else {
m_o << "can not remove field; current entry is no account entry" << endl;
}
} else {
m_o << "can not remove field; no file open" << endl;
}
}
void InteractiveCli::printHelp()
@ -742,7 +737,8 @@ string InteractiveCli::askForPassphrase(bool confirm)
m_o << endl;
if (input1.empty()) {
m_o << "you did not enter a passphrase" << endl;
} else {
return input1;
}
if (confirm) {
m_o << "confirm new passphrase: ";
m_o.flush();
@ -757,7 +753,6 @@ string InteractiveCli::askForPassphrase(bool confirm)
throw runtime_error("confirmation failed");
}
}
}
return input1;
}
}

View File

@ -39,8 +39,8 @@
#include <QUndoView>
#include <cassert>
#include <stdexcept>
#include <functional>
#include <stdexcept>
using namespace std;
using namespace IoUtilities;

View File

@ -47,6 +47,7 @@ int main(int argc, char *argv[])
qtConfigArgs.qtWidgetsGuiArg().addSubArgument(&fileArg);
// cli argument
Argument cliArg("interactive-cli", 'i', "starts the interactive command line interface");
cliArg.setDenotesOperation(true);
cliArg.setSubArguments({ &fileArg });
// help argument
HelpArgument helpArg(parser);