Skip to content

Commit 9435e6f

Browse files
chore!: refactored into freeze-code.api usage (#11)
* feat!: api usage and config separation * test: modified tests with the new api * fix: formatting * docs: added `FreezeLine` keymaps and api usage * docs: update `doc/freeze-code.nvim.txt` skip-checks: true * fix: correct use of `api` * fix: formatting * docs: update `doc/freeze-code.nvim.txt` skip-checks: true * fix: `go_install_freeze` -> `go_installation` --------- Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
1 parent cf118dd commit 9435e6f

File tree

11 files changed

+450
-375
lines changed

11 files changed

+450
-375
lines changed

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,11 +116,14 @@ visual mode, and it will take a screenshot of the selected lines.
116116
### Keymaps
117117

118118
```lua
119-
vim.keymap.set("n", "<leader>fz", require("freeze-code").freeze)
119+
local fz_api = require("freeze-code.utils.api")
120+
vim.keymap.set("n", "<leader>fz", fz_api.freeze)
120121
vim.keymap.set("v", "<leader>fz", function()
121-
require("freeze-code").freeze(vim.fn.line("'<"), vim.fn.line("'>"))
122+
fz_api.freeze(vim.fn.line("'<"), vim.fn.line("'>"))
122123
end)
123124
-- or using `<cmd>Freeze<cr>`
125+
vim.keymap.set("n", "<leader>fl", fz.freeze_line)
126+
-- or using `<cmd>FreezeLine<cr>`
124127
```
125128

126129
## Contributing

doc/freeze-code.nvim.txt

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
1-
*freeze-code.nvim.txt* For Neovim >= 0.9.0 Last change: 2024 May 19
1+
*freeze-code.nvim.txt* For Neovim >= 0.9.0 Last change: 2024 June 04
22

33
==============================================================================
44
Table of Contents *freeze-code.nvim-table-of-contents*
55

66
- Installation |freeze-code.nvim-installation|
7+
- Usage |freeze-code.nvim-usage|
78
- Contributing |freeze-code.nvim-contributing|
89

910

@@ -89,6 +90,29 @@ tools.
8990

9091

9192

93+
USAGE *freeze-code.nvim-usage*
94+
95+
To use this plugin, simply call `:Freeze` and it will take a screenshot of the
96+
current buffer and save it in the `dir` path you have configured.
97+
98+
If you want to take a screenshot of a specific line, you can use the `:Freeze`
99+
in visual mode, and it will take a screenshot of the selected lines.
100+
101+
102+
KEYMAPS ~
103+
104+
>lua
105+
local fz_api = require("freeze-code.utils.api")
106+
vim.keymap.set("n", "<leader>fz", fz_api.freeze)
107+
vim.keymap.set("v", "<leader>fz", function()
108+
fz_api.freeze(vim.fn.line("'<"), vim.fn.line("'>"))
109+
end)
110+
-- or using `<cmd>Freeze<cr>`
111+
vim.keymap.set("n", "<leader>fl", fz.freeze_line)
112+
-- or using `<cmd>FreezeLine<cr>`
113+
<
114+
115+
92116
CONTRIBUTING *freeze-code.nvim-contributing*
93117

94118
Thank you to everyone that is contributing and to those who want to contribute.
Lines changed: 147 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,147 @@
1+
local cfg = require("freeze-code.config")
2+
local u = require("freeze-code.utils")
3+
local logger = u.logger
4+
5+
local FreezeBinaryFetcher = {}
6+
7+
---@class FreezeBinaryFetcher
8+
---@field go_installation function: installs `freeze` using `go install github.com/charmbracelet/freeze@latest`
9+
---Freeze installation using `go install`
10+
---@param opts FreezeCodeConfig
11+
function FreezeBinaryFetcher:go_installation(opts)
12+
local cmd_args = {
13+
"go",
14+
"install",
15+
"github.com/charmbracelet/freeze@latest",
16+
}
17+
local stdio = { stdout = "", stderr = "" }
18+
local job = nil
19+
20+
local function on_output(err, data)
21+
if err then
22+
logger.err(err)
23+
end
24+
if data then
25+
stdio.stderr = stdio.stderr .. data
26+
end
27+
end
28+
local callbacks = {
29+
on_sterr = vim.schedule_wrap(function(_, data, _)
30+
local out = table.concat(data, "\n")
31+
on_output(out)
32+
end),
33+
on_exit = vim.schedule_wrap(function()
34+
opts._installed = true
35+
opts.freeze_path = vim.env.HOME .. "/go/bin/freeze"
36+
opts.install_path = opts.freeze_path
37+
logger.warn("[freeze-code] go install github.com/charmbracelet/freeze@latest completed")
38+
cfg.setup(opts)
39+
vim.fn.jobstop(job)
40+
end),
41+
}
42+
job = vim.fn.jobstart(cmd_args, callbacks)
43+
end
44+
45+
---@class FreezeBinaryFetcher
46+
---@field agnostic_installation function: installs `freeze` using `cURL` from GitHub release
47+
---Freeze installation using GitHub release
48+
---@param opts FreezeCodeConfig
49+
function FreezeBinaryFetcher:agnostic_installation(opts)
50+
local os_name = u.get_os_info()
51+
local release_url = u.release_file_url()
52+
if release_url == "" then
53+
logger.err("could not get release file")
54+
return
55+
end
56+
57+
local install_path = vim.fn.expand(opts.install_path)
58+
if install_path == "" then
59+
install_path = vim.fn.expand("~/.local/bin")
60+
end
61+
local output_filename = "freeze.tar.gz"
62+
local download_command = { "curl", "-sL", "-o", output_filename, release_url }
63+
local extract_command = { "tar", "-zxf", output_filename, "-C", install_path }
64+
-- vim.loop.spawn("rm", { args = { "-rf", install_path .. "/" .. u.get_freeze_filename() } })
65+
local rm_command_args = { "-rf", install_path .. "/" .. u.get_freeze_filename() }
66+
if os_name == "Windows" then
67+
extract_command = { "Expand-Archive", output_filename, install_path }
68+
rm_command_args = { "-r", "-Force", install_path .. "/" .. u.get_freeze_filename() }
69+
end
70+
local binary_path = vim.fn.expand(table.concat({ install_path, u.get_freeze_filename() .. "/freeze" }, "/"))
71+
72+
-- check for existing files / folders
73+
if vim.fn.isdirectory(install_path) == 0 then
74+
vim.loop.fs_mkdir(install_path, tonumber("777", 8))
75+
end
76+
77+
if vim.fn.filereadable(binary_path) == 1 then
78+
local success = vim.loop.fs_unlink(binary_path)
79+
if not success then
80+
logger.err("[freeze-code.nvim] ERROR: `freeze` binary could not be removed!")
81+
return
82+
end
83+
end
84+
local stdio = { stdout = "", stderr = "" }
85+
local job = nil
86+
87+
local function on_output(err, data)
88+
if err then
89+
logger.err(err)
90+
end
91+
if data then
92+
stdio.stderr = stdio.stderr .. data
93+
end
94+
end
95+
96+
-- download and install the freeze binary
97+
local callbacks = {
98+
on_sterr = vim.schedule_wrap(function(_, data, _)
99+
local out = table.concat(data, "\n")
100+
on_output(out)
101+
end),
102+
on_exit = vim.schedule_wrap(function()
103+
logger.info_fmt("[freeze-code.nvim] extracting release with `%s`", table.concat(extract_command, " "))
104+
vim.fn.system(extract_command)
105+
if vim.v.shell_error ~= 0 then
106+
logger.err("[freeze-code.nvim] ERROR: extracting release failed")
107+
return
108+
end
109+
-- remove the archive after completion
110+
if vim.fn.filereadable(output_filename) == 1 then
111+
local success = vim.loop.fs_unlink(output_filename)
112+
if not success then
113+
logger.err("[freeze-code.nvim] ERROR: existing archive could not be removed")
114+
return
115+
end
116+
end
117+
vim.loop.spawn("mv", { args = { binary_path, install_path .. "/freeze" } })
118+
binary_path = install_path .. "/freeze"
119+
opts.freeze_path = binary_path
120+
opts._installed = true
121+
opts.install_path = install_path
122+
logger.warn_fmt("[freeze-code.nvim] `freeze` binary installed in installed in path=%s", cfg.config.freeze_path)
123+
vim.loop.spawn("rm", { args = rm_command_args })
124+
logger.warn_fmt("[freeze-code.nvim] `freeze` binary installed in path=%s", cfg.config.freeze_path)
125+
cfg.setup(opts)
126+
vim.fn.jobstop(job)
127+
end),
128+
}
129+
logger.info_fmt("[freeze-code.nvim] downloading release from `%s`", release_url)
130+
job = vim.fn.jobstart(download_command, callbacks)
131+
end
132+
133+
---@class FreezeBinaryFetcher
134+
---@field install_freeze function: `freeze` installation process
135+
---Install freeze for the user
136+
---@param opts FreezeCodeConfig
137+
function FreezeBinaryFetcher:install_freeze(opts)
138+
if u.check_executable("go", vim.fn.exepath("go")) then
139+
logger.warn("[freeze-code.nvim] go install github.com/charmbracelet/freeze@latest completed")
140+
self:go_installation(opts)
141+
return
142+
end
143+
logger.info("[freeze-code.nvim] Installing info with `curl`")
144+
self:agnostic_installation(opts)
145+
end
146+
147+
return FreezeBinaryFetcher
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
local binary_fetcher = require("freeze-code.binary.binary_fetcher")
2+
local cfg = require("freeze-code.config")
3+
local commands = require("freeze-code.commands")
4+
local u = require("freeze-code.utils")
5+
local logger = u.logger
6+
local FreezeBinary = {}
7+
8+
---@class FreezeBinary
9+
---@field freeze function: Running `freeze` function
10+
---Freeze file with a range or current buffer if no range is given
11+
---@param s_line? number: line to start range
12+
---@param e_line? number: line to start range
13+
function FreezeBinary:freeze(s_line, e_line)
14+
if not cfg.config._installed then
15+
logger.warn("[freeze-code.nvim] `freeze` not installed")
16+
binary_fetcher:install_freeze(cfg.config)
17+
return
18+
end
19+
20+
s_line = s_line or 1
21+
e_line = e_line or vim.api.nvim_buf_line_count(vim.api.nvim_get_current_buf())
22+
23+
local cmd = cfg.config.freeze_path
24+
25+
if not u.check_executable("freeze", cmd) then
26+
return
27+
end
28+
29+
local lang = ""
30+
if vim.fn.has("nvim-0.10") == 1 then
31+
lang = vim.api.nvim_get_option_value("filetype", { buf = vim.api.nvim_get_current_buf() })
32+
else
33+
---@diagnostic disable-next-line: deprecated
34+
lang = vim.api.nvim_buf_get_option(vim.api.nvim_get_current_buf(), "filetype")
35+
end
36+
local file = vim.api.nvim_buf_get_name(vim.api.nvim_get_current_buf())
37+
local conf = cfg.config.freeze_config.config
38+
local dir = cfg.config.dir
39+
local theme = cfg.config.freeze_config.theme
40+
local output = cfg.config.freeze_config.output
41+
42+
if output ~= "freeze" then
43+
local t_stamp = os.date("%Y%m%d%H%M%S")
44+
local filename = file:match("^.+/(.*)$") or file
45+
46+
output = string.format("%s_%s_%s", tostring(t_stamp), filename, output)
47+
end
48+
49+
cfg.config.output = dir .. "/" .. output .. ".png"
50+
51+
local cmd_args = {
52+
"--output",
53+
cfg.config.output,
54+
"--language",
55+
lang,
56+
"--lines",
57+
s_line .. "," .. e_line,
58+
"--config",
59+
conf,
60+
file,
61+
}
62+
if conf == "base" or conf == "full" then
63+
vim.list_extend(cmd_args, {
64+
"--theme",
65+
theme,
66+
})
67+
end
68+
69+
commands.job = {}
70+
commands.job.stdout = vim.loop.new_pipe(false)
71+
commands.job.stderr = vim.loop.new_pipe(false)
72+
73+
local job_opts = {
74+
args = cmd_args,
75+
stdio = { nil, commands.job.stdout, commands.job.stderr },
76+
}
77+
78+
local msg = "🍧 frozen frame in path=" .. cfg.config.output
79+
commands.job.handle = vim.loop.spawn(cmd, job_opts, commands.on_exit(msg))
80+
vim.loop.read_start(commands.job.stdout, vim.schedule_wrap(commands.on_output))
81+
vim.loop.read_start(commands.job.stderr, vim.schedule_wrap(commands.on_output))
82+
end
83+
84+
---@class FreezeBinary
85+
---@field freeze_line function: Running `freeze` function for current line
86+
---Freeze file with a range or current buffer if no range is given
87+
function FreezeBinary:freeze_line()
88+
local curent_line = vim.api.nvim_win_get_cursor(0)[1]
89+
self:freeze(curent_line, curent_line)
90+
end
91+
92+
return FreezeBinary

lua/freeze-code/commands.lua

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -41,18 +41,18 @@ end
4141
---@param msg string: Message to display if success
4242
---@return function cb: Schedule wrap callback function
4343
function M.on_exit(msg, opts)
44-
local freeze_code = require("freeze-code")
44+
local cfg = require("freeze-code.config")
4545
return vim.schedule_wrap(function(code, _)
4646
if code == 0 then
4747
vim.notify("[freeze-code.nvim] " .. msg, vim.log.levels.INFO, { title = "FreezeCode" })
4848
else
4949
vim.notify(M.stdio.stdout, vim.log.levels.ERROR, { title = "Freeze" })
5050
end
51-
if freeze_code.config.copy == true then
52-
freeze_code.copy(freeze_code.config)
51+
if cfg.config.copy == true then
52+
M.copy(cfg.config)
5353
end
54-
if freeze_code.config.open == true then
55-
freeze_code.open(freeze_code.config)
54+
if cfg.config.open == true then
55+
M.open(cfg.config)
5656
end
5757
if opts and opts.freeze then
5858
vim.wait(5000, function()

lua/freeze-code/config.lua

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
---@meta
2+
3+
---@class FreezeConfig
4+
---@field output string: Freeze output filename `--output "freeze.png"`
5+
---@field theme string: Freeze theme `--theme "default"`
6+
---@field config string: Freeze configuration `--config "base"`
7+
8+
---@class FreezeCodeConfig
9+
---@field freeze_path string: Path to `freeze` executable
10+
---@field copy_cmd string: Path to copy `image/png` to clipboard command
11+
---@field copy boolean: Open image after creation option
12+
---@field open boolean: Open image after creation option
13+
---@field dir string: Directory to create image
14+
---@field freeze_config FreezeConfig
15+
---@field output? string: output filename
16+
---@field install_path string: path in where to install `freeze`
17+
---@field _installed boolean:
18+
19+
---@type FreezeCodeConfig
20+
local default_config = {
21+
freeze_config = {
22+
output = "freeze",
23+
config = "base",
24+
theme = "default",
25+
},
26+
_installed = vim.fn.exepath("freeze") ~= "",
27+
install_path = vim.env.HOME .. "/.local/bin",
28+
freeze_path = vim.fn.exepath("freeze"),
29+
copy_cmd = vim.env.HOME .. "/dev/nvim_plugins/freeze-code.nvim/bin/pngcopy-macos",
30+
copy = false,
31+
open = false,
32+
dir = vim.env.PWD,
33+
output = nil,
34+
}
35+
36+
local M = {
37+
config = vim.deepcopy(default_config),
38+
}
39+
40+
M.setup = function(opts)
41+
M.config = vim.tbl_deep_extend("force", vim.deepcopy(default_config), opts or {})
42+
end
43+
44+
return setmetatable(M, {
45+
__index = function(_, key)
46+
if key == "setup" then
47+
return M.setup
48+
end
49+
return rawget(M.config, key)
50+
end,
51+
})

0 commit comments

Comments
 (0)