-
Notifications
You must be signed in to change notification settings - Fork 1
/
init.lua
228 lines (207 loc) · 6.7 KB
/
init.lua
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
-- Send error notification
local function notify_error(message, urgency)
ya.notify({
title = "Archive",
content = message,
level = urgency,
timeout = 5,
})
end
-- Check for windows
local is_windows = ya.target_family() == "windows"
-- Make table of selected or hovered: path = filenames
local selected_or_hovered = ya.sync(function()
local tab, paths, names, path_fnames = cx.active, {}, {}, {}
for _, u in pairs(tab.selected) do
paths[#paths + 1] = tostring(u:parent())
names[#names + 1] = tostring(u:name())
end
if #paths == 0 and tab.current.hovered then
paths[1] = tostring(tab.current.hovered.url:parent())
names[1] = tostring(tab.current.hovered.name)
end
for idx, name in ipairs(names) do
if not path_fnames[paths[idx]] then
path_fnames[paths[idx]] = {}
end
table.insert(path_fnames[paths[idx]], name)
end
return path_fnames, tostring(tab.current.cwd)
end)
-- Check if archive command is available
local function is_command_available(cmd)
local stat_cmd
if is_windows then
stat_cmd = string.format("where %s > nul 2>&1", cmd)
else
stat_cmd = string.format("command -v %s >/dev/null 2>&1", cmd)
end
local cmd_exists = os.execute(stat_cmd)
if cmd_exists then
return true
else
return false
end
end
-- Archive command list --> string
local function find_binary(cmd_list)
for _, cmd in ipairs(cmd_list) do
if is_command_available(cmd) then
return cmd
end
end
return cmd_list[1] -- Return first command as fallback
end
-- Check if file exists
local function file_exists(name)
local f = io.open(name, "r")
if f ~= nil then
io.close(f)
return true
else
return false
end
end
-- Append filename to it's parent directory
local function combine_url(path, file)
path, file = Url(path), Url(file)
return tostring(path:join(file))
end
return {
entry = function()
-- Exit visual mode
ya.manager_emit("escape", { visual = true })
-- Define file table and output_dir (pwd)
local path_fnames, output_dir = selected_or_hovered()
-- Get input
local output_name, event = ya.input({
title = "Create archive:",
position = { "top-center", y = 3, w = 40 },
})
if event ~= 1 then
return
end
-- Use appropriate archive command
local archive_commands = {
["%.zip$"] = { command = "zip", args = { "-r" } },
["%.7z$"] = { command = { "7z", "7zz" }, args = { "a" } },
["%.tar.gz$"] = { command = "tar", args = { "rpf" }, compress = "gzip" },
["%.tar.xz$"] = { command = "tar", args = { "rpf" }, compress = "xz" },
["%.tar.bz2$"] = { command = "tar", args = { "rpf" }, compress = "bzip2" },
["%.tar.zst$"] = { command = "tar", args = { "rpf" }, compress = "zstd", compress_args = { "--rm" } },
["%.tar$"] = { command = "tar", args = { "rpf" } },
}
if is_windows then
archive_commands = {
["%.zip$"] = { command = "7z", args = { "a", "-tzip" } },
["%.7z$"] = { command = "7z", args = { "a" } },
["%.tar.gz$"] = {
command = "tar",
args = { "rpf" },
compress = "7z",
compress_args = { "a", "-tgzip", "-sdel", output_name },
},
["%.tar.xz$"] = {
command = "tar",
args = { "rpf" },
compress = "7z",
compress_args = { "a", "-txz", "-sdel", output_name },
},
["%.tar.bz2$"] = {
command = "tar",
args = { "rpf" },
compress = "7z",
compress_args = { "a", "-tbzip2", "-sdel", output_name },
},
["%.tar.zst$"] = { command = "tar", args = { "rpf" }, compress = "zstd", compress_args = { "--rm" } },
["%.tar$"] = { command = "tar", args = { "rpf" } },
}
end
-- Match user input to archive command
local archive_cmd, archive_args, archive_compress, archive_compress_args
for pattern, cmd_pair in pairs(archive_commands) do
if output_name:match(pattern) then
archive_cmd = cmd_pair.command
archive_args = cmd_pair.args
archive_compress = cmd_pair.compress
archive_compress_args = cmd_pair.compress_args or {}
end
end
-- Check if archive command has multiple names
if type(archive_cmd) == "table" then
archive_cmd = find_binary(archive_cmd)
end
-- Check if no archive command is available for the extention
if not archive_cmd then
notify_error("Unsupported file extention", "error")
return
end
-- Exit if archive command is not available
if not is_command_available(archive_cmd) then
notify_error(string.format("%s not available", archive_cmd), "error")
return
end
-- Exit if compress command is not available
if archive_compress and not is_command_available(archive_compress) then
notify_error(string.format("%s compression not available", archive_compress), "error")
return
end
-- If file exists show overwrite prompt
local output_url = combine_url(output_dir, output_name)
while true do
if file_exists(output_url) then
local overwrite_answer = ya.input({
title = "Overwrite " .. output_name .. "? y/N:",
position = { "top-center", y = 3, w = 40 },
})
if overwrite_answer:lower() ~= "y" then
notify_error("Operation canceled", "warn")
return -- If no overwrite selected, exit
else
local rm_status, rm_err = os.remove(output_url)
if not rm_status then
notify_error(string.format("Failed to remove %s, exit code %s", output_name, rm_err), "error")
return
end -- If overwrite fails, exit
end
end
if archive_compress and not output_name:match("%.tar$") then
output_name = output_name:match("(.*%.tar)") -- Test for .tar and .tar.*
output_url = combine_url(output_dir, output_name) -- Update output_url
else
break
end
end
-- Add to output archive in each path, their respective files
for path, names in pairs(path_fnames) do
local archive_status, archive_err =
Command(archive_cmd):args(archive_args):arg(output_url):args(names):cwd(path):spawn():wait()
if not archive_status or not archive_status.success then
notify_error(
string.format(
"%s with selected files failed, exit code %s",
archive_args,
archive_status and archive_status.code or archive_err
),
"error"
)
end
end
-- Use compress command if needed
if archive_compress then
local compress_status, compress_err =
Command(archive_compress):args(archive_compress_args):arg(output_name):cwd(output_dir):spawn():wait()
if not compress_status or not compress_status.success then
notify_error(
string.format(
"%s with %s failed, exit code %s",
archive_compress,
output_name,
compress_status and compress_status.code or compress_err
),
"error"
)
end
end
end,
}