xaizek / vifm (License: GPLv2+) (since 2018-12-07)
Vifm is a file manager with curses interface, which provides Vi[m]-like environment for managing objects within file systems, extended with some useful ideas from mutt.
Commit 2baf12a7cf14ae13eaa5077237cffd97b2e03ce7

Support description of user keys in engine/keys
While at it, make sure return value of vle_keys_user_add() is asserted
in tests to be a success.
Author: xaizek
Author date (UTC): 2025-06-13 21:27
Committer name: xaizek
Committer date (UTC): 2025-06-14 08:36
Parent(s): d84f9c96d4e871fd5c588bbc4145ec01457830ad
Signing key: 99DC5E4DB05F6BE2
Tree: 9f8096c3ee9c423e44c19f6653a2bc27d58d305e
File Lines added Lines deleted
src/cmd_handlers.c 1 1
src/engine/keys.c 27 6
src/engine/keys.h 7 6
tests/fuzz/suite.c 4 2
tests/keys/multi_keys.c 3 3
tests/keys/noremap.c 6 3
tests/keys/silent.c 2 1
tests/keys/suggestions.c 14 1
tests/keys/suite.c 1 1
tests/keys/wait.c 2 1
tests/lua/api_keys.c 1 1
tests/misc/cmdline_history.c 16 8
tests/misc/event_loop.c 4 2
File src/cmd_handlers.c changed (mode: 100644) (index 33934813f..f945afbee)
... ... do_map(const cmd_info_t *cmd_info, const char map_type[], int mode,
5418 5418 wchar_t *mapping = substitute_specs(rhs); wchar_t *mapping = substitute_specs(rhs);
5419 5419 if(keys != NULL && mapping != NULL) if(keys != NULL && mapping != NULL)
5420 5420 { {
5421 if(vle_keys_user_add(keys, mapping, mode, flags) != 0)
5421 if(vle_keys_user_add(keys, mapping, /*descr=*/NULL, mode, flags) != 0)
5422 5422 { {
5423 5423 show_error_msg("Mapping Error", "Unable to allocate enough memory"); show_error_msg("Mapping Error", "Unable to allocate enough memory");
5424 5424 } }
File src/engine/keys.c changed (mode: 100644) (index 1c1d49df6..70276be75)
... ... free_chunk_data(key_chunk_t *chunk)
306 306 free(chunk->conf.data.cmd); free(chunk->conf.data.cmd);
307 307 } }
308 308
309 if(chunk->foreign)
309 if(chunk->type == USER_CMD || chunk->foreign)
310 310 { {
311 311 free((char *)chunk->conf.descr); free((char *)chunk->conf.descr);
312 312 } }
 
... ... vle_keys_foreign_add(const wchar_t lhs[], const key_conf_t *info,
1045 1045 } }
1046 1046
1047 1047 int int
1048 vle_keys_user_add(const wchar_t lhs[], const wchar_t rhs[], int mode,
1049 int flags)
1048 vle_keys_user_add(const wchar_t keys[], const wchar_t rhs[], const char descr[],
1049 int mode, int flags)
1050 1050 { {
1051 key_chunk_t *curr = add_keys_inner(&user_cmds_root[mode], lhs);
1051 wchar_t *rhs_copy = vifm_wcsdup(rhs);
1052 if(rhs_copy == NULL)
1053 {
1054 return -1;
1055 }
1056
1057 char *descr_copy = NULL;
1058 if(descr != NULL)
1059 {
1060 descr_copy = strdup(descr);
1061 if(descr_copy == NULL)
1062 {
1063 free(rhs_copy);
1064 return -1;
1065 }
1066 }
1067
1068 key_chunk_t *curr = add_keys_inner(&user_cmds_root[mode], keys);
1052 1069 if(curr == NULL) if(curr == NULL)
1053 1070 { {
1071 free(rhs_copy);
1072 free(descr_copy);
1054 1073 return -1; return -1;
1055 1074 } }
1056 1075
1057 1076 curr->type = USER_CMD; curr->type = USER_CMD;
1058 curr->conf.data.cmd = vifm_wcsdup(rhs);
1077 curr->conf.descr = descr_copy;
1078 curr->conf.data.cmd = rhs_copy;
1059 1079 curr->no_remap = ((flags & KEYS_FLAG_NOREMAP) != 0); curr->no_remap = ((flags & KEYS_FLAG_NOREMAP) != 0);
1060 1080 curr->silent = ((flags & KEYS_FLAG_SILENT) != 0); curr->silent = ((flags & KEYS_FLAG_SILENT) != 0);
1061 1081 curr->wait = ((flags & KEYS_FLAG_WAIT) != 0); curr->wait = ((flags & KEYS_FLAG_WAIT) != 0);
 
... ... suggest_chunk(const key_chunk_t *chunk, const wchar_t lhs[], void *arg)
1558 1578
1559 1579 if(chunk->type == USER_CMD) if(chunk->type == USER_CMD)
1560 1580 { {
1561 cb(lhs, chunk->conf.data.cmd, "");
1581 cb(lhs, chunk->conf.data.cmd,
1582 (chunk->conf.descr == NULL) ? "" : chunk->conf.descr);
1562 1583 } }
1563 1584 else if(chunk->children_count == 0 || else if(chunk->children_count == 0 ||
1564 1585 chunk->conf.followed != FOLLOWED_BY_NONE) chunk->conf.followed != FOLLOWED_BY_NONE)
File src/engine/keys.h changed (mode: 100644) (index 1d1a0ec5e..8c3533932)
... ... keys_info_t;
99 99 typedef void (*vle_keys_handler)(key_info_t key_info, keys_info_t *keys_info); typedef void (*vle_keys_handler)(key_info_t key_info, keys_info_t *keys_info);
100 100 /* Type of function invoked by vle_keys_list() and vle_keys_suggest(). rhs is /* Type of function invoked by vle_keys_list() and vle_keys_suggest(). rhs is
101 101 * provided for user-defined keys and is empty otherwise. Description is empty * provided for user-defined keys and is empty otherwise. Description is empty
102 * for user-defined keys or when not set. Extra messages have empty lhs and
103 * rhs, but can have non-empty description. */
102 * when unset. Extra messages have empty lhs and rhs, but can have non-empty
103 * description. */
104 104 typedef void (*vle_keys_list_cb)(const wchar_t lhs[], const wchar_t rhs[], typedef void (*vle_keys_list_cb)(const wchar_t lhs[], const wchar_t rhs[],
105 105 const char descr[]); const char descr[]);
106 106 /* User-provided suggestion callback for multikeys. */ /* User-provided suggestion callback for multikeys. */
 
... ... typedef struct
130 130 vle_suggest_func suggest; /* Suggestion function (can be NULL). Invoked for vle_suggest_func suggest; /* Suggestion function (can be NULL). Invoked for
131 131 multikeys. */ multikeys. */
132 132 const char *descr; /* Brief description of the key (can be NULL). const char *descr; /* Brief description of the key (can be NULL).
133 Not a literal for foreign keys, but needs
133 Not a literal for user or foreign keys, but needs
134 134 to be `const` for arrays of builtin keys. */ to be `const` for arrays of builtin keys. */
135 135 void *user_data; /* User data for the key (can be NULL). */ void *user_data; /* User data for the key (can be NULL). */
136 136 } }
 
... ... int vle_keys_foreign_add(const wchar_t lhs[], const key_conf_t *info,
189 189 int is_selector, int mode); int is_selector, int mode);
190 190
191 191 /* Registers user key mapping. The flags parameter accepts combinations of /* Registers user key mapping. The flags parameter accepts combinations of
192 * KEYS_FLAG_*. Returns non-zero or error, otherwise zero is returned. */
193 int vle_keys_user_add(const wchar_t keys[], const wchar_t rhs[], int mode,
194 int flags);
192 * KEYS_FLAG_*. The descr parameter can be NULL. Returns non-zero or error,
193 * otherwise zero is returned. */
194 int vle_keys_user_add(const wchar_t keys[], const wchar_t rhs[],
195 const char descr[], int mode, int flags);
195 196
196 197 /* Checks whether given user mapping exists. Returns non-zero if so, otherwise /* Checks whether given user mapping exists. Returns non-zero if so, otherwise
197 198 * zero is returned. */ * zero is returned. */
File tests/fuzz/suite.c changed (mode: 100644) (index 06821b34e..a70996824)
... ... fuzz_keys(const char input[])
188 188 vle_keys_exec_timed_out(winput); vle_keys_exec_timed_out(winput);
189 189 vle_keys_exec_timed_out_no_remap(winput); vle_keys_exec_timed_out_no_remap(winput);
190 190 vle_keys_user_exists(winput, 0); vle_keys_user_exists(winput, 0);
191 vle_keys_user_add(winput, winput, 0, KEYS_FLAG_NOREMAP);
191 assert_success(vle_keys_user_add(winput, winput, "descr", 0,
192 KEYS_FLAG_NOREMAP));
192 193 vle_keys_user_exists(winput, 0); vle_keys_user_exists(winput, 0);
193 194 vle_keys_user_remove(winput, 0); vle_keys_user_remove(winput, 0);
194 195
 
... ... fuzz_keys(const char input[])
198 199 vle_keys_exec_timed_out(winput); vle_keys_exec_timed_out(winput);
199 200 vle_keys_exec_timed_out_no_remap(winput); vle_keys_exec_timed_out_no_remap(winput);
200 201 vle_keys_user_exists(winput, 1); vle_keys_user_exists(winput, 1);
201 vle_keys_user_add(winput, winput, 1, KEYS_FLAG_NOREMAP);
202 assert_success(vle_keys_user_add(winput, winput, "descr", 1,
203 KEYS_FLAG_NOREMAP));
202 204 vle_keys_user_exists(winput, 1); vle_keys_user_exists(winput, 1);
203 205 vle_keys_user_remove(winput, 1); vle_keys_user_remove(winput, 1);
204 206
File tests/keys/multi_keys.c changed (mode: 100644) (index 3ee0362cf..aac59aa4a)
... ... TEST(cancel_on_ctrl_c_and_escape)
28 28
29 29 TEST(rhs_multikeys_only) TEST(rhs_multikeys_only)
30 30 { {
31 assert_success(vle_keys_user_add(L"a", L"mg", NORMAL_MODE,
31 assert_success(vle_keys_user_add(L"a", L"mg", "descr", NORMAL_MODE,
32 32 KEYS_FLAG_NOREMAP)); KEYS_FLAG_NOREMAP));
33 33 assert_success(vle_keys_exec(L"a")); assert_success(vle_keys_exec(L"a"));
34 34 } }
35 35
36 36 TEST(rhs_multikeys_and_full_command) TEST(rhs_multikeys_and_full_command)
37 37 { {
38 assert_success(vle_keys_user_add(L"b", L"mbj", NORMAL_MODE,
38 assert_success(vle_keys_user_add(L"b", L"mbj", "descr", NORMAL_MODE,
39 39 KEYS_FLAG_NOREMAP)); KEYS_FLAG_NOREMAP));
40 40 last = 0; last = 0;
41 41 assert_success(vle_keys_exec(L"b")); assert_success(vle_keys_exec(L"b"));
 
... ... TEST(rhs_multikeys_and_full_command)
44 44
45 45 TEST(rhs_multikeys_and_partial_command) TEST(rhs_multikeys_and_partial_command)
46 46 { {
47 assert_success(vle_keys_user_add(L"b", L"mbg", NORMAL_MODE,
47 assert_success(vle_keys_user_add(L"b", L"mbg", "descr", NORMAL_MODE,
48 48 KEYS_FLAG_NOREMAP)); KEYS_FLAG_NOREMAP));
49 49 last = 0; last = 0;
50 50 assert_true(IS_KEYS_RET_CODE(vle_keys_exec(L"b"))); assert_true(IS_KEYS_RET_CODE(vle_keys_exec(L"b")));
File tests/keys/noremap.c changed (mode: 100644) (index c7ed03985..f298791e0)
... ... TEST(with_noremap)
34 34
35 35 assert_success(set_user_key(L"j", L"k", NORMAL_MODE)); assert_success(set_user_key(L"j", L"k", NORMAL_MODE));
36 36 assert_success(set_user_key(L"q", L"j", NORMAL_MODE)); assert_success(set_user_key(L"q", L"j", NORMAL_MODE));
37 assert_success(vle_keys_user_add(L"q", L"j", NORMAL_MODE, KEYS_FLAG_NOREMAP));
37 assert_success(vle_keys_user_add(L"q", L"j", "descr", NORMAL_MODE,
38 KEYS_FLAG_NOREMAP));
38 39
39 40 assert_int_equal(0, vle_keys_exec(L"j")); assert_int_equal(0, vle_keys_exec(L"j"));
40 41 assert_int_equal(1, last); assert_int_equal(1, last);
 
... ... TEST(noremap_functions)
56 57
57 58 TEST(remap_selector_waitpoint) TEST(remap_selector_waitpoint)
58 59 { {
59 assert_success(vle_keys_user_add(L"y", L"d", NORMAL_MODE, KEYS_FLAG_NOREMAP));
60 assert_success(vle_keys_user_add(L"y", L"d", "descr", NORMAL_MODE,
61 KEYS_FLAG_NOREMAP));
60 62
61 63 last = -1; last = -1;
62 64 assert_false(IS_KEYS_RET_CODE(vle_keys_exec(L"yj"))); assert_false(IS_KEYS_RET_CODE(vle_keys_exec(L"yj")));
 
... ... TEST(remap_selector_waitpoint)
70 72 assert_false(IS_KEYS_RET_CODE(vle_keys_exec(L"2yk"))); assert_false(IS_KEYS_RET_CODE(vle_keys_exec(L"2yk")));
71 73 assert_int_equal(4, last); assert_int_equal(4, last);
72 74
73 assert_success(vle_keys_user_add(L"z", L"d", NORMAL_MODE, KEYS_FLAG_NOREMAP));
75 assert_success(vle_keys_user_add(L"z", L"d", "descr", NORMAL_MODE,
76 KEYS_FLAG_NOREMAP));
74 77
75 78 last = -1; last = -1;
76 79 assert_false(IS_KEYS_RET_CODE(vle_keys_exec(L"zj"))); assert_false(IS_KEYS_RET_CODE(vle_keys_exec(L"zj")));
File tests/keys/silent.c changed (mode: 100644) (index 4708d48c5..6f5bd710a)
... ... TEST(removing_user_mapping_from_a_mapping_is_fine)
27 27 vle_keys_add(&keys, 1U, NORMAL_MODE); vle_keys_add(&keys, 1U, NORMAL_MODE);
28 28
29 29 assert_int_equal(0, silence); assert_int_equal(0, silence);
30 assert_success(vle_keys_user_add(L"a", L"x", NORMAL_MODE, KEYS_FLAG_SILENT));
30 assert_success(vle_keys_user_add(L"a", L"x", "descr", NORMAL_MODE,
31 KEYS_FLAG_SILENT));
31 32 assert_false(IS_KEYS_RET_CODE(vle_keys_exec(L"a"))); assert_false(IS_KEYS_RET_CODE(vle_keys_exec(L"a")));
32 33 assert_int_equal(0, silence); assert_int_equal(0, silence);
33 34 } }
File tests/keys/suggestions.c changed (mode: 100644) (index 9f7795578..b1f1abfcf)
... ... SETUP()
24 24 assert_success(set_user_key(L"ha2", L"ho", NORMAL_MODE)); assert_success(set_user_key(L"ha2", L"ho", NORMAL_MODE));
25 25
26 26 nsuggestions = 0; nsuggestions = 0;
27 rhs = NULL;
27 28 descr = NULL; descr = NULL;
28 29 } }
29 30
 
... ... TEST(suggestions_after_user_mapped_builtin_prefix)
116 117
117 118 TEST(suggestions_after_user_noremapped_builtin_prefix) TEST(suggestions_after_user_noremapped_builtin_prefix)
118 119 { {
119 assert_success(vle_keys_user_add(L"x", L"g", NORMAL_MODE, KEYS_FLAG_NOREMAP));
120 assert_success(vle_keys_user_add(L"x", L"g", "descr", NORMAL_MODE,
121 KEYS_FLAG_NOREMAP));
120 122
121 123 vle_keys_suggest(L"x", &process_suggestion, 0, 0); vle_keys_suggest(L"x", &process_suggestion, 0, 0);
122 124 assert_int_equal(3, nsuggestions); assert_int_equal(3, nsuggestions);
 
... ... TEST(suggestions_on_common_selector_or_command_prefix)
133 135 assert_string_equal("", descr); assert_string_equal("", descr);
134 136 } }
135 137
138 TEST(user_help_message_is_used_as_a_description)
139 {
140 assert_success(vle_keys_user_add(L"hx", L"G", "hx help", NORMAL_MODE,
141 KEYS_FLAG_NONE));
142
143 vle_keys_suggest(L"h", &process_suggestion, 0, 0);
144 assert_int_equal(5, nsuggestions);
145 assert_wstring_equal(L"G", rhs);
146 assert_string_equal("hx help", descr);
147 }
148
136 149 static void static void
137 150 process_suggestion(const wchar_t lhs[], const wchar_t r[], const char d[]) process_suggestion(const wchar_t lhs[], const wchar_t r[], const char d[])
138 151 { {
File tests/keys/suite.c changed (mode: 100644) (index 50ac3affd..c7fe39c69)
... ... TEARDOWN()
38 38 int int
39 39 set_user_key(const wchar_t keys[], const wchar_t rhs[], int mode) set_user_key(const wchar_t keys[], const wchar_t rhs[], int mode)
40 40 { {
41 return vle_keys_user_add(keys, rhs, mode, KEYS_FLAG_NONE);
41 return vle_keys_user_add(keys, rhs, /*descr=*/"", mode, KEYS_FLAG_NONE);
42 42 } }
43 43
44 44 /* vim: set tabstop=2 softtabstop=2 shiftwidth=2 noexpandtab cinoptions-=(0: */ /* vim: set tabstop=2 softtabstop=2 shiftwidth=2 noexpandtab cinoptions-=(0: */
File tests/keys/wait.c changed (mode: 100644) (index 2c81cea31..a3481aece)
... ... TEST(wait_flag_turns_short_wait_into_wait)
9 9 { {
10 10 assert_success(set_user_key(L"vj", L"j", NORMAL_MODE)); assert_success(set_user_key(L"vj", L"j", NORMAL_MODE));
11 11 assert_int_equal(KEYS_WAIT_SHORT, vle_keys_exec(L"v")); assert_int_equal(KEYS_WAIT_SHORT, vle_keys_exec(L"v"));
12 assert_success(vle_keys_user_add(L"vj", L"j", NORMAL_MODE, KEYS_FLAG_WAIT));
12 assert_success(vle_keys_user_add(L"vj", L"j", "descr", NORMAL_MODE,
13 KEYS_FLAG_WAIT));
13 14 assert_int_equal(KEYS_WAIT, vle_keys_exec(L"v")); assert_int_equal(KEYS_WAIT, vle_keys_exec(L"v"));
14 15 assert_success(set_user_key(L"vj", L"j", NORMAL_MODE)); assert_success(set_user_key(L"vj", L"j", NORMAL_MODE));
15 16 assert_int_equal(KEYS_WAIT_SHORT, vle_keys_exec(L"v")); assert_int_equal(KEYS_WAIT_SHORT, vle_keys_exec(L"v"));
File tests/lua/api_keys.c changed (mode: 100644) (index 4a1ae9874..0f710e51f)
... ... TEST(keys_add)
231 231 "end"); "end");
232 232
233 233 /* Create a mapping. */ /* Create a mapping. */
234 assert_success(vle_keys_user_add(L"X", L"x", NORMAL_MODE, 0));
234 assert_success(vle_keys_user_add(L"X", L"x", "descr", NORMAL_MODE, 0));
235 235
236 236 /* Replace a mapping. */ /* Replace a mapping. */
237 237 GLUA_EQ(vlua, "true", GLUA_EQ(vlua, "true",
File tests/misc/cmdline_history.c changed (mode: 100644) (index dc4a29f38..fab3d2788)
... ... TEST(entry_matching_input_is_skipped)
82 82
83 83 TEST(entering_and_leaving_via_the_same_mapping_skips_cmdline_history) TEST(entering_and_leaving_via_the_same_mapping_skips_cmdline_history)
84 84 { {
85 vle_keys_user_add(L"x", L":cmd" WK_CR, NORMAL_MODE, KEYS_FLAG_NONE);
85 assert_success(vle_keys_user_add(L"x", L":cmd" WK_CR, "descr", NORMAL_MODE,
86 KEYS_FLAG_NONE));
86 87 assert_false(IS_KEYS_RET_CODE(vle_keys_exec_timed_out(L"x"))); assert_false(IS_KEYS_RET_CODE(vle_keys_exec_timed_out(L"x")));
87 88 assert_true(hist_is_empty(&curr_stats.cmd_hist)); assert_true(hist_is_empty(&curr_stats.cmd_hist));
88 89
89 vle_keys_user_add(L"x", L"/spattern" WK_CR, NORMAL_MODE, KEYS_FLAG_NONE);
90 assert_success(vle_keys_user_add(L"x", L"/spattern" WK_CR, "descr",
91 NORMAL_MODE, KEYS_FLAG_NONE));
90 92 assert_false(IS_KEYS_RET_CODE(vle_keys_exec_timed_out(L"x"))); assert_false(IS_KEYS_RET_CODE(vle_keys_exec_timed_out(L"x")));
91 93 assert_false(hist_is_empty(&curr_stats.search_hist)); assert_false(hist_is_empty(&curr_stats.search_hist));
92 94
93 vle_keys_user_add(L"x", L"=fpattern" WK_CR, NORMAL_MODE, KEYS_FLAG_NONE);
95 assert_success(vle_keys_user_add(L"x", L"=fpattern" WK_CR, "descr",
96 NORMAL_MODE, KEYS_FLAG_NONE));
94 97 assert_false(IS_KEYS_RET_CODE(vle_keys_exec_timed_out(L"x"))); assert_false(IS_KEYS_RET_CODE(vle_keys_exec_timed_out(L"x")));
95 98 assert_false(hist_is_empty(&curr_stats.filter_hist)); assert_false(hist_is_empty(&curr_stats.filter_hist));
96 99
97 vle_keys_user_add(L"x", L"cwname" WK_CR, NORMAL_MODE, KEYS_FLAG_NONE);
100 assert_success(vle_keys_user_add(L"x", L"cwname" WK_CR, "descr", NORMAL_MODE,
101 KEYS_FLAG_NONE));
98 102 assert_false(IS_KEYS_RET_CODE(vle_keys_exec_timed_out(L"x"))); assert_false(IS_KEYS_RET_CODE(vle_keys_exec_timed_out(L"x")));
99 103 assert_false(hist_is_empty(&curr_stats.prompt_hist)); assert_false(hist_is_empty(&curr_stats.prompt_hist));
100 104 } }
101 105
102 106 TEST(just_entering_via_a_mapping_does_not_skip_cmdline_history) TEST(just_entering_via_a_mapping_does_not_skip_cmdline_history)
103 107 { {
104 vle_keys_user_add(L";", L":", NORMAL_MODE, KEYS_FLAG_NONE);
108 assert_success(vle_keys_user_add(L";", L":", "descr", NORMAL_MODE,
109 KEYS_FLAG_NONE));
105 110 assert_false(IS_KEYS_RET_CODE(vle_keys_exec_timed_out(L";"))); assert_false(IS_KEYS_RET_CODE(vle_keys_exec_timed_out(L";")));
106 111 assert_false(IS_KEYS_RET_CODE(vle_keys_exec_timed_out(L"cmd" WK_CR))); assert_false(IS_KEYS_RET_CODE(vle_keys_exec_timed_out(L"cmd" WK_CR)));
107 112 assert_false(hist_is_empty(&curr_stats.cmd_hist)); assert_false(hist_is_empty(&curr_stats.cmd_hist));
 
... ... TEST(just_entering_via_a_mapping_does_not_skip_cmdline_history)
109 114
110 115 TEST(just_leaving_via_a_mapping_does_not_skip_cmdline_history) TEST(just_leaving_via_a_mapping_does_not_skip_cmdline_history)
111 116 { {
112 vle_keys_user_add(L"x", WK_CR, CMDLINE_MODE, KEYS_FLAG_NONE);
117 assert_success(vle_keys_user_add(L"x", WK_CR, "descr", CMDLINE_MODE,
118 KEYS_FLAG_NONE));
113 119 assert_false(IS_KEYS_RET_CODE(vle_keys_exec_timed_out(L":cmdx"))); assert_false(IS_KEYS_RET_CODE(vle_keys_exec_timed_out(L":cmdx")));
114 120 assert_false(hist_is_empty(&curr_stats.cmd_hist)); assert_false(hist_is_empty(&curr_stats.cmd_hist));
115 121 } }
116 122
117 123 TEST(entering_and_leaving_via_different_mappings_does_not_skip_cmdline_history) TEST(entering_and_leaving_via_different_mappings_does_not_skip_cmdline_history)
118 124 { {
119 vle_keys_user_add(L";", L":", NORMAL_MODE, KEYS_FLAG_NONE);
120 vle_keys_user_add(L"x", WK_CR, CMDLINE_MODE, KEYS_FLAG_NONE);
125 assert_success(vle_keys_user_add(L";", L":", "descr", NORMAL_MODE,
126 KEYS_FLAG_NONE));
127 assert_success(vle_keys_user_add(L"x", WK_CR, "descr", CMDLINE_MODE,
128 KEYS_FLAG_NONE));
121 129 assert_false(IS_KEYS_RET_CODE(vle_keys_exec_timed_out(L";cmdx"))); assert_false(IS_KEYS_RET_CODE(vle_keys_exec_timed_out(L";cmdx")));
122 130 assert_false(hist_is_empty(&curr_stats.cmd_hist)); assert_false(hist_is_empty(&curr_stats.cmd_hist));
123 131 } }
File tests/misc/event_loop.c changed (mode: 100644) (index ade3ff724..dd43b8b4e)
... ... TEST(key_suggestions)
166 166 keys_add_info_t x_key = { WK_X, { {&X_key} } }; keys_add_info_t x_key = { WK_X, { {&X_key} } };
167 167 vle_keys_add(&x_key, 1U, NORMAL_MODE); vle_keys_add(&x_key, 1U, NORMAL_MODE);
168 168
169 assert_success(vle_keys_user_add(L"Xj", L"j", NORMAL_MODE, KEYS_FLAG_NONE));
170 assert_success(vle_keys_user_add(L"Xk", L"k", NORMAL_MODE, KEYS_FLAG_NONE));
169 assert_success(vle_keys_user_add(L"Xj", L"j", "Xj help", NORMAL_MODE,
170 KEYS_FLAG_NONE));
171 assert_success(vle_keys_user_add(L"Xk", L"k", "Xk help", NORMAL_MODE,
172 KEYS_FLAG_NONE));
171 173
172 174 feed_keys(L"X"); feed_keys(L"X");
173 175
Hints

Before first commit, do not forget to setup your git environment:
git config --global user.name "your_name_here"
git config --global user.email "your@email_here"

Clone this repository using HTTP(S):
git clone https://code.reversed.top/user/xaizek/vifm

Clone this repository using ssh (do not forget to upload a key first):
git clone ssh://rocketgit@code.reversed.top/user/xaizek/vifm

You are allowed to anonymously push to this repository.
This means that your pushed commits will automatically be transformed into a pull request:
... clone the repository ...
... make some changes and some commits ...
git push origin master