Skip to content

Commit

Permalink
Now the vim test runs
Browse files Browse the repository at this point in the history
  • Loading branch information
mls-m5 committed Nov 13, 2023
1 parent 2a3b6c4 commit 93a2b13
Show file tree
Hide file tree
Showing 6 changed files with 128 additions and 21 deletions.
2 changes: 2 additions & 0 deletions src/modes/normalmode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ std::shared_ptr<IMode> createNormalMode() {
{{"s"}, sc.combine(sc.erase_after, sc.insert_mode)},
{{">"}, {sc.indent}},
{{"<"}, {sc.deindent}},

{{"D"}, {sc.erase_until_end_of_line}},
},
};

Expand Down
21 changes: 21 additions & 0 deletions src/script/standardcommands.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,16 @@ StandardCommands create() {
commands.namedCommands[#name] = \
commands.name = [=](StandardCommands::EnvPtrT env)

// Repeat the command specified number of times
#define REPEAT \
size_t NUM_REPEATS = numRepeats(env); \
for (size_t i = 0; i < NUM_REPEATS; ++i)

// Repeat minus one time
#define REPEAT_M1 \
size_t NUM_REPEATS = numRepeats(env); \
for (size_t i = 1; i < NUM_REPEATS; ++i)

StandardCommands commands{};
DEF(left) {
auto &e = env->editor();
Expand Down Expand Up @@ -244,6 +250,19 @@ StandardCommands create() {
}
};

DEF(erase_until_end_of_line) {
auto &e = env->editor();
auto cursor = e.cursor();
auto end = cursor;

REPEAT_M1 {
end.y(end.y() + 1);
}

end = ::end(end);
erase({cursor, end});
};

DEF(paste_before) {
auto str = env->registers().load(standardRegister);
REPEAT {
Expand Down Expand Up @@ -466,6 +485,8 @@ StandardCommands create() {

#undef MAP_DEBUG
#undef DEF
#undef REPEAT
#undef REPEAT_M1

return commands;
}
Expand Down
1 change: 1 addition & 0 deletions src/script/standardcommands.h
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
STD_DEF(erase) \
STD_DEF(erase_after) \
STD_DEF(erase_before_word) \
STD_DEF(erase_until_end_of_line) \
STD_DEF(paste_before) \
STD_DEF(paste) \
STD_DEF(join) \
Expand Down
6 changes: 6 additions & 0 deletions src/text/position.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#pragma once

#include <cstddef>
#include <ostream>

class Position {
private:
Expand Down Expand Up @@ -68,3 +69,8 @@ class Position {
return *this;
}
};

inline std::ostream &operator<<(std::ostream &stream,
const Position &position) {
return stream << "(" << position.x() << ", " << position.y() << ")";
}
11 changes: 10 additions & 1 deletion test/res/vimtest.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,14 +17,16 @@ hello [N-dw]there you
hello [N]you
```

## TODO: dw on end of line does not seem to work

```
hello [N-dw]there
----
hello [N]
```


## cw
## TODO: cw

```
hello [N-cw]there
Expand All @@ -47,4 +49,11 @@ hello [N-D]there you
hello [N]
```

```
hello [N-2D]there you
another line that should be removed
----
hello [N]
```


108 changes: 88 additions & 20 deletions test/vim_test.cpp
Original file line number Diff line number Diff line change
@@ -1,22 +1,35 @@
/*
* Scripted tests. The tests are loaded from a file
* */
#include "core/registers.h"
#include "keys/event.h"
#include "mls-unit-test/unittest.h"
#include "mock/script/mockenvironment.h"
#include "modes/normalmode.h"
#include "script/ienvironment.h"
#include "script/standardcommands.h"
#include "text/buffer.h"
#include "text/cursorrangeops.h"
#include "text/position.h"
#include "views/editor.h"
#include <fstream>
#include <iterator>
#include <memory>
#include <regex>
#include <sstream>
#include <stdexcept>
#include <string>
#include <vector>

namespace {

static const auto vimPartCommandRegex = std::regex{R"(\[([A-Z])(\-(.*))?\])"};
// static const auto vimPartCommandRegex = std::regex{R"(N)"};

} // namespace

struct VimCodePart : public std::string {
std::string input;
std::string mode;
std::string command;
Position position;
Expand All @@ -28,8 +41,21 @@ struct VimCodePart : public std::string {
if (back() == '\n') {
pop_back();
}
input = *this;

auto match = std::smatch{};
if (std::regex_search(*this, match, vimPartCommandRegex)) {
// std::cout << "match " << match.str() << std::endl;

command = match[3];
mode = match[1];

// TODO: Handle newlines
position.x(match.position());

// TODO: Handle mode, position etc
// erase(match[0].first, match[0].second);
erase(match.position(), match[0].str().size());
}
}
};

Expand Down Expand Up @@ -90,24 +116,25 @@ std::vector<VimTest> loadVimTests() {
return ret;
}

// struct Environment: public MockEnvironment {
// using MockEnvironment::MockEnvironment;

// std::
//};

std::shared_ptr<MockEnvironment> createMockEnvironment() {

auto env = std::make_unique<MockEnvironment>();
createNormalMode();

env->mock_standardCommands_0.returnValueRef(StandardCommands::get());
env->mock_statusMessage_1.onCall(
[](auto msg) { std::cout << msg << "\n"; });

return env;
}

void emulateKeyPress(MockEnvironment &env, std::shared_ptr<std::string> keys) {
env.mock_key_0.onCall([keys]() {
if (keys->empty()) {
throw std::runtime_error{"out of keys"};
}
else {
auto c = keys->front();
keys->erase(0, 1);
return KeyEvent{Key::Text,
c}; // Dummy event, this should not happend
}
});
void emulateKeyPress(MockEnvironment &env, char c) {
env.mock_key_0.onCall([c]() { return KeyEvent{Key::Text, c}; });
}

struct TestSuitVim : public unittest::StaticTestSuit {
Expand All @@ -116,22 +143,63 @@ struct TestSuitVim : public unittest::StaticTestSuit {
unittest::testResult = &this->testResult;

for (auto &test : loadVimTests()) {
newTest(test.name) = [tests = test.tests]() {
newTest(test.name) = [name = test.name, tests = test.tests]() {
if (name.find("TODO") != std::string::npos) {
std::cout << "Test or tested code is not implemented yet"
<< std::endl;
return;
}
for (auto &test : tests) {

if (test.empty()) {
continue;
}

Registers registers;

auto env = createMockEnvironment();
env->mock_registers_0.returnValueRef(registers);

auto buffer = std::make_shared<Buffer>(test.front());
auto editor = Editor{nullptr, buffer};

editor.cursor(test.front().position);

env->mock_editor_0.returnValueRef(editor);

std::cout << "should run:\n";
std::cout << "code:\n";

auto result = std::string{};

for (auto &part : test) {
auto keys = std::make_shared<std::string>(part.command);
emulateKeyPress(*env, keys);
editor.keyPress(env);
std::cout << "part:" << part << "\n";
std::cout << "raw: \n'''" << part.input << "'''\n";
std::cout << "part:\n'''" << part << "'''\n";
std::cout << "command: " << part.command << "\n";
std::cout << "mode: " << part.mode << "\n";
std::cout << "pos: " << part.position.x() << ", "
<< part.position.y() << "\n";

if (!result.empty()) {
std::cout << "resulting text from previous:\n'''";
std::cout << result << "'''" << std::endl;
std::cout << "resulting pos: " << editor.cursor()
<< std::endl;

EXPECT_EQ(part, result);
EXPECT_EQ(part.position, editor.cursor());
}

auto keys = part.command;
editor.cursor(part.position);

while (!keys.empty()) {
emulateKeyPress(*env, keys.front());
editor.keyPress(env);
keys.erase(0, 1);
}

result = content({buffer->begin(), buffer->end()});
std::cout << "\n";
}
std::cout.flush();
}
Expand Down

0 comments on commit 93a2b13

Please sign in to comment.