aegisub-scripts/dupe-and-comment.lua

125 lines
5.2 KiB
Lua

script_name="Dupe and Comment"
script_description="Copies a line and comments out the original.\nbecause i like seeing the original while editing, and being able to go back to it easily"
script_author = "garret"
script_version = "5.0.0"
script_namespace = "garret.dupe-and-comment"
script_changelog = {
["5.0.0"] = {"subtle BREAKING CHANGE: Undo no longer cares whether the edit is a comment or not. This means it'll work in places it didn't before.", "Undo now sets the restored line to whatever comment status the edited line was. You won't get the same result when restoring lines where the edit is a comment.", "There is now a changelog for DepCtrl. (hint: you're reading it)"},
["4.0.0"] = {"Use on fold boundaries now works as expected."},
["3.0.2"] = {"code cleanup: variable names are now informative again."},
["3.0.1"] = {"Fixing selected/active lines is now more efficient."},
["3.0.0"] = {"Selected lines and active line will now be properly set after do and undo.", "Duplicating no longer depends on aegisub.util."},
["2.1.3"] = {"Trying to undo the final line no longer gives an out-of-range error (it fails silently instead)."},
["2.1.2"] = {"code cleanup: change variable names"},
["2.1.1"] = {"code cleanup: use local functions"},
["2.1.0"] = {"Added DepCtrl compatibility."},
["2.0.0"] = {"version 2021-04-11", "BREAKING CHANGE: Automation menu entries have been moved to a dedicated submenu."},
["1.1.0"] = {"version 2021-04-10", "Added undo macro."},
["1.0.0"] = {"inital git commit, version 2021-04-05", "The script now works with multiple lines.", "Switched to using aegisub.util for copying lines.", "cleaned up code"},
["0.1.0"] = {"snapshot from 2021-04-04, earliest copy i have", "has comment function, but only works on a single line at a time"},
}
local haveDepCtrl, DependencyControl, depctrl = pcall(require, "l0.DependencyControl")
if haveDepCtrl then
depctrl = DependencyControl {
--feed="TODO",
}
end
local function strnumtobool(i) if i == "0" then return false else return true end end
local function find_fold_boundary(line)
local fold = line.extra["_aegi_folddata"]
if fold then -- we are indeed at a fold boundary
-- now work out which one
local at_fold_end = strnumtobool(string.sub(fold, 1, 1))
-- first char is a bool, 0 = at start, 1 = at end
return at_fold_end
end
end
local function comment(subs, sel, act)
for i=#sel,1,-1 do
local edit=subs[sel[i]] -- current line
local original=subs[sel[i]] -- and a copy of it
-- deal with being at the start/end of a fold
local at_fold_end = find_fold_boundary(edit)
if at_fold_end then
edit.extra["_aegi_folddata"] = nil -- remove fold data from the edit
-- but not from the dupe, so effectively the end of the fold gets moved down one
elseif at_fold_end == false then -- if at fold start
original.extra["_aegi_folddata"] = nil -- ditto ^, but from the original
-- so we don't have loads of extra fold starts that might interfere later
end
subs[sel[i]] = edit
-- now use that copy we made to make a different line
original.comment = true -- comment out the new dupe line
subs.insert(sel[i]+1, original) -- and put it below
-- sort out sel/act
local preceding_lines = i - 1
local on_act = act == sel[i]
sel[i] = sel[i] + preceding_lines
if on_act then act = sel[i] end
end
aegisub.set_undo_point(script_name)
return sel, act
end
local function undo(subs, sel, act)
for i=#sel,1,-1 do
local edit=subs[sel[i]]
if not (sel[i] + 1 > #subs) then -- preventing out-of-range errors
local original=subs[sel[i]+1]
if original.comment == true then
original.comment = edit.comment
-- deal with being at the start/end of a fold
local at_fold_end = find_fold_boundary(edit)
if at_fold_end == false then -- that is, if we're at the start
original.extra["_aegi_folddata"] = edit.extra["_aegi_folddata"]
-- preserve the original fold boundary so the fold doesnt magically disappear
end
subs[sel[i]+1] = original
subs.delete(sel[i])
if #sel > 1 then
-- sort out selection. same as `do`, but the other way round.
local preceding_lines = i + 1
local on_act = act == sel[i]
sel[i] = sel[i] - preceding_lines
if on_act then act = sel[i] end
end
end
end
end
aegisub.set_undo_point("Undo "..script_name)
return sel, act
end
local macros = {
{"Do", script_description, comment},
{"Undo","Deletes selected line and restores the original", undo}
}
if haveDepCtrl then
depctrl:registerMacros(macros)
else
for _,macro in ipairs(macros) do
local name, desc, fun = unpack(macro)
aegisub.register_macro(script_name .. '/' .. name, desc, fun)
end
end
-- i trust what petzku from the cartel has to say on adding multiple macros with depctrl