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 b9bdb83cdf030a1a04d717258dc426ad36346e8d

Add extpromptpath option (use external editor for path/filename edits)
Author: Kaspars Vandans
Author date (UTC): 2025-12-11 09:35
Committer name: Kaspars Vandans
Committer date (UTC): 2025-12-11 09:35
Parent(s): 294d904f9076bb66277fec947b32fadc288cff7d
Signing key:
Tree: 9b1d36391b9f0a5c3f08f32e142fa20c78649c3e
File Lines added Lines deleted
ChangeLog 2 0
data/man/vifm.1 9 1
data/vim/doc/app/vifm-app.txt 10 2
data/vim/syntax/vifm.vim 4 4
src/cfg/config.c 2 0
src/cfg/config.h 3 0
src/cfg/info.c 1 0
src/fops_common.c 39 0
src/fops_common.h 8 0
src/fops_misc.c 2 2
src/fops_put.c 3 2
src/fops_rename.c 2 2
src/opt_handlers.c 12 0
src/tags.c 1 0
File ChangeLog changed (mode: 100644) (index 06b16b05c..969c13ba1)
27 27 Added optional "next" and "prev" actions to :view command to switch Added optional "next" and "prev" actions to :view command to switch
28 28 default previewer for the current and similar files. default previewer for the current and similar files.
29 29
30 Added extpromptpath option to open path input boxes in external editor.
31
30 32 Updated utf8proc to v2.10.0. Updated utf8proc to v2.10.0.
31 33
32 34 Made documentation on which :commands can have comments a bit more Made documentation on which :commands can have comments a bit more
File data/man/vifm.1 changed (mode: 100644) (index 82ccdca97..0eb92232e)
1 .TH VIFM 1 "2 September 2025" "vifm 0.15"
1 .TH VIFM 1 "10 December 2025" "vifm 0.15"
2 2 .\" --------------------------------------------------------------------------- .\" ---------------------------------------------------------------------------
3 3 .SH NAME .SH NAME
4 4 .\" --------------------------------------------------------------------------- .\" ---------------------------------------------------------------------------
 
... ... type: boolean
5672 5672 default: true default: true
5673 5673 .br .br
5674 5674 Searches wrap around end of the list. Searches wrap around end of the list.
5675 .TP
5676 .BI "'extpromptpath'"
5677 type: boolean
5678 .br
5679 default: false
5680 .br
5681 When vifm prompts to amend paths or file names, use the external editor instead
5682 of the built-in line-prompt. This may happen, for example, during renaming.
5675 5683 .\" --------------------------------------------------------------------------- .\" ---------------------------------------------------------------------------
5676 5684 .SH Mappings .SH Mappings
5677 5685 .\" --------------------------------------------------------------------------- .\" ---------------------------------------------------------------------------
File data/vim/doc/app/vifm-app.txt changed (mode: 100644) (index ced1d1a84..5aa9a0940)
1 *vifm-app.txt* For Vifm version 0.15 Last change: 2025 September 2
1 *vifm-app.txt* For Vifm version 0.15 Last change: 2025 December 10
2 2
3 3 Email for bugs and suggestions: <xaizek@posteo.net> Email for bugs and suggestions: <xaizek@posteo.net>
4 4
 
... ... default: true
4791 4791
4792 4792 Searches wrap around end of the list. Searches wrap around end of the list.
4793 4793
4794 --------------------------------------------------------------------------------
4794 *vifm-'extpromptpath'*
4795 extpromptpath
4796 type: boolean
4797 default: false
4798
4799 When vifm prompts to amend paths, use the external editor instead of the
4800 built-in line-prompt. This may happen, for example, during renaming.
4801 -------------------------------------------------------------------------------
4802
4795 4803 *vifm-mappings* *vifm-mappings*
4796 4804
4797 4805 A user mapping like `nnoremap lhs rhs` defines a substitution of the A user mapping like `nnoremap lhs rhs` defines a substitution of the
File data/vim/syntax/vifm.vim changed (mode: 100644) (index 0c2f5a2b1..8f0be5199)
1 1 " vifm syntax file " vifm syntax file
2 2 " Maintainer: xaizek <xaizek@posteo.net> " Maintainer: xaizek <xaizek@posteo.net>
3 " Last Change: June 15, 2025
3 " Last Change: December 10, 2025
4 4 " Inspired By: Vim syntax file by Dr. Charles E. Campbell, Jr. " Inspired By: Vim syntax file by Dr. Charles E. Campbell, Jr.
5 5
6 6 if exists('b:current_syntax') if exists('b:current_syntax')
 
... ... syntax keyword vifmOption contained aproposprg autocd autochpos caseoptions
172 172 \ tabline tabprefix tabscope tabstop tabsuffix tal timefmt timeoutlen title \ tabline tabprefix tabscope tabstop tabsuffix tal timefmt timeoutlen title
173 173 \ tm trash trashdir ts tuioptions to uioptions undolevels ul vicmd \ tm trash trashdir ts tuioptions to uioptions undolevels ul vicmd
174 174 \ viewcolumns vifminfo vimhelp vixcmd wildinc wildmenu wmnu wildstyle \ viewcolumns vifminfo vimhelp vixcmd wildinc wildmenu wmnu wildstyle
175 \ wordchars wrap wrapscan ws
175 \ wordchars wrap wrapscan ws extpromptpath
176 176
177 177 " Disabled boolean options " Disabled boolean options
178 178 syntax keyword vifmOption contained noautocd noautochpos nocf nochaselinks syntax keyword vifmOption contained noautocd noautochpos nocf nochaselinks
 
... ... syntax keyword vifmOption contained noautocd noautochpos nocf nochaselinks
180 180 \ noic noincsearch nois nolaststatus nols nolsview nomillerview nonumber \ noic noincsearch nois nolaststatus nols nolsview nomillerview nonumber
181 181 \ nonu noquickview norelativenumber nornu noscrollbind noscb norunexec \ nonu noquickview norelativenumber nornu noscrollbind noscb norunexec
182 182 \ nosmartcase noscs nosortnumbers nosyscalls notitle notrash novimhelp \ nosmartcase noscs nosortnumbers nosyscalls notitle notrash novimhelp
183 \ nowildmenu nowmnu nowrap nowrapscan nows
183 \ nowildmenu nowmnu nowrap nowrapscan nows noextpromptpath
184 184
185 185 " Inverted boolean options " Inverted boolean options
186 186 syntax keyword vifmOption contained invautocd invautochpos invcf invchaselinks syntax keyword vifmOption contained invautocd invautochpos invcf invchaselinks
 
... ... syntax keyword vifmOption contained invautocd invautochpos invcf invchaselinks
189 189 \ invmillerview invnumber invnu invquickview invrelativenumber invrnu \ invmillerview invnumber invnu invquickview invrelativenumber invrnu
190 190 \ invscrollbind invscb invrunexec invsmartcase invscs invsortnumbers \ invscrollbind invscb invrunexec invsmartcase invscs invsortnumbers
191 191 \ invsyscalls invtitle invtrash invvimhelp invwildmenu invwmnu invwrap \ invsyscalls invtitle invtrash invvimhelp invwildmenu invwmnu invwrap
192 \ invwrapscan invws
192 \ invwrapscan invws invextpromptpath
193 193
194 194 " Expressions " Expressions
195 195 syntax region vifmStatement start='^\(\s\|:\)*' syntax region vifmStatement start='^\(\s\|:\)*'
File src/cfg/config.c changed (mode: 100644) (index bddc25230..f36145561)
... ... cfg_init(void)
257 257
258 258 cfg.auto_ch_pos = 1; cfg.auto_ch_pos = 1;
259 259 cfg.ch_pos_on = CHPOS_STARTUP | CHPOS_DIRMARK | CHPOS_ENTER; cfg.ch_pos_on = CHPOS_STARTUP | CHPOS_DIRMARK | CHPOS_ENTER;
260
261 cfg.ext_prompt_path = 0;
260 262 } }
261 263
262 264 void void
File src/cfg/config.h changed (mode: 100644) (index bd0dd0e71..d9483d940)
... ... typedef struct config_t
398 398 /* Control over automatic cursor positioning. */ /* Control over automatic cursor positioning. */
399 399 int auto_ch_pos; /* Weird option that drops positions from histories. */ int auto_ch_pos; /* Weird option that drops positions from histories. */
400 400 int ch_pos_on; /* List of cases when historical cursor position is used. */ int ch_pos_on; /* List of cases when historical cursor position is used. */
401
402 /* Whether to open path/filename amendment prompts in external editor */
403 int ext_prompt_path;
401 404 } }
402 405 config_t; config_t;
403 406
File src/cfg/info.c changed (mode: 100644) (index 4b12c1096..a8ae6578b)
... ... store_global_options(JSON_Object *root)
2372 2372 append_dstr(options, format_str("wordchars=%s", append_dstr(options, format_str("wordchars=%s",
2373 2373 escape_spaces(vle_opts_get("wordchars", OPT_GLOBAL)))); escape_spaces(vle_opts_get("wordchars", OPT_GLOBAL))));
2374 2374 append_dstr(options, format_str("%swrap", cfg.wrap_quick_view ? "" : "no")); append_dstr(options, format_str("%swrap", cfg.wrap_quick_view ? "" : "no"));
2375 append_dstr(options, format_str("%sextpromptpath", cfg.ext_prompt_path ? "" : "no"));
2375 2376 } }
2376 2377
2377 2378 /* Serializes view-specific options into JSON table. */ /* Serializes view-specific options into JSON table. */
File src/fops_common.c changed (mode: 100644) (index f8cf4d984..0bcb34a5f)
76 76 #include "trash.h" #include "trash.h"
77 77 #include "types.h" #include "types.h"
78 78 #include "undo.h" #include "undo.h"
79 #include "cmd_core.h"
79 80
80 81 /* 10 to the power of number of digits after decimal point to take into account /* 10 to the power of number of digits after decimal point to take into account
81 82 * on progress percentage counting. */ * on progress percentage counting. */
 
... ... fops_is_dir_writable(DirRole dir_role, const char path[])
1433 1434 return 0; return 0;
1434 1435 } }
1435 1436
1437 /* Queries prompt input using external editor.
1438 * Analogous to cmdline/extedit_prompt. */
1439 void
1440 fops_extedit_path(const char path[], fo_prompt_cb cb, void *cb_arg)
1441 {
1442 char *ext_cmd = cmds_get_ext(path, /*line_pos=*/0, CIT_PROMPT_INPUT);
1443
1444 if(ext_cmd != NULL)
1445 {
1446 hists_prompt_save(ext_cmd);
1447 }
1448 else
1449 {
1450 hists_prompt_save(path);
1451 show_error_msg("Editing", "Error querying data from external source.");
1452 }
1453
1454 /* Invoking this with NULL in case of error to report it. */
1455 cb(ext_cmd, cb_arg);
1456 free(ext_cmd);
1457 }
1458
1459 /* Prompts the user to input/amend a path. */
1460 void
1461 fops_prompt_path(const char prompt[], const char path[], fo_prompt_cb cb,
1462 void *cb_arg, fo_complete_cmd_func complete)
1463 {
1464 if(cfg.ext_prompt_path)
1465 {
1466 fops_extedit_path(path, cb, cb_arg);
1467 }
1468 else
1469 {
1470 fops_line_prompt(prompt, path, cb, cb_arg, complete);
1471 }
1472 }
1473
1474
1436 1475 /* vim: set tabstop=2 softtabstop=2 shiftwidth=2 noexpandtab cinoptions-=(0 : */ /* vim: set tabstop=2 softtabstop=2 shiftwidth=2 noexpandtab cinoptions-=(0 : */
1437 1476 /* vim: set cinoptions+=t0 filetype=c : */ /* vim: set cinoptions+=t0 filetype=c : */
File src/fops_common.h changed (mode: 100644) (index 26731d790..fff19c1f4)
... ... const char * fops_get_dst_dir(const struct view_t *view, int at);
222 222 * returned. */ * returned. */
223 223 int fops_is_dir_writable(DirRole dir_role, const char path[]); int fops_is_dir_writable(DirRole dir_role, const char path[]);
224 224
225 /* Prompts the user to amend path. Wrapper for fops_extedit_path and
226 * fops_line_prompt. */
227 void fops_prompt_path(const char prompt[], const char path[], fo_prompt_cb cb,
228 void *cb_arg, fo_complete_cmd_func complete);
229
230 /* Prompts the user to amend path using the external editor. */
231 void fops_extedit_path(const char path[], fo_prompt_cb cb, void *cb_arg);
232
225 233 TSTATIC_DEFS( TSTATIC_DEFS(
226 234 struct ext_edit_t; struct ext_edit_t;
227 235 struct progress_data_t; struct progress_data_t;
File src/fops_misc.c changed (mode: 100644) (index f0a09b4af..e414e2c7c)
... ... retarget_one(view_t *view)
591 591 return 0; return 0;
592 592 } }
593 593
594 fops_line_prompt("Link target: ", linkto, &change_link_cb, /*cb_arg=*/NULL,
595 &complete_filename);
594 fops_prompt_path("Link target: ", linkto, &change_link_cb, /*cb_arg=*/NULL,
595 &complete_filename);
596 596 return 0; return 0;
597 597 } }
598 598
File src/fops_put.c changed (mode: 100644) (index 5e854f5ab..f8079f4e3)
... ... prompt_dst_name(const char src_name[])
1178 1178 char prompt[128 + PATH_MAX]; char prompt[128 + PATH_MAX];
1179 1179
1180 1180 snprintf(prompt, ARRAY_LEN(prompt), "New name for %s: ", src_name); snprintf(prompt, ARRAY_LEN(prompt), "New name for %s: ", src_name);
1181 fops_line_prompt(prompt, src_name, &prompt_dst_name_cb, /*cb_arg=*/NULL,
1182 /*complete=*/NULL);
1181
1182 fops_prompt_path(prompt, src_name, &prompt_dst_name_cb, /*cb_arg=*/NULL,
1183 /*complete=*/NULL);
1183 1184 } }
1184 1185
1185 1186 /* Callback for line prompt result. */ /* Callback for line prompt result. */
File src/fops_rename.c changed (mode: 100644) (index 3ef03e8b3..3cd823dd6)
... ... fops_rename_current(view_t *view, int name_only)
94 94 } }
95 95
96 96 flist_sel_stash(view); flist_sel_stash(view);
97 fops_line_prompt(name_only ? "New name root: " : "New full name: ", filename,
98 &rename_file_cb, rename_file_ext, &complete_filename_only);
97 fops_prompt_path(name_only ? "New name root: " : "New full name: ", filename,
98 &rename_file_cb, rename_file_ext, &complete_filename_only);
99 99 } }
100 100
101 101 /* Callback for processing file rename query. */ /* Callback for processing file rename query. */
File src/opt_handlers.c changed (mode: 100644) (index d96773588..49d3195e5)
... ... static int parse_endpoint(const char **str, int *endpoint);
255 255 static void wrap_handler(OPT_OP op, optval_t val); static void wrap_handler(OPT_OP op, optval_t val);
256 256 static void text_option_changed(void); static void text_option_changed(void);
257 257 static void wrapscan_handler(OPT_OP op, optval_t val); static void wrapscan_handler(OPT_OP op, optval_t val);
258 static void extpromptpath_handler(OPT_OP op, optval_t val);
258 259
259 260 /* Possible values of 'caseoptions'. */ /* Possible values of 'caseoptions'. */
260 261 static const char *caseoptions_vals[][2] = { static const char *caseoptions_vals[][2] = {
 
... ... options[] = {
926 927 OPT_BOOL, 0, NULL, &wrapscan_handler, NULL, OPT_BOOL, 0, NULL, &wrapscan_handler, NULL,
927 928 { .ref.bool_val = &cfg.wrap_scan }, { .ref.bool_val = &cfg.wrap_scan },
928 929 }, },
930 { "extpromptpath", "", "open path/file name input in external editor",
931 OPT_BOOL, 0, NULL, &extpromptpath_handler, NULL,
932 { .ref.bool_val = &cfg.ext_prompt_path },
933 },
929 934
930 935 /* Local options must be grouped here. */ /* Local options must be grouped here. */
931 936 { "dotfiles", "", "show dot files", { "dotfiles", "", "show dot files",
 
... ... wrapscan_handler(OPT_OP op, optval_t val)
4124 4129 cfg.wrap_scan = val.bool_val; cfg.wrap_scan = val.bool_val;
4125 4130 } }
4126 4131
4132 static void
4133 extpromptpath_handler(OPT_OP op, optval_t val)
4134 {
4135 cfg.ext_prompt_path = val.bool_val;
4136 }
4137
4138
4127 4139 /* vim: set tabstop=2 softtabstop=2 shiftwidth=2 noexpandtab cinoptions-=(0 : */ /* vim: set tabstop=2 softtabstop=2 shiftwidth=2 noexpandtab cinoptions-=(0 : */
4128 4140 /* vim: set cinoptions+=t0 filetype=c : */ /* vim: set cinoptions+=t0 filetype=c : */
File src/tags.c changed (mode: 100644) (index ad219091d..90210c38d)
... ... const char *tags[] = {
59 59 "vifm-'dirsize'", "vifm-'dirsize'",
60 60 "vifm-'dotdirs'", "vifm-'dotdirs'",
61 61 "vifm-'dotfiles'", "vifm-'dotfiles'",
62 "vifm-'extpromptpath'",
62 63 "vifm-'fastrun'", "vifm-'fastrun'",
63 64 "vifm-'fcs'", "vifm-'fcs'",
64 65 "vifm-'fillchars'", "vifm-'fillchars'",
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