Skip to content

Commit 6a4da61

Browse files
authored
Merge pull request #5 from Rawnly/feature/upload-selection
2 parents 56c21ba + 01d5964 commit 6a4da61

File tree

6 files changed

+211
-33
lines changed

6 files changed

+211
-33
lines changed

README.md

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ You also need to have the gh command-line tool installed and configured with you
1111
Once you have Neovim and gh installed, you can install `gist.nvim` using your favorite plugin manager.
1212
For example, if you are using packer, you can add the following line to your init.vim file:
1313

14-
```
14+
```lua
1515
use "rawnly/gist.nvim"
1616
```
1717

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

2323
```vim
24-
:CreateGist
24+
:CreateGist [description] [public=true]
2525
```
2626

27-
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.
28-
You can then paste the URL into a browser to view the Gist.
27+
- `:CreateGist` will create the gist from the current selection
28+
- `:CreateGistFromFile` will create the gist from the current file
29+
30+
Both the commands accept the same options which are `[description=]` and `[public=true]`
31+
32+
If you don't pass the `description` it will prompt to insert one later.
33+
If you pass `[public=true]` it won't prompt for privacy later.
34+
35+
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.
2936

3037
## Configuration
3138

doc/gist.txt

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,29 @@ NAME
55

66
SYNOPSIS
77
:CreateGist
8+
:CreateGistFromFile
89

910
DESCRIPTION
10-
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.
11+
The `:CreateGist` command creates a GitHub Gist from the buffer selection using the `gh` command-line tool.
12+
The `:CreateGistFile` command creates a GitHub Gist from the current file using the `gh` command-line tool.
13+
14+
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.
1115

1216
OPTIONS
13-
None
17+
<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.
18+
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.
1419

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

18-
:CreateGist
23+
:CreateGistFile [description] [public=true]
24+
25+
The plugin will prompt you for a description and privacy settings for the Gist.
26+
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.
27+
28+
To Create a Gist from current selection, run the following command in Neovim:
1929

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

2232
SEE ALSO
2333
:help gist.config

lua/gist/core/gh.lua

Lines changed: 22 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,44 +1,47 @@
1+
local utils = require("gist.core.utils")
12
local M = {}
23

34
--- Creates a Github gist with the specified filename and description
45
--
56
-- @param filename string The filename of the Gist
7+
-- @param content string|nil The content of the Gist
68
-- @param description string The description of the Gist
79
-- @param private boolean Wether the Gist should be private
810
-- @return string|nil The URL of the created Gist
911
-- @return number|nil The error of the command
10-
function M.create_gist(filename, description, private)
12+
function M.create_gist(filename, content, description, private)
1113
local public_flag = private and "" or "--public"
12-
local escaped_description = vim.fn.shellescape(description)
13-
14-
local cmd = string.format(
15-
"gh gist create %s %s --filename %s -d %s",
16-
vim.fn.expand("%"),
17-
public_flag,
18-
filename,
19-
escaped_description
20-
)
21-
22-
local handle = io.popen(cmd)
23-
24-
-- null check on handle
25-
if handle == nil then
26-
return nil
14+
description = vim.fn.shellescape(description)
15+
16+
local cmd
17+
18+
if content ~= nil then
19+
filename = vim.fn.shellescape(filename)
20+
cmd = string.format("gh gist create -f %s -d %s %s", filename, description, public_flag)
21+
else
22+
-- expand filepath if no content is provided
23+
cmd = string.format(
24+
"gh gist create %s %s --filename %s -d %s",
25+
vim.fn.expand("%"),
26+
public_flag,
27+
filename,
28+
description
29+
)
2730
end
2831

29-
local output = handle:read("*a")
30-
handle:close()
32+
local output = utils.exec(cmd, content)
3133

3234
if vim.v.shell_error ~= 0 then
3335
return output, vim.v.shell_error
3436
end
3537

36-
local url = string.gsub(output, "\n", "")
38+
local url = utils.extract_gist_url(output)
3739

3840
return url, nil
3941
end
4042

4143
--- Reads the configuration from the user's vimrc
44+
--
4245
-- @return table A table with the configuration properties
4346
function M.read_config()
4447
local ok, values = pcall(vim.api.nvim_get_var, { "gist_is_private", "gist_clipboard" })

lua/gist/core/utils.lua

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
local M = {}
2+
3+
local function is_visual()
4+
if vim.fn.mode() ~= "v" and vim.fn.mode() ~= "V" and vim.fn.mode() ~= "<C-V>" then
5+
return false
6+
end
7+
8+
return true
9+
end
10+
11+
function M.get_current_selection(start_line, end_line)
12+
local bufnr = vim.api.nvim_get_current_buf()
13+
14+
start_line = start_line - 1 -- Convert to 0-based line number
15+
end_line = end_line - 1 -- Convert to 0-based line number
16+
17+
local lines = vim.api.nvim_buf_get_lines(bufnr, start_line, end_line + 1, false)
18+
19+
return table.concat(lines, "\n")
20+
end
21+
22+
function M.get_last_selection()
23+
local bufnr = vim.api.nvim_get_current_buf()
24+
25+
-- Save the current cursor position
26+
local saved_cursor = vim.api.nvim_win_get_cursor(0)
27+
28+
-- Get the start and end positions of the visual selection
29+
vim.cmd("normal! gv")
30+
local start_pos = vim.fn.getpos("'<")
31+
local end_pos = vim.fn.getpos("'>")
32+
33+
-- Restore the cursor position
34+
vim.api.nvim_win_set_cursor(0, saved_cursor)
35+
36+
local start_line = start_pos[2] - 1
37+
local end_line = end_pos[2]
38+
local content_lines = vim.api.nvim_buf_get_lines(bufnr, start_line, end_line, false)
39+
local content = table.concat(content_lines, "\n")
40+
41+
return content
42+
end
43+
44+
local function read_file(path)
45+
local file = io.open(path, "rb") -- r read mode and b binary mode
46+
if not file then
47+
return nil
48+
end
49+
local content = file:read("*a") -- *a or *all reads the whole file
50+
file:close()
51+
return content
52+
end
53+
54+
function M.exec(cmd, stdin)
55+
print(string.format("Executing: %s", cmd))
56+
local tmp = os.tmpname()
57+
58+
local pipe = io.popen(cmd .. "> " .. tmp, "w")
59+
60+
if not pipe then
61+
return nil
62+
end
63+
64+
if stdin then
65+
pipe:write(stdin)
66+
end
67+
68+
pipe:close()
69+
70+
local output = read_file(tmp)
71+
os.remove(tmp)
72+
73+
return output
74+
end
75+
76+
function M.extract_gist_url(output)
77+
local pattern = "https://gist.github.com/%S+"
78+
79+
return output:match(pattern)
80+
end
81+
82+
-- @param args string
83+
function M.parseArgs(args)
84+
-- parse args as key=value
85+
local parsed = {}
86+
87+
for _, arg in ipairs(vim.split(args, " ", {})) do
88+
local key, value = unpack(vim.split(arg, "=", { plain = true }))
89+
90+
if value == "true" then
91+
value = true
92+
elseif value == "false" then
93+
value = false
94+
end
95+
96+
parsed[key] = value
97+
end
98+
99+
return parsed
100+
end
101+
102+
return M

lua/gist/init.lua

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,34 @@
1+
local utils = require("gist.core.utils")
12
local core = require("gist.core.gh")
23

34
local M = {}
45

5-
function M.create()
6+
local function get_details(ctx)
67
local config = core.read_config()
78

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

12-
local url, err = core.create_gist(filename, description, is_private)
12+
local is_private
13+
14+
if ctx.public ~= nil then
15+
is_private = not ctx.public
16+
else
17+
is_private = config.public or vim.fn.input("Create a private Gist? (y/n): ") == "y"
18+
end
19+
20+
return {
21+
filename = filename,
22+
description = description,
23+
is_private = is_private,
24+
}
25+
end
26+
27+
local function create(content, ctx)
28+
local config = core.read_config()
29+
local details = get_details(ctx)
30+
31+
local url, err = core.create_gist(details.filename, content, details.description, details.is_private)
1332

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

41+
--- Creates a Gist from the current selection
42+
function M.create(opts)
43+
local content = nil
44+
local args = utils.parseArgs(opts.args)
45+
46+
local start_line = opts.line1
47+
local end_line = opts.line2
48+
local description = opts.fargs[1]
49+
50+
if start_line ~= end_line then
51+
content = utils.get_current_selection(start_line, end_line)
52+
end
53+
54+
return create(content, {
55+
description = description,
56+
public = args.public,
57+
})
58+
end
59+
60+
--- Creates a Gist from the current file.
61+
function M.create_from_file(opts)
62+
local args = utils.parseArgs(opts.args)
63+
local description = opts.fargs[1]
64+
65+
create(nil, {
66+
description = description,
67+
public = args.public,
68+
})
69+
end
70+
2271
return M

plugin/gist.lua

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,13 @@
11
local gist = require("gist")
22

3+
vim.api.nvim_create_user_command("CreateGistFromFile", gist.create_from_file, {
4+
nargs = "?",
5+
desc = "Create a Gist from the current file.",
6+
range = false,
7+
})
8+
39
vim.api.nvim_create_user_command("CreateGist", gist.create, {
4-
bang = true,
5-
desc = "Create a new gist from current file",
10+
nargs = "?",
11+
desc = "Create a Gist from the current selection.",
12+
range = true,
613
})

0 commit comments

Comments
 (0)