1if exists('g:loaded_gocode')
2	finish
3endif
4let g:loaded_gocode = 1
5
6fu! s:gocodeCurrentBuffer()
7	let buf = getline(1, '$')
8	if &encoding != 'utf-8'
9		let buf = map(buf, 'iconv(v:val, &encoding, "utf-8")')
10	endif
11	if &l:fileformat == 'dos'
12		" XXX: line2byte() depend on 'fileformat' option.
13		" so if fileformat is 'dos', 'buf' must include '\r'.
14		let buf = map(buf, 'v:val."\r"')
15	endif
16	let file = tempname()
17	call writefile(buf, file)
18	return file
19endf
20
21let s:vim_system = get(g:, 'gocomplete#system_function', 'system')
22
23fu! s:system(str, ...)
24	return call(s:vim_system, [a:str] + a:000)
25endf
26
27fu! s:gocodeShellescape(arg)
28	try
29		let ssl_save = &shellslash
30		set noshellslash
31		return shellescape(a:arg)
32	finally
33		let &shellslash = ssl_save
34	endtry
35endf
36
37fu! s:gocodeCommand(cmd, preargs, args)
38	for i in range(0, len(a:args) - 1)
39		let a:args[i] = s:gocodeShellescape(a:args[i])
40	endfor
41	for i in range(0, len(a:preargs) - 1)
42		let a:preargs[i] = s:gocodeShellescape(a:preargs[i])
43	endfor
44	let result = s:system(printf('gocode %s %s %s', join(a:preargs), a:cmd, join(a:args)))
45	if v:shell_error != 0
46		return "[\"0\", []]"
47	else
48		if &encoding != 'utf-8'
49			let result = iconv(result, 'utf-8', &encoding)
50		endif
51		return result
52	endif
53endf
54
55fu! s:gocodeCurrentBufferOpt(filename)
56	return '-in=' . a:filename
57endf
58
59fu! s:gocodeCursor()
60	if &encoding != 'utf-8'
61		let c = col('.')
62		let buf = line('.') == 1 ? "" : (join(getline(1, line('.')-1), "\n") . "\n")
63		let buf .= c == 1 ? "" : getline('.')[:c-2]
64		return printf('%d', len(iconv(buf, &encoding, "utf-8")))
65	endif
66	return printf('%d', line2byte(line('.')) + (col('.')-2))
67endf
68
69fu! s:gocodeAutocomplete()
70	let filename = s:gocodeCurrentBuffer()
71	let result = s:gocodeCommand('autocomplete',
72				   \ [s:gocodeCurrentBufferOpt(filename), '-f=vim'],
73				   \ [expand('%:p'), s:gocodeCursor()])
74	call delete(filename)
75	return result
76endf
77
78fu! gocomplete#Complete(findstart, base)
79	"findstart = 1 when we need to get the text length
80	if a:findstart == 1
81		execute "silent let g:gocomplete_completions = " . s:gocodeAutocomplete()
82		return col('.') - g:gocomplete_completions[0] - 1
83	"findstart = 0 when we need to return the list of completions
84	else
85		return g:gocomplete_completions[1]
86	endif
87endf
88