0
0
mirror of https://github.com/vim/vim.git synced 2025-07-26 11:04:33 -04:00

fix: preserve symlink paths when changing directory

Problem: File paths change from symlink to target path after :cd command
when editing files through symbolic links

Solution: Add '~' flag to 'cpoptions' to control symlink resolution.
When included (default), symlinks are resolved maintaining backward
compatibility. When excluded, symlinks are preserved providing the
improved behavior.
This commit is contained in:
glepnir 2025-06-29 19:56:10 +08:00
parent 523f9f5898
commit 25ddc99c52
5 changed files with 76 additions and 5 deletions

View File

@ -2390,7 +2390,7 @@ A jump table for the options with a short description can be found at |Q_op|.
*'cpoptions'* *'cpo'* *cpo*
'cpoptions' 'cpo' string (Vim default: "aABceFsz",
Vi default: all flags, except "#{|&/\."
Vi default: all flags, except "#{|&/\.~"
|$VIM_POSIX|: all flags)
global
A sequence of single character flags. When a character is present
@ -2680,6 +2680,13 @@ A jump table for the options with a short description can be found at |Q_op|.
character, the cursor won't move. When not included,
the cursor would skip over it and jump to the
following occurrence.
*cpo-~*
~ When included, don't resolve symbolic links when
changing directory with |:cd|, |:lcd|, or |:tcd|.
This preserves the symbolic link path in buffer names
and when displaying the current directory. When
excluded (default), symbolic links are resolved to
their target paths.
POSIX flags. These are not included in the Vi default value, except
when $VIM_POSIX was set on startup. |posix|

View File

@ -8029,7 +8029,7 @@ post_chdir(cdscope_T scope)
}
last_chdir_reason = NULL;
shorten_fnames(TRUE);
shorten_fnames(vim_strchr(p_cpo, CPO_NOSYMLINKS) == NULL);
}
/*

View File

@ -231,10 +231,11 @@ typedef enum {
#define CPO_CHDIR '.' // don't chdir if buffer is modified
#define CPO_SCOLON ';' // using "," and ";" will skip over char if
// cursor would not move
#define CPO_NOSYMLINKS '~' // don't resolve symlinks when changing directory
// default values for Vim, Vi and POSIX
#define CPO_VIM "aABceFsz"
#define CPO_VI "aAbBcCdDeEfFgHiIjJkKlLmMnoOpPqrRsStuvwWxXyZz$!%*-+<>;"
#define CPO_ALL "aAbBcCdDeEfFgHiIjJkKlLmMnoOpPqrRsStuvwWxXyZz$!%*-+<>#{|&/\\.;"
#define CPO_ALL "aAbBcCdDeEfFgHiIjJkKlLmMnoOpPqrRsStuvwWxXyZz$!%*-+<>#{|&/\\.;~"
// characters for p_ww option:
#define WW_ALL "bshl<>[]~"

View File

@ -252,4 +252,67 @@ func Test_getcwd_actual_dir()
call chdir(startdir)
endfunc
func Test_cd_preserve_symlinks()
" Test new behavior: preserve symlinks when cpo-=~
set cpoptions+=~
let savedir = getcwd()
call mkdir('Xsource', 'R')
call writefile(['abc'], 'Xsource/foo.txt', 'D')
if has("win32")
silent !mklink /D Xdest Xsource
else
silent !ln -s Xsource Xdest
endif
if v:shell_error
call delete('Xsource', 'rf')
throw 'Skipped: cannot create symlinks'
endif
edit Xdest/foo.txt
let path_before = expand('%')
call assert_match('Xdest[/\\]foo\.txt$', path_before)
cd .
let path_after = expand('%')
call assert_equal(path_before, path_after)
call assert_match('Xdest[/\\]foo\.txt$', path_after)
bwipe!
set cpoptions&
call delete('Xdest', 'rf')
call delete('Xsource', 'rf')
call chdir(savedir)
endfunc
func Test_cd_symlinks()
CheckNotMSWindows
let savedir = getcwd()
call mkdir('Xsource', 'R')
call writefile(['abc'], 'Xsource/foo.txt', 'D')
silent !ln -s Xsource Xdest
if v:shell_error
call delete('Xsource', 'rf')
throw 'Skipped: cannot create symlinks'
endif
edit Xdest/foo.txt
let path_before = expand('%')
call assert_match('Xdest[/\\]foo\.txt$', path_before)
cd .
let path_after = expand('%')
call assert_match('Xsource[/\\]foo\.txt$', path_after)
call assert_notequal(path_before, path_after)
bwipe!
set cpoptions&
call delete('Xdest', 'rf')
call delete('Xsource', 'rf')
call chdir(savedir)
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@ -2273,7 +2273,7 @@ func Test_VIM_POSIX()
qall
[CODE]
if RunVim([], after, '')
call assert_equal(['aAbBcCdDeEfFgHiIjJkKlLmMnoOpPqrRsStuvwWxXyZz$!%*-+<>#{|&/\.;',
call assert_equal(['aAbBcCdDeEfFgHiIjJkKlLmMnoOpPqrRsStuvwWxXyZz$!%*-+<>#{|&/\.;~',
\ 'AS'], readfile('X_VIM_POSIX'))
endif
@ -2528,7 +2528,7 @@ func Test_string_option_revert_on_failure()
\ ['completeopt', 'popup', 'a123'],
\ ['completepopup', 'width:20', 'border'],
\ ['concealcursor', 'v', 'xyz'],
\ ['cpoptions', 'HJ', '~'],
\ ['cpoptions', 'HJ', 'Q'],
\ ['cryptmethod', 'zip', 'a123'],
\ ['cursorlineopt', 'screenline', 'a123'],
\ ['debug', 'throw', 'a123'],