From f0ef30a4c5eed9f0b15bdcd9bdd1093aba72348e Mon Sep 17 00:00:00 2001 From: Tom Ryder Date: Sat, 25 Apr 2020 22:34:39 +1200 Subject: Improve compliance/sanity of XDG implementation --- vim/autoload/xdg.vim | 45 +++++++++++++---------- vim/vimrc | 100 +++++++++++++++++++++++++++++++-------------------- 2 files changed, 89 insertions(+), 56 deletions(-) diff --git a/vim/autoload/xdg.vim b/vim/autoload/xdg.vim index 675cf460..62d515c1 100644 --- a/vim/autoload/xdg.vim +++ b/vim/autoload/xdg.vim @@ -7,6 +7,8 @@ let s:defaults = { \ 'XDG_DATA_DIRS': '/usr/local/share/:/usr/share/', \} +let s:subdir = 'vim' + function! s:Get(name) abort let name = a:name let env = environ() @@ -23,31 +25,38 @@ function! s:Absolute(path) abort return a:path =~# '^[/~]' endfunction -function! xdg#CacheDir(name) abort - let name = a:name - let home = s:Get('XDG_CACHE_HOME') +function! s:Home(name) abort + let home = s:Get(a:name) if !s:Absolute(home) return '' endif - return join([home, name], '/') + return join([home, s:subdir], '/') endfunction -function! xdg#ConfigDirs(name) abort - let name = a:name - let home = s:Get('XDG_CONFIG_HOME') - let dirs = split(s:Get('XDG_CONFIG_DIRS'), ':') - return map( - \ filter(insert(dirs, home), 's:Absolute(v:val)') - \,'join([v:val, name], "/")' - \) +function! xdg#CacheHome() abort + return s:Home('XDG_CACHE_HOME') endfunction -function! xdg#DataDirs(name) abort - let name = a:name - let home = s:Get('XDG_DATA_HOME') - let dirs = split(s:Get('XDG_DATA_DIRS'), ':') +function! xdg#ConfigHome() abort + return s:Home('XDG_CONFIG_HOME') +endfunction + +function! xdg#DataHome() abort + return s:Home('XDG_DATA_HOME') +endfunction + +function! s:Dirs(name) abort + let dirs = split(s:Get(a:name), ':') return map( - \ filter(insert(dirs, home), 's:Absolute(v:val)') - \,'join([v:val, name], "/")' + \ filter(dirs, 's:Absolute(v:val)') + \,'join([v:val, s:subdir], "/")' \) endfunction + +function! xdg#ConfigDirs() abort + return s:Dirs('XDG_CONFIG_DIRS') +endfunction + +function! xdg#DataDirs() abort + return s:Dirs('XDG_DATA_DIRS') +endfunction diff --git a/vim/vimrc b/vim/vimrc index 8afb52d0..b4347b4f 100644 --- a/vim/vimrc +++ b/vim/vimrc @@ -103,21 +103,39 @@ endif " We'll use the XDG directories as machine-local configuration and storage. " " +"" Cache +let s:cache_home = xdg#CacheHome() +if strlen(s:cache_home) == 0 + unlet s:cache_home +endif "" Config -for s:configdir in reverse(xdg#ConfigDirs('vim')) - execute 'set runtimepath^=' - \.option#Escape(option#item#Escape(s:configdir)) -endfor -"" Cache; put this first so that e.g. spellfiles get created in it -let s:cachedir = xdg#CacheDir('vim') -if strlen(s:cachedir) - execute 'set runtimepath^=' - \.option#Escape(option#item#Escape(s:cachedir)) -else - unlet s:cachedir +let s:config_home = xdg#ConfigHome() +if strlen(s:config_home) == 0 + unlet s:config_home endif +let s:config_dirs = xdg#ConfigDirs() "" Data -let s:datadir = xdg#DataDirs('vim')[0] +let s:data_home = xdg#DataHome() +if strlen(s:data_home) == 0 + unlet s:data_home +endif +let s:data_dirs = xdg#DataDirs() + +" Add all the configuration directories to 'runtimepath', and then put the +" cache home at the very front, so that e.g. 'spellfile' gets created in there +" rather than in the configuration directories. +" +let s:runtime_dirs = s:config_dirs +if exists('s:config_home') + call insert(s:runtime_dirs, s:config_home) +endif +if exists('s:cache_home') + call insert(s:runtime_dirs, s:config_home) +endif +for s:runtime_dir in reverse(s:runtime_dirs) + execute 'set runtimepath^=' + \.option#Escape(option#item#Escape(s:runtime_dir)) +endfor " We need a command to reliably establish a full path, whether or not the " directories already exist. We create a wrapper for the autoloaded function @@ -148,9 +166,9 @@ command! -bang -bar -complete=dir -nargs=1 CreatePath " " " -if exists('s:cachedir') - execute 'set viminfo+='.option#Escape('n'.s:cachedir.'/viminfo') - call path#Create(s:cachedir) +if exists('s:cache_home') + execute 'set viminfo+='.option#Escape('n'.s:cache_home.'/viminfo') + call path#Create(s:cache_home) endif " Speaking of recorded data in viminfo files, the default Vim limit of a mere @@ -196,11 +214,11 @@ set history=10000 " 'backupfullname', 'swapfilefullname' would have been clearer. " set backup -if exists('s:cachedir') +if exists('s:cache_home') execute 'set backupdir^='.option#Escape(option#item#Escape( - \ s:cachedir.'/backup'.(has#('patch-8.1.251') ? '//' : ''), + \ s:cache_home.'/backup'.(has#('patch-8.1.251') ? '//' : ''), \)) - call path#Create(s:cachedir.'/backup') + call path#Create(s:cache_home.'/backup') endif " Files in certain directories on Unix-compatible filesystems should not be @@ -237,11 +255,11 @@ endif " option has supported that hint for much longer than 'backupdir' has. We " apply path#Create() to attempt to create the path, if needed. " -if exists('s:cachedir') - let s:swap = s:cachedir.'/swap' +if exists('s:cache_home') + let s:directory = s:cache_home.'/swap' execute 'set directory^=' - \.option#Escape(option#item#Escape(s:swap.'//')) - call path#Create(s:swap) + \.option#Escape(option#item#Escape(s:directory.'//')) + call path#Create(s:directory) endif " Keep tracked undo history for files permanently, in a dedicated cache @@ -259,8 +277,8 @@ endif " if has#('persistent_undo') set undofile - if exists('s:cachedir') - let s:undodir = s:cachedir.'/undo' + if exists('s:cache_home') + let s:undodir = s:cache_home.'/undo' execute 'set undodir^=' \.option#Escape(option#item#Escape(s:undodir.'//')) call path#Create(s:undodir) @@ -272,8 +290,8 @@ endif " directories of this type. This isn't a comma-separated list like the others " ('backupdir', 'directory', 'spell', 'undodir') " -if has#('mksession') && exists('s:cachedir') - let s:viewdir = s:cachedir.'/view' +if has#('mksession') && exists('s:cache_home') + let s:viewdir = s:cache_home.'/view' execute 'set viewdir=' \.option#Escape(option#item#Escape(s:viewdir)) call path#Create(s:viewdir) @@ -381,21 +399,27 @@ set spellcapcheck=[.?!]\\%(\ \ \\\|[\\n\\r\\t]\\) " first two metadata lines from thesaurus.txt, as Vim appeared to interpret " them as part of the body data. " -" Extra checks for appending the 'dictionary' and 'thesaurus' paths in MYVIM -" need to be made, because the P_NDNAME property is assigned to them, which -" enforces a character blacklist in the option value. We check for the -" expected Vim error code here, and if the MYVIM path offends, we just skip -" the setting entirely, rather than throwing cryptic errors at the user. None -" of the blacklisted characters are particularly wise characters to have in -" paths, anyway, legal though they may be on Unix filesystems. We can’t work -" around this one with 'isfname'; the blacklist is hard-coded. +" Extra checks for appending the 'dictionary' and 'thesaurus' paths need to be +" made, because the P_NDNAME property is assigned to them, which enforces +" a character blacklist in the option value. We check for the expected Vim +" error code here, and if the path offends, we just skip the setting entirely, +" rather than throwing cryptic errors at the user. None of the blacklisted +" characters are particularly wise characters to have in paths, anyway, legal +" though they may be on Unix filesystems. We can’t work around this one with +" 'isfname'; the blacklist is hard-coded. " set dictionary^=/usr/share/dict/words try - execute 'set dictionary^=' - \.option#Escape(option#item#Escape(s:datadir.'/dictionary.txt')) - execute 'set thesaurus^=' - \.option#Escape(option#item#Escape(s:datadir.'/thesaurus.txt')) + let s:ref_dirs = s:data_dirs + if exists('s:data_home') + call insert(s:ref_dirs, s:data_home) + endif + for s:ref_dir in reverse(s:ref_dirs) + execute 'set dictionary^=' + \.option#Escape(option#item#Escape(s:ref_dir.'/dictionary.txt')) + execute 'set thesaurus^=' + \.option#Escape(option#item#Escape(s:ref_dir.'/thesaurus.txt')) + endfor catch /^Vim\%((\a\+)\)\=:E474:/ endtry -- cgit v1.2.3