Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Version 7.2: This is an upgrade for Gist.vim: fixed many bugs.

  • Loading branch information...
commit 7f279e51590494a9b6af1180770e0b5f46d3a13b 1 parent 52df580
@mattn mattn authored committed
Showing with 338 additions and 343 deletions.
  1. +0 −215 README.mkd
  2. +283 −121 autoload/gist.vim
  3. +47 −6 doc/gist-vim.txt
  4. +8 −1 plugin/gist.vim
View
215 README.mkd
@@ -1,215 +0,0 @@
-### Gist.vim
-
-This is a vimscript for creating gists (http://gist.github.com).
-
-For the latest version please see https://github.com/mattn/gist-vim.
-
-## Usage:
-
-- Post current buffer to gist, using default privacy option.
-
- :Gist
-
-- Post selected text to gist, using default privacy option.
- This applies to all permutations listed below (except multi).
-
- :'<,'>Gist
-
-- Create a private gist.
-
- :Gist -p
-
-- Create a public gist.
- (Only relevant if you've set gists to be private by default.)
-
- :Gist -P
-
-> This is only relevant if you've set gists to be private by default;
-> if you get an empty gist list, try ":Gist --abandon".
-
-- Create a gist anonymously.
-
- :Gist -a
-
-- Create a gist with all open buffers.
-
- :Gist -m
-
-- Edit the gist (you need to have opened the gist buffer first).
- You can update the gist with the ":w" command within the gist buffer.
-
- :Gist -e
-
-- Edit the gist with name 'foo.js' (you need to have opened the gist buffer
- first).
-
- :Gist -e foo.js
-
-- Post/Edit with the description " (you need to have opened the gist buffer
- first). >
-
- :Gist -s something
- :Gist -e -s something
-
-- Delete the gist (you need to have opened the gist buffer first).
- Password authentication is needed.
-
- :Gist -d
-
-- Fork the gist (you need to have opened the gist buffer first).
- Password authentication is needed.
-
- :Gist -f
-
-- Star the gist (you need to have opened the gist buffer first).
- Password authentication is needed.
-
- :Gist +1
-
-- Unstar the gist (you need to have opened the gist buffer first).
- Password authentication is needed.
-
- :Gist -1
-
-- Get gist XXXXX.
-
- :Gist XXXXX
-
-- Get gist XXXXX and add to clipboard.
-
- :Gist -c XXXXX
-
-- List your public gists.
-
- :Gist -l
-
-- List gists from user "mattn".
-
- :Gist -l mattn
-
-- List everyone's gists.
-
- :Gist -la
-
-- List gists from your starred gists.
-
- :Gist -ls
-
-## Tips:
-
-If you set g:gist_clip_command, gist.vim will copy the gist code with option
-'-c'.
-
-- Mac:
-
- let g:gist_clip_command = 'pbcopy'
-
-- Linux:
-
- let g:gist_clip_command = 'xclip -selection clipboard'
-
-- Others (cygwin?):
-
- let g:gist_clip_command = 'putclip'
-
-If you want to detect filetype from the filename:
-
- let g:gist_detect_filetype = 1
-
-If you want to open browser after the post:
-
- let g:gist_open_browser_after_post = 1
-
-If you want to change the browser:
-
- let g:gist_browser_command = 'w3m %URL%'
-
-or:
-
- let g:gist_browser_command = 'opera %URL% &'
-
-On windows, this should work with your user settings.
-
-If you want to show your private gists with ":Gist -l":
-
- let g:gist_show_privates = 1
-
-If you want your gist to be private by default:
-
- let g:gist_post_private = 1
-
-If you want to manipulate multiple files in a gist:
-
- let g:gist_get_multiplefile = 1
-
-If you want to use on Github Enterprise:
-
- let g:github_api_url = 'http://your-github-enterprise-domain/api/v3'
-
-You need to either set global git config:
-
- $ git config --global github.user Username
-
-## License:
-
- Copyright 2010 by Yasuhiro Matsumoto
- modification, are permitted provided that the following conditions are met:
-
- 1. Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
- 2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
- FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
- REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
- INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
- SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
- STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
- ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
- OF THE POSSIBILITY OF SUCH DAMAGE.
-
-
-## Install:
-
-Copy it to your plugin directory.
-gist.vim will create a curl cookie-jar file in your runtimepath.
-
-- rtp:
- - autoload/gist.vim
- - plugin/gist.vim
-
-If you want to uninstall gist.vim, remember to also remove `~/.gist-vim`.
-
-You need to install webapi-vim also:
-
- http://www.vim.org/scripts/script.php?script_id=4019
-
-If you want to use latest one:
-
- https://github.com/mattn/webapi-vim
-
-## Requirements:
-
-- curl command (http://curl.haxx.se/)
-- webapi-vim (https://github.com/mattn/webapi-vim)
-- and if you want to use your git profile, the git command-line client.
-
-## Setup:
-
-This plugin uses github API v3. Setting value is stored in `~/.gist-vim`.
-gist-vim have two ways to access APIs.
-
-First, you need to set your Github username in global git config:
-
- $ git config --global github.user Username
-
-Then, gist.vim will ask for your password to create an authorization when you
-first use it. The password is not stored and only the OAuth access token will
-be kept for later use. You can revoke the token at any time from the list of
-["Authorized applications" on Github's "Account Settings" page](https://github.com/settings/applications).
View
404 autoload/gist.vim
@@ -1,14 +1,20 @@
"=============================================================================
" File: gist.vim
" Author: Yasuhiro Matsumoto <mattn.jp@gmail.com>
-" Last Change: 13-Dec-2012.
-" Version: 7.1
+" Last Change: 19-Oct-2014.
+" Version: 7.2
" WebPage: http://github.com/mattn/gist-vim
" License: BSD
let s:save_cpo = &cpo
set cpo&vim
+if exists('g:gist_disabled') && g:gist_disabled == 1
+ function gist#Gist(...)
+ endfunction
+ finish
+endif
+
if !exists('g:github_user') && !executable('git')
echohl ErrorMsg | echomsg "Gist: require 'git' command" | echohl None
finish
@@ -19,18 +25,47 @@ if !executable('curl')
finish
endif
-let s:configfile = expand('~/.gist-vim')
+if globpath(&rtp, 'autoload/webapi/http.vim') == ''
+ echohl ErrorMsg | echomsg "Gist: require 'webapi', install https://github.com/mattn/webapi-vim" | echohl None
+ finish
+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 s:system = function(get(g:, 'webapi#system_function', 'system'))
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:github_api_url')
- let g:github_api_url = 'https://api.github.com'
+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()
@@ -86,26 +121,32 @@ function! s:format_gist(gist)
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
- return printf("gist: %s %s%s", a:gist.id, type(a:gist.description)==0?"": a:gist.description, code)
+ 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')
+ return printf("gist: %s %s %s%s", a:gist.id, name, desc, code)
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)
+function! s:GistList(gistls, page) abort
if a:gistls == '-all'
- let url = g:github_api_url.'/gists/public'
+ let url = g:gist_api_url.'gists/public'
elseif get(g:, 'gist_show_privates', 0) && a:gistls == 'starred'
- let url = g:github_api_url.'/gists/starred'
+ let url = g:gist_api_url.'gists/starred'
elseif get(g:, 'gist_show_privates') && a:gistls == 'mine'
- let url = g:github_api_url.'/gists'
+ let url = g:gist_api_url.'gists'
else
- let url = g:github_api_url.'/users/'.a:gistls.'/gists'
+ let url = g:gist_api_url.'users/'.a:gistls.'/gists'
endif
let winnum = bufwinnr(bufnr(s:bufprefix.a:gistls))
if winnum != -1
@@ -114,7 +155,13 @@ function! s:GistList(gistls, page)
endif
setlocal modifiable
else
- exec 'silent noautocmd split' s:bufprefix.a:gistls
+ 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('$'))
@@ -131,7 +178,7 @@ function! s:GistList(gistls, page)
if len(auth) == 0
bw!
redraw
- echohl ErrorMsg | echomsg 'Canceled' | echohl None
+ echohl ErrorMsg | echomsg v:errmsg | echohl None
return
endif
let res = webapi#http#get(url, '', { "Authorization": auth })
@@ -147,7 +194,7 @@ function! s:GistList(gistls, page)
redraw
echohl ErrorMsg | echomsg content.message | echohl None
if content.message == 'Bad credentials'
- call delete(s:configfile)
+ call delete(s:gist_token_file)
endif
return
endif
@@ -163,6 +210,7 @@ function! s:GistList(gistls, page)
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> <s-cr> :call <SID>GistListAction(1)<cr>
@@ -171,16 +219,72 @@ function! s:GistList(gistls, page)
redraw | echo ''
endfunction
+function! gist#list_recursively(user, ...)
+ 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)
+ 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, ...)
let page = get(a:000, 0, 0)
if a:user == '-all'
- let url = g:github_api_url.'/gists/public'
+ let url = g:gist_api_url.'gists/public'
elseif get(g:, 'gist_show_privates', 0) && a:user == 'starred'
- let url = g:github_api_url.'/gists/starred'
+ let url = g:gist_api_url.'gists/starred'
elseif get(g:, 'gist_show_privates') && a:user == 'mine'
- let url = g:github_api_url.'/gists'
+ let url = g:gist_api_url.'gists'
else
- let url = g:github_api_url.'/users/'.a:user.'/gists'
+ let url = g:gist_api_url.'users/'.a:user.'/gists'
endif
let auth = s:GistGetAuthHeader()
@@ -191,12 +295,12 @@ function! gist#list(user, ...)
return webapi#json#decode(res.content)
endfunction
-function! s:GistGetFileName(gistid)
+function! s:GistGetFileName(gistid) abort
let auth = s:GistGetAuthHeader()
if len(auth) == 0
return ''
endif
- let res = webapi#http#get(g:github_api_url.'/gists/'.a:gistid, '', { "Authorization": auth })
+ 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]
@@ -204,12 +308,12 @@ function! s:GistGetFileName(gistid)
return ''
endfunction
-function! s:GistDetectFiletype(gistid)
+function! s:GistDetectFiletype(gistid) abort
let auth = s:GistGetAuthHeader()
if len(auth) == 0
return ''
endif
- let res = webapi#http#get(g:github_api_url.'/gists/'.a:gistid, '', { "Authorization": auth })
+ 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')
@@ -221,9 +325,13 @@ function! s:GistDetectFiletype(gistid)
silent! exec "setlocal ft=".tolower(type)
endfunction
-function! s:GistWrite(fname)
+function! s:GistWrite(fname) abort
if substitute(a:fname, '\\', '/', 'g') == expand("%:p:gs@\\@/@")
- Gist -e
+ 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)
@@ -231,12 +339,17 @@ function! s:GistWrite(fname)
endif
endfunction
-function! s:GistGet(gistid, clipboard)
+function! s:GistGet(gistid, clipboard) abort
redraw | echon 'Getting gist... '
- let res = webapi#http#get(g:github_api_url.'/gists/'.a:gistid, '', { "Authorization": s:GistGetAuthHeader() })
- let status = matchstr(matchstr(res.header, '^Status:'), '^[^:]\+: \zs.*')
- if status =~ '^2'
- let gist = webapi#json#decode(res.content)
+ 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
@@ -259,9 +372,16 @@ function! s:GistGet(gistid, clipboard)
endif
setlocal modifiable
else
- exec 'silent noautocmd new'
+ if num_file == 1
+ silent only!
+ endif
+ if get(g:, 'gist_list_vsplit', 0)
+ exec 'silent noautocmd rightbelow vnew'
+ else
+ exec 'silent noautocmd rightbelow new'
+ endif
setlocal noswapfile
- exec 'noautocmd file' s:bufprefix.a:gistid."/".fnameescape(filename)
+ silent exec 'noautocmd file' s:bufprefix.a:gistid."/".fnameescape(filename)
endif
set undolevels=-1
filetype detect
@@ -310,7 +430,7 @@ function! s:GistGet(gistid, clipboard)
endif
endfunction
-function! s:GistListAction(shift)
+function! s:GistListAction(shift) abort
let line = getline('.')
let mx = '^gist:\s*\zs\(\w\+\)\ze.*'
if line =~# mx
@@ -328,7 +448,7 @@ function! s:GistListAction(shift)
endif
endfunction
-function! s:GistUpdate(content, gistid, gistnm, desc)
+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, 'private') && b:gist.private | let gist["public"] = function('webapi#json#false') | endif
@@ -343,7 +463,7 @@ function! s:GistUpdate(content, gistid, gistnm, desc)
let auth = s:GistGetAuthHeader()
if len(auth) == 0
redraw
- echohl ErrorMsg | echomsg 'Canceled' | echohl None
+ echohl ErrorMsg | echomsg v:errmsg | echohl None
return
endif
@@ -352,9 +472,8 @@ function! s:GistUpdate(content, gistid, gistnm, desc)
if a:desc != ' '
let gist["description"] = a:desc
else
- let res = webapi#http#get(g:github_api_url.'/gists/'.a:gistid, '', { "Authorization": auth })
- let status = matchstr(matchstr(res.header, '^Status:'), '^[^:]\+: \zs.*')
- if status =~ '^2'
+ 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
@@ -363,13 +482,12 @@ function! s:GistUpdate(content, gistid, gistnm, desc)
let gist.files[filename] = { "content": a:content, "filename": filename }
redraw | echon 'Updating gist... '
- let res = webapi#http#post(g:github_api_url.'/gists/' . a:gistid,
+ let res = webapi#http#post(g:gist_api_url.'gists/' . a:gistid,
\ webapi#json#encode(gist), {
\ "Authorization": auth,
\ "Content-Type": "application/json",
\})
- let status = matchstr(matchstr(res.header, '^Status:'), '^[^:]\+: \zs.*')
- if status =~ '^2'
+ if res.status =~ '^2'
let obj = webapi#json#decode(res.content)
let loc = obj["html_url"]
redraw | echomsg 'Done: '.loc
@@ -377,34 +495,31 @@ function! s:GistUpdate(content, gistid, gistnm, desc)
setlocal nomodified
else
let loc = ''
- let status = matchstr(status, '^\d\+\s*\zs.*')
- echohl ErrorMsg | echomsg 'Post failed: '.status | echohl None
+ echohl ErrorMsg | echomsg 'Post failed: ' . res.message | echohl None
endif
return loc
endfunction
-function! s:GistDelete(gistid)
+function! s:GistDelete(gistid) abort
let auth = s:GistGetAuthHeader()
if len(auth) == 0
redraw
- echohl ErrorMsg | echomsg 'Canceled' | echohl None
+ echohl ErrorMsg | echomsg v:errmsg | echohl None
return
endif
redraw | echon 'Deleting gist... '
- let res = webapi#http#post(g:github_api_url.'/gists/'.a:gistid, '', {
+ let res = webapi#http#post(g:gist_api_url.'gists/'.a:gistid, '', {
\ "Authorization": auth,
\ "Content-Type": "application/json",
\}, 'DELETE')
- let status = matchstr(matchstr(res.header, '^Status:'), '^[^:]\+: \zs.*')
- if status =~ '^2'
+ if res.status =~ '^2'
redraw | echomsg 'Done: '
if exists('b:gist')
unlet b:gist
endif
else
- let status = matchstr(status, '^\d\+\s*\zs.*')
- echohl ErrorMsg | echomsg 'Delete failed: '.status | echohl None
+ echohl ErrorMsg | echomsg 'Delete failed: ' . res.message | echohl None
endif
endfunction
@@ -422,6 +537,20 @@ function! s:get_current_filename(no)
return filename
endfunction
+function! s:update_GistID(id)
+ 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
"
@@ -429,15 +558,11 @@ endfunction
" it will just update it.
" -- by c9s
"
-" embedded gist url format:
-"
-" Gist: https://gist.github.com/123123
-"
" embedded gist id format:
"
" GistID: 123123
"
-function! s:GistPost(content, private, desc, anonymous)
+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
@@ -449,16 +574,15 @@ function! s:GistPost(content, private, desc, anonymous)
let auth = s:GistGetAuthHeader()
if len(auth) == 0
redraw
- echohl ErrorMsg | echomsg 'Canceled' | echohl None
+ 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:github_api_url.'/gists', webapi#json#encode(gist), header)
- let status = matchstr(matchstr(res.header, '^Status:'), '^[^:]\+: \zs.*')
- if status =~ '^2'
+ 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"]
redraw | echomsg 'Done: '.loc
@@ -468,15 +592,17 @@ function! s:GistPost(content, private, desc, anonymous)
\ "description": gist['description'],
\ "private": a:private,
\}
+ if s:update_GistID(b:gist["id"])
+ Gist -e
+ endif
else
let loc = ''
- let status = matchstr(status, '^\d\+\s*\zs.*')
- echohl ErrorMsg | echomsg 'Post failed: '.status | echohl None
+ echohl ErrorMsg | echomsg 'Post failed: '. res.message | echohl None
endif
return loc
endfunction
-function! s:GistPostBuffers(private, desc, anonymous)
+function! s:GistPostBuffers(private, desc, anonymous) abort
let bufnrs = range(1, bufnr("$"))
let bn = bufnr('%')
let query = []
@@ -504,34 +630,36 @@ function! s:GistPostBuffers(private, desc, anonymous)
let auth = s:GistGetAuthHeader()
if len(auth) == 0
redraw
- echohl ErrorMsg | echomsg 'Canceled' | echohl None
+ 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:github_api_url.'/gists', webapi#json#encode(gist), header)
- let status = matchstr(matchstr(res.header, '^Status:'), '^[^:]\+: \zs.*')
- if status =~ '^2'
+ 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"]
redraw | echomsg 'Done: '.loc
- let b:gist = {"id": matchstr(loc, '[^/]\+$'), "filename": filename, "private": a:private}
+ let b:gist = {
+ \ "filename": filename,
+ \ "id": matchstr(loc, '[^/]\+$'),
+ \ "description": gist['description'],
+ \ "private": a:private,
+ \}
+ if s:update_GistID(b:gist["id"])
+ Gist -e
+ endif
else
let loc = ''
- let status = matchstr(status, '^\d\+\s*\zs.*')
- echohl ErrorMsg | echomsg 'Post failed: '.status | echohl None
+ echohl ErrorMsg | echomsg 'Post failed: ' . res.message | echohl None
endif
return loc
endfunction
-function! gist#Gist(count, line1, line2, ...)
+function! gist#Gist(count, line1, line2, ...) abort
redraw
- if strlen(g:github_user) == 0
- echohl ErrorMsg | echomsg "You don't have github account. read ':help gist-vim-setup'." | echohl None
- return
- endif
let bufname = bufname("%")
" find GistID: in content , then we should just update
let gistid = ''
@@ -543,11 +671,18 @@ function! gist#Gist(count, line1, line2, ...)
let clipboard = 0
let deletepost = 0
let editpost = 0
- let anonymous = 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 don't have github account. read ':help gist-vim-setup'." | echohl None
+ return
+ endif
if 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
@@ -557,6 +692,12 @@ function! gist#Gist(count, line1, line2, ...)
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'
@@ -579,6 +720,10 @@ function! gist#Gist(count, line1, line2, ...)
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
@@ -588,12 +733,11 @@ function! gist#Gist(count, line1, line2, ...)
elseif arg =~ '^\(+1\|--star\)$\C' && gistidbuf != ''
let auth = s:GistGetAuthHeader()
if len(auth) == 0
- echohl ErrorMsg | echomsg 'Canceled' | echohl None
+ echohl ErrorMsg | echomsg v:errmsg | echohl None
else
let gistid = gistidbuf
- let res = webapi#http#post(g:github_api_url.'/gists/'.gistid.'/star', '', { "Authorization": auth }, 'PUT')
- let status = matchstr(matchstr(res.header, '^Status:'), '^[^:]\+: \zs.*')
- if status =~ '^2'
+ let res = webapi#http#post(g:gist_api_url.'gists/'.gistid.'/star', '', { "Authorization": auth }, 'PUT')
+ if res.status =~ '^2'
echomsg "Stared" gistid
else
echohl ErrorMsg | echomsg 'Star failed' | echohl None
@@ -603,11 +747,11 @@ function! gist#Gist(count, line1, line2, ...)
elseif arg =~ '^\(-1\|--unstar\)$\C' && gistidbuf != ''
let auth = s:GistGetAuthHeader()
if len(auth) == 0
- echohl ErrorMsg | echomsg 'Canceled' | echohl None
+ echohl ErrorMsg | echomsg v:errmsg | echohl None
else
let gistid = gistidbuf
- let res = webapi#http#post(g:github_api_url.'/gists/'.gistid.'/star', '', { "Authorization": auth }, 'DELETE')
- if status =~ '^2'
+ let res = webapi#http#post(g:gist_api_url.'gists/'.gistid.'/star', '', { "Authorization": auth }, 'DELETE')
+ if res.status =~ '^2'
echomsg "Unstared" gistid
else
echohl ErrorMsg | echomsg 'Unstar failed' | echohl None
@@ -617,13 +761,12 @@ function! gist#Gist(count, line1, line2, ...)
elseif arg =~ '^\(-f\|--fork\)$\C' && gistidbuf != ''
let auth = s:GistGetAuthHeader()
if len(auth) == 0
- echohl ErrorMsg | echomsg 'Canceled' | echohl None
+ echohl ErrorMsg | echomsg v:errmsg | echohl None
return
else
let gistid = gistidbuf
- let res = webapi#http#post(g:github_api_url.'/gists/'.gistid.'/fork', '', { "Authorization": auth })
- let status = matchstr(matchstr(res.header, '^Status:'), '^[^:]\+: \zs.*')
- if status =~ '^2'
+ 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
@@ -631,6 +774,8 @@ function! gist#Gist(count, line1, line2, ...)
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*$')
@@ -652,16 +797,16 @@ function! gist#Gist(count, line1, line2, ...)
endif
endfor
unlet args
- "echo "gistid=".gistid
- "echo "gistls=".gistls
- "echo "gistnm=".gistnm
- "echo "gistdesc=".gistdesc
- "echo "private=".private
- "echo "clipboard=".clipboard
- "echo "editpost=".editpost
- "echo "deletepost=".deletepost
-
- if gistidbuf != '' && gistid == '' && editpost == 0 && deletepost == 0
+ "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
@@ -696,11 +841,11 @@ function! gist#Gist(count, line1, line2, ...)
endif
endif
if len(url) > 0
- if get(g:, 'gist_open_browser_after_post', 0) == 1
+ 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
+ if gist_put_url_to_clipboard_after_post > 0 || clipboard
if gist_put_url_to_clipboard_after_post == 2
let url = url . "\n"
endif
@@ -717,15 +862,15 @@ function! gist#Gist(count, line1, line2, ...)
return 1
endfunction
-function! s:GistGetAuthHeader()
+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:configfile)
- let str = join(readfile(s:configfile), "")
+ if filereadable(s:gist_token_file)
+ let str = join(readfile(s:gist_token_file), "")
if type(str) == 1
let auth = str
endif
@@ -736,34 +881,51 @@ function! s:GistGetAuthHeader()
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".'
+ 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 insecureSecret = printf("basic %s", webapi#base64#b64encode(g:github_user.":".password))
- let res = webapi#http#post(g:github_api_url.'/authorizations', webapi#json#encode({
+ 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" : "Gist.vim on ".hostname(),
- \ "note_url" : "http://www.vim.org/scripts/script.php?script_id=2423"
+ \ "note" : note,
+ \ "note_url" : note_url,
\}), {
\ "Content-Type" : "application/json",
\ "Authorization" : insecureSecret,
+ \ "X-GitHub-OTP" : otp,
\})
- let authorization = webapi#json#decode(res.content)
- if has_key(authorization, 'token')
- let secret = printf("token %s", authorization.token)
- call writefile([secret], s:configfile)
- if !(has('win32') || has('win64'))
- call system("chmod go= ".s:configfile)
- endif
- elseif has_key(authorization, 'message')
- echohl WarningMsg
- echo authorization.message
- echohl None
- let secret = ''
+ 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
- else
+ elseif has_key(authorization, 'message')
let secret = ''
+ let v:errmsg = authorization.message
endif
return secret
endfunction
View
53 doc/gist-vim.txt
@@ -6,6 +6,7 @@ License |gist-vim-license|
Install |gist-vim-install|
Requirements |gist-vim-requirements|
Setup |gist-vim-setup|
+FAQ |gist-vim-faq|
This is a vimscript for creating gists (http://gist.github.com)
@@ -18,7 +19,7 @@ USAGE *:Gist* *gist-vim-usage*
:Gist
<
-- Post selected text to gist, using defualt privacy option.
+- Post selected text to gist, using default privacy option.
This applies to all permutations listed below (except multi). >
:'<,'>Gist
@@ -105,6 +106,10 @@ USAGE *:Gist* *gist-vim-usage*
>
:Gist -ls
<
+- Open the gist on browser after you post or update it.
+>
+ :Gist -b
+<
==============================================================================
TIPS *gist-vim-tips*
@@ -142,14 +147,22 @@ If you want to show your private gists with ":Gist -l": >
let g:gist_show_privates = 1
<
+If you want your gist to be private by default: >
+
+ let g:gist_post_private = 1
+<
+If you want your gist to be anonymous by default: >
+
+ let g:gist_post_anonymous = 1
+<
If you want to edit all files for gists containing more than one: >
let g:gist_get_multiplefile = 1
<
-If you want to use on Github Enterprise: >
+If you want to use on GitHub Enterprise: >
- let g:github_api_url = 'http://your-github-enterprise-domain/api/v3'
+ let g:gist_api_url = 'http://your-github-enterprise-domain/api/v3'
<
If you want to update a gist, embed >
@@ -160,6 +173,18 @@ in your local file, then call >
:Gist
>
+
+If you want to update a gist when only |:w!|: >
+
+ " :w and :w! update a gist.
+ let g:gist_update_on_write = 1
+
+ " Only :w! updates a gist.
+ let g:gist_update_on_write = 2
+>
+All other values are treated as 1.
+This variable's value is 1 by default.
+
==============================================================================
LICENSE *gist-vim-license*
@@ -215,19 +240,27 @@ REQUIREMENTS *gist-vim-requirements*
==============================================================================
SETUP *gist-vim-setup*
-This plugin uses github API v3. Setting value is stored in `~/.gist.vim`.
+This plugin uses GitHub API v3. Setting value is stored in `~/.gist-vim`.
gist-vim have two ways to access APIs.
-First, you need to set your Github username in global git config:
+First, you need to set your GitHub username in global git config:
>
$ git config --global github.user Username
<
Then, gist.vim will ask for your password to create an authorization when you
first use it. The password is not stored and only the OAuth access token will
be kept for later use. You can revoke the token at any time from the list of
-"Authorized applications" on Github's "Account Settings" page.
+"Authorized applications" on GitHub's "Account Settings" page.
(https://github.com/settings/applications)
+If you have two-factor authentication enabled on GitHub, you'll see the message
+"Must specify two-factor authentication OTP code." In this case, you need to
+create a "Personal Access Token" on GitHub's "Account Settings" page
+(https://github.com/settings/applications) and place it in a file
+named ~/.gist-vim like this:
+>
+ token xxxxx
+<
If you happen to have your password already written in ~/.gitconfig like
below:
>
@@ -240,6 +273,14 @@ Then, add following into your ~/.vimrc
<
This is not secure at all, so strongly discouraged.
+NOTE: the username is optional if you only send anonymous gists.
+
+==============================================================================
+FAQ *gist-vim-faq*
+
+Q. :Gist give Forbidden error
+A. Try to delete ~/.gist-vim. And authenticate again.
+
==============================================================================
THANKS *gist-vim-thanks*
View
9 plugin/gist.vim
@@ -11,6 +11,13 @@ if &cp || (exists('g:loaded_gist_vim') && g:loaded_gist_vim)
endif
let g:loaded_gist_vim = 1
-command! -nargs=? -range=% Gist :call gist#Gist(<count>, <line1>, <line2>, <f-args>)
+function! s:CompleteArgs(arg_lead,cmdline,cursor_pos)
+ return ["-p", "-P", "-a", "-m", "-e", "-s", "-d", "+1", "-1", "-f", "-c", "-l", "-la", "-ls", "-b",
+ \ "--listall", "--liststar", "--list", "--multibuffer", "--private", "--public", "--anonymous", "--description", "--clipboard",
+ \ "--rawurl", "--delete", "--edit", "--star", "--unstar", "--fork", "--browser"
+ \ ]
+endfunction
+
+command! -nargs=? -range=% -complete=customlist,s:CompleteArgs Gist :call gist#Gist(<count>, <line1>, <line2>, <f-args>)
" vim:set et:
Please sign in to comment.
Something went wrong with that request. Please try again.