aboutsummaryrefslogblamecommitdiff
path: root/autoload/spellfile_local.vim
blob: dc9d2cca0d522002082a7afbb994bf486d9ee678 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

















                                                                              
                                                                         

                                                                              

                               
                                                        
                          
                

                      






                                                                       
            
       
 




                                                                              
 
                                                                              

                                                                           
   

                                                                       
                                       
          
 
                                                                              
                                                                          


                                           

                                
           
                                       
           
          






                                                                         
                                                           
   


                                   

       

                                                                        
   




                                                          
        
                                             


           
                                                                           
                                                        
                                 
                                        

                                
                                                      

           


                                                      
                       
                                                           





                                                       

                                                    

           
" Entry point for plugin
function! spellfile_local#() abort

  " If this is a special buffer, don't do anything
  if index(['nofile', 'quickfix', 'help'], &buftype) >= 0
    return
  endif

  " Get the first item in the spelling languages list, bail if there aren't
  " any; strip any regional suffix (e.g. en_NZ), too, as the final 'spellfile'
  " value won't tolerate it
  "
  let spelllangs = s:OptionSplit(&spelllang)
  if len(spelllangs) == 0
    return
  endif
  let lang = split(spelllangs[0], '_')[0]

  " Make a list of all the spellfile names for which we want to search in
  " every directory; first is the normal lang.encoding.add, then if there's
  " a path set filename.lang.encoding.add, and then if there's a filetype set,
  " filetype.lang.encoding.add.
  "
  let basenames = [s:Filename([lang, &encoding, 'add'])]
  let path = expand('%:p')
  if path !=# ''
    call add(
          \ basenames,
          \ s:Filename(['path', path, lang, &encoding, 'add'])
          \)
  endif
  if &filetype !=# ''
    call add(
          \ basenames,
          \ s:Filename(['filetype', &filetype, lang, &encoding, 'add'])
          \)
  endif

  " Now make a list of all of the directories in which those files will be
  " searched, and where applicable, created; the method for doing this depends
  " on whether we have a configured list of directories or not
  "
  let dirnames = []

  " If we have a list of directories to use as the base for 'spellfile' /spell
  " subdirectories, we'll add all of them to the list with /spell suffixed,
  " regardless of whether Vim can write to them.
  "
  if exists('g:spellfile_local_dirs') && !empty(g:spellfile_local_dirs)
    for path in g:spellfile_local_dirs
      call add(dirnames, path.'/spell')
    endfor

  " Failing that, do what Vim does by default: use the first *writeable* entry
  " in 'runtimepath'. If none of them are writable, we raise an exception.
  "
  else
    for path in s:OptionSplit(&runtimepath)
      if filewritable(path) != 2
        continue
      endif
      call add(dirnames, path.'/spell')
      break
    endfor
    if empty(dirnames)
      echoerr 'No writable runtime dirs for ''spellfile'''
      return
    endif
  endif

  " Attempt to create the first directory in the list if it doesn't exist
  " already.  Just let any error happen and reach the user.
  "
  let dirname = expand(dirnames[0])
  if !isdirectory(dirname)
    call mkdir(dirname, 'p', 0700)
  endif

  " Now we'll actually combine those two together to make a long list of
  " spellfiles, and then set the option
  "
  let spellfiles = []
  for dirname in dirnames
    for basename in basenames
      call add(spellfiles, join([dirname, basename], '/'))
    endfor
  endfor
  let &l:spellfile = s:OptionJoin(spellfiles)

endfunction

" Escape a path for use as a valid option file name; replace any characters
" that won't work nicely as filenames with percent signs
function! s:Filename(parts) abort
  let pat = has('win32') || has('win64')
        \ ? '\c[^[:fname:]]\|\\'
        \ : '\c[^[:fname:]]\|/'
  return substitute(join(a:parts, '.'), pat, '%', 'g')
endfunction

" Join a list of strings into a comma-separated option
function! s:OptionJoin(list) abort
  return join(map(
        \ copy(a:list),
        \ 'substitute(v:val, ''\\\@<!,'', ''\\,'', ''g'')',
        \), ',')
endfunction

" Split a comma-separated option into a list of strings
function! s:OptionSplit(string) abort
  return map(
        \ split(a:string, '\\\@<!,[, ]*'),
        \ 'substitute(v:val, ''\\,'', '''', ''g'')',
        \)
endfunction