aboutsummaryrefslogtreecommitdiffstats
path: root/dupe-and-comment.lua
blob: 16e2e97886133a21cb7cd7d28b72ddf732768a73 (plain) (blame)
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
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