summaryrefslogtreecommitdiffstats
path: root/runtime/autoload/spellfile.vim
blob: 43f7dffa1a893095cd5bc3f2ea9269e036bfdbef (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
" Vim script to download a missing spell file
" Maintainer:	The Vim Project <https://github.com/vim/vim>
" Last Change:	2023 Aug 10
" Former Maintainer:	Bram Moolenaar <Bram@vim.org>

if !exists('g:spellfile_URL')
  " Always use https:// because it's secure.  The certificate is for nluug.nl,
  " thus we can't use the alias ftp.vim.org here.
  let g:spellfile_URL = 'https://ftp.nluug.nl/pub/vim/runtime/spell'
endif
let s:spellfile_URL = ''    " Start with nothing so that s:donedict is reset.

" This function is used for the spellfile plugin.
function! spellfile#LoadFile(lang)
  " If the netrw plugin isn't loaded we silently skip everything.
  if !exists(":Nread")
    if &verbose
      echomsg 'spellfile#LoadFile(): Nread command is not available.'
    endif
    return
  endif
  let lang = tolower(a:lang)

  " If the URL changes we try all files again.
  if s:spellfile_URL != g:spellfile_URL
    let s:donedict = {}
    let s:spellfile_URL = g:spellfile_URL
  endif

  " I will say this only once!
  if has_key(s:donedict, lang . &enc)
    if &verbose
      echomsg 'spellfile#LoadFile(): Tried this language/encoding before.'
    endif
    return
  endif
  let s:donedict[lang . &enc] = 1

  " Find spell directories we can write in.
  let [dirlist, dirchoices] = spellfile#GetDirChoices()
  if len(dirlist) == 0
    let dir_to_create = spellfile#WritableSpellDir()
    if &verbose || dir_to_create != ''
      echomsg 'spellfile#LoadFile(): There is no writable spell directory.'
    endif
    if dir_to_create != ''
      if confirm("Shall I create " . dir_to_create, "&Yes\n&No", 2) == 1
	" After creating the directory it should show up in the list.
	call mkdir(dir_to_create, "p")
	let [dirlist, dirchoices] = spellfile#GetDirChoices()
      endif
    endif
    if len(dirlist) == 0
      return
    endif
  endif

  let msg = 'Cannot find spell file for "' . lang . '" in ' . &enc
  let msg .= "\nDo you want me to try downloading it?"
  if confirm(msg, "&Yes\n&No", 2) == 1
    let enc = &encoding
    if enc == 'iso-8859-15'
      let enc = 'latin1'
    endif
    let fname = lang . '.' . enc . '.spl'

    " Split the window, read the file into a new buffer.
    " Remember the buffer number, we check it below.
    new
    let newbufnr = winbufnr(0)
    setlocal bin fenc=
    echo 'Downloading ' . fname . '...'
    call spellfile#Nread(fname)
    if getline(2) !~ 'VIMspell'
      " Didn't work, perhaps there is an ASCII one.
      " Careful: Nread() may have opened a new window for the error message,
      " we need to go back to our own buffer and window.
      if newbufnr != winbufnr(0)
	let winnr = bufwinnr(newbufnr)
	if winnr == -1
	  " Our buffer has vanished!?  Open a new window.
	  echomsg "download buffer disappeared, opening a new one"
	  new
	  setlocal bin fenc=
	else
	  exe winnr . "wincmd w"
	endif
      endif
      if newbufnr == winbufnr(0)
	" We are back the old buffer, remove any (half-finished) download.
        g/^/d
      else
	let newbufnr = winbufnr(0)
      endif

      let fname = lang . '.ascii.spl'
      echo 'Could not find it, trying ' . fname . '...'
      call spellfile#Nread(fname)
      if getline(2) !~ 'VIMspell'
	echo 'Sorry, downloading failed'
	exe newbufnr . "bwipe!"
	return
      endif
    endif

    " Delete the empty first line and mark the file unmodified.
    1d
    set nomod

    let msg = "In which directory do you want to write the file:"
    for i in range(len(dirlist))
      let msg .= "\n" . (i + 1) . '. ' . dirlist[i]
    endfor
    let dirchoice = confirm(msg, dirchoices) - 2
    if dirchoice >= 0
      if exists('*fnameescape')
	let dirname = fnameescape(dirlist[dirchoice])
      else
	let dirname = escape(dirlist[dirchoice], ' ')
      endif
      setlocal fenc=
      exe "write " . dirname . '/' . fname

      " Also download the .sug file, if the user wants to.
      let msg = "Do you want me to try getting the .sug file?\n"
      let msg .= "This will improve making suggestions for spelling mistakes,\n"
      let msg .= "but it uses quite a bit of memory."
      if confirm(msg, "&No\n&Yes") == 2
	g/^/d
	let fname = substitute(fname, '\.spl$', '.sug', '')
	echo 'Downloading ' . fname . '...'
	call spellfile#Nread(fname)
	if getline(2) =~ 'VIMsug'
	  1d
	  exe "write " . dirname . '/' . fname
	  set nomod
	else
	  echo 'Sorry, downloading failed'
	  " Go back to our own buffer/window, Nread() may have taken us to
	  " another window.
	  if newbufnr != winbufnr(0)
	    let winnr = bufwinnr(newbufnr)
	    if winnr != -1
	      exe winnr . "wincmd w"
	    endif
	  endif
	  if newbufnr == winbufnr(0)
	    set nomod
	  endif
	endif
      endif
    endif

    " Wipe out the buffer we used.
    exe newbufnr . "bwipe"
  endif
endfunc

" Read "fname" from the server.
function! spellfile#Nread(fname)
  " We do our own error handling, don't want a window for it.
  if exists("g:netrw_use_errorwindow")
    let save_ew = g:netrw_use_errorwindow
  endif
  let g:netrw_use_errorwindow=0

  if g:spellfile_URL =~ '^ftp://'
    " for an ftp server use a default login and password to avoid a prompt
    let machine = substitute(g:spellfile_URL, 'ftp://\([^/]*\).*', '\1', '')
    let dir = substitute(g:spellfile_URL, 'ftp://[^/]*/\(.*\)', '\1', '')
    exe 'Nread "' . machine . ' anonymous vim7user ' . dir . '/' . a:fname . '"'
  else
    exe 'Nread ' g:spellfile_URL . '/' . a:fname
  endif

  if exists("save_ew")
    let g:netrw_use_errorwindow = save_ew
  else
    unlet g:netrw_use_errorwindow
  endif
endfunc

" Get a list of writable spell directories and choices for confirm().
function! spellfile#GetDirChoices()
  let dirlist = []
  let dirchoices = '&Cancel'
  for dir in split(globpath(&rtp, 'spell'), "\n")
    if filewritable(dir) == 2
      call add(dirlist, dir)
      let dirchoices .= "\n&" . len(dirlist)
    endif
  endfor
  return [dirlist, dirchoices]
endfunc

function! spellfile#WritableSpellDir()
  if has("unix")
    " For Unix always use the $HOME/.vim directory
    return $HOME . "/.vim/spell"
  endif
  for dir in split(&rtp, ',')
    if filewritable(dir) == 2
      return dir . "/spell"
    endif
  endfor
  return ''
endfunction