summaryrefslogtreecommitdiff
path: root/debian/.config/yazi/plugins/mactag.yazi/main.lua
blob: 309a46a7bf8d46f88e118e80d38c4e25a63240a6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
--- @since 25.5.31

local update = ya.sync(function(st, tags)
	for path, tag in pairs(tags) do
		st.tags[path] = #tag > 0 and tag or nil
	end
	-- TODO: remove this
	if ui.render then
		ui.render()
	else
		ya.render()
	end
end)

local selected_or_hovered = ya.sync(function()
	local tab, urls = cx.active, {}
	for _, u in pairs(tab.selected) do
		urls[#urls + 1] = u
	end
	if #urls == 0 and tab.current.hovered then
		urls[1] = tab.current.hovered.url
	end
	return urls
end)

local function setup(st, opts)
	st.tags = {}
	st.keys = opts.keys
	st.colors = opts.colors

	Linemode:children_add(function(self)
		local url = tostring(self._file.url)
		local spans = {}
		for _, tag in ipairs(st.tags[url] or {}) do
			if self._file.is_hovered then
				spans[#spans + 1] = ui.Span(" ●"):bg(st.colors[tag] or "reset")
			else
				spans[#spans + 1] = ui.Span(" ●"):fg(st.colors[tag] or "reset")
			end
		end
		return ui.Line(spans)
	end, 500)
end

local function fetch(_, job)
	local paths = {}
	for _, file in ipairs(job.files) do
		paths[#paths + 1] = tostring(file.url)
	end

	local output, err = Command("tag"):arg(paths):stdout(Command.PIPED):output()
	if not output then
		return true, Err("Cannot spawn `tag` command, error: %s", err)
	end

	local i, tags = 1, {}
	for line in output.stdout:gmatch("[^\r\n]+") do
		if i > #paths then
			break
		end
		tags[paths[i]] = tags[paths[i]] or {}

		local joint = line:match("\t(.+)$") or ""
		for s in joint:gmatch("[^,]+") do
			table.insert(tags[paths[i]], s)
		end
		i = i + 1
	end

	update(tags)
	return true
end

local cands = ya.sync(function(st)
	local t = {}
	for k, v in pairs(st.keys) do
		t[#t + 1] = { on = k, desc = v }
	end
	return t
end)

local function entry(self, job)
	assert(job.args[1] == "add" or job.args[1] == "remove", "Invalid action")
	ya.emit("escape", { visual = true })

	local cands = cands()
	local choice = ya.which { cands = cands }
	if not choice then
		return
	end

	local t = { job.args[1] == "remove" and "-r" or "-a", cands[choice].desc }
	local files = {}
	for _, url in ipairs(selected_or_hovered()) do
		t[#t + 1] = tostring(url)
		files[#files + 1] = { url = url }
	end

	local status = Command("tag"):arg(t):status()
	if status.success then
		fetch(self, { files = files })
	end
end

return { setup = setup, fetch = fetch, entry = entry }