"============================================================================= " File: gist.vim " Author: Yasuhiro Matsumoto " Last Change: 10-Oct-2016. " Version: 7.3 " WebPage: http://github.com/mattn/gist-vim " 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 :call GistListAction(0) nnoremap o :call GistListAction(0) nnoremap b :call GistListAction(1) nnoremap y :call GistListAction(2) nnoremap p :call GistListAction(3) nnoremap :bw nnoremap :call GistListAction(1) 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 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 call s:GistWrite(expand("")) 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('\:\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-vim-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 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: