1
0
forked from aniani/vim

patch 9.1.0327: No support for using $XDG_CONFIG_HOME

Problem:  No support for using $XDG_CONFIG_HOME
Solution: optionally source $XDG_CONFIG_HOME/vim/vimrc
          (Luca Saccarola)

fixes: #2034
closes: #14182

Signed-off-by: Luca Saccarola <github.e41mv@aleeas.com>
Signed-off-by: Christian Brabandt <cb@256bit.org>
This commit is contained in:
Luca Saccarola 2024-04-14 22:53:22 +02:00 committed by Christian Brabandt
parent f9f5424d3e
commit c9df1fb35a
No known key found for this signature in database
GPG Key ID: F3F92DA383FDDE09
13 changed files with 359 additions and 12 deletions

View File

@ -1,4 +1,4 @@
*starting.txt* For Vim version 9.1. Last change: 2024 Mar 13
*starting.txt* For Vim version 9.1. Last change: 2024 Apr 14
VIM REFERENCE MANUAL by Bram Moolenaar
@ -811,7 +811,8 @@ accordingly. Vim proceeds in this order:
name. Also see |vimrc-intro|.
Places for your personal initializations:
Unix $HOME/.vimrc or $HOME/.vim/vimrc
Unix $HOME/.vimrc, $HOME/.vim/vimrc
or $XDG_CONFIG_HOME/vim/vimrc
MS-Windows $HOME/_vimrc, $HOME/vimfiles/vimrc
or $VIM/_vimrc
Amiga s:.vimrc, home:.vimrc, home:vimfiles:vimrc
@ -853,15 +854,16 @@ accordingly. Vim proceeds in this order:
I The environment variable VIMINIT (see also |compatible-default|) (*)
The value of $VIMINIT is used as an Ex command line.
II The user vimrc file(s):
"$HOME/.vimrc" (for Unix) (*)
"$HOME/.vim/vimrc" (for Unix) (*)
"s:.vimrc" (for Amiga) (*)
"home:.vimrc" (for Amiga) (*)
"home:vimfiles:vimrc" (for Amiga) (*)
"$VIM/.vimrc" (for Amiga) (*)
"$HOME/_vimrc" (for Win32) (*)
"$HOME/vimfiles/vimrc" (for Win32) (*)
"$VIM/_vimrc" (for Win32) (*)
"$HOME/.vimrc" (for Unix) (*)
"$HOME/.vim/vimrc" (for Unix) (*)
"$HOME/.config/vim/vimrc" (for Unix) (*)
"s:.vimrc" (for Amiga) (*)
"home:.vimrc" (for Amiga) (*)
"home:vimfiles:vimrc" (for Amiga) (*)
"$VIM/.vimrc" (for Amiga) (*)
"$HOME/_vimrc" (for Win32) (*)
"$HOME/vimfiles/vimrc" (for Win32) (*)
"$VIM/_vimrc" (for Win32) (*)
"$HOME/config/settings/vim/vimrc" (for Haiku) (*)
Note: For Unix and Amiga, when ".vimrc" does not exist,
@ -1085,6 +1087,44 @@ defaults.vim from your .vimrc, first unlet skip_defaults_vim, as in the
example above.
*xdg-base-dir* *$XDG_CONFIG_HOME*
XDG Base Directory Specification ~
The XDG Base Directory Specification aims to define a standard location for
configuration files used by applications. This is mainly done to prevent
the legacy behavior of dumping everything into the users home directory.
The specification can be found online at
https://specifications.freedesktop.org/basedir-spec/latest/
The location of this standard configuration directory is configurable by the
user, using environment variable but should also give fallback in case those
variables weren't set.
This is a not an exhaustive list of those directories:
Environment var default location Description ~
`$XDG_CACHE_HOME` $HOME/.cache Ephemiral data files
`$XDG_CONFIG_HOME` $HOME/.config Configuration files
`$XDG_DATA_HOME` $HOME/.local/share Persistent data files
`$XDG_STATE_HOME` $HOME/.local/state State data files
Vim will only care of the `$XDG_CONFIG_HOME` directory, the others are not
(yet) used for its various configuration and state files.
*xdg-vimrc*
Vim, on Unix systems, will look at `$XDG_CONFIG_HOME/vim/vimrc` for its
configuration (see |vimrc|) but it will source it only if no other
initialization file is found in `$HOME` or `$HOME/.vim` (thus making this
feature backward compatible). However, if you want to migrate to use
`$XDG_CONFIG_HOME/vim/` directory, you will have to move away your `~/.vimrc`
and `~/.vim/vimrc` file.
*xdg-runtime*
When the |xdg-vimrc| is used the |'runtimepath'| will be modified accordingly
to respect the |xdg-base-dir|: >
"$XDG_CONFIG_HOME/vim,$VIMRUNTIME,/after,$XDG_CONFIG_HOME/vim/after"
<
Avoiding trojan horses ~
*trojan-horse*
While reading the "vimrc" or the "exrc" file in the current directory, some

View File

@ -12,6 +12,7 @@ $VIM starting.txt /*$VIM*
$VIM-use version5.txt /*$VIM-use*
$VIMRUNTIME starting.txt /*$VIMRUNTIME*
$VIM_POSIX vi_diff.txt /*$VIM_POSIX*
$XDG_CONFIG_HOME starting.txt /*$XDG_CONFIG_HOME*
$quote eval.txt /*$quote*
% motion.txt /*%*
%:. cmdline.txt /*%:.*
@ -11371,6 +11372,9 @@ x11-clientserver remote.txt /*x11-clientserver*
x11-cut-buffer gui_x11.txt /*x11-cut-buffer*
x11-selection gui_x11.txt /*x11-selection*
xattr editing.txt /*xattr*
xdg-base-dir starting.txt /*xdg-base-dir*
xdg-runtime starting.txt /*xdg-runtime*
xdg-vimrc starting.txt /*xdg-vimrc*
xf86conf.vim syntax.txt /*xf86conf.vim*
xfontset mbyte.txt /*xfontset*
xfree-xterm syntax.txt /*xfree-xterm*

View File

@ -41543,6 +41543,8 @@ and is a work in progress.
Support for Wayland UI.
Support for the XDG Desktop Specification |xdg-base-dir|
Vim9 script
-----------
Add support for internal builtin functions with vim9 objects, see

View File

@ -3276,6 +3276,10 @@ source_startup_scripts(mparm_T *parmp)
&& do_source((char_u *)USR_VIMRC_FILE2, TRUE,
DOSO_VIMRC, NULL) == FAIL
#endif
#ifdef XDG_VIMRC_FILE
&& do_source((char_u *)XDG_VIMRC_FILE, TRUE,
DOSO_VIMRC, NULL) == FAIL
#endif
#ifdef USR_VIMRC_FILE3
&& do_source((char_u *)USR_VIMRC_FILE3, TRUE,
DOSO_VIMRC, NULL) == FAIL

View File

@ -364,6 +364,66 @@ set_init_clean_rtp(void)
}
#endif
#ifdef UNIX
/*
* Change 'runtimepath' and 'packdir' to '$XDG_CONFIG_HOME/vim' if the only
* vimrc found is located in '$XDG_CONFIG_HOME/vim/vimrc'.
* In case the '$XDG_CONFIG_HOME' variable is not set, '$HOME/.config' is used
* as a fallback as is defined in the XDG base dir specification:
* <https://specifications.freedesktop.org/basedir-spec/basedir-spec-latest.html>
*/
static void
set_init_xdg_rtp(void)
{
int opt_idx;
int has_xdg_env = TRUE;
int should_free_xdg_dir = FALSE;
char_u *vimrc1 = NULL;
char_u *vimrc2 = NULL;
char_u *xdg_dir = NULL;
char_u *xdg_rtp = NULL;
char_u *vimrc_xdg = NULL;
vimrc1 = expand_env_save((char_u *)USR_VIMRC_FILE);
vimrc2 = expand_env_save((char_u *)USR_VIMRC_FILE2);
xdg_dir = mch_getenv("XDG_CONFIG_HOME");
if (!xdg_dir)
{
xdg_dir = expand_env_save((char_u *)"~/.config");
should_free_xdg_dir = TRUE;
has_xdg_env = FALSE;
}
vimrc_xdg = concat_fnames(xdg_dir, (char_u *)"vim/vimrc", TRUE);
if (file_is_readable(vimrc1) || file_is_readable(vimrc2) ||
!file_is_readable(vimrc_xdg))
goto theend;
xdg_rtp = has_xdg_env ? (char_u *)XDG_RUNTIMEPATH
: (char_u *)XDG_RUNTIMEPATH_FB;
if ((opt_idx = findoption((char_u *)"runtimepath")) < 0)
goto theend;
options[opt_idx].def_val[VI_DEFAULT] = xdg_rtp;
p_rtp = xdg_rtp;
if ((opt_idx = findoption((char_u *)"packpath")) < 0)
goto theend;
options[opt_idx].def_val[VI_DEFAULT] = xdg_rtp;
p_pp = xdg_rtp;
theend:
vim_free(vimrc1);
vim_free(vimrc2);
vim_free(vimrc_xdg);
if (should_free_xdg_dir)
vim_free(xdg_dir);
}
#endif
/*
* Expand environment variables and things like "~" for the defaults.
* If option_expand() returns non-NULL the variable is expanded. This can
@ -588,6 +648,7 @@ set_init_1(int clean_arg)
set_options_default(0);
#ifdef UNIX
set_init_xdg_rtp();
set_init_restricted_mode();
#endif

View File

@ -236,7 +236,7 @@ typedef struct dsc$descriptor DESC;
# ifdef VMS
# define USR_VIMRC_FILE "sys$login:.vimrc"
# else
# define USR_VIMRC_FILE "$HOME/.vimrc"
# define USR_VIMRC_FILE "~/.vimrc"
# endif
#endif
@ -249,6 +249,12 @@ typedef struct dsc$descriptor DESC;
# endif
#endif
#ifndef XDG_VIMRC_FILE
# define XDG_VIMRC_FILE mch_getenv("XDG_CONFIG_HOME") \
? (char_u *)"$XDG_CONFIG_HOME/vim/vimrc" \
: (char_u *)"~/.config/vim/vimrc"
#endif
#if !defined(USR_VIMRC_FILE3) && defined(VMS)
# define USR_VIMRC_FILE3 "sys$login:_vimrc"
#endif
@ -349,13 +355,19 @@ typedef struct dsc$descriptor DESC;
# ifdef RUNTIME_GLOBAL
# ifdef RUNTIME_GLOBAL_AFTER
# define DFLT_RUNTIMEPATH "~/.vim," RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL_AFTER ",~/.vim/after"
# define XDG_RUNTIMEPATH "$XDG_CONFIG_HOME/vim," RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL_AFTER "/after,$XDG_CONFIG_HOME/vim/after"
# define XDG_RUNTIMEPATH_FB "~/.config/vim," RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL_AFTER "/after,~/.config/vim/after"
# define CLEAN_RUNTIMEPATH RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL_AFTER
# else
# define DFLT_RUNTIMEPATH "~/.vim," RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL "/after,~/.vim/after"
# define XDG_RUNTIMEPATH "$XDG_CONFIG_HOME/vim," RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL "/after,$XDG_CONFIG_HOME/vim/after"
# define XDG_RUNTIMEPATH_FB "~/.config/vim," RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL "/after,~/.config/vim/after"
# define CLEAN_RUNTIMEPATH RUNTIME_GLOBAL ",$VIMRUNTIME," RUNTIME_GLOBAL "/after"
# endif
# else
# define DFLT_RUNTIMEPATH "~/.vim,$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after,~/.vim/after"
# define XDG_RUNTIMEPATH "$XDG_CONFIG_HOME/vim,$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after,$XDG_CONFIG_HOME/vim/after"
# define XDG_RUNTIMEPATH_FB "~/.config/vim,$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after,~/.config/vim/after"
# define CLEAN_RUNTIMEPATH "$VIM/vimfiles,$VIMRUNTIME,$VIM/vimfiles/after"
# endif
# endif

View File

@ -331,6 +331,7 @@ NEW_TESTS = \
test_wnext \
test_wordcount \
test_writefile \
test_xdg \
test_xxd \
test_alot_latin \
test_alot_utf8 \
@ -564,6 +565,7 @@ NEW_TESTS_RES = \
test_winfixbuf.res \
test_wordcount.res \
test_writefile.res \
test_xdg.res \
test_xxd.res \
test_alot_latin.res \
test_alot_utf8.res \

View File

@ -0,0 +1,20 @@
|~+0#4040ff13#ffffff0| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|r+0#0000000&|c|_|o|n|e| @16|o|n|e| @48
|r|c| @20|.|v|i|m|r|c| @45
|P+0#00e0003&|r|e|s@1| |E|N|T|E|R| |o|r| |t|y|p|e| |c|o|m@1|a|n|d| |t|o| |c|o|n|t|i|n|u|e> +0#0000000&@35

View File

@ -0,0 +1,20 @@
|~+0#4040ff13#ffffff0| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|r+0#0000000&|c|_|t|w|o| @16|t|w|o| @48
|r|c| @20|.|v|i|m|/|v|i|m|r|c| @41
|P+0#00e0003&|r|e|s@1| |E|N|T|E|R| |o|r| |t|y|p|e| |c|o|m@1|a|n|d| |t|o| |c|o|n|t|i|n|u|e> +0#0000000&@35

View File

@ -0,0 +1,20 @@
|~+0#4040ff13#ffffff0| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|r+0#0000000&|c|_|t|h|r|e@1| @14|t|h|r|e@1| @46
|r|c| @20|.|c|o|n|f|i|g|/|v|i|m|/|v|i|m|r|c| @34
|P+0#00e0003&|r|e|s@1| |E|N|T|E|R| |o|r| |t|y|p|e| |c|o|m@1|a|n|d| |t|o| |c|o|n|t|i|n|u|e> +0#0000000&@35

View File

@ -0,0 +1,20 @@
|~+0#4040ff13#ffffff0| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|~| @73
|r+0#0000000&|c|_|f|o|u|r| @15|f|o|u|r| @47
|r|c| @20|x|d|g|/|v|i|m|/|v|i|m|r|c| @38
|P+0#00e0003&|r|e|s@1| |E|N|T|E|R| |o|r| |t|y|p|e| |c|o|m@1|a|n|d| |t|o| |c|o|n|t|i|n|u|e> +0#0000000&@35

140
src/testdir/test_xdg.vim Normal file
View File

@ -0,0 +1,140 @@
" Tests for the XDG feature
source check.vim
CheckFeature terminal
source shared.vim
source screendump.vim
source mouse.vim
source term_util.vim
func s:get_rcs()
let rcs = {
\ 'file1': { 'path': '~/.vimrc' },
\ 'file2': { 'path': '~/.vim/vimrc' },
\ 'xdg': { 'path': exists('$XDG_CONFIG_HOME') ? '$XDG_CONFIG_HOME' : "~/.config" },
\}
for v in values(rcs)
let v.exists = filereadable(expand(v.path))
endfor
return rcs
endfunc
func Test_xdg_rc_detection()
CheckUnix
let rc = s:get_rcs()
let before =<< trim CODE
call writefile([expand('$MYVIMRC')], "XMY_VIMRC")
quit!
CODE
call RunVim(before, [], "")
let my_rc = readfile("XMY_VIMRC")
if rc.file1.exists
call assert_equal(rc.file1.path, my_rc)
elseif !rc.file1.exists && rc.file2.exists
call assert_equal(rc.file2.path, my_rc)
elseif !rc.file1.exists && !rc.file2.exists && rc.xdg.exists
call assert_equal(rc.xdg.path, my_rc)
endif
call delete("XMY_VIMRC")
endfunc
func Test_xdg_runtime_files()
" This tests, that the initialization file from
" ~/.vimrc, ~/.vim/vimrc and ~/.config/vim/vimrc (or
" $XDG_HOMECONFIG/vim/vimrc) are sourced in that order
CheckUnix
call mkdir(expand('~/.vim/'), 'pD')
call mkdir(expand('~/.config/vim/'), 'pD')
call mkdir(expand('~/xdg/vim/'), 'pD')
let rc1=expand('~/.vimrc')
let rc2=expand('~/.vim/vimrc')
let rc3=expand('~/.config/vim/vimrc')
let rc4=expand('~/xdg/vim/vimrc')
" g:rc_one|two|three|four is to verify, that the other
" init files are not source
" g:rc is to verify which rc file has been loaded.
let file1 =<< trim CODE
let g:rc_one = 'one'
let g:rc = '.vimrc'
CODE
let file2 =<< trim CODE
let g:rc_two = 'two'
let g:rc = '.vim/vimrc'
CODE
let file3 =<< trim CODE
let g:rc_three = 'three'
let g:rc = '.config/vim/vimrc'
CODE
let file4 =<< trim CODE
let g:rc_four = 'four'
let g:rc = 'xdg/vim/vimrc'
CODE
call writefile(file1, rc1)
call writefile(file2, rc2)
call writefile(file3, rc3)
call writefile(file4, rc4)
let rows = 20
let buf = RunVimInTerminal('', #{rows: rows, no_clean: 1})
call TermWait(buf)
call term_sendkeys(buf, ":echo \$MYVIMRC\<cr>")
call WaitForAssert({-> assert_match('XfakeHOME/\.vimrc', term_getline(buf, rows))})
call term_sendkeys(buf, ":call filter(g:, {idx, _ -> idx =~ '^rc'})\<cr>")
call TermWait(buf)
call term_sendkeys(buf, ":redraw!\<cr>")
call TermWait(buf)
call term_sendkeys(buf, ":let g:\<cr>")
call VerifyScreenDump(buf, 'Test_xdg_1', {})
call StopVimInTerminal(buf)
call delete(rc1)
bw
let buf = RunVimInTerminal('', #{rows: rows, no_clean: 1})
call TermWait(buf)
call term_sendkeys(buf, ":echo \$MYVIMRC\<cr>")
call WaitForAssert({-> assert_match('XfakeHOME/\.vim/vimrc', term_getline(buf, rows))})
call term_sendkeys(buf, ":call filter(g:, {idx, _ -> idx =~ '^rc'})\<cr>")
call TermWait(buf)
call term_sendkeys(buf, ":redraw!\<cr>")
call TermWait(buf)
call term_sendkeys(buf, ":let g:\<cr>")
call VerifyScreenDump(buf, 'Test_xdg_2', {})
call StopVimInTerminal(buf)
call delete(rc2)
bw
let buf = RunVimInTerminal('', #{rows: rows, no_clean: 1})
call TermWait(buf)
call term_sendkeys(buf, ":echo \$MYVIMRC\<cr>")
call WaitForAssert({-> assert_match('XfakeHOME/\.config/vim/vimrc', term_getline(buf, rows))})
call term_sendkeys(buf, ":call filter(g:, {idx, _ -> idx =~ '^rc'})\<cr>")
call TermWait(buf)
call term_sendkeys(buf, ":redraw!\<cr>")
call TermWait(buf)
call term_sendkeys(buf, ":let g:\<cr>")
call VerifyScreenDump(buf, 'Test_xdg_3', {})
call StopVimInTerminal(buf)
call delete(rc3)
bw
let $XDG_CONFIG_HOME=expand('~/xdg/')
let buf = RunVimInTerminal('', #{rows: rows, no_clean: 1})
call TermWait(buf)
call term_sendkeys(buf, ":redraw!\<cr>")
call TermWait(buf)
call term_sendkeys(buf, ":echo \$MYVIMRC\<cr>")
call WaitForAssert({-> assert_match('xdg/vim/vimrc', term_getline(buf, rows))})
call term_sendkeys(buf, ":call filter(g:, {idx, _ -> idx =~ '^rc'})\<cr>")
call TermWait(buf)
call term_sendkeys(buf, ":let g:\<cr>")
call VerifyScreenDump(buf, 'Test_xdg_4', {})
call StopVimInTerminal(buf)
call delete(rc4)
bw
unlet $XDG_CONFIG_HOME
endfunc
" vim: shiftwidth=2 sts=2 expandtab

View File

@ -704,6 +704,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
327,
/**/
326,
/**/