| Line | Branch | Exec | Source |
|---|---|---|---|
| 1 | #include "test.h" | ||
| 2 | #include "bind.h" | ||
| 3 | #include "block.h" | ||
| 4 | #include "change.h" | ||
| 5 | #include "command/args.h" | ||
| 6 | #include "commands.h" | ||
| 7 | #include "editor.h" | ||
| 8 | |||
| 9 | 1 | static void test_add_binding(TestContext *ctx) | |
| 10 | { | ||
| 11 | 1 | EditorState *e = ctx->userdata; | |
| 12 | // TODO: Use a temporary IntMap, instead of normal mode bindings? | ||
| 13 | 1 | IntMap *bindings = &e->normal_mode->key_bindings; | |
| 14 | 1 | KeyCode key = MOD_CTRL | MOD_SHIFT | KEY_F12; | |
| 15 | 1 | const CachedCommand *bind = lookup_binding(bindings, key); | |
| 16 | 1 | EXPECT_NULL(bind); | |
| 17 | |||
| 18 | 1 | const Command *insert_cmd = find_normal_command("insert"); | |
| 19 | 1 | ASSERT_NONNULL(insert_cmd); | |
| 20 | |||
| 21 | 1 | static const char cmd_str[] = "insert xyz"; | |
| 22 | 1 | CommandRunner runner = normal_mode_cmdrunner(e); | |
| 23 | 1 | CachedCommand *cc = cached_command_new(&runner, cmd_str); | |
| 24 | 1 | ASSERT_NONNULL(cc); | |
| 25 | |||
| 26 | 1 | add_binding(bindings, key, cc); | |
| 27 | 1 | bind = lookup_binding(bindings, key); | |
| 28 | 1 | ASSERT_NONNULL(bind); | |
| 29 | 1 | EXPECT_PTREQ(bind->cmd, insert_cmd); | |
| 30 | 1 | EXPECT_EQ(bind->a.nr_args, 1); | |
| 31 | 1 | EXPECT_EQ(bind->a.nr_flags, 0); | |
| 32 | 1 | EXPECT_STREQ(bind->cmd_str, cmd_str); | |
| 33 | |||
| 34 | 1 | remove_binding(bindings, key); | |
| 35 | 1 | EXPECT_NULL(lookup_binding(bindings, key)); | |
| 36 | 1 | } | |
| 37 | |||
| 38 | 1 | static void test_handle_binding(TestContext *ctx) | |
| 39 | { | ||
| 40 | 1 | const Command *insert = find_normal_command("insert"); | |
| 41 | 1 | ASSERT_NONNULL(insert); | |
| 42 | |||
| 43 | 1 | EditorState *e = ctx->userdata; | |
| 44 | 1 | EXPECT_TRUE(handle_normal_command(e, "open; bind C-S-F11 'insert -m zzz'", false)); | |
| 45 | |||
| 46 | // Bound command should be cached | ||
| 47 | 1 | const ModeHandler *mode = e->normal_mode; | |
| 48 | 1 | const IntMap *bindings = &mode->key_bindings; | |
| 49 | 1 | KeyCode key = MOD_CTRL | MOD_SHIFT | KEY_F11; | |
| 50 | 1 | const CachedCommand *binding = lookup_binding(bindings, key); | |
| 51 | 1 | ASSERT_NONNULL(binding); | |
| 52 | 1 | EXPECT_PTREQ(binding->cmd, insert); | |
| 53 | 1 | EXPECT_EQ(binding->a.nr_flags, 1); | |
| 54 | 1 | EXPECT_EQ(binding->a.nr_args, 1); | |
| 55 | 1 | EXPECT_STREQ(binding->a.args[0], "zzz"); | |
| 56 | 1 | EXPECT_NULL(binding->a.args[1]); | |
| 57 | 1 | EXPECT_EQ(binding->a.flags[0], 'm'); | |
| 58 | 1 | EXPECT_EQ(binding->a.flags[1], '\0'); | |
| 59 | 1 | EXPECT_TRUE(cmdargs_has_flag(&binding->a, 'm')); | |
| 60 | |||
| 61 | 1 | ASSERT_TRUE(handle_binding(e, mode, key)); | |
| 62 | 1 | const Block *block = BLOCK(e->buffer->blocks.next); | |
| 63 | 1 | ASSERT_NONNULL(block); | |
| 64 | 1 | EXPECT_MEMEQ(block->data, block->size, "zzz\n", 4); | |
| 65 | 1 | EXPECT_EQ(block->nl, 1); | |
| 66 | |||
| 67 | 1 | ASSERT_TRUE(handle_binding(e, mode, KEY_BACKSPACE)); | |
| 68 | 1 | EXPECT_MEMEQ(block->data, block->size, "zz\n", 3); | |
| 69 | 1 | EXPECT_EQ(block->nl, 1); | |
| 70 | |||
| 71 | 1 | ASSERT_TRUE(handle_binding(e, mode, MOD_CTRL | KEY_BACKSPACE)); | |
| 72 | 1 | EXPECT_MEMEQ(block->data, block->size, "\n", 1); | |
| 73 | 1 | EXPECT_EQ(block->nl, 1); | |
| 74 | |||
| 75 | 1 | View *view = e->view; | |
| 76 | 1 | ASSERT_NONNULL(view); | |
| 77 | 1 | EXPECT_TRUE(undo(view)); | |
| 78 | 1 | ASSERT_EQ(block->size, 3); | |
| 79 | 1 | EXPECT_TRUE(undo(view)); | |
| 80 | 1 | ASSERT_EQ(block->size, 4); | |
| 81 | 1 | EXPECT_TRUE(undo(view)); | |
| 82 | 1 | EXPECT_EQ(block->size, 0); | |
| 83 | 1 | EXPECT_EQ(block->nl, 0); | |
| 84 | 1 | EXPECT_FALSE(undo(view)); | |
| 85 | 1 | EXPECT_TRUE(handle_normal_command(e, "close", false)); | |
| 86 | 1 | } | |
| 87 | |||
| 88 | static const TestEntry tests[] = { | ||
| 89 | TEST(test_add_binding), | ||
| 90 | TEST(test_handle_binding), | ||
| 91 | }; | ||
| 92 | |||
| 93 | const TestGroup bind_tests = TEST_GROUP(tests); | ||
| 94 |