1
0
Fork 0
mirror of synced 2024-11-15 21:48:57 -05:00
ultimate-vim/sources_non_forked/vim-gist/autoload/gist.vim
2020-04-25 21:56:16 -04:00

1165 lines
34 KiB
VimL

"=============================================================================
" File: gist.vim
" Author: Yasuhiro Matsumoto <mattn.jp@gmail.com>
" Last Change: 10-Oct-2016.
" Version: 7.3
" WebPage: http://github.com/mattn/vim-gist
" License: BSD
let s:save_cpo = &cpoptions
set cpoptions&vim
if exists('g:gist_disabled') && g:gist_disabled == 1
function! gist#Gist(...) abort
endfunction
finish
endif
if !exists('g:github_user') && !executable('git')
echohl ErrorMsg | echomsg 'Gist: require ''git'' command' | echohl None
finish
endif
if !executable('curl')
echohl ErrorMsg | echomsg 'Gist: require ''curl'' command' | echohl None
finish
endif
if globpath(&rtp, 'autoload/webapi/http.vim') ==# ''
echohl ErrorMsg | echomsg 'Gist: require ''webapi'', install https://github.com/mattn/webapi-vim' | echohl None
finish
else
call webapi#json#true()
endif
let s:gist_token_file = expand(get(g:, 'gist_token_file', '~/.gist-vim'))
let s:system = function(get(g:, 'webapi#system_function', 'system'))
if !exists('g:github_user')
let g:github_user = substitute(s:system('git config --get github.user'), "\n", '', '')
if strlen(g:github_user) == 0
let g:github_user = $GITHUB_USER
end
endif
if !exists('g:gist_api_url')
let g:gist_api_url = substitute(s:system('git config --get github.apiurl'), "\n", '', '')
if strlen(g:gist_api_url) == 0
let g:gist_api_url = 'https://api.github.com/'
end
if exists('g:github_api_url') && !exists('g:gist_shutup_issue154')
if matchstr(g:gist_api_url, 'https\?://\zs[^/]\+\ze') != matchstr(g:github_api_url, 'https\?://\zs[^/]\+\ze')
echohl WarningMsg
echo '--- Warning ---'
echo 'It seems that you set different URIs for github_api_url/gist_api_url.'
echo 'If you want to remove this message: let g:gist_shutup_issue154 = 1'
echohl None
if confirm('Continue?', '&Yes\n&No') != 1
let g:gist_disabled = 1
finish
endif
redraw!
endif
endif
endif
if g:gist_api_url !~# '/$'
let g:gist_api_url .= '/'
endif
if !exists('g:gist_update_on_write')
let g:gist_update_on_write = 1
endif
function! s:get_browser_command() abort
let gist_browser_command = get(g:, 'gist_browser_command', '')
if gist_browser_command ==# ''
if has('win32') || has('win64')
let gist_browser_command = '!start rundll32 url.dll,FileProtocolHandler %URL%'
elseif has('mac') || has('macunix') || has('gui_macvim') || system('uname') =~? '^darwin'
let gist_browser_command = 'open %URL%'
elseif executable('xdg-open')
let gist_browser_command = 'xdg-open %URL%'
elseif executable('firefox')
let gist_browser_command = 'firefox %URL% &'
else
let gist_browser_command = ''
endif
endif
return gist_browser_command
endfunction
function! s:open_browser(url) abort
let cmd = s:get_browser_command()
if len(cmd) == 0
redraw
echohl WarningMsg
echo 'It seems that you don''t have general web browser. Open URL below.'
echohl None
echo a:url
return
endif
let quote = &shellxquote == '"' ? "'" : '"'
if cmd =~# '^!'
let cmd = substitute(cmd, '%URL%', '\=quote.a:url.quote', 'g')
silent! exec cmd
elseif cmd =~# '^:[A-Z]'
let cmd = substitute(cmd, '%URL%', '\=a:url', 'g')
exec cmd
else
let cmd = substitute(cmd, '%URL%', '\=quote.a:url.quote', 'g')
call system(cmd)
endif
endfunction
function! s:shellwords(str) abort
let words = split(a:str, '\%(\([^ \t\''"]\+\)\|''\([^\'']*\)''\|"\(\%([^\"\\]\|\\.\)*\)"\)\zs\s*\ze')
let words = map(words, 'substitute(v:val, ''\\\([\\ ]\)'', ''\1'', "g")')
let words = map(words, 'matchstr(v:val, ''^\%\("\zs\(.*\)\ze"\|''''\zs\(.*\)\ze''''\|.*\)$'')')
return words
endfunction
function! s:truncate(str, num)
let mx_first = '^\(.\)\(.*\)$'
let str = a:str
let ret = ''
let width = 0
while 1
let char = substitute(str, mx_first, '\1', '')
let cells = strdisplaywidth(char)
if cells == 0 || width + cells > a:num
break
endif
let width = width + cells
let ret .= char
let str = substitute(str, mx_first, '\2', '')
endwhile
while width + 1 <= a:num
let ret .= " "
let width = width + 1
endwhile
return ret
endfunction
function! s:format_gist(gist) abort
let files = sort(keys(a:gist.files))
if empty(files)
return ''
endif
let file = a:gist.files[files[0]]
let name = file.filename
if has_key(file, 'content')
let code = file.content
let code = "\n".join(map(split(code, "\n"), '" ".v:val'), "\n")
else
let code = ''
endif
let desc = type(a:gist.description)==0 || a:gist.description ==# '' ? '' : a:gist.description
let name = substitute(name, '[\r\n\t]', ' ', 'g')
let name = substitute(name, ' ', ' ', 'g')
let desc = substitute(desc, '[\r\n\t]', ' ', 'g')
let desc = substitute(desc, ' ', ' ', 'g')
" Display a nice formatted (and truncated if needed) table of gists on screen
" Calculate field lengths for gist-listing formatting on screen
redir =>a |exe "sil sign place buffer=".bufnr('')|redir end
let signlist = split(a, '\n')
let width = winwidth(0) - ((&number||&relativenumber) ? &numberwidth : 0) - &foldcolumn - (len(signlist) > 2 ? 2 : 0)
let idlen = 33
let namelen = get(g:, 'gist_namelength', 30)
let desclen = width - (idlen + namelen + 10)
return printf('gist: %s %s %s', s:truncate(a:gist.id, idlen), s:truncate(name, namelen), s:truncate(desc, desclen))
endfunction
" Note: A colon in the file name has side effects on Windows due to NTFS Alternate Data Streams; avoid it.
let s:bufprefix = 'gist' . (has('unix') ? ':' : '_')
function! s:GistList(gistls, page) abort
if a:gistls ==# '-all'
let url = g:gist_api_url.'gists/public'
elseif get(g:, 'gist_show_privates', 0) && a:gistls ==# 'starred'
let url = g:gist_api_url.'gists/starred'
elseif get(g:, 'gist_show_privates') && a:gistls ==# 'mine'
let url = g:gist_api_url.'gists'
else
let url = g:gist_api_url.'users/'.a:gistls.'/gists'
endif
let winnum = bufwinnr(bufnr(s:bufprefix.a:gistls))
if winnum != -1
if winnum != bufwinnr('%')
exe winnum 'wincmd w'
endif
setlocal modifiable
else
if get(g:, 'gist_list_vsplit', 0)
exec 'silent noautocmd vsplit +set\ winfixwidth ' s:bufprefix.a:gistls
elseif get(g:, 'gist_list_rightbelow', 0)
exec 'silent noautocmd rightbelow 5 split +set\ winfixheight ' s:bufprefix.a:gistls
else
exec 'silent noautocmd split' s:bufprefix.a:gistls
endif
endif
if a:page > 1
let oldlines = getline(0, line('$'))
let url = url . '?page=' . a:page
endif
setlocal modifiable
let old_undolevels = &undolevels
let oldlines = []
silent %d _
redraw | echon 'Listing gists... '
let auth = s:GistGetAuthHeader()
if len(auth) == 0
bw!
redraw
echohl ErrorMsg | echomsg v:errmsg | echohl None
return
endif
let res = webapi#http#get(url, '', { "Authorization": auth })
if v:shell_error != 0
bw!
redraw
echohl ErrorMsg | echomsg 'Gists not found' | echohl None
return
endif
let content = webapi#json#decode(res.content)
if type(content) == 4 && has_key(content, 'message') && len(content.message)
bw!
redraw
echohl ErrorMsg | echomsg content.message | echohl None
if content.message ==# 'Bad credentials'
call delete(s:gist_token_file)
endif
return
endif
let lines = map(filter(content, '!empty(v:val.files)'), 's:format_gist(v:val)')
call setline(1, split(join(lines, "\n"), "\n"))
$put='more...'
let b:gistls = a:gistls
let b:page = a:page
setlocal buftype=nofile bufhidden=hide noswapfile
setlocal cursorline
setlocal nomodified
setlocal nomodifiable
syntax match SpecialKey /^gist:/he=e-1
syntax match Title /^gist: \S\+/hs=s+5 contains=ALL
nnoremap <silent> <buffer> <cr> :call <SID>GistListAction(0)<cr>
nnoremap <silent> <buffer> o :call <SID>GistListAction(0)<cr>
nnoremap <silent> <buffer> b :call <SID>GistListAction(1)<cr>
nnoremap <silent> <buffer> y :call <SID>GistListAction(2)<cr>
nnoremap <silent> <buffer> p :call <SID>GistListAction(3)<cr>
nnoremap <silent> <buffer> <esc> :bw<cr>
nnoremap <silent> <buffer> <s-cr> :call <SID>GistListAction(1)<cr>
cal cursor(1+len(oldlines),1)
nohlsearch
redraw | echo ''
endfunction
function! gist#list_recursively(user, ...) abort
let use_cache = get(a:000, 0, 1)
let limit = get(a:000, 1, -1)
let verbose = get(a:000, 2, 1)
if a:user ==# 'mine'
let url = g:gist_api_url . 'gists'
elseif a:user ==# 'starred'
let url = g:gist_api_url . 'gists/starred'
else
let url = g:gist_api_url.'users/'.a:user.'/gists'
endif
let auth = s:GistGetAuthHeader()
if len(auth) == 0
" anonymous user cannot get gists to prevent infinite recursive loading
return []
endif
if use_cache && exists('g:gist_list_recursively_cache')
if has_key(g:gist_list_recursively_cache, a:user)
return webapi#json#decode(g:gist_list_recursively_cache[a:user])
endif
endif
let page = 1
let gists = []
let lastpage = -1
function! s:get_lastpage(res) abort
let links = split(a:res.header[match(a:res.header, 'Link')], ',')
let link = links[match(links, 'rel=[''"]last[''"]')]
let page = str2nr(matchlist(link, '\%(page=\)\(\d\+\)')[1])
return page
endfunction
if verbose > 0
redraw | echon 'Loading gists...'
endif
while limit == -1 || page <= limit
let res = webapi#http#get(url.'?page='.page, '', {'Authorization': auth})
if limit == -1
" update limit to the last page
let limit = s:get_lastpage(res)
endif
if verbose > 0
redraw | echon 'Loading gists... ' . page . '/' . limit . ' pages has loaded.'
endif
let gists = gists + webapi#json#decode(res.content)
let page = page + 1
endwhile
let g:gist_list_recursively_cache = get(g:, 'gist_list_recursively_cache', {})
let g:gist_list_recursively_cache[a:user] = webapi#json#encode(gists)
return gists
endfunction
function! gist#list(user, ...) abort
let page = get(a:000, 0, 0)
if a:user ==# '-all'
let url = g:gist_api_url.'gists/public'
elseif get(g:, 'gist_show_privates', 0) && a:user ==# 'starred'
let url = g:gist_api_url.'gists/starred'
elseif get(g:, 'gist_show_privates') && a:user ==# 'mine'
let url = g:gist_api_url.'gists'
else
let url = g:gist_api_url.'users/'.a:user.'/gists'
endif
let auth = s:GistGetAuthHeader()
if len(auth) == 0
return []
endif
let res = webapi#http#get(url, '', { "Authorization": auth })
return webapi#json#decode(res.content)
endfunction
function! s:GistGetFileName(gistid) abort
let auth = s:GistGetAuthHeader()
if len(auth) == 0
return ''
endif
let res = webapi#http#get(g:gist_api_url.'gists/'.a:gistid, '', { "Authorization": auth })
let gist = webapi#json#decode(res.content)
if has_key(gist, 'files')
return sort(keys(gist.files))[0]
endif
return ''
endfunction
function! s:GistDetectFiletype(gistid) abort
let auth = s:GistGetAuthHeader()
if len(auth) == 0
return ''
endif
let res = webapi#http#get(g:gist_api_url.'gists/'.a:gistid, '', { "Authorization": auth })
let gist = webapi#json#decode(res.content)
let filename = sort(keys(gist.files))[0]
let ext = fnamemodify(filename, ':e')
if has_key(s:extmap, ext)
let type = s:extmap[ext]
else
let type = get(gist.files[filename], 'type', 'text')
endif
silent! exec 'setlocal ft='.tolower(type)
endfunction
function! s:GistWrite(fname) abort
if substitute(a:fname, '\\', '/', 'g') == expand("%:p:gs@\\@/@")
if g:gist_update_on_write != 2 || v:cmdbang
Gist -e
else
echohl ErrorMsg | echomsg 'Please type ":w!" to update a gist.' | echohl None
endif
else
exe 'w'.(v:cmdbang ? '!' : '') fnameescape(v:cmdarg) fnameescape(a:fname)
silent! exe 'file' fnameescape(a:fname)
silent! au! BufWriteCmd <buffer>
endif
endfunction
function! s:GistGet(gistid, clipboard) abort
redraw | echon 'Getting gist... '
let res = webapi#http#get(g:gist_api_url.'gists/'.a:gistid, '', { "Authorization": s:GistGetAuthHeader() })
if res.status =~# '^2'
try
let gist = webapi#json#decode(res.content)
catch
redraw
echohl ErrorMsg | echomsg 'Gist seems to be broken' | echohl None
return
endtry
if get(g:, 'gist_get_multiplefile', 0) != 0
let num_file = len(keys(gist.files))
else
let num_file = 1
endif
redraw
if num_file > len(keys(gist.files))
echohl ErrorMsg | echomsg 'Gist not found' | echohl None
return
endif
augroup GistWrite
au!
augroup END
for n in range(num_file)
try
let old_undolevels = &undolevels
let filename = sort(keys(gist.files))[n]
let winnum = bufwinnr(bufnr(s:bufprefix.a:gistid.'/'.filename))
if winnum != -1
if winnum != bufwinnr('%')
exe winnum 'wincmd w'
endif
setlocal modifiable
else
if num_file == 1
if get(g:, 'gist_edit_with_buffers', 0)
let found = -1
for wnr in range(1, winnr('$'))
let bnr = winbufnr(wnr)
if bnr != -1 && !empty(getbufvar(bnr, 'gist'))
let found = wnr
break
endif
endfor
if found != -1
exe found 'wincmd w'
setlocal modifiable
else
if get(g:, 'gist_list_vsplit', 0)
exec 'silent noautocmd rightbelow vnew'
else
exec 'silent noautocmd rightbelow new'
endif
endif
else
silent only!
if get(g:, 'gist_list_vsplit', 0)
exec 'silent noautocmd rightbelow vnew'
else
exec 'silent noautocmd rightbelow new'
endif
endif
else
if get(g:, 'gist_list_vsplit', 0)
exec 'silent noautocmd rightbelow vnew'
else
exec 'silent noautocmd rightbelow new'
endif
endif
setlocal noswapfile
silent exec 'noautocmd file' s:bufprefix.a:gistid.'/'.fnameescape(filename)
endif
set undolevels=-1
filetype detect
silent %d _
let content = gist.files[filename].content
call setline(1, split(content, "\n"))
let b:gist = {
\ "filename": filename,
\ "id": gist.id,
\ "description": gist.description,
\ "private": gist.public =~ 'true',
\}
catch
let &undolevels = old_undolevels
bw!
redraw
echohl ErrorMsg | echomsg 'Gist contains binary' | echohl None
return
endtry
let &undolevels = old_undolevels
setlocal buftype=acwrite bufhidden=hide noswapfile
setlocal nomodified
doau StdinReadPost,BufRead,BufReadPost
let gist_detect_filetype = get(g:, 'gist_detect_filetype', 0)
if (&ft ==# '' && gist_detect_filetype == 1) || gist_detect_filetype == 2
call s:GistDetectFiletype(a:gistid)
endif
if a:clipboard
if exists('g:gist_clip_command')
exec 'silent w !'.g:gist_clip_command
elseif has('clipboard')
silent! %yank +
else
%yank
endif
endif
1
augroup GistWrite
au! BufWriteCmd <buffer> call s:GistWrite(expand("<amatch>"))
augroup END
endfor
else
bw!
redraw
echohl ErrorMsg | echomsg 'Gist not found' | echohl None
return
endif
endfunction
function! s:GistListAction(mode) abort
let line = getline('.')
let mx = '^gist:\s*\zs\(\w\+\)\ze.*'
if line =~# mx
let gistid = matchstr(line, mx)
if a:mode == 1
call s:open_browser('https://gist.github.com/' . gistid)
elseif a:mode == 0
call s:GistGet(gistid, 0)
wincmd w
bw
elseif a:mode == 2
call s:GistGet(gistid, 1)
" TODO close with buffe rname
bdelete
bdelete
elseif a:mode == 3
call s:GistGet(gistid, 1)
" TODO close with buffe rname
bdelete
bdelete
normal! "+p
endif
return
endif
if line =~# '^more\.\.\.$'
call s:GistList(b:gistls, b:page+1)
return
endif
endfunction
function! s:GistUpdate(content, gistid, gistnm, desc) abort
let gist = { "id": a:gistid, "files" : {}, "description": "","public": function('webapi#json#true') }
if exists('b:gist')
if has_key(b:gist, 'filename') && len(a:gistnm) > 0
let gist.files[b:gist.filename] = { "content": '', "filename": b:gist.filename }
let b:gist.filename = a:gistnm
endif
if has_key(b:gist, 'private') && b:gist.private | let gist['public'] = function('webapi#json#false') | endif
if has_key(b:gist, 'description') | let gist['description'] = b:gist.description | endif
if has_key(b:gist, 'filename') | let filename = b:gist.filename | endif
else
let filename = a:gistnm
if len(filename) == 0 | let filename = s:GistGetFileName(a:gistid) | endif
if len(filename) == 0 | let filename = s:get_current_filename(1) | endif
endif
let auth = s:GistGetAuthHeader()
if len(auth) == 0
redraw
echohl ErrorMsg | echomsg v:errmsg | echohl None
return
endif
" Update description
" If no new description specified, keep the old description
if a:desc !=# ' '
let gist['description'] = a:desc
else
let res = webapi#http#get(g:gist_api_url.'gists/'.a:gistid, '', { "Authorization": auth })
if res.status =~# '^2'
let old_gist = webapi#json#decode(res.content)
let gist['description'] = old_gist.description
endif
endif
let gist.files[filename] = { "content": a:content, "filename": filename }
redraw | echon 'Updating gist... '
let res = webapi#http#post(g:gist_api_url.'gists/' . a:gistid,
\ webapi#json#encode(gist), {
\ "Authorization": auth,
\ "Content-Type": "application/json",
\})
if res.status =~# '^2'
let obj = webapi#json#decode(res.content)
let loc = obj['html_url']
let b:gist = {"id": a:gistid, "filename": filename}
setlocal nomodified
redraw | echomsg 'Done: '.loc
else
let loc = ''
echohl ErrorMsg | echomsg 'Post failed: ' . res.message | echohl None
endif
return loc
endfunction
function! s:GistDelete(gistid) abort
let auth = s:GistGetAuthHeader()
if len(auth) == 0
redraw
echohl ErrorMsg | echomsg v:errmsg | echohl None
return
endif
redraw | echon 'Deleting gist... '
let res = webapi#http#post(g:gist_api_url.'gists/'.a:gistid, '', {
\ "Authorization": auth,
\ "Content-Type": "application/json",
\}, 'DELETE')
if res.status =~# '^2'
if exists('b:gist')
unlet b:gist
endif
redraw | echomsg 'Done: '
else
echohl ErrorMsg | echomsg 'Delete failed: ' . res.message | echohl None
endif
endfunction
function! s:get_current_filename(no) abort
let filename = expand('%:t')
if len(filename) == 0 && &ft !=# ''
let pair = filter(items(s:extmap), 'v:val[1] == &ft')
if len(pair) > 0
let filename = printf('gistfile%d%s', a:no, pair[0][0])
endif
endif
if filename ==# ''
let filename = printf('gistfile%d.txt', a:no)
endif
return filename
endfunction
function! s:update_GistID(id) abort
let view = winsaveview()
normal! gg
let ret = 0
if search('\<GistID\>:\s*$')
let line = getline('.')
let line = substitute(line, '\s\+$', '', 'g')
call setline('.', line . ' ' . a:id)
let ret = 1
endif
call winrestview(view)
return ret
endfunction
" GistPost function:
" Post new gist to github
"
" if there is an embedded gist url or gist id in your file,
" it will just update it.
" -- by c9s
"
" embedded gist id format:
"
" GistID: 123123
"
function! s:GistPost(content, private, desc, anonymous) abort
let gist = { "files" : {}, "description": "","public": function('webapi#json#true') }
if a:desc !=# ' ' | let gist['description'] = a:desc | endif
if a:private | let gist['public'] = function('webapi#json#false') | endif
let filename = s:get_current_filename(1)
let gist.files[filename] = { "content": a:content, "filename": filename }
let header = {"Content-Type": "application/json"}
if !a:anonymous
let auth = s:GistGetAuthHeader()
if len(auth) == 0
redraw
echohl ErrorMsg | echomsg v:errmsg | echohl None
return
endif
let header['Authorization'] = auth
endif
redraw | echon 'Posting it to gist... '
let res = webapi#http#post(g:gist_api_url.'gists', webapi#json#encode(gist), header)
if res.status =~# '^2'
let obj = webapi#json#decode(res.content)
let loc = obj['html_url']
let b:gist = {
\ "filename": filename,
\ "id": matchstr(loc, '[^/]\+$'),
\ "description": gist['description'],
\ "private": a:private,
\}
if s:update_GistID(b:gist['id'])
Gist -e
endif
redraw | echomsg 'Done: '.loc
else
let loc = ''
echohl ErrorMsg | echomsg 'Post failed: '. res.message | echohl None
endif
return loc
endfunction
function! s:GistPostBuffers(private, desc, anonymous) abort
let bufnrs = range(1, bufnr('$'))
let bn = bufnr('%')
let query = []
let gist = { "files" : {}, "description": "","public": function('webapi#json#true') }
if a:desc !=# ' ' | let gist['description'] = a:desc | endif
if a:private | let gist['public'] = function('webapi#json#false') | endif
let index = 1
for bufnr in bufnrs
if !bufexists(bufnr) || buflisted(bufnr) == 0
continue
endif
echo 'Creating gist content'.index.'... '
silent! exec 'buffer!' bufnr
let content = join(getline(1, line('$')), "\n")
let filename = s:get_current_filename(index)
let gist.files[filename] = { "content": content, "filename": filename }
let index = index + 1
endfor
silent! exec 'buffer!' bn
let header = {"Content-Type": "application/json"}
if !a:anonymous
let auth = s:GistGetAuthHeader()
if len(auth) == 0
redraw
echohl ErrorMsg | echomsg v:errmsg | echohl None
return
endif
let header['Authorization'] = auth
endif
redraw | echon 'Posting it to gist... '
let res = webapi#http#post(g:gist_api_url.'gists', webapi#json#encode(gist), header)
if res.status =~# '^2'
let obj = webapi#json#decode(res.content)
let loc = obj['html_url']
let b:gist = {
\ "filename": filename,
\ "id": matchstr(loc, '[^/]\+$'),
\ "description": gist['description'],
\ "private": a:private,
\}
if s:update_GistID(b:gist['id'])
Gist -e
endif
redraw | echomsg 'Done: '.loc
else
let loc = ''
echohl ErrorMsg | echomsg 'Post failed: ' . res.message | echohl None
endif
return loc
endfunction
function! gist#Gist(count, bang, line1, line2, ...) abort
redraw
let bufname = bufname('%')
" find GistID: in content , then we should just update
let gistid = ''
let gistls = ''
let gistnm = ''
let gistdesc = ' '
let private = get(g:, 'gist_post_private', 0)
let multibuffer = 0
let clipboard = 0
let deletepost = 0
let editpost = 0
let anonymous = get(g:, 'gist_post_anonymous', 0)
let openbrowser = 0
let listmx = '^\%(-l\|--list\)\s*\([^\s]\+\)\?$'
let bufnamemx = '^' . s:bufprefix .'\(\zs[0-9a-f]\+\ze\|\zs[0-9a-f]\+\ze[/\\].*\)$'
if strlen(g:github_user) == 0 && anonymous == 0
echohl ErrorMsg | echomsg 'You have not configured a Github account. Read '':help gist-setup''.' | echohl None
return
endif
if a:bang == '!'
let gistidbuf = ''
elseif bufname =~# bufnamemx
let gistidbuf = matchstr(bufname, bufnamemx)
elseif exists('b:gist') && has_key(b:gist, 'id')
let gistidbuf = b:gist['id']
else
let gistidbuf = matchstr(join(getline(a:line1, a:line2), "\n"), 'GistID:\s*\zs\w\+')
endif
let args = (a:0 > 0) ? s:shellwords(a:1) : []
for arg in args
if arg =~# '^\(-h\|--help\)$\C'
help :Gist
return
elseif arg =~# '^\(-g\|--git\)$\C' && gistidbuf !=# '' && g:gist_api_url ==# 'https://api.github.com/' && has_key(b:, 'gist') && has_key(b:gist, 'id')
echo printf('git clone git@github.com:%s', b:gist['id'])
return
elseif arg =~# '^\(-G\|--gitclone\)$\C' && gistidbuf !=# '' && g:gist_api_url ==# 'https://api.github.com/' && has_key(b:, 'gist') && has_key(b:gist, 'id')
exe '!' printf('git clone git@github.com:%s', b:gist['id'])
return
elseif arg =~# '^\(-la\|--listall\)$\C'
let gistls = '-all'
elseif arg =~# '^\(-ls\|--liststar\)$\C'
let gistls = 'starred'
elseif arg =~# '^\(-l\|--list\)$\C'
if get(g:, 'gist_show_privates')
let gistls = 'mine'
else
let gistls = g:github_user
endif
elseif arg =~# '^\(-m\|--multibuffer\)$\C'
let multibuffer = 1
elseif arg =~# '^\(-p\|--private\)$\C'
let private = 1
elseif arg =~# '^\(-P\|--public\)$\C'
let private = 0
elseif arg =~# '^\(-a\|--anonymous\)$\C'
let anonymous = 1
elseif arg =~# '^\(-s\|--description\)$\C'
let gistdesc = ''
elseif arg =~# '^\(-c\|--clipboard\)$\C'
let clipboard = 1
elseif arg =~# '^--rawurl$\C' && gistidbuf !=# '' && g:gist_api_url ==# 'https://api.github.com/'
let gistid = gistidbuf
echo 'https://gist.github.com/raw/'.gistid
return
elseif arg =~# '^\(-d\|--delete\)$\C' && gistidbuf !=# ''
let gistid = gistidbuf
let deletepost = 1
elseif arg =~# '^\(-e\|--edit\)$\C'
if gistidbuf !=# ''
let gistid = gistidbuf
endif
let editpost = 1
elseif arg =~# '^\(+1\|--star\)$\C' && gistidbuf !=# ''
let auth = s:GistGetAuthHeader()
if len(auth) == 0
echohl ErrorMsg | echomsg v:errmsg | echohl None
else
let gistid = gistidbuf
let res = webapi#http#post(g:gist_api_url.'gists/'.gistid.'/star', '', { "Authorization": auth }, 'PUT')
if res.status =~# '^2'
echomsg 'Starred' gistid
else
echohl ErrorMsg | echomsg 'Star failed' | echohl None
endif
endif
return
elseif arg =~# '^\(-1\|--unstar\)$\C' && gistidbuf !=# ''
let auth = s:GistGetAuthHeader()
if len(auth) == 0
echohl ErrorMsg | echomsg v:errmsg | echohl None
else
let gistid = gistidbuf
let res = webapi#http#post(g:gist_api_url.'gists/'.gistid.'/star', '', { "Authorization": auth }, 'DELETE')
if res.status =~# '^2'
echomsg 'Unstarred' gistid
else
echohl ErrorMsg | echomsg 'Unstar failed' | echohl None
endif
endif
return
elseif arg =~# '^\(-f\|--fork\)$\C' && gistidbuf !=# ''
let auth = s:GistGetAuthHeader()
if len(auth) == 0
echohl ErrorMsg | echomsg v:errmsg | echohl None
return
else
let gistid = gistidbuf
let res = webapi#http#post(g:gist_api_url.'gists/'.gistid.'/fork', '', { "Authorization": auth })
if res.status =~# '^2'
let obj = webapi#json#decode(res.content)
let gistid = obj['id']
else
echohl ErrorMsg | echomsg 'Fork failed' | echohl None
return
endif
endif
elseif arg =~# '^\(-b\|--browser\)$\C'
let openbrowser = 1
elseif arg !~# '^-' && len(gistnm) == 0
if gistdesc !=# ' '
let gistdesc = matchstr(arg, '^\s*\zs.*\ze\s*$')
elseif editpost == 1 || deletepost == 1
let gistnm = arg
elseif len(gistls) > 0 && arg !=# '^\w\+$\C'
let gistls = arg
elseif arg =~# '^[0-9a-z]\+$\C'
let gistid = arg
else
echohl ErrorMsg | echomsg 'Invalid arguments: '.arg | echohl None
unlet args
return 0
endif
elseif len(arg) > 0
echohl ErrorMsg | echomsg 'Invalid arguments: '.arg | echohl None
unlet args
return 0
endif
endfor
unlet args
"echom "gistid=".gistid
"echom "gistls=".gistls
"echom "gistnm=".gistnm
"echom "gistdesc=".gistdesc
"echom "private=".private
"echom "clipboard=".clipboard
"echom "editpost=".editpost
"echom "deletepost=".deletepost
if gistidbuf !=# '' && gistid ==# '' && editpost == 0 && deletepost == 0 && anonymous == 0
let editpost = 1
let gistid = gistidbuf
endif
if len(gistls) > 0
call s:GistList(gistls, 1)
elseif len(gistid) > 0 && editpost == 0 && deletepost == 0
call s:GistGet(gistid, clipboard)
else
let url = ''
if multibuffer == 1
let url = s:GistPostBuffers(private, gistdesc, anonymous)
else
if a:count < 1
let content = join(getline(a:line1, a:line2), "\n")
else
let save_regcont = @"
let save_regtype = getregtype('"')
silent! normal! gvy
let content = @"
call setreg('"', save_regcont, save_regtype)
endif
if editpost == 1
let url = s:GistUpdate(content, gistid, gistnm, gistdesc)
elseif deletepost == 1
call s:GistDelete(gistid)
else
let url = s:GistPost(content, private, gistdesc, anonymous)
endif
if a:count >= 1 && get(g:, 'gist_keep_selection', 0) == 1
silent! normal! gv
endif
endif
if type(url) == 1 && len(url) > 0
if get(g:, 'gist_open_browser_after_post', 0) == 1 || openbrowser
call s:open_browser(url)
endif
let gist_put_url_to_clipboard_after_post = get(g:, 'gist_put_url_to_clipboard_after_post', 1)
if gist_put_url_to_clipboard_after_post > 0 || clipboard
if gist_put_url_to_clipboard_after_post == 2
let url = url . "\n"
endif
if exists('g:gist_clip_command')
call system(g:gist_clip_command, url)
elseif has('clipboard')
let @+ = url
else
let @" = url
endif
endif
endif
endif
return 1
endfunction
function! s:GistGetAuthHeader() abort
if get(g:, 'gist_use_password_in_gitconfig', 0) != 0
let password = substitute(system('git config --get github.password'), "\n", '', '')
if password =~# '^!' | let password = system(password[1:]) | endif
return printf('basic %s', webapi#base64#b64encode(g:github_user.':'.password))
endif
let auth = ''
if !empty(get(g:, 'gist_token', $GITHUB_TOKEN))
let auth = 'token ' . get(g:, 'gist_token', $GITHUB_TOKEN)
elseif filereadable(s:gist_token_file)
let str = join(readfile(s:gist_token_file), '')
if type(str) == 1
let auth = str
endif
endif
if len(auth) > 0
return auth
endif
redraw
echohl WarningMsg
echo 'Gist.vim requires authorization to use the GitHub API. These settings are stored in "~/.gist-vim". If you want to revoke, do "rm ~/.gist-vim".'
echohl None
let password = inputsecret('GitHub Password for '.g:github_user.':')
if len(password) == 0
let v:errmsg = 'Canceled'
return ''
endif
let note = 'Gist.vim on '.hostname().' '.strftime('%Y/%m/%d-%H:%M:%S')
let note_url = 'http://www.vim.org/scripts/script.php?script_id=2423'
let insecureSecret = printf('basic %s', webapi#base64#b64encode(g:github_user.':'.password))
let res = webapi#http#post(g:gist_api_url.'authorizations', webapi#json#encode({
\ "scopes" : ["gist"],
\ "note" : note,
\ "note_url" : note_url,
\}), {
\ "Content-Type" : "application/json",
\ "Authorization" : insecureSecret,
\})
let h = filter(res.header, 'stridx(v:val, "X-GitHub-OTP:") == 0')
if len(h)
let otp = inputsecret('OTP:')
if len(otp) == 0
let v:errmsg = 'Canceled'
return ''
endif
let res = webapi#http#post(g:gist_api_url.'authorizations', webapi#json#encode({
\ "scopes" : ["gist"],
\ "note" : note,
\ "note_url" : note_url,
\}), {
\ "Content-Type" : "application/json",
\ "Authorization" : insecureSecret,
\ "X-GitHub-OTP" : otp,
\})
endif
let authorization = webapi#json#decode(res.content)
if has_key(authorization, 'token')
let secret = printf('token %s', authorization.token)
call writefile([secret], s:gist_token_file)
if !(has('win32') || has('win64'))
call system('chmod go= '.s:gist_token_file)
endif
elseif has_key(authorization, 'message')
let secret = ''
let v:errmsg = authorization.message
endif
return secret
endfunction
let s:extmap = extend({
\".adb": "ada",
\".ahk": "ahk",
\".arc": "arc",
\".as": "actionscript",
\".asm": "asm",
\".asp": "asp",
\".aw": "php",
\".b": "b",
\".bat": "bat",
\".befunge": "befunge",
\".bmx": "bmx",
\".boo": "boo",
\".c-objdump": "c-objdump",
\".c": "c",
\".cfg": "cfg",
\".cfm": "cfm",
\".ck": "ck",
\".cl": "cl",
\".clj": "clj",
\".cmake": "cmake",
\".coffee": "coffee",
\".cpp": "cpp",
\".cppobjdump": "cppobjdump",
\".cs": "csharp",
\".css": "css",
\".cw": "cw",
\".d-objdump": "d-objdump",
\".d": "d",
\".darcspatch": "darcspatch",
\".diff": "diff",
\".duby": "duby",
\".dylan": "dylan",
\".e": "e",
\".ebuild": "ebuild",
\".eclass": "eclass",
\".el": "lisp",
\".erb": "erb",
\".erl": "erlang",
\".f90": "f90",
\".factor": "factor",
\".feature": "feature",
\".fs": "fs",
\".fy": "fy",
\".go": "go",
\".groovy": "groovy",
\".gs": "gs",
\".gsp": "gsp",
\".haml": "haml",
\".hs": "haskell",
\".html": "html",
\".hx": "hx",
\".ik": "ik",
\".ino": "ino",
\".io": "io",
\".j": "j",
\".java": "java",
\".js": "javascript",
\".json": "json",
\".jsp": "jsp",
\".kid": "kid",
\".lhs": "lhs",
\".lisp": "lisp",
\".ll": "ll",
\".lua": "lua",
\".ly": "ly",
\".m": "objc",
\".mak": "mak",
\".man": "man",
\".mao": "mao",
\".matlab": "matlab",
\".md": "markdown",
\".minid": "minid",
\".ml": "ml",
\".moo": "moo",
\".mu": "mu",
\".mustache": "mustache",
\".mxt": "mxt",
\".myt": "myt",
\".n": "n",
\".nim": "nim",
\".nu": "nu",
\".numpy": "numpy",
\".objdump": "objdump",
\".ooc": "ooc",
\".parrot": "parrot",
\".pas": "pas",
\".pasm": "pasm",
\".pd": "pd",
\".phtml": "phtml",
\".pir": "pir",
\".pl": "perl",
\".po": "po",
\".py": "python",
\".pytb": "pytb",
\".pyx": "pyx",
\".r": "r",
\".raw": "raw",
\".rb": "ruby",
\".rhtml": "rhtml",
\".rkt": "rkt",
\".rs": "rs",
\".rst": "rst",
\".s": "s",
\".sass": "sass",
\".sc": "sc",
\".scala": "scala",
\".scm": "scheme",
\".scpt": "scpt",
\".scss": "scss",
\".self": "self",
\".sh": "sh",
\".sml": "sml",
\".sql": "sql",
\".st": "smalltalk",
\".swift": "swift",
\".tcl": "tcl",
\".tcsh": "tcsh",
\".tex": "tex",
\".textile": "textile",
\".tpl": "smarty",
\".twig": "twig",
\".txt" : "text",
\".v": "verilog",
\".vala": "vala",
\".vb": "vbnet",
\".vhd": "vhdl",
\".vim": "vim",
\".weechatlog": "weechatlog",
\".xml": "xml",
\".xq": "xquery",
\".xs": "xs",
\".yml": "yaml",
\}, get(g:, 'gist_extmap', {}))
let &cpo = s:save_cpo
unlet s:save_cpo
" vim:set et: