Skip to content

Commit

Permalink
Merge pull request #5 from Rawnly/feature/upload-selection
Browse files Browse the repository at this point in the history
  • Loading branch information
rawnly authored Mar 15, 2023
2 parents 56c21ba + 01d5964 commit 6a4da61
Show file tree
Hide file tree
Showing 6 changed files with 211 additions and 33 deletions.
15 changes: 11 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ You also need to have the gh command-line tool installed and configured with you
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:

```
```lua
use "rawnly/gist.nvim"
```

Expand All @@ -21,11 +21,18 @@ To create a Gist from the current file, use the `:CreateGist` command in Neovim.
The plugin will prompt you for a description and whether the Gist should be private or public.

```vim
:CreateGist
:CreateGist [description] [public=true]
```

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 system clipboard.
You can then paste the URL into a browser to view the Gist.
- `:CreateGist` will create the gist from the current selection
- `:CreateGistFromFile` will create the gist from the current file

Both the commands accept the same options which are `[description=]` and `[public=true]`

If you don't pass the `description` it will prompt to insert one later.
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.

## Configuration

Expand Down
18 changes: 14 additions & 4 deletions doc/gist.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,19 +5,29 @@ NAME

SYNOPSIS
:CreateGist
:CreateGistFromFile

DESCRIPTION
The `:CreateGist` command creates a GitHub Gist from the current file using the `gh` command-line tool. 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 `: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 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.

OPTIONS
None
<description> 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.
public=true You can override the privacy settings for the Gist as an argument to the command. If you don't provide privacy settings, the plugin will prompt you for them.

EXAMPLES
To create a Gist from the current file, run the following command in Neovim:

:CreateGist
:CreateGistFile [description] [public=true]

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:

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.
:CreateGist [description] [public=true]

SEE ALSO
:help gist.config
Expand Down
41 changes: 22 additions & 19 deletions lua/gist/core/gh.lua
Original file line number Diff line number Diff line change
@@ -1,44 +1,47 @@
local utils = require("gist.core.utils")
local M = {}

--- Creates a Github gist with the specified filename and description
--
-- @param filename string The filename of the Gist
-- @param content string|nil The content of the Gist
-- @param description string The description of the Gist
-- @param private boolean Wether the Gist should be private
-- @return string|nil The URL of the created Gist
-- @return number|nil The error of the command
function M.create_gist(filename, description, private)
function M.create_gist(filename, content, description, private)
local public_flag = private and "" or "--public"
local escaped_description = vim.fn.shellescape(description)

local cmd = string.format(
"gh gist create %s %s --filename %s -d %s",
vim.fn.expand("%"),
public_flag,
filename,
escaped_description
)

local handle = io.popen(cmd)

-- null check on handle
if handle == nil then
return nil
description = vim.fn.shellescape(description)

local cmd

if content ~= nil then
filename = vim.fn.shellescape(filename)
cmd = string.format("gh gist create -f %s -d %s %s", filename, description, public_flag)
else
-- expand filepath if no content is provided
cmd = string.format(
"gh gist create %s %s --filename %s -d %s",
vim.fn.expand("%"),
public_flag,
filename,
description
)
end

local output = handle:read("*a")
handle:close()
local output = utils.exec(cmd, content)

if vim.v.shell_error ~= 0 then
return output, vim.v.shell_error
end

local url = string.gsub(output, "\n", "")
local url = utils.extract_gist_url(output)

return url, nil
end

--- Reads the configuration from the user's vimrc
--
-- @return table A table with the configuration properties
function M.read_config()
local ok, values = pcall(vim.api.nvim_get_var, { "gist_is_private", "gist_clipboard" })
Expand Down
102 changes: 102 additions & 0 deletions lua/gist/core/utils.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
local M = {}

local function is_visual()
if vim.fn.mode() ~= "v" and vim.fn.mode() ~= "V" and vim.fn.mode() ~= "<C-V>" then
return false
end

return true
end

function M.get_current_selection(start_line, end_line)
local bufnr = vim.api.nvim_get_current_buf()

start_line = start_line - 1 -- Convert to 0-based line number
end_line = end_line - 1 -- Convert to 0-based line number

local lines = vim.api.nvim_buf_get_lines(bufnr, start_line, end_line + 1, false)

return table.concat(lines, "\n")
end

function M.get_last_selection()
local bufnr = vim.api.nvim_get_current_buf()

-- Save the current cursor position
local saved_cursor = vim.api.nvim_win_get_cursor(0)

-- Get the start and end positions of the visual selection
vim.cmd("normal! gv")
local start_pos = vim.fn.getpos("'<")
local end_pos = vim.fn.getpos("'>")

-- Restore the cursor position
vim.api.nvim_win_set_cursor(0, saved_cursor)

local start_line = start_pos[2] - 1
local end_line = end_pos[2]
local content_lines = vim.api.nvim_buf_get_lines(bufnr, start_line, end_line, false)
local content = table.concat(content_lines, "\n")

return content
end

local function read_file(path)
local file = io.open(path, "rb") -- r read mode and b binary mode
if not file then
return nil
end
local content = file:read("*a") -- *a or *all reads the whole file
file:close()
return content
end

function M.exec(cmd, stdin)
print(string.format("Executing: %s", cmd))
local tmp = os.tmpname()

local pipe = io.popen(cmd .. "> " .. tmp, "w")

if not pipe then
return nil
end

if stdin then
pipe:write(stdin)
end

pipe:close()

local output = read_file(tmp)
os.remove(tmp)

return output
end

function M.extract_gist_url(output)
local pattern = "https://gist.github.com/%S+"

return output:match(pattern)
end

-- @param args string
function M.parseArgs(args)
-- parse args as key=value
local parsed = {}

for _, arg in ipairs(vim.split(args, " ", {})) do
local key, value = unpack(vim.split(arg, "=", { plain = true }))

if value == "true" then
value = true
elseif value == "false" then
value = false
end

parsed[key] = value
end

return parsed
end

return M
57 changes: 53 additions & 4 deletions lua/gist/init.lua
Original file line number Diff line number Diff line change
@@ -1,15 +1,34 @@
local utils = require("gist.core.utils")
local core = require("gist.core.gh")

local M = {}

function M.create()
local function get_details(ctx)
local config = core.read_config()

local filename = vim.fn.expand("%:t")
local description = vim.fn.input("Description: ")
local is_private = config.is_private or vim.fn.input("Create a private Gist? (y/n): ") == "y"
local description = ctx.description or vim.fn.input("Gist description: ")

local url, err = core.create_gist(filename, description, is_private)
local is_private

if ctx.public ~= nil then
is_private = not ctx.public
else
is_private = config.public or vim.fn.input("Create a private Gist? (y/n): ") == "y"
end

return {
filename = filename,
description = description,
is_private = is_private,
}
end

local function create(content, ctx)
local config = core.read_config()
local details = get_details(ctx)

local url, err = core.create_gist(details.filename, content, details.description, details.is_private)

if err ~= nil then
vim.api.nvim_err_writeln("Error creating Gist: " .. err)
Expand All @@ -19,4 +38,34 @@ function M.create()
end
end

--- Creates a Gist from the current selection
function M.create(opts)
local content = nil
local args = utils.parseArgs(opts.args)

local start_line = opts.line1
local end_line = opts.line2
local description = opts.fargs[1]

if start_line ~= end_line then
content = utils.get_current_selection(start_line, end_line)
end

return create(content, {
description = description,
public = args.public,
})
end

--- Creates a Gist from the current file.
function M.create_from_file(opts)
local args = utils.parseArgs(opts.args)
local description = opts.fargs[1]

create(nil, {
description = description,
public = args.public,
})
end

return M
11 changes: 9 additions & 2 deletions plugin/gist.lua
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
local gist = require("gist")

vim.api.nvim_create_user_command("CreateGistFromFile", gist.create_from_file, {
nargs = "?",
desc = "Create a Gist from the current file.",
range = false,
})

vim.api.nvim_create_user_command("CreateGist", gist.create, {
bang = true,
desc = "Create a new gist from current file",
nargs = "?",
desc = "Create a Gist from the current selection.",
range = true,
})

0 comments on commit 6a4da61

Please sign in to comment.