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 864d69018c3cfebdcaf854144cddede2dfada269

Make `--select dir` and `--select file` consistent
Change `--select path/to/directory` to behave the same as with files
instead of opening a directory except for the root (/) directory.

That's about the same as :goto command except that it fails with an
error when trying to select root. The different seems tolerable given
that :goto is interactive and there may be some value in opening root
on `--select /` from command-line.

Thanks to David Sierra DiazGranados (a.k.a. davidsierradz).

Fixes #1108 on GitHub.
Author: xaizek
Author date (UTC): 2026-06-14 12:18
Committer name: xaizek
Committer date (UTC): 2026-06-14 14:53
Parent(s): 819d5ec34951f714498ffaa48fe1694ce5179406
Signing key: 99DC5E4DB05F6BE2
Tree: eaa54b6cf8fd7f4bbf93eb4f178f49e4a9552004
File Lines added Lines deleted
ChangeLog 5 0
src/utils/path.c 0 9
src/utils/path.h 0 3
src/vifm.c 32 13
File ChangeLog changed (mode: 100644) (index 2c0c33a60..5000a9cd1)
7 7 inside of a directory, instead of to indicate directories. Thanks to inside of a directory, instead of to indicate directories. Thanks to
8 8 CaptainFantastic. CaptainFantastic.
9 9
10 Changed `--select path/to/directory` to behave the same as with files
11 instead of opening a directory (doesn't apply to root directory which gets
12 opened as before). Thanks to David Sierra DiazGranados (a.k.a.
13 davidsierradz).
14
10 15 Added <help> :*map argument that enables providing description for the Added <help> :*map argument that enables providing description for the
11 16 mapping with the same curly braces syntax as used by :file[x]type. mapping with the same curly braces syntax as used by :file[x]type.
12 17
File src/utils/path.c changed (mode: 100644) (index 9f67e89b1..896904e8a)
... ... find_ext_dot(const char path[])
696 696 return no_ext ? NULL : dot; return no_ext ? NULL : dot;
697 697 } }
698 698
699 void
700 exclude_file_name(char path[])
701 {
702 if(path_exists(path, DEREF) && !is_valid_dir(path))
703 {
704 remove_last_path_component(path);
705 }
706 }
707
708 699 int int
709 700 is_parent_dir(const char path[]) is_parent_dir(const char path[])
710 701 { {
File src/utils/path.h changed (mode: 100644) (index 2bf2d8b02..0f0f73f15)
... ... void split_ext(char path[], int *root_len, const char **ext_pos);
110 110 * extension, which points to trailing null character for an empty extension. */ * extension, which points to trailing null character for an empty extension. */
111 111 char * get_ext(const char path[]); char * get_ext(const char path[]);
112 112
113 /* Removes file name from path. Does nothing if path refers to a directory. */
114 void exclude_file_name(char path[]);
115
116 113 /* Checks whether path equals to ".." or "../". Returns non-zero if it is, /* Checks whether path equals to ".." or "../". Returns non-zero if it is,
117 114 * otherwise zero is returned. */ * otherwise zero is returned. */
118 115 int is_parent_dir(const char path[]); int is_parent_dir(const char path[]);
File src/vifm.c changed (mode: 100644) (index 0e4efbe33..63e169a07)
97 97
98 98 static int vifm_main(int argc, char *argv[]); static int vifm_main(int argc, char *argv[]);
99 99 static int get_start_cwd(char buf[], size_t buf_len); static int get_start_cwd(char buf[], size_t buf_len);
100 static void set_view_path(view_t *view, const char path[]);
100 static void set_view_path(view_t *view, const char path[], int handle);
101 101 static OpsResult undo_perform_func(OPS op, void *data, const char src[], static OpsResult undo_perform_func(OPS op, void *data, const char src[],
102 102 const char dst[]); const char dst[]);
103 103 static void parse_received_arguments(char *args[]); static void parse_received_arguments(char *args[]);
 
... ... vifm_main(int argc, char *argv[])
271 271
272 272 fops_init(&modcline_prompt, &prompt_msg_custom); fops_init(&modcline_prompt, &prompt_msg_custom);
273 273
274 set_view_path(&lwin, vifm_args.lwin_path);
275 set_view_path(&rwin, vifm_args.rwin_path);
274 set_view_path(&lwin, vifm_args.lwin_path, vifm_args.lwin_handle);
275 set_view_path(&rwin, vifm_args.rwin_path, vifm_args.rwin_handle);
276 276
277 277 if(need_to_switch_active_pane(vifm_args.lwin_path, vifm_args.rwin_path)) if(need_to_switch_active_pane(vifm_args.lwin_path, vifm_args.rwin_path))
278 278 { {
 
... ... get_start_cwd(char buf[], size_t buf_len)
401 401
402 402 /* Sets view's current directory from path value. */ /* Sets view's current directory from path value. */
403 403 static void static void
404 set_view_path(view_t *view, const char path[])
404 set_view_path(view_t *view, const char path[], int handle)
405 405 { {
406 if(view_needs_cd(view, path))
406 if(path[0] == '\0')
407 {
408 return;
409 }
410
411 if(!handle || view_needs_cd(view, path))
407 412 { {
408 413 copy_str(view->curr_dir, sizeof(view->curr_dir), path); copy_str(view->curr_dir, sizeof(view->curr_dir), path);
409 exclude_file_name(view->curr_dir);
414 if(!handle && !is_root_dir(path))
415 {
416 remove_last_path_component(view->curr_dir);
417 }
410 418 } }
411 419 } }
412 420
 
... ... parse_received_arguments(char *argv[])
446 454 SetForegroundWindow(GetConsoleWindow()); SetForegroundWindow(GetConsoleWindow());
447 455 #endif #endif
448 456
449 if(view_needs_cd(&lwin, args.lwin_path))
457 if(!args.lwin_handle || view_needs_cd(&lwin, args.lwin_path))
450 458 { {
451 459 remote_cd(&lwin, args.lwin_path, args.lwin_handle); remote_cd(&lwin, args.lwin_path, args.lwin_handle);
452 460 } }
453 461
454 if(view_needs_cd(&rwin, args.rwin_path))
462 if(!args.rwin_handle || view_needs_cd(&rwin, args.rwin_path))
455 463 { {
456 464 remote_cd(&rwin, args.rwin_path, args.rwin_handle); remote_cd(&rwin, args.rwin_path, args.rwin_handle);
457 465 } }
 
... ... parse_received_arguments(char *argv[])
471 479 static void static void
472 480 remote_cd(view_t *view, const char path[], int handle) remote_cd(view_t *view, const char path[], int handle)
473 481 { {
474 char buf[PATH_MAX + 1];
482 if(path[0] == '\0')
483 {
484 return;
485 }
475 486
476 487 if(view->explore_mode) if(view->explore_mode)
477 488 { {
 
... ... remote_cd(view_t *view, const char path[], int handle)
488 499 qv_toggle(); qv_toggle();
489 500 } }
490 501
491 copy_str(buf, sizeof(buf), path);
492 exclude_file_name(buf);
502 char cd_path[PATH_MAX + 1];
503 copy_str(cd_path, sizeof(cd_path), path);
504 /* A view is navigated the to parent directory of a path that's being
505 * selected or of a file that's being opened provided that the path exists and
506 * has a parent. */
507 if((!handle || !is_dir(cd_path)) && !is_root_dir(cd_path) &&
508 path_exists(cd_path, DEREF))
509 {
510 remove_last_path_component(cd_path);
511 }
493 512
494 (void)cd(view, view->curr_dir, buf);
513 (void)cd(view, view->curr_dir, cd_path);
495 514 check_path_for_file(view, path, handle); check_path_for_file(view, path, handle);
496 515 } }
497 516
 
... ... remote_cd(view_t *view, const char path[], int handle)
500 519 static void static void
501 520 check_path_for_file(view_t *view, const char path[], int handle) check_path_for_file(view_t *view, const char path[], int handle)
502 521 { {
503 if(path[0] == '\0' || is_dir(path) || (handle && strcmp(path, "-") == 0))
522 if(path[0] == '\0' || (handle && (is_dir(path) || strcmp(path, "-") == 0)))
504 523 { {
505 524 return; return;
506 525 } }
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