1

I use gh (the official GitHub CLI tool) to edit my gists from the terminal. When I issue gh gist edit <gist-ID> then Vim opens, I do the deed, and when I save the file and quit Vim (by using :wq), the gist will get updated.

My problem is that if I need to do subsequent edits, and use the same gh command above, it does open up the gist, but the undo buffer is empty (because it is another temporary file). It would be helpful to send a signal to the terminal that the file has been closed (I assume that is what triggers the push) but without exiting Vim. Is this possible?

EDIT: Just realized that even if this is possible, I have other trouble on my hand, because the subsequent closure of the file may not trigger anything and/or even deleted from /tmp. Anyway, still interested:)

1
2

So if I understand you correctly you would like to trigger gist publish from within spawned from gh gist edit <gist-ID> vim without closing said vim.

There is no gh gist push or similar that you could use in :!gh ... command, but what you can try is to use regular !git push command -- each gist in github is a separate git repo.

Have a look at the vimscript as an inspiration: https://gist.github.com/habamax/2b99e5eb82500d88418bf9e640918dd3

There as I already pointed I use gh and git tools to edit and publish existing files as gists. The command I use in the end to publish a gist is:

call system("git add -A && git diff-index --quiet HEAD || git commit -m 'vim-update' && git push")

Provided I am in the temp directory gist repo was cloned to.

For the sake of the SE rules, here is the full script:

" Author: Maxim Kim <habamax@gmail.com>
" Desc: Sync current buffer with the github gist having the same file name.
"
" Prereqs:
" 1. Install and setup https://cli.github.com/
" 2. Put this file to ~/.vim/autoload/gist.vim
"
" Usage: Open file and :call gist#sync()
"
" Create helper command if needed
" command! GistSync call gist#sync()


func! gist#sync() abort
    if empty(bufname())
        echohl Error
        echomsg "Can't sync empty buffer!"
        echohl None
        return
    elseif empty(get(b:, 'gist_repo', '')) && !s:gist_init()
        echohl Error
        echomsg "Can't sync '" .. expand("%:t") .. "' gist!"
        echohl None
        return
    endif

    try
        exe printf('%write! %s/%s', b:gist_repo, expand('%:t'))
        let cwd = getcwd()
        exe 'lcd ' .. b:gist_repo
        call system("git add -A && git diff-index --quiet HEAD || git commit -m 'vim-update' && git push")
        if v:shell_error
            echohl Error
            echomsg "Can't sync '" .. expand("%:t") .. "' gist. Error code: " .. v:shell_error
            echohl None
            return
        else
            echomsg "Gist '" .. expand("%:t") .. "' is updated."
        endif
    finally
        exe 'lcd ' .. cwd
    endtry
endfunc


func! s:gist_init() abort
    let gist_id = s:gist_get_id()
    if empty(gist_id)
        echomsg "Gist '" .. expand("%:t") .. "' doesn't exist, creating..."
        try
            let cwd = getcwd()
            lcd %:p:h
            call system('gh gist create -p ' .. shellescape(expand("%:t")))
        finally
            exe 'lcd ' .. cwd
        endtry
        if v:shell_error
            echohl Error
            echomsg "Can't create '" .. expand("%:t") .. "' as a gist... Error code: " .. v:shell_error
            echohl None
            return v:false
        else
            let gist_id = s:gist_get_id()
        endif
        if exists("b:gist_repo")
            unlet b:gist_repo
        endif
    endif

    if !empty(gist_id) && empty(get(b:, 'gist_repo', ''))
        return s:gist_clone(gist_id)
    endif

    return v:true
endfunc


func! s:gist_clone(id) abort
    let gist_repo = tempname()
    call system(printf('gh gist clone %s %s', a:id, gist_repo))
    if v:shell_error
        echohl Error
        echomsg "Can't edit '" .. expand("%:t") .. "' as a gist... Error code: " .. v:shell_error
        echohl None
        return v:false
    else
        let b:gist_repo = gist_repo
        return v:true
    endif
endfunc


func! s:gist_info(gist) abort
    let gist = a:gist->split('\t')
    return [gist[0], gist[1]]
endfunc


func! s:gist_get_id() abort
    let gists = systemlist('gh gist list')->map({idx, val -> s:gist_info(val)})
    let idx = gists->copy()->map({idx, val -> val[1]})->index(expand('%:t'))
    if idx >= 0
        return gists[idx][0]
    else
        return ''
    endif
endfunc
3
  • This script looks great, thanks! I totally missed gh gist clone, which alone solves my problem, but your plugin is more useful (and educational to learn how to create a wrapper with Vimscript). Didn't accept it as answer (yet) because this doesn't answer the main question, but if there are no other gh-agnostic takes in a day or two then I will just change the question, and accept it. Thanks again!
    – toraritte
    Aug 29 at 18:55
  • @toraritte did you ever follow up and see if this answered your question?
    – D. Ben Knoble
    Oct 5 at 14:28
  • Apologies, forgot to follow up on this... Thanks for the reminder!
    – toraritte
    Oct 5 at 15:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.