Skip to content

Commit

Permalink
vim: Implemented savig, exiting and jumps
Browse files Browse the repository at this point in the history
  • Loading branch information
Petr Laštovička committed May 4, 2022
1 parent f375403 commit 3464c8b
Show file tree
Hide file tree
Showing 15 changed files with 197 additions and 57 deletions.
11 changes: 6 additions & 5 deletions Semestralni_prace/src/cz/lastaapps/vimxel/app.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,16 @@ namespace cz::lastaapps::vimxel {
int App::run(vector<string> args) {
log("App started");
printArgs(args);
string filename = args.size() >= 2 ? args[1] : "";
initNCurses();
try {
log("Loading data");
shared_ptr<table::Table> table = loadTable(args);
shared_ptr<table::Table> table = loadTable(filename);
shared_ptr<table::CellContract> cellContract = table->createCellContract();
shared_ptr<display::State> dState = make_shared<display::State>();

log("Staring parser");
vim::VimParser vim(dState, table, args);
vim::VimParser vim(dState, table, filename);
shared_ptr<vim::VimContract> vimContract = vim.createContract();

log("Setting up display");
Expand Down Expand Up @@ -66,10 +67,10 @@ void App::printArgs(const vector<string> &args) {
mlog << endl;
}

shared_ptr<table::Table> App::loadTable(const vector<string> &args) {
shared_ptr<table::Table> App::loadTable(const string &filename) {
auto table = shared_ptr<table::Table>(new table::Table);
if (args.size() >= 2)
storage::Storage::loadData(args.at(1), table);
if (!filename.empty())
storage::Storage::loadData(filename, table);
return table;
}

Expand Down
2 changes: 1 addition & 1 deletion Semestralni_prace/src/cz/lastaapps/vimxel/app.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ class App final {
int run(vector<string> args);

private:
shared_ptr<table::Table> loadTable(const vector<string> &args);
shared_ptr<table::Table> loadTable(const string &filename);
void printArgs(const vector<string> &args);
void initNCurses();
void destroyNCurses();
Expand Down
5 changes: 3 additions & 2 deletions Semestralni_prace/src/cz/lastaapps/vimxel/storage/storage.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,9 @@ void Storage::saveData(shared_ptr<table::Table> table, const string& path) {
auto size = table->tableSize();
ofstream file;
openFileForWrite(path, file);
for (size_t x = 0; x < size.x(); x++) {
for (size_t y = 0; y < size.y(); y++) {
bool isFirst = true;
for (size_t y = 0; y < size.y(); y++) {
for (size_t x = 0; x < size.x(); x++) {
if (isFirst)
isFirst = false;
else
Expand Down Expand Up @@ -51,6 +51,7 @@ void Storage::loadData(const string& path, shared_ptr<table::Table>& table) {
if (lineEnd) break;
}
}
table -> clearChanged();
}

string Storage::escapeText(const string& str) {
Expand Down
28 changes: 28 additions & 0 deletions Semestralni_prace/src/cz/lastaapps/vimxel/stringUtils.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#ifndef H_STRING_UTILS
#define H_STRING_UTILS
#include <algorithm>
#include <string>

using namespace std;
namespace cz::lastaapps::vimxel {

inline void ltrim(std::string &s) {
s.erase(s.begin(), find_if(s.begin(), s.end(), [](unsigned char ch) {
return !std::isspace(ch);
}));
}

inline void rtrim(std::string &s) {
s.erase(find_if(s.rbegin(), s.rend(), [](unsigned char ch) {
return !std::isspace(ch);
}).base(), s.end());
}

inline void trim(std::string &s) {
ltrim(s);
rtrim(s);
}

} // namespace cz::lastaapps::vimxel

#endif
36 changes: 24 additions & 12 deletions Semestralni_prace/src/cz/lastaapps/vimxel/table/table.cpp
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
#include "table.hpp"
#include "cell.hpp"
#include "../log.hpp"

#include <iostream>
#include <map>
#include <memory>
#include <optional>
#include <string>

#include "../log.hpp"
#include "cell.hpp"

namespace cz::lastaapps::vimxel::table {


// --- Table ------------------------------------------------------------------
const Cell& Table::getCell(const Coordinates& coord) const {
const auto iter = mMap.find(coord);
Expand All @@ -28,16 +27,18 @@ void Table::updateCell(const Coordinates& coord, const Cell& cell) {
mMap.insert_or_assign(coord, unique_ptr<const Cell>(cell.clone()));

updateContracts(coord);
mChanged = true;
}
inline void Table::deleteCell(const Coordinates& coord) {
updateCell(coord, emptyCell);
}
shared_ptr<CellContract> Table::createCellContract() {
class TableCellContract final : public CellContract {
const Table& mT;
public:
TableCellContract(const Table & t) : mT(t) {}
string getDataAt(const Coordinates & coord) const override {

public:
TableCellContract(const Table& t) : mT(t) {}
string getDataAt(const Coordinates& coord) const override {
return mT.getCell(coord).getContent();
}
};
Expand All @@ -53,19 +54,30 @@ void Table::updateContracts(const Coordinates& coord) {
mContracts.erase(mContracts.begin() + i);
i--;
} else {
ptr -> dataUpdatedAt(coord);
ptr->dataUpdatedAt(coord);
}
}
}
Coordinates Table::tableSize() const {
Coordinates biggest;
for (const auto & [key, value] : mMap)
if (key.x() >= biggest.x() && key.y() >= biggest.y())
biggest = key;
return biggest;
size_t maxX = 0, maxY = 0;
for (const auto& [key, value] : mMap) {
if (key.x() > maxX) maxX = key.x();
if (key.y() > maxY) maxY = key.y();
}
return Coordinates(maxX + 1, maxY + 1); // to convert coordinates to size
}
bool Table::isEmpty() const {
return mMap.empty();
}
void Table::eraseAll() {
mMap.erase(mMap.begin(), mMap.end());
mChanged = true;
}
bool Table::changed() const {
return mChanged;
}
void Table::clearChanged() {
mChanged = false;
}

} // namespace cz::lastaapps::vimxel::table
4 changes: 4 additions & 0 deletions Semestralni_prace/src/cz/lastaapps/vimxel/table/table.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ class Table final {
map<Coordinates, unique_ptr<const Cell>> mMap;
EmptyCell emptyCell;
vector<shared_ptr<CellContract>> mContracts;
bool mChanged = false;

public:
Table() = default;
Expand All @@ -26,6 +27,9 @@ class Table final {
shared_ptr<CellContract> createCellContract();
Coordinates tableSize() const;
bool isEmpty() const;
void eraseAll();
bool changed() const;
void clearChanged();

private:
void updateContracts(const Coordinates& coord);
Expand Down
86 changes: 79 additions & 7 deletions Semestralni_prace/src/cz/lastaapps/vimxel/vim/commandParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

#include <ncurses.h>

#include "../storage/storage.hpp"
#include "../stringUtils.hpp"
#include "mode.hpp"

using namespace std;
Expand All @@ -16,13 +18,13 @@ ParserResult CommandParser::handleKey(Mode& outMode) {
if (ch == ERR) return Res::NOPE;

switch (ch) {
case 27: { // ESC
case 27: { // ESC
mCommand = "";
outMode = Mode::NORMAL;
return Res::FINE;
return Res::UPDATE;
}
case KEY_ENTER:
case '\n': { // ENTER
case KEY_ENTER:
case '\n': { // ENTER
Res res = handleCommand();
mCommand = "";
outMode = Mode::NORMAL;
Expand All @@ -31,19 +33,89 @@ ParserResult CommandParser::handleKey(Mode& outMode) {
case KEY_BACKSPACE: {
if (!mCommand.empty())
mCommand.erase(--mCommand.end());
return Res::FINE;
return Res::UPDATE;
}
}
if (' ' <= ch && ch <= '~') {
mCommand += ch;
return Res::FINE;
return Res::UPDATE;
}
return Res::NOPE;
}

ParserResult CommandParser::handleCommand() {
trim(mCommand);
if (mCommand.empty()) return ParserResult::NOPE;
if (mCommand == "q") return ParserResult::QUIT;

{
auto res = tryQuitAndWrite();
if (res != ParserResult::UNKNOWN) return res;
}
{
auto res = tryJump();
if (res != ParserResult::UNKNOWN) return res;
}
return ParserResult::UNKNOWN;
}
ParserResult CommandParser::tryQuitAndWrite() {
mState->mErrorMsg = "No filename specified";
if (mCommand == "q") {
if (mState->mTable->changed()) {
mState->mErrorMsg = "You have unsaved changes";
return ParserResult::ERROR;
} else {
return ParserResult::QUIT;
}
}
if (mCommand == "q!") return ParserResult::QUIT;
if (mCommand == "wq" || mCommand == "w") {
if (mState->mFilename.empty()) return ParserResult::ERROR;
storage::Storage::saveData(mState->mTable, mState->mFilename);
mState->mTable->clearChanged();
if (mCommand == "w")
return ParserResult::UPDATE;
else
return ParserResult::QUIT;
}
auto save = [&](size_t len) -> bool {
string filename = string(mCommand.begin() + len, mCommand.end());
trim(filename);
if (filename.empty()) {
mState -> mErrorMsg = "No filename entered";
return false;
}
if (mState->mFilename == "") mState->mFilename = filename;
storage::Storage::saveData(mState->mTable, filename);
return true;
};
if (mCommand.rfind("w ", 0) == 0) {
return save(2) ? ParserResult::UPDATE : ParserResult::ERROR;
}
if (mCommand.rfind("wq ") == 0) {
return save(3) ? ParserResult::QUIT : ParserResult::ERROR;
}
return ParserResult::UNKNOWN;
}
ParserResult CommandParser::tryJump() {
string letters;
size_t pos = 0;
bool inDigits = false;
for (auto itr = mCommand.begin(); itr != mCommand.end(); ++itr) {
char c = *itr;
if (isdigit(c)) {
inDigits = true;
pos *= 10;
pos += c - '0';
} else if (isalpha(c)) {
if (inDigits) break;
letters += c;
} else
break;
}
if (!letters.empty() && pos > 0) {
mState->mDisplayState->setPosition(table::Coordinates(letters, pos - 1));
return ParserResult::UPDATE;
}
return ParserResult::UNKNOWN;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ class CommandParser final : public AbsParser {
pair<string, size_t> getTextAndPosition() override;
private:
ParserResult handleCommand();
ParserResult tryQuitAndWrite();
ParserResult tryJump();
};
}

Expand Down
18 changes: 9 additions & 9 deletions Semestralni_prace/src/cz/lastaapps/vimxel/vim/insertParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ InsertParser::InsertParser(VimState* state)

ParserResult InsertParser::handleKey(Mode& outMode) {
using Res = ParserResult;
if (checkLoad()) return Res::FINE;
if (checkLoad()) return Res::UPDATE;

int ch = getch();
if (ch == ERR) return Res::NOPE;
Expand All @@ -22,15 +22,15 @@ ParserResult InsertParser::handleKey(Mode& outMode) {
mText = "";
mCursor = (size_t)-1;
outMode = Mode::NORMAL;
return Res::FINE;
return Res::UPDATE;
}
case KEY_ENTER:
case '\n': { // ENTER
saveContent();
mText = "";
mCursor = (size_t)-1;
outMode = Mode::NORMAL;
return Res::FINE;
return Res::UPDATE;
}
case KEY_BACKSPACE: {
if (!mText.empty()) {
Expand All @@ -40,29 +40,29 @@ ParserResult InsertParser::handleKey(Mode& outMode) {
} else
mText.erase(mText.begin());
}
return Res::FINE;
return Res::UPDATE;
}
case KEY_LEFT:{
if (mCursor != 0) mCursor --;
return Res::FINE;
return Res::UPDATE;
}
case KEY_RIGHT:{
if (mCursor < mText.length()) mCursor ++;
return Res::FINE;
return Res::UPDATE;
}
case KEY_UP:{
mCursor = 0;
return Res::FINE;
return Res::UPDATE;
}
case KEY_DOWN:{
mCursor = mText.length();
return Res::FINE;
return Res::UPDATE;
}
}
if (' ' <= ch && ch <= '~') {
mText.insert(mText.begin() + mCursor, ch);
mCursor++;
return Res::FINE;
return Res::UPDATE;
}
return Res::NOPE;
}
Expand Down
Loading

0 comments on commit 3464c8b

Please sign in to comment.