From 31b076da9d06d3148d214b366dddab8caa3621c4 Mon Sep 17 00:00:00 2001 From: lnc3l0t Date: Sat, 13 May 2023 16:51:28 +0200 Subject: [PATCH] feat: added ListGists command With this command one can list all of his gists on github, choose one then edit all of its files in place inside neovim! I added nvim_unception dependency, it is not strictly necessary but makes things look nicer; with it the editable gist is in a neovim buffer in the already opened neovim session, not in a nested instance inside a terminal buffer. Anyway the plugin works if without it --- README.md | 37 ++++++++++++++++++-- doc/gist.txt | 10 +++--- lua/gist/core/gh.lua | 28 +++++++++++++++ lua/gist/init.lua | 82 ++++++++++++++++++++++++++++++++++++++++++++ plugin/gist.lua | 4 +++ 5 files changed, 155 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 939c717..602b7dd 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 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 46346a1..b9c8e4d 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 `: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. @@ -22,7 +24,7 @@ EXAMPLES :CreateGistFile [description] [public=true] - The plugin will prompt you for a description and privacy settings for the Gist. + The plugin will prompt you for a description and privacy settings for the Gist. After you enter the description and privacy settings, the plugin will create the Gist using the `gh` command-line tool and copy the URL of the created Gist to the system clipboard. To Create a Gist from current selection, run the following command in Neovim: diff --git a/lua/gist/core/gh.lua b/lua/gist/core/gh.lua index 06d2a99..7eb6695 100644 --- a/lua/gist/core/gh.lua +++ b/lua/gist/core/gh.lua @@ -40,6 +40,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 ba4fac1..e8ca829 100644 --- a/lua/gist/init.lua +++ b/lua/gist/init.lua @@ -68,4 +68,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.", +})