spellfile.vim 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. " Vim script to download a missing spell file
  2. if !exists('g:spellfile_URL')
  3. " Prefer using http:// when netrw should be able to use it, since
  4. " more firewalls let this through.
  5. if executable("curl") || executable("wget") || executable("fetch")
  6. let g:spellfile_URL = 'http://ftp.vim.org/pub/vim/runtime/spell'
  7. else
  8. let g:spellfile_URL = 'ftp://ftp.vim.org/pub/vim/runtime/spell'
  9. endif
  10. endif
  11. let s:spellfile_URL = '' " Start with nothing so that s:donedict is reset.
  12. " This function is used for the spellfile plugin.
  13. function! spellfile#LoadFile(lang)
  14. " If the netrw plugin isn't loaded we silently skip everything.
  15. if !exists(":Nread")
  16. if &verbose
  17. echomsg 'spellfile#LoadFile(): Nread command is not available.'
  18. endif
  19. return
  20. endif
  21. let lang = tolower(a:lang)
  22. " If the URL changes we try all files again.
  23. if s:spellfile_URL != g:spellfile_URL
  24. let s:donedict = {}
  25. let s:spellfile_URL = g:spellfile_URL
  26. endif
  27. " I will say this only once!
  28. if has_key(s:donedict, lang . &enc)
  29. if &verbose
  30. echomsg 'spellfile#LoadFile(): Tried this language/encoding before.'
  31. endif
  32. return
  33. endif
  34. let s:donedict[lang . &enc] = 1
  35. " Find spell directories we can write in.
  36. let [dirlist, dirchoices] = spellfile#GetDirChoices()
  37. if len(dirlist) == 0
  38. let dir_to_create = spellfile#WritableSpellDir()
  39. if &verbose || dir_to_create != ''
  40. echomsg 'spellfile#LoadFile(): No (writable) spell directory found.'
  41. endif
  42. if dir_to_create != ''
  43. call mkdir(dir_to_create, "p")
  44. " Now it should show up in the list.
  45. let [dirlist, dirchoices] = spellfile#GetDirChoices()
  46. endif
  47. if len(dirlist) == 0
  48. echomsg 'Failed to create: '.dir_to_create
  49. return
  50. else
  51. echomsg 'Created '.dir_to_create
  52. endif
  53. endif
  54. let msg = 'No spell file for "' . a:lang . '" in ' . &enc
  55. let msg .= "\nDownload it?"
  56. if confirm(msg, "&Yes\n&No", 2) == 1
  57. let enc = &encoding
  58. if enc == 'iso-8859-15'
  59. let enc = 'latin1'
  60. endif
  61. let fname = a:lang . '.' . enc . '.spl'
  62. " Split the window, read the file into a new buffer.
  63. " Remember the buffer number, we check it below.
  64. new
  65. let newbufnr = winbufnr(0)
  66. setlocal bin fenc=
  67. echo 'Downloading ' . fname . '...'
  68. call spellfile#Nread(fname)
  69. if getline(2) !~ 'VIMspell'
  70. " Didn't work, perhaps there is an ASCII one.
  71. " Careful: Nread() may have opened a new window for the error message,
  72. " we need to go back to our own buffer and window.
  73. if newbufnr != winbufnr(0)
  74. let winnr = bufwinnr(newbufnr)
  75. if winnr == -1
  76. " Our buffer has vanished!? Open a new window.
  77. echomsg "download buffer disappeared, opening a new one"
  78. new
  79. setlocal bin fenc=
  80. else
  81. exe winnr . "wincmd w"
  82. endif
  83. endif
  84. if newbufnr == winbufnr(0)
  85. " We are back to the old buffer, remove any (half-finished) download.
  86. keeppatterns g/^/d_
  87. else
  88. let newbufnr = winbufnr(0)
  89. endif
  90. let fname = lang . '.ascii.spl'
  91. echo 'Could not find it, trying ' . fname . '...'
  92. call spellfile#Nread(fname)
  93. if getline(2) !~ 'VIMspell'
  94. echo 'Download failed'
  95. exe newbufnr . "bwipe!"
  96. return
  97. endif
  98. endif
  99. " Delete the empty first line and mark the file unmodified.
  100. 1d_
  101. set nomod
  102. if len(dirlist) == 1
  103. let dirchoice = 0
  104. else
  105. let msg = "In which directory do you want to write the file:"
  106. for i in range(len(dirlist))
  107. let msg .= "\n" . (i + 1) . '. ' . dirlist[i]
  108. endfor
  109. let dirchoice = confirm(msg, dirchoices) - 2
  110. endif
  111. if dirchoice >= 0
  112. if exists('*fnameescape')
  113. let dirname = fnameescape(dirlist[dirchoice])
  114. else
  115. let dirname = escape(dirlist[dirchoice], ' ')
  116. endif
  117. setlocal fenc=
  118. exe "write " . dirname . '/' . fname
  119. " Also download the .sug file.
  120. keeppatterns g/^/d_
  121. let fname = substitute(fname, '\.spl$', '.sug', '')
  122. echo 'Downloading ' . fname . '...'
  123. call spellfile#Nread(fname)
  124. if getline(2) =~ 'VIMsug'
  125. 1d_
  126. exe "write " . dirname . '/' . fname
  127. set nomod
  128. else
  129. echo 'Download failed'
  130. " Go back to our own buffer/window, Nread() may have taken us to
  131. " another window.
  132. if newbufnr != winbufnr(0)
  133. let winnr = bufwinnr(newbufnr)
  134. if winnr != -1
  135. exe winnr . "wincmd w"
  136. endif
  137. endif
  138. if newbufnr == winbufnr(0)
  139. set nomod
  140. endif
  141. endif
  142. endif
  143. " Wipe out the buffer we used.
  144. exe newbufnr . "bwipe"
  145. endif
  146. endfunc
  147. " Read "fname" from the server.
  148. function! spellfile#Nread(fname)
  149. " We do our own error handling, don't want a window for it.
  150. if exists("g:netrw_use_errorwindow")
  151. let save_ew = g:netrw_use_errorwindow
  152. endif
  153. let g:netrw_use_errorwindow=0
  154. if g:spellfile_URL =~ '^ftp://'
  155. " for an ftp server use a default login and password to avoid a prompt
  156. let machine = substitute(g:spellfile_URL, 'ftp://\([^/]*\).*', '\1', '')
  157. let dir = substitute(g:spellfile_URL, 'ftp://[^/]*/\(.*\)', '\1', '')
  158. exe 'Nread "' . machine . ' anonymous vim7user ' . dir . '/' . a:fname . '"'
  159. else
  160. exe 'Nread ' g:spellfile_URL . '/' . a:fname
  161. endif
  162. if exists("save_ew")
  163. let g:netrw_use_errorwindow = save_ew
  164. else
  165. unlet g:netrw_use_errorwindow
  166. endif
  167. endfunc
  168. " Get a list of writable spell directories and choices for confirm().
  169. function! spellfile#GetDirChoices()
  170. let dirlist = []
  171. let dirchoices = '&Cancel'
  172. for dir in split(globpath(&rtp, 'spell'), "\n")
  173. if filewritable(dir) == 2
  174. call add(dirlist, dir)
  175. let dirchoices .= "\n&" . len(dirlist)
  176. endif
  177. endfor
  178. return [dirlist, dirchoices]
  179. endfunc
  180. function! spellfile#WritableSpellDir()
  181. " Always use the $XDG_DATA_HOME/…/site directory
  182. return stdpath('data').'/site/spell'
  183. endfunction