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 3b0681faccae5d743d608f85d4319d81c48f265f

Allow descriptions for commands of :fileviewer
They currently appear only in `:fileviewer filename` menu.
Author: xaizek
Author date (UTC): 2025-08-18 16:44
Committer name: xaizek
Committer date (UTC): 2025-08-18 16:46
Parent(s): a71e0f5b829fd00d1ec592cbebdf6c6372a3e381
Signing key: 99DC5E4DB05F6BE2
Tree: a164430ac15640191f8a794cec8640fcfb55f1c8
File Lines added Lines deleted
ChangeLog 2 0
data/man/vifm.1 7 6
data/vim/doc/app/vifm-app.txt 7 6
src/filetype.c 5 5
tests/filetype/viewers.c 2 5
File ChangeLog changed (mode: 100644) (index 41a25b9c4..adf6e6a43)
59 59 Prefer to use more generic "items" instead of "files" when referring to Prefer to use more generic "items" instead of "files" when referring to
60 60 file-system objects. Thanks to qadzek. file-system objects. Thanks to qadzek.
61 61
62 Allowed descriptions for commands of `:fileviewer`.
63
62 64 Fixed 'trashdir' with "%r" on BSD-like systems (those with getmntinfo() Fixed 'trashdir' with "%r" on BSD-like systems (those with getmntinfo()
63 65 instead of getmntent() API). The regression was apparently introduced in instead of getmntent() API). The regression was apparently introduced in
64 66 v0.9.1-beta. Thanks to sublimal. v0.9.1-beta. Thanks to sublimal.
File data/man/vifm.1 changed (mode: 100644) (index cf8cd6aae..2ab76dd3f)
... ... name. Same as ":filetype filename".
2133 2133 .TP .TP
2134 2134 .BI " :fileviewer" .BI " :fileviewer"
2135 2135 .TP .TP
2136 .BI ":filev[iewer] pattern-list command1,command2,..."
2136 .BI ":filev[iewer] pattern-list [{ descr }]command1,[{ descr }]command2,..."
2137 2137 register specified list of commands as viewers for each of the patterns. register specified list of commands as viewers for each of the patterns.
2138 2138 Viewer is a command which output is captured and displayed in one of the panes Viewer is a command which output is captured and displayed in one of the panes
2139 of vifm after pressing "e" or running :view command. When the command doesn't
2140 contain any of vifm macros, name of current file is appended as if command
2141 ended with %c macro. Comma escaping and missing commands processing rules as
2142 for :filetype apply to this command. See "Patterns" section below for pattern
2143 definition. Supports Lua handlers.
2139 of vifm after pressing "e" or running :view command. Optional description can
2140 be given to each command to ease understanding of what the command does in UI.
2141 When the command doesn't contain any of vifm macros, name of current file is
2142 appended as if command ended with %c macro. Comma escaping and missing commands
2143 processing rules as for :filetype apply to this command. See "Patterns"
2144 section below for pattern definition. Supports Lua handlers.
2144 2145
2145 2146 Example for zip archives: Example for zip archives:
2146 2147 .EX .EX
File data/vim/doc/app/vifm-app.txt changed (mode: 100644) (index c6d18af43..1d5c91df8)
... ... Also see |vifm-file-copying|.
1826 1826 file name. Same as ":filetype filename". file name. Same as ":filetype filename".
1827 1827
1828 1828 *vifm-:fileviewer* *vifm-:filev* *vifm-:fileviewer* *vifm-:filev*
1829 :filev[iewer] pattern-list command1,command2,...
1829 :filev[iewer] pattern-list [{ descr }]command1,[{ descr }]command2,...
1830 1830 register specified list of commands as viewers for each of the patterns. register specified list of commands as viewers for each of the patterns.
1831 1831 Viewer is a command which output is captured and displayed in one of the Viewer is a command which output is captured and displayed in one of the
1832 1832 panes of vifm after pressing |vifm-e| or running |vifm-:view| command. panes of vifm after pressing |vifm-e| or running |vifm-:view| command.
1833 When the command doesn't contain any of vifm macros, name of current file
1834 is appended as if command ended with |vifm-%c| macro. Comma escaping and
1835 missing commands processing rules as for |vifm-:filetype| apply to this
1836 command. See |vifm-patterns| for pattern definition. Supports
1837 |vifm-lua-handlers|.
1833 Optional description can be given to each command to ease understanding of
1834 what the command does in UI. When the command doesn't contain any of vifm
1835 macros, name of current file is appended as if command ended with
1836 |vifm-%c| macro. Comma escaping and missing commands processing rules as
1837 for |vifm-:filetype| apply to this command. See |vifm-patterns| for
1838 pattern definition. Supports |vifm-lua-handlers|.
1838 1839
1839 1840 Example for zip archives: > Example for zip archives: >
1840 1841
File src/filetype.c changed (mode: 100644) (index aee1a9f6c..98f0661cb)
37 37 static const char * find_existing_cmd(const assoc_list_t *record_list, static const char * find_existing_cmd(const assoc_list_t *record_list,
38 38 const char file[]); const char file[]);
39 39 static assoc_record_t find_existing_cmd_record(const assoc_records_t *records); static assoc_record_t find_existing_cmd_record(const assoc_records_t *records);
40 static assoc_records_t parse_command_list(const char cmds[], int with_descr);
40 static assoc_records_t parse_command_list(const char cmds[]);
41 41 static assoc_records_t clone_all_matching_records(const char file[], static assoc_records_t clone_all_matching_records(const char file[],
42 42 const assoc_list_t *record_list); const assoc_list_t *record_list);
43 43 static int add_assoc(assoc_list_t *assoc_list, assoc_t assoc); static int add_assoc(assoc_list_t *assoc_list, assoc_t assoc);
 
... ... ft_set_programs(matchers_group_t mg, const char programs[], int for_x, int in_x)
196 196 { {
197 197 const assoc_t assoc = { const assoc_t assoc = {
198 198 .mg = mg, .mg = mg,
199 .records = parse_command_list(programs, 1),
199 .records = parse_command_list(programs),
200 200 }; };
201 201
202 202 /* On error, add_assoc() frees assoc, so just exit then. */ /* On error, add_assoc() frees assoc, so just exit then. */
 
... ... ft_set_programs(matchers_group_t mg, const char programs[], int for_x, int in_x)
212 212 /* Parses comma separated list of commands into array of associations. Returns /* Parses comma separated list of commands into array of associations. Returns
213 213 * the list. */ * the list. */
214 214 static assoc_records_t static assoc_records_t
215 parse_command_list(const char cmds[], int with_descr)
215 parse_command_list(const char cmds[])
216 216 { {
217 217 assoc_records_t records = {}; assoc_records_t records = {};
218 218
 
... ... parse_command_list(const char cmds[], int with_descr)
223 223 { {
224 224 const char *description = ""; const char *description = "";
225 225
226 if(with_descr && *part == '{')
226 if(*part == '{')
227 227 { {
228 228 char *p = strchr(part + 1, '}'); char *p = strchr(part + 1, '}');
229 229 if(p != NULL) if(p != NULL)
 
... ... ft_set_viewers(matchers_group_t mg, const char viewers[])
276 276 { {
277 277 const assoc_t assoc = { const assoc_t assoc = {
278 278 .mg = mg, .mg = mg,
279 .records = parse_command_list(viewers, 0),
279 .records = parse_command_list(viewers),
280 280 }; };
281 281 /* On error, add_assoc() frees assoc, so just exit then. */ /* On error, add_assoc() frees assoc, so just exit then. */
282 282 (void)add_assoc(&fileviewers, assoc); (void)add_assoc(&fileviewers, assoc);
File tests/filetype/viewers.c changed (mode: 100644) (index 59d1143ea..73f3107ed)
... ... TEST(multiple_choice_joined)
74 74 assert_true(viewer == NULL); assert_true(viewer == NULL);
75 75 } }
76 76
77 TEST(description_is_not_allowed)
77 TEST(description_is_allowed)
78 78 { {
79 const char *viewer;
80
81 79 assoc_viewers("*.tar.bz2", "{archives} prog1"); assoc_viewers("*.tar.bz2", "{archives} prog1");
82 80
83 81 ft_init(&prog1_available); ft_init(&prog1_available);
84 viewer = ft_get_viewer("file.version.tar.bz2");
85 assert_true(viewer == NULL);
82 assert_string_equal("prog1", ft_get_viewer("file.version.tar.bz2"));
86 83 } }
87 84
88 85 TEST(several_patterns) TEST(several_patterns)
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