diff --git a/README.md b/README.md index 9807920..6687d37 100644 --- a/README.md +++ b/README.md @@ -7,12 +7,39 @@ The plugin uses the gh command-line tool to create the Gist and provides a simpl To use `gist.nvim`, you need to have Neovim installed on your system. You also need to have the gh command-line tool installed and configured with your GitHub account. +If you intend to use the `ListGists` command to list and edit all your gists, I suggest the `nvim-unception` plugin. Once you have Neovim and gh installed, you can install `gist.nvim` using your favorite plugin manager. -For example, if you are using packer, you can add the following line to your init.vim file: +#### Using [lazy.nvim](https://github.com/folke/lazy.nvim): ```lua - use "rawnly/gist.nvim" +return { + { + "Rawnly/gist.nvim", + cmd = { "CreateGist", "CreateGistFromFile", "ListGists" }, + init = function() + vim.g.gist_is_private = false -- All gists will be private, you won't be prompted again + vim.g.gist_clipboard = "+" -- The registry to use for copying the Gist URL + end, + }, + -- `ListGists` opens the selected gif in a terminal buffer, + -- nvim-unception uses neovim remote rpc functionality to open the gist in an actual buffer + -- and prevents neovim buffer inception + { + "samjwill/nvim-unception", + lazy = false, + init = function() vim.g.unception_block_while_host_edits = true end + } +} +``` +#### Using [packer.nvim](https://github.com/wbthomason/packer.nvim): +```lua +use { + "rawnly/gist.nvim", + -- `ListGists` opens the selected gif in a terminal buffer, + -- this plugin uses neovim remote rpc functionality to open the gist in an actual buffer and not have buffer inception + requires = { "samjwill/nvim-unception", setup = function() vim.g.unception_block_while_host_edits = true end } +} ``` ## Usage @@ -34,6 +61,12 @@ If you pass `[public=true]` it won't prompt for privacy later. After you enter the description and privacy settings, the plugin ask for confirmation and will create the Gist using the gh command-line tool and copy the Gist's URL to the given clipboard registry. +You can also list your gists and edit their files on the fly. +```vim + :ListGists +``` +- `:ListGists` will list all your gists and after you select one it will open a buffer to edit it + ## Configuration `gist.nvim` provides a few configuration options that you can set as global params: diff --git a/doc/gist.txt b/doc/gist.txt index 974fb95..0d2fdd5 100644 --- a/doc/gist.txt +++ b/doc/gist.txt @@ -6,12 +6,14 @@ NAME SYNOPSIS :CreateGist :CreateGistFromFile + :ListGists DESCRIPTION The `:CreateGist` command creates a GitHub Gist from the buffer selection using the `gh` command-line tool. The `:CreateGistFile` command creates a GitHub Gist from the current file using the `gh` command-line tool. + The `:ListGists` command lists all the GitHub Gists from your account and allows you to edit them directly inside neovim. - The plugin prompts you for a description and privacy settings for the Gist, and then copies the URL of the created Gist to the system clipboard. + The plugin prompts you for a description and privacy settings for the Gist creation, and then copies the URL of the created Gist to the system clipboard. OPTIONS You can provide description for the Gist as an argument to the command. If you don't provide a description, the plugin will prompt you for one. diff --git a/lua/gist/core/gh.lua b/lua/gist/core/gh.lua index 0b9f777..6defddf 100644 --- a/lua/gist/core/gh.lua +++ b/lua/gist/core/gh.lua @@ -47,6 +47,34 @@ function M.create_gist(filename, content, description, private) return url, nil end +--- List all Github gists +-- +-- @return [string]|nil The URLs of all the Gists +function M.list_gists() + local cmd = "gh gist list" + + local output = utils.exec(cmd) + if type(output) == "string" then + local list = {} + + local gists = vim.split(output, "\n") + table.remove(gists, #gists) + + for _, gist in ipairs(gists) do + local g = vim.split(gist, "\t") + + table.insert(list, { + hash = g[1], + name = g[2], + files = tonumber(g[3]:sub(1,1)), + privacy = g[4], + date = g[5] + }) + end + return list + end +end + --- Reads the configuration from the user's vimrc -- -- @return table A table with the configuration properties diff --git a/lua/gist/init.lua b/lua/gist/init.lua index 3a8024a..8543efe 100644 --- a/lua/gist/init.lua +++ b/lua/gist/init.lua @@ -69,4 +69,86 @@ function M.create_from_file(opts) }) end +local function create_split_terminal(command) + vim.cmd.vsplit() + local win = vim.api.nvim_get_current_win() + local buf = vim.api.nvim_create_buf(false, true) + vim.api.nvim_win_set_buf(win, buf) + vim.api.nvim_win_set_option(win, "number", false) + vim.api.nvim_win_set_option(win, "relativenumber", false) + vim.api.nvim_buf_set_name(buf, ("term://%s/%s"):format(buf, command[1])) + vim.keymap.set("t", "", "", { buffer = buf }) + vim.keymap.set("t", "", "", { buffer = buf }) + vim.api.nvim_win_set_option(win, "winbar", "%=Use CTRL-{n,p} to cycle") + vim.cmd.startinsert() + return buf +end + +local function format_gist(g) + return string.format("%s (%s) |%s 📃| [%s]", + g.name, -- Gist name + g.hash, -- Gist hash + g.files, -- Gist files number + g.privacy == "public" and "➕" or "➖" -- Gist privacy setting (public/private) + ) +end + +--- List user gists via telescope or vim.select. +function M.list_gists() + if pcall(require, "unception") and not vim.g.unception_block_while_host_edits then + print("You need to set this option `:h g:unception_block_while_host_edits`") + return + end + + local list = core.list_gists() + if #list == 0 then + print("No gists. You can create one from current buffer with `CreateGist`") + return + end + + vim.ui.select(list, { + prompt = "Select a gist to edit", + format_item = format_gist + }, function(gist) + if not gist then return end + + local job_id + + local command = { "gh", "gist", "edit", gist.hash } + local buf = create_split_terminal(command) + + local term_chan_id = vim.api.nvim_open_term(buf, { + on_input = function(_, _, _, data) + vim.api.nvim_chan_send(job_id, data) + end + }) + + job_id = vim.fn.jobstart(command, vim.tbl_extend("force", { + on_stdout = function(_, data) + vim.api.nvim_chan_send(term_chan_id, table.concat(data, "\r\n")) + + local changed = vim.fn.bufnr() ~= buf + if changed then + vim.api.nvim_buf_set_option(vim.fn.bufnr(), "bufhidden", "wipe") + vim.api.nvim_buf_set_option(vim.fn.bufnr(), "swapfile", true) + + local winbar = ("%sGIST `%s`"):format("%=", gist.name) + vim.api.nvim_win_set_option(vim.fn.win_getid(), "winbar", winbar) + end + if gist.files > 1 and changed then + vim.api.nvim_create_autocmd({ "BufDelete" }, { + buffer = vim.fn.bufnr(), + group = vim.api.nvim_create_augroup("gist_save", {}), + callback = function() vim.cmd.startinsert() end + }) + end + end, + on_exit = function() + vim.api.nvim_buf_delete(buf, { force = true }) + end, + pty = true, + }, {})) + end) +end + return M diff --git a/plugin/gist.lua b/plugin/gist.lua index dd9f72e..1a9f5d6 100644 --- a/plugin/gist.lua +++ b/plugin/gist.lua @@ -11,3 +11,7 @@ vim.api.nvim_create_user_command("CreateGist", gist.create, { desc = "Create a Gist from the current selection.", range = true, }) + +vim.api.nvim_create_user_command("ListGists", gist.list_gists, { + desc = "List user Gists.", +})