-
Notifications
You must be signed in to change notification settings - Fork 4
/
blink.vim
executable file
·231 lines (216 loc) · 7.22 KB
/
blink.vim
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
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
if exists("g:loaded_blink")
finish
endif
let g:loaded_blink=1
let s:active_jobs=get(s:,"active_jobs",[])
let s:job_queue=get(s:,"job_queue",[])
function! blink#init()
if exists("g:blink_path")
let s:blink_path = expand(g:blink_path)
else
let s:blink_path = expand("~/.vim/pack/blink")
endif
call mkdir(s:blink_path."/opt","p")
endfunction
function! blink#new_window()
redraw!
redraw!
let s:blink_window = get(s:, 'blink_window', -1)
let buflist = tabpagebuflist()
if s:blink_window < 0 || index(buflist,s:blink_window) < 0
if bufexists('[vim-blink]')
split [vim-blink]
else
new
setlocal buftype=nofile bufhidden=hide noswapfile
silent file [vim-blink]
let s:blink_window = bufnr()
call setbufline(s:blink_window,0,"vim-blink plugin manager")
endif
redraw
endif
endfunction
function! blink#activate(url)
let pluginname = substitute(a:url,"/","_",'')
if (!isdirectory(s:blink_path."/opt/".pluginname))
let job = blink#install(a:url,0)
while job_status(job) == 'run'
sleep 5m
endwhile
endif
exe "packadd! ".pluginname
endfunction
function! blink#install(url,update=0)
call blink#new_window()
let pluginname = substitute(a:url,"/","_",'')
if (isdirectory(s:blink_path."/opt/".pluginname) && a:update==0)
call appendbufline(s:blink_window, '$', a:url." is already installed")
return
elseif a:update != 0
"echom "Checking" a:url "for updates..."
call appendbufline(s:blink_window, '$', "Checking ".a:url." for updates...")
endif
while len(s:active_jobs) > 0
sleep 10m
call filter(s:active_jobs,"job_status(v:val.job) == 'run'")
endwhile
let branch = blink#ghBranch(a:url)
if branch is v:null
return
endif
let commit = blink#ghLastCommit(a:url,branch)
if commit is v:null
return
endif
if filereadable(expand(s:blink_path."/opt/".pluginname."/.blinkplugin.version"))
let current = readfile(expand(s:blink_path."/opt/".pluginname."/.blinkplugin.version"))
if current[0] == commit
"echom "The latest version of" a:url "is already installed"
call appendbufline(s:blink_window, '$', "The latest version of ".a:url." is already installed")
return
endif
endif
let url = "https://github.com/".a:url."/archive/".branch.".tar.gz"
call appendbufline(s:blink_window, '$', "Downloading ".a:url."/archive/".branch.".tar.gz...")
let cmd = "curl -fLo ".s:blink_path."/".pluginname."-".branch."-".commit.".tgz ".url
let active_job = { 'plugin': a:url, 'branch': branch, 'commit': commit, 'name': pluginname }
let job = job_start(cmd, {'err_cb': 's:curlProgress','exit_cb': 's:Done', 'err_mode': 'raw'})
let active_job.job = job
let active_job.channel = job_getchannel(job)
call add(s:active_jobs,active_job)
return job
endfunction
function! blink#update()
let plugins = glob(s:blink_path."/opt/*/.blinkplugin.repo",0,1)
for plugin in plugins
call blink#install(readfile(plugin)[0],1)
endfor
endfunction
function! blink#ghBranch(url)
let url = "https://github.com/".a:url."/refs?type=branch"
let cmd = "curl -s -H 'accept: application/json' ".url
let job = job_start(cmd)
while job_status(job) == 'run'
endwhile
let resp = ch_readraw(job)
try
let resp = json_decode(resp)
if has_key(resp,'error')
echow "Error getting branch for" a:url ":" resp['error']
return v:null
endif
let branch = resp['refs'][0]
return branch
catch
echow "Error getting branch for" a:url ": unknown response"
return v:null
endtry
endfunction
function! blink#ghLastCommit(url, branch)
let url = "https://github.com/".a:url."/latest-commit/".a:branch
let cmd = "curl -s -H 'accept: application/json' ".url
let job = job_start(cmd)
while job_status(job) == 'run'
endwhile
let resp = ch_readraw(job)
try
let resp = json_decode(resp)
if has_key(resp,'error')
echow "Error getting latest commit hash for" a:url ":" resp['error']
return v:null
endif
let commit = resp['oid'][:6]
return commit
catch
echow "Error getting branch for" a:url ": unknown response"
return v:null
endtry
endfunction
function s:curlProgress(channel, msg)
for j in s:active_jobs
if j.channel == a:channel
let active_job = j
break
endif
endfor
if !exists("active_job.message")
let active_job.message = ''
endif
for i in range(0,strlen(a:msg))
if a:msg[i:i] =~ '[\xd\x0]'
if strlen(active_job.message) > 0
"redraw!
let pct = matchstr(active_job.message,'[0-9]\+')
if pct > 0
let pct .= '%'
"echom 'Downloading ' . active_job.plugin . ': ' . pct
call setbufline(s:blink_window, '$', 'Downloading '.active_job.plugin.': '.pct)
else
"echom 'Downloading ' . active_job.plugin . '...'
call setbufline(s:blink_window, '$', 'Downloading '.active_job.plugin.'...')
endif
endif
let active_job.message = ''
else
let active_job.message .= a:msg[i:i]
endif
endfor
endfunction
function s:Done(job, status)
for j in s:active_jobs
if j.job == a:job
let active_job = j
break
endif
endfor
unlet active_job.message
sleep 5m
if a:status != 0
"redraw!
echow 'Could not download' active_job.plugin 'Err:' a:status
unlet active_job
return
endif
"redraw!
"echom 'Downloaded ' . active_job.plugin . '!'
call setbufline(s:blink_window, '$', 'Downloaded '.active_job.plugin)
call s:unpack(active_job)
endfunction
function s:unpack(job)
let plugin = a:job.plugin
let branch = a:job.branch
let commit = a:job.commit
let name = a:job.name
"redraw!
"echom "Extracting plugin: ".plugin
call setbufline(s:blink_window, '$', 'Extracting: '.plugin)
call mkdir(s:blink_path."/opt/".name,"p")
let cmd = "tar xf ".s:blink_path."/".name."-".branch."-".commit.".tgz --strip-components=1 -C ".s:blink_path."/opt/".name
let job = job_start(cmd, {'exit_cb': 's:Finish'})
let a:job.job = job
endfunction
function s:Finish(job,status)
"redraw!
for j in s:active_jobs
if j.job == a:job
let active_job = j
break
endif
endfor
let plugin = active_job.plugin
let branch = active_job.branch
let commit = active_job.commit
let name = active_job.name
call writefile([commit], s:blink_path."/opt/".name."/.blinkplugin.version", 'b')
call writefile([plugin], s:blink_path."/opt/".name."/.blinkplugin.repo", 'b')
call delete(s:blink_path."/".name."-".branch."-".commit.".tgz")
"echom "Installed plugin: ".plugin
call setbufline(s:blink_window, '$', 'Installed '.plugin)
call filter(s:active_jobs,"v:val != active_job")
"sleep 1
"redraw
endfunction
call blink#init()
command! -bang -nargs=+ BlinkInstall call blink#install(<args>,<bang>0)
command! -nargs=1 Blink call blink#activate(<args>)
command! -nargs=0 BlinkUpdate call blink#update()