Skip to content

Commit 4d18173

Browse files
committed
Add BadgeInsert functionality
Insert badges with :BadgeInsert, choose from various badges and dynamically fill the fields with the information needed
1 parent c6b5f1f commit 4d18173

6 files changed

Lines changed: 304 additions & 2 deletions

File tree

data/badges.json

Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
{
2+
"static": {
3+
"label": "Custom Badge",
4+
"template": "![{label}](https://img.shields.io/badge/{label}-{message}-{color}?style={style}&logo={logo}&logoColor={logoColor})",
5+
"fields": [
6+
{
7+
"key": "label",
8+
"prompt": "label: "
9+
},
10+
{
11+
"key": "message",
12+
"prompt": "message: "
13+
},
14+
{
15+
"key": "color",
16+
"prompt": "color (hex, no #): "
17+
},
18+
{
19+
"key": "logo",
20+
"prompt": "logo (simpleicons name): "
21+
},
22+
{
23+
"key": "logoColor",
24+
"prompt": "logo color: "
25+
}
26+
]
27+
},
28+
"github_stars": {
29+
"label": "GitHub Stars",
30+
"template": "![GitHub Stars](https://img.shields.io/github/stars/{user}/{repo}?style={style})",
31+
"fields": [
32+
{
33+
"key": "user",
34+
"prompt": "username: "
35+
},
36+
{
37+
"key": "repo",
38+
"prompt": "repo: "
39+
}
40+
]
41+
},
42+
"github_issues": {
43+
"label": "GitHub Issues",
44+
"template": "![GitHub Issues](https://img.shields.io/github/issues/{user}/{repo}?style={style})",
45+
"fields": [
46+
{
47+
"key": "user",
48+
"prompt": "username: "
49+
},
50+
{
51+
"key": "repo",
52+
"prompt": "repo: "
53+
}
54+
]
55+
},
56+
"github_forks": {
57+
"label": "GitHub Forks",
58+
"template": "![GitHub Forks](https://img.shields.io/github/forks/{user}/{repo}?style={style})",
59+
"fields": [
60+
{
61+
"key": "user",
62+
"prompt": "username: "
63+
},
64+
{
65+
"key": "repo",
66+
"prompt": "repo: "
67+
}
68+
]
69+
},
70+
"github_license": {
71+
"label": "GitHub License",
72+
"template": "![GitHub License](https://img.shields.io/github/license/{user}/{repo}?style={style})",
73+
"fields": [
74+
{
75+
"key": "user",
76+
"prompt": "username: "
77+
},
78+
{
79+
"key": "repo",
80+
"prompt": "repo: "
81+
}
82+
]
83+
},
84+
"github_workflow": {
85+
"label": "GitHub Workflow",
86+
"template": "![GitHub Workflow](https://img.shields.io/github/actions/workflow/status/{user}/{repo}/{workflow}?style={style})",
87+
"fields": [
88+
{
89+
"key": "user",
90+
"prompt": "username: "
91+
},
92+
{
93+
"key": "repo",
94+
"prompt": "repo: "
95+
},
96+
{
97+
"key": "workflow",
98+
"prompt": "workflow file (e.g. ci.yml): "
99+
}
100+
]
101+
},
102+
"npm_version": {
103+
"label": "NPM Version",
104+
"template": "![NPM Version](https://img.shields.io/npm/v/{package}?style={style})",
105+
"fields": [
106+
{
107+
"key": "package",
108+
"prompt": "package name: "
109+
}
110+
]
111+
},
112+
"npm_downloads": {
113+
"label": "NPM Downloads",
114+
"template": "![NPM Downloads](https://img.shields.io/npm/dm/{package}?style={style})",
115+
"fields": [
116+
{
117+
"key": "package",
118+
"prompt": "package name: "
119+
}
120+
]
121+
},
122+
"crates_version": {
123+
"label": "Crates.io Version",
124+
"template": "![Crates.io](https://img.shields.io/crates/v/{crate}?style={style})",
125+
"fields": [
126+
{
127+
"key": "crate",
128+
"prompt": "crate name: "
129+
}
130+
]
131+
},
132+
"crates_downloads": {
133+
"label": "Crates.io Downloads",
134+
"template": "![Crates.io Downloads](https://img.shields.io/crates/d/{crate}?style={style})",
135+
"fields": [
136+
{
137+
"key": "crate",
138+
"prompt": "crate name: "
139+
}
140+
]
141+
},
142+
"pypi_version": {
143+
"label": "PyPI Version",
144+
"template": "![PyPI](https://img.shields.io/pypi/v/{package}?style={style})",
145+
"fields": [
146+
{
147+
"key": "package",
148+
"prompt": "package name: "
149+
}
150+
]
151+
},
152+
"pypi_downloads": {
153+
"label": "PyPI Downloads",
154+
"template": "![PyPI Downloads](https://img.shields.io/pypi/dm/{package}?style={style})",
155+
"fields": [
156+
{
157+
"key": "package",
158+
"prompt": "package name: "
159+
}
160+
]
161+
},
162+
"docker_pulls": {
163+
"label": "Docker Pulls",
164+
"template": "![Docker Pulls](https://img.shields.io/docker/pulls/{user}/{image}?style={style})",
165+
"fields": [
166+
{
167+
"key": "user",
168+
"prompt": "dockerhub username: "
169+
},
170+
{
171+
"key": "image",
172+
"prompt": "image name: "
173+
}
174+
]
175+
},
176+
"neovim": {
177+
"label": "Neovim",
178+
"template": "![Neovim](https://img.shields.io/badge/Neovim-%2357A143?style={style}&logo=neovim&logoColor=white)",
179+
"fields": []
180+
},
181+
"rust": {
182+
"label": "Rust",
183+
"template": "![Rust](https://img.shields.io/badge/Rust-%23000000?style={style}&logo=rust&logoColor=white)",
184+
"fields": []
185+
},
186+
"lua": {
187+
"label": "Lua",
188+
"template": "![Lua](https://img.shields.io/badge/Lua-%232C2D72?style={style}&logo=lua&logoColor=white)",
189+
"fields": []
190+
},
191+
"python": {
192+
"label": "Python",
193+
"template": "![Python](https://img.shields.io/badge/Python-%233776AB?style={style}&logo=python&logoColor=white)",
194+
"fields": []
195+
},
196+
"typescript": {
197+
"label": "TypeScript",
198+
"template": "![TypeScript](https://img.shields.io/badge/TypeScript-%233178C6?style={style}&logo=typescript&logoColor=white)",
199+
"fields": []
200+
},
201+
"javascript": {
202+
"label": "JavaScript",
203+
"template": "![JavaScript](https://img.shields.io/badge/JavaScript-%23F7DF1E?style={style}&logo=javascript&logoColor=black)",
204+
"fields": []
205+
},
206+
"go": {
207+
"label": "Go",
208+
"template": "![Go](https://img.shields.io/badge/Go-%2300ADD8?style={style}&logo=go&logoColor=white)",
209+
"fields": []
210+
},
211+
"zig": {
212+
"label": "Zig",
213+
"template": "![Zig](https://img.shields.io/badge/Zig-%23F7A41D?style={style}&logo=zig&logoColor=white)",
214+
"fields": []
215+
}
216+
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
-- main module file
2-
local module = require("plugin_name.module")
2+
local module = require("badges.module")
33

44
---@class Config
55
---@field opt string Your config option

lua/badges/init.lua

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
local M = {}
2+
3+
local STYLES = { "flat", "flat-square", "plastic", "for-the-badge", "social" }
4+
5+
M.config = { style = "flat" }
6+
7+
local function load_badges()
8+
local plugin_dir = debug.getinfo(1, "S").source:sub(2):match("(.*/lua/)")
9+
local path = plugin_dir .. "../data/badges.json"
10+
local ok, lines = pcall(vim.fn.readfile, path)
11+
if not ok then
12+
vim.notify("badges.nvim: failed to read badges.json", vim.log.levels.ERROR)
13+
return {}
14+
end
15+
local decoded_ok, data = pcall(vim.json.decode, table.concat(lines, "\n"))
16+
if not decoded_ok then
17+
vim.notify("badges.nvim: failed to parse badges.json", vim.log.levels.ERROR)
18+
return {}
19+
end
20+
return data
21+
end
22+
23+
local function insert_at_cursor(text)
24+
local row, col = unpack(vim.api.nvim_win_get_cursor(0))
25+
local line = vim.api.nvim_get_current_line()
26+
local new_line = line:sub(1, col) .. text .. line:sub(col + 1)
27+
vim.api.nvim_set_current_line(new_line)
28+
vim.api.nvim_win_set_cursor(0, { row, col + #text })
29+
end
30+
31+
local function fill_fields(fields, values, badge_label, callback)
32+
if #fields == 0 then
33+
callback(values)
34+
return
35+
end
36+
37+
local field = fields[1]
38+
local remaining = vim.list_slice(fields, 2)
39+
40+
vim.ui.input({ prompt = badge_label .. " > " .. field.prompt }, function(input)
41+
if not input then
42+
return
43+
end
44+
values[field.key] = input
45+
fill_fields(remaining, values, badge_label, callback)
46+
end)
47+
end
48+
49+
function M.select_badge()
50+
local badges = load_badges()
51+
local names = vim.tbl_keys(badges)
52+
table.sort(names)
53+
54+
vim.ui.select(names, { prompt = "Select badge: " }, function(choice)
55+
if not choice then
56+
return
57+
end
58+
local badge = badges[choice]
59+
60+
local style_options = vim.list_extend({ "default (" .. M.config.style .. ")" }, STYLES)
61+
vim.ui.select(style_options, { prompt = "Select style: " }, function(style_choice)
62+
if not style_choice then
63+
return
64+
end
65+
66+
local style = M.config.style
67+
if style_choice ~= style_options[1] then
68+
style = style_choice
69+
end
70+
71+
fill_fields(badge.fields, {}, badge.label, function(values)
72+
values.style = style
73+
local url = badge.template:gsub("{(%w+)}", values)
74+
insert_at_cursor(url)
75+
end)
76+
end)
77+
end)
78+
end
79+
80+
function M.setup(opts)
81+
M.config = vim.tbl_deep_extend("force", M.config, opts or {})
82+
vim.api.nvim_create_user_command("BadgeInsert", function()
83+
M.select_badge()
84+
end, {})
85+
end
86+
87+
return M

plugin/plugin_name.lua

Lines changed: 0 additions & 1 deletion
This file was deleted.

0 commit comments

Comments
 (0)